Make toolbar icons customizale

This is the enhancement of a long time forgotten feature.

To override the current toolbar icons, we needs 2 things: "toolbarIcons.xml" file and one icons set.
Here are the instructions to customize toolbar icons:

1. Put the file "toolbarIcons.xml" (Note 1) in the same folder of "config.xml" file (Note 2).
2. Create a new folder "toolbarIcons" in the folder where you put "toolbarIcons.xml" file.
3. Edit the file "toolbarIcons.xml": put the icon set name you want in "icoFolderName" attribute (Note 3).
   for example: `<ToolBarIcons icoFolderName="myAwesomeIcons" />`
4. Go into "toolbarIcons" folder and create a new folder with the exact name of the icon set name you provided in "icoFolderName".
5. Put all your customized icons into "[toolbarIcons.xml's folder]\toolbarIcons\myAwesomeIcons\".
6. Now it's the magic moment: Relaunch Notepad++ and you'll see your icon set instead of the default icons.

Note:
1. The content of "toolbarIcons.xml" is following:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<NotepadPlus>
    <ToolBarIcons icoFolderName="nppLagacyIcons" />
</NotepadPlus>
```
2. If you find the file "doLocalConf.xml" in the Notepad++ installed directory, you will find the "config.xml" in Notepad++ installed directory. Otherwise it should be in "%APPDATA%\Notepad++\" directory.
3. if "icoFolderName" value is an emptty string, the path of icons will be in "[toolbarIcons.xml's folder]\toolbarIcons\default\" folder.

Each replacing icon (45 icons) has the fixed and specific name:

| index |  Normal icon             |  Disabled icon                  |
|-------|--------------------------|---------------------------------|
|1      |  new.ico                 |                                 |
|2      |  open.ico                |                                 |
|3      |  save.ico                |  save_disabled.ico              |
|4      |  save-all.ico            |  save-all_disabled.ico          |
|5      |  close.ico               |                                 |
|6      |  close-all.ico           |                                 |
|7      |  print.ico               |                                 |
|8      |  cut.ico                 |  cut_disabled.ico               |
|9      |  copy.ico                |  copy_disabled.ico              |
|10     |  paste.ico               |  paste_disabled.ico             |
|11     |  undo.ico                |  undo_disabled.ico              |
|12     |  redo.ico                |  redo_disabled.ico              |
|13     |  find.ico                |                                 |
|14     |  replace.ico             |                                 |
|15     |  zoom-in.ico             |                                 |
|16     |  zoom-out.ico            |                                 |
|17     |  sync-vertical.ico       |                                 |
|18     |  sync-horizontal.ico     |                                 |
|19     |  word-wrap.ico           |                                 |
|20     |  all-chars.ico           |                                 |
|21     |  indent-guide.ico        |                                 |
|22     |  udl-dlg.ico             |                                 |
|23     |  doc-map.ico             |                                 |
|24     |  doc-list.ico            |                                 |
|25     |  function-list.ico       |                                 |
|26     |  folder-as-workspace.ico |                                 |
|27     |  monitoring.ico          |  monitoring_disabled.ico        |
|28     |  record.ico              |  record_disabled.ico            |
|29     |  stop-record.ico         |  stop-record_disabled.ico       |
|30     |  playback.ico            |  playback_disabled.ico          |
|31     |  playback-multiple.ico   |  playback-multiple_disabled.ico |
|32     |  save-macro.ico          |  save-macro_disabled.ico        |

It's not necessary to have all complete set (45 icons). The absent icons won't just be substituted.

Fix #9913
pull/11722/head
Don Ho 3 years ago
parent 05dae4a720
commit d85b9a7464

@ -140,7 +140,7 @@ Notepad_plus::Notepad_plus()
nppParam.setNativeLangSpeaker(&_nativeLangSpeaker);
TiXmlDocument *toolIconsDocRoot = nppParam.getToolIcons();
TiXmlDocument *toolIconsDocRoot = nppParam.getCustomizedToolIcons();
if (toolIconsDocRoot)
{

@ -1469,7 +1469,7 @@ public:
TiXmlDocumentA * getNativeLangA() const {return _pXmlNativeLangDocA;};
TiXmlDocument * getToolIcons() const {return _pXmlToolIconsDoc;};
TiXmlDocument * getCustomizedToolIcons() const {return _pXmlToolIconsDoc;};
bool isTransparentAvailable() const {
return (_transparentFuncAddr != NULL);

@ -58,12 +58,12 @@ void IconList::addIcon(HICON hIcon) const
ImageList_AddIcon(_hImglst, hIcon);
};
bool IconList::changeIcon(int index, const TCHAR *iconLocation) const
bool IconList::changeIcon(size_t index, const TCHAR *iconLocation) const
{
HBITMAP hBmp = (HBITMAP)::LoadImage(_hInst, iconLocation, IMAGE_ICON, _iconSize, _iconSize, LR_LOADFROMFILE | LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT);
if (!hBmp)
return false;
int i = ImageList_ReplaceIcon(_hImglst, index, (HICON)hBmp);
int i = ImageList_ReplaceIcon(_hImglst, int(index), (HICON)hBmp);
ImageList_AddMasked(_hImglst, (HBITMAP)hBmp, RGB(255,0,255));
::DeleteObject(hBmp);
return (i == index);

@ -42,7 +42,7 @@ public :
void addIcon(int iconID) const;
void addIcon(HICON hIcon) const;
bool changeIcon(int index, const TCHAR *iconLocation) const;
bool changeIcon(size_t index, const TCHAR *iconLocation) const;
void addIcons(int size) const;
@ -144,7 +144,7 @@ public :
return _tbiis[i]._stdIcon;
};
bool replaceIcon(int witchList, int iconIndex, const TCHAR *iconLocation) const {
bool replaceIcon(size_t witchList, size_t iconIndex, const TCHAR *iconLocation) const {
if ((witchList != HLIST_DEFAULT) && (witchList != HLIST_DISABLE) &&
(witchList != HLIST_DEFAULT2) && (witchList != HLIST_DISABLE2))
return false;

@ -15,16 +15,56 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <stdexcept>
#include <shlwapi.h>
#include "ToolBar.h"
#include "shortcut.h"
#include "Parameters.h"
#include "FindReplaceDlg_rc.h"
#include "NppDarkMode.h"
#include "resource.h"
const int WS_TOOLBARSTYLE = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS |TBSTYLE_FLAT | CCS_TOP | BTNS_AUTOSIZE | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_NODIVIDER;
struct ToolbarIconIdUnit
{
generic_string _id;
bool hasDisabledIcon = false;
};
ToolbarIconIdUnit toolbarIconIDs[] = {
{ L"new", false },
{ L"open", false },
{ L"save", true },
{ L"save-all", true },
{ L"close", false },
{ L"close-all", false },
{ L"print", false },
{ L"cut", true },
{ L"copy", true },
{ L"paste", true },
{ L"undo", true },
{ L"redo", true },
{ L"find", false },
{ L"replace", false },
{ L"zoom-in", false },
{ L"zoom-out", false },
{ L"sync-vertical", false },
{ L"sync-horizontal", false },
{ L"word-wrap", false },
{ L"all-chars", false },
{ L"indent-guide", false },
{ L"udl-dlg", false },
{ L"doc-map", false },
{ L"doc-list", false },
{ L"function-list", false },
{ L"folder-as-workspace", false },
{ L"monitoring", true },
{ L"record", true },
{ L"stop-record", true },
{ L"playback", true },
{ L"playback-multiple", true },
{ L"save-macro", true }
};
void ToolBar::initTheme(TiXmlDocument *toolIconsDocRoot)
{
_toolIcons = toolIconsDocRoot->FirstChild(TEXT("NotepadPlus"));
@ -33,62 +73,38 @@ void ToolBar::initTheme(TiXmlDocument *toolIconsDocRoot)
_toolIcons = _toolIcons->FirstChild(TEXT("ToolBarIcons"));
if (_toolIcons)
{
_toolIcons = _toolIcons->FirstChild(TEXT("Theme"));
if (_toolIcons)
generic_string iconFolderDir = NppParameters::getInstance().getUserPath();
generic_string toolbarIconsRootFolderName = TEXT("toolbarIcons");
pathAppend(iconFolderDir, toolbarIconsRootFolderName);
generic_string folderName = (_toolIcons->ToElement())->Attribute(TEXT("icoFolderName"));
if (folderName.empty())
folderName = TEXT("default");
pathAppend(iconFolderDir, folderName);
size_t i = 0;
generic_string disabled_suffix = L"_disabled";
generic_string ext = L".ico";
for (ToolbarIconIdUnit icoUnit : toolbarIconIDs)
{
const TCHAR *themeDir = (_toolIcons->ToElement())->Attribute(TEXT("pathPrefix"));
for (TiXmlNode *childNode = _toolIcons->FirstChildElement(TEXT("Icon"));
childNode ;
childNode = childNode->NextSibling(TEXT("Icon")))
generic_string locator = iconFolderDir;
locator += L"\\";
locator += icoUnit._id;
locator += ext;
if (::PathFileExists(locator.c_str()))
_customIconVect.push_back(iconLocator(0, i, locator));
if (icoUnit.hasDisabledIcon)
{
int iIcon;
const TCHAR *res = (childNode->ToElement())->Attribute(TEXT("id"), &iIcon);
if (res)
{
TiXmlNode *grandChildNode = childNode->FirstChildElement(TEXT("normal"));
if (grandChildNode)
{
TiXmlNode *valueNode = grandChildNode->FirstChild();
//putain, enfin!!!
if (valueNode)
{
generic_string locator = themeDir?themeDir:TEXT("");
locator += valueNode->Value();
_customIconVect.push_back(iconLocator(0, iIcon, locator));
}
}
grandChildNode = childNode->FirstChildElement(TEXT("hover"));
if (grandChildNode)
{
TiXmlNode *valueNode = grandChildNode->FirstChild();
//putain, enfin!!!
if (valueNode)
{
generic_string locator = themeDir?themeDir:TEXT("");
locator += valueNode->Value();
_customIconVect.push_back(iconLocator(1, iIcon, locator));
}
}
grandChildNode = childNode->FirstChildElement(TEXT("disabled"));
if (grandChildNode)
{
TiXmlNode *valueNode = grandChildNode->FirstChild();
//putain, enfin!!!
if (valueNode)
{
generic_string locator = themeDir?themeDir:TEXT("");
locator += valueNode->Value();
_customIconVect.push_back(iconLocator(2, iIcon, locator));
}
}
}
generic_string locator_dis = iconFolderDir;
locator_dis += L"\\";
locator_dis += icoUnit._id;
locator_dis += disabled_suffix;
locator_dis += ext;
if (::PathFileExists(locator_dis.c_str()))
_customIconVect.push_back(iconLocator(1, i, locator_dis));
}
i++;
}
}
}
@ -274,16 +290,16 @@ void ToolBar::reset(bool create)
}
_hSelf = ::CreateWindowEx(
WS_EX_PALETTEWINDOW,
TOOLBARCLASSNAME,
TEXT(""),
WS_TOOLBARSTYLE | dwExtraStyle,
0, 0,
0, 0,
_hParent,
NULL,
_hInst,
0);
WS_EX_PALETTEWINDOW,
TOOLBARCLASSNAME,
TEXT(""),
WS_TOOLBARSTYLE | dwExtraStyle,
0, 0,
0, 0,
_hParent,
NULL,
_hInst,
0);
NppDarkMode::setDarkTooltips(_hSelf, NppDarkMode::ToolTipsType::toolbar);
@ -298,66 +314,75 @@ void ToolBar::reset(bool create)
throw std::runtime_error("ToolBar::reset : CreateWindowEx() function return null");
}
if (_state != TB_STANDARD) //If non standard icons, use custom imagelists
bool doOverrideToolbarIcons = _customIconVect.size() > 0;
if (doOverrideToolbarIcons)
{
setDefaultImageList();
setDisableImageList();
}
else // use internal icons according the settings
{
if (_state == TB_SMALL || _state == TB_LARGE)
if (_state != TB_STANDARD) //If non standard icons, use custom imagelists
{
if (NppDarkMode::isEnabled())
if (_state == TB_SMALL || _state == TB_LARGE)
{
setDefaultImageListDM();
setDisableImageListDM();
if (NppDarkMode::isEnabled())
{
setDefaultImageListDM();
setDisableImageListDM();
if (NppDarkMode::isWindows11())
if (NppDarkMode::isWindows11())
{
setHoveredImageListDM();
}
}
else
{
setHoveredImageListDM();
setDefaultImageList();
setDisableImageList();
}
}
else
{
setDefaultImageList();
setDisableImageList();
if (NppDarkMode::isEnabled())
{
setDefaultImageListDM2();
setDisableImageListDM2();
if (NppDarkMode::isWindows11())
{
setHoveredImageListDM2();
}
}
else
{
setDefaultImageList2();
setDisableImageList2();
}
}
}
else
{
if (NppDarkMode::isEnabled())
{
setDefaultImageListDM2();
setDisableImageListDM2();
//Else set the internal imagelist with standard bitmaps
int iconDpiDynamicalSize = NppParameters::getInstance()._dpiManager.scaleX(16);
::SendMessage(_hSelf, TB_SETBITMAPSIZE, 0, MAKELPARAM(iconDpiDynamicalSize, iconDpiDynamicalSize));
if (NppDarkMode::isWindows11())
{
setHoveredImageListDM2();
}
}
else
TBADDBITMAP addbmp = { 0, 0 };
TBADDBITMAP addbmpdyn = { 0, 0 };
for (size_t i = 0; i < _nbButtons; ++i)
{
setDefaultImageList2();
setDisableImageList2();
int icoID = _toolBarIcons.getStdIconAt(static_cast<int32_t>(i));
HBITMAP hBmp = static_cast<HBITMAP>(::LoadImage(_hInst, MAKEINTRESOURCE(icoID), IMAGE_BITMAP, iconDpiDynamicalSize, iconDpiDynamicalSize, LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT));
addbmp.nID = reinterpret_cast<UINT_PTR>(hBmp);
::SendMessage(_hSelf, TB_ADDBITMAP, 1, reinterpret_cast<LPARAM>(&addbmp));
}
}
}
else
{
//Else set the internal imagelist with standard bitmaps
int iconDpiDynamicalSize = NppParameters::getInstance()._dpiManager.scaleX(16);
::SendMessage(_hSelf, TB_SETBITMAPSIZE, 0, MAKELPARAM(iconDpiDynamicalSize, iconDpiDynamicalSize));
TBADDBITMAP addbmp = {0, 0};
TBADDBITMAP addbmpdyn = {0, 0};
for (size_t i = 0 ; i < _nbButtons ; ++i)
{
int icoID = _toolBarIcons.getStdIconAt(static_cast<int32_t>(i));
HBITMAP hBmp = static_cast<HBITMAP>(::LoadImage(_hInst, MAKEINTRESOURCE(icoID), IMAGE_BITMAP, iconDpiDynamicalSize, iconDpiDynamicalSize, LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT));
addbmp.nID = reinterpret_cast<UINT_PTR>(hBmp);
::SendMessage(_hSelf, TB_ADDBITMAP, 1, reinterpret_cast<LPARAM>(&addbmp));
}
if (_nbDynButtons > 0)
{
for (size_t j = 0; j < _nbDynButtons; ++j)
if (_nbDynButtons > 0)
{
addbmpdyn.nID = reinterpret_cast<UINT_PTR>(_vDynBtnReg.at(j)._hBmp);
::SendMessage(_hSelf, TB_ADDBITMAP, 1, reinterpret_cast<LPARAM>(&addbmpdyn));
for (size_t j = 0; j < _nbDynButtons; ++j)
{
addbmpdyn.nID = reinterpret_cast<UINT_PTR>(_vDynBtnReg.at(j)._hBmp);
::SendMessage(_hSelf, TB_ADDBITMAP, 1, reinterpret_cast<LPARAM>(&addbmpdyn));
}
}
}
}

@ -34,12 +34,12 @@ enum toolBarStatusType {TB_SMALL, TB_LARGE, TB_SMALL2, TB_LARGE2, TB_STANDARD};
struct iconLocator {
int listIndex = 0;
int iconIndex = 0;
generic_string iconLocation;
size_t _listIndex = 0;
size_t _iconIndex = 0;
generic_string _iconLocation;
iconLocator(int iList, int iIcon, const generic_string& iconLoc)
: listIndex(iList), iconIndex(iIcon), iconLocation(iconLoc){};
iconLocator(size_t iList, size_t iIcon, const generic_string& iconLoc)
: _listIndex(iList), _iconIndex(iIcon), _iconLocation(iconLoc){};
};
class ReBar;
@ -86,11 +86,11 @@ public :
if (!_toolIcons) return false;
for (size_t i = 0, len = _customIconVect.size(); i < len; ++i)
changeIcons(_customIconVect[i].listIndex, _customIconVect[i].iconIndex, (_customIconVect[i].iconLocation).c_str());
changeIcons(_customIconVect[i]._listIndex, _customIconVect[i]._iconIndex, (_customIconVect[i]._iconLocation).c_str());
return true;
};
bool changeIcons(int whichLst, int iconIndex, const TCHAR *iconLocation){
bool changeIcons(size_t whichLst, size_t iconIndex, const TCHAR *iconLocation){
return _toolBarIcons.replaceIcon(whichLst, iconIndex, iconLocation);
};

@ -1,94 +1,59 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
This file is for customizing your toolbar icons.
To override the current toolbar icons, you needs 2 things: this file and your icons set.
Here are the instructions to customize your toolbar icons:
1. Put this file ("toolbarIcons.xml") in the same folder of "config.xml" file (Note 1).
2. Create a new folder "toolbarIcons" in the folder where you put "toolbarIcons.xml" file.
3. Edit this file ("toolbarIcons.xml"): put the icon set name you want in "icoFolderName" attribute (Note 2).
for example: <ToolBarIcons icoFolderName="myAwesomeIcons" />
4. Go into "toolbarIcons" folder and create a new folder with the exact name of the icon set name you provided in "icoFolderName".
5. Put all your customized icons into "[toolbarIcons.xml's folder]\toolbarIcons\myAwesomeIcons\".
6. Now it's the magic moment: Relaunch Notepad++ and you'll see your icon set instead of the default icons.
Note:
1. If you find the file "doLocalConf.xml" in the Notepad++ installed directory, you will find the "config.xml" in Notepad++ installed directory. Otherwise it should be in "%APPDATA%\Notepad++\" directory.
2. if "icoFolderName" value is an emptty string, the path of icons will be in "[toolbarIcons.xml's folder]\toolbarIcons\default\" folder.
Each replacing icon (45 icons) has the fixed and specific name:
1 new.ico
2 open.ico
3 save.ico save_disabled.ico
4 save-all.ico save-all_disabled.ico
5 close.ico
6 close-all.ico
7 print.ico
8 cut.ico cut_disabled.ico
9 copy.ico copy_disabled.ico
10 paste.ico paste_disabled.ico
12 redo.ico redo_disabled.ico
11 undo.ico undo_disabled.ico
13 find.ico
14 replace.ico
15 zoom-in.ico
16 zoom-out.ico
17 sync-vertical.ico
18 sync-horizontal.ico
19 word-wrap.ico
20 all-chars.ico
21 indent-guide.ico
22 udl-dlg.ico
23 doc-map.ico
24 doc-list.ico
25 function-list.ico
26 folder-as-workspace.ico
27 monitoring.ico monitoring_disabled.ico
28 record.ico record_disabled.ico
29 stop-record.ico stop-record_disabled.ico
30 playback.ico playback_disabled.ico
31 playback-multiple.ico playback-multiple_disabled.ico
32 save-macro.ico save-macro_disabled.ico
It's not necessary to have all complete set (45 icons). The absent icons won't just be substituted.
-->
<NotepadPlus>
<ToolBarIcons>
<Theme name = "virgin" pathPrefix = "">
<Icon name = "new" id = "0">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "open" id = "1">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "save" id = "2">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "save all" id = "3">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "close" id = "4">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "close all" id = "5">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "cut" id = "6">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "copy" id = "7">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "paste" id = "8">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "undo" id = "9">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "redo" id = "10">
<normal></normal>
<hover></hover>
<disabled></disabled>
</Icon>
<Icon name = "find" id = "11">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "replace" id = "12">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "zoom in" id = "13">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "zoom out" id = "14">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "wrap text" id = "15">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "invisible char" id = "16">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "indent guideline" id = "17">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "user language define panel" id = "18">
<normal></normal>
<hover></hover>
</Icon>
<Icon name = "print" id = "19">
<normal></normal>
<hover></hover>
</Icon>
</Theme>
</ToolBarIcons>
</NotepadPlus>
<ToolBarIcons icoFolderName="" />
</NotepadPlus>
Loading…
Cancel
Save