You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
7.6 KiB
247 lines
7.6 KiB
// 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(); |
|
} |
|
} |
|
} |
|
}
|
|
|