diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index 49a06d742..e1153c595 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -464,33 +464,24 @@ LRESULT Notepad_plus::init(HWND hwnd) // Macro Menu HMENU hMacroMenu = ::GetSubMenu(_mainMenuHandle, MENUINDEX_MACRO); - size_t const posBase = 6; - size_t nbTopLevelItem = nppParam.getMacroMenuItems().getTopLevelItemNumber(); - if (nbTopLevelItem >= 1) - ::InsertMenu(hMacroMenu, posBase - 1, MF_BYPOSITION, static_cast(-1), 0); - + size_t const macroPosBase = 6; DynamicMenu& macroMenuItems = nppParam.getMacroMenuItems(); - macroMenuItems.attach(hMacroMenu, posBase); + size_t nbMacroTopLevelItem = macroMenuItems.getTopLevelItemNumber(); + if (nbMacroTopLevelItem >= 1) + ::InsertMenu(hMacroMenu, macroPosBase - 1, MF_BYPOSITION, static_cast(-1), 0); + + macroMenuItems.attach(hMacroMenu, macroPosBase, IDM_SETTING_SHORTCUT_MAPPER_MACRO, TEXT("Modify Shortcut/Delete Macro...")); // Run Menu - std::vector & userCommands = nppParam.getUserCommandList(); HMENU hRunMenu = ::GetSubMenu(_mainMenuHandle, MENUINDEX_RUN); int const runPosBase = 2; - size_t nbUserCommand = userCommands.size(); - if (nbUserCommand >= 1) + DynamicMenu& runMenuItems = nppParam.getRunMenuItems(); + size_t nbRunTopLevelItem = runMenuItems.getTopLevelItemNumber(); + if (nbRunTopLevelItem >= 1) ::InsertMenu(hRunMenu, runPosBase - 1, MF_BYPOSITION, static_cast(-1), 0); - for (size_t i = 0; i < nbUserCommand; ++i) - { - ::InsertMenu(hRunMenu, static_cast(runPosBase + i), MF_BYPOSITION, ID_USER_CMD + i, userCommands[i].toMenuItemString().c_str()); - } - - if (nbUserCommand >= 1) - { - ::InsertMenu(hRunMenu, static_cast(runPosBase + nbUserCommand + 1), MF_BYPOSITION, static_cast(-1), 0); - ::InsertMenu(hRunMenu, static_cast(runPosBase + nbUserCommand + 2), MF_BYCOMMAND, IDM_SETTING_SHORTCUT_MAPPER_RUN, TEXT("Modify Shortcut/Delete Command...")); - } + runMenuItems.attach(hRunMenu, runPosBase, IDM_SETTING_SHORTCUT_MAPPER_RUN, TEXT("Modify Shortcut/Delete Command...")); // Updater menu item if (!nppGUI._doesExistUpdater) @@ -5194,10 +5185,10 @@ bool Notepad_plus::addCurrentMacro() if (ms.doDialog() != -1) { HMENU hMacroMenu = ::GetSubMenu(_mainMenuHandle, MENUINDEX_MACRO); - int const posBase = 6; //separator at index 5 + unsigned int posBase = macroMenu.getPosBase(); if (nbTopLevelItem == 0) { - ::InsertMenu(hMacroMenu, posBase-1, MF_BYPOSITION, static_cast(-1), 0); //no separator yet, add one + ::InsertMenu(hMacroMenu, posBase - 1, MF_BYPOSITION, static_cast(-1), 0); //no separator yet, add one // Insert the separator and modify/delete command ::InsertMenu(hMacroMenu, posBase + nbTopLevelItem + 1, MF_BYPOSITION, static_cast(-1), 0); @@ -5205,13 +5196,13 @@ bool Notepad_plus::addCurrentMacro() NativeLangSpeaker *pNativeLangSpeaker = nppParams.getNativeLangSpeaker(); generic_string nativeLangShortcutMapperMacro = pNativeLangSpeaker->getNativeLangMenuString(IDM_SETTING_SHORTCUT_MAPPER_MACRO); if (nativeLangShortcutMapperMacro == TEXT("")) - nativeLangShortcutMapperMacro = TEXT("Modify Shortcut/Delete Macro..."); + nativeLangShortcutMapperMacro = macroMenu.getLastCmdLabel(); ::InsertMenu(hMacroMenu, posBase + nbTopLevelItem + 2, MF_BYCOMMAND, IDM_SETTING_SHORTCUT_MAPPER_MACRO, nativeLangShortcutMapperMacro.c_str()); } theMacros.push_back(ms); macroMenu.push_back(MenuItemUnit(cmdID, ms.getName())); - ::InsertMenu(hMacroMenu, posBase + nbTopLevelItem, MF_BYPOSITION, cmdID, ms.toMenuItemString().c_str()); + ::InsertMenu(hMacroMenu, static_cast(posBase + nbTopLevelItem), MF_BYPOSITION, cmdID, ms.toMenuItemString().c_str()); _accelerator.updateShortcuts(); nppParams.setShortcutDirty(); return true; diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index fbb64738b..fa196ef2c 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -751,12 +751,14 @@ int DynamicMenu::getTopLevelItemNumber() const return nb; } -bool DynamicMenu::attach(HMENU hMenu, size_t posBase) +bool DynamicMenu::attach(HMENU hMenu, unsigned int posBase, int lastCmd, const generic_string& lastCmdLabel) { if (!hMenu) return false; _hMenu = hMenu; _posBase = posBase; + _lastCmd = lastCmd; + _lastCmdLabel = lastCmdLabel; return createMenu(); } @@ -835,7 +837,7 @@ bool DynamicMenu::createMenu() const if (nb > 0) { ::InsertMenu(_hMenu, static_cast(_posBase + i), MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - ::InsertMenu(_hMenu, static_cast(_posBase + i + 2), MF_BYCOMMAND, IDM_SETTING_SHORTCUT_MAPPER_MACRO, TEXT("Modify Shortcut/Delete Macro...")); + ::InsertMenu(_hMenu, static_cast(_posBase + i + 2), MF_BYCOMMAND, _lastCmd, _lastCmdLabel.c_str()); } return true; @@ -2746,12 +2748,8 @@ void NppParameters::feedMacros(TiXmlNode *node) Macro macro; getActions(childNode, macro); int cmdID = ID_MACRO + static_cast(_macros.size()); - - MacroShortcut ms(sc, macro, cmdID); - _macros.push_back(ms); - - MenuItemUnit miu(cmdID, sc.getName(), fdnm); - _macroMenuItems.push_back(miu); + _macros.push_back(MacroShortcut(sc, macro, cmdID)); + _macroMenuItems.push_back(MenuItemUnit(cmdID, sc.getName(), fdnm)); } } } @@ -2797,7 +2795,8 @@ void NppParameters::feedUserCmds(TiXmlNode *node) childNode = childNode->NextSibling(TEXT("Command")) ) { Shortcut sc; - if (getShortcuts(childNode, sc)) + generic_string fdnm; + if (getShortcuts(childNode, sc, &fdnm)) { TiXmlNode *aNode = childNode->FirstChild(); if (aNode) @@ -2806,8 +2805,8 @@ void NppParameters::feedUserCmds(TiXmlNode *node) if (cmdStr) { int cmdID = ID_USER_CMD + static_cast(_userCommands.size()); - UserCommand uc(sc, cmdStr, cmdID); - _userCommands.push_back(uc); + _userCommands.push_back(UserCommand(sc, cmdStr, cmdID)); + _runMenuItems.push_back(MenuItemUnit(cmdID, sc.getName(), fdnm)); } } } @@ -3386,7 +3385,7 @@ void NppParameters::insertMacro(TiXmlNode *macrosRoot, const MacroShortcut & mac } -void NppParameters::insertUserCmd(TiXmlNode *userCmdRoot, const UserCommand & userCmd) +void NppParameters::insertUserCmd(TiXmlNode *userCmdRoot, const UserCommand & userCmd, const generic_string& folderName) { const KeyCombo & key = userCmd.getKeyCombo(); TiXmlNode *cmdRoot = userCmdRoot->InsertEndChild(TiXmlElement(TEXT("Command"))); @@ -3396,6 +3395,8 @@ void NppParameters::insertUserCmd(TiXmlNode *userCmdRoot, const UserCommand & us cmdRoot->ToElement()->SetAttribute(TEXT("Shift"), key._isShift?TEXT("yes"):TEXT("no")); cmdRoot->ToElement()->SetAttribute(TEXT("Key"), key._key); cmdRoot->InsertEndChild(TiXmlText(userCmd._cmd.c_str())); + if (!folderName.empty()) + cmdRoot->ToElement()->SetAttribute(TEXT("FolderName"), folderName); } @@ -3595,7 +3596,7 @@ void NppParameters::writeShortcuts() for (size_t i = 0, len = _userCommands.size(); i < len ; ++i) { - insertUserCmd(userCmdRoot, _userCommands[i]); + insertUserCmd(userCmdRoot, _userCommands[i], _runMenuItems.getItemFromIndex(i)._parentFolderName); } TiXmlNode *pluginCmdRoot = root->FirstChild(TEXT("PluginCommands")); diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 86a24da3c..1fb7870f7 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -1334,7 +1334,7 @@ const int RECENTFILES_SHOWONLYFILENAME = 0; class DynamicMenu final { public: - bool attach(HMENU hMenu, size_t posBase); + bool attach(HMENU hMenu, unsigned int posBase, int lastCmd, const generic_string& lastCmdLabel); bool createMenu() const; bool clearMenu() const; int getTopLevelItemNumber() const; @@ -1350,10 +1350,16 @@ public: _menuItems.erase(_menuItems.begin() + i); } + unsigned int getPosBase() const { return _posBase; }; + + generic_string getLastCmdLabel() const { return _lastCmdLabel; }; + private: std::vector _menuItems; HMENU _hMenu = nullptr; - size_t _posBase = 0; + unsigned int _posBase = 0; + int _lastCmd = 0; + generic_string _lastCmdLabel; }; class NppParameters final @@ -1582,6 +1588,7 @@ public: std::vector& getContextMenuItems() { return _contextMenuItems; }; std::vector& getTabContextMenuItems() { return _tabContextMenuItems; }; DynamicMenu& getMacroMenuItems() { return _macroMenuItems; }; + DynamicMenu& getRunMenuItems() { return _runMenuItems; }; bool hasCustomContextMenu() const {return !_contextMenuItems.empty();}; bool hasCustomTabContextMenu() const {return !_tabContextMenuItems.empty();}; @@ -1859,6 +1866,7 @@ private: std::vector _contextMenuItems; std::vector _tabContextMenuItems; DynamicMenu _macroMenuItems; + DynamicMenu _runMenuItems; Session _session; generic_string _shortcutsPath; @@ -1969,7 +1977,7 @@ private: void insertUserLang2Tree(TiXmlNode *node, UserLangContainer *userLang); void insertCmd(TiXmlNode *cmdRoot, const CommandShortcut & cmd); void insertMacro(TiXmlNode *macrosRoot, const MacroShortcut & macro, const generic_string& folderName); - void insertUserCmd(TiXmlNode *userCmdRoot, const UserCommand & userCmd); + void insertUserCmd(TiXmlNode *userCmdRoot, const UserCommand & userCmd, const generic_string& folderName); void insertScintKey(TiXmlNode *scintKeyRoot, const ScintillaKeyMap & scintKeyMap); void insertPluginCmd(TiXmlNode *pluginCmdRoot, const PluginCmdShortcut & pluginCmd); TiXmlElement * insertGUIConfigBoolNode(TiXmlNode *r2w, const TCHAR *name, bool bVal); diff --git a/PowerEditor/src/WinControls/Grid/ShortcutMapper.cpp b/PowerEditor/src/WinControls/Grid/ShortcutMapper.cpp index 8a04c3f5a..01af5bd90 100644 --- a/PowerEditor/src/WinControls/Grid/ShortcutMapper.cpp +++ b/PowerEditor/src/WinControls/Grid/ShortcutMapper.cpp @@ -947,10 +947,6 @@ intptr_t CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARA const int row = _babygrid.getSelectedRow(); size_t shortcutIndex = _shortcutIndex[row-1]; - // Menu data - int32_t posBase = 0; - size_t nbElem = 0; - HMENU hMenu = NULL; switch(_currentState) { case STATE_MENU: @@ -963,10 +959,7 @@ intptr_t CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARA case STATE_MACRO: { vector & theMacros = nppParam.getMacroList(); - vector::iterator it = theMacros.begin(); - theMacros.erase(it + shortcutIndex); - - + theMacros.erase(theMacros.begin() + shortcutIndex); //save the current view _lastHomeRow[_currentState] = _babygrid.getHomeRow(); @@ -987,8 +980,7 @@ intptr_t CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARA // Erase the menu item macroMenu.erase(shortcutIndex); - - nbElem = theMacros.size(); + size_t nbElem = theMacros.size(); for (size_t i = shortcutIndex; i < nbElem; ++i) //lower the IDs of the remaining items so there are no gaps { MacroShortcut ms = theMacros[i]; @@ -1003,8 +995,10 @@ intptr_t CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARA macroMenu.createMenu(); HMENU m = reinterpret_cast(::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0)); - hMenu = ::GetSubMenu(m, MENUINDEX_MACRO); - posBase = 6; + HMENU hMenu = ::GetSubMenu(m, MENUINDEX_MACRO); + if (!hMenu) return FALSE; + + int32_t posBase = macroMenu.getPosBase(); if (nbElem == 0) { ::RemoveMenu(hMenu, IDM_SETTING_SHORTCUT_MAPPER_MACRO, MF_BYCOMMAND); @@ -1019,8 +1013,7 @@ intptr_t CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARA case STATE_USER: { vector & theUserCmds = nppParam.getUserCommandList(); - vector::iterator it = theUserCmds.begin(); - theUserCmds.erase(it + shortcutIndex); + theUserCmds.erase(theUserCmds.begin() + shortcutIndex); //save the current view _lastHomeRow[_currentState] = _babygrid.getHomeRow(); @@ -1034,24 +1027,34 @@ intptr_t CALLBACK ShortcutMapper::run_dlgProc(UINT message, WPARAM wParam, LPARA fillOutBabyGrid(); - // preparing to remove from menu - posBase = 2; - nbElem = theUserCmds.size(); - HMENU m = reinterpret_cast(::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0)); - hMenu = ::GetSubMenu(m, MENUINDEX_RUN); + // clear all menu + DynamicMenu& runMenu = nppParam.getRunMenuItems(); + runMenu.clearMenu(); + + // Erase the menu item + runMenu.erase(shortcutIndex); + // preparing to remove from menu + + size_t nbElem = theUserCmds.size(); for (size_t i = shortcutIndex; i < nbElem; ++i) //lower the IDs of the remaining items so there are no gaps { UserCommand uc = theUserCmds[i]; uc.setID(uc.getID() - 1); //shift all IDs theUserCmds[i] = uc; + + // Ajust menu items + MenuItemUnit& miu = runMenu.getItemFromIndex(i); + miu._cmdID -= 1; //shift all IDs } + // create from scratch according the new menu items structure + runMenu.createMenu(); + HMENU m = reinterpret_cast(::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0)); + HMENU hMenu = ::GetSubMenu(m, MENUINDEX_RUN); if (!hMenu) return FALSE; - // All menu items are shifted up. So we delete the last item - ::RemoveMenu(hMenu, posBase + static_cast(nbElem), MF_BYPOSITION); - + int32_t posBase = runMenu.getPosBase(); if (nbElem == 0) { ::RemoveMenu(hMenu, IDM_SETTING_SHORTCUT_MAPPER_RUN, MF_BYCOMMAND); diff --git a/PowerEditor/src/WinControls/StaticDialog/RunDlg/RunDlg.cpp b/PowerEditor/src/WinControls/StaticDialog/RunDlg/RunDlg.cpp index 97afa5569..45f79302b 100644 --- a/PowerEditor/src/WinControls/StaticDialog/RunDlg/RunDlg.cpp +++ b/PowerEditor/src/WinControls/StaticDialog/RunDlg/RunDlg.cpp @@ -327,11 +327,15 @@ intptr_t CALLBACK RunDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam case IDC_BUTTON_SAVE : { - std::vector & theUserCmds = (NppParameters::getInstance()).getUserCommandList(); + NppParameters& nppParams = NppParameters::getInstance(); + std::vector & theUserCmds = nppParams.getUserCommandList(); int nbCmd = static_cast(theUserCmds.size()); - int cmdID = ID_USER_CMD + nbCmd; + + DynamicMenu& runMenu = nppParams.getRunMenuItems(); + int nbTopLevelItem = runMenu.getTopLevelItemNumber(); + TCHAR cmd[MAX_PATH]; ::GetDlgItemText(_hSelf, IDC_COMBO_RUN_PATH, cmd, MAX_PATH); UserCommand uc(Shortcut(), cmd, cmdID); @@ -341,25 +345,26 @@ intptr_t CALLBACK RunDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam { HMENU mainMenu = reinterpret_cast(::SendMessage(_hParent, NPPM_INTERNAL_GETMENU, 0, 0)); HMENU hRunMenu = ::GetSubMenu(mainMenu, MENUINDEX_RUN); - int const posBase = 2; + int const posBase = runMenu.getPosBase(); - if (nbCmd == 0) + if (nbTopLevelItem == 0) ::InsertMenu(hRunMenu, posBase - 1, MF_BYPOSITION, static_cast(-1), 0); theUserCmds.push_back(uc); - ::InsertMenu(hRunMenu, posBase + nbCmd, MF_BYPOSITION, cmdID, uc.toMenuItemString().c_str()); + runMenu.push_back(MenuItemUnit(cmdID, uc.getName())); + ::InsertMenu(hRunMenu, posBase + nbTopLevelItem, MF_BYPOSITION, cmdID, uc.toMenuItemString().c_str()); NppParameters& nppParams = NppParameters::getInstance(); - if (nbCmd == 0) + if (nbTopLevelItem == 0) { // Insert the separator and modify/delete command - ::InsertMenu(hRunMenu, posBase + nbCmd + 1, MF_BYPOSITION, static_cast(-1), 0); + ::InsertMenu(hRunMenu, posBase + nbTopLevelItem + 1, MF_BYPOSITION, static_cast(-1), 0); NativeLangSpeaker *pNativeLangSpeaker = nppParams.getNativeLangSpeaker(); generic_string nativeLangShortcutMapperMacro = pNativeLangSpeaker->getNativeLangMenuString(IDM_SETTING_SHORTCUT_MAPPER_MACRO); if (nativeLangShortcutMapperMacro == TEXT("")) - nativeLangShortcutMapperMacro = TEXT("Modify Shortcut/Delete Command..."); + nativeLangShortcutMapperMacro = runMenu.getLastCmdLabel(); - ::InsertMenu(hRunMenu, posBase + nbCmd + 2, MF_BYCOMMAND, IDM_SETTING_SHORTCUT_MAPPER_RUN, nativeLangShortcutMapperMacro.c_str()); + ::InsertMenu(hRunMenu, posBase + nbTopLevelItem + 2, MF_BYCOMMAND, IDM_SETTING_SHORTCUT_MAPPER_RUN, nativeLangShortcutMapperMacro.c_str()); } nppParams.getAccelerator()->updateShortcuts(); nppParams.setShortcutDirty();