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

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

fix #8428 - Always show buttons for legacy setting .buttonhiding=false + constructors javadoc

  • Property svn:eol-style set to native
File size: 32.2 KB
Line 
1// License: GPL. See LICENSE file for details.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.AWTEvent;
7import java.awt.BorderLayout;
8import java.awt.Component;
9import java.awt.Container;
10import java.awt.Dimension;
11import java.awt.FlowLayout;
12import java.awt.Graphics;
13import java.awt.GridBagLayout;
14import java.awt.GridLayout;
15import java.awt.Image;
16import java.awt.Rectangle;
17import java.awt.Toolkit;
18import java.awt.event.AWTEventListener;
19import java.awt.event.ActionEvent;
20import java.awt.event.ActionListener;
21import java.awt.event.ComponentAdapter;
22import java.awt.event.ComponentEvent;
23import java.awt.event.MouseAdapter;
24import java.awt.event.MouseEvent;
25import java.awt.event.WindowAdapter;
26import java.awt.event.WindowEvent;
27import java.beans.PropertyChangeEvent;
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.Collection;
31import java.util.LinkedList;
32import java.util.List;
33
34import javax.swing.AbstractAction;
35import javax.swing.BorderFactory;
36import javax.swing.ImageIcon;
37import javax.swing.JButton;
38import javax.swing.JCheckBoxMenuItem;
39import javax.swing.JComponent;
40import javax.swing.JDialog;
41import javax.swing.JLabel;
42import javax.swing.JMenu;
43import javax.swing.JOptionPane;
44import javax.swing.JPanel;
45import javax.swing.JPopupMenu;
46import javax.swing.JRadioButtonMenuItem;
47import javax.swing.JScrollPane;
48import javax.swing.JToggleButton;
49
50import org.openstreetmap.josm.Main;
51import org.openstreetmap.josm.actions.JosmAction;
52import org.openstreetmap.josm.data.preferences.ParametrizedEnumProperty;
53import org.openstreetmap.josm.gui.MainMenu;
54import org.openstreetmap.josm.gui.ShowHideButtonListener;
55import org.openstreetmap.josm.gui.SideButton;
56import org.openstreetmap.josm.gui.dialogs.DialogsPanel.Action;
57import org.openstreetmap.josm.gui.help.HelpUtil;
58import org.openstreetmap.josm.gui.help.Helpful;
59import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
60import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
61import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
62import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
63import org.openstreetmap.josm.tools.Destroyable;
64import org.openstreetmap.josm.tools.GBC;
65import org.openstreetmap.josm.tools.ImageProvider;
66import org.openstreetmap.josm.tools.Shortcut;
67import org.openstreetmap.josm.tools.WindowGeometry;
68import org.openstreetmap.josm.tools.WindowGeometry.WindowGeometryException;
69
70/**
71 * This class is a toggle dialog that can be turned on and off.
72 *
73 */
74public class ToggleDialog extends JPanel implements ShowHideButtonListener, Helpful, AWTEventListener {
75
76 public enum ButtonHiddingType {
77 ALWAYS_SHOWN, ALWAYS_HIDDEN, DYNAMIC
78 }
79
80 private final ParametrizedEnumProperty<ButtonHiddingType> PROP_BUTTON_HIDING = new ParametrizedEnumProperty<ToggleDialog.ButtonHiddingType>(ButtonHiddingType.class, ButtonHiddingType.DYNAMIC) {
81 @Override
82 protected String getKey(String... params) {
83 return preferencePrefix + ".buttonhiding";
84 }
85 @Override
86 protected ButtonHiddingType parse(String s) {
87 try {
88 return super.parse(s);
89 } catch (IllegalArgumentException e) {
90 // Legacy settings
91 return Boolean.parseBoolean(s)?ButtonHiddingType.DYNAMIC:ButtonHiddingType.ALWAYS_SHOWN;
92 }
93 }
94 };
95
96 /** The action to toggle this dialog */
97 protected ToggleDialogAction toggleAction;
98 protected String preferencePrefix;
99 final protected String name;
100
101 /** DialogsPanel that manages all ToggleDialogs */
102 protected DialogsPanel dialogsPanel;
103
104 protected TitleBar titleBar;
105
106 /**
107 * Indicates whether the dialog is showing or not.
108 */
109 protected boolean isShowing;
110 /**
111 * If isShowing is true, indicates whether the dialog is docked or not, e. g.
112 * shown as part of the main window or as a separate dialog window.
113 */
114 protected boolean isDocked;
115 /**
116 * If isShowing and isDocked are true, indicates whether the dialog is
117 * currently minimized or not.
118 */
119 protected boolean isCollapsed;
120 /**
121 * Indicates whether dynamic button hiding is active or not.
122 */
123 protected ButtonHiddingType buttonHiding;
124
125 /** the preferred height if the toggle dialog is expanded */
126 private int preferredHeight;
127
128 /** the label in the title bar which shows whether the toggle dialog is expanded or collapsed */
129 private JLabel lblMinimized;
130
131 /** the label in the title bar which shows whether buttons are dynamic or not */
132 private JButton buttonsHide = null;
133
134 /** the JDialog displaying the toggle dialog as undocked dialog */
135 protected JDialog detachedDialog;
136
137 protected JToggleButton button;
138 private JPanel buttonsPanel;
139 private List<javax.swing.Action> buttonActions = new ArrayList<javax.swing.Action>();
140
141 /** holds the menu entry in the windows menu. Required to properly
142 * toggle the checkbox on show/hide
143 */
144 protected JCheckBoxMenuItem windowMenuItem;
145
146 /**
147 * The linked preferences class (optional). If set, accessible from the title bar with a dedicated button
148 */
149 protected Class<? extends PreferenceSetting> preferenceClass;
150
151 /**
152 * Constructor
153 *
154 * @param name the name of the dialog
155 * @param iconName the name of the icon to be displayed
156 * @param tooltip the tool tip
157 * @param shortcut the shortcut
158 * @param preferredHeight the preferred height for the dialog
159 */
160 public ToggleDialog(String name, String iconName, String tooltip, Shortcut shortcut, int preferredHeight) {
161 this(name, iconName, tooltip, shortcut, preferredHeight, false);
162 }
163 /**
164 * Constructor
165
166 * @param name the name of the dialog
167 * @param iconName the name of the icon to be displayed
168 * @param tooltip the tool tip
169 * @param shortcut the shortcut
170 * @param preferredHeight the preferred height for the dialog
171 * @param defShow if the dialog should be shown by default, if there is no preference
172 */
173 public ToggleDialog(String name, String iconName, String tooltip, Shortcut shortcut, int preferredHeight, boolean defShow) {
174 this(name, iconName, tooltip, shortcut, preferredHeight, defShow, null);
175 }
176 /**
177 * Constructor
178 *
179 * @param name the name of the dialog
180 * @param iconName the name of the icon to be displayed
181 * @param tooltip the tool tip
182 * @param shortcut the shortcut
183 * @param preferredHeight the preferred height for the dialog
184 * @param defShow if the dialog should be shown by default, if there is no preference
185 * @param prefClass the preferences settings class, or null if not applicable
186 */
187 public ToggleDialog(String name, String iconName, String tooltip, Shortcut shortcut, int preferredHeight, boolean defShow, Class<? extends PreferenceSetting> prefClass) {
188 super(new BorderLayout());
189 this.preferencePrefix = iconName;
190 this.name = name;
191 this.preferenceClass = prefClass;
192
193 /** Use the full width of the parent element */
194 setPreferredSize(new Dimension(0, preferredHeight));
195 /** Override any minimum sizes of child elements so the user can resize freely */
196 setMinimumSize(new Dimension(0,0));
197 this.preferredHeight = preferredHeight;
198 toggleAction = new ToggleDialogAction(name, "dialogs/"+iconName, tooltip, shortcut, iconName);
199 String helpId = "Dialog/"+getClass().getName().substring(getClass().getName().lastIndexOf('.')+1);
200 toggleAction.putValue("help", helpId.substring(0, helpId.length()-6));
201
202 isShowing = Main.pref.getBoolean(preferencePrefix+".visible", defShow);
203 isDocked = Main.pref.getBoolean(preferencePrefix+".docked", true);
204 isCollapsed = Main.pref.getBoolean(preferencePrefix+".minimized", false);
205 buttonHiding = PROP_BUTTON_HIDING.get();
206
207 /** show the minimize button */
208 titleBar = new TitleBar(name, iconName);
209 add(titleBar, BorderLayout.NORTH);
210
211 setBorder(BorderFactory.createEtchedBorder());
212
213 Main.redirectToMainContentPane(this);
214
215 windowMenuItem = MainMenu.addWithCheckbox(Main.main.menu.windowMenu,
216 (JosmAction) getToggleAction(),
217 MainMenu.WINDOW_MENU_GROUP.TOGGLE_DIALOG);
218 }
219
220 /**
221 * The action to toggle the visibility state of this toggle dialog.
222 *
223 * Emits {@link PropertyChangeEvent}s for the property <tt>selected</tt>:
224 * <ul>
225 * <li>true, if the dialog is currently visible</li>
226 * <li>false, if the dialog is currently invisible</li>
227 * </ul>
228 *
229 */
230 public final class ToggleDialogAction extends JosmAction {
231
232 private ToggleDialogAction(String name, String iconName, String tooltip, Shortcut shortcut, String prefname) {
233 super(name, iconName, tooltip, shortcut, false);
234 }
235
236 public void actionPerformed(ActionEvent e) {
237 toggleButtonHook();
238 if(getValue("toolbarbutton") != null && getValue("toolbarbutton") instanceof JButton) {
239 ((JButton) getValue("toolbarbutton")).setSelected(!isShowing);
240 }
241 if (isShowing) {
242 hideDialog();
243 dialogsPanel.reconstruct(Action.ELEMENT_SHRINKS, null);
244 hideNotify();
245 } else {
246 showDialog();
247 if (isDocked && isCollapsed) {
248 expand();
249 }
250 if (isDocked) {
251 dialogsPanel.reconstruct(Action.INVISIBLE_TO_DEFAULT, ToggleDialog.this);
252 }
253 showNotify();
254 }
255 }
256
257 @Override
258 public void destroy() {
259 super.destroy();
260 }
261 }
262
263 /**
264 * Shows the dialog
265 */
266 public void showDialog() {
267 setIsShowing(true);
268 if (!isDocked) {
269 detach();
270 } else {
271 dock();
272 this.setVisible(true);
273 }
274 // toggling the selected value in order to enforce PropertyChangeEvents
275 setIsShowing(true);
276 windowMenuItem.setState(true);
277 toggleAction.putValue("selected", false);
278 toggleAction.putValue("selected", true);
279 }
280
281 /**
282 * Changes the state of the dialog such that the user can see the content.
283 * (takes care of the panel reconstruction)
284 */
285 public void unfurlDialog() {
286 if (isDialogInDefaultView())
287 return;
288 if (isDialogInCollapsedView()) {
289 expand();
290 dialogsPanel.reconstruct(Action.COLLAPSED_TO_DEFAULT, this);
291 } else if (!isDialogShowing()) {
292 showDialog();
293 if (isDocked && isCollapsed) {
294 expand();
295 }
296 if (isDocked) {
297 dialogsPanel.reconstruct(Action.INVISIBLE_TO_DEFAULT, this);
298 }
299 showNotify();
300 }
301 }
302
303 @Override
304 public void buttonHidden() {
305 if ((Boolean) toggleAction.getValue("selected")) {
306 toggleAction.actionPerformed(null);
307 }
308 }
309
310 public void buttonShown() {
311 unfurlDialog();
312 }
313
314
315 /**
316 * Hides the dialog
317 */
318 public void hideDialog() {
319 closeDetachedDialog();
320 this.setVisible(false);
321 windowMenuItem.setState(false);
322 setIsShowing(false);
323 toggleAction.putValue("selected", false);
324 }
325
326 /**
327 * Displays the toggle dialog in the toggle dialog view on the right
328 * of the main map window.
329 *
330 */
331 protected void dock() {
332 detachedDialog = null;
333 titleBar.setVisible(true);
334 setIsDocked(true);
335 }
336
337 /**
338 * Display the dialog in a detached window.
339 *
340 */
341 protected void detach() {
342 setContentVisible(true);
343 this.setVisible(true);
344 titleBar.setVisible(false);
345 detachedDialog = new DetachedDialog();
346 detachedDialog.setVisible(true);
347 setIsShowing(true);
348 setIsDocked(false);
349 }
350
351 /**
352 * Collapses the toggle dialog to the title bar only
353 *
354 */
355 public void collapse() {
356 if (isDialogInDefaultView()) {
357 setContentVisible(false);
358 setIsCollapsed(true);
359 setPreferredSize(new Dimension(0,20));
360 setMaximumSize(new Dimension(Integer.MAX_VALUE,20));
361 setMinimumSize(new Dimension(Integer.MAX_VALUE,20));
362 lblMinimized.setIcon(ImageProvider.get("misc", "minimized"));
363 }
364 else throw new IllegalStateException();
365 }
366
367 /**
368 * Expands the toggle dialog
369 */
370 protected void expand() {
371 if (isDialogInCollapsedView()) {
372 setContentVisible(true);
373 setIsCollapsed(false);
374 setPreferredSize(new Dimension(0,preferredHeight));
375 setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
376 lblMinimized.setIcon(ImageProvider.get("misc", "normal"));
377 }
378 else throw new IllegalStateException();
379 }
380
381 /**
382 * Sets the visibility of all components in this toggle dialog, except the title bar
383 *
384 * @param visible true, if the components should be visible; false otherwise
385 */
386 protected void setContentVisible(boolean visible) {
387 Component comps[] = getComponents();
388 for(int i=0; i<comps.length; i++) {
389 if (comps[i] != titleBar && (!visible || comps[i] != buttonsPanel || buttonHiding != ButtonHiddingType.ALWAYS_HIDDEN)) {
390 comps[i].setVisible(visible);
391 }
392 }
393 }
394
395 public void destroy() {
396 closeDetachedDialog();
397 hideNotify();
398 Main.main.menu.windowMenu.remove(windowMenuItem);
399 Toolkit.getDefaultToolkit().removeAWTEventListener(this);
400 destroyComponents(this);
401 }
402
403 private void destroyComponents(Component component) {
404 if (component instanceof Container) {
405 for (Component c: ((Container)component).getComponents()) {
406 destroyComponents(c);
407 }
408 }
409 if (component instanceof Destroyable) {
410 ((Destroyable) component).destroy();
411 }
412 }
413
414 /**
415 * Closes the detached dialog if this toggle dialog is currently displayed
416 * in a detached dialog.
417 *
418 */
419 public void closeDetachedDialog() {
420 if (detachedDialog != null) {
421 detachedDialog.setVisible(false);
422 detachedDialog.getContentPane().removeAll();
423 detachedDialog.dispose();
424 }
425 }
426
427 /**
428 * Called when toggle dialog is shown (after it was created or expanded). Descendants may overwrite this
429 * method, it's a good place to register listeners needed to keep dialog updated
430 */
431 public void showNotify() {
432
433 }
434
435 /**
436 * Called when toggle dialog is hidden (collapsed, removed, MapFrame is removed, ...). Good place to unregister
437 * listeners
438 */
439 public void hideNotify() {
440
441 }
442
443 /**
444 * The title bar displayed in docked mode
445 *
446 */
447 protected class TitleBar extends JPanel {
448 final private JLabel lblTitle;
449 final private JComponent lblTitle_weak;
450
451 public TitleBar(String toggleDialogName, String iconName) {
452 setLayout(new GridBagLayout());
453
454 lblMinimized = new JLabel(ImageProvider.get("misc", "normal"));
455 add(lblMinimized);
456
457 // scale down the dialog icon
458 ImageIcon inIcon = ImageProvider.get("dialogs", iconName);
459 ImageIcon smallIcon = new ImageIcon(inIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
460 lblTitle = new JLabel("",smallIcon, JLabel.TRAILING);
461 lblTitle.setIconTextGap(8);
462
463 JPanel conceal = new JPanel();
464 conceal.add(lblTitle);
465 conceal.setVisible(false);
466 add(conceal, GBC.std());
467
468 // Cannot add the label directly since it would displace other elements on resize
469 lblTitle_weak = new JComponent() {
470 @Override
471 public void paintComponent(Graphics g) {
472 lblTitle.paint(g);
473 }
474 };
475 lblTitle_weak.setPreferredSize(new Dimension(Integer.MAX_VALUE,20));
476 lblTitle_weak.setMinimumSize(new Dimension(0,20));
477 add(lblTitle_weak, GBC.std().fill(GBC.HORIZONTAL));
478
479 addMouseListener(
480 new MouseAdapter() {
481 @Override
482 public void mouseClicked(MouseEvent e) {
483 if (isCollapsed) {
484 expand();
485 dialogsPanel.reconstruct(Action.COLLAPSED_TO_DEFAULT, ToggleDialog.this);
486 } else {
487 collapse();
488 dialogsPanel.reconstruct(Action.ELEMENT_SHRINKS, null);
489 }
490 }
491
492 private void maybeShowPopup(MouseEvent e) {
493 if (e.isPopupTrigger()) {
494 JPopupMenu menu = new JPopupMenu();
495 JMenu buttonHidingMenu = new JMenu(tr("Side buttons"));
496 JRadioButtonMenuItem alwaysShown = new JRadioButtonMenuItem(new AbstractAction(tr("Always shown")) {
497 @Override
498 public void actionPerformed(ActionEvent e) {
499 setIsButtonHiding(ButtonHiddingType.ALWAYS_SHOWN);
500 }
501 });
502 JRadioButtonMenuItem dynamic = new JRadioButtonMenuItem(new AbstractAction(tr("Dynamic")) {
503 @Override
504 public void actionPerformed(ActionEvent e) {
505 setIsButtonHiding(ButtonHiddingType.DYNAMIC);
506 }
507 });
508 JRadioButtonMenuItem alwaysHidden = new JRadioButtonMenuItem(new AbstractAction(tr("Always hidden")) {
509 @Override
510 public void actionPerformed(ActionEvent e) {
511 setIsButtonHiding(ButtonHiddingType.ALWAYS_HIDDEN);
512 }
513 });
514 alwaysShown.setSelected(buttonHiding == ButtonHiddingType.ALWAYS_SHOWN);
515 dynamic.setSelected(buttonHiding == ButtonHiddingType.DYNAMIC);
516 alwaysHidden.setSelected(buttonHiding == ButtonHiddingType.ALWAYS_HIDDEN);
517 buttonHidingMenu.add(alwaysShown);
518 buttonHidingMenu.add(dynamic);
519 buttonHidingMenu.add(alwaysHidden);
520 menu.add(buttonHidingMenu);
521 for (javax.swing.Action action: buttonActions) {
522 menu.add(action);
523 }
524 menu.show(TitleBar.this, e.getX(), e.getY());
525 }
526 }
527
528 @Override
529 public void mousePressed(MouseEvent e) {
530 maybeShowPopup(e);
531 }
532
533 @Override
534 public void mouseReleased(MouseEvent e) {
535 maybeShowPopup(e);
536 }
537 }
538 );
539
540 if(Main.pref.getBoolean("dialog.dynamic.buttons", true)) {
541 buttonsHide = new JButton(ImageProvider.get("misc", buttonHiding != ButtonHiddingType.ALWAYS_SHOWN ? "buttonhide" : "buttonshow"));
542 buttonsHide.setToolTipText(tr("Toggle dynamic buttons"));
543 buttonsHide.setBorder(BorderFactory.createEmptyBorder());
544 buttonsHide.addActionListener(
545 new ActionListener(){
546 public void actionPerformed(ActionEvent e) {
547 setIsButtonHiding(buttonHiding == ButtonHiddingType.ALWAYS_SHOWN?ButtonHiddingType.DYNAMIC:ButtonHiddingType.ALWAYS_SHOWN);
548 }
549 }
550 );
551 add(buttonsHide);
552 }
553
554 // show the pref button if applicable
555 if (preferenceClass != null) {
556 inIcon = ImageProvider.get("preference");
557 smallIcon = new ImageIcon(inIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
558 JButton pref = new JButton(smallIcon);
559 pref.setToolTipText(tr("Open preferences for this panel"));
560 pref.setBorder(BorderFactory.createEmptyBorder());
561 pref.addActionListener(
562 new ActionListener(){
563 @SuppressWarnings("unchecked")
564 public void actionPerformed(ActionEvent e) {
565 final PreferenceDialog p = new PreferenceDialog(Main.parent);
566 if (TabPreferenceSetting.class.isAssignableFrom(preferenceClass)) {
567 p.selectPreferencesTabByClass((Class<? extends TabPreferenceSetting>) preferenceClass);
568 } else if (SubPreferenceSetting.class.isAssignableFrom(preferenceClass)) {
569 p.selectSubPreferencesTabByClass((Class<? extends SubPreferenceSetting>) preferenceClass);
570 }
571 p.setVisible(true);
572 }
573 }
574 );
575 add(pref);
576 }
577
578 // show the sticky button
579 JButton sticky = new JButton(ImageProvider.get("misc", "sticky"));
580 sticky.setToolTipText(tr("Undock the panel"));
581 sticky.setBorder(BorderFactory.createEmptyBorder());
582 sticky.addActionListener(
583 new ActionListener(){
584 public void actionPerformed(ActionEvent e) {
585 detach();
586 dialogsPanel.reconstruct(Action.ELEMENT_SHRINKS, null);
587 }
588 }
589 );
590 add(sticky);
591
592 // show the close button
593 JButton close = new JButton(ImageProvider.get("misc", "close"));
594 close.setToolTipText(tr("Close this panel. You can reopen it with the buttons in the left toolbar."));
595 close.setBorder(BorderFactory.createEmptyBorder());
596 close.addActionListener(
597 new ActionListener(){
598 public void actionPerformed(ActionEvent e) {
599 hideDialog();
600 dialogsPanel.reconstruct(Action.ELEMENT_SHRINKS, null);
601 hideNotify();
602 }
603 }
604 );
605 add(close);
606 setToolTipText(tr("Click to minimize/maximize the panel content"));
607 setTitle(toggleDialogName);
608 }
609
610 public void setTitle(String title) {
611 lblTitle.setText(title);
612 lblTitle_weak.repaint();
613 }
614
615 public String getTitle() {
616 return lblTitle.getText();
617 }
618 }
619
620 /**
621 * The dialog class used to display toggle dialogs in a detached window.
622 *
623 */
624 private class DetachedDialog extends JDialog{
625 public DetachedDialog() {
626 super(JOptionPane.getFrameForComponent(Main.parent));
627 getContentPane().add(ToggleDialog.this);
628 addWindowListener(new WindowAdapter(){
629 @Override public void windowClosing(WindowEvent e) {
630 rememberGeometry();
631 getContentPane().removeAll();
632 dispose();
633 if (dockWhenClosingDetachedDlg()) {
634 dock();
635 if (isDialogInCollapsedView()) {
636 expand();
637 }
638 dialogsPanel.reconstruct(Action.INVISIBLE_TO_DEFAULT, ToggleDialog.this);
639 } else {
640 hideDialog();
641 hideNotify();
642 }
643 }
644 });
645 addComponentListener(new ComponentAdapter() {
646 @Override public void componentMoved(ComponentEvent e) {
647 rememberGeometry();
648 }
649 @Override public void componentResized(ComponentEvent e) {
650 rememberGeometry();
651 }
652 });
653
654 try {
655 new WindowGeometry(preferencePrefix+".geometry").applySafe(this);
656 } catch (WindowGeometryException e) {
657 ToggleDialog.this.setPreferredSize(ToggleDialog.this.getDefaultDetachedSize());
658 pack();
659 setLocationRelativeTo(Main.parent);
660 }
661 setTitle(titleBar.getTitle());
662 HelpUtil.setHelpContext(getRootPane(), helpTopic());
663 }
664
665 protected void rememberGeometry() {
666 if (detachedDialog != null) {
667 new WindowGeometry(detachedDialog).remember(preferencePrefix+".geometry");
668 }
669 }
670 }
671
672 /**
673 * Replies the action to toggle the visible state of this toggle dialog
674 *
675 * @return the action to toggle the visible state of this toggle dialog
676 */
677 public AbstractAction getToggleAction() {
678 return toggleAction;
679 }
680
681 /**
682 * Replies the prefix for the preference settings of this dialog.
683 *
684 * @return the prefix for the preference settings of this dialog.
685 */
686 public String getPreferencePrefix() {
687 return preferencePrefix;
688 }
689
690 /**
691 * Sets the dialogsPanel managing all toggle dialogs
692 */
693 public void setDialogsPanel(DialogsPanel dialogsPanel) {
694 this.dialogsPanel = dialogsPanel;
695 }
696
697 /**
698 * Replies the name of this toggle dialog
699 */
700 @Override
701 public String getName() {
702 return "toggleDialog." + preferencePrefix;
703 }
704
705 /**
706 * Sets the title
707 */
708 public void setTitle(String title) {
709 titleBar.setTitle(title);
710 if (detachedDialog != null) {
711 detachedDialog.setTitle(title);
712 }
713 }
714
715 protected void setIsShowing(boolean val) {
716 isShowing = val;
717 Main.pref.put(preferencePrefix+".visible", val);
718 stateChanged();
719 }
720
721 protected void setIsDocked(boolean val) {
722 if(buttonsPanel != null && buttonsHide != null) {
723 buttonsPanel.setVisible(val ? buttonHiding == ButtonHiddingType.ALWAYS_SHOWN : true);
724 }
725 isDocked = val;
726 Main.pref.put(preferencePrefix+".docked", val);
727 stateChanged();
728 }
729
730 protected void setIsCollapsed(boolean val) {
731 isCollapsed = val;
732 Main.pref.put(preferencePrefix+".minimized", val);
733 stateChanged();
734 }
735
736 protected void setIsButtonHiding(ButtonHiddingType val) {
737 buttonHiding = val;
738 PROP_BUTTON_HIDING.put(val);
739 if (buttonsHide != null) {
740 buttonsHide.setIcon(ImageProvider.get("misc", val != ButtonHiddingType.ALWAYS_SHOWN ? "buttonhide" : "buttonshow"));
741 }
742 if (buttonsPanel != null) {
743 buttonsPanel.setVisible(val != ButtonHiddingType.ALWAYS_HIDDEN);
744 }
745 stateChanged();
746 }
747
748 public int getPreferredHeight() {
749 return preferredHeight;
750 }
751
752 public String helpTopic() {
753 String help = getClass().getName();
754 help = help.substring(help.lastIndexOf('.')+1, help.length()-6);
755 return "Dialog/"+help;
756 }
757
758 @Override
759 public String toString() {
760 return name;
761 }
762
763 /**
764 * Replies true if this dialog is showing either as docked or as detached dialog
765 */
766 public boolean isDialogShowing() {
767 return isShowing;
768 }
769
770 /**
771 * Replies true if this dialog is docked and expanded
772 */
773 public boolean isDialogInDefaultView() {
774 return isShowing && isDocked && (! isCollapsed);
775 }
776
777 /**
778 * Replies true if this dialog is docked and collapsed
779 */
780 public boolean isDialogInCollapsedView() {
781 return isShowing && isDocked && isCollapsed;
782 }
783
784 public void setButton(JToggleButton button) {
785 this.button = button;
786 }
787
788 public JToggleButton getButton() {
789 return button;
790 }
791
792 /***
793 * The following methods are intended to be overridden, in order to customize
794 * the toggle dialog behavior.
795 **/
796
797 /**
798 * Change the Geometry of the detached dialog to better fit the content.
799 */
800 protected Rectangle getDetachedGeometry(Rectangle last) {
801 return last;
802 }
803
804 /**
805 * Default size of the detached dialog.
806 * Override this method to customize the initial dialog size.
807 */
808 protected Dimension getDefaultDetachedSize() {
809 return new Dimension(dialogsPanel.getWidth(), preferredHeight);
810 }
811
812 /**
813 * Do something when the toggleButton is pressed.
814 */
815 protected void toggleButtonHook() {
816 }
817
818 protected boolean dockWhenClosingDetachedDlg() {
819 return true;
820 }
821
822 /**
823 * primitive stateChangedListener for subclasses
824 */
825 protected void stateChanged() {
826 }
827
828 protected Component createLayout(Component data, boolean scroll, Collection<SideButton> buttons) {
829 return createLayout(data, scroll, buttons, (Collection<SideButton>[]) null);
830 }
831
832 protected Component createLayout(Component data, boolean scroll, Collection<SideButton> firstButtons, Collection<SideButton>... nextButtons) {
833 if (scroll) {
834 data = new JScrollPane(data);
835 }
836 LinkedList<Collection<SideButton>> buttons = new LinkedList<Collection<SideButton>>();
837 buttons.addFirst(firstButtons);
838 if (nextButtons != null) {
839 buttons.addAll(Arrays.asList(nextButtons));
840 }
841 add(data, BorderLayout.CENTER);
842 if (buttons.size() > 0 && buttons.get(0) != null && !buttons.get(0).isEmpty()) {
843 buttonsPanel = new JPanel(new GridLayout(buttons.size(), 1));
844 for (Collection<SideButton> buttonRow : buttons) {
845 if (buttonRow == null) {
846 continue;
847 }
848 final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean("dialog.align.left", false)
849 ? new FlowLayout(FlowLayout.LEFT) : new GridLayout(1, buttonRow.size()));
850 buttonsPanel.add(buttonRowPanel);
851 for (SideButton button : buttonRow) {
852 buttonRowPanel.add(button);
853 javax.swing.Action action = button.getAction();
854 if (action != null) {
855 buttonActions.add(action);
856 } else {
857 System.err.println("Button " + button + " doesn't have action defined");
858 new Exception().printStackTrace();
859 }
860 }
861 }
862 add(buttonsPanel, BorderLayout.SOUTH);
863 if (Main.pref.getBoolean("dialog.dynamic.buttons", true)) {
864 Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.MOUSE_MOTION_EVENT_MASK);
865 buttonsPanel.setVisible(buttonHiding == ButtonHiddingType.ALWAYS_SHOWN || !isDocked);
866 } else if (buttonHiding == ButtonHiddingType.ALWAYS_HIDDEN) {
867 buttonsPanel.setVisible(false);
868 }
869 } else if (buttonsHide != null) {
870 buttonsHide.setVisible(false);
871 }
872 return data;
873 }
874
875 @Override
876 public void eventDispatched(AWTEvent event) {
877 if(isShowing() && !isCollapsed && isDocked && buttonHiding == ButtonHiddingType.DYNAMIC) {
878 Rectangle b = this.getBounds();
879 b.setLocation(getLocationOnScreen());
880 if (b.contains(((MouseEvent)event).getLocationOnScreen())) {
881 if(!buttonsPanel.isVisible()) {
882 buttonsPanel.setVisible(true);
883 }
884 } else if (buttonsPanel.isVisible()) {
885 buttonsPanel.setVisible(false);
886 }
887 }
888 }
889}
Note: See TracBrowser for help on using the repository browser.