source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationDialogManager.java@ 1930

Last change on this file since 1930 was 1857, checked in by Gubaer, 15 years ago

replaced JOptionDialog.show... by OptionPaneUtil.show....
improved relation editor

File size: 10.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import java.awt.Dimension;
5import java.awt.Point;
6import java.awt.Toolkit;
7import java.awt.event.WindowAdapter;
8import java.awt.event.WindowEvent;
9import java.util.HashMap;
10import java.util.Iterator;
11import java.util.Map.Entry;
12
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.gui.layer.Layer;
15import org.openstreetmap.josm.gui.layer.OsmDataLayer;
16import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
17
18
19/**
20 * RelationDialogManager keeps track of the open relation editors.
21 *
22 */
23public class RelationDialogManager extends WindowAdapter implements LayerChangeListener{
24
25 /** keeps track of open relation editors */
26 static RelationDialogManager relationDialogManager;
27
28 /**
29 * Replies the singleton {@see RelationDialogManager}
30 *
31 * @return the singleton {@see RelationDialogManager}
32 */
33 static public RelationDialogManager getRelationDialogManager() {
34 if (RelationDialogManager.relationDialogManager == null) {
35 RelationDialogManager.relationDialogManager = new RelationDialogManager();
36 Layer.listeners.add(RelationDialogManager.relationDialogManager);
37 }
38 return RelationDialogManager.relationDialogManager;
39 }
40
41 /**
42 * Helper class for keeping the context of a relation editor. A relation editor
43 * is open for a specific relation managed by a specific {@see OsmDataLayer}
44 *
45 */
46 static private class DialogContext {
47 public Relation relation;
48 public OsmDataLayer layer;
49
50 public DialogContext(OsmDataLayer layer, Relation relation) {
51 this.layer = layer;
52 this.relation = relation;
53 }
54
55 @Override
56 public int hashCode() {
57 final int prime = 31;
58 int result = 1;
59 result = prime * result + ((layer == null) ? 0 : layer.hashCode());
60 result = prime * result + ((relation == null) ? 0 : relation.hashCode());
61 return result;
62 }
63 @Override
64 public boolean equals(Object obj) {
65 if (this == obj)
66 return true;
67 if (obj == null)
68 return false;
69 if (getClass() != obj.getClass())
70 return false;
71 DialogContext other = (DialogContext) obj;
72 if (layer == null) {
73 if (other.layer != null)
74 return false;
75 } else if (!layer.equals(other.layer))
76 return false;
77 if (relation == null) {
78 if (other.relation != null)
79 return false;
80 } else if (!relation.equals(other.relation))
81 return false;
82 return true;
83 }
84
85 public boolean matchesLayer(OsmDataLayer layer) {
86 if (layer == null) return false;
87 return this.layer.equals(layer);
88 }
89
90 @Override
91 public String toString() {
92 return "[Context: layer=" + layer.getName() + ",relation=" + relation.id + "]";
93 }
94 }
95
96 /** the map of open dialogs */
97 private HashMap<DialogContext, RelationEditor> openDialogs;
98
99 /**
100 * constructor
101 */
102 public RelationDialogManager(){
103 openDialogs = new HashMap<DialogContext, RelationEditor>();
104 }
105
106 /**
107 * Register the relation editor for a relation managed by a
108 * {@see OsmDataLayer}.
109 *
110 * @param layer the layer
111 * @param relation the relation
112 * @param editor the editor
113 */
114 public void register(OsmDataLayer layer, Relation relation, RelationEditor editor) {
115 if (relation == null) {
116 relation = new Relation();
117 }
118 DialogContext context = new DialogContext(layer, relation);
119 openDialogs.put(context, editor);
120 editor.addWindowListener(this);
121 }
122
123 public void updateContext(OsmDataLayer layer, Relation relation, RelationEditor editor) {
124 // lookup the entry for editor and remove it
125 //
126 for (DialogContext context: openDialogs.keySet()) {
127 if (openDialogs.get(context) == editor) {
128 openDialogs.remove(context);
129 break;
130 }
131 }
132 // don't add a window listener. Editor is already known to the relation dialog manager
133 //
134 DialogContext context = new DialogContext(layer, relation);
135 openDialogs.put(context, editor);
136 }
137
138 /**
139 * Closes the editor open for a specific layer and a specific relation.
140 *
141 * @param layer the layer
142 * @param relation the relation
143 */
144 public void close(OsmDataLayer layer, Relation relation) {
145 DialogContext context = new DialogContext(layer, relation);
146 RelationEditor editor = openDialogs.get(context);
147 if (editor != null) {
148 editor.setVisible(false);
149 }
150 }
151
152 /**
153 * Replies true if there is an open relation editor for the relation managed
154 * by the given layer. Replies false if relation is null.
155 *
156 * @param layer the layer
157 * @param relation the relation. May be null.
158 * @return true if there is an open relation editor for the relation managed
159 * by the given layer; false otherwise
160 */
161 public boolean isOpenInEditor(OsmDataLayer layer, Relation relation) {
162 if (relation == null) return false;
163 DialogContext context = new DialogContext(layer, relation);
164 return openDialogs.keySet().contains(context);
165
166 }
167
168 /**
169 * Replies the editor for the relation managed by layer. Null, if no such editor
170 * is currently open. Returns null, if relation is null.
171 *
172 * @param layer the layer
173 * @param relation the relation
174 * @return the editor for the relation managed by layer. Null, if no such editor
175 * is currently open.
176 *
177 * @see #isOpenInEditor(OsmDataLayer, Relation)
178 */
179 public RelationEditor getEditorForRelation(OsmDataLayer layer, Relation relation) {
180 if (relation == null) return null;
181 DialogContext context = new DialogContext(layer, relation);
182 return openDialogs.get(context);
183 }
184
185 /**
186 * called when a layer is removed
187 *
188 */
189 public void layerRemoved(Layer oldLayer) {
190 if (oldLayer == null || ! (oldLayer instanceof OsmDataLayer))
191 return;
192 OsmDataLayer dataLayer = (OsmDataLayer)oldLayer;
193
194 Iterator<Entry<DialogContext,RelationEditor>> it = openDialogs.entrySet().iterator();
195 while(it.hasNext()) {
196 Entry<DialogContext,RelationEditor> entry = it.next();
197 if (entry.getKey().matchesLayer(dataLayer)) {
198 RelationEditor editor = entry.getValue();
199 it.remove();
200 editor.setVisible(false);
201 editor.dispose();
202 }
203 }
204 }
205
206 public void activeLayerChange(Layer oldLayer, Layer newLayer) {
207 // do nothing
208 }
209
210 public void layerAdded(Layer newLayer) {
211 // do nothing
212 }
213
214 @Override
215 public void windowClosed(WindowEvent e) {
216 RelationEditor editor = (RelationEditor)e.getWindow();
217 DialogContext context = null;
218 for (DialogContext c : openDialogs.keySet()) {
219 if (openDialogs.get(c).equals(editor)) {
220 context = c;
221 break;
222 }
223 }
224 if (context != null) {
225 openDialogs.remove(context);
226 }
227 }
228
229 /**
230 * Positions an {@see RelationEditor} centered on the screen
231 *
232 * @param editor the editor
233 */
234 protected void centerOnScreen(RelationEditor editor) {
235 Point p = new Point(0,0);
236 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
237 p.x = (d.width - editor.getSize().width)/2;
238 p.y = (d.height - editor.getSize().height)/2;
239 p.x = Math.max(p.x,0);
240 p.y = Math.max(p.y,0);
241 editor.setLocation(p);
242 }
243
244 /**
245 * Replies true, if there is another open {@see RelationEditor} whose
246 * upper left corner is close to <code>p</code>.
247 *
248 * @param p the reference point to check
249 * @return true, if there is another open {@see RelationEditor} whose
250 * upper left corner is close to <code>p</code>.
251 */
252 protected boolean hasEditorWithCloseUpperLeftCorner(Point p) {
253 for (RelationEditor editor: openDialogs.values()) {
254 Point corner = editor.getLocation();
255 if (p.x >= corner.x -5 && corner.x + 5 >= p.x
256 && p.y >= corner.y -5 && corner.y + 5 >= p.y)
257 return true;
258 }
259 return false;
260 }
261
262 /**
263 * Positions a {@see RelationEditor} close to the center of the screen, in such
264 * a way, that it doesn't entirely cover another {@see RelationEditor}
265 *
266 * @param editor
267 */
268 protected void positionCloseToScreenCenter(RelationEditor editor) {
269 Point p = new Point(0,0);
270 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
271 p.x = (d.width - editor.getSize().width)/2;
272 p.y = (d.height - editor.getSize().height)/2;
273 p.x = Math.max(p.x,0);
274 p.y = Math.max(p.y,0);
275 while(hasEditorWithCloseUpperLeftCorner(p)) {
276 p.x += 20;
277 p.y += 20;
278 }
279 editor.setLocation(p);
280 }
281
282 /**
283 * Positions a {@see RelationEditor} on the screen. Tries to center it on the
284 * screen. If it hide another instance of an editor at the same position this
285 * method tries to reposition <code>editor</code> by moving it slightly down and
286 * slightly to the right.
287 *
288 * @param editor the editor
289 */
290 public void positionOnScreen(RelationEditor editor) {
291 if (editor == null) return;
292 if (openDialogs.isEmpty()) {
293 centerOnScreen(editor);
294 } else {
295 positionCloseToScreenCenter(editor);
296 }
297 }
298
299}
Note: See TracBrowser for help on using the repository browser.