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