Browse Source

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
pull/12624/head
Don Ho 2 years ago
parent
commit
f1e1f6be87
  1. 37
      PowerEditor/src/Notepad_plus.cpp
  2. 27
      PowerEditor/src/Parameters.cpp
  3. 14
      PowerEditor/src/Parameters.h
  4. 47
      PowerEditor/src/WinControls/Grid/ShortcutMapper.cpp
  5. 23
      PowerEditor/src/WinControls/StaticDialog/RunDlg/RunDlg.cpp

37
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<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;

27
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<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"));

14
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<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);

47
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<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);

23
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<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…
Cancel
Save