propgrid.h 40 KB

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