|
2 | 2 |
|
3 | 3 | By [Chris Lovett](http://lovettsoftware.com/), Microsoft
|
4 | 4 |
|
5 |
| -In the GitHub repo, you'll find the core `XmlNotepad` DLL project, an `Application` project that |
6 |
| -builds XmlNotepad.exe, and some setup projects like `XmlNotepadSetup` which builds the .msi |
7 |
| -installer, and the `UnitTests` project for testing XML Notepad. |
| 5 | +In the GitHub repo, you'll find the core `XmlNotepad` DLL project, an `Application` project that builds XmlNotepad.exe, |
| 6 | +and some setup projects like `XmlNotepadSetup` which builds the .msi installer, and the `UnitTests` project for testing |
| 7 | +XML Notepad. |
8 | 8 |
|
9 |
| -The following DGML diagram shows the relationships between the main UI classes. The main form |
10 |
| -contains all the UI elements from the TaskList to the main XmlTreeView with Resizers in between; |
11 |
| -it's the launching point for the dialogs such as FormSearch, FormSchemas, FormOption, and FormAbout. |
| 9 | +The following DGML diagram shows the relationships between the main UI classes. The main form contains all the UI |
| 10 | +elements from the TaskList to the main XmlTreeView with Resizers in between; it's the launching point for the dialogs |
| 11 | +such as FormSearch, FormSchemas, FormOption, and FormAbout. |
12 | 12 |
|
13 | 13 | 
|
14 | 14 |
|
15 |
| -The main tab control contains the XmlTreeView and the XsltViewer for showing XSL output. The |
16 |
| -XmlTreeView contains a TreeView on the left and a NodeTextView on the right and coordinates |
17 |
| -scrolling between these two views. Both the TreeView and NodeTextView provide the same IntelliSense |
18 |
| -editing functionality using a TextEditorOverlay component. The XmlTreeView implements IFindTarget, |
19 |
| -which is used by the Find dialog (FormSearch) to implement find/replace functionality. |
| 15 | +The main tab control contains the XmlTreeView and the XsltViewer for showing XSL output. The XmlTreeView contains a |
| 16 | +TreeView on the left and a NodeTextView on the right and coordinates scrolling between these two views. Both the |
| 17 | +TreeView and NodeTextView provide the same IntelliSense editing functionality using a TextEditorOverlay component. The |
| 18 | +XmlTreeView implements IFindTarget, which is used by the Find dialog (FormSearch) to implement find/replace |
| 19 | +functionality. |
20 | 20 |
|
21 | 21 | 
|
22 | 22 |
|
23 | 23 | The Find dialog supports full text, regex, or XPath expressions and can filter by names or values.
|
24 | 24 |
|
25 | 25 | ## Model
|
26 | 26 |
|
27 |
| -The core data model behind the UI is `System.Xml.XmlDocument` and its `XmlNode` objects. These |
28 |
| -nodes are wrapped by `TreeNode` UI objects. To facilitate support for the XML Include spec, there is a |
29 |
| -custom reader that processes XML Includes, and there is also a custom DomLoader that keeps track of |
30 |
| -line information for error messages. |
| 27 | +The core data model behind the UI is `System.Xml.XmlDocument` and its `XmlNode` objects. These nodes are wrapped by |
| 28 | +`TreeNode` UI objects. To facilitate support for the XML Include spec, there is a custom reader that processes XML |
| 29 | +Includes, and there is also a custom DomLoader that keeps track of line information for error messages. |
31 | 30 |
|
32 | 31 | 
|
33 | 32 |
|
34 | 33 | ## Validation, IntelliSense, and Custom Editors
|
35 | 34 |
|
36 |
| -The biggest new feature is IntelliSense, which is driven by XML Schema information provided via the |
37 |
| -SchemaCache. For example, if your element or attribute is defined by an XSD simpleType and this |
38 |
| -simpleType contains a list of enumeration facets, then you will get a drop-down like this: |
| 35 | +The biggest new feature is IntelliSense, which is driven by XML Schema information provided via the SchemaCache. For |
| 36 | +example, if your element or attribute is defined by an XSD simpleType and this simpleType contains a list of enumeration |
| 37 | +facets, then you will get a drop-down like this: |
39 | 38 |
|
40 | 39 | 
|
41 | 40 |
|
42 |
| -The way this works is that the Checker runs after each edit operation to validate the document and |
43 |
| -report errors in the TaskList. This process also puts `System.Xml.Schema.XmlSchemaType` information |
44 |
| -on each element and attribute in the XmlDocument; then, when editing the value of that node, the |
45 |
| -TextEditorOverlay uses the `XmlIntelliSenseProvider` to get back a list of possible values. In the |
46 |
| -above example, it returns the values from the simpleType enumeration facets. For element name |
47 |
| -IntelliSense in the tree view, the `XmlIntelliSenseProvider` invokes the Checker again, captures |
48 |
| -GetExpectedParticles and GetExpectedAttributes on the `System.Xml.Schema.XmlSchemaValidator`, and |
49 |
| -uses that to provide IntelliSense. |
| 41 | +The way this works is that the Checker runs after each edit operation to validate the document and report errors in the |
| 42 | +TaskList. This process also puts `System.Xml.Schema.XmlSchemaType` information on each element and attribute in the |
| 43 | +XmlDocument; then, when editing the value of that node, the TextEditorOverlay uses the `XmlIntelliSenseProvider` to get |
| 44 | +back a list of possible values. In the above example, it returns the values from the simpleType enumeration facets. For |
| 45 | +element name IntelliSense in the tree view, the `XmlIntelliSenseProvider` invokes the Checker again, captures |
| 46 | +GetExpectedParticles and GetExpectedAttributes on the `System.Xml.Schema.XmlSchemaValidator`, and uses that to provide |
| 47 | +IntelliSense. |
50 | 48 |
|
51 | 49 | 
|
52 | 50 |
|
53 |
| -The `TextEditorOverlay` also supports custom editors like the `DateTimeEditor` or the `UriBuilder` |
54 |
| -or `ColorBuilder`. There are two types of custom editors: IXmlEditors, which are inline editors that |
55 |
| -replace the default TextBox, and IXmlBuilders, which are popup dialogs like the OpenFileDialog or |
56 |
| -ColorDialog. The type of editor is derived from the schema type information — "xs:date", "xs:time", |
57 |
| -"xs:datetime" results in the DateTimeEditor, and "xs:anyURI" results in the UriBuilder. You can also |
58 |
| -annotate the schema with a custom "vs:builder" attribute in the |
59 |
| -`http://schemas.microsoft.com/Visual-Studio-IntelliSense` namespace. See the Help content for more |
60 |
| -information. |
| 51 | +The `TextEditorOverlay` also supports custom editors like the `DateTimeEditor` or the `UriBuilder` or `ColorBuilder`. |
| 52 | +There are two types of custom editors: IXmlEditors, which are inline editors that replace the default TextBox, and |
| 53 | +IXmlBuilders, which are popup dialogs like the OpenFileDialog or ColorDialog. The type of editor is derived from the |
| 54 | +schema type information — "xs:date", "xs:time", "xs:datetime" results in the DateTimeEditor, and "xs:anyURI" results in |
| 55 | +the UriBuilder. You can also annotate the schema with a custom "vs:builder" attribute in the |
| 56 | +`http://schemas.microsoft.com/Visual-Studio-IntelliSense` namespace. See the Help content for more information. |
61 | 57 |
|
62 | 58 | ## Infinite Undo/Redo
|
63 | 59 |
|
64 |
| -To implement undo/redo, XML Notepad follows a common design pattern of Command objects with Undo and |
65 |
| -Redo methods. Commands operate on both a `TreeNode` and an `XmlNode` because some commands like |
66 |
| -`InsertNode` don't have an `XmlNode` yet until they are performed, but the command needs to know |
67 |
| -where in the tree this new node will be inserted and during `Undo` where it should be removed. The |
68 |
| -UndoManager collects these in a list. Then the state of the UndoManager controls the |
69 |
| -enabled/disabled state of the Undo/Redo MenuItems. When the user selects the Undo menu item, the |
70 |
| -Undo method is called on the active command, and that command is pushed onto the Redo stack. |
| 60 | +To implement undo/redo, XML Notepad follows a common design pattern of Command objects with Undo and Redo methods. |
| 61 | +Commands operate on both a `TreeNode` and an `XmlNode` because some commands like `InsertNode` don't have an `XmlNode` |
| 62 | +yet until they are performed, but the command needs to know where in the tree this new node will be inserted and during |
| 63 | +`Undo` where it should be removed. The UndoManager collects these in a list. Then the state of the UndoManager controls |
| 64 | +the enabled/disabled state of the Undo/Redo MenuItems. When the user selects the Undo menu item, the Undo method is |
| 65 | +called on the active command, and that command is pushed onto the Redo stack. |
71 | 66 |
|
72 | 67 | 
|
73 | 68 |
|
74 |
| -Some operations in the editor cause many edits in the tree, including the replace-all operation and |
75 |
| -editing the value of a namespace attribute. (When you change the value of a namespace attribute, |
76 |
| -every XmlNode bound to that namespace needs to be reconstructed with a new namespace URI, which can |
77 |
| -obviously affect a lot of nodes in the tree!) So, to make these operations one atomic undo |
78 |
| -operation, there is a `CompoundCommand` object that contains a list of smaller edit commands, and |
79 |
| -this CompoundCommand is put into the `UndoManager`. |
| 69 | +Some operations in the editor cause many edits in the tree, including the replace-all operation and editing the value of |
| 70 | +a namespace attribute. (When you change the value of a namespace attribute, every XmlNode bound to that namespace needs |
| 71 | +to be reconstructed with a new namespace URI, which can obviously affect a lot of nodes in the tree!) So, to make these |
| 72 | +operations one atomic undo operation, there is a `CompoundCommand` object that contains a list of smaller edit commands, |
| 73 | +and this CompoundCommand is put into the `UndoManager`. |
80 | 74 |
|
81 |
| -Other simpler command objects include the following, which all operate on XmlTreeNode and XmlNode |
82 |
| -objects: |
| 75 | +Other simpler command objects include the following, which all operate on XmlTreeNode and XmlNode objects: |
83 | 76 |
|
84 | 77 | 
|
85 | 78 |
|
86 |
| -The PasteCommand is special because it takes random XML text off the clipboard and parses it in |
87 |
| -the context of the currently selected element in the tree, inheriting the namespaces in scope. The |
88 |
| -helper class TreeData uses the special XmlTextReader constructor that takes an XmlParserContext as |
89 |
| -input. |
| 79 | +The PasteCommand is special because it takes random XML text off the clipboard and parses it in the context of the |
| 80 | +currently selected element in the tree, inheriting the namespaces in scope. The helper class TreeData uses the special |
| 81 | +XmlTextReader constructor that takes an XmlParserContext as input. |
90 | 82 |
|
91 | 83 | ### Accessibility
|
92 | 84 |
|
93 |
| -In order to make testing possible using `System.Windows.Automation`, there are some custom |
94 |
| -`AccessibleObject` implementations inside the TreeView and NodeTextView. See `AccessibleNode` and |
95 |
| -`AccessibleNodeTextViewNode`. These accessibility classes should also make Windows accessibility |
96 |
| -features work better with those custom views. |
| 85 | +In order to make testing possible using `System.Windows.Automation`, there are some custom `AccessibleObject` |
| 86 | +implementations inside the TreeView and NodeTextView. See `AccessibleNode` and `AccessibleNodeTextViewNode`. These |
| 87 | +accessibility classes should also make Windows accessibility features work better with those custom views. |
97 | 88 |
|
98 | 89 | ### Missing Documentation?
|
99 | 90 |
|
100 |
| -If you want more detailed documentation on some aspect of XML Notepad, please create a new [GitHub issue](https://github.com/microsoft/XmlNotepad/issues). |
| 91 | +If you want more detailed documentation on some aspect of XML Notepad, please create a new [GitHub |
| 92 | +issue](https://github.com/microsoft/XmlNotepad/issues). |
0 commit comments