-
Notifications
You must be signed in to change notification settings - Fork 259
Implementing a Document and Its Client
This section reviews how a document and its client are implemented, as demonstrated in the ATF Simple DOM Editor Sample.
The SimpleDOMEditor sample implements IDocument in its EventSequenceDocument class by deriving from DomDocument, which implements IDocument.
Here are the properties:
public virtual bool IsReadOnly
{
get { return false; }
}
...
public virtual bool Dirty
{
get
{
return m_dirty;
}
set
{
if (value != m_dirty)
{
m_dirty = value;
OnDirtyChanged(EventArgs.Empty);
}
}
}And here is the event handler that raises the event:
protected virtual void OnDirtyChanged(EventArgs e)
{
DirtyChanged.Raise(this, e);
}The document client handles the details of how file contents are retrieved and turned into a document, and vice versa. The items in this interface, discussed in IDocumentClient Interface are implemented in the Editor class of the SimpleDOMEditor sample.
First, the implementation of the DocumentClientInfo property is straightforward:
public DocumentClientInfo Info
{
get { return DocumentClientInfo; }
}
...
public static DocumentClientInfo DocumentClientInfo = new DocumentClientInfo(
Localizer.Localize("Event Sequence"),
new string[] { ".xml", ".esq" },
Sce.Atf.Resources.DocumentImage,
Sce.Atf.Resources.FolderImage,
true);This indicates the application can open files with extensions of ".xml" and ".esq", and multiple documents can be open at once. Icons are also provided for the UI.
The CanOpen() method uses DocumentClientInfo.IsCompatibleUri() to determine if the file's extension is one of the ones set up in the DocumentClientInfo:
public bool CanOpen(Uri uri)
{
return DocumentClientInfo.IsCompatibleUri(uri);
}SimpleDOMEditor uses the ATF DOM for its application data. The ATF DOM supports saving its data to XML using the DomXmlWriter class and reading it with DomXmlReader, and SimpleDOMEditor takes full advantage of this.
The Open() method uses DomXmlReader if the file exists, and otherwise creates a new document. The DomNode, node, is the root node of the DomNode tree.
Through adaptation, a DomNode can be dynamically cast to many different kinds of objects. In this method, the root DomNode is cast to both an EventSequenceDocument and an EventSequenceContext. This can be done, because both EventSequenceDocument and EventSequenceContext are DOM node adapters: both ultimately derive from the DomNodeAdapter class. For more information about adaptation, see Adaptation in ATF and the ATF Programmer’s Guide: Document Object Model (DOM), downloadable at ATF Documentation.
The second part of this method creates an EventSequenceDocument, document, which derives from DomDocument. The method casts the root DomNode node as an EventSequenceDocument object. It goes on to set various properties for the EventSequenceDocument object.
The document is displayed in a ListView control, which is part of the EventSequenceContext that is also cast from the root DomNode. The method sets up a ControlInfo for this control and also registers it.
This shows that the object implementing the IDocument interface can be adapted to various classes, as needed.
public IDocument Open(Uri uri)
{
DomNode node = null;
string filePath = uri.LocalPath;
string fileName = Path.GetFileName(filePath);
if (File.Exists(filePath))
{
// read existing document using standard XML reader
using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
DomXmlReader reader = new DomXmlReader(m_schemaLoader);
node = reader.Read(stream, uri);
}
}
else
{
// create new document by creating a Dom node of the root type defined by the schema
node = new DomNode(Schema.eventSequenceType.Type, Schema.eventSequenceRootElement);
}
EventSequenceDocument document = null;
if (node != null)
{
// Initialize Dom extensions now that the data is complete
node.InitializeExtensions();
EventSequenceContext context = node.As<EventSequenceContext>();
ControlInfo controlInfo = new ControlInfo(fileName, filePath, StandardControlGroup.Center);
context.ControlInfo = controlInfo;
// set document URI
document = node.As<EventSequenceDocument>();
document.Uri = uri;
// set document GUIs for search and replace
document.SearchUI = new DomNodeSearchToolStrip();
document.ReplaceUI = new DomNodeReplaceToolStrip();
document.ResultsUI = new DomNodeSearchResultsListView(m_contextRegistry);
context.ListView.Tag = document;
// show the ListView control
m_controlHostService.RegisterControl(context.ListView, controlInfo, this);
}
return document;
}Show() uses an EventSequenceContext object, which it also casts from the EventSequenceDocument, document. The method then uses the ControlHostService object to show the document, which is displayed in a ListView in the context:
public void Show(IDocument document)
{
EventSequenceContext context = Adapters.As<EventSequenceContext>(document);
m_controlHostService.Show(context.ListView);
}To complete the symmetry of the Open() method, Save() uses the DomXmlWriter class to write the document to an XML file. The DomXmlWriter.Write() method needs a DomNode, so the document is adapted to one:
public void Save(IDocument document, Uri uri)
{
string filePath = uri.LocalPath;
FileMode fileMode = File.Exists(filePath) ? FileMode.Truncate : FileMode.OpenOrCreate;
using (FileStream stream = new FileStream(filePath, fileMode))
{
DomXmlWriter writer = new DomXmlWriter(m_schemaLoader.TypeCollection);
EventSequenceDocument eventSequenceDocument = (EventSequenceDocument)document;
writer.Write(eventSequenceDocument.DomNode, stream, uri);
}
}To close this DocumentClientInfo interface implementation discussion, Close() again adapts the document to an EventSequenceContext. It gets the ListView control from the context and unregisters it using the ControlHostService object. It performs various context clean up. Finally, it uses the DocumentRegistry object to invoke the Remove() method to remove the document from the document registry.
public void Close(IDocument document)
{
EventSequenceContext context = Adapters.As<EventSequenceContext>(document);
m_controlHostService.UnregisterControl(context.ListView);
context.ControlInfo = null;
// close all active EditingContexts in the document
foreach (DomNode node in context.DomNode.Subtree)
foreach (EditingContext editingContext in node.AsAll<EditingContext>())
m_contextRegistry.RemoveContext(editingContext);
// close the document
m_documentRegistry.Remove(document);
}-
What is a Document in ATF: Introduces the
IDocumentandIDocumentClientinterfaces that an individual document uses. -
Document Registry and Services: Discusses the
DocumentRegistryto track documents and other document services offered inIDocumentService. - Document Handling Components: Details the MEF components providing services document handlers need.
-
Implementing a Document and Its Client: Shows how to implement both
IDocumentandIDocumentClientinterfaces for a document type.
- 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