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: import java.awt.image.BufferedImage;
047: import java.awt.image.RescaleOp;
048: import javax.swing.plaf.synth.Region;
049: import javax.swing.plaf.synth.SynthConstants;
050: import javax.swing.plaf.synth.SynthContext;
051: import javax.swing.plaf.synth.SynthLookAndFeel;
052: import javax.swing.plaf.synth.SynthPainter;
053: import javax.swing.plaf.synth.SynthStyle;
054: import javax.swing.plaf.synth.SynthStyleFactory;
055:
056: /**
057: * Gtk implementation of tab renderer
058: *
059: * @author Marek Slama
060: */
061: final class GtkEditorTabCellRenderer extends AbstractTabCellRenderer {
062:
063: private static final TabPainter leftClip = new GtkLeftClipPainter();
064: private static final TabPainter rightClip = new GtkRightClipPainter();
065: private static final TabPainter normal = new GtkPainter();
066:
067: private static JTabbedPane dummyTab;
068:
069: static final Color ATTENTION_COLOR = new Color(255, 238, 120);
070:
071: /**
072: * Creates a new instance of GtkEditorTabCellRenderer
073: */
074: public GtkEditorTabCellRenderer() {
075: super (leftClip, normal, rightClip, new Dimension(28, 32));
076: }
077:
078: public Color getSelectedForeground() {
079: return UIManager.getColor("textText"); //NOI18N
080: }
081:
082: public Color getForeground() {
083: return getSelectedForeground();
084: }
085:
086: /**
087: * #56245 - need more space between icon and edge on classic for the case
088: * of full 16x16 icons.
089: */
090: public int getPixelsToAddToSelection() {
091: return 4;
092: }
093:
094: protected int getCaptionYAdjustment() {
095: return 0;
096: }
097:
098: public Dimension getPadding() {
099: Dimension d = super .getPadding();
100: d.width = isShowCloseButton()
101: && !Boolean.getBoolean("nb.tabs.suppressCloseButton") ? 28
102: : 14;
103: return d;
104: }
105:
106: private static final Insets INSETS = new Insets(0, 2, 0, 10);
107:
108: private static void paintTabBackground(Graphics g, int index,
109: int state, int x, int y, int w, int h) {
110: if (dummyTab == null) {
111: dummyTab = new JTabbedPane();
112: }
113: Region region = Region.TABBED_PANE_TAB;
114: SynthLookAndFeel laf = (SynthLookAndFeel) UIManager
115: .getLookAndFeel();
116: SynthStyleFactory sf = laf.getStyleFactory();
117: SynthStyle style = sf.getStyle(dummyTab, region);
118: SynthContext context = new SynthContext(
119: dummyTab,
120: region,
121: style,
122: state == SynthConstants.FOCUSED ? SynthConstants.SELECTED
123: : state);
124: SynthPainter painter = style.getPainter(context);
125: if (state == SynthConstants.DEFAULT) {
126: painter.paintTabbedPaneTabBackground(context, g, x, y, w,
127: h, index);
128: } else {
129: BufferedImage bufIm = new BufferedImage(w, h,
130: BufferedImage.TYPE_INT_RGB);
131: Graphics2D g2d = bufIm.createGraphics();
132: g2d.setBackground(UIManager.getColor("Panel.background"));
133: g2d.clearRect(0, 0, w, h);
134: painter.paintTabbedPaneTabBackground(context, g2d, 0, 0, w,
135: h, index);
136: // differentiate active and selected tabs, active tab made brighter,
137: // selected tab darker
138: RescaleOp op = state == SynthConstants.FOCUSED ? new RescaleOp(
139: 1.08f, 0, null)
140: : new RescaleOp(0.96f, 0, null);
141: BufferedImage img = op.filter(bufIm, null);
142: g.drawImage(img, x, y, null);
143: }
144:
145: }
146:
147: private static int getHeightDifference(GtkEditorTabCellRenderer ren) {
148: return ren.isSelected() ? ren.isActive() ? 0 : 1 : 2;
149: }
150:
151: private static class GtkPainter implements TabPainter {
152:
153: public Insets getBorderInsets(Component c) {
154: return INSETS;
155: }
156:
157: public Polygon getInteriorPolygon(Component c) {
158: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
159:
160: Insets ins = getBorderInsets(c);
161: Polygon p = new Polygon();
162: int x = ren.isLeftmost() ? 1 : 0;
163: int y = 1;
164:
165: int width = ren.isLeftmost() ? c.getWidth() - 1 : c
166: .getWidth();
167: int height = ren.isSelected() ? c.getHeight() + 2 : c
168: .getHeight() - 1;
169:
170: //Modified to return rectangle
171: p.addPoint(x, y);
172: p.addPoint(x + width, y);
173: p.addPoint(x + width, y + height);
174: p.addPoint(x, y + height);
175: return p;
176: }
177:
178: public boolean isBorderOpaque() {
179: return true;
180: }
181:
182: public void paintBorder(Component c, Graphics g, int x, int y,
183: int width, int height) {
184: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
185: Polygon p = getInteriorPolygon(c);
186: return;
187: }
188:
189: public void paintInterior(Graphics g, Component c) {
190: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
191: Polygon p = getInteriorPolygon(c);
192: int state = ren.isSelected() ? ren.isActive() ? SynthConstants.FOCUSED
193: : SynthConstants.SELECTED
194: : SynthConstants.DEFAULT;
195: Rectangle bounds = p.getBounds();
196: int yDiff = getHeightDifference(ren);
197: paintTabBackground(g, 0, state, bounds.x, bounds.y + yDiff,
198: bounds.width, bounds.height - yDiff);
199:
200: if (!supportsCloseButton((JComponent) c)) {
201: return;
202: }
203:
204: paintCloseButton(g, (JComponent) c);
205: }
206:
207: public void getCloseButtonRectangle(JComponent jc,
208: Rectangle rect, Rectangle bounds) {
209: boolean rightClip = ((GtkEditorTabCellRenderer) jc)
210: .isClipRight();
211: boolean leftClip = ((GtkEditorTabCellRenderer) jc)
212: .isClipLeft();
213: boolean notSupported = !((GtkEditorTabCellRenderer) jc)
214: .isShowCloseButton();
215: if (leftClip || rightClip || notSupported) {
216: rect.x = -100;
217: rect.y = -100;
218: rect.width = 0;
219: rect.height = 0;
220: } else {
221: String iconPath = findIconPath((GtkEditorTabCellRenderer) jc);
222: Icon icon = TabControlButtonFactory.getIcon(iconPath);
223: int iconWidth = icon.getIconWidth();
224: int iconHeight = icon.getIconHeight();
225: rect.x = bounds.x + bounds.width - iconWidth - 2;
226: rect.y = bounds.y
227: + (Math.max(0, bounds.height / 2 - iconHeight
228: / 2));
229: rect.width = iconWidth;
230: rect.height = iconHeight;
231: }
232: }
233:
234: private void paintCloseButton(Graphics g, JComponent c) {
235: if (((AbstractTabCellRenderer) c).isShowCloseButton()) {
236:
237: Rectangle r = new Rectangle(0, 0, c.getWidth(), c
238: .getHeight());
239: Rectangle cbRect = new Rectangle();
240: getCloseButtonRectangle((JComponent) c, cbRect, r);
241:
242: //paint close button
243: String iconPath = findIconPath((GtkEditorTabCellRenderer) c);
244: Icon icon = TabControlButtonFactory.getIcon(iconPath);
245: icon.paintIcon(c, g, cbRect.x, cbRect.y);
246: }
247: }
248:
249: /**
250: * Returns path of icon which is correct for currect state of tab at given
251: * index
252: */
253: private String findIconPath(GtkEditorTabCellRenderer renderer) {
254: if (renderer.inCloseButton() && renderer.isPressed()) {
255: return "org/netbeans/swing/tabcontrol/resources/gtk_close_pressed.png"; // NOI18N
256: }
257: if (renderer.inCloseButton()) {
258: return "org/netbeans/swing/tabcontrol/resources/gtk_close_rollover.png"; // NOI18N
259: }
260: return "org/netbeans/swing/tabcontrol/resources/gtk_close_enabled.png"; // NOI18N
261: }
262:
263: public boolean supportsCloseButton(JComponent renderer) {
264: return ((AbstractTabCellRenderer) renderer)
265: .isShowCloseButton();
266: }
267:
268: }
269:
270: private static class GtkLeftClipPainter implements TabPainter {
271:
272: public Insets getBorderInsets(Component c) {
273: return INSETS;
274: }
275:
276: public Polygon getInteriorPolygon(Component c) {
277: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
278:
279: Insets ins = getBorderInsets(c);
280: Polygon p = new Polygon();
281: int x = -3;
282: int y = 1;
283:
284: int width = c.getWidth() + 3;
285: int height = ren.isSelected() ? c.getHeight() + 2 : c
286: .getHeight() - 1;
287:
288: //Modified to return rectangle
289: p.addPoint(x, y);
290: p.addPoint(x + width, y);
291: p.addPoint(x + width, y + height);
292: p.addPoint(x, y + height);
293: return p;
294: }
295:
296: public void paintBorder(Component c, Graphics g, int x, int y,
297: int width, int height) {
298: return;
299: }
300:
301: public void paintInterior(Graphics g, Component c) {
302: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
303: Polygon p = getInteriorPolygon(c);
304: int state = ren.isSelected() ? ren.isActive() ? SynthConstants.FOCUSED
305: : SynthConstants.SELECTED
306: : SynthConstants.DEFAULT;
307: Rectangle bounds = p.getBounds();
308: int yDiff = getHeightDifference(ren);
309: paintTabBackground(g, 0, state, bounds.x, bounds.y + yDiff,
310: bounds.width, bounds.height - yDiff);
311: }
312:
313: public boolean isBorderOpaque() {
314: return true;
315: }
316:
317: public void getCloseButtonRectangle(JComponent jc,
318: final Rectangle rect, Rectangle bounds) {
319: rect.setBounds(-20, -20, 0, 0);
320: }
321:
322: public boolean supportsCloseButton(JComponent renderer) {
323: return false;
324: }
325: }
326:
327: private static class GtkRightClipPainter implements TabPainter {
328:
329: public Insets getBorderInsets(Component c) {
330: return INSETS;
331: }
332:
333: public boolean isBorderOpaque() {
334: return true;
335: }
336:
337: public Polygon getInteriorPolygon(Component c) {
338: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
339:
340: Insets ins = getBorderInsets(c);
341: Polygon p = new Polygon();
342: int x = 0;
343: int y = 1;
344:
345: int width = c.getWidth() + 10;
346: int height = ren.isSelected() ? c.getHeight() + 2 : c
347: .getHeight() - 1;
348:
349: //Modified to return rectangle
350: p.addPoint(x, y);
351: p.addPoint(x + width, y);
352: p.addPoint(x + width, y + height);
353: p.addPoint(x, y + height);
354: return p;
355: }
356:
357: public void paintBorder(Component c, Graphics g, int x, int y,
358: int width, int height) {
359: }
360:
361: public void paintInterior(Graphics g, Component c) {
362: GtkEditorTabCellRenderer ren = (GtkEditorTabCellRenderer) c;
363:
364: Polygon p = getInteriorPolygon(c);
365: int state = ren.isSelected() ? ren.isActive() ? SynthConstants.FOCUSED
366: : SynthConstants.SELECTED
367: : SynthConstants.DEFAULT;
368: Rectangle bounds = p.getBounds();
369: int yDiff = getHeightDifference(ren);
370: paintTabBackground(g, 0, state, bounds.x, bounds.y + yDiff,
371: bounds.width, bounds.height - yDiff);
372: }
373:
374: public boolean supportsCloseButton(JComponent renderer) {
375: return false;
376: }
377:
378: public void getCloseButtonRectangle(JComponent jc,
379: final Rectangle rect, Rectangle bounds) {
380: rect.setBounds(-20, -20, 0, 0);
381: }
382: }
383:
384: }
|