1   package demo.yext.graphml;
2   
3   import y.base.DataMap;
4   import y.base.Graph;
5   import y.base.Node;
6   import y.base.NodeMap;
7   import y.option.OptionHandler;
8   import y.util.Maps;
9   import y.view.EditMode;
10  import y.view.PopupMode;
11  import y.view.ViewMode;
12  import y.view.HitInfo;
13  import yext.graphml.graph2D.GraphMLIOHandler;
14  
15  import javax.swing.AbstractAction;
16  import javax.swing.JMenu;
17  import javax.swing.JPopupMenu;
18  import java.awt.event.ActionEvent;
19  import java.util.HashMap;
20  import java.util.StringTokenizer;
21  
22  /**
23   * This demo shows how to configure GraphMLIOHandler to be able to handle
24   * extra node and graph data of complex type.
25   * Additional data for a node and edge can be edited by right-clicking on the corresponding
26   * element. To edit the graph data, right-click on the canvas background.
27   * The element tooltip will show the currently set data values for each element.
28   */
29  public class ComplexExtensionGraphMLDemo extends GraphMLDemo {
30  
31    /**
32     * Stores a newline-separated string for each node that is interpreted as
33     * a list of items. The GraphML representation of this String will have the
34     * structured form
35     * <ItemList>
36     *   <Item>  </Item>
37     *   <Item>  </Item>
38     *   ...
39     * </ItemList>
40     */
41    NodeMap nodeDataMap;
42  
43    /**
44     * Stores a String value for the graph using a custom serialization mechanism
45     */
46    DataMap graphDataMap;
47  
48  
49    public ComplexExtensionGraphMLDemo() {
50  
51      //define a view mode that displays the currently set data values
52      ViewMode tooltipMode = new ViewMode() {
53        public void mouseMoved(double x, double y) {
54          HitInfo info = getHitInfo(x,y);
55          if (info.getHitNode() != null) {
56            String items = (String) nodeDataMap.get(info.getHitNode());
57            if(items != null) {
58              StringTokenizer tok = new StringTokenizer(items, "\n\r");
59              String tipText = "<html>Node Items:<table>";
60              while (tok.hasMoreTokens())
61                tipText += "</tr></td>" + tok.nextToken() + "</td></tr>";
62              tipText += "</table>";
63              view.setToolTipText(tipText);
64            }
65          }
66          else {
67            view.setToolTipText("MyGraphAttribute=" + graphDataMap.get(view.getGraph2D()));
68          }
69        }
70      };
71  
72      //add the view mode to the view
73      view.addViewMode(tooltipMode);
74    }
75  
76    /**
77     * Create a GraphMLIOHandler that reads and writes additional node and graph data
78     * of complex type.
79     */
80    protected GraphMLIOHandler createGraphMLIOHandler() {
81  
82      nodeDataMap = view.getGraph2D().createNodeMap();
83      graphDataMap = Maps.createDataMap(new HashMap());
84  
85      GraphMLIOHandler ioHandler = new ComplexExtensionGraphMLIOHandler(nodeDataMap, graphDataMap);
86  
87      return ioHandler;
88    }
89  
90    /**
91     * Create an edit mode that displays a context-sensitive popup-menu when right-clicking
92     * on an the canvas.
93     */
94    protected EditMode createEditMode() {
95      EditMode editMode = super.createEditMode();
96  
97      editMode.setPopupMode(new PopupMode() {
98        public JPopupMenu getNodePopup(Node v) {
99          JPopupMenu pm = new JPopupMenu();
100         pm.add(new EditAttributeAction("Edit Node Attribute...", v, nodeDataMap));
101         return pm;
102       }
103 
104       public JPopupMenu getPaperPopup(double x, double y) {
105         JPopupMenu pm = new JPopupMenu();
106         pm.add(new EditAttributeAction("Edit Graph Attribute...", getGraph2D(), graphDataMap));
107         return pm;
108       }
109     });
110 
111     return editMode;
112   }
113 
114 
115   /**
116    * Editor action for the additional node, edge and graph attributes.
117    */
118   static class EditAttributeAction extends AbstractAction {
119     private Object object;
120     private DataMap dataMap;
121 
122     private OptionHandler op;
123 
124     EditAttributeAction(String name, Object object, DataMap dataMap) {
125       super(name);
126       this.object = object;
127       this.dataMap = dataMap;
128       op = new OptionHandler(name);
129       if (object instanceof Node) {
130         op.addString("Node Items", (String)dataMap.get(object), 10);
131       } else if (object instanceof Graph) {
132         op.addString("MyGraphAttribute", (String)dataMap.get(object));
133       }
134     }
135 
136     public void actionPerformed(ActionEvent actionEvent) {
137       if (op.showEditor()) {
138         if (object instanceof Node) {
139           dataMap.set(object, op.getString("Node Items"));
140         } else if(object instanceof Graph) {
141           dataMap.set(object, op.getString("MyGraphAttribute"));
142         }
143       }
144     }
145   }
146 
147 
148   /**
149    * Add sample graphs to the menu.
150    */
151   protected JMenu createSampleGraphMenu() {
152     return createSampleGraphMenu(new String[]{"resources/custom/complexdemo.graphml"});
153   }
154 
155   /**
156    * Launches this demo.
157    */
158   public static void main(String[] args) {
159     initLnF();
160     final ComplexExtensionGraphMLDemo demo = new ComplexExtensionGraphMLDemo();
161     demo.start();
162   }
163 }
164