Source Code Cross Referenced for PlasticTabbedPaneUI.java in  » Swing-Library » jgoodies-looks » com » jgoodies » looks » plastic » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » jgoodies looks » com.jgoodies.looks.plastic 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2001-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
0003:         *
0004:         * Redistribution and use in source and binary forms, with or without 
0005:         * modification, are permitted provided that the following conditions are met:
0006:         * 
0007:         *  o Redistributions of source code must retain the above copyright notice, 
0008:         *    this list of conditions and the following disclaimer. 
0009:         *     
0010:         *  o Redistributions in binary form must reproduce the above copyright notice, 
0011:         *    this list of conditions and the following disclaimer in the documentation 
0012:         *    and/or other materials provided with the distribution. 
0013:         *     
0014:         *  o Neither the name of JGoodies Karsten Lentzsch nor the names of 
0015:         *    its contributors may be used to endorse or promote products derived 
0016:         *    from this software without specific prior written permission. 
0017:         *     
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
0020:         * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
0021:         * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
0022:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
0023:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
0024:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
0025:         * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
0026:         * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
0027:         * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
0028:         * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
0029:         */
0030:
0031:        package com.jgoodies.looks.plastic;
0032:
0033:        import java.awt.Color;
0034:        import java.awt.Component;
0035:        import java.awt.Container;
0036:        import java.awt.Dimension;
0037:        import java.awt.Font;
0038:        import java.awt.FontMetrics;
0039:        import java.awt.Graphics;
0040:        import java.awt.Graphics2D;
0041:        import java.awt.Insets;
0042:        import java.awt.LayoutManager;
0043:        import java.awt.Point;
0044:        import java.awt.Polygon;
0045:        import java.awt.Rectangle;
0046:        import java.awt.Shape;
0047:        import java.awt.event.ActionEvent;
0048:        import java.awt.event.ActionListener;
0049:        import java.awt.event.MouseEvent;
0050:        import java.beans.PropertyChangeEvent;
0051:        import java.beans.PropertyChangeListener;
0052:
0053:        import javax.swing.AbstractAction;
0054:        import javax.swing.Action;
0055:        import javax.swing.ActionMap;
0056:        import javax.swing.Icon;
0057:        import javax.swing.JButton;
0058:        import javax.swing.JComponent;
0059:        import javax.swing.JPanel;
0060:        import javax.swing.JTabbedPane;
0061:        import javax.swing.JViewport;
0062:        import javax.swing.SwingConstants;
0063:        import javax.swing.SwingUtilities;
0064:        import javax.swing.UIManager;
0065:        import javax.swing.event.ChangeEvent;
0066:        import javax.swing.event.ChangeListener;
0067:        import javax.swing.plaf.ComponentUI;
0068:        import javax.swing.plaf.UIResource;
0069:        import javax.swing.plaf.basic.BasicTabbedPaneUI;
0070:        import javax.swing.plaf.metal.MetalTabbedPaneUI;
0071:        import javax.swing.text.View;
0072:
0073:        import com.jgoodies.looks.LookUtils;
0074:        import com.jgoodies.looks.Options;
0075:
0076:        /**
0077:         * The JGoodies Plastic Look&Feel implementation of 
0078:         * <code>TabbedPaneUI</code>. It differs from its superclass
0079:         * <code>MetalTabbedPaneUI</code> in that it paints new tab shapes,
0080:         * provides two options, and supports ClearLook.
0081:         * <p>
0082:         * You can enable or disable icons in tabs globally via 
0083:         * com.jgoodies.looks.Options.setTabIconsEnabled(boolean).
0084:         * <p>
0085:         * To disable the content border set
0086:         * <pre>
0087:         * JTabbedPane tabbedPane = new JTabbedPane();
0088:         * tabbedPane.putClientProperty(Option.NO_CONTENT_BORDER_KEY, Boolean.TRUE);
0089:         * </pre>
0090:         * To paint embedded tabs use
0091:         * <pre>
0092:         * JTabbedPane tabbedPane = new JTabbedPane();
0093:         * tabbedPane.putClientProperty(Option.EMBEDDED_TABS_KEY, Boolean.TRUE);
0094:         * </pre>
0095:         * <p>
0096:         * There's a special mode that helps you detect content borders in 
0097:         * heavily wrapped component hierarchies - such as the NetBeans IDE. 
0098:         * In this marked mode the content border is painted as a Magenta line. 
0099:         * You can enable this mode by setting the System property 
0100:         * <tt>markContentBorders</tt> to <tt>true</tt>; in a command line:
0101:         * <pre>
0102:         * java -DmarkContentBorders=true
0103:         * </pre>
0104:         *  
0105:         * @author  Karsten Lentzsch
0106:         * @author  Torge Husfeldt
0107:         * @author  Andrej Golovnin
0108:         * @version $Revision: 1.6 $
0109:         * 
0110:         * @see     Options
0111:         */
0112:        public final class PlasticTabbedPaneUI extends MetalTabbedPaneUI {
0113:
0114:            // State ******************************************************************
0115:
0116:            /**
0117:             * Describes if tabs are painted with or without icons.
0118:             */
0119:            private static boolean isTabIconsEnabled = Options
0120:                    .isTabIconsEnabled();
0121:
0122:            /**
0123:             * Describes if we paint no content border or not; is false by default. 
0124:             * You can disable the content border by setting the client property
0125:             * Options.NO_CONTENT_BORDER_KEY to Boolean.TRUE;
0126:             */
0127:            private Boolean noContentBorder;
0128:
0129:            /**
0130:             * Describes if we paint tabs in an embedded style that is with
0131:             * less decoration; this is false by default.
0132:             * You can enable the embedded tabs style by setting the client property
0133:             * Options.EMBEDDED_TABS_KEY to Boolean.TRUE.
0134:             */
0135:            private Boolean embeddedTabs;
0136:
0137:            /**
0138:             * Holds the renderer that is used to render the tabs.
0139:             */
0140:            private AbstractRenderer renderer;
0141:
0142:            /** For use when tabLayoutPolicy == SCROLL_TAB_LAYOUT. */
0143:            private ScrollableTabSupport tabScroller;
0144:
0145:            /**
0146:             * Creates the <code>PlasticTabbedPaneUI</code>.
0147:             * 
0148:             * @see javax.swing.plaf.ComponentUI#createUI(JComponent)
0149:             */
0150:            public static ComponentUI createUI(JComponent tabPane) {
0151:                return new PlasticTabbedPaneUI();
0152:            }
0153:
0154:            /**
0155:             * Installs the UI.
0156:             * 
0157:             * @see javax.swing.plaf.ComponentUI#installUI(JComponent)
0158:             */
0159:            public void installUI(JComponent c) {
0160:                super .installUI(c);
0161:                embeddedTabs = (Boolean) c
0162:                        .getClientProperty(Options.EMBEDDED_TABS_KEY);
0163:                noContentBorder = (Boolean) c
0164:                        .getClientProperty(Options.NO_CONTENT_BORDER_KEY);
0165:                renderer = createRenderer(tabPane);
0166:            }
0167:
0168:            /**
0169:             * Uninstalls the UI.
0170:             * @see javax.swing.plaf.ComponentUI#uninstallUI(JComponent)
0171:             */
0172:            public void uninstallUI(JComponent c) {
0173:                renderer = null;
0174:                super .uninstallUI(c);
0175:            }
0176:
0177:            /**
0178:             * Creates and installs any required subcomponents for the JTabbedPane.
0179:             * Invoked by installUI.
0180:             * @see javax.swing.plaf.basic.BasicTabbedPaneUI#installComponents()
0181:             */
0182:            protected void installComponents() {
0183:                if (scrollableTabLayoutEnabled()) {
0184:                    if (tabScroller == null) {
0185:                        tabScroller = new ScrollableTabSupport(tabPane
0186:                                .getTabPlacement());
0187:                        tabPane.add(tabScroller.viewport);
0188:                    }
0189:                }
0190:            }
0191:
0192:            /**
0193:             * Removes any installed subcomponents from the JTabbedPane.
0194:             * Invoked by uninstallUI.
0195:             * @see javax.swing.plaf.basic.BasicTabbedPaneUI#uninstallComponents()
0196:             */
0197:            protected void uninstallComponents() {
0198:                if (scrollableTabLayoutEnabled()) {
0199:                    tabPane.remove(tabScroller.viewport);
0200:                    tabPane.remove(tabScroller.scrollForwardButton);
0201:                    tabPane.remove(tabScroller.scrollBackwardButton);
0202:                    tabScroller = null;
0203:                }
0204:            }
0205:
0206:            protected void installListeners() {
0207:                super .installListeners();
0208:                // if the layout policy is the SCROLL_TAB_LAYOUT, the super class
0209:                // will install the mouse listener on tabPane instead of
0210:                // tabScroller#tabPanel and there is no way to prevent this. 
0211:                // That's why the mouse listener must be removed from tabPane and
0212:                // added to tabScroller#tabPanel when the scroll tab layout is enabled.
0213:                // This applies only to JDK 1.4!!!
0214:                if ((mouseListener != null) && (LookUtils.IS_JAVA_1_4)) {
0215:                    if (scrollableTabLayoutEnabled()) {
0216:                        tabPane.removeMouseListener(mouseListener);
0217:                        tabScroller.tabPanel.addMouseListener(mouseListener);
0218:                    }
0219:                }
0220:            }
0221:
0222:            protected void uninstallListeners() {
0223:                if ((mouseListener != null) && (LookUtils.IS_JAVA_1_4)) {
0224:                    if (scrollableTabLayoutEnabled()) { // SCROLL_TAB_LAYOUT
0225:                        tabScroller.tabPanel.removeMouseListener(mouseListener);
0226:                    } else { // WRAP_TAB_LAYOUT
0227:                        tabPane.removeMouseListener(mouseListener);
0228:                    }
0229:                    mouseListener = null;
0230:                }
0231:                super .uninstallListeners();
0232:            }
0233:
0234:            protected void installKeyboardActions() {
0235:                super .installKeyboardActions();
0236:                // if the layout policy is the SCROLL_TAB_LAYOUT, then replace
0237:                // the forward and backward actions, installed in the action map
0238:                // in the supper class, by our own.
0239:                if (scrollableTabLayoutEnabled()) {
0240:                    Action forwardAction = new ScrollTabsForwardAction();
0241:                    Action backwardAction = new ScrollTabsBackwardAction();
0242:                    ActionMap am = SwingUtilities.getUIActionMap(tabPane);
0243:                    am.put("scrollTabsForwardAction", forwardAction);
0244:                    am.put("scrollTabsBackwardAction", backwardAction);
0245:                    tabScroller.scrollForwardButton.setAction(forwardAction);
0246:                    tabScroller.scrollBackwardButton.setAction(backwardAction);
0247:                }
0248:            }
0249:
0250:            /**
0251:             * Checks and answers if content border will be painted.
0252:             * This is controlled by the component's client property
0253:             * Options.NO_CONTENT_BORDER or Options.EMBEDDED.
0254:             */
0255:            private boolean hasNoContentBorder() {
0256:                return Boolean.TRUE.equals(noContentBorder);
0257:            }
0258:
0259:            /**
0260:             * Checks and answers if tabs are painted with minimal decoration.
0261:             */
0262:            private boolean hasEmbeddedTabs() {
0263:                return Boolean.TRUE.equals(embeddedTabs);
0264:            }
0265:
0266:            /**
0267:             * Creates the renderer used to lay out and paint the tabs.
0268:             * @param tabbedPane               the UIs component
0269:             * @return AbstractRenderer     the renderer that will be used to paint
0270:             */
0271:            private AbstractRenderer createRenderer(JTabbedPane tabbedPane) {
0272:                return hasEmbeddedTabs() ? AbstractRenderer
0273:                        .createEmbeddedRenderer(tabbedPane) : AbstractRenderer
0274:                        .createRenderer(tabPane);
0275:            }
0276:
0277:            /**
0278:             * Creates and answer a handler that listens to property changes.
0279:             * Unlike the superclass BasicTabbedPane, the PlasticTabbedPaneUI
0280:             * uses an extended Handler.
0281:             */
0282:            protected PropertyChangeListener createPropertyChangeListener() {
0283:                return new MyPropertyChangeHandler();
0284:            }
0285:
0286:            protected ChangeListener createChangeListener() {
0287:                return new TabSelectionHandler();
0288:            }
0289:
0290:            /*
0291:             * Private helper method for the next three methods.
0292:             */
0293:            private void doLayout() {
0294:                tabPane.revalidate();
0295:                tabPane.repaint();
0296:            }
0297:
0298:            /**
0299:             * Updates the renderer and layout. This message is sent by 
0300:             * my PropertyChangeHandler whenever the tab placement changes.
0301:             */
0302:            private void tabPlacementChanged() {
0303:                renderer = createRenderer(tabPane);
0304:                if (scrollableTabLayoutEnabled()) {
0305:                    tabScroller.createButtons();
0306:                }
0307:                doLayout();
0308:            }
0309:
0310:            /**
0311:             * Updates the embedded tabs property. This message is sent by
0312:             * my PropertyChangeHandler whenever the embedded tabs property changes.
0313:             */
0314:            private void embeddedTabsPropertyChanged(Boolean newValue) {
0315:                embeddedTabs = newValue;
0316:                renderer = createRenderer(tabPane);
0317:                doLayout();
0318:            }
0319:
0320:            /**
0321:             * Updates the no content border property. This message is sent 
0322:             * by my PropertyChangeHandler whenever the noContentBorder
0323:             * property changes.
0324:             */
0325:            private void noContentBorderPropertyChanged(Boolean newValue) {
0326:                noContentBorder = newValue;
0327:                tabPane.repaint();
0328:            }
0329:
0330:            public void paint(Graphics g, JComponent c) {
0331:                int selectedIndex = tabPane.getSelectedIndex();
0332:                int tabPlacement = tabPane.getTabPlacement();
0333:
0334:                ensureCurrentLayout();
0335:
0336:                // Paint tab area
0337:                // If scrollable tabs are enabled, the tab area will be
0338:                // painted by the scrollable tab panel instead.
0339:                //
0340:                if (!scrollableTabLayoutEnabled()) { // WRAP_TAB_LAYOUT
0341:                    paintTabArea(g, tabPlacement, selectedIndex);
0342:                }
0343:
0344:                // Paint content border
0345:                paintContentBorder(g, tabPlacement, selectedIndex);
0346:            }
0347:
0348:            protected void paintTab(Graphics g, int tabPlacement,
0349:                    Rectangle[] rects, int tabIndex, Rectangle iconRect,
0350:                    Rectangle textRect) {
0351:                Rectangle tabRect = rects[tabIndex];
0352:                int selectedIndex = tabPane.getSelectedIndex();
0353:                boolean isSelected = selectedIndex == tabIndex;
0354:                Graphics2D g2 = null;
0355:                Polygon cropShape = null;
0356:                Shape save = null;
0357:                int cropx = 0;
0358:                int cropy = 0;
0359:
0360:                if (scrollableTabLayoutEnabled()) {
0361:                    if (g instanceof  Graphics2D) {
0362:                        g2 = (Graphics2D) g;
0363:
0364:                        // Render visual for cropped tab edge...
0365:                        Rectangle viewRect = tabScroller.viewport.getViewRect();
0366:                        int cropline;
0367:                        switch (tabPlacement) {
0368:                        case LEFT:
0369:                        case RIGHT:
0370:                            cropline = viewRect.y + viewRect.height;
0371:                            if ((tabRect.y < cropline)
0372:                                    && (tabRect.y + tabRect.height > cropline)) {
0373:                                cropShape = createCroppedTabClip(tabPlacement,
0374:                                        tabRect, cropline);
0375:                                cropx = tabRect.x;
0376:                                cropy = cropline - 1;
0377:                            }
0378:                            break;
0379:                        case TOP:
0380:                        case BOTTOM:
0381:                        default:
0382:                            cropline = viewRect.x + viewRect.width;
0383:                            if ((tabRect.x < cropline)
0384:                                    && (tabRect.x + tabRect.width > cropline)) {
0385:                                cropShape = createCroppedTabClip(tabPlacement,
0386:                                        tabRect, cropline);
0387:                                cropx = cropline - 1;
0388:                                cropy = tabRect.y;
0389:                            }
0390:                        }
0391:                        if (cropShape != null) {
0392:                            save = g.getClip();
0393:                            g2.clip(cropShape);
0394:                        }
0395:                    }
0396:                }
0397:
0398:                paintTabBackground(g, tabPlacement, tabIndex, tabRect.x,
0399:                        tabRect.y, tabRect.width, tabRect.height, isSelected);
0400:
0401:                paintTabBorder(g, tabPlacement, tabIndex, tabRect.x, tabRect.y,
0402:                        tabRect.width, tabRect.height, isSelected);
0403:
0404:                String title = tabPane.getTitleAt(tabIndex);
0405:                Font font = tabPane.getFont();
0406:                FontMetrics metrics = g.getFontMetrics(font);
0407:                Icon icon = getIconForTab(tabIndex);
0408:
0409:                layoutLabel(tabPlacement, metrics, tabIndex, title, icon,
0410:                        tabRect, iconRect, textRect, isSelected);
0411:
0412:                paintText(g, tabPlacement, font, metrics, tabIndex, title,
0413:                        textRect, isSelected);
0414:
0415:                paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
0416:
0417:                paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect,
0418:                        textRect, isSelected);
0419:
0420:                if (cropShape != null) {
0421:                    paintCroppedTabEdge(g, tabPlacement, tabIndex, isSelected,
0422:                            cropx, cropy);
0423:                    g.setClip(save);
0424:                }
0425:            }
0426:
0427:            /*
0428:             * This method will create and return a polygon shape for the given tab
0429:             * rectangle which has been cropped at the specified cropline with a torn
0430:             * edge visual. e.g. A "File" tab which has cropped been cropped just after
0431:             * the "i": 
0432:             *    -------------
0433:             *    |  .....     |
0434:             *    |  .          |
0435:             *    |  ...  .    |
0436:             *    |  .    .   |
0437:             *    |  .    .    |
0438:             *    |  .    .     |
0439:             *    --------------
0440:             * 
0441:             * The x, y arrays below define the pattern used to create a "torn" edge
0442:             * segment which is repeated to fill the edge of the tab. For tabs placed on
0443:             * TOP and BOTTOM, this righthand torn edge is created by line segments
0444:             * which are defined by coordinates obtained by subtracting xCropLen[i] from
0445:             * (tab.x + tab.width) and adding yCroplen[i] to (tab.y). For tabs placed on
0446:             * LEFT or RIGHT, the bottom torn edge is created by subtracting xCropLen[i]
0447:             * from (tab.y + tab.height) and adding yCropLen[i] to (tab.x).
0448:             */
0449:            private int[] xCropLen = { 1, 1, 0, 0, 1, 1, 2, 2 };
0450:
0451:            private int[] yCropLen = { 0, 3, 3, 6, 6, 9, 9, 12 };
0452:
0453:            private static final int CROP_SEGMENT = 12;
0454:
0455:            private Polygon createCroppedTabClip(int tabPlacement,
0456:                    Rectangle tabRect, int cropline) {
0457:                int rlen = 0;
0458:                int start = 0;
0459:                int end = 0;
0460:                int ostart = 0;
0461:
0462:                switch (tabPlacement) {
0463:                case LEFT:
0464:                case RIGHT:
0465:                    rlen = tabRect.width;
0466:                    start = tabRect.x;
0467:                    end = tabRect.x + tabRect.width;
0468:                    ostart = tabRect.y;
0469:                    break;
0470:                case TOP:
0471:                case BOTTOM:
0472:                default:
0473:                    rlen = tabRect.height;
0474:                    start = tabRect.y;
0475:                    end = tabRect.y + tabRect.height;
0476:                    ostart = tabRect.x;
0477:                }
0478:                int rcnt = rlen / CROP_SEGMENT;
0479:                if (rlen % CROP_SEGMENT > 0) {
0480:                    rcnt++;
0481:                }
0482:                int npts = 2 + (rcnt * 8);
0483:                int[] xp = new int[npts];
0484:                int[] yp = new int[npts];
0485:                int pcnt = 0;
0486:
0487:                xp[pcnt] = ostart;
0488:                yp[pcnt++] = end;
0489:                xp[pcnt] = ostart;
0490:                yp[pcnt++] = start;
0491:                for (int i = 0; i < rcnt; i++) {
0492:                    for (int j = 0; j < xCropLen.length; j++) {
0493:                        xp[pcnt] = cropline - xCropLen[j];
0494:                        yp[pcnt] = start + (i * CROP_SEGMENT) + yCropLen[j];
0495:                        if (yp[pcnt] >= end) {
0496:                            yp[pcnt] = end;
0497:                            pcnt++;
0498:                            break;
0499:                        }
0500:                        pcnt++;
0501:                    }
0502:                }
0503:                if (tabPlacement == SwingConstants.TOP
0504:                        || tabPlacement == SwingConstants.BOTTOM) {
0505:                    return new Polygon(xp, yp, pcnt);
0506:
0507:                }
0508:                //LEFT or RIGHT
0509:                return new Polygon(yp, xp, pcnt);
0510:            }
0511:
0512:            /* If tabLayoutPolicy == SCROLL_TAB_LAYOUT, this method will paint an edge
0513:             * indicating the tab is cropped in the viewport display
0514:             */
0515:            private void paintCroppedTabEdge(Graphics g, int tabPlacement,
0516:                    int tabIndex, boolean isSelected, int x, int y) {
0517:                switch (tabPlacement) {
0518:                case LEFT:
0519:                case RIGHT:
0520:                    int xx = x;
0521:                    g.setColor(shadow);
0522:                    while (xx <= x + rects[tabIndex].width) {
0523:                        for (int i = 0; i < xCropLen.length; i += 2) {
0524:                            g.drawLine(xx + yCropLen[i], y - xCropLen[i], xx
0525:                                    + yCropLen[i + 1] - 1, y - xCropLen[i + 1]);
0526:                        }
0527:                        xx += CROP_SEGMENT;
0528:                    }
0529:                    break;
0530:                case TOP:
0531:                case BOTTOM:
0532:                default:
0533:                    int yy = y;
0534:                    g.setColor(shadow);
0535:                    while (yy <= y + rects[tabIndex].height) {
0536:                        for (int i = 0; i < xCropLen.length; i += 2) {
0537:                            g
0538:                                    .drawLine(x - xCropLen[i],
0539:                                            yy + yCropLen[i], x
0540:                                                    - xCropLen[i + 1], yy
0541:                                                    + yCropLen[i + 1] - 1);
0542:                        }
0543:                        yy += CROP_SEGMENT;
0544:                    }
0545:                }
0546:            }
0547:
0548:            private void ensureCurrentLayout() {
0549:                if (!tabPane.isValid()) {
0550:                    tabPane.validate();
0551:                }
0552:                /* If tabPane doesn't have a peer yet, the validate() call will
0553:                 * silently fail.  We handle that by forcing a layout if tabPane
0554:                 * is still invalid.  See bug 4237677.
0555:                 */
0556:                if (!tabPane.isValid()) {
0557:                    TabbedPaneLayout layout = (TabbedPaneLayout) tabPane
0558:                            .getLayout();
0559:                    layout.calculateLayoutInfo();
0560:                }
0561:            }
0562:
0563:            /**
0564:             * Returns the tab index which intersects the specified point
0565:             * in the JTabbedPane's coordinate space.
0566:             */
0567:            public int tabForCoordinate(JTabbedPane pane, int x, int y) {
0568:                ensureCurrentLayout();
0569:                Point p = new Point(x, y);
0570:
0571:                if (scrollableTabLayoutEnabled()) {
0572:                    translatePointToTabPanel(x, y, p);
0573:                    Rectangle viewRect = tabScroller.viewport.getViewRect();
0574:                    if (!viewRect.contains(p)) {
0575:                        return -1;
0576:                    }
0577:                }
0578:                int tabCount = tabPane.getTabCount();
0579:                for (int i = 0; i < tabCount; i++) {
0580:                    if (rects[i].contains(p.x, p.y)) {
0581:                        return i;
0582:                    }
0583:                }
0584:                return -1;
0585:            }
0586:
0587:            protected Rectangle getTabBounds(int tabIndex, Rectangle dest) {
0588:                dest.width = rects[tabIndex].width;
0589:                dest.height = rects[tabIndex].height;
0590:                if (scrollableTabLayoutEnabled()) { // SCROLL_TAB_LAYOUT
0591:                    // Need to translate coordinates based on viewport location & 
0592:                    // view position
0593:                    Point vpp = tabScroller.viewport.getLocation();
0594:                    Point viewp = tabScroller.viewport.getViewPosition();
0595:                    dest.x = rects[tabIndex].x + vpp.x - viewp.x;
0596:                    dest.y = rects[tabIndex].y + vpp.y - viewp.y;
0597:                } else { // WRAP_TAB_LAYOUT
0598:                    dest.x = rects[tabIndex].x;
0599:                    dest.y = rects[tabIndex].y;
0600:                }
0601:                return dest;
0602:            }
0603:
0604:            /**
0605:             * Returns the index of the tab closest to the passed in location, note
0606:             * that the returned tab may not contain the location x,y.
0607:             */
0608:            private int getClosestTab(int x, int y) {
0609:                int min = 0;
0610:                int tabCount = Math.min(rects.length, tabPane.getTabCount());
0611:                int max = tabCount;
0612:                int tabPlacement = tabPane.getTabPlacement();
0613:                boolean useX = (tabPlacement == TOP || tabPlacement == BOTTOM);
0614:                int want = (useX) ? x : y;
0615:
0616:                while (min != max) {
0617:                    int current = (max + min) / 2;
0618:                    int minLoc;
0619:                    int maxLoc;
0620:
0621:                    if (useX) {
0622:                        minLoc = rects[current].x;
0623:                        maxLoc = minLoc + rects[current].width;
0624:                    } else {
0625:                        minLoc = rects[current].y;
0626:                        maxLoc = minLoc + rects[current].height;
0627:                    }
0628:                    if (want < minLoc) {
0629:                        max = current;
0630:                        if (min == max) {
0631:                            return Math.max(0, current - 1);
0632:                        }
0633:                    } else if (want >= maxLoc) {
0634:                        min = current;
0635:                        if (max - min <= 1) {
0636:                            return Math.max(current + 1, tabCount - 1);
0637:                        }
0638:                    } else {
0639:                        return current;
0640:                    }
0641:                }
0642:                return min;
0643:            }
0644:
0645:            /**
0646:             * Returns a point which is translated from the specified point in the
0647:             * JTabbedPane's coordinate space to the coordinate space of the
0648:             * ScrollableTabPanel.  This is used for SCROLL_TAB_LAYOUT ONLY.
0649:             */
0650:            private Point translatePointToTabPanel(int srcx, int srcy,
0651:                    Point dest) {
0652:                Point vpp = tabScroller.viewport.getLocation();
0653:                Point viewp = tabScroller.viewport.getViewPosition();
0654:                dest.x = srcx - vpp.x + viewp.x;
0655:                dest.y = srcy - vpp.y + viewp.y;
0656:                return dest;
0657:            }
0658:
0659:            protected void paintTabArea(Graphics g, int tabPlacement,
0660:                    int selectedIndex) {
0661:                int tabCount = tabPane.getTabCount();
0662:
0663:                Rectangle iconRect = new Rectangle(), textRect = new Rectangle();
0664:                Rectangle clipRect = g.getClipBounds();
0665:
0666:                // Paint tabRuns of tabs from back to front
0667:                for (int i = runCount - 1; i >= 0; i--) {
0668:                    int start = tabRuns[i];
0669:                    int next = tabRuns[(i == runCount - 1) ? 0 : i + 1];
0670:                    int end = (next != 0 ? next - 1 : tabCount - 1);
0671:                    for (int j = end; j >= start; j--) {
0672:                        if (j != selectedIndex && rects[j].intersects(clipRect)) {
0673:                            paintTab(g, tabPlacement, rects, j, iconRect,
0674:                                    textRect);
0675:                        }
0676:                    }
0677:                }
0678:
0679:                // Paint selected tab if its in the front run
0680:                // since it may overlap other tabs
0681:                if (selectedIndex >= 0
0682:                        && rects[selectedIndex].intersects(clipRect)) {
0683:                    paintTab(g, tabPlacement, rects, selectedIndex, iconRect,
0684:                            textRect);
0685:                }
0686:            }
0687:
0688:            /*
0689:             * Copied here from super(super)class to avoid labels being centered on 
0690:             * vertical tab runs if they consist of icon and text
0691:             */
0692:            protected void layoutLabel(int tabPlacement, FontMetrics metrics,
0693:                    int tabIndex, String title, Icon icon, Rectangle tabRect,
0694:                    Rectangle iconRect, Rectangle textRect, boolean isSelected) {
0695:                textRect.x = textRect.y = iconRect.x = iconRect.y = 0;
0696:                //fix of issue #4
0697:                View v = getTextViewForTab(tabIndex);
0698:                if (v != null) {
0699:                    tabPane.putClientProperty("html", v);
0700:                }
0701:
0702:                Rectangle calcRectangle = new Rectangle(tabRect);
0703:                if (isSelected) {
0704:                    Insets calcInsets = getSelectedTabPadInsets(tabPlacement);
0705:                    calcRectangle.x += calcInsets.left;
0706:                    calcRectangle.y += calcInsets.top;
0707:                    calcRectangle.width -= calcInsets.left + calcInsets.right;
0708:                    calcRectangle.height -= calcInsets.bottom + calcInsets.top;
0709:                }
0710:                int xNudge = getTabLabelShiftX(tabPlacement, tabIndex,
0711:                        isSelected);
0712:                int yNudge = getTabLabelShiftY(tabPlacement, tabIndex,
0713:                        isSelected);
0714:                if ((tabPlacement == RIGHT || tabPlacement == LEFT)
0715:                        && icon != null && title != null && !title.equals("")) {
0716:                    SwingUtilities.layoutCompoundLabel(tabPane, metrics, title,
0717:                            icon, SwingConstants.CENTER, SwingConstants.LEFT,
0718:                            SwingConstants.CENTER, SwingConstants.TRAILING,
0719:                            calcRectangle, iconRect, textRect, textIconGap);
0720:                    xNudge += 4;
0721:                } else {
0722:                    SwingUtilities.layoutCompoundLabel(tabPane, metrics, title,
0723:                            icon, SwingConstants.CENTER, SwingConstants.CENTER,
0724:                            SwingConstants.CENTER, SwingConstants.TRAILING,
0725:                            calcRectangle, iconRect, textRect, textIconGap);
0726:                    iconRect.y += calcRectangle.height % 2;
0727:                }
0728:
0729:                //fix of issue #4
0730:                tabPane.putClientProperty("html", null);
0731:
0732:                iconRect.x += xNudge;
0733:                iconRect.y += yNudge;
0734:                textRect.x += xNudge;
0735:                textRect.y += yNudge;
0736:            }
0737:
0738:            /**
0739:             * Answers the icon for the tab with the specified index.
0740:             * In case, we have globally switched of the use tab icons,
0741:             * we answer <code>null</code> if and only if we have a title.
0742:             */
0743:            protected Icon getIconForTab(int tabIndex) {
0744:                String title = tabPane.getTitleAt(tabIndex);
0745:                boolean hasTitle = (title != null) && (title.length() > 0);
0746:                return !isTabIconsEnabled && hasTitle ? null : super 
0747:                        .getIconForTab(tabIndex);
0748:            }
0749:
0750:            /**
0751:             * Creates the layout manager used to set the tab's bounds.
0752:             */
0753:            protected LayoutManager createLayoutManager() {
0754:                if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) {
0755:                    return new TabbedPaneScrollLayout();
0756:                }
0757:                /* WRAP_TAB_LAYOUT */
0758:                return new TabbedPaneLayout();
0759:            }
0760:
0761:            /* In an attempt to preserve backward compatibility for programs
0762:             * which have extended BasicTabbedPaneUI to do their own layout, the
0763:             * UI uses the installed layoutManager (and not tabLayoutPolicy) to
0764:             * determine if scrollTabLayout is enabled.
0765:             */
0766:            private boolean scrollableTabLayoutEnabled() {
0767:                return tabPane.getLayout() instanceof  TabbedPaneScrollLayout;
0768:            }
0769:
0770:            protected boolean isTabInFirstRun(int tabIndex) {
0771:                return getRunForTab(tabPane.getTabCount(), tabIndex) == 0;
0772:            }
0773:
0774:            protected void paintContentBorder(Graphics g, int tabPlacement,
0775:                    int selectedIndex) {
0776:                int width = tabPane.getWidth();
0777:                int height = tabPane.getHeight();
0778:                Insets insets = tabPane.getInsets();
0779:
0780:                int x = insets.left;
0781:                int y = insets.top;
0782:                int w = width - insets.right - insets.left;
0783:                int h = height - insets.top - insets.bottom;
0784:
0785:                switch (tabPlacement) {
0786:                case LEFT:
0787:                    x += calculateTabAreaWidth(tabPlacement, runCount,
0788:                            maxTabWidth);
0789:                    w -= (x - insets.left);
0790:                    break;
0791:                case RIGHT:
0792:                    w -= calculateTabAreaWidth(tabPlacement, runCount,
0793:                            maxTabWidth);
0794:                    break;
0795:                case BOTTOM:
0796:                    h -= calculateTabAreaHeight(tabPlacement, runCount,
0797:                            maxTabHeight);
0798:                    break;
0799:                case TOP:
0800:                default:
0801:                    y += calculateTabAreaHeight(tabPlacement, runCount,
0802:                            maxTabHeight);
0803:                    h -= (y - insets.top);
0804:                }
0805:                // Fill region behind content area
0806:                g.setColor(selectColor == null ? tabPane.getBackground()
0807:                        : selectColor);
0808:                g.fillRect(x, y, w, h);
0809:
0810:                Rectangle selRect;
0811:                selRect = (selectedIndex < 0) ? null : getTabBounds(
0812:                        selectedIndex, calcRect);
0813:                boolean drawBroken = selectedIndex >= 0
0814:                        && isTabInFirstRun(selectedIndex);
0815:                boolean isContentBorderPainted = !hasNoContentBorder();
0816:                // It sounds a bit odd to call paintContentBorder with 
0817:                // a parameter isContentBorderPainted set to false.
0818:                // But in this case the part of the border touching the tab
0819:                // area will still be painted so best let the renderer decide.
0820:                renderer.paintContentBorderTopEdge(g, x, y, w, h, drawBroken,
0821:                        selRect, isContentBorderPainted);
0822:                renderer.paintContentBorderLeftEdge(g, x, y, w, h, drawBroken,
0823:                        selRect, isContentBorderPainted);
0824:                renderer.paintContentBorderBottomEdge(g, x, y, w, h,
0825:                        drawBroken, selRect, isContentBorderPainted);
0826:                renderer.paintContentBorderRightEdge(g, x, y, w, h, drawBroken,
0827:                        selRect, isContentBorderPainted);
0828:            }
0829:
0830:            //
0831:            // Here comes a number of methods that are just delegated to the 
0832:            // appropriate renderer
0833:            //
0834:            /** 
0835:             * Returns the insets (i.e. the width) of the content Border.
0836:             */
0837:            protected Insets getContentBorderInsets(int tabPlacement) {
0838:                return renderer.getContentBorderInsets(super 
0839:                        .getContentBorderInsets(tabPlacement));
0840:            }
0841:
0842:            /**
0843:             * Returns the amount by which the Tab Area is inset. 
0844:             */
0845:            protected Insets getTabAreaInsets(int tabPlacement) {
0846:                return renderer.getTabAreaInsets(super 
0847:                        .getTabAreaInsets(tabPlacement));
0848:            }
0849:
0850:            /**
0851:             * Returns the amount by which the label should be shifted horizontally.
0852:             */
0853:            protected int getTabLabelShiftX(int tabPlacement, int tabIndex,
0854:                    boolean isSelected) {
0855:                return renderer.getTabLabelShiftX(tabIndex, isSelected);
0856:            }
0857:
0858:            /**
0859:             * Returns the amount by which the label should be shifted vertically.
0860:             */
0861:            protected int getTabLabelShiftY(int tabPlacement, int tabIndex,
0862:                    boolean isSelected) {
0863:                return renderer.getTabLabelShiftY(tabIndex, isSelected);
0864:            }
0865:
0866:            /**
0867:             * Returns the amount (in pixels) by which two runs should overlap.
0868:             */
0869:            protected int getTabRunOverlay(int tabPlacement) {
0870:                return renderer.getTabRunOverlay(tabRunOverlay);
0871:            }
0872:
0873:            /**
0874:             * This boolean controls wheather the given run should be padded to 
0875:             * use up as much space as the others (with more tabs in them).
0876:             */
0877:            protected boolean shouldPadTabRun(int tabPlacement, int run) {
0878:                return renderer.shouldPadTabRun(run, super .shouldPadTabRun(
0879:                        tabPlacement, run));
0880:            }
0881:
0882:            /**
0883:             * Returns the amount by which the run number <code>run</code>
0884:             * should be indented. Add six pixels for every run to make
0885:             * diagonal lines align.
0886:             */
0887:            protected int getTabRunIndent(int tabPlacement, int run) {
0888:                return renderer.getTabRunIndent(run);
0889:            }
0890:
0891:            /**
0892:             * Returns the insets for this tab.
0893:             */
0894:            protected Insets getTabInsets(int tabPlacement, int tabIndex) {
0895:                return renderer.getTabInsets(tabIndex, tabInsets);
0896:            }
0897:
0898:            /**
0899:             * Returns the insets for selected tab.
0900:             */
0901:            protected Insets getSelectedTabPadInsets(int tabPlacement) {
0902:                return renderer.getSelectedTabPadInsets();
0903:            }
0904:
0905:            /**
0906:             * Draws the rectancle around the Tab label which indicates keyboard focus.
0907:             */
0908:            protected void paintFocusIndicator(Graphics g, int tabPlacement,
0909:                    Rectangle[] rectangles, int tabIndex, Rectangle iconRect,
0910:                    Rectangle textRect, boolean isSelected) {
0911:                renderer.paintFocusIndicator(g, rectangles, tabIndex, iconRect,
0912:                        textRect, isSelected);
0913:            }
0914:
0915:            /**
0916:             * Fills the background of the given tab to make sure overlap of 
0917:             * tabs is handled correctly.
0918:             * Note: that tab backgrounds seem to be painted somewhere else, too.
0919:             */
0920:            protected void paintTabBackground(Graphics g, int tabPlacement,
0921:                    int tabIndex, int x, int y, int w, int h, boolean isSelected) {
0922:                renderer
0923:                        .paintTabBackground(g, tabIndex, x, y, w, h, isSelected);
0924:            }
0925:
0926:            /**
0927:             * Paints the border for one tab. Gets the bounds of the tab as parameters.
0928:             * Note that the result is not clipped so you can paint outside that
0929:             * rectangle. Tabs painted later on have a chance to overwrite though.
0930:             */
0931:            protected void paintTabBorder(Graphics g, int tabPlacement,
0932:                    int tabIndex, int x, int y, int w, int h, boolean isSelected) {
0933:                renderer.paintTabBorder(g, tabIndex, x, y, w, h, isSelected);
0934:            }
0935:
0936:            /**
0937:             * Answers wheather tab runs should be rotated. If true, the layout mechanism
0938:             * will move the run containing the selected tab so that it touches
0939:             * the content pane.
0940:             */
0941:            protected boolean shouldRotateTabRuns(int tabPlacement) {
0942:                return false;
0943:            }
0944:
0945:            private class TabSelectionHandler implements  ChangeListener {
0946:
0947:                private Rectangle rect = new Rectangle();
0948:
0949:                public void stateChanged(ChangeEvent e) {
0950:                    JTabbedPane tabPane = (JTabbedPane) e.getSource();
0951:                    tabPane.revalidate();
0952:                    tabPane.repaint();
0953:
0954:                    if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) {
0955:                        int index = tabPane.getSelectedIndex();
0956:                        if (index < rects.length && index != -1) {
0957:                            rect.setBounds(rects[index]);
0958:                            Point viewPosition = tabScroller.viewport
0959:                                    .getViewPosition();
0960:                            if (rect.x < viewPosition.x) {
0961:                                rect.x -= renderer.getTabsOverlay();
0962:                            } else {
0963:                                rect.x += renderer.getTabsOverlay();
0964:                            }
0965:                            tabScroller.tabPanel.scrollRectToVisible(rect);
0966:                        }
0967:                    }
0968:                }
0969:            }
0970:
0971:            /**
0972:             * Catches and handles property change events. In addition to the super 
0973:             * class behavior we listen to changes of the ancestor, tab placement, 
0974:             * and JGoodies options for content border, and embedded tabs.
0975:             */
0976:            private class MyPropertyChangeHandler extends
0977:                    BasicTabbedPaneUI.PropertyChangeHandler {
0978:                public void propertyChange(PropertyChangeEvent e) {
0979:                    String pName = e.getPropertyName();
0980:
0981:                    if (null == pName) {
0982:                        return;
0983:                    }
0984:
0985:                    super .propertyChange(e);
0986:
0987:                    if (pName.equals("tabPlacement")) {
0988:                        tabPlacementChanged();
0989:                        return;
0990:                    }
0991:                    if (pName.equals(Options.EMBEDDED_TABS_KEY)) {
0992:                        embeddedTabsPropertyChanged((Boolean) e.getNewValue());
0993:                        return;
0994:                    }
0995:                    if (pName.equals(Options.NO_CONTENT_BORDER_KEY)) {
0996:                        noContentBorderPropertyChanged((Boolean) e
0997:                                .getNewValue());
0998:                        return;
0999:                    }
1000:                }
1001:            }
1002:
1003:            /**
1004:             * Does all the layout work. The result is stored in the container
1005:             * class's instance variables. Mainly the rects[] vector.
1006:             */
1007:            private class TabbedPaneLayout extends
1008:                    BasicTabbedPaneUI.TabbedPaneLayout implements  LayoutManager {
1009:
1010:                protected void calculateTabRects(int tabPlacement, int tabCount) {
1011:                    FontMetrics metrics = getFontMetrics();
1012:                    Dimension size = tabPane.getSize();
1013:                    Insets insets = tabPane.getInsets();
1014:                    Insets theTabAreaInsets = getTabAreaInsets(tabPlacement);
1015:                    int fontHeight = metrics.getHeight();
1016:                    int selectedIndex = tabPane.getSelectedIndex();
1017:                    int theTabRunOverlay;
1018:                    int i, j;
1019:                    int x, y;
1020:                    int returnAt;
1021:                    boolean verticalTabRuns = (tabPlacement == LEFT || tabPlacement == RIGHT);
1022:                    boolean leftToRight = PlasticUtils.isLeftToRight(tabPane);
1023:
1024:                    //
1025:                    // Calculate bounds within which a tab run must fit
1026:                    //
1027:                    switch (tabPlacement) {
1028:                    case LEFT:
1029:                        maxTabWidth = calculateMaxTabWidth(tabPlacement);
1030:                        x = insets.left + theTabAreaInsets.left;
1031:                        y = insets.top + theTabAreaInsets.top;
1032:                        returnAt = size.height
1033:                                - (insets.bottom + theTabAreaInsets.bottom);
1034:                        break;
1035:                    case RIGHT:
1036:                        maxTabWidth = calculateMaxTabWidth(tabPlacement);
1037:                        x = size.width - insets.right - theTabAreaInsets.right
1038:                                - maxTabWidth;
1039:                        y = insets.top + theTabAreaInsets.top;
1040:                        returnAt = size.height
1041:                                - (insets.bottom + theTabAreaInsets.bottom);
1042:                        break;
1043:                    case BOTTOM:
1044:                        maxTabHeight = calculateMaxTabHeight(tabPlacement);
1045:                        x = insets.left + theTabAreaInsets.left;
1046:                        y = size.height - insets.bottom
1047:                                - theTabAreaInsets.bottom - maxTabHeight;
1048:                        returnAt = size.width
1049:                                - (insets.right + theTabAreaInsets.right);
1050:                        break;
1051:                    case TOP:
1052:                    default:
1053:                        maxTabHeight = calculateMaxTabHeight(tabPlacement);
1054:                        x = insets.left + theTabAreaInsets.left;
1055:                        y = insets.top + theTabAreaInsets.top;
1056:                        returnAt = size.width
1057:                                - (insets.right + theTabAreaInsets.right);
1058:                        break;
1059:                    }
1060:
1061:                    theTabRunOverlay = getTabRunOverlay(tabPlacement);
1062:
1063:                    runCount = 0;
1064:                    selectedRun = -1;
1065:                    //keeps track of where we are in the current run.
1066:                    //this helps not to rely on fragile positioning 
1067:                    //informaion to find out wheter the active Tab
1068:                    //is the first in run
1069:                    int tabInRun = -1;
1070:                    // make a copy of returnAt for the current run and modify
1071:                    // that so returnAt may still be used later on
1072:                    int runReturnAt = returnAt;
1073:
1074:                    if (tabCount == 0) {
1075:                        return;
1076:                    }
1077:
1078:                    // Run through tabs and partition them into runs
1079:                    Rectangle rect;
1080:                    for (i = 0; i < tabCount; i++) {
1081:                        rect = rects[i];
1082:                        tabInRun++;
1083:
1084:                        if (!verticalTabRuns) {
1085:                            // Tabs on TOP or BOTTOM....
1086:                            if (i > 0) {
1087:                                rect.x = rects[i - 1].x + rects[i - 1].width;
1088:                            } else {
1089:                                tabRuns[0] = 0;
1090:                                runCount = 1;
1091:                                maxTabWidth = 0;
1092:                                rect.x = x;
1093:                                //  tabInRun = 0;
1094:                            }
1095:                            rect.width = calculateTabWidth(tabPlacement, i,
1096:                                    metrics);
1097:                            maxTabWidth = Math.max(maxTabWidth, rect.width);
1098:
1099:                            // Never move a TAB down a run if it is the first in run. 
1100:                            // Even if there isn't enough room, moving it to a fresh 
1101:                            // line won't help.
1102:                            //                    if (rect.x != 2 + insets.left && rect.x + rect.width > returnAt) {
1103:                            // Never rely on phisical position information to determine 
1104:                            // logical position (if you can avoid it)
1105:                            if (tabInRun != 0
1106:                                    && rect.x + rect.width > runReturnAt) {
1107:                                if (runCount > tabRuns.length - 1) {
1108:                                    expandTabRunsArray();
1109:                                }
1110:                                // just created a new run, adjust some counters
1111:                                tabInRun = 0;
1112:                                tabRuns[runCount] = i;
1113:                                runCount++;
1114:                                rect.x = x;
1115:                                runReturnAt = runReturnAt
1116:                                        - 2
1117:                                        * getTabRunIndent(tabPlacement,
1118:                                                runCount);
1119:                            }
1120:                            // Initialize y position in case there's just one run
1121:                            rect.y = y;
1122:                            rect.height = maxTabHeight /* - 2*/;
1123:
1124:                        } else {
1125:                            // Tabs on LEFT or RIGHT...
1126:                            if (i > 0) {
1127:                                rect.y = rects[i - 1].y + rects[i - 1].height;
1128:                            } else {
1129:                                tabRuns[0] = 0;
1130:                                runCount = 1;
1131:                                maxTabHeight = 0;
1132:                                rect.y = y;
1133:                                //                        tabInRun = 0;
1134:                            }
1135:                            rect.height = calculateTabHeight(tabPlacement, i,
1136:                                    fontHeight);
1137:                            maxTabHeight = Math.max(maxTabHeight, rect.height);
1138:
1139:                            // Never move a TAB over a run if it is the first in run. 
1140:                            // Even if there isn't enough room, moving it to a fresh 
1141:                            // run won't help.
1142:                            //                    if (rect.y != 2 + insets.top && rect.y + rect.height > returnAt) {
1143:                            if (tabInRun != 0
1144:                                    && rect.y + rect.height > runReturnAt) {
1145:                                if (runCount > tabRuns.length - 1) {
1146:                                    expandTabRunsArray();
1147:                                }
1148:                                tabRuns[runCount] = i;
1149:                                runCount++;
1150:                                rect.y = y;
1151:                                tabInRun = 0;
1152:                                runReturnAt -= 2 * getTabRunIndent(
1153:                                        tabPlacement, runCount);
1154:                            }
1155:                            // Initialize x position in case there's just one column
1156:                            rect.x = x;
1157:                            rect.width = maxTabWidth /* - 2*/;
1158:
1159:                        }
1160:                        if (i == selectedIndex) {
1161:                            selectedRun = runCount - 1;
1162:                        }
1163:                    }
1164:
1165:                    if (runCount > 1) {
1166:                        // Re-distribute tabs in case last run has leftover space
1167:                        //last line flush left is OK
1168:                        //                normalizeTabRuns(tabPlacement, tabCount, verticalTabRuns? y : x, returnAt);
1169:                        //don't need to recalculate selectedRun if not changed
1170:                        //                selectedRun = getRunForTab(tabCount, selectedIndex);
1171:
1172:                        // Rotate run array so that selected run is first
1173:                        if (shouldRotateTabRuns(tabPlacement)) {
1174:                            rotateTabRuns(tabPlacement, selectedRun);
1175:                        }
1176:                    }
1177:
1178:                    // Step through runs from back to front to calculate
1179:                    // tab y locations and to pad runs appropriately
1180:                    for (i = runCount - 1; i >= 0; i--) {
1181:                        int start = tabRuns[i];
1182:                        int next = tabRuns[i == (runCount - 1) ? 0 : i + 1];
1183:                        int end = (next != 0 ? next - 1 : tabCount - 1);
1184:                        int indent = getTabRunIndent(tabPlacement, i);
1185:                        if (!verticalTabRuns) {
1186:                            for (j = start; j <= end; j++) {
1187:                                rect = rects[j];
1188:                                rect.y = y;
1189:                                rect.x += indent;
1190:                                // try to make tabRunIndent symmetric          
1191:                                //	rect.width -= 2* indent + 20;
1192:                            }
1193:                            if (shouldPadTabRun(tabPlacement, i)) {
1194:                                padTabRun(tabPlacement, start, end, returnAt
1195:                                        - 2 * indent);
1196:                            }
1197:                            if (tabPlacement == BOTTOM) {
1198:                                y -= (maxTabHeight - theTabRunOverlay);
1199:                            } else {
1200:                                y += (maxTabHeight - theTabRunOverlay);
1201:                            }
1202:                        } else {
1203:                            for (j = start; j <= end; j++) {
1204:                                rect = rects[j];
1205:                                rect.x = x;
1206:                                rect.y += indent;
1207:                            }
1208:                            if (shouldPadTabRun(tabPlacement, i)) {
1209:                                padTabRun(tabPlacement, start, end, returnAt
1210:                                        - 2 * indent);
1211:                            }
1212:                            if (tabPlacement == RIGHT) {
1213:                                x -= (maxTabWidth - theTabRunOverlay);
1214:                            } else {
1215:                                x += (maxTabWidth - theTabRunOverlay);
1216:                            }
1217:                        }
1218:                    }
1219:
1220:                    // Pad the selected tab so that it appears raised in front
1221:                    padSelectedTab(tabPlacement, selectedIndex);
1222:
1223:                    // if right to left and tab placement on the top or
1224:                    // the bottom, flip x positions and adjust by widths
1225:                    if (!leftToRight && !verticalTabRuns) {
1226:                        int rightMargin = size.width
1227:                                - (insets.right + theTabAreaInsets.right);
1228:                        for (i = 0; i < tabCount; i++) {
1229:                            rects[i].x = rightMargin - rects[i].x
1230:                                    - rects[i].width
1231:                                    + renderer.getTabsOverlay();
1232:                        }
1233:                    }
1234:                }
1235:
1236:                /**
1237:                 * Overridden to insure the same behavior in JDK 6.0 as in JDK 5.0.
1238:                 */
1239:                protected void padSelectedTab(int tabPlacement,
1240:                        int selectedIndex) {
1241:                    if (selectedIndex >= 0) {
1242:                        Rectangle selRect = rects[selectedIndex];
1243:                        Insets padInsets = getSelectedTabPadInsets(tabPlacement);
1244:                        selRect.x -= padInsets.left;
1245:                        selRect.width += (padInsets.left + padInsets.right);
1246:                        selRect.y -= padInsets.top;
1247:                        selRect.height += (padInsets.top + padInsets.bottom);
1248:                    }
1249:                }
1250:
1251:            }
1252:
1253:            private boolean requestFocusForVisibleComponent() {
1254:                Component visibleComponent = getVisibleComponent();
1255:                if (visibleComponent.isFocusable()) {
1256:                    visibleComponent.requestFocus();
1257:                    return true;
1258:                }
1259:                if (visibleComponent instanceof  JComponent) {
1260:                    if (((JComponent) visibleComponent).requestDefaultFocus()) {
1261:                        return true;
1262:                    }
1263:                }
1264:                return false;
1265:            }
1266:
1267:            private static class ScrollTabsForwardAction extends AbstractAction {
1268:
1269:                public void actionPerformed(ActionEvent e) {
1270:                    JTabbedPane pane = null;
1271:                    Object src = e.getSource();
1272:                    if (src instanceof  JTabbedPane) {
1273:                        pane = (JTabbedPane) src;
1274:                    } else if (src instanceof  PlasticArrowButton) {
1275:                        pane = (JTabbedPane) ((PlasticArrowButton) src)
1276:                                .getParent();
1277:                    } else {
1278:                        return; // shouldn't happen
1279:                    }
1280:                    PlasticTabbedPaneUI ui = (PlasticTabbedPaneUI) pane.getUI();
1281:
1282:                    if (ui.scrollableTabLayoutEnabled()) {
1283:                        ui.tabScroller.scrollForward(pane.getTabPlacement());
1284:                    }
1285:                }
1286:            }
1287:
1288:            private static class ScrollTabsBackwardAction extends
1289:                    AbstractAction {
1290:
1291:                public void actionPerformed(ActionEvent e) {
1292:                    JTabbedPane pane = null;
1293:                    Object src = e.getSource();
1294:                    if (src instanceof  JTabbedPane) {
1295:                        pane = (JTabbedPane) src;
1296:                    } else if (src instanceof  PlasticArrowButton) {
1297:                        pane = (JTabbedPane) ((PlasticArrowButton) src)
1298:                                .getParent();
1299:                    } else {
1300:                        return; // shouldn't happen
1301:                    }
1302:                    PlasticTabbedPaneUI ui = (PlasticTabbedPaneUI) pane.getUI();
1303:
1304:                    if (ui.scrollableTabLayoutEnabled()) {
1305:                        ui.tabScroller.scrollBackward(pane.getTabPlacement());
1306:                    }
1307:                }
1308:            }
1309:
1310:            private class TabbedPaneScrollLayout extends TabbedPaneLayout {
1311:
1312:                protected int preferredTabAreaHeight(int tabPlacement, int width) {
1313:                    return calculateMaxTabHeight(tabPlacement);
1314:                }
1315:
1316:                protected int preferredTabAreaWidth(int tabPlacement, int height) {
1317:                    return calculateMaxTabWidth(tabPlacement);
1318:                }
1319:
1320:                public void layoutContainer(Container parent) {
1321:                    int tabPlacement = tabPane.getTabPlacement();
1322:                    int tabCount = tabPane.getTabCount();
1323:                    Insets insets = tabPane.getInsets();
1324:                    int selectedIndex = tabPane.getSelectedIndex();
1325:                    Component visibleComponent = getVisibleComponent();
1326:
1327:                    calculateLayoutInfo();
1328:
1329:                    if (selectedIndex < 0) {
1330:                        if (visibleComponent != null) {
1331:                            // The last tab was removed, so remove the component
1332:                            setVisibleComponent(null);
1333:                        }
1334:                    } else {
1335:                        Component selectedComponent = tabPane
1336:                                .getComponentAt(selectedIndex);
1337:                        boolean shouldChangeFocus = false;
1338:
1339:                        // In order to allow programs to use a single component
1340:                        // as the display for multiple tabs, we will not change
1341:                        // the visible compnent if the currently selected tab
1342:                        // has a null component.  This is a bit dicey, as we don't
1343:                        // explicitly state we support this in the spec, but since
1344:                        // programs are now depending on this, we're making it work.
1345:                        //
1346:                        if (selectedComponent != null) {
1347:                            if (selectedComponent != visibleComponent
1348:                                    && visibleComponent != null) {
1349:                                if (SwingUtilities
1350:                                        .findFocusOwner(visibleComponent) != null) {
1351:                                    shouldChangeFocus = true;
1352:                                }
1353:                            }
1354:                            setVisibleComponent(selectedComponent);
1355:                        }
1356:                        int tx, ty, tw, th; // tab area bounds
1357:                        int cx, cy, cw, ch; // content area bounds
1358:                        Insets contentInsets = getContentBorderInsets(tabPlacement);
1359:                        Rectangle bounds = tabPane.getBounds();
1360:                        int numChildren = tabPane.getComponentCount();
1361:
1362:                        if (numChildren > 0) {
1363:                            switch (tabPlacement) {
1364:                            case LEFT:
1365:                                // calculate tab area bounds
1366:                                tw = calculateTabAreaWidth(tabPlacement,
1367:                                        runCount, maxTabWidth);
1368:                                th = bounds.height - insets.top - insets.bottom;
1369:                                tx = insets.left;
1370:                                ty = insets.top;
1371:
1372:                                // calculate content area bounds
1373:                                cx = tx + tw + contentInsets.left;
1374:                                cy = ty + contentInsets.top;
1375:                                cw = bounds.width - insets.left - insets.right
1376:                                        - tw - contentInsets.left
1377:                                        - contentInsets.right;
1378:                                ch = bounds.height - insets.top - insets.bottom
1379:                                        - contentInsets.top
1380:                                        - contentInsets.bottom;
1381:                                break;
1382:                            case RIGHT:
1383:                                // calculate tab area bounds
1384:                                tw = calculateTabAreaWidth(tabPlacement,
1385:                                        runCount, maxTabWidth);
1386:                                th = bounds.height - insets.top - insets.bottom;
1387:                                tx = bounds.width - insets.right - tw;
1388:                                ty = insets.top;
1389:
1390:                                // calculate content area bounds
1391:                                cx = insets.left + contentInsets.left;
1392:                                cy = insets.top + contentInsets.top;
1393:                                cw = bounds.width - insets.left - insets.right
1394:                                        - tw - contentInsets.left
1395:                                        - contentInsets.right;
1396:                                ch = bounds.height - insets.top - insets.bottom
1397:                                        - contentInsets.top
1398:                                        - contentInsets.bottom;
1399:                                break;
1400:                            case BOTTOM:
1401:                                // calculate tab area bounds
1402:                                tw = bounds.width - insets.left - insets.right;
1403:                                th = calculateTabAreaHeight(tabPlacement,
1404:                                        runCount, maxTabHeight);
1405:                                tx = insets.left;
1406:                                ty = bounds.height - insets.bottom - th;
1407:
1408:                                // calculate content area bounds
1409:                                cx = insets.left + contentInsets.left;
1410:                                cy = insets.top + contentInsets.top;
1411:                                cw = bounds.width - insets.left - insets.right
1412:                                        - contentInsets.left
1413:                                        - contentInsets.right;
1414:                                ch = bounds.height - insets.top - insets.bottom
1415:                                        - th - contentInsets.top
1416:                                        - contentInsets.bottom;
1417:                                break;
1418:                            case TOP:
1419:                            default:
1420:                                // calculate tab area bounds
1421:                                tw = bounds.width - insets.left - insets.right;
1422:                                th = calculateTabAreaHeight(tabPlacement,
1423:                                        runCount, maxTabHeight);
1424:                                tx = insets.left;
1425:                                ty = insets.top;
1426:
1427:                                // calculate content area bounds
1428:                                cx = tx + contentInsets.left;
1429:                                cy = ty + th + contentInsets.top;
1430:                                cw = bounds.width - insets.left - insets.right
1431:                                        - contentInsets.left
1432:                                        - contentInsets.right;
1433:                                ch = bounds.height - insets.top - insets.bottom
1434:                                        - th - contentInsets.top
1435:                                        - contentInsets.bottom;
1436:                            }
1437:
1438:                            for (int i = 0; i < numChildren; i++) {
1439:                                Component child = tabPane.getComponent(i);
1440:
1441:                                if (tabScroller != null
1442:                                        && child == tabScroller.viewport) {
1443:                                    JViewport viewport = (JViewport) child;
1444:                                    Rectangle viewRect = viewport.getViewRect();
1445:                                    int vw = tw;
1446:                                    int vh = th;
1447:                                    Dimension butSize = tabScroller.scrollForwardButton
1448:                                            .getPreferredSize();
1449:                                    switch (tabPlacement) {
1450:                                    case LEFT:
1451:                                    case RIGHT:
1452:                                        int totalTabHeight = rects[tabCount - 1].y
1453:                                                + rects[tabCount - 1].height;
1454:                                        if (totalTabHeight > th) {
1455:                                            // Allow space for scrollbuttons
1456:                                            vh = (th > 2 * butSize.height) ? th
1457:                                                    - 2 * butSize.height : 0;
1458:                                            if (totalTabHeight - viewRect.y <= vh) {
1459:                                                // Scrolled to the end, so ensure the
1460:                                                // viewport size is
1461:                                                // such that the scroll offset aligns
1462:                                                // with a tab
1463:                                                vh = totalTabHeight
1464:                                                        - viewRect.y;
1465:                                            }
1466:                                        }
1467:                                        break;
1468:                                    case BOTTOM:
1469:                                    case TOP:
1470:                                    default:
1471:                                        int totalTabWidth = rects[tabCount - 1].x
1472:                                                + rects[tabCount - 1].width
1473:                                                + renderer.getTabsOverlay();
1474:                                        if (totalTabWidth > tw) {
1475:                                            // Need to allow space for scrollbuttons
1476:                                            vw = (tw > 2 * butSize.width) ? tw
1477:                                                    - 2 * butSize.width : 0;
1478:                                            if (totalTabWidth - viewRect.x <= vw) {
1479:                                                // Scrolled to the end, so ensure the
1480:                                                // viewport size is
1481:                                                // such that the scroll offset aligns
1482:                                                // with a tab
1483:                                                vw = totalTabWidth - viewRect.x;
1484:                                            }
1485:                                        }
1486:                                    }
1487:                                    child.setBounds(tx, ty, vw, vh);
1488:
1489:                                } else if (tabScroller != null
1490:                                        && (child == tabScroller.scrollForwardButton || child == tabScroller.scrollBackwardButton)) {
1491:                                    Component scrollbutton = child;
1492:                                    Dimension bsize = scrollbutton
1493:                                            .getPreferredSize();
1494:                                    int bx = 0;
1495:                                    int by = 0;
1496:                                    int bw = bsize.width;
1497:                                    int bh = bsize.height;
1498:                                    boolean visible = false;
1499:
1500:                                    switch (tabPlacement) {
1501:                                    case LEFT:
1502:                                    case RIGHT:
1503:                                        int totalTabHeight = rects[tabCount - 1].y
1504:                                                + rects[tabCount - 1].height
1505:                                                + renderer.getTabsOverlay();
1506:                                        if (totalTabHeight > th) {
1507:                                            visible = true;
1508:                                            bx = (tabPlacement == LEFT ? tx
1509:                                                    + tw - bsize.width : tx);
1510:                                            by = (child == tabScroller.scrollForwardButton) ? bounds.height
1511:                                                    - insets.bottom
1512:                                                    - bsize.height
1513:                                                    : bounds.height
1514:                                                            - insets.bottom - 2
1515:                                                            * bsize.height;
1516:                                        }
1517:                                        break;
1518:
1519:                                    case BOTTOM:
1520:                                    case TOP:
1521:                                    default:
1522:                                        int totalTabWidth = rects[tabCount - 1].x
1523:                                                + rects[tabCount - 1].width
1524:                                                + renderer.getTabsOverlay();
1525:
1526:                                        if (totalTabWidth > tw) {
1527:                                            visible = true;
1528:                                            bx = (child == tabScroller.scrollForwardButton) ? bounds.width
1529:                                                    - insets.left - bsize.width
1530:                                                    : bounds.width
1531:                                                            - insets.left - 2
1532:                                                            * bsize.width;
1533:                                            by = (tabPlacement == TOP ? ty + th
1534:                                                    - bsize.height : ty);
1535:                                        }
1536:                                    }
1537:                                    child.setVisible(visible);
1538:                                    if (visible) {
1539:                                        child.setBounds(bx, by, bw, bh);
1540:                                    }
1541:
1542:                                } else {
1543:                                    // All content children...
1544:                                    child.setBounds(cx, cy, cw, ch);
1545:                                }
1546:                            }
1547:                            if (shouldChangeFocus) {
1548:                                if (!requestFocusForVisibleComponent()) {
1549:                                    tabPane.requestFocus();
1550:                                }
1551:                            }
1552:                        }
1553:                    }
1554:                }
1555:
1556:                protected void calculateTabRects(int tabPlacement, int tabCount) {
1557:                    FontMetrics metrics = getFontMetrics();
1558:                    Dimension size = tabPane.getSize();
1559:                    Insets insets = tabPane.getInsets();
1560:                    Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
1561:                    int fontHeight = metrics.getHeight();
1562:                    int selectedIndex = tabPane.getSelectedIndex();
1563:                    boolean verticalTabRuns = (tabPlacement == LEFT || tabPlacement == RIGHT);
1564:                    boolean leftToRight = PlasticUtils.isLeftToRight(tabPane);
1565:                    int x = tabAreaInsets.left;
1566:                    int y = tabAreaInsets.top;
1567:                    int totalWidth = 0;
1568:                    int totalHeight = 0;
1569:
1570:                    //
1571:                    // Calculate bounds within which a tab run must fit
1572:                    //
1573:                    switch (tabPlacement) {
1574:                    case LEFT:
1575:                    case RIGHT:
1576:                        maxTabWidth = calculateMaxTabWidth(tabPlacement);
1577:                        break;
1578:                    case BOTTOM:
1579:                    case TOP:
1580:                    default:
1581:                        maxTabHeight = calculateMaxTabHeight(tabPlacement);
1582:                    }
1583:
1584:                    runCount = 0;
1585:                    selectedRun = -1;
1586:
1587:                    if (tabCount == 0) {
1588:                        return;
1589:                    }
1590:
1591:                    selectedRun = 0;
1592:                    runCount = 1;
1593:
1594:                    // Run through tabs and lay them out in a single run
1595:                    Rectangle rect;
1596:                    for (int i = 0; i < tabCount; i++) {
1597:                        rect = rects[i];
1598:
1599:                        if (!verticalTabRuns) {
1600:                            // Tabs on TOP or BOTTOM....
1601:                            if (i > 0) {
1602:                                rect.x = rects[i - 1].x + rects[i - 1].width;
1603:                            } else {
1604:                                tabRuns[0] = 0;
1605:                                maxTabWidth = 0;
1606:                                totalHeight += maxTabHeight;
1607:                                rect.x = x;
1608:                            }
1609:                            rect.width = calculateTabWidth(tabPlacement, i,
1610:                                    metrics);
1611:                            totalWidth = rect.x + rect.width
1612:                                    + renderer.getTabsOverlay();
1613:                            maxTabWidth = Math.max(maxTabWidth, rect.width);
1614:
1615:                            rect.y = y;
1616:                            rect.height = maxTabHeight/* - 2*/;
1617:
1618:                        } else {
1619:                            // Tabs on LEFT or RIGHT...
1620:                            if (i > 0) {
1621:                                rect.y = rects[i - 1].y + rects[i - 1].height;
1622:                            } else {
1623:                                tabRuns[0] = 0;
1624:                                maxTabHeight = 0;
1625:                                totalWidth = maxTabWidth;
1626:                                rect.y = y;
1627:                            }
1628:                            rect.height = calculateTabHeight(tabPlacement, i,
1629:                                    fontHeight);
1630:                            totalHeight = rect.y + rect.height;
1631:                            maxTabHeight = Math.max(maxTabHeight, rect.height);
1632:
1633:                            rect.x = x;
1634:                            rect.width = maxTabWidth/* - 2*/;
1635:
1636:                        }
1637:                    }
1638:
1639:                    // Pad the selected tab so that it appears raised in front
1640:                    padSelectedTab(tabPlacement, selectedIndex);
1641:
1642:                    // if right to left and tab placement on the top or
1643:                    // the bottom, flip x positions and adjust by widths
1644:                    if (!leftToRight && !verticalTabRuns) {
1645:                        int rightMargin = size.width
1646:                                - (insets.right + tabAreaInsets.right);
1647:                        for (int i = 0; i < tabCount; i++) {
1648:                            rects[i].x = rightMargin - rects[i].x
1649:                                    - rects[i].width;
1650:                        }
1651:                    }
1652:                    tabScroller.tabPanel.setPreferredSize(new Dimension(
1653:                            totalWidth, totalHeight));
1654:                }
1655:            }
1656:
1657:            private class ScrollableTabSupport implements  ActionListener,
1658:                    ChangeListener {
1659:
1660:                public ScrollableTabViewport viewport;
1661:                public ScrollableTabPanel tabPanel;
1662:                public JButton scrollForwardButton;
1663:                public JButton scrollBackwardButton;
1664:                public int leadingTabIndex;
1665:                private Point tabViewPosition = new Point(0, 0);
1666:
1667:                ScrollableTabSupport(int tabPlacement) {
1668:                    viewport = new ScrollableTabViewport();
1669:                    tabPanel = new ScrollableTabPanel();
1670:                    viewport.setView(tabPanel);
1671:                    viewport.addChangeListener(this );
1672:                    createButtons();
1673:                }
1674:
1675:                /**
1676:                 * Recreates the scroll buttons and adds them to the TabbedPane.
1677:                 */
1678:                void createButtons() {
1679:                    if (scrollForwardButton != null) {
1680:                        tabPane.remove(scrollForwardButton);
1681:                        scrollForwardButton.removeActionListener(this );
1682:                        tabPane.remove(scrollBackwardButton);
1683:                        scrollBackwardButton.removeActionListener(this );
1684:                    }
1685:                    int tabPlacement = tabPane.getTabPlacement();
1686:                    int width = UIManager.getInt("ScrollBar.width");
1687:                    if (tabPlacement == TOP || tabPlacement == BOTTOM) {
1688:                        scrollForwardButton = new ArrowButton(EAST, width);
1689:                        scrollBackwardButton = new ArrowButton(WEST, width);
1690:                    } else { // tabPlacement = LEFT || RIGHT
1691:                        scrollForwardButton = new ArrowButton(SOUTH, width);
1692:                        scrollBackwardButton = new ArrowButton(NORTH, width);
1693:                    }
1694:                    scrollForwardButton.addActionListener(this );
1695:                    scrollBackwardButton.addActionListener(this );
1696:                    tabPane.add(scrollForwardButton);
1697:                    tabPane.add(scrollBackwardButton);
1698:                }
1699:
1700:                public void scrollForward(int tabPlacement) {
1701:                    Dimension viewSize = viewport.getViewSize();
1702:                    Rectangle viewRect = viewport.getViewRect();
1703:
1704:                    if (tabPlacement == TOP || tabPlacement == BOTTOM) {
1705:                        if (viewRect.width >= viewSize.width - viewRect.x) {
1706:                            return; // no room left to scroll
1707:                        }
1708:                    } else { // tabPlacement == LEFT || tabPlacement == RIGHT
1709:                        if (viewRect.height >= viewSize.height - viewRect.y) {
1710:                            return;
1711:                        }
1712:                    }
1713:                    setLeadingTabIndex(tabPlacement, leadingTabIndex + 1);
1714:                }
1715:
1716:                public void scrollBackward(int tabPlacement) {
1717:                    if (leadingTabIndex == 0) {
1718:                        return; // no room left to scroll
1719:                    }
1720:                    setLeadingTabIndex(tabPlacement, leadingTabIndex - 1);
1721:                }
1722:
1723:                public void setLeadingTabIndex(int tabPlacement, int index) {
1724:                    leadingTabIndex = index;
1725:                    Dimension viewSize = viewport.getViewSize();
1726:                    Rectangle viewRect = viewport.getViewRect();
1727:
1728:                    switch (tabPlacement) {
1729:                    case TOP:
1730:                    case BOTTOM:
1731:                        tabViewPosition.x = leadingTabIndex == 0 ? 0
1732:                                : rects[leadingTabIndex].x
1733:                                        - renderer.getTabsOverlay();
1734:
1735:                        if ((viewSize.width - tabViewPosition.x) < viewRect.width) {
1736:                            // We've scrolled to the end, so adjust the viewport size
1737:                            // to ensure the view position remains aligned on a tab
1738:                            // boundary
1739:                            Dimension extentSize = new Dimension(viewSize.width
1740:                                    - tabViewPosition.x, viewRect.height);
1741:                            viewport.setExtentSize(extentSize);
1742:                        }
1743:                        break;
1744:                    case LEFT:
1745:                    case RIGHT:
1746:                        tabViewPosition.y = leadingTabIndex == 0 ? 0
1747:                                : rects[leadingTabIndex].y;
1748:
1749:                        if ((viewSize.height - tabViewPosition.y) < viewRect.height) {
1750:                            // We've scrolled to the end, so adjust the viewport size
1751:                            // to ensure the view position remains aligned on a tab
1752:                            // boundary
1753:                            Dimension extentSize = new Dimension(
1754:                                    viewRect.width, viewSize.height
1755:                                            - tabViewPosition.y);
1756:                            viewport.setExtentSize(extentSize);
1757:                        }
1758:                    }
1759:                    viewport.setViewPosition(tabViewPosition);
1760:                }
1761:
1762:                public void stateChanged(ChangeEvent e) {
1763:                    JViewport viewport = (JViewport) e.getSource();
1764:                    int tabPlacement = tabPane.getTabPlacement();
1765:                    int tabCount = tabPane.getTabCount();
1766:                    Rectangle vpRect = viewport.getBounds();
1767:                    Dimension viewSize = viewport.getViewSize();
1768:                    Rectangle viewRect = viewport.getViewRect();
1769:
1770:                    leadingTabIndex = getClosestTab(viewRect.x, viewRect.y);
1771:
1772:                    // If the tab isn't right aligned, adjust it.
1773:                    if (leadingTabIndex + 1 < tabCount) {
1774:                        switch (tabPlacement) {
1775:                        case TOP:
1776:                        case BOTTOM:
1777:                            if (rects[leadingTabIndex].x < viewRect.x) {
1778:                                leadingTabIndex++;
1779:                            }
1780:                            break;
1781:                        case LEFT:
1782:                        case RIGHT:
1783:                            if (rects[leadingTabIndex].y < viewRect.y) {
1784:                                leadingTabIndex++;
1785:                            }
1786:                            break;
1787:                        }
1788:                    }
1789:                    Insets contentInsets = getContentBorderInsets(tabPlacement);
1790:                    switch (tabPlacement) {
1791:                    case LEFT:
1792:                        tabPane.repaint(vpRect.x + vpRect.width, vpRect.y,
1793:                                contentInsets.left, vpRect.height);
1794:                        scrollBackwardButton.setEnabled(viewRect.y > 0
1795:                                && leadingTabIndex > 0);
1796:                        scrollForwardButton
1797:                                .setEnabled(leadingTabIndex < tabCount - 1
1798:                                        && viewSize.height - viewRect.y > viewRect.height);
1799:                        break;
1800:                    case RIGHT:
1801:                        tabPane.repaint(vpRect.x - contentInsets.right,
1802:                                vpRect.y, contentInsets.right, vpRect.height);
1803:                        scrollBackwardButton.setEnabled(viewRect.y > 0
1804:                                && leadingTabIndex > 0);
1805:                        scrollForwardButton
1806:                                .setEnabled(leadingTabIndex < tabCount - 1
1807:                                        && viewSize.height - viewRect.y > viewRect.height);
1808:                        break;
1809:                    case BOTTOM:
1810:                        tabPane.repaint(vpRect.x, vpRect.y
1811:                                - contentInsets.bottom, vpRect.width,
1812:                                contentInsets.bottom);
1813:                        scrollBackwardButton.setEnabled(viewRect.x > 0
1814:                                && leadingTabIndex > 0);
1815:                        scrollForwardButton
1816:                                .setEnabled(leadingTabIndex < tabCount - 1
1817:                                        && viewSize.width - viewRect.x > viewRect.width);
1818:                        break;
1819:                    case TOP:
1820:                    default:
1821:                        tabPane.repaint(vpRect.x, vpRect.y + vpRect.height,
1822:                                vpRect.width, contentInsets.top);
1823:                        scrollBackwardButton.setEnabled(viewRect.x > 0
1824:                                && leadingTabIndex > 0);
1825:                        scrollForwardButton
1826:                                .setEnabled(leadingTabIndex < tabCount - 1
1827:                                        && viewSize.width - viewRect.x > viewRect.width);
1828:                    }
1829:                }
1830:
1831:                /**
1832:                 * ActionListener for the scroll buttons.
1833:                 */
1834:                public void actionPerformed(ActionEvent e) {
1835:                    ActionMap map = tabPane.getActionMap();
1836:
1837:                    if (map != null) {
1838:                        String actionKey;
1839:
1840:                        if (e.getSource() == scrollForwardButton) {
1841:                            actionKey = "scrollTabsForwardAction";
1842:                        } else {
1843:                            actionKey = "scrollTabsBackwardAction";
1844:                        }
1845:                        Action action = map.get(actionKey);
1846:
1847:                        if (action != null && action.isEnabled()) {
1848:                            action.actionPerformed(new ActionEvent(tabPane,
1849:                                    ActionEvent.ACTION_PERFORMED, null, e
1850:                                            .getWhen(), e.getModifiers()));
1851:                        }
1852:                    }
1853:                }
1854:
1855:            }
1856:
1857:            private class ScrollableTabViewport extends JViewport implements 
1858:                    UIResource {
1859:
1860:                public ScrollableTabViewport() {
1861:                    super ();
1862:                    setName("TabbedPane.scrollableViewport");
1863:                    setScrollMode(SIMPLE_SCROLL_MODE);
1864:                    setOpaque(tabPane.isOpaque());
1865:                    Color bgColor = UIManager
1866:                            .getColor("TabbedPane.tabAreaBackground");
1867:                    if (bgColor == null) {
1868:                        bgColor = tabPane.getBackground();
1869:                    }
1870:                    setBackground(bgColor);
1871:                }
1872:            }
1873:
1874:            private class ScrollableTabPanel extends JPanel implements 
1875:                    UIResource {
1876:
1877:                public ScrollableTabPanel() {
1878:                    super (null);
1879:                    setOpaque(tabPane.isOpaque());
1880:                    Color bgColor = UIManager
1881:                            .getColor("TabbedPane.tabAreaBackground");
1882:                    if (bgColor == null) {
1883:                        bgColor = tabPane.getBackground();
1884:                    }
1885:                    setBackground(bgColor);
1886:                }
1887:
1888:                public void paintComponent(Graphics g) {
1889:                    super .paintComponent(g);
1890:                    PlasticTabbedPaneUI.this .paintTabArea(g, tabPane
1891:                            .getTabPlacement(), tabPane.getSelectedIndex());
1892:
1893:                }
1894:            }
1895:
1896:            private static class ArrowButton extends JButton implements 
1897:                    UIResource {
1898:
1899:                private final int buttonWidth;
1900:                private final int direction;
1901:                private boolean mouseIsOver;
1902:
1903:                ArrowButton(int direction, int buttonWidth) {
1904:                    this .direction = direction;
1905:                    this .buttonWidth = buttonWidth;
1906:                    setRequestFocusEnabled(false);
1907:                }
1908:
1909:                protected void processMouseEvent(MouseEvent e) {
1910:                    super .processMouseEvent(e);
1911:                    switch (e.getID()) {
1912:                    case MouseEvent.MOUSE_ENTERED:
1913:                        mouseIsOver = true;
1914:                        revalidate();
1915:                        repaint();
1916:                        break;
1917:                    case MouseEvent.MOUSE_EXITED:
1918:                        mouseIsOver = false;
1919:                        revalidate();
1920:                        repaint();
1921:                        break;
1922:                    }
1923:                }
1924:
1925:                protected void paintBorder(Graphics g) {
1926:                    if (mouseIsOver && isEnabled()) {
1927:                        super .paintBorder(g);
1928:                    }
1929:                }
1930:
1931:                protected void paintComponent(Graphics g) {
1932:                    if (mouseIsOver) {
1933:                        super .paintComponent(g);
1934:                    } else {
1935:                        g.setColor(getBackground());
1936:                        g.fillRect(0, 0, getWidth(), getHeight());
1937:                    }
1938:                    paintArrow(g);
1939:                }
1940:
1941:                private void paintArrow(Graphics g) {
1942:                    Color oldColor = g.getColor();
1943:
1944:                    boolean isEnabled = isEnabled();
1945:                    g.setColor(isEnabled ? PlasticLookAndFeel.getControlInfo()
1946:                            : PlasticLookAndFeel.getControlDisabled());
1947:
1948:                    int arrowWidth, arrowHeight;
1949:                    switch (direction) {
1950:                    case NORTH:
1951:                    case SOUTH:
1952:                        arrowWidth = 9;
1953:                        arrowHeight = 5;
1954:                        break;
1955:                    case WEST:
1956:                    case EAST:
1957:                    default:
1958:                        arrowWidth = 5;
1959:                        arrowHeight = 9;
1960:                        break;
1961:                    }
1962:                    int x = (getWidth() - arrowWidth) / 2;
1963:                    int y = (getHeight() - arrowHeight) / 2;
1964:                    g.translate(x, y);
1965:
1966:                    boolean paintShadow = !mouseIsOver || !isEnabled;
1967:                    Color shadow = isEnabled ? PlasticLookAndFeel
1968:                            .getControlShadow() : UIManager
1969:                            .getColor("ScrollBar.highlight");
1970:
1971:                    switch (direction) {
1972:                    case NORTH:
1973:                        g.fillRect(0, 4, 9, 1);
1974:                        g.fillRect(1, 3, 7, 1);
1975:                        g.fillRect(2, 2, 5, 1);
1976:                        g.fillRect(3, 1, 3, 1);
1977:                        g.fillRect(4, 0, 1, 1);
1978:                        if (paintShadow) {
1979:                            g.setColor(shadow);
1980:                            g.fillRect(1, 5, 9, 1);
1981:                        }
1982:                        break;
1983:                    case SOUTH:
1984:                        g.fillRect(0, 0, 9, 1);
1985:                        g.fillRect(1, 1, 7, 1);
1986:                        g.fillRect(2, 2, 5, 1);
1987:                        g.fillRect(3, 3, 3, 1);
1988:                        g.fillRect(4, 4, 1, 1);
1989:                        if (paintShadow) {
1990:                            g.setColor(shadow);
1991:                            g.drawLine(5, 4, 8, 1);
1992:                            g.drawLine(5, 5, 9, 1);
1993:                        }
1994:                        break;
1995:                    case WEST:
1996:                        g.fillRect(0, 4, 1, 1);
1997:                        g.fillRect(1, 3, 1, 3);
1998:                        g.fillRect(2, 2, 1, 5);
1999:                        g.fillRect(3, 1, 1, 7);
2000:                        g.fillRect(4, 0, 1, 9);
2001:                        if (paintShadow) {
2002:                            g.setColor(shadow);
2003:                            g.fillRect(5, 1, 1, 9);
2004:                        }
2005:                        break;
2006:                    case EAST:
2007:                        g.fillRect(0, 0, 1, 9);
2008:                        g.fillRect(1, 1, 1, 7);
2009:                        g.fillRect(2, 2, 1, 5);
2010:                        g.fillRect(3, 3, 1, 3);
2011:                        g.fillRect(4, 4, 1, 1);
2012:                        if (paintShadow) {
2013:                            g.setColor(shadow);
2014:                            g.drawLine(1, 8, 4, 5);
2015:                            g.drawLine(1, 9, 5, 5);
2016:                        }
2017:                        break;
2018:                    }
2019:
2020:                    g.translate(-x, -y);
2021:                    g.setColor(oldColor);
2022:                }
2023:
2024:                public Dimension getPreferredSize() {
2025:                    return new Dimension(buttonWidth, buttonWidth);
2026:                }
2027:
2028:                public Dimension getMinimumSize() {
2029:                    return getPreferredSize();
2030:                }
2031:
2032:                public Dimension getMaximumSize() {
2033:                    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
2034:                }
2035:            }
2036:
2037:            /**
2038:             * This is the abstract superclass for all TabbedPane renderers.
2039:             * Those will be defined in the rest of this file
2040:             */
2041:            private abstract static class AbstractRenderer {
2042:
2043:                protected static final Insets EMPTY_INSETS = new Insets(0, 0,
2044:                        0, 0);
2045:                protected static final Insets NORTH_INSETS = new Insets(1, 0,
2046:                        0, 0);
2047:                protected static final Insets WEST_INSETS = new Insets(0, 1, 0,
2048:                        0);
2049:                protected static final Insets SOUTH_INSETS = new Insets(0, 0,
2050:                        1, 0);
2051:                protected static final Insets EAST_INSETS = new Insets(0, 0, 0,
2052:                        1);
2053:
2054:                protected final JTabbedPane tabPane;
2055:                protected final int tabPlacement;
2056:                protected Color shadowColor;
2057:                protected Color darkShadow;
2058:                protected Color selectColor;
2059:                protected Color selectLight;
2060:                protected Color selectHighlight;
2061:                protected Color lightHighlight;
2062:                protected Color focus;
2063:
2064:                private AbstractRenderer(JTabbedPane tabPane) {
2065:                    initColors();
2066:                    this .tabPane = tabPane;
2067:                    this .tabPlacement = tabPane.getTabPlacement();
2068:                }
2069:
2070:                private static AbstractRenderer createRenderer(
2071:                        JTabbedPane tabPane) {
2072:                    switch (tabPane.getTabPlacement()) {
2073:                    case SwingConstants.TOP:
2074:                        return new TopRenderer(tabPane);
2075:                    case SwingConstants.BOTTOM:
2076:                        return new BottomRenderer(tabPane);
2077:                    case SwingConstants.LEFT:
2078:                        return new LeftRenderer(tabPane);
2079:                    case SwingConstants.RIGHT:
2080:                        return new RightRenderer(tabPane);
2081:                    default:
2082:                        return new TopRenderer(tabPane);
2083:                    }
2084:                }
2085:
2086:                private static AbstractRenderer createEmbeddedRenderer(
2087:                        JTabbedPane tabPane) {
2088:                    switch (tabPane.getTabPlacement()) {
2089:                    case SwingConstants.TOP:
2090:                        return new TopEmbeddedRenderer(tabPane);
2091:                    case SwingConstants.BOTTOM:
2092:                        return new BottomEmbeddedRenderer(tabPane);
2093:                    case SwingConstants.LEFT:
2094:                        return new LeftEmbeddedRenderer(tabPane);
2095:                    case SwingConstants.RIGHT:
2096:                        return new RightEmbeddedRenderer(tabPane);
2097:                    default:
2098:                        return new TopEmbeddedRenderer(tabPane);
2099:                    }
2100:                }
2101:
2102:                private void initColors() {
2103:                    shadowColor = UIManager.getColor("TabbedPane.shadow");
2104:                    darkShadow = UIManager.getColor("TabbedPane.darkShadow");
2105:                    selectColor = UIManager.getColor("TabbedPane.selected");
2106:                    focus = UIManager.getColor("TabbedPane.focus");
2107:                    selectHighlight = UIManager
2108:                            .getColor("TabbedPane.selectHighlight");
2109:                    lightHighlight = UIManager.getColor("TabbedPane.highlight");
2110:                    selectLight = new Color(
2111:                            (2 * selectColor.getRed() + selectHighlight
2112:                                    .getRed()) / 3,
2113:                            (2 * selectColor.getGreen() + selectHighlight
2114:                                    .getGreen()) / 3, (2 * selectColor
2115:                                    .getBlue() + selectHighlight.getBlue()) / 3);
2116:                }
2117:
2118:                protected boolean isFirstDisplayedTab(int tabIndex,
2119:                        int position, int paneBorder) {
2120:                    return tabIndex == 0;
2121:                    //            return (position - paneBorder) < 8;
2122:                }
2123:
2124:                protected Insets getTabAreaInsets(Insets defaultInsets) {
2125:                    return defaultInsets;
2126:                }
2127:
2128:                protected Insets getContentBorderInsets(Insets defaultInsets) {
2129:                    return defaultInsets;
2130:                }
2131:
2132:                /**
2133:                 * Returns the amount by which the label should be shifted horizontally.
2134:                 */
2135:                protected int getTabLabelShiftX(int tabIndex, boolean isSelected) {
2136:                    return 0;
2137:                }
2138:
2139:                /**
2140:                 * Returns the amount by which the label should be shifted vertically.
2141:                 */
2142:                protected int getTabLabelShiftY(int tabIndex, boolean isSelected) {
2143:                    return 0;
2144:                }
2145:
2146:                /**
2147:                 * Returns the amount of overlap for two Runs.
2148:                 */
2149:                protected int getTabRunOverlay(int tabRunOverlay) {
2150:                    return tabRunOverlay;
2151:                }
2152:
2153:                /**
2154:                 * Returns if a run should be padded with empty space
2155:                 * to take up as much room as the others.
2156:                 */
2157:                protected boolean shouldPadTabRun(int run, boolean aPriori) {
2158:                    return aPriori;
2159:                }
2160:
2161:                /**
2162:                 * Returns the amount by which the run number <code>run</code>
2163:                 * should be indented. Add a few pixels for every run to make
2164:                 * diagonal lines align.
2165:                 */
2166:                protected int getTabRunIndent(int run) {
2167:                    return 0;
2168:                }
2169:
2170:                /**
2171:                 * Returns the insets for the given tab.
2172:                 */
2173:                protected abstract Insets getTabInsets(int tabIndex,
2174:                        Insets tabInsets);
2175:
2176:                /**
2177:                 * Draws the rectancle around the Tab label which indicates keyboard focus.
2178:                 */
2179:                protected abstract void paintFocusIndicator(Graphics g,
2180:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2181:                        Rectangle textRect, boolean isSelected);
2182:
2183:                /**
2184:                 * Fills the background of the given tab to make sure overlap of 
2185:                 * tabs is handled correctly.
2186:                 */
2187:                protected abstract void paintTabBackground(Graphics g,
2188:                        int tabIndex, int x, int y, int w, int h,
2189:                        boolean isSelected);
2190:
2191:                /**
2192:                 * Paints the border around the given tab.
2193:                 */
2194:                protected abstract void paintTabBorder(Graphics g,
2195:                        int tabIndex, int x, int y, int w, int h,
2196:                        boolean isSelected);
2197:
2198:                /**
2199:                 * Returns additional the insets for the selected tab. This allows to "raise"
2200:                 * The selected tab over the others
2201:                 */
2202:                protected Insets getSelectedTabPadInsets() {
2203:                    return EMPTY_INSETS;
2204:                }
2205:
2206:                /**
2207:                 * Draws the top edge of the border around the content area.
2208:                 * Draw unbroken line for tabs are not on TOP
2209:                 * override where appropriate.
2210:                 */
2211:                protected void paintContentBorderTopEdge(Graphics g, int x,
2212:                        int y, int w, int h, boolean drawBroken,
2213:                        Rectangle selRect, boolean isContentBorderPainted) {
2214:                    if (isContentBorderPainted) {
2215:                        g.setColor(selectHighlight);
2216:                        g.fillRect(x, y, w - 1, 1);
2217:                    }
2218:                }
2219:
2220:                /**
2221:                 * Draws the bottom edge of the Border around the content area.
2222:                 * Draw broken line if selected tab is visible and adjacent to content
2223:                 * and TabPlacement is same as painted edge.
2224:                 */
2225:                protected void paintContentBorderBottomEdge(Graphics g, int x,
2226:                        int y, int w, int h, boolean drawBroken,
2227:                        Rectangle selRect, boolean isContentBorderPainted) {
2228:                    if (isContentBorderPainted) {
2229:                        g.setColor(darkShadow);
2230:                        g.fillRect(x, y + h - 1, w - 1, 1);
2231:                    }
2232:                }
2233:
2234:                /**
2235:                 * Draws the left edge of the Border around the content area.
2236:                 * Draw broken line if selected tab is visible and adjacent to content
2237:                 * and TabPlacement is same as painted edge
2238:                 */
2239:                protected void paintContentBorderLeftEdge(Graphics g, int x,
2240:                        int y, int w, int h, boolean drawBroken,
2241:                        Rectangle selRect, boolean isContentBorderPainted) {
2242:                    if (isContentBorderPainted) {
2243:                        g.setColor(selectHighlight);
2244:                        g.fillRect(x, y, 1, h - 1);
2245:                    }
2246:                }
2247:
2248:                /**
2249:                 * Draws the right edge of the Border around the content area.
2250:                 * Draw broken line if selected tab is visible and adjacent to content
2251:                 * and TabPlacement is same as painted edge
2252:                 */
2253:                protected void paintContentBorderRightEdge(Graphics g, int x,
2254:                        int y, int w, int h, boolean drawBroken,
2255:                        Rectangle selRect, boolean isContentBorderPainted) {
2256:                    if (isContentBorderPainted) {
2257:                        g.setColor(darkShadow);
2258:                        g.fillRect(x + w - 1, y, 1, h);
2259:                    }
2260:                }
2261:
2262:                /**
2263:                 * Returns the amount of overlap for two tabs.
2264:                 */
2265:                protected int getTabsOverlay() {
2266:                    return 0;
2267:                }
2268:            }
2269:
2270:            /** 
2271:             * The renderer for the case where tabs are displayed below the contents
2272:             * and with minimal decoration.
2273:             */
2274:            private static final class BottomEmbeddedRenderer extends
2275:                    AbstractRenderer {
2276:
2277:                private BottomEmbeddedRenderer(JTabbedPane tabPane) {
2278:                    super (tabPane);
2279:                }
2280:
2281:                protected Insets getTabAreaInsets(Insets insets) {
2282:                    return EMPTY_INSETS;
2283:                }
2284:
2285:                protected Insets getContentBorderInsets(Insets defaultInsets) {
2286:                    return SOUTH_INSETS;
2287:                }
2288:
2289:                protected Insets getSelectedTabPadInsets() {
2290:                    return EMPTY_INSETS;
2291:                }
2292:
2293:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2294:                    return new Insets(tabInsets.top, tabInsets.left,
2295:                            tabInsets.bottom, tabInsets.right);
2296:                }
2297:
2298:                /**
2299:                 * Paints no focus: minimal decoration is really minimal.
2300:                 */
2301:                protected void paintFocusIndicator(Graphics g,
2302:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2303:                        Rectangle textRect, boolean isSelected) {
2304:                    // Embedded tabs paint no focus.
2305:                }
2306:
2307:                protected void paintTabBackground(Graphics g, int tabIndex,
2308:                        int x, int y, int w, int h, boolean isSelected) {
2309:
2310:                    g.setColor(selectColor);
2311:                    g.fillRect(x, y, w + 1, h);
2312:                }
2313:
2314:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2315:                        int y, int w, int h, boolean isSelected) {
2316:
2317:                    int bottom = h;
2318:                    int right = w + 1;
2319:
2320:                    g.translate(x, y);
2321:                    if (isFirstDisplayedTab(tabIndex, x, tabPane.getBounds().x)) {
2322:                        if (isSelected) {
2323:                            // selected and first in line
2324:                            g.setColor(shadowColor);
2325:                            g.fillRect(right, 0, 1, bottom - 1);
2326:                            g.fillRect(right - 1, bottom - 1, 1, 1);
2327:                            // it is open to discussion if the outer border of the tab
2328:                            // should be painted because in the primary case it won't
2329:                            // be visible anyway. uncomment the following two lines if wanted
2330:                            //                    g.fillRect(0,bottom, right, 1);
2331:                            //                    g.fillRect(-1,0,1,bottom;
2332:                            g.setColor(selectHighlight);
2333:                            g.fillRect(0, 0, 1, bottom);
2334:                            g.fillRect(right - 1, 0, 1, bottom - 1);
2335:                            g.fillRect(1, bottom - 1, right - 2, 1);
2336:                        } else {
2337:                            //not selected and first in line
2338:                        }
2339:                    } else {
2340:                        if (isSelected) {
2341:                            //selected and not first in line
2342:                            g.setColor(shadowColor);
2343:                            g.fillRect(0, 0, 1, bottom - 1);
2344:                            g.fillRect(1, bottom - 1, 1, 1);
2345:                            g.fillRect(right, 0, 1, bottom - 1);
2346:                            g.fillRect(right - 1, bottom - 1, 1, 1);
2347:                            // outside line:
2348:                            //                    g.fillRect(2,bottom, right-3, 1);
2349:                            g.setColor(selectHighlight);
2350:                            g.fillRect(1, 0, 1, bottom - 1);
2351:                            g.fillRect(right - 1, 0, 1, bottom - 1);
2352:                            g.fillRect(2, bottom - 1, right - 3, 1);
2353:                        } else {
2354:                            g.setColor(shadowColor);
2355:                            g.fillRect(1, h / 2, 1, h - (h / 2));
2356:                        }
2357:                    }
2358:                    g.translate(-x, -y);
2359:                }
2360:
2361:                protected void paintContentBorderBottomEdge(Graphics g, int x,
2362:                        int y, int w, int h, boolean drawBroken,
2363:                        Rectangle selRect, boolean isContentBorderPainted) {
2364:
2365:                    g.setColor(shadowColor);
2366:                    g.fillRect(x, y + h - 1, w, 1);
2367:                }
2368:
2369:            }
2370:
2371:            /**
2372:             * The renderer for the case where Tabs are below the content and
2373:             * decoration is standard.
2374:             */
2375:            private static final class BottomRenderer extends AbstractRenderer {
2376:
2377:                private BottomRenderer(JTabbedPane tabPane) {
2378:                    super (tabPane);
2379:                }
2380:
2381:                protected Insets getTabAreaInsets(Insets defaultInsets) {
2382:                    return new Insets(defaultInsets.top,
2383:                            defaultInsets.left + 5, defaultInsets.bottom,
2384:                            defaultInsets.right);
2385:                }
2386:
2387:                protected int getTabLabelShiftY(int tabIndex, boolean isSelected) {
2388:                    return isSelected ? 0 : -1;
2389:                }
2390:
2391:                protected int getTabRunOverlay(int tabRunOverlay) {
2392:                    return tabRunOverlay - 2;
2393:                }
2394:
2395:                protected int getTabRunIndent(int run) {
2396:                    return 6 * run;
2397:                }
2398:
2399:                protected Insets getSelectedTabPadInsets() {
2400:                    return SOUTH_INSETS;
2401:                }
2402:
2403:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2404:                    return new Insets(tabInsets.top, tabInsets.left - 2,
2405:                            tabInsets.bottom, tabInsets.right - 2);
2406:                }
2407:
2408:                protected void paintFocusIndicator(Graphics g,
2409:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2410:                        Rectangle textRect, boolean isSelected) {
2411:
2412:                    if (!tabPane.hasFocus() || !isSelected)
2413:                        return;
2414:                    Rectangle tabRect = rects[tabIndex];
2415:                    int top = tabRect.y;
2416:                    int left = tabRect.x + 6;
2417:                    int height = tabRect.height - 3;
2418:                    int width = tabRect.width - 12;
2419:                    g.setColor(focus);
2420:                    g.drawRect(left, top, width, height);
2421:                }
2422:
2423:                protected void paintTabBackground(Graphics g, int tabIndex,
2424:                        int x, int y, int w, int h, boolean isSelected) {
2425:
2426:                    g.setColor(selectColor);
2427:                    g.fillRect(x, y, w, h);
2428:                }
2429:
2430:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2431:                        int y, int w, int h, boolean isSelected) {
2432:
2433:                    int bottom = h - 1;
2434:                    int right = w + 4;
2435:
2436:                    g.translate(x - 3, y);
2437:
2438:                    // Paint Border
2439:                    g.setColor(selectHighlight);
2440:
2441:                    // Paint left
2442:                    g.fillRect(0, 0, 1, 2);
2443:                    g.drawLine(0, 2, 4, bottom - 4);
2444:                    g.fillRect(5, bottom - 3, 1, 2);
2445:                    g.fillRect(6, bottom - 1, 1, 1);
2446:
2447:                    // Paint bootom
2448:                    g.fillRect(7, bottom, 1, 1);
2449:                    g.setColor(darkShadow);
2450:                    g.fillRect(8, bottom, right - 13, 1);
2451:
2452:                    // Paint right
2453:                    g.drawLine(right + 1, 0, right - 3, bottom - 4);
2454:                    g.fillRect(right - 4, bottom - 3, 1, 2);
2455:                    g.fillRect(right - 5, bottom - 1, 1, 1);
2456:
2457:                    g.translate(-x + 3, -y);
2458:                }
2459:
2460:                protected void paintContentBorderBottomEdge(Graphics g, int x,
2461:                        int y, int w, int h, boolean drawBroken,
2462:                        Rectangle selRect, boolean isContentBorderPainted) {
2463:                    int bottom = y + h - 1;
2464:                    int right = x + w - 1;
2465:                    g.translate(x, bottom);
2466:                    if (drawBroken && selRect.x >= x && selRect.x <= x + w) {
2467:                        // Break line to show visual connection to selected tab
2468:                        g.setColor(darkShadow);
2469:                        g.fillRect(0, 0, selRect.x - x - 2, 1);
2470:                        if (selRect.x + selRect.width < x + w - 2) {
2471:                            g.setColor(darkShadow);
2472:                            g.fillRect(selRect.x + selRect.width + 2 - x, 0,
2473:                                    right - selRect.x - selRect.width - 2, 1);
2474:                        }
2475:                    } else {
2476:                        g.setColor(darkShadow);
2477:                        g.fillRect(0, 0, w - 1, 1);
2478:                    }
2479:                    g.translate(-x, -bottom);
2480:                }
2481:
2482:                protected int getTabsOverlay() {
2483:                    return 4;
2484:                }
2485:
2486:            }
2487:
2488:            /**
2489:             * The renderer for tabs on the left with minimal decoration.
2490:             */
2491:            private static final class LeftEmbeddedRenderer extends
2492:                    AbstractRenderer {
2493:
2494:                private LeftEmbeddedRenderer(JTabbedPane tabPane) {
2495:                    super (tabPane);
2496:                }
2497:
2498:                protected Insets getTabAreaInsets(Insets insets) {
2499:                    return EMPTY_INSETS;
2500:                }
2501:
2502:                protected Insets getContentBorderInsets(Insets defaultInsets) {
2503:                    return WEST_INSETS;
2504:                }
2505:
2506:                protected int getTabRunOverlay(int tabRunOverlay) {
2507:                    return 0;
2508:                }
2509:
2510:                protected boolean shouldPadTabRun(int run, boolean aPriori) {
2511:                    return false;
2512:                }
2513:
2514:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2515:                    return new Insets(tabInsets.top, tabInsets.left,
2516:                            tabInsets.bottom, tabInsets.right);
2517:                }
2518:
2519:                protected Insets getSelectedTabPadInsets() {
2520:                    return EMPTY_INSETS;
2521:                }
2522:
2523:                /**
2524:                 * minimal decoration is really minimal: no focus.
2525:                 */
2526:                protected void paintFocusIndicator(Graphics g,
2527:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2528:                        Rectangle textRect, boolean isSelected) {
2529:                    // Embedded tabs paint no focus.
2530:                }
2531:
2532:                protected void paintTabBackground(Graphics g, int tabIndex,
2533:                        int x, int y, int w, int h, boolean isSelected) {
2534:                    g.setColor(selectColor);
2535:                    g.fillRect(x, y, w, h);
2536:                }
2537:
2538:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2539:                        int y, int w, int h, boolean isSelected) {
2540:
2541:                    int bottom = h;
2542:                    int right = w;
2543:
2544:                    g.translate(x, y);
2545:
2546:                    if (isFirstDisplayedTab(tabIndex, y, tabPane.getBounds().y)) {
2547:                        if (isSelected) {
2548:                            //selected and first in line
2549:                            g.setColor(selectHighlight);
2550:                            g.fillRect(0, 0, right, 1);
2551:                            g.fillRect(0, 0, 1, bottom - 1);
2552:                            g.fillRect(1, bottom - 1, right - 1, 1);
2553:                            g.setColor(shadowColor);
2554:                            g.fillRect(0, bottom - 1, 1, 1);
2555:                            g.fillRect(1, bottom, right - 1, 1);
2556:                            // outside line:
2557:                            //                    g.fillRect(-1,0,1,bottom-1)
2558:                        } else {
2559:                            //not selected but first in line
2560:                        }
2561:                    } else {
2562:                        if (isSelected) {
2563:                            //selected but not first in line
2564:                            g.setColor(selectHighlight);
2565:                            g.fillRect(1, 1, right - 1, 1);
2566:                            g.fillRect(0, 2, 1, bottom - 2);
2567:                            g.fillRect(1, bottom - 1, right - 1, 1);
2568:                            g.setColor(shadowColor);
2569:                            g.fillRect(1, 0, right - 1, 1);
2570:                            g.fillRect(0, 1, 1, 1);
2571:                            g.fillRect(0, bottom - 1, 1, 1);
2572:                            g.fillRect(1, bottom, right - 1, 1);
2573:                            // outside line:
2574:                            //                    g.fillRect(-1,2,1,bottom-3)
2575:                        } else {
2576:                            g.setColor(shadowColor);
2577:                            g.fillRect(0, 0, right / 3, 1);
2578:                        }
2579:                    }
2580:
2581:                    g.translate(-x, -y);
2582:                }
2583:
2584:                protected void paintContentBorderLeftEdge(Graphics g, int x,
2585:                        int y, int w, int h, boolean drawBroken,
2586:                        Rectangle selRect, boolean isContentBorderPainted) {
2587:                    g.setColor(shadowColor);
2588:                    g.fillRect(x, y, 1, h);
2589:                }
2590:            }
2591:
2592:            /**
2593:             * Renderer for tabs on the left with normal decoration.
2594:             */
2595:            private static final class LeftRenderer extends AbstractRenderer {
2596:
2597:                private LeftRenderer(JTabbedPane tabPane) {
2598:                    super (tabPane);
2599:                }
2600:
2601:                protected Insets getTabAreaInsets(Insets defaultInsets) {
2602:                    return new Insets(defaultInsets.top + 4,
2603:                            defaultInsets.left, defaultInsets.bottom,
2604:                            defaultInsets.right);
2605:                }
2606:
2607:                protected int getTabLabelShiftX(int tabIndex, boolean isSelected) {
2608:                    return 1;
2609:                }
2610:
2611:                protected int getTabRunOverlay(int tabRunOverlay) {
2612:                    return 1;
2613:                }
2614:
2615:                protected boolean shouldPadTabRun(int run, boolean aPriori) {
2616:                    return false;
2617:                }
2618:
2619:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2620:                    return new Insets(tabInsets.top, tabInsets.left - 5,
2621:                            tabInsets.bottom + 1, tabInsets.right - 5);
2622:                }
2623:
2624:                protected Insets getSelectedTabPadInsets() {
2625:                    return WEST_INSETS;
2626:                }
2627:
2628:                protected void paintFocusIndicator(Graphics g,
2629:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2630:                        Rectangle textRect, boolean isSelected) {
2631:
2632:                    if (!tabPane.hasFocus() || !isSelected)
2633:                        return;
2634:                    Rectangle tabRect = rects[tabIndex];
2635:                    int top = tabRect.y + 2;
2636:                    int left = tabRect.x + 3;
2637:                    int height = tabRect.height - 5;
2638:                    int width = tabRect.width - 6;
2639:                    g.setColor(focus);
2640:                    g.drawRect(left, top, width, height);
2641:                }
2642:
2643:                protected void paintTabBackground(Graphics g, int tabIndex,
2644:                        int x, int y, int w, int h, boolean isSelected) {
2645:                    if (!isSelected) {
2646:                        g.setColor(selectLight);
2647:                        g.fillRect(x + 1, y + 1, w - 1, h - 2);
2648:                    } else {
2649:                        g.setColor(selectColor);
2650:                        g.fillRect(x + 1, y + 1, w - 3, h - 2);
2651:                    }
2652:                }
2653:
2654:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2655:                        int y, int w, int h, boolean isSelected) {
2656:
2657:                    int bottom = h - 1;
2658:                    int left = 0;
2659:                    g.translate(x, y);
2660:
2661:                    // Paint Border
2662:                    g.setColor(selectHighlight);
2663:                    // Paint top
2664:                    g.fillRect(left + 2, 0, w - 2 - left, 1);
2665:
2666:                    // Paint left
2667:                    g.fillRect(left + 1, 1, 1, 1);
2668:                    g.fillRect(left, 2, 1, bottom - 3);
2669:                    g.setColor(darkShadow);
2670:                    g.fillRect(left + 1, bottom - 1, 1, 1);
2671:
2672:                    // Paint bottom
2673:                    g.fillRect(left + 2, bottom, w - 2 - left, 1);
2674:
2675:                    g.translate(-x, -y);
2676:                }
2677:
2678:                protected void paintContentBorderLeftEdge(Graphics g, int x,
2679:                        int y, int w, int h, boolean drawBroken,
2680:                        Rectangle selRect, boolean isContentBorderPainted) {
2681:                    g.setColor(selectHighlight);
2682:                    if (drawBroken && selRect.y >= y && selRect.y <= y + h) {
2683:                        // Break line to show visual connection to selected tab
2684:                        g.fillRect(x, y, 1, selRect.y + 1 - y);
2685:                        if (selRect.y + selRect.height < y + h - 2) {
2686:                            g.fillRect(x, selRect.y + selRect.height - 1, 1, y
2687:                                    + h - selRect.y - selRect.height);
2688:                        }
2689:                    } else {
2690:                        g.fillRect(x, y, 1, h - 1);
2691:                    }
2692:                }
2693:
2694:            }
2695:
2696:            /**
2697:             * The renderer for tabs on the right with minimal decoration.
2698:             */
2699:            private static final class RightEmbeddedRenderer extends
2700:                    AbstractRenderer {
2701:
2702:                private RightEmbeddedRenderer(JTabbedPane tabPane) {
2703:                    super (tabPane);
2704:                }
2705:
2706:                protected Insets getTabAreaInsets(Insets insets) {
2707:                    return EMPTY_INSETS;
2708:                }
2709:
2710:                protected Insets getContentBorderInsets(Insets defaultInsets) {
2711:                    return EAST_INSETS;
2712:                }
2713:
2714:                protected int getTabRunIndent(int run) {
2715:                    return 4 * run;
2716:                }
2717:
2718:                protected int getTabRunOverlay(int tabRunOverlay) {
2719:                    return 0;
2720:                }
2721:
2722:                protected boolean shouldPadTabRun(int run, boolean aPriori) {
2723:                    return false;
2724:                }
2725:
2726:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2727:                    return new Insets(tabInsets.top, tabInsets.left,
2728:                            tabInsets.bottom, tabInsets.right);
2729:                }
2730:
2731:                protected Insets getSelectedTabPadInsets() {
2732:                    return EMPTY_INSETS;
2733:                }
2734:
2735:                /**
2736:                 * Minimal decoration: no focus.
2737:                 */
2738:                protected void paintFocusIndicator(Graphics g,
2739:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2740:                        Rectangle textRect, boolean isSelected) {
2741:                    // Embedded tabs paint no focus.
2742:                }
2743:
2744:                protected void paintTabBackground(Graphics g, int tabIndex,
2745:                        int x, int y, int w, int h, boolean isSelected) {
2746:
2747:                    g.setColor(selectColor);
2748:                    g.fillRect(x, y, w, h);
2749:                }
2750:
2751:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2752:                        int y, int w, int h, boolean isSelected) {
2753:
2754:                    int bottom = h;
2755:                    int right = w - 1;
2756:
2757:                    g.translate(x + 1, y);
2758:
2759:                    if (isFirstDisplayedTab(tabIndex, y, tabPane.getBounds().y)) {
2760:                        if (isSelected) {
2761:                            //selected and first in line
2762:                            g.setColor(shadowColor);
2763:                            //outside lines:
2764:                            //                    g.fillRect(0,-1,right,1);
2765:                            //                    g.fillRect(right,-1,1,bottom);
2766:                            g.fillRect(right - 1, bottom - 1, 1, 1);
2767:                            g.fillRect(0, bottom, right - 1, 1);
2768:                            g.setColor(selectHighlight);
2769:                            g.fillRect(0, 0, right - 1, 1);
2770:                            g.fillRect(right - 1, 0, 1, bottom - 1);
2771:                            g.fillRect(0, bottom - 1, right - 1, 1);
2772:                        }
2773:                    } else {
2774:                        if (isSelected) {
2775:                            //selected but not first in line
2776:                            g.setColor(shadowColor);
2777:                            g.fillRect(0, -1, right - 1, 1);
2778:                            g.fillRect(right - 1, 0, 1, 1);
2779:                            //outside line:
2780:                            //                    g.fillRect(right,0,1,bottom);
2781:                            g.fillRect(right - 1, bottom - 1, 1, 1);
2782:                            g.fillRect(0, bottom, right - 1, 1);
2783:                            g.setColor(selectHighlight);
2784:                            g.fillRect(0, 0, right - 1, 1);
2785:                            g.fillRect(right - 1, 1, 1, bottom - 2);
2786:                            g.fillRect(0, bottom - 1, right - 1, 1);
2787:                        } else {
2788:                            //not selected and not first in line
2789:                            g.setColor(shadowColor);
2790:                            g.fillRect(2 * right / 3, 0, right / 3, 1);
2791:                        }
2792:                    }
2793:                    g.translate(-x - 1, -y);
2794:                }
2795:
2796:                protected void paintContentBorderRightEdge(Graphics g, int x,
2797:                        int y, int w, int h, boolean drawBroken,
2798:                        Rectangle selRect, boolean isContentBorderPainted) {
2799:                    g.setColor(shadowColor);
2800:                    g.fillRect(x + w - 1, y, 1, h);
2801:                }
2802:
2803:            }
2804:
2805:            /**
2806:             * Renderer for tabs on the right with normal decoration.
2807:             */
2808:            private static final class RightRenderer extends AbstractRenderer {
2809:
2810:                private RightRenderer(JTabbedPane tabPane) {
2811:                    super (tabPane);
2812:                }
2813:
2814:                protected int getTabLabelShiftX(int tabIndex, boolean isSelected) {
2815:                    return 1;
2816:                }
2817:
2818:                protected int getTabRunOverlay(int tabRunOverlay) {
2819:                    return 1;
2820:                }
2821:
2822:                protected boolean shouldPadTabRun(int run, boolean aPriori) {
2823:                    return false;
2824:                }
2825:
2826:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2827:                    return new Insets(tabInsets.top, tabInsets.left - 5,
2828:                            tabInsets.bottom + 1, tabInsets.right - 5);
2829:                }
2830:
2831:                protected Insets getSelectedTabPadInsets() {
2832:                    return EAST_INSETS;
2833:                }
2834:
2835:                protected void paintFocusIndicator(Graphics g,
2836:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2837:                        Rectangle textRect, boolean isSelected) {
2838:
2839:                    if (!tabPane.hasFocus() || !isSelected)
2840:                        return;
2841:                    Rectangle tabRect = rects[tabIndex];
2842:                    int top = tabRect.y + 2;
2843:                    int left = tabRect.x + 3;
2844:                    int height = tabRect.height - 5;
2845:                    int width = tabRect.width - 6;
2846:                    g.setColor(focus);
2847:                    g.drawRect(left, top, width, height);
2848:                }
2849:
2850:                protected void paintTabBackground(Graphics g, int tabIndex,
2851:                        int x, int y, int w, int h, boolean isSelected) {
2852:                    if (!isSelected) {
2853:                        g.setColor(selectLight);
2854:                        g.fillRect(x, y, w, h);
2855:                    } else {
2856:                        g.setColor(selectColor);
2857:                        g.fillRect(x + 2, y, w - 2, h);
2858:                    }
2859:                }
2860:
2861:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2862:                        int y, int w, int h, boolean isSelected) {
2863:
2864:                    int bottom = h - 1;
2865:                    int right = w;
2866:
2867:                    g.translate(x, y);
2868:
2869:                    // Paint Border
2870:
2871:                    g.setColor(selectHighlight);
2872:                    g.fillRect(0, 0, right - 1, 1);
2873:                    // Paint right
2874:                    g.setColor(darkShadow);
2875:                    g.fillRect(right - 1, 1, 1, 1);
2876:                    g.fillRect(right, 2, 1, bottom - 3);
2877:                    // Paint bottom
2878:                    g.fillRect(right - 1, bottom - 1, 1, 1);
2879:                    g.fillRect(0, bottom, right - 1, 1);
2880:
2881:                    g.translate(-x, -y);
2882:                }
2883:
2884:                protected void paintContentBorderRightEdge(Graphics g, int x,
2885:                        int y, int w, int h, boolean drawBroken,
2886:                        Rectangle selRect, boolean isContentBorderPainted) {
2887:                    g.setColor(darkShadow);
2888:                    if (drawBroken && selRect.y >= y && selRect.y <= y + h) {
2889:                        // Break line to show visual connection to selected tab
2890:                        g.fillRect(x + w - 1, y, 1, selRect.y - y);
2891:                        if (selRect.y + selRect.height < y + h - 2) {
2892:                            g.fillRect(x + w - 1, selRect.y + selRect.height,
2893:                                    1, y + h - selRect.y - selRect.height);
2894:                        }
2895:                    } else {
2896:                        g.fillRect(x + w - 1, y, 1, h - 1);
2897:                    }
2898:                }
2899:            }
2900:
2901:            /**
2902:             * Renderer for tabs on top with minimal decoration.
2903:             */
2904:            private static final class TopEmbeddedRenderer extends
2905:                    AbstractRenderer {
2906:
2907:                private TopEmbeddedRenderer(JTabbedPane tabPane) {
2908:                    super (tabPane);
2909:                }
2910:
2911:                protected Insets getTabAreaInsets(Insets insets) {
2912:                    return EMPTY_INSETS;
2913:                }
2914:
2915:                protected Insets getContentBorderInsets(Insets defaultInsets) {
2916:                    return NORTH_INSETS;
2917:                }
2918:
2919:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
2920:                    return new Insets(tabInsets.top, tabInsets.left + 1,
2921:                            tabInsets.bottom, tabInsets.right);
2922:                }
2923:
2924:                protected Insets getSelectedTabPadInsets() {
2925:                    return EMPTY_INSETS;
2926:                }
2927:
2928:                /**
2929:                 * Minimal decoration: no focus.
2930:                 */
2931:                protected void paintFocusIndicator(Graphics g,
2932:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
2933:                        Rectangle textRect, boolean isSelected) {
2934:                    // Embedded tabs paint no focus.
2935:                }
2936:
2937:                protected void paintTabBackground(Graphics g, int tabIndex,
2938:                        int x, int y, int w, int h, boolean isSelected) {
2939:
2940:                    g.setColor(selectColor);
2941:                    g.fillRect(x, y, w, h);
2942:                }
2943:
2944:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
2945:                        int y, int w, int h, boolean isSelected) {
2946:
2947:                    g.translate(x, y);
2948:
2949:                    int right = w;
2950:                    int bottom = h;
2951:
2952:                    if (isFirstDisplayedTab(tabIndex, x, tabPane.getBounds().x)) {
2953:                        if (isSelected) {
2954:                            g.setColor(selectHighlight);
2955:                            //left
2956:                            g.fillRect(0, 0, 1, bottom);
2957:                            //top
2958:                            g.fillRect(0, 0, right - 1, 1);
2959:                            //right
2960:                            g.fillRect(right - 1, 0, 1, bottom);
2961:                            g.setColor(shadowColor);
2962:                            //topright corner
2963:                            g.fillRect(right - 1, 0, 1, 1);
2964:                            //right
2965:                            g.fillRect(right, 1, 1, bottom);
2966:                        }
2967:                    } else {
2968:                        if (isSelected) {
2969:                            g.setColor(selectHighlight);
2970:                            //left
2971:                            g.fillRect(1, 1, 1, bottom - 1);
2972:                            //top
2973:                            g.fillRect(2, 0, right - 3, 1);
2974:                            //right
2975:                            g.fillRect(right - 1, 1, 1, bottom - 1);
2976:                            g.setColor(shadowColor);
2977:                            //left
2978:                            g.fillRect(0, 1, 1, bottom - 1);
2979:                            //topleft corner
2980:                            g.fillRect(1, 0, 1, 1);
2981:                            //topright corner
2982:                            g.fillRect(right - 1, 0, 1, 1);
2983:                            //right
2984:                            g.fillRect(right, 1, 1, bottom);
2985:                        } else {
2986:                            g.setColor(shadowColor);
2987:                            g.fillRect(0, 0, 1, bottom + 2 - bottom / 2);
2988:                        }
2989:                    }
2990:                    g.translate(-x, -y);
2991:                }
2992:
2993:                protected void paintContentBorderTopEdge(Graphics g, int x,
2994:                        int y, int w, int h, boolean drawBroken,
2995:                        Rectangle selRect, boolean isContentBorderPainted) {
2996:                    g.setColor(shadowColor);
2997:                    g.fillRect(x, y, w, 1);
2998:                }
2999:
3000:            }
3001:
3002:            /**
3003:             * Renderer for tabs on top with normal decoration.
3004:             */
3005:            private static final class TopRenderer extends AbstractRenderer {
3006:
3007:                private TopRenderer(JTabbedPane tabPane) {
3008:                    super (tabPane);
3009:                }
3010:
3011:                protected Insets getTabAreaInsets(Insets defaultInsets) {
3012:                    return new Insets(defaultInsets.top,
3013:                            defaultInsets.left + 4, defaultInsets.bottom,
3014:                            defaultInsets.right);
3015:                }
3016:
3017:                protected int getTabLabelShiftY(int tabIndex, boolean isSelected) {
3018:                    return isSelected ? -1 : 0;
3019:                }
3020:
3021:                protected int getTabRunOverlay(int tabRunOverlay) {
3022:                    return tabRunOverlay - 2;
3023:                }
3024:
3025:                protected int getTabRunIndent(int run) {
3026:                    return 6 * run;
3027:                }
3028:
3029:                protected Insets getSelectedTabPadInsets() {
3030:                    return NORTH_INSETS;
3031:                }
3032:
3033:                protected Insets getTabInsets(int tabIndex, Insets tabInsets) {
3034:                    return new Insets(tabInsets.top - 1, tabInsets.left - 4,
3035:                            tabInsets.bottom, tabInsets.right - 4);
3036:                }
3037:
3038:                protected void paintFocusIndicator(Graphics g,
3039:                        Rectangle[] rects, int tabIndex, Rectangle iconRect,
3040:                        Rectangle textRect, boolean isSelected) {
3041:
3042:                    if (!tabPane.hasFocus() || !isSelected)
3043:                        return;
3044:                    Rectangle tabRect = rects[tabIndex];
3045:                    int top = tabRect.y + 1;
3046:                    int left = tabRect.x + 4;
3047:                    int height = tabRect.height - 3;
3048:                    int width = tabRect.width - 9;
3049:                    g.setColor(focus);
3050:                    g.drawRect(left, top, width, height);
3051:                }
3052:
3053:                protected void paintTabBackground(Graphics g, int tabIndex,
3054:                        int x, int y, int w, int h, boolean isSelected) {
3055:
3056:                    int sel = (isSelected) ? 0 : 1;
3057:                    g.setColor(selectColor);
3058:                    g.fillRect(x, y + sel, w, h / 2);
3059:                    g.fillRect(x - 1, y + sel + h / 2, w + 2, h - h / 2);
3060:                }
3061:
3062:                protected void paintTabBorder(Graphics g, int tabIndex, int x,
3063:                        int y, int w, int h, boolean isSelected) {
3064:
3065:                    g.translate(x - 4, y);
3066:
3067:                    int top = 0;
3068:                    int right = w + 6;
3069:
3070:                    // Paint Border
3071:                    g.setColor(selectHighlight);
3072:
3073:                    // Paint left
3074:                    g.drawLine(1, h - 1, 4, top + 4);
3075:                    g.fillRect(5, top + 2, 1, 2);
3076:                    g.fillRect(6, top + 1, 1, 1);
3077:
3078:                    // Paint top
3079:                    g.fillRect(7, top, right - 12, 1);
3080:
3081:                    // Paint right
3082:                    g.setColor(darkShadow);
3083:                    g.drawLine(right, h - 1, right - 3, top + 4);
3084:                    g.fillRect(right - 4, top + 2, 1, 2);
3085:                    g.fillRect(right - 5, top + 1, 1, 1);
3086:
3087:                    g.translate(-x + 4, -y);
3088:                }
3089:
3090:                protected void paintContentBorderTopEdge(Graphics g, int x,
3091:                        int y, int w, int h, boolean drawBroken,
3092:                        Rectangle selRect, boolean isContentBorderPainted) {
3093:                    int right = x + w - 1;
3094:                    int top = y;
3095:                    g.setColor(selectHighlight);
3096:
3097:                    if (drawBroken && selRect.x >= x && selRect.x <= x + w) {
3098:                        // Break line to show visual connection to selected tab
3099:                        g.fillRect(x, top, selRect.x - 2 - x, 1);
3100:                        if (selRect.x + selRect.width < x + w - 2) {
3101:                            g.fillRect(selRect.x + selRect.width + 2, top,
3102:                                    right - 2 - selRect.x - selRect.width, 1);
3103:                        } else {
3104:                            g.fillRect(x + w - 2, top, 1, 1);
3105:                        }
3106:                    } else {
3107:                        g.fillRect(x, top, w - 1, 1);
3108:                    }
3109:                }
3110:
3111:                protected int getTabsOverlay() {
3112:                    return 6;
3113:                }
3114:            }
3115:
3116:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.