The property classes help a programmer to express relationships between data and physical windows, in particular:
With a consistent framework, the programmer should be able to use existing components and design new ones in a principled manner, to solve many data entry requirements.
Each datum is represented in a wxProperty, which has a name and a value. Various C++ types are permitted in the value of a property, and the property can store a pointer to the data instead of a copy of the data. A wxPropertySheet represents a number of these properties.
These two classes are independent from the way in which the data is visually manipulated. To mediate between property sheets and windows, the abstract class wxPropertyView is available for programmers to derive new kinds of view. One kind of view that is available is the wxPropertyListView, which displays the data in a Visual Basic-style list, with a small number of controls for editing the currently selected property. Another is wxPropertyFormView which mediates between an existing dialog or panel and the property sheet.
The hard work of mediation is actually performed by validators, which are instances of classes derived from wxPropertyValidator. A validator is associated with a particular property and is responsible for responding to user interface events, and displaying, updating and checking the property value. Because a validator's behaviour depends largely on the kind of view being used, there has to be a separate hierarchy of validators for each class of view. So for wxPropertyListView, there is an abstract class wxPropertyListValidator from which concrete classes are derived, such as wxRealListValidator and wxStringListValidator.
A validator can be explicitly set for a property, so there is no doubt which validator should be used to edit that property. However, it is also possible to define a registry of validators, and have the validator chosen on the basis of the role of the property. So a property with a "filename" role would match the "filename" validator, which pops up a file selector when the user double clicks on the property.
You don't have to define your own frame or window classes: there are some predefined that will work with the property list view. See Window classes for further details.
Example 1: Property list view
Example 2: Property form view
The following code fragment shows the essentials of creating a registry of standard validators, a property sheet containing some properties, and a property list view and dialog or frame. RegisterValidators will be called on program start, and PropertySheetTest is called in response to a menu command.
Note how some properties are created with an explicit reference to a validator, and others are provided with a "role'' which can be matched against a validator in the registry.
The interface generated by this test program is shown in the section Appearance and behaviour of a property list view.
void RegisterValidators(void) { myListValidatorRegistry.RegisterValidator((wxString)"real", new wxRealListValidator); myListValidatorRegistry.RegisterValidator((wxString)"string", new wxStringListValidator); myListValidatorRegistry.RegisterValidator((wxString)"integer", new wxIntegerListValidator); myListValidatorRegistry.RegisterValidator((wxString)"bool", new wxBoolListValidator); } void PropertyListTest(Bool useDialog) { wxPropertySheet *sheet = new wxPropertySheet; sheet->AddProperty(new wxProperty("fred", 1.0, "real")); sheet->AddProperty(new wxProperty("tough choice", (Bool)TRUE, "bool")); sheet->AddProperty(new wxProperty("ian", (long)45, "integer", new wxIntegerListValidator(-50, 50))); sheet->AddProperty(new wxProperty("bill", 25.0, "real", new wxRealListValidator(0.0, 100.0))); sheet->AddProperty(new wxProperty("julian", "one", "string")); sheet->AddProperty(new wxProperty("bitmap", "none", "string", new wxFilenameListValidator("Select a bitmap file", "*.bmp"))); wxStringList *strings = new wxStringList("one", "two", "three", NULL); sheet->AddProperty(new wxProperty("constrained", "one", "string", new wxStringListValidator(strings))); wxPropertyListView *view = new wxPropertyListView(NULL, wxPROP_BUTTON_CHECK_CROSS|wxPROP_DYNAMIC_VALUE_FIELD|wxPROP_PULLDOWN); wxDialogBox *propDialog = NULL; wxPropertyListFrame *propFrame = NULL; if (useDialog) { propDialog = new wxPropertyListDialog(view, NULL, "Property Sheet Test", TRUE, -1, -1, 400, 500); } else { propFrame = new wxPropertyListFrame(view, NULL, "Property Sheet Test", -1, -1, 400, 500); } view->AddRegistry(&myListValidatorRegistry); if (useDialog) { view->ShowView(sheet, propDialog); propDialog->Centre(wxBOTH); propDialog->Show(TRUE); } else { propFrame->Initialize(); view->ShowView(sheet, propFrame->GetPropertyPanel()); propFrame->Centre(wxBOTH); propFrame->Show(TRUE); } }
This example is similar to Example 1, but uses a property form view to edit a property sheet using a predefined dialog box.
void RegisterValidators(void) { myFormValidatorRegistry.RegisterValidator((wxString)"real", new wxRealFormValidator); myFormValidatorRegistry.RegisterValidator((wxString)"string", new wxStringFormValidator); myFormValidatorRegistry.RegisterValidator((wxString)"integer", new wxIntegerFormValidator); myFormValidatorRegistry.RegisterValidator((wxString)"bool", new wxBoolFormValidator); } void PropertyFormTest(Bool useDialog) { wxPropertySheet *sheet = new wxPropertySheet; sheet->AddProperty(new wxProperty("fred", 25.0, "real", new wxRealFormValidator(0.0, 100.0))); sheet->AddProperty(new wxProperty("tough choice", (Bool)TRUE, "bool")); sheet->AddProperty(new wxProperty("ian", (long)45, "integer", new wxIntegerFormValidator(-50, 50))); sheet->AddProperty(new wxProperty("julian", "one", "string")); wxStringList *strings = new wxStringList("one", "two", "three", NULL); sheet->AddProperty(new wxProperty("constrained", "one", "string", new wxStringFormValidator(strings))); wxPropertyFormView *view = new wxPropertyFormView(NULL); wxDialogBox *propDialog = NULL; wxPropertyFormFrame *propFrame = NULL; if (useDialog) { propDialog = new wxPropertyFormDialog(view, NULL, "Property Form Test", TRUE, -1, -1, 400, 300); } else { propFrame = new wxPropertyFormFrame(view, NULL, "Property Form Test", -1, -1, 400, 300); propFrame->Initialize(); } wxPanel *panel = propDialog ? propDialog : propFrame->GetPropertyPanel(); panel->SetLabelPosition(wxVERTICAL); // Add items to the panel (void) new wxButton(panel, (wxFunction)NULL, "OK", -1, -1, -1, -1, 0, "ok"); (void) new wxButton(panel, (wxFunction)NULL, "Cancel", -1, -1, 80, -1, 0, "cancel"); (void) new wxButton(panel, (wxFunction)NULL, "Update", -1, -1, 80, -1, 0, "update"); (void) new wxButton(panel, (wxFunction)NULL, "Revert", -1, -1, -1, -1, 0, "revert"); panel->NewLine(); // The name of this text item matches the "fred" property (void) new wxText(panel, (wxFunction)NULL, "Fred", "", -1, -1, 90, -1, 0, "fred"); (void) new wxCheckBox(panel, (wxFunction)NULL, "Yes or no", -1, -1, -1, -1, 0, "tough choice"); (void) new wxSlider(panel, (wxFunction)NULL, "Sliding scale", 0, -50, 50, 100, -1, -1, wxHORIZONTAL, "ian"); panel->NewLine(); (void) new wxListBox(panel, (wxFunction)NULL, "Constrained", wxSINGLE, -1, -1, 100, 90, 0, NULL, 0, "constrained"); view->AddRegistry(&myFormValidatorRegistry); if (useDialog) { view->ShowView(sheet, propDialog); view->AssociateNames(); view->TransferToDialog(); propDialog->Centre(wxBOTH); propDialog->Show(TRUE); } else { view->ShowView(sheet, propFrame->GetPropertyPanel()); view->AssociateNames(); view->TransferToDialog(); propFrame->Centre(wxBOTH); propFrame->Show(TRUE); } }