X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f8ec7b81b280bf11b40529c7fc9317ba9f052bee..1f11ce5b66872407bc97a0e446a5f82dea401930:/src/generic/treelist.cpp diff --git a/src/generic/treelist.cpp b/src/generic/treelist.cpp index 806ae748ba..6063ccf0a6 100644 --- a/src/generic/treelist.cpp +++ b/src/generic/treelist.cpp @@ -378,6 +378,10 @@ public: virtual unsigned GetChildren(const wxDataViewItem& item, wxDataViewItemArray& children) const; virtual bool IsListModel() const { return m_isFlat; } + virtual int Compare(const wxDataViewItem& item1, + const wxDataViewItem& item2, + unsigned col, + bool ascending) const; private: // The control we're associated with. @@ -953,6 +957,27 @@ wxTreeListModel::GetChildren(const wxDataViewItem& item, return numChildren; } +int +wxTreeListModel::Compare(const wxDataViewItem& item1, + const wxDataViewItem& item2, + unsigned col, + bool ascending) const +{ + // Compare using default alphabetical order if no custom comparator. + wxTreeListItemComparator* const comp = m_treelist->m_comparator; + if ( !comp ) + return wxDataViewModel::Compare(item1, item2, col, ascending); + + // Forward comparison to the comparator: + int result = comp->Compare(m_treelist, col, FromDVI(item1), FromDVI(item2)); + + // And adjust by the sort order if necessary. + if ( !ascending ) + result = -result; + + return result; +} + // ============================================================================ // wxTreeListCtrl implementation // ============================================================================ @@ -963,6 +988,7 @@ BEGIN_EVENT_TABLE(wxTreeListCtrl, wxWindow) EVT_DATAVIEW_ITEM_EXPANDED(wxID_ANY, wxTreeListCtrl::OnItemExpanded) EVT_DATAVIEW_ITEM_ACTIVATED(wxID_ANY, wxTreeListCtrl::OnItemActivated) EVT_DATAVIEW_ITEM_CONTEXT_MENU(wxID_ANY, wxTreeListCtrl::OnItemContextMenu) + EVT_DATAVIEW_COLUMN_SORTED(wxID_ANY, wxTreeListCtrl::OnColumnSorted) EVT_SIZE(wxTreeListCtrl::OnSize) END_EVENT_TABLE() @@ -975,6 +1001,7 @@ void wxTreeListCtrl::Init() { m_view = NULL; m_model = NULL; + m_comparator = NULL; } bool wxTreeListCtrl::Create(wxWindow* parent, @@ -1454,11 +1481,48 @@ wxTreeListCtrl::AreAllChildrenInState(wxTreeListItem item, return true; } +// ---------------------------------------------------------------------------- +// Sorting +// ---------------------------------------------------------------------------- + +void wxTreeListCtrl::SetSortColumn(unsigned col, bool ascendingOrder) +{ + wxCHECK_RET( col < m_view->GetColumnCount(), "Invalid column index" ); + + m_view->GetColumn(col)->SetSortOrder(ascendingOrder); +} + +bool wxTreeListCtrl::GetSortColumn(unsigned* col, bool* ascendingOrder) +{ + const unsigned numColumns = m_view->GetColumnCount(); + for ( unsigned n = 0; n < numColumns; n++ ) + { + wxDataViewColumn* const column = m_view->GetColumn(n); + if ( column->IsSortKey() ) + { + if ( col ) + *col = n; + + if ( ascendingOrder ) + *ascendingOrder = column->IsSortOrderAscending(); + + return true; + } + } + + return false; +} + +void wxTreeListCtrl::SetItemComparator(wxTreeListItemComparator* comparator) +{ + m_comparator = comparator; +} + // ---------------------------------------------------------------------------- // Events // ---------------------------------------------------------------------------- -void wxTreeListCtrl::SendEvent(wxEventType evt, wxDataViewEvent& eventDV) +void wxTreeListCtrl::SendItemEvent(wxEventType evt, wxDataViewEvent& eventDV) { wxTreeListEvent eventTL(evt, this, m_model->FromDVI(eventDV.GetItem())); @@ -1474,6 +1538,23 @@ void wxTreeListCtrl::SendEvent(wxEventType evt, wxDataViewEvent& eventDV) } } +void wxTreeListCtrl::SendColumnEvent(wxEventType evt, wxDataViewEvent& eventDV) +{ + wxTreeListEvent eventTL(evt, this, wxTreeListItem()); + eventTL.SetColumn(eventDV.GetColumn()); + + if ( !ProcessWindowEvent(eventTL) ) + { + eventDV.Skip(); + return; + } + + if ( !eventTL.IsAllowed() ) + { + eventDV.Veto(); + } +} + void wxTreeListCtrl::OnItemToggled(wxTreeListItem item, wxCheckBoxState stateOld) { @@ -1485,27 +1566,32 @@ wxTreeListCtrl::OnItemToggled(wxTreeListItem item, wxCheckBoxState stateOld) void wxTreeListCtrl::OnSelectionChanged(wxDataViewEvent& event) { - SendEvent(wxEVT_COMMAND_TREELIST_SELECTION_CHANGED, event); + SendItemEvent(wxEVT_COMMAND_TREELIST_SELECTION_CHANGED, event); } void wxTreeListCtrl::OnItemExpanding(wxDataViewEvent& event) { - SendEvent(wxEVT_COMMAND_TREELIST_ITEM_EXPANDING, event); + SendItemEvent(wxEVT_COMMAND_TREELIST_ITEM_EXPANDING, event); } void wxTreeListCtrl::OnItemExpanded(wxDataViewEvent& event) { - SendEvent(wxEVT_COMMAND_TREELIST_ITEM_EXPANDED, event); + SendItemEvent(wxEVT_COMMAND_TREELIST_ITEM_EXPANDED, event); } void wxTreeListCtrl::OnItemActivated(wxDataViewEvent& event) { - SendEvent(wxEVT_COMMAND_TREELIST_ITEM_ACTIVATED, event); + SendItemEvent(wxEVT_COMMAND_TREELIST_ITEM_ACTIVATED, event); } void wxTreeListCtrl::OnItemContextMenu(wxDataViewEvent& event) { - SendEvent(wxEVT_COMMAND_TREELIST_ITEM_CONTEXT_MENU, event); + SendItemEvent(wxEVT_COMMAND_TREELIST_ITEM_CONTEXT_MENU, event); +} + +void wxTreeListCtrl::OnColumnSorted(wxDataViewEvent& event) +{ + SendColumnEvent(wxEVT_COMMAND_TREELIST_COLUMN_SORTED, event); } // ---------------------------------------------------------------------------- @@ -1522,32 +1608,50 @@ void wxTreeListCtrl::OnSize(wxSizeEvent& event) const wxRect rect = GetClientRect(); m_view->SetSize(rect); - // Resize the first column to take the remaining available space, if - // any. +#ifdef wxHAS_GENERIC_DATAVIEWCTRL + // The generic implementation doesn't refresh itself immediately which + // is annoying during "live resizing", so do it forcefully here to + // ensure that the items are re-laid out and the focus rectangle is + // redrawn correctly (instead of leaving traces) while our size is + // being changed. + wxWindow* const view = GetView(); + view->Refresh(); + view->Update(); +#endif // wxHAS_GENERIC_DATAVIEWCTRL + + // Resize the first column to take the remaining available space. const unsigned numColumns = GetColumnCount(); if ( !numColumns ) return; // There is a bug in generic wxDataViewCtrl: if the column width sums // up to the total size, horizontal scrollbar (unnecessarily) appears, - // so subtract 10 pixels to ensure this doesn't happen. - int remainingWidth = rect.width - 10; + // so subtract a bit to ensure this doesn't happen. + int remainingWidth = rect.width - 5; for ( unsigned n = 1; n < GetColumnCount(); n++ ) { remainingWidth -= GetColumnWidth(n); - if ( remainingWidth < 0 ) - break; + if ( remainingWidth <= 0 ) + { + // There is not enough space, as we're not going to give the + // first column negative width anyhow, just don't do anything. + return; + } } - // We don't decrease the width of the first column, even if we had - // increased it ourselves, because we want to avoid changing its size - // if the user resized it. We might want to remember if this was the - // case or if we only ever adjusted it automatically in the future. - if ( remainingWidth > GetColumnWidth(0) ) - SetColumnWidth(0, remainingWidth); + SetColumnWidth(0, remainingWidth); } } +wxWindow* wxTreeListCtrl::GetView() const +{ +#ifdef wxHAS_GENERIC_DATAVIEWCTRL + return m_view->GetMainWindow(); +#else + return m_view; +#endif +} + // ============================================================================ // wxTreeListEvent implementation // ============================================================================ @@ -1563,6 +1667,7 @@ wxDEFINE_TREELIST_EVENT(ITEM_EXPANDED); wxDEFINE_TREELIST_EVENT(ITEM_CHECKED); wxDEFINE_TREELIST_EVENT(ITEM_ACTIVATED); wxDEFINE_TREELIST_EVENT(ITEM_CONTEXT_MENU); +wxDEFINE_TREELIST_EVENT(COLUMN_SORTED); #undef wxDEFINE_TREELIST_EVENT