source: josm/trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java@ 1922

Last change on this file since 1922 was 1902, checked in by Gubaer, 15 years ago

temporary fix for #3181: Dialogs causes JOSM window to be set as "always on top", preventing switchiong to other windows.

File size: 7.7 KB
Line 
1package org.openstreetmap.josm.gui;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.Component;
6import java.awt.Dimension;
7import java.awt.GridBagLayout;
8import java.awt.Toolkit;
9import java.awt.event.ActionEvent;
10import java.util.ArrayList;
11
12import javax.swing.AbstractAction;
13import javax.swing.Action;
14import javax.swing.JButton;
15import javax.swing.JComponent;
16import javax.swing.JDialog;
17import javax.swing.JOptionPane;
18import javax.swing.JPanel;
19import javax.swing.JScrollBar;
20import javax.swing.JScrollPane;
21import javax.swing.KeyStroke;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.tools.GBC;
25import org.openstreetmap.josm.tools.ImageProvider;
26
27
28public class ExtendedDialog extends JDialog {
29 private int result = 0;
30 private Component parent;
31 private final String[] bTexts;
32
33 // For easy access when inherited
34 protected Object contentConstraints = GBC.eol().anchor(GBC.CENTER).fill(GBC.HORIZONTAL).insets(5,10,5,0);
35 protected ArrayList<JButton> buttons = new ArrayList<JButton>();
36
37 /**
38 * Sets up the dialog. The first button is always the default.
39 * @param parent The parent element that will be used for position and maximum size
40 * @param title The text that will be shown in the window titlebar
41 * @param content Any component that should be show above the buttons (e.g. JLabel)
42 * @param buttonTexts The labels that will be displayed on the buttons
43 * @param buttonIcons The path to the icons that will be displayed on the buttons. Path is relative to JOSM's image directory. File extensions need to be included. If a button should not have an icon pass null.
44 */
45 public ExtendedDialog(Component parent, String title, Component content, String[] buttonTexts, String[] buttonIcons) {
46 super(JOptionPane.getFrameForComponent(parent), title, true);
47 this.parent = parent;
48 bTexts = buttonTexts;
49 setupDialog(content, buttonIcons);
50 setVisible(true);
51 }
52
53 public ExtendedDialog(Component parent, String title, Component content, String[] buttonTexts) {
54 this(parent, title, content, buttonTexts, null);
55 }
56
57 /**
58 * Sets up the dialog and displays the given message in a breakable label
59 */
60 public ExtendedDialog(Component parent, String title, String message, String[] buttonTexts, String[] buttonIcons) {
61 super(JOptionPane.getFrameForComponent(parent), title, true);
62
63 JMultilineLabel lbl = new JMultilineLabel(message);
64 // Make it not wider than 2/3 of the screen
65 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
66 lbl.setMaxWidth(Math.round(screenSize.width*2/3));
67
68 bTexts = buttonTexts;
69 setupDialog(lbl, buttonIcons);
70 setVisible(true);
71 }
72
73 public ExtendedDialog(Component parent, String title, String message, String[] buttonTexts) {
74 this(parent, title, message, buttonTexts, null);
75 }
76
77 /**
78 * Constructor that doesn't make the dialog visible immediately. Intended for when inheriting.
79 */
80 public ExtendedDialog(Component parent, String title, String[] buttonTexts, boolean modal) {
81 super(JOptionPane.getFrameForComponent(parent), title, modal);
82 bTexts = buttonTexts;
83 }
84
85 protected void setupDialog(Component content, String[] buttonIcons) {
86 setupEscListener();
87
88 JButton button;
89 JPanel buttonsPanel = new JPanel(new GridBagLayout());
90
91 for(int i=0; i < bTexts.length; i++) {
92 Action action = new AbstractAction(bTexts[i]) {
93 public void actionPerformed(ActionEvent evt) {
94 buttonAction(evt);
95 }
96 };
97
98 button = new JButton(action);
99 if(buttonIcons != null && buttonIcons[i] != null) {
100 button.setIcon(ImageProvider.get(buttonIcons[i]));
101 }
102
103 if(i == 0) {
104 rootPane.setDefaultButton(button);
105 }
106 buttonsPanel.add(button, GBC.std().insets(2,2,2,2));
107 buttons.add(button);
108 }
109
110 JPanel cp = new JPanel(new GridBagLayout());
111 cp.add(content, contentConstraints);
112 cp.add(buttonsPanel, GBC.eol().anchor(GBC.CENTER).insets(5,5,5,5));
113
114 JScrollPane pane = new JScrollPane(cp);
115 pane.setBorder(null);
116 setContentPane(pane);
117
118 pack();
119
120 // Try to make it not larger than the parent window or at least not larger than 2/3 of the screen
121 Dimension d = getSize();
122 Dimension x = findMaxDialogSize();
123
124 boolean limitedInWidth = d.width > x.width;
125 boolean limitedInHeight = d.height > x.height;
126
127 if(x.width > 0 && d.width > x.width) {
128 d.width = x.width;
129 }
130 if(x.height > 0 && d.height > x.height) {
131 d.height = x.height;
132 }
133
134 // We have a vertical scrollbar and enough space to prevent a horizontal one
135 if(!limitedInWidth && limitedInHeight) {
136 d.width += new JScrollBar().getPreferredSize().width;
137 }
138
139 setSize(d);
140 setLocationRelativeTo(parent);
141
142 // temporary fix for "#3181 : Dialogs causes JOSM window to be set as "always on top", preventing switchiong to
143 // other windows."
144 // See also {@see OptionPaneUtil}
145 //
146 if (Main.pref.getBoolean("window-handling.option-pane-always-on-top", true)) {
147 // try to put always on top
148 //
149 try {
150 setAlwaysOnTop(true);
151 } catch(SecurityException e) {
152 System.out.println(tr("Warning: failed to bring extended dialog always on top. Exception: {0}", e.toString()));
153 }
154 }
155 }
156
157 /**
158 * @return int The selected button. The count starts with 1.
159 * A return value of 0 means the dialog has been closed otherwise.
160 */
161 public int getValue() {
162 return result;
163 }
164
165 /**
166 * This gets performed whenever a button is clicked or activated
167 * @param evt the button event
168 */
169 protected void buttonAction(ActionEvent evt) {
170 String a = evt.getActionCommand();
171 for(int i=0; i < bTexts.length; i++)
172 if(bTexts[i].equals(a)) {
173 result = i+1;
174 break;
175 }
176
177 setVisible(false);
178 }
179
180 /**
181 * Tries to find a good value of how large the dialog should be
182 * @return Dimension Size of the parent Component or 2/3 of screen size if not available
183 */
184 protected Dimension findMaxDialogSize() {
185 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
186 Dimension x = new Dimension(Math.round(screenSize.width*2/3),
187 Math.round(screenSize.height*2/3));
188 try {
189 if(parent != null) {
190 x = JOptionPane.getFrameForComponent(parent).getSize();
191 }
192 } catch(NullPointerException e) { }
193 return x;
194 }
195
196 /**
197 * Makes the dialog listen to ESC keypressed
198 */
199 private void setupEscListener() {
200 Action actionListener = new AbstractAction() {
201 public void actionPerformed(ActionEvent actionEvent) {
202 // 0 means that the dialog has been closed otherwise.
203 // We need to set it to zero again, in case the dialog has been re-used
204 // and the result differs from its default value
205 result = 0;
206 setVisible(false);
207 }
208 };
209
210 rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
211 .put(KeyStroke.getKeyStroke("ESCAPE"), "ESCAPE");
212 rootPane.getActionMap().put("ESCAPE", actionListener);
213 }
214
215 @Override
216 public void setVisible(boolean visible) {
217 super.setVisible(visible);
218 if (visible) {
219 toFront();
220 }
221 }
222}
Note: See TracBrowser for help on using the repository browser.