-
Notifications
You must be signed in to change notification settings - Fork 263
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
IDocument
andIDocumentClient
interfaces that an individual document uses. -
Document Registry and Services: Discusses the
DocumentRegistry
to 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
IDocument
andIDocumentClient
interfaces 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