///Enables or disables a menu item based on its name (not the ///label in the menu bar, but the name of the command.) ///If you give it the name of a multi-item (one that was ///added using AddItemList(), it will enable or disable all ///of them at once void CommandManager::Enable(CommandListEntry *entry, bool enabled) { if (!entry->menu) { entry->enabled = enabled; return; } // LL: Refresh from real state as we can get out of sync on the // Mac due to its reluctance to enable menus when in a modal // state. entry->enabled = entry->menu->IsEnabled(entry->id); // Only enabled if needed if (entry->enabled != enabled) { entry->menu->Enable(entry->id, enabled); entry->enabled = entry->menu->IsEnabled(entry->id); } if (entry->multi) { int i; int ID = entry->id; for(i=1; i<entry->count; i++) { ID = NextIdentifier(ID); // This menu item is not necessarily in the same menu, because // multi-items can be spread across multiple sub menus CommandListEntry *multiEntry = mCommandIDHash[ID]; if (multiEntry) { wxMenuItem *item = multiEntry->menu->FindItem(ID); if (item) { item->Enable(enabled); } else { wxLogDebug(wxT("Warning: Menu entry with id %i in %s not found"), ID, (const wxChar*)entry->name); } } else { wxLogDebug(wxT("Warning: Menu entry with id %i not in hash"), ID); } } } }
///Enables or disables a menu item based on its name (not the ///label in the menu bar, but the name of the command.) ///If you give it the name of a multi-item (one that was ///added using AddItemList(), it will enable or disable all ///of them at once void CommandManager::Enable(CommandListEntry *entry, bool enabled) { // Don't do anything if the command's enabled state // is already the same if (entry->enabled == enabled) return; entry->enabled = enabled; if (!entry->menu) return; entry->menu->Enable(entry->id, enabled); if (entry->multi) { int i; int ID = entry->id; for(i=1; i<entry->count; i++) { ID = NextIdentifier(ID); // This menu item is not necessarily in the same menu, because // multi-items can be spread across multiple sub menus CommandListEntry *multiEntry = mCommandIDHash[ID]; if (multiEntry) { wxMenuItem *item = multiEntry->menu->FindItem(ID); if (item) { item->Enable(enabled); } else { wxLogDebug(wxT("Warning: Menu entry with id %i in %s not found"), ID, (const wxChar*)entry->name); } } else { wxLogDebug(wxT("Warning: Menu entry with id %i not in hash"), ID); } } } }
///Given all of the information for a command, comes up with a new unique ///ID, adds it to a list, and returns the ID. ///WARNING: Does this conflict with the identifiers set for controls/windows? ///If it does, a workaround may be to keep controls below wxID_LOWEST ///and keep menus above wxID_HIGHEST int CommandManager::NewIdentifier(wxString name, wxString label, wxMenu *menu, CommandFunctor *callback, bool multi, int index, int count) { CommandListEntry *tmpEntry = new CommandListEntry; wxString labelPrefix; if (!mSubMenuList.IsEmpty()) { labelPrefix = mSubMenuList[mSubMenuList.GetCount() - 1]->name; } // wxMac 2.5 and higher will do special things with the // Preferences, Exit (Quit), and About menu items, // if we give them the right IDs. // Otherwise we just pick increasing ID numbers for each new // command. Note that the name string we are comparing // ("About", "Preferences") is the internal command name // (untranslated), not the label that actually appears in the // menu (which might be translated). mCurrentID = NextIdentifier(mCurrentID); tmpEntry->id = mCurrentID; tmpEntry->key = GetKey(label); #if defined(__WXMAC__) if (name == wxT("Preferences")) tmpEntry->id = wxID_PREFERENCES; else if (name == wxT("Exit")) tmpEntry->id = wxID_EXIT; else if (name == wxT("About")) tmpEntry->id = wxID_ABOUT; #endif tmpEntry->defaultKey = tmpEntry->key; tmpEntry->name = name; tmpEntry->label = label; tmpEntry->labelPrefix = labelPrefix; tmpEntry->labelTop = wxMenuItem::GetLabelFromText(mCurrentMenuName); tmpEntry->menu = menu; tmpEntry->callback = callback; tmpEntry->multi = multi; tmpEntry->index = index; tmpEntry->count = count; tmpEntry->flags = mDefaultFlags; tmpEntry->mask = mDefaultMask; tmpEntry->enabled = true; // Key from preferences overridse the default key given gPrefs->SetPath(wxT("/NewKeys")); if (gPrefs->HasEntry(name)) { tmpEntry->key = KeyStringNormalize(gPrefs->Read(name, tmpEntry->key)); } gPrefs->SetPath(wxT("/")); mCommandList.Add(tmpEntry); mCommandIDHash[tmpEntry->id] = tmpEntry; if (index == 0 || !multi) { #if defined(__WXDEBUG__) CommandListEntry *prev = mCommandNameHash[name]; if (prev) { wxLogDebug(wxT("Command '%s' defined by '%s' and '%s'"), name.c_str(), prev->label.BeforeFirst(wxT('\t')).c_str(), tmpEntry->label.BeforeFirst(wxT('\t')).c_str()); wxASSERT(!prev); } #endif mCommandNameHash[name] = tmpEntry; } if (tmpEntry->key != wxT("")) { mCommandKeyHash[tmpEntry->key] = tmpEntry; } return tmpEntry->id; }
///Given all of the information for a command, comes up with a new unique ///ID, adds it to a list, and returns the ID. ///WARNING: Does this conflict with the identifiers set for controls/windows? ///If it does, a workaround may be to keep controls below wxID_LOWEST ///and keep menus above wxID_HIGHEST int CommandManager::NewIdentifier(wxString name, wxString label, wxMenu *menu, CommandFunctor *callback, bool multi, int index, int count) { CommandListEntry *tmpEntry = new CommandListEntry; wxString labelPrefix; if (!mSubMenuList.IsEmpty()) { labelPrefix = mSubMenuList[mSubMenuList.GetCount() - 1]->name; } // wxMac 2.5 and higher will do special things with the // Preferences, Exit (Quit), and About menu items, // if we give them the right IDs. // Otherwise we just pick increasing ID numbers for each new // command. Note that the name string we are comparing // ("About", "Preferences") is the internal command name // (untranslated), not the label that actually appears in the // menu (which might be translated). mCurrentID = NextIdentifier(mCurrentID); tmpEntry->id = mCurrentID; tmpEntry->key = GetKey(label); #if defined(__WXMAC__) if (name == wxT("Preferences")) tmpEntry->id = wxID_PREFERENCES; else if (name == wxT("Exit")) tmpEntry->id = wxID_EXIT; else if (name == wxT("About")) tmpEntry->id = wxID_ABOUT; #endif tmpEntry->defaultKey = tmpEntry->key; // For key bindings for commands with a list, such as effects, // the name in prefs is the category name plus the effect name. if( multi ) name= wxString::Format( wxT("%s:%s"), name.c_str(), label.c_str() ); tmpEntry->name = name; tmpEntry->label = label; tmpEntry->labelPrefix = labelPrefix; tmpEntry->labelTop = wxMenuItem::GetLabelFromText(mCurrentMenuName); tmpEntry->menu = menu; tmpEntry->callback = callback; tmpEntry->multi = multi; tmpEntry->index = index; tmpEntry->count = count; tmpEntry->flags = mDefaultFlags; tmpEntry->mask = mDefaultMask; tmpEntry->enabled = true; tmpEntry->wantevent = (label.Find(wxT("\twantevent")) != wxNOT_FOUND); // Key from preferences overridse the default key given gPrefs->SetPath(wxT("/NewKeys")); if (gPrefs->HasEntry(name)) { tmpEntry->key = KeyStringNormalize(gPrefs->Read(name, tmpEntry->key)); } gPrefs->SetPath(wxT("/")); mCommandList.Add(tmpEntry); mCommandIDHash[tmpEntry->id] = tmpEntry; #if defined(__WXDEBUG__) CommandListEntry *prev = mCommandNameHash[name]; if (prev) { // Under Linux it looks as if we may ask for a newID for the same command // more than once. So it's only an error if two different commands // have the exact same name. if( prev->label != tmpEntry->label ) { wxLogDebug(wxT("Command '%s' defined by '%s' and '%s'"), name.c_str(), prev->label.BeforeFirst(wxT('\t')).c_str(), tmpEntry->label.BeforeFirst(wxT('\t')).c_str()); wxFAIL_MSG( wxString::Format(wxT("Command '%s' defined by '%s' and '%s'"), name.c_str(), prev->label.BeforeFirst(wxT('\t')).c_str(), tmpEntry->label.BeforeFirst(wxT('\t')).c_str())); } } #endif mCommandNameHash[name] = tmpEntry; if (tmpEntry->key != wxT("")) { mCommandKeyHash[tmpEntry->key] = tmpEntry; } return tmpEntry->id; }