source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/PopupMenuLauncher.java@ 14977

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

ensures consistency of upload comment:

  • fix #11168 - ctrl-z/undo could reset unwanted old changeset comment
  • fix #13474 - selecting "new changeset" after having entered a changeset comment did reset it to the previous value
  • fix #17452 - ctrl-enter while typing a changeset comment did upload with the previous value
  • fix behaviour of upload.comment.max-age: values were reset after 5 months instead of intended 4 hours because seconds were compared to milliseconds
  • avoid creation of unneeded undo/redo internal classes for non-editable text fields
  • ensures consistency of upload dialog if upload.comment properties are modified manually from advanced preferences
  • add a source attribute to preference events to know which class modified the preference entry
  • refactor reflection utils
  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.widgets;
3
4import java.awt.Component;
5import java.awt.Point;
6import java.awt.event.FocusAdapter;
7import java.awt.event.FocusEvent;
8import java.awt.event.MouseAdapter;
9import java.awt.event.MouseEvent;
10
11import javax.swing.JList;
12import javax.swing.JPopupMenu;
13import javax.swing.JTable;
14import javax.swing.JTree;
15import javax.swing.SwingUtilities;
16import javax.swing.tree.TreePath;
17
18import org.openstreetmap.josm.tools.Logging;
19
20/**
21 * Utility class that helps to display popup menus on mouse events.
22 * @since 2688
23 */
24public class PopupMenuLauncher extends MouseAdapter {
25 protected JPopupMenu menu;
26 private final boolean checkEnabled;
27
28 /**
29 * Creates a new {@link PopupMenuLauncher} with no defined menu.
30 * It is then needed to override the {@link #launch} method.
31 * @see #launch(MouseEvent)
32 */
33 public PopupMenuLauncher() {
34 this(null);
35 }
36
37 /**
38 * Creates a new {@link PopupMenuLauncher} with the given menu.
39 * @param menu The popup menu to display
40 */
41 public PopupMenuLauncher(JPopupMenu menu) {
42 this(menu, false);
43 }
44
45 /**
46 * Creates a new {@link PopupMenuLauncher} with the given menu.
47 * @param menu The popup menu to display
48 * @param checkEnabled if {@code true}, the popup menu will only be displayed if the component triggering the mouse event is enabled
49 * @since 5886
50 */
51 public PopupMenuLauncher(JPopupMenu menu, boolean checkEnabled) {
52 this.menu = menu;
53 this.checkEnabled = checkEnabled;
54 }
55
56 @Override
57 public void mousePressed(MouseEvent e) {
58 processEvent(e);
59 }
60
61 @Override
62 public void mouseReleased(MouseEvent e) {
63 processEvent(e);
64 }
65
66 private void processEvent(MouseEvent e) {
67 if (e.isPopupTrigger() && (!checkEnabled || e.getComponent().isEnabled())) {
68 launch(e);
69 }
70 }
71
72 /**
73 * Launches the popup menu according to the given mouse event.
74 * This method needs to be overriden if the default constructor has been called.
75 * @param evt A mouse event
76 */
77 public void launch(final MouseEvent evt) {
78 if (evt != null) {
79 final Component component = evt.getComponent();
80 if (checkSelection(component, evt.getPoint())) {
81 checkFocusAndShowMenu(component, evt);
82 }
83 }
84 }
85
86 protected boolean checkSelection(Component component, Point p) {
87 if (component instanceof JList) {
88 return checkListSelection((JList<?>) component, p) > -1;
89 } else if (component instanceof JTable) {
90 return checkTableSelection((JTable) component, p) > -1;
91 } else if (component instanceof JTree) {
92 return checkTreeSelection((JTree) component, p) != null;
93 }
94 return true;
95 }
96
97 protected void checkFocusAndShowMenu(final Component component, final MouseEvent evt) {
98 if (component != null && component.isFocusable() && !component.hasFocus() && component.requestFocusInWindow()) {
99 component.addFocusListener(new FocusAdapter() {
100 @Override
101 public void focusGained(FocusEvent e) {
102 showMenu(evt);
103 component.removeFocusListener(this);
104 }
105 });
106 } else {
107 showMenu(evt);
108 }
109 }
110
111 protected void showMenu(MouseEvent evt) {
112 if (menu != null && evt != null) {
113 Component component = evt.getComponent();
114 if (component.isShowing()) {
115 menu.show(component, evt.getX(), evt.getY());
116 }
117 } else {
118 Logging.warn("Unable to display menu {0} - {1}", menu, evt);
119 }
120 }
121
122 protected int checkListSelection(JList<?> list, Point p) {
123 int idx = list.locationToIndex(p);
124 if (idx >= 0 && idx < list.getModel().getSize() && list.getSelectedIndices().length < 2 && !list.isSelectedIndex(idx)) {
125 list.setSelectedIndex(idx);
126 }
127 return idx;
128 }
129
130 protected int checkTableSelection(JTable table, Point p) {
131 int row = table.rowAtPoint(p);
132 if (row >= 0 && row < table.getRowCount() && table.getSelectedRowCount() < 2 && table.getSelectedRow() != row) {
133 table.getSelectionModel().setSelectionInterval(row, row);
134 }
135 return row;
136 }
137
138 protected TreePath checkTreeSelection(JTree tree, Point p) {
139 TreePath path = tree.getPathForLocation(p.x, p.y);
140 if (path != null && tree.getSelectionCount() < 2 && !tree.isPathSelected(path)) {
141 tree.setSelectionPath(path);
142 }
143 return path;
144 }
145
146 protected static boolean isDoubleClick(MouseEvent e) {
147 return e != null && SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2;
148 }
149
150 /**
151 * @return the popup menu if defined, {@code null} otherwise.
152 * @since 5884
153 */
154 public final JPopupMenu getMenu() {
155 return menu;
156 }
157
158 /**
159 * Empties the internal undo manager, if any.
160 * @since 14977
161 */
162 public void discardAllUndoableEdits() {
163 if (menu instanceof TextContextualPopupMenu) {
164 ((TextContextualPopupMenu) menu).discardAllUndoableEdits();
165 }
166 }
167}
Note: See TracBrowser for help on using the repository browser.