1
/////////////////////////////////////////////////////////////////////////////
2
// Name: samples/propgrid/sampleprops.cpp
3
// Purpose: wxPropertyGrid Sample Properties
4
// Author: Jaakko Salli
7
// RCS-ID: $Id: sampleprops.cpp 67681 2011-05-03 16:29:04Z DS $
8
// Copyright: (c) Jaakko Salli
9
// Licence: wxWindows licence
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
#include "wx/fontdlg.h"
27
// -----------------------------------------------------------------------
30
#include <wx/propgrid/propgrid.h>
31
#include <wx/propgrid/advprops.h>
33
#ifndef WX_PROPGRID_SAMPLEPROPS_H
34
#include "sampleprops.h"
38
// -----------------------------------------------------------------------
40
// -----------------------------------------------------------------------
42
// Dummy comparison required by value type implementation.
43
bool operator == (const wxFontData&, const wxFontData&)
48
// Custom version of wxFontProperty that also holds colour in the value.
49
// Original version by Vladimir Vainer.
51
IMPLEMENT_VARIANT_OBJECT_SHALLOWCMP(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
wxFontData fontData(value);
62
fontData.SetChosenFont(value.GetInitialFont());
63
if ( !fontData.GetColour().IsOk() )
64
fontData.SetColour(*wxBLACK);
66
// Set initial value - should be done in a simpler way like this
67
// (instead of calling SetValue) in derived (wxObject) properties.
68
m_value_wxFontData << value;
70
// Add extra children.
71
AddPrivateChild( new wxColourProperty(_("Colour"), wxPG_LABEL,
72
fontData.GetColour() ) );
75
wxFontDataProperty::~wxFontDataProperty () { }
77
void wxFontDataProperty::OnSetValue()
79
if ( m_value.GetType() != "wxFontData" )
81
if ( m_value.GetType() == "wxFont" )
86
fontData.SetChosenFont(font);
87
if ( !m_value_wxFontData.IsNull() )
89
wxFontData oldFontData;
90
oldFontData << m_value_wxFontData;
91
fontData.SetColour(oldFontData.GetColour());
95
fontData.SetColour(*wxBLACK);
99
m_value_wxFontData = variant;
103
wxFAIL_MSG(wxT("Value to wxFontDataProperty must be eithe wxFontData or wxFont"));
108
// Set m_value to wxFont so that wxFontProperty methods will work
110
m_value_wxFontData = m_value;
113
fontData << m_value_wxFontData;
115
wxFont font = fontData.GetChosenFont();
117
font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
119
m_value = WXVARIANT(font);
123
wxVariant wxFontDataProperty::DoGetValue() const
125
return m_value_wxFontData;
128
// Must re-create font dialog displayer.
129
bool wxFontDataProperty::OnEvent( wxPropertyGrid* propgrid,
130
wxWindow* WXUNUSED(primary), wxEvent& event )
132
if ( propgrid->IsMainButtonEvent(event) )
134
wxVariant useValue = propgrid->GetUncommittedPropertyValue();
137
fontData << useValue;
139
fontData.SetInitialFont(fontData.GetChosenFont());
141
wxFontDialog dlg(propgrid, fontData);
143
if ( dlg.ShowModal() == wxID_OK )
146
variant << dlg.GetFontData();
147
SetValueInEvent( variant );
154
void wxFontDataProperty::RefreshChildren()
156
wxFontProperty::RefreshChildren();
157
if ( GetChildCount() < 6 ) // Number is count of wxFontProperty's children + 1.
159
wxFontData fontData; fontData << m_value_wxFontData;
160
wxVariant variant; variant << fontData.GetColour();
161
Item(6)->SetValue( variant );
164
wxVariant wxFontDataProperty::ChildChanged( wxVariant& thisValue,
166
wxVariant& childValue ) const
169
fontData << thisValue;
173
switch ( childIndex )
177
fontData.SetColour( col );
180
// Transfer from subset to superset.
181
wxFont font = fontData.GetChosenFont();
182
variant = WXVARIANT(font);
183
wxFontProperty::ChildChanged( variant, childIndex, childValue );
185
fontData.SetChosenFont(font);
188
wxVariant newVariant;
189
newVariant << fontData;
193
// -----------------------------------------------------------------------
195
// -----------------------------------------------------------------------
197
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSizeProperty,wxPGProperty,
198
wxSize,const wxSize&,TextCtrl)
200
wxSizeProperty::wxSizeProperty( const wxString& label, const wxString& name,
201
const wxSize& value) : wxPGProperty(label,name)
204
AddPrivateChild( new wxIntProperty(wxT("Width"),wxPG_LABEL,value.x) );
205
AddPrivateChild( new wxIntProperty(wxT("Height"),wxPG_LABEL,value.y) );
208
wxSizeProperty::~wxSizeProperty() { }
210
void wxSizeProperty::RefreshChildren()
212
if ( !GetChildCount() ) return;
213
const wxSize& size = wxSizeRefFromVariant(m_value);
214
Item(0)->SetValue( (long)size.x );
215
Item(1)->SetValue( (long)size.y );
218
wxVariant wxSizeProperty::ChildChanged( wxVariant& thisValue,
220
wxVariant& childValue ) const
222
wxSize& size = wxSizeRefFromVariant(thisValue);
223
int val = childValue.GetLong();
224
switch ( childIndex )
226
case 0: size.x = val; break;
227
case 1: size.y = val; break;
229
wxVariant newVariant;
234
// -----------------------------------------------------------------------
236
// -----------------------------------------------------------------------
238
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxPointProperty,wxPGProperty,
239
wxPoint,const wxPoint&,TextCtrl)
241
wxPointProperty::wxPointProperty( const wxString& label, const wxString& name,
242
const wxPoint& value) : wxPGProperty(label,name)
245
AddPrivateChild( new wxIntProperty(wxT("X"),wxPG_LABEL,value.x) );
246
AddPrivateChild( new wxIntProperty(wxT("Y"),wxPG_LABEL,value.y) );
249
wxPointProperty::~wxPointProperty() { }
251
void wxPointProperty::RefreshChildren()
253
if ( !GetChildCount() ) return;
254
const wxPoint& point = wxPointRefFromVariant(m_value);
255
Item(0)->SetValue( (long)point.x );
256
Item(1)->SetValue( (long)point.y );
259
wxVariant wxPointProperty::ChildChanged( wxVariant& thisValue,
261
wxVariant& childValue ) const
263
wxPoint& point = wxPointRefFromVariant(thisValue);
264
int val = childValue.GetLong();
265
switch ( childIndex )
267
case 0: point.x = val; break;
268
case 1: point.y = val; break;
270
wxVariant newVariant;
276
// -----------------------------------------------------------------------
278
// -----------------------------------------------------------------------
280
WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY_WITH_VALIDATOR(wxDirsProperty, ',',
285
wxValidator* wxDirsProperty::DoGetValidator() const
287
return wxFileProperty::GetClassValidator();
293
bool wxDirsProperty::OnCustomStringEdit( wxWindow* parent, wxString& value )
295
wxDirDialog dlg(parent,
296
_("Select a directory to be added to the list:"),
300
if ( dlg.ShowModal() == wxID_OK )
302
value = dlg.GetPath();
308
// -----------------------------------------------------------------------
309
// wxArrayDoubleEditorDialog
310
// -----------------------------------------------------------------------
314
// You can *almost* convert wxArrayDoubleEditorDialog to wxArrayXXXEditorDialog
315
// by replacing each ArrayDouble with ArrayXXX.
318
class wxArrayDoubleEditorDialog : public wxPGArrayEditorDialog
321
wxArrayDoubleEditorDialog();
325
wxArrayDoubleEditorDialog(wxWindow *parent,
326
const wxString& message,
327
const wxString& caption,
328
wxArrayDouble& array,
329
long style = wxAEDIALOG_STYLE,
330
const wxPoint& pos = wxDefaultPosition,
331
const wxSize& sz = wxDefaultSize );
333
bool Create(wxWindow *parent,
334
const wxString& message,
335
const wxString& caption,
336
wxArrayDouble& array,
337
long style = wxAEDIALOG_STYLE,
338
const wxPoint& pos = wxDefaultPosition,
339
const wxSize& sz = wxDefaultSize );
341
const wxArrayDouble& GetArray() const { return m_array; }
343
// Extra method for this type of array
344
void SetPrecision ( int precision )
346
m_precision = precision;
347
m_dtoaTemplate.Empty();
351
// Mandatory array of type
352
wxArrayDouble m_array;
354
// Use this to avoid extra wxString creation+Printf
355
// on double-to-wxString conversion.
356
wxString m_dtoaTemplate;
360
// Mandatory overridden methods
361
virtual wxString ArrayGet( size_t index );
362
virtual size_t ArrayGetCount();
363
virtual bool ArrayInsert( const wxString& str, int index );
364
virtual bool ArraySet( size_t index, const wxString& str );
365
virtual void ArrayRemoveAt( int index );
366
virtual void ArraySwap( size_t first, size_t second );
369
DECLARE_DYNAMIC_CLASS_NO_COPY(wxArrayDoubleEditorDialog)
372
IMPLEMENT_DYNAMIC_CLASS(wxArrayDoubleEditorDialog, wxPGArrayEditorDialog)
375
// Array dialog array access and manipulation
378
wxString wxArrayDoubleEditorDialog::ArrayGet( size_t index )
381
wxPropertyGrid::DoubleToString(str,m_array[index],m_precision,true,&m_dtoaTemplate);
385
size_t wxArrayDoubleEditorDialog::ArrayGetCount()
387
return m_array.GetCount();
390
bool wxArrayDoubleEditorDialog::ArrayInsert( const wxString& str, int index )
393
if ( !str.ToDouble(&d) )
399
m_array.Insert(d,index);
403
bool wxArrayDoubleEditorDialog::ArraySet( size_t index, const wxString& str )
406
if ( !str.ToDouble(&d) )
412
void wxArrayDoubleEditorDialog::ArrayRemoveAt( int index )
414
m_array.RemoveAt(index);
417
void wxArrayDoubleEditorDialog::ArraySwap( size_t first, size_t second )
419
double a = m_array[first];
420
double b = m_array[second];
426
// Array dialog construction etc.
429
wxArrayDoubleEditorDialog::wxArrayDoubleEditorDialog()
430
: wxPGArrayEditorDialog()
435
void wxArrayDoubleEditorDialog::Init()
437
wxPGArrayEditorDialog::Init();
441
wxArrayDoubleEditorDialog::wxArrayDoubleEditorDialog(wxWindow *parent,
442
const wxString& message,
443
const wxString& caption,
444
wxArrayDouble& array,
448
: wxPGArrayEditorDialog()
451
Create(parent,message,caption,array,style,pos,sz);
454
bool wxArrayDoubleEditorDialog::Create(wxWindow *parent,
455
const wxString& message,
456
const wxString& caption,
457
wxArrayDouble& array,
465
return wxPGArrayEditorDialog::Create (parent,message,caption,style,pos,sz);
468
// -----------------------------------------------------------------------
469
// wxArrayDoubleProperty
470
// -----------------------------------------------------------------------
472
#include <math.h> // for fabs
474
// Comparison required by value type implementation.
475
bool operator == (const wxArrayDouble& a, const wxArrayDouble& b)
477
if ( a.GetCount() != b.GetCount() )
482
for ( i=0; i<a.GetCount(); i++ )
484
// Can't do direct equality comparison with floating point numbers.
485
if ( fabs(a[i] - b[i]) > 0.0000000001 )
487
//wxLogDebug(wxT("%f != %f"),a[i],b[i]);
494
WX_PG_IMPLEMENT_VARIANT_DATA_DUMMY_EQ(wxArrayDouble)
496
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayDoubleProperty,
499
const wxArrayDouble&,
503
wxArrayDoubleProperty::wxArrayDoubleProperty (const wxString& label,
504
const wxString& name,
505
const wxArrayDouble& array )
506
: wxPGProperty(label,name)
511
// Need to figure out delimiter needed for this locale
512
// (ie. can't use comma when comma acts as decimal point in float).
513
wxChar use_delimiter = wxT(',');
515
if (wxString::Format(wxT("%.2f"),12.34).Find(use_delimiter) >= 0)
516
use_delimiter = wxT(';');
518
m_delimiter = use_delimiter;
520
SetValue( WXVARIANT(array) );
523
wxArrayDoubleProperty::~wxArrayDoubleProperty () { }
525
void wxArrayDoubleProperty::OnSetValue()
527
// Generate cached display string, to optimize grid drawing
528
GenerateValueAsString( m_display, m_precision, true );
531
wxString wxArrayDoubleProperty::ValueToString( wxVariant& value,
536
if ( argFlags & wxPG_FULL_VALUE )
538
GenerateValueAsString(s,-1,false);
543
// Display cached string only if value truly matches m_value
544
if ( value.GetData() == m_value.GetData() )
547
GenerateValueAsString( s, m_precision, true );
553
void wxArrayDoubleProperty::GenerateValueAsString( wxString& target, int prec, bool removeZeroes ) const
556
wxString template_str;
557
wxChar between[3] = wxT(", ");
560
between[0] = m_delimiter;
564
const wxArrayDouble& value = wxArrayDoubleRefFromVariant(m_value);
566
for ( i=0; i<value.GetCount(); i++ )
569
wxPropertyGrid::DoubleToString(s,value[i],prec,removeZeroes,&template_str);
573
if ( i<(value.GetCount()-1) )
578
bool wxArrayDoubleProperty::OnEvent( wxPropertyGrid* propgrid,
579
wxWindow* WXUNUSED(primary),
582
if ( propgrid->IsMainButtonEvent(event) )
584
// Update the value in case of last minute changes
585
wxVariant useValue = propgrid->GetUncommittedPropertyValue();
587
wxArrayDouble& value = wxArrayDoubleRefFromVariant(useValue);
589
// Create editor dialog.
590
wxArrayDoubleEditorDialog dlg;
591
dlg.SetPrecision(m_precision);
592
dlg.Create( propgrid, wxEmptyString, m_label, value );
593
dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
595
// Execute editor dialog
596
int res = dlg.ShowModal();
597
if ( res == wxID_OK && dlg.IsModified() )
599
SetValueInEvent( WXVARIANT(dlg.GetArray()) );
607
bool wxArrayDoubleProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
611
// Add values to a temporary array so that in case
612
// of error we can opt not to use them.
613
wxArrayDouble new_array;
617
wxChar delimiter = m_delimiter;
619
WX_PG_TOKENIZER1_BEGIN(text,delimiter)
621
if ( !token.empty() )
624
// If token was invalid, exit the loop now
625
if ( !token.ToDouble(&tval) )
627
tstr.Printf ( _("\"%s\" is not a floating-point number."), token.c_str() );
631
// TODO: Put validator code here
637
WX_PG_TOKENIZER1_END()
639
// When invalid token found, show error message and don't change anything
646
if ( !(wxArrayDoubleRefFromVariant(m_value) == new_array) )
648
variant = WXVARIANT(new_array);
655
bool wxArrayDoubleProperty::DoSetAttribute( const wxString& name, wxVariant& value )
657
if ( name == wxPG_FLOAT_PRECISION )
659
m_precision = value.GetLong();
660
GenerateValueAsString( m_display, m_precision, true );