1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/propgrid/sampleprops.cpp
3 // Purpose: wxPropertyGrid Sample Properties
4 // Author: Jaakko Salli
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
19 // for all others, include the necessary headers (this file is usually all you
20 // need because it includes almost all "standard" wxWidgets headers)
25 // -----------------------------------------------------------------------
28 #include <wx/propgrid/propgrid.h>
29 #include <wx/propgrid/advprops.h>
31 #ifndef WX_PROPGRID_SAMPLEPROPS_H
32 #include "sampleprops.h"
36 // -----------------------------------------------------------------------
38 // -----------------------------------------------------------------------
40 // Dummy comparison required by value type implementation.
41 bool operator == (const wxFontData
&, const wxFontData
&)
46 // Custom version of wxFontProperty that also holds colour in the value.
47 // Original version by Vladimir Vainer.
49 #include <wx/fontdlg.h>
51 WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA(wxPGVariantDataFontData
, wxFontData
)
53 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontDataProperty
,wxFontProperty
,
54 wxFontData
,const wxFontData
&,TextCtrlAndButton
)
56 wxFontDataProperty::wxFontDataProperty( const wxString
& label
, const wxString
& name
,
57 const wxFontData
& value
) : wxFontProperty(label
,name
,value
.GetInitialFont())
59 // Set initial value - should be done in a simpler way like this
60 // (instead of calling SetValue) in derived (wxObject) properties.
61 m_value_wxFontData
<< value
;
63 wxFontData
& fontData
= wxFontDataFromVariant(m_value_wxFontData
);
66 fontData
.SetChosenFont(value
.GetInitialFont());
67 if ( !fontData
.GetColour().Ok() )
68 fontData
.SetColour(*wxBLACK
);
70 // Add extra children.
71 AddChild( new wxColourProperty(_("Colour"),wxPG_LABEL
,
72 fontData
.GetColour() ) );
76 wxFontDataProperty::~wxFontDataProperty () { }
78 void wxFontDataProperty::OnSetValue()
80 if ( !(&wxFontDataFromVariant(m_value
)) )
82 wxFont
* pFont
= &wxFontFromVariant(m_value
);
86 fontData
.SetChosenFont(*pFont
);
87 m_value
= WXVARIANT(fontData
);
91 wxFAIL_MSG(wxT("Value to wxFontDataProperty must be eithe wxFontData or wxFont"));
95 // Set m_value to wxFont so that wxFontProperty methods will work
97 m_value_wxFontData
= m_value
;
98 wxFontData
& fontData
= wxFontDataFromVariant(m_value_wxFontData
);
100 wxFont font
= fontData
.GetChosenFont();
102 font
= wxFont(10,wxSWISS
,wxNORMAL
,wxNORMAL
);
103 m_value
= WXVARIANT(font
);
106 wxVariant
wxFontDataProperty::DoGetValue() const
108 return m_value_wxFontData
;
111 // Must re-create font dialog displayer.
112 bool wxFontDataProperty::OnEvent( wxPropertyGrid
* propgrid
,
113 wxWindow
* WXUNUSED(primary
), wxEvent
& event
)
115 if ( propgrid
->IsMainButtonEvent(event
) )
117 // Update value from last minute changes
118 PrepareValueForDialogEditing(propgrid
);
120 wxFontData
& fontData
= wxFontDataFromVariant(m_value_wxFontData
);
122 fontData
.SetInitialFont(fontData
.GetChosenFont());
124 wxFontDialog
dlg(propgrid
, fontData
);
126 if ( dlg
.ShowModal() == wxID_OK
)
128 SetValueInEvent( wxFontDataToVariant(dlg
.GetFontData()) );
135 void wxFontDataProperty::RefreshChildren()
137 wxFontProperty::RefreshChildren();
138 if ( GetChildCount() < 6 ) // Number is count of inherit prop's children + 1.
140 wxFontData
& fontData
= wxFontDataFromVariant(m_value_wxFontData
);
141 wxVariant variant
; variant
<< fontData
.GetColour();
142 Item(6)->SetValue( variant
);
145 void wxFontDataProperty::ChildChanged( wxVariant
& thisValue
, int childIndex
, wxVariant
& childValue
) const
147 wxFontData
& fontData
= wxFontDataFromVariant(thisValue
);
151 switch ( childIndex
)
155 fontData
.SetColour( col
);
158 // Transfer between subset to superset.
159 variant
= WXVARIANT(fontData
.GetChosenFont());
160 wxFontProperty::ChildChanged( variant
, childIndex
, childValue
);
161 fontData
.SetChosenFont(wxFontFromVariant(variant
));
165 // -----------------------------------------------------------------------
167 // -----------------------------------------------------------------------
169 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSizeProperty
,wxPGProperty
,
170 wxSize
,const wxSize
&,TextCtrl
)
172 wxSizeProperty::wxSizeProperty( const wxString
& label
, const wxString
& name
,
173 const wxSize
& value
) : wxPGProperty(label
,name
)
176 AddChild( new wxIntProperty(wxT("Width"),wxPG_LABEL
,value
.x
) );
177 AddChild( new wxIntProperty(wxT("Height"),wxPG_LABEL
,value
.y
) );
180 wxSizeProperty::~wxSizeProperty() { }
182 void wxSizeProperty::RefreshChildren()
184 if ( !GetChildCount() ) return;
185 const wxSize
& size
= wxSizeFromVariant(m_value
);
186 Item(0)->SetValue( (long)size
.x
);
187 Item(1)->SetValue( (long)size
.y
);
190 void wxSizeProperty::ChildChanged( wxVariant
& thisValue
, int childIndex
, wxVariant
& childValue
) const
192 wxSize
& size
= wxSizeFromVariant(thisValue
);
193 int val
= wxPGVariantToInt(childValue
);
194 switch ( childIndex
)
196 case 0: size
.x
= val
; break;
197 case 1: size
.y
= val
; break;
201 // -----------------------------------------------------------------------
203 // -----------------------------------------------------------------------
205 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxPointProperty
,wxPGProperty
,
206 wxPoint
,const wxPoint
&,TextCtrl
)
208 wxPointProperty::wxPointProperty( const wxString
& label
, const wxString
& name
,
209 const wxPoint
& value
) : wxPGProperty(label
,name
)
212 AddChild( new wxIntProperty(wxT("X"),wxPG_LABEL
,value
.x
) );
213 AddChild( new wxIntProperty(wxT("Y"),wxPG_LABEL
,value
.y
) );
216 wxPointProperty::~wxPointProperty() { }
218 void wxPointProperty::RefreshChildren()
220 if ( !GetChildCount() ) return;
221 const wxPoint
& point
= wxPointFromVariant(m_value
);
222 Item(0)->SetValue( (long)point
.x
);
223 Item(1)->SetValue( (long)point
.y
);
226 void wxPointProperty::ChildChanged( wxVariant
& thisValue
, int childIndex
, wxVariant
& childValue
) const
228 wxPoint
& point
= wxPointFromVariant(thisValue
);
229 int val
= wxPGVariantToInt(childValue
);
230 switch ( childIndex
)
232 case 0: point
.x
= val
; break;
233 case 1: point
.y
= val
; break;
238 // -----------------------------------------------------------------------
240 // -----------------------------------------------------------------------
242 WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY_WITH_VALIDATOR(wxDirsProperty
,wxT(','),wxT("Browse"))
246 wxValidator
* wxDirsProperty::DoGetValidator() const
248 return wxFileProperty::GetClassValidator();
254 bool wxDirsProperty::OnCustomStringEdit( wxWindow
* parent
, wxString
& value
)
256 wxDirDialog
dlg(parent
,
257 _("Select a directory to be added to the list:"),
261 if ( dlg
.ShowModal() == wxID_OK
)
263 value
= dlg
.GetPath();
269 // -----------------------------------------------------------------------
270 // wxArrayDoubleEditorDialog
271 // -----------------------------------------------------------------------
275 // You can *almost* convert wxArrayDoubleEditorDialog to wxArrayXXXEditorDialog
276 // by replacing each ArrayDouble with ArrayXXX.
279 class wxArrayDoubleEditorDialog
: public wxArrayEditorDialog
282 wxArrayDoubleEditorDialog();
286 wxArrayDoubleEditorDialog(wxWindow
*parent
,
287 const wxString
& message
,
288 const wxString
& caption
,
289 wxArrayDouble
& array
,
290 long style
= wxAEDIALOG_STYLE
,
291 const wxPoint
& pos
= wxDefaultPosition
,
292 const wxSize
& sz
= wxDefaultSize
);
294 bool Create(wxWindow
*parent
,
295 const wxString
& message
,
296 const wxString
& caption
,
297 wxArrayDouble
& array
,
298 long style
= wxAEDIALOG_STYLE
,
299 const wxPoint
& pos
= wxDefaultPosition
,
300 const wxSize
& sz
= wxDefaultSize
);
302 const wxArrayDouble
& GetArray() const { return m_array
; }
304 // Extra method for this type of array
305 void SetPrecision ( int precision
)
307 m_precision
= precision
;
308 m_dtoaTemplate
.Empty();
312 // Mandatory array of type
313 wxArrayDouble m_array
;
315 // Use this to avoid extra wxString creation+Printf
316 // on double-to-wxString conversion.
317 wxString m_dtoaTemplate
;
321 // Mandatory overridden methods
322 virtual wxString
ArrayGet( size_t index
);
323 virtual size_t ArrayGetCount();
324 virtual bool ArrayInsert( const wxString
& str
, int index
);
325 virtual bool ArraySet( size_t index
, const wxString
& str
);
326 virtual void ArrayRemoveAt( int index
);
327 virtual void ArraySwap( size_t first
, size_t second
);
330 DECLARE_DYNAMIC_CLASS_NO_COPY(wxArrayDoubleEditorDialog
)
333 IMPLEMENT_DYNAMIC_CLASS(wxArrayDoubleEditorDialog
, wxArrayEditorDialog
)
336 // Array dialog array access and manipulation
339 wxString
wxArrayDoubleEditorDialog::ArrayGet( size_t index
)
342 wxPropertyGrid::DoubleToString(str
,m_array
[index
],m_precision
,true,&m_dtoaTemplate
);
346 size_t wxArrayDoubleEditorDialog::ArrayGetCount()
348 return m_array
.GetCount();
351 bool wxArrayDoubleEditorDialog::ArrayInsert( const wxString
& str
, int index
)
354 if ( !str
.ToDouble(&d
) )
360 m_array
.Insert(d
,index
);
364 bool wxArrayDoubleEditorDialog::ArraySet( size_t index
, const wxString
& str
)
367 if ( !str
.ToDouble(&d
) )
373 void wxArrayDoubleEditorDialog::ArrayRemoveAt( int index
)
375 m_array
.RemoveAt(index
);
378 void wxArrayDoubleEditorDialog::ArraySwap( size_t first
, size_t second
)
380 double a
= m_array
[first
];
381 double b
= m_array
[second
];
387 // Array dialog construction etc.
390 wxArrayDoubleEditorDialog::wxArrayDoubleEditorDialog()
391 : wxArrayEditorDialog()
396 void wxArrayDoubleEditorDialog::Init()
398 wxArrayEditorDialog::Init();
402 wxArrayDoubleEditorDialog::wxArrayDoubleEditorDialog(wxWindow
*parent
,
403 const wxString
& message
,
404 const wxString
& caption
,
405 wxArrayDouble
& array
,
409 : wxArrayEditorDialog()
412 Create(parent
,message
,caption
,array
,style
,pos
,sz
);
415 bool wxArrayDoubleEditorDialog::Create(wxWindow
*parent
,
416 const wxString
& message
,
417 const wxString
& caption
,
418 wxArrayDouble
& array
,
426 return wxArrayEditorDialog::Create (parent
,message
,caption
,style
,pos
,sz
);
429 // -----------------------------------------------------------------------
430 // wxArrayDoubleProperty
431 // -----------------------------------------------------------------------
433 #include <math.h> // for fabs
435 // Comparison required by value type implementation.
436 bool operator == (const wxArrayDouble
& a
, const wxArrayDouble
& b
)
438 if ( a
.GetCount() != b
.GetCount() )
443 for ( i
=0; i
<a
.GetCount(); i
++ )
445 // Can't do direct equality comparison with floating point numbers.
446 if ( fabs(a
[i
] - b
[i
]) > 0.0000000001 )
448 //wxLogDebug(wxT("%f != %f"),a[i],b[i]);
455 WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataArrayDouble
, wxArrayDouble
)
457 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayDoubleProperty
,
460 const wxArrayDouble
&,
464 wxArrayDoubleProperty::wxArrayDoubleProperty (const wxString
& label
,
465 const wxString
& name
,
466 const wxArrayDouble
& array
)
467 : wxPGProperty(label
,name
)
472 // Need to figure out delimiter needed for this locale
473 // (ie. can't use comma when comma acts as decimal point in float).
474 wxChar use_delimiter
= wxT(',');
476 if (wxString::Format(wxT("%.2f"),12.34).Find(use_delimiter
) >= 0)
477 use_delimiter
= wxT(';');
479 m_delimiter
= use_delimiter
;
481 SetValue( wxArrayDoubleToVariant(array
) );
484 wxArrayDoubleProperty::~wxArrayDoubleProperty () { }
486 void wxArrayDoubleProperty::OnSetValue()
488 GenerateValueAsString( m_display
, m_precision
, true );
491 wxString
wxArrayDoubleProperty::GetValueAsString( int arg_flags
) const
493 if ( !(arg_flags
& wxPG_FULL_VALUE
))
497 GenerateValueAsString(s
,-1,false);
501 void wxArrayDoubleProperty::GenerateValueAsString( wxString
& target
, int prec
, bool removeZeroes
) const
504 wxString template_str
;
505 wxChar between
[3] = wxT(", ");
508 between
[0] = m_delimiter
;
512 const wxArrayDouble
& value
= wxArrayDoubleFromVariant(m_value
);
514 for ( i
=0; i
<value
.GetCount(); i
++ )
517 wxPropertyGrid::DoubleToString(s
,value
[i
],prec
,removeZeroes
,&template_str
);
521 if ( i
<(value
.GetCount()-1) )
526 bool wxArrayDoubleProperty::OnEvent( wxPropertyGrid
* propgrid
,
527 wxWindow
* WXUNUSED(primary
),
530 if ( propgrid
->IsMainButtonEvent(event
) )
532 wxArrayDouble
& value
= wxArrayDoubleFromVariant(m_value
);
534 // Update the value in case of last minute changes
535 PrepareValueForDialogEditing(propgrid
);
537 // Create editor dialog.
538 wxArrayDoubleEditorDialog dlg
;
539 dlg
.SetPrecision(m_precision
);
540 dlg
.Create( propgrid
, wxEmptyString
, m_label
, value
);
541 dlg
.Move( propgrid
->GetGoodEditorDialogPosition(this,dlg
.GetSize()) );
543 // Execute editor dialog
544 int res
= dlg
.ShowModal();
545 if ( res
== wxID_OK
&& dlg
.IsModified() )
547 SetValueInEvent( wxArrayDoubleToVariant(dlg
.GetArray()) );
555 bool wxArrayDoubleProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
559 // Add values to a temporary array so that in case
560 // of error we can opt not to use them.
561 wxArrayDouble new_array
;
565 wxChar delimiter
= m_delimiter
;
567 WX_PG_TOKENIZER1_BEGIN(text
,delimiter
)
569 if ( token
.length() )
572 // If token was invalid, exit the loop now
573 if ( !token
.ToDouble(&tval
) )
575 tstr
.Printf ( _("\"%s\" is not a floating-point number."), token
.c_str() );
579 // TODO: Put validator code here
585 WX_PG_TOKENIZER1_END()
587 // When invalid token found, show error message and don't change anything
594 if ( !(wxArrayDoubleFromVariant(m_value
) == new_array
) )
596 variant
= wxArrayDoubleToVariant(new_array
);
603 bool wxArrayDoubleProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
605 if ( name
== wxPG_FLOAT_PRECISION
)
607 m_precision
= value
.GetLong();
608 GenerateValueAsString( m_display
, m_precision
, true );