source: josm/trunk/src/org/openstreetmap/josm/gui/MapFrame.java@ 2646

Last change on this file since 2646 was 2629, checked in by bastiK, 14 years ago

geoimage: usability - allow clicking on the image symbols only when in select mode

  • introduces MapModeChangeListener
  • Property svn:eol-style set to native
File size: 12.4 KB
Line 
1// License: GPL. See LICENSE file for details.
2
3package org.openstreetmap.josm.gui;
4
5import java.awt.BorderLayout;
6import java.awt.Container;
7import java.awt.Dimension;
8import java.awt.event.MouseWheelEvent;
9import java.awt.event.MouseWheelListener;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.List;
13import java.util.concurrent.CopyOnWriteArrayList;
14
15import javax.swing.AbstractButton;
16import javax.swing.Action;
17import javax.swing.BoxLayout;
18import javax.swing.ButtonGroup;
19import javax.swing.JPanel;
20import javax.swing.JSplitPane;
21import javax.swing.JToolBar;
22import javax.swing.border.Border;
23import javax.swing.plaf.basic.BasicSplitPaneDivider;
24import javax.swing.plaf.basic.BasicSplitPaneUI;
25
26import org.openstreetmap.josm.Main;
27import org.openstreetmap.josm.actions.mapmode.DeleteAction;
28import org.openstreetmap.josm.actions.mapmode.DrawAction;
29import org.openstreetmap.josm.actions.mapmode.ExtrudeAction;
30import org.openstreetmap.josm.actions.mapmode.MapMode;
31import org.openstreetmap.josm.actions.mapmode.SelectAction;
32import org.openstreetmap.josm.actions.mapmode.ZoomAction;
33import org.openstreetmap.josm.gui.dialogs.ChangesetDialog;
34import org.openstreetmap.josm.gui.dialogs.CommandStackDialog;
35import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
36import org.openstreetmap.josm.gui.dialogs.DialogsPanel;
37import org.openstreetmap.josm.gui.dialogs.FilterDialog;
38import org.openstreetmap.josm.gui.dialogs.HistoryDialog;
39import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
40import org.openstreetmap.josm.gui.dialogs.PropertiesDialog;
41import org.openstreetmap.josm.gui.dialogs.RelationListDialog;
42import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
43import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
44import org.openstreetmap.josm.gui.dialogs.UserListDialog;
45import org.openstreetmap.josm.tools.Destroyable;
46
47/**
48 * One Map frame with one dataset behind. This is the container gui class whose
49 * display can be set to the different views.
50 *
51 * @author imi
52 */
53public class MapFrame extends JPanel implements Destroyable {
54
55 /**
56 * The current mode, this frame operates.
57 */
58 public MapMode mapMode;
59 /**
60 * The view control displayed.
61 */
62 public MapView mapView;
63 /**
64 * The toolbar with the action icons. To add new toggle dialog actions, use addToggleDialog
65 * instead of adding directly to this list. To add a new mode use addMapMode.
66 */
67 private JToolBar toolBarActions = new JToolBar(JToolBar.VERTICAL);
68 private JToolBar toolBarToggle = new JToolBar(JToolBar.VERTICAL);
69 /**
70 * The status line below the map
71 */
72 public MapStatus statusLine;
73
74 public ConflictDialog conflictDialog;
75 /**
76 * The dialog that shows all relations and lets the user edit them.
77 */
78 public RelationListDialog relationListDialog;
79 /**
80 * The panel list of all toggle dialog icons. To add new toggle dialog actions, use addToggleDialog
81 * instead of adding directly to this list.
82 */
83 private List<ToggleDialog> allDialogs = new ArrayList<ToggleDialog>();
84 private final DialogsPanel dialogsPanel;
85
86 public final ButtonGroup toolGroup = new ButtonGroup();
87
88 /**
89 * Default width of the toggle dialog area.
90 */
91 public final int DEF_TOGGLE_DLG_WIDTH = 330;
92
93 public MapFrame() {
94 setSize(400,400);
95 setLayout(new BorderLayout());
96
97 mapView = new MapView();
98
99 new FileDrop(mapView);
100
101 // show menu entry
102 Main.main.menu.viewMenu.setVisible(true);
103
104 // toolbar
105 toolBarActions.setFloatable(false);
106 addMapMode(new IconToggleButton(new SelectAction(this)));
107 addMapMode(new IconToggleButton(new DrawAction(this)));
108 addMapMode(new IconToggleButton(new ExtrudeAction(this)));
109 addMapMode(new IconToggleButton(new ZoomAction(this)));
110 addMapMode(new IconToggleButton(new DeleteAction(this)));
111
112 toolGroup.setSelected(((AbstractButton)toolBarActions.getComponent(0)).getModel(), true);
113
114 JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
115 dialogsPanel = new DialogsPanel(splitPane);
116 splitPane.setLeftComponent(mapView);
117 splitPane.setRightComponent(dialogsPanel);
118
119 /**
120 * All additional space goes to the mapView
121 */
122 splitPane.setResizeWeight(1.0);
123
124 /**
125 * Some beautifications.
126 */
127 splitPane.setDividerSize(5);
128 splitPane.setBorder(null);
129 splitPane.setUI(new BasicSplitPaneUI() {
130 @Override
131 public BasicSplitPaneDivider createDefaultDivider() {
132 return new BasicSplitPaneDivider(this) {
133 @Override
134 public void setBorder(Border b) {
135 }
136 };
137 }
138 });
139
140 add(splitPane, BorderLayout.CENTER);
141
142 dialogsPanel.setLayout(new BoxLayout(dialogsPanel, BoxLayout.Y_AXIS));
143 dialogsPanel.setPreferredSize(new Dimension(Main.pref.getInteger("toggleDialogs.width",DEF_TOGGLE_DLG_WIDTH), 0));
144
145 dialogsPanel.setMinimumSize(new Dimension(24, 0));
146 mapView.setMinimumSize(new Dimension(10,0));
147
148 toolBarToggle.setFloatable(false);
149 LayerListDialog.createInstance(this);
150 addToggleDialog(LayerListDialog.getInstance());
151 addToggleDialog(new PropertiesDialog(this));
152 addToggleDialog(new HistoryDialog());
153 addToggleDialog(new SelectionListDialog());
154 if(Main.pref.getBoolean("displayfilter", false)) {
155 addToggleDialog(new FilterDialog());
156 }
157 addToggleDialog(new UserListDialog());
158 addToggleDialog(conflictDialog = new ConflictDialog());
159 addToggleDialog(new CommandStackDialog(this));
160 addToggleDialog(relationListDialog = new RelationListDialog());
161 addToggleDialog(new ChangesetDialog(this));
162
163 // status line below the map
164 statusLine = new MapStatus(this);
165 }
166
167 public void selectSelectTool(boolean onlyIfModeless) {
168 if(onlyIfModeless && !Main.pref.getBoolean("modeless", false))
169 return;
170
171 selectMapMode((MapMode)getDefaultButtonAction());
172 }
173
174 public void selectDrawTool(boolean onlyIfModeless) {
175 if(onlyIfModeless && !Main.pref.getBoolean("modeless", false))
176 return;
177
178 Action drawAction = ((AbstractButton)toolBarActions.getComponent(1)).getAction();
179 selectMapMode((MapMode)drawAction);
180 }
181
182 /**
183 * Called as some kind of destructor when the last layer has been removed.
184 * Delegates the call to all Destroyables within this component (e.g. MapModes)
185 */
186 public void destroy() {
187 dialogsPanel.destroy();
188 for (int i = 0; i < toolBarActions.getComponentCount(); ++i)
189 if (toolBarActions.getComponent(i) instanceof Destroyable) {
190 ((Destroyable)toolBarActions).destroy();
191 }
192 for (int i = 0; i < toolBarToggle.getComponentCount(); ++i)
193 if (toolBarToggle.getComponent(i) instanceof Destroyable) {
194 ((Destroyable)toolBarToggle).destroy();
195 }
196
197 // remove menu entries
198 Main.main.menu.viewMenu.setVisible(false);
199
200 // MapFrame gets destroyed when the last layer is removed, but the status line background
201 // thread that collects the information doesn't get destroyed automatically.
202 if(statusLine.thread == null) return;
203 try {
204 statusLine.thread.interrupt();
205 } catch (Exception e) {}
206 }
207
208 public Action getDefaultButtonAction() {
209 return ((AbstractButton)toolBarActions.getComponent(0)).getAction();
210 }
211
212 /**
213 * Open all ToggleDialogs that have their preferences property set. Close all others.
214 */
215 public void initializeDialogsPane() {
216 dialogsPanel.initialize(allDialogs);
217 }
218
219 /**
220 *
221 */
222 public void tearDownDialogsPane() {
223 dialogsPanel.tearDown();
224 }
225
226 /**
227 * Call this to add new toggle dialogs to the left button-list
228 * @param dlg The toggle dialog. It must not be in the list already.
229 */
230 public IconToggleButton addToggleDialog(ToggleDialog dlg) {
231 IconToggleButton button = new IconToggleButton(dlg.getToggleAction());
232 toolBarToggle.add(button);
233 allDialogs.add(dlg);
234 if (dialogsPanel.initialized) {
235 dialogsPanel.add(dlg);
236 }
237 return button;
238 }
239
240 public void addMapMode(IconToggleButton b) {
241 toolBarActions.add(b);
242 toolGroup.add(b);
243 }
244
245 /**
246 * Fires an property changed event "visible".
247 */
248 @Override public void setVisible(boolean aFlag) {
249 boolean old = isVisible();
250 super.setVisible(aFlag);
251 if (old != aFlag) {
252 firePropertyChange("visible", old, aFlag);
253 }
254 }
255
256 /**
257 * Change the operating map mode for the view. Will call unregister on the
258 * old MapMode and register on the new one.
259 * @param mapMode The new mode to set.
260 */
261 public void selectMapMode(MapMode newMapMode) {
262 MapMode oldMapMode = this.mapMode;
263 if (newMapMode == oldMapMode)
264 return;
265 if (oldMapMode != null) {
266 oldMapMode.exitMode();
267 }
268 this.mapMode = newMapMode;
269 newMapMode.enterMode();
270 fireMapModeChanged(oldMapMode, newMapMode);
271 }
272
273 /**
274 * Fill the given panel by adding all necessary components to the different
275 * locations.
276 *
277 * @param panel The container to fill. Must have an BorderLayout.
278 */
279 public void fillPanel(Container panel) {
280 panel.add(this, BorderLayout.CENTER);
281 JToolBar jb = new JToolBar(JToolBar.VERTICAL);
282 jb.setFloatable(false);
283 jb.add(toolBarActions);
284 jb.addSeparator(new Dimension(0,10));
285 jb.add(toolBarToggle);
286 if(Main.pref.getBoolean("sidetoolbar.visible", true))
287 {
288 if(Main.pref.getBoolean("sidetoolbar.scrollable", true)) {
289 final ScrollViewport svp = new ScrollViewport(jb, ScrollViewport.VERTICAL_DIRECTION);
290 panel.add(svp, BorderLayout.WEST);
291 jb.addMouseWheelListener(new MouseWheelListener() {
292 public void mouseWheelMoved(MouseWheelEvent e) {
293 svp.scroll(0,e.getUnitsToScroll() * 5);
294 }
295 });
296 } else {
297 panel.add(jb, BorderLayout.WEST);
298 }
299 }
300 if (statusLine != null && Main.pref.getBoolean("statusline.visible", true)) {
301 panel.add(statusLine, BorderLayout.SOUTH);
302 }
303 }
304
305 /**
306 * Replies the instance of a toggle dialog of type <code>type</code> managed by this
307 * map frame
308 *
309 * @param <T>
310 * @param type the class of the toggle dialog, i.e. UserListDialog.class
311 * @return the instance of a toggle dialog of type <code>type</code> managed by this
312 * map frame; null, if no such dialog exists
313 *
314 */
315 public <T> T getToggleDialog(Class<T> type) {
316 return dialogsPanel.getToggleDialog(type);
317 }
318
319 /**
320 * Returns the current width of the (possibly resized) toggle dialog area
321 */
322 public int getToggleDlgWidth() {
323 return dialogsPanel.getWidth();
324 }
325
326 /**
327 * Interface to notify listeners of the change of the mapMode.
328 */
329 public interface MapModeChangeListener {
330 void mapModeChange(MapMode oldMapMode, MapMode newMapMode);
331 }
332
333 /**
334 * the mapMode listeners
335 */
336 private static final Collection<MapModeChangeListener> mapModeChangeListeners = new CopyOnWriteArrayList<MapModeChangeListener>();
337 /**
338 * Adds a mapMode change listener
339 *
340 * @param listener the listener. Ignored if null or already registered.
341 */
342 public static void addMapModeChangeListener(MapModeChangeListener listener) {
343 if (listener != null && ! mapModeChangeListeners.contains(listener)) {
344 mapModeChangeListeners.add(listener);
345 }
346 }
347 /**
348 * Removes a mapMode change listener
349 *
350 * @param listener the listener. Ignored if null or already registered.
351 */
352 public static void removeMapModeChangeListener(MapModeChangeListener listener) {
353 if (listener != null && mapModeChangeListeners.contains(listener)) {
354 mapModeChangeListeners.remove(listener);
355 }
356 }
357
358 protected static void fireMapModeChanged(MapMode oldMapMode, MapMode newMapMode) {
359 for (MapModeChangeListener l : mapModeChangeListeners) {
360 l.mapModeChange(oldMapMode, newMapMode);
361 }
362 }
363}
Note: See TracBrowser for help on using the repository browser.