diff --git a/include/wx/dataview.h b/include/wx/dataview.h index 051447a2f1..76b98fcf14 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -25,7 +25,7 @@ #if defined(__WXGTK20__) // for testing - // #define wxUSE_GENERICDATAVIEWCTRL 1 + #define wxUSE_GENERICDATAVIEWCTRL 1 #elif defined(__WXMAC__) #else #define wxUSE_GENERICDATAVIEWCTRL 1 @@ -154,7 +154,7 @@ public: // default compare function virtual int Compare( const wxDataViewItem &item1, const wxDataViewItem &item2, unsigned int column, bool ascending ); - + protected: // the user should not delete this class directly: he should use DecRef() instead! virtual ~wxDataViewModel() { } @@ -487,6 +487,11 @@ public: virtual void EnsureVisible( const wxDataViewItem & item, wxDataViewColumn *column = NULL ) = 0; + + virtual void HitTest( const wxPoint &point, + wxDataViewItem &item, unsigned int &column ) const = 0; + virtual wxRect GetItemRect( const wxDataViewItem &item, + unsigned int column ) const = 0; protected: virtual void DoSetExpanderColumn() = 0 ; diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 083d4b1cfb..4207e50ef6 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -326,6 +326,7 @@ class WXDLLIMPEXP_ADV wxDataViewCtrl: public wxDataViewCtrlBase, public: wxDataViewCtrl() : wxScrollHelperNative(this) { + m_sortingColumn = 0; Init(); } @@ -353,12 +354,22 @@ public: virtual void DoSetExpanderColumn(); virtual void DoSetIndent(); + virtual wxDataViewItem GetSelection(); virtual int GetSelections( wxDataViewItemArray & sel ) const; virtual void SetSelections( const wxDataViewItemArray & sel ); virtual void Select( const wxDataViewItem & item ); virtual void Unselect( const wxDataViewItem & item ); virtual bool IsSelected( const wxDataViewItem & item ) const; + virtual void SelectAll(); + virtual void UnselectAll(); + + virtual void EnsureVisible( const wxDataViewItem & item, + wxDataViewColumn *column = NULL ); + virtual void HitTest( const wxPoint & point, wxDataViewItem & item, unsigned int & column ) const; + virtual wxRect GetItemRect( const wxDataViewItem & item, unsigned int column ) const; + +protected: virtual int GetSelections( wxArrayInt & sel ) const; virtual void SetSelections( const wxArrayInt & sel ); virtual void Select( int row ); @@ -367,15 +378,13 @@ public: virtual void SelectRange( int from, int to ); virtual void UnselectRange( int from, int to ); - virtual void SelectAll(); - virtual void UnselectAll(); - virtual void EnsureVisible( int row ); - virtual void EnsureVisible( const wxDataViewItem & item, wxDataViewColumn *column = NULL ); virtual wxDataViewItem GetItemByRow( unsigned int row ) const; virtual int GetRowByItem( const wxDataViewItem & item ) const; + unsigned int GetSortingColumn() { return m_sortingColumn; } + void SetSortingColumn( unsigned int column ) { m_sortingColumn = column; } public: // utility functions not part of the API @@ -394,6 +403,7 @@ private: wxDataViewModelNotifier *m_notifier; wxDataViewMainWindow *m_clientArea; wxDataViewHeaderWindow *m_headerArea; + unsigned int m_sortingColumn; private: void OnSize( wxSizeEvent &event ); diff --git a/include/wx/gtk/dataview.h b/include/wx/gtk/dataview.h index d98ec0fb10..6a94076629 100644 --- a/include/wx/gtk/dataview.h +++ b/include/wx/gtk/dataview.h @@ -317,6 +317,12 @@ public: virtual void EnsureVisible( const wxDataViewItem & item, wxDataViewColumn *column = NULL ); + virtual void HitTest( const wxPoint &point, + wxDataViewItem &item, unsigned int &column ) const; + virtual wxRect GetItemRect( const wxDataViewItem &item, + unsigned int column ) const; + + static wxVisualAttributes GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index 1572f8c75f..87e5d3b807 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -683,6 +683,9 @@ bool wxDataViewCtrlBase::ClearColumns() wxDataViewColumn* wxDataViewCtrlBase::GetColumn( unsigned int pos ) { + if( pos >= m_cols.GetCount() ) + return NULL; + return (wxDataViewColumn*) m_cols[ pos ]; } diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 0f609572ed..5caf300891 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -385,15 +385,17 @@ private: //Below is the compare stuff //For the generic implements, both the leaf nodes and the nodes are sorted for fast search when needed static wxDataViewModel * g_model; +static unsigned int g_column; +static bool g_asending; int LINKAGEMODE wxGenericTreeModelNodeCmp( wxDataViewTreeNode * node1, wxDataViewTreeNode * node2) { - return g_model->Compare( node1->GetItem(), node2->GetItem() ); + return g_model->Compare( node1->GetItem(), node2->GetItem(), g_column, g_asending ); } int LINKAGEMODE wxGenericTreeModelItemCmp( void * id1, void * id2) { - return g_model->Compare( id1, id2 ); + return g_model->Compare( id1, id2, g_column, g_asending ); } @@ -425,8 +427,25 @@ public: bool ValueChanged( const wxDataViewItem &item, unsigned int col ); bool Cleared(); void Resort() - { g_model = GetOwner()->GetModel(); m_root->Resort(); UpdateDisplay(); } + { + SortPrepare(); + m_root->Resort(); + UpdateDisplay(); + } + void SortPrepare() + { + g_model = GetOwner()->GetModel(); + g_column = GetOwner()->GetSortingColumn(); + wxDataViewColumn * col = GetOwner()->GetColumn(g_column); + if( !col ) + { + g_asending = true; + return; + } + g_asending = col->IsSortOrderAscending(); + } + void SetOwner( wxDataViewCtrl* owner ) { m_owner = owner; } wxDataViewCtrl *GetOwner() { return m_owner; } const wxDataViewCtrl *GetOwner() const { return m_owner; } @@ -490,6 +509,8 @@ public: //Methods for building the mapping tree void BuildTree( wxDataViewModel * model ); void DestroyTree(); + void HitTest( const wxPoint & point, wxDataViewItem & item, unsigned int & column ); + wxRect GetItemRect( const wxDataViewItem & item, unsigned int column ); private: wxDataViewTreeNode * GetTreeNodeByRow( unsigned int row ); //We did not need this temporarily @@ -497,6 +518,7 @@ private: int RecalculateCount() ; + wxDataViewEvent SendExpanderEvent( wxEventType type, const wxDataViewItem & item ); void OnExpanding( unsigned int row ); void OnCollapsing( unsigned int row ); @@ -1197,7 +1219,7 @@ void wxDataViewHeaderWindowMSW::UpdateDisplay() //hdi.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP); //sorting support - if(model && model->GetSortingColumn() == i) + if(model && m_owner->GetSortingColumn() == i) { //The Microsoft Comctrl32.dll 6.0 support SORTUP/SORTDOWN, but they are not default //see http://msdn2.microsoft.com/en-us/library/ms649534.aspx for more detail @@ -1332,16 +1354,14 @@ bool wxDataViewHeaderWindowMSW::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARA wxDataViewColumn *col = GetColumn(idx); if(col->IsSortable()) { - if(model && model->GetSortingColumn() == idx) + if(model && m_owner->GetSortingColumn() == idx) { bool order = col->IsSortOrderAscending(); col->SetSortOrder(!order); - model->SetSortOrderAscending(!order); } else if(model) { - model->SetSortingColumn(idx); - model->SetSortOrderAscending(col->IsSortOrderAscending()); + m_owner->SetSortingColumn(idx); } } UpdateDisplay(); @@ -1505,7 +1525,7 @@ void wxGenericDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) int ch = h; wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE; - if (col->IsSortable() && GetOwner()->GetModel()->GetSortingColumn() == i) + if (col->IsSortable() && GetOwner()->GetSortingColumn() == i) { if (col->IsSortOrderAscending()) sortArrow = wxHDR_SORT_ICON_UP; @@ -1670,17 +1690,15 @@ void wxGenericDataViewHeaderWindow::OnMouse( wxMouseEvent &event ) wxDataViewColumn *col = GetColumn(m_column); if(col->IsSortable()) { - unsigned int colnum = model->GetSortingColumn(); + unsigned int colnum = m_owner->GetSortingColumn(); if(model && static_cast(colnum) == m_column) { bool order = col->IsSortOrderAscending(); col->SetSortOrder(!order); - model->SetSortOrderAscending(!order); } else if(model) { - model->SetSortingColumn(m_column); - model->SetSortOrderAscending(col->IsSortOrderAscending()); + m_owner->SetSortingColumn(m_column); } } UpdateDisplay(); @@ -1944,7 +1962,7 @@ void wxDataViewMainWindow::SendModelEvent( wxEventType type, const wxDataViewIte bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxDataViewItem & item) { - g_model = GetOwner()->GetModel(); + SortPrepare(); wxDataViewTreeNode * node; node = FindNode(parent); @@ -1978,7 +1996,7 @@ void DestroyTreeHelper( wxDataViewTreeNode * node); bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, const wxDataViewItem& item) { - g_model = GetOwner()->GetModel(); + SortPrepare(); wxDataViewTreeNode * node; node = FindNode(parent); @@ -2029,7 +2047,7 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item) { - g_model = GetOwner()->GetModel(); + SortPrepare(); g_model->Resort(); SendModelEvent(wxEVT_COMMAND_DATAVIEW_MODEL_ITEM_CHANGED,item); @@ -2048,7 +2066,7 @@ bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned i return true; */ - g_model = GetOwner()->GetModel(); + SortPrepare(); g_model->Resort(); //Send event @@ -2066,7 +2084,7 @@ bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned i bool wxDataViewMainWindow::Cleared() { - g_model = GetOwner()->GetModel(); + SortPrepare(); DestroyTree(); UpdateDisplay(); @@ -2757,20 +2775,41 @@ wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row) return job.GetResult(); } +wxDataViewEvent wxDataViewMainWindow::SendExpanderEvent( wxEventType type, const wxDataViewItem & item ) +{ + wxWindow *parent = GetParent(); + wxDataViewEvent le(type, parent->GetId()); + + le.SetEventObject(parent); + le.SetModel(GetOwner()->GetModel()); + le.SetItem( item ); + + parent->GetEventHandler()->ProcessEvent(le); + return le; +} + void wxDataViewMainWindow::OnExpanding( unsigned int row ) { wxDataViewTreeNode * node = GetTreeNodeByRow(row); if( node != NULL ) { if( node->HasChildren()) + { if( !node->IsOpen()) { + wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,node->GetItem()); + //Check if the user prevent expanding + if( e.GetSkipped() ) + return; + node->ToggleOpen(); //Here I build the children of current node if( node->GetChildrenNumber() == 0 ) BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node); m_count = -1; UpdateDisplay(); + //Send the expanded event + SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,node->GetItem()); } else { @@ -2778,6 +2817,7 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row ) SelectRow( row + 1, true ); ChangeCurrentRow( row + 1 ); } + } else delete node; } @@ -2792,27 +2832,30 @@ void wxDataViewMainWindow::OnCollapsing(unsigned int row) if( node->HasChildren() && node->IsOpen() ) { + wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING,node->GetItem()); + if( e.GetSkipped() ) + return; node->ToggleOpen(); m_count = -1; UpdateDisplay(); - //RefreshRows(row,GetLastVisibleRow()); - } - else - { - node = node->GetParent(); - if( node != NULL ) - { - int parent = GetRowByItem( node->GetItem() ) ; - if( parent >= 0 ) - { - SelectRow( row, false); - SelectRow(parent , true ); - ChangeCurrentRow( parent ); - } - } - } - if( !nd->HasChildren()) - delete nd; + SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED,nd->GetItem()); + } + else + { + node = node->GetParent(); + if( node != NULL ) + { + int parent = GetRowByItem( node->GetItem() ) ; + if( parent >= 0 ) + { + SelectRow( row, false); + SelectRow(parent , true ); + ChangeCurrentRow( parent ); + } + } + } + if( !nd->HasChildren()) + delete nd; } } @@ -2858,6 +2901,49 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item return node; } +void wxDataViewMainWindow::HitTest( const wxPoint & point, wxDataViewItem & item, unsigned int & column ) +{ + unsigned int cols = GetOwner()->GetColumnCount(); + unsigned int colnum = 0; + unsigned int x_start = 0; + int x, y; + m_owner->CalcUnscrolledPosition( point.x, point.y, &x, &y ); + for (x_start = 0; colnum < cols; colnum++) + { + wxDataViewColumn *col = GetOwner()->GetColumn(colnum); + if (col->IsHidden()) + continue; // skip it! + + unsigned int w = col->GetWidth(); + if (x_start+w >= (unsigned int)x) + break; + + x_start += w; + } + + column = colnum; + item = GetItemByRow( y/m_lineHeight ); +} + +wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item, unsigned int column ) +{ + int row = GetRowByItem(item); + int y = row*m_lineHeight; + int h = m_lineHeight; + int x = 0; + wxDataViewColumn *col = NULL; + for( int i = 0, cols = GetOwner()->GetColumnCount(); i < cols; i ++ ) + { + col = GetOwner()->GetColumn( i ); + x += col->GetWidth(); + if( i == column - 1 ) + break; + } + int w = col->GetWidth(); + m_owner->CalcScrolledPosition( x, y, &x, &y ); + return wxRect(x, y, w, h); +} + int wxDataViewMainWindow::RecalculateCount() { return m_root->GetSubTreeCount(); @@ -2970,7 +3056,7 @@ void wxDataViewMainWindow::BuildTree(wxDataViewModel * model) { //First we define a invalid item to fetch the top-level elements wxDataViewItem item; - g_model = GetOwner()->GetModel(); + SortPrepare(); BuildTreeHelper( model, item, m_root); m_count = -1 ; } @@ -3494,6 +3580,11 @@ void wxDataViewCtrl::DoSetIndent() } //Selection code with wxDataViewItem as parameters +wxDataViewItem wxDataViewCtrl::GetSelection() +{ + return m_clientArea->GetSelection(); +} + int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const { sel.Empty(); @@ -3622,13 +3713,23 @@ void wxDataViewCtrl::EnsureVisible( int row ) m_clientArea->ScrollTo( row ); } -void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, wxDataViewColumn *column ) +void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, wxDataViewColumn * column ) { int row = m_clientArea->GetRowByItem(item); if( row >= 0 ) EnsureVisible(row); } +void wxDataViewCtrl::HitTest( const wxPoint & point, wxDataViewItem & item, unsigned int & column ) const +{ + m_clientArea->HitTest(point, item, column); +} + +wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem & item, unsigned int column ) const +{ + return m_clientArea->GetItemRect(item, column); +} + wxDataViewItem wxDataViewCtrl::GetItemByRow( unsigned int row ) const { return m_clientArea->GetItemByRow( row ); diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index c74207cd42..b27fb05cc9 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -3156,6 +3156,19 @@ void wxDataViewCtrl::EnsureVisible( const wxDataViewItem & item, wxDataViewColum gtk_tree_path_free( path ); } +void wxDataViewCtrl::HitTest( const wxPoint &point, + wxDataViewItem &item, unsigned int &column ) const +{ + item = wxDataViewItem(0); + column = 0; +} + +wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem &item, + unsigned int column ) const +{ + return wxRect(); +} + void wxDataViewCtrl::DoSetExpanderColumn() { }