source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java@ 2019

Last change on this file since 2019 was 2010, checked in by Gubaer, 15 years ago

added getter isDialogShowing()

  • Property svn:eol-style set to native
File size: 15.4 KB
Line 
1package org.openstreetmap.josm.gui.dialogs;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.BorderLayout;
6import java.awt.Component;
7import java.awt.Dimension;
8import java.awt.EventQueue;
9import java.awt.GridBagLayout;
10import java.awt.Image;
11import java.awt.event.ActionEvent;
12import java.awt.event.ActionListener;
13import java.awt.event.ComponentAdapter;
14import java.awt.event.ComponentEvent;
15import java.awt.event.MouseAdapter;
16import java.awt.event.MouseEvent;
17import java.awt.event.WindowAdapter;
18import java.awt.event.WindowEvent;
19import java.util.logging.Logger;
20
21import javax.swing.AbstractAction;
22import javax.swing.BorderFactory;
23import javax.swing.Box;
24import javax.swing.ImageIcon;
25import javax.swing.JButton;
26import javax.swing.JDialog;
27import javax.swing.JLabel;
28import javax.swing.JOptionPane;
29import javax.swing.JPanel;
30
31import org.openstreetmap.josm.Main;
32import org.openstreetmap.josm.actions.JosmAction;
33import org.openstreetmap.josm.actions.HelpAction.Helpful;
34import org.openstreetmap.josm.tools.GBC;
35import org.openstreetmap.josm.tools.ImageProvider;
36import org.openstreetmap.josm.tools.Shortcut;
37
38/**
39 * This class is a toggle dialog that can be turned on and off.
40 *
41 *
42 */
43public class ToggleDialog extends JPanel implements Helpful {
44 private static final Logger logger = Logger.getLogger(ToggleDialog.class.getName());
45
46 /**
47 * The action to toggle the visibility state of this toggle dialog.
48 *
49 * Emits {@see PropertyChangeEvent}s for the property <tt>selected</tt>:
50 * <ul>
51 * <li>true, if the dialog is currently visible</li>
52 * <li>false, if the dialog is currently invisible</li>
53 * </ul>
54 *
55 */
56 public final class ToggleDialogAction extends JosmAction {
57 private ToggleDialogAction(String name, String iconName, String tooltip, Shortcut shortcut, String prefname) {
58 super(name, iconName, tooltip, shortcut, false);
59 }
60
61 public void actionPerformed(ActionEvent e) {
62 toggleVisibility();
63 }
64
65 public void toggleVisibility() {
66 if (isShowing) {
67 hideDialog();
68 } else {
69 showDialog();
70 }
71 }
72 }
73
74 /**
75 * The action to toggle this dialog.
76 */
77 private ToggleDialogAction toggleAction;
78 private String preferencePrefix;
79
80 private JPanel parent;
81 private TitleBar titleBar;
82 private String title;
83
84 /** indicates whether the dialog is currently minimized or not */
85 private boolean collapsed;
86 /** indicates whether the dialog is docked or not */
87 private boolean docked;
88 /** indicates whether the dialog is showing or not */
89 private boolean isShowing;
90
91 /** the preferred height if the toggle dialog is expanded */
92 private int preferredHeight;
93 /** the label in the title bar which shows whether the toggle dialog is expanded or collapsed */
94 private JLabel lblMinimized;
95 /** the JDialog displaying the toggle dialog as undocked dialog */
96 private JDialog detachedDialog;
97
98
99 /**
100 * Constructor
101 *
102 * @param name the name of the dialog
103 * @param iconName the name of the icon to be displayed
104 * @param tooltip the tool tip
105 * @param shortcut the shortcut
106 * @param preferredHeight the preferred height for the dialog
107 */
108 public ToggleDialog(String name, String iconName, String tooltip, Shortcut shortcut, int preferredHeight) {
109 super(new BorderLayout());
110 this.preferencePrefix = iconName;
111 init(name, iconName, tooltip, shortcut, preferredHeight);
112 }
113
114 /**
115 * Sets the visibility of all components in this toggle dialog, except the title bar
116 *
117 * @param visible true, if the components should be visible; false otherwise
118 */
119 protected void setContentVisible(boolean visible) {
120 Component comps[] = getComponents();
121 for(int i=0; i<comps.length; i++) {
122 if(comps[i] != titleBar) {
123 comps[i].setVisible(visible);
124 }
125 }
126 }
127
128 /**
129 * Initializes the toggle dialog
130 *
131 * @param name
132 * @param iconName
133 * @param tooltip
134 * @param shortcut
135 * @param preferredHeight
136 */
137 private void init(String name, String iconName, String tooltip, Shortcut shortcut, final int preferredHeight) {
138 setPreferredSize(new Dimension(330,preferredHeight));
139 toggleAction = new ToggleDialogAction(name, "dialogs/"+iconName, tooltip, shortcut, iconName);
140 String helpId = "Dialog/"+getClass().getName().substring(getClass().getName().lastIndexOf('.')+1);
141 toggleAction.putValue("help", helpId.substring(0, helpId.length()-6));
142
143 setLayout(new BorderLayout());
144
145 // show the minimize button
146 lblMinimized = new JLabel(ImageProvider.get("misc", "normal"));
147 titleBar = new TitleBar(name, iconName);
148 add(titleBar, BorderLayout.NORTH);
149
150 setVisible(false);
151 setBorder(BorderFactory.createEtchedBorder());
152
153 docked = Main.pref.getBoolean(preferencePrefix+".docked", true);
154 if (!docked) {
155 EventQueue.invokeLater(new Runnable(){
156 public void run() {
157 detach();
158 }
159 });
160 }
161 collapsed = Main.pref.getBoolean(preferencePrefix+".minimized", false);
162 if (collapsed) {
163 EventQueue.invokeLater(new Runnable(){
164 public void run() {
165 collapse();
166 }
167 });
168 }
169 }
170
171 /**
172 * Collapses the toggle dialog to the title bar only
173 *
174 */
175 protected void collapse() {
176 setContentVisible(false);
177 this.collapsed = true;
178 Main.pref.put(preferencePrefix+".minimized", true);
179 setPreferredSize(new Dimension(330,20));
180 setMaximumSize(new Dimension(330,20));
181 lblMinimized.setIcon(ImageProvider.get("misc", "minimized"));
182 refreshToggleDialogsView();
183 }
184
185 /**
186 * Expands the toggle dialog
187 */
188 protected void expand() {
189 setContentVisible(true);
190 this.collapsed = false;
191 Main.pref.put(preferencePrefix+".minimized", false);
192 setPreferredSize(new Dimension(330,preferredHeight));
193 setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
194 lblMinimized.setIcon(ImageProvider.get("misc", "normal"));
195 refreshToggleDialogsView();
196 }
197
198 /**
199 * Replies the index of this toggle dialog in the view of
200 * toggle dialog.
201 *
202 * @return
203 */
204 protected int getDialogPosition() {
205 for (int i=0; i< parent.getComponentCount(); i++) {
206 String name = parent.getComponent(i).getName();
207 if (name != null && name.equals(this.getName()))
208 return i;
209 }
210 return -1;
211 }
212
213 /**
214 * Displays the toggle dialog in the toggle dialog view on the right
215 * of the main map window.
216 *
217 */
218 protected void dock() {
219 detachedDialog = null;
220
221 // check whether the toggle dialog view contains a placeholder
222 // for this toggle dialog. If so, replace it with this dialog.
223 //
224 int idx = getDialogPosition();
225 if (idx > -1) {
226 parent.remove(idx);
227 parent.add(ToggleDialog.this,idx);
228 } else {
229 parent.add(ToggleDialog.this);
230 }
231
232 if(Main.pref.getBoolean(preferencePrefix+".visible")) {
233 setVisible(true);
234 } else {
235 setVisible(false);
236 }
237 titleBar.setVisible(true);
238 collapsed = Main.pref.getBoolean(preferencePrefix+".minimized", false);
239 if (collapsed) {
240 collapse();
241 } else {
242 expand();
243 }
244 docked = true;
245 Main.pref.put(preferencePrefix+".docked", docked);
246 }
247
248 /**
249 * Display the dialog in a detached window.
250 *
251 */
252 protected void detach() {
253 setContentVisible(true);
254 setVisible(true);
255
256 // replace the toggle dialog by an invisible place holder. Makes sure
257 // we can place the toggle dialog where it was when it becomes docked
258 // again.
259 //
260 if (parent != null) {
261 int idx = getDialogPosition();
262 if (idx > -1) {
263 JPanel placeHolder = new JPanel();
264 placeHolder.setName(this.getName());
265 placeHolder.setVisible(false);
266 parent.add(placeHolder,idx);
267 }
268 parent.remove(ToggleDialog.this);
269 }
270
271 titleBar.setVisible(false);
272 detachedDialog = new DetachedDialog();
273 detachedDialog.setVisible(true);
274 refreshToggleDialogsView();
275 docked = false;
276 Main.pref.put(preferencePrefix+".docked", docked);
277 }
278
279 /**
280 * Hides the dialog
281 */
282 public void hideDialog() {
283 if (!isShowing) return;
284 if (detachedDialog != null) {
285 detachedDialog.setVisible(false);
286 detachedDialog.getContentPane().removeAll();
287 detachedDialog.dispose();
288 }
289 setVisible(false);
290 isShowing = false;
291 refreshToggleDialogsView();
292 toggleAction.putValue("selected", false);
293 }
294
295 /**
296 * Replies true if this dialog is showing either as docked or as detached dialog
297 */
298 public boolean isDialogShowing() {
299 return this.isShowing;
300 }
301
302 /**
303 * Shows the dialog
304 */
305 public void showDialog() {
306 if (isShowing) return;
307 if (!docked) {
308 detach();
309 } else if (!collapsed) {
310 expand();
311 setVisible(true);
312 refreshToggleDialogsView();
313 } else {
314 setVisible(true);
315 refreshToggleDialogsView();
316 }
317 isShowing = true;
318 toggleAction.putValue("selected", true);
319 }
320
321 /**
322 * Toggles between collapsed and expanded state
323 *
324 */
325 protected void toggleExpandedState() {
326 if (this.collapsed) {
327 expand();
328 } else {
329 collapse();
330 }
331 }
332
333 /**
334 * Refreshes the layout of the parent toggle dialog view
335 *
336 */
337 protected void refreshToggleDialogsView() {
338 if(parent != null){
339 parent.validate();
340 }
341 }
342
343 /**
344 * Closes the the detached dialog if this toggle dialog is currently displayed
345 * in a detached dialog.
346 *
347 */
348 public void closeDetachedDialog() {
349 if (detachedDialog != null) {
350 detachedDialog.setVisible(false);
351 }
352 }
353
354 public String helpTopic() {
355 String help = getClass().getName();
356 help = help.substring(help.lastIndexOf('.')+1, help.length()-6);
357 return "Dialog/"+help;
358 }
359
360 /**
361 * Replies the action to toggle the visible state of this toggle dialog
362 *
363 * @return the action to toggle the visible state of this toggle dialog
364 */
365 public AbstractAction getToggleAction() {
366 return toggleAction;
367 }
368
369 /**
370 * Replies the prefix for the preference settings of this dialog.
371 *
372 * @return the prefix for the preference settings of this dialog.
373 */
374 public String getPreferencePrefix() {
375 return preferencePrefix;
376 }
377
378 /**
379 * Sets the parent displaying all toggle dialogs
380 *
381 * @param parent the parent
382 */
383 public void setParent(JPanel parent) {
384 this.parent = parent;
385 }
386
387 /**
388 * Replies the name of this toggle dialog
389 */
390 @Override
391 public String getName() {
392 return "toggleDialog." + preferencePrefix;
393 }
394
395 /**
396 * Sets the title
397 *
398 * @param title the title
399 */
400 public void setTitle(String title) {
401 titleBar.setTitle(title);
402 }
403
404 /**
405 * The title bar displayed in docked mode
406 *
407 */
408 private class TitleBar extends JPanel {
409 private JLabel leftPart;
410
411 public TitleBar(String toggleDialogName, String iconName) {
412 setLayout(new GridBagLayout());
413 lblMinimized = new JLabel(ImageProvider.get("misc", "normal"));
414 add(lblMinimized);
415
416 // scale down the dialog icon
417 ImageIcon inIcon = ImageProvider.get("dialogs", iconName);
418 ImageIcon smallIcon = new ImageIcon(inIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
419 leftPart = new JLabel("",smallIcon, JLabel.TRAILING);
420 leftPart.setIconTextGap(8);
421 add(leftPart, GBC.std());
422 add(Box.createHorizontalGlue(),GBC.std().fill(GBC.HORIZONTAL));
423 addMouseListener(
424 new MouseAdapter() {
425 @Override
426 public void mouseClicked(MouseEvent e) {
427 toggleExpandedState();
428 }
429 }
430 );
431
432 // show the sticky button
433 JButton sticky = new JButton(ImageProvider.get("misc", "sticky"));
434 sticky.setToolTipText(tr("Undock the panel"));
435 sticky.setBorder(BorderFactory.createEmptyBorder());
436 sticky.addActionListener(
437 new ActionListener(){
438 public void actionPerformed(ActionEvent e) {
439 detach();
440 }
441 }
442 );
443 add(sticky);
444
445 // show the close button
446 JButton close = new JButton(ImageProvider.get("misc", "close"));
447 close.setToolTipText(tr("Close this panel. You can reopen it with the buttons in the left toolbar."));
448 close.setBorder(BorderFactory.createEmptyBorder());
449 close.addActionListener(
450 new ActionListener(){
451 public void actionPerformed(ActionEvent e) {
452 hideDialog();
453 }
454 }
455 );
456 add(close);
457 setToolTipText(tr("Click to minimize/maximize the panel content"));
458 setTitle(toggleDialogName);
459 }
460
461 public void setTitle(String title) {
462 leftPart.setText(title);
463 }
464
465 public String getTitle() {
466 return leftPart.getText();
467 }
468 }
469
470 /**
471 * The dialog class used to display toggle dialogs in a detached window.
472 *
473 */
474 private class DetachedDialog extends JDialog {
475 public DetachedDialog() {
476 super(JOptionPane.getFrameForComponent(Main.parent),false /* not modal*/);
477 getContentPane().add(ToggleDialog.this);
478 addWindowListener(new WindowAdapter(){
479 @Override public void windowClosing(WindowEvent e) {
480 getContentPane().removeAll();
481 dispose();
482 dock();
483 }
484 });
485 addComponentListener(new ComponentAdapter(){
486 @Override public void componentMoved(ComponentEvent e) {
487 rememberGeometry();
488 }
489 });
490 String bounds = Main.pref.get(preferencePrefix+".bounds",null);
491 if (bounds != null) {
492 String[] b = bounds.split(",");
493 setBounds(Integer.parseInt(b[0]),Integer.parseInt(b[1]),Integer.parseInt(b[2]),Integer.parseInt(b[3]));
494 } else {
495 pack();
496 }
497 setTitle(titleBar.getTitle());
498 }
499
500 protected void rememberGeometry() {
501 Main.pref.put(preferencePrefix+".bounds", detachedDialog.getX()+","+detachedDialog.getY()+","+detachedDialog.getWidth()+","+detachedDialog.getHeight());
502 }
503 }
504}
Note: See TracBrowser for help on using the repository browser.