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: * AquaEditorTabCellRenderer.java
043: *
044: * Created on December 28, 2003, 12:04 AM
045: */
046:
047: package org.netbeans.swing.tabcontrol.plaf;
048:
049: import java.awt.Component;
050: import java.awt.Dimension;
051: import java.awt.Graphics;
052: import java.awt.Graphics2D;
053: import java.awt.Insets;
054: import java.awt.Polygon;
055: import java.awt.Rectangle;
056: import javax.swing.Icon;
057: import javax.swing.JComponent;
058:
059: /**
060: * A tab cell renderer for OS-X. Basically does its work by subclassing JButton
061: * and doing some tricks to use it as a cell renderer, so the Aqua borders do
062: * all the heavy eye-candy lifting (how's that for mixed metaphors?)
063: *
064: * @author Tim Boudreau
065: */
066: final class AquaEditorTabCellRenderer extends AbstractTabCellRenderer {
067: private static final AquaTabPainter AquaTabPainter = new AquaTabPainter();
068:
069: static final int TOP_INSET = 0;
070: static final int LEFT_INSET = 3;
071: static final int RIGHT_INSET = 6;
072: static final int BOTTOM_INSET = 2;
073:
074: private static final ChicletWrapper chiclet = new ChicletWrapper();
075:
076: public AquaEditorTabCellRenderer() {
077: super (AquaTabPainter, AquaTabPainter, AquaTabPainter,
078: new Dimension(23, 8));
079: }
080:
081: protected int getCaptionYAdjustment() {
082: return 0;
083: }
084:
085: protected int getIconYAdjustment() {
086: return -1;
087: }
088:
089: public Dimension getPadding() {
090: Dimension d = super .getPadding();
091: d.width = isShowCloseButton()
092: && !Boolean.getBoolean("nb.tabs.suppressCloseButton") ? 26
093: : 13;
094: return d;
095: }
096:
097: private static class AquaTabPainter implements TabPainter {
098: private static Insets insets = new Insets(TOP_INSET,
099: LEFT_INSET, BOTTOM_INSET, RIGHT_INSET);
100:
101: public AquaTabPainter() {
102: }
103:
104: public Insets getBorderInsets(Component c) {
105: boolean leftmost = ((AquaEditorTabCellRenderer) c)
106: .isLeftmost();
107:
108: if (leftmost) {
109: return new Insets(TOP_INSET, LEFT_INSET + 4,
110: BOTTOM_INSET, RIGHT_INSET);
111: } else {
112: return insets;
113: }
114: }
115:
116: public void getCloseButtonRectangle(JComponent jc,
117: Rectangle rect, Rectangle bounds) {
118: boolean rightClip = ((AquaEditorTabCellRenderer) jc)
119: .isClipRight();
120: boolean leftClip = ((AquaEditorTabCellRenderer) jc)
121: .isClipLeft();
122: boolean notSupported = !((AbstractTabCellRenderer) jc)
123: .isShowCloseButton();
124: if (leftClip || rightClip || notSupported) {
125: rect.x = -100;
126: rect.y = -100;
127: rect.width = 0;
128: rect.height = 0;
129: } else {
130: String iconPath = findIconPath((AquaEditorTabCellRenderer) jc);
131: Icon icon = TabControlButtonFactory.getIcon(iconPath);
132: int iconWidth = icon.getIconWidth();
133: int iconHeight = icon.getIconHeight();
134: rect.x = bounds.x + bounds.width - iconWidth - 2;
135: rect.y = bounds.y
136: + (Math.max(0, bounds.height / 2 - iconHeight
137: / 2));
138: rect.width = iconWidth;
139: rect.height = iconHeight;
140: }
141: }
142:
143: /**
144: * Returns path of icon which is correct for currect state of tab at given
145: * index
146: */
147: private String findIconPath(AquaEditorTabCellRenderer renderer) {
148: if (renderer.inCloseButton() && renderer.isPressed()) {
149: return "org/netbeans/swing/tabcontrol/resources/mac_close_pressed.png"; // NOI18N
150: }
151: if (renderer.inCloseButton()) {
152: return "org/netbeans/swing/tabcontrol/resources/mac_close_rollover.png"; // NOI18N
153: }
154: return "org/netbeans/swing/tabcontrol/resources/mac_close_enabled.png"; // NOI18N
155: }
156:
157: private void paintCloseButton(Graphics g, JComponent c) {
158: if (((AbstractTabCellRenderer) c).isShowCloseButton()) {
159:
160: Rectangle r = new Rectangle(0, 0, c.getWidth(), c
161: .getHeight());
162: Rectangle cbRect = new Rectangle();
163: getCloseButtonRectangle((JComponent) c, cbRect, r);
164:
165: //paint close button
166: String iconPath = findIconPath((AquaEditorTabCellRenderer) c);
167: Icon icon = TabControlButtonFactory.getIcon(iconPath);
168: icon.paintIcon(c, g, cbRect.x, cbRect.y);
169: }
170: }
171:
172: public Polygon getInteriorPolygon(Component c) {
173: return new Polygon(new int[] { 0, c.getWidth(),
174: c.getWidth(), 0 }, new int[] { 0, 0, c.getHeight(),
175: c.getHeight() }, 4);
176: }
177:
178: public boolean isBorderOpaque() {
179: return false;
180: }
181:
182: public void paintBorder(Component c, Graphics g, int x, int y,
183: int width, int height) {
184: paintCloseButton(g, (JComponent) c);
185: }
186:
187: public void paintInterior(Graphics g, Component c) {
188: if (true) {
189: Rectangle bds = c.getBounds();
190:
191: boolean rightmost = ((AquaEditorTabCellRenderer) c)
192: .isRightmost();
193: boolean rightClip = ((AquaEditorTabCellRenderer) c)
194: .isClipRight();
195: boolean sel = ((AquaEditorTabCellRenderer) c)
196: .isSelected();
197: boolean active = ((AquaEditorTabCellRenderer) c)
198: .isActive();
199: boolean pressed = ((AquaEditorTabCellRenderer) c)
200: .isPressed();
201: boolean leftClip = ((AquaEditorTabCellRenderer) c)
202: .isClipLeft();
203: boolean leftmost = ((AquaEditorTabCellRenderer) c)
204: .isLeftmost();
205: boolean closing = pressed
206: && ((AquaEditorTabCellRenderer) c)
207: .inCloseButton();
208: boolean attention = !pressed
209: && !closing
210: && ((AquaEditorTabCellRenderer) c)
211: .isAttention();
212:
213: //add in a pixel for rightmost/leftmost so we don't clip off
214: //antialiasing of the curve
215: chiclet.setBounds(0, 0, bds.width, bds.height);
216:
217: chiclet.setNotch(rightClip, leftClip);
218: int state = 0;
219: float leftarc = leftmost && !leftClip ? 0.5f : 0f;
220: float rightarc = rightmost && !rightClip ? 0.5f : 0f;
221:
222: if (pressed && (rightClip || leftClip)) {
223: state |= GenericGlowingChiclet.STATE_PRESSED;
224: }
225: if (active) {
226: state |= GenericGlowingChiclet.STATE_ACTIVE;
227: }
228: if (sel) {
229: state |= GenericGlowingChiclet.STATE_SELECTED;
230: }
231: if (closing) {
232: state |= GenericGlowingChiclet.STATE_CLOSING;
233: }
234: if (attention) {
235: state |= GenericGlowingChiclet.STATE_ATTENTION;
236: }
237: chiclet.setArcs(leftarc, rightarc, leftarc, rightarc);
238:
239: chiclet.setState(state);
240: chiclet.draw((Graphics2D) g);
241: return;
242: }
243: }
244:
245: public boolean supportsCloseButton(JComponent c) {
246: boolean leftClip = ((AquaEditorTabCellRenderer) c)
247: .isClipLeft();
248: boolean rightClip = ((AquaEditorTabCellRenderer) c)
249: .isClipRight();
250: boolean supported = ((AquaEditorTabCellRenderer) c)
251: .isShowCloseButton();
252: return !leftClip && !rightClip && supported;
253: }
254:
255: }
256: }
|