-
Notifications
You must be signed in to change notification settings - Fork 263
Value Editors
Every property descriptor has an explicit or implicit value editor to allow a user to edit the property value described by the descriptor. The PropertyDescriptor.GetEditor()
method returns the editor for a given type. If the property descriptor class derived from PropertyDescriptor
does not implement GetEditor()
, the base PropertyDescriptor.GetEditor()
method is called:
public override object GetEditor(Type editorBaseType)
{
if (m_editor != null &&
editorBaseType.IsAssignableFrom(m_editor.GetType()))
{
return m_editor;
}
return base.GetEditor(editorBaseType);
}
If a value editor for the type editorBaseType
is not found, the base method System.ComponentModel.PropertyDescriptor.GetEditor()
is called, which returns a default editor for that type, assuming one can be found.
Note that the value editor is not a control itself. Instead, each value editor has a value editing control associated with it, described in Value Editors and Value Editing Controls. This value editing control class is not necessarily in the value editor class's file.
There are two types of value editors: those that derive from UITypeEditor
and those that don't. They can both implement the IPropertyEditor
interface, which obtains a value editing control object.
System.Drawing.Design.UITypeEditor is a base class for a value editor with a value editing control that either drops down, such as a color swatch, or displays a modal dialog, such as a file selection dialog. It may also display no interactive control at all, although this option is not used in ATF. The property editor for this property typically shows either a tab or an ellipsis button to display either the drop down control or dialog. The illustration below, for instance, shows the ColorEditor
drop down value editing control used in the ATF Timeline Editor Sample.
UITypeEditor
includes the following methods:
-
GetEditStyle()
: Get the editor style used byEditValue()
, a System.Drawing.Design.UITypeEditorEditStyle indicating the displayed control's style:Modal
,DropDown
, orNone
. -
EditValue()
: Edit the value of the specified object using an appropriate value editing control. This displays the a value editing control or modal dialog and returns the value after user selection. -
PaintValue()
: Paint a representation of the value of the specified object.
The following sections demonstrate several UITypeEditor
implementations.
The ATF Timeline Editor Sample's "timelineRef" type has a color attribute with a color value editor defined in an XML Schema annotation:
<scea.dom.editors.attribute name="color" displayName="Color" description="Display Color"
editor="Sce.Atf.Controls.PropertyEditing.ColorEditor,Atf.Gui"
converter="Sce.Atf.Controls.PropertyEditing.IntColorConverter" />
This value editing control for ColorEditor
is seen in the earlier illustration.
The Sce.Atf.Controls.PropertyEditing.ColorEditor.EditValue()
implementation is:
public override object EditValue(
ITypeDescriptorContext context,
IServiceProvider provider,
object value)
{
TypeConverter converter = context.PropertyDescriptor.Converter;
if (value == null)
value = Color.Transparent;
Color oldColor = (Color)converter.ConvertTo(value, typeof(Color)); // convert from underlying type to Color
Color newColor = (Color)base.EditValue(context, provider, oldColor);
return converter.ConvertFrom(newColor);
}
Note that this method gets the property descriptor (context.PropertyDescriptor
) from the context and then gets a value converter from the descriptor's Converter
property. It uses the converter to convert the old value to the Color
Type
with the ConvertTo()
method.
ATF's ColorEditor
derives from System.Drawing.Design.ColorEditor
, so the following line invokes the base class's EditValue()
method, which displays its own color picker:
Color newColor = (Color)base.EditValue(context, provider, oldColor);
This returned value is then converted to an appropriate form with the ConvertFrom()
method, and that converted value is returned by EditValue()
.
Here is Sce.Atf.Controls.PropertyEditing.ColorEditor.PaintValue()
:
public override void PaintValue(PaintValueEventArgs e)
{
if (e.Value is Color)
{
base.PaintValue(e);
}
else
{
TypeConverter converter = e.Context.PropertyDescriptor.Converter;
object value = converter.ConvertTo(e.Value, typeof(Color)); // convert from underlying type to Color
if (value is Color)
{
Color color = (Color)value;
base.PaintValue(new PaintValueEventArgs(e.Context, color, e.Graphics, e.Bounds));
}
}
}
This method uses the value converter to convert the new color to a Color
object, and then paints the new value using the base class's PaintValue()
method. For information on converters, see Value converters.
A PaintValue()
method is not needed if the control handles the painting. For instance, the BoundedIntEditor
value editor class implements just this EditValue()
method:
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorService =
provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
if (editorService != null)
{
if (!(value is int))
value = m_min;
IntInputControl intInputControl = new IntInputControl((int)value, m_min, m_max);
editorService.DropDownControl(intInputControl);
// be careful to return the same object if the value didn't change
if (!intInputControl.Value.Equals(value))
value = intInputControl.Value;
}
return value;
}
This EditValue()
method creates an IntInputControl
control (a separate class) that handles all control painting. Similarly, EnumUITypeEditor
provides a ListBox
control to list enumerated values and does not implement PaintValue
.
BoundedFloatEditor
creates a dropdown value editing control with a slider and textbox to enter a floating point number.
It implements GetEditStyle()
to specify how the control appears, dropdown in this case:
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
Its EditValue()
method gets a IWindowsFormsEditorService
object to display a control in a drop-down area and uses it to display a FloatInputControl
value editing control it creates and drops down with IWindowsFormsEditorService.DropDownControl()
:
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorService =
provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
if (editorService != null)
{
if (!(value is float))
value = m_min;
FloatInputControl floatInputControl = new FloatInputControl((float)value, m_min, m_max);
editorService.DropDownControl(floatInputControl);
// be careful to return the same object if the value didn't change
if (!floatInputControl.Value.Equals(value))
value = floatInputControl.Value;
}
return value;
}
This value editor displays a folder selection dialog, and its constructor creates this FolderBrowserDialog
for later use:
public FolderBrowserDialogUITypeEditor(string description)
{
// create instance of editing control,
// resuse this instance for subsequence calls
m_dialog = new FolderBrowserDialog();
m_dialog.Description = description;
}
Its GetEditStyle()
method indicates a modal dialog is displayed:
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.Modal; // editor type is modal dialog.
}
The EditValue()
method displays the FolderBrowserDialog
, gets the user's selected path from it, and returns this value:
public override object EditValue(ITypeDescriptorContext context, IServiceProvider sp, object value)
{
IWindowsFormsEditorService editorService =
(IWindowsFormsEditorService)sp.GetService(typeof(IWindowsFormsEditorService));
if (editorService != null)
{
if (value != null)
m_dialog.SelectedPath = value.ToString();
m_dialog.ShowDialog();
value = m_dialog.SelectedPath;
}
return value;
}
IPropertyEditor
contains this method to get the value editing control associated with the value editor:
Control GetEditingControl(PropertyEditorControlContext context);
For example, the BoundedIntEditor
value editor class implements IPropertyEditor
:
public virtual Control GetEditingControl(PropertyEditorControlContext context)
{
return new BoundedIntControl(context, m_min, m_max);
}
As noted previously, UITypeEditor
classes, of which BoundedIntEditor
is one, can also implement IPropertyEditor
but are not required to do so, because the UITypeEditor.EditValue()
method instantiates the value editing control. If a UITypeEditor
does implement IPropertyEditor
, it does not need to return the same control that it uses in UITypeEditor.EditValue()
, and these controls are indeed different for BoundedIntEditor
. As seen previously, BoundedIntEditor.EditValue()
uses IntInputControl
and BoundedIntEditor
.GetEditingControl()
returns a BoundedIntControl
, a protected class inside BoundedIntEditor
.
Property editors, containing value editors, ultimately derive from the PropertyView
class. When a selection occurs, PropertyView
calls PropertyDescriptor.GetEditor()
to get the value editor (for a property of an item in the selection) and determines if it implements IPropertyEditor
. If it does, IPropertyEditor.GetEditingControl()
is called to get the value editing control, which is used to edit the value. Otherwise, UITypeEditor.EditValue()
gets called to edit the value. Thus the IPropertyEditor
value editing control has priority and would be used — in ATF. However, a UITypeEditor
can be used with a .NET Framework two-column style property editor, because UITypeEditor
is a .NET Framework class. In this case, the control specified in the UITypeEditor.EditValue()
method would be used.
If a value editor does not derive from UITypeEditor
, it must implement IPropertyEditor
to specify the value editing control.
Such editors need to implement IPropertyEditor.GetEditingControl()
, which is demonstrated here with BoolEditor
.
BoolEditor
is used in several samples, including the ATF Simple DOM Editor Sample. This figure shows the property editor for an "Animation" object:
The "Compressed" Boolean property is shown with the check box associated with the BoolEditor
.
Here is IPropertyEditor.GetEditingControl()
for BoolEditor
:
public Control GetEditingControl(PropertyEditorControlContext context)
{
m_boolControl = new BoolControl(context);
return m_boolControl;
}
BoolEditor
also contains the implementation of the private BoolControl
class, although it could be in a separate file.
BoolControl
's constructor creates a CheckBox
control object, which is shown in the previous illustration of the value editor's control:
public BoolControl(PropertyEditorControlContext context)
{
m_context = context;
m_checkBox = new CheckBox();
m_checkBox.Size = m_checkBox.PreferredSize;
m_checkBox.CheckAlign = ContentAlignment.MiddleLeft;
m_checkBox.CheckedChanged += checkBox_CheckedChanged;
Controls.Add(m_checkBox);
Height = m_checkBox.Height + m_topAndLeftMargin;
RefreshValue();
}
The other methods in BoolControl
do things like refresh the control, and check for changed state or size.
If a value editor can have parameters in an XML Schema annotation, the value editor must implement IAnnotatedParams
. This interface gets the parameters from the schema annotation and initializes the value editor for those parameters.
For example, the ATF Timeline Editor Sample defines a value editor for a file name that takes a file filter parameter in its schema definition for the "timelineRef" type:
<scea.dom.editors.attribute name="ref" displayName="File Name" description="File name of timeline reference"
editor="Sce.Atf.Controls.PropertyEditing.FileUriEditor,Atf.Gui.WinForms:Timeline files (*.timeline)|*.timeline"/>
The editor FileUriEditor
implements IAnnotatedParams:Initialize()
to obtain the filter string and place it in the m_filter
field, which is used later for a file dialog:
public void Initialize(string[] parameters)
{
if (parameters.Length >= 1)
m_filter = parameters[0];
}
Value converters also use the IAnnotatedParams
interface, as described in IAnnotatedParams Interface.
- Using Properties in ATF: Overview of the ATF property editing process.
-
Selection Property Editing Context: How the
SelectionPropertyEditingContext
class is used in editing properties. -
Property Descriptors: Discusses various kinds of
PropertyDescriptor
classes and how they are created from constructors or XML Schema annotations. - Value Editors: Types of value editors and how they are implemented.
- Value Editors and Value Editing Controls: Survey of the various kinds of ATF value editors and their associated value controls.
- Value Converters: How value converters convert values between value editors and value controls.
- Property Editor Components: Discussion of widely used ATF property editor components.
- Implementing a Property Editor: How to implement a property editor.
- Home
- Getting Started
- Features & Benefits
- Requirements & Dependencies
- Gallery
- Technology & Samples
- Adoption
- News
- Release Notes
- ATF Community
- Searching Documentation
- Using Documentation
- Videos
- Tutorials
- How To
- Programmer's Guide
- Reference
- Code Samples
- Documentation Files
© 2014-2015, Sony Computer Entertainment America LLC