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