/// <summary>
 /// Event method auto-called when the "chatter log" box is double-clicked.
 /// </summary>
 private void ChatterLogGrid_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
 {
     if (!Enum.TryParse(ChatterLogGrid[1, e.RowIndex].Value.ToString(), true, out Keys key))
     {
         MessageBox.Show("Error: chatter log grid misconfigured, invalid key name!", "Keyboard Chatter Blocker", MessageBoxButtons.OK);
         return;
     }
     else if (e.ColumnIndex == 3) // 'Configure' column
     {
         if (!Program.Blocker.KeysToChatterTime[key].HasValue)
         {
             Program.Blocker.KeysToChatterTime[key] = Program.Blocker.GlobalChatterTimeLimit;
             Program.Blocker.SaveConfig();
             ConfigureKeysGrid.Rows.Add(key.Stringify(), Program.Blocker.GlobalChatterTimeLimit.ToString(), "[X]");
         }
         string keyText = key.Stringify();
         TabControl1.SelectedTab = KeysTabPage;
         foreach (DataGridViewRow row in ConfigureKeysGrid.Rows)
         {
             if (row.Cells[0].Value.ToString() == keyText)
             {
                 ConfigureKeysGrid.Select();
                 ConfigureKeysGrid.ClearSelection();
                 row.Selected = true;
                 ConfigureKeysGrid.FirstDisplayedScrollingRowIndex = row.Index;
                 break;
             }
         }
     }
 }
 /// <summary>
 /// Pushes all keys to the GUI grid.
 /// Key configurations are tracked locally, not directly on the grid, to avoid performance impact.
 /// This needs to be called to update key configuration GUI properly.
 /// </summary>
 public void PushKeysToGrid()
 {
     ConfigureKeysGrid.SuspendLayout();
     ConfigureKeysGrid.Rows.Clear();
     foreach (KeyValuePair <Keys, uint?> keyData in Program.Blocker.KeysToChatterTime.MainDictionary)
     {
         if (!keyData.Value.HasValue)
         {
             continue;
         }
         ConfigureKeysGrid.Rows.Add(keyData.Key.Stringify(), keyData.Value.Value, "[X]");
     }
     ConfigureKeysGrid.ResumeLayout(true);
 }