001 /*
002 * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.swing.plaf.basic;
027
028 import java.awt.event.ActionEvent;
029 import java.awt.KeyboardFocusManager;
030 import java.awt.Component;
031 import java.awt.Point;
032 import java.awt.Rectangle;
033 import java.beans.PropertyChangeEvent;
034 import java.beans.PropertyChangeListener;
035 import javax.swing.*;
036 import javax.swing.plaf.*;
037 import sun.swing.DefaultLookup;
038 import sun.swing.UIAction;
039
040 /**
041 * Basic implementation of RootPaneUI, there is one shared between all
042 * JRootPane instances.
043 *
044 * @version 1.23 05/05/07
045 * @author Scott Violet
046 * @since 1.3
047 */
048 public class BasicRootPaneUI extends RootPaneUI implements
049 PropertyChangeListener {
050 private static RootPaneUI rootPaneUI = new BasicRootPaneUI();
051
052 public static ComponentUI createUI(JComponent c) {
053 return rootPaneUI;
054 }
055
056 public void installUI(JComponent c) {
057 installDefaults((JRootPane) c);
058 installComponents((JRootPane) c);
059 installListeners((JRootPane) c);
060 installKeyboardActions((JRootPane) c);
061 }
062
063 public void uninstallUI(JComponent c) {
064 uninstallDefaults((JRootPane) c);
065 uninstallComponents((JRootPane) c);
066 uninstallListeners((JRootPane) c);
067 uninstallKeyboardActions((JRootPane) c);
068 }
069
070 protected void installDefaults(JRootPane c) {
071 LookAndFeel.installProperty(c, "opaque", Boolean.FALSE);
072 }
073
074 protected void installComponents(JRootPane root) {
075 }
076
077 protected void installListeners(JRootPane root) {
078 root.addPropertyChangeListener(this );
079 }
080
081 protected void installKeyboardActions(JRootPane root) {
082 InputMap km = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW,
083 root);
084 SwingUtilities.replaceUIInputMap(root,
085 JComponent.WHEN_IN_FOCUSED_WINDOW, km);
086 km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
087 root);
088 SwingUtilities.replaceUIInputMap(root,
089 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km);
090
091 LazyActionMap.installLazyActionMap(root, BasicRootPaneUI.class,
092 "RootPane.actionMap");
093 updateDefaultButtonBindings(root);
094 }
095
096 protected void uninstallDefaults(JRootPane root) {
097 }
098
099 protected void uninstallComponents(JRootPane root) {
100 }
101
102 protected void uninstallListeners(JRootPane root) {
103 root.removePropertyChangeListener(this );
104 }
105
106 protected void uninstallKeyboardActions(JRootPane root) {
107 SwingUtilities.replaceUIInputMap(root,
108 JComponent.WHEN_IN_FOCUSED_WINDOW, null);
109 SwingUtilities.replaceUIActionMap(root, null);
110 }
111
112 InputMap getInputMap(int condition, JComponent c) {
113 if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
114 return (InputMap) DefaultLookup.get(c, this ,
115 "RootPane.ancestorInputMap");
116 }
117
118 if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
119 return createInputMap(condition, c);
120 }
121 return null;
122 }
123
124 ComponentInputMap createInputMap(int condition, JComponent c) {
125 return new RootPaneInputMap(c);
126 }
127
128 static void loadActionMap(LazyActionMap map) {
129 map.put(new Actions(Actions.PRESS));
130 map.put(new Actions(Actions.RELEASE));
131 map.put(new Actions(Actions.POST_POPUP));
132 }
133
134 /**
135 * Invoked when the default button property has changed. This reloads
136 * the bindings from the defaults table with name
137 * <code>RootPane.defaultButtonWindowKeyBindings</code>.
138 */
139 void updateDefaultButtonBindings(JRootPane root) {
140 InputMap km = SwingUtilities.getUIInputMap(root,
141 JComponent.WHEN_IN_FOCUSED_WINDOW);
142 while (km != null && !(km instanceof RootPaneInputMap)) {
143 km = km.getParent();
144 }
145 if (km != null) {
146 km.clear();
147 if (root.getDefaultButton() != null) {
148 Object[] bindings = (Object[]) DefaultLookup
149 .get(root, this ,
150 "RootPane.defaultButtonWindowKeyBindings");
151 if (bindings != null) {
152 LookAndFeel.loadKeyBindings(km, bindings);
153 }
154 }
155 }
156 }
157
158 /**
159 * Invoked when a property changes on the root pane. If the event
160 * indicates the <code>defaultButton</code> has changed, this will
161 * reinstall the keyboard actions.
162 */
163 public void propertyChange(PropertyChangeEvent e) {
164 if (e.getPropertyName().equals("defaultButton")) {
165 JRootPane rootpane = (JRootPane) e.getSource();
166 updateDefaultButtonBindings(rootpane);
167 if (rootpane.getClientProperty("temporaryDefaultButton") == null) {
168 rootpane.putClientProperty("initialDefaultButton", e
169 .getNewValue());
170 }
171 }
172 }
173
174 static class Actions extends UIAction {
175 public static final String PRESS = "press";
176 public static final String RELEASE = "release";
177 public static final String POST_POPUP = "postPopup";
178
179 Actions(String name) {
180 super (name);
181 }
182
183 public void actionPerformed(ActionEvent evt) {
184 JRootPane root = (JRootPane) evt.getSource();
185 JButton owner = root.getDefaultButton();
186 String key = getName();
187
188 if (key == POST_POPUP) { // Action to post popup
189 Component c = KeyboardFocusManager
190 .getCurrentKeyboardFocusManager()
191 .getFocusOwner();
192
193 if (c instanceof JComponent) {
194 JComponent src = (JComponent) c;
195 JPopupMenu jpm = src.getComponentPopupMenu();
196 if (jpm != null) {
197 Point pt = src.getPopupLocation(null);
198 if (pt == null) {
199 Rectangle vis = src.getVisibleRect();
200 pt = new Point(vis.x + vis.width / 2, vis.y
201 + vis.height / 2);
202 }
203 jpm.show(c, pt.x, pt.y);
204 }
205 }
206 } else if (owner != null
207 && SwingUtilities.getRootPane(owner) == root) {
208 if (key == PRESS) {
209 owner.doClick(20);
210 }
211 }
212 }
213
214 public boolean isEnabled(Object sender) {
215 String key = getName();
216 if (key == POST_POPUP) {
217 MenuElement[] elems = MenuSelectionManager
218 .defaultManager().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
244 ComponentInputMapUIResource {
245 public RootPaneInputMap(JComponent c) {
246 super(c);
247 }
248 }
249 }
|