]> git.saurik.com Git - wxWidgets.git/blame - samples/propgrid/sampleprops.cpp
Compilation fix to propgrid sample after r74628.
[wxWidgets.git] / samples / propgrid / sampleprops.cpp
CommitLineData
1c4293cb
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: samples/propgrid/sampleprops.cpp
3// Purpose: wxPropertyGrid Sample Properties
4// Author: Jaakko Salli
5// Modified by:
6// Created: 2006-03-05
1c4293cb 7// Copyright: (c) Jaakko Salli
526954c5 8// Licence: wxWindows licence
1c4293cb
VZ
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx/wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18// for all others, include the necessary headers (this file is usually all you
19// need because it includes almost all "standard" wxWidgets headers)
20#ifndef WX_PRECOMP
21 #include "wx/wx.h"
22#endif
23
081d8d96
PC
24#include "wx/fontdlg.h"
25
1c4293cb
VZ
26// -----------------------------------------------------------------------
27
28
29#include <wx/propgrid/propgrid.h>
30#include <wx/propgrid/advprops.h>
31
32#ifndef WX_PROPGRID_SAMPLEPROPS_H
33 #include "sampleprops.h"
34#endif
35
36
37// -----------------------------------------------------------------------
38// wxFontDataProperty
39// -----------------------------------------------------------------------
40
41// Dummy comparison required by value type implementation.
42bool operator == (const wxFontData&, const wxFontData&)
43{
44 return FALSE;
45}
46
47// Custom version of wxFontProperty that also holds colour in the value.
48// Original version by Vladimir Vainer.
49
0372d42e 50IMPLEMENT_VARIANT_OBJECT_SHALLOWCMP(wxFontData)
1c4293cb
VZ
51
52WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontDataProperty,wxFontProperty,
53 wxFontData,const wxFontData&,TextCtrlAndButton)
54
55wxFontDataProperty::wxFontDataProperty( const wxString& label, const wxString& name,
56 const wxFontData& value ) : wxFontProperty(label,name,value.GetInitialFont())
57{
0372d42e 58 wxFontData fontData(value);
1c4293cb
VZ
59
60 // Fix value.
61 fontData.SetChosenFont(value.GetInitialFont());
a1b806b9 62 if ( !fontData.GetColour().IsOk() )
1c4293cb
VZ
63 fontData.SetColour(*wxBLACK);
64
0372d42e
JS
65 // Set initial value - should be done in a simpler way like this
66 // (instead of calling SetValue) in derived (wxObject) properties.
67 m_value_wxFontData << value;
68
1c4293cb 69 // Add extra children.
48a32cf6
JS
70 AddPrivateChild( new wxColourProperty(_("Colour"), wxPG_LABEL,
71 fontData.GetColour() ) );
1c4293cb
VZ
72}
73
74wxFontDataProperty::~wxFontDataProperty () { }
75
76void wxFontDataProperty::OnSetValue()
77{
0372d42e 78 if ( m_value.GetType() != "wxFontData" )
1c4293cb 79 {
0372d42e 80 if ( m_value.GetType() == "wxFont" )
1c4293cb 81 {
0372d42e
JS
82 wxFont font;
83 font << m_value;
1c4293cb 84 wxFontData fontData;
0372d42e
JS
85 fontData.SetChosenFont(font);
86 if ( !m_value_wxFontData.IsNull() )
87 {
88 wxFontData oldFontData;
89 oldFontData << m_value_wxFontData;
90 fontData.SetColour(oldFontData.GetColour());
91 }
92 else
93 {
94 fontData.SetColour(*wxBLACK);
95 }
96 wxVariant variant;
97 variant << fontData;
98 m_value_wxFontData = variant;
1c4293cb
VZ
99 }
100 else
101 {
102 wxFAIL_MSG(wxT("Value to wxFontDataProperty must be eithe wxFontData or wxFont"));
103 }
104 }
0372d42e
JS
105 else
106 {
107 // Set m_value to wxFont so that wxFontProperty methods will work
108 // correctly.
109 m_value_wxFontData = m_value;
110
111 wxFontData fontData;
112 fontData << m_value_wxFontData;
1c4293cb 113
0372d42e 114 wxFont font = fontData.GetChosenFont();
a1b806b9 115 if ( !font.IsOk() )
0372d42e 116 font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
1c4293cb 117
0372d42e
JS
118 m_value = WXVARIANT(font);
119 }
1c4293cb
VZ
120}
121
122wxVariant wxFontDataProperty::DoGetValue() const
123{
124 return m_value_wxFontData;
125}
126
127// Must re-create font dialog displayer.
128bool wxFontDataProperty::OnEvent( wxPropertyGrid* propgrid,
129 wxWindow* WXUNUSED(primary), wxEvent& event )
130{
131 if ( propgrid->IsMainButtonEvent(event) )
132 {
703ee9f5 133 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1c4293cb 134
0372d42e 135 wxFontData fontData;
9b5bafcf 136 fontData << useValue;
1c4293cb
VZ
137
138 fontData.SetInitialFont(fontData.GetChosenFont());
139
140 wxFontDialog dlg(propgrid, fontData);
141
142 if ( dlg.ShowModal() == wxID_OK )
143 {
0372d42e
JS
144 wxVariant variant;
145 variant << dlg.GetFontData();
146 SetValueInEvent( variant );
1c4293cb
VZ
147 return true;
148 }
149 }
150 return false;
151}
152
153void wxFontDataProperty::RefreshChildren()
154{
155 wxFontProperty::RefreshChildren();
0372d42e 156 if ( GetChildCount() < 6 ) // Number is count of wxFontProperty's children + 1.
1c4293cb 157 return;
0372d42e 158 wxFontData fontData; fontData << m_value_wxFontData;
1c4293cb
VZ
159 wxVariant variant; variant << fontData.GetColour();
160 Item(6)->SetValue( variant );
161}
162
b8b1ff48
JS
163wxVariant wxFontDataProperty::ChildChanged( wxVariant& thisValue,
164 int childIndex,
165 wxVariant& childValue ) const
1c4293cb 166{
0372d42e
JS
167 wxFontData fontData;
168 fontData << thisValue;
1c4293cb
VZ
169 wxColour col;
170 wxVariant variant;
171
172 switch ( childIndex )
173 {
174 case 6:
175 col << childValue;
176 fontData.SetColour( col );
177 break;
178 default:
0372d42e
JS
179 // Transfer from subset to superset.
180 wxFont font = fontData.GetChosenFont();
181 variant = WXVARIANT(font);
1c4293cb 182 wxFontProperty::ChildChanged( variant, childIndex, childValue );
0372d42e
JS
183 font << variant;
184 fontData.SetChosenFont(font);
1c4293cb 185 }
0372d42e 186
b8b1ff48
JS
187 wxVariant newVariant;
188 newVariant << fontData;
189 return newVariant;
1c4293cb
VZ
190}
191
192// -----------------------------------------------------------------------
193// wxSizeProperty
194// -----------------------------------------------------------------------
195
196WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSizeProperty,wxPGProperty,
197 wxSize,const wxSize&,TextCtrl)
198
199wxSizeProperty::wxSizeProperty( const wxString& label, const wxString& name,
200 const wxSize& value) : wxPGProperty(label,name)
201{
202 SetValueI(value);
48a32cf6
JS
203 AddPrivateChild( new wxIntProperty(wxT("Width"),wxPG_LABEL,value.x) );
204 AddPrivateChild( new wxIntProperty(wxT("Height"),wxPG_LABEL,value.y) );
1c4293cb
VZ
205}
206
207wxSizeProperty::~wxSizeProperty() { }
208
209void wxSizeProperty::RefreshChildren()
210{
211 if ( !GetChildCount() ) return;
0372d42e 212 const wxSize& size = wxSizeRefFromVariant(m_value);
1c4293cb
VZ
213 Item(0)->SetValue( (long)size.x );
214 Item(1)->SetValue( (long)size.y );
215}
216
b8b1ff48
JS
217wxVariant wxSizeProperty::ChildChanged( wxVariant& thisValue,
218 int childIndex,
219 wxVariant& childValue ) const
1c4293cb 220{
0372d42e 221 wxSize& size = wxSizeRefFromVariant(thisValue);
4e00b908 222 int val = childValue.GetLong();
1c4293cb
VZ
223 switch ( childIndex )
224 {
225 case 0: size.x = val; break;
226 case 1: size.y = val; break;
227 }
b8b1ff48
JS
228 wxVariant newVariant;
229 newVariant << size;
230 return newVariant;
1c4293cb
VZ
231}
232
233// -----------------------------------------------------------------------
234// wxPointProperty
235// -----------------------------------------------------------------------
236
237WX_PG_IMPLEMENT_PROPERTY_CLASS(wxPointProperty,wxPGProperty,
238 wxPoint,const wxPoint&,TextCtrl)
239
240wxPointProperty::wxPointProperty( const wxString& label, const wxString& name,
241 const wxPoint& value) : wxPGProperty(label,name)
242{
243 SetValueI(value);
48a32cf6
JS
244 AddPrivateChild( new wxIntProperty(wxT("X"),wxPG_LABEL,value.x) );
245 AddPrivateChild( new wxIntProperty(wxT("Y"),wxPG_LABEL,value.y) );
1c4293cb
VZ
246}
247
248wxPointProperty::~wxPointProperty() { }
249
250void wxPointProperty::RefreshChildren()
251{
252 if ( !GetChildCount() ) return;
0372d42e 253 const wxPoint& point = wxPointRefFromVariant(m_value);
1c4293cb
VZ
254 Item(0)->SetValue( (long)point.x );
255 Item(1)->SetValue( (long)point.y );
256}
257
b8b1ff48
JS
258wxVariant wxPointProperty::ChildChanged( wxVariant& thisValue,
259 int childIndex,
260 wxVariant& childValue ) const
1c4293cb 261{
0372d42e 262 wxPoint& point = wxPointRefFromVariant(thisValue);
4e00b908 263 int val = childValue.GetLong();
1c4293cb
VZ
264 switch ( childIndex )
265 {
266 case 0: point.x = val; break;
267 case 1: point.y = val; break;
268 }
b8b1ff48
JS
269 wxVariant newVariant;
270 newVariant << point;
271 return newVariant;
1c4293cb
VZ
272}
273
274
275// -----------------------------------------------------------------------
276// Dirs Property
277// -----------------------------------------------------------------------
278
525b2912
JS
279WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY_WITH_VALIDATOR(wxDirsProperty, ',',
280 "Browse")
1c4293cb
VZ
281
282#if wxUSE_VALIDATORS
283
284wxValidator* wxDirsProperty::DoGetValidator() const
285{
286 return wxFileProperty::GetClassValidator();
287}
288
289#endif
290
291
292bool wxDirsProperty::OnCustomStringEdit( wxWindow* parent, wxString& value )
293{
294 wxDirDialog dlg(parent,
295 _("Select a directory to be added to the list:"),
296 value,
297 0);
298
299 if ( dlg.ShowModal() == wxID_OK )
300 {
301 value = dlg.GetPath();
302 return TRUE;
303 }
304 return FALSE;
305}
306
307// -----------------------------------------------------------------------
308// wxArrayDoubleEditorDialog
309// -----------------------------------------------------------------------
310
311
312//
313// You can *almost* convert wxArrayDoubleEditorDialog to wxArrayXXXEditorDialog
314// by replacing each ArrayDouble with ArrayXXX.
315//
316
2906967c 317class wxArrayDoubleEditorDialog : public wxPGArrayEditorDialog
1c4293cb
VZ
318{
319public:
320 wxArrayDoubleEditorDialog();
321
322 void Init();
323
324 wxArrayDoubleEditorDialog(wxWindow *parent,
325 const wxString& message,
326 const wxString& caption,
327 wxArrayDouble& array,
328 long style = wxAEDIALOG_STYLE,
329 const wxPoint& pos = wxDefaultPosition,
330 const wxSize& sz = wxDefaultSize );
331
332 bool Create(wxWindow *parent,
333 const wxString& message,
334 const wxString& caption,
335 wxArrayDouble& array,
336 long style = wxAEDIALOG_STYLE,
337 const wxPoint& pos = wxDefaultPosition,
338 const wxSize& sz = wxDefaultSize );
339
340 const wxArrayDouble& GetArray() const { return m_array; }
341
342 // Extra method for this type of array
343 void SetPrecision ( int precision )
344 {
345 m_precision = precision;
346 m_dtoaTemplate.Empty();
347 }
348
349protected:
350 // Mandatory array of type
351 wxArrayDouble m_array;
352
353 // Use this to avoid extra wxString creation+Printf
354 // on double-to-wxString conversion.
355 wxString m_dtoaTemplate;
356
357 int m_precision;
358
359 // Mandatory overridden methods
360 virtual wxString ArrayGet( size_t index );
361 virtual size_t ArrayGetCount();
362 virtual bool ArrayInsert( const wxString& str, int index );
363 virtual bool ArraySet( size_t index, const wxString& str );
364 virtual void ArrayRemoveAt( int index );
365 virtual void ArraySwap( size_t first, size_t second );
366
367private:
368 DECLARE_DYNAMIC_CLASS_NO_COPY(wxArrayDoubleEditorDialog)
369};
370
2906967c 371IMPLEMENT_DYNAMIC_CLASS(wxArrayDoubleEditorDialog, wxPGArrayEditorDialog)
1c4293cb
VZ
372
373//
374// Array dialog array access and manipulation
375//
376
377wxString wxArrayDoubleEditorDialog::ArrayGet( size_t index )
378{
379 wxString str;
380 wxPropertyGrid::DoubleToString(str,m_array[index],m_precision,true,&m_dtoaTemplate);
381 return str;
382}
383
384size_t wxArrayDoubleEditorDialog::ArrayGetCount()
385{
386 return m_array.GetCount();
387}
388
389bool wxArrayDoubleEditorDialog::ArrayInsert( const wxString& str, int index )
390{
391 double d;
392 if ( !str.ToDouble(&d) )
393 return FALSE;
394
395 if (index<0)
396 m_array.Add(d);
397 else
398 m_array.Insert(d,index);
399 return TRUE;
400}
401
402bool wxArrayDoubleEditorDialog::ArraySet( size_t index, const wxString& str )
403{
404 double d;
405 if ( !str.ToDouble(&d) )
406 return FALSE;
407 m_array[index] = d;
408 return TRUE;
409}
410
411void wxArrayDoubleEditorDialog::ArrayRemoveAt( int index )
412{
413 m_array.RemoveAt(index);
414}
415
416void wxArrayDoubleEditorDialog::ArraySwap( size_t first, size_t second )
417{
418 double a = m_array[first];
419 double b = m_array[second];
420 m_array[first] = b;
421 m_array[second] = a;
422}
423
424//
425// Array dialog construction etc.
426//
427
428wxArrayDoubleEditorDialog::wxArrayDoubleEditorDialog()
2906967c 429 : wxPGArrayEditorDialog()
1c4293cb
VZ
430{
431 Init();
432}
433
434void wxArrayDoubleEditorDialog::Init()
435{
2906967c 436 wxPGArrayEditorDialog::Init();
1c4293cb
VZ
437 SetPrecision(-1);
438}
439
440wxArrayDoubleEditorDialog::wxArrayDoubleEditorDialog(wxWindow *parent,
441 const wxString& message,
442 const wxString& caption,
443 wxArrayDouble& array,
444 long style,
445 const wxPoint& pos,
446 const wxSize& sz )
2906967c 447 : wxPGArrayEditorDialog()
1c4293cb
VZ
448{
449 Init();
450 Create(parent,message,caption,array,style,pos,sz);
451}
452
453bool wxArrayDoubleEditorDialog::Create(wxWindow *parent,
454 const wxString& message,
455 const wxString& caption,
456 wxArrayDouble& array,
457 long style,
458 const wxPoint& pos,
459 const wxSize& sz )
460{
461
462 m_array = array;
463
2906967c 464 return wxPGArrayEditorDialog::Create (parent,message,caption,style,pos,sz);
1c4293cb
VZ
465}
466
467// -----------------------------------------------------------------------
468// wxArrayDoubleProperty
469// -----------------------------------------------------------------------
470
471#include <math.h> // for fabs
472
473// Comparison required by value type implementation.
474bool operator == (const wxArrayDouble& a, const wxArrayDouble& b)
475{
476 if ( a.GetCount() != b.GetCount() )
477 return FALSE;
478
479 size_t i;
480
481 for ( i=0; i<a.GetCount(); i++ )
482 {
483 // Can't do direct equality comparison with floating point numbers.
484 if ( fabs(a[i] - b[i]) > 0.0000000001 )
485 {
486 //wxLogDebug(wxT("%f != %f"),a[i],b[i]);
487 return FALSE;
488 }
489 }
490 return TRUE;
491}
492
0372d42e 493WX_PG_IMPLEMENT_VARIANT_DATA_DUMMY_EQ(wxArrayDouble)
1c4293cb
VZ
494
495WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayDoubleProperty,
496 wxPGProperty,
497 wxArrayDouble,
498 const wxArrayDouble&,
499 TextCtrlAndButton)
500
501
502wxArrayDoubleProperty::wxArrayDoubleProperty (const wxString& label,
503 const wxString& name,
504 const wxArrayDouble& array )
505 : wxPGProperty(label,name)
506{
507 m_precision = -1;
508
509 //
510 // Need to figure out delimiter needed for this locale
511 // (ie. can't use comma when comma acts as decimal point in float).
512 wxChar use_delimiter = wxT(',');
513
514 if (wxString::Format(wxT("%.2f"),12.34).Find(use_delimiter) >= 0)
515 use_delimiter = wxT(';');
516
517 m_delimiter = use_delimiter;
518
0372d42e 519 SetValue( WXVARIANT(array) );
1c4293cb
VZ
520}
521
522wxArrayDoubleProperty::~wxArrayDoubleProperty () { }
523
524void wxArrayDoubleProperty::OnSetValue()
525{
1425eca5 526 // Generate cached display string, to optimize grid drawing
1c4293cb
VZ
527 GenerateValueAsString( m_display, m_precision, true );
528}
529
1425eca5
JS
530wxString wxArrayDoubleProperty::ValueToString( wxVariant& value,
531 int argFlags ) const
1c4293cb 532{
1c4293cb 533 wxString s;
1425eca5
JS
534
535 if ( argFlags & wxPG_FULL_VALUE )
536 {
537 GenerateValueAsString(s,-1,false);
538 }
539 else
540 {
541 //
542 // Display cached string only if value truly matches m_value
543 if ( value.GetData() == m_value.GetData() )
544 return m_display;
545 else
546 GenerateValueAsString( s, m_precision, true );
547 }
548
1c4293cb
VZ
549 return s;
550}
551
552void wxArrayDoubleProperty::GenerateValueAsString( wxString& target, int prec, bool removeZeroes ) const
553{
554 wxString s;
555 wxString template_str;
556 wxChar between[3] = wxT(", ");
557 size_t i;
558
559 between[0] = m_delimiter;
560
561 target.Empty();
562
0372d42e 563 const wxArrayDouble& value = wxArrayDoubleRefFromVariant(m_value);
1c4293cb
VZ
564
565 for ( i=0; i<value.GetCount(); i++ )
566 {
567
568 wxPropertyGrid::DoubleToString(s,value[i],prec,removeZeroes,&template_str);
569
570 target += s;
571
572 if ( i<(value.GetCount()-1) )
573 target += between;
574 }
575}
576
577bool wxArrayDoubleProperty::OnEvent( wxPropertyGrid* propgrid,
578 wxWindow* WXUNUSED(primary),
579 wxEvent& event)
580{
581 if ( propgrid->IsMainButtonEvent(event) )
582 {
1c4293cb 583 // Update the value in case of last minute changes
703ee9f5 584 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
9b5bafcf
JS
585
586 wxArrayDouble& value = wxArrayDoubleRefFromVariant(useValue);
1c4293cb
VZ
587
588 // Create editor dialog.
589 wxArrayDoubleEditorDialog dlg;
590 dlg.SetPrecision(m_precision);
591 dlg.Create( propgrid, wxEmptyString, m_label, value );
592 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
593
594 // Execute editor dialog
595 int res = dlg.ShowModal();
596 if ( res == wxID_OK && dlg.IsModified() )
597 {
0372d42e 598 SetValueInEvent( WXVARIANT(dlg.GetArray()) );
1c4293cb
VZ
599 return true;
600 }
601 return false;
602 }
603 return false;
604}
605
606bool wxArrayDoubleProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
607{
608 double tval;
609 wxString tstr;
610 // Add values to a temporary array so that in case
611 // of error we can opt not to use them.
612 wxArrayDouble new_array;
613
614 bool ok = true;
615
616 wxChar delimiter = m_delimiter;
617
618 WX_PG_TOKENIZER1_BEGIN(text,delimiter)
619
6636ef8d 620 if ( !token.empty() )
1c4293cb
VZ
621 {
622
623 // If token was invalid, exit the loop now
624 if ( !token.ToDouble(&tval) )
625 {
626 tstr.Printf ( _("\"%s\" is not a floating-point number."), token.c_str() );
627 ok = false;
628 break;
629 }
630 // TODO: Put validator code here
631
632 new_array.Add(tval);
633
634 }
635
636 WX_PG_TOKENIZER1_END()
637
638 // When invalid token found, show error message and don't change anything
639 if ( !ok )
640 {
641 //ShowError( tstr );
642 return false;
643 }
644
0372d42e 645 if ( !(wxArrayDoubleRefFromVariant(m_value) == new_array) )
1c4293cb 646 {
0372d42e 647 variant = WXVARIANT(new_array);
1c4293cb
VZ
648 return true;
649 }
650
651 return false;
652}
653
654bool wxArrayDoubleProperty::DoSetAttribute( const wxString& name, wxVariant& value )
655{
656 if ( name == wxPG_FLOAT_PRECISION )
657 {
658 m_precision = value.GetLong();
659 GenerateValueAsString( m_display, m_precision, true );
660 return true;
661 }
662 return false;
663}
664