- /*
- * @(#)SynthTabbedPaneUI.java 1.25 03/05/08
- *
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package com.sun.java.swing.plaf.gtk;
- import javax.swing.*;
- import javax.swing.event.*;
- import javax.swing.plaf.*;
- import javax.swing.text.View;
- import java.awt.*;
- import java.awt.event.*;
- import java.beans.PropertyChangeListener;
- import java.beans.PropertyChangeEvent;
- import java.util.Vector;
- import java.util.Hashtable;
- // PENDING: nuke this
- import javax.swing.plaf.basic.BasicHTML;
- /**
- * A Basic L&F implementation of TabbedPaneUI.
- *
- * @version 1.25, 05/08/03 (based on BasicTabbedPaneUI v 1.123)
- * @author Amy Fowler
- * @author Philip Milne
- * @author Steve Wilson
- * @author Tom Santos
- * @author Dave Moore
- */
- /**
- * Looks up 'selectedTabPadInsets' from the Style, which will be additional
- * insets for the selected tab.
- */
- class SynthTabbedPaneUI extends TabbedPaneUI implements SynthUI, SwingConstants {
- private static Action scrollTabsForwardAction =
- new ScrollTabsForwardAction();
- private static Action scrollTabsBackwardAction =
- new ScrollTabsBackwardAction();
- // Instance variables initialized at installation
- // PENDING: These should be fetched as necessary, eg not maintained as
- // fields but passed around.
- private SynthContext tabAreaContext;
- private TabContext tabContext;
- private SynthContext tabContentContext;
- private SynthStyle style;
- private SynthStyle tabStyle;
- private SynthStyle tabAreaStyle;
- private SynthStyle tabContentStyle;
- private int tabRunOverlay;
- protected JTabbedPane tabPane;
- // Transient variables (recalculated each time TabbedPane is layed out)
- protected int tabRuns[] = new int[10];
- protected int runCount = 0;
- protected int selectedRun = -1;
- protected Rectangle rects[] = new Rectangle[0];
- protected int maxTabHeight;
- protected int maxTabWidth;
- // Listeners
- protected ChangeListener tabChangeListener;
- protected PropertyChangeListener propertyChangeListener;
- protected MouseInputListener mouseInputListener;
- protected FocusListener focusListener;
- // PENDING(api): See comment for ContainerHandler
- private ContainerListener containerListener;
- // Private instance data
- private Insets currentPadInsets = new Insets(0,0,0,0);
- private Insets currentTabAreaInsets = new Insets(0,0,0,0);
- private Component visibleComponent;
- // PENDING(api): See comment for ContainerHandler
- private Vector htmlViews;
- private Hashtable mnemonicToIndexMap;
- /**
- * InputMap used for mnemonics. Only non-null if the JTabbedPane has
- * mnemonics associated with it. Lazily created in initMnemonics.
- */
- private InputMap mnemonicInputMap;
- // For use when tabLayoutPolicy = SCROLL_TAB_LAYOUT
- private ScrollableTabSupport tabScroller;
- /**
- * A rectangle used for general layout calculations in order
- * to avoid constructing many new Rectangles on the fly.
- */
- protected transient Rectangle calcRect = new Rectangle(0,0,0,0);
- /**
- * Number of tabs. When the count differs, the mnemonics are updated.
- */
- // PENDING: This wouldn't be necessary if JTabbedPane had a better
- // way of notifying listeners when the count changed.
- private int tabCount;
- /**
- * Index of the tab the mouse is over.
- */
- private int mouseIndex;
- /**
- * Index of the tab that has focus.
- */
- private boolean selectionFollowsFocus = true;
- private int focusIndex = -1;
- /**
- * Bounds of the tab under the mouse.
- */
- private Rectangle mouseBounds;
- // UI creation
- public static ComponentUI createUI(JComponent c) {
- return new SynthTabbedPaneUI();
- }
- public static void loadActionMap(ActionMap map) {
- // NOTE: this needs to remain static. If you have a need to
- // have Actions that reference the UI in the ActionMap,
- // then you'll also need to change the registeration of the
- // ActionMap.
- map.put("navigateNext", new NextAction());
- map.put("navigatePrevious", new PreviousAction());
- map.put("navigateRight", new RightAction());
- map.put("navigateLeft", new LeftAction());
- map.put("navigateUp", new UpAction());
- map.put("navigateDown", new DownAction());
- map.put("navigatePageUp", new PageUpAction());
- map.put("navigatePageDown", new PageDownAction());
- map.put("requestFocus", new RequestFocusAction());
- map.put("requestFocusForVisibleComponent",
- new RequestFocusForVisibleAction());
- map.put("setSelectedIndex", new SetSelectedIndexAction());
- map.put("selectTabWithFocus", new SelectFocusIndexAction());
- map.put("scrollTabsForwardAction", scrollTabsForwardAction);
- map.put("scrollTabsBackwardAction", scrollTabsBackwardAction);
- }
- // UI Installation/De-installation
- public void installUI(JComponent c) {
- this.tabPane = (JTabbedPane)c;
- c.setLayout(createLayoutManager());
- installComponents();
- installDefaults();
- installListeners();
- installKeyboardActions();
- }
- public void uninstallUI(JComponent c) {
- uninstallKeyboardActions();
- uninstallListeners();
- uninstallDefaults();
- uninstallComponents();
- c.setLayout(null);
- this.tabPane = null;
- }
- /**
- * Invoked by <code>installUI</code> to create
- * a layout manager object to manage
- * the <code>JTabbedPane</code>.
- *
- * @return a layout manager object
- *
- * @see TabbedPaneLayout
- * @see javax.swing.JTabbedPane#getTabLayoutPolicy
- */
- protected LayoutManager createLayoutManager() {
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) {
- return new TabbedPaneScrollLayout();
- } else { /* WRAP_TAB_LAYOUT */
- return new TabbedPaneLayout();
- }
- }
- /* In an attempt to preserve backward compatibility for programs
- * which have extended BasicTabbedPaneUI to do their own layout, the
- * UI uses the installed layoutManager (and not tabLayoutPolicy) to
- * determine if scrollTabLayout is enabled.
- */
- private boolean scrollableTabLayoutEnabled() {
- return (tabPane.getLayout() instanceof TabbedPaneScrollLayout);
- }
- /**
- * Creates and installs any required subcomponents for the JTabbedPane.
- * Invoked by installUI.
- *
- * @since 1.4
- */
- protected void installComponents() {
- if (scrollableTabLayoutEnabled()) {
- if (tabScroller == null) {
- tabScroller = new ScrollableTabSupport(tabPane.getTabPlacement());
- tabPane.add(tabScroller.viewport);
- tabPane.add(tabScroller.scrollForwardButton);
- tabPane.add(tabScroller.scrollBackwardButton);
- }
- }
- }
- /**
- * Removes any installed subcomponents from the JTabbedPane.
- * Invoked by uninstallUI.
- *
- * @since 1.4
- */
- protected void uninstallComponents() {
- if (scrollableTabLayoutEnabled()) {
- tabPane.remove(tabScroller.viewport);
- tabPane.remove(tabScroller.scrollForwardButton);
- tabPane.remove(tabScroller.scrollBackwardButton);
- tabScroller = null;
- }
- }
- protected void installDefaults() {
- fetchStyle(tabPane);
- }
- private void fetchStyle(JTabbedPane c) {
- SynthContext context = getContext(c, ENABLED);
- SynthStyle oldStyle = style;
- style = SynthLookAndFeel.updateStyle(context, this);
- // Add properties other than JComponent colors, Borders and
- // opacity settings here:
- if (style != oldStyle) {
- tabRunOverlay = 0;
- Integer value = (Integer)context.getStyle().get(
- context, "tabRunOverlay");
- if (value != null) {
- tabRunOverlay = value.intValue();
- }
- selectionFollowsFocus = context.getStyle().getBoolean(context,
- "TabbedPane.selectionFollowsFocus",
- true);
- }
- context.dispose();
- if (tabContext != null) {
- tabContext.dispose();
- }
- tabContext = (TabContext)getContext(c, Region.TABBED_PANE_TAB,
- ENABLED);
- this.tabStyle = SynthLookAndFeel.updateStyle(tabContext, this);
- if (tabAreaContext != null) {
- tabAreaContext.dispose();
- }
- tabAreaContext = getContext(c, Region.TABBED_PANE_TAB_AREA, ENABLED);
- this.tabAreaStyle = SynthLookAndFeel.updateStyle(tabAreaContext, this);
- if (tabContentContext != null) {
- tabContentContext.dispose();
- }
- tabContentContext = getContext(c, Region.TABBED_PANE_CONTENT, ENABLED);
- this.tabContentStyle = SynthLookAndFeel.updateStyle(tabContentContext,
- this);
- }
- protected void uninstallDefaults() {
- SynthContext context = getContext(tabPane, ENABLED);
- style.uninstallDefaults(context);
- context.dispose();
- style = null;
- context = getContext(tabPane, Region.TABBED_PANE_TAB, ENABLED);
- tabStyle.uninstallDefaults(context);
- context.dispose();
- tabStyle = null;
- context = getContext(tabPane,Region.TABBED_PANE_TAB_AREA, ENABLED);
- tabAreaStyle.uninstallDefaults(context);
- context.dispose();
- tabAreaStyle = null;
- context = getContext(tabPane, Region.TABBED_PANE_CONTENT, ENABLED);
- tabContentStyle.uninstallDefaults(context);
- context.dispose();
- tabContentStyle = null;
- }
- protected void installListeners() {
- if ((propertyChangeListener = createPropertyChangeListener()) != null) {
- tabPane.addPropertyChangeListener(propertyChangeListener);
- }
- if ((tabChangeListener = createChangeListener()) != null) {
- tabPane.addChangeListener(tabChangeListener);
- }
- if ((mouseInputListener = createMouseInputListener()) != null) {
- if (scrollableTabLayoutEnabled()) {
- tabScroller.tabPanel.addMouseListener(mouseInputListener);
- tabScroller.tabPanel.addMouseMotionListener(mouseInputListener);
- } else { // WRAP_TAB_LAYOUT
- tabPane.addMouseListener(mouseInputListener);
- tabPane.addMouseMotionListener(mouseInputListener);
- }
- }
- if ((focusListener = createFocusListener()) != null) {
- tabPane.addFocusListener(focusListener);
- }
- // PENDING(api) : See comment for ContainerHandler
- if ((containerListener = new ContainerHandler()) != null) {
- tabPane.addContainerListener(containerListener);
- if (tabPane.getTabCount()>0) {
- htmlViews = createHTMLVector();
- }
- }
- }
- protected void uninstallListeners() {
- if (mouseInputListener != null) {
- if (scrollableTabLayoutEnabled()) { // SCROLL_TAB_LAYOUT
- tabScroller.tabPanel.removeMouseListener(mouseInputListener);
- tabScroller.tabPanel.removeMouseMotionListener(
- mouseInputListener);
- } else { // WRAP_TAB_LAYOUT
- tabPane.removeMouseListener(mouseInputListener);
- tabPane.removeMouseMotionListener(mouseInputListener);
- }
- mouseInputListener = null;
- }
- if (focusListener != null) {
- tabPane.removeFocusListener(focusListener);
- focusListener = null;
- }
- // PENDING(api): See comment for ContainerHandler
- if (containerListener != null) {
- tabPane.removeContainerListener(containerListener);
- containerListener = null;
- if (htmlViews!=null) {
- htmlViews.removeAllElements();
- htmlViews = null;
- }
- }
- if (tabChangeListener != null) {
- tabPane.removeChangeListener(tabChangeListener);
- tabChangeListener = null;
- }
- if (propertyChangeListener != null) {
- tabPane.removePropertyChangeListener(propertyChangeListener);
- propertyChangeListener = null;
- }
- }
- protected MouseInputListener createMouseInputListener() {
- return new MouseHandler();
- }
- protected FocusListener createFocusListener() {
- return new FocusHandler();
- }
- protected ChangeListener createChangeListener() {
- return new TabSelectionHandler();
- }
- protected PropertyChangeListener createPropertyChangeListener() {
- return new PropertyChangeHandler();
- }
- protected void installKeyboardActions() {
- InputMap km = getInputMap(JComponent.
- WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
- SwingUtilities.replaceUIInputMap(tabPane, JComponent.
- WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
- km);
- km = getInputMap(JComponent.WHEN_FOCUSED);
- SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, km);
- LazyActionMap.installLazyActionMap(tabPane, SynthTabbedPaneUI.class,
- "TabbedPane.actionMap");
- if (scrollableTabLayoutEnabled()) {
- tabScroller.scrollForwardButton.setAction(
- scrollTabsForwardAction);
- tabScroller.scrollBackwardButton.setAction(
- scrollTabsBackwardAction);
- }
- }
- InputMap getInputMap(int condition) {
- SynthContext context = getContext(tabPane, ENABLED);
- InputMap map = null;
- if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
- map = (InputMap)context.getStyle().get(context,
- "TabbedPane.ancestorInputMap");
- }
- else if (condition == JComponent.WHEN_FOCUSED) {
- map = (InputMap)context.getStyle().get(context,
- "TabbedPane.focusInputMap");
- }
- context.dispose();
- return map;
- }
- protected void uninstallKeyboardActions() {
- SwingUtilities.replaceUIActionMap(tabPane, null);
- SwingUtilities.replaceUIInputMap(tabPane, JComponent.
- WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
- null);
- SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED,
- null);
- }
- /**
- * Reloads the mnemonics. This should be invoked when a memonic changes,
- * when the title of a mnemonic changes, or when tabs are added/removed.
- */
- private void updateMnemonics() {
- resetMnemonics();
- for (int counter = tabPane.getTabCount() - 1; counter >= 0;
- counter--) {
- int mnemonic = tabPane.getMnemonicAt(counter);
- if (mnemonic > 0) {
- addMnemonic(counter, mnemonic);
- }
- }
- }
- /**
- * Resets the mnemonics bindings to an empty state.
- */
- private void resetMnemonics() {
- if (mnemonicToIndexMap != null) {
- mnemonicToIndexMap.clear();
- mnemonicInputMap.clear();
- }
- }
- /**
- * Adds the specified mnemonic at the specified index.
- */
- private void addMnemonic(int index, int mnemonic) {
- if (mnemonicToIndexMap == null) {
- initMnemonics();
- }
- mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK),
- "setSelectedIndex");
- mnemonicToIndexMap.put(new Integer(mnemonic), new Integer(index));
- }
- /**
- * Installs the state needed for mnemonics.
- */
- private void initMnemonics() {
- mnemonicToIndexMap = new Hashtable();
- mnemonicInputMap = new InputMapUIResource();
- mnemonicInputMap.setParent(SwingUtilities.getUIInputMap(tabPane,
- JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT));
- SwingUtilities.replaceUIInputMap(tabPane,
- JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
- mnemonicInputMap);
- }
- // Geometry
- public Dimension getPreferredSize(JComponent c) {
- // Default to LayoutManager's preferredLayoutSize
- return null;
- }
- public Dimension getMinimumSize(JComponent c) {
- // Default to LayoutManager's minimumLayoutSize
- return null;
- }
- public Dimension getMaximumSize(JComponent c) {
- // Default to LayoutManager's maximumLayoutSize
- return null;
- }
- private void repaintTab(int index) {
- }
- private void updateMouseOver(int x, int y) {
- setMouseOverTab(getTabAtLocation(x, y));
- }
- private void setMouseOverTab(int index) {
- if (index != mouseIndex) {
- if (mouseBounds != null) {
- tabPane.repaint(mouseBounds);
- }
- mouseIndex = index;
- if (index != -1 && index < tabPane.getTabCount()) {
- mouseBounds = tabPane.getBoundsAt(index);
- if (mouseBounds != null) {
- tabPane.repaint(mouseBounds);
- }
- }
- else {
- mouseBounds = null;
- }
- }
- }
- // UI Rendering
- public SynthContext getContext(JComponent c) {
- return getContext(c, getComponentState(c));
- }
- public SynthContext getContext(JComponent c, int state) {
- return SynthContext.getContext(SynthContext.class, c,
- SynthLookAndFeel.getRegion(c),style, state);
- }
- public SynthContext getContext(JComponent c, Region subregion) {
- return getContext(c, subregion, getComponentState(c));
- }
- private SynthContext getContext(JComponent c, Region subregion, int state){
- SynthStyle style = null;
- Class klass = SynthContext.class;
- if (subregion == Region.TABBED_PANE_TAB) {
- style = tabStyle;
- klass = TabContext.class;
- }
- else if (subregion == Region.TABBED_PANE_TAB_AREA) {
- style = tabAreaStyle;
- }
- else if (subregion == Region.TABBED_PANE_CONTENT) {
- style = tabContentStyle;
- }
- return SynthContext.getContext(klass, c, subregion, style, state);
- }
- private Region getRegion(JComponent c) {
- return SynthLookAndFeel.getRegion(c);
- }
- private int getComponentState(JComponent c) {
- return SynthLookAndFeel.getComponentState(c);
- }
- public void update(Graphics g, JComponent c) {
- SynthContext context = getContext(c);
- SynthLookAndFeel.update(context, g);
- paint(context, g);
- context.dispose();
- }
- public void paint(Graphics g, JComponent c) {
- SynthContext context = getContext(c);
- paint(context, g);
- context.dispose();
- }
- protected void paint(SynthContext context, Graphics g) {
- int tc = tabPane.getTabCount();
- if (tabCount != tc) {
- tabCount = tc;
- updateMnemonics();
- }
- int selectedIndex = tabPane.getSelectedIndex();
- int tabPlacement = tabPane.getTabPlacement();
- ensureCurrentLayout();
- // Paint tab area
- // If scrollable tabs are enabled, the tab area will be
- // painted by the scrollable tab panel instead.
- //
- if (!scrollableTabLayoutEnabled()) { // WRAP_TAB_LAYOUT
- Insets insets = tabPane.getInsets();
- int x = insets.left;
- int y = insets.top;
- int width = tabPane.getWidth() - insets.left - insets.right;
- int height = tabPane.getHeight() - insets.top - insets.bottom;
- int size;
- switch(tabPlacement) {
- case LEFT:
- width = calculateTabAreaWidth(tabPlacement, runCount,
- maxTabWidth);
- break;
- case RIGHT:
- size = calculateTabAreaWidth(tabPlacement, runCount,
- maxTabWidth);
- x = x + width - size;
- width = size;
- break;
- case BOTTOM:
- size = calculateTabAreaHeight(tabPlacement, runCount,
- maxTabHeight);
- y = y + height - size;
- height = size;
- break;
- case TOP:
- default:
- height = calculateTabAreaHeight(tabPlacement, runCount,
- maxTabHeight);
- }
- paintTabArea(tabAreaContext, g, tabPlacement,
- selectedIndex, new Rectangle(x, y, width, height));
- }
- // Paint content border
- paintContentBorder(tabContentContext, g, tabPlacement, selectedIndex);
- }
- /**
- * Paints the tabs in the tab area.
- * Invoked by paint().
- * The graphics parameter must be a valid <code>Graphics</code>
- * object. Tab placement may be either:
- * <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>,
- * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>.
- * The selected index must be a valid tabbed pane tab index (0 to
- * tab count - 1, inclusive) or -1 if no tab is currently selected.
- * The handling of invalid parameters is unspecified.
- *
- * @param g the graphics object to use for rendering
- * @param tabPlacement the placement for the tabs within the JTabbedPane
- * @param selectedIndex the tab index of the selected component
- *
- * @since 1.4
- */
- protected void paintTabArea(SynthContext ss, Graphics g,
- int tabPlacement, int selectedIndex,
- Rectangle tabAreaBounds) {
- // Paint the tab area.
- SynthLookAndFeel.updateSubregion(ss, g, tabAreaBounds);
- int tabCount = tabPane.getTabCount();
- Rectangle iconRect = new Rectangle(),
- textRect = new Rectangle();
- Rectangle clipRect = g.getClipBounds();
- // Paint tabRuns of tabs from back to front
- for (int i = runCount - 1; i >= 0; i--) {
- int start = tabRuns[i];
- int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
- int end = (next != 0? next - 1: tabCount - 1);
- for (int j = start; j <= end; j++) {
- if (rects[j].intersects(clipRect) && selectedIndex != j) {
- paintTab(tabContext, g, tabPlacement, rects, j, iconRect,
- textRect);
- }
- }
- }
- if (selectedIndex >= 0) {
- if (rects[selectedIndex].intersects(clipRect)) {
- paintTab(tabContext, g, tabPlacement, rects, selectedIndex,
- iconRect, textRect);
- }
- }
- }
- protected void paintTab(SynthContext ss, Graphics g,
- int tabPlacement, Rectangle[] rects, int tabIndex,
- Rectangle iconRect, Rectangle textRect) {
- Rectangle tabRect = rects[tabIndex];
- int selectedIndex = tabPane.getSelectedIndex();
- boolean isSelected = selectedIndex == tabIndex;
- tabContext.update(tabIndex, isSelected, (mouseIndex == tabIndex),
- (focusIndex == tabIndex));
- SynthLookAndFeel.updateSubregion(ss, g, tabRect);
- String title = tabPane.getTitleAt(tabIndex);
- Font font = ss.getStyle().getFont(ss);
- FontMetrics metrics = g.getFontMetrics(font);
- Icon icon = getIconForTab(tabIndex);
- layoutLabel(ss, tabPlacement, metrics, tabIndex, title, icon,
- tabRect, iconRect, textRect, isSelected);
- paintText(ss, g, tabPlacement, font, metrics,
- tabIndex, title, textRect, isSelected);
- paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
- }
- protected void layoutLabel(SynthContext ss, int tabPlacement,
- FontMetrics metrics, int tabIndex,
- String title, Icon icon,
- Rectangle tabRect, Rectangle iconRect,
- Rectangle textRect, boolean isSelected ) {
- View v = getTextViewForTab(tabIndex);
- if (v != null) {
- tabPane.putClientProperty("html", v);
- }
- textRect.x = textRect.y = iconRect.x = iconRect.y = 0;
- ss.getStyle().getSynthGraphics(ss).layoutText(ss, metrics, title,
- icon, SwingUtilities.CENTER, SwingUtilities.CENTER,
- SwingUtilities.LEADING, SwingUtilities.TRAILING,
- tabRect, iconRect, textRect, getTextIconGap());
- tabPane.putClientProperty("html", null);
- // PENDING: Can these be nuked? Don't fit well...
- // If this is necessary, they should be in a special TextLayout
- // that special cases this behavior.
- int xNudge = getTabLabelShiftX(tabPlacement, tabIndex, isSelected);
- int yNudge = getTabLabelShiftY(tabPlacement, tabIndex, isSelected);
- iconRect.x += xNudge;
- iconRect.y += yNudge;
- textRect.x += xNudge;
- textRect.y += yNudge;
- }
- protected void paintIcon(Graphics g, int tabPlacement,
- int tabIndex, Icon icon, Rectangle iconRect,
- boolean isSelected ) {
- if (icon != null) {
- icon.paintIcon(tabPane, g, iconRect.x, iconRect.y);
- }
- }
- protected void paintText(SynthContext ss,
- Graphics g, int tabPlacement,
- Font font, FontMetrics metrics, int tabIndex,
- String title, Rectangle textRect,
- boolean isSelected) {
- g.setFont(font);
- View v = getTextViewForTab(tabIndex);
- if (v != null) {
- // html
- v.paint(g, textRect);
- } else {
- // plain text
- int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
- g.setColor(ss.getStyle().getColor(ss, ColorType.TEXT_FOREGROUND));
- ss.getStyle().getSynthGraphics(ss).paintText(ss, g, title,
- textRect, mnemIndex);
- }
- }
- protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) {
- Rectangle tabRect = rects[tabIndex];
- int nudge = 0;
- switch(tabPlacement) {
- case LEFT:
- nudge = isSelected? -1 : 1;
- break;
- case RIGHT:
- nudge = isSelected? 1 : -1;
- break;
- case BOTTOM:
- case TOP:
- default:
- nudge = tabRect.width % 2;
- }
- return nudge;
- }
- protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) {
- Rectangle tabRect = rects[tabIndex];
- int nudge = 0;
- switch(tabPlacement) {
- case BOTTOM:
- nudge = isSelected? 1 : -1;
- break;
- case LEFT:
- case RIGHT:
- nudge = tabRect.height % 2;
- break;
- case TOP:
- default:
- nudge = isSelected? -1 : 1;;
- }
- return nudge;
- }
- protected void paintContentBorder(SynthContext ss, Graphics g,
- int tabPlacement, int selectedIndex) {
- int width = tabPane.getWidth();
- int height = tabPane.getHeight();
- Insets insets = tabPane.getInsets();
- int x = insets.left;
- int y = insets.top;
- int w = width - insets.right - insets.left;
- int h = height - insets.top - insets.bottom;
- switch(tabPlacement) {
- case LEFT:
- x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
- w -= (x - insets.left);
- break;
- case RIGHT:
- w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
- break;
- case BOTTOM:
- h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
- break;
- case TOP:
- default:
- y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
- h -= (y - insets.top);
- }
- SynthLookAndFeel.updateSubregion(ss, g, new Rectangle(x, y, w, h));
- }
- private void ensureCurrentLayout() {
- if (!tabPane.isValid()) {
- tabPane.validate();
- }
- /* If tabPane doesn't have a peer yet, the validate() call will
- * silently fail. We handle that by forcing a layout if tabPane
- * is still invalid. See bug 4237677.
- */
- if (!tabPane.isValid()) {
- TabbedPaneLayout layout = (TabbedPaneLayout)tabPane.getLayout();
- layout.calculateLayoutInfo();
- }
- }
- // TabbedPaneUI methods
- /**
- * Returns the bounds of the specified tab index. The bounds are
- * with respect to the JTabbedPane's coordinate space.
- */
- public Rectangle getTabBounds(JTabbedPane pane, int i) {
- ensureCurrentLayout();
- Rectangle tabRect = new Rectangle();
- return getTabBounds(i, tabRect);
- }
- public int getTabRunCount(JTabbedPane pane) {
- ensureCurrentLayout();
- return runCount;
- }
- /**
- * Returns the tab index which intersects the specified point
- * in the JTabbedPane's coordinate space.
- */
- public int tabForCoordinate(JTabbedPane pane, int x, int y) {
- ensureCurrentLayout();
- Point p = new Point(x, y);
- if (scrollableTabLayoutEnabled()) {
- translatePointToTabPanel(x, y, p);
- }
- int tabCount = tabPane.getTabCount();
- for (int i = 0; i < tabCount; i++) {
- if (rects[i].contains(p.x, p.y)) {
- return i;
- }
- }
- return -1;
- }
- /**
- * Returns the bounds of the specified tab in the coordinate space
- * of the JTabbedPane component. This is required because the tab rects
- * are by default defined in the coordinate space of the component where
- * they are rendered, which could be the JTabbedPane
- * (for WRAP_TAB_LAYOUT) or a ScrollableTabPanel (SCROLL_TAB_LAYOUT).
- * This method should be used whenever the tab rectangle must be relative
- * to the JTabbedPane itself and the result should be placed in a
- * designated Rectangle object (rather than instantiating and returning
- * a new Rectangle each time). The tab index parameter must be a valid
- * tabbed pane tab index (0 to tab count - 1, inclusive). The destination
- * rectangle parameter must be a valid <code>Rectangle</code> instance.
- * The handling of invalid parameters is unspecified.
- *
- * @param tabIndex the index of the tab
- * @param dest the rectangle where the result should be placed
- * @return the resulting rectangle
- *
- * @since 1.4
- */
- protected Rectangle getTabBounds(int tabIndex, Rectangle dest) {
- dest.width = rects[tabIndex].width;
- dest.height = rects[tabIndex].height;
- if (scrollableTabLayoutEnabled()) { // SCROLL_TAB_LAYOUT
- // Need to translate coordinates based on viewport location &
- // view position
- Point vpp = tabScroller.viewport.getLocation();
- Point viewp = tabScroller.viewport.getViewPosition();
- dest.x = rects[tabIndex].x-vpp.x-viewp.x;
- dest.y = rects[tabIndex].y-vpp.y-viewp.y;
- } else { // WRAP_TAB_LAYOUT
- dest.x = rects[tabIndex].x;
- dest.y = rects[tabIndex].y;
- }
- return dest;
- }
- /**
- * Returns the tab index which intersects the specified point
- * in the coordinate space of the component where the
- * tabs are actually rendered, which could be the JTabbedPane
- * (for WRAP_TAB_LAYOUT) or a ScrollableTabPanel (SCROLL_TAB_LAYOUT).
- */
- private int getTabAtLocation(int x, int y) {
- ensureCurrentLayout();
- int tabCount = tabPane.getTabCount();
- for (int i = 0; i < tabCount; i++) {
- if (rects[i].contains(x, y)) {
- return i;
- }
- }
- return -1;
- }
- /**
- * Returns the index of the tab closest to the passed in location, note
- * that the returned tab may not contain the location x,y.
- */
- private int getClosestTab(int x, int y) {
- int min = 0;
- int tabCount = Math.min(rects.length, tabPane.getTabCount());
- int max = tabCount;
- int tabPlacement = tabPane.getTabPlacement();
- boolean useX = (tabPlacement == TOP || tabPlacement == BOTTOM);
- int want = (useX) ? x : y;
- while (min != max) {
- int current = (max + min) / 2;
- int minLoc;
- int maxLoc;
- if (useX) {
- minLoc = rects[current].x;
- maxLoc = minLoc + rects[current].width;
- }
- else {
- minLoc = rects[current].y;
- maxLoc = minLoc + rects[current].height;
- }
- if (want < minLoc) {
- max = current;
- if (min == max) {
- return Math.max(0, current - 1);
- }
- }
- else if (want >= maxLoc) {
- min = current;
- if (max - min <= 1) {
- return Math.max(current + 1, tabCount - 1);
- }
- }
- else {
- return current;
- }
- }
- return min;
- }
- /**
- * Returns a point which is translated from the specified point in the
- * JTabbedPane's coordinate space to the coordinate space of the
- * ScrollableTabPanel. This is used for SCROLL_TAB_LAYOUT ONLY.
- */
- private Point translatePointToTabPanel(int srcx, int srcy, Point dest) {
- Point vpp = tabScroller.viewport.getLocation();
- Point viewp = tabScroller.viewport.getViewPosition();
- dest.x = srcx + vpp.x + viewp.x;
- dest.y = srcy + vpp.y + viewp.y;
- return dest;
- }
- // BasicTabbedPaneUI methods
- protected Component getVisibleComponent() {
- return visibleComponent;
- }
- protected void setVisibleComponent(Component component) {
- if (visibleComponent != null && visibleComponent != component &&
- visibleComponent.getParent() == tabPane) {
- visibleComponent.setVisible(false);
- }
- if (component != null && !component.isVisible()) {
- component.setVisible(true);
- }
- visibleComponent = component;
- }
- protected void assureRectsCreated(int tabCount) {
- int rectArrayLen = rects.length;
- if (tabCount != rectArrayLen ) {
- Rectangle[] tempRectArray = new Rectangle[tabCount];
- System.arraycopy(rects, 0, tempRectArray, 0,
- Math.min(rectArrayLen, tabCount));
- rects = tempRectArray;
- for (int rectIndex = rectArrayLen; rectIndex < tabCount; rectIndex++) {
- rects[rectIndex] = new Rectangle();
- }
- }
- }
- protected void expandTabRunsArray() {
- int rectLen = tabRuns.length;
- int[] newArray = new int[rectLen+10];
- System.arraycopy(tabRuns, 0, newArray, 0, runCount);
- tabRuns = newArray;
- }
- protected int getRunForTab(int tabCount, int tabIndex) {
- for (int i = 0; i < runCount; i++) {
- int first = tabRuns[i];
- int last = lastTabInRun(tabCount, i);
- if (tabIndex >= first && tabIndex <= last) {
- return i;
- }
- }
- return 0;
- }
- protected int lastTabInRun(int tabCount, int run) {
- if (runCount == 1) {
- return tabCount - 1;
- }
- int nextRun = (run == runCount - 1? 0 : run + 1);
- if (tabRuns[nextRun] == 0) {
- return tabCount - 1;
- }
- return tabRuns[nextRun]-1;
- }
- protected int getTabRunOverlay(int tabPlacement) {
- return tabRunOverlay;
- }
- protected int getTabRunIndent(int tabPlacement, int run) {
- return 0;
- }
- protected boolean shouldPadTabRun(int tabPlacement, int run) {
- return runCount > 1;
- }
- protected boolean shouldRotateTabRuns(int tabPlacement) {
- return true;
- }
- protected Icon getIconForTab(int tabIndex) {
- return (!tabPane.isEnabled() || !tabPane.isEnabledAt(tabIndex))?
- tabPane.getDisabledIconAt(tabIndex) : tabPane.getIconAt(tabIndex);
- }
- /**
- * Returns the text View object required to render stylized text (HTML) for
- * the specified tab or null if no specialized text rendering is needed
- * for this tab. This is provided to support html rendering inside tabs.
- *
- * @param tabIndex the index of the tab
- * @return the text view to render the tab's text or null if no
- * specialized rendering is required
- *
- * @since 1.4
- */
- protected View getTextViewForTab(int tabIndex) {
- if (htmlViews != null) {
- return (View)htmlViews.elementAt(tabIndex);
- }
- return null;
- }
- protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight) {
- int height = 0;
- View v = getTextViewForTab(tabIndex);
- if (v != null) {
- // html
- height += (int)v.getPreferredSpan(View.Y_AXIS);
- } else {
- // plain text
- height += fontHeight;
- }
- Icon icon = getIconForTab(tabIndex);
- Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
- if (icon != null) {
- height = Math.max(height, icon.getIconHeight());
- }
- height += tabInsets.top + tabInsets.bottom + 2;
- return height;
- }
- protected int calculateMaxTabHeight(int tabPlacement) {
- FontMetrics metrics = getFontMetrics(tabContext.getStyle().getFont(
- tabContext));
- int tabCount = tabPane.getTabCount();
- int result = 0;
- int fontHeight = metrics.getHeight();
- for(int i = 0; i < tabCount; i++) {
- result = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), result);
- }
- return result;
- }
- protected int calculateTabWidth(int tabPlacement, int tabIndex,
- FontMetrics metrics) {
- Icon icon = getIconForTab(tabIndex);
- Insets tabInsets = getTabInsets(tabPlacement, tabIndex);
- int width = tabInsets.left + tabInsets.right + 3;
- if (icon != null) {
- // PENDING: This should call to SynthIcon for size.
- width += icon.getIconWidth() + getTextIconGap();
- }
- View v = getTextViewForTab(tabIndex);
- if (v != null) {
- // html
- width += (int)v.getPreferredSpan(View.X_AXIS);
- } else {
- // plain text
- String title = tabPane.getTitleAt(tabIndex);
- width += tabContext.getStyle().getSynthGraphics(tabContext).
- computeStringWidth(tabContext, metrics.getFont(),
- metrics, title);
- }
- return width;
- }
- private int getTextIconGap() {
- Integer gap = (Integer)tabContext.getStyle().get(tabContext,"textIconGap");
- if (gap == null) {
- return 0;
- }
- return gap.intValue();
- }
- protected int calculateMaxTabWidth(int tabPlacement) {
- FontMetrics metrics = getFontMetrics(tabContext.getStyle().getFont(
- tabContext));
- int tabCount = tabPane.getTabCount();
- int result = 0;
- for(int i = 0; i < tabCount; i++) {
- result = Math.max(calculateTabWidth(tabPlacement, i, metrics),
- result);
- }
- return result;
- }
- protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount,
- int maxTabHeight) {
- Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
- int tabRunOverlay = getTabRunOverlay(tabPlacement);
- return (horizRunCount > 0?
- horizRunCount * (maxTabHeight-tabRunOverlay) + tabRunOverlay +
- tabAreaInsets.top + tabAreaInsets.bottom :
- 0);
- }
- protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount,
- int maxTabWidth) {
- Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
- int tabRunOverlay = getTabRunOverlay(tabPlacement);
- return (vertRunCount > 0?
- vertRunCount * (maxTabWidth-tabRunOverlay) + tabRunOverlay +
- tabAreaInsets.left + tabAreaInsets.right :
- 0);
- }
- protected Insets getTabInsets(int tabPlacement, int tabIndex) {
- tabContext.update(tabIndex, false, (mouseIndex == tabIndex),
- (focusIndex == tabIndex));
- return tabContext.getStyle().getInsets(tabContext, null);
- }
- protected Insets getSelectedTabPadInsets(int tabPlacement) {
- Insets insets = (Insets)tabContext.getStyle().get(tabContext,
- "selectedTabPadInsets");
- if (insets == null) {
- return new Insets(0, 0, 0, 0);
- }
- Insets result = new Insets(0, 0, 0, 0);
- rotateInsets(insets, new Insets(0, 0, 0, 0), tabPlacement);
- return result;
- }
- protected Insets getTabAreaInsets(int tabPlacement) {
- return tabAreaContext.getStyle().getInsets(tabAreaContext, null);
- }
- protected Insets getContentBorderInsets(int tabPlacement) {
- return tabContentContext.getStyle().getInsets(tabContentContext,
- null);
- }
- protected FontMetrics getFontMetrics() {
- return getFontMetrics(tabContext.getStyle().getFont(tabContext));
- }
- protected FontMetrics getFontMetrics(Font font) {
- return Toolkit.getDefaultToolkit().getFontMetrics(font);
- }
- // Tab Navigation methods
- protected void navigateSelectedTab(int direction) {
- int tabPlacement = tabPane.getTabPlacement();
- int current = selectionFollowsFocus? tabPane.getSelectedIndex() :
- focusIndex;
- int tabCount = tabPane.getTabCount();
- // If we have no tabs then don't navigate.
- if (tabCount <= 0) {
- return;
- }
- int offset;
- switch(tabPlacement) {
- case NEXT:
- selectNextTab(current);
- break;
- case PREVIOUS:
- selectPreviousTab(current);
- break;
- case LEFT:
- case RIGHT:
- switch(direction) {
- case NORTH:
- selectPreviousTabInRun(current);
- break;
- case SOUTH:
- selectNextTabInRun(current);
- break;
- case WEST:
- offset = getTabRunOffset(tabPlacement, tabCount, current, false);
- selectAdjacentRunTab(tabPlacement, current, offset);
- break;
- case EAST:
- offset = getTabRunOffset(tabPlacement, tabCount, current, true);
- selectAdjacentRunTab(tabPlacement, current, offset);
- break;
- default:
- }
- break;
- case BOTTOM:
- case TOP:
- default:
- switch(direction) {
- case NORTH:
- offset = getTabRunOffset(tabPlacement, tabCount, current, false);
- selectAdjacentRunTab(tabPlacement, current, offset);
- break;
- case SOUTH:
- offset = getTabRunOffset(tabPlacement, tabCount, current, true);
- selectAdjacentRunTab(tabPlacement, current, offset);
- break;
- case EAST:
- selectNextTabInRun(current);
- break;
- case WEST:
- selectPreviousTabInRun(current);
- break;
- default:
- }
- }
- }
- protected void selectNextTabInRun(int current) {
- int tabCount = tabPane.getTabCount();
- int tabIndex = getNextTabIndexInRun(tabCount, current);
- while(tabIndex != current && !tabPane.isEnabledAt(tabIndex)) {
- tabIndex = getNextTabIndexInRun(tabCount, tabIndex);
- }
- navigateTo(tabIndex);
- }
- protected void selectPreviousTabInRun(int current) {
- int tabCount = tabPane.getTabCount();
- int tabIndex = getPreviousTabIndexInRun(tabCount, current);
- while(tabIndex != current && !tabPane.isEnabledAt(tabIndex)) {
- tabIndex = getPreviousTabIndexInRun(tabCount, tabIndex);
- }
- navigateTo(tabIndex);
- }
- protected void selectNextTab(int current) {
- int tabIndex = getNextTabIndex(current);
- while (tabIndex != current && !tabPane.isEnabledAt(tabIndex)) {
- tabIndex = getNextTabIndex(tabIndex);
- }
- navigateTo(tabIndex);
- }
- protected void selectPreviousTab(int current) {
- int tabIndex = getPreviousTabIndex(current);
- while (tabIndex != current && !tabPane.isEnabledAt(tabIndex)) {
- tabIndex = getPreviousTabIndex(tabIndex);
- }
- navigateTo(tabIndex);
- }
- protected void selectAdjacentRunTab(int tabPlacement,
- int tabIndex, int offset) {
- if ( runCount < 2 ) {
- return;
- }
- int newIndex;
- Rectangle r = rects[tabIndex];
- switch(tabPlacement) {
- case LEFT:
- case RIGHT:
- newIndex = getTabAtLocation(r.x + r.width2 + offset,
- r.y + r.height2);
- break;
- case BOTTOM:
- case TOP:
- default:
- newIndex = getTabAtLocation(r.x + r.width2,
- r.y + r.height2 + offset);
- }
- if (newIndex != -1) {
- while (!tabPane.isEnabledAt(newIndex) && newIndex != tabIndex) {
- newIndex = getNextTabIndex(newIndex);
- }
- navigateTo(newIndex);
- }
- }
- private void navigateTo(int index) {
- if (selectionFollowsFocus) {
- setFocusIndex(index);
- tabPane.setSelectedIndex(index);
- } else {
- // Just move focus (not selection)
- int oldFocusIndex = focusIndex;
- setFocusIndex(index);
- tabPane.repaint(getTabBounds(tabPane, focusIndex));
- if (oldFocusIndex != -1) {
- tabPane.repaint(getTabBounds(tabPane, oldFocusIndex));
- }
- }
- }
- void setFocusIndex(int index) {
- focusIndex = index;
- }
- int getFocusIndex() {
- return focusIndex;
- }
- protected int getTabRunOffset(int tabPlacement, int tabCount,
- int tabIndex, boolean forward) {
- int run = getRunForTab(tabCount, tabIndex);
- int offset;
- switch(tabPlacement) {
- case LEFT: {
- if (run == 0) {
- offset = (forward?
- -(calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth)-maxTabWidth) :
- -maxTabWidth);
- } else if (run == runCount - 1) {
- offset = (forward?
- maxTabWidth :
- calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth)-maxTabWidth);
- } else {
- offset = (forward? maxTabWidth : -maxTabWidth);
- }
- break;
- }
- case RIGHT: {
- if (run == 0) {
- offset = (forward?
- maxTabWidth :
- calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth)-maxTabWidth);
- } else if (run == runCount - 1) {
- offset = (forward?
- -(calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth)-maxTabWidth) :
- -maxTabWidth);
- } else {
- offset = (forward? maxTabWidth : -maxTabWidth);
- }
- break;
- }
- case BOTTOM: {
- if (run == 0) {
- offset = (forward?
- maxTabHeight :
- calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight)-maxTabHeight);
- } else if (run == runCount - 1) {
- offset = (forward?
- -(calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight)-maxTabHeight) :
- -maxTabHeight);
- } else {
- offset = (forward? maxTabHeight : -maxTabHeight);
- }
- break;
- }
- case TOP:
- default: {
- if (run == 0) {
- offset = (forward?
- -(calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight)-maxTabHeight) :
- -maxTabHeight);
- } else if (run == runCount - 1) {
- offset = (forward?
- maxTabHeight :
- calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight)-maxTabHeight);
- } else {
- offset = (forward? maxTabHeight : -maxTabHeight);
- }
- }
- }
- return offset;
- }
- protected int getPreviousTabIndex(int base) {
- int tabIndex = (base - 1 >= 0? base - 1 : tabPane.getTabCount() - 1);
- return (tabIndex >= 0? tabIndex : 0);
- }
- protected int getNextTabIndex(int base) {
- return (base+1)%tabPane.getTabCount();
- }
- protected int getNextTabIndexInRun(int tabCount, int base) {
- if (runCount < 2) {
- return getNextTabIndex(base);
- }
- int currentRun = getRunForTab(tabCount, base);
- int next = getNextTabIndex(base);
- if (next == tabRuns[getNextTabRun(currentRun)]) {
- return tabRuns[currentRun];
- }
- return next;
- }
- protected int getPreviousTabIndexInRun(int tabCount, int base) {
- if (runCount < 2) {
- return getPreviousTabIndex(base);
- }
- int currentRun = getRunForTab(tabCount, base);
- if (base == tabRuns[currentRun]) {
- int previous = tabRuns[getNextTabRun(currentRun)]-1;
- return (previous != -1? previous : tabCount-1);
- }
- return getPreviousTabIndex(base);
- }
- protected int getPreviousTabRun(int baseRun) {
- int runIndex = (baseRun - 1 >= 0? baseRun - 1 : runCount - 1);
- return (runIndex >= 0? runIndex : 0);
- }
- protected int getNextTabRun(int baseRun) {
- return (baseRun+1)%runCount;
- }
- protected static void rotateInsets(Insets topInsets, Insets targetInsets, int targetPlacement) {
- switch(targetPlacement) {
- case LEFT:
- targetInsets.top = topInsets.left;
- targetInsets.left = topInsets.top;
- targetInsets.bottom = topInsets.right;
- targetInsets.right = topInsets.bottom;
- break;
- case BOTTOM:
- targetInsets.top = topInsets.bottom;
- targetInsets.left = topInsets.left;
- targetInsets.bottom = topInsets.top;
- targetInsets.right = topInsets.right;
- break;
- case RIGHT:
- targetInsets.top = topInsets.left;
- targetInsets.left = topInsets.bottom;
- targetInsets.bottom = topInsets.right;
- targetInsets.right = topInsets.top;
- break;
- case TOP:
- default:
- targetInsets.top = topInsets.top;
- targetInsets.left = topInsets.left;
- targetInsets.bottom = topInsets.bottom;
- targetInsets.right = topInsets.right;
- }
- }
- // REMIND(aim,7/29/98): This method should be made
- // protected in the next release where
- // API changes are allowed
- //
- boolean requestFocusForVisibleComponent() {
- Component visibleComponent = getVisibleComponent();
- if (visibleComponent.isFocusTraversable()) {
- visibleComponent.requestFocus();
- return true;
- } else if (visibleComponent instanceof JComponent) {
- if (((JComponent)visibleComponent).requestDefaultFocus()) {
- return true;
- }
- }
- return false;
- }
- private static class RightAction extends AbstractAction {
- public void actionPerformed(ActionEvent e) {
- JTabbedPane pane = (JTabbedPane)e.getSource();
- SynthTabbedPaneUI ui = (SynthTabbedPaneUI)pane.getUI();
- ui.navigateSelectedTab(EAST);
- }
- };
- private static class LeftAction extends AbstractAction {
- public void actionPerformed(ActionEvent e) {
- JTabbedPane pane = (JTabbedPane)e.getSource();
- SynthTabbedPaneUI ui = (SynthTabbedPaneUI)pane.getUI();
- ui.navigateSelectedTab(WEST);
- }
- };
- private static class UpAction extends AbstractAction {
- public void actionPerformed(ActionEvent e) {
- JTabbedPane pane = (JTabbedPane)e.getSource();
- SynthTabbedPaneUI ui = (