-
Notifications
You must be signed in to change notification settings - Fork 263
DOM Use in Simple DOM Editor
This section shows how the ATF Simple DOM Editor Sample uses DOM concepts and operations discussed in the previous sections of DOM in a Nutshell.
The Simple DOM Editor Programming Discussion section in ATF Code Samples Discussions explains how this sample works in general. The topic here goes into the specifics of how this sample uses the DOM, and references the appropriate parts of the more general section.
The SimpleDOMEditor sample edits sequences of events and can save an event sequence to a document file — and then read it back for further editing. Its UI is seen in the figure below.
This sample application can have multiple documents open. Each event has attributes and can also contain any number of animation and geometry resources. Event sequences are created by dragging event objects from the palette onto the ListView
control associated with a document, in the "Untitled.xml" tab in the figure. Resources are added to an event by dragging a resource from the palette to the Resources tab (also a ListView
) when an event is selected. When an event or resource object is selected in either ListView
, its attributes can be edited in either a PropertyEditor
or GridPropertyEditor
; both editors show the same attributes but organize them differently. Selected objects can also be copied, cut, deleted, and pasted. Each event sequence, event, and resource object is represented by a DomNode
.
This sample provides two ways of editing application data: creating objects by dragging them from the palette, and editing these objects' attributes in a property editor. This section demonstrates how this editing takes place using the DOM.
The data model defines types for the event, event sequence, and resource objects using an XML Schema in the type definition file eventSequence.xsd
. The types are:
- "eventType": For an event.
- "resourceType": For a resource, and there are two types based on this:
- "animationResourceType": For an animation resource.
- "geometryResourceType": For a geometry resource.
- "eventSequenceType": For a sequence of "eventType" objects.
In terms of the DOM node tree, the root DomNode
has the type "eventSequenceType", because the root object contains the events. The root DomNode
has a child DomNode
of type "eventType" for every event in the sequence. Each "eventType" DomNode
can have child DomNode
s of type "animationResourceType" or "geometryResourceType".
For more details on this data model, see Type Definition in Simple DOM Editor Programming Discussion.
This sample uses DomGen to create a Schema
class referencing the metadata class objects that the type loader creates. For information on what's in this class in SimpleDOMEditor, see Schema Class in Simple DOM Editor Programming Discussion. For general information on DomGen and the Schema
class, see Using the DomGen Utility to Create a Schema Class in the Type Loaders section.
SimpleDOMEditor derives its type loader from XmlSchemaTypeLoader
, and its constructor loads the type definition file eventSequence.xsd
. Creating the type loader is straightforward, because this sample uses an XML Schema.
The type loader's OnSchemaSetLoaded()
method performs the various functions discussed in Type Loaders. Most of these functions are discussed further here, as noted:
- Initialize the
Schema
class by callingSchema.Initialize()
. - Define various DOM adapters, most on the type of the root
DomNode
"eventSequenceType". For this discussion, see DOM Adapters. - Create
NodeTypePaletteItem
objects and add them toDomNodeType
metadata objects by callingNamedMetadata.SetTag
for the types "eventType", "animationResourceType", and "geometryResourceType". This provides the information needed for adding objects of these types to the palette. For further details, see Palette Handling. - Create collections of property descriptors to enable editing object's attributes. For a description, see Editing Attributes Using Property Descriptors.
The SimpleDOMEditor sample creates simple DOM adapters for its basic types:
-
Event
: Adapter for "eventType". HasName
,Time
, andDuration
properties for attributes and theResources
property for a list of the child resources in an event. -
EventSequence
: Adapter for "eventSequenceType". ItsEvents
property gets the list of events in the sequence. -
Resource
: Adapter for "resourceType". HasName
andSize
properties for attributes.
The other DOM adapters do considerably more and are defined on the root DomNode
's type "eventSequenceType". Several of these adapters are general ATF DOM adapters, not particular to this sample:
-
MultipleHistoryContext
: DOM adapter for multiple history contexts, so that the undo/redo history stack for each document is distinct. -
ReferenceValidator
: DOM validator for internal references between DOM nodes and references to external resources. -
UniqueIdValidator
: Adapter that ensures that every DOM node in the tree has a unique ID. -
DomNodeQueryable
: Adapter enablingDomNode
s to be searched, to supply the search results, and to have those results replaced with other data. For more details, see Node Searching in Simple DOM Editor Programming Discussion.
UniqueIdValidator
, are DOM validators, discussed in DOM Adapters Validate in DOM Adapters.
The other DOM adapters are specific to this sample. These are workhorses, performing a variety of functions because they implement several interfaces:
-
EventSequenceDocument
: Serves as a document for the application. For a description of how this adapter functions as a document, see Document Handling in Simple DOM Editor Programming Discussion. -
EventSequenceContext
: Provides an event sequence context for the application. In particular, it implementsIInstancingContext
to copy, insert, and delete items, so it is fundamental to editing. For more on editing, see Application Data Creation.
DomNode
s make them phenomenally useful.
SimpleDOMEditor sets up a palette that is integrated with the DOM.
The sample's PaletteClient
component populates the palette with objects and imports IPaletteService
. This import is satisfied by the ATF PaletteService
component, which manages a palette of objects that can be dragged onto other controls.
In its schema loader, the sample specifies which objects go on the palette by constructing a NodeTypePaletteItem
object for each object, and placing this information in the DomNodeType
metadata object for the type:
Schema.eventType.Type.SetTag(
new NodeTypePaletteItem(
Schema.eventType.Type,
"Event".Localize(),
"Event in a sequence".Localize(),
Resources.EventImage));
Schema.animationResourceType.Type.SetTag(
new NodeTypePaletteItem(
Schema.animationResourceType.Type,
"Animation".Localize(),
"Animation resource".Localize(),
Resources.AnimationImage));
Schema.geometryResourceType.Type.SetTag(
new NodeTypePaletteItem(
Schema.geometryResourceType.Type,
"Geometry".Localize(),
"Geometry resource".Localize(),
Resources.GeometryImage));
The NodeTypePaletteItem
specifies the object type, a name, and an image that appears on the palette. For more information on specifying these palette items, see Adding Palette Information in Using DOM Metadata for Palettes and Other Items.
The PaletteClient
component's IInitializable.Initialize()
method uses these NodeTypePaletteItem
items added to the DomNodeType
metadata objects to determine which objects go on the palette: if the DomNodeType
has a NodeTypePaletteItem
associated with it, the DomNodeType
is added to the palette. As a result, event, animation, and geometry objects appear on the palette.
PaletteClient
implements the IPaletteClient
interface. IPaletteClient.Convert()
takes a palette item and returns an object that can be inserted into an IInstancingContext
. In this case, it is a DomNode
with the DomNodeType
associated with the palette item. In other words, the item dragged is a DomNode
that could serve as new application data. To find out how data is created this way, see Application Data Creation.
For more details on palette operation, see Using a Palette in Simple DOM Editor Programming Discussion.
SimpleDOMEditor allows creating new objects by dragging objects from a palette onto ListView
controls. The sample's EventSequenceContext
DOM adapter shows how you create data by adding new DOM nodes to the tree representing an event sequence.
The EventListEditor
component edits event sequences in ListView
s on document tabs in the editor. There is a tab and an EventSequenceContext
for each document, and each EventSequenceContext
owns the ListView
for each document.
EventListEditor
keeps track of the active context with the context registry component. It knows when a given EventSequenceContext
and its ListView
are active, because it tracks context changes. For more information, see Context Registry.
EventListEditor
subscribes to drag events on the ListView
associated with a document, and its listView_DragDrop()
method is called when an object is dropped onto this ListView
:
private void listView_DragDrop(object sender, DragEventArgs e)
{
IInstancingContext context = m_eventSequenceContext;
if (context.CanInsert(e.Data))
{
ITransactionContext transactionContext = context as ITransactionContext;
TransactionContexts.DoTransaction(transactionContext,
delegate
{
context.Insert(e.Data);
},
Localizer.Localize("Drag and Drop"));
if (m_statusService != null)
m_statusService.ShowStatus(Localizer.Localize("Drag and Drop"));
}
}
The field m_eventSequenceContext
contains the active EventSequenceContext
and was set when the context changed. EventSequenceContext
implements IInstancingContext
, and listView_DragDrop()
calls IInstancingContext.CanInsert()
on this context to see if the object can be inserted:
public bool CanInsert(object insertingObject)
{
IDataObject dataObject = (IDataObject)insertingObject;
object[] items = dataObject.GetData(typeof(object[])) as object[];
if (items == null)
return false;
foreach (object item in items)
if (!Adapters.Is<Event>(item))
return false;
return true;
}
CanInsert()
casts the data as an IDataObject
and then casts it to an array of object
s, each of which is a DomNode
. Recall that a dragged palette object is a DomNode
with the DomNodeType
of the palette object, as described in Palette Handling previously.
Only event objects can be dragged onto the ListView
associated with documents of event sequences. The second part of CanInsert()
checks whether each dragged item is a DomNode
with the DomNodeType
for "eventType" with this line:
if (!Adapters.Is<Event>(item))
The method Adapters.Is()
returns true if and only if the object can be adapted to the given type, Event
in this case. The DOM adapter Event
is defined on "eventType" in SchemaLoader
:
Schema.eventType.Type.Define(new ExtensionInfo<Event>());
This means that any object of type "eventType" can be adapted to Event
. Because "eventType" is the only type that Event
is defined for, only "eventType" DomNode
s meet this condition.
Assuming that the object can be inserted, listView_DragDrop()
gets an ITransactionContext
so the insertion can take place in a transaction. And where does it get this context? It adapts the EventSequenceContext
to ITransactionContext
, because EventSequenceContext
derives from EditingContext
, which implements ITransactionContext
(through a class it derives from). For more on this versatile context class, see Sce.Atf.Dom.EditingContext Class in Context Classes. The extension method TransactionContexts.DoTransaction
is called using the adapted ITransactionContext
. DOM adapters are frequently adapted to useful classes like this.
During the transaction, the IInstancingContext.Insert()
method actually creates the new data as DomNode
s and adds them to the event sequence:
public void Insert(object insertingObject)
{
IDataObject dataObject = (IDataObject)insertingObject;
object[] items = dataObject.GetData(typeof(object[])) as object[];
if (items == null)
return;
DomNode[] itemCopies = DomNode.Copy(Adapters.AsIEnumerable<DomNode>(items));
IList<Event> events = this.Cast<EventSequence>().Events;
foreach (Event _event in Adapters.AsIEnumerable<Event>(itemCopies))
events.Add(_event);
Selection.SetRange(itemCopies);
}
The first part of Insert()
is the same as CanInsert()
: casting the data as a IDataObject
and then casting to an array of object
s. These objects are actually DomNode
s with the DomNodeType
for "eventType". The inserted objects are copied to itemCopies
, an array of DomNode
s.
The next line shows adaptation in action in the DOM adapter. Here this
, which is an EventSequenceContext
, is adapted to EventSequence
. This works, because both the EventSequenceContext
and EventSequence
DOM adapters are defined on the type "eventSequenceType" in SchemaLoader
:
Schema.eventSequenceType.Type.Define(new ExtensionInfo<EventSequence>());
...
Schema.eventSequenceType.Type.Define(new ExtensionInfo<EventSequence>());
The type "eventSequenceType" is the root DomNode
's type, so this DomNode
is the root and can be adapted to any DOM adapter defined for its type, as previously discussed.
Once adapted to EventSequence
, the root object's Events
property can provide a list of events, which is saved in the IList<Event> events
variable. Finally, Insert()
adds each new Event
in itemCopies
to this event list.
The key thing to note here is that the creation of event data is done by creating DomNode
s. An event is added to the sequence by adding a DomNode
to the list of DomNode
s maintained by the EventSequence
DomNode
, which is the root DomNode
. This DomNode
's type has numerous DOM adapters defined on it, so this node can function as an EventSequenceContext
, which also allows it to function as a ITransactionContext
. This is a common paradigm in the ATF DOM: define DOM adapters implementing any needed interfaces on the root DomNode
's type so the root DomNode
can take on all these roles. Recall that when multiple DOM adapters are defined for a type, an object of that type can be adapted to any interface implemented by any of these DOM adapters; for details, see Adapting to All Available Interfaces.
For more information about how this context functions in the sample, see EventSequenceContext Class in Simple DOM Editor Programming Discussion.
You add resources to an event by dragging a resource object from the palette to the Resources ListView
. In this operation, the ResourceListEditor
component and EventContext
class function very similarly to EventListEditor
and EventSequenceContext
in adding a DomNode
of the appropriate resource type as a child to an Event
DomNode
. For further details, see ResourceListEditor Component in Simple DOM Editor Programming Discussion.
You can also remove event and resource objects by selecting them and deleting them. This simply removes the associated DomNode
s from the tree.
Besides defining DOM adapters, SchemaLoader
creates property descriptors for several types to make it easy to edit their attributes/properties in ATF property editors.
For example, here are the property descriptors constructed for the attributes "Name", "Time", and "Duration" of "eventType":
Schema.eventType.Type.SetTag(
new PropertyDescriptorCollection(
new PropertyDescriptor[] {
new AttributePropertyDescriptor(
"Name".Localize(),
Schema.eventType.nameAttribute,
null,
"Event name".Localize(),
false),
new AttributePropertyDescriptor(
"Time".Localize(),
Schema.eventType.timeAttribute,
null,
"Event starting time".Localize(),
false),
new AttributePropertyDescriptor(
"Duration".Localize(),
Schema.eventType.durationAttribute,
null,
"Event duration".Localize(),
false),
}));
These descriptors provide basic information about each attribute. In this case, the property value editing controls appropriate to the data type are used, such as a text box for a string attribute. However, you can specify more information by using a different form of the AttributePropertyDescriptor
constructor, as in this descriptor for the "Compressed" attribute of "animationResourceType":
new AttributePropertyDescriptor(
"Compressed".Localize(),
Schema.animationResourceType.compressedAttribute,
null,
"Whether or not animation is compressed".Localize(),
false,
new BoolEditor()),
In this case, the constructor specifies BoolEditor
as the value editor, which results in a check box being used as the value editor for this Boolean attribute.
In addition, the sample imports the MEF components PropertyEditor
, GridPropertyEditor
, and PropertyEditingCommands
to provide these two property editors and context menu commands for them. These editors automatically display the properties for attributes that were defined in the property descriptors when an object is selected — no further programming effort required.
For a DOM related discussion, see DOM Property Descriptors. For a broader description of how properties are edited in ATF, see the Property Editing in ATF section.
Because SimpleDOMEditor uses an XML Schema to specify its data model and a schema loader derived from XmlSchemaTypeLoader
, it can easily save its application data and read it back later using ATF classes and XML.
SimpleDOMEditor uses a DomXmlWriter
object to write application data — in a tree of DomNode
s — to an XML file. It reads the file contents back to a DomNode
tree with the same data using DomXmlReader
.
For a general description of these classes, see DOM Persistence. For details on how SimpleDOMEditor uses DomXmlReader
to read a document from XML, see Opening a Document in Simple DOM Editor Programming Discussion. For the sample's writing the document to XML with DomXmlWriter
, see Saving a Document in Simple DOM Editor Programming Discussion.
- What is the DOM For: Overview of the DOM's features and advantages.
- It All Starts With Data: Defining application data models with types, especially using XML Schema.
-
DomNodes and DOM Metadata Classes: The fundamental
DomNode
class and its type metadata classes, such asDomNodeType
. Application data resides in a tree ofDomNode
s. - Type Loaders: Loading the type definition file into the application to use the file's data types and create type metadata class objects.
-
DOM Adapters: DOM adapters allow adapting
DomNode
s to other types and monitor events in theDomNode
tree to validate data. - DOM Property Descriptors: DOM property descriptors make it easy to use property editors on application data and are stored in type metadata.
- Using DOM Metadata for Palettes and Other Items: Type metadata can hold all sorts of data, such as palette object information.
-
DOM Persistence: Persisting application data using classes to write the
DomNode
tree to XML and read it back to aDomNode
tree. - DOM Debugging: ATF tools to facilitate debugging DOM code.
- DOM Use in Simple DOM Editor: Explains how the ATF Simple DOM Editor Sample uses the DOM.
- 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