I am using wxWidgets 2.8, together with wxPropertyGrid 1.4 in an application. For float values, I would like to use a slider to edit them. However, a slider editor is not provided by default, so I have resorted to implementing my own editor, following the guidelines mentioned in the documentation.
However, with this new editor, even though I set it as the editor for my float property, it's not actually appearing until the property grid cell is in any way interacted with (e.g. clicked). Until then, the classic, textbox based controller is still visible.
Apparently, the actual CreateControl method for the slider editor isn't called when the propgrid gets generated - it's only called when the cell itself is somehow interacted with.
Here's my custom property editor:
wxpgslider.h
class WXDLLIMPEXP_PG wxPGSliderEditor : public wxPGEditor { #ifndef SWIG WX_PG_DECLARE_EDITOR_CLASS(wxPGSliderEditor) #endif public: wxPGSliderEditor (int p = 10000) : precision(p) { } ~wxPGSliderEditor () {} // Macro for the CreateControls method stub wxPG_DECLARE_CREATECONTROLS void UpdateControl ( wxPGProperty* property, wxWindow* wnd) const; bool OnEvent ( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* wnd, wxEvent& event) const; bool GetValueFromControl ( wxVariant& variant, wxPGProperty* property, wxWindow* wnd) const; void SetValueToUnspecified ( wxPGProperty* property, wxWindow* wnd) const; //void DrawValue ( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text) const; private: int precision; };
wxpgslider.cpp
#include "cseditor/wxpgslider.h" //----------------- wxPGSliderEditor --------------------- WX_PG_IMPLEMENT_EDITOR_CLASS(SliderEditor, wxPGSliderEditor, wxPGEditor) wxPGWindowList wxPGSliderEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, const wxPoint& pos, const wxSize& size ) const { double v_d = property->GetValue().GetDouble(); if ( v_d 1 ) v_d = 1; wxSlider *ctrl = new wxSlider(); #ifdef __WXMSW__ ctrl->Hide(); #endif ctrl->Create ( propgrid->GetPanel(), wxPG_SUBID2, (int)(v_d * precision), 0, precision, pos, size, wxSL_HORIZONTAL ); return wxPGWindowList(ctrl); } void wxPGSliderEditor::UpdateControl ( wxPGProperty* property, wxWindow* wnd ) const { wxSlider* ctrl = wxDynamicCast ( wnd, wxSlider ); if ( ctrl ) { double val; if (wxPGVariantToDouble (property->DoGetValue(), &val)) { if ( val 1 ) val = 1; ctrl->SetValue ( (int)(val * precision) ); //static_cast(property)->GetLabel() // ->SetValue( wxString::Format(wxT("%ld"), val * precision) ); } } } bool wxPGSliderEditor::OnEvent ( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* wnd, wxEvent& event ) const { if(event.GetEventType() == wxEVT_SCROLL_CHANGED) { // Update the value event.Skip(); propgrid->EditorsValueWasModified(); return true; } return false; } bool wxPGSliderEditor::GetValueFromControl ( wxVariant& variant, wxPGProperty* property, wxWindow* wnd ) const { wxSlider* ctrl = wxDynamicCast ( wnd, wxSlider ); if ( ctrl ) { variant = wxVariant ( (double)(ctrl->GetValue())/(double)(precision) ); property->SetValue ( variant ); } return true; } void wxPGSliderEditor::SetValueToUnspecified ( wxPGProperty* property, wxWindow* wnd) const { wxSlider* ctrl = wxDynamicCast ( wnd, wxSlider ); if ( ctrl ) { ctrl->SetValue (0); } }
And this is the code I'm using to generate the slider, in a Populate function:
double value = variant->GetFloat(); // Generate a homebrewed slider wxFloatProperty* fp = new wxFloatProperty(translatedName, originalName, value); wxPGEditor* rHandle = wxPropertyGrid::RegisterEditorClass(new wxPGSliderEditor(), wxT("SliderEditor")); fp->SetEditor(rHandle); page->AppendIn(categoryID, fp);
I register the class, in case it's not been registered before, then set the property's editor. Then I add the property to the grid. Why is the slider not showing up until the cell gets interacted with?
Is calling pgMan->GetGrid()->SelectProperty(fp, false);
the only way to make it get drawn?