]>
Commit | Line | Data |
---|---|---|
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, 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 | ||
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 INT_MAX) is not allowed as list | |
300 | item 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 | 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 | ||
408 | You can later change choices of property by using wxPGProperty::InsertChoice(), | |
409 | wxPGProperty::DeleteChoice(), and wxPGProperty::SetChoices(). | |
410 | ||
411 | <b>wxEditEnumProperty</b> is works exactly like wxEnumProperty, except | |
412 | is uses non-readonly combobox as default editor, and value is stored as | |
413 | string when it is not any of the choices. | |
414 | ||
415 | wxFlagsProperty 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 | ||
434 | wxFlagsProperty 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, | |
437 | you will need to use wxPGProperty::SetChoices() to replace all choices | |
438 | at 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. | |
443 | To 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 | ||
493 | You can use somewhat STL'ish iterator classes to iterate through the grid. | |
494 | Here is a simple example of forward iterating through all individual | |
495 | properties (not categories or sub-propeties that are normally 'transparent' | |
496 | to 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 | ||
512 | As 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 | ||
528 | You can give some arguments to GetIterator to determine which properties | |
529 | get automatically filtered out. For complete list of options, see | |
530 | @ref propgrid_iterator_flags. GetIterator() also accepts other arguments. | |
531 | See wxPropertyGridInterface::GetIterator() for details. | |
532 | ||
533 | This 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 | ||
552 | GetIterator() only works with wxPropertyGrid and the individual pages | |
553 | of wxPropertyGridManager. In order to iterate through an arbitrary | |
554 | property container, you need to use wxPropertyGridInterface::GetVIterator(). | |
555 | Note 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 | ||
574 | Getting value of selected wxSystemColourProperty (which value type is derived | |
575 | from 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 | ||
617 | Example of populating an empty wxPropertyGrid from a values stored | |
618 | in 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 | ||
645 | Class wxPropertyGridPopulator may be helpful when writing code that | |
646 | loads properties from a text-source. In fact, the supplied xrc handler | |
647 | (src/xh_propgrid.cpp) uses it. See that code for more info. | |
648 | NOTE: src/xh_propgrid.cpp is not included in the library by default, | |
649 | to avoid dependency to wxXRC. You will need to add it to your application | |
650 | separately. | |
651 | ||
652 | @subsection propgrid_editablestate Saving and Restoring User-Editable State | |
653 | ||
654 | You can use wxPGEditableState and wxPGMEditableState classes, and | |
655 | wxPropertyGrid::SaveEditableState() and wxPropertyGrid::RestoreEditableState() | |
656 | to save and restore user-editable state (selected property, expanded/ | |
657 | collapsed properties, and scrolled position). For convience with | |
658 | program configuration, wxPGEditableState has functions to save/load | |
659 | its 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 | ||
676 | Probably the most important event is the Changed event which occurs when | |
677 | value of any property is changed by the user. Use EVT_PG_CHANGED(id,func) | |
678 | in your event table to use it. | |
679 | ||
680 | For complete list of event types, see wxPropertyGrid class reference. | |
681 | ||
682 | The custom event class, wxPropertyGridEvent, has methods to directly | |
683 | access the property that triggered the event. | |
684 | ||
685 | Here's a small sample: | |
686 | ||
687 | @code | |
688 | ||
689 | // Portion of an imaginary event table | |
690 | BEGIN_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 | ||
699 | END_EVENT_TABLE() | |
700 | ||
701 | void 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 | ||
718 | Another event type you might find useful is EVT_PG_CHANGING, which occurs | |
719 | just prior property value is being changed by user. You can acquire pending | |
720 | value using wxPropertyGridEvent::GetValue(), and if it is not acceptable, | |
721 | call wxPropertyGridEvent::Veto() to prevent the value change from taking | |
722 | place. | |
723 | ||
724 | @code | |
725 | ||
726 | // Portion of an imaginary event table | |
727 | BEGIN_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 | ||
736 | END_EVENT_TABLE() | |
737 | ||
738 | void 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 | ||
768 | There are various ways to make sure user enters only correct values. First, you | |
769 | can use wxValidators similar to as you would with ordinary controls. Use | |
770 | wxPropertyGridInterface::SetPropertyValidator() to assign wxValidator to | |
771 | property. | |
772 | ||
773 | Second, you can subclass a property and override wxPGProperty::ValidateValue(), | |
774 | or handle wxEVT_PG_CHANGING for the same effect. Both of these methods do not | |
775 | actually prevent user from temporarily entering invalid text, but they do give | |
776 | you an opportunity to warn the user and block changed value from being committed | |
777 | in a property. | |
778 | ||
779 | Various validation failure options can be controlled globally with | |
780 | wxPropertyGrid::SetValidationFailureBehavior(), or on an event basis by | |
781 | calling wxEvent::SetValidationFailureBehavior(). Here's a code snippet of | |
782 | how to handle wxEVT_PG_CHANGING, and to set custom failure behaviour and | |
783 | message. | |
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 | ||
817 | You can control text colour, background colour, and attached image of | |
818 | each cell in the property grid. Use wxPropertyGridInterface::SetPropertyCell() or | |
819 | wxPGProperty::SetCell() for this purpose. | |
820 | ||
821 | In addition, it is possible to control these characteristics for | |
822 | wxPGChoices list items. See wxPGChoices class | |
823 | reference for more info. | |
824 | ||
825 | ||
826 | @section propgrid_customizing Customizing Properties (without sub-classing) | |
827 | ||
828 | In this section are presented miscellaneous ways to have custom appearance | |
829 | and behavior for your properties without all the necessary hassle | |
830 | of sub-classing a property class etc. | |
831 | ||
832 | @subsection propgrid_customimage Setting Value Image | |
833 | ||
834 | Every property can have a small value image placed in front of the | |
835 | actual value text. Built-in example of this can be seen with | |
836 | wxColourProperty and wxImageFileProperty, but for others it can | |
837 | be set using wxPropertyGrid::SetPropertyImage method. | |
838 | ||
839 | @subsection propgrid_customvalidator Setting Validator | |
840 | ||
841 | You can set wxValidator for a property using wxPropertyGrid::SetPropertyValidator. | |
842 | ||
843 | Validator will work just like in wxWidgets (ie. editorControl->SetValidator(validator) | |
844 | is called). | |
845 | ||
846 | @subsection propgrid_customeditor Setting Property's Editor Control(s) | |
847 | ||
848 | You can set editor control (or controls, in case of a control and button), | |
849 | of any property using wxPropertyGrid::SetPropertyEditor. Editors are passed | |
850 | using wxPG_EDITOR(EditorName) macro, and valid built-in EditorNames are | |
851 | TextCtrl, Choice, ComboBox, CheckBox, TextCtrlAndButton, ChoiceAndButton, | |
852 | SpinCtrl, and DatePickerCtrl. Two last mentioned ones require call to | |
853 | static member function wxPropertyGrid::RegisterAdditionalEditors(). | |
854 | ||
855 | Following example changes wxColourProperty's editor from default Choice | |
856 | to TextCtrlAndButton. wxColourProperty has its internal event handling set | |
857 | up so that button click events of the button will be used to trigger | |
858 | colour 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 | ||
868 | Naturally, creating and setting custom editor classes is a possibility as | |
869 | well. 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 | ||
877 | See 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): | |
882 | Occurs 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 | |
884 | from the original TextCtrl). | |
885 | ||
886 | @subsection propgrid_attributes Property Attributes | |
887 | ||
888 | Miscellaneous values, often specific to a property type, can be set | |
889 | using wxPropertyGrid::SetPropertyAttribute and wxPropertyGrid::SetPropertyAttributeAll | |
890 | methods. | |
891 | ||
892 | Attribute names are strings and values wxVariant. Arbitrary names are allowed | |
893 | inorder to store user values. Constant equivalents of all attribute string names are | |
894 | provided. Some of them are defined as cached strings, so using constants can provide | |
895 | for smaller binary size. | |
896 | ||
897 | For complete list of attributes, see @ref propgrid_property_attributes. | |
898 | ||
899 | @subsection propgrid_boolcheckbox Setting wxBoolProperties to Use Check Box | |
900 | ||
901 | To have all wxBoolProperties to use CheckBox editor instead of Choice, use | |
902 | following (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 | ||
911 | wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid, | |
912 | which can optionally have toolbar for mode and page selection, and a help text | |
913 | box. | |
914 | ||
915 | wxPropertyGridManager inherits from wxPropertyGridInterface, and as such | |
916 | it has most property manipulation functions. However, only some of them affect | |
917 | properties on all pages (eg. GetPropertyByName() and ExpandAll()), while some | |
918 | (eg. Append()) only apply to the currently selected page. | |
919 | ||
920 | To operate explicitly on properties on specific page, use wxPropertyGridManager::GetPage() | |
921 | to obtain pointer to page's wxPropertyGridPage object. | |
922 | ||
923 | Visual methods, such as SetCellBackgroundColour and GetNextVisible are only | |
924 | available in wxPropertyGrid. Use wxPropertyGridManager::GetGrid() to obtain | |
925 | pointer to it. | |
926 | ||
927 | Iteration methods will not work in wxPropertyGridManager. Instead, you must acquire | |
928 | the internal grid (GetGrid()) or wxPropertyGridPage object (GetPage()). | |
929 | ||
930 | wxPropertyGridManager constructor has exact same format as wxPropertyGrid | |
931 | constructor, and basicly accepts same extra window style flags (albeit also | |
932 | has some extra ones). | |
933 | ||
934 | Here'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 | ||
978 | wxPropertyGridPage is holder of properties for one page in manager. It is derived from | |
979 | wxEvtHandler, so you can subclass it to process page-specific property grid events. Hand | |
980 | over your page instance in wxPropertyGridManager::AddPage. | |
981 | ||
982 | Please note that the wxPropertyGridPage itself only sports subset of wxPropertyGrid API | |
983 | (but unlike manager, this include item iteration). Naturally it inherits from | |
984 | wxPropertyGridMethods and wxPropertyGridPageState. | |
985 | ||
986 | ||
987 | @section propgrid_subclassing Subclassing wxPropertyGrid and wxPropertyGridManager | |
988 | ||
989 | Few 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 | |
1011 | directly by their base name (ie. name given for property in its constructor). | |
1012 | Other properties can be accessed via "ParentsName.BaseName" notation, | |
1013 | Naturally, 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. | |
1018 | However, care must be taken to ensure that each property still has | |
1019 | unique (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. | |
1038 | wxEVT_PG_CHANGED is sent etc.) *only* when (1) user presser enter, (2) | |
1039 | user moves to edit another property, or (3) when focus leaves | |
1040 | the grid. | |
1041 | ||
1042 | Because of this, you may find it useful, in some apps, to call | |
1043 | wxPropertyGrid::CommitChangesFromEditor() just before you need to do any | |
1044 | computations based on property grid values. Note that CommitChangesFromEditor() | |
1045 | will dispatch wxEVT_PG_CHANGED with ProcessEvent, so any of your event handlers | |
1046 | will 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, | |
1051 | then do <b>not</b> use the wxPG_SPLITTER_AUTO_CENTER window style, but the | |
1052 | wxPropertyGrid::CenterSplitter() method. <b>However, be sure to call it after | |
1053 | the sizer setup and SetSize calls!</b> (ie. usually at the end of the | |
1054 | frame/dialog constructor) | |
1055 | ||
1056 | @subsection propgrid_splittersetting Setting Splitter Position When Creating Property Grid | |
1057 | ||
1058 | Splitter position cannot exceed grid size, and therefore setting it during | |
1059 | form creation may fail as initial grid size is often smaller than desired | |
1060 | splitter position, especially when sizers are being used. | |
1061 | ||
1062 | @subsection propgrid_colourproperty wxColourProperty and wxSystemColourProperty | |
1063 | ||
1064 | Through subclassing, these two property classes provide substantial customization | |
1065 | features. Subclass wxSystemColourProperty if you want to use wxColourPropertyValue | |
1066 | (which features colour type in addition to wxColour), and wxColourProperty if plain | |
1067 | wxColour is enough. | |
1068 | ||
1069 | Override wxSystemColourProperty::ColourToString() to redefine how colours are | |
1070 | printed as strings. | |
1071 | ||
1072 | Override wxSystemColourProperty::GetCustomColourIndex() to redefine location of | |
1073 | the item that triggers colour picker dialog (default is last). | |
1074 | ||
1075 | Override wxSystemColourProperty::GetColour() to determine which colour matches | |
1076 | which choice entry. | |
1077 | ||
1078 | @section propgrid_proplist Property Class Descriptions | |
1079 | ||
1080 | See @ref pgproperty_properties | |
1081 | ||
1082 | */ | |
1083 |