1   /****************************************************************************
2    **
3    ** This file is part of the yFiles extension package ySVG-2.1.
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2007 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  
15  package demo.yext.svg;
16  
17  import java.util.HashMap;
18  import java.util.Map;
19  import y.base.Edge;
20  import y.base.Node;
21  import y.option.OptionHandler;
22  import y.view.EdgeLabel;
23  import y.view.EdgeRealizer;
24  import y.view.EditMode;
25  import y.view.HitInfo;
26  import y.view.NodeLabel;
27  import y.view.NodeRealizer;
28  import y.view.ViewMode;
29  import yext.svg.io.SVGDOMEnhancer;
30  import yext.svg.io.SVGIOHandler;
31  
32  /** 
33   * Demonstrates how to write SVG that hyperlinks nodes, edges and labels of a graph. 
34   * <p>
35   * Basic Usage: After nodes, edges and labels have been created in the editor it is 
36   * possible to associate an URL with these objects by right clicking on them.  
37   */
38  public class HyperlinkDemo extends SVGExportDemo
39  {
40    //Map used to store URLs for nodes, edges and labels.
41    Map linkMap;
42    
43    /**
44     * Instantiates HyperlinkDemo
45     */
46    public HyperlinkDemo()
47    {
48      //add right click handler
49      view.addViewMode(new RightClickMode());
50      
51      //configure default edge
52      EdgeRealizer er = view.getGraph2D().getDefaultEdgeRealizer();
53      EdgeLabel el = er.getLabel();
54      el.setText("EDGE LABEL");
55  
56      //configure default node
57      NodeRealizer nr = view.getGraph2D().getDefaultNodeRealizer();
58      nr.setSize(120, 40);
59      NodeLabel nl = nr.getLabel();
60      nl.setText("LABEL");
61      linkMap = new HashMap();
62    }
63    
64    /**
65     * Create an edit mode that displays the URL
66     * of a node as tooltip.
67     */
68    protected EditMode createEditMode()
69    {
70      EditMode editMode = new EditMode() {
71        public String getNodeTip(Node v) {
72          String url = (String)linkMap.get(v);
73          if(url != null)
74          {
75            return "<html>URL: <b>" + url + "</b></html>";
76          }
77          else
78          {
79            return "<html>No URL assigned to node. <br><b>Right click on node</b></html>";
80          }
81        }
82      };
83      editMode.showNodeTips(true);
84      return editMode;
85    }
86    
87    /**
88     * Creates and configures the SVGIOHandlers to be used.
89     * This method will add a specialized SVGDOMEnhancer to
90     * the IOHandler.
91     */
92    protected SVGIOHandler createSVGIOHandler(boolean svgz)
93    {
94      SVGIOHandler ioh = super.createSVGIOHandler(svgz);
95      SVGDOMEnhancer enhancer = new HttpLinksEnhancer();
96      ioh.setSVGGraph2DRenderer(enhancer);
97      return ioh;
98    }
99    
100   /**
101    * A custom SVGDOMEnhancer. This class will add hyperlink statements 
102    * around each node, node label, edge and
103    * edge label for which the user has given a URL.
104    */
105   class HttpLinksEnhancer extends SVGDOMEnhancer
106   {
107     protected void initializeDOM() {
108       final String function =
109               "function yhref(evt) {\n" +
110               "  if (evt.charAt(0) != '#') {\n" +
111               "    window.parent.location.href = evt;\n" +
112               "  } else {\n" +
113               "    window.parent.location.hash = evt;\n" +
114               "  }\n" +
115               "}";
116       org.w3c.dom.Element script = createElement("script");
117       script.setAttribute("type", "text/ecmascript");
118       script.appendChild(createCDATASection(function));
119       addToSVGDefinition(script);
120     }
121 
122     /**
123      * Override a callback method. Hyperlink the given node.
124      */
125     protected void nodeAddedToDOM(Node yNode, org.w3c.dom.Element element)
126     {
127       insertLink(yNode, element, true);
128     }
129     
130     /**
131      * Override a callback method. Hyperlink the given edge.
132      */
133     protected void edgeAddedToDOM(Edge yEdge, org.w3c.dom.Element element)
134     {
135       insertLink(yEdge, element, true);
136     }
137     
138     
139     /**
140      * Override a callback method. Hyperlink the given node label.
141      */
142     protected void nodeLabelAddedToDOM(NodeLabel yNodeLabel, org.w3c.dom.Element element)
143     {
144       insertLink(yNodeLabel, element, false);
145     }
146 
147     /**
148      * Override a callback method. Hyperlink the given edge label.
149      */
150     protected void edgeLabelAddedToDOM(EdgeLabel yEdgeLabel, org.w3c.dom.Element element)
151     {
152       insertLink(yEdgeLabel, element, false);
153     }
154     
155     /**
156      * Inserts a new hyperlink element in the dom tree. The URL of the hyperlink
157      * will be looked up in <CODE>linkMap</CODE>.
158      */   
159     private void insertLink(Object obj, org.w3c.dom.Element element, boolean notALabel)
160     {
161       String url = (String)linkMap.get(obj);
162       if(url != null) {
163         if (notALabel) {
164           org.w3c.dom.Element a = createElement("a");
165           element.setAttribute("onclick", "yhref('" + url + "')");
166           insertNodeBelow(a, element);
167         } else {
168           if (!"text".equals(element.getLocalName())) {
169             org.w3c.dom.NodeList text = element.getElementsByTagName("text");
170             element = text.getLength() > 0 ? (org.w3c.dom.Element)text.item(0) : null;
171           }
172           if (element != null) {
173             element.setAttribute("onclick", "yhref('" + url + "')");
174           }
175         }
176       }
177     }
178   }
179   
180   /**
181    * ViewMode reponsible for processing a right mouse click.
182    * Right clicking on nodes, edges amd labels will bring up
183    * an option handler that allows to enter a URL for each item.
184    * Hyperlinks to these URLs will be integrated in the SVG output.
185    */   
186   class RightClickMode extends ViewMode
187   {
188     public void mouseReleasedRight(double x, double y)
189     {
190       HitInfo hitInfo = getGraph2D().getHitInfo(x,y, false);
191 
192       if(hitInfo.getHitNodeLabel() != null)
193       {
194         editLinkInfo(hitInfo.getHitNodeLabel(), "node label");
195       }
196       else if(hitInfo.getHitEdgeLabel() != null)
197       {
198         editLinkInfo(hitInfo.getHitEdgeLabel(), "edge label");
199       }
200       else if(hitInfo.getHitNode() != null)
201       {
202         editLinkInfo(hitInfo.getHitNode(), "node");
203       }
204       else if(hitInfo.getHitEdge() != null)
205       {
206         editLinkInfo(hitInfo.getHitEdge(), "edge");
207       }
208       
209     }
210     
211     void editLinkInfo(Object key, String type)
212     {
213       OptionHandler op = new OptionHandler("Hyperlink for " + type);
214       String url = (String)linkMap.get(key);
215       if(url != null)
216       {
217         op.addString("Hyperlink URL",url);
218       }
219       else
220       {
221         op.addString("Hyperlink URL","");
222       }
223       if(op.showEditor())
224       {
225         url = op.getString("Hyperlink URL");
226         if(url.length() > 0)
227         {
228           linkMap.put(key, url);
229         }
230         else
231         {
232           linkMap.remove(key);
233         }
234       } 
235     }
236   }
237   
238   /**
239    * Launches this demo.
240    */
241   public static void main(String args[])
242   {
243     initLnF();
244     HyperlinkDemo demo = new HyperlinkDemo();
245     demo.start();
246   }
247   
248 }