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 javax.swing.*;
045: import java.awt.*;
046:
047: /**
048: * Windows classic implementation of tab renderer
049: *
050: * @author Tim Boudreau
051: */
052: final class WinClassicEditorTabCellRenderer extends
053: AbstractTabCellRenderer {
054:
055: private static final TabPainter leftClip = new WinClassicLeftClipPainter();
056: private static final TabPainter rightClip = new WinClassicRightClipPainter();
057: private static final TabPainter normal = new WinClassicPainter();
058:
059: private static final Color GTK_TABBED_PANE_BACKGROUND_1 = new Color(
060: 255, 255, 255);
061:
062: static final Color ATTENTION_COLOR = new Color(255, 238, 120);
063:
064: private static boolean isGenericUI = !"Windows".equals(UIManager
065: .getLookAndFeel().getID());
066:
067: /**
068: * Creates a new instance of WinClassicEditorTabCellRenderer
069: */
070: public WinClassicEditorTabCellRenderer() {
071: super (leftClip, normal, rightClip, new Dimension(28, 32));
072: }
073:
074: public Color getSelectedForeground() {
075: return UIManager.getColor("textText"); //NOI18N
076: }
077:
078: public Color getForeground() {
079: return getSelectedForeground();
080: }
081:
082: /**
083: * #56245 - need more space between icon and edge on classic for the case
084: * of full 16x16 icons.
085: */
086: public int getPixelsToAddToSelection() {
087: return 4;
088: }
089:
090: protected int getCaptionYAdjustment() {
091: return 0;
092: }
093:
094: public Dimension getPadding() {
095: Dimension d = super .getPadding();
096: d.width = isShowCloseButton()
097: && !Boolean.getBoolean("nb.tabs.suppressCloseButton") ? 28
098: : 14;
099: return d;
100: }
101:
102: private static final Insets INSETS = new Insets(0, 2, 0, 10);
103:
104: private static class WinClassicPainter implements TabPainter {
105:
106: public Insets getBorderInsets(Component c) {
107: return INSETS;
108: }
109:
110: public Polygon getInteriorPolygon(Component c) {
111: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
112:
113: Insets ins = getBorderInsets(c);
114: Polygon p = new Polygon();
115: int x = ren.isLeftmost() ? 1 : 0;
116: int y = isGenericUI ? 0 : 1;
117:
118: int width = ren.isLeftmost() ? c.getWidth() - 1 : c
119: .getWidth();
120: int height = ren.isSelected() ? c.getHeight() + 2 : c
121: .getHeight() - 1;
122:
123: p.addPoint(x, y + ins.top + 2);
124: p.addPoint(x + 2, y + ins.top);
125: p.addPoint(x + width - 3, y + ins.top);
126: p.addPoint(x + width - 1, y + ins.top + 2);
127: p.addPoint(x + width - 1, y + height - 2);
128: p.addPoint(x, y + height - 2);
129: return p;
130: }
131:
132: public boolean isBorderOpaque() {
133: return true;
134: }
135:
136: public void paintBorder(Component c, Graphics g, int x, int y,
137: int width, int height) {
138: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
139: Polygon p = getInteriorPolygon(c);
140: g.setColor(ren.isSelected() ? UIManager
141: .getColor("controlLtHighlight") : UIManager
142: .getColor("controlHighlight")); //NOI18N
143:
144: int[] xpoints = p.xpoints;
145: int[] ypoints = p.ypoints;
146:
147: g.drawLine(xpoints[0], ypoints[0], xpoints[p.npoints - 1],
148: ypoints[p.npoints - 1]);
149:
150: for (int i = 0; i < p.npoints - 1; i++) {
151: g.drawLine(xpoints[i], ypoints[i], xpoints[i + 1],
152: ypoints[i + 1]);
153: if (i == p.npoints - 4) {
154: g.setColor(ren.isSelected() ? UIManager
155: .getColor("controlDkShadow") : UIManager
156: .getColor("controlShadow")); //NOI18N
157: g.drawLine(xpoints[i] + 1, ypoints[i] + 1,
158: xpoints[i] + 2, ypoints[i] + 2);
159: }
160: }
161: }
162:
163: public void paintInterior(Graphics g, Component c) {
164:
165: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
166: boolean wantGradient = ren.isSelected()
167: && ren.isActive()
168: || ((ren.isClipLeft() || ren.isClipRight()) && ren
169: .isPressed());
170:
171: if (wantGradient) {
172: ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0,
173: 0, getSelGradientColor(), ren.getWidth(), 0,
174: getSelGradientColor2()));
175: } else {
176: if (!ren.isAttention()) {
177: g.setColor(ren.isSelected() ? UIManager
178: .getColor("TabbedPane.background")
179: : UIManager.getColor("tab_unsel_fill")); //NOI18N
180: } else {
181: g.setColor(ATTENTION_COLOR);
182: }
183: }
184: Polygon p = getInteriorPolygon(c);
185: g.fillPolygon(p);
186:
187: if (!supportsCloseButton((JComponent) c)) {
188: return;
189: }
190:
191: paintCloseButton(g, (JComponent) c);
192: }
193:
194: public void getCloseButtonRectangle(JComponent jc,
195: Rectangle rect, Rectangle bounds) {
196: boolean rightClip = ((WinClassicEditorTabCellRenderer) jc)
197: .isClipRight();
198: boolean leftClip = ((WinClassicEditorTabCellRenderer) jc)
199: .isClipLeft();
200: boolean notSupported = !((WinClassicEditorTabCellRenderer) jc)
201: .isShowCloseButton();
202: if (leftClip || rightClip || notSupported) {
203: rect.x = -100;
204: rect.y = -100;
205: rect.width = 0;
206: rect.height = 0;
207: } else {
208: String iconPath = findIconPath((WinClassicEditorTabCellRenderer) jc);
209: Icon icon = TabControlButtonFactory.getIcon(iconPath);
210: int iconWidth = icon.getIconWidth();
211: int iconHeight = icon.getIconHeight();
212: rect.x = bounds.x + bounds.width - iconWidth - 2;
213: rect.y = bounds.y
214: + (Math.max(0, bounds.height / 2 - iconHeight
215: / 2));
216: rect.width = iconWidth;
217: rect.height = iconHeight;
218: }
219: }
220:
221: private void paintCloseButton(Graphics g, JComponent c) {
222: if (((AbstractTabCellRenderer) c).isShowCloseButton()) {
223:
224: Rectangle r = new Rectangle(0, 0, c.getWidth(), c
225: .getHeight());
226: Rectangle cbRect = new Rectangle();
227: getCloseButtonRectangle((JComponent) c, cbRect, r);
228:
229: //paint close button
230: String iconPath = findIconPath((WinClassicEditorTabCellRenderer) c);
231: Icon icon = TabControlButtonFactory.getIcon(iconPath);
232: icon.paintIcon(c, g, cbRect.x, cbRect.y);
233: }
234: }
235:
236: /**
237: * Returns path of icon which is correct for currect state of tab at given
238: * index
239: */
240: private String findIconPath(
241: WinClassicEditorTabCellRenderer renderer) {
242: if (renderer.inCloseButton() && renderer.isPressed()) {
243: return "org/netbeans/swing/tabcontrol/resources/win_close_pressed.png"; // NOI18N
244: }
245: if (renderer.inCloseButton()) {
246: return "org/netbeans/swing/tabcontrol/resources/win_close_rollover.png"; // NOI18N
247: }
248: return "org/netbeans/swing/tabcontrol/resources/win_close_enabled.png"; // NOI18N
249: }
250:
251: public boolean supportsCloseButton(JComponent renderer) {
252: return ((AbstractTabCellRenderer) renderer)
253: .isShowCloseButton();
254: }
255:
256: }
257:
258: private static class WinClassicLeftClipPainter implements
259: TabPainter {
260:
261: public Insets getBorderInsets(Component c) {
262: return INSETS;
263: }
264:
265: public Polygon getInteriorPolygon(Component c) {
266: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
267:
268: Insets ins = getBorderInsets(c);
269: Polygon p = new Polygon();
270: int x = -3;
271: int y = isGenericUI ? 0 : 1;
272:
273: int width = c.getWidth() + 3;
274: int height = ren.isSelected() ? c.getHeight() + 2 : c
275: .getHeight() - 1;
276:
277: p.addPoint(x, y + ins.top + 2);
278: p.addPoint(x + 2, y + ins.top);
279: p.addPoint(x + width - 3, y + ins.top);
280: p.addPoint(x + width - 1, y + ins.top + 2);
281: p.addPoint(x + width - 1, y + height - 1);
282: p.addPoint(x, y + height - 1);
283: return p;
284: }
285:
286: public void paintBorder(Component c, Graphics g, int x, int y,
287: int width, int height) {
288: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
289: Polygon p = getInteriorPolygon(c);
290: g.setColor(ren.isSelected() ? UIManager
291: .getColor("controlLtHighlight") : UIManager
292: .getColor("controlHighlight")); //NOI18N
293:
294: int[] xpoints = p.xpoints;
295: int[] ypoints = p.ypoints;
296:
297: g.drawLine(xpoints[0], ypoints[0], xpoints[p.npoints - 1],
298: ypoints[p.npoints - 1]);
299:
300: for (int i = 0; i < p.npoints - 1; i++) {
301: g.drawLine(xpoints[i], ypoints[i], xpoints[i + 1],
302: ypoints[i + 1]);
303: if (i == p.npoints - 4) {
304: g.setColor(ren.isSelected() ? UIManager
305: .getColor("controlDkShadow") : UIManager
306: .getColor("controlShadow")); //NOI18N
307: g.drawLine(xpoints[i] + 1, ypoints[i] + 1,
308: xpoints[i] + 2, ypoints[i] + 2);
309: }
310: }
311: }
312:
313: public void paintInterior(Graphics g, Component c) {
314: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
315: boolean wantGradient = ren.isSelected()
316: && ren.isActive()
317: || ((ren.isClipLeft() || ren.isClipRight()) && ren
318: .isPressed());
319:
320: if (wantGradient) {
321: ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0,
322: 0, getSelGradientColor(), ren.getWidth(), 0,
323: getSelGradientColor2()));
324: } else {
325: if (!ren.isAttention()) {
326: g.setColor(ren.isSelected() ? UIManager
327: .getColor("TabbedPane.background")
328: : UIManager.getColor("tab_unsel_fill")); //NOI18N
329: } else {
330: g.setColor(ATTENTION_COLOR);
331: }
332: }
333: Polygon p = getInteriorPolygon(c);
334: g.fillPolygon(p);
335: }
336:
337: public boolean isBorderOpaque() {
338: return true;
339: }
340:
341: public void getCloseButtonRectangle(JComponent jc,
342: final Rectangle rect, Rectangle bounds) {
343: rect.setBounds(-20, -20, 0, 0);
344: }
345:
346: public boolean supportsCloseButton(JComponent renderer) {
347: return false;
348: }
349: }
350:
351: private static class WinClassicRightClipPainter implements
352: TabPainter {
353:
354: public Insets getBorderInsets(Component c) {
355: return INSETS;
356: }
357:
358: public boolean isBorderOpaque() {
359: return true;
360: }
361:
362: public Polygon getInteriorPolygon(Component c) {
363: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
364:
365: Insets ins = getBorderInsets(c);
366: Polygon p = new Polygon();
367: int x = 0;
368: int y = isGenericUI ? 0 : 1;
369:
370: int width = c.getWidth();
371: int height = ren.isSelected() ? c.getHeight() + 2 : c
372: .getHeight() - 1;
373:
374: p.addPoint(x, y + ins.top + 2);
375: p.addPoint(x + 2, y + ins.top);
376: p.addPoint(x + width - 1, y + ins.top);
377: p.addPoint(x + width - 1, y + height - 1);
378: p.addPoint(x, y + height - 1);
379: return p;
380: }
381:
382: public void paintBorder(Component c, Graphics g, int x, int y,
383: int width, int height) {
384: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
385: Polygon p = getInteriorPolygon(c);
386: g.setColor(ren.isSelected() ? UIManager
387: .getColor("controlLtHighlight") : UIManager
388: .getColor("controlHighlight")); //NOI18N
389:
390: int[] xpoints = p.xpoints;
391: int[] ypoints = p.ypoints;
392:
393: g.drawLine(xpoints[0], ypoints[0], xpoints[p.npoints - 1],
394: ypoints[p.npoints - 1]);
395:
396: for (int i = 0; i < p.npoints - 1; i++) {
397: g.drawLine(xpoints[i], ypoints[i], xpoints[i + 1],
398: ypoints[i + 1]);
399: if (ren.isSelected() && i == p.npoints - 4) {
400: g.setColor(ren.isActive() ? UIManager
401: .getColor("Table.selectionBackground")
402: : UIManager.getColor("control")); //NOI18n
403: } else if (i == p.npoints - 4) {
404: break;
405: }
406: if (i == p.npoints - 3) {
407: break;
408: }
409: }
410: }
411:
412: public void paintInterior(Graphics g, Component c) {
413: WinClassicEditorTabCellRenderer ren = (WinClassicEditorTabCellRenderer) c;
414: boolean wantGradient = ren.isSelected()
415: && ren.isActive()
416: || ((ren.isClipLeft() || ren.isClipRight()) && ren
417: .isPressed());
418:
419: if (wantGradient) {
420: ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0,
421: 0, getSelGradientColor(), ren.getWidth(), 0,
422: getSelGradientColor2()));
423: } else {
424: if (!ren.isAttention()) {
425: g.setColor(ren.isSelected() ? UIManager
426: .getColor("TabbedPane.background") : //NOI18N
427: UIManager.getColor("tab_unsel_fill")); //NOI18N
428: } else {
429: g.setColor(ATTENTION_COLOR);
430: }
431: }
432:
433: Polygon p = getInteriorPolygon(c);
434: g.fillPolygon(p);
435: }
436:
437: public boolean supportsCloseButton(JComponent renderer) {
438: return false;
439: }
440:
441: public void getCloseButtonRectangle(JComponent jc,
442: final Rectangle rect, Rectangle bounds) {
443: rect.setBounds(-20, -20, 0, 0);
444: }
445: }
446:
447: private static final Color getSelGradientColor() {
448: if ("GTK".equals(UIManager.getLookAndFeel().getID())) { // NOI18N
449: return GTK_TABBED_PANE_BACKGROUND_1; // #68200
450: } else {
451: return UIManager.getColor("winclassic_tab_sel_gradient"); // NOI18N
452: }
453: }
454:
455: private static final Color getSelGradientColor2() {
456: return UIManager.getColor("TabbedPane.background"); // NOI18N
457: }
458:
459: }
|