//// ---------------------------------------------------------------------------- //void clKeyboardManager::OnStartupCompleted(wxCommandEvent& event) //// ---------------------------------------------------------------------------- //{ // event.Skip(); // this->Initialize(); //} // ---------------------------------------------------------------------------- void clKeyboardManager::DoConvertToIntMap(const MenuItemDataMap_t& strMap, MenuItemDataIntMap_t& intMap) // ---------------------------------------------------------------------------- { // Convert the string map into int based map MenuItemDataMap_t::const_iterator iter = strMap.begin(); for(; iter != strMap.end(); ++iter) { wxString resourceIDStr = iter->second.resourceID; long lnResourceID; resourceIDStr.ToLong(&lnResourceID); //-intMap.insert(std::make_pair(wxXmlResource::GetXRCID(iter->second.resourceID), iter->second)); intMap.insert(std::make_pair(lnResourceID, iter->second)); } }
//int clKeyboardManager::PopupNewKeyboardShortcutDlg(wxWindow* parent, MenuItemData& menuItemData) //{ // NewKeyShortcutDlg dlg(parent, menuItemData); // if(dlg.ShowModal() == wxID_OK) { // menuItemData.accel = dlg.GetAccel(); // return wxID_OK; // } // return wxID_CANCEL; //} // ---------------------------------------------------------------------------- bool clKeyboardManager::Exists(const wxString& accel) const // ---------------------------------------------------------------------------- { if(accel.IsEmpty()) return false; MenuItemDataMap_t accels; GetAllAccelerators(accels); MenuItemDataMap_t::const_iterator iter = accels.begin(); for(; iter != accels.end(); ++iter) { if(iter->second.accel == accel) { return true; } } return false; }
void EditSnippetsDlg::DoItemSelected(const wxString& text) { m_textCtrlMenuEntry->SetValue(text); m_textCtrlSnippet->SetValue(GetStringDb()->GetSnippetString(text)); MenuItemDataMap_t accelMap; clKeyboardManager::Get()->GetAllAccelerators(accelMap); if(text.IsEmpty()) { return; } m_textCtrlAccelerator->SetValue(wxT("")); MenuItemDataMap_t::iterator iter = accelMap.begin(); for(; iter != accelMap.end(); ++iter) { MenuItemData mid = iter->second; if(mid.action == text) { m_textCtrlAccelerator->SetValue(mid.accel); } } }
// ---------------------------------------------------------------------------- void clKeyboardManager::SetAccelerators(const MenuItemDataMap_t& accels) // ---------------------------------------------------------------------------- { // separate the globals from the menu accelerators // The process is done by checking each item's parentMenu // If the parentMenu is empty -> global accelerator MenuItemDataMap_t globals, menus; MenuItemDataMap_t::const_iterator iter = accels.begin(); for(; iter != accels.end(); ++iter) { if(iter->second.parentMenu.IsEmpty()) { globals.insert(std::make_pair(iter->first, iter->second)); } else { menus.insert(std::make_pair(iter->first, iter->second)); } } m_menuTable.swap(menus); m_globalTable.swap(globals); Update(); Save(); }
// ---------------------------------------------------------------------------- wxArrayString clKeyboardManager::GetAllUnasignedKeyboardShortcuts() const // ---------------------------------------------------------------------------- { MenuItemDataMap_t accels; GetAllAccelerators(accels); wxStringSet_t usedShortcuts; std::for_each(accels.begin(), accels.end(), [&](const std::pair<wxString, MenuItemData>& p) { if(!p.second.accel.IsEmpty()) { usedShortcuts.insert(p.second.accel); } }); // Remove all duplicate entries wxArrayString allUnasigned; std::set_difference(m_allShorcuts.begin(), m_allShorcuts.end(), usedShortcuts.begin(), usedShortcuts.end(), std::back_inserter(allUnasigned)); return allUnasigned; }
void AccelTableDlg::PopulateTable(const wxString& filter) { m_dvListCtrl->DeleteAllItems(); MenuItemDataMap_t filteredMap; if(filter.IsEmpty()) { filteredMap = m_accelMap; } else { for(MenuItemDataMap_t::iterator iter = m_accelMap.begin(); iter != m_accelMap.end(); ++iter) { if(!IsMatchesFilter(filter, iter->second)) continue; filteredMap.insert(std::make_pair(iter->first, iter->second)); } } if(filteredMap.empty()) return; // Add core entries for(MenuItemDataMap_t::const_iterator iter = filteredMap.begin(); iter != filteredMap.end(); ++iter) { const MenuItemData& mid = iter->second; wxVector<wxVariant> cols; wxString parentMenu = mid.parentMenu.BeforeFirst(':'); if(parentMenu.IsEmpty()) { parentMenu = "<Global>"; } cols.push_back(parentMenu); // Parent menu cols.push_back(mid.action.AfterLast(':')); // Action description cols.push_back(mid.accel); // shortcut m_dvListCtrl->AppendItem(cols, (wxUIntPtr) new AccelItemData(mid)); } m_dvListCtrl->GetColumn(0)->SetSortable(true); m_dvListCtrl->GetColumn(1)->SetSortable(true); m_dvListCtrl->GetColumn(2)->SetSortable(true); }
// ----------------------------------------------------------------------------------------------------------------- void clKeyboardManager::CheckForDuplicateAccels(MenuItemDataMap_t& accelMap) const //(2019/04/22) // ----------------------------------------------------------------------------------------------------------------- { // Warn about duplicate Menu accelerators //(2019/04/22) wxArrayString dupMsgs; for(MenuItemDataMap_t::iterator accelIter = accelMap.begin(); accelIter != accelMap.end(); ++accelIter) { if (accelIter->second.accel.empty()) continue; if (accelIter->second.parentMenu.empty()) continue; //skip global accelerators MenuItemDataMap_t::iterator foundIter = accelMap.end(); MenuItemDataMap_t::iterator patternIter = accelIter; while (accelMap.end() != (foundIter = ExistsALikeAccel(accelMap, patternIter)) ) { #if defined(LOGGING) wxString patternAccel = patternIter->second.accel; wxString patternAction = patternIter->second.action; wxString dupAccel = foundIter->second.accel; wxString dupAction = foundIter->second.action; #endif //skip found global accelerators if (foundIter->second.parentMenu.empty()) { patternIter = foundIter; continue; } // found a duplicate menu accelerator further down the accelerator map MenuItemDataMap_t::iterator srcIter = patternIter; wxString srcMenuLabel = srcIter->second.parentMenu; srcMenuLabel.Replace(_T("\t"), _T(" ")); srcMenuLabel.Replace(_T("&"), _T("")); srcMenuLabel.Replace(_T("::"), _T("/")); wxString foundMenuLabel = foundIter->second.parentMenu; foundMenuLabel.Replace(_T("\t"), _T(" ")); foundMenuLabel.Replace(_T("&"), _T("")); foundMenuLabel.Replace(_T("::"), _T("/")); long srcMenuID; srcIter->first.ToLong(&srcMenuID); long foundMenuID; foundIter->first.ToLong(&foundMenuID); wxString msg = wxString::Format(_T("Conflicting menu items: \'%s\' && \'%s\'"), srcMenuLabel.wx_str(), foundMenuLabel.wx_str()) + wxString::Format(_T("\n Both using shortcut: \'%s\'"), foundIter->second.accel.wx_str()) + wxString::Format(_T(" (IDs [%ld] [%ld])"),srcMenuID, foundMenuID ); msg += _T("\n\n"); dupMsgs.Add(msg); patternIter = foundIter; }//end while } if (dupMsgs.GetCount()) { bool isParentWindowDialog = false; // Get top window to solve msg window getting hidden behind keybinder dialog wxWindow* pMainWin = nullptr; if ( (pMainWin = wxFindWindowByLabel(_T("Configure editor"))) ) { pMainWin = wxFindWindowByLabel(_T("Configure editor")); isParentWindowDialog = true; } else pMainWin = Manager::Get()->GetAppWindow(); wxString msg = _T("Keyboard shortcut conflicts found.\n"); if (not isParentWindowDialog) msg += _T("Use Settings/Editor/KeyboardShortcuts to resolve conflicts.\n\n"); for (size_t ii=0; ii<dupMsgs.GetCount(); ++ii) msg += dupMsgs[ii]; //-cbMessageBox(msg, _T("Keyboard shortcuts conflicts"), wxOK, pMainWin); AnnoyingDialog dlg(_("Keyboard shortcuts conflicts"), msg, wxART_INFORMATION, AnnoyingDialog::OK); dlg.ShowModal(); }//endif dupMsgs return; }
// ---------------------------------------------------------------------------- void clKeyboardManager::Initialize(bool isRefreshRequest) // ---------------------------------------------------------------------------- { wxUnusedVar(isRefreshRequest); m_menuTable.clear(); // First, try to load accelerators from %appdata% keybindings.conf // containing merged default + user defined accerators // Second, try loading from default accerators in %appdata% + accerators.conf clKeyboardBindingConfig config; if( not config.Exists()) //does keybindings.conf exist? { #if defined(LOGGING) LOGIT( _T("[%s]"), _("Keyboard manager: No configuration found - importing old settings")); #endif //CL_DEBUG("Keyboard manager: No configuration found - importing old settings"); // Decide which file we want to load, take the user settings file first // GetUserDataDir() == "c:\Users\<username>\AppData\Roaming\<appname>\config\keybindings.conf" // GetDataDir() == executable directory // Old accererator setting are in %appdata% wxFileName fnOldSettings(wxStandardPaths::Get().GetTempDir(), _T("keyMnuAccels.conf")); wxString personality = Manager::Get()->GetPersonalityManager()->GetPersonality(); fnOldSettings.SetName(personality + _T(".") + fnOldSettings.GetName()); wxFileName fnFileToLoad; bool canDeleteOldSettings(false); // If %appdata% accerators.conf exist, use it if(fnOldSettings.FileExists()) { fnFileToLoad = fnOldSettings; //-canDeleteOldSettings = true; } else // else use executable dir accerators.conf.default accerators { //-fnFileToLoad = fnDefaultOldSettings; wxASSERT_MSG(0, _("clKeyboardManager::Initialize() missing accerators.conf file")); } if(fnFileToLoad.FileExists()) { #if defined(LOGGING) LOGIT( _T("KeyboardManager:Importing settings from:\n\t[%s]"), fnFileToLoad.GetFullPath().wx_str()); #endif // Apply the old settings to the menus wxString content; if(not ReadFileContent(fnFileToLoad, content)) return; wxArrayString lines = ::wxStringTokenize(content, _T("\r\n"), wxTOKEN_STRTOK); for(size_t i = 0; i < lines.GetCount(); ++i) { #if defined(LOGGING) #if wxVERSION_NUMBER > 3000 LOGIT( _T("AccelFile[%u:%s]"), (unsigned)i, lines.Item(i).wx_str() ); #else LOGIT( _T("AccelFile[%u:%s]"), i, lines.Item(i).wx_str() ); #endif #endif wxArrayString parts = ::wxStringTokenize(lines.Item(i), _T("|"), wxTOKEN_RET_EMPTY); if(parts.GetCount() < 3) continue; MenuItemData binding; binding.resourceID = parts.Item(0); binding.parentMenu = parts.Item(1); binding.action = parts.Item(2); if(parts.GetCount() == 4) { binding.accel = parts.Item(3); } m_menuTable.insert(std::make_pair(binding.resourceID, binding)); } if(canDeleteOldSettings) { if (fnFileToLoad.FileExists()) ::wxRemoveFile(fnFileToLoad.GetFullPath()); } } } else //config exists: "keybindings.conf" { config.Load(); m_menuTable = config.GetBindings(); } // Load the default settings and add any new entries from accerators.conf MenuItemDataMap_t defaultEntries = DoLoadDefaultAccelerators(); // Remove any map items nolonger matching the menu structure for (MenuItemDataMap_t::iterator mapIter = m_menuTable.begin(); mapIter != m_menuTable.end(); ++mapIter) { mnuContinue: if (mapIter == m_menuTable.end()) break; //search menu structure map for map menuId if ( defaultEntries.count(mapIter->first) == 0) { // menuID nolonger exists #if defined(LOGGING) wxString mapAccel = mapIter->second.accel; wxString mapParent = mapIter->second.parentMenu; wxString mapMnuID = mapIter->first; LOGIT( _T("Removing ID mismatch[%s][%s][%s]"), mapMnuID.wx_str(), mapParent.wx_str(), mapAccel.wx_str()); #endif mapIter = m_menuTable.erase(mapIter); goto mnuContinue; } else //remove the found map item if its label doesn't match menu structure label//(pecan 2019/05/18) { // Have matching map resoureID and menu structure resourceID (ie., menuItemID) MenuItemDataMap_t::iterator mnuIter = defaultEntries.find(mapIter->first); if (mnuIter == defaultEntries.end()) continue; wxString mapParent = mapIter->second.parentMenu; if (mapParent.empty()) continue; //skip global accelerators wxString mnuParent = mnuIter->second.parentMenu; if (mnuParent.empty()) continue; //skip global accelerators if (mapParent.Lower() != mnuParent.Lower()) { #if defined(LOGGING) wxString mapMnuID = mapIter->first; wxString mapAccel = mapIter->second.accel; LOGIT( _T("Removing LabelMismatch[%s][%s][%s]"), mapMnuID.wx_str(), mapParent.wx_str(), mapAccel.wx_str()); #endif mapIter = m_menuTable.erase(mapIter); goto mnuContinue; }//endif label compare }//endif else have matching resourceID }//endfor mapIter // Add any new entries from accerators.conf (the menu structure) std::for_each(defaultEntries.begin(), defaultEntries.end(), [&](const MenuItemDataMap_t::value_type& vdflt) { //-wxString vtValue = vdflt.first; //The menu id number if(m_menuTable.count(vdflt.first) == 0) { //searches map for like shortcut string m_menuTable.insert(vdflt); } // ---------------------------------------------------------------------------- // NO!no! don't overwrite past user changes; m_menuTable already has user keybinder.conf changes. // while defaultEntries have original CodeBlocks menu accelerators // User must make (or made) m_menuTable changes via KeyBinder configuration dialog. // ---------------------------------------------------------------------------- //-else //verify keyboard shortcut //-{ //- MenuItemDataMap_t::iterator mapIter = m_menuTable.find(vdflt.first); //- if (mapIter != m_menuTable.end()) //should never be true! //- if (mapIter->second.accel != vdflt.second.accel) //- { //- #if defined(LOGGING) //- wxString mapMenuItem = mapIter->second.parentMenu + mapIter->second.accel; //- wxString vdfltMenuItem = vdflt.second.parentMenu +vdflt.second.accel; //- LOGIT( _T("Initialize changing accel[%s]to[%s]"), mapMenuItem.wx_str(), vdfltMenuItem.wx_str()); //- #endif //- mapIter->second.accel = vdflt.second.accel; //- } //-} }); // Warn about duplicate shortcut entries (eg., (Print/PrevCallTip Ctrl-P) and (CC Search/Ctrl-Shift-.) have duplicates) //(2019/04/23) CheckForDuplicateAccels(m_menuTable); // Store the correct configuration; globalTable is inserted into menuTable config.SetBindings(m_menuTable, m_globalTable).Save(); // And apply the changes Update(); }