Keep Doc Switcher's ordering in sync with Tab bar

Close #946, close #1684, close #2342, close #4015
This commit is contained in:
AngryGamer 2018-02-11 17:13:34 -08:00 committed by Don HO
parent 87feb9677e
commit 883045d96f
5 changed files with 155 additions and 72 deletions

View File

@ -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

View File

@ -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));
}
}

View File

@ -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();
@ -84,11 +91,18 @@ public:
std::vector<SwitcherFileInfo> getSelectedFiles(bool reverse = false) const {
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;
};

View File

@ -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;
RECT rc;
::GetClientRect(_hParent, &rc);
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)
// check if columns need to be added
if (columnCount <= 1)
{
generic_string extStr = pNativeSpeaker->getAttrNameStr(TEXT("Ext."), FS_ROOTNODE, FS_CLMNEXT);
insertColumn(extStr.c_str(), 50, 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)
{

View File

@ -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