From: Vadim Zeitlin Date: Mon, 22 Aug 2011 12:41:19 +0000 (+0000) Subject: Harmonize wxDataViewCtrl::GetSelection() behaviour in all ports. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/fa93d732e2afd376527d9c0eb726057f15f18868?hp=c3ad4d4a455aed28178d8a22c305e1a4d6b23f23 Harmonize wxDataViewCtrl::GetSelection() behaviour in all ports. wxDataViewCtrl::GetSelection() now always returns invalid item if more than a single item is selected in a multi-selection control. Also add HasSelection() and GetSelectedItemsCount() to allow checking if any items are selected. Updated the documentation, all ports and added a test for all these functions. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@68844 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index fd5ba917f5..0e560db278 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -199,6 +199,10 @@ Changes in behaviour not resulting in compilation errors, please read this! prevent the parent wxTopLevelWindow from interfering with the keyboard handling of the window that captured the mouse. +- wxDataViewCtrl::GetSelection() now returns invalid item in all ports (this + behaved differently in wxMSW and wxGTK/wxOSX before) if more than one item + is selected in a control with wxDV_MULTIPLE style. + Changes in behaviour which may result in compilation errors ----------------------------------------------------------- @@ -458,6 +462,7 @@ All (GUI): - Added customizable wxDocManager::OnMRUFileNotExist() virtual method. - Fix stock labels when not using mnemonics for Chinese (cw.ahbong). - Added wxComboBox::IsListEmpty() and IsTextEmpty(). +- Added wxDataViewCtrl::GetSelectedItemsCount() and HasSelection(). OSX: diff --git a/include/wx/dataview.h b/include/wx/dataview.h index c99fe07fe7..a1639f2533 100644 --- a/include/wx/dataview.h +++ b/include/wx/dataview.h @@ -663,7 +663,15 @@ public: wxDataViewItem GetCurrentItem() const; void SetCurrentItem(const wxDataViewItem& item); - virtual wxDataViewItem GetSelection() const = 0; + // Selection: both GetSelection() and GetSelections() can be used for the + // controls both with and without wxDV_MULTIPLE style. For single selection + // controls GetSelections() is not very useful however. And for multi + // selection controls GetSelection() returns an invalid item if more than + // one item is selected. Use GetSelectedItemsCount() or HasSelection() to + // check if any items are selected at all. + virtual int GetSelectedItemsCount() const = 0; + bool HasSelection() const { return GetSelectedItemsCount() != 0; } + wxDataViewItem GetSelection() const; virtual int GetSelections( wxDataViewItemArray & sel ) const = 0; virtual void SetSelections( const wxDataViewItemArray & sel ) = 0; virtual void Select( const wxDataViewItem & item ) = 0; diff --git a/include/wx/generic/dataview.h b/include/wx/generic/dataview.h index 51c0e59077..ce3540749d 100644 --- a/include/wx/generic/dataview.h +++ b/include/wx/generic/dataview.h @@ -155,7 +155,7 @@ public: virtual wxDataViewColumn *GetSortingColumn() const; - virtual wxDataViewItem GetSelection() const; + virtual int GetSelectedItemsCount() const; virtual int GetSelections( wxDataViewItemArray & sel ) const; virtual void SetSelections( const wxDataViewItemArray & sel ); virtual void Select( const wxDataViewItem & item ); diff --git a/include/wx/gtk/dataview.h b/include/wx/gtk/dataview.h index 55beb85d48..8a4e12c354 100644 --- a/include/wx/gtk/dataview.h +++ b/include/wx/gtk/dataview.h @@ -142,7 +142,7 @@ public: virtual wxDataViewColumn *GetSortingColumn() const; - virtual wxDataViewItem GetSelection() const; + virtual int GetSelectedItemsCount() const; virtual int GetSelections( wxDataViewItemArray & sel ) const; virtual void SetSelections( const wxDataViewItemArray & sel ); virtual void Select( const wxDataViewItem & item ); diff --git a/include/wx/osx/carbon/dataview.h b/include/wx/osx/carbon/dataview.h index b6d88a2661..ca6a5e5ea4 100644 --- a/include/wx/osx/carbon/dataview.h +++ b/include/wx/osx/carbon/dataview.h @@ -406,6 +406,7 @@ public: // virtual wxDataViewItem GetCurrentItem() const; virtual void SetCurrentItem(const wxDataViewItem& item); + virtual int GetSelectedItemsCount() const; virtual int GetSelections(wxDataViewItemArray& sel) const; virtual bool IsSelected (wxDataViewItem const& item) const; virtual void Select (wxDataViewItem const& item); diff --git a/include/wx/osx/cocoa/dataview.h b/include/wx/osx/cocoa/dataview.h index 624c2cb3f7..e4c5ef65d4 100644 --- a/include/wx/osx/cocoa/dataview.h +++ b/include/wx/osx/cocoa/dataview.h @@ -474,6 +474,7 @@ public: // virtual wxDataViewItem GetCurrentItem() const; virtual void SetCurrentItem(const wxDataViewItem& item); + virtual int GetSelectedItemsCount() const; virtual int GetSelections(wxDataViewItemArray& sel) const; virtual bool IsSelected(const wxDataViewItem& item) const; virtual void Select(const wxDataViewItem& item); diff --git a/include/wx/osx/core/dataview.h b/include/wx/osx/core/dataview.h index 1a554d704b..20b0fe9bdd 100644 --- a/include/wx/osx/core/dataview.h +++ b/include/wx/osx/core/dataview.h @@ -89,6 +89,7 @@ public: virtual wxDataViewItem GetCurrentItem() const = 0; virtual void SetCurrentItem(const wxDataViewItem& item) = 0; + virtual int GetSelectedItemsCount() const = 0; virtual int GetSelections(wxDataViewItemArray& sel) const = 0; // returns all selected items in the native control virtual bool IsSelected (wxDataViewItem const& item) const = 0; // checks if the passed item is selected in the native control virtual void Select (wxDataViewItem const& item) = 0; // selects the passed item in the native control diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index e585fa01d3..883438001f 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -176,7 +176,7 @@ public: virtual unsigned int GetCount() const; virtual wxRect GetItemRect(const wxDataViewItem& item, const wxDataViewColumn* columnPtr) const; - virtual wxDataViewItem GetSelection() const; + virtual int GetSelectedItemsCount() const; virtual int GetSelections(wxDataViewItemArray& sel) const; virtual void HitTest(const wxPoint& point, wxDataViewItem& item, wxDataViewColumn*& columnPtr) const; diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index 9c24be7d76..0c06dae862 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -1016,13 +1016,35 @@ public: */ wxDataViewModel* GetModel(); + /** + Returns the number of currently selected items. + + This method may be called for both the controls with single and + multiple selections and returns the number of selected item, possibly + 0, in any case. + + @since 2.9.3 + */ + virtual int GetSelectedItemsCount() const; + /** Returns first selected item or an invalid item if none is selected. + + This method may be called for both the controls with single and + multiple selections but returns an invalid item if more than one item + is selected in the latter case, use HasSelection() to determine if + there are any selected items when using multiple selection. */ virtual wxDataViewItem GetSelection() const; /** Fills @a sel with currently selected items and returns their number. + + This method may be called for both the controls with single and + multiple selections. In the single selection case it returns the array + with at most one element in it. + + @see GetSelectedItemsCount() */ virtual int GetSelections(wxDataViewItemArray& sel) const; @@ -1032,6 +1054,20 @@ public: */ virtual wxDataViewColumn* GetSortingColumn() const; + /** + Returns true if any items are currently selected. + + This method may be called for both the controls with single and + multiple selections. + + Calling this method is equivalent to calling GetSelectedItemsCount() + and comparing its result with 0 but is more clear and might also be + implemented more efficiently in the future. + + @since 2.9.3 + */ + bool HasSelection() const; + /** Hittest. */ diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index 7c2f06f457..059b7df1b3 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -1094,6 +1094,16 @@ void wxDataViewCtrlBase::SetCurrentItem(const wxDataViewItem& item) Select(item); } +wxDataViewItem wxDataViewCtrlBase::GetSelection() const +{ + if ( GetSelectedItemsCount() != 1 ) + return wxDataViewItem(); + + wxDataViewItemArray selections; + GetSelections(selections); + return selections[0]; +} + wxDataViewColumn * wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column, wxDataViewCellMode mode, int width, wxAlignment align, int flags ) diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index af9e477cb7..582137ff02 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -518,7 +518,6 @@ public: unsigned int GetLastVisibleRow(); unsigned int GetRowCount(); - wxDataViewItem GetSelection() const; const wxDataViewSelection& GetSelections() const { return m_selection; } void SetSelections( const wxDataViewSelection & sel ) { m_selection = sel; UpdateDisplay(); } @@ -3962,14 +3961,6 @@ void wxDataViewMainWindow::OnKillFocus( wxFocusEvent &event ) event.Skip(); } -wxDataViewItem wxDataViewMainWindow::GetSelection() const -{ - if( m_selection.GetCount() != 1 ) - return wxDataViewItem(); - - return GetItemByRow( m_selection.Item(0)); -} - //----------------------------------------------------------------------------- // wxDataViewCtrl //----------------------------------------------------------------------------- @@ -4486,10 +4477,9 @@ void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item) } } -// Selection code with wxDataViewItem as parameters -wxDataViewItem wxDataViewCtrl::GetSelection() const +int wxDataViewCtrl::GetSelectedItemsCount() const { - return m_clientArea->GetSelection(); + return m_clientArea->GetSelections().size(); } int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index b664d402d5..a1b7a3ccbb 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -4930,39 +4930,11 @@ void wxDataViewCtrl::StartEditor(const wxDataViewItem& item, unsigned int column gtk_tree_view_set_cursor(GTK_TREE_VIEW(m_treeview), path, gcolumn, TRUE); } -wxDataViewItem wxDataViewCtrl::GetSelection() const +int wxDataViewCtrl::GetSelectedItemsCount() const { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) ); - if (m_windowStyle & wxDV_MULTIPLE) - { - // Report the first one - GtkTreeModel *model; - GList *list = gtk_tree_selection_get_selected_rows( selection, &model ); - - if (list) - { - GtkTreePath *path = (GtkTreePath*) list->data; - wxDataViewItem item(GTKPathToItem(path)); - - // delete list - g_list_foreach( list, (GFunc) gtk_tree_path_free, NULL ); - g_list_free( list ); - - return item; - } - } - else - { - GtkTreeIter iter; - if (gtk_tree_selection_get_selected( selection, NULL, &iter )) - { - wxDataViewItem item( iter.user_data ); - return item; - } - } - - return wxDataViewItem(0); + return gtk_tree_selection_count_selected_rows(selection); } int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const @@ -4975,30 +4947,23 @@ int wxDataViewCtrl::GetSelections( wxDataViewItemArray & sel ) const GtkTreeModel *model; wxGtkTreePathList list(gtk_tree_selection_get_selected_rows(selection, &model)); - int count = 0; for ( GList* current = list; current; current = g_list_next(current) ) { - GtkTreePath *path = (GtkTreePath*) list->data; + GtkTreePath *path = (GtkTreePath*) current->data; sel.Add(GTKPathToItem(path)); - count++; } - - return count; } else { - GtkTreeModel *model; GtkTreeIter iter; - gboolean has_selection = gtk_tree_selection_get_selected( selection, &model, &iter ); - if (has_selection) + if (gtk_tree_selection_get_selected( selection, NULL, &iter )) { - sel.Add( wxDataViewItem( (void*) iter.user_data) ); - return 1; + sel.Add( wxDataViewItem(iter.user_data) ); } } - return 0; + return sel.size(); } void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel ) diff --git a/src/osx/carbon/dataview.cpp b/src/osx/carbon/dataview.cpp index 2d316d9e0c..dd288d8e17 100644 --- a/src/osx/carbon/dataview.cpp +++ b/src/osx/carbon/dataview.cpp @@ -1107,6 +1107,23 @@ void wxMacDataViewDataBrowserListViewControl::SetCurrentItem(const wxDataViewIte wxFAIL_MSG( "unimplemented for Carbon" ); } +int wxMacDataViewDataBrowserListViewControl::GetSelectedItemsCount() const +{ + Handle handle(::NewHandle(0)); + + if ( GetItems(kDataBrowserNoItem,true,kDataBrowserItemIsSelected,handle) != noErr ) + { + wxFAIL_MSG( "failed to get selected items" ); + return 0; + } + + size_t noOfItems = static_cast(::GetHandleSize(handle)/sizeof(DataBrowserItemID)); + HUnlock(handle); + DisposeHandle(handle); + + return noOfItems; +} + int wxMacDataViewDataBrowserListViewControl::GetSelections(wxDataViewItemArray& sel) const { size_t noOfSelectedItems; diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 148c9b0113..f9600c916e 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -2265,6 +2265,11 @@ void wxCocoaDataViewControl::SetCurrentItem(const wxDataViewItem& item) Select(item); } +int wxCocoaDataViewControl::GetSelectedItemsCount() const +{ + return [m_OutlineView numberOfSelectedRows]; +} + int wxCocoaDataViewControl::GetSelections(wxDataViewItemArray& sel) const { NSIndexSet* selectedRowIndexes([m_OutlineView selectedRowIndexes]); diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index c239ca35ff..490f6d9fd7 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -535,15 +535,9 @@ wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn return wxRect(); } -wxDataViewItem wxDataViewCtrl::GetSelection() const +int wxDataViewCtrl::GetSelectedItemsCount() const { - wxDataViewItemArray itemIDs; - - - if (GetDataViewPeer()->GetSelections(itemIDs) > 0) - return itemIDs[0]; - else - return wxDataViewItem(); + return GetDataViewPeer()->GetSelectedItemsCount(); } int wxDataViewCtrl::GetSelections(wxDataViewItemArray& sel) const diff --git a/tests/controls/dataviewctrltest.cpp b/tests/controls/dataviewctrltest.cpp index a02aa313e7..e62b1b95a8 100644 --- a/tests/controls/dataviewctrltest.cpp +++ b/tests/controls/dataviewctrltest.cpp @@ -40,10 +40,19 @@ private: CPPUNIT_TEST_SUITE( DataViewCtrlTestCase ); CPPUNIT_TEST( DeleteSelected ); CPPUNIT_TEST( DeleteNotSelected ); + CPPUNIT_TEST( GetSelectionForMulti ); + CPPUNIT_TEST( GetSelectionForSingle ); CPPUNIT_TEST_SUITE_END(); + // Create wxDataViewTreeCtrl with the given style. + void Create(long style); + void DeleteSelected(); void DeleteNotSelected(); + void GetSelectionForMulti(); + void GetSelectionForSingle(); + + void TestSelectionFor0and1(); // the dataview control itself wxDataViewTreeCtrl *m_dvc; @@ -67,13 +76,13 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( DataViewCtrlTestCase, "DataViewCtrlTestCa // test initialization // ---------------------------------------------------------------------------- -void DataViewCtrlTestCase::setUp() +void DataViewCtrlTestCase::Create(long style) { m_dvc = new wxDataViewTreeCtrl(wxTheApp->GetTopWindow(), wxID_ANY, wxDefaultPosition, wxSize(400, 200), - wxDV_MULTIPLE); + style); m_root = m_dvc->AppendContainer(wxDataViewItem(), "The root"); m_child1 = m_dvc->AppendContainer(m_root, "child1"); @@ -86,6 +95,11 @@ void DataViewCtrlTestCase::setUp() m_dvc->Update(); } +void DataViewCtrlTestCase::setUp() +{ + Create(wxDV_MULTIPLE); +} + void DataViewCtrlTestCase::tearDown() { delete m_dvc; @@ -131,10 +145,55 @@ void DataViewCtrlTestCase::DeleteNotSelected() m_dvc->GetSelections(sel); - // m_child1 and its children should be removed from the selection now + // m_child1 and its children should be unaffected CPPUNIT_ASSERT_EQUAL( 2, sel.size() ); CPPUNIT_ASSERT( sel[0] == m_child1 ); CPPUNIT_ASSERT( sel[1] == m_grandchild ); } +void DataViewCtrlTestCase::TestSelectionFor0and1() +{ + wxDataViewItemArray selections; + + // Initially there is no selection. + CPPUNIT_ASSERT_EQUAL( 0, m_dvc->GetSelectedItemsCount() ); + CPPUNIT_ASSERT( !m_dvc->HasSelection() ); + CPPUNIT_ASSERT( !m_dvc->GetSelection().IsOk() ); + + CPPUNIT_ASSERT( !m_dvc->GetSelections(selections) ); + CPPUNIT_ASSERT( selections.empty() ); + + // Select one item. + m_dvc->Select(m_child1); + CPPUNIT_ASSERT_EQUAL( 1, m_dvc->GetSelectedItemsCount() ); + CPPUNIT_ASSERT( m_dvc->HasSelection() ); + CPPUNIT_ASSERT( m_dvc->GetSelection().IsOk() ); + CPPUNIT_ASSERT_EQUAL( 1, m_dvc->GetSelections(selections) ); + CPPUNIT_ASSERT( selections[0] == m_child1 ); +} + +void DataViewCtrlTestCase::GetSelectionForMulti() +{ + wxDataViewItemArray selections; + + TestSelectionFor0and1(); + + // Also test with more than one selected item. + m_dvc->Select(m_child2); + + CPPUNIT_ASSERT_EQUAL( 2, m_dvc->GetSelectedItemsCount() ); + CPPUNIT_ASSERT( m_dvc->HasSelection() ); + CPPUNIT_ASSERT( !m_dvc->GetSelection().IsOk() ); + CPPUNIT_ASSERT_EQUAL( 2, m_dvc->GetSelections(selections) ); + CPPUNIT_ASSERT( selections[1] == m_child2 ); +} + +void DataViewCtrlTestCase::GetSelectionForSingle() +{ + delete m_dvc; + Create(0); + + TestSelectionFor0and1(); +} + #endif //wxUSE_TREECTRL