View Javadoc
1   /*
2    * Copyright (c) 2003, The JUNG Authors
3    * All rights reserved.
4    * 
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or https://github.com/jrtom/jung/blob/master/LICENSE for a description.
7    * 
8    */
9   package edu.uci.ics.jung.samples;
10  
11  import java.awt.BorderLayout;
12  import java.awt.Color;
13  import java.awt.Container;
14  import java.awt.Dimension;
15  import java.awt.Font;
16  import java.awt.FontMetrics;
17  import java.awt.Graphics;
18  import java.awt.GridLayout;
19  import java.awt.Shape;
20  import java.awt.event.ActionEvent;
21  import java.awt.event.ActionListener;
22  import java.awt.event.InputEvent;
23  import java.awt.geom.Rectangle2D;
24  
25  import javax.swing.JApplet;
26  import javax.swing.JButton;
27  import javax.swing.JFrame;
28  import javax.swing.JOptionPane;
29  import javax.swing.JPanel;
30  import javax.swing.JScrollPane;
31  import javax.swing.JTextArea;
32  
33  import com.google.common.base.Functions;
34  
35  import edu.uci.ics.jung.algorithms.layout.FRLayout;
36  import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
37  import edu.uci.ics.jung.graph.Graph;
38  import edu.uci.ics.jung.graph.util.TestGraphs;
39  import edu.uci.ics.jung.visualization.DefaultVisualizationModel;
40  import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
41  import edu.uci.ics.jung.visualization.VisualizationModel;
42  import edu.uci.ics.jung.visualization.VisualizationViewer;
43  import edu.uci.ics.jung.visualization.control.AnimatedPickingGraphMousePlugin;
44  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
45  import edu.uci.ics.jung.visualization.control.LayoutScalingControl;
46  import edu.uci.ics.jung.visualization.control.PickingGraphMousePlugin;
47  import edu.uci.ics.jung.visualization.control.RotatingGraphMousePlugin;
48  import edu.uci.ics.jung.visualization.control.ScalingGraphMousePlugin;
49  import edu.uci.ics.jung.visualization.control.ShearingGraphMousePlugin;
50  import edu.uci.ics.jung.visualization.control.TranslatingGraphMousePlugin;
51  import edu.uci.ics.jung.visualization.control.ViewScalingControl;
52  import edu.uci.ics.jung.visualization.decorators.EdgeShape;
53  import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
54  import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
55  import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
56  import edu.uci.ics.jung.visualization.picking.MultiPickedState;
57  import edu.uci.ics.jung.visualization.picking.PickedState;
58  import edu.uci.ics.jung.visualization.picking.ShapePickSupport;
59  
60  /**
61   * Demonstrates 3 views of one graph in one model with one layout.
62   * Each view uses a different scaling graph mouse.
63   * 
64   * @author Tom Nelson 
65   * 
66   */
67  @SuppressWarnings("serial")
68  public class MultiViewDemo extends JApplet {
69  
70      /**
71       * the graph
72       */
73      Graph<String,Number> graph;
74  
75      /**
76       * the visual components and renderers for the graph
77       */
78      VisualizationViewer<String,Number> vv1;
79      VisualizationViewer<String,Number> vv2;
80      VisualizationViewer<String,Number> vv3;
81      
82      /**
83       * the normal Function
84       */
85  //    MutableTransformer Function;
86      
87      Dimension preferredSize = new Dimension(300,300);
88      
89      final String messageOne = "The mouse wheel will scale the model's layout when activated"+
90      " in View 1. Since all three views share the same layout Function, all three views will"+
91      " show the same scaling of the layout.";
92      
93      final String messageTwo = "The mouse wheel will scale the view when activated in"+
94      " View 2. Since all three views share the same view Function, all three views will be affected.";
95      
96      final String messageThree = "   The mouse wheel uses a 'crossover' feature in View 3."+
97      " When the combined layout and view scale is greater than '1', the model's layout will be scaled."+
98      " Since all three views share the same layout Function, all three views will show the same "+
99      " scaling of the layout.\n   When the combined scale is less than '1', the scaling function"+
100     " crosses over to the view, and then, since all three views share the same view Function,"+
101     " all three views will show the same scaling.";
102     
103     JTextArea textArea;
104     JScrollPane scrollPane;
105     
106     /**
107      * create an instance of a simple graph in two views with controls to
108      * demo the zoom features.
109      * 
110      */
111     public MultiViewDemo() {
112         
113         // create a simple graph for the demo
114         graph = TestGraphs.getOneComponentGraph();
115         
116         // create one layout for the graph
117         FRLayout<String,Number> layout = new FRLayout<String,Number>(graph);
118         layout.setMaxIterations(1000);
119         
120         // create one model that all 3 views will share
121         VisualizationModel<String,Number> visualizationModel =
122             new DefaultVisualizationModel<String,Number>(layout, preferredSize);
123  
124         // create 3 views that share the same model
125         vv1 = new VisualizationViewer<String,Number>(visualizationModel, preferredSize);
126         vv2 = new VisualizationViewer<String,Number>(visualizationModel, preferredSize);
127         vv3 = new VisualizationViewer<String,Number>(visualizationModel, preferredSize);
128         
129         vv1.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph));
130         vv2.getRenderContext().setVertexShapeTransformer(
131         		Functions.<Shape>constant(new Rectangle2D.Float(-6,-6,12,12)));
132 
133         vv2.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph));
134         
135         vv3.getRenderContext().setEdgeShapeTransformer(EdgeShape.cubicCurve(graph));
136 
137 //        Function = vv1.getLayoutTransformer();
138 //        vv2.setLayoutTransformer(Function);
139 //        vv3.setLayoutTransformer(Function);
140 //        
141 //        vv2.setViewTransformer(vv1.getViewTransformer());
142 //        vv3.setViewTransformer(vv1.getViewTransformer());
143         
144         vv2.getRenderContext().setMultiLayerTransformer(vv1.getRenderContext().getMultiLayerTransformer());
145         vv3.getRenderContext().setMultiLayerTransformer(vv1.getRenderContext().getMultiLayerTransformer());
146 
147         vv1.getRenderContext().getMultiLayerTransformer().addChangeListener(vv1);
148         vv2.getRenderContext().getMultiLayerTransformer().addChangeListener(vv2);
149         vv3.getRenderContext().getMultiLayerTransformer().addChangeListener(vv3);
150 
151         
152         vv1.setBackground(Color.white);
153         vv2.setBackground(Color.white);
154         vv3.setBackground(Color.white);
155         
156         // create one pick support for all 3 views to share
157         GraphElementAccessor<String,Number> pickSupport = new ShapePickSupport<String,Number>(vv1);
158         vv1.setPickSupport(pickSupport);
159         vv2.setPickSupport(pickSupport);
160         vv3.setPickSupport(pickSupport);
161 
162         // create one picked state for all 3 views to share
163         PickedState<Number> pes = new MultiPickedState<Number>();
164         PickedState<String> pvs = new MultiPickedState<String>();
165         vv1.setPickedVertexState(pvs);
166         vv2.setPickedVertexState(pvs);
167         vv3.setPickedVertexState(pvs);
168         vv1.setPickedEdgeState(pes);
169         vv2.setPickedEdgeState(pes);
170         vv3.setPickedEdgeState(pes);
171         
172         // set an edge paint function that shows picked edges
173         vv1.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(pes, Color.black, Color.red));
174         vv2.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(pes, Color.black, Color.red));
175         vv3.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(pes, Color.black, Color.red));
176         vv1.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(pvs, Color.red, Color.yellow));
177         vv2.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(pvs, Color.blue, Color.cyan));
178         vv3.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(pvs, Color.red, Color.yellow));
179         
180         // add default listener for ToolTips
181         vv1.setVertexToolTipTransformer(new ToStringLabeller());
182         vv2.setVertexToolTipTransformer(new ToStringLabeller());
183         vv3.setVertexToolTipTransformer(new ToStringLabeller());
184         
185         Container content = getContentPane();
186         JPanel panel = new JPanel(new GridLayout(1,0));
187         
188         final JPanel p1 = new JPanel(new BorderLayout());
189         final JPanel p2 = new JPanel(new BorderLayout());
190         final JPanel p3 = new JPanel(new BorderLayout());
191         
192         p1.add(new GraphZoomScrollPane(vv1));
193         p2.add(new GraphZoomScrollPane(vv2));
194         p3.add(new GraphZoomScrollPane(vv3));
195         
196         JButton h1 = new JButton("?");
197         h1.addActionListener(new ActionListener() {
198             public void actionPerformed(ActionEvent e) {
199                 textArea.setText(messageOne);
200                 JOptionPane.showMessageDialog(p1, scrollPane, 
201                         "View 1", JOptionPane.PLAIN_MESSAGE);
202             }});
203         JButton h2 = new JButton("?");
204         h2.addActionListener(new ActionListener() {
205             public void actionPerformed(ActionEvent e) {
206                 textArea.setText(messageTwo);
207                 JOptionPane.showMessageDialog(p2, scrollPane, 
208                         "View 2", JOptionPane.PLAIN_MESSAGE);
209             }});
210         JButton h3 = new JButton("?");
211         h3.addActionListener(new ActionListener() {
212             public void actionPerformed(ActionEvent e) {
213                 textArea.setText(messageThree);
214                 textArea.setCaretPosition(0);
215                 JOptionPane.showMessageDialog(p3, scrollPane, 
216                         "View 3", JOptionPane.PLAIN_MESSAGE);
217            }});
218         
219         // create a GraphMouse for each view
220         // each one has a different scaling plugin
221         DefaultModalGraphMouse<String,Number> gm1 = new DefaultModalGraphMouse<String,Number>() {
222             protected void loadPlugins() {
223                 pickingPlugin = new PickingGraphMousePlugin<String,Number>();
224                 animatedPickingPlugin = new AnimatedPickingGraphMousePlugin<String,Number>();
225                 translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK);
226                 scalingPlugin = new ScalingGraphMousePlugin(new LayoutScalingControl(), 0);
227                 rotatingPlugin = new RotatingGraphMousePlugin();
228                 shearingPlugin = new ShearingGraphMousePlugin();
229 
230                 add(scalingPlugin);
231                 setMode(Mode.TRANSFORMING);
232             }
233         };
234 
235         DefaultModalGraphMouse<String,Number> gm2 = new DefaultModalGraphMouse<String,Number>() {
236             protected void loadPlugins() {
237                 pickingPlugin = new PickingGraphMousePlugin<String,Number>();
238                 animatedPickingPlugin = new AnimatedPickingGraphMousePlugin<String,Number>();
239                 translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK);
240                 scalingPlugin = new ScalingGraphMousePlugin(new ViewScalingControl(), 0);
241                 rotatingPlugin = new RotatingGraphMousePlugin();
242                 shearingPlugin = new ShearingGraphMousePlugin();
243 
244                 add(scalingPlugin);
245                 setMode(Mode.TRANSFORMING);
246             }
247        	
248         };
249 
250         DefaultModalGraphMouse<String,Number> gm3 = new DefaultModalGraphMouse<String,Number>() {};
251         
252         vv1.setGraphMouse(gm1);
253         vv2.setGraphMouse(gm2);
254         vv3.setGraphMouse(gm3);
255 
256         vv1.setToolTipText("<html><center>MouseWheel Scales Layout</center></html>");
257         vv2.setToolTipText("<html><center>MouseWheel Scales View</center></html>");
258         vv3.setToolTipText("<html><center>MouseWheel Scales Layout and<p>crosses over to view<p>ctrl+MouseWheel scales view</center></html>");
259  
260         vv1.addPostRenderPaintable(new BannerLabel(vv1, "View 1"));
261         vv2.addPostRenderPaintable(new BannerLabel(vv2, "View 2"));
262         vv3.addPostRenderPaintable(new BannerLabel(vv3, "View 3"));
263         
264         textArea = new JTextArea(6,30);
265         scrollPane = new JScrollPane(textArea, 
266                 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
267         textArea.setLineWrap(true);
268         textArea.setWrapStyleWord(true);
269         textArea.setEditable(false);
270         
271         JPanel flow = new JPanel();
272         flow.add(h1);
273         flow.add(gm1.getModeComboBox());
274         p1.add(flow, BorderLayout.SOUTH);
275         flow = new JPanel();
276         flow.add(h2);
277         flow.add(gm2.getModeComboBox());
278         p2.add(flow, BorderLayout.SOUTH);
279         flow = new JPanel();
280         flow.add(h3);
281         flow.add(gm3.getModeComboBox());
282         p3.add(flow, BorderLayout.SOUTH);
283         
284         panel.add(p1);
285         panel.add(p2);
286         panel.add(p3);
287         content.add(panel);
288         
289 
290     }
291     
292     class BannerLabel implements VisualizationViewer.Paintable {
293         int x;
294         int y;
295         Font font;
296         FontMetrics metrics;
297         int swidth;
298         int sheight;
299         String str;
300         VisualizationViewer<String,Number> vv;
301         
302         public BannerLabel(VisualizationViewer<String,Number> vv, String label) {
303             this.vv = vv;
304             this.str = label;
305         }
306         
307         public void paint(Graphics g) {
308             Dimension d = vv.getSize();
309             if(font == null) {
310                 font = new Font(g.getFont().getName(), Font.BOLD, 30);
311                 metrics = g.getFontMetrics(font);
312                 swidth = metrics.stringWidth(str);
313                 sheight = metrics.getMaxAscent()+metrics.getMaxDescent();
314                 x = (3*d.width/2-swidth)/2;
315                 y = d.height-sheight;
316             }
317             g.setFont(font);
318             Color oldColor = g.getColor();
319             g.setColor(Color.gray);
320             g.drawString(str, x, y);
321             g.setColor(oldColor);
322         }
323         public boolean useTransform() {
324             return false;
325         }
326     }
327 
328     public static void main(String[] args) {
329         JFrame f = new JFrame();
330         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
331         f.getContentPane().add(new MultiViewDemo());
332         f.pack();
333         f.setVisible(true);
334     }
335 }