diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index 5c0122fc1..9a71dcf54 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -241,7 +241,7 @@ LRESULT Notepad_plus::init(HWND hwnd) const ScintillaViewParams & svp = nppParam.getSVP(); - int tabBarStatus = nppGUI._tabStatus; + size_t tabBarStatus = nppGUI._tabStatus; TabBarPlus::setReduced((tabBarStatus & TAB_REDUCE) != 0, &_mainDocTab); const int tabIconSet = NppDarkMode::getTabIconSet(NppDarkMode::isEnabled()); @@ -415,6 +415,7 @@ LRESULT Notepad_plus::init(HWND hwnd) TabBarPlus::setDrawInactiveTab((tabBarStatus & TAB_DRAWINACTIVETAB) != 0, &_mainDocTab); TabBarPlus::setDrawTabCloseButton((tabBarStatus & TAB_CLOSEBUTTON) != 0, &_mainDocTab); TabBarPlus::setDrawTabPinButton((tabBarStatus & TAB_PINBUTTON) != 0, &_mainDocTab); + TabBarPlus::setPutTabPinButtonInFront((tabBarStatus & TAB_PUTPINBUTTONINFRONT) != 0); TabBarPlus::setDbClk2Close((tabBarStatus & TAB_DBCLK2CLOSE) != 0); TabBarPlus::setVertical((tabBarStatus & TAB_VERTICAL) != 0); drawTabbarColoursFromStylerArray(); @@ -913,6 +914,7 @@ bool Notepad_plus::saveGUIParams() (TabBarPlus::isReduced() ? TAB_REDUCE : 0) | \ (TabBarPlus::drawTabCloseButton() ? TAB_CLOSEBUTTON : 0) | \ (TabBarPlus::drawTabPinButton() ? TAB_PINBUTTON : 0) | \ + (TabBarPlus::pinButtonInFront() ? TAB_PUTPINBUTTONINFRONT : 0) | \ (TabBarPlus::isDbClk2Close() ? TAB_DBCLK2CLOSE : 0) | \ (TabBarPlus::isVertical() ? TAB_VERTICAL : 0) | \ (TabBarPlus::isMultiLine() ? TAB_MULTILINE : 0) |\ @@ -7358,7 +7360,7 @@ void Notepad_plus::launchDocumentListPanel(bool changeFromBtnCmd) if (!_pDocumentListPanel) { NppParameters& nppParams = NppParameters::getInstance(); - int tabBarStatus = nppParams.getNppGUI()._tabStatus; + size_t tabBarStatus = nppParams.getNppGUI()._tabStatus; _pDocumentListPanel = new VerticalFileSwitcher; diff --git a/PowerEditor/src/Notepad_plus_Window.cpp b/PowerEditor/src/Notepad_plus_Window.cpp index 4c2f5cc06..a46fd6f1b 100644 --- a/PowerEditor/src/Notepad_plus_Window.cpp +++ b/PowerEditor/src/Notepad_plus_Window.cpp @@ -153,7 +153,7 @@ void Notepad_plus_Window::init(HINSTANCE hInst, HWND parent, const wchar_t *cmdL if (cmdLineParams->_isNoTab || (nppGUI._tabStatus & TAB_HIDE)) { - const int tabStatusOld = nppGUI._tabStatus; + const size_t tabStatusOld = nppGUI._tabStatus; ::SendMessage(_hSelf, NPPM_HIDETABBAR, 0, TRUE); if (cmdLineParams->_isNoTab) { diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp index 01c988afc..3fb2f56ed 100644 --- a/PowerEditor/src/NppBigSwitch.cpp +++ b/PowerEditor/src/NppBigSwitch.cpp @@ -4099,7 +4099,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } case NPPM_INTERNAL_DRAWINACTIVETABBARBUTTON: + case NPPM_INTERNAL_PUTTABPINBUTTONINFRONT: { + if (message == NPPM_INTERNAL_PUTTABPINBUTTONINFRONT) + TabBarPlus::setPutTabPinButtonInFront(!TabBarPlus::pinButtonInFront()); + ::SendMessage(_mainDocTab.getHSelf(), NPPM_INTERNAL_REFRESHDARKMODE, 0, 0); ::SendMessage(_subDocTab.getHSelf(), NPPM_INTERNAL_REFRESHDARKMODE, 0, 0); diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 64ce26772..8666a1102 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -4879,7 +4879,7 @@ void NppParameters::feedGUIParameters(TiXmlNode *node) else if (!lstrcmp(nm, L"TabBar")) { bool isFailed = false; - int oldValue = _nppGUI._tabStatus; + size_t oldValue = _nppGUI._tabStatus; const wchar_t* val = element->Attribute(L"dragAndDrop"); if (val) { @@ -4950,6 +4950,17 @@ void NppParameters::feedGUIParameters(TiXmlNode *node) _nppGUI._tabStatus |= TAB_PINBUTTON; } + val = element->Attribute(L"putPinButtonInFront"); + if (val) + { + if (!lstrcmp(val, L"yes")) + _nppGUI._tabStatus |= TAB_PUTPINBUTTONINFRONT; + else if (!lstrcmp(val, L"no")) + _nppGUI._tabStatus |= 0; + else + isFailed = true; + } + val = element->Attribute(L"buttonsOninactiveTabs"); if (val) { @@ -7295,7 +7306,7 @@ void NppParameters::createXmlTreeFromGUIParams() GUIConfigElement->InsertEndChild(TiXmlText(pStr)); } - // + // { TiXmlElement *GUIConfigElement = (newGUIRoot->InsertEndChild(TiXmlElement(L"GUIConfig")))->ToElement(); GUIConfigElement->SetAttribute(L"name", L"TabBar"); @@ -7318,6 +7329,9 @@ void NppParameters::createXmlTreeFromGUIParams() pStr = (_nppGUI._tabStatus & TAB_PINBUTTON) ? L"yes" : L"no"; GUIConfigElement->SetAttribute(L"pinButton", pStr); + pStr = (_nppGUI._tabStatus & TAB_PUTPINBUTTONINFRONT) ? L"yes" : L"no"; + GUIConfigElement->SetAttribute(L"putPinButtonInFront", pStr); + pStr = (_nppGUI._tabStatus & TAB_INACTIVETABSHOWBUTTON) ? L"yes" : L"no"; GUIConfigElement->SetAttribute(L"buttonsOninactiveTabs", pStr); diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 89a2a90f1..02390e9c9 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -77,6 +77,7 @@ const int TAB_QUITONEMPTY = 512; // 0000 0010 0000 0000 const int TAB_ALTICONS = 1024; // 0000 0100 0000 0000 const int TAB_PINBUTTON = 2048; // 0000 1000 0000 0000 const int TAB_INACTIVETABSHOWBUTTON = 4096; // 0001 0000 0000 0000 +const int TAB_PUTPINBUTTONINFRONT = 8192; // 0010 0000 0000 0000 const bool activeText = true; const bool activeNumeric = false; @@ -795,7 +796,7 @@ struct NppGUI final bool _statusBarShow = true; bool _menuBarShow = true; - int _tabStatus = (TAB_DRAWTOPBAR | TAB_DRAWINACTIVETAB | TAB_DRAGNDROP | TAB_REDUCE | TAB_CLOSEBUTTON | TAB_PINBUTTON); + size_t _tabStatus = (TAB_DRAWTOPBAR | TAB_DRAWINACTIVETAB | TAB_DRAGNDROP | TAB_REDUCE | TAB_CLOSEBUTTON | TAB_PINBUTTON); bool _splitterPos = POS_VERTICAL; int _userDefineDlgStatus = UDD_DOCKED; diff --git a/PowerEditor/src/WinControls/Preference/preference.rc b/PowerEditor/src/WinControls/Preference/preference.rc index e598afafa..77bedd14e 100644 --- a/PowerEditor/src/WinControls/Preference/preference.rc +++ b/PowerEditor/src/WinControls/Preference/preference.rc @@ -57,19 +57,20 @@ BEGIN CONTROL "Hide",IDC_CHECK_HIDESTATUSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,179,174,10 GROUPBOX "Tab Bar",IDC_TABBAR_GB_STATIC,235,0,177,195,BS_CENTER - CONTROL "Hide",IDC_CHECK_TAB_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,15,100,10 - CONTROL "Multi-line",IDC_CHECK_TAB_MULTILINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,28,164,10 - CONTROL "Vertical",IDC_CHECK_TAB_VERTICAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,41,164,10 - CONTROL "Reduce",IDC_CHECK_REDUCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,54,164,10 - CONTROL "Alternate icons",IDC_CHECK_TAB_ALTICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,67,164,10 - CONTROL "Lock (no drag and drop)",IDC_CHECK_LOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,80,164,10 - CONTROL "Change inactive tab color",IDC_CHECK_DRAWINACTIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,93,164,10 - CONTROL "Draw a coloured bar on active tab",IDC_CHECK_ORANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,106,164,10 - CONTROL "Show close button",IDC_CHECK_ENABLETABCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,119,164,10 - CONTROL "Enable pin tab feature",IDC_CHECK_ENABLETABPIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,132,164,10 - CONTROL "Show buttons on inactive tabs",IDC_CHECK_INACTTABDRAWBUTTON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,145,164,10 - CONTROL "Double click to close document",IDC_CHECK_DBCLICK2CLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,158,164,10 - CONTROL "Exit on close the last tab",IDC_CHECK_TAB_LAST_EXIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,171,164,10 + CONTROL "Hide",IDC_CHECK_TAB_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,10,100,10 + CONTROL "Multi-line",IDC_CHECK_TAB_MULTILINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,23,164,10 + CONTROL "Vertical",IDC_CHECK_TAB_VERTICAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,36,164,10 + CONTROL "Reduce",IDC_CHECK_REDUCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,49,164,10 + CONTROL "Alternate icons",IDC_CHECK_TAB_ALTICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,62,164,10 + CONTROL "Lock (no drag and drop)",IDC_CHECK_LOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,75,164,10 + CONTROL "Change inactive tab color",IDC_CHECK_DRAWINACTIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,88,164,10 + CONTROL "Draw a coloured bar on active tab",IDC_CHECK_ORANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,101,164,10 + CONTROL "Show close button",IDC_CHECK_ENABLETABCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,114,164,10 + CONTROL "Enable pin tab feature",IDC_CHECK_ENABLETABPIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,127,164,10 + CONTROL "Put pin in front",IDC_CHECK_PUTPININFRONT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,140,164,10 + CONTROL "Show buttons on inactive tabs",IDC_CHECK_INACTTABDRAWBUTTON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,153,164,10 + CONTROL "Double click to close document",IDC_CHECK_DBCLICK2CLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,166,164,10 + CONTROL "Exit on close the last tab",IDC_CHECK_TAB_LAST_EXIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,241,179,164,10 END IDD_PREFERENCE_SUB_EDITING DIALOGEX 115, 10, 460, 205 diff --git a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp index 13409f709..0c0af7e9d 100644 --- a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp +++ b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp @@ -580,7 +580,7 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM { NppGUI & nppGUI = nppParam.getNppGUI(); toolBarStatusType tbStatus = nppGUI._toolBarStatus; - int tabBarStatus = nppGUI._tabStatus; + size_t tabBarStatus = nppGUI._tabStatus; bool showTool = nppGUI._toolbarShow; bool showStatus = nppGUI._statusBarShow; bool showMenu = nppGUI._menuBarShow; @@ -615,10 +615,12 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM bool showCloseButton = tabBarStatus & TAB_CLOSEBUTTON; bool enablePinButton = tabBarStatus & TAB_PINBUTTON; + bool putPinButtonInFront = tabBarStatus & TAB_PUTPINBUTTONINFRONT; bool showButtonOnInactiveTabs = tabBarStatus & TAB_INACTIVETABSHOWBUTTON; ::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLETABCLOSE, BM_SETCHECK, showCloseButton, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLETABPIN, BM_SETCHECK, enablePinButton, 0); + ::SendDlgItemMessage(_hSelf, IDC_CHECK_PUTPININFRONT, BM_SETCHECK, putPinButtonInFront, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_INACTTABDRAWBUTTON, BM_SETCHECK, showButtonOnInactiveTabs, 0); if (!(showCloseButton || enablePinButton)) @@ -628,6 +630,11 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_INACTTABDRAWBUTTON), FALSE); } + if (!enablePinButton) + { + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_PUTPININFRONT), FALSE); + } + ::SendDlgItemMessage(_hSelf, IDC_CHECK_DBCLICK2CLOSE, BM_SETCHECK, tabBarStatus & TAB_DBCLK2CLOSE, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_TAB_VERTICAL, BM_SETCHECK, tabBarStatus & TAB_VERTICAL, 0); ::SendDlgItemMessage(_hSelf, IDC_CHECK_TAB_MULTILINE, BM_SETCHECK, tabBarStatus & TAB_MULTILINE, 0); @@ -734,6 +741,8 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_DRAWINACTIVE), !toBeHidden); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_ENABLETABCLOSE), !toBeHidden); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_ENABLETABPIN), !toBeHidden); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_PUTPININFRONT), !toBeHidden); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_INACTTABDRAWBUTTON), !toBeHidden); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_DBCLICK2CLOSE), !toBeHidden); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_TAB_LAST_EXIT), !toBeHidden); ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_TAB_ALTICONS), !toBeHidden); @@ -800,7 +809,11 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM ::SendDlgItemMessage(_hSelf, IDC_CHECK_INACTTABDRAWBUTTON, BM_SETCHECK, FALSE, 0); ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_DRAWINACTIVETABBARBUTTON, 0, 0); } - ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_INACTTABDRAWBUTTON), showCloseButton || enablePinButton); + + if (wParam == IDC_CHECK_ENABLETABPIN) + { + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_PUTPININFRONT), enablePinButton); + } return TRUE; } @@ -818,6 +831,19 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM return TRUE; } + case IDC_CHECK_PUTPININFRONT: + { + const bool isChecked = isCheckedOrNot(IDC_CHECK_PUTPININFRONT); + NppGUI& nppgui = nppParam.getNppGUI(); + if (isChecked) + nppgui._tabStatus |= TAB_PUTPINBUTTONINFRONT; + else + nppgui._tabStatus &= ~TAB_PUTPINBUTTONINFRONT; + + ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_PUTTABPINBUTTONINFRONT, 0, 0); + return TRUE; + } + case IDC_CHECK_DBCLICK2CLOSE : ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_TABDBCLK2CLOSE, 0, 0); return TRUE; diff --git a/PowerEditor/src/WinControls/Preference/preference_rc.h b/PowerEditor/src/WinControls/Preference/preference_rc.h index 28a7687f3..b5071de04 100644 --- a/PowerEditor/src/WinControls/Preference/preference_rc.h +++ b/PowerEditor/src/WinControls/Preference/preference_rc.h @@ -57,6 +57,7 @@ #define IDC_CHECK_HIDERIGHTSHORTCUTSOFMENUBAR (IDD_PREFERENCE_SUB_GENRAL + 32) #define IDC_STATUSBAR_GB_STATIC (IDD_PREFERENCE_SUB_GENRAL + 33) #define IDC_CHECK_HIDESTATUSBAR (IDD_PREFERENCE_SUB_GENRAL + 34) + #define IDC_CHECK_PUTPININFRONT (IDD_PREFERENCE_SUB_GENRAL + 35) #define IDD_PREFERENCE_SUB_MULTIINSTANCE 6150 //(IDD_PREFERENCE_BOX + 150) #define IDC_MULTIINST_GB_STATIC (IDD_PREFERENCE_SUB_MULTIINSTANCE + 1) diff --git a/PowerEditor/src/WinControls/TabBar/TabBar.cpp b/PowerEditor/src/WinControls/TabBar/TabBar.cpp index 3aec5e74e..9a9d9d43e 100644 --- a/PowerEditor/src/WinControls/TabBar/TabBar.cpp +++ b/PowerEditor/src/WinControls/TabBar/TabBar.cpp @@ -31,6 +31,7 @@ bool TabBarPlus::_drawTopBar = true; bool TabBarPlus::_drawInactiveTab = true; bool TabBarPlus::_drawTabCloseButton = true; bool TabBarPlus::_drawTabPinButton = true; +bool TabBarPlus::_pinButtonInFront = false; bool TabBarPlus::_isDbClk2Close = false; bool TabBarPlus::_isCtrlVertical = false; bool TabBarPlus::_isCtrlMultiLine = false; @@ -822,7 +823,15 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara if (_drawTabPinButton) { - if (_pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical)) + int imageSize = 0; + if (_pinButtonInFront) + { + RECT imageRect{}; + getImageRectFromImglst(imageRect); + imageSize = imageRect.right - imageRect.left; + } + + if (_pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical, imageSize)) { _whichPinClickDown = getTabIndexAt(xPos, yPos); ::SendMessage(_hParent, WM_SIZE, 0, 0); @@ -992,8 +1001,15 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara if (_currentHoverTabItem != -1) // tab item is being hovered { ::SendMessage(_hSelf, TCM_GETITEMRECT, _currentHoverTabItem, reinterpret_cast(&_currentHoverTabRect)); - _isPinHover = _pinButtonZone.isHit(p.x, p.y, _currentHoverTabRect, _isVertical); - _isPinHover = _pinButtonZone.isHit(p.x, p.y, _currentHoverTabRect, _isVertical); + + int imageSize = 0; + if (_pinButtonInFront) + { + RECT imageRect{}; + getImageRectFromImglst(imageRect); + imageSize = imageRect.right - imageRect.left; + } + _isPinHover = _pinButtonZone.isHit(p.x, p.y, _currentHoverTabRect, _isVertical, imageSize); } else { @@ -1094,7 +1110,15 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara if (_drawTabPinButton) { - if ((_whichPinClickDown == currentTabOn) && _pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical)) + int imageSize = 0; + if (_pinButtonInFront) + { + RECT imageRect{}; + getImageRectFromImglst(imageRect); + imageSize = imageRect.right - imageRect.left; + } + + if ((_whichPinClickDown == currentTabOn) && _pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical, imageSize)) { notify(TCN_TABPINNED, currentTabOn); _whichPinClickDown = -1; @@ -1107,7 +1131,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara if (nextTab != -1) { ::SendMessage(_hSelf, TCM_GETITEMRECT, nextTab, reinterpret_cast(&_currentHoverTabRect)); - _isPinHover = _pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical); + _isPinHover = _pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical, imageSize); } return TRUE; } @@ -1346,7 +1370,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) { - RECT rect = pDrawItemStruct->rcItem; + RECT tabItemRect = pDrawItemStruct->rcItem; int nTab = pDrawItemStruct->itemID; assert(nTab >= 0); @@ -1383,11 +1407,11 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) HDC hDC = pDrawItemStruct->hDC; - int nSavedDC = ::SaveDC(hDC); + int savedStateId = ::SaveDC(hDC); ::SetBkMode(hDC, TRANSPARENT); HBRUSH hBrush = ::CreateSolidBrush(colorInactiveBgBase); - ::FillRect(hDC, &rect, hBrush); + ::FillRect(hDC, &tabItemRect, hBrush); ::DeleteObject(static_cast(hBrush)); // equalize drawing areas of active and inactive tabs @@ -1398,34 +1422,34 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) // the drawing area of the active tab extends on all borders by default const int xEdge = _dpiManager.getSystemMetricsForDpi(SM_CXEDGE); const int yEdge = _dpiManager.getSystemMetricsForDpi(SM_CYEDGE); - ::InflateRect(&rect, -xEdge, -yEdge); + ::InflateRect(&tabItemRect, -xEdge, -yEdge); // the active tab is also slightly higher by default (use this to shift the tab cotent up bx two pixels if tobBar is not drawn) if (_isVertical) { - rect.left += _drawTopBar ? paddingDynamicTwoX : 0; - rect.right -= _drawTopBar ? 0 : paddingDynamicTwoX; + tabItemRect.left += _drawTopBar ? paddingDynamicTwoX : 0; + tabItemRect.right -= _drawTopBar ? 0 : paddingDynamicTwoX; } else { - rect.top += _drawTopBar ? paddingDynamicTwoY : 0; - rect.bottom -= _drawTopBar ? 0 : paddingDynamicTwoY; + tabItemRect.top += _drawTopBar ? paddingDynamicTwoY : 0; + tabItemRect.bottom -= _drawTopBar ? 0 : paddingDynamicTwoY; } } else { if (_isVertical) { - rect.left += paddingDynamicTwoX; - rect.right += paddingDynamicTwoX; - rect.top -= paddingDynamicTwoY; - rect.bottom += paddingDynamicTwoY; + tabItemRect.left += paddingDynamicTwoX; + tabItemRect.right += paddingDynamicTwoX; + tabItemRect.top -= paddingDynamicTwoY; + tabItemRect.bottom += paddingDynamicTwoY; } else { - rect.left -= paddingDynamicTwoX; - rect.right += paddingDynamicTwoX; - rect.top += paddingDynamicTwoY; - rect.bottom += paddingDynamicTwoY; + tabItemRect.left -= paddingDynamicTwoX; + tabItemRect.right += paddingDynamicTwoX; + tabItemRect.top += paddingDynamicTwoY; + tabItemRect.bottom += paddingDynamicTwoY; } } @@ -1435,18 +1459,18 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) { if (_isVertical) { - rect.left -= paddingDynamicTwoX; + tabItemRect.left -= paddingDynamicTwoX; } else { - rect.top -= paddingDynamicTwoY; + tabItemRect.top -= paddingDynamicTwoY; } } const int individualColourId = getIndividualTabColourId(nTab); // draw highlights on tabs (top bar for active tab / darkened background for inactive tab) - RECT barRect = rect; + RECT barRect = tabItemRect; NppParameters& nppParam = NppParameters::getInstance(); if (isSelected) { @@ -1539,11 +1563,19 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) idxCloseImg = (_currentHoverTabItem == nTab) ? _closeTabHoverOnTabIdx : _closeTabInactIdx; } - RECT buttonRect = _closeButtonZone.getButtonRectFrom(rect, _isVertical); + RECT buttonRect = _closeButtonZone.getButtonRectFrom(tabItemRect, _isVertical); ::ImageList_Draw(_hCloseBtnImgLst, idxCloseImg, hDC, buttonRect.left, buttonRect.top, ILD_TRANSPARENT); } + + HIMAGELIST hImgLst = (HIMAGELIST)::SendMessage(_hSelf, TCM_GETIMAGELIST, 0, 0); + IMAGEINFO info{}; + ImageList_GetImageInfo(hImgLst, tci.iImage, &info); + RECT& imageRect = info.rcImage; + + RECT pinButtonRect{}; + // draw pin button Buffer* buf = reinterpret_cast(tci.lParam); if (_drawTabPinButton && _hPinBtnImgLst != nullptr && buf) @@ -1615,36 +1647,31 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) } } - RECT buttonRect = _pinButtonZone.getButtonRectFrom(rect, _isVertical); + int imageSize = _pinButtonInFront ? imageRect.right - imageRect.left : 0; + pinButtonRect = _pinButtonZone.getButtonRectFrom(tabItemRect, _isVertical, imageSize); - ::ImageList_Draw(_hPinBtnImgLst, idxPinImg, hDC, buttonRect.left, buttonRect.top, ILD_TRANSPARENT); + ::ImageList_Draw(_hPinBtnImgLst, idxPinImg, hDC, pinButtonRect.left, pinButtonRect.top, ILD_TRANSPARENT); } // draw image - HIMAGELIST hImgLst = (HIMAGELIST)::SendMessage(_hSelf, TCM_GETIMAGELIST, 0, 0); if (hImgLst && tci.iImage >= 0) { - IMAGEINFO info{}; - ImageList_GetImageInfo(hImgLst, tci.iImage, &info); - - RECT& imageRect = info.rcImage; - int fromBorder; int xPos, yPos; if (_isVertical) { - fromBorder = (rect.right - rect.left - (imageRect.right - imageRect.left) + 1) / 2; - xPos = rect.left + fromBorder; - yPos = rect.bottom - fromBorder - (imageRect.bottom - imageRect.top); - rect.bottom -= fromBorder + (imageRect.bottom - imageRect.top); + fromBorder = (tabItemRect.right - tabItemRect.left - (imageRect.right - imageRect.left) + 1) / 2; + xPos = tabItemRect.left + fromBorder; + yPos = tabItemRect.bottom - fromBorder - (imageRect.bottom - imageRect.top); + tabItemRect.bottom -= fromBorder + (imageRect.bottom - imageRect.top); } else { - fromBorder = (rect.bottom - rect.top - (imageRect.bottom - imageRect.top) + 1) / 2; - yPos = rect.top + fromBorder; - xPos = rect.left + fromBorder; - rect.left += fromBorder + (imageRect.right - imageRect.left); + fromBorder = (tabItemRect.bottom - tabItemRect.top - (imageRect.bottom - imageRect.top) + 1) / 2; + yPos = tabItemRect.top + fromBorder; + xPos = tabItemRect.left + fromBorder; + tabItemRect.left += fromBorder + (imageRect.right - imageRect.left); } ImageList_Draw(hImgLst, tci.iImage, hDC, xPos, yPos, isSelected ? ILD_TRANSPARENT : ILD_SELECTED); } @@ -1696,15 +1723,15 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) // center text horizontally (rotated text is positioned as if it were unrotated, therefore manual positioning is necessary) flags |= DT_LEFT; flags |= DT_BOTTOM; - rect.left += (rect.right - rect.left - textHeight) / 2; - rect.bottom += textHeight; + tabItemRect.left += (tabItemRect.right - tabItemRect.left - textHeight) / 2; + tabItemRect.bottom += textHeight; // ignoring the descent when centering (text elements below the base line) is more pleasing to the eye - rect.left += textDescent / 2; - rect.right += textDescent / 2; + tabItemRect.left += textDescent / 2; + tabItemRect.right += textDescent / 2; // 1 space distance to save icon - rect.bottom -= spaceUnit; + tabItemRect.bottom -= spaceUnit; } else { @@ -1714,24 +1741,24 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode) const int paddingText = ((pDrawItemStruct->rcItem.bottom - pDrawItemStruct->rcItem.top) - (textHeight + textDescent)) / 2; const int paddingDescent = !hasMultipleLines ? ((textDescent + ((isDarkMode || !isSelected) ? 1 : 0)) / 2) : 0; - rect.top = pDrawItemStruct->rcItem.top + paddingText + paddingDescent; - rect.bottom = pDrawItemStruct->rcItem.bottom - paddingText + paddingDescent; + tabItemRect.top = pDrawItemStruct->rcItem.top + paddingText + paddingDescent; + tabItemRect.bottom = pDrawItemStruct->rcItem.bottom - paddingText + paddingDescent; if (isDarkMode || !isSelected || _drawTopBar) { - rect.top += paddingDynamicTwoY; + tabItemRect.top += paddingDynamicTwoY; } // 1 space distance to save icon - rect.left += spaceUnit; + tabItemRect.left += _pinButtonInFront ? spaceUnit + (pinButtonRect.right - pinButtonRect.left) + spaceUnit : spaceUnit; } COLORREF textColor = isSelected ? colorActiveText : colorInactiveText; ::SetTextColor(hDC, textColor); - ::DrawText(hDC, decodedLabel, lstrlen(decodedLabel), &rect, flags); - ::RestoreDC(hDC, nSavedDC); + ::DrawText(hDC, decodedLabel, lstrlen(decodedLabel), &tabItemRect, flags); + ::RestoreDC(hDC, savedStateId); } @@ -1862,9 +1889,9 @@ void TabBarPlus::exchangeItemData(POINT point) } -bool TabButtonZone::isHit(int x, int y, const RECT & tabRect, bool isVertical) const +bool TabButtonZone::isHit(int x, int y, const RECT & tabRect, bool isVertical, int imageSize/* = 0 */) const { - RECT buttonRect = getButtonRectFrom(tabRect, isVertical); + RECT buttonRect = getButtonRectFrom(tabRect, isVertical, imageSize); if (x >= buttonRect.left && x <= buttonRect.right && y >= buttonRect.top && y <= buttonRect.bottom) return true; @@ -1872,7 +1899,7 @@ bool TabButtonZone::isHit(int x, int y, const RECT & tabRect, bool isVertical) c return false; } -RECT TabButtonZone::getButtonRectFrom(const RECT & tabRect, bool isVertical) const +RECT TabButtonZone::getButtonRectFrom(const RECT & tabRect, bool isVertical, int imageSize/* = 0 */) const { RECT buttonRect{}; const UINT dpi = DPIManagerV2::getDpiForWindow(_parent); @@ -1898,11 +1925,17 @@ RECT TabButtonZone::getButtonRectFrom(const RECT & tabRect, bool isVertical) con fromBorder = (tabRect.bottom - tabRect.top - _height + 1) / 2; if (_order == 0) { - buttonRect.left = tabRect.right - fromBorder - _width; + if (!imageSize) + buttonRect.left = tabRect.right - fromBorder - _width; + else + buttonRect.left = tabRect.left + inBetween + imageSize; } else if (_order == 1) { - buttonRect.left = tabRect.right - fromBorder - _width * 2 - inBetween; + if (!imageSize) + buttonRect.left = tabRect.right - fromBorder - _width * 2 - inBetween; + else + buttonRect.left = tabRect.left + inBetween + imageSize; } buttonRect.top = tabRect.top + fromBorder; diff --git a/PowerEditor/src/WinControls/TabBar/TabBar.h b/PowerEditor/src/WinControls/TabBar/TabBar.h index 2873665e3..cf0119588 100644 --- a/PowerEditor/src/WinControls/TabBar/TabBar.h +++ b/PowerEditor/src/WinControls/TabBar/TabBar.h @@ -158,8 +158,8 @@ struct TabButtonZone _order = order; } - bool isHit(int x, int y, const RECT & tabRect, bool isVertical) const; - RECT getButtonRectFrom(const RECT & tabRect, bool isVertical) const; + bool isHit(int x, int y, const RECT & tabRect, bool isVertical, int imageSize = 0) const; + RECT getButtonRectFrom(const RECT & tabRect, bool isVertical, int imageSize = 0) const; void setOrder(int newOrder) { _order = newOrder; }; HWND _parent = nullptr; @@ -210,6 +210,7 @@ public : static bool drawInactiveTab() {return _drawInactiveTab;}; static bool drawTabCloseButton() {return _drawTabCloseButton;}; static bool drawTabPinButton() {return _drawTabPinButton;}; + static bool pinButtonInFront() {return _pinButtonInFront;}; static bool isDbClk2Close() {return _isDbClk2Close;}; static bool isVertical() { return _isCtrlVertical;}; static bool isMultiLine() { return _isCtrlMultiLine;}; @@ -239,6 +240,10 @@ public : _isDbClk2Close = b; } + static void setPutTabPinButtonInFront(bool b) { + _pinButtonInFront = b; + } + static void setVertical(bool b) { _isCtrlVertical = b; doVertical(); @@ -278,6 +283,15 @@ public : deletItemAt(index); } + void getImageRectFromImglst(RECT& imageRect) const { + HIMAGELIST hImgLst = (HIMAGELIST)::SendMessage(_hSelf, TCM_GETIMAGELIST, 0, 0); + IMAGEINFO info{}; + TCITEM tci{}; + tci.mask = TCIF_IMAGE; + ImageList_GetImageInfo(hImgLst, tci.iImage, &info); + imageRect = info.rcImage; + } + protected: // it's the boss to decide if we do the drag N drop static bool _doDragNDrop; @@ -335,6 +349,7 @@ protected: static bool _drawTopBar; static bool _drawTabCloseButton; static bool _drawTabPinButton; + static bool _pinButtonInFront; static bool _isDbClk2Close; static bool _isCtrlVertical; static bool _isCtrlMultiLine; diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h index 1117177a4..c9323a0b4 100644 --- a/PowerEditor/src/resource.h +++ b/PowerEditor/src/resource.h @@ -667,7 +667,7 @@ #define NPPM_INTERNAL_SCINTILLAFINDERCLEARALL (NOTEPADPLUS_USER_INTERNAL + 27) #define NPPM_INTERNAL_CHANGETABBARICONSET (NOTEPADPLUS_USER_INTERNAL + 28) #define NPPM_INTERNAL_SET_TAB_SETTINGS (NOTEPADPLUS_USER_INTERNAL + 29) - //#define NPPM_INTERNAL_SETTING_TAB_SIZE (NOTEPADPLUS_USER_INTERNAL + 30) + #define NPPM_INTERNAL_PUTTABPINBUTTONINFRONT (NOTEPADPLUS_USER_INTERNAL + 30) #define NPPM_INTERNAL_RELOADSTYLERS (NOTEPADPLUS_USER_INTERNAL + 31) #define NPPM_INTERNAL_DOCORDERCHANGED (NOTEPADPLUS_USER_INTERNAL + 32) #define NPPM_INTERNAL_SETMULTISELCTION (NOTEPADPLUS_USER_INTERNAL + 33)