--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.graphviz;\r
+\r
+import java.util.ArrayList;\r
+\r
+/**\r
+ * A helper class for creating record shaped nodes.\r
+ * \r
+ * @author Hannu Niemistö\r
+ */\r
+public class Record {\r
+ \r
+ static class IdentifiableField {\r
+ String id;\r
+ String label;\r
+ \r
+ public IdentifiableField(String id, String label) {\r
+ super();\r
+ this.id = id;\r
+ this.label = label;\r
+ } \r
+ }\r
+ \r
+ static class Field {\r
+ String label;\r
+\r
+ public Field(String label) {\r
+ super();\r
+ this.label = label;\r
+ } \r
+ }\r
+ \r
+ ArrayList<Object> fields = new ArrayList<Object>();\r
+ boolean rotated = false;\r
+ \r
+ public Record() { \r
+ }\r
+ \r
+ /**\r
+ * Adds a simple nonreferable field to a record.\r
+ */\r
+ public void add(String label) {\r
+ fields.add(new Field(label));\r
+ }\r
+\r
+ /**\r
+ * Adds a field to a record that can be referred in \r
+ * connections. Example\r
+ * <blockquote><pre>\r
+ * Record r = new Record();\r
+ * r.add("A field");\r
+ * r.add("id1", "An another field");\r
+ * Node n1 = r.toField(g);\r
+ * Node n2 = new Node(g2);\r
+ * new Edge(n1.getPort("id1"), n2);\r
+ * </pre></blockquote>\r
+ */\r
+ public void add(String id, String label) {\r
+ fields.add(new IdentifiableField(id, label));\r
+ }\r
+ \r
+ /**\r
+ * Puts a record inside this record. This is most useful\r
+ * if the record added is rotated. In this way, one can\r
+ * build records that both horizontally and vertically\r
+ * divided areas.\r
+ */\r
+ public void add(Record record) {\r
+ fields.add(record);\r
+ }\r
+ \r
+ /**\r
+ * Creates a node whose shape is build according to the\r
+ * record definition.\r
+ */\r
+ public Node toNode(Graph g) {\r
+ Node node = new Node(g);\r
+ node.setShape("record");\r
+ StringBuilder b = new StringBuilder();\r
+ toString(b);\r
+ node.setLabel(b.toString());\r
+ return node;\r
+ }\r
+ \r
+ private void toString(StringBuilder b) {\r
+ if(rotated)\r
+ b.append('{');\r
+ for(int i=0;i<fields.size();++i) {\r
+ Object f = fields.get(i);\r
+ if(i > 0)\r
+ b.append('|');\r
+ if(f instanceof Field) {\r
+ Field ff = (Field)f;\r
+ b.append(ff.label);\r
+ }\r
+ else if(f instanceof IdentifiableField) {\r
+ IdentifiableField ff = (IdentifiableField)f;\r
+ b.append('<');\r
+ b.append(ff.id);\r
+ b.append('>');\r
+ b.append(ff.label);\r
+ }\r
+ else if(f instanceof Record) {\r
+ ((Record)f).toString(b);\r
+ }\r
+ }\r
+ if(rotated)\r
+ b.append('}');\r
+ }\r
+ \r
+ /**\r
+ * Tells if the record has opposite orientation from\r
+ * its surroundings. If the record is converted into\r
+ * node, this means the rankdir of the graph. If\r
+ * the record is put inside other record, then rotation\r
+ * is relative to the orientation of the parent record.\r
+ */\r
+ public void setRotated(boolean rotated) {\r
+ this.rotated = rotated;\r
+ }\r
+}\r