1
2
3
4
5
6
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.Graphics2D;
16 import java.awt.event.ActionEvent;
17 import java.awt.event.ActionListener;
18 import java.awt.image.BufferedImage;
19 import java.awt.print.Printable;
20 import java.awt.print.PrinterJob;
21 import java.io.File;
22 import java.util.HashMap;
23
24 import javax.imageio.ImageIO;
25 import javax.swing.AbstractAction;
26 import javax.swing.JApplet;
27 import javax.swing.JButton;
28 import javax.swing.JComboBox;
29 import javax.swing.JFileChooser;
30 import javax.swing.JFrame;
31 import javax.swing.JMenu;
32 import javax.swing.JMenuBar;
33 import javax.swing.JOptionPane;
34 import javax.swing.JPanel;
35 import javax.swing.JPopupMenu;
36
37 import org.apache.commons.collections15.Factory;
38 import org.apache.commons.collections15.functors.MapTransformer;
39 import org.apache.commons.collections15.map.LazyMap;
40
41 import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
42 import edu.uci.ics.jung.algorithms.layout.StaticLayout;
43 import edu.uci.ics.jung.graph.Graph;
44 import edu.uci.ics.jung.graph.SparseMultigraph;
45 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
46 import edu.uci.ics.jung.visualization.VisualizationViewer;
47 import edu.uci.ics.jung.visualization.annotations.AnnotationControls;
48 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
49 import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse;
50 import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
51 import edu.uci.ics.jung.visualization.control.ScalingControl;
52 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
53
54
55
56
57
58
59
60
61
62
63
64 public class GraphEditorDemo extends JApplet implements Printable {
65
66
67
68
69 private static final long serialVersionUID = -2023243689258876709L;
70
71
72
73
74 Graph<Number,Number> graph;
75
76 AbstractLayout<Number,Number> layout;
77
78
79
80
81 VisualizationViewer<Number,Number> vv;
82
83 String instructions =
84 "<html>"+
85 "<h3>All Modes:</h3>"+
86 "<ul>"+
87 "<li>Right-click an empty area for <b>Create Vertex</b> popup"+
88 "<li>Right-click on a Vertex for <b>Delete Vertex</b> popup"+
89 "<li>Right-click on a Vertex for <b>Add Edge</b> menus <br>(if there are selected Vertices)"+
90 "<li>Right-click on an Edge for <b>Delete Edge</b> popup"+
91 "<li>Mousewheel scales with a crossover value of 1.0.<p>"+
92 " - scales the graph layout when the combined scale is greater than 1<p>"+
93 " - scales the graph view when the combined scale is less than 1"+
94
95 "</ul>"+
96 "<h3>Editing Mode:</h3>"+
97 "<ul>"+
98 "<li>Left-click an empty area to create a new Vertex"+
99 "<li>Left-click on a Vertex and drag to another Vertex to create an Undirected Edge"+
100 "<li>Shift+Left-click on a Vertex and drag to another Vertex to create a Directed Edge"+
101 "</ul>"+
102 "<h3>Picking Mode:</h3>"+
103 "<ul>"+
104 "<li>Mouse1 on a Vertex selects the vertex"+
105 "<li>Mouse1 elsewhere unselects all Vertices"+
106 "<li>Mouse1+Shift on a Vertex adds/removes Vertex selection"+
107 "<li>Mouse1+drag on a Vertex moves all selected Vertices"+
108 "<li>Mouse1+drag elsewhere selects Vertices in a region"+
109 "<li>Mouse1+Shift+drag adds selection of Vertices in a new region"+
110 "<li>Mouse1+CTRL on a Vertex selects the vertex and centers the display on it"+
111 "<li>Mouse1 double-click on a vertex or edge allows you to edit the label"+
112 "</ul>"+
113 "<h3>Transforming Mode:</h3>"+
114 "<ul>"+
115 "<li>Mouse1+drag pans the graph"+
116 "<li>Mouse1+Shift+drag rotates the graph"+
117 "<li>Mouse1+CTRL(or Command)+drag shears the graph"+
118 "<li>Mouse1 double-click on a vertex or edge allows you to edit the label"+
119 "</ul>"+
120 "<h3>Annotation Mode:</h3>"+
121 "<ul>"+
122 "<li>Mouse1 begins drawing of a Rectangle"+
123 "<li>Mouse1+drag defines the Rectangle shape"+
124 "<li>Mouse1 release adds the Rectangle as an annotation"+
125 "<li>Mouse1+Shift begins drawing of an Ellipse"+
126 "<li>Mouse1+Shift+drag defines the Ellipse shape"+
127 "<li>Mouse1+Shift release adds the Ellipse as an annotation"+
128 "<li>Mouse3 shows a popup to input text, which will become"+
129 "<li>a text annotation on the graph at the mouse location"+
130 "</ul>"+
131 "</html>";
132
133
134
135
136
137
138 public GraphEditorDemo() {
139
140
141 graph = new SparseMultigraph<Number,Number>();
142
143 this.layout = new StaticLayout<Number,Number>(graph,
144 new Dimension(600,600));
145
146 vv = new VisualizationViewer<Number,Number>(layout);
147 vv.setBackground(Color.white);
148
149 vv.getRenderContext().setVertexLabelTransformer(MapTransformer.<Number,String>getInstance(
150 LazyMap.<Number,String>decorate(new HashMap<Number,String>(), new ToStringLabeller<Number>())));
151
152 vv.getRenderContext().setEdgeLabelTransformer(MapTransformer.<Number,String>getInstance(
153 LazyMap.<Number,String>decorate(new HashMap<Number,String>(), new ToStringLabeller<Number>())));
154
155 vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer());
156
157
158 Container content = getContentPane();
159 final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
160 content.add(panel);
161 Factory<Number> vertexFactory = new VertexFactory();
162 Factory<Number> edgeFactory = new EdgeFactory();
163
164 final EditingModalGraphMouse<Number,Number> graphMouse =
165 new EditingModalGraphMouse<Number,Number>(vv.getRenderContext(), vertexFactory, edgeFactory);
166
167
168
169
170
171 vv.setGraphMouse(graphMouse);
172 vv.addKeyListener(graphMouse.getModeKeyListener());
173
174 graphMouse.setMode(ModalGraphMouse.Mode.EDITING);
175
176 final ScalingControl scaler = new CrossoverScalingControl();
177 JButton plus = new JButton("+");
178 plus.addActionListener(new ActionListener() {
179 public void actionPerformed(ActionEvent e) {
180 scaler.scale(vv, 1.1f, vv.getCenter());
181 }
182 });
183 JButton minus = new JButton("-");
184 minus.addActionListener(new ActionListener() {
185 public void actionPerformed(ActionEvent e) {
186 scaler.scale(vv, 1/1.1f, vv.getCenter());
187 }
188 });
189
190 JButton help = new JButton("Help");
191 help.addActionListener(new ActionListener() {
192
193 public void actionPerformed(ActionEvent e) {
194 JOptionPane.showMessageDialog(vv, instructions);
195 }});
196
197 AnnotationControls<Number,Number> annotationControls =
198 new AnnotationControls<Number,Number>(graphMouse.getAnnotatingPlugin());
199 JPanel controls = new JPanel();
200 controls.add(plus);
201 controls.add(minus);
202 JComboBox modeBox = graphMouse.getModeComboBox();
203 controls.add(modeBox);
204 controls.add(annotationControls.getAnnotationsToolBar());
205 controls.add(help);
206 content.add(controls, BorderLayout.SOUTH);
207 }
208
209
210
211
212
213 public void writeJPEGImage(File file) {
214 int width = vv.getWidth();
215 int height = vv.getHeight();
216
217 BufferedImage bi = new BufferedImage(width, height,
218 BufferedImage.TYPE_INT_RGB);
219 Graphics2D graphics = bi.createGraphics();
220 vv.paint(graphics);
221 graphics.dispose();
222
223 try {
224 ImageIO.write(bi, "jpeg", file);
225 } catch (Exception e) {
226 e.printStackTrace();
227 }
228 }
229
230 public int print(java.awt.Graphics graphics,
231 java.awt.print.PageFormat pageFormat, int pageIndex)
232 throws java.awt.print.PrinterException {
233 if (pageIndex > 0) {
234 return (Printable.NO_SUCH_PAGE);
235 } else {
236 java.awt.Graphics2D g2d = (java.awt.Graphics2D) graphics;
237 vv.setDoubleBuffered(false);
238 g2d.translate(pageFormat.getImageableX(), pageFormat
239 .getImageableY());
240
241 vv.paint(g2d);
242 vv.setDoubleBuffered(true);
243
244 return (Printable.PAGE_EXISTS);
245 }
246 }
247
248 class VertexFactory implements Factory<Number> {
249
250 int i=0;
251
252 public Number create() {
253 return i++;
254 }
255 }
256
257 class EdgeFactory implements Factory<Number> {
258
259 int i=0;
260
261 public Number create() {
262 return i++;
263 }
264 }
265
266
267
268
269 @SuppressWarnings("serial")
270 public static void main(String[] args) {
271 JFrame frame = new JFrame();
272 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
273 final GraphEditorDemo demo = new GraphEditorDemo();
274
275 JMenu menu = new JMenu("File");
276 menu.add(new AbstractAction("Make Image") {
277 public void actionPerformed(ActionEvent e) {
278 JFileChooser chooser = new JFileChooser();
279 int option = chooser.showSaveDialog(demo);
280 if(option == JFileChooser.APPROVE_OPTION) {
281 File file = chooser.getSelectedFile();
282 demo.writeJPEGImage(file);
283 }
284 }});
285 menu.add(new AbstractAction("Print") {
286 public void actionPerformed(ActionEvent e) {
287 PrinterJob printJob = PrinterJob.getPrinterJob();
288 printJob.setPrintable(demo);
289 if (printJob.printDialog()) {
290 try {
291 printJob.print();
292 } catch (Exception ex) {
293 ex.printStackTrace();
294 }
295 }
296 }});
297 JPopupMenu.setDefaultLightWeightPopupEnabled(false);
298 JMenuBar menuBar = new JMenuBar();
299 menuBar.add(menu);
300 frame.setJMenuBar(menuBar);
301 frame.getContentPane().add(demo);
302 frame.pack();
303 frame.setVisible(true);
304 }
305 }
306