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.swing.tabcontrol.plaf;
043:
044: import java.awt.Component;
045: import java.awt.Dimension;
046: import java.awt.Font;
047: import java.awt.FontMetrics;
048: import java.awt.Graphics;
049: import java.awt.Graphics2D;
050: import java.awt.Insets;
051: import java.awt.Rectangle;
052: import org.netbeans.swing.tabcontrol.TabDisplayer;
053: import org.openide.awt.HtmlRenderer;
054:
055: import javax.swing.plaf.ComponentUI;
056: import java.awt.event.MouseEvent;
057: import java.util.HashMap;
058: import java.util.Map;
059: import javax.swing.Icon;
060: import javax.swing.JComponent;
061: import javax.swing.UIManager;
062:
063: /**
064: * A view tabs ui for OS-X adapted from the view tabs UI for Metal.
065: *
066: * @author Tim Boudreau
067: */
068: public final class AquaViewTabDisplayerUI extends
069: AbstractViewTabDisplayerUI {
070:
071: private static final int TXT_X_PAD = 5;
072: private static final int ICON_X_PAD = 2;
073:
074: /********* static fields ***********/
075:
076: private static Map<Integer, String[]> buttonIconPaths;
077:
078: /**
079: * ******* instance fields *********
080: */
081:
082: private Dimension prefSize;
083: /**
084: * Reusable Rectangle to optimize rectangle creation/garbage collection
085: * during paints
086: */
087: private Rectangle tempRect = new Rectangle();
088:
089: /**
090: * Should be constructed only from createUI method.
091: */
092: private AquaViewTabDisplayerUI(TabDisplayer displayer) {
093: super (displayer);
094: prefSize = new Dimension(100, 19); //XXX huh?
095: }
096:
097: public static ComponentUI createUI(JComponent c) {
098: return new AquaViewTabDisplayerUI((TabDisplayer) c);
099: }
100:
101: protected AbstractViewTabDisplayerUI.Controller createController() {
102: return new OwnController();
103: }
104:
105: public Dimension getPreferredSize(JComponent c) {
106: FontMetrics fm = getTxtFontMetrics();
107: int height = fm == null ? 21 : fm.getAscent() + 2
108: * fm.getDescent() + 3;
109: Insets insets = c.getInsets();
110: prefSize.height = height + insets.bottom + insets.top;
111: return prefSize;
112: }
113:
114: public void paint(Graphics g, JComponent c) {
115: ColorUtil.setupAntialiasing(g);
116: super .paint(g, c);
117: paintBottomBorder(g, c);
118: }
119:
120: protected Font getTxtFont() {
121: return getDisplayer().getFont();
122: }
123:
124: /**
125: * Paints bottom "activation" line
126: */
127: private void paintBottomBorder(Graphics g, JComponent c) {
128: }
129:
130: protected void paintTabContent(Graphics g, int index, String text,
131: int x, int y, int width, int height) {
132: FontMetrics fm = getTxtFontMetrics();
133:
134: // setting font already here to compute string width correctly
135: g.setFont(getTxtFont());
136: int textW = width;
137:
138: if (isSelected(index)) {
139: Component buttons = getControlButtons();
140: if (null != buttons) {
141: Dimension buttonsSize = buttons.getPreferredSize();
142:
143: textW = width
144: - (buttonsSize.width + ICON_X_PAD + 2 * TXT_X_PAD);
145: if (index == getDataModel().size() - 1) {
146: textW -= 3;
147: }
148: buttons.setLocation(x + textW + 2 * TXT_X_PAD, y
149: + (height - buttonsSize.height) / 2);
150: }
151: } else {
152: textW = width - 2 * TXT_X_PAD;
153: }
154:
155: if (text.length() == 0) {
156: return;
157: }
158:
159: int textHeight = fm.getHeight();
160: int textY;
161: int textX = x + TXT_X_PAD;
162: if (index == 0)
163: textX = x + 5;
164:
165: if (textHeight > height) {
166: textY = (-1 * ((textHeight - height) / 2)) + fm.getAscent()
167: - 1;
168: } else {
169: textY = (height / 2) - (textHeight / 2) + fm.getAscent();
170: }
171:
172: HtmlRenderer.renderString(text, g, textX, textY, textW, height,
173: getTxtFont(), UIManager.getColor("textText"),
174: HtmlRenderer.STYLE_TRUNCATE, true);
175: }
176:
177: protected void paintTabBorder(Graphics g, int index, int x, int y,
178: int width, int height) {
179:
180: }
181:
182: private static final ChicletWrapper chiclet = new ChicletWrapper();
183:
184: protected void paintTabBackground(Graphics g, int index, int x,
185: int y, int width, int height) {
186: boolean first = index == 0;
187: boolean last = index == getDataModel().size() - 1;
188: int state = 0;
189: if (isActive()) {
190: state |= GenericGlowingChiclet.STATE_ACTIVE;
191: }
192: if (isSelected(index)) {
193: state |= GenericGlowingChiclet.STATE_SELECTED;
194: }
195: if (isAttention(index)) {
196: state |= GenericGlowingChiclet.STATE_ATTENTION;
197: }
198:
199: y += 1; //align with top of editor tabs
200:
201: chiclet.setState(state);
202: chiclet.setBounds(x, y, width, height);
203: chiclet.setArcs(first ? 0.5f : 0f, last ? 0.5f : 0f,
204: first ? 0.0f : 0f, last ? 0.0f : 0f);
205: chiclet.setNotch(false, false);
206: g.translate(x, y);
207: chiclet.draw((Graphics2D) g);
208: g.translate(-x, -y);
209: }
210:
211: private boolean containsMouse = false;
212:
213: private void setContainsMouse(boolean val) {
214: if (val != containsMouse) {
215: containsMouse = val;
216: getDisplayer().repaint();
217: }
218: }
219:
220: private boolean isContainsMouse() {
221: return containsMouse;
222: }
223:
224: private static void initIcons() {
225: //TODO add icons for aqua l&f
226:
227: if (null == buttonIconPaths) {
228: buttonIconPaths = new HashMap<Integer, String[]>(7);
229:
230: //close button
231: String[] iconPaths = new String[4];
232: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/mac_bigclose_enabled.png"; // NOI18N
233: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/mac_bigclose_pressed.png"; // NOI18N
234: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
235: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/mac_bigclose_rollover.png"; // NOI18N
236: buttonIconPaths.put(TabControlButton.ID_CLOSE_BUTTON,
237: iconPaths);
238:
239: //slide/pin button
240: iconPaths = new String[4];
241: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/mac_slideright_enabled.png"; // NOI18N
242: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/mac_slideright_pressed.png"; // NOI18N
243: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
244: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/mac_slideright_rollover.png"; // NOI18N
245: buttonIconPaths.put(TabControlButton.ID_SLIDE_RIGHT_BUTTON,
246: iconPaths);
247:
248: iconPaths = new String[4];
249: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/mac_slideleft_enabled.png"; // NOI18N
250: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/mac_slideleft_pressed.png"; // NOI18N
251: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
252: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/mac_slideleft_rollover.png"; // NOI18N
253: buttonIconPaths.put(TabControlButton.ID_SLIDE_LEFT_BUTTON,
254: iconPaths);
255:
256: iconPaths = new String[4];
257: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/mac_slidebottom_enabled.png"; // NOI18N
258: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/mac_slidebottom_pressed.png"; // NOI18N
259: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
260: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/mac_slidebottom_rollover.png"; // NOI18N
261: buttonIconPaths.put(TabControlButton.ID_SLIDE_DOWN_BUTTON,
262: iconPaths);
263:
264: iconPaths = new String[4];
265: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/mac_pin_enabled.png"; // NOI18N
266: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/mac_pin_pressed.png"; // NOI18N
267: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
268: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/mac_pin_rollover.png"; // NOI18N
269: buttonIconPaths.put(TabControlButton.ID_PIN_BUTTON,
270: iconPaths);
271: }
272: }
273:
274: public Icon getButtonIcon(int buttonId, int buttonState) {
275: Icon res = null;
276: initIcons();
277: String[] paths = buttonIconPaths.get(buttonId);
278: if (null != paths && buttonState >= 0
279: && buttonState < paths.length) {
280: res = TabControlButtonFactory.getIcon(paths[buttonState]);
281: }
282: return res;
283: }
284:
285: /**
286: * Own close icon button controller
287: */
288: private class OwnController extends Controller {
289:
290: public void mouseEntered(MouseEvent me) {
291: super .mouseEntered(me);
292: setContainsMouse(true);
293: }
294:
295: public void mouseExited(MouseEvent me) {
296: super .mouseExited(me);
297: setContainsMouse(false);
298: }
299: } // end of OwnController
300:
301: }
|