From 12f649bf5410af293eecd61cec24c95b1dcb195d Mon Sep 17 00:00:00 2001 From: Don Ho Date: Fri, 10 Mar 2023 18:54:12 +0100 Subject: [PATCH] Add ability to copy "Find what" to "Replace with" and vice versa This feature use the same swap button for new added actions: Use mouse right click on swap button to have popup menu for toggling among "Swap Replace with Find", "Copy from Find to Replace" and "Copy from Replace to Find". Related to #12195 Fix #12122, close #13332 --- PowerEditor/installer/nativeLang/english.xml | 11 +- PowerEditor/installer/nativeLang/french.xml | 11 +- .../nativeLang/taiwaneseMandarin.xml | 11 +- .../src/ScintillaComponent/FindReplaceDlg.cpp | 114 +++++++++++++++++- .../src/ScintillaComponent/FindReplaceDlg.h | 11 ++ .../ScintillaComponent/FindReplaceDlg_rc.h | 4 + .../WinControls/FileBrowser/fileBrowser.cpp | 20 +-- PowerEditor/src/localization.cpp | 12 +- PowerEditor/src/localization.h | 2 +- 9 files changed, 168 insertions(+), 28 deletions(-) diff --git a/PowerEditor/installer/nativeLang/english.xml b/PowerEditor/installer/nativeLang/english.xml index 16fb5554e..2e356b507 100644 --- a/PowerEditor/installer/nativeLang/english.xml +++ b/PowerEditor/installer/nativeLang/english.xml @@ -3,7 +3,7 @@ The comments are here for explanation, it's not necessary to translate them. --> - +
@@ -475,6 +475,11 @@ The comments are here for explanation, it's not necessary to translate them. + + + + + @@ -1476,7 +1481,7 @@ Do you want to save your changes before switching themes?"/> - +
@@ -469,6 +469,11 @@ The comments are here for explanation, it's not necessary to translate them. + + + + + @@ -1470,7 +1475,7 @@ Voulez-vous enregistrer vos modifications avant de changer de thème ?"/> @@ -455,6 +455,11 @@ + + + + + @@ -1375,7 +1380,7 @@ - + @@ -1385,7 +1390,7 @@ - + diff --git a/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp b/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp index 4befb72fd..b8e010823 100644 --- a/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp +++ b/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp @@ -77,6 +77,22 @@ void delLeftWordInEdit(HWND hEdit) } } +LRESULT run_swapButtonProc(WNDPROC oldEditProc, HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_RBUTTONUP: + { + ::SendMessage(GetParent(hwnd), message, wParam, lParam); + break; + } + + default: + break; + } + return ::CallWindowProc(oldEditProc, hwnd, message, wParam, lParam); +} + int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int length) { //query may equal to result, since it always gets smaller int i = 0, j = 0; @@ -1379,12 +1395,17 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA ::SetWindowTextW(::GetDlgItem(_hSelf, IDC_FINDPREV), TEXT("▲")); ::SetWindowTextW(::GetDlgItem(_hSelf, IDC_FINDNEXT), TEXT("▼ Find Next")); - ::SetWindowTextW(::GetDlgItem(_hSelf, IDD_FINDREPLACE_SWAP_BUTTON), TEXT("⇅")); + + _hSwapButton = ::GetDlgItem(_hSelf, IDD_FINDREPLACE_SWAP_BUTTON); + ::SetWindowLongPtr(_hSwapButton, GWLP_USERDATA, reinterpret_cast(this)); + _oldSwapButtonProc = reinterpret_cast(::SetWindowLongPtr(_hSwapButton, GWLP_WNDPROC, reinterpret_cast(swapButtonProc))); + ::SetWindowTextW(_hSwapButton, TEXT("⇅")); + ::SetWindowTextW(::GetDlgItem(_hSelf, IDD_RESIZE_TOGGLE_BUTTON), TEXT("˄")); // "⇅" enlargement _hLargerBolderFont = createFont(TEXT("Courier New"), 14, true, _hSelf); - SendMessage(::GetDlgItem(_hSelf, IDD_FINDREPLACE_SWAP_BUTTON), WM_SETFONT, (WPARAM)_hLargerBolderFont, MAKELPARAM(true, 0)); + SendMessage(_hSwapButton, WM_SETFONT, (WPARAM)_hLargerBolderFont, MAKELPARAM(true, 0)); // Make "˄" & "˅" look better _hCourrierNewFont = createFont(TEXT("Courier New"), 12, false, _hSelf); @@ -1393,6 +1414,34 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA return TRUE; } + case WM_RBUTTONUP: + { + if (!_swapPopupMenu.isCreated()) + { + + vector itemUnitArray; + itemUnitArray.push_back(MenuItemUnit(IDC_SWAP_FIND_REPLACE, TEXT("⇅ Swap Find with Replace"))); + itemUnitArray.push_back(MenuItemUnit(IDC_COPY_FIND2REPLACE, TEXT("⤵ Copy from Find to Replace"))); + itemUnitArray.push_back(MenuItemUnit(IDC_COPY_REPLACE2FIND, TEXT("⤴ Copy from Replace to Find"))); + + NativeLangSpeaker* pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker(); + for (auto&& i : itemUnitArray) + { + i._itemName = pNativeSpeaker->getDlgLangMenuStr("Dialog", "Find", i._cmdID, i._itemName.c_str()); + } + + _swapPopupMenu.create(_hSelf, itemUnitArray); + } + RECT rc{}; + ::GetClientRect(_hSwapButton, &rc); + POINT p{}; + ::ClientToScreen(_hSwapButton, &p); + p.y += rc.bottom; + _swapPopupMenu.display(p); + + return TRUE; + } + case WM_DRAWITEM : { drawItem((DRAWITEMSTRUCT *)lParam); @@ -1591,6 +1640,42 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA nppParamInst._isFindReplacing = false; } return TRUE; + + case IDC_SWAP_FIND_REPLACE: + { + if (_swapButtonStatus != swap) + { + _swapButtonStatus = swap; + ::SetWindowTextW(_hSwapButton, L"⇅"); + SendMessage(_hSwapButton, WM_SETFONT, (WPARAM)_hLargerBolderFont, MAKELPARAM(true, 0)); + } + ::SendMessage(_hSelf, WM_COMMAND, IDD_FINDREPLACE_SWAP_BUTTON, 0); + return TRUE; + } + + case IDC_COPY_FIND2REPLACE: + { + if (_swapButtonStatus != down) + { + _swapButtonStatus = down; + ::SetWindowTextW(_hSwapButton, L"⤵"); + SendMessage(_hSwapButton, WM_SETFONT, (WPARAM)_hLargerBolderFont, MAKELPARAM(true, 0)); + } + ::SendMessage(_hSelf, WM_COMMAND, IDD_FINDREPLACE_SWAP_BUTTON, 0); + return TRUE; + } + + case IDC_COPY_REPLACE2FIND: + { + if (_swapButtonStatus != up) + { + _swapButtonStatus = up; + ::SetWindowTextW(_hSwapButton, L"⤴"); + SendMessage(_hSwapButton, WM_SETFONT, (WPARAM)_hLargerBolderFont, MAKELPARAM(true, 0)); + } + ::SendMessage(_hSelf, WM_COMMAND, IDD_FINDREPLACE_SWAP_BUTTON, 0); + return TRUE; + } case IDD_FINDREPLACE_SWAP_BUTTON: { @@ -1598,10 +1683,29 @@ intptr_t CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA generic_string findWhatText = getTextFromCombo(hFindWhat); HWND hPlaceWith = ::GetDlgItem(_hSelf, IDREPLACEWITH); generic_string replaceWithText = getTextFromCombo(hPlaceWith); - if ((!findWhatText.empty() || !replaceWithText.empty()) && (findWhatText != replaceWithText)) + + + if (_swapButtonStatus == swap) { - ::SendMessage(hFindWhat, WM_SETTEXT, 0, reinterpret_cast(replaceWithText.c_str())); - ::SendMessage(hPlaceWith, WM_SETTEXT, 0, reinterpret_cast(findWhatText.c_str())); + if ((!findWhatText.empty() || !replaceWithText.empty()) && (findWhatText != replaceWithText)) + { + ::SendMessage(hFindWhat, WM_SETTEXT, 0, reinterpret_cast(replaceWithText.c_str())); + ::SendMessage(hPlaceWith, WM_SETTEXT, 0, reinterpret_cast(findWhatText.c_str())); + } + } + else if (_swapButtonStatus == down) + { + if (!findWhatText.empty() && (findWhatText != replaceWithText)) + { + ::SendMessage(hPlaceWith, WM_SETTEXT, 0, reinterpret_cast(findWhatText.c_str())); + } + } + else // if (_swapButtonStatus == up) + { + if (!replaceWithText.empty() && (findWhatText != replaceWithText)) + { + ::SendMessage(hFindWhat, WM_SETTEXT, 0, reinterpret_cast(replaceWithText.c_str())); + } } } return TRUE; diff --git a/PowerEditor/src/ScintillaComponent/FindReplaceDlg.h b/PowerEditor/src/ScintillaComponent/FindReplaceDlg.h index d16c57464..6e9c919e0 100644 --- a/PowerEditor/src/ScintillaComponent/FindReplaceDlg.h +++ b/PowerEditor/src/ScintillaComponent/FindReplaceDlg.h @@ -238,6 +238,8 @@ private: void writeOptions(); }; +LRESULT run_swapButtonProc(WNDPROC oldEditProc, HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + class FindReplaceDlg : public StaticDialog { friend class FindIncrementDlg; @@ -502,6 +504,15 @@ private : bool replaceInFilesConfirmCheck(generic_string directory, generic_string fileTypes); bool replaceInProjectsConfirmCheck(); bool replaceInOpenDocsConfirmCheck(void); + + ContextMenu _swapPopupMenu; + enum SwapButtonStatus {swap, down, up} _swapButtonStatus = swap; + HWND _hSwapButton = nullptr; + static LRESULT CALLBACK swapButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { + const auto dlg = (FindReplaceDlg*)(::GetWindowLongPtr(hwnd, GWLP_USERDATA)); + return (run_swapButtonProc(dlg->_oldSwapButtonProc, hwnd, message, wParam, lParam)); + }; + WNDPROC _oldSwapButtonProc = nullptr; }; //FindIncrementDlg: incremental search dialog, docked in rebar diff --git a/PowerEditor/src/ScintillaComponent/FindReplaceDlg_rc.h b/PowerEditor/src/ScintillaComponent/FindReplaceDlg_rc.h index c0b75f33f..55c76cca8 100644 --- a/PowerEditor/src/ScintillaComponent/FindReplaceDlg_rc.h +++ b/PowerEditor/src/ScintillaComponent/FindReplaceDlg_rc.h @@ -137,4 +137,8 @@ #define IDC_COPY_MARKED_TEXT 1725 +#define IDC_SWAP_FIND_REPLACE 1726 +#define IDC_COPY_FIND2REPLACE 1727 +#define IDC_COPY_REPLACE2FIND 1728 + #endif //FINDREPLACE_DLG_H diff --git a/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp b/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp index 48dd00da3..caebc264f 100644 --- a/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp +++ b/PowerEditor/src/WinControls/FileBrowser/fileBrowser.cpp @@ -329,16 +329,16 @@ void FileBrowser::initPopupMenus() { NativeLangSpeaker* pNativeSpeaker = NppParameters::getInstance().getNativeLangSpeaker(); - generic_string addRoot = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_ADDROOT, FB_ADDROOT); - generic_string removeAllRoot = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_REMOVEALLROOTS, FB_REMOVEALLROOTS); - generic_string removeRootFolder = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_REMOVEROOTFOLDER, FB_REMOVEROOTFOLDER); - generic_string copyPath = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_COPYPATH, FB_COPYPATH); - generic_string copyFileName = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_COPYFILENAME, FB_COPYFILENAME); - generic_string findInFile = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_FINDINFILES, FB_FINDINFILES); - generic_string explorerHere = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_EXPLORERHERE, FB_EXPLORERHERE); - generic_string cmdHere = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_CMDHERE, FB_CMDHERE); - generic_string openInNpp = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_OPENINNPP, FB_OPENINNPP); - generic_string shellExecute = pNativeSpeaker->getFileBrowserLangMenuStr(IDM_FILEBROWSER_SHELLEXECUTE, FB_SHELLEXECUTE); + generic_string addRoot = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_ADDROOT, FB_ADDROOT); + generic_string removeAllRoot = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_REMOVEALLROOTS, FB_REMOVEALLROOTS); + generic_string removeRootFolder = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_REMOVEROOTFOLDER, FB_REMOVEROOTFOLDER); + generic_string copyPath = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_COPYPATH, FB_COPYPATH); + generic_string copyFileName = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_COPYFILENAME, FB_COPYFILENAME); + generic_string findInFile = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_FINDINFILES, FB_FINDINFILES); + generic_string explorerHere = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_EXPLORERHERE, FB_EXPLORERHERE); + generic_string cmdHere = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_CMDHERE, FB_CMDHERE); + generic_string openInNpp = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_OPENINNPP, FB_OPENINNPP); + generic_string shellExecute = pNativeSpeaker->getDlgLangMenuStr(FOLDERASWORKSPACE_NODE, nullptr, IDM_FILEBROWSER_SHELLEXECUTE, FB_SHELLEXECUTE); _hGlobalMenu = ::CreatePopupMenu(); ::InsertMenu(_hGlobalMenu, 0, MF_BYCOMMAND, IDM_FILEBROWSER_ADDROOT, addRoot.c_str()); diff --git a/PowerEditor/src/localization.cpp b/PowerEditor/src/localization.cpp index 7ce04c8da..3526103d3 100644 --- a/PowerEditor/src/localization.cpp +++ b/PowerEditor/src/localization.cpp @@ -1277,14 +1277,20 @@ bool NativeLangSpeaker::getMsgBoxLang(const char *msgBoxTagName, generic_string return false; } -generic_string NativeLangSpeaker::getFileBrowserLangMenuStr(int cmdID, const TCHAR *defaultStr) const +generic_string NativeLangSpeaker::getDlgLangMenuStr(const char* firstLevelNodeName, const char* secondLevelNodeName, int cmdID, const TCHAR* defaultStr) const { if (!_nativeLangA) return defaultStr; - TiXmlNodeA *targetNode = _nativeLangA->FirstChild(FOLDERASWORKSPACE_NODE); + TiXmlNodeA *targetNode = _nativeLangA->FirstChild(firstLevelNodeName); if (!targetNode) return defaultStr; - targetNode = targetNode->FirstChild("Menus"); + if (secondLevelNodeName && secondLevelNodeName[0]) + { + targetNode = targetNode->FirstChild(secondLevelNodeName); + if (!targetNode) return defaultStr; + } + + targetNode = targetNode->FirstChild("Menu"); if (!targetNode) return defaultStr; const char *name = NULL; diff --git a/PowerEditor/src/localization.h b/PowerEditor/src/localization.h index 2d3c74d8a..3be14cd35 100644 --- a/PowerEditor/src/localization.h +++ b/PowerEditor/src/localization.h @@ -79,7 +79,7 @@ public: bool getMsgBoxLang(const char *msgBoxTagName, generic_string & title, generic_string & message); generic_string getShortcutMapperLangStr(const char *nodeName, const TCHAR *defaultStr) const; generic_string getProjectPanelLangMenuStr(const char * nodeName, int cmdID, const TCHAR *defaultStr) const; - generic_string getFileBrowserLangMenuStr(int cmdID, const TCHAR *defaultStr) const; + generic_string getDlgLangMenuStr(const char* firstLevelNodeName, const char* secondLevelNodeName, int cmdID, const TCHAR *defaultStr) const; generic_string getAttrNameStr(const TCHAR *defaultStr, const char *nodeL1Name, const char *nodeL2Name, const char *nodeL3Name = "name") const; generic_string getAttrNameByIdStr(const TCHAR *defaultStr, TiXmlNodeA *targetNode, const char *nodeL1Value, const char *nodeL1Name = "id", const char *nodeL2Name = "name") const; generic_string getLocalizedStrFromID(const char *strID, const generic_string& defaultString) const;