001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.palette.ui;
043:
044: import java.awt.Component;
045: import java.awt.dnd.Autoscroll;
046: import java.awt.event.FocusEvent;
047: import java.awt.event.FocusListener;
048: import java.awt.event.KeyEvent;
049: import javax.swing.*;
050: import javax.swing.border.CompoundBorder;
051: import java.awt.*;
052: import java.awt.event.ActionEvent;
053: import java.awt.event.ActionListener;
054: import org.netbeans.modules.palette.Category;
055: import org.netbeans.modules.palette.Utils;
056: import org.openide.awt.Mnemonics;
057: import org.openide.nodes.Node;
058: import org.openide.util.Utilities;
059:
060: /**
061: * @author David Kaspar, Jan Stola
062: */
063: class CategoryButton extends JCheckBox implements Autoscroll {
064:
065: private static final Color AQUA_BK_COLOR = new Color(225, 235, 240);
066:
067: static final boolean isGTK = "GTK".equals(UIManager
068: .getLookAndFeel().getID());
069: static final boolean isAqua = "Aqua".equals(UIManager
070: .getLookAndFeel().getID());
071:
072: private CategoryDescriptor descriptor;
073: private Category category;
074:
075: private AutoscrollSupport support;
076:
077: // Workaround for JDK bug in GTK #6527149 - use Metal UI class
078: static {
079: if (isGTK) {
080: UIManager.put("MetalCheckBoxUI_4_GTK",
081: "javax.swing.plaf.metal.MetalCheckBoxUI");
082: }
083: }
084:
085: @Override
086: public String getUIClassID() {
087: String classID = super .getUIClassID();
088: if (isGTK) {
089: classID = "MetalCheckBoxUI_4_GTK";
090: }
091: return classID;
092: }
093:
094: CategoryButton(CategoryDescriptor descriptor, Category category) {
095: this .descriptor = descriptor;
096: this .category = category;
097:
098: //force initialization of PropSheet look'n'feel values
099: UIManager.get("nb.propertysheet");
100:
101: setFont(getFont().deriveFont(Font.BOLD));
102: setMargin(new Insets(0, 3, 0, 3));
103: setFocusPainted(false);
104:
105: setSelected(false);
106:
107: setHorizontalAlignment(SwingConstants.LEFT);
108: setHorizontalTextPosition(SwingConstants.RIGHT);
109: setVerticalTextPosition(SwingConstants.CENTER);
110:
111: updateProperties();
112:
113: if (getBorder() instanceof CompoundBorder) { // from BasicLookAndFeel
114: Dimension pref = getPreferredSize();
115: pref.height -= 3;
116: setPreferredSize(pref);
117: }
118:
119: addActionListener(new ActionListener() {
120: public void actionPerformed(ActionEvent e) {
121: boolean opened = !CategoryButton.this .descriptor
122: .isOpened();
123: setExpanded(opened);
124: }
125: });
126:
127: addFocusListener(new FocusListener() {
128: public void focusGained(FocusEvent e) {
129: scrollRectToVisible(getBounds());
130: }
131:
132: public void focusLost(FocusEvent e) {
133: }
134: });
135:
136: initActions();
137: }
138:
139: private void initActions() {
140: InputMap inputMap = getInputMap(WHEN_FOCUSED);
141: inputMap.put(
142: KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false),
143: "moveFocusDown"); //NOI18N
144: inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false),
145: "moveFocusUp"); //NOI18N
146: inputMap.put(
147: KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false),
148: "collapse"); //NOI18N
149: inputMap.put(KeyStroke
150: .getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "expand"); //NOI18N
151: inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F10,
152: KeyEvent.SHIFT_DOWN_MASK, false), "popup"); //NOI18N
153: inputMap.put(KeyStroke.getKeyStroke("ctrl V"), "paste"); //NOI18N //NOI18N
154: inputMap.put(KeyStroke.getKeyStroke("PASTE"), "paste"); //NOI18N //NOI18N
155:
156: ActionMap actionMap = getActionMap();
157: actionMap.put("moveFocusDown", new MoveFocusAction(true)); //NOI18N
158: actionMap.put("moveFocusUp", new MoveFocusAction(false)); //NOI18N
159: actionMap.put("collapse", new ExpandAction(false)); //NOI18N
160: actionMap.put("expand", new ExpandAction(true)); //NOI18N
161: actionMap.put("popup", new PopupAction()); //NOI18N
162: Node categoryNode = (Node) category.getLookup().lookup(
163: Node.class);
164: if (null != categoryNode)
165: actionMap.put("paste", new Utils.PasteItemAction(
166: categoryNode)); //NOI18N
167: }
168:
169: void updateProperties() {
170: setIcon((Icon) UIManager.get("Tree.collapsedIcon"));
171: setSelectedIcon((Icon) UIManager.get("Tree.expandedIcon"));
172: Mnemonics.setLocalizedText(this , category.getDisplayName());
173: setToolTipText(category.getShortDescription());
174: getAccessibleContext().setAccessibleName(
175: category.getDisplayName());
176: getAccessibleContext().setAccessibleDescription(
177: category.getShortDescription());
178: }
179:
180: Category getCategory() {
181: return category;
182: }
183:
184: /** notify the Component to autoscroll */
185: public void autoscroll(Point cursorLoc) {
186: Point p = SwingUtilities.convertPoint(this , cursorLoc,
187: getParent().getParent());
188: getSupport().autoscroll(p);
189: }
190:
191: /** @return the Insets describing the autoscrolling
192: * region or border relative to the geometry of the
193: * implementing Component.
194: */
195: public Insets getAutoscrollInsets() {
196: return getSupport().getAutoscrollInsets();
197: }
198:
199: boolean isExpanded() {
200: return isSelected();
201: }
202:
203: void setExpanded(boolean expand) {
204: setSelected(expand);
205: descriptor.setOpened(expand);
206: descriptor.getPalettePanel().computeHeights(
207: expand ? CategoryButton.this .category : null);
208: requestFocus();
209: }
210:
211: /** Safe getter for autoscroll support. */
212: AutoscrollSupport getSupport() {
213: if (null == support) {
214: support = new AutoscrollSupport(PalettePanel.getDefault());
215: }
216:
217: return support;
218: }
219:
220: public Color getBackground() {
221: if (isFocusOwner()) {
222: if (isAqua)
223: return UIManager.getColor("Table.selectionBackground"); //NOI18N
224: return UIManager
225: .getColor("PropSheet.selectedSetBackground"); //NOI18N
226: } else {
227: if (isAqua) {
228: return AQUA_BK_COLOR;
229: } else {
230: return UIManager.getColor("PropSheet.setBackground"); //NOI18N
231: }
232: }
233: }
234:
235: public Color getForeground() {
236: if (isFocusOwner()) {
237: if (isAqua)
238: return UIManager.getColor("Table.selectionForeground"); //NOI18N
239: return UIManager
240: .getColor("PropSheet.selectedSetForeground"); //NOI18N
241: } else {
242: return super .getForeground();
243: }
244: }
245:
246: private class MoveFocusAction extends AbstractAction {
247: private boolean moveDown;
248:
249: public MoveFocusAction(boolean moveDown) {
250: this .moveDown = moveDown;
251: }
252:
253: public void actionPerformed(ActionEvent e) {
254: KeyboardFocusManager kfm = KeyboardFocusManager
255: .getCurrentKeyboardFocusManager();
256: Container container = kfm.getCurrentFocusCycleRoot();
257: FocusTraversalPolicy policy = container
258: .getFocusTraversalPolicy();
259: if (null == policy)
260: policy = kfm.getDefaultFocusTraversalPolicy();
261: Component next = moveDown ? policy.getComponentAfter(
262: container, CategoryButton.this ) : policy
263: .getComponentBefore(container, CategoryButton.this );
264: if (null != next && next instanceof CategoryList) {
265: if (((CategoryList) next).getModel().getSize() != 0) {
266: ((CategoryList) next)
267: .takeFocusFrom(CategoryButton.this );
268: return;
269: } else {
270: next = moveDown ? policy.getComponentAfter(
271: container, next) : policy
272: .getComponentBefore(container, next);
273: }
274: }
275: if (null != next && next instanceof CategoryButton) {
276: next.requestFocus();
277: }
278: }
279: }
280:
281: private class ExpandAction extends AbstractAction {
282: private boolean expand;
283:
284: public ExpandAction(boolean expand) {
285: this .expand = expand;
286: }
287:
288: public void actionPerformed(ActionEvent e) {
289: if (expand == isExpanded())
290: return;
291: setExpanded(expand);
292: }
293: }
294:
295: private class PopupAction extends AbstractAction {
296:
297: public void actionPerformed(ActionEvent e) {
298: Action[] actions = category.getActions();
299: JPopupMenu popup = Utilities.actionsToPopup(actions,
300: CategoryButton.this );
301: Utils.addCustomizationMenuItems(popup, descriptor
302: .getPalettePanel().getController(), descriptor
303: .getPalettePanel().getSettings());
304: popup.show(getParent(), 0, getHeight());
305: }
306: }
307: }
|