All (GUI):
- wxAUI: support auto-orientable toolbars (wsu).
+- Added wxDataViewCtrl::Set/GetCurrentItem().
- wxHTML: render in RTL order inside RTL window (Richard Bullington-McGuire).
- wxRibbon: added EVT_RIBBONGALLERY_CLICKED event (John Roberts).
- Add support for CP-866 encoding to wxEncodingConverter (madnut).
int GetIndent() const
{ return m_indent; }
+ // Current item is the one used by the keyboard navigation, it is the same
+ // as the (unique) selected item in single selection mode so these
+ // functions are mostly useful for controls with wxDV_MULTIPLE style.
+ wxDataViewItem GetCurrentItem() const;
+ void SetCurrentItem(const wxDataViewItem& item);
+
virtual wxDataViewItem GetSelection() const = 0;
virtual int GetSelections( wxDataViewItemArray & sel ) const = 0;
virtual void SetSelections( const wxDataViewItemArray & sel ) = 0;
virtual void DoSetIndent() = 0;
private:
+ // Implementation of the public Set/GetCurrentItem() methods which are only
+ // called in multi selection case (for single selection controls their
+ // implementation is trivial and is done in the base class itself).
+ virtual wxDataViewItem DoGetCurrentItem() const = 0;
+ virtual void DoSetCurrentItem(const wxDataViewItem& item) = 0;
+
wxDataViewModel *m_model;
wxDataViewColumn *m_expander_column;
int m_indent ;
wxDataViewColumn *GetColumnAt(unsigned int pos) const;
private:
+ virtual wxDataViewItem DoGetCurrentItem() const;
+ virtual void DoSetCurrentItem(const wxDataViewItem& item);
+
wxDataViewColumnList m_cols;
wxDataViewModelNotifier *m_notifier;
wxDataViewMainWindow *m_clientArea;
private:
void Init();
+ virtual wxDataViewItem DoGetCurrentItem() const;
+ virtual void DoSetCurrentItem(const wxDataViewItem& item);
+
friend class wxDataViewCtrlDCImpl;
friend class wxDataViewColumn;
friend class wxGtkDataViewModelNotifier;
//
// selection related methods (inherited from wxDataViewWidgetImpl)
//
+ virtual wxDataViewItem GetCurrentItem() const;
+ virtual void SetCurrentItem(const wxDataViewItem& item);
virtual int GetSelections(wxDataViewItemArray& sel) const;
virtual bool IsSelected (wxDataViewItem const& item) const;
virtual void Select (wxDataViewItem const& item);
//
// selection related methods (inherited from wxDataViewWidgetImpl)
//
+ virtual wxDataViewItem GetCurrentItem() const;
+ virtual void SetCurrentItem(const wxDataViewItem& item);
virtual int GetSelections(wxDataViewItemArray& sel) const;
virtual bool IsSelected(const wxDataViewItem& item) const;
virtual void Select(const wxDataViewItem& item);
//
// selection related methods
//
+ virtual wxDataViewItem GetCurrentItem() const = 0;
+ virtual void SetCurrentItem(const wxDataViewItem& item) = 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
virtual void Expand(const wxDataViewItem& item);
virtual bool IsExpanded(const wxDataViewItem & item) const;
-
virtual unsigned int GetCount() const;
virtual wxRect GetItemRect(const wxDataViewItem& item, const wxDataViewColumn* columnPtr) const;
virtual wxDataViewItem GetSelection() const;
// initializing of local variables:
void Init();
+ virtual wxDataViewItem DoGetCurrentItem() const;
+ virtual void DoSetCurrentItem(const wxDataViewItem& item);
+
//
// variables
//
*/
wxDataViewColumn* GetExpanderColumn() const;
+ /**
+ Returns the currently focused item.
+
+ This is the item that the keyboard commands apply to. It may be invalid
+ if there is no focus currently.
+
+ This method is mostly useful for the controls with @c wxDV_MULTIPLE
+ style as in the case of single selection it returns the same thing as
+ GetSelection().
+
+ Notice that under all platforms except Mac OS X the currently focused
+ item may be selected or not but under OS X the current item is always
+ selected.
+
+ @see SetCurrentItem()
+
+ @since 2.9.2
+ */
+ wxDataViewItem GetCurrentItem() const;
+
/**
Returns indentation.
*/
*/
void SetExpanderColumn(wxDataViewColumn* col);
+ /**
+ Changes the currently focused item.
+
+ The @a item parameter must be valid, there is no way to remove the
+ current item from the control.
+
+ In single selection mode, calling this method is the same as calling
+ Select() and is thus not very useful. In multiple selection mode this
+ method only moves the current item however without changing the
+ selection except under OS X where the current item is always selected,
+ so calling SetCurrentItem() selects @a item if it hadn't been selected
+ before.
+
+ @see GetCurrentItem()
+
+ @since 2.9.2
+ */
+ void SetCurrentItem(const wxDataViewItem& item);
+
/**
Sets the indendation.
*/
void OnSelectNinth(wxCommandEvent& event);
void OnCollapse(wxCommandEvent& event);
void OnExpand(wxCommandEvent& event);
+ void OnShowCurrent(wxCommandEvent& event);
+ void OnSetNinthCurrent(wxCommandEvent& event);
void OnPrependList(wxCommandEvent& event);
void OnDeleteList(wxCommandEvent& event);
ID_SELECT_NINTH = 103,
ID_COLLAPSE = 104,
ID_EXPAND = 105,
+ ID_SHOW_CURRENT,
+ ID_SET_NINTH_CURRENT,
ID_PREPEND_LIST = 200,
ID_DELETE_LIST = 201,
EVT_BUTTON( ID_SELECT_NINTH, MyFrame::OnSelectNinth )
EVT_BUTTON( ID_COLLAPSE, MyFrame::OnCollapse )
EVT_BUTTON( ID_EXPAND, MyFrame::OnExpand )
+ EVT_BUTTON( ID_SHOW_CURRENT, MyFrame::OnShowCurrent )
+ EVT_BUTTON( ID_SET_NINTH_CURRENT, MyFrame::OnSetNinthCurrent )
EVT_BUTTON( ID_PREPEND_LIST, MyFrame::OnPrependList )
EVT_BUTTON( ID_DELETE_LIST, MyFrame::OnDeleteList )
BuildDataViewCtrl(firstPanel, 0); // sets m_ctrl[0]
+ const wxSizerFlags border = wxSizerFlags().DoubleBorder();
+
wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
- button_sizer->Add( new wxButton( firstPanel, ID_ADD_MOZART, "Add Mozart"), 0, wxALL, 10 );
- button_sizer->Add( new wxButton( firstPanel, ID_DELETE_SEL, "Delete selected"), 0, wxALL, 10 );
- button_sizer->Add( new wxButton( firstPanel, ID_DELETE_YEAR, "Delete \"Year\" column"), 0, wxALL, 10 );
- button_sizer->Add( new wxButton( firstPanel, ID_SELECT_NINTH,"Select ninth symphony"), 0, wxALL, 10 );
- button_sizer->Add( new wxButton( firstPanel, ID_COLLAPSE, "Collapse"), 0, wxALL, 10 );
- button_sizer->Add( new wxButton( firstPanel, ID_EXPAND, "Expand"), 0, wxALL, 10 );
+ button_sizer->Add( new wxButton( firstPanel, ID_ADD_MOZART, "Add Mozart"), border );
+ button_sizer->Add( new wxButton( firstPanel, ID_DELETE_SEL, "Delete selected"), border );
+ button_sizer->Add( new wxButton( firstPanel, ID_DELETE_YEAR, "Delete \"Year\" column"), border );
+ button_sizer->Add( new wxButton( firstPanel, ID_SELECT_NINTH,"Select ninth symphony"), border );
+ button_sizer->Add( new wxButton( firstPanel, ID_COLLAPSE, "Collapse"), border );
+ button_sizer->Add( new wxButton( firstPanel, ID_EXPAND, "Expand"), border );
+
+ wxBoxSizer *sizerCurrent = new wxBoxSizer(wxHORIZONTAL);
+ sizerCurrent->Add(new wxButton(firstPanel, ID_SHOW_CURRENT,
+ "&Show current"), border);
+ sizerCurrent->Add(new wxButton(firstPanel, ID_SET_NINTH_CURRENT,
+ "Make &ninth symphony current"), border);
wxSizer *firstPanelSz = new wxBoxSizer( wxVERTICAL );
m_ctrl[0]->SetMinSize(wxSize(-1, 200));
new wxStaticText(firstPanel, wxID_ANY, "Most of the cells above are editable!"),
0, wxGROW|wxALL, 5);
firstPanelSz->Add(button_sizer);
+ firstPanelSz->Add(sizerCurrent);
firstPanel->SetSizerAndFit(firstPanelSz);
m_ctrl[0]->Expand( item );
}
+void MyFrame::OnShowCurrent(wxCommandEvent& WXUNUSED(event))
+{
+ wxDataViewItem item = m_ctrl[0]->GetCurrentItem();
+ if ( item.IsOk() )
+ {
+ wxLogMessage("Current item: \"%s\" by %s",
+ m_music_model->GetTitle(item),
+ m_music_model->GetArtist(item));
+ }
+ else
+ {
+ wxLogMessage("There is no current item.");
+ }
+}
+
+void MyFrame::OnSetNinthCurrent(wxCommandEvent& WXUNUSED(event))
+{
+ wxDataViewItem item(m_music_model->GetNinthItem());
+ if ( !item.IsOk() )
+ {
+ wxLogError( "Cannot make the ninth symphony current: it was removed!" );
+ return;
+ }
+
+ m_ctrl[0]->SetCurrentItem(item);
+}
+
void MyFrame::OnValueChanged( wxDataViewEvent &event )
{
if (!m_log)
}
}
+wxDataViewItem wxDataViewCtrlBase::GetCurrentItem() const
+{
+ return HasFlag(wxDV_MULTIPLE) ? DoGetCurrentItem()
+ : GetSelection();
+}
+
+void wxDataViewCtrlBase::SetCurrentItem(const wxDataViewItem& item)
+{
+ wxCHECK_RET( item.IsOk(), "Can't make current an invalid item." );
+
+ if ( HasFlag(wxDV_MULTIPLE) )
+ DoSetCurrentItem(item);
+ else
+ Select(item);
+}
+
wxDataViewColumn *
wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
void ScrollWindow( int dx, int dy, const wxRect *rect = NULL );
void ScrollTo( int rows, int column );
+ unsigned GetCurrentRow() const { return m_currentRow; }
bool HasCurrentRow() { return m_currentRow != (unsigned int)-1; }
void ChangeCurrentRow( unsigned int row );
: GetColumn(m_sortingColumnIdx);
}
+wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const
+{
+ return GetItemByRow(m_clientArea->GetCurrentRow());
+}
+
+void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
+{
+ const int row = m_clientArea->GetRowByItem(item);
+
+ const unsigned oldCurrent = m_clientArea->GetCurrentRow();
+ if ( static_cast<unsigned>(row) != oldCurrent )
+ {
+ m_clientArea->ChangeCurrentRow(row);
+ m_clientArea->RefreshRow(oldCurrent);
+ m_clientArea->RefreshRow(row);
+ }
+}
+
// Selection code with wxDataViewItem as parameters
wxDataViewItem wxDataViewCtrl::GetSelection() const
{
wxDECLARE_NO_COPY_CLASS(wxGtkTreePath);
};
+// ----------------------------------------------------------------------------
+// wxGtkTreeSelectionLock: prevent selection from changing during the
+// lifetime of this object
+// ----------------------------------------------------------------------------
+
+// Implementation note: it could be expected that setting the selection
+// function in this class ctor and resetting it back to the old value in its
+// dtor would work. However currently gtk_tree_selection_get_select_function()
+// can't be passed NULL (see https://bugzilla.gnome.org/show_bug.cgi?id=626276)
+// so we can't do this. Instead, we always use the selection function (which
+// imposes extra overhead, albeit minimal one, on all selection operations) and
+// just set/reset the flag telling it whether it should allow or forbid the
+// selection.
+//
+// Also notice that currently only a single object of this class may exist at
+// any given moment. It's just simpler like this and we don't need anything
+// more for now.
+
+extern "C"
+gboolean wxdataview_selection_func(GtkTreeSelection * WXUNUSED(selection),
+ GtkTreeModel * WXUNUSED(model),
+ GtkTreePath * WXUNUSED(path),
+ gboolean WXUNUSED(path_currently_selected),
+ gpointer data)
+{
+ return data == NULL;
+}
+
+class wxGtkTreeSelectionLock
+{
+public:
+ wxGtkTreeSelectionLock(GtkTreeSelection *selection)
+ : m_selection(selection)
+ {
+ wxASSERT_MSG( !ms_instance, "this class is not reentrant currently" );
+
+ ms_instance = this;
+
+ CheckCurrentSelectionFunc(NULL);
+
+ // Pass some non-NULL pointer as "data" for the callback, it doesn't
+ // matter what it is as long as it's non-NULL.
+ gtk_tree_selection_set_select_function(selection,
+ wxdataview_selection_func,
+ this,
+ NULL);
+ }
+
+ ~wxGtkTreeSelectionLock()
+ {
+ CheckCurrentSelectionFunc(wxdataview_selection_func);
+
+ gtk_tree_selection_set_select_function(m_selection,
+ wxdataview_selection_func,
+ NULL,
+ NULL);
+
+ ms_instance = NULL;
+ }
+
+private:
+ void CheckCurrentSelectionFunc(GtkTreeSelectionFunc func)
+ {
+ // We can only use gtk_tree_selection_get_select_function() with 2.14+
+ // so check for its availability both during compile- and run-time.
+#if GTK_CHECK_VERSION(2, 14, 0)
+ if ( gtk_check_version(2, 14, 0) != NULL )
+ return;
+
+ // If this assert is triggered, it means the code elsewhere has called
+ // gtk_tree_selection_set_select_function() but currently doing this
+ // breaks this class so the code here needs to be changed.
+ wxASSERT_MSG
+ (
+ gtk_tree_selection_get_select_function(m_selection) == func,
+ "selection function has changed unexpectedly, review this code!"
+ );
+#endif // GTK+ 2.14+
+
+ wxUnusedVar(func);
+ }
+
+ static wxGtkTreeSelectionLock *ms_instance;
+
+ GtkTreeSelection * const m_selection;
+
+ wxDECLARE_NO_COPY_CLASS(wxGtkTreeSelectionLock);
+};
+
+wxGtkTreeSelectionLock *wxGtkTreeSelectionLock::ms_instance = NULL;
+
//-----------------------------------------------------------------------------
// wxDataViewCtrlInternal
//-----------------------------------------------------------------------------
return gtk_tree_view_row_expanded( GTK_TREE_VIEW(m_treeview), path );
}
+wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const
+{
+ // The tree doesn't have any current item if it hadn't been created yet but
+ // it's arguably not an error to call this function in this case so just
+ // return an invalid item without asserting.
+ if ( !m_treeview )
+ return wxDataViewItem();
+
+ wxGtkTreePath path;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(m_treeview), path.ByRef(), NULL);
+
+ return GTKPathToItem(path);
+}
+
+void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
+{
+ wxCHECK_RET( m_treeview,
+ "Current item can't be set before creating the control." );
+
+ // We need to make sure the model knows about this item or the path would
+ // be invalid and gtk_tree_view_set_cursor() would silently do nothing.
+ ExpandAncestors(item);
+
+ // We also need to preserve the existing selection from changing.
+ // Unfortunately the only way to do it seems to use our own selection
+ // function and forbid any selection changes during set cursor call.
+ wxGtkTreeSelectionLock
+ lock(gtk_tree_view_get_selection(GTK_TREE_VIEW(m_treeview)));
+
+ // Do move the cursor now.
+ GtkTreeIter iter;
+ iter.user_data = item.GetID();
+ wxGtkTreePath path(m_internal->get_path( &iter ));
+
+ gtk_tree_view_set_cursor(GTK_TREE_VIEW(m_treeview), path, NULL, FALSE);
+}
+
wxDataViewItem wxDataViewCtrl::GetSelection() const
{
GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(m_treeview) );
//
// selection related methods (inherited from wxDataViewWidgetImpl)
//
+wxDataViewItem wxMacDataViewDataBrowserListViewControl::GetCurrentItem() const
+{
+ wxFAIL_MSG( "unimplemented for Carbon" );
+
+ return wxDataViewItem();
+}
+
+void wxMacDataViewDataBrowserListViewControl::SetCurrentItem(const wxDataViewItem& WXUNUSED(item))
+{
+ wxFAIL_MSG( "unimplemented for Carbon" );
+}
+
int wxMacDataViewDataBrowserListViewControl::GetSelections(wxDataViewItemArray& sel) const
{
size_t noOfSelectedItems;
//
// selection related methods (inherited from wxDataViewWidgetImpl)
//
+
+wxDataViewItem wxCocoaDataViewControl::GetCurrentItem() const
+{
+ return wxDataViewItem([[m_OutlineView itemAtRow:[m_OutlineView selectedRow]] pointer]);
+}
+
+void wxCocoaDataViewControl::SetCurrentItem(const wxDataViewItem& item)
+{
+ // We can't have unselected current item in a NSTableView, as the
+ // documentation of its deselectRow method explains, the control will
+ // automatically change the current item to the closest still selected item
+ // if the current item is deselected. So we have no choice but to select
+ // the item in the same time as making it current.
+ Select(item);
+}
+
int wxCocoaDataViewControl::GetSelections(wxDataViewItemArray& sel) const
{
NSIndexSet* selectedRowIndexes([m_OutlineView selectedRowIndexes]);
return GetDataViewPeer()->GetCount();
}
+wxDataViewItem wxDataViewCtrl::DoGetCurrentItem() const
+{
+ return GetDataViewPeer()->GetCurrentItem();
+}
+
+void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem& item)
+{
+ GetDataViewPeer()->SetCurrentItem(item);
+}
+
wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) const
{
if (item.IsOk() && (columnPtr != NULL))