source: josm/trunk/src/org/openstreetmap/josm/tools/WindowGeometry.java@ 4571

Last change on this file since 4571 was 4571, checked in by Don-vip, 13 years ago

fix #6343 - Relation windows don't remember their last position

  • Property svn:eol-style set to native
File size: 9.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.Dimension;
8import java.awt.GraphicsConfiguration;
9import java.awt.GraphicsDevice;
10import java.awt.GraphicsEnvironment;
11import java.awt.Point;
12import java.awt.Rectangle;
13import java.awt.Toolkit;
14import java.awt.Window;
15import java.util.regex.Matcher;
16import java.util.regex.Pattern;
17
18import org.openstreetmap.josm.Main;
19
20/**
21 * This is a helper class for persisting the geometry of a JOSM window to the preference store
22 * and for restoring it from the preference store.
23 *
24 */
25public class WindowGeometry {
26
27 /**
28 * Replies a window geometry object for a window with a specific size which is
29 * centered on screen
30 *
31 * @param extent the size
32 * @return the geometry object
33 */
34 static public WindowGeometry centerOnScreen(Dimension extent) {
35 Point topLeft = new Point(
36 Math.max(0, (Toolkit.getDefaultToolkit().getScreenSize().width - extent.width) /2),
37 Math.max(0, (Toolkit.getDefaultToolkit().getScreenSize().height - extent.height) /2)
38 );
39 return new WindowGeometry(topLeft, extent);
40 }
41
42 /**
43 * Replies a window geometry object for a window with a specific size which is centered
44 * relative to the parent window of a reference component.
45 *
46 * @param reference the reference component.
47 * @param extent the size
48 * @return the geometry object
49 */
50 static public WindowGeometry centerInWindow(Component reference, Dimension extent) {
51 Window parentWindow = null;
52 while(reference != null && ! (reference instanceof Window) ) {
53 reference = reference.getParent();
54 }
55 if (reference == null)
56 return new WindowGeometry(new Point(0,0), extent);
57 parentWindow = (Window)reference;
58 Point topLeft = new Point(
59 Math.max(0, (parentWindow.getSize().width - extent.width) /2),
60 Math.max(0, (parentWindow.getSize().height - extent.height) /2)
61 );
62 topLeft.x += parentWindow.getLocation().x;
63 topLeft.y += parentWindow.getLocation().y;
64 return new WindowGeometry(topLeft, extent);
65 }
66
67 /**
68 * Exception thrown by the WindowGeometry class if something goes wrong
69 *
70 */
71 static public class WindowGeometryException extends Exception {
72 public WindowGeometryException(String message, Throwable cause) {
73 super(message, cause);
74 }
75
76 public WindowGeometryException(String message) {
77 super(message);
78 }
79 }
80
81 /** the top left point */
82 private Point topLeft;
83 /** the size */
84 private Dimension extent;
85
86 /**
87 *
88 * @param topLeft the top left point
89 * @param extent the extent
90 */
91 public WindowGeometry(Point topLeft, Dimension extent) {
92 this.topLeft = topLeft;
93 this.extent = extent;
94 }
95
96 /**
97 * Creates a window geometry from the position and the size of a window.
98 *
99 * @param window the window
100 */
101 public WindowGeometry(Window window) {
102 this(window.getLocationOnScreen(), window.getSize());
103 }
104
105 protected int parseField(String preferenceKey, String preferenceValue, String field) throws WindowGeometryException {
106 String v = "";
107 try {
108 Pattern p = Pattern.compile(field + "=(-?\\d+)",Pattern.CASE_INSENSITIVE);
109 Matcher m = p.matcher(preferenceValue);
110 if (!m.find())
111 throw new WindowGeometryException(tr("Preference with key ''{0}'' does not include ''{1}''. Cannot restore window geometry from preferences.", preferenceKey, field));
112 v = m.group(1);
113 return Integer.parseInt(v);
114 } catch(WindowGeometryException e) {
115 throw e;
116 } catch(NumberFormatException e) {
117 throw new WindowGeometryException(tr("Preference with key ''{0}'' does not provide an int value for ''{1}''. Got {2}. Cannot restore window geometry from preferences.", preferenceKey, field, v));
118 } catch(Exception e) {
119 throw new WindowGeometryException(tr("Failed to parse field ''{1}'' in preference with key ''{0}''. Exception was: {2}. Cannot restore window geometry from preferences.", preferenceKey, field, e.toString()), e);
120 }
121 }
122
123 protected void initFromPreferences(String preferenceKey) throws WindowGeometryException {
124 String value = Main.pref.get(preferenceKey);
125 if (value == null || value.equals(""))
126 throw new WindowGeometryException(tr("Preference with key ''{0}'' does not exist. Cannot restore window geometry from preferences.", preferenceKey));
127 topLeft = new Point();
128 extent = new Dimension();
129 topLeft.x = parseField(preferenceKey, value, "x");
130 topLeft.y = parseField(preferenceKey, value, "y");
131 extent.width = parseField(preferenceKey, value, "width");
132 extent.height = parseField(preferenceKey, value, "height");
133 }
134
135 protected void initFromWindowGeometry(WindowGeometry other) {
136 this.topLeft = other.topLeft;
137 this.extent = other.extent;
138 }
139
140 /**
141 * Creates a window geometry from the values kept in the preference store under the
142 * key <code>preferenceKey</code>
143 *
144 * @param preferenceKey the preference key
145 * @throws WindowGeometryException thrown if no such key exist or if the preference value has
146 * an illegal format
147 */
148 public WindowGeometry(String preferenceKey) throws WindowGeometryException {
149 initFromPreferences(preferenceKey);
150 }
151
152 /**
153 * Creates a window geometry from the values kept in the preference store under the
154 * key <code>preferenceKey</code>. Falls back to the <code>defaultGeometry</code> if
155 * something goes wrong.
156 *
157 * @param preferenceKey the preference key
158 * @param defaultGeometry the default geometry
159 *
160 */
161 public WindowGeometry(String preferenceKey, WindowGeometry defaultGeometry) {
162 try {
163 initFromPreferences(preferenceKey);
164 } catch(WindowGeometryException e) {
165 // System.out.println(tr("Warning: Failed to restore window geometry from key ''{0}''. Falling back to default geometry. Details: {1}", preferenceKey, e.getMessage()));
166 initFromWindowGeometry(defaultGeometry);
167 }
168 }
169
170 /**
171 * Remembers a window geometry under a specific preference key
172 *
173 * @param preferenceKey the preference key
174 */
175 public void remember(String preferenceKey) {
176 StringBuffer value = new StringBuffer();
177 value.append("x=").append(topLeft.x).append(",")
178 .append("y=").append(topLeft.y).append(",")
179 .append("width=").append(extent.width).append(",")
180 .append("height=").append(extent.height);
181 Main.pref.put(preferenceKey, value.toString());
182 }
183
184 /**
185 * Replies the top left point for the geometry
186 *
187 * @return the top left point for the geometry
188 */
189 public Point getTopLeft() {
190 return topLeft;
191 }
192
193 /**
194 * Replies the size spezified by the geometry
195 *
196 * @return the size spezified by the geometry
197 */
198 public Dimension getSize() {
199 return extent;
200 }
201
202 /**
203 * Applies this geometry to a window
204 *
205 * @param window the window
206 */
207 public void apply(Window window) {
208 window.setLocation(topLeft);
209 window.setSize(extent);
210 }
211
212 /**
213 * Applies this geometry to a window. Makes sure that the window is not placed outside
214 * of the coordinate range of the current screen.
215 *
216 * @param window the window
217 */
218 public void applySafe(Window window) {
219 Point p = new Point(topLeft);
220 if (p.x < 0 || p.x > Toolkit.getDefaultToolkit().getScreenSize().width - 10) {
221 p.x = 0;
222 }
223 if (p.y < 0 || p.y > Toolkit.getDefaultToolkit().getScreenSize().height - 10) {
224 p.y = 0;
225 }
226 window.setLocation(p);
227 window.setSize(extent);
228 }
229
230 /**
231 * Applies this geometry to a window. Makes sure that the window is not
232 * placed outside of the coordinate range of all available screens.
233 *
234 * @param window the window
235 */
236 public void applySafeMultiScreen(Window window) {
237 Point p = new Point(topLeft);
238
239 Rectangle virtualBounds = new Rectangle();
240 GraphicsEnvironment ge = GraphicsEnvironment
241 .getLocalGraphicsEnvironment();
242 GraphicsDevice[] gs = ge.getScreenDevices();
243 for (int j = 0; j < gs.length; j++) {
244 GraphicsDevice gd = gs[j];
245 GraphicsConfiguration[] gc = gd.getConfigurations();
246 for (int i = 0; i < gc.length; i++) {
247 virtualBounds = virtualBounds.union(gc[i].getBounds());
248 }
249 }
250
251 if (p.x < virtualBounds.x) {
252 p.x = virtualBounds.x;
253 } else if (p.x > virtualBounds.x + virtualBounds.width - extent.width) {
254 p.x = virtualBounds.x + virtualBounds.width - extent.width;
255 }
256
257 if (p.y < virtualBounds.y) {
258 p.y = virtualBounds.y;
259 } else if (p.y > virtualBounds.y + virtualBounds.height - extent.height) {
260 p.y = virtualBounds.y + virtualBounds.height - extent.height;
261 }
262
263 window.setLocation(p);
264 window.setSize(extent);
265 }
266}
Note: See TracBrowser for help on using the repository browser.