/[schmitzm]/trunk/src/skrueger/geotools/MapPaneToolBar.java
ViewVC logotype

Contents of /trunk/src/skrueger/geotools/MapPaneToolBar.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (show annotations)
Fri Apr 17 12:49:33 2009 UTC (15 years, 10 months ago) by alfonx
File size: 22200 byte(s)


1 package skrueger.geotools;
2
3 import java.awt.Dimension;
4 import java.awt.event.ActionEvent;
5 import java.util.ArrayList;
6 import java.util.SortedMap;
7 import java.util.TreeMap;
8
9 import javax.swing.AbstractAction;
10 import javax.swing.AbstractButton;
11 import javax.swing.BorderFactory;
12 import javax.swing.Icon;
13 import javax.swing.ImageIcon;
14 import javax.swing.JButton;
15 import javax.swing.JToggleButton;
16 import javax.swing.JToolBar;
17
18 import org.apache.log4j.Logger;
19
20 import schmitzm.geotools.gui.JMapPane;
21 import schmitzm.geotools.map.event.JMapPaneEvent;
22 import schmitzm.geotools.map.event.JMapPaneListener;
23 import schmitzm.geotools.map.event.MapAreaChangedEvent;
24 import schmitzm.swing.ButtonGroup;
25 import schmitzm.swing.SwingUtil;
26
27 import com.vividsolutions.jts.geom.Envelope;
28
29 /**
30 * A toolbar to controll a {@link JMapPane} (Atlas visualization). This contains two types
31 * of buttons. A group of <i>tools</i> for the mouse actions on the map represented
32 * by {@link JToggleButton JToggleButtons}, where only one tool can be activated
33 * every time. And some (general) <i>actions</i>, represented by normal
34 * {@link JButton JButtons}.
35 * @author <a href="mailto:[email protected]">Martin Schmitz</a> (University of Bonn/Germany)
36 */
37 public class MapPaneToolBar extends JToolBar {
38 private static final Logger LOGGER = Logger.getLogger(MapPaneToolBar.class.getName());
39 /** Constant for the tool "Panning" (10). */
40 public static final int TOOL_PAN = 10;
41 /** Constant for the tool "Zoom In" (30). */
42 public static final int TOOL_ZOOMIN = 30;
43 /** Constant for the tool "Zoom Out" (40). */
44 public static final int TOOL_ZOOMOUT = 40;
45 /** Constant for the tool "Info" (20). */
46 public static final int TOOL_INFO = 20;
47
48 /** Tool currently selected */
49 protected int selectedTool = TOOL_ZOOMIN;
50 /** Holds the tool buttons of the tool bar. */
51 protected SortedMap<Integer, JToggleButton> toolButtons = null;
52 /** Controls that only one tool button is activated. */
53 protected ButtonGroup toolButtonGroup = null;
54 /** Constant for the action "Zoom back" (100). */
55 public static final int ACTION_ZOOM_BACK = 100;
56 /** Constant for the action "Zoom forward" (110). */
57 public static final int ACTION_ZOOM_FORWARD = 110;
58 /** Constant for the action "Search Labels" (120). */
59 public static final int ACTION_SEARCH = 120;
60
61 /** Holds the action buttons of the bar. */
62 protected SortedMap<Integer, JButton> actionButtons = null;
63
64 /** Holds the {@link JMapPane} this tool bar controls. */
65 protected JMapPane mapPane = null;
66
67 /**
68 * A List to remember the last Envelopes that have been watched. Used for
69 * the zoomBack- and zoomForwardButtons *
70 */
71 protected ArrayList<Envelope> lastZooms = new ArrayList<Envelope>();
72 /** Holds the index to the current element in {@link #lastZooms}. */
73 protected int zoomBackIndex = 0;
74
75 /** Listener to sniff the zoom actions on the map. */
76 protected JMapPaneListener mapPaneListener = null;
77
78 protected boolean zoomBackForwardButtonInAction;
79
80 /**
81 * Creates a new toolbar. Notice: This toolbar does nothing
82 * until {@link #setMapPane(JMapPane)} is called!
83 */
84 public MapPaneToolBar() {
85 this(null);
86 }
87
88 /**
89 * Creates a new tool bar.
90 * @param mapPane {@link JMapPane} the tool bar controls
91 */
92 public MapPaneToolBar(JMapPane mapPane) {
93 super("Control the map", JToolBar.HORIZONTAL);
94 this.toolButtons = new TreeMap<Integer,JToggleButton>();
95 this.toolButtonGroup = new ButtonGroup();
96 this.actionButtons = new TreeMap<Integer,JButton>();
97 // Create a Listener to sniff the zooms on the JMapPane
98 this.mapPaneListener = new JMapPaneListener() {
99 public void performMapPaneEvent(JMapPaneEvent e) {
100 if ( !(e instanceof MapAreaChangedEvent) )
101 return;
102
103 if ( zoomBackForwardButtonInAction ) {
104 zoomBackForwardButtonInAction = false;
105 return;
106 }
107
108 Envelope oldMapArea = ((MapAreaChangedEvent)e).getOldMapArea();
109 if (lastZooms.size() == 0 && oldMapArea != null ) {
110 lastZooms.add(oldMapArea);
111 zoomBackIndex = 1;
112 }
113
114 final Envelope mapArea = ((MapAreaChangedEvent)e).getNewMapArea();
115 if (mapArea == null)
116 return;
117
118 if (lastZooms.size() > 0 && mapArea.equals(lastZooms.get(lastZooms.size() - 1))) {
119 // LOGGER.debug("MapAreaChangedEvent ausgelassen bei der Zaehlung der Zoomschritt weil identisch");
120 return;
121 }
122
123 if (lastZooms.size() > 0)
124 while (zoomBackIndex < lastZooms.size())
125 lastZooms.remove(lastZooms.size() - 1);
126
127 lastZooms.add(mapArea);
128 zoomBackIndex = lastZooms.size();
129 setButtonEnabled(ACTION_ZOOM_BACK, lastZooms.size() > 1);
130 setButtonEnabled(ACTION_ZOOM_FORWARD, false);
131 }
132 };
133
134 setMapPane(mapPane);
135 setFloatable(false);
136 setRollover(true);
137
138 init();
139 }
140
141 /**
142 * Sets the {@link JMapPane} controlled by this tool bar.
143 * @param mapPane {@link JMapPane} to control (if {@code null} this
144 * tool bar controls NOTHING!)
145 */
146 public void setMapPane(JMapPane mapPane) {
147 // Remove listener from old MapPane
148 if ( this.mapPane != null )
149 this.mapPane.removeMapPaneListener( mapPaneListener );
150 this.mapPane = mapPane;
151 if ( this.mapPane != null && mapPaneListener != null )
152 this.mapPane.addMapPaneListener( mapPaneListener );
153 }
154
155 /**
156 * Calls {@link #initTools()} and {@link #initActions()} and then puts
157 * all tool buttons and all actions buttons to the tool bar.
158 */
159 protected void init() {
160 initTools();
161 initActions();
162 initToolBar();
163 }
164
165
166 /**
167 * Creates the tool buttons, adds them to {@link #toolButtons} and finally
168 * creates a button group for all tools. So sub-classes which override this
169 * method should FIRST add their new tool buttons to {@link #toolButtons}
170 * before calling {@code super.initTools()}.
171 */
172 protected void initTools() {
173 // Panning
174 addTool( new MapPaneToolBarAction(
175 TOOL_PAN,
176 this,
177 "",
178 new ImageIcon(MapView.class.getResource("pan.png"))
179 ), false );
180 // Info
181 addTool( new MapPaneToolBarAction(
182 TOOL_INFO,
183 this,
184 "",
185 new ImageIcon(MapView.class.getResource("info.png"))
186 ), false );
187 // Zoom in
188 addTool( new MapPaneToolBarAction(
189 TOOL_ZOOMIN,
190 this,
191 "",
192 new ImageIcon(MapView.class.getResource("zoom_in.png"))
193 ), false );
194 // Zoom out
195 addTool( new MapPaneToolBarAction(
196 TOOL_ZOOMOUT,
197 this,
198 "",
199 new ImageIcon(MapView.class.getResource("zoom_out.png"))
200 ), false );
201
202 // set the selected tool enabled
203 setSelectedTool(selectedTool);
204
205 }
206
207 /**
208 * Creates the action buttons and adds them to {@link #actionButtons}.
209 */
210 protected void initActions() {
211 // Action button to revert the last zoom
212 addAction( new MapPaneToolBarAction(
213 ACTION_ZOOM_BACK,
214 this,
215 "",
216 new ImageIcon(MapView.class.getResource("zoom_back.png"))
217 ), false);
218 setButtonEnabled( ACTION_ZOOM_BACK, false );
219
220 // Action button to redo the last zoom
221 addAction( new MapPaneToolBarAction(
222 ACTION_ZOOM_FORWARD,
223 this,
224 "",
225 new ImageIcon(MapView.class.getResource("zoom_forward.png"))
226 ), false);
227 setButtonEnabled( ACTION_ZOOM_FORWARD, false );
228
229 }
230
231 /**
232 * Clears the GUI of all components and adds all tool and action buttons to the
233 * tool bar.
234 */
235 protected void initToolBar() {
236 setAlignmentY( 1f );
237 removeAll();
238 // Separator to the left of the tool actions to start
239 // the tool buttons with the map (not with the coordinate grid)
240 Dimension dimension = new Dimension( 49,10);
241 addSeparator(dimension);
242 // Tool buttons
243 for (JToggleButton b : toolButtons.values())
244 add(b);
245 // Space between tool buttons and action buttons
246 Dimension dimension2 = new Dimension( 10,10);
247 this.addSeparator(dimension2);
248 // Action buttons
249 for (JButton b : actionButtons.values())
250 add(b);
251 }
252
253 /**
254 * Performs the activation of a tool.
255 * @param tool the tool to activate
256 * @param e the event of the button
257 */
258 public void performToolButton(int tool, ActionEvent e) {
259 if ( mapPane == null )
260 return;
261
262 selectedTool = tool;
263
264 switch( tool ) {
265 case TOOL_PAN:
266 // Set the mouse tool to "Panning"
267 mapPane.setWindowSelectionState(JMapPane.NONE);
268 mapPane.setState(JMapPane.PAN);
269 mapPane.setHighlight(false);
270 mapPane.setNormalCursor(SwingUtil.PAN_CURSOR);
271 break;
272 case TOOL_INFO:
273 // Set the mouse tool to "Info"
274 mapPane.setWindowSelectionState(JMapPane.NONE);
275 mapPane.setState(JMapPane.SELECT_TOP);
276 mapPane.setHighlight(true);
277 mapPane.setNormalCursor(SwingUtil.CROSSHAIR_CURSOR);
278 break;
279 case TOOL_ZOOMIN:
280 // Set the mouse tool to "Zoom in"
281 mapPane.setWindowSelectionState(JMapPane.ZOOM_IN);
282 mapPane.setState(JMapPane.ZOOM_IN);
283 mapPane.setHighlight(false);
284 mapPane.setNormalCursor(SwingUtil.ZOOMIN_CURSOR);
285 break;
286 case TOOL_ZOOMOUT:
287 // Set the mouse tool to "Zoom out"
288 mapPane.setWindowSelectionState(JMapPane.NONE);
289 mapPane.setState(JMapPane.ZOOM_OUT);
290 mapPane.setHighlight(false);
291 mapPane.setNormalCursor(SwingUtil.ZOOMOUT_CURSOR);
292 break;
293 default:
294 // Set map actions to default
295 mapPane.setWindowSelectionState(JMapPane.NONE);
296 mapPane.setState(JMapPane.NONE);
297 mapPane.setHighlight(false);
298 mapPane.setNormalCursor(null);
299 break;
300 }
301 mapPane.updateCursor();
302 }
303
304 /**
305 * Performs the action of an action button.
306 * @param tool the action
307 * @param e the event of the button
308 */
309 protected void performActionButton(int action, ActionEvent e) {
310 if ( mapPane == null )
311 return;
312
313 // Perform the action "Zoom back": Revert the last zoom
314 if ( action == ACTION_ZOOM_BACK ) {
315 if (zoomBackIndex <= 1)
316 return;
317
318 zoomBackForwardButtonInAction = true;
319 zoomBackIndex--;
320 getButton(ACTION_ZOOM_FORWARD).setEnabled(true);
321 getButton(ACTION_ZOOM_BACK).setEnabled( zoomBackIndex > 1 );
322
323 mapPane.setMapArea( lastZooms.get(zoomBackIndex-1) );
324 mapPane.refresh();
325 }
326
327 // Perform the action "Zoom forward": Redo the last zoom
328 if ( action == ACTION_ZOOM_FORWARD ) {
329 if (zoomBackIndex < lastZooms.size()) {
330 zoomBackForwardButtonInAction = true;
331 zoomBackIndex++;
332 getButton(ACTION_ZOOM_BACK).setEnabled(true);
333 getButton(ACTION_ZOOM_FORWARD).setEnabled(zoomBackIndex < lastZooms.size());
334
335 mapPane.setMapArea( lastZooms.get(zoomBackIndex-1) );
336 mapPane.refresh();
337 }
338 }
339 }
340
341
342 /**
343 * Adds a tool to the tool bar. Does nothing if a tool or action with the
344 * specified ID already exists!
345 * @param buttonAction action for the toggle button
346 * @param resetToolBar indicates whether the toolbar GUI is reset after adding
347 * the button (if adding several actions it useful only to
348 * reset the GUI for the last added tool)
349 */
350 public void addTool(MapPaneToolBarAction buttonAction, boolean resetToolBar) {
351 if ( isButtonIDUsed(buttonAction.getID()) ) {
352 LOGGER.warn("addTool(.) ignored because ID already used for tool or action: "+buttonAction.getID());
353 return;
354 }
355 JToggleButton button = new JToggleButton(buttonAction);
356 button.setBorder( BorderFactory.createRaisedBevelBorder() );
357 toolButtonGroup.add(button);
358 toolButtons.put(buttonAction.getID(), button);
359 if ( resetToolBar )
360 initToolBar();
361 }
362
363 /**
364 * Adds a tool to the tool bar and resets the toolbar GUI.
365 * @param buttonAction action for the toggle button
366 */
367 public void addTool(MapPaneToolBarAction buttonAction) {
368 addTool(buttonAction, true);
369 }
370
371 /**
372 * Adds an action to the tool bar. Does nothing if a tool or action with the
373 * specified ID already exists!
374 * @param buttonAction action for the button
375 * @param resetToolBar indicates whether the toolbar GUI is reset after adding
376 * the button (if adding several actions it useful only to
377 * reset the GUI for the last added tool)
378 */
379 public void addAction(MapPaneToolBarAction buttonAction, boolean resetToolBar) {
380 if ( isButtonIDUsed(buttonAction.getID()) ) {
381 LOGGER.warn("addAction(.) ignored because ID already used for tool or action: "+buttonAction.getID());
382 return;
383 }
384 JButton button = new JButton(buttonAction);
385 actionButtons.put( buttonAction.getID(), button );
386 if ( resetToolBar )
387 initToolBar();
388 }
389
390 /**
391 * Adds an action to the tool bar and resets the toolbar GUI.
392 * @param buttonAction action for the toggle button
393 */
394 public void addAction(MapPaneToolBarAction buttonAction) {
395 addAction(buttonAction, true);
396 }
397
398 /**
399 * Returns the button for a specific tool or action.
400 * @param id the constant for a tool
401 * @return a {@link JButton} if {@code id} specifies an {@linkplain #getActionButton(int) action button}
402 * or {@link JToogleButton} if {@code id} specifies a {@linkplain #getToolButton(int) tool button}
403 */
404 public AbstractButton getButton(int id) {
405 AbstractButton button = toolButtons.get(id);
406 if ( button == null )
407 button = actionButtons.get(id);
408 if ( button == null )
409 LOGGER.warn("Unknown tool or action ID: "+id);
410 return button;
411 }
412
413 /**
414 * Returns the button for a specific tool.
415 * @param tool the constant for a tool
416 */
417 public JToggleButton getToolButton(int tool) {
418 AbstractButton button = getButton(tool);
419 if ( button != null && !(button instanceof JToggleButton) ) {
420 LOGGER.warn("ID specifies no tool: "+tool);
421 button = null;
422 }
423 return (JToggleButton)button;
424 }
425
426 /**
427 * Returns the button for a specific action.
428 * @param action the constant an action
429 */
430 public JButton getActionButton(int action) {
431 AbstractButton button = getButton(action);
432 if ( button != null && !(button instanceof JButton) ) {
433 LOGGER.warn("ID specifies no action: "+action);
434 button = null;
435 }
436 return (JButton)button;
437
438 }
439
440 /**
441 * Sets the selected tool.
442 * @param tool ID of the tool
443 */
444 public void setSelectedTool(Integer tool) {
445 if ( tool == null )
446 toolButtonGroup.setUnselected();
447
448 JToggleButton button = getToolButton(tool);
449 if ( button == null )
450 return;
451 button.setSelected( true );
452 button.getAction().actionPerformed(null);
453 }
454
455 /**
456 * Returns the selected tool.
457 * @return -1 if no tool is active
458 */
459 public int getSelectedTool() {
460 if ( toolButtonGroup.getSelectedButton() == null )
461 return -1;
462 return selectedTool;
463 }
464
465 /**
466 * Sets whether a tool or action is activated or not. The visible property
467 * of the button is not affected.
468 * @param id tool or actionID
469 * @param enabled if {@code true} the tool becomes available
470 */
471 public void setButtonEnabled(int id, boolean enabled) {
472 AbstractButton button = getButton(id);
473 if ( button == null )
474 return;
475 button.setEnabled( enabled );
476 }
477
478 /**
479 * Sets whether a tool or action is activated or not.
480 * @param id tool or actionID
481 * @param enabled if {@code true} the tool becomes available
482 * @param hideOnDisable if {@code true} the button is also hidden if
483 * {@code enabled} is {@code false}
484 */
485 public void setButtonEnabled(int id, boolean enabled, boolean hideOnDisable) {
486 AbstractButton button = getButton(id);
487 if ( button == null )
488 return;
489 button.setEnabled( enabled );
490 // if button is enabled, it becomes visible anyway
491 // if button is disabled and the "hide" option is set, it is also hidden
492 if ( enabled )
493 button.setVisible( true );
494 else
495 button.setVisible( !hideOnDisable );
496 }
497
498 /**
499 * Checks whether a ID is already used for a tool or action.
500 * @param tool tool ID
501 */
502 public boolean isButtonIDUsed(int id) {
503 return toolButtons.get(id) != null || actionButtons.get(id) != null;
504 }
505
506 /**
507 * Checks whether a tool is activated.
508 * @param tool tool ID
509 * @return {@code false} if an unknown ID is specified
510 */
511 public boolean isButtonEnabled(int id) {
512 AbstractButton button = getButton(id);
513 if ( button != null )
514 return button.isEnabled();
515 return false;
516 }
517
518 /**
519 * Sets the activation for all tools.
520 * @param enabled if {@code true} all tools becomes available
521 * @param hideOnDisable if {@code true} the buttons are also hidden if
522 * {@code enabled} is {@code false}
523 */
524 public void setAllToolsEnabled(boolean enabled, boolean hideOnDisable) {
525 for (int tool : toolButtons.keySet())
526 setButtonEnabled(tool,enabled,hideOnDisable);
527 }
528
529 /**
530 * Sets the activation for all actions.
531 * @param enabled if {@code true} all actions becomes available
532 * @param hideOnDisable if {@code true} the buttons are also hidden if
533 * {@code enabled} is {@code false}
534 */
535 public void setAllActionsEnabled(boolean enabled, boolean hideOnDisable) {
536 for (int tool : actionButtons.keySet())
537 setButtonEnabled(tool,enabled,hideOnDisable);
538 }
539
540 /**
541 * Returns the maximum ID of tools.
542 */
543 public int getMaxToolID() {
544 return toolButtons.lastKey();
545 }
546
547 /**
548 * Returns the minimum ID of tools.
549 */
550 public int getMinToolID() {
551 return toolButtons.firstKey();
552 }
553
554 /**
555 * Returns the maximum ID of actions.
556 */
557 public int getMaxActionID() {
558 return actionButtons.lastKey();
559 }
560
561 /**
562 * Returns the minimum ID of actions.
563 */
564 public int getMinActionID() {
565 return actionButtons.firstKey();
566 }
567
568 /**
569 * Extends the {@link AbstractAction} with maintaining an ID and
570 * the {@link MapPaneToolBar} the actions controls.
571 * Additionally this class automatically calls {@link MapPaneToolBar#performToolButton(int, ActionEvent)}
572 * or {@link MapPaneToolBar#performActionButton(int, ActionEvent)}
573 * depending on whether the action is added via {@link MapPaneToolBar#addTool(MapPaneToolBarAction)}
574 * or {@link MapPaneToolBar#addAction(MapPaneToolBarAction)}.
575 * @author <a href="mailto:[email protected]">Martin Schmitz</a> (University of Bonn/Germany)
576 */
577 public static class MapPaneToolBarAction extends AbstractAction {
578 /** The ID of the action */
579 protected int id = -1;
580 /** The tool bar, this action is made for. */
581 protected MapPaneToolBar toolBar = null;
582
583 /**
584 * Creates a new action with a dummy description and no icon.
585 * @param id unique ID for the action
586 * @param toolBar toolbar this action is made for
587 */
588 public MapPaneToolBarAction(int id, MapPaneToolBar toolBar) {
589 this(id,toolBar,""+id);
590 }
591
592 /**
593 * Creates a new action without an icon.
594 * @param id unique ID for the action
595 * @param toolBar toolbar this action is made for
596 * @param name description used for buttons or menus
597 */
598 public MapPaneToolBarAction(int id, MapPaneToolBar toolBar, String name) {
599 this(id,toolBar,name,null);
600 }
601
602 /**
603 * Creates a new action.
604 * @param id unique ID for the action
605 * @param toolBar toolbar this action is made for
606 * @param name description used for buttons or menus
607 * @param icon icon used for buttons or menus
608 */
609 public MapPaneToolBarAction(int id, MapPaneToolBar toolBar, String name, Icon icon) {
610 super(name,icon);
611 this.id = id;
612 this.toolBar = toolBar;
613 }
614
615 /**
616 * Calls {@link MapPaneToolBar#performToolButton(int, ActionEvent)}
617 * or {@link MapPaneToolBar#performActionButton(int, ActionEvent)}
618 * depending on whether the action is added to the toolbar via
619 * {@link MapPaneToolBar#addTool(MapPaneToolBarAction)}
620 * or {@link MapPaneToolBar#addAction(MapPaneToolBarAction)}.
621 */
622 public void actionPerformed(ActionEvent e) {
623 if ( toolBar.toolButtons.get(id) != null )
624 toolBar.performToolButton(id, e);
625 if ( toolBar.actionButtons.get(id) != null )
626 toolBar.performActionButton(id, e);
627 }
628
629 /**
630 * Returns the (unique) id of this action.
631 * @return
632 */
633 public int getID() {
634 return id;
635 }
636 }
637 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26