]> granicus.if.org Git - graphviz/commitdiff
Win tweak panel for graph, default node and default edge attributes
authorglenlow <devnull@localhost>
Tue, 1 Apr 2008 16:37:51 +0000 (16:37 +0000)
committerglenlow <devnull@localhost>
Tue, 1 Apr 2008 16:37:51 +0000 (16:37 +0000)
windows/AttributeInspectorForm.cs [new file with mode: 0755]

diff --git a/windows/AttributeInspectorForm.cs b/windows/AttributeInspectorForm.cs
new file mode 100755 (executable)
index 0000000..97fc33a
--- /dev/null
@@ -0,0 +1,193 @@
+/* $Id$ $Revision$ */\r
+/* vim:set shiftwidth=4 ts=8: */\r
+\r
+/**********************************************************\r
+*      This software is part of the graphviz package      *\r
+*                http://www.graphviz.org/                 *\r
+*                                                         *\r
+*            Copyright (c) 1994-2008 AT&T Corp.           *\r
+*                and is licensed under the                *\r
+*            Common Public License, Version 1.0           *\r
+*                      by AT&T Corp.                      *\r
+*                                                         *\r
+*        Information and Software Systems Research        *\r
+*              AT&T Research, Florham Park NJ             *\r
+**********************************************************/\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel;\r
+using System.IO;\r
+using System.Text;\r
+using System.Windows.Forms;\r
+using System.Windows.Forms.Design;\r
+using System.Xml;\r
+using System.Xml.XPath;\r
+\r
+namespace Graphviz\r
+{\r
+       public partial class AttributeInspectorForm : Form\r
+       {\r
+               public static Form Instance\r
+               {\r
+                       get\r
+                       {\r
+                               return _instance;\r
+                       }\r
+               }\r
+               \r
+               public AttributeInspectorForm()\r
+               {\r
+                       InitializeComponent();\r
+       \r
+                       /* remove existing tabs and add in our attribute property tabs */\r
+                       List<Type> tabsToRemove = new List<Type>();\r
+                       foreach (PropertyTab tabToRemove in attributePropertyGrid.PropertyTabs)\r
+                               tabsToRemove.Add(tabToRemove.GetType());\r
+                       foreach (Type tabToRemove in tabsToRemove)\r
+                               attributePropertyGrid.PropertyTabs.RemoveTabType(tabToRemove);\r
+                       attributePropertyGrid.PropertyTabs.AddTabType(typeof(GraphPropertyTab), PropertyTabScope.Static);\r
+                       attributePropertyGrid.PropertyTabs.AddTabType(typeof(NodePropertyTab), PropertyTabScope.Static);\r
+                       attributePropertyGrid.PropertyTabs.AddTabType(typeof(EdgePropertyTab), PropertyTabScope.Static);\r
+                        \r
+                       /* inspect the graph when the handle has been created */\r
+                       /* NOTE: if we set the SelectedObject BEFORE the handle has been created, this damages the property tabs, a Microsoft bug */\r
+                       if (attributePropertyGrid.IsHandleCreated)\r
+                               InspectMainForm();\r
+                       else\r
+                               attributePropertyGrid.HandleCreated += delegate(object sender, EventArgs e)\r
+                               {\r
+                                       InspectMainForm();\r
+                               };\r
+                       \r
+                       /* inspect the graph when the main form changes */\r
+                       FormController.Instance.MainFormChanged += delegate(object sender, EventArgs e)\r
+                       {\r
+                               InspectMainForm();\r
+                       };\r
+               }\r
+\r
+               protected override void OnFormClosing(FormClosingEventArgs e)\r
+               {\r
+                       /* instead of closing, we hide ourselves */\r
+                       Hide();\r
+                       e.Cancel = true;\r
+               }\r
+               \r
+               private class GraphPropertyTab : ExternalPropertyTab\r
+               {\r
+                       public GraphPropertyTab() : base("Graph Attributes", Properties.Resources.GraphAttributes, _graphProperties)\r
+                       {\r
+                       }\r
+               }\r
+\r
+               private class NodePropertyTab : ExternalPropertyTab\r
+               {\r
+                       public NodePropertyTab() : base("Node Attributes", Properties.Resources.NodeAttributes, _nodeProperties)\r
+                       {\r
+                       }\r
+               }\r
+\r
+               private class EdgePropertyTab : ExternalPropertyTab\r
+               {\r
+                       public EdgePropertyTab() : base("Edge Attributes", Properties.Resources.EdgeAttributes, _edgeProperties)\r
+                       {\r
+                       }\r
+               }\r
+\r
+               private void InspectMainForm()\r
+               {\r
+                       /* if the main form has a graph, show its properties */\r
+                       GraphForm graphForm = FormController.Instance.MainForm as GraphForm;\r
+                       if (graphForm != null)\r
+                       {\r
+                               Text = "Attributes of " + graphForm.Text;\r
+                               attributePropertyGrid.SelectedObject = graphForm.Graph;\r
+                       }\r
+               }\r
+               \r
+               private static PropertyDescriptorCollection GetComponentProperties(XPathNavigator schema, string component)\r
+               {\r
+                       PropertyDescriptorCollection properties = new PropertyDescriptorCollection(new PropertyDescriptor[0]);\r
+                       \r
+                       XmlNamespaceManager namespaces = new XmlNamespaceManager(schema.NameTable);\r
+                       namespaces.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");\r
+                       namespaces.AddNamespace("html", "http://www.w3.org/1999/xhtml");\r
+                       \r
+                       /* look for each attribute with the graph component */\r
+                       XPathNodeIterator componentElements = schema.Select(\r
+                               string.Format("/xsd:schema/xsd:complexType[@name='{0}']/xsd:attribute", component),\r
+                               namespaces);\r
+                       while (componentElements.MoveNext()) {\r
+                               List<Attribute> descriptorAttributes = new List<Attribute>();\r
+                               string name = componentElements.Current.GetAttribute("ref", string.Empty);\r
+                               \r
+                               /* add default attribute for any defaults */\r
+                               string descriptorDefault = componentElements.Current.GetAttribute("default", string.Empty);\r
+                               if (!string.IsNullOrEmpty (descriptorDefault))\r
+                                       descriptorAttributes.Add(new DefaultValueAttribute(descriptorDefault));\r
+                                       \r
+                               /* add description attribute for any documentation (we'll need to preserve paragraph breaks though) */\r
+                               StringBuilder description = new StringBuilder();\r
+                               XPathNodeIterator paragraphs = schema.Select (\r
+                                       string.Format("/xsd:schema/xsd:attribute[@name='{0}']/xsd:annotation/xsd:documentation/html:p", name), namespaces);\r
+                               while (paragraphs.MoveNext ()) {\r
+                                       if (description.Length > 0)\r
+                                               description.Append("\r\n");\r
+                                       description.Append((string)paragraphs.Current.Evaluate("normalize-space(.)", namespaces));\r
+                               }\r
+                               if (description.Length > 0)\r
+                                       descriptorAttributes.Add(new DescriptionAttribute(description.ToString()));\r
+                               \r
+                               /* add standard values and type converter attribute for xsd:boolean or any enumerations */\r
+                               string type = (string)schema.Evaluate(\r
+                                       string.Format("string(/xsd:schema/xsd:attribute[@name='{0}']/@type)", name), namespaces);\r
+                               switch (type) {\r
+                               case "xsd:boolean":\r
+                                       descriptorAttributes.Add(new StandardValuesTypeConverter.Attribute(new string[]{"false", "true"}));\r
+                                       descriptorAttributes.Add(new TypeConverterAttribute(typeof(StandardValuesTypeConverter)));\r
+                                       break;\r
+                               default:\r
+                                       if (!type.StartsWith("xsd")) {\r
+                                               XPathNodeIterator enumeration = schema.Select(\r
+                                                       string.Format("/xsd:schema/xsd:simpleType[@name='{0}']/xsd:restriction/xsd:enumeration/@value", type),\r
+                                                       namespaces);\r
+                                               if (enumeration.Count > 0) {\r
+                                                       List<string> standardValues = new List<string>();\r
+                                                       while (enumeration.MoveNext())\r
+                                                               standardValues.Add(enumeration.Current.Value);\r
+                                                       \r
+                                                       descriptorAttributes.Add(new StandardValuesTypeConverter.Attribute(standardValues));\r
+                                                       descriptorAttributes.Add(new TypeConverterAttribute(typeof(StandardValuesTypeConverter)));\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                               }\r
+                               \r
+                               /* now create and add the property to the collection */\r
+                               properties.Add(new GraphPropertyDescriptor(component, name, descriptorAttributes.ToArray()));\r
+                       }\r
+                       return properties;\r
+               }\r
+               \r
+               static AttributeInspectorForm()\r
+               {\r
+                       /* read the schema from our application directory */\r
+                       /* NOTE: we use XPathDocument instead of XmlDocument since it is faster in the read-only case */\r
+                       XPathNavigator schema = new XPathDocument(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "attributes.xml")).CreateNavigator();\r
+                       \r
+                       /* scan attribute schema for graph components */\r
+                       _graphProperties = GetComponentProperties(schema, "graph");\r
+                       _nodeProperties = GetComponentProperties(schema, "node");\r
+                       _edgeProperties = GetComponentProperties(schema, "edge");\r
+\r
+                       // NOTE: this has to run AFTER we set up the graph, node & edge properties so the external property tabs can read them in\r
+                       _instance = new AttributeInspectorForm();\r
+               }\r
+               \r
+               private static AttributeInspectorForm _instance;\r
+               private static PropertyDescriptorCollection _graphProperties;\r
+               private static PropertyDescriptorCollection _nodeProperties;\r
+               private static PropertyDescriptorCollection _edgeProperties;\r
+       }\r
+}
\ No newline at end of file