]> git.saurik.com Git - wxWidgets.git/blame_incremental - docs/doxygen/overviews/propgrid.h
Eliminated WX_PG_DECLARE/IMPLEMENT_DERIVED_PROPERTY_CLASS
[wxWidgets.git] / docs / doxygen / overviews / propgrid.h
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: propgrid.h
3// Purpose: topic overview
4// Author: wxWidgets team
5// RCS-ID: $Id:
6// Licence: wxWindows license
7/////////////////////////////////////////////////////////////////////////////
8
9/**
10
11@page overview_propgrid wxPropertyGrid Overview
12
13Key Classes:
14@li wxPGProperty
15@li wxPropertyGrid
16@li wxPropertyGridEvent
17@li wxPropertyGridManager
18@li wxPropertyGridPage
19
20 wxPropertyGrid is a specialized grid for editing properties such as strings,
21numbers, flagsets, fonts, and colours. It is possible, for example, to categorize
22properties, set up a complete tree-hierarchy, add multiple columns, and set
23arbitrary per-property attributes.
24
25@li @ref propgrid_basics
26@li @ref propgrid_categories
27@li @ref propgrid_parentprops
28@li @ref propgrid_enumandflags
29@li @ref propgrid_advprops
30@li @ref propgrid_iterating
31@li @ref propgrid_operations
32@li @ref propgrid_events
33@li @ref propgrid_validating
34@li @ref propgrid_populating
35@li @ref propgrid_cellrender
36@li @ref propgrid_customizing
37@li @ref propgrid_usage2
38@li @ref propgrid_subclassing
39@li @ref propgrid_misc
40@li @ref propgrid_proplist
41@li @ref propgrid_userhelp
42@li @ref propgrid_notes
43@li @ref propgrid_newprops
44@li @ref propgrid_neweditors
45
46@section propgrid_basics Creating and Populating wxPropertyGrid
47
48As seen here, wxPropertyGrid is constructed in the same way as
49other wxWidgets controls:
50
51@code
52
53// Necessary header file
54#include <wx/propgrid/propgrid.h>
55
56...
57
58 // Assumes code is in frame/dialog constructor
59
60 // Construct wxPropertyGrid control
61 wxPropertyGrid* pg = new wxPropertyGrid(
62 this, // parent
63 PGID, // id
64 wxDefaultPosition, // position
65 wxDefaultSize, // size
66 // Here are just some of the supported window styles
67 wxPG_AUTO_SORT | // Automatic sorting after items added
68 wxPG_SPLITTER_AUTO_CENTER | // Automatically center splitter until user manually adjusts it
69 // Default style
70 wxPG_DEFAULT_STYLE );
71
72 // Window style flags are at premium, so some less often needed ones are
73 // available as extra window styles (wxPG_EX_xxx) which must be set using
74 // SetExtraStyle member function. wxPG_EX_HELP_AS_TOOLTIPS, for instance,
75 // allows displaying help strings as tooltips.
76 pg->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS );
77
78@endcode
79
80 (for complete list of new window styles, see @ref propgrid_window_styles)
81
82 wxPropertyGrid is usually populated with lines like this:
83
84@code
85 pg->Append( new wxStringProperty(wxT("Label"),wxT("Name"),wxT("Initial Value")) );
86@endcode
87
88Naturally, wxStringProperty is a property class. Only the first function argument (label)
89is mandatory. Second one, name, defaults to label and, third, the initial value, to
90default value. If constant wxPG_LABEL is used as the name argument, then the label is
91automatically used as a name as well (this is more efficient than manually defining both
92as the same). Use of empty name is discouraged and will sometimes result in run-time error.
93Note that all property class constructors have quite similar constructor argument list.
94
95To demonstrate other common property classes, here's another code snippet:
96
97@code
98
99 // Add int property
100 pg->Append( new wxIntProperty(wxT("IntProperty"), wxPG_LABEL, 12345678) );
101
102 // Add float property (value type is actually double)
103 pg->Append( new wxFloatProperty(wxT("FloatProperty"), wxPG_LABEL, 12345.678) );
104
105 // Add a bool property
106 pg->Append( new wxBoolProperty(wxT("BoolProperty"), wxPG_LABEL, false) );
107
108 // A string property that can be edited in a separate editor dialog.
109 pg->Append( new wxLongStringProperty(wxT("LongStringProperty"),
110 wxPG_LABEL,
111 wxT("This is much longer string than the ")
112 wxT("first one. Edit it by clicking the button.")));
113
114 // String editor with dir selector button.
115 pg->Append( new wxDirProperty(wxT("DirProperty"), wxPG_LABEL, ::wxGetUserHome()) );
116
117 // wxArrayStringProperty embeds a wxArrayString.
118 pg->Append( new wxArrayStringProperty(wxT("Label of ArrayStringProperty"),
119 wxT("NameOfArrayStringProp")));
120
121 // A file selector property.
122 pg->Append( new wxFileProperty(wxT("FileProperty"), wxPG_LABEL, wxEmptyString) );
123
124 // Extra: set wildcard for file property (format same as in wxFileDialog).
125 pg->SetPropertyAttribute( wxT("FileProperty"),
126 wxPG_FILE_WILDCARD,
127 wxT("All files (*.*)|*.*") );
128
129@endcode
130
131 Operations on properties should be done either via wxPropertyGrid's
132(or wxPropertyGridManager's) methods, or by acquiring pointer to a property
133(Append returns a wxPGProperty* or wxPGId, which is typedef for same), and then
134calling its method. Note however that property's methods generally do not
135automatically update grid graphics.
136
137 Property container functions operating on properties, such as SetPropertyValue or
138DisableProperty, all accept a special wxPGPropArg, argument which can automatically
139convert name of a property to a pointer. For instance:
140
141@code
142 // A file selector property.
143 wxPGPropety* p = pg->Append( new wxFileProperty(wxT("FileProperty"), wxPG_LABEL, wxEmptyString) );
144
145 // Valid: Set wildcard by name
146 pg->SetPropertyAttribute( wxT("FileProperty"),
147 wxPG_FILE_WILDCARD,
148 wxT("All files (*.*)|*.*") );
149
150 // Also Valid: Set wildcard by ptr
151 pg->SetPropertyAttribute( p,
152 wxPG_FILE_WILDCARD,
153 wxT("All files (*.*)|*.*") );
154@endcode
155
156Using pointer is faster, since it doesn't require hash map lookup. Anyway, you can allways
157get property pointer (wxPGProperty*) as Append/Insert return value, or by calling
158GetPropertyByName.
159
160 Below are samples for using some of the more commong operations. See
161wxPropertyGridInterface and wxPropertyGrid class references for complete list.
162
163@code
164
165 // wxPGId is a short-hand for wxPGProperty*. Let's use it this time.
166 wxPGId id = pg->GetPropertyByName( wxT("MyProperty") );
167
168 // There are many overloaded versions of this method, of which each accept
169 // different type of value.
170 pg->SetPropertyValue( wxT("MyProperty"), 200 );
171
172 // Setting a string works for all properties - conversion is done
173 // automatically.
174 pg->SetPropertyValue( id, wxT("400") );
175
176 // Getting property value as wxVariant.
177 wxVariant value = pg->GetPropertyValue( wxT("MyProperty") );
178
179 // Getting property value as String (again, works for all typs).
180 wxString value = pg->GetPropertyValueAsString( id );
181
182 // Getting property value as int. Provokes a run-time error
183 // if used with property which value type is not "long".
184 long value = pg->GetPropertyValueAsLong( wxT("MyProperty") );
185
186 // Set new name.
187 pg->SetPropertyName( wxT("MyProperty"), wxT("X") );
188
189 // Set new label - we need to use the new name.
190 pg->SetPropertyLabel( wxT("X"), wxT("New Label") );
191
192 // Disable the property. It's text will appear greyed.
193 // This is probably the closest you can get if you want
194 // a "read-only" property.
195 pg->DisableProperty( id );
196
197@endcode
198
199
200@section propgrid_categories Categories
201
202 wxPropertyGrid has a hierarchial property storage and display model, which
203allows property categories to hold child properties and even other
204categories. Other than that, from the programmer's point of view, categories
205can be treated exactly the same as "other" properties. For example, despite
206its name, GetPropertyByName also returns a category by name, and SetPropertyLabel
207also sets label of a category. Note however that sometimes the label of a
208property category may be referred as caption (for example, there is
209SetCaptionForegroundColour method that sets text colour of a property category's label).
210
211 When category is added at the top (i.e. root) level of the hierarchy,
212it becomes a *current category*. This means that all other (non-category)
213properties after it are automatically added to it. You may add
214properties to specific categories by using wxPropertyGrid::Insert or wxPropertyGrid::AppendIn.
215
216 Category code sample:
217
218@code
219
220 // One way to add category (similar to how other properties are added)
221 pg->Append( new wxPropertyCategory(wxT("Main")) );
222
223 // All these are added to "Main" category
224 pg->Append( new wxStringProperty(wxT("Name")) );
225 pg->Append( new wxIntProperty(wxT("Age"),wxPG_LABEL,25) );
226 pg->Append( new wxIntProperty(wxT("Height"),wxPG_LABEL,180) );
227 pg->Append( new wxIntProperty(wxT("Weight")) );
228
229 // Another one
230 pg->Append( new wxPropertyCategory(wxT("Attrikbutes")) );
231
232 // All these are added to "Attributes" category
233 pg->Append( new wxIntProperty(wxT("Intelligence")) );
234 pg->Append( new wxIntProperty(wxT("Agility")) );
235 pg->Append( new wxIntProperty(wxT("Strength")) );
236
237@endcode
238
239
240@section propgrid_parentprops Tree-like Property Structure
241
242 As a new feature in version 1.3.1, basicly any property can have children. There
243are few limitations, however.
244
245@remarks
246- Names of properties with non-category, non-root parents are not stored in hash map.
247 Instead, they can be accessed with strings like "Parent.Child". For instance, in
248 the sample below, child property named "Max. Speed (mph)" can be accessed by global
249 name "Car.Speeds.Max Speed (mph)".
250- If you want to property's value to be a string composed based on the values of
251 child properties, you must use wxStringProperty as parent and use value "<composed>".
252- Events (eg. change of value) that occur in parent do not propagate to children. Events
253 that occur in children will propagate to parents, but only if they are wxStringProperties
254 with "<composed>" value.
255- Old wxParentProperty class is deprecated, and remains as a typedef of wxStringProperty.
256 If you want old value behavior, you must specify "<composed>" as wxStringProperty's
257 value.
258
259Sample:
260
261@code
262 wxPGId pid = pg->Append( new wxStringProperty(wxT("Car"),wxPG_LABEL,wxT("<composed>")) );
263
264 pg->AppendIn( pid, new wxStringProperty(wxT("Model"),
265 wxPG_LABEL,
266 wxT("Lamborghini Diablo SV")) );
267
268 pg->AppendIn( pid, new wxIntProperty(wxT("Engine Size (cc)"),
269 wxPG_LABEL,
270 5707) );
271
272 wxPGId speedId = pg->AppendIn( pid, new wxStringProperty(wxT("Speeds"),wxPG_LABEL,wxT("<composed>")) );
273 pg->AppendIn( speedId, new wxIntProperty(wxT("Max. Speed (mph)"),wxPG_LABEL,290) );
274 pg->AppendIn( speedId, new wxFloatProperty(wxT("0-100 mph (sec)"),wxPG_LABEL,3.9) );
275 pg->AppendIn( speedId, new wxFloatProperty(wxT("1/4 mile (sec)"),wxPG_LABEL,8.6) );
276
277 // Make sure the child properties can be accessed correctly
278 pg->SetPropertyValue( wxT("Car.Speeds.Max. Speed (mph)"), 300 );
279
280 pg->AppendIn( pid, new wxIntProperty(wxT("Price ($)"),
281 wxPG_LABEL,
282 300000) );
283 // Displayed value of "Car" property is now:
284 // "Lamborghini Diablo SV; [300; 3.9; 8.6]; 300000"
285
286@endcode
287
288@section propgrid_enumandflags wxEnumProperty and wxFlagsProperty
289
290 wxEnumProperty is used when you want property's (integer or string) value
291to be selected from a popup list of choices.
292
293 Creating wxEnumProperty is more complex than those described earlier.
294You have to provide list of constant labels, and optionally relevant values
295(if label indexes are not sufficient).
296
297@remarks
298
299- Value wxPG_INVALID_VALUE (equals INT_MAX) is not allowed as list
300 item value.
301
302A very simple example:
303
304@code
305
306 //
307 // Using wxArrayString
308 //
309 wxArrayString arrDiet;
310 arr.Add(wxT("Herbivore"));
311 arr.Add(wxT("Carnivore"));
312 arr.Add(wxT("Omnivore"));
313
314 pg->Append( new wxEnumProperty(wxT("Diet"),
315 wxPG_LABEL,
316 arrDiet) );
317
318
319
320 //
321 // Using wxChar* array
322 //
323 const wxChar* arrayDiet[] =
324 { wxT("Herbivore"), wxT("Carnivore"), wxT("Omnivore"), NULL };
325
326 pg->Append( new wxEnumProperty(wxT("Diet"),
327 wxPG_LABEL,
328 arrayDiet) );
329
330
331@endcode
332
333Here's extended example using values as well:
334
335@code
336
337 //
338 // Using wxArrayString and wxArrayInt
339 //
340 wxArrayString arrDiet;
341 arr.Add(wxT("Herbivore"));
342 arr.Add(wxT("Carnivore"));
343 arr.Add(wxT("Omnivore"));
344
345 wxArrayInt arrIds;
346 arrIds.Add(40);
347 arrIds.Add(45);
348 arrIds.Add(50);
349
350 // Note that the initial value (the last argument) is the actual value,
351 // not index or anything like that. Thus, our value selects "Omnivore".
352 pg->Append( new wxEnumProperty(wxT("Diet"),
353 wxPG_LABEL,
354 arrDiet,
355 arrIds,
356 50));
357
358
359 //
360 // Using wxChar* and long arrays
361 //
362 const wxChar* array_diet[] =
363 { wxT("Herbivore"), wxT("Carnivore"), wxT("Omnivore"), NULL };
364
365 long array_diet_ids[] =
366 { 40, 45, 50 };
367
368 pg->Append( new wxEnumProperty(wxT("Diet"),
369 wxPG_LABEL,
370 array_diet,
371 array_diet_ids);
372
373@endcode
374
375 wxPGChoices is a class where wxEnumProperty, and other properties which
376 require label storage, actually stores strings and values. It is used
377 to facilitiate reference counting, and therefore recommended way of
378 adding items when multiple properties share the same set.
379
380 You can use wxPGChoices directly as well, filling it and then passing it
381 to the constructor. Infact, if you wish to display bitmaps next to labels,
382 your best choice is to use this approach.
383
384@code
385
386 wxPGChoices chs;
387 chs.Add(wxT("Herbivore"),40);
388 chs.Add(wxT("Carnivore"),45);
389 chs.Add(wxT("Omnivore"),50);
390
391 // Let's add an item with bitmap, too
392 chs.Add(wxT("None of the above"), wxBitmap(), 60);
393
394 // Note: you can add even whole arrays to wxPGChoices
395
396 pg->Append( new wxEnumProperty(wxT("Primary Diet"),
397 wxPG_LABEL,
398 chs) );
399
400 // Add same choices to another property as well - this is efficient due
401 // to reference counting
402 pg->Append( new wxEnumProperty(wxT("Secondary Diet"),
403 wxPG_LABEL,
404 chs) );
405
406@endcode
407
408You can later change choices of property by using wxPGProperty::InsertChoice(),
409wxPGProperty::DeleteChoice(), and wxPGProperty::SetChoices().
410
411<b>wxEditEnumProperty</b> is works exactly like wxEnumProperty, except
412is uses non-readonly combobox as default editor, and value is stored as
413string when it is not any of the choices.
414
415wxFlagsProperty has similar construction:
416
417@code
418
419 const wxChar* flags_prop_labels[] = { wxT("wxICONIZE"),
420 wxT("wxCAPTION"), wxT("wxMINIMIZE_BOX"), wxT("wxMAXIMIZE_BOX"), NULL };
421
422 // this value array would be optional if values matched string indexes
423 long flags_prop_values[] = { wxICONIZE, wxCAPTION, wxMINIMIZE_BOX,
424 wxMAXIMIZE_BOX };
425
426 pg->Append( new wxFlagsProperty(wxT("Window Style"),
427 wxPG_LABEL,
428 flags_prop_labels,
429 flags_prop_values,
430 wxDEFAULT_FRAME_STYLE) );
431
432@endcode
433
434wxFlagsProperty can use wxPGChoices just the same way as wxEnumProperty
435(and also custom property classes can be created with similar macro pairs).
436<b>Note: </b> When changing "choices" (ie. flag labels) of wxFlagsProperty,
437you will need to use wxPGProperty::SetChoices() to replace all choices
438at once - otherwise they will not get updated properly.
439
440@section propgrid_advprops Specialized Properties
441
442 This section describes the use of less often needed property classes.
443To use them, you have to include <wx/propgrid/advprops.h>.
444
445@code
446
447// Necessary extra header file
448#include <wx/propgrid/advprops.h>
449
450...
451
452 // Date property.
453 pg->Append( new wxDateProperty(wxT("MyDateProperty"),
454 wxPG_LABEL,
455 wxDateTime::Now()) );
456
457 // Image file property. Wildcard is auto-generated from available
458 // image handlers, so it is not set this time.
459 pg->Append( new wxImageFileProperty(wxT("Label of ImageFileProperty"),
460 wxT("NameOfImageFileProp")) );
461
462 // Font property has sub-properties. Note that we give window's font as
463 // initial value.
464 pg->Append( new wxFontProperty(wxT("Font"),
465 wxPG_LABEL,
466 GetFont()) );
467
468 // Colour property with arbitrary colour.
469 pg->Append( new wxColourProperty(wxT("My Colour 1"),
470 wxPG_LABEL,
471 wxColour(242,109,0) ) );
472
473 // System colour property.
474 pg->Append( new wxSystemColourProperty(wxT("My SysColour 1"),
475 wxPG_LABEL,
476 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) );
477
478 // System colour property with custom colour.
479 pg->Append( new wxSystemColourProperty(wxT("My SysColour 2"),
480 wxPG_LABEL,
481 wxColour(0,200,160) ) );
482
483 // Cursor property
484 pg->Append( new wxCursorProperty(wxT("My Cursor"),
485 wxPG_LABEL,
486 wxCURSOR_ARROW));
487
488@endcode
489
490
491@section propgrid_iterating Iterating through a property container
492
493You can use somewhat STL'ish iterator classes to iterate through the grid.
494Here is a simple example of forward iterating through all individual
495properties (not categories or sub-propeties that are normally 'transparent'
496to application code):
497
498@code
499
500 wxPropertyGridIterator it;
501
502 for ( it = pg->GetIterator();
503 !it.AtEnd();
504 it++ )
505 {
506 wxPGProperty* p = *it;
507 // Do something with the property
508 }
509
510@endcode
511
512As expected there is also a const iterator:
513
514@code
515
516 wxPropertyGridConstIterator it;
517
518 for ( it = pg->GetIterator();
519 !it.AtEnd();
520 it++ )
521 {
522 const wxPGProperty* p = *it;
523 // Do something with the property
524 }
525
526@endcode
527
528You can give some arguments to GetIterator to determine which properties
529get automatically filtered out. For complete list of options, see
530@ref propgrid_iterator_flags. GetIterator() also accepts other arguments.
531See wxPropertyGridInterface::GetIterator() for details.
532
533This example reverse-iterates through all visible items:
534
535@code
536
537 wxPropertyGridIterator it;
538
539 for ( it = pg->GetIterator(wxPG_ITERATE_VISIBLE, wxBOTTOM);
540 !it.AtEnd();
541 it-- )
542 {
543 wxPGProperty* p = *it;
544 // Do something with the property
545 }
546
547@endcode
548
549<b>wxPython Note:</b> Instead of ++ operator, use Next() method, and instead of
550* operator, use GetProperty() method.
551
552GetIterator() only works with wxPropertyGrid and the individual pages
553of wxPropertyGridManager. In order to iterate through an arbitrary
554property container, you need to use wxPropertyGridInterface::GetVIterator().
555Note however that this virtual iterater is limited to forward iteration.
556
557@code
558
559 wxPGVIterator it;
560
561 for ( it = manager->GetVIterator();
562 !it.AtEnd();
563 it.Next() )
564 {
565 wxPGProperty* p = it.GetProperty();
566 // Do something with the property
567 }
568
569@endcode
570
571
572@section propgrid_operations More About Operating with Properties
573
574Getting value of selected wxSystemColourProperty (which value type is derived
575from wxObject):
576
577@code
578
579 wxPGId id = pg->GetSelection();
580
581 if ( id )
582 {
583 // Get name of property
584 const wxString& name = pg->GetPropertyName( id );
585
586 // If type is not correct, GetColour() method will produce run-time error
587 if ( pg->GetPropertyValueType() == wxT("wxColourPropertyValue") ) )
588 {
589 wxColourPropertyValue* pcolval =
590 wxDynamicCast(pg->GetPropertyValueAsWxObjectPtr(id),
591 wxColourPropertyValue);
592
593 // Report value
594 wxString text;
595 if ( pcolval->m_type == wxPG_CUSTOM_COLOUR )
596 text.Printf( wxT("It is custom colour: (%i,%i,%i)"),
597 (int)pcolval->m_colour.Red(),
598 (int)pcolval->m_colour.Green(),
599 (int)pcolval->m_colour.Blue());
600 else
601 text.Printf( wxT("It is wx system colour (number=%i): (%i,%i,%i)"),
602 (int)pcolval->m_type,
603 (int)pcolval->m_colour.Red(),
604 (int)pcolval->m_colour.Green(),
605 (int)pcolval->m_colour.Blue());
606
607 wxMessageBox( text );
608 }
609 }
610
611@endcode
612
613@section propgrid_populating Populating wxPropertyGrid Automatically
614
615@subsection propgrid_fromvariants Populating from List of wxVariants
616
617Example of populating an empty wxPropertyGrid from a values stored
618in an arbitrary list of wxVariants.
619
620@code
621
622 // This is a static method that initializes *all* builtin type handlers
623 // available, including those for wxColour and wxFont. Refers to *all*
624 // included properties, so when compiling with static library, this
625 // method may increase the executable size significantly.
626 pg->InitAllTypeHandlers();
627
628 // Get contents of the grid as a wxVariant list
629 wxVariant all_values = pg->GetPropertyValues();
630
631 // Populate the list with values. If a property with appropriate
632 // name is not found, it is created according to the type of variant.
633 pg->SetPropertyValues( my_list_variant );
634
635 // In order to get wxObject ptr from a variant value,
636 // wxGetVariantCast(VARIANT,CLASSNAME) macro has to be called.
637 // Like this:
638 wxVariant v_txcol = pg->GetPropertyValue(wxT("Text Colour"));
639 const wxColour& txcol = wxGetVariantCast(v_txcol,wxColour);
640
641@endcode
642
643@subsection propgrid_fromfile Loading Population from a Text-based Storage
644
645Class wxPropertyGridPopulator may be helpful when writing code that
646loads properties from a text-source. In fact, the supplied xrc handler
647(src/xh_propgrid.cpp) uses it. See that code for more info.
648NOTE: src/xh_propgrid.cpp is not included in the library by default,
649to avoid dependency to wxXRC. You will need to add it to your application
650separately.
651
652@subsection propgrid_editablestate Saving and Restoring User-Editable State
653
654You can use wxPGEditableState and wxPGMEditableState classes, and
655wxPropertyGrid::SaveEditableState() and wxPropertyGrid::RestoreEditableState()
656to save and restore user-editable state (selected property, expanded/
657collapsed properties, and scrolled position). For convience with
658program configuration, wxPGEditableState has functions to save/load
659its value in wxString. For instance:
660
661@code
662 // Save state into config
663 wxPGEditableState edState;
664 pg->SaveEditableState(&edState);
665 programConfig->Store(wxT("PropertyGridState"), edState.GetAsString());
666
667 // Restore state from config
668 wxPGEditableState edState;
669 edState.SetFromString(programConfig->Load(wxT("PropertyGridState")));
670 pg->RestoreEditableState(edState);
671@endcode
672
673
674@section propgrid_events Event Handling
675
676Probably the most important event is the Changed event which occurs when
677value of any property is changed by the user. Use EVT_PG_CHANGED(id,func)
678in your event table to use it.
679
680For complete list of event types, see wxPropertyGrid class reference.
681
682The custom event class, wxPropertyGridEvent, has methods to directly
683access the property that triggered the event.
684
685Here's a small sample:
686
687@code
688
689// Portion of an imaginary event table
690BEGIN_EVENT_TABLE(MyForm, wxFrame)
691
692 ...
693
694 // This occurs when a property value changes
695 EVT_PG_CHANGED( PGID, MyForm::OnPropertyGridChange )
696
697 ...
698
699END_EVENT_TABLE()
700
701void MyForm::OnPropertyGridChange( wxPropertyGridEvent& event )
702{
703 wxPGProperty *property = event.GetProperty();
704
705 // It may be NULL
706 if ( !property )
707 return;
708
709 // Get name of changed property
710 const wxString& name = property->GetName();
711
712 // Get resulting value
713 wxVariant value = property->GetValue();
714}
715
716@endcode
717
718Another event type you might find useful is EVT_PG_CHANGING, which occurs
719just prior property value is being changed by user. You can acquire pending
720value using wxPropertyGridEvent::GetValue(), and if it is not acceptable,
721call wxPropertyGridEvent::Veto() to prevent the value change from taking
722place.
723
724@code
725
726// Portion of an imaginary event table
727BEGIN_EVENT_TABLE(MyForm, wxFrame)
728
729 ...
730
731 // This occurs when a property value changes
732 EVT_PG_CHANGING( PGID, MyForm::OnPropertyGridChanging )
733
734 ...
735
736END_EVENT_TABLE()
737
738void MyForm::OnPropertyGridChanging( wxPropertyGridEvent& event )
739{
740 wxPGProperty* property = event.GetProperty();
741
742 if ( property == m_pWatchThisProperty )
743 {
744 // GetValue() returns the pending value, but is only
745 // supported by wxEVT_PG_CHANGING.
746 if ( event.GetValue().GetString() == g_pThisTextIsNotAllowed )
747 {
748 event.Veto();
749 return;
750 }
751 }
752}
753
754@endcode
755
756@remarks On Sub-property Event Handling
757- For aggregate type properties (wxFontProperty, wxFlagsProperty, etc), events
758 occur for the main parent property only. For other properties events occur
759 for the children themselves..
760
761- When property's child gets changed, you can use wxPropertyGridEvent::GetMainParent
762 to obtain its topmost non-category parent (useful, if you have deeply nested
763 properties).
764
765
766@section propgrid_validating Validating Property Values
767
768There are various ways to make sure user enters only correct values. First, you
769can use wxValidators similar to as you would with ordinary controls. Use
770wxPropertyGridInterface::SetPropertyValidator() to assign wxValidator to
771property.
772
773Second, you can subclass a property and override wxPGProperty::ValidateValue(),
774or handle wxEVT_PG_CHANGING for the same effect. Both of these methods do not
775actually prevent user from temporarily entering invalid text, but they do give
776you an opportunity to warn the user and block changed value from being committed
777in a property.
778
779Various validation failure options can be controlled globally with
780wxPropertyGrid::SetValidationFailureBehavior(), or on an event basis by
781calling wxEvent::SetValidationFailureBehavior(). Here's a code snippet of
782how to handle wxEVT_PG_CHANGING, and to set custom failure behaviour and
783message.
784
785@code
786 void MyFrame::OnPropertyGridChanging(wxPropertyGridEvent& event)
787 {
788 wxPGProperty* property = event.GetProperty();
789
790 // You must use wxPropertyGridEvent::GetValue() to access
791 // the value to be validated.
792 wxVariant pendingValue = event.GetValue();
793
794 if ( property->GetName() == wxT("Font") )
795 {
796 // Make sure value is not unspecified
797 if ( !pendingValue.IsNull() )
798 {
799 wxFont font << pendingValue;
800
801 // Let's just allow Arial font
802 if ( font.GetFaceName() != wxT("Arial") )
803 {
804 event.Veto();
805 event.SetValidationFailureBehavior(wxPG_VFB_STAY_IN_PROPERTY |
806 wxPG_VFB_BEEP |
807 wxPG_VFB_SHOW_MESSAGE);
808 }
809 }
810 }
811 }
812@endcode
813
814
815@section propgrid_cellrender Customizing Individual Cell Appearance
816
817You can control text colour, background colour, and attached image of
818each cell in the property grid. Use wxPropertyGridInterface::SetPropertyCell() or
819wxPGProperty::SetCell() for this purpose.
820
821In addition, it is possible to control these characteristics for
822wxPGChoices list items. See wxPGChoices class
823reference for more info.
824
825
826@section propgrid_customizing Customizing Properties (without sub-classing)
827
828In this section are presented miscellaneous ways to have custom appearance
829and behavior for your properties without all the necessary hassle
830of sub-classing a property class etc.
831
832@subsection propgrid_customimage Setting Value Image
833
834Every property can have a small value image placed in front of the
835actual value text. Built-in example of this can be seen with
836wxColourProperty and wxImageFileProperty, but for others it can
837be set using wxPropertyGrid::SetPropertyImage method.
838
839@subsection propgrid_customvalidator Setting Validator
840
841You can set wxValidator for a property using wxPropertyGrid::SetPropertyValidator.
842
843Validator will work just like in wxWidgets (ie. editorControl->SetValidator(validator)
844is called).
845
846@subsection propgrid_customeditor Setting Property's Editor Control(s)
847
848You can set editor control (or controls, in case of a control and button),
849of any property using wxPropertyGrid::SetPropertyEditor. Editors are passed
850using wxPG_EDITOR(EditorName) macro, and valid built-in EditorNames are
851TextCtrl, Choice, ComboBox, CheckBox, TextCtrlAndButton, ChoiceAndButton,
852SpinCtrl, and DatePickerCtrl. Two last mentioned ones require call to
853static member function wxPropertyGrid::RegisterAdditionalEditors().
854
855Following example changes wxColourProperty's editor from default Choice
856to TextCtrlAndButton. wxColourProperty has its internal event handling set
857up so that button click events of the button will be used to trigger
858colour selection dialog.
859
860@code
861
862 wxPGId colProp = pg->Append(wxColourProperty(wxT("Text Colour")));
863
864 pg->SetPropertyEditor(colProp,wxPG_EDITOR(TextCtrlAndButton));
865
866@endcode
867
868Naturally, creating and setting custom editor classes is a possibility as
869well. For more information, see wxPGEditor class reference.
870
871@subsection propgrid_editorattrs Property Attributes Recognized by Editors
872
873<b>SpinCtrl</b> editor can make use of property's "Min", "Max", "Step" and "Wrap" attributes.
874
875@subsection propgrid_multiplebuttons Adding Multiple Buttons Next to an Editor
876
877See wxPGMultiButton class reference.
878
879@subsection propgrid_customeventhandling Handling Events Passed from Properties
880
881<b>wxEVT_COMMAND_BUTTON_CLICKED </b>(corresponds to event table macro EVT_BUTTON):
882Occurs when editor button click is not handled by the property itself
883(as is the case, for example, if you set property's editor to TextCtrlAndButton
884from the original TextCtrl).
885
886@subsection propgrid_attributes Property Attributes
887
888Miscellaneous values, often specific to a property type, can be set
889using wxPropertyGrid::SetPropertyAttribute and wxPropertyGrid::SetPropertyAttributeAll
890methods.
891
892Attribute names are strings and values wxVariant. Arbitrary names are allowed
893inorder to store user values. Constant equivalents of all attribute string names are
894provided. Some of them are defined as cached strings, so using constants can provide
895for smaller binary size.
896
897For complete list of attributes, see @ref propgrid_property_attributes.
898
899@subsection propgrid_boolcheckbox Setting wxBoolProperties to Use Check Box
900
901To have all wxBoolProperties to use CheckBox editor instead of Choice, use
902following (call after bool properties have been added):
903
904@code
905 pg->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX,true);
906@endcode
907
908
909@section propgrid_usage2 Using wxPropertyGridManager
910
911wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid,
912which can optionally have toolbar for mode and page selection, and a help text
913box.
914
915wxPropertyGridManager inherits from wxPropertyGridInterface, and as such
916it has most property manipulation functions. However, only some of them affect
917properties on all pages (eg. GetPropertyByName() and ExpandAll()), while some
918(eg. Append()) only apply to the currently selected page.
919
920To operate explicitly on properties on specific page, use wxPropertyGridManager::GetPage()
921to obtain pointer to page's wxPropertyGridPage object.
922
923Visual methods, such as SetCellBackgroundColour and GetNextVisible are only
924available in wxPropertyGrid. Use wxPropertyGridManager::GetGrid() to obtain
925pointer to it.
926
927Iteration methods will not work in wxPropertyGridManager. Instead, you must acquire
928the internal grid (GetGrid()) or wxPropertyGridPage object (GetPage()).
929
930wxPropertyGridManager constructor has exact same format as wxPropertyGrid
931constructor, and basicly accepts same extra window style flags (albeit also
932has some extra ones).
933
934Here's some example code for creating and populating a wxPropertyGridManager:
935
936@code
937
938 wxPropertyGridManager* pgMan = new wxPropertyGridManager(this, PGID,
939 wxDefaultPosition, wxDefaultSize,
940 // These and other similar styles are automatically
941 // passed to the embedded wxPropertyGrid.
942 wxPG_BOLD_MODIFIED|wxPG_SPLITTER_AUTO_CENTER|
943 // Include toolbar.
944 wxPG_TOOLBAR |
945 // Include description box.
946 wxPG_DESCRIPTION |
947 // Include compactor.
948 wxPG_COMPACTOR |
949 // Plus defaults.
950 wxPGMAN_DEFAULT_STYLE
951 );
952
953 wxPropertyGridPage* page;
954
955 // Adding a page sets target page to the one added, so
956 // we don't have to call SetTargetPage if we are filling
957 // it right after adding.
958 pgMan->AddPage(wxT("First Page"));
959 page = pgMan->GetLastPage();
960
961 page->Append( new wxPropertyCategory(wxT("Category A1")) );
962
963 page->Append( new wxIntProperty(wxT("Number"),wxPG_LABEL,1) );
964
965 page->Append( new wxColourProperty(wxT("Colour"),wxPG_LABEL,*wxWHITE) );
966
967 pgMan->AddPage(wxT("Second Page"));
968 page = pgMan->GetLastPage();
969
970 page->Append( wxT("Text"),wxPG_LABEL,wxT("(no text)") );
971
972 page->Append( new wxFontProperty(wxT("Font"),wxPG_LABEL) );
973
974@endcode
975
976@subsection propgrid_propgridpage wxPropertyGridPage
977
978wxPropertyGridPage is holder of properties for one page in manager. It is derived from
979wxEvtHandler, so you can subclass it to process page-specific property grid events. Hand
980over your page instance in wxPropertyGridManager::AddPage.
981
982Please note that the wxPropertyGridPage itself only sports subset of wxPropertyGrid API
983(but unlike manager, this include item iteration). Naturally it inherits from
984wxPropertyGridMethods and wxPropertyGridPageState.
985
986
987@section propgrid_subclassing Subclassing wxPropertyGrid and wxPropertyGridManager
988
989Few things to note:
990
991- Only a small percentage of member functions are virtual. If you need more,
992 just e-mail to wx-dev mailing list.
993
994- Data manipulation is done in wxPropertyGridPageState class. So, instead of
995 overriding wxPropertyGrid::Insert, you'll probably want to override wxPropertyGridPageState::DoInsert.
996
997- Override wxPropertyGrid::CreateState to instantiate your derivate wxPropertyGridPageState.
998 For wxPropertyGridManager, you'll need to subclass wxPropertyGridPage instead (since it
999 is derived from wxPropertyGridPageState), and hand over instances in wxPropertyGridManager::AddPage
1000 calls.
1001
1002- You can use a derivate wxPropertyGrid with manager by overriding wxPropertyGridManager::CreatePropertyGrid
1003 member function.
1004
1005
1006@section propgrid_misc Miscellaneous Topics
1007
1008@subsection propgrid_namescope Property Name Scope
1009
1010 All properties which parent is category or root can be accessed
1011directly by their base name (ie. name given for property in its constructor).
1012Other properties can be accessed via "ParentsName.BaseName" notation,
1013Naturally, all property names should be unique.
1014
1015@subsection propgrid_nonuniquelabels Non-unique Labels
1016
1017 It is possible to have properties with identical label under same parent.
1018However, care must be taken to ensure that each property still has
1019unique (base) name.
1020
1021@subsection propgrid_boolproperty wxBoolProperty
1022
1023 There are few points about wxBoolProperty that require futher discussion:
1024 - wxBoolProperty can be shown as either normal combobox or as a checkbox.
1025 Property attribute wxPG_BOOL_USE_CHECKBOX is used to change this.
1026 For example, if you have a wxFlagsProperty, you can
1027 set its all items to use check box using the following:
1028 @code
1029 pg->SetPropertyAttribute(wxT("MyFlagsProperty"),wxPG_BOOL_USE_CHECKBOX,true,wxPG_RECURSE);
1030 @endcode
1031
1032 - Default item names for wxBoolProperty are ["False", "True"]. This can be
1033 changed using wxPropertyGrid::SetBoolChoices(trueChoice, falseChoice).
1034
1035@subsection propgrid_textctrlupdates Updates from wxTextCtrl Based Editor
1036
1037 Changes from wxTextCtrl based property editors are committed (ie.
1038wxEVT_PG_CHANGED is sent etc.) *only* when (1) user presser enter, (2)
1039user moves to edit another property, or (3) when focus leaves
1040the grid.
1041
1042 Because of this, you may find it useful, in some apps, to call
1043wxPropertyGrid::CommitChangesFromEditor() just before you need to do any
1044computations based on property grid values. Note that CommitChangesFromEditor()
1045will dispatch wxEVT_PG_CHANGED with ProcessEvent, so any of your event handlers
1046will be called immediately.
1047
1048@subsection propgrid_splittercentering Centering the Splitter
1049
1050 If you need to center the splitter, but only once when the program starts,
1051then do <b>not</b> use the wxPG_SPLITTER_AUTO_CENTER window style, but the
1052wxPropertyGrid::CenterSplitter() method. <b>However, be sure to call it after
1053the sizer setup and SetSize calls!</b> (ie. usually at the end of the
1054frame/dialog constructor)
1055
1056@subsection propgrid_splittersetting Setting Splitter Position When Creating Property Grid
1057
1058Splitter position cannot exceed grid size, and therefore setting it during
1059form creation may fail as initial grid size is often smaller than desired
1060splitter position, especially when sizers are being used.
1061
1062@subsection propgrid_colourproperty wxColourProperty and wxSystemColourProperty
1063
1064Through subclassing, these two property classes provide substantial customization
1065features. Subclass wxSystemColourProperty if you want to use wxColourPropertyValue
1066(which features colour type in addition to wxColour), and wxColourProperty if plain
1067wxColour is enough.
1068
1069Override wxSystemColourProperty::ColourToString() to redefine how colours are
1070printed as strings.
1071
1072Override wxSystemColourProperty::GetCustomColourIndex() to redefine location of
1073the item that triggers colour picker dialog (default is last).
1074
1075Override wxSystemColourProperty::GetColour() to determine which colour matches
1076which choice entry.
1077
1078@section propgrid_proplist Property Class Descriptions
1079
1080See @ref pgproperty_properties
1081
1082*/
1083