source: josm/trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java@ 6767

Last change on this file since 6767 was 6666, checked in by Don-vip, 10 years ago

see #9508 - refactor validator preferences + handling of JScrollPane policies ("vertical as needed" / "horizontal as needed" are default policies)

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.util;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BasicStroke;
7import java.awt.Component;
8import java.awt.Container;
9import java.awt.Dialog;
10import java.awt.Dimension;
11import java.awt.Font;
12import java.awt.GraphicsEnvironment;
13import java.awt.Image;
14import java.awt.Stroke;
15import java.awt.Toolkit;
16import java.awt.Window;
17import java.awt.event.ActionListener;
18import java.awt.event.HierarchyEvent;
19import java.awt.event.HierarchyListener;
20import java.awt.image.FilteredImageSource;
21import java.lang.reflect.InvocationTargetException;
22import java.util.Arrays;
23import java.util.List;
24
25import javax.swing.GrayFilter;
26import javax.swing.Icon;
27import javax.swing.ImageIcon;
28import javax.swing.JOptionPane;
29import javax.swing.JScrollPane;
30import javax.swing.SwingUtilities;
31import javax.swing.Timer;
32
33import org.openstreetmap.josm.Main;
34import org.openstreetmap.josm.gui.ExtendedDialog;
35import org.openstreetmap.josm.tools.ImageProvider;
36
37/**
38 * basic gui utils
39 */
40public final class GuiHelper {
41
42 private GuiHelper() {
43 // Hide default constructor for utils classes
44 }
45
46 /**
47 * disable / enable a component and all its child components
48 */
49 public static void setEnabledRec(Container root, boolean enabled) {
50 root.setEnabled(enabled);
51 Component[] children = root.getComponents();
52 for (Component child : children) {
53 if(child instanceof Container) {
54 setEnabledRec((Container) child, enabled);
55 } else {
56 child.setEnabled(enabled);
57 }
58 }
59 }
60
61 public static void executeByMainWorkerInEDT(final Runnable task) {
62 Main.worker.submit(new Runnable() {
63 @Override
64 public void run() {
65 runInEDTAndWait(task);
66 }
67 });
68 }
69
70 public static void runInEDT(Runnable task) {
71 if (SwingUtilities.isEventDispatchThread()) {
72 task.run();
73 } else {
74 SwingUtilities.invokeLater(task);
75 }
76 }
77
78 public static void runInEDTAndWait(Runnable task) {
79 if (SwingUtilities.isEventDispatchThread()) {
80 task.run();
81 } else {
82 try {
83 SwingUtilities.invokeAndWait(task);
84 } catch (InterruptedException e) {
85 Main.error(e);
86 } catch (InvocationTargetException e) {
87 Main.error(e);
88 }
89 }
90 }
91
92 /**
93 * returns true if the user wants to cancel, false if they
94 * want to continue
95 */
96 public static final boolean warnUser(String title, String content, ImageIcon baseActionIcon, String continueToolTip) {
97 ExtendedDialog dlg = new ExtendedDialog(Main.parent,
98 title, new String[] {tr("Cancel"), tr("Continue")});
99 dlg.setContent(content);
100 dlg.setButtonIcons(new Icon[] {
101 ImageProvider.get("cancel"),
102 ImageProvider.overlay(
103 ImageProvider.get("upload"),
104 new ImageIcon(ImageProvider.get("warning-small").getImage().getScaledInstance(10 , 10, Image.SCALE_SMOOTH)),
105 ImageProvider.OverlayPosition.SOUTHEAST)});
106 dlg.setToolTipTexts(new String[] {
107 tr("Cancel"),
108 continueToolTip});
109 dlg.setIcon(JOptionPane.WARNING_MESSAGE);
110 dlg.setCancelButton(1);
111 return dlg.showDialog().getValue() != 2;
112 }
113
114 /**
115 * Replies the disabled (grayed) version of the specified image.
116 * @param image The image to disable
117 * @return The disabled (grayed) version of the specified image, brightened by 20%.
118 * @since 5484
119 */
120 public static final Image getDisabledImage(Image image) {
121 return Toolkit.getDefaultToolkit().createImage(
122 new FilteredImageSource(image.getSource(), new GrayFilter(true, 20)));
123 }
124
125 /**
126 * Replies the disabled (grayed) version of the specified icon.
127 * @param icon The icon to disable
128 * @return The disabled (grayed) version of the specified icon, brightened by 20%.
129 * @since 5484
130 */
131 public static final ImageIcon getDisabledIcon(ImageIcon icon) {
132 return new ImageIcon(getDisabledImage(icon.getImage()));
133 }
134
135 /**
136 * Attaches a {@code HierarchyListener} to the specified {@code Component} that
137 * will set its parent dialog resizeable. Use it before a call to JOptionPane#showXXXXDialog
138 * to make it resizeable.
139 * @param pane The component that will be displayed
140 * @param minDimension The minimum dimension that will be set for the dialog. Ignored if null
141 * @return {@code pane}
142 * @since 5493
143 */
144 public static final Component prepareResizeableOptionPane(final Component pane, final Dimension minDimension) {
145 if (pane != null) {
146 pane.addHierarchyListener(new HierarchyListener() {
147 @Override
148 public void hierarchyChanged(HierarchyEvent e) {
149 Window window = SwingUtilities.getWindowAncestor(pane);
150 if (window instanceof Dialog) {
151 Dialog dialog = (Dialog)window;
152 if (!dialog.isResizable()) {
153 dialog.setResizable(true);
154 if (minDimension != null) {
155 dialog.setMinimumSize(minDimension);
156 }
157 }
158 }
159 }
160 });
161 }
162 return pane;
163 }
164
165 /**
166 * Schedules a new Timer to be run in the future (once or several times).
167 * @param initialDelay milliseconds for the initial and between-event delay if repeatable
168 * @param actionListener an initial listener; can be null
169 * @param repeats specify false to make the timer stop after sending its first action event
170 * @return The (started) timer.
171 * @since 5735
172 */
173 public static final Timer scheduleTimer(int initialDelay, ActionListener actionListener, boolean repeats) {
174 Timer timer = new Timer(initialDelay, actionListener);
175 timer.setRepeats(repeats);
176 timer.start();
177 return timer;
178 }
179
180 /**
181 * Return s new BasicStroke object with given thickness and style
182 * @param code = 3.5 -> thickness=3.5px; 3.5 10 5 -> thickness=3.5px, dashed: 10px filled + 5px empty
183 * @return stroke for drawing
184 */
185 public static Stroke getCustomizedStroke(String code) {
186 String[] s = code.trim().split("[^\\.0-9]+");
187
188 if (s.length==0) return new BasicStroke();
189 float w;
190 try {
191 w = Float.parseFloat(s[0]);
192 } catch (NumberFormatException ex) {
193 w = 1.0f;
194 }
195 if (s.length>1) {
196 float[] dash= new float[s.length-1];
197 float sumAbs = 0;
198 try {
199 for (int i=0; i<s.length-1; i++) {
200 dash[i] = Float.parseFloat(s[i+1]);
201 sumAbs += Math.abs(dash[i]);
202 }
203 } catch (NumberFormatException ex) {
204 Main.error("Error in stroke preference format: "+code);
205 dash = new float[]{5.0f};
206 }
207 if (sumAbs < 1e-1) {
208 Main.error("Error in stroke dash fomat (all zeros): "+code);
209 return new BasicStroke(w);
210 }
211 // dashed stroke
212 return new BasicStroke(w, BasicStroke.CAP_BUTT,
213 BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);
214 } else {
215 if (w>1) {
216 // thick stroke
217 return new BasicStroke(w, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
218 } else {
219 // thin stroke
220 return new BasicStroke(w);
221 }
222 }
223 }
224
225 /**
226 * Gets the font used to display JOSM title in about dialog and splash screen.
227 * @return By order or priority, the first font available in local fonts:
228 * 1. Helvetica Bold 20
229 * 2. Calibri Bold 23
230 * 3. Arial Bold 20
231 * 4. SansSerif Bold 20
232 * @since 5797
233 */
234 public static Font getTitleFont() {
235 List<String> fonts = Arrays.asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
236 // Helvetica is the preferred choice but is not available by default on Windows
237 // (http://www.microsoft.com/typography/fonts/product.aspx?pid=161)
238 if (fonts.contains("Helvetica")) {
239 return new Font("Helvetica", Font.BOLD, 20);
240 // Calibri is the default Windows font since Windows Vista but is not available on older versions of Windows, where Arial is preferred
241 } else if (fonts.contains("Calibri")) {
242 return new Font("Calibri", Font.BOLD, 23);
243 } else if (fonts.contains("Arial")) {
244 return new Font("Arial", Font.BOLD, 20);
245 // No luck, nothing found, fallback to one of the 5 fonts provided with Java (Serif, SansSerif, Monospaced, Dialog, and DialogInput)
246 } else {
247 return new Font("SansSerif", Font.BOLD, 20);
248 }
249 }
250
251 /**
252 * Embeds the given component into a new vertical-only scrollable {@code JScrollPane}.
253 * @param panel The component to embed
254 * @return the vertical scrollable {@code JScrollPane}
255 * @since 6666
256 */
257 public static JScrollPane embedInVerticalScrollPane(Component panel) {
258 return new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
259 }
260}
Note: See TracBrowser for help on using the repository browser.