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

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

fix #7631 - NPE when toggling dynamic buttons

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