]> git.saurik.com Git - wxWidgets.git/blob - docs/doxygen/overviews/propgrid.h
use #defines, not typedefs, for compatibility class names declarations to avoid break...
[wxWidgets.git] / docs / doxygen / overviews / propgrid.h
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
13 Key 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,
21 numbers, flagsets, fonts, and colours. It is possible, for example, to categorize
22 properties, set up a complete tree-hierarchy, add multiple columns, and set
23 arbitrary 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
48 As seen here, wxPropertyGrid is constructed in the same way as
49 other 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: @link wndflags Additional Window Styles@endlink)
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
88 Naturally, wxStringProperty is a property class. Only the first function argument (label)
89 is mandatory. Second one, name, defaults to label and, third, the initial value, to
90 default value. If constant wxPG_LABEL is used as the name argument, then the label is
91 automatically used as a name as well (this is more efficient than manually defining both
92 as the same). Use of empty name is discouraged and will sometimes result in run-time error.
93 Note that all property class constructors have quite similar constructor argument list.
94
95 To 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
134 calling its method. Note however that property's methods generally do not
135 automatically update grid graphics.
136
137 Property container functions operating on properties, such as SetPropertyValue or
138 DisableProperty, all accept a special wxPGPropArg, argument which can automatically
139 convert 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
156 Using pointer is faster, since it doesn't require hash map lookup. Anyway, you can allways
157 get property pointer (wxPGProperty*) as Append/Insert return value, or by calling
158 GetPropertyByName.
159
160 Below are samples for using some of the more commong operations. See
161 wxPropertyGridInterface 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
203 allows property categories to hold child properties and even other
204 categories. Other than that, from the programmer's point of view, categories
205 can be treated exactly the same as "other" properties. For example, despite
206 its name, GetPropertyByName also returns a category by name, and SetPropertyLabel
207 also sets label of a category. Note however that sometimes the label of a
208 property category may be referred as caption (for example, there is
209 SetCaptionForegroundColour 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,
212 it becomes a *current category*. This means that all other (non-category)
213 properties after it are automatically added to it. You may add
214 properties 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
243 are 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
259 Sample:
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
291 to be selected from a popup list of choices.
292
293 Creating wxEnumProperty is more complex than those described earlier.
294 You 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 2147483647 which usually equals INT_MAX) is not
300 allowed as value.
301
302 A 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
333 Here'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 // Value can be set from string as well
369 pg->Append( new wxEnumProperty(wxT("Diet"),
370 wxPG_LABEL,
371 array_diet,
372 array_diet_ids);
373
374 @endcode
375
376 wxPGChoices is a class where wxEnumProperty, and other properties which
377 require label storage, actually stores strings and values. It is used
378 to facilitiate reference counting, and therefore recommended way of
379 adding items when multiple properties share the same set.
380
381 You can use wxPGChoices directly as well, filling it and then passing it
382 to the constructor. Infact, if you wish to display bitmaps next to labels,
383 your best choice is to use this approach.
384
385 @code
386
387 wxPGChoices chs;
388 chs.Add(wxT("Herbivore"),40);
389 chs.Add(wxT("Carnivore"),45);
390 chs.Add(wxT("Omnivore"),50);
391
392 // Let's add an item with bitmap, too
393 chs.Add(wxT("None of the above"), wxBitmap(), 60);
394
395 // Note: you can add even whole arrays to wxPGChoices
396
397 pg->Append( new wxEnumProperty(wxT("Diet"),
398 wxPG_LABEL,
399 chs) );
400
401 // Add same choices to another property as well - this is efficient due
402 // to reference counting
403 pg->Append( new wxEnumProperty(wxT("Diet 2"),
404 wxPG_LABEL,
405 chs) );
406
407 @endcode
408
409 If you later need to change choices used by a property, there is function
410 for that as well.
411
412 @code
413
414 //
415 // Example 1: Add one extra item
416 wxPGChoices& choices = pg->GetPropertyChoices(wxT("Diet"));
417 choices.Add(wxT("Custom"),55);
418
419 //
420 // Example 2: Replace all the choices
421 wxPGChoices chs;
422 chs.Add(wxT("<No valid items yet>"),0);
423 pg->SetPropertyChoices(wxT("Diet"),chs);
424
425 @endcode
426
427 If you want to create your enum properties with simple (label,name,value)
428 constructor, then you need to create a new property class using one of the
429 supplied macro pairs. See @ref pgproperty_creating for details.
430
431 <b>wxEditEnumProperty</b> is works exactly like wxEnumProperty, except
432 is uses non-readonly combobox as default editor, and value is stored as
433 string when it is not any of the choices.
434
435 wxFlagsProperty is similar:
436
437 @code
438
439 const wxChar* flags_prop_labels[] = { wxT("wxICONIZE"),
440 wxT("wxCAPTION"), wxT("wxMINIMIZE_BOX"), wxT("wxMAXIMIZE_BOX"), NULL };
441
442 // this value array would be optional if values matched string indexes
443 long flags_prop_values[] = { wxICONIZE, wxCAPTION, wxMINIMIZE_BOX,
444 wxMAXIMIZE_BOX };
445
446 pg->Append( new wxFlagsProperty(wxT("Window Style"),
447 wxPG_LABEL,
448 flags_prop_labels,
449 flags_prop_values,
450 wxDEFAULT_FRAME_STYLE) );
451
452 @endcode
453
454 wxFlagsProperty can use wxPGChoices just the same way as wxEnumProperty
455 (and also custom property classes can be created with similar macro pairs).
456 <b>Note: </b> When changing "choices" (ie. flag labels) of wxFlagsProperty,
457 you will need to use SetPropertyChoices - otherwise they will not get updated
458 properly.
459
460 @section propgrid_advprops Specialized Properties
461
462 This section describes the use of less often needed property classes.
463 To use them, you have to include <wx/propgrid/advprops.h>.
464
465 @code
466
467 // Necessary extra header file
468 #include <wx/propgrid/advprops.h>
469
470 ...
471
472 // Date property.
473 pg->Append( new wxDateProperty(wxT("MyDateProperty"),
474 wxPG_LABEL,
475 wxDateTime::Now()) );
476
477 // Image file property. Wildcard is auto-generated from available
478 // image handlers, so it is not set this time.
479 pg->Append( new wxImageFileProperty(wxT("Label of ImageFileProperty"),
480 wxT("NameOfImageFileProp")) );
481
482 // Font property has sub-properties. Note that we give window's font as
483 // initial value.
484 pg->Append( new wxFontProperty(wxT("Font"),
485 wxPG_LABEL,
486 GetFont()) );
487
488 // Colour property with arbitrary colour.
489 pg->Append( new wxColourProperty(wxT("My Colour 1"),
490 wxPG_LABEL,
491 wxColour(242,109,0) ) );
492
493 // System colour property.
494 pg->Append( new wxSystemColourProperty(wxT("My SysColour 1"),
495 wxPG_LABEL,
496 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) );
497
498 // System colour property with custom colour.
499 pg->Append( new wxSystemColourProperty(wxT("My SysColour 2"),
500 wxPG_LABEL,
501 wxColour(0,200,160) ) );
502
503 // Cursor property
504 pg->Append( new wxCursorProperty(wxT("My Cursor"),
505 wxPG_LABEL,
506 wxCURSOR_ARROW));
507
508 @endcode
509
510
511 @section propgrid_iterating Iterating through a property container
512
513 You can use somewhat STL'ish iterator classes to iterate through the grid.
514 Here is a simple example of forward iterating through all individual
515 properties (not categories or sub-propeties that are normally 'transparent'
516 to application code):
517
518 @code
519
520 wxPropertyGridIterator it;
521
522 for ( it = pg->GetIterator();
523 !it.AtEnd();
524 it++ )
525 {
526 wxPGProperty* p = *it;
527 // Do something with the property
528 }
529
530 @endcode
531
532 As expected there is also a const iterator:
533
534 @code
535
536 wxPropertyGridConstIterator it;
537
538 for ( it = pg->GetIterator();
539 !it.AtEnd();
540 it++ )
541 {
542 const wxPGProperty* p = *it;
543 // Do something with the property
544 }
545
546 @endcode
547
548 You can give some arguments to GetIterator to determine which properties
549 get automatically filtered out. For complete list of options, see
550 @link iteratorflags List of Property Iterator Flags@endlink. GetIterator()
551 also accepts other arguments. See wxPropertyGridInterface::GetIterator()
552 for details.
553
554 This example reverse-iterates through all visible items:
555
556 @code
557
558 wxPropertyGridIterator it;
559
560 for ( it = pg->GetIterator(wxPG_ITERATE_VISIBLE, wxBOTTOM);
561 !it.AtEnd();
562 it-- )
563 {
564 wxPGProperty* p = *it;
565 // Do something with the property
566 }
567
568 @endcode
569
570 <b>wxPython Note:</b> Instead of ++ operator, use Next() method, and instead of
571 * operator, use GetProperty() method.
572
573 GetIterator() only works with wxPropertyGrid and the individual pages
574 of wxPropertyGridManager. In order to iterate through an arbitrary
575 property container, you need to use wxPropertyGridInterface::GetVIterator().
576 Note however that this virtual iterater is limited to forward iteration.
577
578 @code
579
580 wxPGVIterator it;
581
582 for ( it = manager->GetVIterator();
583 !it.AtEnd();
584 it.Next() )
585 {
586 wxPGProperty* p = it.GetProperty();
587 // Do something with the property
588 }
589
590 @endcode
591
592
593 @section propgrid_operations More About Operating with Properties
594
595 Getting value of selected wxSystemColourProperty (which value type is derived
596 from wxObject):
597
598 @code
599
600 wxPGId id = pg->GetSelection();
601
602 if ( id )
603 {
604 // Get name of property
605 const wxString& name = pg->GetPropertyName( id );
606
607 // If type is not correct, GetColour() method will produce run-time error
608 if ( pg->GetPropertyValueType() == wxT("wxColourPropertyValue") ) )
609 {
610 wxColourPropertyValue* pcolval =
611 wxDynamicCast(pg->GetPropertyValueAsWxObjectPtr(id),
612 wxColourPropertyValue);
613
614 // Report value
615 wxString text;
616 if ( pcolval->m_type == wxPG_CUSTOM_COLOUR )
617 text.Printf( wxT("It is custom colour: (%i,%i,%i)"),
618 (int)pcolval->m_colour.Red(),
619 (int)pcolval->m_colour.Green(),
620 (int)pcolval->m_colour.Blue());
621 else
622 text.Printf( wxT("It is wx system colour (number=%i): (%i,%i,%i)"),
623 (int)pcolval->m_type,
624 (int)pcolval->m_colour.Red(),
625 (int)pcolval->m_colour.Green(),
626 (int)pcolval->m_colour.Blue());
627
628 wxMessageBox( text );
629 }
630 }
631
632 @endcode
633
634 @section propgrid_populating Populating wxPropertyGrid Automatically
635
636 @subsection propgrid_fromvariants Populating from List of wxVariants
637
638 Example of populating an empty wxPropertyGrid from a values stored
639 in an arbitrary list of wxVariants.
640
641 @code
642
643 // This is a static method that initializes *all* builtin type handlers
644 // available, including those for wxColour and wxFont. Refers to *all*
645 // included properties, so when compiling with static library, this
646 // method may increase the executable size significantly.
647 pg->InitAllTypeHandlers();
648
649 // Get contents of the grid as a wxVariant list
650 wxVariant all_values = pg->GetPropertyValues();
651
652 // Populate the list with values. If a property with appropriate
653 // name is not found, it is created according to the type of variant.
654 pg->SetPropertyValues( my_list_variant );
655
656 // In order to get wxObject ptr from a variant value,
657 // wxGetVariantCast(VARIANT,CLASSNAME) macro has to be called.
658 // Like this:
659 wxVariant v_txcol = pg->GetPropertyValue(wxT("Text Colour"));
660 const wxColour& txcol = wxGetVariantCast(v_txcol,wxColour);
661
662 @endcode
663
664 @subsection propgrid_fromfile Loading Population from a Text-based Storage
665
666 Class wxPropertyGridPopulator may be helpful when writing code that
667 loads properties from a text-source. In fact, the supplied xrc handler
668 (src/xh_propgrid.cpp) uses it. See that code for more info.
669 NOTE: src/xh_propgrid.cpp is not included in the library by default,
670 to avoid dependency to wxXRC. You will need to add it to your application
671 separately.
672
673 @subsection propgrid_editablestate Saving and Restoring User-Editable State
674
675 You can use wxPGEditableState and wxPGMEditableState classes, and
676 wxPropertyGrid::SaveEditableState() and wxPropertyGrid::RestoreEditableState()
677 to save and restore user-editable state (selected property, expanded/
678 collapsed properties, and scrolled position). For convience with
679 program configuration, wxPGEditableState has functions to save/load
680 its value in wxString. For instance:
681
682 @code
683 // Save state into config
684 wxPGEditableState edState;
685 pg->SaveEditableState(&edState);
686 programConfig->Store(wxT("PropertyGridState"), edState.GetAsString());
687
688 // Restore state from config
689 wxPGEditableState edState;
690 edState.SetFromString(programConfig->Load(wxT("PropertyGridState")));
691 pg->RestoreEditableState(edState);
692 @endcode
693
694
695 @section propgrid_events Event Handling
696
697 Probably the most important event is the Changed event which occurs when
698 value of any property is changed by the user. Use EVT_PG_CHANGED(id,func)
699 in your event table to use it.
700
701 For complete list of event types, see wxPropertyGrid class reference.
702
703 The custom event class, wxPropertyGridEvent, has methods to directly
704 access the property that triggered the event.
705
706 Here's a small sample:
707
708 @code
709
710 // Portion of an imaginary event table
711 BEGIN_EVENT_TABLE(MyForm, wxFrame)
712
713 ...
714
715 // This occurs when a property value changes
716 EVT_PG_CHANGED( PGID, MyForm::OnPropertyGridChange )
717
718 ...
719
720 END_EVENT_TABLE()
721
722 void MyForm::OnPropertyGridChange( wxPropertyGridEvent& event )
723 {
724 wxPGProperty *property = event.GetProperty();
725
726 // It may be NULL
727 if ( !property )
728 return;
729
730 // Get name of changed property
731 const wxString& name = property->GetName();
732
733 // Get resulting value
734 wxVariant value = property->GetValue();
735 }
736
737 @endcode
738
739 Another event type you might find useful is EVT_PG_CHANGING, which occurs
740 just prior property value is being changed by user. You can acquire pending
741 value using wxPropertyGridEvent::GetValue(), and if it is not acceptable,
742 call wxPropertyGridEvent::Veto() to prevent the value change from taking
743 place.
744
745 @code
746
747 // Portion of an imaginary event table
748 BEGIN_EVENT_TABLE(MyForm, wxFrame)
749
750 ...
751
752 // This occurs when a property value changes
753 EVT_PG_CHANGING( PGID, MyForm::OnPropertyGridChanging )
754
755 ...
756
757 END_EVENT_TABLE()
758
759 void MyForm::OnPropertyGridChanging( wxPropertyGridEvent& event )
760 {
761 wxPGProperty* property = event.GetProperty();
762
763 if ( property == m_pWatchThisProperty )
764 {
765 // GetValue() returns the pending value, but is only
766 // supported by wxEVT_PG_CHANGING.
767 if ( event.GetValue().GetString() == g_pThisTextIsNotAllowed )
768 {
769 event.Veto();
770 return;
771 }
772 }
773 }
774
775 @endcode
776
777 @remarks On Sub-property Event Handling
778 - For aggregate type properties (wxFontProperty, wxFlagsProperty, etc), events
779 occur for the main parent property only. For other properties events occur
780 for the children themselves..
781
782 - When property's child gets changed, you can use wxPropertyGridEvent::GetMainParent
783 to obtain its topmost non-category parent (useful, if you have deeply nested
784 properties).
785
786
787 @section propgrid_validating Validating Property Values
788
789 There are various ways to make sure user enters only correct values. First, you
790 can use wxValidators similar to as you would with ordinary controls. Use
791 wxPropertyGridInterface::SetPropertyValidator() to assign wxValidator to
792 property.
793
794 Second, you can subclass a property and override wxPGProperty::ValidateValue(),
795 or handle wxEVT_PG_CHANGING for the same effect. Both of these methods do not
796 actually prevent user from temporarily entering invalid text, but they do give
797 you an opportunity to warn the user and block changed value from being committed
798 in a property.
799
800 Various validation failure options can be controlled globally with
801 wxPropertyGrid::SetValidationFailureBehavior(), or on an event basis by
802 calling wxEvent::SetValidationFailureBehavior(). Here's a code snippet of
803 how to handle wxEVT_PG_CHANGING, and to set custom failure behaviour and
804 message.
805
806 @code
807 void MyFrame::OnPropertyGridChanging(wxPropertyGridEvent& event)
808 {
809 wxPGProperty* property = event.GetProperty();
810
811 // You must use wxPropertyGridEvent::GetValue() to access
812 // the value to be validated.
813 wxVariant pendingValue = event.GetValue();
814
815 if ( property->GetName() == wxT("Font") )
816 {
817 // Make sure value is not unspecified
818 if ( !pendingValue.IsNull() )
819 {
820 wxFont font << pendingValue;
821
822 // Let's just allow Arial font
823 if ( font.GetFaceName() != wxT("Arial") )
824 {
825 event.Veto();
826 event.SetValidationFailureBehavior(wxPG_VFB_STAY_IN_PROPERTY |
827 wxPG_VFB_BEEP |
828 wxPG_VFB_SHOW_MESSAGE);
829 }
830 }
831 }
832 }
833 @endcode
834
835
836 @section propgrid_cellrender Customizing Individual Cell Appearance
837
838 You can control text colour, background colour, and attached image of
839 each cell in the property grid. Use wxPropertyGridInterface::SetPropertyCell() or
840 wxPGProperty::SetCell() for this purpose.
841
842 In addition, it is possible to control these characteristics for
843 wxPGChoices list items. See wxPGChoices::Item() and wxPGChoiceEntry class
844 reference for more info.
845
846
847 @section propgrid_customizing Customizing Properties (without sub-classing)
848
849 In this section are presented miscellaneous ways to have custom appearance
850 and behavior for your properties without all the necessary hassle
851 of sub-classing a property class etc.
852
853 @subsection propgrid_customimage Setting Value Image
854
855 Every property can have a small value image placed in front of the
856 actual value text. Built-in example of this can be seen with
857 wxColourProperty and wxImageFileProperty, but for others it can
858 be set using wxPropertyGrid::SetPropertyImage method.
859
860 @subsection propgrid_customvalidator Setting Validator
861
862 You can set wxValidator for a property using wxPropertyGrid::SetPropertyValidator.
863
864 Validator will work just like in wxWidgets (ie. editorControl->SetValidator(validator)
865 is called).
866
867 @subsection propgrid_customeditor Setting Property's Editor Control(s)
868
869 You can set editor control (or controls, in case of a control and button),
870 of any property using wxPropertyGrid::SetPropertyEditor. Editors are passed
871 using wxPG_EDITOR(EditorName) macro, and valid built-in EditorNames are
872 TextCtrl, Choice, ComboBox, CheckBox, TextCtrlAndButton, ChoiceAndButton,
873 SpinCtrl, and DatePickerCtrl. Two last mentioned ones require call to
874 static member function wxPropertyGrid::RegisterAdditionalEditors().
875
876 Following example changes wxColourProperty's editor from default Choice
877 to TextCtrlAndButton. wxColourProperty has its internal event handling set
878 up so that button click events of the button will be used to trigger
879 colour selection dialog.
880
881 @code
882
883 wxPGId colProp = pg->Append(wxColourProperty(wxT("Text Colour")));
884
885 pg->SetPropertyEditor(colProp,wxPG_EDITOR(TextCtrlAndButton));
886
887 @endcode
888
889 Naturally, creating and setting custom editor classes is a possibility as
890 well. For more information, see wxPGEditor class reference.
891
892 @subsection propgrid_editorattrs Property Attributes Recognized by Editors
893
894 <b>SpinCtrl</b> editor can make use of property's "Min", "Max", "Step" and "Wrap" attributes.
895
896 @subsection propgrid_multiplebuttons Adding Multiple Buttons Next to an Editor
897
898 See wxPGMultiButton class reference.
899
900 @subsection propgrid_customeventhandling Handling Events Passed from Properties
901
902 <b>wxEVT_COMMAND_BUTTON_CLICKED </b>(corresponds to event table macro EVT_BUTTON):
903 Occurs when editor button click is not handled by the property itself
904 (as is the case, for example, if you set property's editor to TextCtrlAndButton
905 from the original TextCtrl).
906
907 @subsection propgrid_attributes Property Attributes
908
909 Miscellaneous values, often specific to a property type, can be set
910 using wxPropertyGrid::SetPropertyAttribute and wxPropertyGrid::SetPropertyAttributeAll
911 methods.
912
913 Attribute names are strings and values wxVariant. Arbitrary names are allowed
914 inorder to store user values. Constant equivalents of all attribute string names are
915 provided. Some of them are defined as cached strings, so using constants can provide
916 for smaller binary size.
917
918 For complete list of attributes, see @link attrids Property Attributes@endlink.
919
920 @subsection propgrid_boolcheckbox Setting wxBoolProperties to Use Check Box
921
922 To have all wxBoolProperties to use CheckBox editor instead of Choice, use
923 following (call after bool properties have been added):
924
925 @code
926 pg->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX,true);
927 @endcode
928
929
930 @section propgrid_usage2 Using wxPropertyGridManager
931
932 wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid,
933 which can optionally have toolbar for mode and page selection, and a help text
934 box.
935
936 wxPropertyGridManager inherits from wxPropertyGridInterface, and as such
937 it has most property manipulation functions. However, only some of them affect
938 properties on all pages (eg. GetPropertyByName() and ExpandAll()), while some
939 (eg. Append()) only apply to the currently selected page.
940
941 To operate explicitly on properties on specific page, use wxPropertyGridManager::GetPage()
942 to obtain pointer to page's wxPropertyGridPage object.
943
944 Visual methods, such as SetCellBackgroundColour and GetNextVisible are only
945 available in wxPropertyGrid. Use wxPropertyGridManager::GetGrid() to obtain
946 pointer to it.
947
948 Iteration methods will not work in wxPropertyGridManager. Instead, you must acquire
949 the internal grid (GetGrid()) or wxPropertyGridPage object (GetPage()).
950
951 wxPropertyGridManager constructor has exact same format as wxPropertyGrid
952 constructor, and basicly accepts same extra window style flags (albeit also
953 has some extra ones).
954
955 Here's some example code for creating and populating a wxPropertyGridManager:
956
957 @code
958
959 wxPropertyGridManager* pgMan = new wxPropertyGridManager(this, PGID,
960 wxDefaultPosition, wxDefaultSize,
961 // These and other similar styles are automatically
962 // passed to the embedded wxPropertyGrid.
963 wxPG_BOLD_MODIFIED|wxPG_SPLITTER_AUTO_CENTER|
964 // Include toolbar.
965 wxPG_TOOLBAR |
966 // Include description box.
967 wxPG_DESCRIPTION |
968 // Include compactor.
969 wxPG_COMPACTOR |
970 // Plus defaults.
971 wxPGMAN_DEFAULT_STYLE
972 );
973
974 wxPropertyGridPage* page;
975
976 // Adding a page sets target page to the one added, so
977 // we don't have to call SetTargetPage if we are filling
978 // it right after adding.
979 pgMan->AddPage(wxT("First Page"));
980 page = pgMan->GetLastPage();
981
982 page->Append( new wxPropertyCategory(wxT("Category A1")) );
983
984 page->Append( new wxIntProperty(wxT("Number"),wxPG_LABEL,1) );
985
986 page->Append( new wxColourProperty(wxT("Colour"),wxPG_LABEL,*wxWHITE) );
987
988 pgMan->AddPage(wxT("Second Page"));
989 page = pgMan->GetLastPage();
990
991 page->Append( wxT("Text"),wxPG_LABEL,wxT("(no text)") );
992
993 page->Append( new wxFontProperty(wxT("Font"),wxPG_LABEL) );
994
995 @endcode
996
997 @subsection propgrid_propgridpage wxPropertyGridPage
998
999 wxPropertyGridPage is holder of properties for one page in manager. It is derived from
1000 wxEvtHandler, so you can subclass it to process page-specific property grid events. Hand
1001 over your page instance in wxPropertyGridManager::AddPage.
1002
1003 Please note that the wxPropertyGridPage itself only sports subset of wxPropertyGrid API
1004 (but unlike manager, this include item iteration). Naturally it inherits from
1005 wxPropertyGridMethods and wxPropertyGridPageState.
1006
1007
1008 @section propgrid_subclassing Subclassing wxPropertyGrid and wxPropertyGridManager
1009
1010 Few things to note:
1011
1012 - Only a small percentage of member functions are virtual. If you need more,
1013 just e-mail to wx-dev mailing list.
1014
1015 - Data manipulation is done in wxPropertyGridPageState class. So, instead of
1016 overriding wxPropertyGrid::Insert, you'll probably want to override wxPropertyGridPageState::DoInsert.
1017
1018 - Override wxPropertyGrid::CreateState to instantiate your derivate wxPropertyGridPageState.
1019 For wxPropertyGridManager, you'll need to subclass wxPropertyGridPage instead (since it
1020 is derived from wxPropertyGridPageState), and hand over instances in wxPropertyGridManager::AddPage
1021 calls.
1022
1023 - You can use a derivate wxPropertyGrid with manager by overriding wxPropertyGridManager::CreatePropertyGrid
1024 member function.
1025
1026
1027 @section propgrid_misc Miscellaneous Topics
1028
1029 @subsection propgrid_namescope Property Name Scope
1030
1031 All properties which parent is category or root can be accessed
1032 directly by their base name (ie. name given for property in its constructor).
1033 Other properties can be accessed via "ParentsName.BaseName" notation,
1034 Naturally, all property names should be unique.
1035
1036 @subsection propgrid_nonuniquelabels Non-unique Labels
1037
1038 It is possible to have properties with identical label under same parent.
1039 However, care must be taken to ensure that each property still has
1040 unique (base) name.
1041
1042 @subsection propgrid_boolproperty wxBoolProperty
1043
1044 There are few points about wxBoolProperty that require futher discussion:
1045 - wxBoolProperty can be shown as either normal combobox or as a checkbox.
1046 Property attribute wxPG_BOOL_USE_CHECKBOX is used to change this.
1047 For example, if you have a wxFlagsProperty, you can
1048 set its all items to use check box using the following:
1049 @code
1050 pg->SetPropertyAttribute(wxT("MyFlagsProperty"),wxPG_BOOL_USE_CHECKBOX,true,wxPG_RECURSE);
1051 @endcode
1052
1053 - Default item names for wxBoolProperty are [wxT("False"),wxT("True")]. This can be
1054 changed using wxPropertyGrid::SetBoolChoices(trueChoice,falseChoice).
1055
1056 @subsection propgrid_textctrlupdates Updates from wxTextCtrl Based Editor
1057
1058 Changes from wxTextCtrl based property editors are committed (ie.
1059 wxEVT_PG_CHANGED is sent etc.) *only* when (1) user presser enter, (2)
1060 user moves to edit another property, or (3) when focus leaves
1061 the grid.
1062
1063 Because of this, you may find it useful, in some apps, to call
1064 wxPropertyGrid::CommitChangesFromEditor() just before you need to do any
1065 computations based on property grid values. Note that CommitChangesFromEditor()
1066 will dispatch wxEVT_PG_CHANGED with ProcessEvent, so any of your event handlers
1067 will be called immediately.
1068
1069 @subsection propgrid_splittercentering Centering the Splitter
1070
1071 If you need to center the splitter, but only once when the program starts,
1072 then do <b>not</b> use the wxPG_SPLITTER_AUTO_CENTER window style, but the
1073 wxPropertyGrid::CenterSplitter() method. <b>However, be sure to call it after
1074 the sizer setup and SetSize calls!</b> (ie. usually at the end of the
1075 frame/dialog constructor)
1076
1077 @subsection propgrid_splittersetting Setting Splitter Position When Creating Property Grid
1078
1079 Splitter position cannot exceed grid size, and therefore setting it during
1080 form creation may fail as initial grid size is often smaller than desired
1081 splitter position, especially when sizers are being used.
1082
1083 @subsection propgrid_colourproperty wxColourProperty and wxSystemColourProperty
1084
1085 Through subclassing, these two property classes provide substantial customization
1086 features. Subclass wxSystemColourProperty if you want to use wxColourPropertyValue
1087 (which features colour type in addition to wxColour), and wxColourProperty if plain
1088 wxColour is enough.
1089
1090 Override wxSystemColourProperty::ColourToString() to redefine how colours are
1091 printed as strings.
1092
1093 Override wxSystemColourProperty::GetCustomColourIndex() to redefine location of
1094 the item that triggers colour picker dialog (default is last).
1095
1096 Override wxSystemColourProperty::GetColour() to determine which colour matches
1097 which choice entry.
1098
1099 @section propgrid_proplist Property Class Descriptions
1100
1101 See @ref pgproperty_properties
1102
1103 */
1104