]> git.saurik.com Git - wxWidgets.git/blame - docs/doxygen/overviews/propgrid.h
use #defines, not typedefs, for compatibility class names declarations to avoid break...
[wxWidgets.git] / docs / doxygen / overviews / propgrid.h
CommitLineData
1c4293cb
VZ
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
216214f8
JS
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
1c4293cb
VZ
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: @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
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
d665918b
JS
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.
1c4293cb
VZ
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
216214f8 200@section propgrid_categories Categories
1c4293cb
VZ
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
216214f8 240@section propgrid_parentprops Tree-like Property Structure
1c4293cb
VZ
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
216214f8 288@section propgrid_enumandflags wxEnumProperty and wxFlagsProperty
1c4293cb
VZ
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 2147483647 which usually equals INT_MAX) is not
300 allowed as 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 // 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
409If you later need to change choices used by a property, there is function
410for 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
427If you want to create your enum properties with simple (label,name,value)
428constructor, then you need to create a new property class using one of the
216214f8 429supplied macro pairs. See @ref pgproperty_creating for details.
1c4293cb
VZ
430
431<b>wxEditEnumProperty</b> is works exactly like wxEnumProperty, except
432is uses non-readonly combobox as default editor, and value is stored as
433string when it is not any of the choices.
434
435wxFlagsProperty 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
454wxFlagsProperty 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,
457you will need to use SetPropertyChoices - otherwise they will not get updated
458properly.
459
216214f8 460@section propgrid_advprops Specialized Properties
1c4293cb
VZ
461
462 This section describes the use of less often needed property classes.
463To 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
216214f8 511@section propgrid_iterating Iterating through a property container
1c4293cb
VZ
512
513You can use somewhat STL'ish iterator classes to iterate through the grid.
514Here is a simple example of forward iterating through all individual
515properties (not categories or sub-propeties that are normally 'transparent'
516to 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
532As 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
548You can give some arguments to GetIterator to determine which properties
549get automatically filtered out. For complete list of options, see
550@link iteratorflags List of Property Iterator Flags@endlink. GetIterator()
551also accepts other arguments. See wxPropertyGridInterface::GetIterator()
552for details.
553
554This 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
573GetIterator() only works with wxPropertyGrid and the individual pages
574of wxPropertyGridManager. In order to iterate through an arbitrary
575property container, you need to use wxPropertyGridInterface::GetVIterator().
576Note 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
216214f8 593@section propgrid_operations More About Operating with Properties
1c4293cb
VZ
594
595Getting value of selected wxSystemColourProperty (which value type is derived
596from 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
216214f8 634@section propgrid_populating Populating wxPropertyGrid Automatically
1c4293cb 635
216214f8 636@subsection propgrid_fromvariants Populating from List of wxVariants
1c4293cb
VZ
637
638Example of populating an empty wxPropertyGrid from a values stored
639in 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
216214f8 664@subsection propgrid_fromfile Loading Population from a Text-based Storage
1c4293cb
VZ
665
666Class wxPropertyGridPopulator may be helpful when writing code that
667loads properties from a text-source. In fact, the supplied xrc handler
668(src/xh_propgrid.cpp) uses it. See that code for more info.
669NOTE: src/xh_propgrid.cpp is not included in the library by default,
670to avoid dependency to wxXRC. You will need to add it to your application
671separately.
672
216214f8 673@subsection propgrid_editablestate Saving and Restoring User-Editable State
1c4293cb
VZ
674
675You can use wxPGEditableState and wxPGMEditableState classes, and
676wxPropertyGrid::SaveEditableState() and wxPropertyGrid::RestoreEditableState()
677to save and restore user-editable state (selected property, expanded/
678collapsed properties, and scrolled position). For convience with
679program configuration, wxPGEditableState has functions to save/load
680its 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
216214f8 695@section propgrid_events Event Handling
1c4293cb
VZ
696
697Probably the most important event is the Changed event which occurs when
698value of any property is changed by the user. Use EVT_PG_CHANGED(id,func)
699in your event table to use it.
700
701For complete list of event types, see wxPropertyGrid class reference.
702
703The custom event class, wxPropertyGridEvent, has methods to directly
704access the property that triggered the event.
705
706Here's a small sample:
707
708@code
709
710// Portion of an imaginary event table
711BEGIN_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
720END_EVENT_TABLE()
721
722void 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
739Another event type you might find useful is EVT_PG_CHANGING, which occurs
740just prior property value is being changed by user. You can acquire pending
741value using wxPropertyGridEvent::GetValue(), and if it is not acceptable,
742call wxPropertyGridEvent::Veto() to prevent the value change from taking
743place.
744
745@code
746
747// Portion of an imaginary event table
748BEGIN_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
757END_EVENT_TABLE()
758
759void 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
216214f8 787@section propgrid_validating Validating Property Values
1c4293cb
VZ
788
789There are various ways to make sure user enters only correct values. First, you
790can use wxValidators similar to as you would with ordinary controls. Use
791wxPropertyGridInterface::SetPropertyValidator() to assign wxValidator to
792property.
793
794Second, you can subclass a property and override wxPGProperty::ValidateValue(),
795or handle wxEVT_PG_CHANGING for the same effect. Both of these methods do not
796actually prevent user from temporarily entering invalid text, but they do give
797you an opportunity to warn the user and block changed value from being committed
798in a property.
799
800Various validation failure options can be controlled globally with
801wxPropertyGrid::SetValidationFailureBehavior(), or on an event basis by
802calling wxEvent::SetValidationFailureBehavior(). Here's a code snippet of
803how to handle wxEVT_PG_CHANGING, and to set custom failure behaviour and
804message.
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
216214f8 836@section propgrid_cellrender Customizing Individual Cell Appearance
1c4293cb
VZ
837
838You can control text colour, background colour, and attached image of
839each cell in the property grid. Use wxPropertyGridInterface::SetPropertyCell() or
840wxPGProperty::SetCell() for this purpose.
841
842In addition, it is possible to control these characteristics for
843wxPGChoices list items. See wxPGChoices::Item() and wxPGChoiceEntry class
844reference for more info.
845
846
216214f8 847@section propgrid_customizing Customizing Properties (without sub-classing)
1c4293cb
VZ
848
849In this section are presented miscellaneous ways to have custom appearance
850and behavior for your properties without all the necessary hassle
851of sub-classing a property class etc.
852
216214f8 853@subsection propgrid_customimage Setting Value Image
1c4293cb
VZ
854
855Every property can have a small value image placed in front of the
856actual value text. Built-in example of this can be seen with
857wxColourProperty and wxImageFileProperty, but for others it can
858be set using wxPropertyGrid::SetPropertyImage method.
859
216214f8 860@subsection propgrid_customvalidator Setting Validator
1c4293cb
VZ
861
862You can set wxValidator for a property using wxPropertyGrid::SetPropertyValidator.
863
864Validator will work just like in wxWidgets (ie. editorControl->SetValidator(validator)
865is called).
866
216214f8 867@subsection propgrid_customeditor Setting Property's Editor Control(s)
1c4293cb
VZ
868
869You can set editor control (or controls, in case of a control and button),
870of any property using wxPropertyGrid::SetPropertyEditor. Editors are passed
871using wxPG_EDITOR(EditorName) macro, and valid built-in EditorNames are
872TextCtrl, Choice, ComboBox, CheckBox, TextCtrlAndButton, ChoiceAndButton,
873SpinCtrl, and DatePickerCtrl. Two last mentioned ones require call to
874static member function wxPropertyGrid::RegisterAdditionalEditors().
875
876Following example changes wxColourProperty's editor from default Choice
877to TextCtrlAndButton. wxColourProperty has its internal event handling set
878up so that button click events of the button will be used to trigger
879colour 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
889Naturally, creating and setting custom editor classes is a possibility as
890well. For more information, see wxPGEditor class reference.
891
216214f8 892@subsection propgrid_editorattrs Property Attributes Recognized by Editors
1c4293cb
VZ
893
894<b>SpinCtrl</b> editor can make use of property's "Min", "Max", "Step" and "Wrap" attributes.
895
216214f8 896@subsection propgrid_multiplebuttons Adding Multiple Buttons Next to an Editor
1c4293cb
VZ
897
898See wxPGMultiButton class reference.
899
216214f8 900@subsection propgrid_customeventhandling Handling Events Passed from Properties
1c4293cb
VZ
901
902<b>wxEVT_COMMAND_BUTTON_CLICKED </b>(corresponds to event table macro EVT_BUTTON):
903Occurs 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
905from the original TextCtrl).
906
216214f8 907@subsection propgrid_attributes Property Attributes
1c4293cb
VZ
908
909Miscellaneous values, often specific to a property type, can be set
910using wxPropertyGrid::SetPropertyAttribute and wxPropertyGrid::SetPropertyAttributeAll
911methods.
912
913Attribute names are strings and values wxVariant. Arbitrary names are allowed
914inorder to store user values. Constant equivalents of all attribute string names are
915provided. Some of them are defined as cached strings, so using constants can provide
916for smaller binary size.
917
918For complete list of attributes, see @link attrids Property Attributes@endlink.
919
216214f8 920@subsection propgrid_boolcheckbox Setting wxBoolProperties to Use Check Box
1c4293cb
VZ
921
922To have all wxBoolProperties to use CheckBox editor instead of Choice, use
923following (call after bool properties have been added):
924
925@code
926 pg->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX,true);
927@endcode
928
929
216214f8 930@section propgrid_usage2 Using wxPropertyGridManager
1c4293cb
VZ
931
932wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid,
933which can optionally have toolbar for mode and page selection, and a help text
934box.
935
936wxPropertyGridManager inherits from wxPropertyGridInterface, and as such
937it has most property manipulation functions. However, only some of them affect
938properties on all pages (eg. GetPropertyByName() and ExpandAll()), while some
939(eg. Append()) only apply to the currently selected page.
940
941To operate explicitly on properties on specific page, use wxPropertyGridManager::GetPage()
942to obtain pointer to page's wxPropertyGridPage object.
943
944Visual methods, such as SetCellBackgroundColour and GetNextVisible are only
945available in wxPropertyGrid. Use wxPropertyGridManager::GetGrid() to obtain
946pointer to it.
947
948Iteration methods will not work in wxPropertyGridManager. Instead, you must acquire
949the internal grid (GetGrid()) or wxPropertyGridPage object (GetPage()).
950
951wxPropertyGridManager constructor has exact same format as wxPropertyGrid
952constructor, and basicly accepts same extra window style flags (albeit also
953has some extra ones).
954
955Here'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
216214f8 997@subsection propgrid_propgridpage wxPropertyGridPage
1c4293cb
VZ
998
999wxPropertyGridPage is holder of properties for one page in manager. It is derived from
1000wxEvtHandler, so you can subclass it to process page-specific property grid events. Hand
1001over your page instance in wxPropertyGridManager::AddPage.
1002
1003Please note that the wxPropertyGridPage itself only sports subset of wxPropertyGrid API
1004(but unlike manager, this include item iteration). Naturally it inherits from
1005wxPropertyGridMethods and wxPropertyGridPageState.
1006
1007
216214f8 1008@section propgrid_subclassing Subclassing wxPropertyGrid and wxPropertyGridManager
1c4293cb
VZ
1009
1010Few 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
216214f8 1027@section propgrid_misc Miscellaneous Topics
1c4293cb 1028
216214f8 1029@subsection propgrid_namescope Property Name Scope
1c4293cb 1030
258ccb95
JS
1031 All properties which parent is category or root can be accessed
1032directly by their base name (ie. name given for property in its constructor).
1033Other properties can be accessed via "ParentsName.BaseName" notation,
1034Naturally, all property names should be unique.
1c4293cb 1035
216214f8 1036@subsection propgrid_nonuniquelabels Non-unique Labels
258ccb95
JS
1037
1038 It is possible to have properties with identical label under same parent.
1039However, care must be taken to ensure that each property still has
1040unique (base) name.
1c4293cb 1041
216214f8 1042@subsection propgrid_boolproperty wxBoolProperty
1c4293cb
VZ
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
216214f8 1056@subsection propgrid_textctrlupdates Updates from wxTextCtrl Based Editor
1c4293cb
VZ
1057
1058 Changes from wxTextCtrl based property editors are committed (ie.
1059wxEVT_PG_CHANGED is sent etc.) *only* when (1) user presser enter, (2)
1060user moves to edit another property, or (3) when focus leaves
1061the grid.
1062
1063 Because of this, you may find it useful, in some apps, to call
1064wxPropertyGrid::CommitChangesFromEditor() just before you need to do any
1065computations based on property grid values. Note that CommitChangesFromEditor()
1066will dispatch wxEVT_PG_CHANGED with ProcessEvent, so any of your event handlers
1067will be called immediately.
1068
216214f8 1069@subsection propgrid_splittercentering Centering the Splitter
1c4293cb
VZ
1070
1071 If you need to center the splitter, but only once when the program starts,
1072then do <b>not</b> use the wxPG_SPLITTER_AUTO_CENTER window style, but the
1073wxPropertyGrid::CenterSplitter() method. <b>However, be sure to call it after
1074the sizer setup and SetSize calls!</b> (ie. usually at the end of the
1075frame/dialog constructor)
1076
216214f8 1077@subsection propgrid_splittersetting Setting Splitter Position When Creating Property Grid
1c4293cb
VZ
1078
1079Splitter position cannot exceed grid size, and therefore setting it during
1080form creation may fail as initial grid size is often smaller than desired
1081splitter position, especially when sizers are being used.
1082
216214f8 1083@subsection propgrid_colourproperty wxColourProperty and wxSystemColourProperty
1c4293cb
VZ
1084
1085Through subclassing, these two property classes provide substantial customization
1086features. Subclass wxSystemColourProperty if you want to use wxColourPropertyValue
1087(which features colour type in addition to wxColour), and wxColourProperty if plain
1088wxColour is enough.
1089
1090Override wxSystemColourProperty::ColourToString() to redefine how colours are
1091printed as strings.
1092
1093Override wxSystemColourProperty::GetCustomColourIndex() to redefine location of
1094the item that triggers colour picker dialog (default is last).
1095
1096Override wxSystemColourProperty::GetColour() to determine which colour matches
1097which choice entry.
1098
216214f8 1099@section propgrid_proplist Property Class Descriptions
1c4293cb
VZ
1100
1101See @ref pgproperty_properties
1102
1103*/
1104