1 /*
2 * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.swing.plaf.basic;
27
28 import java.awt.event.ActionEvent;
29 import java.awt.KeyboardFocusManager;
30 import java.awt.Component;
31 import java.awt.Point;
32 import java.awt.Rectangle;
33 import java.beans.PropertyChangeEvent;
34 import java.beans.PropertyChangeListener;
35 import javax.swing;
36 import javax.swing.plaf;
37 import sun.swing.DefaultLookup;
38 import sun.swing.UIAction;
39
40 /**
41 * Basic implementation of RootPaneUI, there is one shared between all
42 * JRootPane instances.
43 *
44 * @author Scott Violet
45 * @since 1.3
46 */
47 public class BasicRootPaneUI extends RootPaneUI implements
48 PropertyChangeListener {
49 private static RootPaneUI rootPaneUI = new BasicRootPaneUI();
50
51 public static ComponentUI createUI(JComponent c) {
52 return rootPaneUI;
53 }
54
55 public void installUI(JComponent c) {
56 installDefaults((JRootPane)c);
57 installComponents((JRootPane)c);
58 installListeners((JRootPane)c);
59 installKeyboardActions((JRootPane)c);
60 }
61
62
63 public void uninstallUI(JComponent c) {
64 uninstallDefaults((JRootPane)c);
65 uninstallComponents((JRootPane)c);
66 uninstallListeners((JRootPane)c);
67 uninstallKeyboardActions((JRootPane)c);
68 }
69
70 protected void installDefaults(JRootPane c){
71 LookAndFeel.installProperty(c, "opaque", Boolean.FALSE);
72 }
73
74 protected void installComponents(JRootPane root) {
75 }
76
77 protected void installListeners(JRootPane root) {
78 root.addPropertyChangeListener(this);
79 }
80
81 protected void installKeyboardActions(JRootPane root) {
82 InputMap km = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, root);
83 SwingUtilities.replaceUIInputMap(root,
84 JComponent.WHEN_IN_FOCUSED_WINDOW, km);
85 km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
86 root);
87 SwingUtilities.replaceUIInputMap(root,
88 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km);
89
90 LazyActionMap.installLazyActionMap(root, BasicRootPaneUI.class,
91 "RootPane.actionMap");
92 updateDefaultButtonBindings(root);
93 }
94
95 protected void uninstallDefaults(JRootPane root) {
96 }
97
98 protected void uninstallComponents(JRootPane root) {
99 }
100
101 protected void uninstallListeners(JRootPane root) {
102 root.removePropertyChangeListener(this);
103 }
104
105 protected void uninstallKeyboardActions(JRootPane root) {
106 SwingUtilities.replaceUIInputMap(root, JComponent.
107 WHEN_IN_FOCUSED_WINDOW, null);
108 SwingUtilities.replaceUIActionMap(root, null);
109 }
110
111 InputMap getInputMap(int condition, JComponent c) {
112 if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
113 return (InputMap)DefaultLookup.get(c, this,
114 "RootPane.ancestorInputMap");
115 }
116
117 if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
118 return createInputMap(condition, c);
119 }
120 return null;
121 }
122
123 ComponentInputMap createInputMap(int condition, JComponent c) {
124 return new RootPaneInputMap(c);
125 }
126
127 static void loadActionMap(LazyActionMap map) {
128 map.put(new Actions(Actions.PRESS));
129 map.put(new Actions(Actions.RELEASE));
130 map.put(new Actions(Actions.POST_POPUP));
131 }
132
133 /**
134 * Invoked when the default button property has changed. This reloads
135 * the bindings from the defaults table with name
136 * <code>RootPane.defaultButtonWindowKeyBindings</code>.
137 */
138 void updateDefaultButtonBindings(JRootPane root) {
139 InputMap km = SwingUtilities.getUIInputMap(root, JComponent.
140 WHEN_IN_FOCUSED_WINDOW);
141 while (km != null && !(km instanceof RootPaneInputMap)) {
142 km = km.getParent();
143 }
144 if (km != null) {
145 km.clear();
146 if (root.getDefaultButton() != null) {
147 Object[] bindings = (Object[])DefaultLookup.get(root, this,
148 "RootPane.defaultButtonWindowKeyBindings");
149 if (bindings != null) {
150 LookAndFeel.loadKeyBindings(km, bindings);
151 }
152 }
153 }
154 }
155
156 /**
157 * Invoked when a property changes on the root pane. If the event
158 * indicates the <code>defaultButton</code> has changed, this will
159 * reinstall the keyboard actions.
160 */
161 public void propertyChange(PropertyChangeEvent e) {
162 if(e.getPropertyName().equals("defaultButton")) {
163 JRootPane rootpane = (JRootPane)e.getSource();
164 updateDefaultButtonBindings(rootpane);
165 if (rootpane.getClientProperty("temporaryDefaultButton") == null) {
166 rootpane.putClientProperty("initialDefaultButton", e.getNewValue());
167 }
168 }
169 }
170
171
172 static class Actions extends UIAction {
173 public static final String PRESS = "press";
174 public static final String RELEASE = "release";
175 public static final String POST_POPUP = "postPopup";
176
177 Actions(String name) {
178 super(name);
179 }
180
181 public void actionPerformed(ActionEvent evt) {
182 JRootPane root = (JRootPane)evt.getSource();
183 JButton owner = root.getDefaultButton();
184 String key = getName();
185
186 if (key == POST_POPUP) { // Action to post popup
187 Component c = KeyboardFocusManager
188 .getCurrentKeyboardFocusManager()
189 .getFocusOwner();
190
191 if(c instanceof JComponent) {
192 JComponent src = (JComponent) c;
193 JPopupMenu jpm = src.getComponentPopupMenu();
194 if(jpm != null) {
195 Point pt = src.getPopupLocation(null);
196 if(pt == null) {
197 Rectangle vis = src.getVisibleRect();
198 pt = new Point(vis.x+vis.width/2,
199 vis.y+vis.height/2);
200 }
201 jpm.show(c, pt.x, pt.y);
202 }
203 }
204 }
205 else if (owner != null
206 && SwingUtilities.getRootPane(owner) == root) {
207 if (key == PRESS) {
208 owner.doClick(20);
209 }
210 }
211 }
212
213 public boolean isEnabled(Object sender) {
214 String key = getName();
215 if(key == POST_POPUP) {
216 MenuElement[] elems = MenuSelectionManager
217 .defaultManager()
218 .getSelectedPath();
219 if(elems != null && elems.length != 0) {
220 return false;
221 // We shall not interfere with already opened menu
222 }
223
224 Component c = KeyboardFocusManager
225 .getCurrentKeyboardFocusManager()
226 .getFocusOwner();
227 if(c instanceof JComponent) {
228 JComponent src = (JComponent) c;
229 return src.getComponentPopupMenu() != null;
230 }
231
232 return false;
233 }
234
235 if (sender != null && sender instanceof JRootPane) {
236 JButton owner = ((JRootPane)sender).getDefaultButton();
237 return (owner != null && owner.getModel().isEnabled());
238 }
239 return true;
240 }
241 }
242
243 private static class RootPaneInputMap extends ComponentInputMapUIResource {
244 public RootPaneInputMap(JComponent c) {
245 super(c);
246 }
247 }
248 }