JAL-1807 includes ?j2sdebug flag and DebugJS._(msg)
[jalviewjs.git] / site / j2s / swingjs / plaf / JSButtonListener.java
1 /*\r
2  * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.\r
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
4  *\r
5  * This code is free software; you can redistribute it and/or modify it\r
6  * under the terms of the GNU General Public License version 2 only, as\r
7  * published by the Free Software Foundation.  Oracle designates this\r
8  * particular file as subject to the "Classpath" exception as provided\r
9  * by Oracle in the LICENSE file that accompanied this code.\r
10  *\r
11  * This code is distributed in the hope that it will be useful, but WITHOUT\r
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
14  * version 2 for more details (a copy is included in the LICENSE file that\r
15  * accompanied this code).\r
16  *\r
17  * You should have received a copy of the GNU General Public License version\r
18  * 2 along with this work; if not, write to the Free Software Foundation,\r
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\r
22  * or visit www.oracle.com if you need additional information or have any\r
23  * questions.\r
24  */\r
25 \r
26 package swingjs.plaf;\r
27 \r
28 import jsjava.awt.event.ActionEvent;\r
29 import jsjava.awt.event.FocusEvent;\r
30 import jsjava.awt.event.FocusListener;\r
31 import jsjava.awt.event.InputEvent;\r
32 import jsjava.awt.event.MouseEvent;\r
33 import jsjava.awt.event.MouseListener;\r
34 import jsjava.awt.event.MouseMotionListener;\r
35 import jsjava.beans.PropertyChangeEvent;\r
36 import jsjava.beans.PropertyChangeListener;\r
37 import jsjavax.swing.AbstractButton;\r
38 import jsjavax.swing.ButtonModel;\r
39 import jsjavax.swing.InputMap;\r
40 import jsjavax.swing.JComponent;\r
41 import jsjavax.swing.KeyStroke;\r
42 import jsjavax.swing.SwingUtilities;\r
43 import jsjavax.swing.event.ChangeEvent;\r
44 import jsjavax.swing.event.ChangeListener;\r
45 import jsjavax.swing.plaf.ComponentInputMapUIResource;\r
46 import jsjavax.swing.plaf.ComponentUI;\r
47 import jssun.swing.UIAction;\r
48 \r
49 /**\r
50  * Button Listener\r
51  *\r
52  * @author Jeff Dinkins\r
53  * @author Arnaud Weber (keyboard UI support)\r
54  */\r
55 \r
56 public class JSButtonListener implements MouseListener, MouseMotionListener,\r
57                                    FocusListener, ChangeListener, PropertyChangeListener\r
58 {\r
59     private long lastPressedTimestamp = -1;\r
60     private boolean shouldDiscardRelease = false;\r
61                 private AbstractButton btn;\r
62 \r
63     /**\r
64      * Populates Buttons actions.\r
65      */\r
66     static void loadActionMap(LazyActionMap map) {\r
67         map.put(new Actions(Actions.PRESS));\r
68         map.put(new Actions(Actions.RELEASE));\r
69     }\r
70 \r
71 \r
72     public JSButtonListener(AbstractButton b) {\r
73         btn = b;\r
74     }\r
75 \r
76         public void propertyChange(PropertyChangeEvent e) {\r
77                 String prop = e.getPropertyName();\r
78                 //System.out.println("JSButtonListener property change: " + prop + " " + e.getSource());\r
79                 if (prop == AbstractButton.MNEMONIC_CHANGED_PROPERTY) {\r
80                         updateMnemonicBinding((AbstractButton) e.getSource());\r
81                 } else if (prop == AbstractButton.CONTENT_AREA_FILLED_CHANGED_PROPERTY) {\r
82                         checkOpacity((AbstractButton) e.getSource());\r
83                 } else if (prop == AbstractButton.TEXT_CHANGED_PROPERTY || "font" == prop\r
84                                 || "foreground" == prop) {\r
85                         AbstractButton b = (AbstractButton) e.getSource();\r
86                         ((JSComponentUI) (Object) b.getUI()).notifyPropertyChanged(prop);\r
87                 }\r
88         }\r
89 \r
90     protected void checkOpacity(AbstractButton b) {\r
91         b.setOpaque( b.isContentAreaFilled() );\r
92     }\r
93 \r
94     /**\r
95      * Register default key actions: pressing space to "click" a\r
96      * button and registring the keyboard mnemonic (if any).\r
97      */\r
98     public void installKeyboardActions(JComponent c) {\r
99         AbstractButton b = (AbstractButton)c;\r
100         // Update the mnemonic binding.\r
101         updateMnemonicBinding(b);\r
102 \r
103         LazyActionMap.installLazyActionMap(c, JSButtonListener.class,\r
104                                            "Button.actionMap");\r
105 \r
106         InputMap km = getInputMap(JComponent.WHEN_FOCUSED, c);\r
107 \r
108         SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, km);\r
109     }\r
110 \r
111     /**\r
112      * Unregister's default key actions\r
113      */\r
114     public void uninstallKeyboardActions(JComponent c) {\r
115         SwingUtilities.replaceUIInputMap(c, JComponent.\r
116                                          WHEN_IN_FOCUSED_WINDOW, null);\r
117         SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null);\r
118         SwingUtilities.replaceUIActionMap(c, null);\r
119     }\r
120 \r
121     /**\r
122      * Returns the InputMap for condition <code>condition</code>. Called as\r
123      * part of <code>installKeyboardActions</code>.\r
124      */\r
125     InputMap getInputMap(int condition, JComponent c) {\r
126 //        if (condition == JComponent.WHEN_FOCUSED) {\r
127 //            BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(\r
128 //                         ((AbstractButton)c).getUI(), BasicButtonUI.class);\r
129 //            if (ui != null) {\r
130 //                return (InputMap)DefaultLookup.get(\r
131 //                             c, ui, ui.getPropertyPrefix() + "focusInputMap");\r
132 //            }\r
133 //        }\r
134         return null;\r
135     }\r
136 \r
137     /**\r
138      * Resets the binding for the mnemonic in the WHEN_IN_FOCUSED_WINDOW\r
139      * UI InputMap.\r
140      */\r
141     void updateMnemonicBinding(AbstractButton b) {\r
142         int m = b.getMnemonic();\r
143         if(m != 0) {\r
144             InputMap map = SwingUtilities.getUIInputMap(\r
145                                 b, JComponent.WHEN_IN_FOCUSED_WINDOW);\r
146 \r
147             if (map == null) {\r
148                 map = new ComponentInputMapUIResource(b);\r
149                 SwingUtilities.replaceUIInputMap(b,\r
150                                JComponent.WHEN_IN_FOCUSED_WINDOW, map);\r
151             }\r
152             map.clear();\r
153             map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, false),\r
154                     "pressed");\r
155             map.put(KeyStroke.getKeyStroke(m, InputEvent.ALT_MASK, true),\r
156                     "released");\r
157             map.put(KeyStroke.getKeyStroke(m, 0, true), "released");\r
158         }\r
159         else {\r
160             InputMap map = SwingUtilities.getUIInputMap(b, JComponent.\r
161                                              WHEN_IN_FOCUSED_WINDOW);\r
162             if (map != null) {\r
163                 map.clear();\r
164             }\r
165         }\r
166     }\r
167 \r
168     public void stateChanged(ChangeEvent e) {\r
169         AbstractButton b = (AbstractButton) e.getSource();\r
170         b.repaint();\r
171     }\r
172 \r
173     public void focusGained(FocusEvent e) {\r
174 //        AbstractButton b = (AbstractButton) e.getSource();\r
175 //        if (b instanceof JButton && ((JButton)b).isDefaultCapable()) {\r
176 //            JRootPane root = b.getRootPane();\r
177 //            if (root != null) {\r
178 //               BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(\r
179 //                         ((AbstractButton)b).getUI(), BasicButtonUI.class);\r
180 //               if (ui != null && DefaultLookup.getBoolean(b, ui,\r
181 //                                   ui.getPropertyPrefix() +\r
182 //                                   "defaultButtonFollowsFocus", true)) {\r
183 //                   root.putClientProperty("temporaryDefaultButton", b);\r
184 //                   root.setDefaultButton((JButton)b);\r
185 //                   root.putClientProperty("temporaryDefaultButton", null);\r
186 //               }\r
187 //            }\r
188 //        }\r
189 //        b.repaint();\r
190     }\r
191 \r
192     public void focusLost(FocusEvent e) {\r
193         AbstractButton b = (AbstractButton) e.getSource();\r
194 //        JRootPane root = b.getRootPane();\r
195 //        if (root != null) {\r
196 //           JButton initialDefault = (JButton)root.getClientProperty("initialDefaultButton");\r
197 //           if (b != initialDefault) {\r
198 //               BasicButtonUI ui = (BasicButtonUI)BasicLookAndFeel.getUIOfType(\r
199 //                         ((AbstractButton)b).getUI(), BasicButtonUI.class);\r
200 //               if (ui != null && DefaultLookup.getBoolean(b, ui,\r
201 //                                   ui.getPropertyPrefix() +\r
202 //                                   "defaultButtonFollowsFocus", true)) {\r
203 //                   root.setDefaultButton(initialDefault);\r
204 //               }\r
205 //           }\r
206 //        }\r
207 //\r
208         ButtonModel model = b.getModel();\r
209         model.setArmed(false);\r
210         model.setPressed(false);\r
211 //\r
212 //        b.repaint();\r
213     }\r
214 \r
215     public void mouseMoved(MouseEvent e) {\r
216     }\r
217 \r
218 \r
219     public void mouseDragged(MouseEvent e) {\r
220     }\r
221 \r
222     public void mouseClicked(MouseEvent e) {\r
223     }\r
224 \r
225         public void mousePressed(MouseEvent e) {\r
226                 if (SwingUtilities.isLeftMouseButton(e)) {\r
227                         AbstractButton b = (AbstractButton) e.getSource();\r
228                         if (!b.contains(e.getX(), e.getY()))\r
229                                 return;\r
230                         // We need to check the state before and after the button click \r
231                         // for radio and checkboxes to make sure the DOM button actually got hit.\r
232                         // mousePress is an "arm"; mouseRelease is a "click"\r
233                         \r
234                         ((JSButtonUI) (ComponentUI) b.getUI()).verifyButtonClick(false);\r
235                         long multiClickThreshhold = b.getMultiClickThreshhold();\r
236                         long lastTime = lastPressedTimestamp;\r
237                         long currentTime = lastPressedTimestamp = e.getWhen();\r
238                         if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {\r
239                                 shouldDiscardRelease = true;\r
240                                 return;\r
241                         }\r
242 \r
243                         //System.out.println("JSButtonListener press " + b.getName() + " " + e);\r
244 \r
245                         ButtonModel model = b.getModel();\r
246                         if (!model.isEnabled()) {\r
247                                 // Disabled buttons ignore all input...\r
248                                 return;\r
249                         }\r
250                         if (!model.isArmed()) {\r
251                                 // button not armed, should be\r
252                                 model.setArmed(true);\r
253                         }\r
254                         model.setPressed(true);\r
255                         if (!b.hasFocus() && b.isRequestFocusEnabled()) {\r
256                                 b.requestFocus();\r
257                         }\r
258                 }\r
259         };\r
260 \r
261     public void mouseReleased(MouseEvent e) {\r
262         if (SwingUtilities.isLeftMouseButton(e)) {\r
263             // Support for multiClickThreshhold\r
264             if (shouldDiscardRelease) {\r
265                 shouldDiscardRelease = false;\r
266                 return;\r
267             }\r
268             AbstractButton b = (AbstractButton) e.getSource();\r
269                         if (!((JSButtonUI) (ComponentUI) b.getUI()).verifyButtonClick(true))\r
270                                 return;\r
271                         \r
272                         //System.out.println("JSButtonListener released " + b.getName() + " " + e);\r
273 \r
274             ButtonModel model = b.getModel();\r
275             model.setPressed(false);\r
276             model.setArmed(false);\r
277         }\r
278     };\r
279 \r
280     public void mouseEntered(MouseEvent e) {\r
281         AbstractButton b = (AbstractButton) e.getSource();\r
282         ButtonModel model = b.getModel();\r
283         if (b.isRolloverEnabled() && !SwingUtilities.isLeftMouseButton(e)) {\r
284             model.setRollover(true);\r
285         }\r
286         if (model.isPressed())\r
287                 model.setArmed(true);\r
288     };\r
289 \r
290     public void mouseExited(MouseEvent e) {\r
291         AbstractButton b = (AbstractButton) e.getSource();\r
292         ButtonModel model = b.getModel();\r
293         if(b.isRolloverEnabled()) {\r
294             model.setRollover(false);\r
295         }\r
296         model.setArmed(false);\r
297     };\r
298 \r
299 \r
300     /**\r
301      * Actions for Buttons. Two types of action are supported:\r
302      * pressed: Moves the button to a pressed state\r
303      * released: Disarms the button.\r
304      */\r
305     private static class Actions extends UIAction {\r
306         private static final String PRESS = "pressed";\r
307         private static final String RELEASE = "released";\r
308 \r
309         Actions(String name) {\r
310             super(name);\r
311         }\r
312 \r
313         public void actionPerformed(ActionEvent e) {\r
314             AbstractButton b = (AbstractButton)e.getSource();\r
315             String key = getName();\r
316             if (key == PRESS) {\r
317                 ButtonModel model = b.getModel();\r
318                 model.setArmed(true);\r
319                 model.setPressed(true);\r
320                 if(!b.hasFocus()) {\r
321                     b.requestFocus();\r
322                 }\r
323             }\r
324             else if (key == RELEASE) {\r
325                 ButtonModel model = b.getModel();\r
326                 model.setPressed(false);\r
327                 model.setArmed(false);\r
328             }\r
329         }\r
330 \r
331         public boolean isEnabled(Object sender) {\r
332             if(sender != null && (sender instanceof AbstractButton) &&\r
333                       !((AbstractButton)sender).getModel().isEnabled()) {\r
334                 return false;\r
335             } else {\r
336                 return true;\r
337             }\r
338         }\r
339     }\r
340 }\r
341