Browse Source

Added a new view to the XML Editor which shows the XML as a tree view. Not feature complete. Currently it is possible to edit existing attribute values and element text but not add new ones or remove existing ones.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1797 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 20 years ago
parent
commit
df3d79371c
  1. BIN
      src/AddIns/DisplayBindings/XmlEditor/Project/Resources/XmlElementTreeNodeIcon.png
  2. BIN
      src/AddIns/DisplayBindings/XmlEditor/Project/Resources/XmlTextTreeNodeIcon.png
  3. 64
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/IXmlTreeView.cs
  4. 96
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlAttributePropertyDescriptor.cs
  5. 96
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlAttributeTypeDescriptor.cs
  6. 73
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlElementTreeNode.cs
  7. 59
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTextTreeNode.cs
  8. 97
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeEditor.cs
  9. 81
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs
  10. 418
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs
  11. 109
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs
  12. 38
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs
  13. 11
      src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.csproj
  14. 44
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/AttributeChangedTestFixture.cs
  15. 42
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DocumentElementOnlyTestFixture.cs
  16. 180
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/ExpandChildNodesInTreeControlTestFixture.cs
  17. 97
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/GetXmlAttributePropertyDescriptorTestFixture.cs
  18. 89
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/RootNodeAddedToTreeControlTestFixture.cs
  19. 82
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TextNodeTextChangedTestFixture.cs
  20. 61
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TreeControlViewStateTestFixture.cs
  21. 46
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/ViewInvalidXmlDocumentTestFixture.cs
  22. 50
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlAttributeTypeDescriptorTestFixture.cs
  23. 62
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlElementSelectedTestFixture.cs
  24. 52
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlElementTreeNodeTests.cs
  25. 49
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTextSelectedTestFixture.cs
  26. 59
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTextTreeNodeTextTests.cs
  27. 32
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTreeViewTestFixtureBase.cs
  28. 123
      src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockXmlTreeView.cs
  29. 16
      src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj

BIN
src/AddIns/DisplayBindings/XmlEditor/Project/Resources/XmlElementTreeNodeIcon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

BIN
src/AddIns/DisplayBindings/XmlEditor/Project/Resources/XmlTextTreeNodeIcon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

64
src/AddIns/DisplayBindings/XmlEditor/Project/Src/IXmlTreeView.cs

@ -0,0 +1,64 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
public interface IXmlTreeView
{
/// <summary>
/// Displays an error message indicating that the xml tree view
/// could not display the xml since the xml is not well formed.
/// </summary>
/// <param name="ex">The exception that occurred when the xml
/// was loaded.</param>
void ShowXmlIsNotWellFormedMessage(XmlException ex);
/// <summary>
/// Gets or sets whether this view needs saving.
/// </summary>
bool IsDirty {get; set;}
/// <summary>
/// Gets or sets the xml document element.
/// </summary>
XmlElement DocumentElement {get; set;}
/// <summary>
/// Gets the xml element selected.
/// </summary>
XmlElement SelectedElement {get;}
/// <summary>
/// Shows the attributes for the selected xml element in the view.
/// </summary>
void ShowAttributes(XmlAttributeCollection attributes);
/// <summary>
/// Removes the attributes from the view.
/// </summary>
void ClearAttributes();
/// <summary>
/// Shows the xml element text content.
/// </summary>
void ShowTextContent(string text);
/// <summary>
/// Gets the text content currently on display.
/// </summary>
string TextContent {get;}
/// <summary>
/// Gets the xml element text node.
/// </summary>
XmlText SelectedTextNode {get;}
}
}

96
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlAttributePropertyDescriptor.cs

@ -0,0 +1,96 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Property descriptor for an XmlAttribute. This is used when displaying
/// an XmlAttribute in the property grid.
/// </summary>
public class XmlAttributePropertyDescriptor : PropertyDescriptor
{
XmlAttribute xmlAttribute;
public XmlAttributePropertyDescriptor(XmlAttribute xmlAttribute)
: base(xmlAttribute.LocalName, new Attribute[0])
{
this.xmlAttribute = xmlAttribute;
}
/// <summary>
/// Gets the property descriptors for the specified attributes.
/// </summary>
public static PropertyDescriptorCollection GetProperties(XmlAttributeCollection xmlAttributes)
{
List<PropertyDescriptor> properties = new List<PropertyDescriptor>();
foreach (XmlAttribute xmlAttribute in xmlAttributes) {
properties.Add(new XmlAttributePropertyDescriptor(xmlAttribute));
}
return new PropertyDescriptorCollection(properties.ToArray());
}
public override Type ComponentType {
get {
return typeof(String);
}
}
public override bool IsReadOnly {
get {
return false;
}
}
/// <summary>
/// Returns the property type in this case a string.
/// </summary>
public override Type PropertyType {
get {
return typeof(String);
}
}
public override bool CanResetValue(object component)
{
return false;
}
/// <summary>
/// Gets the value of the xml attribute.
/// </summary>
public override object GetValue(object component)
{
return xmlAttribute.Value;
}
public override void ResetValue(object component)
{
}
/// <summary>
/// Sets the xml attribute value.
/// </summary>
public override void SetValue(object component, object value)
{
xmlAttribute.Value = (String)value;
}
/// <summary>
/// If the current value has changed from the default value then this
/// method will return true.
/// </summary>
public override bool ShouldSerializeValue(object component)
{
return true;
}
}
}

96
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlAttributeTypeDescriptor.cs

@ -0,0 +1,96 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Type descriptor that allows us to display properties in the property grid
/// for Xml attributes.
/// </summary>
public class XmlAttributeTypeDescriptor : ICustomTypeDescriptor
{
PropertyDescriptorCollection properties;
public XmlAttributeTypeDescriptor(XmlAttributeCollection xmlAttributes)
{
if (xmlAttributes != null) {
properties = XmlAttributePropertyDescriptor.GetProperties(xmlAttributes);
} else {
properties = new PropertyDescriptorCollection(new XmlAttributePropertyDescriptor[0]);
}
}
public AttributeCollection GetAttributes()
{
return null;
}
public string GetClassName()
{
return null;
}
public string GetComponentName()
{
return null;
}
public TypeConverter GetConverter()
{
return null;
}
public EventDescriptor GetDefaultEvent()
{
return null;
}
public PropertyDescriptor GetDefaultProperty()
{
return null;
}
public object GetEditor(Type editorBaseType)
{
return null;
}
public EventDescriptorCollection GetEvents()
{
return null;
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return null;
}
public PropertyDescriptorCollection GetProperties()
{
return GetProperties(new Attribute[0]);
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return properties;
}
/// <summary>
/// Returns this class instance.
/// </summary>
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
}
}

73
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlElementTreeNode.cs

@ -0,0 +1,73 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop.Gui;
using System;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
public class XmlElementTreeNode : ExtTreeNode
{
public const string XmlElementTreeNodeImageKey = "XmlElementTreeNodeImage";
XmlElement element;
public XmlElementTreeNode(XmlElement element)
{
this.element = element;
Text = GetDisplayText(element);
Tag = element;
ImageKey = XmlElementTreeNodeImageKey;
if (element.HasChildNodes) {
// Add dummy node so that the tree node can be
// expanded in the tree view.
Nodes.Add(new ExtTreeNode());
}
}
/// <summary>
/// Gets the XmlElement associated with this tree node.
/// </summary>
public XmlElement XmlElement {
get {
return element;
}
}
/// <summary>
/// Adds child elements to this tree node.
/// </summary>
protected override void Initialize()
{
Nodes.Clear();
foreach (XmlNode childNode in element.ChildNodes) {
XmlElement childElement = childNode as XmlElement;
XmlText text = childNode as XmlText;
if (childElement != null) {
XmlElementTreeNode treeNode = new XmlElementTreeNode(childElement);
treeNode.AddTo(this);
} else if (text != null) {
XmlTextTreeNode treeNode = new XmlTextTreeNode(text);
treeNode.AddTo(this);
}
}
}
/// <summary>
/// Gets the tree node's text for the element.
/// </summary>
static string GetDisplayText(XmlElement element)
{
if (element.Prefix.Length > 0) {
return String.Concat(element.Prefix, ":", element.LocalName);
}
return element.LocalName;
}
}
}

59
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTextTreeNode.cs

@ -0,0 +1,59 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop.Gui;
using System;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
public class XmlTextTreeNode : ExtTreeNode
{
public const string XmlTextTreeNodeImageKey = "XmlTextTreeNodeImage";
XmlText xmlText;
public XmlTextTreeNode(XmlText xmlText)
{
this.xmlText = xmlText;
ImageKey = XmlTextTreeNodeImageKey;
SelectedImageKey = ImageKey;
Text = GetDisplayText(xmlText.InnerText);
}
public XmlText XmlText {
get {
return xmlText;
}
}
/// <summary>
/// Gets the text to display for this tree node.
/// </summary>
/// <remarks>If the text is a single line then it is returned, but
/// trimmed. If the text has multiple lines then the first line that
/// is not empty is returned. This line may have "..." appended to indicate
/// there is more text for this node that is not being displayed. The
/// "..." will be appended only if there are multiple lines containing
/// text.</remarks>
static string GetDisplayText(string s)
{
string[] lines = s.Trim().Split('\n');
for (int i = 0; i < lines.Length; ++i) {
string line = lines[i].Trim();
if (line.Length > 0) {
if (lines.Length == 1) {
return line;
} else {
return String.Concat(line, "...");
}
}
}
return String.Empty;
}
}
}

97
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeEditor.cs

@ -0,0 +1,97 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// The class that is responsible for controlling the editing of the
/// Xml tree view.
/// </summary>
public class XmlTreeEditor
{
IXmlTreeView view;
XmlDocument document;
public XmlTreeEditor(IXmlTreeView view)
{
this.view = view;
}
/// <summary>
/// Loads the xml into the editor.
/// </summary>
public void LoadXml(string xml)
{
try {
document = new XmlDocument();
document.LoadXml(xml);
XmlElement documentElement = document.DocumentElement;
view.DocumentElement = documentElement;
} catch (XmlException ex) {
view.ShowXmlIsNotWellFormedMessage(ex);
}
}
/// <summary>
/// Gets the Xml document being edited.
/// </summary>
public XmlDocument Document {
get {
return document;
}
}
/// <summary>
/// The selected xml element in the view has changed.
/// </summary>
public void SelectedElementChanged()
{
XmlElement selectedElement = view.SelectedElement;
if (selectedElement != null) {
view.ShowAttributes(selectedElement.Attributes);
} else {
view.ClearAttributes();
}
}
/// <summary>
/// The selected xml text node in the view has changed.
/// </summary>
public void SelectedTextNodeChanged()
{
XmlText selectedTextNode = view.SelectedTextNode;
if (selectedTextNode != null) {
view.ShowTextContent(selectedTextNode.InnerText);
} else {
view.ShowTextContent(String.Empty);
}
}
/// <summary>
/// The attribute value has changed.
/// </summary>
public void AttributeValueChanged()
{
view.IsDirty = true;
}
/// <summary>
/// The text content has been changed in the view.
/// </summary>
public void TextContentChanged()
{
XmlText textNode = view.SelectedTextNode;
if (textNode != null) {
view.IsDirty = true;
textNode.Value = view.TextContent;
}
}
}
}

81
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs

@ -0,0 +1,81 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using System;
using System.Windows.Forms;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// The secondary view content that displays the XML document as a tree view.
/// </summary>
public class XmlTreeView : AbstractSecondaryViewContent
{
XmlTreeViewContainerControl treeViewContainer = new XmlTreeViewContainerControl();
XmlView xmlView;
bool disposed;
public XmlTreeView(XmlView xmlView)
{
this.xmlView = xmlView;
treeViewContainer.DirtyChanged += TreeViewContainerDirtyChanged;
}
public override Control Control {
get {
return treeViewContainer;
}
}
public override string TabPageText {
get {
return "XML Tree";
}
}
public override void Dispose()
{
if (!disposed) {
disposed = true;
treeViewContainer.Dispose();
}
}
public override void Selected()
{
treeViewContainer.LoadXml(xmlView.Text);
xmlView.CheckIsWellFormed();
}
public override void Deselecting()
{
if (!disposed) {
if (treeViewContainer.IsDirty) {
xmlView.ReplaceAll(treeViewContainer.Document.OuterXml);
treeViewContainer.IsDirty = false;
}
}
}
public XmlElement DocumentElement {
get {
return treeViewContainer.TreeView.DocumentElement;
}
set {
treeViewContainer.DocumentElement = value;
}
}
void TreeViewContainerDirtyChanged(object source, EventArgs e)
{
xmlView.IsDirty = treeViewContainer.IsDirty;
}
}
}

418
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs

@ -0,0 +1,418 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// This user control holds both the XmlTreeViewControl and the
/// attributes property grid in a split container. This is separate from
/// the XmlTreeView class so we can use the forms designer to design this control.
/// </summary>
public class XmlTreeViewContainerControl : System.Windows.Forms.UserControl, IXmlTreeView
{
XmlTreeEditor editor;
bool dirty;
bool errorMessageTextBoxVisible;
bool attributesGridVisible = true;
bool textBoxVisible;
public event EventHandler DirtyChanged;
public XmlTreeViewContainerControl()
{
InitializeComponent();
InitImages();
}
/// <summary>
/// Gets or sets whether the xml document needs saving.
/// </summary>
public bool IsDirty {
get {
return dirty;
}
set {
dirty = value;
}
}
/// <summary>
/// Gets or sets the error message to display.
/// </summary>
public string ErrorMessage {
get {
return errorMessageTextBox.Text;
}
set {
errorMessageTextBox.Text = value;
}
}
/// <summary>
/// Gets or sets whether the error message is visible. When visible the
/// error message text box replaces the property grid.
/// </summary>
public bool IsErrorMessageTextBoxVisible {
get {
return errorMessageTextBoxVisible;
}
set {
errorMessageTextBoxVisible = value;
if (value) {
errorMessageTextBox.BringToFront();
errorMessageTextBox.TabStop = true;;
IsAttributesGridVisible = false;
IsTextBoxVisible = false;
} else {
errorMessageTextBox.SendToBack();
errorMessageTextBox.TabStop = false;
}
}
}
public XmlTreeViewControl TreeView {
get {
return xmlElementTreeView;
}
}
public void ShowXmlIsNotWellFormedMessage(XmlException ex)
{
xmlElementTreeView.Clear();
ErrorMessage = ex.Message;
IsErrorMessageTextBoxVisible = true;
}
public XmlElement DocumentElement {
get {
return xmlElementTreeView.DocumentElement;
}
set {
xmlElementTreeView.DocumentElement = value;
}
}
/// <summary>
/// Displays the specified xml as a tree.
/// </summary>
public void LoadXml(string xml)
{
textBox.Clear();
IsAttributesGridVisible = true;
ClearAttributes();
editor = new XmlTreeEditor(this);
editor.LoadXml(xml);
// Expand document element node. This ensures that the view state
// can be restored since the child nodes are lazily added.
if (xmlElementTreeView.Nodes.Count > 0) {
xmlElementTreeView.Nodes[0].Expand();
}
}
/// <summary>
/// Gets the xml document created from the loaded Xml.
/// </summary>
public XmlDocument Document {
get {
return editor.Document;
}
}
/// <summary>
/// Shows the attributes.
/// </summary>
public void ShowAttributes(XmlAttributeCollection attributes)
{
IsAttributesGridVisible = true;
attributesGrid.SelectedObject = new XmlAttributeTypeDescriptor(attributes);
}
/// <summary>
/// Clears all the attributes currently on display.
/// </summary>
public void ClearAttributes()
{
attributesGrid.SelectedObject = null;
}
/// <summary>
/// Shows the xml element's text content after the user has
/// selected the text node.
/// </summary>
public void ShowTextContent(string text)
{
IsTextBoxVisible = true;
textBox.Text = text;
}
/// <summary>
/// Gets the text node text currently on display.
/// </summary>
public string TextContent {
get {
return textBox.Text;
}
}
/// <summary>
/// Gets the element currently selected.
/// </summary>
public XmlElement SelectedElement {
get {
return xmlElementTreeView.SelectedElement;
}
}
/// <summary>
/// Gets the element text node currently selected.
/// </summary>
public XmlText SelectedTextNode {
get {
return xmlElementTreeView.SelectedTextNode;
}
}
/// <summary>
/// Disposes resources used by the control.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Forms Designer generated code
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
System.ComponentModel.IContainer components = null;
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
ICSharpCode.SharpDevelop.Gui.ExtTreeViewComparer extTreeViewComparer1 = new ICSharpCode.SharpDevelop.Gui.ExtTreeViewComparer();
this.splitContainer = new System.Windows.Forms.SplitContainer();
this.xmlElementTreeView = new ICSharpCode.XmlEditor.XmlTreeViewControl();
this.attributesGrid = new System.Windows.Forms.PropertyGrid();
this.errorMessageTextBox = new System.Windows.Forms.RichTextBox();
this.textBox = new System.Windows.Forms.RichTextBox();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
this.splitContainer.SuspendLayout();
this.SuspendLayout();
//
// splitContainer
//
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer.Location = new System.Drawing.Point(0, 0);
this.splitContainer.Name = "splitContainer";
//
// splitContainer.Panel1
//
this.splitContainer.Panel1.Controls.Add(this.xmlElementTreeView);
//
// splitContainer.Panel2
//
this.splitContainer.Panel2.Controls.Add(this.attributesGrid);
this.splitContainer.Panel2.Controls.Add(this.errorMessageTextBox);
this.splitContainer.Panel2.Controls.Add(this.textBox);
this.splitContainer.Size = new System.Drawing.Size(562, 326);
this.splitContainer.SplitterDistance = 185;
this.splitContainer.SplitterWidth = 2;
this.splitContainer.TabIndex = 0;
this.splitContainer.TabStop = false;
//
// xmlElementTreeView
//
this.xmlElementTreeView.AllowDrop = true;
this.xmlElementTreeView.CanClearSelection = true;
this.xmlElementTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
this.xmlElementTreeView.DocumentElement = null;
this.xmlElementTreeView.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawText;
this.xmlElementTreeView.HideSelection = false;
this.xmlElementTreeView.ImageIndex = 0;
this.xmlElementTreeView.IsSorted = false;
this.xmlElementTreeView.Location = new System.Drawing.Point(0, 0);
this.xmlElementTreeView.Name = "xmlElementTreeView";
this.xmlElementTreeView.NodeSorter = extTreeViewComparer1;
this.xmlElementTreeView.SelectedImageIndex = 0;
this.xmlElementTreeView.Size = new System.Drawing.Size(185, 326);
this.xmlElementTreeView.TabIndex = 0;
this.xmlElementTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.XmlElementTreeViewAfterSelect);
//
// attributesGrid
//
this.attributesGrid.Dock = System.Windows.Forms.DockStyle.Fill;
this.attributesGrid.HelpVisible = false;
this.attributesGrid.Location = new System.Drawing.Point(0, 0);
this.attributesGrid.Name = "attributesGrid";
this.attributesGrid.PropertySort = System.Windows.Forms.PropertySort.Alphabetical;
this.attributesGrid.Size = new System.Drawing.Size(375, 326);
this.attributesGrid.TabIndex = 1;
this.attributesGrid.ToolbarVisible = false;
this.attributesGrid.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.AttributesGridPropertyValueChanged);
//
// errorMessageTextBox
//
this.errorMessageTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.errorMessageTextBox.Location = new System.Drawing.Point(0, 0);
this.errorMessageTextBox.Name = "errorMessageTextBox";
this.errorMessageTextBox.Size = new System.Drawing.Size(375, 326);
this.errorMessageTextBox.TabIndex = 0;
this.errorMessageTextBox.TabStop = false;
this.errorMessageTextBox.Text = "";
//
// textBox
//
this.textBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox.Location = new System.Drawing.Point(0, 0);
this.textBox.Name = "textBox";
this.textBox.Size = new System.Drawing.Size(375, 326);
this.textBox.TabIndex = 2;
this.textBox.TabStop = false;
this.textBox.Text = "";
this.textBox.TextChanged += new System.EventHandler(this.TextBoxTextChanged);
//
// XmlTreeViewContainerControl
//
this.Controls.Add(this.splitContainer);
this.Name = "XmlTreeViewContainerControl";
this.Size = new System.Drawing.Size(562, 326);
this.splitContainer.Panel1.ResumeLayout(false);
this.splitContainer.Panel2.ResumeLayout(false);
this.splitContainer.ResumeLayout(false);
this.ResumeLayout(false);
}
private System.Windows.Forms.RichTextBox textBox;
private System.Windows.Forms.PropertyGrid attributesGrid;
private System.Windows.Forms.RichTextBox errorMessageTextBox;
private ICSharpCode.XmlEditor.XmlTreeViewControl xmlElementTreeView;
private System.Windows.Forms.SplitContainer splitContainer;
#endregion
/// <summary>
/// Creates an image list that will be used for the XmlTreeViewControl.
/// </summary>
void InitImages()
{
if (components == null) {
components = new Container();
}
ImageList images = new ImageList(components);
Image xmlElementImage = Image.FromStream(GetType().Assembly.GetManifestResourceStream("ICSharpCode.XmlEditor.Resources.XmlElementTreeNodeIcon.png"));
images.Images.Add(XmlElementTreeNode.XmlElementTreeNodeImageKey, xmlElementImage);
Image xmlTextImage = Image.FromStream(GetType().Assembly.GetManifestResourceStream("ICSharpCode.XmlEditor.Resources.XmlTextTreeNodeIcon.png"));
images.Images.Add(XmlTextTreeNode.XmlTextTreeNodeImageKey, xmlTextImage);
xmlElementTreeView.ImageList = images;
}
void XmlElementTreeViewAfterSelect(object sender, TreeViewEventArgs e)
{
if (xmlElementTreeView.IsTextNodeSelected) {
editor.SelectedTextNodeChanged();
} else {
editor.SelectedElementChanged();
}
}
void TextBoxTextChanged(object sender, EventArgs e)
{
bool previousIsDirty = dirty;
editor.TextContentChanged();
OnXmlChanged(previousIsDirty);
}
void AttributesGridPropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
bool previousIsDirty = dirty;
editor.AttributeValueChanged();
OnXmlChanged(previousIsDirty);
}
/// <summary>
/// Raises the dirty changed event if the dirty flag has changed.
/// </summary>
void OnXmlChanged(bool previousIsDirty)
{
if (previousIsDirty != dirty) {
OnDirtyChanged();
}
}
/// <summary>
/// Raises the DirtyChanged event.
/// </summary>
void OnDirtyChanged()
{
if (DirtyChanged != null) {
DirtyChanged(this, new EventArgs());
}
}
/// <summary>
/// Gets or sets whether the attributes grid is visible.
/// </summary>
bool IsAttributesGridVisible {
get {
return attributesGridVisible;
}
set {
attributesGridVisible = value;
if (value) {
attributesGrid.BringToFront();
attributesGrid.TabStop = true;
IsTextBoxVisible = false;
IsErrorMessageTextBoxVisible = false;
} else {
attributesGrid.SendToBack();
attributesGrid.TabStop = false;
}
}
}
/// <summary>
/// Gets or sets whether the text node text box is visible.
/// </summary>
bool IsTextBoxVisible {
get {
return textBoxVisible;
}
set {
textBoxVisible = value;
if (value) {
textBox.BringToFront();
textBox.TabStop = true;
IsAttributesGridVisible = false;
IsErrorMessageTextBoxVisible = false;
} else {
textBox.SendToBack();
textBox.TabStop = false;
}
}
}
}
}

109
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs

@ -0,0 +1,109 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Xml;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Displays a tree of XML elements. This is a separate control so it can
/// be unit tested. It has no SharpDevelop specific parts, for example,
/// the context menus are defined in the XmlTreeViewContainerControl.
/// </summary>
public class XmlTreeViewControl : ExtTreeView
{
const string ViewStatePropertyName = "XmlTreeViewControl.ViewState";
XmlElement documentElement;
public XmlTreeViewControl()
{
}
[Browsable(false)]
public XmlElement DocumentElement {
get {
return documentElement;
}
set {
documentElement = value;
// Update display.
BeginUpdate();
try {
ShowDocumentElement();
} finally {
EndUpdate();
}
}
}
public XmlElement SelectedElement {
get {
XmlElementTreeNode xmlElementTreeNode = SelectedNode as XmlElementTreeNode;
if (xmlElementTreeNode != null) {
return xmlElementTreeNode.XmlElement;
}
return null;
}
}
public bool IsElementSelected {
get {
return SelectedElement != null;
}
}
public XmlText SelectedTextNode {
get {
XmlTextTreeNode xmlTextTreeNode = SelectedNode as XmlTextTreeNode;
if (xmlTextTreeNode != null) {
return xmlTextTreeNode.XmlText;
}
return null;
}
}
public bool IsTextNodeSelected {
get {
return SelectedTextNode != null;
}
}
/// <summary>
/// Saves the current state of the tree.
/// </summary>
public void SaveViewState(Properties properties)
{
properties.Set(ViewStatePropertyName, ExtTreeView.GetViewStateString(this));
}
/// <summary>
/// Restores the node state of the tree.
/// </summary>
public void RestoreViewState(Properties properties)
{
ExtTreeView.ApplyViewStateString(properties.Get(ViewStatePropertyName, String.Empty), this);
}
void ShowDocumentElement()
{
Nodes.Clear();
if (documentElement != null) {
XmlElementTreeNode node = new XmlElementTreeNode(documentElement);
node.AddTo(this);
}
}
}
}

38
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs

@ -49,6 +49,7 @@ namespace ICSharpCode.XmlEditor
bool wasChangedExternally; bool wasChangedExternally;
static MessageViewCategory category; static MessageViewCategory category;
string stylesheetFileName; string stylesheetFileName;
XmlTreeView xmlTreeView;
public XmlView() public XmlView()
{ {
@ -65,6 +66,9 @@ namespace ICSharpCode.XmlEditor
XmlEditorAddInOptions.PropertyChanged += PropertyChanged; XmlEditorAddInOptions.PropertyChanged += PropertyChanged;
XmlSchemaManager.UserSchemaAdded += new EventHandler(UserSchemaAdded); XmlSchemaManager.UserSchemaAdded += new EventHandler(UserSchemaAdded);
XmlSchemaManager.UserSchemaRemoved += new EventHandler(UserSchemaRemoved); XmlSchemaManager.UserSchemaRemoved += new EventHandler(UserSchemaRemoved);
xmlTreeView = new XmlTreeView(this);
SecondaryViewContents.Add(xmlTreeView);
} }
/// <summary> /// <summary>
@ -364,9 +368,7 @@ namespace ICSharpCode.XmlEditor
TaskService.ClearExceptCommentTasks(); TaskService.ClearExceptCommentTasks();
if (IsWellFormed) { if (IsWellFormed) {
string xml = SimpleFormat(IndentedFormat(Text)); ReplaceAll(Text);
xmlEditor.Document.Replace(0, xmlEditor.Document.TextLength, xml);
UpdateFolding();
} else { } else {
ShowErrorList(); ShowErrorList();
} }
@ -417,6 +419,29 @@ namespace ICSharpCode.XmlEditor
} }
} }
/// <summary>
/// Checks that the xml is well formed. Any errors are displayed in the
/// errors list.
/// </summary>
public void CheckIsWellFormed()
{
TaskService.ClearExceptCommentTasks();
if (!IsWellFormed) {
ShowErrorList();
}
}
/// <summary>
/// Replaces the entire text of the xml view with the xml in the
/// specified. The xml will be formatted.
/// </summary>
public void ReplaceAll(string xml)
{
string formattedXml = SimpleFormat(IndentedFormat(xml));
xmlEditor.Document.Replace(0, xmlEditor.Document.TextLength, formattedXml);
UpdateFolding();
}
#region IEditable interface #region IEditable interface
public IClipboardHandler ClipboardHandler { public IClipboardHandler ClipboardHandler {
@ -604,9 +629,8 @@ namespace ICSharpCode.XmlEditor
xmlEditor.Document.HighlightingStrategy = highlightingStrategy; xmlEditor.Document.HighlightingStrategy = highlightingStrategy;
} }
} }
xmlEditor.ActiveTextAreaControl.TextArea.TextView.FirstVisibleLine = properties.Get("VisibleLine", 0); xmlEditor.ActiveTextAreaControl.TextArea.TextView.FirstVisibleLine = properties.Get("VisibleLine", 0);
xmlEditor.Document.FoldingManager.DeserializeFromString(properties.Get("Foldings", String.Empty));
xmlEditor.Document.FoldingManager.DeserializeFromString(properties.Get("Foldings", ""));
} }
public Properties CreateMemento() public Properties CreateMemento()
@ -1005,7 +1029,7 @@ namespace ICSharpCode.XmlEditor
bool IsWellFormed { bool IsWellFormed {
get { get {
try { try {
XmlDocument Document = new XmlDocument( ); XmlDocument Document = new XmlDocument();
Document.LoadXml(Text); Document.LoadXml(Text);
return true; return true;
} catch(XmlException ex) { } catch(XmlException ex) {

11
src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.csproj

@ -115,6 +115,17 @@
<Compile Include="Src\RemoveXPathHighlightingCommand.cs" /> <Compile Include="Src\RemoveXPathHighlightingCommand.cs" />
<Compile Include="Src\GoToSchemaDefinitionCommand.cs" /> <Compile Include="Src\GoToSchemaDefinitionCommand.cs" />
<Compile Include="Src\GoToSchemaDefinitionEditAction.cs" /> <Compile Include="Src\GoToSchemaDefinitionEditAction.cs" />
<Compile Include="Src\XmlTreeEditor.cs" />
<Compile Include="Src\IXmlTreeView.cs" />
<Compile Include="Src\XmlTreeView.cs" />
<Compile Include="Src\XmlTreeViewContainerControl.cs" />
<Compile Include="Src\XmlTreeViewControl.cs" />
<EmbeddedResource Include="Resources\XmlElementTreeNodeIcon.png" />
<Compile Include="Src\XmlElementTreeNode.cs" />
<Compile Include="Src\XmlTextTreeNode.cs" />
<EmbeddedResource Include="Resources\XmlTextTreeNodeIcon.png" />
<Compile Include="Src\XmlAttributePropertyDescriptor.cs" />
<Compile Include="Src\XmlAttributeTypeDescriptor.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj"> <ProjectReference Include="..\..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj">

44
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/AttributeChangedTestFixture.cs

@ -0,0 +1,44 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests that an attribute being changed updates the xml document and
/// sets the view to be dirty.
/// </summary>
[TestFixture]
public class AttributeChangedTestFixture : XmlTreeViewTestFixtureBase
{
[SetUp]
public void SetUpFixture()
{
base.InitFixture();
mockXmlTreeView.SelectedElement = mockXmlTreeView.DocumentElement;
editor.SelectedElementChanged();
XmlAttribute attribute = mockXmlTreeView.DocumentElement.Attributes["first"];
attribute.Value = "new value";
editor.AttributeValueChanged();
}
[Test]
public void IsDirty()
{
Assert.IsTrue(mockXmlTreeView.IsDirty);
}
protected override string GetXml()
{
return "<root first='a'/>";
}
}
}

42
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DocumentElementOnlyTestFixture.cs

@ -0,0 +1,42 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
using XmlEditor.Tests.Utils;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class DocumentElementOnlyTestFixture : XmlTreeViewTestFixtureBase
{
[TestFixtureSetUp]
public void SetUpFixture()
{
base.InitFixture();
}
[Test]
public void RootElementAdded()
{
Assert.AreEqual("root", mockXmlTreeView.DocumentElement.Name);
}
[Test]
public void RootElementInDocument()
{
Assert.IsTrue(Object.ReferenceEquals(editor.Document.DocumentElement, mockXmlTreeView.DocumentElement));
}
protected override string GetXml()
{
return "<root/>";
}
}
}

180
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/ExpandChildNodesInTreeControlTestFixture.cs

@ -0,0 +1,180 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Windows.Forms;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class ExpandChildNodesInTreeControlTestFixture
{
ExtTreeNode rootNode;
XmlDocument doc;
ExtTreeNode firstChildNode;
ExtTreeNode secondChildNode;
ExtTreeNode textChildNode;
ExtTreeNode textNode;
bool rootNodeHadChildrenBeforeExpansion;
bool firstChildNodeHadChildrenBeforeExpansion;
XmlElement rootNodeElement;
XmlElement textNodeElement;
bool isRootElementSelected;
bool isTextContentSelectedBeforeTextNodeSelected;
bool isTextContentSelectedAfterTextNodeSelected;
XmlText textContentBefore;
XmlText textContentAfter;
[TestFixtureSetUp]
public void SetUpFixture()
{
doc = new XmlDocument();
doc.LoadXml("<root><firstChild><secondChild/></firstChild><textChild>some text</textChild></root>");
using (XmlTreeViewControl treeView = new XmlTreeViewControl()) {
treeView.DocumentElement = doc.DocumentElement;
treeView.SelectedNode = treeView.Nodes[0];
rootNodeElement = treeView.SelectedElement;
isRootElementSelected = treeView.IsElementSelected;
rootNode = (ExtTreeNode)treeView.SelectedNode;
rootNodeHadChildrenBeforeExpansion = rootNode.Nodes.Count > 0;
rootNode.Expanding();
firstChildNode = (ExtTreeNode)rootNode.Nodes[0];
firstChildNodeHadChildrenBeforeExpansion = firstChildNode.Nodes.Count > 0;
firstChildNode.Expanding();
secondChildNode = (ExtTreeNode)firstChildNode.Nodes[0];
textChildNode = (ExtTreeNode)rootNode.Nodes[1];
textChildNode.Expanding();
textNode = (ExtTreeNode)textChildNode.Nodes[0];
isTextContentSelectedBeforeTextNodeSelected = treeView.IsTextNodeSelected;
textContentBefore = treeView.SelectedTextNode;
treeView.SelectedNode = textNode;
isTextContentSelectedAfterTextNodeSelected = treeView.IsTextNodeSelected;
textContentAfter = treeView.SelectedTextNode;
textNodeElement = treeView.SelectedElement;
}
}
[Test]
public void RootElementIsDocumentElement()
{
Assert.IsTrue(Object.ReferenceEquals(rootNodeElement, doc.DocumentElement));
}
[Test]
public void RootNodeHadChildrenBeforeExpansion()
{
Assert.IsTrue(rootNodeHadChildrenBeforeExpansion);
}
[Test]
public void RootNodeText()
{
Assert.AreEqual("root", rootNode.Text);
}
[Test]
public void FirstChildNodeHadChildrenBeforeExpansion()
{
Assert.IsTrue(firstChildNodeHadChildrenBeforeExpansion);
}
[Test]
public void FirstChildNodeText()
{
Assert.AreEqual("firstChild", firstChildNode.Text);
}
[Test]
public void FirstChildNodeImageKey()
{
Assert.AreEqual(XmlElementTreeNode.XmlElementTreeNodeImageKey, firstChildNode.ImageKey);
}
[Test]
public void SecondChildNodeText()
{
Assert.AreEqual("secondChild", secondChildNode.Text);
}
[Test]
public void SecondChildNodeImageKey()
{
Assert.AreEqual(XmlElementTreeNode.XmlElementTreeNodeImageKey, secondChildNode.ImageKey);
}
[Test]
public void TextChildNodeText()
{
Assert.AreEqual("textChild", textChildNode.Text);
}
[Test]
public void TextNodeExists()
{
Assert.IsNotNull(textNode);
}
[Test]
public void TextNodeImageKey()
{
Assert.AreEqual(XmlTextTreeNode.XmlTextTreeNodeImageKey, textNode.ImageKey);
}
[Test]
public void TextNodeSelectedImageKey()
{
Assert.AreEqual(XmlTextTreeNode.XmlTextTreeNodeImageKey, textNode.SelectedImageKey);
}
[Test]
public void TextNodeText()
{
Assert.AreEqual("some text", textNode.Text);
}
[Test]
public void NoElementForSelectedTextNode()
{
Assert.IsNull(textNodeElement);
}
[Test]
public void IsElementSelectedForRootNode()
{
Assert.IsTrue(isRootElementSelected);
}
[Test]
public void TextContentNotSelectedBeforeTextNodeSelected()
{
Assert.IsFalse(isTextContentSelectedBeforeTextNodeSelected);
}
[Test]
public void TextContentSelectedAfterTextNodeSelected()
{
Assert.IsTrue(isTextContentSelectedAfterTextNodeSelected);
}
[Test]
public void TextNodeNotSelectedBeforeTextNodeSelected()
{
Assert.IsNull(textContentBefore);
}
[Test]
public void TextNodeSelectedAfterTextNodeSelected()
{
Assert.IsNotNull(textContentAfter);
Assert.AreEqual("some text", textContentAfter.InnerText);
}
}
}

97
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/GetXmlAttributePropertyDescriptorTestFixture.cs

@ -0,0 +1,97 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.ComponentModel;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class GetXmlAttributePropertyDescriptorTestFixture
{
PropertyDescriptorCollection properties;
XmlAttributePropertyDescriptor firstAttributePropertyDescriptor;
XmlAttributePropertyDescriptor secondAttributePropertyDescriptor;
XmlAttribute firstAttribute;
[SetUp]
public void Init()
{
XmlDocument document = new XmlDocument();
document.LoadXml("<root first='a' second='b'/>");
firstAttribute = document.DocumentElement.GetAttributeNode("first");
properties = XmlAttributePropertyDescriptor.GetProperties(document.DocumentElement.Attributes);
firstAttributePropertyDescriptor = (XmlAttributePropertyDescriptor)properties["first"];
secondAttributePropertyDescriptor = (XmlAttributePropertyDescriptor)properties["second"];
}
[Test]
public void TwoPropertyDescriptors()
{
Assert.AreEqual(2, properties.Count);
}
[Test]
public void FirstPropertyName()
{
Assert.AreEqual("first", firstAttributePropertyDescriptor.Name);
}
[Test]
public void FirstPropertyComponentType()
{
Assert.AreEqual(typeof(String), firstAttributePropertyDescriptor.ComponentType);
}
[Test]
public void FirstPropertyReadOnly()
{
Assert.IsFalse(firstAttributePropertyDescriptor.IsReadOnly);
}
[Test]
public void FirstPropertyType()
{
Assert.AreEqual(typeof(String), firstAttributePropertyDescriptor.PropertyType);
}
[Test]
public void FirstPropertyCanResetValue()
{
Assert.IsFalse(firstAttributePropertyDescriptor.CanResetValue(null));
}
[Test]
public void FirstPropertyShouldSerializeValue()
{
Assert.IsTrue(firstAttributePropertyDescriptor.ShouldSerializeValue(null));
}
[Test]
public void FirstPropertyValue()
{
Assert.AreEqual("a", (String)firstAttributePropertyDescriptor.GetValue(null));
}
[Test]
public void SecondPropertyValue()
{
Assert.AreEqual("b", (String)secondAttributePropertyDescriptor.GetValue(null));
}
[Test]
public void SetFirstPropertyValue()
{
firstAttributePropertyDescriptor.SetValue(null, "new value");
Assert.AreEqual("new value", (String)firstAttributePropertyDescriptor.GetValue(null));
Assert.AreEqual("new value", firstAttribute.Value);
}
}
}

89
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/RootNodeAddedToTreeControlTestFixture.cs

@ -0,0 +1,89 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Windows.Forms;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class RootNodeAddedToTreeControlTestFixture
{
XmlElementTreeNode rootNode;
int nodeCount;
XmlDocument doc;
XmlElement initialElementSelected;
bool initialIsElementSelected;
[TestFixtureSetUp]
public void SetUpFixture()
{
doc = new XmlDocument();
doc.LoadXml("<test/>");
using (XmlTreeViewControl treeView = new XmlTreeViewControl()) {
treeView.DocumentElement = doc.DocumentElement;
initialElementSelected = treeView.SelectedElement;
initialIsElementSelected = treeView.IsElementSelected;
// Set the document element again to make sure the existing node
// is removed.
doc.LoadXml("<root/>");
treeView.DocumentElement = null;
treeView.DocumentElement = doc.DocumentElement;
rootNode = (XmlElementTreeNode)treeView.Nodes[0];
nodeCount = treeView.Nodes.Count;
}
}
[Test]
public void NoElementSelectedInitially()
{
Assert.IsNull(initialElementSelected);
}
[Test]
public void IsNoElementSelectedInitially()
{
Assert.IsFalse(initialIsElementSelected);
}
[Test]
public void OneNodeAdded()
{
Assert.AreEqual(1, nodeCount);
}
[Test]
public void RootNodeText()
{
Assert.AreEqual("root", rootNode.Text);
}
[Test]
public void ImageKey()
{
Assert.AreEqual(XmlElementTreeNode.XmlElementTreeNodeImageKey, rootNode.ImageKey);
}
[Test]
public void RootNodeHasNoChildren()
{
Assert.AreEqual(0, rootNode.Nodes.Count);
}
[Test]
public void RootXmlElement()
{
Assert.IsTrue(Object.ReferenceEquals(rootNode.XmlElement, doc.DocumentElement));
}
}
}

82
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TextNodeTextChangedTestFixture.cs

@ -0,0 +1,82 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests that the text for a text node being changed updates the xml document and
/// sets the view to be dirty.
/// </summary>
[TestFixture]
public class TextNodeTextChangedTestFixture : XmlTreeViewTestFixtureBase
{
XmlText textNode;
[SetUp]
public void SetUpFixture()
{
base.InitFixture();
// User selects text node and alters its text.
textNode = (XmlText)mockXmlTreeView.DocumentElement.FirstChild;
mockXmlTreeView.SelectedTextNode = textNode;
editor.SelectedTextNodeChanged();
mockXmlTreeView.TextContentDisplayed = "new value";
editor.TextContentChanged();
// The user then selects another element and then switches
// back to the text node.
mockXmlTreeView.SelectedElement = mockXmlTreeView.DocumentElement;
editor.SelectedElementChanged();
mockXmlTreeView.TextContentDisplayed = String.Empty;
mockXmlTreeView.SelectedTextNode = textNode;
editor.SelectedTextNodeChanged();
}
[Test]
public void IsDirty()
{
Assert.IsTrue(mockXmlTreeView.IsDirty);
}
[Test]
public void TextContentDisplayed()
{
Assert.AreEqual("new value", mockXmlTreeView.TextContentDisplayed);
}
[Test]
public void TextNodeUpdated()
{
Assert.AreEqual("new value", textNode.Value);
}
/// <summary>
/// Tests that no exception occurs when the view's text node is null and
/// that the IsDirty flag is not set to true when there is no text node.
/// </summary>
[Test]
public void NoTextNodeSelected()
{
mockXmlTreeView.IsDirty = false;
mockXmlTreeView.SelectedTextNode = null;
editor.TextContentChanged();
Assert.IsFalse(mockXmlTreeView.IsDirty);
}
protected override string GetXml()
{
return "<root>text</root>";
}
}
}

61
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TreeControlViewStateTestFixture.cs

@ -0,0 +1,61 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class TreeControlViewStateTestFixture
{
Properties savedProperties = new Properties();
Properties restoredProperties = new Properties();
string expectedSavedViewState;
[TestFixtureSetUp]
public void SetUpFixture()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<a><b>text</b><c>text</c></a>");
// Save view state.
using (XmlTreeViewControl treeView = new XmlTreeViewControl()) {
treeView.DocumentElement = doc.DocumentElement;
ExtTreeNode node = (ExtTreeNode)treeView.Nodes[0];
node.Expanding();
expectedSavedViewState = ExtTreeView.GetViewStateString(treeView);
treeView.SaveViewState(savedProperties);
}
// Load view state.
using (XmlTreeViewControl treeView = new XmlTreeViewControl()) {
treeView.DocumentElement = doc.DocumentElement;
ExtTreeNode node = (ExtTreeNode)treeView.Nodes[0];
node.Expanding();
treeView.RestoreViewState(restoredProperties);
}
}
[Test]
public void ViewStateSaved()
{
string savedViewState = (string)savedProperties.Get("XmlTreeViewControl.ViewState");
Assert.AreEqual(expectedSavedViewState, savedViewState);
}
[Test]
public void ViewStateLoaded()
{
Assert.AreEqual(String.Empty, restoredProperties.Get("XmlTreeViewControl.ViewState"));
}
}
}

46
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/ViewInvalidXmlDocumentTestFixture.cs

@ -0,0 +1,46 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
using XmlEditor.Tests.Utils;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests that the XmlTreeEditor shows an error message when the xml
/// is not well formed.
/// </summary>
[TestFixture]
public class ViewInvalidXmlDocumentTestFixture : XmlTreeViewTestFixtureBase
{
[TestFixtureSetUp]
public void SetUpFixture()
{
base.InitFixture();
}
[Test]
public void IsXmlNotWellFormedErrorDisplayed()
{
Assert.IsTrue(mockXmlTreeView.IsXmlNotWellFormedMessageDisplayed);
}
[Test]
public void XmlExceptionPassedToView()
{
Assert.IsNotNull(mockXmlTreeView.NotWellFormedExceptionPassed);
}
protected override string GetXml()
{
return "<BadXml>";
}
}
}

50
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlAttributeTypeDescriptorTestFixture.cs

@ -0,0 +1,50 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.ComponentModel;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class XmlAttributeTypeDescriptorTestFixture
{
XmlAttributeTypeDescriptor typeDescriptor;
[SetUp]
public void Init()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<root first='a'/>");
typeDescriptor = new XmlAttributeTypeDescriptor(doc.DocumentElement.Attributes);
}
[Test]
public void OneProperty()
{
PropertyDescriptorCollection properties = typeDescriptor.GetProperties();
Assert.AreEqual(1, properties.Count);
}
[Test]
public void PropertyName()
{
PropertyDescriptorCollection properties = typeDescriptor.GetProperties();
PropertyDescriptor descriptor = properties[0];
Assert.AreEqual("first", descriptor.Name);
}
[Test]
public void PropertyOwner()
{
Assert.IsTrue(Object.ReferenceEquals(typeDescriptor, typeDescriptor.GetPropertyOwner(null)));
}
}
}

62
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlElementSelectedTestFixture.cs

@ -0,0 +1,62 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// A tree node that represents an xml element is selected. This test
/// checks that the XmlTreeEditor tells the view to display the
/// element's attributes.
/// </summary>
[TestFixture]
public class XmlElementSelectedTestFixture : XmlTreeViewTestFixtureBase
{
[SetUp]
public void SetUpFixture()
{
base.InitFixture();
mockXmlTreeView.SelectedElement = mockXmlTreeView.DocumentElement;
editor.SelectedElementChanged();
}
[Test]
public void AttributesDisplayed()
{
Assert.AreEqual(2, mockXmlTreeView.AttributesDisplayed.Count);
}
[Test]
public void FirstAttributeName()
{
Assert.AreEqual("first", mockXmlTreeView.AttributesDisplayed[0].Name);
}
[Test]
public void SecondAttributeName()
{
Assert.AreEqual("second", mockXmlTreeView.AttributesDisplayed[1].Name);
}
[Test]
public void NoElementSelected()
{
mockXmlTreeView.SelectedElement = null;
editor.SelectedElementChanged();
Assert.AreEqual(0, mockXmlTreeView.AttributesDisplayed.Count);
}
protected override string GetXml()
{
return "<root first='a' second='b'/>";
}
}
}

52
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlElementTreeNodeTests.cs

@ -0,0 +1,52 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class XmlElementTreeNodeTextTests
{
XmlDocument doc;
[TestFixtureSetUp]
public void SetUpFixture()
{
doc = new XmlDocument();
doc.LoadXml("<root/>");
}
[Test]
public void UnqualifiedName()
{
XmlElement element = doc.CreateElement("child");
XmlElementTreeNode node = new XmlElementTreeNode(element);
Assert.AreEqual("child", node.Text);
}
[Test]
public void QualifiedName()
{
XmlElement element = doc.CreateElement("child", "http://test.com");
XmlElementTreeNode node = new XmlElementTreeNode(element);
Assert.AreEqual("child", node.Text);
}
[Test]
public void PrefixedName()
{
XmlElement element = doc.CreateElement("t", "child", "http://test.com");
XmlElementTreeNode node = new XmlElementTreeNode(element);
Assert.AreEqual("t:child", node.Text);
}
}
}

49
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTextSelectedTestFixture.cs

@ -0,0 +1,49 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests that the XmlTreeEditor tells the view to show the text when
/// an XmlText node is selected.
/// </summary>
[TestFixture]
public class XmlTextSelectedTestFixture : XmlTreeViewTestFixtureBase
{
[SetUp]
public void SetUpFixture()
{
base.InitFixture();
mockXmlTreeView.SelectedTextNode = (XmlText)mockXmlTreeView.DocumentElement.FirstChild;
editor.SelectedTextNodeChanged();
}
[Test]
public void IsViewShowingText()
{
Assert.AreEqual("text here", mockXmlTreeView.TextContentDisplayed);
}
[Test]
public void TextNodeNotSelected()
{
mockXmlTreeView.SelectedTextNode = null;
editor.SelectedTextNodeChanged();
Assert.AreEqual(String.Empty, mockXmlTreeView.TextContentDisplayed);
}
protected override string GetXml()
{
return "<root>text here</root>";
}
}
}

59
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTextTreeNodeTextTests.cs

@ -0,0 +1,59 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using System;
using System.Xml;
namespace XmlEditor.Tests.Tree
{
[TestFixture]
public class XmlTextTreeNodeTextTests
{
XmlDocument doc;
[TestFixtureSetUp]
public void SetUpFixture()
{
doc = new XmlDocument();
doc.LoadXml("<root/>");
}
[Test]
public void WhiteSpaceRemoved()
{
XmlText text = doc.CreateTextNode(" \t\tTest\t\t ");
XmlTextTreeNode node = new XmlTextTreeNode(text);
Assert.AreEqual("Test", node.Text);
}
[Test]
public void TextOnSecondLine()
{
XmlText text = doc.CreateTextNode("\r\nTest");
XmlTextTreeNode node = new XmlTextTreeNode(text);
Assert.AreEqual("Test", node.Text);
}
[Test]
public void ThreeLinesTextOnSecondLine()
{
XmlText text = doc.CreateTextNode("\r\nTest\r\n");
XmlTextTreeNode node = new XmlTextTreeNode(text);
Assert.AreEqual("Test", node.Text);
}
[Test]
public void TwoLines()
{
XmlText text = doc.CreateTextNode("Test\r\nSecond Line");
XmlTextTreeNode node = new XmlTextTreeNode(text);
Assert.AreEqual("Test...", node.Text);
}
}
}

32
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTreeViewTestFixtureBase.cs

@ -0,0 +1,32 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using System;
using System.Xml;
using XmlEditor.Tests.Utils;
namespace XmlEditor.Tests.Tree
{
public abstract class XmlTreeViewTestFixtureBase
{
protected MockXmlTreeView mockXmlTreeView;
protected XmlTreeEditor editor;
public void InitFixture()
{
mockXmlTreeView = new MockXmlTreeView();
editor = new XmlTreeEditor(mockXmlTreeView);
editor.LoadXml(GetXml());
}
protected virtual string GetXml()
{
return String.Empty;
}
}
}

123
src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockXmlTreeView.cs

@ -0,0 +1,123 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.XmlEditor;
using System;
using System.Collections.Generic;
using System.Xml;
namespace XmlEditor.Tests.Utils
{
public class MockXmlTreeView : IXmlTreeView
{
bool notWellFormedMessageDisplayed;
XmlException notWellFormedException;
XmlElement documentElement;
XmlElement selectedElement;
List<XmlAttribute> attributesDisplayed = new List<XmlAttribute>();
string textContentDisplayed;
XmlText selectedTextNode;
bool dirty;
public MockXmlTreeView()
{
}
public void ShowXmlIsNotWellFormedMessage(XmlException ex)
{
notWellFormedMessageDisplayed = true;
notWellFormedException = ex;
}
public bool IsDirty {
get {
return dirty;
}
set {
dirty = value;
}
}
public XmlElement DocumentElement {
get {
return documentElement;
}
set {
documentElement = value;
}
}
public XmlElement SelectedElement {
get {
return selectedElement;
}
set {
selectedElement = value;
}
}
public XmlText SelectedTextNode {
get {
return selectedTextNode;
}
set {
selectedTextNode = value;
}
}
public void ShowAttributes(XmlAttributeCollection attributes)
{
attributesDisplayed = new List<XmlAttribute>();
foreach (XmlAttribute attribute in attributes) {
attributesDisplayed.Add(attribute);
}
}
public void ClearAttributes()
{
attributesDisplayed.Clear();
}
public void ShowTextContent(string text)
{
textContentDisplayed = text;
}
public string TextContent {
get {
return textContentDisplayed;
}
}
public List<XmlAttribute> AttributesDisplayed {
get {
return attributesDisplayed;
}
}
public string TextContentDisplayed {
get {
return textContentDisplayed;
}
set {
textContentDisplayed = value;
}
}
public bool IsXmlNotWellFormedMessageDisplayed {
get {
return notWellFormedMessageDisplayed;
}
}
public XmlException NotWellFormedExceptionPassed {
get {
return notWellFormedException;
}
}
}
}

16
src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj

@ -119,6 +119,21 @@
<Compile Include="FindSchemaObject\ElementTypeSelectedTestFixture.cs" /> <Compile Include="FindSchemaObject\ElementTypeSelectedTestFixture.cs" />
<Compile Include="FindSchemaObject\ElementTypeWithPrefixSelectedTestFixture.cs" /> <Compile Include="FindSchemaObject\ElementTypeWithPrefixSelectedTestFixture.cs" />
<Compile Include="FindSchemaObject\AttributeTypeSelectedTestFixture.cs" /> <Compile Include="FindSchemaObject\AttributeTypeSelectedTestFixture.cs" />
<Compile Include="Tree\ViewInvalidXmlDocumentTestFixture.cs" />
<Compile Include="Utils\MockXmlTreeView.cs" />
<Compile Include="Tree\DocumentElementOnlyTestFixture.cs" />
<Compile Include="Tree\XmlTreeViewTestFixtureBase.cs" />
<Compile Include="Tree\RootNodeAddedToTreeControlTestFixture.cs" />
<Compile Include="Tree\ExpandChildNodesInTreeControlTestFixture.cs" />
<Compile Include="Tree\XmlElementSelectedTestFixture.cs" />
<Compile Include="Tree\XmlTextSelectedTestFixture.cs" />
<Compile Include="Tree\XmlTextTreeNodeTextTests.cs" />
<Compile Include="Tree\GetXmlAttributePropertyDescriptorTestFixture.cs" />
<Compile Include="Tree\XmlAttributeTypeDescriptorTestFixture.cs" />
<Compile Include="Tree\XmlElementTreeNodeTests.cs" />
<Compile Include="Tree\TreeControlViewStateTestFixture.cs" />
<Compile Include="Tree\AttributeChangedTestFixture.cs" />
<Compile Include="Tree\TextNodeTextChangedTestFixture.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Schema\" /> <Folder Include="Schema\" />
@ -145,6 +160,7 @@
<Name>ICSharpCode.Core</Name> <Name>ICSharpCode.Core</Name>
</ProjectReference> </ProjectReference>
<Folder Include="FindSchemaObject" /> <Folder Include="FindSchemaObject" />
<Folder Include="Tree" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project> </Project>
Loading…
Cancel
Save