Make Run menu organizable with sub-menu
This commit uses the same mechanism (8e85110b5e
) for organization of macro menu:
Add attribute `FolderName="sub-menu name"` in "Command" node to have the sub-menu.
Close #12617
This commit is contained in:
parent
8e85110b5e
commit
f1e1f6be87
|
@ -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<UINT>(-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<UINT>(-1), 0);
|
||||
|
||||
macroMenuItems.attach(hMacroMenu, macroPosBase, IDM_SETTING_SHORTCUT_MAPPER_MACRO, TEXT("Modify Shortcut/Delete Macro..."));
|
||||
|
||||
|
||||
// Run Menu
|
||||
std::vector<UserCommand> & 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<UINT>(-1), 0);
|
||||
|
||||
for (size_t i = 0; i < nbUserCommand; ++i)
|
||||
{
|
||||
::InsertMenu(hRunMenu, static_cast<UINT>(runPosBase + i), MF_BYPOSITION, ID_USER_CMD + i, userCommands[i].toMenuItemString().c_str());
|
||||
}
|
||||
|
||||
if (nbUserCommand >= 1)
|
||||
{
|
||||
::InsertMenu(hRunMenu, static_cast<UINT>(runPosBase + nbUserCommand + 1), MF_BYPOSITION, static_cast<UINT>(-1), 0);
|
||||
::InsertMenu(hRunMenu, static_cast<UINT>(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<UINT>(-1), 0); //no separator yet, add one
|
||||
::InsertMenu(hMacroMenu, posBase - 1, MF_BYPOSITION, static_cast<UINT>(-1), 0); //no separator yet, add one
|
||||
|
||||
// Insert the separator and modify/delete command
|
||||
::InsertMenu(hMacroMenu, posBase + nbTopLevelItem + 1, MF_BYPOSITION, static_cast<UINT>(-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<UINT>(posBase + nbTopLevelItem), MF_BYPOSITION, cmdID, ms.toMenuItemString().c_str());
|
||||
_accelerator.updateShortcuts();
|
||||
nppParams.setShortcutDirty();
|
||||
return true;
|
||||
|
|
|
@ -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<int32_t>(_posBase + i), MF_BYPOSITION | MF_SEPARATOR, 0, nullptr);
|
||||
::InsertMenu(_hMenu, static_cast<UINT>(_posBase + i + 2), MF_BYCOMMAND, IDM_SETTING_SHORTCUT_MAPPER_MACRO, TEXT("Modify Shortcut/Delete Macro..."));
|
||||
::InsertMenu(_hMenu, static_cast<UINT>(_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<int32_t>(_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<int32_t>(_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"));
|
||||
|
|
|
@ -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<MenuItemUnit> _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<MenuItemUnit>& getContextMenuItems() { return _contextMenuItems; };
|
||||
std::vector<MenuItemUnit>& 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<MenuItemUnit> _contextMenuItems;
|
||||
std::vector<MenuItemUnit> _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);
|
||||
|
|
|
@ -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<MacroShortcut> & theMacros = nppParam.getMacroList();
|
||||
vector<MacroShortcut>::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<HMENU>(::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<UserCommand> & theUserCmds = nppParam.getUserCommandList();
|
||||
vector<UserCommand>::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<HMENU>(::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<HMENU>(::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<int32_t>(nbElem), MF_BYPOSITION);
|
||||
|
||||
int32_t posBase = runMenu.getPosBase();
|
||||
if (nbElem == 0)
|
||||
{
|
||||
::RemoveMenu(hMenu, IDM_SETTING_SHORTCUT_MAPPER_RUN, MF_BYCOMMAND);
|
||||
|
|
|
@ -327,11 +327,15 @@ intptr_t CALLBACK RunDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam
|
|||
|
||||
case IDC_BUTTON_SAVE :
|
||||
{
|
||||
std::vector<UserCommand> & theUserCmds = (NppParameters::getInstance()).getUserCommandList();
|
||||
NppParameters& nppParams = NppParameters::getInstance();
|
||||
std::vector<UserCommand> & theUserCmds = nppParams.getUserCommandList();
|
||||
|
||||
int nbCmd = static_cast<int32_t>(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<HMENU>(::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<unsigned int>(-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<unsigned int>(-1), 0);
|
||||
::InsertMenu(hRunMenu, posBase + nbTopLevelItem + 1, MF_BYPOSITION, static_cast<unsigned int>(-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();
|
||||
|
|
Loading…
Reference in New Issue