Attribute Editor API Overview
Attribute Editors provide a way to present information to the user in a way that is customized based on the type of the value being presented. When a value needs to be displayed in some context, the specifics of how to display that value are handled by the Attribute Editor, so the displaying context doesn't need to know those details. This simplifies the work of building a View or other display context, and helps ensure that values displayed in multiple contexts appear and behave uniformly. CPIA Attribute Editors are derived from wxWidgets AttributeEditor and AttributeRenderer classes.
Overview
We'd like Attribute Editors to be written by a wide variety of authors in the open source community, and we'd like to see them used in several different contexts. Currently Attribute Editors are invoked to draw entries in Tables (Grid items), and inside an Attribute Editor Block. In writting the Attribute Editor Block I became aware that the API makes it difficult to write some of the Attribute Editors that I had envisioned. These restrictions come from the Table/Grid invokation process. We've defined an API that allows an Attribute Editor to operate in a restricted mode when being invoked from the Table/Grid context, but without those restrictions in other contexts. The two main restriction for the Grid context are:
- When a control is created. The Grid context doesn't facilitate having a control to present the information, but requires one when editing the information.
- Storage for information associated with individual values. Because many Grid elements share a single Attribute Editor Instance, there's no convenient place to store information associated with individual elements and their values.
API Overview
For complete details, and the lastest information on the API, see the auto-generated documentation. Here we simply present an overview of the API at a conceptual level:
Public API to an Attribute Editor
__init__(self, isShared, presentationStyle=None)
- Create a shared, or unshared instance of an Attribute Editor.
- A single shared instance is used for all Grid entries in all Tables.
- Individual instances are created for each AEBlock, or other non-Grid context.
- When not shared, a presentationStyle is passed in to the Attribute Editor, so it can present itself in an enhanced style.
ReadOnly (self, (item, attribute))
- Should return True iff this Attribute Editor refuses to edit.
Draw (self, dc, rect, item, attributeName, isSelected)
- Draw the value of the attribute in the specified rect of the dc
Create (self, parent, id)
- Create and return a control to use for editing the attribute value.
BeginControlEdit (self, control, value)
- Prepare the control to begin editing the value
EndControlEdit (self, item, attributeName, control)
- End editing the value.
- Called before destroying the control created in Create().
GetControlValue (self, control)
- Get the value from the control.
SetControlValue (self, control, value)
- Set the value in the control.
GetAttributeValue (self, item, attributeName)
- Get the value from the specified attribute of the item, and convert to the type needed by the control.
SetAttributeValue (self, item, attributeName, value)
- Set the value of the attribute given by the value. Should convert the value from the type used by the control to the native type of the attribute.
Informal API Conventions for an Attribute Editor
onKeyPressed(self, event)
- Handle a Key pressed in the control. May do validation or completion.
Notes
- Presentation Style is passed into the Attribute Editor, so it can provide multiple presentations for a given type.
- Type Conversion. Each AEs provides a GetAttribute (and optional SetAttribute) method that does any type conversion needed by that editor. For example, the DateTime AE converts to/from String because it uses the StringAttribute editor to display the value in a TextCtrl.
- Attribute Editors can be made to work with Python properties, as well as Python attributes, but there are some issues. See the issues section for details.
- The AEBlock rebinds the editor with each call to Synchronize, in order to get the best binding to the current attribute value.
- The default Attribute Editor is RepositoryAttributeEditor, which can edit any type of data the repository knows about in a text control, by using the repository's methods to convert to and from String.
Tasks
- Improve List handling. We don't have any framework support for cardinality=list. We're thinking we could look for an AE that explicitly handles lists of the given type first, then fall back on the type-general AE.
Issues
- Validation. It's up to the attribute editors to validate, but they could probably use some help from the AE framework.
- Using Python Properties instead of Chandler Attributes. For this to work smoothly, the setter for your property should be able to convert the value from the type used by the control presenting that property. When using the LabeledAttributeEditor there may be an issue determining the appropriate label, since it uses the display name of the Chandler attribute to determine the label and there is none for properties. See the _GetAttributeLabel method of LabeledAttributeEditor for more information.
Investigations
- Can we use AE's in an arbitrary canvas, like in the calendar? Probably will need to update the API for this, so the rect of the AE gets passed in to Init, Create, etc.