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.Color;
045: import java.awt.Component;
046: import java.awt.Dimension;
047: import java.awt.Font;
048: import java.awt.FontMetrics;
049: import java.awt.Graphics;
050: import java.awt.Graphics2D;
051: import java.awt.Insets;
052: import java.awt.Paint;
053: import java.awt.Rectangle;
054: import org.netbeans.swing.tabcontrol.TabDisplayer;
055:
056: import javax.swing.plaf.ComponentUI;
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: import org.openide.awt.HtmlRenderer;
063:
064: /**
065: * Windows classic-like user interface of view type tabs. Implements Border just
066: * to save one class, change if apropriate.
067: *
068: * @author Dafe Simonek
069: */
070: public final class WinClassicViewTabDisplayerUI extends
071: AbstractViewTabDisplayerUI {
072:
073: private static final boolean isGenericUI = !"Windows"
074: .equals(UIManager.getLookAndFeel().getID()); //NOI18N
075:
076: private static final Color GTK_TABBED_PANE_BACKGROUND_1 = new Color(
077: 255, 255, 255);
078:
079: /**
080: * ******** constants ************
081: */
082:
083: private static final int BUMP_X_PAD = isGenericUI ? 0 : 3;
084: private static final int BUMP_WIDTH = isGenericUI ? 0 : 3;
085: private static final int TXT_X_PAD = isGenericUI ? 3 : BUMP_X_PAD
086: + BUMP_WIDTH + 5;
087: private static final int TXT_Y_PAD = 3;
088:
089: private static final int ICON_X_PAD = 2;
090:
091: private static Map<Integer, String[]> buttonIconPaths;
092:
093: /**
094: * ******** instance fields ********
095: */
096:
097: private Dimension prefSize;
098:
099: /**
100: * Reusable Rectangle to optimize rectangle creation/garbage collection
101: * during paints
102: */
103: private Rectangle tempRect = new Rectangle();
104:
105: /**
106: * Should be constructed only from createUI method.
107: */
108: private WinClassicViewTabDisplayerUI(TabDisplayer displayer) {
109: super (displayer);
110: prefSize = new Dimension(100, 19);
111: }
112:
113: public static ComponentUI createUI(JComponent c) {
114: return new WinClassicViewTabDisplayerUI((TabDisplayer) c);
115: }
116:
117: public Dimension getPreferredSize(JComponent c) {
118: FontMetrics fm = getTxtFontMetrics();
119: int height = fm == null ? 19 : fm.getAscent() + 2
120: * fm.getDescent() + 2;
121: Insets insets = c.getInsets();
122: prefSize.height = height + insets.bottom + insets.top;
123: return prefSize;
124: }
125:
126: /**
127: * adds painting of overall border
128: */
129: public void paint(Graphics g, JComponent c) {
130:
131: ColorUtil.setupAntialiasing(g);
132:
133: Color col = c.getBackground();
134: if (col != null) {
135: g.setColor(col);
136: g.fillRect(0, 0, c.getWidth(), c.getHeight());
137: }
138: paintOverallBorder(g, c);
139: super .paint(g, c);
140: }
141:
142: /**
143: * Paints lower border, bottom line, separating tabs from content
144: */
145: protected void paintOverallBorder(Graphics g, JComponent c) {
146: if (isGenericUI) {
147: return;
148: }
149: Rectangle r = c.getBounds();
150: g
151: .setColor(UIManager
152: .getColor("InternalFrame.borderDarkShadow")); //NOI18N
153: g.drawLine(0, r.height - 1, r.width - 1, r.height - 1);
154: }
155:
156: protected Font getTxtFont() {
157: if (isGenericUI) {
158: Font result = UIManager.getFont("controlFont");
159: if (result != null) {
160: return result;
161: }
162: }
163: return super .getTxtFont();
164: }
165:
166: protected void paintTabContent(Graphics g, int index, String text,
167: int x, int y, int width, int height) {
168: // substract lower border
169: height--;
170: y -= 2; //align to center
171: FontMetrics fm = getTxtFontMetrics();
172: // setting font already here to compute string width correctly
173: g.setFont(getTxtFont());
174: int txtWidth = width;
175: if (isSelected(index)) {
176: Component buttons = getControlButtons();
177: if (null != buttons) {
178: Dimension buttonsSize = buttons.getPreferredSize();
179: txtWidth = width
180: - (buttonsSize.width + ICON_X_PAD + 2 * TXT_X_PAD);
181: buttons.setLocation(x + txtWidth + 2 * TXT_X_PAD, y
182: + (height - buttonsSize.height) / 2 + 1);
183: }
184: } else {
185: txtWidth = width - 2 * TXT_X_PAD;
186: }
187: // draw bump (dragger)
188: drawBump(g, index, x + 4, y + 6, BUMP_WIDTH, height - 8);
189:
190: // draw text in right color
191: Color txtC = UIManager.getColor("TabbedPane.foreground"); //NOI18N
192:
193: HtmlRenderer.renderString(text, g, x + TXT_X_PAD, y
194: + fm.getAscent() + TXT_Y_PAD, txtWidth, height,
195: getTxtFont(), txtC, HtmlRenderer.STYLE_TRUNCATE, true);
196: }
197:
198: protected void paintTabBorder(Graphics g, int index, int x, int y,
199: int width, int height) {
200:
201: // subtract lower border
202: height--;
203: boolean isSelected = isSelected(index);
204:
205: g.translate(x, y);
206:
207: g.setColor(UIManager.getColor("InternalFrame.borderShadow")); //NOI18N
208: g.drawLine(0, height - 1, width - 2, height - 1);
209: g.drawLine(width - 1, height - 1, width - 1, 0);
210:
211: g.setColor(isSelected ? UIManager
212: .getColor("InternalFrame.borderHighlight") //NOI18N
213: : UIManager.getColor("InternalFrame.borderLight")); //NOI18N
214: g.drawLine(0, 0, 0, height - 1);
215: g.drawLine(1, 0, width - 2, 0);
216:
217: g.translate(-x, -y);
218: }
219:
220: protected void paintTabBackground(Graphics g, int index, int x,
221: int y, int width, int height) {
222: // substract lower border
223: height--;
224: ((Graphics2D) g).setPaint(getBackgroundPaint(g, index, x, y,
225: width, height));
226: if (isFocused(index)) {
227: g.fillRect(x, y, width, height);
228: } else {
229: g.fillRect(x + 1, y + 1, width - 2, height - 2);
230: }
231: }
232:
233: private Paint getBackgroundPaint(Graphics g, int index, int x,
234: int y, int width, int height) {
235: // background body, colored according to state
236: boolean selected = isSelected(index);
237: boolean focused = isFocused(index);
238: boolean attention = isAttention(index);
239:
240: Paint result = null;
241: if (focused && !attention) {
242: result = ColorUtil.getGradientPaint(x, y,
243: getSelGradientColor(), x + width, y,
244: getSelGradientColor2());
245: } else if (selected && !attention) {
246: result = UIManager.getColor("TabbedPane.background"); //NOI18N
247: } else if (attention) {
248: result = WinClassicEditorTabCellRenderer.ATTENTION_COLOR;
249: } else {
250: result = UIManager.getColor("tab_unsel_fill");
251: }
252: return result;
253: }
254:
255: /**
256: * Paints dragger in given rectangle
257: */
258: private void drawBump(Graphics g, int index, int x, int y,
259: int width, int height) {
260: if (isGenericUI) {
261: //This look and feel is also used as the default UI on non-JDS
262: return;
263: }
264:
265: // prepare colors
266: Color highlightC, bodyC, shadowC;
267: if (isFocused(index)) {
268: bodyC = new Color(210, 220, 243); //XXX
269: highlightC = bodyC.brighter();
270: shadowC = bodyC.darker();
271: } else if (isSelected(index)) {
272: highlightC = UIManager
273: .getColor("InternalFrame.borderHighlight"); //NOI18N
274: bodyC = UIManager.getColor("InternalFrame.borderLight"); //NOI18N
275: shadowC = UIManager.getColor("InternalFrame.borderShadow"); //NOI18N
276: } else {
277: highlightC = UIManager
278: .getColor("InternalFrame.borderLight"); //NOI18N
279: bodyC = UIManager.getColor("tab_unsel_fill");
280: shadowC = UIManager.getColor("InternalFrame.borderShadow"); //NOI18N
281: }
282: // draw
283: for (int i = 0; i < width / 3; i++, x += 3) {
284: g.setColor(highlightC);
285: g.drawLine(x, y, x, y + height - 1);
286: g.drawLine(x, y, x + 1, y);
287: g.setColor(bodyC);
288: g.drawLine(x + 1, y + 1, x + 1, y + height - 2);
289: g.setColor(shadowC);
290: g.drawLine(x + 2, y, x + 2, y + height - 1);
291: g.drawLine(x, y + height - 1, x + 1, y + height - 1);
292: }
293: }
294:
295: private static final Color getSelGradientColor() {
296: if ("GTK".equals(UIManager.getLookAndFeel().getID())) { // NOI18N
297: return GTK_TABBED_PANE_BACKGROUND_1; // #68200
298: } else {
299: return UIManager.getColor("winclassic_tab_sel_gradient"); // NOI18N
300: }
301: }
302:
303: private static final Color getSelGradientColor2() {
304: return UIManager.getColor("TabbedPane.background"); // NOI18N
305: }
306:
307: private static void initIcons() {
308: if (null == buttonIconPaths) {
309: buttonIconPaths = new HashMap<Integer, String[]>(7);
310:
311: //close button
312: String[] iconPaths = new String[4];
313: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/win_bigclose_enabled.png"; // NOI18N
314: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/win_bigclose_pressed.png"; // NOI18N
315: iconPaths[TabControlButton.STATE_DISABLED] = "org/netbeans/swing/tabcontrol/resources/win_bigclose_disabled.png"; // NOI18N
316: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/win_bigclose_rollover.png"; // NOI18N
317: buttonIconPaths.put(TabControlButton.ID_CLOSE_BUTTON,
318: iconPaths);
319:
320: //slide/pin button
321: iconPaths = new String[4];
322: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/win_slideright_enabled.png"; // NOI18N
323: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/win_slideright_pressed.png"; // NOI18N
324: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
325: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/win_slideright_rollover.png"; // NOI18N
326: buttonIconPaths.put(TabControlButton.ID_SLIDE_RIGHT_BUTTON,
327: iconPaths);
328:
329: iconPaths = new String[4];
330: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/win_slideleft_enabled.png"; // NOI18N
331: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/win_slideleft_pressed.png"; // NOI18N
332: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
333: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/win_slideleft_rollover.png"; // NOI18N
334: buttonIconPaths.put(TabControlButton.ID_SLIDE_LEFT_BUTTON,
335: iconPaths);
336:
337: iconPaths = new String[4];
338: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/win_slidebottom_enabled.png"; // NOI18N
339: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/win_slidebottom_pressed.png"; // NOI18N
340: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
341: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/win_slidebottom_rollover.png"; // NOI18N
342: buttonIconPaths.put(TabControlButton.ID_SLIDE_DOWN_BUTTON,
343: iconPaths);
344:
345: iconPaths = new String[4];
346: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/win_pin_enabled.png"; // NOI18N
347: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/win_pin_pressed.png"; // NOI18N
348: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
349: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/win_pin_rollover.png"; // NOI18N
350: buttonIconPaths.put(TabControlButton.ID_PIN_BUTTON,
351: iconPaths);
352: }
353: }
354:
355: public Icon getButtonIcon(int buttonId, int buttonState) {
356: Icon res = null;
357: initIcons();
358: String[] paths = buttonIconPaths.get(buttonId);
359: if (null != paths && buttonState >= 0
360: && buttonState < paths.length) {
361: res = TabControlButtonFactory.getIcon(paths[buttonState]);
362: }
363: return res;
364: }
365: }
|