View Javadoc
1   package edu.uci.ics.jung.visualization.control;
2   
3   import java.awt.Component;
4   import java.awt.Cursor;
5   import java.awt.Dimension;
6   import java.awt.ItemSelectable;
7   import java.awt.event.InputEvent;
8   import java.awt.event.ItemEvent;
9   import java.awt.event.ItemListener;
10  import java.awt.event.KeyAdapter;
11  import java.awt.event.KeyEvent;
12  
13  import javax.swing.ButtonGroup;
14  import javax.swing.Icon;
15  import javax.swing.JComboBox;
16  import javax.swing.JMenu;
17  import javax.swing.JRadioButtonMenuItem;
18  import javax.swing.plaf.basic.BasicIconFactory;
19  
20  import com.google.common.base.Supplier;
21  
22  import edu.uci.ics.jung.visualization.MultiLayerTransformer;
23  import edu.uci.ics.jung.visualization.RenderContext;
24  import edu.uci.ics.jung.visualization.annotations.AnnotatingGraphMousePlugin;
25  
26  public class EditingModalGraphMouse<V,E> extends AbstractModalGraphMouse 
27  	implements ModalGraphMouse, ItemSelectable {
28  
29  	protected Supplier<V> vertexFactory;
30  	protected Supplier<E> edgeFactory;
31  	protected EditingGraphMousePlugin<V,E> editingPlugin;
32  	protected LabelEditingGraphMousePlugin<V,E> labelEditingPlugin;
33  	protected EditingPopupGraphMousePlugin<V,E> popupEditingPlugin;
34  	protected AnnotatingGraphMousePlugin<V,E> annotatingPlugin;
35  	protected MultiLayerTransformer basicTransformer;
36  	protected RenderContext<V,E> rc;
37  
38  	/**
39  	 * Creates an instance with the specified rendering context and vertex/edge factories,
40  	 * and with default zoom in/out values of 1.1 and 1/1.1.
41  	 * @param rc the rendering context
42  	 * @param vertexFactory used to construct vertices
43  	 * @param edgeFactory used to construct edges
44  	 */
45  	public EditingModalGraphMouse(RenderContext<V,E> rc,
46  			Supplier<V> vertexFactory, Supplier<E> edgeFactory) {
47  		this(rc, vertexFactory, edgeFactory, 1.1f, 1/1.1f);
48  	}
49  
50  	/**
51  	 * Creates an instance with the specified rendering context and vertex/edge factories,
52  	 * and with the specified zoom in/out values.
53  	 * @param rc the rendering context
54  	 * @param vertexFactory used to construct vertices
55  	 * @param edgeFactory used to construct edges
56  	 * @param in amount to zoom in by for each action
57  	 * @param out amount to zoom out by for each action
58  	 */
59  	public EditingModalGraphMouse(RenderContext<V,E> rc,
60  			Supplier<V> vertexFactory, Supplier<E> edgeFactory, float in, float out) {
61  		super(in,out);
62  		this.vertexFactory = vertexFactory;
63  		this.edgeFactory = edgeFactory;
64  		this.rc = rc;
65  		this.basicTransformer = rc.getMultiLayerTransformer();
66  		loadPlugins();
67  		setModeKeyListener(new ModeKeyAdapter(this));
68  	}
69  
70  	/**
71  	 * create the plugins, and load the plugins for TRANSFORMING mode
72  	 *
73  	 */
74  	@Override
75      protected void loadPlugins() {
76  		pickingPlugin = new PickingGraphMousePlugin<V,E>();
77  		animatedPickingPlugin = new AnimatedPickingGraphMousePlugin<V,E>();
78  		translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK);
79  		scalingPlugin = new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, in, out);
80  		rotatingPlugin = new RotatingGraphMousePlugin();
81  		shearingPlugin = new ShearingGraphMousePlugin();
82  		editingPlugin = new EditingGraphMousePlugin<V,E>(vertexFactory, edgeFactory);
83  		labelEditingPlugin = new LabelEditingGraphMousePlugin<V,E>();
84  		annotatingPlugin = new AnnotatingGraphMousePlugin<V,E>(rc);
85  		popupEditingPlugin = new EditingPopupGraphMousePlugin<V,E>(vertexFactory, edgeFactory);
86  		add(scalingPlugin);
87  		setMode(Mode.EDITING);
88  	}
89  
90  	/**
91  	 * setter for the Mode.
92  	 */
93  	@Override
94      public void setMode(Mode mode) {
95  		if(this.mode != mode) {
96  			fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
97  					this.mode, ItemEvent.DESELECTED));
98  			this.mode = mode;
99  			if(mode == Mode.TRANSFORMING) {
100 				setTransformingMode();
101 			} else if(mode == Mode.PICKING) {
102 				setPickingMode();
103 			} else if(mode == Mode.EDITING) {
104 				setEditingMode();
105 			} else if(mode == Mode.ANNOTATING) {
106 				setAnnotatingMode();
107 			}
108 			if(modeBox != null) {
109 				modeBox.setSelectedItem(mode);
110 			}
111 			fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, mode, ItemEvent.SELECTED));
112 		}
113 	}
114 	
115 	@Override
116     protected void setPickingMode() {
117 		remove(translatingPlugin);
118 		remove(rotatingPlugin);
119 		remove(shearingPlugin);
120 		remove(editingPlugin);
121 		remove(annotatingPlugin);
122 		add(pickingPlugin);
123 		add(animatedPickingPlugin);
124 		add(labelEditingPlugin);
125 		add(popupEditingPlugin);
126 	}
127 
128 	@Override
129     protected void setTransformingMode() {
130 		remove(pickingPlugin);
131 		remove(animatedPickingPlugin);
132 		remove(editingPlugin);
133 		remove(annotatingPlugin);
134 		add(translatingPlugin);
135 		add(rotatingPlugin);
136 		add(shearingPlugin);
137 		add(labelEditingPlugin);
138 		add(popupEditingPlugin);
139 	}
140 
141 	protected void setEditingMode() {
142 		remove(pickingPlugin);
143 		remove(animatedPickingPlugin);
144 		remove(translatingPlugin);
145 		remove(rotatingPlugin);
146 		remove(shearingPlugin);
147 		remove(labelEditingPlugin);
148 		remove(annotatingPlugin);
149 		add(editingPlugin);
150 		add(popupEditingPlugin);
151 	}
152 
153 	protected void setAnnotatingMode() {
154 		remove(pickingPlugin);
155 		remove(animatedPickingPlugin);
156 		remove(translatingPlugin);
157 		remove(rotatingPlugin);
158 		remove(shearingPlugin);
159 		remove(labelEditingPlugin);
160 		remove(editingPlugin);
161 		remove(popupEditingPlugin);
162 		add(annotatingPlugin);
163 	}
164 
165 
166 	/**
167 	 * @return the modeBox.
168 	 */
169 	@Override
170     public JComboBox<Mode> getModeComboBox() {
171 		if(modeBox == null) {
172 			modeBox = new JComboBox<Mode>(
173 				new Mode[]{Mode.TRANSFORMING, Mode.PICKING, Mode.EDITING, Mode.ANNOTATING});
174 			modeBox.addItemListener(getModeListener());
175 		}
176 		modeBox.setSelectedItem(mode);
177 		return modeBox;
178 	}
179 
180 	/**
181 	 * create (if necessary) and return a menu that will change
182 	 * the mode
183 	 * @return the menu
184 	 */
185 	@Override
186     public JMenu getModeMenu() {
187 		if(modeMenu == null) {
188 			modeMenu = new JMenu();// {
189 			Icon icon = BasicIconFactory.getMenuArrowIcon();
190 			modeMenu.setIcon(BasicIconFactory.getMenuArrowIcon());
191 			modeMenu.setPreferredSize(new Dimension(icon.getIconWidth()+10, 
192 					icon.getIconHeight()+10));
193 
194 			final JRadioButtonMenuItem transformingButton = 
195 				new JRadioButtonMenuItem(Mode.TRANSFORMING.toString());
196 			transformingButton.addItemListener(new ItemListener() {
197 				public void itemStateChanged(ItemEvent e) {
198 					if(e.getStateChange() == ItemEvent.SELECTED) {
199 						setMode(Mode.TRANSFORMING);
200 					}
201 				}});
202 
203 			final JRadioButtonMenuItem pickingButton =
204 				new JRadioButtonMenuItem(Mode.PICKING.toString());
205 			pickingButton.addItemListener(new ItemListener() {
206 				public void itemStateChanged(ItemEvent e) {
207 					if(e.getStateChange() == ItemEvent.SELECTED) {
208 						setMode(Mode.PICKING);
209 					}
210 				}});
211 
212 			final JRadioButtonMenuItem editingButton =
213 				new JRadioButtonMenuItem(Mode.EDITING.toString());
214 			editingButton.addItemListener(new ItemListener() {
215 				public void itemStateChanged(ItemEvent e) {
216 					if(e.getStateChange() == ItemEvent.SELECTED) {
217 						setMode(Mode.EDITING);
218 					}
219 				}});
220 
221 			ButtonGroup radio = new ButtonGroup();
222 			radio.add(transformingButton);
223 			radio.add(pickingButton);
224 			radio.add(editingButton);
225 			transformingButton.setSelected(true);
226 			modeMenu.add(transformingButton);
227 			modeMenu.add(pickingButton);
228 			modeMenu.add(editingButton);
229 			modeMenu.setToolTipText("Menu for setting Mouse Mode");
230 			addItemListener(new ItemListener() {
231 				public void itemStateChanged(ItemEvent e) {
232 					if(e.getStateChange() == ItemEvent.SELECTED) {
233 						if(e.getItem() == Mode.TRANSFORMING) {
234 							transformingButton.setSelected(true);
235 						} else if(e.getItem() == Mode.PICKING) {
236 							pickingButton.setSelected(true);
237 						} else if(e.getItem() == Mode.EDITING) {
238 							editingButton.setSelected(true);
239 						}
240 					}
241 				}});
242 		}
243 		return modeMenu;
244 	}
245 	
246     public static class ModeKeyAdapter extends KeyAdapter {
247     	private char t = 't';
248     	private char p = 'p';
249     	private char e = 'e';
250     	private char a = 'a';
251     	protected ModalGraphMouse graphMouse;
252 
253     	public ModeKeyAdapter(ModalGraphMouse graphMouse) {
254 			this.graphMouse = graphMouse;
255 		}
256 
257 		public ModeKeyAdapter(char t, char p, char e, char a, ModalGraphMouse graphMouse) {
258 			this.t = t;
259 			this.p = p;
260 			this.e = e;
261 			this.a = a;
262 			this.graphMouse = graphMouse;
263 		}
264 		
265 		@Override
266         public void keyTyped(KeyEvent event) {
267 			char keyChar = event.getKeyChar();
268 			if(keyChar == t) {
269 				((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
270 				graphMouse.setMode(Mode.TRANSFORMING);
271 			} else if(keyChar == p) {
272 				((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
273 				graphMouse.setMode(Mode.PICKING);
274 			} else if(keyChar == e) {
275 				((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
276 				graphMouse.setMode(Mode.EDITING);
277 			} else if(keyChar == a) {
278 				((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
279 				graphMouse.setMode(Mode.ANNOTATING);
280 			}
281 		}
282     }
283 
284 	/**
285 	 * @return the annotatingPlugin
286 	 */
287 	public AnnotatingGraphMousePlugin<V, E> getAnnotatingPlugin() {
288 		return annotatingPlugin;
289 	}
290 
291 	/**
292 	 * @return the editingPlugin
293 	 */
294 	public EditingGraphMousePlugin<V, E> getEditingPlugin() {
295 		return editingPlugin;
296 	}
297 
298 	/**
299 	 * @return the labelEditingPlugin
300 	 */
301 	public LabelEditingGraphMousePlugin<V, E> getLabelEditingPlugin() {
302 		return labelEditingPlugin;
303 	}
304 
305 	/**
306 	 * @return the popupEditingPlugin
307 	 */
308 	public EditingPopupGraphMousePlugin<V, E> getPopupEditingPlugin() {
309 		return popupEditingPlugin;
310 	}
311 }
312