mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-28 08:14:18 +02:00
Keep Doc Switcher's ordering in sync with Tab bar
Close #946, close #1684, close #2342, close #4015
This commit is contained in:
parent
87feb9677e
commit
883045d96f
@ -458,6 +458,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||||||
|
|
||||||
case NPPM_INTERNAL_DOCORDERCHANGED :
|
case NPPM_INTERNAL_DOCORDERCHANGED :
|
||||||
{
|
{
|
||||||
|
if (_pFileSwitcherPanel)
|
||||||
|
{
|
||||||
|
_pFileSwitcherPanel->updateTabOrder();
|
||||||
|
}
|
||||||
|
|
||||||
BufferID id = _pEditView->getCurrentBufferID();
|
BufferID id = _pEditView->getCurrentBufferID();
|
||||||
|
|
||||||
// Notify plugins that current file is about to be closed
|
// Notify plugins that current file is about to be closed
|
||||||
|
@ -34,26 +34,41 @@
|
|||||||
|
|
||||||
int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
||||||
{
|
{
|
||||||
LPNMLISTVIEW pnmListView = (LPNMLISTVIEW)lParamSort;
|
sortCompareData* sortData = (sortCompareData*)lParamSort;
|
||||||
TCHAR str1[MAX_PATH];
|
TCHAR str1[MAX_PATH];
|
||||||
TCHAR str2[MAX_PATH];
|
TCHAR str2[MAX_PATH];
|
||||||
|
|
||||||
ListView_GetItemText(pnmListView->hdr.hwndFrom, lParam1, pnmListView->iSubItem, str1, sizeof(str1));
|
ListView_GetItemText(sortData->hListView, lParam1, sortData->columnIndex, str1, sizeof(str1));
|
||||||
ListView_GetItemText(pnmListView->hdr.hwndFrom, lParam2, pnmListView->iSubItem, str2, sizeof(str2));
|
ListView_GetItemText(sortData->hListView, lParam2, sortData->columnIndex, str2, sizeof(str2));
|
||||||
|
|
||||||
LVCOLUMN lvc;
|
|
||||||
lvc.mask = LVCF_FMT;
|
|
||||||
::SendMessage(pnmListView->hdr.hwndFrom, LVM_GETCOLUMN, pnmListView->iSubItem, reinterpret_cast<LPARAM>(&lvc));
|
|
||||||
bool isDirectionUp = (HDF_SORTUP & lvc.fmt) != 0;
|
|
||||||
|
|
||||||
int result = lstrcmp(str1, str2);
|
int result = lstrcmp(str1, str2);
|
||||||
|
|
||||||
if (isDirectionUp)
|
if (sortData->sortDirection == SORT_DIRECTION_UP)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
return (0 - result);
|
return (0 - result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void VerticalFileSwitcher::startColumnSort()
|
||||||
|
{
|
||||||
|
// reset sorting if exts column was just disabled
|
||||||
|
HWND colHeader = reinterpret_cast<HWND>(SendMessage(_fileListView.getHSelf(), LVM_GETHEADER, 0, 0));
|
||||||
|
int columnCount = static_cast<int32_t>(SendMessage(colHeader, HDM_GETITEMCOUNT, 0, 0));
|
||||||
|
if (_lastSortingColumn >= columnCount)
|
||||||
|
{
|
||||||
|
_lastSortingColumn = 0;
|
||||||
|
_lastSortingDirection = SORT_DIRECTION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastSortingDirection != SORT_DIRECTION_NONE)
|
||||||
|
{
|
||||||
|
sortCompareData sortData = {_fileListView.getHSelf(), _lastSortingColumn, _lastSortingDirection};
|
||||||
|
ListView_SortItemsEx(_fileListView.getHSelf(), ListViewCompareProc, reinterpret_cast<LPARAM>(&sortData));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHeaderArrow();
|
||||||
|
}
|
||||||
|
|
||||||
INT_PTR CALLBACK VerticalFileSwitcher::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
INT_PTR CALLBACK VerticalFileSwitcher::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
switch (message)
|
switch (message)
|
||||||
@ -146,8 +161,17 @@ INT_PTR CALLBACK VerticalFileSwitcher::run_dlgProc(UINT message, WPARAM wParam,
|
|||||||
case LVN_COLUMNCLICK:
|
case LVN_COLUMNCLICK:
|
||||||
{
|
{
|
||||||
LPNMLISTVIEW pnmLV = (LPNMLISTVIEW)lParam;
|
LPNMLISTVIEW pnmLV = (LPNMLISTVIEW)lParam;
|
||||||
setHeaderOrder(pnmLV);
|
_lastSortingDirection = setHeaderOrder(pnmLV->iSubItem);
|
||||||
ListView_SortItemsEx(pnmLV->hdr.hwndFrom, ListViewCompareProc, reinterpret_cast<LPARAM>(pnmLV));
|
_lastSortingColumn = pnmLV->iSubItem;
|
||||||
|
if (_lastSortingDirection != SORT_DIRECTION_NONE)
|
||||||
|
{
|
||||||
|
startColumnSort();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_fileListView.reload();
|
||||||
|
updateHeaderArrow();
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case LVN_KEYDOWN:
|
case LVN_KEYDOWN:
|
||||||
@ -220,51 +244,65 @@ void VerticalFileSwitcher::activateDoc(TaskLstFnStatus *tlfs) const
|
|||||||
::SendMessage(_hParent, NPPM_ACTIVATEDOC, view2set, index2Switch);
|
::SendMessage(_hParent, NPPM_ACTIVATEDOC, view2set, index2Switch);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VerticalFileSwitcher::setHeaderOrder(LPNMLISTVIEW pnm_list_view)
|
int VerticalFileSwitcher::setHeaderOrder(int columnIndex)
|
||||||
{
|
{
|
||||||
HWND hListView, colHeader;
|
HWND hListView = _fileListView.getHSelf();
|
||||||
LVCOLUMN lvc;
|
LVCOLUMN lvc;
|
||||||
int q, cols;
|
|
||||||
int index = pnm_list_view->iSubItem;
|
|
||||||
|
|
||||||
lvc.mask = LVCF_FMT;
|
lvc.mask = LVCF_FMT;
|
||||||
hListView = pnm_list_view->hdr.hwndFrom;
|
|
||||||
SendMessage(hListView, LVM_GETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
//strip HDF_SORTUP and HDF_SORTDOWN from old sort column
|
||||||
if(HDF_SORTUP & lvc.fmt)
|
if (_lastSortingColumn != columnIndex && _lastSortingDirection != SORT_DIRECTION_NONE)
|
||||||
|
{
|
||||||
|
HWND colHeader = reinterpret_cast<HWND>(SendMessage(hListView, LVM_GETHEADER, 0, 0));
|
||||||
|
int columnCount = static_cast<int32_t>(SendMessage(colHeader, HDM_GETITEMCOUNT, 0, 0));
|
||||||
|
if (_lastSortingColumn < columnCount)
|
||||||
|
{
|
||||||
|
// Get current fmt
|
||||||
|
SendMessage(hListView, LVM_GETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||||
|
|
||||||
|
// remove both sort-up and sort-down
|
||||||
|
lvc.fmt = lvc.fmt & (~HDF_SORTUP) & (~HDF_SORTDOWN);
|
||||||
|
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastSortingDirection = SORT_DIRECTION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastSortingDirection == SORT_DIRECTION_NONE)
|
||||||
|
{
|
||||||
|
return SORT_DIRECTION_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastSortingDirection == SORT_DIRECTION_UP)
|
||||||
{
|
{
|
||||||
//set the opposite arrow
|
|
||||||
lvc.fmt = lvc.fmt & (~HDF_SORTUP) | HDF_SORTDOWN; //turns off sort-up, turns on sort-down
|
|
||||||
SendMessage(hListView, LVM_SETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
|
||||||
//use any sorting you would use, e.g. the LVM_SORTITEMS message
|
|
||||||
return SORT_DIRECTION_DOWN;
|
return SORT_DIRECTION_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HDF_SORTDOWN & lvc.fmt)
|
//if (_lastSortingDirection == SORT_DIRECTION_DOWN)
|
||||||
{
|
return SORT_DIRECTION_NONE;
|
||||||
//the opposite
|
}
|
||||||
lvc.fmt = lvc.fmt & (~HDF_SORTDOWN) | HDF_SORTUP;
|
|
||||||
SendMessage(hListView, LVM_SETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
void VerticalFileSwitcher::updateHeaderArrow()
|
||||||
return SORT_DIRECTION_UP;
|
{
|
||||||
}
|
HWND hListView = _fileListView.getHSelf();
|
||||||
|
LVCOLUMN lvc;
|
||||||
// this is the case our clicked column wasn't the one being sorted up until now
|
lvc.mask = LVCF_FMT;
|
||||||
// so first we need to iterate through all columns and send LVM_SETCOLUMN to them with fmt set to NOT include these HDFs
|
|
||||||
colHeader = reinterpret_cast<HWND>(SendMessage(hListView, LVM_GETHEADER, 0, 0));
|
SendMessage(hListView, LVM_GETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||||
cols = static_cast<int32_t>(SendMessage(colHeader, HDM_GETITEMCOUNT, 0, 0));
|
|
||||||
for (q = 0; q < cols; ++q)
|
if (_lastSortingDirection == SORT_DIRECTION_UP)
|
||||||
{
|
{
|
||||||
//Get current fmt
|
lvc.fmt = lvc.fmt | HDF_SORTUP & ~HDF_SORTDOWN;
|
||||||
SendMessage(hListView, LVM_GETCOLUMN, q, reinterpret_cast<LPARAM>(&lvc));
|
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||||
//remove both sort-up and sort-down
|
}
|
||||||
lvc.fmt = lvc.fmt & (~HDF_SORTUP) & (~HDF_SORTDOWN);
|
else if (_lastSortingDirection == SORT_DIRECTION_DOWN)
|
||||||
SendMessage(hListView, LVM_SETCOLUMN, q, reinterpret_cast<LPARAM>(&lvc));
|
{
|
||||||
}
|
lvc.fmt = lvc.fmt & ~HDF_SORTUP | HDF_SORTDOWN;
|
||||||
|
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||||
//read current fmt from clicked column
|
}
|
||||||
SendMessage(hListView, LVM_GETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
else if (_lastSortingDirection == SORT_DIRECTION_NONE)
|
||||||
// then set whichever arrow you feel like and send LVM_SETCOLUMN to this particular column
|
{
|
||||||
lvc.fmt = lvc.fmt | HDF_SORTUP;
|
lvc.fmt = lvc.fmt & (~HDF_SORTUP) & (~HDF_SORTDOWN);
|
||||||
SendMessage(hListView, LVM_SETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||||
|
}
|
||||||
return SORT_DIRECTION_UP;
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,12 @@
|
|||||||
|
|
||||||
#define FS_PROJECTPANELTITLE TEXT("Doc Switcher")
|
#define FS_PROJECTPANELTITLE TEXT("Doc Switcher")
|
||||||
|
|
||||||
|
struct sortCompareData {
|
||||||
|
HWND hListView;
|
||||||
|
int columnIndex;
|
||||||
|
int sortDirection;
|
||||||
|
};
|
||||||
|
|
||||||
class VerticalFileSwitcher : public DockingDlgInterface {
|
class VerticalFileSwitcher : public DockingDlgInterface {
|
||||||
public:
|
public:
|
||||||
VerticalFileSwitcher(): DockingDlgInterface(IDD_FILESWITCHER_PANEL) {};
|
VerticalFileSwitcher(): DockingDlgInterface(IDD_FILESWITCHER_PANEL) {};
|
||||||
@ -75,7 +81,8 @@ public:
|
|||||||
return _fileListView.getFullFilePath(i);
|
return _fileListView.getFullFilePath(i);
|
||||||
};
|
};
|
||||||
|
|
||||||
int setHeaderOrder(LPNMLISTVIEW pnm_list_view);
|
int setHeaderOrder(int columnIndex);
|
||||||
|
void updateHeaderArrow();
|
||||||
|
|
||||||
int nbSelectedFiles() const {
|
int nbSelectedFiles() const {
|
||||||
return _fileListView.nbSelectedFiles();
|
return _fileListView.nbSelectedFiles();
|
||||||
@ -84,11 +91,18 @@ public:
|
|||||||
std::vector<SwitcherFileInfo> getSelectedFiles(bool reverse = false) const {
|
std::vector<SwitcherFileInfo> getSelectedFiles(bool reverse = false) const {
|
||||||
return _fileListView.getSelectedFiles(reverse);
|
return _fileListView.getSelectedFiles(reverse);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void startColumnSort();
|
||||||
|
|
||||||
void reload(){
|
void reload(){
|
||||||
_fileListView.deleteColumn(1);
|
|
||||||
_fileListView.deleteColumn(0);
|
|
||||||
_fileListView.reload();
|
_fileListView.reload();
|
||||||
|
startColumnSort();
|
||||||
|
};
|
||||||
|
|
||||||
|
void updateTabOrder(){
|
||||||
|
if (_lastSortingDirection == SORT_DIRECTION_NONE) {
|
||||||
|
_fileListView.reload();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void setBackgroundColor(COLORREF bgColour) {
|
virtual void setBackgroundColor(COLORREF bgColour) {
|
||||||
@ -98,11 +112,11 @@ public:
|
|||||||
virtual void setForegroundColor(COLORREF fgColour) {
|
virtual void setForegroundColor(COLORREF fgColour) {
|
||||||
_fileListView.setForegroundColor(fgColour);
|
_fileListView.setForegroundColor(fgColour);
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
|
virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int _lastSortingColumn = 0;
|
||||||
|
int _lastSortingDirection = SORT_DIRECTION_NONE;
|
||||||
VerticalFileSwitcherListView _fileListView;
|
VerticalFileSwitcherListView _fileListView;
|
||||||
HIMAGELIST _hImaLst = nullptr;
|
HIMAGELIST _hImaLst = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -97,28 +97,53 @@ LRESULT VerticalFileSwitcherListView::runProc(HWND hwnd, UINT Message, WPARAM wP
|
|||||||
|
|
||||||
void VerticalFileSwitcherListView::initList()
|
void VerticalFileSwitcherListView::initList()
|
||||||
{
|
{
|
||||||
TaskListInfo taskListInfo;
|
HWND colHeader = reinterpret_cast<HWND>(SendMessage(_hSelf, LVM_GETHEADER, 0, 0));
|
||||||
static HWND nppHwnd = ::GetParent(_hParent);
|
int columnCount = static_cast<int32_t>(SendMessage(colHeader, HDM_GETITEMCOUNT, 0, 0));
|
||||||
::SendMessage(nppHwnd, WM_GETTASKLISTINFO, reinterpret_cast<WPARAM>(&taskListInfo), TRUE);
|
|
||||||
|
|
||||||
NppParameters *nppParams = NppParameters::getInstance();
|
NppParameters *nppParams = NppParameters::getInstance();
|
||||||
NativeLangSpeaker *pNativeSpeaker = nppParams->getNativeLangSpeaker();
|
NativeLangSpeaker *pNativeSpeaker = nppParams->getNativeLangSpeaker();
|
||||||
|
|
||||||
bool isExtColumn = !nppParams->getNppGUI()._fileSwitcherWithoutExtColumn;
|
bool isExtColumn = !nppParams->getNppGUI()._fileSwitcherWithoutExtColumn;
|
||||||
|
|
||||||
RECT rc;
|
// check if columns need to be added
|
||||||
::GetClientRect(_hParent, &rc);
|
if (columnCount <= 1)
|
||||||
int totalWidth = rc.right - rc.left;
|
|
||||||
|
|
||||||
generic_string nameStr = pNativeSpeaker->getAttrNameStr(TEXT("Name"), FS_ROOTNODE, FS_CLMNNAME);
|
|
||||||
|
|
||||||
insertColumn(nameStr.c_str(), (isExtColumn ? totalWidth - 50 : totalWidth), 0);
|
|
||||||
|
|
||||||
if (isExtColumn)
|
|
||||||
{
|
{
|
||||||
generic_string extStr = pNativeSpeaker->getAttrNameStr(TEXT("Ext."), FS_ROOTNODE, FS_CLMNEXT);
|
RECT rc;
|
||||||
insertColumn(extStr.c_str(), 50, 1);
|
::GetClientRect(_hParent, &rc);
|
||||||
|
int totalWidth = rc.right - rc.left;
|
||||||
|
|
||||||
|
if (columnCount == 0)
|
||||||
|
{
|
||||||
|
generic_string nameStr = pNativeSpeaker->getAttrNameStr(TEXT("Name"), FS_ROOTNODE, FS_CLMNNAME);
|
||||||
|
insertColumn(nameStr.c_str(), (isExtColumn ? totalWidth - 50 : totalWidth), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExtColumn)
|
||||||
|
{
|
||||||
|
// resize "Name" column when "exts" won't fit
|
||||||
|
LVCOLUMN lvc;
|
||||||
|
SendMessage(_hSelf, LVM_GETCOLUMN, 0, reinterpret_cast<LPARAM>(&lvc));
|
||||||
|
|
||||||
|
if (lvc.cx + 50 > totalWidth)
|
||||||
|
{
|
||||||
|
lvc.cx = totalWidth - 50;
|
||||||
|
SendMessage(_hSelf, LVM_SETCOLUMN, 0, reinterpret_cast<LPARAM>(&lvc));
|
||||||
|
}
|
||||||
|
|
||||||
|
generic_string extStr = pNativeSpeaker->getAttrNameStr(TEXT("Ext."), FS_ROOTNODE, FS_CLMNEXT);
|
||||||
|
insertColumn(extStr.c_str(), 50, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "exts" was disabled
|
||||||
|
if (columnCount >= 2 && !isExtColumn)
|
||||||
|
{
|
||||||
|
ListView_DeleteColumn(_hSelf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskListInfo taskListInfo;
|
||||||
|
static HWND nppHwnd = ::GetParent(_hParent);
|
||||||
|
::SendMessage(nppHwnd, WM_GETTASKLISTINFO, reinterpret_cast<WPARAM>(&taskListInfo), TRUE);
|
||||||
|
|
||||||
for (size_t i = 0, len = taskListInfo._tlfsLst.size(); i < len ; ++i)
|
for (size_t i = 0, len = taskListInfo._tlfsLst.size(); i < len ; ++i)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
class Buffer;
|
class Buffer;
|
||||||
typedef Buffer * BufferID; //each buffer has unique ID by which it can be retrieved
|
typedef Buffer * BufferID; //each buffer has unique ID by which it can be retrieved
|
||||||
|
|
||||||
|
#define SORT_DIRECTION_NONE -1
|
||||||
#define SORT_DIRECTION_UP 0
|
#define SORT_DIRECTION_UP 0
|
||||||
#define SORT_DIRECTION_DOWN 1
|
#define SORT_DIRECTION_DOWN 1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user