]>
Commit | Line | Data |
---|---|---|
1c4293cb VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: propgrid.h | |
3 | // Purpose: topic overview | |
4 | // Author: wxWidgets team | |
de003797 | 5 | // RCS-ID: $Id$ |
1c4293cb VZ |
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 | ||
bba3f9b5 JS |
20 | wxPropertyGrid is a specialized grid for editing properties - in other |
21 | words name = value pairs. List of ready-to-use property classes include | |
22 | strings, numbers, flag sets, fonts, colours and many others. It is possible, | |
23 | for example, to categorize properties, set up a complete tree-hierarchy, | |
24 | add more than two columns, and set arbitrary per-property attributes. | |
1c4293cb | 25 | |
216214f8 JS |
26 | @li @ref propgrid_basics |
27 | @li @ref propgrid_categories | |
28 | @li @ref propgrid_parentprops | |
29 | @li @ref propgrid_enumandflags | |
30 | @li @ref propgrid_advprops | |
bba3f9b5 | 31 | @li @ref propgrid_processingvalues |
216214f8 | 32 | @li @ref propgrid_iterating |
216214f8 JS |
33 | @li @ref propgrid_events |
34 | @li @ref propgrid_validating | |
35 | @li @ref propgrid_populating | |
36 | @li @ref propgrid_cellrender | |
37 | @li @ref propgrid_customizing | |
38 | @li @ref propgrid_usage2 | |
39 | @li @ref propgrid_subclassing | |
40 | @li @ref propgrid_misc | |
41 | @li @ref propgrid_proplist | |
216214f8 JS |
42 | |
43 | @section propgrid_basics Creating and Populating wxPropertyGrid | |
1c4293cb VZ |
44 | |
45 | As seen here, wxPropertyGrid is constructed in the same way as | |
46 | other wxWidgets controls: | |
47 | ||
48 | @code | |
49 | ||
50 | // Necessary header file | |
51 | #include <wx/propgrid/propgrid.h> | |
52 | ||
53 | ... | |
54 | ||
55 | // Assumes code is in frame/dialog constructor | |
56 | ||
57 | // Construct wxPropertyGrid control | |
58 | wxPropertyGrid* pg = new wxPropertyGrid( | |
59 | this, // parent | |
60 | PGID, // id | |
61 | wxDefaultPosition, // position | |
62 | wxDefaultSize, // size | |
63 | // Here are just some of the supported window styles | |
64 | wxPG_AUTO_SORT | // Automatic sorting after items added | |
65 | wxPG_SPLITTER_AUTO_CENTER | // Automatically center splitter until user manually adjusts it | |
66 | // Default style | |
67 | wxPG_DEFAULT_STYLE ); | |
68 | ||
69 | // Window style flags are at premium, so some less often needed ones are | |
70 | // available as extra window styles (wxPG_EX_xxx) which must be set using | |
71 | // SetExtraStyle member function. wxPG_EX_HELP_AS_TOOLTIPS, for instance, | |
bba3f9b5 | 72 | // allows displaying help strings as tool tips. |
1c4293cb VZ |
73 | pg->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS ); |
74 | ||
75 | @endcode | |
76 | ||
b55018ec | 77 | (for complete list of new window styles, see @ref propgrid_window_styles) |
1c4293cb VZ |
78 | |
79 | wxPropertyGrid is usually populated with lines like this: | |
80 | ||
81 | @code | |
82 | pg->Append( new wxStringProperty(wxT("Label"),wxT("Name"),wxT("Initial Value")) ); | |
83 | @endcode | |
84 | ||
85 | Naturally, wxStringProperty is a property class. Only the first function argument (label) | |
86 | is mandatory. Second one, name, defaults to label and, third, the initial value, to | |
87 | default value. If constant wxPG_LABEL is used as the name argument, then the label is | |
d665918b JS |
88 | automatically used as a name as well (this is more efficient than manually defining both |
89 | as the same). Use of empty name is discouraged and will sometimes result in run-time error. | |
90 | Note that all property class constructors have quite similar constructor argument list. | |
1c4293cb VZ |
91 | |
92 | To demonstrate other common property classes, here's another code snippet: | |
93 | ||
94 | @code | |
95 | ||
96 | // Add int property | |
97 | pg->Append( new wxIntProperty(wxT("IntProperty"), wxPG_LABEL, 12345678) ); | |
98 | ||
99 | // Add float property (value type is actually double) | |
100 | pg->Append( new wxFloatProperty(wxT("FloatProperty"), wxPG_LABEL, 12345.678) ); | |
101 | ||
102 | // Add a bool property | |
103 | pg->Append( new wxBoolProperty(wxT("BoolProperty"), wxPG_LABEL, false) ); | |
104 | ||
105 | // A string property that can be edited in a separate editor dialog. | |
106 | pg->Append( new wxLongStringProperty(wxT("LongStringProperty"), | |
107 | wxPG_LABEL, | |
108 | wxT("This is much longer string than the ") | |
109 | wxT("first one. Edit it by clicking the button."))); | |
110 | ||
111 | // String editor with dir selector button. | |
112 | pg->Append( new wxDirProperty(wxT("DirProperty"), wxPG_LABEL, ::wxGetUserHome()) ); | |
113 | ||
114 | // wxArrayStringProperty embeds a wxArrayString. | |
115 | pg->Append( new wxArrayStringProperty(wxT("Label of ArrayStringProperty"), | |
116 | wxT("NameOfArrayStringProp"))); | |
117 | ||
118 | // A file selector property. | |
119 | pg->Append( new wxFileProperty(wxT("FileProperty"), wxPG_LABEL, wxEmptyString) ); | |
120 | ||
bba3f9b5 | 121 | // Extra: set wild card for file property (format same as in wxFileDialog). |
1c4293cb VZ |
122 | pg->SetPropertyAttribute( wxT("FileProperty"), |
123 | wxPG_FILE_WILDCARD, | |
124 | wxT("All files (*.*)|*.*") ); | |
125 | ||
126 | @endcode | |
127 | ||
bba3f9b5 JS |
128 | Operations on properties are usually done by directly calling wxPGProperty's |
129 | or wxPropertyGridInterface's member functions. wxPropertyGridInterface is an | |
130 | abstract base class for property containers such as wxPropertyGrid, | |
131 | wxPropertyGridManager, and wxPropertyGridPage. Note however that wxPGProperty's | |
132 | member functions generally do not refresh the grid. | |
1c4293cb | 133 | |
bba3f9b5 JS |
134 | wxPropertyGridInterface's property operation member functions , such as |
135 | SetPropertyValue() and DisableProperty(), all accept a special wxPGPropArg id | |
136 | argument, using which you can refer to properties either by their pointer | |
137 | (for performance) or by their name (for convenience). For instance: | |
1c4293cb VZ |
138 | |
139 | @code | |
bba3f9b5 JS |
140 | // Add a file selector property. |
141 | wxPGPropety* prop = pg->Append( new wxFileProperty(wxT("FileProperty"), | |
142 | wxPG_LABEL, | |
143 | wxEmptyString) ); | |
1c4293cb | 144 | |
bba3f9b5 | 145 | // Valid: Set wild card by name |
1c4293cb VZ |
146 | pg->SetPropertyAttribute( wxT("FileProperty"), |
147 | wxPG_FILE_WILDCARD, | |
148 | wxT("All files (*.*)|*.*") ); | |
149 | ||
bba3f9b5 JS |
150 | // Also Valid: Set wild card by property pointer |
151 | pg->SetPropertyAttribute( prop, | |
1c4293cb VZ |
152 | wxPG_FILE_WILDCARD, |
153 | wxT("All files (*.*)|*.*") ); | |
154 | @endcode | |
155 | ||
bba3f9b5 JS |
156 | Using pointer is faster, since it doesn't require hash map lookup. Anyway, |
157 | you can always get property pointer (wxPGProperty*) as return value from Append() | |
158 | or Insert(), or by calling wxPropertyGridInterface::GetPropertyByName() or | |
159 | just plain GetProperty(). | |
1c4293cb | 160 | |
216214f8 | 161 | @section propgrid_categories Categories |
1c4293cb | 162 | |
bba3f9b5 | 163 | wxPropertyGrid has a hierarchic property storage and display model, which |
1c4293cb VZ |
164 | allows property categories to hold child properties and even other |
165 | categories. Other than that, from the programmer's point of view, categories | |
166 | can be treated exactly the same as "other" properties. For example, despite | |
bba3f9b5 JS |
167 | its name, GetPropertyByName() also returns a category by name. Note however |
168 | that sometimes the label of a property category may be referred as caption | |
169 | (for example, there is wxPropertyGrid::SetCaptionTextColour() method | |
170 | that sets text colour of property category labels). | |
1c4293cb VZ |
171 | |
172 | When category is added at the top (i.e. root) level of the hierarchy, | |
173 | it becomes a *current category*. This means that all other (non-category) | |
bba3f9b5 JS |
174 | properties after it are automatically appended to it. You may add |
175 | properties to specific categories by using wxPropertyGridInterface::Insert | |
176 | or wxPropertyGridInterface::AppendIn. | |
1c4293cb VZ |
177 | |
178 | Category code sample: | |
179 | ||
180 | @code | |
181 | ||
182 | // One way to add category (similar to how other properties are added) | |
183 | pg->Append( new wxPropertyCategory(wxT("Main")) ); | |
184 | ||
185 | // All these are added to "Main" category | |
186 | pg->Append( new wxStringProperty(wxT("Name")) ); | |
187 | pg->Append( new wxIntProperty(wxT("Age"),wxPG_LABEL,25) ); | |
188 | pg->Append( new wxIntProperty(wxT("Height"),wxPG_LABEL,180) ); | |
189 | pg->Append( new wxIntProperty(wxT("Weight")) ); | |
190 | ||
191 | // Another one | |
bba3f9b5 | 192 | pg->Append( new wxPropertyCategory(wxT("Attributes")) ); |
1c4293cb VZ |
193 | |
194 | // All these are added to "Attributes" category | |
195 | pg->Append( new wxIntProperty(wxT("Intelligence")) ); | |
196 | pg->Append( new wxIntProperty(wxT("Agility")) ); | |
197 | pg->Append( new wxIntProperty(wxT("Strength")) ); | |
198 | ||
199 | @endcode | |
200 | ||
201 | ||
216214f8 | 202 | @section propgrid_parentprops Tree-like Property Structure |
1c4293cb | 203 | |
bba3f9b5 | 204 | Basically any property can have children. There are few limitations, however. |
1c4293cb VZ |
205 | |
206 | @remarks | |
bba3f9b5 JS |
207 | - Names of properties with non-category, non-root parents are not stored in global |
208 | hash map. Instead, they can be accessed with strings like "Parent.Child". | |
209 | For instance, in the sample below, child property named "Max. Speed (mph)" | |
210 | can be accessed by global name "Car.Speeds.Max Speed (mph)". | |
211 | - If you want to property's value to be a string composed of the child property values, | |
212 | you must use wxStringProperty as parent and use magic string "<composed>" as its | |
213 | value. | |
1c4293cb VZ |
214 | - Events (eg. change of value) that occur in parent do not propagate to children. Events |
215 | that occur in children will propagate to parents, but only if they are wxStringProperties | |
216 | with "<composed>" value. | |
1c4293cb VZ |
217 | |
218 | Sample: | |
219 | ||
220 | @code | |
bba3f9b5 JS |
221 | wxPGProperty* carProp = pg->Append(new wxStringProperty(wxT("Car"), |
222 | wxPG_LABEL, | |
223 | wxT("<composed>"))); | |
224 | ||
225 | pg->AppendIn(carProp, new wxStringProperty(wxT("Model"), | |
226 | wxPG_LABEL, | |
227 | wxT("Lamborghini Diablo SV"))); | |
1c4293cb | 228 | |
bba3f9b5 | 229 | pg->AppendIn(carProp, new wxIntProperty(wxT("Engine Size (cc)"), |
1c4293cb | 230 | wxPG_LABEL, |
bba3f9b5 | 231 | 5707) ); |
1c4293cb | 232 | |
bba3f9b5 JS |
233 | wxPGProperty* speedsProp = pg->AppendIn(carProp, |
234 | new wxStringProperty(wxT("Speeds"), | |
235 | wxPG_LABEL, | |
236 | wxT("<composed>"))); | |
1c4293cb | 237 | |
bba3f9b5 JS |
238 | pg->AppendIn( speedsProp, new wxIntProperty(wxT("Max. Speed (mph)"), |
239 | wxPG_LABEL,290) ); | |
240 | pg->AppendIn( speedsProp, new wxFloatProperty(wxT("0-100 mph (sec)"), | |
241 | wxPG_LABEL,3.9) ); | |
242 | pg->AppendIn( speedsProp, new wxFloatProperty(wxT("1/4 mile (sec)"), | |
243 | wxPG_LABEL,8.6) ); | |
1c4293cb | 244 | |
bba3f9b5 | 245 | // This is how child property can be referred to by name |
1c4293cb VZ |
246 | pg->SetPropertyValue( wxT("Car.Speeds.Max. Speed (mph)"), 300 ); |
247 | ||
bba3f9b5 JS |
248 | pg->AppendIn(carProp, new wxIntProperty(wxT("Price ($)"), |
249 | wxPG_LABEL, | |
250 | 300000) ); | |
251 | ||
252 | // Displayed value of "Car" property is now very close to this: | |
253 | // "Lamborghini Diablo SV; 5707 [300; 3.9; 8.6] 300000" | |
1c4293cb VZ |
254 | |
255 | @endcode | |
256 | ||
216214f8 | 257 | @section propgrid_enumandflags wxEnumProperty and wxFlagsProperty |
1c4293cb VZ |
258 | |
259 | wxEnumProperty is used when you want property's (integer or string) value | |
260 | to be selected from a popup list of choices. | |
261 | ||
bba3f9b5 JS |
262 | Creating wxEnumProperty is slightly more complex than those described |
263 | earlier. You have to provide list of constant labels, and optionally relevant | |
264 | values (if label indexes are not sufficient). | |
1c4293cb VZ |
265 | |
266 | @remarks | |
267 | ||
939d9364 JS |
268 | - Value wxPG_INVALID_VALUE (equals INT_MAX) is not allowed as list |
269 | item value. | |
1c4293cb VZ |
270 | |
271 | A very simple example: | |
272 | ||
273 | @code | |
274 | ||
275 | // | |
276 | // Using wxArrayString | |
277 | // | |
278 | wxArrayString arrDiet; | |
279 | arr.Add(wxT("Herbivore")); | |
280 | arr.Add(wxT("Carnivore")); | |
281 | arr.Add(wxT("Omnivore")); | |
282 | ||
283 | pg->Append( new wxEnumProperty(wxT("Diet"), | |
284 | wxPG_LABEL, | |
285 | arrDiet) ); | |
286 | ||
1c4293cb VZ |
287 | // |
288 | // Using wxChar* array | |
289 | // | |
290 | const wxChar* arrayDiet[] = | |
291 | { wxT("Herbivore"), wxT("Carnivore"), wxT("Omnivore"), NULL }; | |
292 | ||
293 | pg->Append( new wxEnumProperty(wxT("Diet"), | |
294 | wxPG_LABEL, | |
295 | arrayDiet) ); | |
296 | ||
1c4293cb VZ |
297 | @endcode |
298 | ||
299 | Here's extended example using values as well: | |
300 | ||
301 | @code | |
302 | ||
303 | // | |
304 | // Using wxArrayString and wxArrayInt | |
305 | // | |
306 | wxArrayString arrDiet; | |
307 | arr.Add(wxT("Herbivore")); | |
308 | arr.Add(wxT("Carnivore")); | |
309 | arr.Add(wxT("Omnivore")); | |
310 | ||
311 | wxArrayInt arrIds; | |
312 | arrIds.Add(40); | |
313 | arrIds.Add(45); | |
314 | arrIds.Add(50); | |
315 | ||
316 | // Note that the initial value (the last argument) is the actual value, | |
317 | // not index or anything like that. Thus, our value selects "Omnivore". | |
318 | pg->Append( new wxEnumProperty(wxT("Diet"), | |
319 | wxPG_LABEL, | |
320 | arrDiet, | |
321 | arrIds, | |
322 | 50)); | |
323 | ||
1c4293cb VZ |
324 | @endcode |
325 | ||
326 | wxPGChoices is a class where wxEnumProperty, and other properties which | |
bba3f9b5 JS |
327 | require storage for list of items, actually stores strings and values. It is |
328 | used to facilitate reference counting, and therefore recommended way of | |
1c4293cb VZ |
329 | adding items when multiple properties share the same set. |
330 | ||
331 | You can use wxPGChoices directly as well, filling it and then passing it | |
bba3f9b5 | 332 | to the constructor. In fact, if you wish to display bitmaps next to labels, |
1c4293cb VZ |
333 | your best choice is to use this approach. |
334 | ||
335 | @code | |
336 | ||
337 | wxPGChoices chs; | |
bba3f9b5 JS |
338 | chs.Add(wxT("Herbivore"), 40); |
339 | chs.Add(wxT("Carnivore"), 45); | |
340 | chs.Add(wxT("Omnivore"), 50); | |
1c4293cb VZ |
341 | |
342 | // Let's add an item with bitmap, too | |
343 | chs.Add(wxT("None of the above"), wxBitmap(), 60); | |
344 | ||
939d9364 | 345 | pg->Append( new wxEnumProperty(wxT("Primary Diet"), |
1c4293cb VZ |
346 | wxPG_LABEL, |
347 | chs) ); | |
348 | ||
349 | // Add same choices to another property as well - this is efficient due | |
350 | // to reference counting | |
939d9364 | 351 | pg->Append( new wxEnumProperty(wxT("Secondary Diet"), |
1c4293cb VZ |
352 | wxPG_LABEL, |
353 | chs) ); | |
1c4293cb VZ |
354 | @endcode |
355 | ||
d5774494 JS |
356 | You can later change choices of property by using wxPGProperty::AddChoice(), |
357 | wxPGProperty::InsertChoice(), wxPGProperty::DeleteChoice(), and | |
358 | wxPGProperty::SetChoices(). | |
1c4293cb | 359 | |
bba3f9b5 JS |
360 | <b>wxEditEnumProperty</b> works exactly like wxEnumProperty, except |
361 | is uses non-read-only combo box as default editor, and value is stored as | |
1c4293cb VZ |
362 | string when it is not any of the choices. |
363 | ||
939d9364 | 364 | wxFlagsProperty has similar construction: |
1c4293cb VZ |
365 | |
366 | @code | |
367 | ||
368 | const wxChar* flags_prop_labels[] = { wxT("wxICONIZE"), | |
369 | wxT("wxCAPTION"), wxT("wxMINIMIZE_BOX"), wxT("wxMAXIMIZE_BOX"), NULL }; | |
370 | ||
371 | // this value array would be optional if values matched string indexes | |
372 | long flags_prop_values[] = { wxICONIZE, wxCAPTION, wxMINIMIZE_BOX, | |
373 | wxMAXIMIZE_BOX }; | |
374 | ||
375 | pg->Append( new wxFlagsProperty(wxT("Window Style"), | |
376 | wxPG_LABEL, | |
377 | flags_prop_labels, | |
378 | flags_prop_values, | |
379 | wxDEFAULT_FRAME_STYLE) ); | |
380 | ||
381 | @endcode | |
382 | ||
383 | wxFlagsProperty can use wxPGChoices just the same way as wxEnumProperty | |
bba3f9b5 | 384 | <b>Note:</b> When changing "choices" (ie. flag labels) of wxFlagsProperty, |
939d9364 | 385 | you will need to use wxPGProperty::SetChoices() to replace all choices |
bba3f9b5 | 386 | at once - otherwise implicit child properties will not get updated properly. |
1c4293cb | 387 | |
216214f8 | 388 | @section propgrid_advprops Specialized Properties |
1c4293cb VZ |
389 | |
390 | This section describes the use of less often needed property classes. | |
391 | To use them, you have to include <wx/propgrid/advprops.h>. | |
392 | ||
393 | @code | |
394 | ||
395 | // Necessary extra header file | |
396 | #include <wx/propgrid/advprops.h> | |
397 | ||
398 | ... | |
399 | ||
400 | // Date property. | |
401 | pg->Append( new wxDateProperty(wxT("MyDateProperty"), | |
402 | wxPG_LABEL, | |
403 | wxDateTime::Now()) ); | |
404 | ||
bba3f9b5 | 405 | // Image file property. Wild card is auto-generated from available |
1c4293cb VZ |
406 | // image handlers, so it is not set this time. |
407 | pg->Append( new wxImageFileProperty(wxT("Label of ImageFileProperty"), | |
408 | wxT("NameOfImageFileProp")) ); | |
409 | ||
410 | // Font property has sub-properties. Note that we give window's font as | |
411 | // initial value. | |
412 | pg->Append( new wxFontProperty(wxT("Font"), | |
413 | wxPG_LABEL, | |
414 | GetFont()) ); | |
415 | ||
416 | // Colour property with arbitrary colour. | |
417 | pg->Append( new wxColourProperty(wxT("My Colour 1"), | |
418 | wxPG_LABEL, | |
419 | wxColour(242,109,0) ) ); | |
420 | ||
421 | // System colour property. | |
422 | pg->Append( new wxSystemColourProperty(wxT("My SysColour 1"), | |
423 | wxPG_LABEL, | |
424 | wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) ); | |
425 | ||
426 | // System colour property with custom colour. | |
427 | pg->Append( new wxSystemColourProperty(wxT("My SysColour 2"), | |
428 | wxPG_LABEL, | |
429 | wxColour(0,200,160) ) ); | |
430 | ||
431 | // Cursor property | |
432 | pg->Append( new wxCursorProperty(wxT("My Cursor"), | |
433 | wxPG_LABEL, | |
434 | wxCURSOR_ARROW)); | |
435 | ||
436 | @endcode | |
437 | ||
438 | ||
bba3f9b5 JS |
439 | @section propgrid_processingvalues Processing Property Values |
440 | ||
441 | Properties store their values internally in wxVariant. You can obtain | |
442 | this value using wxPGProperty::GetValue() or wxPropertyGridInterface:: | |
443 | GetPropertyValue(). | |
444 | ||
445 | If you wish to obtain property value in specific data type, you can | |
446 | call various getter functions, such as wxPropertyGridInterface:: | |
447 | GetPropertyValueAsString(), which, as name might say, returns property | |
448 | value's string representation. While this particular function is very | |
449 | safe to use for any kind of property, some might display error message | |
450 | if property value is not in compatible enough format. For instance, | |
451 | wxPropertyGridInterface::GetPropertyValueAsLongLong() will support | |
452 | long as well as wxLongLong, but GetPropertyValueAsArrayString() only | |
453 | supports wxArrayString and nothing else. | |
454 | ||
455 | In any case, you will need to take extra care when dealing with | |
456 | raw wxVariant values. For instance, wxIntProperty and wxUIntProperty, | |
457 | store value internally as wx(U)LongLong when number doesn't fit into | |
a6162a3e JS |
458 | standard long type. Using << operator to get wx(U)LongLong from wxVariant |
459 | is customized to work quite safely with various types of variant data. | |
bba3f9b5 JS |
460 | |
461 | You may have noticed that properties store, in wxVariant, values of many | |
462 | types which are not natively supported by it. Custom wxVariantDatas | |
463 | are therefore implemented and << and >> operators implemented to | |
464 | convert data from and to wxVariant. | |
465 | ||
466 | Note that in some cases property value can be Null variant, which means | |
467 | that property value is unspecified. This usually occurs only when | |
468 | wxPG_EX_AUTO_UNSPECIFIED_VALUES extra window style is defined or when you | |
469 | manually set property value to Null (or unspecified). | |
470 | ||
471 | ||
216214f8 | 472 | @section propgrid_iterating Iterating through a property container |
1c4293cb VZ |
473 | |
474 | You can use somewhat STL'ish iterator classes to iterate through the grid. | |
475 | Here is a simple example of forward iterating through all individual | |
bba3f9b5 JS |
476 | properties (not categories nor private child properties that are normally |
477 | 'transparent' to application code): | |
1c4293cb VZ |
478 | |
479 | @code | |
480 | ||
481 | wxPropertyGridIterator it; | |
482 | ||
483 | for ( it = pg->GetIterator(); | |
484 | !it.AtEnd(); | |
485 | it++ ) | |
486 | { | |
487 | wxPGProperty* p = *it; | |
488 | // Do something with the property | |
489 | } | |
490 | ||
491 | @endcode | |
492 | ||
493 | As expected there is also a const iterator: | |
494 | ||
495 | @code | |
496 | ||
497 | wxPropertyGridConstIterator it; | |
498 | ||
499 | for ( it = pg->GetIterator(); | |
500 | !it.AtEnd(); | |
501 | it++ ) | |
502 | { | |
503 | const wxPGProperty* p = *it; | |
504 | // Do something with the property | |
505 | } | |
506 | ||
507 | @endcode | |
508 | ||
509 | You can give some arguments to GetIterator to determine which properties | |
510 | get automatically filtered out. For complete list of options, see | |
b55018ec JS |
511 | @ref propgrid_iterator_flags. GetIterator() also accepts other arguments. |
512 | See wxPropertyGridInterface::GetIterator() for details. | |
1c4293cb VZ |
513 | |
514 | This example reverse-iterates through all visible items: | |
515 | ||
516 | @code | |
517 | ||
518 | wxPropertyGridIterator it; | |
519 | ||
520 | for ( it = pg->GetIterator(wxPG_ITERATE_VISIBLE, wxBOTTOM); | |
521 | !it.AtEnd(); | |
522 | it-- ) | |
523 | { | |
524 | wxPGProperty* p = *it; | |
525 | // Do something with the property | |
526 | } | |
527 | ||
528 | @endcode | |
529 | ||
530 | <b>wxPython Note:</b> Instead of ++ operator, use Next() method, and instead of | |
531 | * operator, use GetProperty() method. | |
532 | ||
533 | GetIterator() only works with wxPropertyGrid and the individual pages | |
534 | of wxPropertyGridManager. In order to iterate through an arbitrary | |
bba3f9b5 JS |
535 | property container (such as entire wxPropertyGridManager), you need to use |
536 | wxPropertyGridInterface::GetVIterator(). Note however that this virtual | |
537 | iterator is limited to forward iteration. | |
1c4293cb VZ |
538 | |
539 | @code | |
540 | ||
541 | wxPGVIterator it; | |
542 | ||
543 | for ( it = manager->GetVIterator(); | |
544 | !it.AtEnd(); | |
545 | it.Next() ) | |
546 | { | |
547 | wxPGProperty* p = it.GetProperty(); | |
548 | // Do something with the property | |
549 | } | |
550 | ||
551 | @endcode | |
552 | ||
216214f8 | 553 | @section propgrid_populating Populating wxPropertyGrid Automatically |
1c4293cb | 554 | |
216214f8 | 555 | @subsection propgrid_fromvariants Populating from List of wxVariants |
1c4293cb VZ |
556 | |
557 | Example of populating an empty wxPropertyGrid from a values stored | |
558 | in an arbitrary list of wxVariants. | |
559 | ||
560 | @code | |
561 | ||
bba3f9b5 | 562 | // This is a static method that initializes *all* built-in type handlers |
1c4293cb VZ |
563 | // available, including those for wxColour and wxFont. Refers to *all* |
564 | // included properties, so when compiling with static library, this | |
bba3f9b5 | 565 | // method may increase the executable size noticeably. |
1c4293cb VZ |
566 | pg->InitAllTypeHandlers(); |
567 | ||
568 | // Get contents of the grid as a wxVariant list | |
569 | wxVariant all_values = pg->GetPropertyValues(); | |
570 | ||
571 | // Populate the list with values. If a property with appropriate | |
572 | // name is not found, it is created according to the type of variant. | |
573 | pg->SetPropertyValues( my_list_variant ); | |
574 | ||
1c4293cb VZ |
575 | @endcode |
576 | ||
216214f8 | 577 | @subsection propgrid_fromfile Loading Population from a Text-based Storage |
1c4293cb VZ |
578 | |
579 | Class wxPropertyGridPopulator may be helpful when writing code that | |
bba3f9b5 JS |
580 | loads properties from a text-source. In fact, the wxPropertyGrid xrc-handler |
581 | (which may not be currently included in wxWidgets, but probably will be in | |
582 | near future) uses it. | |
1c4293cb | 583 | |
bba3f9b5 | 584 | @subsection editablestate Saving and Restoring User-Editable State |
1c4293cb | 585 | |
bba3f9b5 JS |
586 | You can use wxPropertyGridInterface::SaveEditableState() and |
587 | wxPropertyGridInterface::RestoreEditableState() to save and restore | |
588 | user-editable state (selected property, expanded/collapsed properties, | |
589 | selected page, scrolled position, and splitter positions). | |
1c4293cb | 590 | |
216214f8 | 591 | @section propgrid_events Event Handling |
1c4293cb VZ |
592 | |
593 | Probably the most important event is the Changed event which occurs when | |
594 | value of any property is changed by the user. Use EVT_PG_CHANGED(id,func) | |
595 | in your event table to use it. | |
596 | ||
597 | For complete list of event types, see wxPropertyGrid class reference. | |
598 | ||
bba3f9b5 JS |
599 | However, one type of event that might need focused attention is EVT_PG_CHANGING, |
600 | which occurs just prior property value is being changed by user. You can | |
601 | acquire pending value using wxPropertyGridEvent::GetValue(), and if it is | |
602 | not acceptable, call wxPropertyGridEvent::Veto() to prevent the value change | |
603 | from taking place. | |
1c4293cb VZ |
604 | |
605 | @code | |
606 | ||
1c4293cb VZ |
607 | void MyForm::OnPropertyGridChanging( wxPropertyGridEvent& event ) |
608 | { | |
609 | wxPGProperty* property = event.GetProperty(); | |
610 | ||
611 | if ( property == m_pWatchThisProperty ) | |
612 | { | |
613 | // GetValue() returns the pending value, but is only | |
614 | // supported by wxEVT_PG_CHANGING. | |
615 | if ( event.GetValue().GetString() == g_pThisTextIsNotAllowed ) | |
616 | { | |
617 | event.Veto(); | |
618 | return; | |
619 | } | |
620 | } | |
621 | } | |
622 | ||
623 | @endcode | |
624 | ||
bba3f9b5 JS |
625 | @remarks On Child Property Event Handling |
626 | - For properties which have private, implicit children (wxFontProperty and | |
627 | wxFlagsProperty), events occur for the main parent property only. | |
628 | For other properties events occur for the children themselves. See | |
629 | @ref propgrid_parentprops. | |
1c4293cb | 630 | |
bba3f9b5 | 631 | - When property's child gets changed, you can use wxPropertyGridEvent::GetMainParent() |
1c4293cb VZ |
632 | to obtain its topmost non-category parent (useful, if you have deeply nested |
633 | properties). | |
634 | ||
635 | ||
216214f8 | 636 | @section propgrid_validating Validating Property Values |
1c4293cb VZ |
637 | |
638 | There are various ways to make sure user enters only correct values. First, you | |
639 | can use wxValidators similar to as you would with ordinary controls. Use | |
640 | wxPropertyGridInterface::SetPropertyValidator() to assign wxValidator to | |
641 | property. | |
642 | ||
643 | Second, you can subclass a property and override wxPGProperty::ValidateValue(), | |
bba3f9b5 | 644 | or handle wxEVT_PG_CHANGING for the same effect. Both of these ways do not |
1c4293cb VZ |
645 | actually prevent user from temporarily entering invalid text, but they do give |
646 | you an opportunity to warn the user and block changed value from being committed | |
647 | in a property. | |
648 | ||
649 | Various validation failure options can be controlled globally with | |
650 | wxPropertyGrid::SetValidationFailureBehavior(), or on an event basis by | |
651 | calling wxEvent::SetValidationFailureBehavior(). Here's a code snippet of | |
652 | how to handle wxEVT_PG_CHANGING, and to set custom failure behaviour and | |
653 | message. | |
654 | ||
655 | @code | |
656 | void MyFrame::OnPropertyGridChanging(wxPropertyGridEvent& event) | |
657 | { | |
658 | wxPGProperty* property = event.GetProperty(); | |
659 | ||
660 | // You must use wxPropertyGridEvent::GetValue() to access | |
661 | // the value to be validated. | |
662 | wxVariant pendingValue = event.GetValue(); | |
663 | ||
664 | if ( property->GetName() == wxT("Font") ) | |
665 | { | |
666 | // Make sure value is not unspecified | |
667 | if ( !pendingValue.IsNull() ) | |
668 | { | |
bba3f9b5 JS |
669 | wxFont font; |
670 | font << pendingValue; | |
1c4293cb VZ |
671 | |
672 | // Let's just allow Arial font | |
673 | if ( font.GetFaceName() != wxT("Arial") ) | |
674 | { | |
675 | event.Veto(); | |
676 | event.SetValidationFailureBehavior(wxPG_VFB_STAY_IN_PROPERTY | | |
677 | wxPG_VFB_BEEP | | |
678 | wxPG_VFB_SHOW_MESSAGE); | |
679 | } | |
680 | } | |
681 | } | |
682 | } | |
683 | @endcode | |
684 | ||
685 | ||
216214f8 | 686 | @section propgrid_cellrender Customizing Individual Cell Appearance |
1c4293cb VZ |
687 | |
688 | You can control text colour, background colour, and attached image of | |
689 | each cell in the property grid. Use wxPropertyGridInterface::SetPropertyCell() or | |
690 | wxPGProperty::SetCell() for this purpose. | |
691 | ||
692 | In addition, it is possible to control these characteristics for | |
bba3f9b5 | 693 | wxPGChoices list items. See wxPGChoices class reference for more info. |
1c4293cb VZ |
694 | |
695 | ||
216214f8 | 696 | @section propgrid_customizing Customizing Properties (without sub-classing) |
1c4293cb VZ |
697 | |
698 | In this section are presented miscellaneous ways to have custom appearance | |
699 | and behavior for your properties without all the necessary hassle | |
700 | of sub-classing a property class etc. | |
701 | ||
216214f8 | 702 | @subsection propgrid_customimage Setting Value Image |
1c4293cb VZ |
703 | |
704 | Every property can have a small value image placed in front of the | |
705 | actual value text. Built-in example of this can be seen with | |
706 | wxColourProperty and wxImageFileProperty, but for others it can | |
707 | be set using wxPropertyGrid::SetPropertyImage method. | |
708 | ||
216214f8 | 709 | @subsection propgrid_customeditor Setting Property's Editor Control(s) |
1c4293cb VZ |
710 | |
711 | You can set editor control (or controls, in case of a control and button), | |
712 | of any property using wxPropertyGrid::SetPropertyEditor. Editors are passed | |
bba3f9b5 | 713 | as wxPGEditor_EditorName, and valid built-in EditorNames are |
1c4293cb VZ |
714 | TextCtrl, Choice, ComboBox, CheckBox, TextCtrlAndButton, ChoiceAndButton, |
715 | SpinCtrl, and DatePickerCtrl. Two last mentioned ones require call to | |
716 | static member function wxPropertyGrid::RegisterAdditionalEditors(). | |
717 | ||
718 | Following example changes wxColourProperty's editor from default Choice | |
719 | to TextCtrlAndButton. wxColourProperty has its internal event handling set | |
720 | up so that button click events of the button will be used to trigger | |
721 | colour selection dialog. | |
722 | ||
723 | @code | |
724 | ||
bba3f9b5 JS |
725 | wxPGProperty* colProp = new wxColourProperty(wxT("Text Colour")); |
726 | pg->Append(colProp); | |
727 | pg->SetPropertyEditor(colProp, wxPGEditor_TextCtrlAndButton); | |
1c4293cb VZ |
728 | |
729 | @endcode | |
730 | ||
731 | Naturally, creating and setting custom editor classes is a possibility as | |
732 | well. For more information, see wxPGEditor class reference. | |
733 | ||
216214f8 | 734 | @subsection propgrid_editorattrs Property Attributes Recognized by Editors |
1c4293cb | 735 | |
bba3f9b5 JS |
736 | <b>SpinCtrl</b> editor can make use of property's "Min", "Max", "Step" and |
737 | "Wrap" attributes. | |
1c4293cb | 738 | |
216214f8 | 739 | @subsection propgrid_multiplebuttons Adding Multiple Buttons Next to an Editor |
1c4293cb VZ |
740 | |
741 | See wxPGMultiButton class reference. | |
742 | ||
216214f8 | 743 | @subsection propgrid_customeventhandling Handling Events Passed from Properties |
1c4293cb VZ |
744 | |
745 | <b>wxEVT_COMMAND_BUTTON_CLICKED </b>(corresponds to event table macro EVT_BUTTON): | |
746 | Occurs when editor button click is not handled by the property itself | |
747 | (as is the case, for example, if you set property's editor to TextCtrlAndButton | |
748 | from the original TextCtrl). | |
749 | ||
216214f8 | 750 | @subsection propgrid_attributes Property Attributes |
1c4293cb VZ |
751 | |
752 | Miscellaneous values, often specific to a property type, can be set | |
bba3f9b5 JS |
753 | using wxPropertyGridInterface::SetPropertyAttribute() and |
754 | wxPropertyGridInterface::SetPropertyAttributeAll() methods. | |
1c4293cb VZ |
755 | |
756 | Attribute names are strings and values wxVariant. Arbitrary names are allowed | |
bba3f9b5 JS |
757 | in order to store values that are relevant to application only and not |
758 | property grid. Constant equivalents of all attribute string names are | |
759 | provided. Some of them are defined as cached strings, so using these constants | |
760 | can provide for smaller binary size. | |
1c4293cb | 761 | |
b55018ec | 762 | For complete list of attributes, see @ref propgrid_property_attributes. |
1c4293cb | 763 | |
1c4293cb | 764 | |
216214f8 | 765 | @section propgrid_usage2 Using wxPropertyGridManager |
1c4293cb VZ |
766 | |
767 | wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid, | |
bba3f9b5 JS |
768 | which can optionally have tool bar for mode and page selection, and a help text |
769 | box. For more information, see wxPropertyGridManager class reference. | |
1c4293cb | 770 | |
216214f8 | 771 | @subsection propgrid_propgridpage wxPropertyGridPage |
1c4293cb VZ |
772 | |
773 | wxPropertyGridPage is holder of properties for one page in manager. It is derived from | |
774 | wxEvtHandler, so you can subclass it to process page-specific property grid events. Hand | |
bba3f9b5 | 775 | over your page instance in wxPropertyGridManager::AddPage(). |
1c4293cb VZ |
776 | |
777 | Please note that the wxPropertyGridPage itself only sports subset of wxPropertyGrid API | |
778 | (but unlike manager, this include item iteration). Naturally it inherits from | |
bba3f9b5 | 779 | wxPropertyGridInterface. |
1c4293cb | 780 | |
bba3f9b5 | 781 | For more information, see wxPropertyGridPage class reference. |
1c4293cb | 782 | |
bba3f9b5 JS |
783 | |
784 | @section propgrid_subclassing Sub-classing wxPropertyGrid and wxPropertyGridManager | |
1c4293cb VZ |
785 | |
786 | Few things to note: | |
787 | ||
788 | - Only a small percentage of member functions are virtual. If you need more, | |
789 | just e-mail to wx-dev mailing list. | |
790 | ||
791 | - Data manipulation is done in wxPropertyGridPageState class. So, instead of | |
bba3f9b5 JS |
792 | overriding wxPropertyGrid::Insert(), you'll probably want to override |
793 | wxPropertyGridPageState::DoInsert(). See header file for details. | |
1c4293cb | 794 | |
bba3f9b5 JS |
795 | - Override wxPropertyGrid::CreateState() to instantiate your derivate |
796 | wxPropertyGridPageState. For wxPropertyGridManager, you'll need to subclass | |
797 | wxPropertyGridPage instead (since it is derived from wxPropertyGridPageState), | |
798 | and hand over instances in wxPropertyGridManager::AddPage() calls. | |
1c4293cb | 799 | |
bba3f9b5 JS |
800 | - You can use a derivate wxPropertyGrid with manager by overriding |
801 | wxPropertyGridManager::CreatePropertyGrid() member function. | |
1c4293cb VZ |
802 | |
803 | ||
216214f8 | 804 | @section propgrid_misc Miscellaneous Topics |
1c4293cb | 805 | |
216214f8 | 806 | @subsection propgrid_namescope Property Name Scope |
1c4293cb | 807 | |
258ccb95 JS |
808 | All properties which parent is category or root can be accessed |
809 | directly by their base name (ie. name given for property in its constructor). | |
810 | Other properties can be accessed via "ParentsName.BaseName" notation, | |
811 | Naturally, all property names should be unique. | |
1c4293cb | 812 | |
216214f8 | 813 | @subsection propgrid_nonuniquelabels Non-unique Labels |
258ccb95 JS |
814 | |
815 | It is possible to have properties with identical label under same parent. | |
816 | However, care must be taken to ensure that each property still has | |
817 | unique (base) name. | |
1c4293cb | 818 | |
216214f8 | 819 | @subsection propgrid_boolproperty wxBoolProperty |
1c4293cb | 820 | |
bba3f9b5 JS |
821 | There are few points about wxBoolProperty that require further discussion: |
822 | - wxBoolProperty can be shown as either normal combo box or as a check box. | |
1c4293cb VZ |
823 | Property attribute wxPG_BOOL_USE_CHECKBOX is used to change this. |
824 | For example, if you have a wxFlagsProperty, you can | |
825 | set its all items to use check box using the following: | |
826 | @code | |
827 | pg->SetPropertyAttribute(wxT("MyFlagsProperty"),wxPG_BOOL_USE_CHECKBOX,true,wxPG_RECURSE); | |
828 | @endcode | |
bba3f9b5 JS |
829 | |
830 | Following will set all individual bool properties in your control to | |
831 | use check box: | |
832 | ||
833 | @code | |
834 | pg->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX, true); | |
835 | @endcode | |
1c4293cb | 836 | |
939d9364 | 837 | - Default item names for wxBoolProperty are ["False", "True"]. This can be |
bba3f9b5 JS |
838 | changed using static function wxPropertyGrid::SetBoolChoices(trueChoice, |
839 | falseChoice). | |
1c4293cb | 840 | |
216214f8 | 841 | @subsection propgrid_textctrlupdates Updates from wxTextCtrl Based Editor |
1c4293cb VZ |
842 | |
843 | Changes from wxTextCtrl based property editors are committed (ie. | |
844 | wxEVT_PG_CHANGED is sent etc.) *only* when (1) user presser enter, (2) | |
845 | user moves to edit another property, or (3) when focus leaves | |
846 | the grid. | |
847 | ||
848 | Because of this, you may find it useful, in some apps, to call | |
849 | wxPropertyGrid::CommitChangesFromEditor() just before you need to do any | |
850 | computations based on property grid values. Note that CommitChangesFromEditor() | |
851 | will dispatch wxEVT_PG_CHANGED with ProcessEvent, so any of your event handlers | |
852 | will be called immediately. | |
853 | ||
216214f8 | 854 | @subsection propgrid_splittercentering Centering the Splitter |
1c4293cb VZ |
855 | |
856 | If you need to center the splitter, but only once when the program starts, | |
857 | then do <b>not</b> use the wxPG_SPLITTER_AUTO_CENTER window style, but the | |
858 | wxPropertyGrid::CenterSplitter() method. <b>However, be sure to call it after | |
859 | the sizer setup and SetSize calls!</b> (ie. usually at the end of the | |
860 | frame/dialog constructor) | |
861 | ||
216214f8 | 862 | @subsection propgrid_splittersetting Setting Splitter Position When Creating Property Grid |
1c4293cb VZ |
863 | |
864 | Splitter position cannot exceed grid size, and therefore setting it during | |
865 | form creation may fail as initial grid size is often smaller than desired | |
866 | splitter position, especially when sizers are being used. | |
867 | ||
216214f8 | 868 | @subsection propgrid_colourproperty wxColourProperty and wxSystemColourProperty |
1c4293cb | 869 | |
bba3f9b5 | 870 | Through sub-classing, these two property classes provide substantial customization |
1c4293cb VZ |
871 | features. Subclass wxSystemColourProperty if you want to use wxColourPropertyValue |
872 | (which features colour type in addition to wxColour), and wxColourProperty if plain | |
873 | wxColour is enough. | |
874 | ||
875 | Override wxSystemColourProperty::ColourToString() to redefine how colours are | |
876 | printed as strings. | |
877 | ||
878 | Override wxSystemColourProperty::GetCustomColourIndex() to redefine location of | |
879 | the item that triggers colour picker dialog (default is last). | |
880 | ||
881 | Override wxSystemColourProperty::GetColour() to determine which colour matches | |
882 | which choice entry. | |
883 | ||
216214f8 | 884 | @section propgrid_proplist Property Class Descriptions |
1c4293cb VZ |
885 | |
886 | See @ref pgproperty_properties | |
887 | ||
888 | */ | |
889 |