diff --git a/docs/changes.txt b/docs/changes.txt index 4762e4888a..d64d16eeca 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -94,6 +94,7 @@ All: All (GUI): +- Add wxDataViewToggleRenderer::ShowAsRadio(). - Improve stock items consistency and aesthetics (dhowland). - Fix bug with missing items in overflowing AUI toolbar (Maarten Bent). - Revert to left-aligning wxSpinCtrl contents by default. diff --git a/include/wx/generic/dvrenderers.h b/include/wx/generic/dvrenderers.h index d85bbe0619..1f23fdee3a 100644 --- a/include/wx/generic/dvrenderers.h +++ b/include/wx/generic/dvrenderers.h @@ -132,6 +132,8 @@ public: wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT ); + void ShowAsRadio() { m_radio = true; } + virtual bool SetValue( const wxVariant &value ) wxOVERRIDE; virtual bool GetValue( wxVariant &value ) const wxOVERRIDE; #if wxUSE_ACCESSIBILITY @@ -149,6 +151,7 @@ public: const wxMouseEvent *mouseEvent) wxOVERRIDE; private: bool m_toggle; + bool m_radio; protected: wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewToggleRenderer); diff --git a/include/wx/gtk/dvrenderers.h b/include/wx/gtk/dvrenderers.h index bd50a515b2..9d4091d90f 100644 --- a/include/wx/gtk/dvrenderers.h +++ b/include/wx/gtk/dvrenderers.h @@ -107,6 +107,8 @@ public: wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT ); + void ShowAsRadio(); + bool SetValue( const wxVariant &value ) wxOVERRIDE; bool GetValue( wxVariant &value ) const wxOVERRIDE; diff --git a/include/wx/osx/dvrenderers.h b/include/wx/osx/dvrenderers.h index 0aa10473dc..e9ad8edd79 100644 --- a/include/wx/osx/dvrenderers.h +++ b/include/wx/osx/dvrenderers.h @@ -198,6 +198,8 @@ public: wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT); + void ShowAsRadio(); + virtual bool MacRender(); virtual void OSXOnCellChanged(NSObject *value, diff --git a/interface/wx/dataview.h b/interface/wx/dataview.h index 22fd11fe88..c673939758 100644 --- a/interface/wx/dataview.h +++ b/interface/wx/dataview.h @@ -2272,6 +2272,9 @@ public: This class is used by wxDataViewCtrl to render toggle controls. + Note that "toggles" can be represented either by check boxes (default) or + radio buttons. + @see wxDataViewCheckIconTextRenderer @library{wxadv} @category{dvc} @@ -2292,6 +2295,24 @@ public: wxDataViewToggleRenderer(const wxString& varianttype = GetDefaultType(), wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT); + + /** + Switch to using radiobutton-like appearance instead of the default + checkbox-like one. + + By default, this renderer uses checkboxes to represent the boolean + values, but using this method its appearance can be changed to use + radio buttons instead. + + Notice that only the appearance is changed, the cells don't really + start behaving as radio buttons after a call to ShowAsRadio(), i.e. the + application code also needs to react to selecting one of the cells + shown by this renderer and clearing all the other ones in the same row + or column to actually implement radio button-like behaviour. + + @since 3.1.2 + */ + void ShowAsRadio(); }; diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 26fbc1dde6..54f3666603 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -108,6 +108,10 @@ private: void OnPrependList(wxCommandEvent& event); void OnDeleteList(wxCommandEvent& event); + + // Third (wxDataViewListCtrl) page. + void OnListValueChanged(wxDataViewEvent& event); + // Fourth page. void OnDeleteTreeItem(wxCommandEvent& event); void OnDeleteAllTreeItems(wxCommandEvent& event); @@ -176,6 +180,9 @@ private: wxLog *m_logOld; private: + // Flag used by OnListValueChanged(), see there. + bool m_eventFromProgram; + wxDECLARE_EVENT_TABLE(); }; @@ -450,6 +457,8 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int m_ctrl[2] = NULL; m_ctrl[3] = NULL; + m_eventFromProgram = false; + SetIcon(wxICON(sample)); @@ -759,6 +768,17 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l page2_model->DecRef(); lc->AppendToggleColumn( "Toggle" ); + + // We're not limited to convenience column-appending functions, it + // can also be done fully manually, which allows us to customize + // the renderer being used. + wxDataViewToggleRenderer* const rendererRadio = + new wxDataViewToggleRenderer("bool", wxDATAVIEW_CELL_ACTIVATABLE); + rendererRadio->ShowAsRadio(); + wxDataViewColumn* const colRadio = + new wxDataViewColumn("Radio", rendererRadio, 1); + lc->AppendColumn(colRadio, "bool"); + lc->AppendTextColumn( "Text" ); lc->AppendProgressColumn( "Progress" ); @@ -767,11 +787,14 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l { data.clear(); data.push_back( (i%3) == 0 ); + data.push_back( i == 7 ); // select a single (random) radio item data.push_back( wxString::Format("row %d", i) ); data.push_back( long(5*i) ); lc->AppendItem( data ); } + + lc->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &MyFrame::OnListValueChanged, this); } break; @@ -1390,6 +1413,48 @@ void MyFrame::OnShowAttributes(wxCommandEvent& WXUNUSED(event)) m_attributes->SetHidden(false); } +// ---------------------------------------------------------------------------- +// MyFrame - event handlers for the third (wxDataViewListCtrl) page +// ---------------------------------------------------------------------------- + +void MyFrame::OnListValueChanged(wxDataViewEvent& event) +{ + // Ignore changes coming from our own SetToggleValue() calls below. + if ( m_eventFromProgram ) + { + m_eventFromProgram = false; + return; + } + + wxDataViewListCtrl* const lc = static_cast(m_ctrl[2]); + + const int columnToggle = 1; + + // Handle selecting a radio button by unselecting all the other ones. + if ( event.GetColumn() == columnToggle ) + { + const int rowChanged = lc->ItemToRow(event.GetItem()); + if ( lc->GetToggleValue(rowChanged, columnToggle) ) + { + for ( int row = 0; row < lc->GetItemCount(); ++row ) + { + if ( row != rowChanged ) + { + m_eventFromProgram = true; + lc->SetToggleValue(false, row, columnToggle); + } + } + } + else // The item was cleared. + { + // Explicitly check it back, we want to always have exactly one + // checked radio item in this column. + m_eventFromProgram = true; + lc->SetToggleValue(true, rowChanged, columnToggle); + } + } +} + // ---------------------------------------------------------------------------- // MyFrame - event handlers for the fourth page // ---------------------------------------------------------------------------- diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 5c45bd7409..719f6ee122 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -1260,6 +1260,7 @@ wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype, wxDataViewRenderer( varianttype, mode, align ) { m_toggle = false; + m_radio = false; } bool wxDataViewToggleRenderer::SetValue( const wxVariant &value ) @@ -1301,11 +1302,12 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state size.IncTo(GetSize()); cell.SetSize(size); - wxRendererNative::Get().DrawCheckBox( - GetOwner()->GetOwner(), - *dc, - cell, - flags ); + wxRendererNative& renderer = wxRendererNative::Get(); + wxWindow* const win = GetOwner()->GetOwner(); + if ( m_radio ) + renderer.DrawRadioBitmap(win, *dc, cell, flags); + else + renderer.DrawCheckBox(win, *dc, cell, flags); return true; } diff --git a/src/gtk/dataview.cpp b/src/gtk/dataview.cpp index 2715737b86..71f9774591 100644 --- a/src/gtk/dataview.cpp +++ b/src/gtk/dataview.cpp @@ -2539,6 +2539,11 @@ wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype, SetAlignment(align); } +void wxDataViewToggleRenderer::ShowAsRadio() +{ + gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(m_renderer), TRUE); +} + bool wxDataViewToggleRenderer::SetValue( const wxVariant &value ) { bool tmp = value; diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 9428747a3c..f70eaae314 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -3326,6 +3326,11 @@ wxDataViewToggleRenderer::wxDataViewToggleRenderer(const wxString& varianttype, [cell release]; } +void wxDataViewToggleRenderer::ShowAsRadio() +{ + [GetNativeData()->GetItemCell() setButtonType:NSRadioButton]; +} + bool wxDataViewToggleRenderer::MacRender() { [GetNativeData()->GetItemCell() setIntValue:GetValue().GetLong()];