Browse Source

Added basic cut, copy and paste to the XML tree editor.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2164 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 19 years ago
parent
commit
c053b954a6
  1. 18
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/IXmlTreeView.cs
  2. 26
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/RemoveCommentCommand.cs
  3. 26
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/RemoveElementCommand.cs
  4. 26
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/RemoveTextNodeCommand.cs
  5. 19
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCommentTreeNode.cs
  6. 52
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorControl.cs
  7. 21
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlElementTreeNode.cs
  8. 19
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTextTreeNode.cs
  9. 324
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeEditor.cs
  10. 106
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs
  11. 175
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs
  12. 80
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs
  13. 66
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs
  14. 41
      src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.addin
  15. 3
      src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.csproj
  16. 39
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs
  17. 11
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/EditCommentNodesInTreeControlTestFixture.cs
  18. 6
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/EditCommentNodesTestFixture.cs
  19. 53
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/MenuCommandsTestFixture.cs
  20. 276
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/PasteInTreeControlTestFixture.cs
  21. 372
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/PasteTestFixture.cs
  22. 6
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/RemoveElementTestFixture.cs
  23. 6
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/RemoveTextNodeTestFixture.cs
  24. 16
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlCommentTreeNodeTests.cs
  25. 16
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTextTreeNodeTextTests.cs
  26. 133
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTreeViewClipboardHandlerTestFixture.cs
  27. 52
      src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTreeViewContainerTestFixture.cs
  28. 6
      src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeView.cs
  29. 10
      src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeViewContainerControl.cs
  30. 47
      src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockXmlTreeView.cs
  31. 4
      src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj
  32. 2
      src/AddIns/DisplayBindings/XmlEditor/XmlEditor.sln
  33. 7
      src/Main/Base/Project/Src/Services/IconService.cs

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

@ -30,6 +30,11 @@ namespace ICSharpCode.XmlEditor @@ -30,6 +30,11 @@ namespace ICSharpCode.XmlEditor
/// </summary>
XmlDocument Document {get; set;}
/// <summary>
/// Gets the selected node in the tree.
/// </summary>
XmlNode SelectedNode {get;}
/// <summary>
/// Gets the xml element selected.
/// </summary>
@ -112,6 +117,19 @@ namespace ICSharpCode.XmlEditor @@ -112,6 +117,19 @@ namespace ICSharpCode.XmlEditor
/// </summary>
void RemoveElement(XmlElement element);
/// <summary>
/// Informs the view that the specified node has been selected
/// to be cut from the tree. The view can then update its display
/// to inform the user that the node has been cut.
/// </summary>
void ShowCut(XmlNode node);
/// <summary>
/// Informs the view that the visual indication of the cut should
/// be cleared.
/// </summary>
void HideCut(XmlNode node);
/// <summary>
/// Appends a new child text node to the currently selected
/// element.

26
src/AddIns/DisplayBindings/XmlEditor/Project/Src/RemoveCommentCommand.cs

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
// <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 ICSharpCode.Core;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Removes the currently selected comment node from the XML tree.
/// </summary>
public class RemoveCommentCommand : AbstractMenuCommand
{
public override void Run()
{
XmlTreeViewContainerControl view = Owner as XmlTreeViewContainerControl;
if (view != null) {
view.RemoveComment();
}
}
}
}

26
src/AddIns/DisplayBindings/XmlEditor/Project/Src/RemoveElementCommand.cs

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
// <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 ICSharpCode.Core;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Removes the selected element from the XML tree.
/// </summary>
public class RemoveElementCommand : AbstractMenuCommand
{
public override void Run()
{
XmlTreeViewContainerControl view = Owner as XmlTreeViewContainerControl;
if (view != null) {
view.RemoveElement();
}
}
}
}

26
src/AddIns/DisplayBindings/XmlEditor/Project/Src/RemoveTextNodeCommand.cs

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
// <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 ICSharpCode.Core;
namespace ICSharpCode.XmlEditor
{
/// <summary>
/// Removes the currently selected text node from the XML tree.
/// </summary>
public class RemoveTextNodeCommand : AbstractMenuCommand
{
public override void Run()
{
XmlTreeViewContainerControl view = Owner as XmlTreeViewContainerControl;
if (view != null) {
view.RemoveTextNode();
}
}
}
}

19
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCommentTreeNode.cs

@ -17,6 +17,7 @@ namespace ICSharpCode.XmlEditor @@ -17,6 +17,7 @@ namespace ICSharpCode.XmlEditor
public class XmlCommentTreeNode : XmlCharacterDataTreeNode
{
public const string XmlCommentTreeNodeImageKey = "XmlCommentTreeNodeImage";
public const string XmlCommentTreeNodeGhostImageKey = "XmlCommentTreeNodeGhostImage";
XmlComment comment;
@ -37,5 +38,23 @@ namespace ICSharpCode.XmlEditor @@ -37,5 +38,23 @@ namespace ICSharpCode.XmlEditor
return comment;
}
}
/// <summary>
/// Gets or sets whether to show the ghost image which is
/// displayed when cutting the node.
/// </summary>
public bool ShowGhostImage {
get {
return ImageKey == XmlCommentTreeNodeGhostImageKey;
}
set {
if (value) {
ImageKey = XmlCommentTreeNodeGhostImageKey;
} else {
ImageKey = XmlCommentTreeNodeImageKey;
}
SelectedImageKey = ImageKey;
}
}
}
}

52
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorControl.cs

@ -23,12 +23,12 @@ namespace ICSharpCode.XmlEditor @@ -23,12 +23,12 @@ namespace ICSharpCode.XmlEditor
/// </summary>
public class XmlEditorControl : ICSharpCode.TextEditor.TextEditorControl
{
static readonly string editActionsPath = "/AddIns/XmlEditor/EditActions";
static readonly string contextMenuPath = "/SharpDevelop/ViewContent/XmlEditor/ContextMenu";
CodeCompletionWindow codeCompletionWindow;
XmlSchemaCompletionDataCollection schemaCompletionDataItems = new XmlSchemaCompletionDataCollection();
XmlSchemaCompletionData defaultSchemaCompletionData = null;
string defaultNamespacePrefix = String.Empty;
ContextMenuStrip contextMenuStrip;
TextAreaControl primaryTextAreaControl;
public XmlEditorControl()
{
@ -37,13 +37,10 @@ namespace ICSharpCode.XmlEditor @@ -37,13 +37,10 @@ namespace ICSharpCode.XmlEditor
Document.HighlightingStrategy = HighlightingManager.Manager.FindHighlighter("XML");
Document.FoldingManager.FoldingStrategy = new XmlFoldingStrategy();
TextEditorProperties = new SharpDevelopTextEditorProperties();
Document.BookmarkManager.Factory = new SDBookmarkFactory(Document.BookmarkManager);
Document.BookmarkManager.Added += new ICSharpCode.TextEditor.Document.BookmarkEventHandler(BookmarkAdded);
Document.BookmarkManager.Removed += new ICSharpCode.TextEditor.Document.BookmarkEventHandler(BookmarkRemoved);
GenerateEditActions();
}
/// <summary>
@ -83,7 +80,6 @@ namespace ICSharpCode.XmlEditor @@ -83,7 +80,6 @@ namespace ICSharpCode.XmlEditor
get {
return defaultSchemaCompletionData;
}
set {
defaultSchemaCompletionData = value;
}
@ -103,12 +99,43 @@ namespace ICSharpCode.XmlEditor @@ -103,12 +99,43 @@ namespace ICSharpCode.XmlEditor
}
}
/// <summary>
/// Adds edit actions to the xml editor.
/// </summary>
public void AddEditActions(IEditAction[] actions)
{
foreach (IEditAction action in actions) {
foreach (Keys key in action.Keys) {
editactions[key] = action;
}
}
}
/// <summary>
/// Gets or sets the right click menu associated with the
/// xml editor.
/// </summary>
public ContextMenuStrip TextAreaContextMenuStrip {
get {
return contextMenuStrip;
}
set {
contextMenuStrip = value;
if (primaryTextAreaControl != null) {
primaryTextAreaControl.ContextMenuStrip = value;
}
}
}
protected override void InitializeTextAreaControl(TextAreaControl newControl)
{
base.InitializeTextAreaControl(newControl);
primaryTextAreaControl = newControl;
newControl.TextArea.KeyEventHandler += new ICSharpCode.TextEditor.KeyEventHandler(HandleKeyPress);
newControl.ContextMenuStrip = MenuService.CreateContextMenu(this, contextMenuPath);
newControl.ContextMenuStrip = contextMenuStrip;
newControl.SelectionManager.SelectionChanged += new EventHandler(SelectionChanged);
newControl.Document.DocumentChanged += new DocumentEventHandler(DocumentChanged);
newControl.TextArea.ClipboardHandler.CopyText += new CopyTextEventHandler(ClipboardHandlerCopyText);
@ -202,17 +229,6 @@ namespace ICSharpCode.XmlEditor @@ -202,17 +229,6 @@ namespace ICSharpCode.XmlEditor
}
}
void GenerateEditActions()
{
IEditAction[] actions = (IEditAction[])(AddInTree.BuildItems(editActionsPath, this, false).ToArray(typeof(IEditAction)));
foreach (IEditAction action in actions) {
foreach (Keys key in action.Keys) {
editactions[key] = action;
}
}
}
void DocumentChanged(object sender, DocumentEventArgs e)
{
}

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

@ -17,6 +17,7 @@ namespace ICSharpCode.XmlEditor @@ -17,6 +17,7 @@ namespace ICSharpCode.XmlEditor
public class XmlElementTreeNode : ExtTreeNode
{
public const string XmlElementTreeNodeImageKey = "XmlElementTreeNodeImage";
public const string XmlElementTreeNodeGhostImageKey = "XmlElementTreeNodeGhostImage";
XmlElement element;
@ -41,7 +42,25 @@ namespace ICSharpCode.XmlEditor @@ -41,7 +42,25 @@ namespace ICSharpCode.XmlEditor
get {
return element;
}
}
}
/// <summary>
/// Gets or sets whether to show the ghost image which is
/// displayed when cutting the node.
/// </summary>
public bool ShowGhostImage {
get {
return ImageKey == XmlElementTreeNodeGhostImageKey;
}
set {
if (value) {
ImageKey = XmlElementTreeNodeGhostImageKey;
} else {
ImageKey = XmlElementTreeNodeImageKey;
}
SelectedImageKey = ImageKey;
}
}
/// <summary>
/// Adds child elements to this tree node.

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

@ -17,6 +17,7 @@ namespace ICSharpCode.XmlEditor @@ -17,6 +17,7 @@ namespace ICSharpCode.XmlEditor
public class XmlTextTreeNode : XmlCharacterDataTreeNode
{
public const string XmlTextTreeNodeImageKey = "XmlTextTreeNodeImage";
public const string XmlTextTreeNodeGhostImageKey = "XmlTextTreeNodeGhostImage";
XmlText xmlText;
@ -37,5 +38,23 @@ namespace ICSharpCode.XmlEditor @@ -37,5 +38,23 @@ namespace ICSharpCode.XmlEditor
return xmlText;
}
}
/// <summary>
/// Gets or sets whether to show the ghost image which is
/// displayed when cutting the node.
/// </summary>
public bool ShowGhostImage {
get {
return ImageKey == XmlTextTreeNodeGhostImageKey;
}
set {
if (value) {
ImageKey = XmlTextTreeNodeGhostImageKey;
} else {
ImageKey = XmlTextTreeNodeImageKey;
}
SelectedImageKey = ImageKey;
}
}
}
}

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

@ -22,6 +22,8 @@ namespace ICSharpCode.XmlEditor @@ -22,6 +22,8 @@ namespace ICSharpCode.XmlEditor
IXmlTreeView view;
XmlDocument document;
XmlCompletionDataProvider completionDataProvider;
XmlNode copiedNode;
XmlNode cutNode;
public XmlTreeEditor(IXmlTreeView view, XmlCompletionDataProvider completionDataProvider)
{
@ -149,8 +151,7 @@ namespace ICSharpCode.XmlEditor @@ -149,8 +151,7 @@ namespace ICSharpCode.XmlEditor
view.IsDirty = true;
foreach (string elementName in selectedElementNames) {
XmlElement newElement = document.CreateElement(elementName, selectedElement.NamespaceURI);
selectedElement.AppendChild(newElement);
view.AppendChildElement(newElement);
AppendChildElement(selectedElement, newElement);
}
}
}
@ -212,46 +213,12 @@ namespace ICSharpCode.XmlEditor @@ -212,46 +213,12 @@ namespace ICSharpCode.XmlEditor
}
}
/// <summary>
/// Removes the currently selected element.
/// </summary>
public void RemoveElement()
{
XmlElement selectedElement = view.SelectedElement;
if (selectedElement != null) {
XmlNode parentNode = selectedElement.ParentNode;
parentNode.RemoveChild(selectedElement);
view.IsDirty = true;
view.RemoveElement(selectedElement);
}
}
/// <summary>
/// Removes the currently select text node.
/// </summary>
public void RemoveTextNode()
{
XmlText textNode = view.SelectedTextNode;
if (textNode != null) {
XmlNode parentNode = textNode.ParentNode;
parentNode.RemoveChild(textNode);
view.IsDirty = true;
view.RemoveTextNode(textNode);
}
}
/// <summary>
/// Adds a child text node to the current selected element.
/// </summary>
public void AppendChildTextNode()
{
XmlElement selectedElement = view.SelectedElement;
if (selectedElement != null) {
XmlText textNode = document.CreateTextNode(String.Empty);
selectedElement.AppendChild(textNode);
view.IsDirty = true;
view.AppendChildTextNode(textNode);
}
AppendChildTextNode(document.CreateTextNode(String.Empty));
}
/// <summary>
@ -299,27 +266,8 @@ namespace ICSharpCode.XmlEditor @@ -299,27 +266,8 @@ namespace ICSharpCode.XmlEditor
/// </summary>
public void AppendChildComment()
{
XmlElement selectedElement = view.SelectedElement;
if (selectedElement != null) {
XmlComment comment = document.CreateComment(String.Empty);
selectedElement.AppendChild(comment);
view.IsDirty = true;
view.AppendChildComment(comment);
}
}
/// <summary>
/// Removes the currently select comment.
/// </summary>
public void RemoveComment()
{
XmlComment comment = view.SelectedComment;
if (comment != null) {
XmlNode parentNode = comment.ParentNode;
parentNode.RemoveChild(comment);
view.IsDirty = true;
view.RemoveComment(comment);
}
XmlComment comment = document.CreateComment(String.Empty);
AppendChildComment(comment);
}
/// <summary>
@ -352,6 +300,105 @@ namespace ICSharpCode.XmlEditor @@ -352,6 +300,105 @@ namespace ICSharpCode.XmlEditor
}
}
/// <summary>
/// Deletes the selected tree node from the xml document.
/// </summary>
public void Delete()
{
XmlNode selectedNode = view.SelectedNode;
XmlElement selectedElement = selectedNode as XmlElement;
XmlComment selectedComment = selectedNode as XmlComment;
XmlText selectedText = selectedNode as XmlText;
if (selectedElement != null) {
RemoveElement(selectedElement);
} else if (selectedComment != null) {
RemoveComment(selectedComment);
} else if (selectedText != null) {
RemoveTextNode(selectedText);
}
}
/// <summary>
/// Copies the selected node.
/// </summary>
public void Copy()
{
copiedNode = view.SelectedNode;
if (cutNode != null) {
view.HideCut(cutNode);
}
}
/// <summary>
/// Pastes the copied or cut node as a child of the selected node.
/// </summary>
public void Paste()
{
if (IsPasteEnabled) {
if (copiedNode != null) {
AppendChildCopy(copiedNode);
} else {
CutAndPasteNode(cutNode);
}
}
}
/// <summary>
/// Cuts the selected node.
/// </summary>
public void Cut()
{
cutNode = view.SelectedNode;
if (cutNode != null) {
view.ShowCut(cutNode);
}
copiedNode = null;
}
/// <summary>
/// Gets whether the cut method is enabled.
/// </summary>
public bool IsCutEnabled {
get {
XmlNode selectedNode = view.SelectedNode;
return selectedNode != null && document.DocumentElement != selectedNode;
}
}
/// <summary>
/// Gets whether the copy method is enabled.
/// </summary>
public bool IsCopyEnabled {
get {
return view.SelectedNode != null;
}
}
/// <summary>
/// Gets whether the paste method is enabled.
/// </summary>
public bool IsPasteEnabled {
get {
XmlNode destinationNode = view.SelectedNode;
if (destinationNode != null) {
XmlNode sourceNode = copiedNode ?? cutNode;
if (sourceNode != null) {
return GetPasteEnabled(sourceNode, destinationNode);
}
}
return false;
}
}
/// <summary>
/// Gets whether the delete method is enabled.
/// </summary>
public bool IsDeleteEnabled {
get {
return view.SelectedNode != null;
}
}
/// <summary>
/// Gets the missing attributes for the specified element based
/// on its associated schema.
@ -436,5 +483,166 @@ namespace ICSharpCode.XmlEditor @@ -436,5 +483,166 @@ namespace ICSharpCode.XmlEditor
}
return view.SelectedElement;
}
/// <summary>
/// Appends the specified element as a child to the selected element.
/// </summary>
void AppendChildElement(XmlElement element)
{
AppendChildElement(view.SelectedElement, element);
}
/// <summary>
/// Appends the specified element as a child to the selected element.
/// </summary>
void AppendChildElement(XmlElement selectedElement, XmlElement element)
{
selectedElement.AppendChild(element);
view.AppendChildElement(element);
view.IsDirty = true;
}
/// <summary>
/// Removes the specified element from the document.
/// </summary>
void RemoveElement(XmlElement element)
{
XmlNode parentNode = element.ParentNode;
parentNode.RemoveChild(element);
view.IsDirty = true;
view.RemoveElement(element);
}
/// <summary>
/// Removes the specified comment from the document.
/// </summary>
void RemoveComment(XmlComment comment)
{
XmlNode parentNode = comment.ParentNode;
parentNode.RemoveChild(comment);
view.IsDirty = true;
view.RemoveComment(comment);
}
/// <summary>
/// Removes the specified text node from the document.
/// </summary>
void RemoveTextNode(XmlText textNode)
{
XmlNode parentNode = textNode.ParentNode;
parentNode.RemoveChild(textNode);
view.IsDirty = true;
view.RemoveTextNode(textNode);
}
/// <summary>
/// Gets whether the source node can be pasted as a child
/// node of the destination node.
/// </summary>
static bool GetPasteEnabled(XmlNode source, XmlNode destination)
{
if (source is XmlElement || source is XmlText || source is XmlComment) {
return destination is XmlElement;
}
return false;
}
/// <summary>
/// Takes a copy of the node and appends it to the selected
/// node.
/// </summary>
void AppendChildCopy(XmlNode nodeToCopy)
{
if (nodeToCopy is XmlElement) {
XmlElement copy = (XmlElement)nodeToCopy.CloneNode(true);
AppendChildElement(copy);
} else if (nodeToCopy is XmlText) {
XmlText copy = (XmlText)nodeToCopy.CloneNode(true);
AppendChildTextNode(copy);
} else if (nodeToCopy is XmlComment) {
XmlComment copy = (XmlComment)nodeToCopy.CloneNode(true);
AppendChildComment(copy);
}
}
/// <summary>
/// Appends the specified text node to the currently selected element.
/// </summary>
void AppendChildTextNode(XmlText textNode)
{
XmlElement selectedElement = view.SelectedElement;
if (selectedElement != null) {
selectedElement.AppendChild(textNode);
view.IsDirty = true;
view.AppendChildTextNode(textNode);
}
}
/// <summary>
/// Cuts from the tree and pastes it to the currently selected node.
/// </summary>
void CutAndPasteNode(XmlNode node)
{
XmlElement cutElement = node as XmlElement;
XmlText cutTextNode = node as XmlText;
XmlComment cutCommentNode = node as XmlComment;
if (cutElement != null) {
CutAndPasteElement(cutElement);
} else if (cutTextNode != null) {
CutAndPasteTextNode(cutTextNode);
} else if (cutCommentNode != null) {
CutAndPasteComment(cutCommentNode);
}
cutNode = null;
}
/// <summary>
/// Cuts the element from the document and pastes it as a child
/// of the selected element.
/// </summary>
void CutAndPasteElement(XmlElement element)
{
if (element != view.SelectedElement) {
view.RemoveElement(element);
AppendChildElement(element);
} else {
// Pasting to the same cut element so just
// change the tree icon back to the uncut state.
view.HideCut(element);
}
}
/// <summary>
/// Cuts the text node from the document and appends it as a child
/// of the currently selected element.
/// </summary>
void CutAndPasteTextNode(XmlText text)
{
view.RemoveTextNode(text);
AppendChildTextNode(text);
}
/// <summary>
/// Appends the specified comment to the currently selected element.
/// </summary>
void AppendChildComment(XmlComment comment)
{
XmlElement selectedElement = view.SelectedElement;
if (selectedElement != null) {
selectedElement.AppendChild(comment);
view.IsDirty = true;
view.AppendChildComment(comment);
}
}
/// <summary>
/// Cuts the comment node from the document and appends it as a child
/// of the currently selected element.
/// </summary>
void CutAndPasteComment(XmlComment comment)
{
view.RemoveComment(comment);
AppendChildComment(comment);
}
}
}

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

@ -17,21 +17,31 @@ namespace ICSharpCode.XmlEditor @@ -17,21 +17,31 @@ namespace ICSharpCode.XmlEditor
/// <summary>
/// The secondary view content that displays the XML document as a tree view.
/// </summary>
public class XmlTreeView : AbstractSecondaryViewContent
public class XmlTreeView : AbstractSecondaryViewContent, IClipboardHandler
{
XmlTreeViewContainerControl treeViewContainer = new XmlTreeViewContainerControl();
XmlView xmlView;
bool disposed;
bool ignoreDirtyChange;
public XmlTreeView(XmlView xmlView)
public XmlTreeView(XmlView xmlView) : this(xmlView, null, null)
{
this.xmlView = xmlView;
treeViewContainer.DirtyChanged += TreeViewContainerDirtyChanged;
treeViewContainer.AttributesGrid.ContextMenuStrip = MenuService.CreateContextMenu(treeViewContainer, "/AddIns/XmlEditor/XmlTree/AttributesGrid/ContextMenu");
treeViewContainer.TreeView.ContextMenuStrip = MenuService.CreateContextMenu(treeViewContainer, "/AddIns/XmlEditor/XmlTree/ContextMenu");
}
/// <summary>
/// Creates an XmlTreeView with the specified context menu strips.
/// This constructor is only used to test the XmlTreeView class.
/// </summary>
public XmlTreeView(XmlView xmlView, ContextMenuStrip attributesGridContextMenuStrip, ContextMenuStrip treeViewContextMenuStrip)
{
this.xmlView = xmlView;
treeViewContainer.DirtyChanged += TreeViewContainerDirtyChanged;
treeViewContainer.AttributesGrid.ContextMenuStrip = attributesGridContextMenuStrip;
treeViewContainer.TreeView.ContextMenuStrip = treeViewContextMenuStrip;
}
public override Control Control {
get {
return treeViewContainer;
@ -86,6 +96,94 @@ namespace ICSharpCode.XmlEditor @@ -86,6 +96,94 @@ namespace ICSharpCode.XmlEditor
}
}
#region IClipboardHandler implementation
/// <summary>
/// Gets whether the edit menu's cut command should be enabled.
/// </summary>
public bool EnableCut {
get {
return treeViewContainer.EnableCut;
}
}
/// <summary>
/// Gets whether the edit menu's copy command should be enabled.
/// </summary>
public bool EnableCopy {
get {
return treeViewContainer.EnableCopy;
}
}
/// <summary>
/// Gets whether the edit menu's paste command should be enabled.
/// </summary>
public bool EnablePaste {
get {
return treeViewContainer.EnablePaste;
}
}
/// <summary>
/// Gets whether the edit menu's delete command should be enabled.
/// </summary>
public bool EnableDelete {
get {
return treeViewContainer.EnableDelete;
}
}
/// <summary>
/// Always returns false.
/// </summary>
public bool EnableSelectAll {
get {
return false;
}
}
/// <summary>
/// Cuts the selected tree node.
/// </summary>
public void Cut()
{
treeViewContainer.Cut();
}
/// <summary>
/// Copies the selected tree node.
/// </summary>
public void Copy()
{
treeViewContainer.Copy();
}
/// <summary>
/// Pastes the copied or cut node as a child of the selected tree node.
/// </summary>
public void Paste()
{
treeViewContainer.Paste();
}
/// <summary>
/// Deletes the selected tree node.
/// </summary>
public void Delete()
{
treeViewContainer.Delete();
}
/// <summary>
/// Select all is not currently supported.
/// </summary>
public void SelectAll()
{
}
#endregion
void TreeViewContainerDirtyChanged(object source, EventArgs e)
{
if (!ignoreDirtyChange) {

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

@ -12,6 +12,8 @@ using System.Windows.Forms; @@ -12,6 +12,8 @@ using System.Windows.Forms;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.XmlEditor
{
@ -20,7 +22,7 @@ namespace ICSharpCode.XmlEditor @@ -20,7 +22,7 @@ namespace ICSharpCode.XmlEditor
/// 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, IOwnerState
public class XmlTreeViewContainerControl : System.Windows.Forms.UserControl, IXmlTreeView, IOwnerState, IClipboardHandler
{
XmlTreeEditor editor;
bool dirty;
@ -216,6 +218,26 @@ namespace ICSharpCode.XmlEditor @@ -216,6 +218,26 @@ namespace ICSharpCode.XmlEditor
}
}
/// <summary>
/// Gets the currently selected node based on what is selected in
/// the tree. This does not return the selected attribute.
/// </summary>
public XmlNode SelectedNode {
get {
XmlElement selectedElement = SelectedElement;
if (selectedElement != null) {
return selectedElement;
}
XmlText selectedTextNode = SelectedTextNode;
if (selectedTextNode != null) {
return selectedTextNode;
}
return SelectedComment;
}
}
/// <summary>
/// Gets the element currently selected.
/// </summary>
@ -357,14 +379,6 @@ namespace ICSharpCode.XmlEditor @@ -357,14 +379,6 @@ namespace ICSharpCode.XmlEditor
xmlElementTreeView.InsertElementAfter(element);
}
/// <summary>
/// Removes the selected element.
/// </summary>
public void RemoveElement()
{
editor.RemoveElement();
}
/// <summary>
/// Removes the specified element from the tree.
/// </summary>
@ -427,14 +441,6 @@ namespace ICSharpCode.XmlEditor @@ -427,14 +441,6 @@ namespace ICSharpCode.XmlEditor
xmlElementTreeView.InsertTextNodeAfter(textNode);
}
/// <summary>
/// Removes the currently selected text node.
/// </summary>
public void RemoveTextNode()
{
editor.RemoveTextNode();
}
/// <summary>
/// Removes the currently selected text node.
/// </summary>
@ -477,14 +483,6 @@ namespace ICSharpCode.XmlEditor @@ -477,14 +483,6 @@ namespace ICSharpCode.XmlEditor
editor.AppendChildComment();
}
/// <summary>
/// Removes the selected comment node from the tree.
/// </summary>
public void RemoveComment()
{
editor.RemoveComment();
}
/// <summary>
/// Removes the specified xml comment from the tree.
/// </summary>
@ -525,6 +523,113 @@ namespace ICSharpCode.XmlEditor @@ -525,6 +523,113 @@ namespace ICSharpCode.XmlEditor
editor.InsertCommentAfter();
}
/// <summary>
/// Updates the view to show that the specified node is going
/// to be cut.
/// </summary>
public void ShowCut(XmlNode node)
{
xmlElementTreeView.ShowCut(node);
}
/// <summary>
/// Updates the view so that the specified node is not displayed
/// as being cut.
/// </summary>
public void HideCut(XmlNode node)
{
xmlElementTreeView.HideCut(node);
}
#region IClipboardHandler implementation
/// <summary>
/// Gets whether cutting is enabled.
/// </summary>
public bool EnableCut {
get {
return editor.IsCutEnabled;
}
}
/// <summary>
/// Gets whether copying is enabled.
/// </summary>
public bool EnableCopy {
get {
return editor.IsCopyEnabled;
}
}
/// <summary>
/// Gets whether pasting is enabled.
/// </summary>
public bool EnablePaste {
get {
return editor.IsPasteEnabled;
}
}
/// <summary>
/// Gets whether deleting is enabled.
/// </summary>
public bool EnableDelete {
get {
return editor.IsDeleteEnabled;
}
}
/// <summary>
/// Currently not possible to select all tree nodes so this
/// always returns false.
/// </summary>
public bool EnableSelectAll {
get {
return false;
}
}
/// <summary>
/// Cuts the selected tree node.
/// </summary>
public void Cut()
{
editor.Cut();
}
/// <summary>
/// Copies the selected tree node.
/// </summary>
public void Copy()
{
editor.Copy();
}
/// <summary>
/// Pastes the selected tree node.
/// </summary>
public void Paste()
{
editor.Paste();
}
/// <summary>
/// Deletes the selected tree node.
/// </summary>
public void Delete()
{
editor.Delete();
}
/// <summary>
/// Selects all tree nodes. Currently not supported.
/// </summary>
public void SelectAll()
{
}
#endregion
/// <summary>
/// Disposes resources used by the control.
/// </summary>
@ -559,6 +664,14 @@ namespace ICSharpCode.XmlEditor @@ -559,6 +664,14 @@ namespace ICSharpCode.XmlEditor
return new AddAttributeDialog(attributeNames);
}
/// <summary>
/// Deletes the selected node.
/// </summary>
protected void XmlElementTreeViewDeleteKeyPressed(object source, EventArgs e)
{
Delete();
}
#region Forms Designer generated code
/// <summary>
@ -611,6 +724,7 @@ namespace ICSharpCode.XmlEditor @@ -611,6 +724,7 @@ namespace ICSharpCode.XmlEditor
this.xmlElementTreeView.AllowDrop = true;
this.xmlElementTreeView.CanClearSelection = true;
this.xmlElementTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
this.xmlElementTreeView.Document = null;
this.xmlElementTreeView.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawText;
this.xmlElementTreeView.HideSelection = false;
this.xmlElementTreeView.ImageIndex = 0;
@ -622,6 +736,7 @@ namespace ICSharpCode.XmlEditor @@ -622,6 +736,7 @@ namespace ICSharpCode.XmlEditor
this.xmlElementTreeView.Size = new System.Drawing.Size(185, 326);
this.xmlElementTreeView.TabIndex = 0;
this.xmlElementTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.XmlElementTreeViewAfterSelect);
this.xmlElementTreeView.DeleteKeyPressed += new System.EventHandler(this.XmlElementTreeViewDeleteKeyPressed);
//
// attributesGrid
//
@ -714,12 +829,22 @@ namespace ICSharpCode.XmlEditor @@ -714,12 +829,22 @@ namespace ICSharpCode.XmlEditor
components = new Container();
}
ImageList images = new ImageList(components);
// Add xml element tree node images.
Image xmlElementImage = Image.FromStream(typeof(XmlTreeViewContainerControl).Assembly.GetManifestResourceStream("ICSharpCode.XmlEditor.Resources.XmlElementTreeNodeIcon.png"));
images.Images.Add(XmlElementTreeNode.XmlElementTreeNodeImageKey, xmlElementImage);
images.Images.Add(XmlElementTreeNode.XmlElementTreeNodeGhostImageKey, IconService.GetGhostBitmap(new Bitmap(xmlElementImage)));
// Add text tree node images.
Image xmlTextImage = Image.FromStream(typeof(XmlTreeViewContainerControl).Assembly.GetManifestResourceStream("ICSharpCode.XmlEditor.Resources.XmlTextTreeNodeIcon.png"));
images.Images.Add(XmlTextTreeNode.XmlTextTreeNodeImageKey, xmlTextImage);
images.Images.Add(XmlTextTreeNode.XmlTextTreeNodeGhostImageKey, IconService.GetGhostBitmap(new Bitmap(xmlTextImage)));
// Add comment tree node images.
Image xmlCommentImage = Image.FromStream(typeof(XmlTreeViewContainerControl).Assembly.GetManifestResourceStream("ICSharpCode.XmlEditor.Resources.XmlCommentTreeNodeIcon.png"));
images.Images.Add(XmlCommentTreeNode.XmlCommentTreeNodeImageKey, xmlCommentImage);
images.Images.Add(XmlCommentTreeNode.XmlCommentTreeNodeGhostImageKey, IconService.GetGhostBitmap(new Bitmap(xmlCommentImage)));
xmlElementTreeView.ImageList = images;
}

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

@ -31,6 +31,11 @@ namespace ICSharpCode.XmlEditor @@ -31,6 +31,11 @@ namespace ICSharpCode.XmlEditor
After = 1
}
/// <summary>
/// Raised when the delete key is pressed.
/// </summary>
public event EventHandler DeleteKeyPressed;
public XmlTreeViewControl()
{
}
@ -279,6 +284,24 @@ namespace ICSharpCode.XmlEditor @@ -279,6 +284,24 @@ namespace ICSharpCode.XmlEditor
InsertComment(comment, InsertionMode.After);
}
/// <summary>
/// Updates the image so the corresponding tree node shows that
/// it is in the process of being cut.
/// </summary>
public void ShowCut(XmlNode node)
{
ShowCut(node, true);
}
/// <summary>
/// Updates the image so the corresponding tree node no longer
/// shows it is in the process of being cut.
/// </summary>
public void HideCut(XmlNode node)
{
ShowCut(node, false);
}
/// <summary>
/// If no node is selected after a mouse click then we make
/// sure the AfterSelect event is fired. Standard behaviour is
@ -292,6 +315,17 @@ namespace ICSharpCode.XmlEditor @@ -292,6 +315,17 @@ namespace ICSharpCode.XmlEditor
this.OnAfterSelect(new TreeViewEventArgs(null, TreeViewAction.ByMouse));
}
}
/// <summary>
/// Raises the DeleteKeyPressed event.
/// </summary>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Delete && DeleteKeyPressed != null) {
DeleteKeyPressed(this, new EventArgs());
}
return base.ProcessCmdKey(ref msg, keyData);
}
/// <summary>
/// Displays the document in the xml tree.
@ -494,5 +528,51 @@ namespace ICSharpCode.XmlEditor @@ -494,5 +528,51 @@ namespace ICSharpCode.XmlEditor
return FindComment(comment, Nodes);
}
}
/// <summary>
/// Shows the corresponding tree node with the ghosted image
/// that indicates it is being cut.
/// </summary>
void ShowCutElement(XmlElement element, bool showGhostImage)
{
XmlElementTreeNode node = FindElement(element);
node.ShowGhostImage = showGhostImage;
}
/// <summary>
/// Shows the corresponding tree node with the ghosted image
/// that indicates it is being cut.
/// </summary>
void ShowCutTextNode(XmlText textNode, bool showGhostImage)
{
XmlTextTreeNode node = FindTextNode(textNode);
node.ShowGhostImage = showGhostImage;
}
/// <summary>
/// Shows the corresponding tree node with the ghosted image
/// that indicates it is being cut.
/// </summary>
void ShowCutComment(XmlComment comment, bool showGhostImage)
{
XmlCommentTreeNode node = FindComment(comment);
node.ShowGhostImage = showGhostImage;
}
/// <summary>
/// Shows the cut node with a ghost image.
/// </summary>
/// <param name="showGhostImage">True if the node should be
/// shown with the ghost image.</param>
void ShowCut(XmlNode node, bool showGhostImage)
{
if (node is XmlElement) {
ShowCutElement((XmlElement)node, showGhostImage);
} else if (node is XmlText) {
ShowCutTextNode((XmlText)node, showGhostImage);
} else if (node is XmlComment) {
ShowCutComment((XmlComment)node, showGhostImage);
}
}
}
}

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

@ -23,6 +23,7 @@ using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; @@ -23,6 +23,7 @@ using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Actions;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.XmlEditor
@ -42,23 +43,39 @@ namespace ICSharpCode.XmlEditor @@ -42,23 +43,39 @@ namespace ICSharpCode.XmlEditor
/// </summary>
public static readonly string CategoryName = "XML";
XmlEditorControl xmlEditor = new XmlEditorControl();
/// <summary>
/// Edit actions addin tree path for the xml editor control.
/// </summary>
static readonly string editActionsPath = "/AddIns/XmlEditor/EditActions";
/// <summary>
/// Right click menu addin tree path for the xml editor control.
/// </summary>
static readonly string contextMenuPath = "/SharpDevelop/ViewContent/XmlEditor/ContextMenu";
XmlEditorControl xmlEditor;
TextEditorDisplayBindingWrapper.FileChangeWatcher watcher;
static MessageViewCategory category;
string stylesheetFileName;
XmlTreeView xmlTreeView;
/// <summary>
/// Creates an XmlView that is used by SharpDevelop to provide an
/// XML editor.
/// </summary>
public XmlView()
: this(new SharpDevelopTextEditorProperties(), XmlSchemaManager.SchemaCompletionDataItems)
{
xmlEditor.Dock = DockStyle.Fill;
watcher = new TextEditorDisplayBindingWrapper.FileChangeWatcher(this);
xmlEditor.SchemaCompletionDataItems = XmlSchemaManager.SchemaCompletionDataItems;
xmlEditor.Document.DocumentChanged += DocumentChanged;
xmlEditor.AddEditActions(GetEditActions());
xmlEditor.TextAreaContextMenuStrip = MenuService.CreateContextMenu(xmlEditor, contextMenuPath);
// Add event handlers so we can update the status bar when
// the cursor position changes.
xmlEditor.ActiveTextAreaControl.Caret.CaretModeChanged += CaretModeChanged;
xmlEditor.ActiveTextAreaControl.Caret.PositionChanged += CaretChanged;
xmlEditor.ActiveTextAreaControl.Enter += CaretUpdate;
watcher = new TextEditorDisplayBindingWrapper.FileChangeWatcher(this);
// Listen for changes to the xml editor properties.
XmlEditorAddInOptions.PropertyChanged += PropertyChanged;
@ -68,6 +85,21 @@ namespace ICSharpCode.XmlEditor @@ -68,6 +85,21 @@ namespace ICSharpCode.XmlEditor
xmlTreeView = new XmlTreeView(this);
SecondaryViewContents.Add(xmlTreeView);
}
/// <summary>
/// Creates an XmlView that is independent of SharpDevelop. This
/// constructor does rely on SharpDevelop being available and is
/// only used for testing the XmlView.
/// </summary>
public XmlView(ITextEditorProperties textEditorProperties, XmlSchemaCompletionDataCollection schemas)
{
xmlEditor = new XmlEditorControl();
xmlEditor.Dock = DockStyle.Fill;
xmlEditor.TextEditorProperties = textEditorProperties;
xmlEditor.SchemaCompletionDataItems = schemas;
xmlEditor.Document.DocumentChanged += DocumentChanged;
}
/// <summary>
/// Gets the active XmlView.
@ -296,12 +328,12 @@ namespace ICSharpCode.XmlEditor @@ -296,12 +328,12 @@ namespace ICSharpCode.XmlEditor
public override void Dispose()
{
base.Dispose();
watcher.Dispose();
XmlEditorAddInOptions.PropertyChanged -= PropertyChanged;
XmlSchemaManager.UserSchemaAdded -= new EventHandler(UserSchemaAdded);
XmlSchemaManager.UserSchemaRemoved -= new EventHandler(UserSchemaRemoved);
if (watcher != null) {
watcher.Dispose();
XmlEditorAddInOptions.PropertyChanged -= PropertyChanged;
XmlSchemaManager.UserSchemaAdded -= new EventHandler(UserSchemaAdded);
XmlSchemaManager.UserSchemaRemoved -= new EventHandler(UserSchemaRemoved);
}
xmlEditor.Dispose();
}
@ -1242,5 +1274,13 @@ namespace ICSharpCode.XmlEditor @@ -1242,5 +1274,13 @@ namespace ICSharpCode.XmlEditor
}
return schemas.ToArray();
}
/// <summary>
/// Gets the edit actions for the xml editor from the addin tree.
/// </summary>
IEditAction[] GetEditActions()
{
return (IEditAction[])(AddInTree.BuildItems(editActionsPath, this, false).ToArray(typeof(IEditAction)));
}
}
}

41
src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.addin

@ -198,6 +198,26 @@ @@ -198,6 +198,26 @@
</Path>
<Path name = "/AddIns/XmlEditor/XmlTree/ContextMenu">
<MenuItem id = "Cut"
label = "${res:XML.TextAreaContextMenu.Cut}"
icon = "Icons.16x16.CutIcon"
shortcut = "Control|X"
class = "ICSharpCode.SharpDevelop.Commands.Cut"/>
<MenuItem id = "Copy"
label = "${res:XML.TextAreaContextMenu.Copy}"
icon = "Icons.16x16.CopyIcon"
shortcut = "Control|C"
class = "ICSharpCode.SharpDevelop.Commands.Copy"/>
<MenuItem id = "Paste"
label = "${res:XML.TextAreaContextMenu.Paste}"
icon = "Icons.16x16.PasteIcon"
shortcut = "Control|V"
class = "ICSharpCode.SharpDevelop.Commands.Paste"/>
<MenuItem id = "Delete"
label = "${res:XML.MainMenu.EditMenu.Delete}"
icon = "Icons.16x16.DeleteIcon"
class = "ICSharpCode.SharpDevelop.Commands.Delete"/>
<MenuItem id = "EditItemsSeparator" type = "Separator"/>
<ComplexCondition action = "Disable">
<Or>
<Condition name = "Ownerstate" ownerstate = "CommentSelected"/>
@ -263,26 +283,5 @@ @@ -263,26 +283,5 @@
label = "${res:ICSharpCode.XmlEditor.XmlTreeView.AddChildCommentMenuLabel}"
class = "ICSharpCode.XmlEditor.AddChildCommentCommand"/>
</Condition>
<Condition name = "Ownerstate" ownerstate = "CommentSelected" action = "Exclude">
<MenuItem id = "RemoveCommentSeparator" type = "Separator"/>
<MenuItem id = "RemoveComment"
label = "${res:XML.MainMenu.EditMenu.Delete}"
icon = "Icons.16x16.DeleteIcon"
class = "ICSharpCode.XmlEditor.RemoveCommentCommand"/>
</Condition>
<Condition name = "Ownerstate" ownerstate = "TextNodeSelected" action = "Exclude">
<MenuItem id = "RemoveTextNodeSeparator" type = "Separator"/>
<MenuItem id = "RemoveTextNode"
label = "${res:XML.MainMenu.EditMenu.Delete}"
icon = "Icons.16x16.DeleteIcon"
class = "ICSharpCode.XmlEditor.RemoveTextNodeCommand"/>
</Condition>
<Condition name = "Ownerstate" ownerstate = "ElementSelected" action = "Exclude">
<MenuItem id = "RemoveElementSeparator" type = "Separator"/>
<MenuItem id = "RemoveElement"
label = "${res:XML.MainMenu.EditMenu.Delete}"
icon = "Icons.16x16.DeleteIcon"
class = "ICSharpCode.XmlEditor.RemoveElementCommand"/>
</Condition>
</Path>
</AddIn>

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

@ -62,9 +62,6 @@ @@ -62,9 +62,6 @@
<Compile Include="Src\InsertCommentBeforeCommand.cs" />
<Compile Include="Src\InsertTextNodeAfterCommand.cs" />
<Compile Include="Src\InsertTextNodeBeforeCommand.cs" />
<Compile Include="Src\RemoveCommentCommand.cs" />
<Compile Include="Src\RemoveElementCommand.cs" />
<Compile Include="Src\RemoveTextNodeCommand.cs" />
<Compile Include="Src\XmlCharacterDataTreeNode.cs" />
<Compile Include="Src\XmlCommentTreeNode.cs" />
<Compile Include="Src\XmlEditorControl.cs">

39
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// <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.Windows.Forms;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using XmlEditor.Tests.Utils;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests that the delete key event is fired so we can
/// </summary>
[TestFixture]
public class DeleteTreeNodeWithDeleteKeyTestFixture
{
bool deleteKeyPressEventFired;
[Test]
public void DeleteKeyPressed()
{
using (DerivedXmlTreeViewControl treeView = new DerivedXmlTreeViewControl()) {
treeView.DeleteKeyPressed += TreeViewDeleteKeyPressed;
treeView.CallProcessCmdKey(Keys.Delete);
}
Assert.IsTrue(deleteKeyPressEventFired);
}
void TreeViewDeleteKeyPressed(object sender, EventArgs e)
{
deleteKeyPressEventFired = true;
}
}
}

11
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/EditCommentNodesInTreeControlTestFixture.cs

@ -277,5 +277,16 @@ namespace XmlEditor.Tests.Tree @@ -277,5 +277,16 @@ namespace XmlEditor.Tests.Tree
Assert.AreEqual("new", node.Text);
Assert.AreEqual(element, node.XmlElement);
}
/// <summary>
/// Tests that when a comment node is selected the tree view container
/// returns this from the SelectedNode property.
/// </summary>
[Test]
public void SelectedNodeWhenCommentNodeSelected()
{
treeView.SelectedNode = childCommentTreeNode;
Assert.AreEqual(childCommentTreeNode.XmlComment, treeViewContainer.SelectedNode);
}
}
}

6
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/EditCommentNodesTestFixture.cs

@ -113,7 +113,8 @@ namespace XmlEditor.Tests.Tree @@ -113,7 +113,8 @@ namespace XmlEditor.Tests.Tree
public void RemoveComment()
{
mockXmlTreeView.SelectedComment = rootComment;
editor.RemoveComment();
mockXmlTreeView.SelectedNode = rootComment;
editor.Delete();
Assert.AreEqual(1, mockXmlTreeView.CommentNodesRemoved.Count);
Assert.AreSame(rootComment, mockXmlTreeView.CommentNodesRemoved[0]);
@ -126,7 +127,8 @@ namespace XmlEditor.Tests.Tree @@ -126,7 +127,8 @@ namespace XmlEditor.Tests.Tree
public void RemoveCommentWhenNoNodeSelected()
{
mockXmlTreeView.SelectedComment = null;
editor.RemoveComment();
mockXmlTreeView.SelectedNode = null;
editor.Delete();
Assert.IsFalse(mockXmlTreeView.IsDirty);
}

53
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/MenuCommandsTestFixture.cs

@ -350,47 +350,12 @@ namespace XmlEditor.Tests.Tree @@ -350,47 +350,12 @@ namespace XmlEditor.Tests.Tree
Assert.AreEqual(String.Empty, insertedTextNode.Value);
}
/// <summary>
/// Expect nothing to happen since the ICommand.Owner is not
/// set.
/// </summary>
[Test]
public void RemoveElementCommandWithNullOwner()
{
RemoveElementCommand command = new RemoveElementCommand();
command.Run();
}
[Test]
public void RemoveRootElementUsingCommand()
{
treeView.SelectedNode = treeView.Nodes[0];
RemoveElementCommand command = new RemoveElementCommand();
command.Owner = treeViewContainer;
command.Run();
Assert.AreEqual(0, treeView.Nodes.Count);
Assert.IsTrue(treeViewContainer.IsDirty);
}
[Test]
public void RemoveTextNodeWithNullOwner()
{
RemoveTextNodeCommand command = new RemoveTextNodeCommand();
command.Run();
}
[Test]
public void RemoveTextNode()
{
AddChildTextNode();
treeView.SelectedNode = bodyTreeNode.Nodes[0];
RemoveTextNodeCommand command = new RemoveTextNodeCommand();
command.Owner = treeViewContainer;
command.Run();
treeViewContainer.Delete();
Assert.IsFalse(bodyElement.HasChildNodes);
Assert.AreEqual(0, bodyTreeNode.Nodes.Count);
@ -419,23 +384,15 @@ namespace XmlEditor.Tests.Tree @@ -419,23 +384,15 @@ namespace XmlEditor.Tests.Tree
Assert.IsNotNull(treeNode);
}
[Test]
public void RemoveCommentWithNullOwner()
{
RemoveCommentCommand command = new RemoveCommentCommand();
command.Run();
}
/// <summary>
/// Removes the selected comment using the delete command.
/// </summary>
[Test]
public void RemoveComment()
{
AddChildCommentNode();
treeView.SelectedNode = bodyTreeNode.Nodes[0];
RemoveCommentCommand command = new RemoveCommentCommand();
command.Owner = treeViewContainer;
command.Run();
treeViewContainer.Delete();
Assert.IsFalse(bodyElement.HasChildNodes);
Assert.AreEqual(0, bodyTreeNode.Nodes.Count);

276
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/PasteInTreeControlTestFixture.cs

@ -0,0 +1,276 @@ @@ -0,0 +1,276 @@
// <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;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests pasting in the XmlTreeViewContainerControl.
/// </summary>
[TestFixture]
public class PasteInTreeControlTestFixture
{
XmlDocument doc;
XmlTreeViewContainerControl treeViewContainerControl;
XmlTreeViewControl treeView;
IClipboardHandler clipboardHandler;
XmlElementTreeNode htmlTreeNode;
XmlElementTreeNode bodyTreeNode;
XmlElementTreeNode paragraphTreeNode;
XmlElement htmlElement;
XmlElement bodyElement;
XmlElement paragraphElement;
XmlTextTreeNode paragraphTextTreeNode;
XmlText paragraphText;
XmlCommentTreeNode bodyCommentTreeNode;
XmlComment bodyComment;
[SetUp]
public void SetUp()
{
XmlCompletionDataProvider completionDataProvider = new XmlCompletionDataProvider(new XmlSchemaCompletionDataCollection(), null, String.Empty);
treeViewContainerControl = new XmlTreeViewContainerControl();
treeView = treeViewContainerControl.TreeView;
treeViewContainerControl.LoadXml(GetXml(), completionDataProvider);
doc = treeViewContainerControl.Document;
clipboardHandler = treeViewContainerControl as IClipboardHandler;
htmlElement = doc.DocumentElement;
bodyElement = htmlElement.FirstChild as XmlElement;
paragraphElement = bodyElement.SelectSingleNode("p") as XmlElement;
paragraphText = paragraphElement.SelectSingleNode("text()") as XmlText;
bodyComment = bodyElement.SelectSingleNode("comment()") as XmlComment;
htmlTreeNode = treeView.Nodes[0] as XmlElementTreeNode;
htmlTreeNode.PerformInitialization();
bodyTreeNode = htmlTreeNode.FirstNode as XmlElementTreeNode;
bodyTreeNode.PerformInitialization();
bodyCommentTreeNode = bodyTreeNode.FirstNode as XmlCommentTreeNode;
paragraphTreeNode = bodyTreeNode.LastNode as XmlElementTreeNode;
paragraphTreeNode.PerformInitialization();
paragraphTextTreeNode = paragraphTreeNode.FirstNode as XmlTextTreeNode;
}
[TearDown]
public void TearDown()
{
if (treeViewContainerControl != null) {
treeViewContainerControl.Dispose();
}
}
[Test]
public void ClipboardCopyDisabledWhenNoNodeSelected()
{
treeView.SelectedNode = null;
Assert.IsFalse(clipboardHandler.EnableCopy);
}
[Test]
public void ClipboardPasteDisabledWhenNoNodeSelected()
{
treeView.SelectedNode = null;
Assert.IsFalse(clipboardHandler.EnablePaste);
}
/// <summary>
/// Select all is not currently implemented since the tree
/// only supports single node selection.
/// </summary>
[Test]
public void SelectAllDisabled()
{
Assert.IsFalse(clipboardHandler.EnableSelectAll);
}
[Test]
public void ClipboardCutDisabledWhenNoNodeSelected()
{
treeView.SelectedNode = null;
Assert.IsFalse(clipboardHandler.EnableCut);
}
[Test]
public void ClipboardDeleteDisabledWhenNoNodeSelected()
{
treeView.SelectedNode = null;
Assert.IsFalse(clipboardHandler.EnableDelete);
}
[Test]
public void ClipboardDeleteEnabledWhenNodeSelected()
{
treeView.SelectedNode = treeView.Nodes[0];
Assert.IsTrue(clipboardHandler.EnableDelete);
}
/// <summary>
/// The cut tree node should have be showing its ghost image
/// after being cut.
/// </summary>
[Test]
public void CutBodyElement()
{
treeView.SelectedNode = bodyTreeNode;
treeViewContainerControl.Cut();
Assert.AreEqual(XmlElementTreeNode.XmlElementTreeNodeGhostImageKey, bodyTreeNode.ImageKey);
Assert.AreEqual(XmlElementTreeNode.XmlElementTreeNodeGhostImageKey, bodyTreeNode.SelectedImageKey);
Assert.IsTrue(bodyTreeNode.ShowGhostImage);
}
/// <summary>
/// This should append a copy of the root element
/// as a child of the existing root element. All child nodes of the
/// root element should be copied too.
/// </summary>
[Test]
public void CopyRootElementAndPasteToRootElement()
{
treeView.SelectedNode = htmlTreeNode;
treeViewContainerControl.Copy();
bool pasteEnabled = treeViewContainerControl.EnablePaste;
treeViewContainerControl.Paste();
XmlElement pastedElement = (XmlElement)htmlElement.LastChild;
XmlElementTreeNode pastedTreeNode = htmlTreeNode.LastNode as XmlElementTreeNode;
Assert.AreEqual(htmlElement.Name, pastedElement.Name);
Assert.AreEqual(pastedElement.Name, pastedTreeNode.Text);
Assert.AreSame(pastedElement, pastedTreeNode.XmlElement);
Assert.IsTrue(pasteEnabled);
}
[Test]
public void CutAndPasteElement()
{
treeView.SelectedNode = paragraphTreeNode;
treeViewContainerControl.Cut();
treeView.SelectedNode = htmlTreeNode;
bool pasteEnabled = treeViewContainerControl.EnablePaste;
treeViewContainerControl.Paste();
XmlElement pastedElement = htmlElement.LastChild as XmlElement;
XmlElementTreeNode pastedTreeNode = htmlTreeNode.LastNode as XmlElementTreeNode;
Assert.AreSame(paragraphElement, pastedElement);
Assert.IsNull(bodyElement.SelectSingleNode("p"));
Assert.AreSame(paragraphElement, pastedTreeNode.XmlElement);
Assert.IsTrue(pasteEnabled);
Assert.AreEqual(XmlElementTreeNode.XmlElementTreeNodeImageKey,
pastedTreeNode.ImageKey,
"Should not be ghost image.");
}
/// <summary>
/// Check that the ghost image is removed when the user pastes the
/// cut node back onto itself.
/// </summary>
[Test]
public void CutAndPasteElementBackOntoItself()
{
treeView.SelectedNode = paragraphTreeNode;
treeViewContainerControl.Cut();
treeView.SelectedNode = paragraphTreeNode;
treeViewContainerControl.Paste();
Assert.IsFalse(treeViewContainerControl.IsDirty);
Assert.AreSame(XmlElementTreeNode.XmlElementTreeNodeImageKey, paragraphTreeNode.ImageKey);
Assert.AreSame(XmlElementTreeNode.XmlElementTreeNodeImageKey, paragraphTreeNode.SelectedImageKey);
}
[Test]
public void CopyAndPasteTextNode()
{
treeView.SelectedNode = paragraphTextTreeNode;
treeViewContainerControl.Copy();
treeView.SelectedNode = bodyTreeNode;
treeViewContainerControl.Paste();
XmlText pastedTextNode = bodyElement.LastChild as XmlText;
XmlTextTreeNode pastedTreeNode = bodyTreeNode.LastNode as XmlTextTreeNode;
Assert.AreEqual(pastedTextNode.InnerText, paragraphText.InnerText);
Assert.AreEqual(paragraphText.InnerText, pastedTreeNode.Text);
Assert.IsTrue(treeViewContainerControl.IsDirty);
}
[Test]
public void CutAndPasteTextNode()
{
treeView.SelectedNode = paragraphTextTreeNode;
treeViewContainerControl.Cut();
string paragraphTextTreeNodeImageKeyAfterCut = paragraphTextTreeNode.ImageKey;
treeView.SelectedNode = bodyTreeNode;
treeViewContainerControl.Paste();
XmlText pastedTextNode = bodyElement.LastChild as XmlText;
XmlTextTreeNode pastedTreeNode = bodyTreeNode.LastNode as XmlTextTreeNode;
Assert.AreSame(paragraphText, pastedTextNode);
Assert.IsNull(paragraphElement.SelectSingleNode("text()"));
Assert.AreEqual(XmlTextTreeNode.XmlTextTreeNodeGhostImageKey,
paragraphTextTreeNodeImageKeyAfterCut);
Assert.AreEqual(XmlTextTreeNode.XmlTextTreeNodeImageKey,
pastedTreeNode.ImageKey,
"Should not be ghost image.");
}
[Test]
public void CopyAndPasteCommentNode()
{
treeView.SelectedNode = bodyCommentTreeNode;
treeViewContainerControl.Copy();
treeView.SelectedNode = htmlTreeNode;
treeViewContainerControl.Paste();
XmlComment pastedCommentNode = htmlElement.LastChild as XmlComment;
XmlCommentTreeNode pastedTreeNode = htmlTreeNode.LastNode as XmlCommentTreeNode;
Assert.AreEqual(pastedCommentNode.InnerText, bodyComment.InnerText);
Assert.AreEqual(bodyComment.InnerText.Trim(), pastedTreeNode.Text);
Assert.IsTrue(treeViewContainerControl.IsDirty);
}
[Test]
public void CutAndPasteCommentNode()
{
treeView.SelectedNode = bodyCommentTreeNode;
treeViewContainerControl.Cut();
string bodyCommentTreeNodeImageKeyAfterCut = bodyCommentTreeNode.ImageKey;
treeView.SelectedNode = htmlTreeNode;
treeViewContainerControl.Paste();
XmlComment pastedCommentNode = htmlElement.LastChild as XmlComment;
XmlCommentTreeNode pastedTreeNode = htmlTreeNode.LastNode as XmlCommentTreeNode;
Assert.AreSame(bodyComment, pastedCommentNode);
Assert.AreSame(bodyComment, pastedTreeNode.XmlComment);
Assert.IsNull(bodyElement.SelectSingleNode("comment()"));
Assert.AreEqual(XmlCommentTreeNode.XmlCommentTreeNodeGhostImageKey,
bodyCommentTreeNodeImageKeyAfterCut);
Assert.AreEqual(XmlCommentTreeNode.XmlCommentTreeNodeImageKey,
pastedTreeNode.ImageKey,
"Should not be ghost image.");
}
string GetXml()
{
return "<html>\r\n" +
"\t<body>\r\n" +
"\t\t<!-- Comment -->\r\n" +
"\t\t<p>some text here</p>\r\n" +
"\t</body>\r\n" +
"</html>";
}
}
}

372
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/PasteTestFixture.cs

@ -0,0 +1,372 @@ @@ -0,0 +1,372 @@
// <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;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using XmlEditor.Tests.Utils;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests pasting nodes with the XmlTreeEditor either from a cut or a copy.
/// Here we are testing the XmlTreeEditor side and now the actual
/// GUI side - XML Tree.
/// </summary>
[TestFixture]
public class PasteTestFixture : XmlTreeViewTestFixtureBase
{
XmlElement rootElement;
XmlElement bodyElement;
XmlElement paragraphElement;
XmlComment bodyComment;
XmlText paragraphText;
[SetUp]
public void Init()
{
base.InitFixture();
rootElement = editor.Document.DocumentElement;
bodyElement = (XmlElement)rootElement.FirstChild;
paragraphElement = (XmlElement)bodyElement.SelectSingleNode("p");
bodyComment = (XmlComment)bodyElement.SelectSingleNode("comment()");
paragraphText = (XmlText)paragraphElement.SelectSingleNode("text()");
}
/// <summary>
/// Here we take a copy of the root element of the document and paste
/// it on top of itself. This should append a copy of the root element
/// as a child of the existing root element. All child nodes of the
/// root element should be copied too.
/// </summary>
[Test]
public void CopyRootElementAndPasteToRootElement()
{
mockXmlTreeView.SelectedElement = rootElement;
editor.Copy();
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
XmlElement pastedElement = (XmlElement)rootElement.LastChild;
Assert.AreEqual(rootElement.Name, pastedElement.Name);
Assert.AreEqual(rootElement.FirstChild.Name, pastedElement.FirstChild.Name);
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.AreEqual(1, mockXmlTreeView.ChildElementsAdded.Count);
Assert.AreEqual(pastedElement, mockXmlTreeView.ChildElementsAdded[0]);
Assert.IsTrue(pasteEnabled);
}
/// <summary>
/// The selected node is null when the paste is attempted. Here
/// nothing should happen.
/// </summary>
[Test]
public void PasteWhenNoNodeSelected()
{
mockXmlTreeView.SelectedNode = rootElement;
editor.Copy();
mockXmlTreeView.SelectedNode = null;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
Assert.IsFalse(mockXmlTreeView.IsDirty);
Assert.IsFalse(pasteEnabled);
}
/// <summary>
/// Check that the view is informed when a node is cut. This allows the
/// view to give some sort of indication that a particular node is
/// being cut.
/// </summary>
[Test]
public void CutElement()
{
mockXmlTreeView.SelectedElement = bodyElement;
editor.Cut();
Assert.AreEqual(1, mockXmlTreeView.CutNodes.Count);
Assert.AreEqual(bodyElement, mockXmlTreeView.CutNodes[0]);
Assert.IsFalse(mockXmlTreeView.IsDirty);
}
[Test]
public void CutAndPasteElement()
{
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Cut();
mockXmlTreeView.SelectedElement = rootElement;
editor.Paste();
XmlElement pastedElement = rootElement.LastChild as XmlElement;
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.AreSame(paragraphElement, pastedElement);
Assert.IsNull(bodyElement.SelectSingleNode("p"));
Assert.AreEqual(1, mockXmlTreeView.ChildElementsAdded.Count);
Assert.AreSame(paragraphElement, mockXmlTreeView.ChildElementsAdded[0]);
Assert.AreEqual(1, mockXmlTreeView.ElementsRemoved.Count);
Assert.AreSame(paragraphElement, mockXmlTreeView.ElementsRemoved[0]);
}
/// <summary>
/// Checks that nothing happens when no node is selected in the tree
/// to cut.
/// </summary>
[Test]
public void NoElementSelectedToCut()
{
editor.Cut();
Assert.AreEqual(0, mockXmlTreeView.CutNodes.Count);
}
/// <summary>
/// The selected node is null when the copy method is called, but
/// there is a selected node when the paste is attempted. Here
/// nothing should happen.
/// </summary>
[Test]
public void CopyWhenNoNodeSelectedThenPaste()
{
mockXmlTreeView.SelectedNode = null;
editor.Copy();
mockXmlTreeView.SelectedNode = rootElement;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
Assert.IsFalse(mockXmlTreeView.IsDirty);
Assert.IsFalse(pasteEnabled);
}
[Test]
public void IsCopyEnabledWhenNoNodeSelected()
{
Assert.IsFalse(editor.IsCopyEnabled);
}
[Test]
public void IsCopyEnabledWhenRootElementSelected()
{
mockXmlTreeView.SelectedElement = rootElement;
mockXmlTreeView.SelectedNode = rootElement;
Assert.IsTrue(editor.IsCopyEnabled);
}
[Test]
public void IsCutEnabledWhenChildElementSelected()
{
mockXmlTreeView.SelectedElement = bodyElement;
mockXmlTreeView.SelectedNode = bodyElement;
Assert.IsTrue(editor.IsCutEnabled);
}
[Test]
public void IsCutEnabledWhenRootElementSelected()
{
mockXmlTreeView.SelectedElement = rootElement;
mockXmlTreeView.SelectedNode = rootElement;
Assert.IsFalse(editor.IsCutEnabled);
}
/// <summary>
/// The document should not change if the user decides to paste the
/// cut node back to itself. All that should happen is the view
/// updates the cut node so it no longer has the ghost image.
/// </summary>
[Test]
public void CutAndPasteToSameNode()
{
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Cut();
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Paste();
Assert.IsFalse(mockXmlTreeView.IsDirty);
Assert.AreEqual(0, mockXmlTreeView.ChildElementsAdded.Count);
Assert.AreEqual(1, mockXmlTreeView.HiddenCutNodes.Count);
Assert.AreSame(paragraphElement, mockXmlTreeView.HiddenCutNodes[0]);
}
[Test]
public void CutThenPasteTwiceToSameNode()
{
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Cut();
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Paste();
mockXmlTreeView.IsDirty = false;
mockXmlTreeView.HiddenCutNodes.Clear();
mockXmlTreeView.SelectedElement = rootElement;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
Assert.IsFalse(mockXmlTreeView.IsDirty);
Assert.AreEqual(0, mockXmlTreeView.ChildElementsAdded.Count);
Assert.IsFalse(pasteEnabled);
}
[Test]
public void CannotPasteElementOntoCommentNode()
{
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Copy();
mockXmlTreeView.SelectedComment = bodyComment;
Assert.IsFalse(editor.IsPasteEnabled);
}
[Test]
public void CannotPasteElementOntoTextNode()
{
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Copy();
mockXmlTreeView.SelectedComment = bodyComment;
Assert.IsFalse(editor.IsPasteEnabled);
}
[Test]
public void CopyAndPasteTextNode()
{
mockXmlTreeView.SelectedTextNode = paragraphText;
editor.Copy();
bool pastedEnabledWhenTextNodeSelected = editor.IsPasteEnabled;
mockXmlTreeView.SelectedElement = bodyElement;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
XmlText pastedTextNode = bodyElement.LastChild as XmlText;
Assert.IsFalse(pastedEnabledWhenTextNodeSelected);
Assert.IsTrue(pasteEnabled);
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.IsNotNull(pastedTextNode);
Assert.AreEqual(paragraphText.InnerText, pastedTextNode.InnerText);
Assert.AreEqual(1, mockXmlTreeView.ChildTextNodesAdded.Count);
Assert.AreEqual(pastedTextNode, mockXmlTreeView.ChildTextNodesAdded[0]);
}
[Test]
public void CutAndPasteTextNode()
{
mockXmlTreeView.SelectedTextNode = paragraphText;
editor.Cut();
mockXmlTreeView.SelectedElement = bodyElement;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
XmlText pastedTextNode = bodyElement.LastChild as XmlText;
Assert.IsTrue(pasteEnabled);
Assert.IsNotNull(pastedTextNode);
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.IsNull(paragraphElement.SelectSingleNode("text()"));
Assert.AreEqual(1, mockXmlTreeView.ChildTextNodesAdded.Count);
Assert.AreEqual(pastedTextNode, mockXmlTreeView.ChildTextNodesAdded[0]);
Assert.AreEqual(1, mockXmlTreeView.CutNodes.Count);
Assert.AreSame(pastedTextNode, mockXmlTreeView.CutNodes[0]);
Assert.AreEqual(1, mockXmlTreeView.TextNodesRemoved.Count);
Assert.AreSame(paragraphText, mockXmlTreeView.TextNodesRemoved[0]);
}
[Test]
public void CopyAndPasteCommentNode()
{
mockXmlTreeView.SelectedComment = bodyComment;
editor.Copy();
bool pastedEnabledWhenCommentSelected = editor.IsPasteEnabled;
mockXmlTreeView.SelectedElement = rootElement;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
XmlComment pastedCommentNode = rootElement.LastChild as XmlComment;
Assert.IsFalse(pastedEnabledWhenCommentSelected);
Assert.IsTrue(pasteEnabled);
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.IsNotNull(pastedCommentNode);
Assert.AreEqual(bodyComment.InnerText, pastedCommentNode.InnerText);
Assert.AreEqual(1, mockXmlTreeView.ChildCommentNodesAdded.Count);
Assert.AreEqual(pastedCommentNode, mockXmlTreeView.ChildCommentNodesAdded[0]);
}
[Test]
public void CutAndPasteCommentNode()
{
mockXmlTreeView.SelectedComment = bodyComment;
editor.Cut();
mockXmlTreeView.SelectedElement = rootElement;
bool pasteEnabled = editor.IsPasteEnabled;
editor.Paste();
XmlComment pastedCommentNode = rootElement.LastChild as XmlComment;
Assert.IsTrue(pasteEnabled);
Assert.IsNotNull(pastedCommentNode);
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.IsNull(bodyElement.SelectSingleNode("comment()"));
Assert.AreSame(bodyComment, pastedCommentNode);
Assert.AreEqual(1, mockXmlTreeView.ChildCommentNodesAdded.Count);
Assert.AreEqual(pastedCommentNode, mockXmlTreeView.ChildCommentNodesAdded[0]);
Assert.AreEqual(1, mockXmlTreeView.CutNodes.Count);
Assert.AreSame(pastedCommentNode, mockXmlTreeView.CutNodes[0]);
Assert.AreEqual(1, mockXmlTreeView.CommentNodesRemoved.Count);
Assert.AreSame(pastedCommentNode, mockXmlTreeView.CommentNodesRemoved[0]);
}
/// <summary>
/// Tests that the cut node has its ghost image removed.
/// </summary>
[Test]
public void CutThenCopyElement()
{
mockXmlTreeView.SelectedElement = bodyElement;
editor.Cut();
editor.Copy();
Assert.AreEqual(1, mockXmlTreeView.HiddenCutNodes.Count);
Assert.AreSame(bodyElement, mockXmlTreeView.HiddenCutNodes[0]);
}
/// <summary>
/// This test makes sure that the copied node is cleared when
/// the user decides to do a cut.
/// </summary>
[Test]
public void CopyThenCutAndPasteElement()
{
mockXmlTreeView.SelectedElement = paragraphElement;
editor.Copy();
editor.Cut();
mockXmlTreeView.SelectedElement = rootElement;
editor.Paste();
Assert.IsNull(bodyElement.SelectSingleNode("p"));
}
/// <summary>
/// Returns the xhtml strict schema as the default schema.
/// </summary>
protected override XmlSchemaCompletionData DefaultSchemaCompletionData {
get {
XmlTextReader reader = ResourceManager.GetXhtmlStrictSchema();
return new XmlSchemaCompletionData(reader);
}
}
protected override string GetXml()
{
return "<html>\r\n" +
"\t<body>\r\n" +
"\t\t<!-- Comment -->\r\n" +
"\t\t<p>some text here</p>\r\n" +
"\t</body>\r\n" +
"</html>";
}
}
}

6
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/RemoveElementTestFixture.cs

@ -31,7 +31,7 @@ namespace XmlEditor.Tests.Tree @@ -31,7 +31,7 @@ namespace XmlEditor.Tests.Tree
bodyElement = (XmlElement)editor.Document.SelectSingleNode("/html/body");
mockXmlTreeView.SelectedElement = bodyElement;
editor.RemoveElement();
editor.Delete();
}
[Test]
@ -58,7 +58,7 @@ namespace XmlEditor.Tests.Tree @@ -58,7 +58,7 @@ namespace XmlEditor.Tests.Tree
{
mockXmlTreeView.SelectedElement = null;
mockXmlTreeView.IsDirty = false;
editor.RemoveElement();
editor.Delete();
Assert.IsFalse(mockXmlTreeView.IsDirty);
}
@ -68,7 +68,7 @@ namespace XmlEditor.Tests.Tree @@ -68,7 +68,7 @@ namespace XmlEditor.Tests.Tree
XmlElement htmlElement = editor.Document.DocumentElement;
mockXmlTreeView.SelectedElement = htmlElement;
mockXmlTreeView.IsDirty = false;
editor.RemoveElement();
editor.Delete();
Assert.IsTrue(mockXmlTreeView.IsDirty);
Assert.IsNull(editor.Document.DocumentElement);
}

6
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/RemoveTextNodeTestFixture.cs

@ -31,8 +31,9 @@ namespace XmlEditor.Tests.Tree @@ -31,8 +31,9 @@ namespace XmlEditor.Tests.Tree
paragraphElement = (XmlElement)editor.Document.SelectSingleNode("/html/body/p");
XmlText textNode = (XmlText)paragraphElement.FirstChild;
mockXmlTreeView.SelectedTextNode = textNode;
mockXmlTreeView.SelectedNode = textNode;
editor.RemoveTextNode();
editor.Delete();
}
[Test]
@ -51,7 +52,8 @@ namespace XmlEditor.Tests.Tree @@ -51,7 +52,8 @@ namespace XmlEditor.Tests.Tree
{
mockXmlTreeView.IsDirty = false;
mockXmlTreeView.SelectedTextNode = null;
editor.RemoveTextNode();
mockXmlTreeView.SelectedNode = null;
editor.Delete();
Assert.IsFalse(mockXmlTreeView.IsDirty);
}

16
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlCommentTreeNodeTests.cs

@ -58,5 +58,21 @@ namespace XmlEditor.Tests.Tree @@ -58,5 +58,21 @@ namespace XmlEditor.Tests.Tree
XmlCommentTreeNode node = new XmlCommentTreeNode(comment);
Assert.AreSame(comment, node.XmlComment);
}
[Test]
public void GhostImage()
{
XmlComment comment = doc.CreateComment(String.Empty);
XmlCommentTreeNode node = new XmlCommentTreeNode(comment);
Assert.IsFalse(node.ShowGhostImage);
node.ShowGhostImage = false;
Assert.AreEqual(XmlCommentTreeNode.XmlCommentTreeNodeImageKey, node.ImageKey);
node.ShowGhostImage = true;
Assert.IsTrue(node.ShowGhostImage);
Assert.AreEqual(XmlCommentTreeNode.XmlCommentTreeNodeGhostImageKey, node.ImageKey);
}
}
}

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

@ -63,5 +63,21 @@ namespace XmlEditor.Tests.Tree @@ -63,5 +63,21 @@ namespace XmlEditor.Tests.Tree
XmlTextTreeNode node = new XmlTextTreeNode(text);
Assert.AreEqual(String.Empty, node.Text);
}
[Test]
public void GhostImage()
{
XmlText text = doc.CreateTextNode("\r\n\r\n\r\n");
XmlTextTreeNode node = new XmlTextTreeNode(text);
Assert.IsFalse(node.ShowGhostImage);
node.ShowGhostImage = false;
Assert.AreEqual(XmlTextTreeNode.XmlTextTreeNodeImageKey, node.ImageKey);
node.ShowGhostImage = true;
Assert.IsTrue(node.ShowGhostImage);
Assert.AreEqual(XmlTextTreeNode.XmlTextTreeNodeGhostImageKey, node.ImageKey);
}
}
}

133
src/AddIns/DisplayBindings/XmlEditor/Test/Tree/XmlTreeViewClipboardHandlerTestFixture.cs

@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
// <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 ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.TextEditor.Document;
using ICSharpCode.XmlEditor;
using NUnit.Framework;
using XmlEditor.Tests.Utils;
namespace XmlEditor.Tests.Tree
{
/// <summary>
/// Tests the XmlTreeView's IClipboardHandler implementation. Here
/// we are just checking that it calls the XmlTreeViewContainerControl
/// class.
/// </summary>
[TestFixture]
public class XmlTreeViewClipboardHandlerTestFixture
{
XmlView xmlView;
XmlTreeView view;
XmlTreeViewContainerControl treeViewContainer;
XmlTreeViewControl treeView;
IClipboardHandler clipboardHandler;
XmlElementTreeNode htmlTreeNode;
XmlElementTreeNode bodyTreeNode;
XmlElementTreeNode paragraphTreeNode;
[SetUp]
public void SetUp()
{
XmlSchemaCompletionDataCollection schemas = new XmlSchemaCompletionDataCollection();
xmlView = new XmlView(new DefaultTextEditorProperties(), schemas);
view = new XmlTreeView(xmlView, null, null);
treeViewContainer = (XmlTreeViewContainerControl)view.Control;
treeView = treeViewContainer.TreeView;
clipboardHandler = view as IClipboardHandler;
xmlView.XmlEditor.Text = "<html><body><p></p></body></html>";
xmlView.IsDirty = false;
view.Selected();
htmlTreeNode = treeView.Nodes[0] as XmlElementTreeNode;
htmlTreeNode.PerformInitialization();
bodyTreeNode = htmlTreeNode.Nodes[0] as XmlElementTreeNode;
bodyTreeNode.PerformInitialization();
paragraphTreeNode = bodyTreeNode.Nodes[0] as XmlElementTreeNode;
treeView.SelectedNode = null;
}
[TearDown]
public void TearDown()
{
if (view != null) {
view.Dispose();
}
if (xmlView != null) {
xmlView.Dispose();
}
}
[Test]
public void CopyDisabledWhenNoNodeSelected()
{
Assert.IsFalse(clipboardHandler.EnableCopy);
}
[Test]
public void CutDisabledWhenNoNodeSelected()
{
Assert.IsFalse(clipboardHandler.EnableCut);
}
[Test]
public void PasteDisabledWhenNoNodeSelected()
{
Assert.IsFalse(clipboardHandler.EnablePaste);
}
[Test]
public void DeleteDisabledWhenNoNodeSelected()
{
Assert.IsFalse(clipboardHandler.EnableDelete);
}
[Test]
public void SelectAllDisabled()
{
Assert.IsFalse(clipboardHandler.EnableSelectAll);
}
[Test]
public void CopyAndPaste()
{
treeView.SelectedNode = htmlTreeNode;
view.Copy();
view.Paste();
Assert.IsTrue(xmlView.IsDirty);
Assert.AreEqual(htmlTreeNode.Text, htmlTreeNode.LastNode.Text);
}
[Test]
public void CutAndPaste()
{
treeView.SelectedNode = paragraphTreeNode;
view.Cut();
treeView.SelectedNode = htmlTreeNode;
view.Paste();
Assert.IsTrue(xmlView.IsDirty);
Assert.AreEqual(paragraphTreeNode.Text, htmlTreeNode.LastNode.Text);
}
[Test]
public void DeleteRootElement()
{
treeView.SelectedNode = htmlTreeNode;
clipboardHandler.Delete();
Assert.AreEqual(0, treeView.Nodes.Count);
Assert.IsTrue(xmlView.IsDirty);
}
}
}

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

@ -328,13 +328,25 @@ namespace XmlEditor.Tests.Tree @@ -328,13 +328,25 @@ namespace XmlEditor.Tests.Tree
[Test]
public void XmlElementTreeNodeImageKey()
{
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlTextTreeNode.XmlTextTreeNodeImageKey));
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlElementTreeNode.XmlElementTreeNodeGhostImageKey));
}
[Test]
public void XmlElementTreeNodeGhostImageKey()
{
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlElementTreeNode.XmlElementTreeNodeGhostImageKey));
}
[Test]
public void XmlTextTreeNodeImageKey()
{
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlElementTreeNode.XmlElementTreeNodeImageKey));
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlTextTreeNode.XmlTextTreeNodeImageKey));
}
[Test]
public void XmlTextTreeNodeGhostImageKey()
{
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlTextTreeNode.XmlTextTreeNodeGhostImageKey));
}
[Test]
@ -343,6 +355,12 @@ namespace XmlEditor.Tests.Tree @@ -343,6 +355,12 @@ namespace XmlEditor.Tests.Tree
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlCommentTreeNode.XmlCommentTreeNodeImageKey));
}
[Test]
public void XmlCommentTreeNodeGhostImageKey()
{
Assert.IsTrue(treeView.ImageList.Images.ContainsKey(XmlCommentTreeNode.XmlCommentTreeNodeGhostImageKey));
}
/// <summary>
/// Checks that setting the TextContent property updates
/// the text in the text box.
@ -362,6 +380,36 @@ namespace XmlEditor.Tests.Tree @@ -362,6 +380,36 @@ namespace XmlEditor.Tests.Tree
Assert.AreSame(doc, treeView.Document);
}
/// <summary>
/// Tests that when a text node is selected the tree view container
/// returns this from the SelectedNode property.
/// </summary>
[Test]
public void SelectedNodeWhenTextNodeSelected()
{
treeView.SelectedNode = textTreeNode;
Assert.AreEqual(textTreeNode.XmlText, treeViewContainer.SelectedNode);
}
/// <summary>
/// Here we make sure the tree view delete key pressed handler
/// removes the selected node.
/// </summary>
[Test]
public void DeleteTextNode()
{
treeView.SelectedNode = textTreeNode;
// Sanity check that the html tree node has a text node child.
Assert.IsNotNull(htmlTreeNode.XmlElement.SelectSingleNode("text()"));
// Call the delete key handler. This is usually called when
// the delete key is pressed in the xml tree view control.
treeViewContainer.CallXmlElementTreeViewDeleteKeyPressed();
Assert.IsNull(htmlTreeNode.XmlElement.SelectSingleNode("text()"));
}
void TreeViewContainerDirtyChanged(object source, EventArgs e)
{
dirtyChanged = true;

6
src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeView.cs

@ -25,5 +25,11 @@ namespace XmlEditor.Tests.Utils @@ -25,5 +25,11 @@ namespace XmlEditor.Tests.Utils
{
base.OnMouseDown(e);
}
public void CallProcessCmdKey(Keys keys)
{
Message msg = new Message();
base.ProcessCmdKey(ref msg, keys);
}
}
}

10
src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeViewContainerControl.cs

@ -100,6 +100,16 @@ namespace XmlEditor.Tests.Utils @@ -100,6 +100,16 @@ namespace XmlEditor.Tests.Utils
base.XmlElementTreeViewAfterSelect(this, new TreeViewEventArgs(null, TreeViewAction.ByMouse));
}
/// <summary>
/// Allows us to call the XmlTreeViewContainer's
/// XmlElementTreeViewDeleteKeyPressed method to fake the user
/// pressing the delete key in the xml tree view control.
/// </summary>
public void CallXmlElementTreeViewDeleteKeyPressed()
{
base.XmlElementTreeViewDeleteKeyPressed(this, new EventArgs());
}
/// <summary>
/// Returns a new MockAddElementDialog for testing.
/// </summary>

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

@ -45,7 +45,10 @@ namespace XmlEditor.Tests.Utils @@ -45,7 +45,10 @@ namespace XmlEditor.Tests.Utils
List<XmlComment> commentNodesRemoved = new List<XmlComment>();
List<XmlComment> commentNodesInsertedBefore = new List<XmlComment>();
List<XmlComment> commentNodesInsertedAfter = new List<XmlComment>();
XmlNode selectedNode;
List<XmlNode> cutNodes = new List<XmlNode>();
List<XmlNode> hiddenCutNodes = new List<XmlNode>();
public MockXmlTreeView()
{
}
@ -80,6 +83,7 @@ namespace XmlEditor.Tests.Utils @@ -80,6 +83,7 @@ namespace XmlEditor.Tests.Utils
}
set {
selectedElement = value;
selectedNode = value;
}
}
@ -89,6 +93,7 @@ namespace XmlEditor.Tests.Utils @@ -89,6 +93,7 @@ namespace XmlEditor.Tests.Utils
}
set {
selectedTextNode = value;
selectedNode = value;
}
}
@ -98,6 +103,16 @@ namespace XmlEditor.Tests.Utils @@ -98,6 +103,16 @@ namespace XmlEditor.Tests.Utils
}
set {
selectedCommentNode = value;
selectedNode = value;
}
}
public XmlNode SelectedNode {
get {
return selectedNode;
}
set {
selectedNode = value;
}
}
@ -213,6 +228,16 @@ namespace XmlEditor.Tests.Utils @@ -213,6 +228,16 @@ namespace XmlEditor.Tests.Utils
commentNodesInsertedAfter.Add(comment);
}
public void ShowCut(XmlNode node)
{
cutNodes.Add(node);
}
public void HideCut(XmlNode node)
{
hiddenCutNodes.Add(node);
}
public string TextContent {
get {
return textContentDisplayed;
@ -453,5 +478,25 @@ namespace XmlEditor.Tests.Utils @@ -453,5 +478,25 @@ namespace XmlEditor.Tests.Utils
return commentNodesInsertedAfter;
}
}
/// <summary>
/// Returns the nodes that used when informing the view
/// that a particular node was about to be cut.
/// </summary>
public List<XmlNode> CutNodes {
get {
return cutNodes;
}
}
/// <summary>
/// Returns the nodes where the cut has been hidden via
/// the HideCut method.
/// </summary>
public List<XmlNode> HiddenCutNodes {
get {
return hiddenCutNodes;
}
}
}
}

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

@ -72,6 +72,7 @@ @@ -72,6 +72,7 @@
<Compile Include="Schema\NestedChoiceTestFixture.cs" />
<Compile Include="Schema\ChildElementAttributesTestFixture.cs" />
<Compile Include="Tree\AddChildTextNodeTestFixture.cs" />
<Compile Include="Tree\DeleteTreeNodeWithDeleteKeyTestFixture.cs" />
<Compile Include="Tree\EditCommentNodesInTreeControlTestFixture.cs" />
<Compile Include="Tree\EditCommentNodesTestFixture.cs" />
<Compile Include="Tree\InsertTextNodeAfterTestFixture.cs" />
@ -79,11 +80,14 @@ @@ -79,11 +80,14 @@
<Compile Include="Tree\MenuCommandsTestFixture.cs" />
<Compile Include="Tree\MouseDownTestFixture.cs" />
<Compile Include="Tree\OwnerStatusTestFixture.cs" />
<Compile Include="Tree\PasteInTreeControlTestFixture.cs" />
<Compile Include="Tree\PasteTestFixture.cs" />
<Compile Include="Tree\RemoveElementsFromTreeControlTestFixture.cs" />
<Compile Include="Tree\RemoveElementTestFixture.cs" />
<Compile Include="Tree\RemoveTextNodesFromTreeControlTestFixture.cs" />
<Compile Include="Tree\RemoveTextNodeTestFixture.cs" />
<Compile Include="Tree\XmlCommentTreeNodeTests.cs" />
<Compile Include="Tree\XmlTreeViewClipboardHandlerTestFixture.cs" />
<Compile Include="Tree\XmlTreeViewContainerTestFixture.cs" />
<Compile Include="Utils\DerivedXmlTreeView.cs" />
<Compile Include="Utils\DerivedXmlTreeViewContainerControl.cs" />

2
src/AddIns/DisplayBindings/XmlEditor/XmlEditor.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
# SharpDevelop 2.1.0.2075
# SharpDevelop 2.1.0.2147
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor", "Project\XmlEditor.csproj", "{6B717BD1-CD5E-498C-A42E-9E6A4584DC48}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor.Tests", "Test\XmlEditor.Tests.csproj", "{FC0FE702-A87D-4D70-A9B6-1ECCD611125F}"

7
src/Main/Base/Project/Src/Services/IconService.cs

@ -40,7 +40,13 @@ namespace ICSharpCode.SharpDevelop @@ -40,7 +40,13 @@ namespace ICSharpCode.SharpDevelop
}
}
public static Bitmap GetGhostBitmap(string name)
{
return GetGhostBitmap(GetBitmap(name));
}
public static Bitmap GetGhostBitmap(Bitmap bitmap)
{
ColorMatrix clrMatrix = new ColorMatrix(new float[][] {
new float[] {1, 0, 0, 0, 0},
@ -55,7 +61,6 @@ namespace ICSharpCode.SharpDevelop @@ -55,7 +61,6 @@ namespace ICSharpCode.SharpDevelop
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap);
Bitmap bitmap = GetBitmap(name);
Bitmap ghostBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(ghostBitmap)) {

Loading…
Cancel
Save