-
Notifications
You must be signed in to change notification settings - Fork 263
Control Adapters
Control adapters give you an easy way to add abilities to certain controls without changing the control at all. ATF has a large number of control adapters performing a variety of functions that you can use on your controls.
These adapters and their interfaces are in the Sce.Atf.Controls.Adaptable
namespace.
To understand how control adapters work, consider how they are used.
Control adapters are used on adaptable controls, which derive from AdaptableControl
. ATF provides two: AdaptableControl
itself and D2dAdaptableControl
, which is the one that is most used, because many of the non-Direct2D classes are deprecated.
Consider this simple example from the Editor
class's constructor in ATF Circuit Editor Sample. It sets up a control that is displayed when the cursor hovers over a subcircuit in a circuit:
m_d2dHoverControl = new D2dAdaptableControl();
m_d2dHoverControl.Dock = DockStyle.Fill;
var xformAdapter = new TransformAdapter();
xformAdapter.EnforceConstraints = false;//to allow the canvas to be panned to view negative coordinates
m_d2dHoverControl.Adapt(xformAdapter,
new D2dGraphAdapter<Module, Connection, ICircuitPin>(m_circuitRenderer, xformAdapter));
After the D2dAdaptableControl
is constructed and configured, the control adapter TransformAdapter
is created to provide transform information about the control. Next, AdaptableControl.Adapt()
is called with a list of the adapters to add to the control. This adds the TransformAdapter
plus a D2dGraphAdapter
constructed inside the Adapt()
call. This is all you need to do to get the benefits of the adapters for the control.
For further discussion of adaptable controls and control adapters, see Adaptable Controls.
Control adapters all derive directly or indirectly from the abstract ControlAdapter
class, which is never used as a control adapter itself. ControlAdapter
implements IControlAdapter
, which contains the following property and methods:
-
AdaptedControl
: Get the adapted control. -
Bind(AdaptableControl control)
: Bind the adapter to the adaptable control. It is called in the order that the adapters were defined on the control. -
BindReverse(AdaptableControl control)
: Bind the adapter to the adaptable control. It is called in the reverse order that the adapters were defined on the control. -
Unbind(AdaptableControl control)
: Unbind the adapter from the adaptable control.
Note that the binding related methods get the control they are binding to as a parameter, so it is available for the AdaptedControl
property. Binding occurs when AdaptableControl.Adapt()
is called. What binding accomplishes is discussed in the next section.
AdaptableControl
augments Control
, from which it derives. It has events before and after when adapters are adapted. It also overrides the base Control
OnMouseDown()
and OnMouseMove()
methods. It overrides the WndProc()
method so that it can call its overridden OnPainting()
method.
The main thing the Adapt()
method does is bind the control adapters to the control:
public void Adapt(params IControlAdapter[] adapters)
{
OnAdapting(EventArgs.Empty);
Adapting.Raise(this, EventArgs.Empty);
// allow existing adapters to detach from context
Context = null;
foreach (IControlAdapter adapter in m_adapters)
{
adapter.Unbind(this);
Dispose(adapter);
}
m_adapters.Clear();
m_adapterCache.Clear();
m_contextAdapterPreferred.Clear();
m_adapters.AddRange(adapters);
foreach (IControlAdapter adapter in m_adapters)
{
adapter.Bind(this);
}
for (int i = m_adapters.Count - 1; i >= 0; i--)
{
m_adapters[i].BindReverse(this);
}
OnAdapted(EventArgs.Empty);
Adapted.Raise(this, EventArgs.Empty);
Invalidate();
}
The first section of this method removes any previous binding, calling Unbind()
for each control adapter. It calls Bind()
for each adapter in the order they were specified, and then calls BindReverse()
for each adapter in the reverse order specified.
The desired order depends on whether the control adapter handles painting or mouse events. For painting events, the order is bottom up, because a higher layer covers lower layers. For mouse events, the order is top up, because higher layers handle events before layers below them. Typically, a painting type adapter overrides only the Bind()
method, while a mouse event adapter overrides only the BindReverse()
method. It's just a matter of convention, however. The benefit of offering both Bind()
and BindReverse()
that are called in reverse orders is that you can put both kinds of control adapters in a single list and order them the way you want. For instance, you could put all the painting control adapters first in the list in the order that you want, followed by the mouse control adapters in their desired order.
The ControlAdapters
property gets a list of all the control adapters in their defined order.
Control adapters are also retrieved and handled by these methods:
-
T As<T>()
: Get a control adapter of the specified type, ornull
if none is available. -
T Cast<T>()
: Get a control adapter of the specified type, throwing an exception if none is available. -
bool Is<T>()
: Return whether the control has the specified control adapter of typeT
. -
IEnumerable<T> AsAll<T>() where T : class
: Get all control adapters of the specified type, ornull
if none.
As()
, that looks through the adapter list to find what's desired:
private object As(Type type)
{
// try cache
object adapter;
if (m_adapterCache.TryGetValue(type, out adapter))
return adapter;
// try adapters (from top to bottom)
for (int i = m_adapters.Count - 1; i >= 0; i--)
{
adapter = m_adapters[i];
if (type.IsAssignableFrom(adapter.GetType()))
{
m_adapterCache.Add(type, adapter);
return adapter;
}
}
// finally, try the adaptable control itself
if (type.IsAssignableFrom(GetType()))
{
m_adapterCache.Add(type, this);
return this;
}
return null;
}
The m_adapterCache
Dictionary<Type, object>
caches the adapters for quick access by type. If not yet cached, the method goes through the list and uses the IsAssignableFrom()
method previously mentioned to find a suitable adapter. Failing this, it tries the control itself, and returns what it finds.
Adaptable controls have a Context
property so their users can specify a desired context for using the control. For instance, the Editor
class in ATF Circuit Editor Sample sets a context:
control.Context = editingContext;
In addition, a preferred adapter for a context can be specified with the RegisterContextAdapter(Type type, object adapter)
method. An adapter for a specified context can be obtained with these methods:
-
T ContextAs<T>()
: Get an adapter to the context of the given type, ornull
if none is available. -
T ContextCast<T>()
: Get an adapter to the context of the given type. If none is available, throw anAdaptationException
. -
bool ContextIs<T>()
: Return whether the context can be adapted to the given type.
Consider MouseWheelManipulator
, a simple adapter that scales the adaptable control viewing area when the user turns the mouse wheel. The constructor for this adapter takes an ITransformAdapter
:
public MouseWheelManipulator(ITransformAdapter transformAdapter)
MouseWheelManipulator
's binding methods are:
protected override void BindReverse(AdaptableControl control)
{
control.MouseWheel += control_MouseWheel;
}
...
protected override void Unbind(AdaptableControl control)
{
control.MouseWheel -= control_MouseWheel;
}
BindReverse()
simply subscribes to the MouseWheel
event; Unbind()
unsubscribes. Note that MouseWheelManipulator
does not override IControlAdapter.Bind()
: control adapters typically override one but not both. This is a mouse event adapter, so it overrides BindReverse()
rather than Bind()
.
The event handler control_MouseWheel
changes the view's scale by manipulating the ITransformAdapter
implementer it was given in its constructor.
TransformAdapter
implements ITransformAdapter
and is a special case adapter. It does not override either Bind()
or BindReverse()
, but is instead used by other adapters, such as MouseWheelManipulator
. Note that an adapter does not need to have an ITransformAdapter
given in its constructor to access it. It can obtain it from the AdaptableControl
with adapter methods, as D2dAnnotationAdapter
does:
m_transformAdapter = control.As<ITransformAdapter>();
For details on these adapter methods like As()
, see AdaptableControl Adapter Methods.
For an example of a painting control adapter, consider CanvasAdapter
, which adjusts the viewing window when its bounds change. It has a Bind()
override, rather than BindReverse
:
protected override void Bind(AdaptableControl control)
{
m_windowBounds = control.ClientRectangle;
m_transformAdapter = control.As<ITransformAdapter>();
if (m_transformAdapter != null)
m_transformAdapter.TransformChanged += transformAdapter_TransformChanged;
control.ClientSizeChanged += control_ClientSizeChanged;
}
This method, too, obtains an ITransformAdapter
using AdaptableControl.As()
. As would be expected, it subscribes to the ClientSizeChanged
event; its Unbind
unsubscribes.
ATF provides a set of interfaces control adapters can use for various purposes. This table describes these interfaces and lists the control adapters that use them.
Control adapter interface | Description | Used by control adapters |
---|---|---|
IAutoTranslateAdapter
|
For auto-translate adapters, which track the mouse when enabled and adjust an ITransformAdapter .
|
AutoTranslateAdapter , D2dAnnotationAdapter , D2dGraphEdgeEditAdapter , D2dGraphNodeEditAdapter , GraphEdgeEditAdapter , MouseLayoutManipulator , RectangleDragSelector
|
ICanvasAdapter
|
For adapters that define a rectangular canvas, with a rectangular window for viewing it. |
CoordinateAxisAdapter , ScrollbarAdapter
|
IDragSelector
|
For adapters that select objects by dragging. Uses DragSelectionEventArgs for drag selection event data.
|
RectangleDragSelector , SelectionAdapter
|
IItemDragAdapter
|
For control adapters that can drag items. This interface provides a mechanism for any control adapter that can drag items to initiate drags of items in other layers at the same time. This way, all selected items may be dragged together even if they are managed by different adapter layers. |
D2dAnnotationAdapter , D2dGraphNodeEditAdapter , SelectionAdapter
|
ILabelEditAdapter
|
For adapters that can do label editing operations. |
LabelEditAdapter
|
IPickingAdapter2
|
For control adapters that perform picking. Note: Use this instead of the obsolete IPickingAdapter .
|
ContextMenuAdapter , D2dAnnotationAdapter , D2dGraphAdapter , KeyboardGraphNavigator , KeyboardIOGraphNavigator , HoverAdapter , SelectionAdapter , ViewingAdapter
|
ISelectionAdapter
|
For control adapters that perform selection. |
LabelEditAdapter , SelectionAdapter
|
ITransformAdapter
|
For adapters that define a transform for the adapted control consisting of a scale, followed by a translation. The TransformAdapters class adds extension methods on ITransformAdapter to transform coordinates and so on.
|
AutoTranslateAdapter , CanvasAdapter , CoordinateAxisAdapter , D2dAnnotationAdapter , D2dGridAdapter , D2dGraphAdapter , D2dGraphEdgeEditAdapter , D2dGraphNodeEditAdapter , D2dSubgraphAdapter , KeyboardGraphNavigator , KeyboardIOGraphNavigator , LabelEditAdapter , MouseLayoutManipulator , MouseTransformManipulator , MouseWheelManipulator , RectangleDragSelector , ScrollbarAdapter , TransformAdapter , ViewingAdapter
|
The table lists the control adapters, what they derive from (if not ControlAdapter
) and implement, and their description.
Some of these adapters, such as D2dGraphEdgeEditAdapter
, operate on graphs in an adaptable control. For more information on graphs, see Graphs in ATF. Also see the discussions of samples that use graphs, such as Circuit Editor Programming Discussion.
Control adapter | Derived from, Implements | Description |
---|---|---|
AutoTranslateAdapter
|
IAutoTranslateAdapter , IDisposable
|
Auto-translate adapter that tracks the mouse when enabled and adjusts an ITransformAdapter .
|
CanvasAdapter
|
ICanvasAdapter , ILayoutConstraint
|
Canvas adapter that defines the canvas bounds and visible window size. |
ContextMenuAdapter
|
Adapter to run a context menu on a MouseUp event with the right button.
|
|
CoordinateAxisAdapter
|
Adapter that renders horizontal and vertical coordinate axes. | |
D2dAnnotationAdapter
|
DraggingControlAdapter IPickingAdapter2 , IItemDragAdapter , IDisposable
|
Adapter that allows displaying and editing diagram annotations (comments). |
D2dGraphAdapter
|
IPickingAdapter2 , IDisposable
|
Adapter to reference and render a graph diagram. Also provides hit testing with the Pick() method, and viewing support with the Frame() and EnsureVisible() methods.
|
D2dGraphEdgeEditAdapter
|
DraggingControlAdapter
|
Adapter that adds graph edge dragging capabilities with a graph adapter. |
D2dGraphNodeEditAdapter
|
DraggingControlAdapter IItemDragAdapter
|
Adapter that adds graph node dragging capabilities with a graph adapter. The Shift key can be pressed to constrain dragging to be parallel to either the x-axis or y-axis. |
D2dGridAdapter
|
ILayoutConstraint
|
Adapter to draw a grid on a diagram and to perform layout constraints using that grid. |
D2dSubgraphAdapter
|
D2dGraphAdapter
|
Control adapter to reference and render a subgraph diagram. Also provides hit testing with the Pick() method, and viewing support with the Frame() and EnsureVisible() methods.
|
DragDropAdapter
|
Adapter to add drag and drop support. | |
DraggingControlAdapter
|
Abstract base class for control adapters that drag. It tracks the mouse and handles the logic of determining when the mouse has moved enough to be considered a drag. | |
GroupPinEditor
|
DraggingControlAdapter IItemDragAdapter , IDisposable
|
Adapter for adding floating group pin location and label editing capabilities to a subgraph control. |
HoverAdapter
|
IDisposable
|
Adapter that uses an IPickingAdapter and a timer to generate events when the user hovers over items. For a discussion of how to use this adapter, see Hover Adapter.
|
KeyboardGraphNavigator
|
Allows for navigating a graph using the arrow keys. It requires that the adaptable control's context be adaptable to ISelectionContext and IGraph . Optionally, this context should be adaptable to IViewingContext . It requires that the adaptable control can be adapted to IPickingAdapter2 . Consider using KeyboardIOGraphNavigator instead, if the graph has inputs and outputs on specific sides of the nodes.
|
|
KeyboardIOGraphNavigator
|
Allows for navigating an "input-output" graph using the arrow keys. This kind of graph has inputs on only one side of a node and outputs on the other side. It requires that the adaptable control's context be adaptable to ISelectionContext and IGraph . Optionally, this context should be adaptable to IViewingContext . It requires that the adaptable control can be adapted to IPickingAdapter2 .
|
|
LabelEditAdapter
|
ILabelEditAdapter , IDisposable
|
Adapter for adding in-place label editing. |
MouseLayoutManipulator
|
DraggingControlAdapter
|
Adapter to add a layout adorner to complex states, such as marking states as selected. |
MouseTransformManipulator
|
Adapter that converts mouse drags into translation and scaling of the adapted control using an ITransformAdapter .
|
|
MouseWheelManipulator
|
Adapter that converts mouse wheel rotation into scaling the adapted control using an ITransformAdapter .
|
|
RectangleDragSelector
|
DraggingControlAdapter IDragSelector
|
Adapter that allows a user to drag-select rectangular regions on the adapted control to modify the selection. It uses DragSelectionEventArgs for drag selection event data.
|
ScrollbarAdapter
|
Adapter that adds horizontal and vertical scrollbars to the adapted control. It requires an ITransformAdapter and ICanvasAdapter .
|
|
SelectionAdapter
|
ISelectionAdapter , IItemDragAdapter , ISelectionPathProvider
|
Adapter that adds mouse click and drag selection to the adapted control. The associated context must be convertible to ISelectionContext . It uses DragSelectionEventArgs for drag selection event data.
|
TransformAdapter
|
ITransformAdapter
|
Adapter that defines a transform for the adapted control consisting of a scale followed by a translation. This transform affects how the adapted control is viewed. The TransformAdapters class adds extension methods on ITransformAdapter to transform coordinates and so on.
|
ViewingAdapter
|
IViewingContext
|
Adapter that defines a viewing context on the adapted control. It requires an ITransformAdapter .
|
The following control adapters are considered obsolete and are replaced by the given Direct2D classes.
Obsolete control adapter | Derived from, Implements | Direct2D version to use |
---|---|---|
AnnotationAdapter
|
DraggingControlAdapter IPickingAdapter , IPrintingAdapter , IItemDragAdapter , IDisposable
|
D2dAnnotationAdapter
|
GraphAdapter
|
IGraphAdapter , IPickingAdapter , IPrintingAdapter , IDisposable
|
D2dGraphAdapter
|
GraphEdgeEditAdapter
|
DraggingControlAdapter
|
D2dGraphEdgeEditAdapter
|
GraphNodeEditAdapter
|
DraggingControlAdapter IItemDragAdapter
|
D2dGraphNodeEditAdapter
|
GridAdapter
|
ILayoutConstraint
|
D2dGridAdapter
|
- What is Adaptation: General discussion of what adaptation is and how it is used in ATF.
- General Adaptation Interfaces: Survey of interfaces for adaptation.
- General Adaptation Classes: Describe fundamental classes in adaptation.
- Control Adapters: Discussion of control adapters, which add abilities to controls without changing the control.
- Other Adaptation Classes: Survey of non-control adapter classes that perform various kinds of adaptation.
- Adapting to All Available Interfaces: A detailed example of how adaptation works and what you need to do to make it work showing how adapters can be obtained for any interface DOM adapters implement.
- 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