diff --git a/PowerEditor/installer/nativeLang/english.xml b/PowerEditor/installer/nativeLang/english.xml
index 760310051..6a3deb8d1 100644
--- a/PowerEditor/installer/nativeLang/english.xml
+++ b/PowerEditor/installer/nativeLang/english.xml
@@ -958,6 +958,7 @@ Translation note:
+
diff --git a/PowerEditor/installer/nativeLang/french.xml b/PowerEditor/installer/nativeLang/french.xml
index af7c235ef..4404be224 100644
--- a/PowerEditor/installer/nativeLang/french.xml
+++ b/PowerEditor/installer/nativeLang/french.xml
@@ -957,6 +957,7 @@ Translation note:
+
diff --git a/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml b/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml
index 2f01e3343..c3a425c94 100644
--- a/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml
+++ b/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml
@@ -910,13 +910,15 @@
-
+
+
+
diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp
index a1e943c3b..919e4c0d0 100644
--- a/PowerEditor/src/Notepad_plus.cpp
+++ b/PowerEditor/src/Notepad_plus.cpp
@@ -405,6 +405,7 @@ LRESULT Notepad_plus::init(HWND hwnd)
TabBarPlus::setDrawTopBar((tabBarStatus & TAB_DRAWTOPBAR) != 0, &_mainDocTab);
TabBarPlus::setDrawInactiveTab((tabBarStatus & TAB_DRAWINACTIVETAB) != 0, &_mainDocTab);
TabBarPlus::setDrawTabCloseButton((tabBarStatus & TAB_CLOSEBUTTON) != 0, &_mainDocTab);
+ TabBarPlus::setDrawTabPinButton((tabBarStatus & TAB_PINBUTTON) != 0, &_mainDocTab);
TabBarPlus::setDbClk2Close((tabBarStatus & TAB_DBCLK2CLOSE) != 0);
TabBarPlus::setVertical((tabBarStatus & TAB_VERTICAL) != 0);
drawTabbarColoursFromStylerArray();
@@ -918,6 +919,7 @@ bool Notepad_plus::saveGUIParams()
(TabBarPlus::drawInactiveTab() ? TAB_DRAWINACTIVETAB : 0) | \
(TabBarPlus::isReduced() ? TAB_REDUCE : 0) | \
(TabBarPlus::drawTabCloseButton() ? TAB_CLOSEBUTTON : 0) | \
+ (TabBarPlus::drawTabPinButton() ? TAB_PINBUTTON : 0) | \
(TabBarPlus::isDbClk2Close() ? TAB_DBCLK2CLOSE : 0) | \
(TabBarPlus::isVertical() ? TAB_VERTICAL : 0) | \
(TabBarPlus::isMultiLine() ? TAB_MULTILINE : 0) |\
@@ -4909,6 +4911,8 @@ void Notepad_plus::docGotoAnotherEditView(FileTransferMode mode)
//First put the doc in the other view if not present (if it is, activate it).
//Then if needed close in the original tab
BufferID current = _pEditView->getCurrentBufferID();
+ Buffer* buf = MainFileManager.getBufferByID(current);
+
int viewToGo = otherView();
int indexFound = _pNonDocTab->getIndexByBuffer(current);
if (indexFound != -1) //activate it
@@ -4929,7 +4933,7 @@ void Notepad_plus::docGotoAnotherEditView(FileTransferMode mode)
}
loadBufferIntoView(current, viewToGo);
- Buffer *buf = MainFileManager.getBufferByID(current);
+
_pEditView->saveCurrentPos(); //allow copying of position
buf->setPosition(buf->getPosition(_pEditView), _pNonEditView);
_pNonEditView->restoreCurrentPosPreStep(); //set position
@@ -4948,7 +4952,6 @@ void Notepad_plus::docGotoAnotherEditView(FileTransferMode mode)
//Close the document if we transfered the document instead of cloning it
if (mode == TransferMove)
{
- Buffer *buf = MainFileManager.getBufferByID(current);
monitoringWasOn = buf->isMonitoringOn();
//just close the activate document, since thats the one we moved (no search)
@@ -4958,6 +4961,13 @@ void Notepad_plus::docGotoAnotherEditView(FileTransferMode mode)
//Activate the other view since thats where the document went
switchEditViewTo(viewToGo);
+ if (buf->isPinned())
+ {
+ buf->setPinned(false);
+ _pDocTab->tabToStart();
+ buf->setPinned(true);
+ }
+
if (monitoringWasOn)
{
command(IDM_VIEW_MONITORING);
@@ -4965,7 +4975,6 @@ void Notepad_plus::docGotoAnotherEditView(FileTransferMode mode)
if (_pDocumentListPanel != nullptr)
{
- Buffer* buf = MainFileManager.getBufferByID(current);
_pDocumentListPanel->setItemColor(buf);
}
}
@@ -6333,7 +6342,7 @@ void Notepad_plus::getCurrentOpenedFiles(Session & session, bool includUntitledD
}
const wchar_t* langName = languageName.c_str();
- sessionFileInfo sfi(buf->getFullPathName(), langName, buf->getEncoding(), buf->getUserReadOnly(), buf->getPosition(editView), buf->getBackupFileName().c_str(), buf->getLastModifiedTimestamp(), buf->getMapPosition());
+ sessionFileInfo sfi(buf->getFullPathName(), langName, buf->getEncoding(), buf->getUserReadOnly(), buf->isPinned(), buf->getPosition(editView), buf->getBackupFileName().c_str(), buf->getLastModifiedTimestamp(), buf->getMapPosition());
sfi._isMonitoring = buf->isMonitoringOn();
sfi._individualTabColour = docTab[k]->getIndividualTabColourId(static_cast(i));
diff --git a/PowerEditor/src/Notepad_plus.h b/PowerEditor/src/Notepad_plus.h
index 0ad06397c..2b26c49a3 100644
--- a/PowerEditor/src/Notepad_plus.h
+++ b/PowerEditor/src/Notepad_plus.h
@@ -192,6 +192,7 @@ public:
bool fileRename(BufferID id = BUFFER_INVALID);
bool fileRenameUntitledPluginAPI(BufferID id, const wchar_t* tabNewName);
+ void unPinnedForAllBuffers();
bool switchToFile(BufferID buffer); //find buffer in active view then in other view.
//@}
diff --git a/PowerEditor/src/Notepad_plus.rc b/PowerEditor/src/Notepad_plus.rc
index 0347c78cd..12be73eb5 100644
--- a/PowerEditor/src/Notepad_plus.rc
+++ b/PowerEditor/src/Notepad_plus.rc
@@ -335,6 +335,15 @@ IDR_CLOSETAB_INACT_DM ICON "icons/dark/tabbar/closeTabButton_in
IDR_CLOSETAB_HOVER_DM ICON "icons/dark/tabbar/closeTabButton_hover.ico"
IDR_CLOSETAB_PUSH_DM ICON "icons/dark/tabbar/closeTabButton_push.ico"
+IDR_PINTAB ICON "icons/standard/tabbar/pinTabButton.ico"
+IDR_PINTAB_HOVER ICON "icons/standard/tabbar/pinTabButton_pinned.ico"
+IDR_PINTAB_PINNED ICON "icons/standard/tabbar/pinTabButton_pinned.ico"
+IDR_PINTAB_PINNEDHOVER ICON "icons/standard/tabbar/pinTabButton.ico"
+IDR_PINTAB_DM ICON "icons/dark/tabbar/pinTabButton.ico"
+IDR_PINTAB_HOVER_DM ICON "icons/dark/tabbar/pinTabButton_hover.ico"
+IDR_PINTAB_PINNED_DM ICON "icons/dark/tabbar/pinTabButton_pinned.ico"
+IDR_PINTAB_PINNEDHOVER_DM ICON "icons/dark/tabbar/pinTabButton_pinnedHover.ico"
+
IDR_DOCMAP_ICO ICON "icons/standard/panels/tabbar/docMap.ico"
IDR_DOCMAP_ICO2 ICON "icons/light/panels/tabbar/docMap.ico"
IDR_DOCMAP_ICO_DM ICON "icons/dark/panels/tabbar/docMap.ico"
diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp
index a47fd2395..0d3cc1e1e 100644
--- a/PowerEditor/src/NppBigSwitch.cpp
+++ b/PowerEditor/src/NppBigSwitch.cpp
@@ -3693,6 +3693,8 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
_subDocTab.resizeIconsDpi();
_mainDocTab.setCloseBtnImageList();
_subDocTab.setCloseBtnImageList();
+ _mainDocTab.setPinBtnImageList();
+ _subDocTab.setPinBtnImageList();
::SendMessage(_pPublicInterface->getHSelf(), WM_COMMAND, IDM_VIEW_REDUCETABBAR, 0);
changeDocumentListIconSet(false);
@@ -3779,6 +3781,57 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
return fileName.length();
}
+ case NPPM_INTERNAL_DRAWTABBARPINBOTTUN:
+ {
+ TabBarPlus::setDrawTabPinButton(!TabBarPlus::drawTabPinButton(), &_mainDocTab);
+
+ bool drawTabPinButton = TabBarPlus::drawTabPinButton();
+ bool drawTabCloseButton = TabBarPlus::drawTabCloseButton();
+
+ if (!drawTabPinButton)
+ {
+ unPinnedForAllBuffers();
+ }
+
+ if (drawTabCloseButton && drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(0);
+ _mainDocTab.setTabPinButtonOrder(1);
+ _subDocTab.setTabCloseButtonOrder(0);
+ _subDocTab.setTabPinButtonOrder(1);
+ }
+ else if (!drawTabCloseButton && drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(-1);
+ _mainDocTab.setTabPinButtonOrder(0);
+ _subDocTab.setTabCloseButtonOrder(-1);
+ _subDocTab.setTabPinButtonOrder(0);
+ }
+ else if (drawTabCloseButton && !drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(0);
+ _mainDocTab.setTabPinButtonOrder(-1);
+ _subDocTab.setTabCloseButtonOrder(0);
+ _subDocTab.setTabPinButtonOrder(-1);
+ }
+ else //if (!drawTabCloseButton && !drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(-1);
+ _mainDocTab.setTabPinButtonOrder(-1);
+ _subDocTab.setTabCloseButtonOrder(-1);
+ _subDocTab.setTabPinButtonOrder(-1);
+ }
+
+ // This part is just for updating (redraw) the tabs
+ int tabDpiDynamicalHeight = _mainDocTab.dpiManager().scale(TabBarPlus::isReduced() ? g_TabHeight : g_TabHeightLarge);
+ int tabDpiDynamicalWidth = _mainDocTab.dpiManager().scale(TabBarPlus::drawTabPinButton() ? g_TabWidthCloseBtn : g_TabWidth);
+ TabCtrl_SetItemSize(_mainDocTab.getHSelf(), tabDpiDynamicalWidth, tabDpiDynamicalHeight);
+ TabCtrl_SetItemSize(_subDocTab.getHSelf(), tabDpiDynamicalWidth, tabDpiDynamicalHeight);
+
+ ::SendMessage(_pPublicInterface->getHSelf(), WM_SIZE, 0, 0);
+ return TRUE;
+ }
+
default:
{
if (message == WDN_NOTIFY)
diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp
index 342049bfc..38d71d0e8 100644
--- a/PowerEditor/src/NppCommands.cpp
+++ b/PowerEditor/src/NppCommands.cpp
@@ -2323,7 +2323,9 @@ void Notepad_plus::command(int id)
case IDM_VIEW_REFRESHTABAR :
{
- ::SendMessage(_pPublicInterface->getHSelf(), WM_SIZE, 0, 0);
+ ::InvalidateRect(_mainDocTab.getHSelf(), NULL, TRUE);
+ ::InvalidateRect(_subDocTab.getHSelf(), NULL, TRUE);
+
break;
}
case IDM_VIEW_LOCKTABBAR:
@@ -2349,6 +2351,38 @@ void Notepad_plus::command(int id)
{
TabBarPlus::setDrawTabCloseButton(!TabBarPlus::drawTabCloseButton(), &_mainDocTab);
+ bool drawTabPinButton = TabBarPlus::drawTabPinButton();
+ bool drawTabCloseButton = TabBarPlus::drawTabCloseButton();
+
+ if (drawTabCloseButton && drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(0);
+ _mainDocTab.setTabPinButtonOrder(1);
+ _subDocTab.setTabCloseButtonOrder(0);
+ _subDocTab.setTabPinButtonOrder(1);
+ }
+ else if (!drawTabCloseButton && drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(-1);
+ _mainDocTab.setTabPinButtonOrder(0);
+ _subDocTab.setTabCloseButtonOrder(-1);
+ _subDocTab.setTabPinButtonOrder(0);
+ }
+ else if (drawTabCloseButton && !drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(0);
+ _mainDocTab.setTabPinButtonOrder(-1);
+ _subDocTab.setTabCloseButtonOrder(0);
+ _subDocTab.setTabPinButtonOrder(-1);
+ }
+ else //if (!drawTabCloseButton && !drawTabPinButton)
+ {
+ _mainDocTab.setTabCloseButtonOrder(-1);
+ _mainDocTab.setTabPinButtonOrder(-1);
+ _subDocTab.setTabCloseButtonOrder(-1);
+ _subDocTab.setTabPinButtonOrder(-1);
+ }
+
// This part is just for updating (redraw) the tabs
int tabDpiDynamicalHeight = _mainDocTab.dpiManager().scale(TabBarPlus::isReduced() ? g_TabHeight : g_TabHeightLarge);
int tabDpiDynamicalWidth = _mainDocTab.dpiManager().scale(TabBarPlus::drawTabCloseButton() ? g_TabWidthCloseBtn : g_TabWidth);
@@ -3345,11 +3379,11 @@ void Notepad_plus::command(int id)
}
case IDM_VIEW_GOTO_START:
- _pDocTab->currentTabToStart();
+ _pDocTab->tabToStart();
break;
case IDM_VIEW_GOTO_END:
- _pDocTab->currentTabToEnd();
+ _pDocTab->tabToEnd();
break;
case IDM_VIEW_GOTO_ANOTHER_VIEW:
diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp
index c893d9059..da669484b 100644
--- a/PowerEditor/src/NppIO.cpp
+++ b/PowerEditor/src/NppIO.cpp
@@ -1111,6 +1111,23 @@ bool Notepad_plus::fileClose(BufferID id, int curView)
return true;
}
+void Notepad_plus::unPinnedForAllBuffers()
+{
+ for (size_t i = 0; i < _mainDocTab.nbItem(); ++i)
+ {
+ BufferID id = _mainDocTab.getBufferByIndex(i);
+ Buffer* buf = MainFileManager.getBufferByID(id);
+ buf->setPinned(false);
+ }
+
+ for (size_t i = 0; i < _subDocTab.nbItem(); ++i)
+ {
+ BufferID id = _mainDocTab.getBufferByIndex(i);
+ Buffer* buf = MainFileManager.getBufferByID(id);
+ buf->setPinned(false);
+ }
+}
+
bool Notepad_plus::fileCloseAll(bool doDeleteBackup, bool isSnapshotMode)
{
bool noSaveToAll = false;
@@ -2407,6 +2424,7 @@ bool Notepad_plus::loadSession(Session & session, bool isSnapshotMode, const wch
buf->setEncoding(session._mainViewFiles[i]._encoding);
buf->setUserReadOnly(session._mainViewFiles[i]._isUserReadOnly);
+ buf->setPinned(session._mainViewFiles[i]._isPinned);
if (isSnapshotMode && !session._mainViewFiles[i]._backupFilePath.empty() && doesFileExist(session._mainViewFiles[i]._backupFilePath.c_str()))
buf->setDirty(true);
@@ -2539,6 +2557,7 @@ bool Notepad_plus::loadSession(Session & session, bool isSnapshotMode, const wch
buf->setLangType(typeToSet, pLn);
buf->setEncoding(session._subViewFiles[k]._encoding);
buf->setUserReadOnly(session._subViewFiles[k]._isUserReadOnly);
+ buf->setPinned(session._subViewFiles[k]._isPinned);
if (isSnapshotMode && !session._subViewFiles[k]._backupFilePath.empty() && doesFileExist(session._subViewFiles[k]._backupFilePath.c_str()))
buf->setDirty(true);
diff --git a/PowerEditor/src/NppNotification.cpp b/PowerEditor/src/NppNotification.cpp
index 8503b6033..bd7bd1010 100644
--- a/PowerEditor/src/NppNotification.cpp
+++ b/PowerEditor/src/NppNotification.cpp
@@ -317,7 +317,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
int index = tabNotification->_tabOrigin;
BufferID bufferToClose = notifyDocTab->getBufferByIndex(index);
Buffer * buf = MainFileManager.getBufferByID(bufferToClose);
- int iView = isFromPrimary?MAIN_VIEW:SUB_VIEW;
+ int iView = isFromPrimary ? MAIN_VIEW : SUB_VIEW;
if (buf->isDirty())
{
activateBuffer(bufferToClose, iView);
@@ -333,6 +333,36 @@ BOOL Notepad_plus::notify(SCNotification *notification)
break;
}
+ case TCN_TABPINNED:
+ {
+ int index = tabNotification->_tabOrigin;
+ BufferID bufferToBePinned = notifyDocTab->getBufferByIndex(index);
+ Buffer * buf = MainFileManager.getBufferByID(bufferToBePinned);
+
+ bool isPinned = buf->isPinned();
+
+ if (_mainDocTab.getHSelf() == notification->nmhdr.hwndFrom)
+ {
+ if (!isPinned)
+ _mainDocTab.tabToStart(index);
+ else
+ _mainDocTab.tabToEnd(index);
+ }
+ else if (_subDocTab.getHSelf() == notification->nmhdr.hwndFrom)
+ {
+ if (!isPinned)
+ _subDocTab.tabToStart(index);
+ else
+ _subDocTab.tabToEnd(index);
+ }
+ else
+ return FALSE;
+
+ buf->setPinned(!isPinned);
+
+ break;
+ }
+
case TCN_SELCHANGE:
{
int iView = -1;
diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp
index ff5d81bf9..5b65b9e33 100644
--- a/PowerEditor/src/Parameters.cpp
+++ b/PowerEditor/src/Parameters.cpp
@@ -2440,7 +2440,12 @@ bool NppParameters::getSessionFromXmlTree(TiXmlDocument *pSessionDoc, Session& s
if (boolStrReadOnly)
isUserReadOnly = _wcsicmp(L"yes", boolStrReadOnly) == 0;
- sessionFileInfo sfi(fileName, langName, encStr ? encoding : -1, isUserReadOnly, position, backupFilePath, fileModifiedTimestamp, mapPosition);
+ bool isPinned = false;
+ const wchar_t* boolStrPinned = (childNode->ToElement())->Attribute(L"tabPinned");
+ if (boolStrPinned)
+ isPinned = _wcsicmp(L"yes", boolStrPinned) == 0;
+
+ sessionFileInfo sfi(fileName, langName, encStr ? encoding : -1, isUserReadOnly, isPinned, position, backupFilePath, fileModifiedTimestamp, mapPosition);
const wchar_t* intStrTabColour = (childNode->ToElement())->Attribute(L"tabColourId");
if (intStrTabColour)
@@ -3675,6 +3680,7 @@ void NppParameters::writeSession(const Session & session, const wchar_t *fileNam
(fileNameNode->ToElement())->SetAttribute(L"originalFileLastModifTimestampHigh", static_cast(viewSessionFiles[i]._originalFileLastModifTimestamp.dwHighDateTime));
(fileNameNode->ToElement())->SetAttribute(L"tabColourId", static_cast(viewSessionFiles[i]._individualTabColour));
(fileNameNode->ToElement())->SetAttribute(L"RTL", viewSessionFiles[i]._isRTL ? L"yes" : L"no");
+ (fileNameNode->ToElement())->SetAttribute(L"tabPinned", viewSessionFiles[i]._isPinned ? L"yes" : L"no");
// docMap
(fileNameNode->ToElement())->SetAttribute(L"mapFirstVisibleDisplayLine", _i64tot(static_cast(viewSessionFiles[i]._mapPos._firstVisibleDisplayLine), szInt64, 10));
@@ -4908,6 +4914,17 @@ void NppParameters::feedGUIParameters(TiXmlNode *node)
isFailed = true;
}
+ val = element->Attribute(L"pinButton");
+ if (val)
+ {
+ if (!lstrcmp(val, L"yes"))
+ _nppGUI._tabStatus |= TAB_PINBUTTON;
+ else if (!lstrcmp(val, L"no"))
+ _nppGUI._tabStatus |= 0;
+ else
+ isFailed = true;
+ }
+
val = element->Attribute(L"doubleClick2Close");
if (val)
{
@@ -7243,6 +7260,9 @@ void NppParameters::createXmlTreeFromGUIParams()
pStr = (_nppGUI._tabStatus & TAB_CLOSEBUTTON) ? L"yes" : L"no";
GUIConfigElement->SetAttribute(L"closeButton", pStr);
+ pStr = (_nppGUI._tabStatus & TAB_PINBUTTON) ? L"yes" : L"no";
+ GUIConfigElement->SetAttribute(L"pinButton", pStr);
+
pStr = (_nppGUI._tabStatus & TAB_DBCLK2CLOSE) ? L"yes" : L"no";
GUIConfigElement->SetAttribute(L"doubleClick2Close", pStr);
diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h
index 12b31c869..c9cc0fcc5 100644
--- a/PowerEditor/src/Parameters.h
+++ b/PowerEditor/src/Parameters.h
@@ -64,17 +64,18 @@ const int UDD_DOCKED = 2; // 0000 0010
// 2 : 0000 0010 hide & docked
// 3 : 0000 0011 show & docked
-const int TAB_DRAWTOPBAR = 1; //0000 0000 0001
-const int TAB_DRAWINACTIVETAB = 2; //0000 0000 0010
-const int TAB_DRAGNDROP = 4; //0000 0000 0100
-const int TAB_REDUCE = 8; //0000 0000 1000
-const int TAB_CLOSEBUTTON = 16; //0000 0001 0000
-const int TAB_DBCLK2CLOSE = 32; //0000 0010 0000
-const int TAB_VERTICAL = 64; //0000 0100 0000
-const int TAB_MULTILINE = 128; //0000 1000 0000
-const int TAB_HIDE = 256; //0001 0000 0000
-const int TAB_QUITONEMPTY = 512; //0010 0000 0000
-const int TAB_ALTICONS = 1024; //0100 0000 0000
+const int TAB_DRAWTOPBAR = 1; //0000 0000 0001
+const int TAB_DRAWINACTIVETAB = 2; //0000 0000 0010
+const int TAB_DRAGNDROP = 4; //0000 0000 0100
+const int TAB_REDUCE = 8; //0000 0000 1000
+const int TAB_CLOSEBUTTON = 16; //0000 0001 0000
+const int TAB_DBCLK2CLOSE = 32; //0000 0010 0000
+const int TAB_VERTICAL = 64; //0000 0100 0000
+const int TAB_MULTILINE = 128; //0000 1000 0000
+const int TAB_HIDE = 256; //0001 0000 0000
+const int TAB_QUITONEMPTY = 512; //0010 0000 0000
+const int TAB_ALTICONS = 1024; //0100 0000 0000
+const int TAB_PINBUTTON = 2048; //1000 0000 0000
const bool activeText = true;
const bool activeNumeric = false;
@@ -216,8 +217,8 @@ public:
struct sessionFileInfo : public Position
{
- sessionFileInfo(const wchar_t* fn, const wchar_t *ln, int encoding, bool userReadOnly, const Position& pos, const wchar_t *backupFilePath, FILETIME originalFileLastModifTimestamp, const MapPosition & mapPos) :
- Position(pos), _encoding(encoding), _isUserReadOnly(userReadOnly), _originalFileLastModifTimestamp(originalFileLastModifTimestamp), _mapPos(mapPos)
+ sessionFileInfo(const wchar_t* fn, const wchar_t *ln, int encoding, bool userReadOnly,bool isPinned, const Position& pos, const wchar_t *backupFilePath, FILETIME originalFileLastModifTimestamp, const MapPosition & mapPos) :
+ Position(pos), _encoding(encoding), _isUserReadOnly(userReadOnly), _isPinned(isPinned), _originalFileLastModifTimestamp(originalFileLastModifTimestamp), _mapPos(mapPos)
{
if (fn) _fileName = fn;
if (ln) _langName = ln;
@@ -235,6 +236,7 @@ struct sessionFileInfo : public Position
bool _isMonitoring = false;
int _individualTabColour = -1;
bool _isRTL = false;
+ bool _isPinned = false;
std::wstring _backupFilePath;
FILETIME _originalFileLastModifTimestamp {};
@@ -791,15 +793,7 @@ struct NppGUI final
bool _statusBarShow = true;
bool _menuBarShow = true;
- // 1st bit : draw top bar;
- // 2nd bit : draw inactive tabs
- // 3rd bit : enable drag & drop
- // 4th bit : reduce the height
- // 5th bit : enable vertical
- // 6th bit : enable multiline
-
- // 0:don't draw; 1:draw top bar 2:draw inactive tabs 3:draw both 7:draw both+drag&drop
- int _tabStatus = (TAB_DRAWTOPBAR | TAB_DRAWINACTIVETAB | TAB_DRAGNDROP | TAB_REDUCE | TAB_CLOSEBUTTON);
+ int _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/ScintillaComponent/Buffer.h b/PowerEditor/src/ScintillaComponent/Buffer.h
index cbb122f9b..e96ec3bec 100644
--- a/PowerEditor/src/ScintillaComponent/Buffer.h
+++ b/PowerEditor/src/ScintillaComponent/Buffer.h
@@ -362,6 +362,9 @@ public:
bool isRTL() const { return _isRTL; };
void setRTL(bool isRTL) { _isRTL = isRTL; };
+ bool isPinned() const { return _isPinned; };
+ void setPinned(bool isPinned) { _isPinned = isPinned; };
+
private:
int indexOfReference(const ScintillaEditView * identifier) const;
@@ -445,4 +448,5 @@ private:
bool _isInaccessible = false;
bool _isRTL = false;
+ bool _isPinned = false;
};
diff --git a/PowerEditor/src/WinControls/ColourPicker/WordStyleDlg.rc b/PowerEditor/src/WinControls/ColourPicker/WordStyleDlg.rc
index 441062816..13338964b 100644
--- a/PowerEditor/src/WinControls/ColourPicker/WordStyleDlg.rc
+++ b/PowerEditor/src/WinControls/ColourPicker/WordStyleDlg.rc
@@ -64,13 +64,13 @@ BEGIN
LTEXT "User-defined keywords",IDC_USER_KEYWORDS_STATIC,350,135,126,8
EDITTEXT IDC_USER_KEYWORDS_EDIT,347,146,136,52,ES_MULTILINE | WS_VSCROLL
- CONTROL "Force foreground color for all styles",IDC_GLOBAL_FG_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,191,134,132,10
- CONTROL "Force background color for all styles",IDC_GLOBAL_BG_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,191,149,132,10
+ CONTROL "Force foreground color for all styles",IDC_GLOBAL_FG_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,191,134,153,10
+ CONTROL "Force background color for all styles",IDC_GLOBAL_BG_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,191,149,153,10
CONTROL "Force font choice for all styles",IDC_GLOBAL_FONT_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,134,153,10
- CONTROL "Force font size choice for all styles",IDC_GLOBAL_FONTSIZE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,149,135,10
- CONTROL "Force bold choice for all styles",IDC_GLOBAL_BOLD_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,164,135,10
- CONTROL "Force italic choice for all styles",IDC_GLOBAL_ITALIC_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,179,135,10
- CONTROL "Force underline choice for all styles",IDC_GLOBAL_UNDERLINE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,194,135,10
+ CONTROL "Force font size choice for all styles",IDC_GLOBAL_FONTSIZE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,149, 153,10
+ CONTROL "Force bold choice for all styles",IDC_GLOBAL_BOLD_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,164,153,10
+ CONTROL "Force italic choice for all styles",IDC_GLOBAL_ITALIC_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,179,153,10
+ CONTROL "Force underline choice for all styles",IDC_GLOBAL_UNDERLINE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,327,194,153,10
LTEXT "Go to settings",IDC_GLOBAL_GOTOSETTINGS_LINK,210,153,131,10,WS_TABSTOP
LTEXT "What is Global override?",IDC_GLOBAL_WHATISGLOBALOVERRIDE_LINK,191,173,132,10,WS_TABSTOP
diff --git a/PowerEditor/src/WinControls/Preference/preference.rc b/PowerEditor/src/WinControls/Preference/preference.rc
index 9ce09b03d..ef355800e 100644
--- a/PowerEditor/src/WinControls/Preference/preference.rc
+++ b/PowerEditor/src/WinControls/Preference/preference.rc
@@ -38,39 +38,35 @@ IDD_PREFERENCE_SUB_GENRAL DIALOGEX 115, 10, 460, 205
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- GROUPBOX "Localization",IDC_LOCALIZATION_GB_STATIC,27,3,186,30,BS_CENTER
+ GROUPBOX "Localization",IDC_LOCALIZATION_GB_STATIC,27,0,186,36,BS_CENTER
COMBOBOX IDC_COMBO_LOCALIZATION,60,14,125,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
-
- GROUPBOX "Status Bar",IDC_STATUSBAR_GB_STATIC,27,37,186,27,BS_CENTER
- CONTROL "Hide",IDC_CHECK_HIDESTATUSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,48,174,10
-
- GROUPBOX "Toolbar",IDC_TOOLBAR_GB_STATIC,27,68,186,88,BS_CENTER
- CONTROL "Hide",IDC_CHECK_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,76,100,10
- CONTROL "Fluent UI: small",IDC_RADIO_SMALLICON,"Button",BS_AUTORADIOBUTTON,33,91,174,10
- CONTROL "Fluent UI: large",IDC_RADIO_BIGICON,"Button",BS_AUTORADIOBUTTON,33,104,174,10
- CONTROL "Filled Fluent UI: small",IDC_RADIO_SMALLICON2,"Button",BS_AUTORADIOBUTTON,33,117,174,10
- CONTROL "Filled Fluent UI: large",IDC_RADIO_BIGICON2,"Button",BS_AUTORADIOBUTTON,33,130,174,10
- CONTROL "Standard icons: small",IDC_RADIO_STANDARD,"Button",BS_AUTORADIOBUTTON,33,143,174,10
-
- GROUPBOX "Tab Bar",IDC_TABBAR_GB_STATIC,223,3,177,153,BS_CENTER
- CONTROL "Hide",IDC_CHECK_TAB_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,11,100,10
- CONTROL "Multi-line",IDC_CHECK_TAB_MULTILINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,26,164,10
- CONTROL "Vertical",IDC_CHECK_TAB_VERTICAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,39,164,10
- CONTROL "Reduce",IDC_CHECK_REDUCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,52,164,10
- CONTROL "Alternate icons",IDC_CHECK_TAB_ALTICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,65,164,10
- CONTROL "Lock (no drag and drop)",IDC_CHECK_LOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,78,164,10
- CONTROL "Darken inactive tabs",IDC_CHECK_DRAWINACTIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,91,164,10
- CONTROL "Draw a coloured bar on active tab",IDC_CHECK_ORANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,104,164,10
- CONTROL "Show close button on each tab",IDC_CHECK_ENABLETABCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,117,164,10
- CONTROL "Double click to close document",IDC_CHECK_DBCLICK2CLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,130,164,10
- CONTROL "Exit on close the last tab",IDC_CHECK_TAB_LAST_EXIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,143,164,10
-
- GROUPBOX "Menu",IDC_MENU_GB_STATIC,27,160,373,34,BS_CENTER
- CONTROL "Hide menu bar (use Alt or F10 key to toggle)",IDC_CHECK_HIDEMENUBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,168,218,10
- CONTROL "Hide right shortcuts + ▼ ✕ from the menu bar (Need to restart Notepad++)",IDC_CHECK_HIDERIGHTSHORTCUTSOFMENUBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,181,350,10
+ GROUPBOX "Status Bar",IDC_STATUSBAR_GB_STATIC,27,39,186,31,BS_CENTER
+ CONTROL "Hide",IDC_CHECK_HIDESTATUSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,52,174,10
+ GROUPBOX "Toolbar",IDC_TOOLBAR_GB_STATIC,27,75,186,91,BS_CENTER
+ CONTROL "Hide",IDC_CHECK_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,84,100,10
+ CONTROL "Fluent UI: small",IDC_RADIO_SMALLICON,"Button",BS_AUTORADIOBUTTON,33,100,174,10
+ CONTROL "Fluent UI: large",IDC_RADIO_BIGICON,"Button",BS_AUTORADIOBUTTON,33,113,174,10
+ CONTROL "Filled Fluent UI: small",IDC_RADIO_SMALLICON2,"Button",BS_AUTORADIOBUTTON,33,126,174,10
+ CONTROL "Filled Fluent UI: large",IDC_RADIO_BIGICON2,"Button",BS_AUTORADIOBUTTON,33,139,174,10
+ CONTROL "Standard icons: small",IDC_RADIO_STANDARD,"Button",BS_AUTORADIOBUTTON,33,152,174,10
+ GROUPBOX "Tab Bar",IDC_TABBAR_GB_STATIC,223,0,177,166,BS_CENTER
+ CONTROL "Hide",IDC_CHECK_TAB_HIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,8,100,10
+ CONTROL "Multi-line",IDC_CHECK_TAB_MULTILINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,21,164,10
+ CONTROL "Vertical",IDC_CHECK_TAB_VERTICAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,34,164,10
+ CONTROL "Reduce",IDC_CHECK_REDUCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,47,164,10
+ CONTROL "Alternate icons",IDC_CHECK_TAB_ALTICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,60,164,10
+ CONTROL "Lock (no drag and drop)",IDC_CHECK_LOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,73,164,10
+ CONTROL "Darken inactive tabs",IDC_CHECK_DRAWINACTIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,86,164,10
+ CONTROL "Draw a coloured bar on active tab",IDC_CHECK_ORANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,99,164,10
+ CONTROL "Show close button on each tab",IDC_CHECK_ENABLETABCLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,112,164,10
+ CONTROL "Enable pin tab feature", IDC_CHECK_ENABLETABPIN,"Button", BS_AUTOCHECKBOX | WS_TABSTOP, 229, 125, 164, 10
+ CONTROL "Double click to close document",IDC_CHECK_DBCLICK2CLOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,138,164,10
+ CONTROL "Exit on close the last tab",IDC_CHECK_TAB_LAST_EXIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,229,151,164,10
+ GROUPBOX "Menu",IDC_MENU_GB_STATIC,27,168,373,34,BS_CENTER
+ CONTROL "Hide menu bar (use Alt or F10 key to toggle)",IDC_CHECK_HIDEMENUBAR, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,176,218,10
+ CONTROL "Hide right shortcuts + ? ? from the menu bar (Need to restart Notepad++)",IDC_CHECK_HIDERIGHTSHORTCUTSOFMENUBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,189,350,10
END
-
IDD_PREFERENCE_SUB_EDITING DIALOGEX 115, 10, 460, 205
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
FONT 8, "MS Shell Dlg", 0, 0, 0x1
diff --git a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp
index ffd1bb21a..cedd39e8e 100644
--- a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp
+++ b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp
@@ -610,6 +610,7 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
::SendDlgItemMessage(_hSelf, IDC_CHECK_ORANGE, BM_SETCHECK, tabBarStatus & TAB_DRAWTOPBAR, 0);
::SendDlgItemMessage(_hSelf, IDC_CHECK_DRAWINACTIVE, BM_SETCHECK, tabBarStatus & TAB_DRAWINACTIVETAB, 0);
::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLETABCLOSE, BM_SETCHECK, tabBarStatus & TAB_CLOSEBUTTON, 0);
+ ::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLETABPIN, BM_SETCHECK, tabBarStatus & TAB_PINBUTTON, 0);
::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);
@@ -699,6 +700,7 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_ORANGE), !toBeHidden);
::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_DBCLICK2CLOSE), !toBeHidden);
::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_TAB_LAST_EXIT), !toBeHidden);
::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_TAB_ALTICONS), !toBeHidden);
@@ -757,6 +759,10 @@ intptr_t CALLBACK GeneralSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
::SendMessage(_hParent, WM_COMMAND, IDM_VIEW_DRAWTABBAR_CLOSEBOTTUN, 0);
return TRUE;
+ case IDC_CHECK_ENABLETABPIN:
+ ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_DRAWTABBARPINBOTTUN, 0, 0);
+ return TRUE;
+
case IDC_CHECK_DBCLICK2CLOSE :
::SendMessage(_hParent, WM_COMMAND, IDM_VIEW_DRAWTABBAR_DBCLK2CLOSE, 0);
return TRUE;
diff --git a/PowerEditor/src/WinControls/Preference/preference_rc.h b/PowerEditor/src/WinControls/Preference/preference_rc.h
index e6f0d1353..0046dfcfe 100644
--- a/PowerEditor/src/WinControls/Preference/preference_rc.h
+++ b/PowerEditor/src/WinControls/Preference/preference_rc.h
@@ -40,7 +40,7 @@
#define IDC_CHECK_ENABLETABCLOSE (IDD_PREFERENCE_SUB_GENRAL + 12)
#define IDC_CHECK_DBCLICK2CLOSE (IDD_PREFERENCE_SUB_GENRAL + 13)
#define IDC_CHECK_ENABLEDOCSWITCHER (IDD_PREFERENCE_SUB_GENRAL + 14)
- //#define IDC_CHECK_MAINTAININDENT (IDD_PREFERENCE_SUB_GENRAL + 15)
+ #define IDC_CHECK_ENABLETABPIN (IDD_PREFERENCE_SUB_GENRAL + 15)
#define IDC_CHECK_KEEPINSAMEDIR (IDD_PREFERENCE_SUB_GENRAL + 16)
#define IDC_CHECK_STYLEMRU (IDD_PREFERENCE_SUB_GENRAL + 17)
#define IDC_CHECK_TAB_HIDE (IDD_PREFERENCE_SUB_GENRAL + 18)
diff --git a/PowerEditor/src/WinControls/TabBar/TabBar.cpp b/PowerEditor/src/WinControls/TabBar/TabBar.cpp
index 4f6e5f23a..87cd74812 100644
--- a/PowerEditor/src/WinControls/TabBar/TabBar.cpp
+++ b/PowerEditor/src/WinControls/TabBar/TabBar.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see .
#include
+#include "Buffer.h"
#include "TabBar.h"
#include "Parameters.h"
#include "DoubleBuffer/DoubleBuffer.h"
@@ -28,7 +29,8 @@ bool TabBarPlus::_doDragNDrop = false;
bool TabBarPlus::_drawTopBar = true;
bool TabBarPlus::_drawInactiveTab = true;
-bool TabBarPlus::_drawTabCloseButton = false;
+bool TabBarPlus::_drawTabCloseButton = true;
+bool TabBarPlus::_drawTabPinButton = true;
bool TabBarPlus::_isDbClk2Close = false;
bool TabBarPlus::_isCtrlVertical = false;
bool TabBarPlus::_isCtrlMultiLine = false;
@@ -277,6 +279,12 @@ void TabBarPlus::destroy()
::ImageList_Destroy(_hCloseBtnImgLst);
_hCloseBtnImgLst = nullptr;
}
+
+ if (_hPinBtnImgLst != nullptr)
+ {
+ ::ImageList_Destroy(_hPinBtnImgLst);
+ _hPinBtnImgLst = nullptr;
+ }
}
@@ -285,7 +293,8 @@ void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMult
Window::init(hInst, parent);
const UINT dpi = DPIManagerV2::getDpiForWindow(_hParent);
- _closeButtonZone.setParent(_hParent);
+ _closeButtonZone.init(_hParent, 0);
+ _pinButtonZone.init(_hParent, 1);
_dpiManager.setDpi(dpi);
int vertical = isVertical ? (TCS_VERTICAL | TCS_MULTILINE | TCS_RIGHTJUSTIFY) : 0;
@@ -350,6 +359,7 @@ void TabBarPlus::init(HINSTANCE hInst, HWND parent, bool isVertical, bool isMult
setFont();
setCloseBtnImageList();
+ setPinBtnImageList();
}
void TabBar::setFont()
@@ -405,9 +415,21 @@ void TabBarPlus::doOwnerDrawTab(TabBarPlus* tbpObj)
if (tbpObj)
{
- const int paddingSizeDynamicW = tbpObj->_dpiManager.scale(6);
- const int paddingSizePlusClosebuttonDynamicW = tbpObj->_dpiManager.scale(10);
- ::SendMessage(_hwndArray[i], TCM_SETPADDING, 0, MAKELPARAM(_drawTabCloseButton ? paddingSizePlusClosebuttonDynamicW : paddingSizeDynamicW, 0));
+ int paddingSize = 0;
+ if (_drawTabCloseButton && _drawTabPinButton) // 2 buttons
+ {
+ paddingSize = 16;
+ }
+ else if (!_drawTabCloseButton && !_drawTabPinButton) // no button
+ {
+ paddingSize = 6;
+ }
+ else // only 1 button
+ {
+ paddingSize = 10;
+ }
+ const int paddingSizeDynamicW = tbpObj->_dpiManager.scale(paddingSize);
+ ::SendMessage(_hwndArray[i], TCM_SETPADDING, 0, MAKELPARAM(paddingSizeDynamicW, 0));
}
}
}
@@ -439,27 +461,33 @@ void TabBarPlus::setColour(COLORREF colour2Set, tabColourIndex i, TabBarPlus* tb
doOwnerDrawTab(tbpObj);
}
-void TabBarPlus::currentTabToStart()
+void TabBarPlus::tabToStart(int index)
{
- int currentTabIndex = getCurrentTabIndex();
- if (currentTabIndex <= 0)
+ if (index < 0 || index >= static_cast(_nbItem))
+ index = getCurrentTabIndex();
+
+ if (index <= 0)
return;
- for (int i = currentTabIndex, j = currentTabIndex - 1; j >= 0; --i, --j)
+ for (int i = index, j = index - 1; j >= 0; --i, --j)
{
- exchangeTabItemData(i, j);
+ if (!exchangeTabItemData(i, j))
+ break;
}
}
-void TabBarPlus::currentTabToEnd()
+void TabBarPlus::tabToEnd(int index)
{
- int currentTabIndex = getCurrentTabIndex();
- if (currentTabIndex >= static_cast(_nbItem))
+ if (index < 0 || index >= static_cast(_nbItem))
+ index = getCurrentTabIndex();
+
+ if (index >= static_cast(_nbItem))
return;
- for (int i = currentTabIndex, j = currentTabIndex + 1; j < static_cast(_nbItem); ++i, ++j)
+ for (int i = index, j = index + 1; j < static_cast(_nbItem); ++i, ++j)
{
- exchangeTabItemData(i, j);
+ if (!exchangeTabItemData(i, j))
+ break;
}
}
@@ -501,6 +529,45 @@ void TabBarPlus::setCloseBtnImageList()
_closeButtonZone._height = btnSize;
}
+
+void TabBarPlus::setPinBtnImageList()
+{
+ int iconSize = 0;
+ std::vector ids;
+
+ if (NppDarkMode::isEnabled())
+ {
+ iconSize = g_TabPinBtnSize_DM;
+ ids = { IDR_PINTAB_DM, IDR_PINTAB_HOVER_DM, IDR_PINTAB_PINNED_DM, IDR_PINTAB_PINNEDHOVER_DM };
+ }
+ else
+ {
+ iconSize = g_TabPinBtnSize;
+ ids = { IDR_PINTAB, IDR_PINTAB_HOVER, IDR_PINTAB_PINNED, IDR_PINTAB_PINNEDHOVER };
+ }
+
+ if (_hPinBtnImgLst != nullptr)
+ {
+ ::ImageList_Destroy(_hPinBtnImgLst);
+ _hPinBtnImgLst = nullptr;
+ }
+
+ const int btnSize = _dpiManager.scale(iconSize);
+
+ _hPinBtnImgLst = ::ImageList_Create(btnSize, btnSize, ILC_COLOR32 | ILC_MASK, static_cast(ids.size()), 0);
+
+ for (const auto& id : ids)
+ {
+ HICON hIcon = nullptr;
+ DPIManagerV2::loadIcon(_hInst, MAKEINTRESOURCE(id), btnSize, btnSize, &hIcon);
+ ::ImageList_AddIcon(_hPinBtnImgLst, hIcon);
+ ::DestroyIcon(hIcon);
+ }
+
+ _pinButtonZone._width = btnSize;
+ _pinButtonZone._height = btnSize;
+}
+
void TabBarPlus::doVertical()
{
for (int i = 0 ; i < _nbCtrl ; ++i)
@@ -566,6 +633,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
{
NppDarkMode::setDarkTooltips(hwnd, NppDarkMode::ToolTipsType::tabbar);
setCloseBtnImageList();
+ setPinBtnImageList();
return TRUE;
}
@@ -667,9 +735,10 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
// clear hover state of the close button,
// WM_MOUSEMOVE won't handle this properly since the tab position will change
- if (_isCloseHover)
+ if (_isCloseHover || _isPinHover)
{
_isCloseHover = false;
+ _isPinHover = false;
::InvalidateRect(_hSelf, &_currentHoverTabRect, false);
}
@@ -681,9 +750,12 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
case WM_LBUTTONDOWN :
{
+ int xPos = LOWORD(lParam);
+ int yPos = HIWORD(lParam);
+
if (::GetWindowLongPtr(_hSelf, GWL_STYLE) & TCS_BUTTONS)
{
- int nTab = getTabIndexAt(LOWORD(lParam), HIWORD(lParam));
+ int nTab = getTabIndexAt(xPos, yPos);
if (nTab != -1 && nTab != static_cast(::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0)))
{
setActiveTab(nTab);
@@ -692,9 +764,6 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
if (_drawTabCloseButton)
{
- int xPos = LOWORD(lParam);
- int yPos = HIWORD(lParam);
-
if (_closeButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical))
{
_whichCloseClickDown = getTabIndexAt(xPos, yPos);
@@ -703,6 +772,16 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
}
}
+ if (_drawTabPinButton)
+ {
+ if (_pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical))
+ {
+ _whichPinClickDown = getTabIndexAt(xPos, yPos);
+ ::SendMessage(_hParent, WM_COMMAND, IDM_VIEW_REFRESHTABAR, 0);
+ return TRUE;
+ }
+ }
+
::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam);
int currentTabOn = static_cast(::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0));
@@ -822,7 +901,7 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
RECT currentHoverTabRectOld = _currentHoverTabRect;
bool isCloseHoverOld = _isCloseHover;
- if (_currentHoverTabItem != -1) // is hovering
+ if (_currentHoverTabItem != -1) // tab item is being hovered
{
::SendMessage(_hSelf, TCM_GETITEMRECT, _currentHoverTabItem, reinterpret_cast(&_currentHoverTabRect));
_isCloseHover = _closeButtonZone.isHit(p.x, p.y, _currentHoverTabRect, _isVertical);
@@ -848,6 +927,39 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
trackMouseEvent(TME_LEAVE);
}
}
+
+ if (_drawTabPinButton)
+ {
+ RECT currentHoverTabRectOld = _currentHoverTabRect;
+ bool isPinHoverOld = _isPinHover;
+
+ 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);
+ }
+ else
+ {
+ SetRectEmpty(&_currentHoverTabRect);
+ _isPinHover = false;
+ }
+
+ if (isFromTabToTab || _isPinHover != isPinHoverOld)
+ {
+ if (isPinHoverOld && (isFromTabToTab || !_isPinHover))
+ InvalidateRect(hwnd, ¤tHoverTabRectOld, FALSE);
+
+ if (_isPinHover)
+ InvalidateRect(hwnd, &_currentHoverTabRect, FALSE);
+ }
+
+ if (_isPinHover)
+ {
+ // Mouse moves out from pin zone will send WM_MOUSELEAVE message
+ trackMouseEvent(TME_LEAVE);
+ }
+ }
// Mouse moves out from tab zone will send WM_MOUSELEAVE message
// but it doesn't track mouse moving from a tab to another
trackMouseEvent(TME_LEAVE);
@@ -858,13 +970,15 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
case WM_MOUSELEAVE:
{
- if (_isCloseHover)
+ if (_isCloseHover || _isPinHover)
InvalidateRect(hwnd, &_currentHoverTabRect, FALSE);
_currentHoverTabItem = -1;
_whichCloseClickDown = -1;
+ _whichPinClickDown = -1;
SetRectEmpty(&_currentHoverTabRect);
_isCloseHover = false;
+ _isPinHover = false;
notify(TCN_MOUSELEAVING, _currentHoverTabItem);
break;
@@ -915,6 +1029,28 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
_whichCloseClickDown = -1;
}
+ if (_drawTabPinButton)
+ {
+ if ((_whichPinClickDown == currentTabOn) && _pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical))
+ {
+ notify(TCN_TABPINNED, currentTabOn);
+ _whichPinClickDown = -1;
+
+ // Get the next tab at same position
+ // If valid tab is found then
+ // update the current hover tab RECT (_currentHoverTabRect)
+ // update pin hover flag (_isPinHover), so that x will be highlighted or not based on new _currentHoverTabRect
+ int nextTab = getTabIndexAt(xPos, yPos);
+ if (nextTab != -1)
+ {
+ ::SendMessage(_hSelf, TCM_GETITEMRECT, nextTab, reinterpret_cast(&_currentHoverTabRect));
+ _isPinHover = _pinButtonZone.isHit(xPos, yPos, _currentHoverTabRect, _isVertical);
+ }
+ return TRUE;
+ }
+ _whichPinClickDown = -1;
+ }
+
break;
}
@@ -1144,30 +1280,23 @@ LRESULT TabBarPlus::runProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPara
return ::CallWindowProc(_tabBarDefaultProc, hwnd, Message, wParam, lParam);
}
-void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct, bool isDarkMode)
+void TabBarPlus::drawItem(DRAWITEMSTRUCT* pDrawItemStruct, bool isDarkMode)
{
RECT rect = pDrawItemStruct->rcItem;
int nTab = pDrawItemStruct->itemID;
- if (nTab < 0)
- {
- ::MessageBox(NULL, L"nTab < 0", L"", MB_OK);
- }
+ assert(nTab >= 0);
+
bool isSelected = (nTab == ::SendMessage(_hSelf, TCM_GETCURSEL, 0, 0));
wchar_t label[MAX_PATH] = { '\0' };
TCITEM tci{};
- tci.mask = TCIF_TEXT|TCIF_IMAGE;
+ tci.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
tci.pszText = label;
tci.cchTextMax = MAX_PATH-1;
- if (!::SendMessage(_hSelf, TCM_GETITEM, nTab, reinterpret_cast(&tci)))
- {
- std::wstring errorMessageTitle = L"TabBarPlus::drawItem wrong: ! TCM_GETITEM";
- std::wstring errorMessage = GetLastErrorAsString(GetLastError());
- ::MessageBox(NULL, errorMessage.c_str(), errorMessageTitle.c_str(), MB_OK);
- }
-
+ ::SendMessage(_hSelf, TCM_GETITEM, nTab, reinterpret_cast(&tci));
+
const COLORREF colorActiveBg = isDarkMode ? NppDarkMode::getSofterBackgroundColor() : ::GetSysColor(COLOR_BTNFACE);
const COLORREF colorInactiveBgBase = isDarkMode ? NppDarkMode::getBackgroundColor() : ::GetSysColor(COLOR_BTNFACE);
@@ -1322,22 +1451,22 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct, bool isDarkMode)
{
// 3 status for each inactive tab and selected tab close item :
// normal / hover / pushed
- int idxCloseImg = 0; // selected
+ int idxCloseImg = _closeTabIdx; // selected
if (_isCloseHover && (_currentHoverTabItem == nTab))
{
if (_whichCloseClickDown == -1) // hover
{
- idxCloseImg += 2;
+ idxCloseImg = _closeTabHoverIdx;
}
else if (_whichCloseClickDown == _currentHoverTabItem) // pushed
{
- idxCloseImg += 3;
+ idxCloseImg = _closeTabPushIdx;
}
}
else if (!isSelected) // inactive
{
- idxCloseImg += 1;
+ idxCloseImg = _closeTabInactIdx;
}
RECT buttonRect = _closeButtonZone.getButtonRectFrom(rect, _isVertical);
@@ -1345,6 +1474,82 @@ void TabBarPlus::drawItem(DRAWITEMSTRUCT *pDrawItemStruct, bool isDarkMode)
::ImageList_Draw(_hCloseBtnImgLst, idxCloseImg, hDC, buttonRect.left, buttonRect.top, ILD_TRANSPARENT);
}
+ // draw pin button
+ if (_drawTabPinButton && _hPinBtnImgLst != nullptr)
+ {
+ // Each tab combined with the following stats :
+ // (active / inactive) | (pinned / unpinned) | (hover / not hover / pushed)
+
+
+ bool isPinned = reinterpret_cast(tci.lParam)->isPinned();
+ int idxPinImg = _unpinnedIdx; // current: upinned as default
+
+
+ if (isPinned)
+ {
+ if (!isSelected) // inactive
+ {
+ if (_isPinHover && (_currentHoverTabItem == nTab))
+ {
+ if (_whichPinClickDown == -1) // hover
+ {
+ idxPinImg = _pinnedHoverIdx;
+ }
+ else if (_whichPinClickDown == _currentHoverTabItem) // pushed
+ {
+ idxPinImg = _unpinnedIdx;
+ }
+
+ }
+ else // pinned inactive
+ {
+ idxPinImg = _pinnedIdx;
+ }
+ }
+ else // current
+ {
+ if (_isPinHover && (_currentHoverTabItem == nTab)) // hover
+ idxPinImg = _pinnedHoverIdx;
+ else
+ idxPinImg = _pinnedIdx;
+ }
+
+ }
+ else // unpinned
+ {
+ if (!isSelected) // inactive
+ {
+ if (_isPinHover && (_currentHoverTabItem == nTab))
+ {
+ if (_whichPinClickDown == -1) // hover
+ {
+ idxPinImg = _unpinnedHoverIdx;
+ }
+ else if (_whichPinClickDown == _currentHoverTabItem) // pushed
+ {
+ idxPinImg = _pinnedIdx;
+ }
+
+ }
+ else // unpinned inactive
+ {
+ idxPinImg = _unpinnedIdx;
+ }
+ }
+ else // current
+ {
+ if (_isPinHover && (_currentHoverTabItem == nTab)) // hover
+ idxPinImg = _unpinnedHoverIdx;
+ else
+ idxPinImg = _unpinnedIdx;
+ }
+ }
+
+ RECT buttonRect = _pinButtonZone.getButtonRectFrom(rect, _isVertical);
+
+ ::ImageList_Draw(_hPinBtnImgLst, idxPinImg, hDC, buttonRect.left, buttonRect.top, ILD_TRANSPARENT);
+ }
+
// draw image
HIMAGELIST hImgLst = (HIMAGELIST)::SendMessage(_hSelf, TCM_GETIMAGELIST, 0, 0);
@@ -1496,7 +1701,7 @@ void TabBarPlus::setActiveTab(int tabIndex)
notify(TCN_SELCHANGE, tabIndex);
}
-void TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
+bool TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
{
//1. shift their data, and insert the source
TCITEM itemData_nDraggedTab{}, itemData_shift{};
@@ -1512,10 +1717,18 @@ void TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
itemData_shift.cchTextMax = (stringSize);
::SendMessage(_hSelf, TCM_GETITEM, oldTab, reinterpret_cast(&itemData_nDraggedTab));
+ Buffer* chosenBuf = reinterpret_cast(itemData_nDraggedTab.lParam);
+
+ ::SendMessage(_hSelf, TCM_GETITEM, newTab, reinterpret_cast(&itemData_shift));
+ Buffer* shiftBuf = reinterpret_cast(itemData_shift.lParam);
+
+ if (chosenBuf->isPinned() != shiftBuf->isPinned())
+ return false;
+ int i = oldTab;
if (oldTab > newTab)
{
- for (int i = oldTab; i > newTab; i--)
+ for (; i > newTab; i--)
{
::SendMessage(_hSelf, TCM_GETITEM, i - 1, reinterpret_cast(&itemData_shift));
::SendMessage(_hSelf, TCM_SETITEM, i, reinterpret_cast(&itemData_shift));
@@ -1523,12 +1736,13 @@ void TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
}
else
{
- for (int i = oldTab; i < newTab; ++i)
+ for (; i < newTab; ++i)
{
::SendMessage(_hSelf, TCM_GETITEM, i + 1, reinterpret_cast(&itemData_shift));
::SendMessage(_hSelf, TCM_SETITEM, i, reinterpret_cast(&itemData_shift));
}
}
+
::SendMessage(_hSelf, TCM_SETITEM, newTab, reinterpret_cast(&itemData_nDraggedTab));
// Tell Notepad_plus to notifiy plugins that a D&D operation was done (so doc index has been changed)
@@ -1536,6 +1750,8 @@ void TabBarPlus::exchangeTabItemData(int oldTab, int newTab)
//2. set to focus
setActiveTab(newTab);
+
+ return true;
}
void TabBarPlus::exchangeItemData(POINT point)
@@ -1556,9 +1772,11 @@ void TabBarPlus::exchangeItemData(POINT point)
return;
}
- exchangeTabItemData(_nTabDragged, nTab);
- _previousTabSwapped = _nTabDragged;
- _nTabDragged = nTab;
+ if (exchangeTabItemData(_nTabDragged, nTab))
+ {
+ _previousTabSwapped = _nTabDragged;
+ _nTabDragged = nTab;
+ }
}
else
{
@@ -1571,11 +1789,10 @@ void TabBarPlus::exchangeItemData(POINT point)
_previousTabSwapped = -1;
_isDraggingInside = false;
}
-
}
-bool CloseButtonZone::isHit(int x, int y, const RECT & tabRect, bool isVertical) const
+bool TabButtonZone::isHit(int x, int y, const RECT & tabRect, bool isVertical) const
{
RECT buttonRect = getButtonRectFrom(tabRect, isVertical);
@@ -1585,22 +1802,42 @@ bool CloseButtonZone::isHit(int x, int y, const RECT & tabRect, bool isVertical)
return false;
}
-RECT CloseButtonZone::getButtonRectFrom(const RECT & tabRect, bool isVertical) const
+RECT TabButtonZone::getButtonRectFrom(const RECT & tabRect, bool isVertical) const
{
RECT buttonRect{};
+ const UINT dpi = DPIManagerV2::getDpiForWindow(_parent);
+ const int inBetween = DPIManagerV2::scale(NppDarkMode::isEnabled() ? 4 : 8, dpi);
int fromBorder = 0;
if (isVertical)
{
fromBorder = (tabRect.right - tabRect.left - _width + 1) / 2;
+ if (_order == 0)
+ {
+ buttonRect.top = tabRect.top + fromBorder;
+ }
+ else if (_order == 1)
+ {
+ buttonRect.top = tabRect.top + fromBorder + _height + inBetween;
+ }
+
buttonRect.left = tabRect.left + fromBorder;
}
else
{
fromBorder = (tabRect.bottom - tabRect.top - _height + 1) / 2;
- buttonRect.left = tabRect.right - fromBorder - _width;
+ if (_order == 0)
+ {
+ buttonRect.left = tabRect.right - fromBorder - _width;
+ }
+ else if (_order == 1)
+ {
+ buttonRect.left = tabRect.right - fromBorder - _width * 2 - inBetween;
+ }
+
+ buttonRect.top = tabRect.top + fromBorder;
}
- buttonRect.top = tabRect.top + fromBorder;
+
buttonRect.bottom = buttonRect.top + _height;
buttonRect.right = buttonRect.left + _width;
diff --git a/PowerEditor/src/WinControls/TabBar/TabBar.h b/PowerEditor/src/WinControls/TabBar/TabBar.h
index 226a5734e..d0fe125ce 100644
--- a/PowerEditor/src/WinControls/TabBar/TabBar.h
+++ b/PowerEditor/src/WinControls/TabBar/TabBar.h
@@ -36,6 +36,7 @@
#define TCN_MOUSEHOVERING (TCN_FIRST - 13)
#define TCN_MOUSELEAVING (TCN_FIRST - 14)
#define TCN_MOUSEHOVERSWITCHING (TCN_FIRST - 15)
+#define TCN_TABPINNED (TCN_FIRST - 16)
#define WM_TABSETSTYLE (WM_APP + 0x024)
@@ -65,7 +66,9 @@ constexpr int g_TabHeightLarge = 25;
constexpr int g_TabWidth = 45;
constexpr int g_TabWidthCloseBtn = 60;
constexpr int g_TabCloseBtnSize = 11;
+constexpr int g_TabPinBtnSize = 11;
constexpr int g_TabCloseBtnSize_DM = 16;
+constexpr int g_TabPinBtnSize_DM = 16;
struct TBHDR
{
@@ -148,15 +151,21 @@ protected:
};
-struct CloseButtonZone
+struct TabButtonZone
{
+ void init(HWND parent, int order) {
+ _parent = parent;
+ _order = order;
+ }
+
bool isHit(int x, int y, const RECT & tabRect, bool isVertical) const;
RECT getButtonRectFrom(const RECT & tabRect, bool isVertical) const;
- void setParent(HWND parent) { _parent = parent; }
+ void setOrder(int newOrder) { _order = newOrder; };
HWND _parent = nullptr;
int _width = 0;
int _height = 0;
+ int _order = -1; // from right to left: 0, 1
};
@@ -200,6 +209,7 @@ public :
static bool drawTopBar() {return _drawTopBar;};
static bool drawInactiveTab() {return _drawInactiveTab;};
static bool drawTabCloseButton() {return _drawTabCloseButton;};
+ static bool drawTabPinButton() {return _drawTabPinButton;};
static bool isDbClk2Close() {return _isDbClk2Close;};
static bool isVertical() { return _isCtrlVertical;};
static bool isMultiLine() { return _isCtrlMultiLine;};
@@ -220,6 +230,11 @@ public :
doOwnerDrawTab(tbpObj);
}
+ static void setDrawTabPinButton(bool b, TabBarPlus* tbpObj) {
+ _drawTabPinButton = b;
+ doOwnerDrawTab(tbpObj);
+ }
+
static void setDbClk2Close(bool b) {
_isDbClk2Close = b;
}
@@ -241,10 +256,19 @@ public :
static void setColour(COLORREF colour2Set, tabColourIndex i, TabBarPlus* tbpObj);
virtual int getIndividualTabColourId(int tabIndex) = 0;
- void currentTabToStart();
- void currentTabToEnd();
+ void tabToStart(int index = -1);
+ void tabToEnd(int index = -1);
void setCloseBtnImageList();
+ void setPinBtnImageList();
+
+ void setTabPinButtonOrder(int newOrder) {
+ _pinButtonZone.setOrder(newOrder);
+ }
+
+ void setTabCloseButtonOrder(int newOrder) {
+ _closeButtonZone.setOrder(newOrder);
+ }
protected:
// it's the boss to decide if we do the drag N drop
@@ -263,10 +287,25 @@ protected:
RECT _currentHoverTabRect{};
int _currentHoverTabItem = -1; // -1 : no mouse on any tab
- CloseButtonZone _closeButtonZone;
+ TabButtonZone _closeButtonZone;
+ TabButtonZone _pinButtonZone;
+
HIMAGELIST _hCloseBtnImgLst = nullptr;
+ const int _closeTabIdx = 0;
+ const int _closeTabInactIdx = 1;
+ const int _closeTabHoverIdx = 2;
+ const int _closeTabPushIdx = 3;
+
+ HIMAGELIST _hPinBtnImgLst = nullptr;
+ const int _unpinnedIdx = 0;
+ const int _unpinnedHoverIdx = 1;
+ const int _pinnedIdx = 2;
+ const int _pinnedHoverIdx = 3;
+
bool _isCloseHover = false;
+ bool _isPinHover = false;
int _whichCloseClickDown = -1;
+ int _whichPinClickDown = -1;
bool _lmbdHit = false; // Left Mouse Button Down Hit
HWND _tooltips = nullptr;
@@ -276,7 +315,7 @@ protected:
return (((TabBarPlus *)(::GetWindowLongPtr(hwnd, GWLP_USERDATA)))->runProc(hwnd, Message, wParam, lParam));
};
void setActiveTab(int tabIndex);
- void exchangeTabItemData(int oldTab, int newTab);
+ bool exchangeTabItemData(int oldTab, int newTab);
void exchangeItemData(POINT point);
@@ -284,6 +323,7 @@ protected:
static bool _drawInactiveTab;
static bool _drawTopBar;
static bool _drawTabCloseButton;
+ static bool _drawTabPinButton;
static bool _isDbClk2Close;
static bool _isCtrlVertical;
static bool _isCtrlMultiLine;
diff --git a/PowerEditor/src/icons/dark/tabbar/pinTabButton.ico b/PowerEditor/src/icons/dark/tabbar/pinTabButton.ico
new file mode 100644
index 000000000..8078bf609
Binary files /dev/null and b/PowerEditor/src/icons/dark/tabbar/pinTabButton.ico differ
diff --git a/PowerEditor/src/icons/dark/tabbar/pinTabButton_hover.ico b/PowerEditor/src/icons/dark/tabbar/pinTabButton_hover.ico
new file mode 100644
index 000000000..7072beefb
Binary files /dev/null and b/PowerEditor/src/icons/dark/tabbar/pinTabButton_hover.ico differ
diff --git a/PowerEditor/src/icons/dark/tabbar/pinTabButton_pinned.ico b/PowerEditor/src/icons/dark/tabbar/pinTabButton_pinned.ico
new file mode 100644
index 000000000..7072beefb
Binary files /dev/null and b/PowerEditor/src/icons/dark/tabbar/pinTabButton_pinned.ico differ
diff --git a/PowerEditor/src/icons/dark/tabbar/pinTabButton_pinnedHover.ico b/PowerEditor/src/icons/dark/tabbar/pinTabButton_pinnedHover.ico
new file mode 100644
index 000000000..8078bf609
Binary files /dev/null and b/PowerEditor/src/icons/dark/tabbar/pinTabButton_pinnedHover.ico differ
diff --git a/PowerEditor/src/icons/standard/tabbar/pinTabButton.ico b/PowerEditor/src/icons/standard/tabbar/pinTabButton.ico
new file mode 100644
index 000000000..b92c30a4f
Binary files /dev/null and b/PowerEditor/src/icons/standard/tabbar/pinTabButton.ico differ
diff --git a/PowerEditor/src/icons/standard/tabbar/pinTabButton_hover.ico b/PowerEditor/src/icons/standard/tabbar/pinTabButton_hover.ico
new file mode 100644
index 000000000..144175d95
Binary files /dev/null and b/PowerEditor/src/icons/standard/tabbar/pinTabButton_hover.ico differ
diff --git a/PowerEditor/src/icons/standard/tabbar/pinTabButton_pinned.ico b/PowerEditor/src/icons/standard/tabbar/pinTabButton_pinned.ico
new file mode 100644
index 000000000..aa77d2fba
Binary files /dev/null and b/PowerEditor/src/icons/standard/tabbar/pinTabButton_pinned.ico differ
diff --git a/PowerEditor/src/icons/standard/tabbar/pinTabButton_pinnedHover.ico b/PowerEditor/src/icons/standard/tabbar/pinTabButton_pinnedHover.ico
new file mode 100644
index 000000000..478b129fb
Binary files /dev/null and b/PowerEditor/src/icons/standard/tabbar/pinTabButton_pinnedHover.ico differ
diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h
index b6f038c19..fc9cbae79 100644
--- a/PowerEditor/src/resource.h
+++ b/PowerEditor/src/resource.h
@@ -405,6 +405,15 @@
#define IDR_FIND_RESULT_ICO2 1564
#define IDR_FIND_RESULT_ICO_DM 1565
+#define IDR_PINTAB 1566
+#define IDR_PINTAB_HOVER 1567
+#define IDR_PINTAB_PINNED 1568
+#define IDR_PINTAB_PINNEDHOVER 1569
+#define IDR_PINTAB_DM 1570
+#define IDR_PINTAB_HOVER_DM 1571
+#define IDR_PINTAB_PINNED_DM 1572
+#define IDR_PINTAB_PINNEDHOVER_DM 1573
+
#define ID_MACRO 20000
// O .
// C .
@@ -698,6 +707,8 @@
#define NPPM_INTERNAL_LINECUTCOPYWITHOUTSELECTION (NOTEPADPLUS_USER_INTERNAL + 78)
#define NPPM_INTERNAL_DOCMODIFIEDBYREPLACEALL (NOTEPADPLUS_USER_INTERNAL + 79)
+ #define NPPM_INTERNAL_DRAWTABBARPINBOTTUN (NOTEPADPLUS_USER_INTERNAL + 80)
+
// See Notepad_plus_msgs.h
//#define NOTEPADPLUS_USER (WM_USER + 1000)