Support sort indicators in wxListCtrl header

This commit is contained in:
Maarten Bent
2021-11-28 19:19:59 +01:00
parent 9febbe2b30
commit d8ec0aa001
7 changed files with 262 additions and 1 deletions

View File

@@ -115,6 +115,13 @@ public:
virtual bool IsItemChecked(long item) const wxOVERRIDE; virtual bool IsItemChecked(long item) const wxOVERRIDE;
virtual void CheckItem(long item, bool check) wxOVERRIDE; virtual void CheckItem(long item, bool check) wxOVERRIDE;
void EnableSortIndicator(const bool enable = true) wxOVERRIDE;
bool IsSortIndicatorEnabled() const wxOVERRIDE;
void ShowSortIndicator(const int idx, const bool ascending = true) wxOVERRIDE;
void RemoveSortIndicator() wxOVERRIDE;
int GetSortIndicator() const wxOVERRIDE;
bool IsAscendingSortIndicator() const wxOVERRIDE;
void SetSingleStyle( long style, bool add = true ) ; void SetSingleStyle( long style, bool add = true ) ;
void SetWindowStyleFlag( long style ) wxOVERRIDE; void SetWindowStyleFlag( long style ) wxOVERRIDE;
void RecreateWindow() {} void RecreateWindow() {}

View File

@@ -381,6 +381,10 @@ public:
int m_colToSend; int m_colToSend;
int m_widthToSend; int m_widthToSend;
bool m_enableSortCol;
bool m_sortAsc;
int m_sortCol;
virtual wxWindow *GetMainWindowOfCompositeControl() wxOVERRIDE { return GetParent(); } virtual wxWindow *GetMainWindowOfCompositeControl() wxOVERRIDE { return GetParent(); }
virtual void OnInternalIdle() wxOVERRIDE; virtual void OnInternalIdle() wxOVERRIDE;

View File

@@ -446,6 +446,14 @@ public:
virtual bool IsItemChecked(long WXUNUSED(item)) const { return false; } virtual bool IsItemChecked(long WXUNUSED(item)) const { return false; }
virtual void CheckItem(long WXUNUSED(item), bool WXUNUSED(check)) { } virtual void CheckItem(long WXUNUSED(item), bool WXUNUSED(check)) { }
// Sort indicator in header.
virtual void EnableSortIndicator(const bool WXUNUSED(enable) = true) { }
virtual bool IsSortIndicatorEnabled() const { return false; }
virtual void ShowSortIndicator(const int WXUNUSED(idx), const bool WXUNUSED(ascending) = true) { }
virtual void RemoveSortIndicator() { }
virtual int GetSortIndicator() const { return -1; }
virtual bool IsAscendingSortIndicator() const { return true; }
protected: protected:
// Return pointer to the corresponding m_imagesXXX. // Return pointer to the corresponding m_imagesXXX.
const wxWithImages* GetImages(int which) const; const wxWithImages* GetImages(int which) const;

View File

@@ -225,6 +225,14 @@ public:
virtual bool IsItemChecked(long item) const wxOVERRIDE; virtual bool IsItemChecked(long item) const wxOVERRIDE;
virtual void CheckItem(long item, bool check) wxOVERRIDE; virtual void CheckItem(long item, bool check) wxOVERRIDE;
// Sort indicator in header
void EnableSortIndicator(const bool enable = true) wxOVERRIDE;
bool IsSortIndicatorEnabled() const wxOVERRIDE;
void ShowSortIndicator(const int idx, const bool ascending = true) wxOVERRIDE;
void RemoveSortIndicator() wxOVERRIDE;
int GetSortIndicator() const wxOVERRIDE;
bool IsAscendingSortIndicator() const wxOVERRIDE;
// Gets the number of selected items in the list control // Gets the number of selected items in the list control
int GetSelectedItemCount() const; int GetSelectedItemCount() const;
@@ -418,6 +426,10 @@ protected:
int m_colCount; // Windows doesn't have GetColumnCount so must int m_colCount; // Windows doesn't have GetColumnCount so must
// keep track of inserted/deleted columns // keep track of inserted/deleted columns
bool m_enableSortCol;
bool m_sortAsc;
int m_sortCol;
// all wxMSWListItemData objects we use // all wxMSWListItemData objects we use
wxVector<wxMSWListItemData *> m_internalData; wxVector<wxMSWListItemData *> m_internalData;
@@ -445,6 +457,8 @@ private:
// in-place editor control. // in-place editor control.
void OnCharHook(wxKeyEvent& event); void OnCharHook(wxKeyEvent& event);
// Draw the sort arrow arror in the header.
void DrawSortArrow();
// Object using for header custom drawing if necessary, may be NULL. // Object using for header custom drawing if necessary, may be NULL.
wxMSWListHeaderCustomDraw* m_headerCustomDraw; wxMSWListHeaderCustomDraw* m_headerCustomDraw;

View File

@@ -1420,6 +1420,72 @@ public:
*/ */
void ExtendRulesAndAlternateColour(bool extend = true); void ExtendRulesAndAlternateColour(bool extend = true);
/**
Enable or disable showing a sort indicator in the header bar.
Sort indicators are only shown in report view.
When clicking on the header of a column, this column will get the sort-
indicator in ascending order, or toggle it in the opposite order. To
sort the list, call SortItems() in EVT_LIST_COL_CLICK.
@note In wxMSW, this will disable the header icon of the column.
@param enable
If @true, enable showing a sort indicator, otherwise disable.
@since 3.1.6
*/
void EnableSortIndicator(const bool enable);
/**
Returns true if a sort indicator is enabled.
@see EnableSortIndicator()
@since 3.1.6
*/
bool IsSortIndicatorEnabled() const;
/**
Show the sort indicator of a specific column in a specific direction.
Sort indicators have to be enabled using EnableSortIndicator().
@note This does not actually sort the list, use SortItems() for this.
@param idx
The column to set the sort indicator for.
If @c -1 is given, then the currently shown sort indicator
will be removed.
@param ascending
If @true or @false show the sort indicator corresponding to
ascending or descending sort order respectively.
@since 3.1.6
*/
void ShowSortIndicator(const int idx, const bool ascending = true);
/**
Remove the sort indicator from the column being used as sort key.
@since 3.1.6
*/
int RemoveSortIndicator() const;
/**
Returns the column that shows the sort indicator.
@since 3.1.6
*/
int GetSortIndicator() const;
/**
Returns @true if the sort indicator direction is ascending,
@false when the direction is descending.
@since 3.1.6
*/
bool IsAscendingSortIndicator() const;
protected: protected:
/** /**

View File

@@ -981,6 +981,10 @@ wxListHeaderWindow::wxListHeaderWindow()
m_owner = NULL; m_owner = NULL;
m_resizeCursor = NULL; m_resizeCursor = NULL;
m_enableSortCol = false;
m_sortAsc = true;
m_sortCol = -1;
} }
bool wxListHeaderWindow::Create( wxWindow *win, bool wxListHeaderWindow::Create( wxWindow *win,
@@ -1099,6 +1103,15 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
flags |= wxCONTROL_SELECTED; flags |= wxCONTROL_SELECTED;
#endif #endif
wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE;
if ( !m_owner->IsVirtual() && m_enableSortCol && i == m_sortCol )
{
if ( m_sortAsc )
sortArrow = wxHDR_SORT_ICON_UP;
else
sortArrow = wxHDR_SORT_ICON_DOWN;
}
if (i == 0) if (i == 0)
flags |= wxCONTROL_SPECIAL; // mark as first column flags |= wxCONTROL_SPECIAL; // mark as first column
@@ -1107,7 +1120,8 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
this, this,
dc, dc,
wxRect(x, HEADER_OFFSET_Y, cw, ch), wxRect(x, HEADER_OFFSET_Y, cw, ch),
flags flags,
sortArrow
); );
// see if we have enough space for the column label // see if we have enough space for the column label
@@ -1320,6 +1334,12 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
colItem.SetState(state & ~wxLIST_STATE_SELECTED); colItem.SetState(state & ~wxLIST_STATE_SELECTED);
m_owner->SetColumn(i, colItem); m_owner->SetColumn(i, colItem);
} }
if ( m_sortCol != m_column )
m_sortAsc = true;
else
m_sortAsc = !m_sortAsc;
m_sortCol = m_column;
} }
SendListEvent( event.LeftDown() SendListEvent( event.LeftDown()
@@ -5064,6 +5084,60 @@ bool wxGenericListCtrl::IsItemChecked(long item) const
return m_mainWin->IsItemChecked(item); return m_mainWin->IsItemChecked(item);
} }
void wxGenericListCtrl::EnableSortIndicator(const bool enable)
{
if ( m_headerWin )
{
m_headerWin->m_enableSortCol = enable;
Refresh();
}
}
bool wxGenericListCtrl::IsSortIndicatorEnabled() const
{
return m_headerWin && m_headerWin->m_enableSortCol;
}
void wxGenericListCtrl::ShowSortIndicator(const int idx, const bool ascending)
{
if ( idx == -1 )
{
RemoveSortIndicator();
}
else if ( m_headerWin )
{
m_headerWin->m_sortCol = idx;
m_headerWin->m_sortAsc = ascending;
Refresh();
}
}
void wxGenericListCtrl::RemoveSortIndicator()
{
if ( m_headerWin )
{
m_headerWin->m_sortCol = -1;
m_headerWin->m_sortAsc = true;
Refresh();
}
}
int wxGenericListCtrl::GetSortIndicator() const
{
if ( m_headerWin )
return m_headerWin->m_sortCol;
return -1;
}
bool wxGenericListCtrl::IsAscendingSortIndicator() const
{
if ( m_headerWin )
return m_headerWin->m_sortAsc;
return true;
}
void wxGenericListCtrl::SetSingleStyle( long style, bool add ) void wxGenericListCtrl::SetSingleStyle( long style, bool add )
{ {
wxASSERT_MSG( !(style & wxLC_VIRTUAL), wxASSERT_MSG( !(style & wxLC_VIRTUAL),

View File

@@ -278,6 +278,10 @@ void wxListCtrl::Init()
m_colCount = 0; m_colCount = 0;
m_textCtrl = NULL; m_textCtrl = NULL;
m_enableSortCol = false;
m_sortAsc = true;
m_sortCol = -1;
m_hasAnyAttr = false; m_hasAnyAttr = false;
m_headerCustomDraw = NULL; m_headerCustomDraw = NULL;
@@ -1452,6 +1456,48 @@ bool wxListCtrl::IsItemChecked(long item) const
return ListView_GetCheckState(GetHwnd(), (UINT)item) != 0; return ListView_GetCheckState(GetHwnd(), (UINT)item) != 0;
} }
void wxListCtrl::EnableSortIndicator(const bool enable)
{
m_enableSortCol = enable;
DrawSortArrow();
}
bool wxListCtrl::IsSortIndicatorEnabled() const
{
return m_enableSortCol;
}
void wxListCtrl::ShowSortIndicator(const int idx, const bool ascending)
{
if ( idx == -1 )
{
RemoveSortIndicator();
}
else
{
m_sortCol = idx;
m_sortAsc = ascending;
DrawSortArrow();
}
}
void wxListCtrl::RemoveSortIndicator()
{
m_sortCol = -1;
m_sortAsc = true;
DrawSortArrow();
}
int wxListCtrl::GetSortIndicator() const
{
return m_sortCol;
}
bool wxListCtrl::IsAscendingSortIndicator() const
{
return m_sortAsc;
}
// Gets the number of selected items in the list control // Gets the number of selected items in the list control
int wxListCtrl::GetSelectedItemCount() const int wxListCtrl::GetSelectedItemCount() const
{ {
@@ -2045,6 +2091,8 @@ long wxListCtrl::DoInsertColumn(long col, const wxListItem& item)
SetColumnWidth(n, wxLIST_AUTOSIZE_USEHEADER); SetColumnWidth(n, wxLIST_AUTOSIZE_USEHEADER);
} }
DrawSortArrow();
return n; return n;
} }
@@ -2419,6 +2467,13 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
break; break;
case LVN_COLUMNCLICK: case LVN_COLUMNCLICK:
if ( m_sortCol != nmLV->iSubItem )
m_sortAsc = true;
else
m_sortAsc = !m_sortAsc;
m_sortCol = nmLV->iSubItem;
DrawSortArrow();
eventType = wxEVT_LIST_COL_CLICK; eventType = wxEVT_LIST_COL_CLICK;
event.m_itemIndex = -1; event.m_itemIndex = -1;
event.m_col = nmLV->iSubItem; event.m_col = nmLV->iSubItem;
@@ -3361,6 +3416,39 @@ void wxListCtrl::OnCharHook(wxKeyEvent& event)
event.Skip(); event.Skip();
} }
void wxListCtrl::DrawSortArrow()
{
if ( HasFlag(wxLC_SORT_ASCENDING) || HasFlag(wxLC_SORT_DESCENDING) )
{
m_sortCol = 0;
m_sortAsc = HasFlag(wxLC_SORT_ASCENDING);
}
LV_COLUMN lvCol;
wxZeroMemory(lvCol);
lvCol.mask = LVCF_FMT;
for ( int col = 0; col < m_colCount; ++col )
{
if ( ListView_GetColumn(GetHwnd(), col, &lvCol) )
{
if ( !IsVirtual() && m_enableSortCol && col == m_sortCol )
{
if ( m_sortAsc )
lvCol.fmt = (lvCol.fmt & ~HDF_SORTDOWN) | HDF_SORTUP;
else
lvCol.fmt = (lvCol.fmt & ~HDF_SORTUP) | HDF_SORTDOWN;
}
else
{
lvCol.fmt = lvCol.fmt & ~(HDF_SORTDOWN | HDF_SORTUP);
}
ListView_SetColumn(GetHwnd(), col, &lvCol);
}
}
}
WXLRESULT WXLRESULT
wxListCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxListCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{ {