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 :
|
||||
{
|
||||
if (_pFileSwitcherPanel)
|
||||
{
|
||||
_pFileSwitcherPanel->updateTabOrder();
|
||||
}
|
||||
|
||||
BufferID id = _pEditView->getCurrentBufferID();
|
||||
|
||||
// Notify plugins that current file is about to be closed
|
||||
|
@ -34,26 +34,41 @@
|
||||
|
||||
int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
||||
{
|
||||
LPNMLISTVIEW pnmListView = (LPNMLISTVIEW)lParamSort;
|
||||
sortCompareData* sortData = (sortCompareData*)lParamSort;
|
||||
TCHAR str1[MAX_PATH];
|
||||
TCHAR str2[MAX_PATH];
|
||||
|
||||
ListView_GetItemText(pnmListView->hdr.hwndFrom, lParam1, pnmListView->iSubItem, str1, sizeof(str1));
|
||||
ListView_GetItemText(pnmListView->hdr.hwndFrom, lParam2, pnmListView->iSubItem, 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;
|
||||
ListView_GetItemText(sortData->hListView, lParam1, sortData->columnIndex, str1, sizeof(str1));
|
||||
ListView_GetItemText(sortData->hListView, lParam2, sortData->columnIndex, str2, sizeof(str2));
|
||||
|
||||
int result = lstrcmp(str1, str2);
|
||||
|
||||
if (isDirectionUp)
|
||||
if (sortData->sortDirection == SORT_DIRECTION_UP)
|
||||
return 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)
|
||||
{
|
||||
switch (message)
|
||||
@ -146,8 +161,17 @@ INT_PTR CALLBACK VerticalFileSwitcher::run_dlgProc(UINT message, WPARAM wParam,
|
||||
case LVN_COLUMNCLICK:
|
||||
{
|
||||
LPNMLISTVIEW pnmLV = (LPNMLISTVIEW)lParam;
|
||||
setHeaderOrder(pnmLV);
|
||||
ListView_SortItemsEx(pnmLV->hdr.hwndFrom, ListViewCompareProc, reinterpret_cast<LPARAM>(pnmLV));
|
||||
_lastSortingDirection = setHeaderOrder(pnmLV->iSubItem);
|
||||
_lastSortingColumn = pnmLV->iSubItem;
|
||||
if (_lastSortingDirection != SORT_DIRECTION_NONE)
|
||||
{
|
||||
startColumnSort();
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileListView.reload();
|
||||
updateHeaderArrow();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
case LVN_KEYDOWN:
|
||||
@ -220,51 +244,65 @@ void VerticalFileSwitcher::activateDoc(TaskLstFnStatus *tlfs) const
|
||||
::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;
|
||||
int q, cols;
|
||||
int index = pnm_list_view->iSubItem;
|
||||
|
||||
lvc.mask = LVCF_FMT;
|
||||
hListView = pnm_list_view->hdr.hwndFrom;
|
||||
SendMessage(hListView, LVM_GETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
||||
if(HDF_SORTUP & lvc.fmt)
|
||||
|
||||
//strip HDF_SORTUP and HDF_SORTDOWN from old sort column
|
||||
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;
|
||||
}
|
||||
|
||||
if(HDF_SORTDOWN & lvc.fmt)
|
||||
{
|
||||
//the opposite
|
||||
lvc.fmt = lvc.fmt & (~HDF_SORTDOWN) | HDF_SORTUP;
|
||||
SendMessage(hListView, LVM_SETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
||||
return SORT_DIRECTION_UP;
|
||||
}
|
||||
|
||||
// this is the case our clicked column wasn't the one being sorted up until now
|
||||
// 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));
|
||||
cols = static_cast<int32_t>(SendMessage(colHeader, HDM_GETITEMCOUNT, 0, 0));
|
||||
for (q = 0; q < cols; ++q)
|
||||
{
|
||||
//Get current fmt
|
||||
SendMessage(hListView, LVM_GETCOLUMN, q, reinterpret_cast<LPARAM>(&lvc));
|
||||
//remove both sort-up and sort-down
|
||||
lvc.fmt = lvc.fmt & (~HDF_SORTUP) & (~HDF_SORTDOWN);
|
||||
SendMessage(hListView, LVM_SETCOLUMN, q, reinterpret_cast<LPARAM>(&lvc));
|
||||
}
|
||||
|
||||
//read current fmt from clicked column
|
||||
SendMessage(hListView, LVM_GETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
||||
// then set whichever arrow you feel like and send LVM_SETCOLUMN to this particular column
|
||||
lvc.fmt = lvc.fmt | HDF_SORTUP;
|
||||
SendMessage(hListView, LVM_SETCOLUMN, index, reinterpret_cast<LPARAM>(&lvc));
|
||||
|
||||
return SORT_DIRECTION_UP;
|
||||
//if (_lastSortingDirection == SORT_DIRECTION_DOWN)
|
||||
return SORT_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
void VerticalFileSwitcher::updateHeaderArrow()
|
||||
{
|
||||
HWND hListView = _fileListView.getHSelf();
|
||||
LVCOLUMN lvc;
|
||||
lvc.mask = LVCF_FMT;
|
||||
|
||||
SendMessage(hListView, LVM_GETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||
|
||||
if (_lastSortingDirection == SORT_DIRECTION_UP)
|
||||
{
|
||||
lvc.fmt = lvc.fmt | HDF_SORTUP & ~HDF_SORTDOWN;
|
||||
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||
}
|
||||
else if (_lastSortingDirection == SORT_DIRECTION_DOWN)
|
||||
{
|
||||
lvc.fmt = lvc.fmt & ~HDF_SORTUP | HDF_SORTDOWN;
|
||||
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||
}
|
||||
else if (_lastSortingDirection == SORT_DIRECTION_NONE)
|
||||
{
|
||||
lvc.fmt = lvc.fmt & (~HDF_SORTUP) & (~HDF_SORTDOWN);
|
||||
SendMessage(hListView, LVM_SETCOLUMN, _lastSortingColumn, reinterpret_cast<LPARAM>(&lvc));
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,12 @@
|
||||
|
||||
#define FS_PROJECTPANELTITLE TEXT("Doc Switcher")
|
||||
|
||||
struct sortCompareData {
|
||||
HWND hListView;
|
||||
int columnIndex;
|
||||
int sortDirection;
|
||||
};
|
||||
|
||||
class VerticalFileSwitcher : public DockingDlgInterface {
|
||||
public:
|
||||
VerticalFileSwitcher(): DockingDlgInterface(IDD_FILESWITCHER_PANEL) {};
|
||||
@ -75,7 +81,8 @@ public:
|
||||
return _fileListView.getFullFilePath(i);
|
||||
};
|
||||
|
||||
int setHeaderOrder(LPNMLISTVIEW pnm_list_view);
|
||||
int setHeaderOrder(int columnIndex);
|
||||
void updateHeaderArrow();
|
||||
|
||||
int nbSelectedFiles() const {
|
||||
return _fileListView.nbSelectedFiles();
|
||||
@ -85,10 +92,17 @@ public:
|
||||
return _fileListView.getSelectedFiles(reverse);
|
||||
};
|
||||
|
||||
void startColumnSort();
|
||||
|
||||
void reload(){
|
||||
_fileListView.deleteColumn(1);
|
||||
_fileListView.deleteColumn(0);
|
||||
_fileListView.reload();
|
||||
startColumnSort();
|
||||
};
|
||||
|
||||
void updateTabOrder(){
|
||||
if (_lastSortingDirection == SORT_DIRECTION_NONE) {
|
||||
_fileListView.reload();
|
||||
}
|
||||
};
|
||||
|
||||
virtual void setBackgroundColor(COLORREF bgColour) {
|
||||
@ -98,11 +112,11 @@ public:
|
||||
virtual void setForegroundColor(COLORREF fgColour) {
|
||||
_fileListView.setForegroundColor(fgColour);
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
private:
|
||||
int _lastSortingColumn = 0;
|
||||
int _lastSortingDirection = SORT_DIRECTION_NONE;
|
||||
VerticalFileSwitcherListView _fileListView;
|
||||
HIMAGELIST _hImaLst = nullptr;
|
||||
};
|
||||
|
@ -97,28 +97,53 @@ LRESULT VerticalFileSwitcherListView::runProc(HWND hwnd, UINT Message, WPARAM wP
|
||||
|
||||
void VerticalFileSwitcherListView::initList()
|
||||
{
|
||||
TaskListInfo taskListInfo;
|
||||
static HWND nppHwnd = ::GetParent(_hParent);
|
||||
::SendMessage(nppHwnd, WM_GETTASKLISTINFO, reinterpret_cast<WPARAM>(&taskListInfo), TRUE);
|
||||
HWND colHeader = reinterpret_cast<HWND>(SendMessage(_hSelf, LVM_GETHEADER, 0, 0));
|
||||
int columnCount = static_cast<int32_t>(SendMessage(colHeader, HDM_GETITEMCOUNT, 0, 0));
|
||||
|
||||
NppParameters *nppParams = NppParameters::getInstance();
|
||||
NativeLangSpeaker *pNativeSpeaker = nppParams->getNativeLangSpeaker();
|
||||
|
||||
bool isExtColumn = !nppParams->getNppGUI()._fileSwitcherWithoutExtColumn;
|
||||
|
||||
// check if columns need to be added
|
||||
if (columnCount <= 1)
|
||||
{
|
||||
RECT rc;
|
||||
::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)
|
||||
{
|
||||
|
@ -35,6 +35,7 @@
|
||||
class Buffer;
|
||||
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_DOWN 1
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user