001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Vadim L. Bogdanov
020: * @version $Revision$
021: */package javax.swing.plaf.basic;
022:
023: import java.awt.Component;
024: import java.awt.KeyboardFocusManager;
025: import java.awt.Point;
026: import java.awt.event.ActionEvent;
027: import java.beans.PropertyChangeEvent;
028: import java.beans.PropertyChangeListener;
029:
030: import javax.swing.AbstractAction;
031: import javax.swing.ActionMap;
032: import javax.swing.InputMap;
033: import javax.swing.JButton;
034: import javax.swing.JComponent;
035: import javax.swing.JPopupMenu;
036: import javax.swing.JRootPane;
037: import javax.swing.KeyStroke;
038: import javax.swing.LookAndFeel;
039: import javax.swing.SwingUtilities;
040: import javax.swing.UIManager;
041: import javax.swing.plaf.ActionMapUIResource;
042: import javax.swing.plaf.ComponentUI;
043: import javax.swing.plaf.RootPaneUI;
044:
045: import org.apache.harmony.x.swing.Utilities;
046:
047: public class BasicRootPaneUI extends RootPaneUI implements
048: PropertyChangeListener {
049:
050: /*
051: * The place to store the shared instance UI.
052: */
053: private static BasicRootPaneUI ui;
054:
055: /*
056: * The class for actions that reside in ActionMap.
057: */
058: private class DefaultButtonAction extends AbstractAction {
059: private JRootPane root;
060: private boolean press;
061:
062: public DefaultButtonAction(final JRootPane root,
063: final boolean press) {
064: this .root = root;
065: this .press = press;
066: }
067:
068: public boolean isEnabled() {
069: JButton defaultButton = root.getDefaultButton();
070: return (defaultButton == null) ? false : defaultButton
071: .isEnabled();
072: }
073:
074: public void actionPerformed(final ActionEvent e) {
075: if (isEnabled() && press) {
076: root.getDefaultButton().doClick(25);
077: }
078: }
079: }
080:
081: protected void installListeners(final JRootPane root) {
082: root.addPropertyChangeListener(this );
083: }
084:
085: protected void uninstallListeners(final JRootPane root) {
086: root.removePropertyChangeListener(this );
087: }
088:
089: protected void installKeyboardActions(final JRootPane root) {
090: SwingUtilities.replaceUIActionMap(root, getActionMap(root));
091:
092: Utilities.installKeyboardActions(root,
093: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
094: "RootPane.ancestorInputMap",
095: "RootPane.ancestorInputMap.RightToLeft");
096: if (root.getDefaultButton() != null) {
097: loadDefaultButtonKeyBindings(root);
098: }
099: }
100:
101: protected void uninstallKeyboardActions(final JRootPane root) {
102: SwingUtilities.replaceUIActionMap(root, null);
103: Utilities.uninstallKeyboardActions(root,
104: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
105: }
106:
107: protected void installDefaults(final JRootPane root) {
108: // do nothing
109: }
110:
111: protected void uninstallDefaults(final JRootPane root) {
112: // do nothing
113: }
114:
115: protected void installComponents(final JRootPane root) {
116: // do nothing
117: }
118:
119: protected void uninstallComponents(final JRootPane root) {
120: // do nothing
121: }
122:
123: public void installUI(final JComponent c) {
124: JRootPane root = (JRootPane) c;
125: //Install any default property values for color, fonts, borders,
126: // icons, opacity, etc. on the component. Whenever possible,
127: // property values initialized by the client program should not be overridden
128: installDefaults(root);
129:
130: //Install a LayoutManager on the component if necessary
131:
132: //Create/add any required sub-components to the component
133: installComponents(root);
134:
135: //Create/install event listeners on the component
136:
137: //Create/install a PropertyChangeListener on the component in order to detect and respond to component property changes appropriately
138: installListeners(root);
139:
140: //Install keyboard UI (mnemonics, traversal, etc.) on the component
141: installKeyboardActions(root);
142:
143: //Initialize any appropriate instance data
144: }
145:
146: public void uninstallUI(final JComponent c) {
147: JRootPane root = (JRootPane) c;
148:
149: //Remove any UI-set borders from the component
150: uninstallDefaults(root);
151:
152: //Remove any UI-set layout managers on the component
153:
154: //Remove any UI-added sub-components from the component
155: uninstallComponents(root);
156:
157: //Remove any UI-added event/property listeners from the component
158: uninstallListeners(root);
159:
160: //Remove any UI-installed keyboard UI from the component
161: uninstallKeyboardActions(root);
162:
163: //Nullify any allocated instance data objects to allow for GC
164: }
165:
166: public void propertyChange(final PropertyChangeEvent e) {
167: if ("defaultButton".equals(e.getPropertyName())) {
168: if (e.getNewValue() == null) {
169: unloadDefaultButtonKeyBindings((JComponent) e
170: .getSource());
171: } else {
172: loadDefaultButtonKeyBindings((JComponent) e.getSource());
173: }
174: }
175: }
176:
177: public static ComponentUI createUI(final JComponent c) {
178: if (ui == null) {
179: ui = new BasicRootPaneUI();
180: }
181:
182: return ui;
183: }
184:
185: /*
186: * Create ActionMap if necessary, and return it.
187: */
188: private ActionMap getActionMap(final JRootPane root) {
189: // the action map cannot be shared
190: return createActionMap(root);
191: }
192:
193: /*
194: * Create a new instance of ActionMap.
195: */
196: private ActionMap createActionMap(final JRootPane root) {
197: ActionMapUIResource actionMap = new ActionMapUIResource();
198:
199: actionMap.put("press", new DefaultButtonAction(root, true));
200: actionMap.put("release", new DefaultButtonAction(root, false));
201: actionMap.put("postPopup", new AbstractAction() {
202: public void actionPerformed(final ActionEvent e) {
203: JComponent focusOwner = getFocusOwner();
204: JPopupMenu menu = focusOwner.getComponentPopupMenu();
205: if (menu == null) {
206: return;
207: }
208: Point location = focusOwner.getPopupLocation(null);
209: if (location == null) {
210: location = Utilities
211: .getMousePointerScreenLocation();
212: SwingUtilities.convertPointFromScreen(location,
213: focusOwner);
214: }
215:
216: menu.show(focusOwner, location.x, location.y);
217: }
218:
219: public boolean isEnabled() {
220: JComponent focusOwner = getFocusOwner();
221: return focusOwner != null
222: && focusOwner.getComponentPopupMenu() != null;
223: }
224:
225: private JComponent getFocusOwner() {
226: Component focusOwner = KeyboardFocusManager
227: .getCurrentKeyboardFocusManager()
228: .getFocusOwner();
229: return focusOwner instanceof JComponent ? (JComponent) focusOwner
230: : null;
231: }
232:
233: });
234:
235: return actionMap;
236: }
237:
238: /*
239: * Load key bindings from UIDefaults to InputMap. This occurs
240: * when the default button is assigned.
241: */
242: private void loadDefaultButtonKeyBindings(final JComponent root) {
243: Object[] bindings = ((Object[]) UIManager
244: .get("RootPane.defaultButtonWindowKeyBindings"));
245:
246: if (bindings != null) {
247: InputMap map = SwingUtilities.getUIInputMap(root,
248: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
249: LookAndFeel.loadKeyBindings(map, bindings);
250: }
251: }
252:
253: private void unloadDefaultButtonKeyBindings(final JComponent root) {
254: Object[] bindings = ((Object[]) UIManager
255: .get("RootPane.defaultButtonWindowKeyBindings"));
256:
257: if (bindings != null) {
258: InputMap map = SwingUtilities.getUIInputMap(root,
259: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
260: for (int i = 0; i < bindings.length; i += 2) {
261: if (bindings[i] instanceof String) {
262: map.remove(KeyStroke
263: .getKeyStroke((String) bindings[i]));
264: } else {
265: map.remove((KeyStroke) bindings[i]);
266: }
267: }
268: }
269: }
270: }
|