// SharpDevelop samples // Copyright (c) 2006, AlphaSierraPapa // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, this list // of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // - Neither the name of the SharpDevelop team nor the names of its contributors may be used to // endorse or promote products derived from this software without specific prior written // permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.Collections; using System.Windows.Forms; using System.Reflection; using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory; namespace NRefactoryDemo { public partial class AstView { CompilationUnit unit; public CompilationUnit Unit { get { return unit; } set { unit = value; UpdateTree(); } } void UpdateTree() { tree.Nodes.Clear(); tree.Nodes.Add(new CollectionNode("CompilationUnit", unit.Children)); tree.SelectedNode = tree.Nodes[0]; } public AstView() { InitializeComponent(); } public void DeleteSelectedNode() { if (tree.SelectedNode is ElementNode) { INode element = (tree.SelectedNode as ElementNode).element; if (tree.SelectedNode.Parent is CollectionNode) { if (MessageBox.Show("Remove selected node from parent collection?", "Remove node", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { IList col = (tree.SelectedNode.Parent as CollectionNode).collection; col.Remove(element); (tree.SelectedNode.Parent as CollectionNode).Update(); } } else if (tree.SelectedNode.Parent is ElementNode) { if (MessageBox.Show("Set selected property to null?", "Remove node", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { // get parent element element = (tree.SelectedNode.Parent as ElementNode).element; string propertyName = (string)tree.SelectedNode.Tag; element.GetType().GetProperty(propertyName).SetValue(element, null, null); (tree.SelectedNode.Parent as ElementNode).Update(); } } } else if (tree.SelectedNode is CollectionNode) { if (MessageBox.Show("Remove all elements from selected collection?", "Clear collection", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { IList col = (tree.SelectedNode as CollectionNode).collection; col.Clear(); (tree.SelectedNode as CollectionNode).Update(); } } } public void EditSelectedNode() { TreeNode node = tree.SelectedNode; while (!(node is ElementNode)) { if (node == null) { return; } node = node.Parent; } INode element = ((ElementNode)node).element; using (EditDialog dlg = new EditDialog(element)) { dlg.ShowDialog(); } ((ElementNode)node).Update(); } public void ApplyTransformation(IAstVisitor visitor) { if (tree.SelectedNode == tree.Nodes[0]) { unit.AcceptVisitor(visitor, null); UpdateTree(); } else { string name = visitor.GetType().Name; ElementNode elementNode = tree.SelectedNode as ElementNode; CollectionNode collectionNode = tree.SelectedNode as CollectionNode; if (elementNode != null) { if (MessageBox.Show(("Apply " + name + " to selected element '" + elementNode.Text + "'?"), "Apply transformation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { elementNode.element.AcceptVisitor(visitor, null); elementNode.Update(); } } else if (collectionNode != null) { if (MessageBox.Show(("Apply " + name + " to all elements in selected collection '" + collectionNode.Text + "'?"), "Apply transformation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { foreach (TreeNode subNode in collectionNode.Nodes) { if (subNode is ElementNode) { (subNode as ElementNode).element.AcceptVisitor(visitor, null); } } collectionNode.Update(); } } } } static TreeNode CreateNode(object child) { if (child == null) { return new TreeNode("*null reference*"); } else if (child is INode) { return new ElementNode(child as INode); } else { return new TreeNode(child.ToString()); } } class CollectionNode : TreeNode { internal IList collection; string baseName; public CollectionNode(string text, IList children) : base(text) { this.baseName = text; this.collection = children; Update(); } public void Update() { if (collection.Count == 0) { Text = baseName + " (empty collection)"; } else if (collection.Count == 1) { Text = baseName + " (collection with 1 element)"; } else { Text = baseName + " (collection with " + collection.Count + " elements)"; } Nodes.Clear(); foreach (object child in collection) { Nodes.Add(CreateNode(child)); } Expand(); } } class ElementNode : TreeNode { internal INode element; public ElementNode(INode node) { this.element = node; Update(); } public void Update() { Nodes.Clear(); Type type = element.GetType(); Text = type.Name; if (Tag != null) { // HACK: after editing property element Text = Tag.ToString() + " = " + Text; } if (!(element is INullable && (element as INullable).IsNull)) { AddProperties(type, element); if (element.Children.Count > 0) { Nodes.Add(new CollectionNode("Children", element.Children)); } } } void AddProperties(Type type, INode node) { if (type == typeof(AbstractNode)) return; foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (pi.DeclaringType != type) // don't add derived properties continue; if (pi.Name == "IsNull") continue; object value = pi.GetValue(node, null); if (value is IList) { Nodes.Add(new CollectionNode(pi.Name, (IList)value)); } else if (value is string) { Text += " " + pi.Name + "='" + value + "'"; } else { TreeNode treeNode = CreateNode(value); treeNode.Text = pi.Name + " = " + treeNode.Text; treeNode.Tag = pi.Name; Nodes.Add(treeNode); } } AddProperties(type.BaseType, node); } } void TreeKeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Delete) { DeleteSelectedNode(); } else if (e.KeyData == Keys.Space || e.KeyData == Keys.Enter) { EditSelectedNode(); } } } }