All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jidesoft.swing.JideTabbedPane Maven / Gradle / Ivy

There is a newer version: 3.6.18
Show newest version
/*
 * @(#)JideTabbedPane.java	Oct 7, 2002
 *
 * Copyright 2002 JIDE Software Inc. All rights reserved.
 */
package com.jidesoft.swing;

import com.jidesoft.plaf.JideTabbedPaneUI;
import com.jidesoft.plaf.LookAndFeelFactory;
import com.jidesoft.plaf.UIDefaultsLookup;
import com.jidesoft.plaf.basic.BasicJideTabbedPaneUI;
import com.jidesoft.popup.JidePopup;
import com.jidesoft.utils.JideFocusTracker;
import com.jidesoft.utils.PortingUtils;
import com.jidesoft.utils.SystemInfo;

import javax.swing.*;
import javax.swing.plaf.TabbedPaneUI;
import javax.swing.plaf.UIResource;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * JideTabbedPane is an enhanced version of JTabbedPane. Different from
 * JTabbedPane, it 
  • has an option to hide tab area if there is only one component in the tabbed * pane.
  • has an option to resize tab width so that all tabs can be fitted in one row.
  • has an option to show a * close button along with scroll left and scroll right buttons in tab area.
Except methods to set additional * options specified above, the usage of JideTabbedPane is the same as JTabbedPane. */ public class JideTabbedPane extends JTabbedPane { private boolean _hideOneTab = false; private boolean _showTabButtons = false; private boolean _showCloseButton = false; private boolean _showCloseButtonOnTab = false; private boolean _showCloseButtonOnMouseOver = false; private boolean _useDefaultShowCloseButtonOnTab = false; private boolean _showTabArea = true; private boolean _showTabContent = true; private boolean _showIconsOnTab = true; private boolean _useDefaultShowIconsOnTab = true; private boolean _rightClickSelect; private boolean _dragOverDisabled; private boolean _scrollSelectedTabOnWheel = false; private int _tabAlignment = SwingConstants.LEADING; /** * Bound property name for shrink tabs. */ public static final String SHRINK_TAB_PROPERTY = "shrinkTab"; /** * Bound property name for hide tab area if there is only one tab. */ public static final String HIDE_IF_ONE_TAB_PROPERTY = "hideIfOneTab"; /** * Bound property name for show tab button. */ public static final String SHOW_TAB_BUTTONS_PROPERTY = "showTabButtons"; /** * Bound property name for box style */ public static final String BOX_STYLE_PROPERTY = "boxStyle"; /** * Bound property name for show icons on tab */ public static final String SHOW_ICONS_PROPERTY = "showIconsOnTab"; /** * Bound property name for using default show icons on tab value from UIDefaults */ public static final String USE_DEFAULT_SHOW_ICONS_PROPERTY = "useDefaultShowIconsOnTab"; /** * Bound property name for if showing close button on tab */ public static final String SHOW_CLOSE_BUTTON_ON_TAB_PROPERTY = "showCloseButtonOnTab"; /** * Bound property name for if showing close button */ public static final String SHOW_CLOSE_BUTTON_PROPERTY = "showCloseButton"; /** * Bound property name for if the tab area is visible. */ public static final String SHOW_TAB_AREA_PROPERTY = "showTabArea"; /** * Bound property name for if the tab area is visible. */ public static final String SHOW_TAB_CONTENT_PROPERTY = "showTabContent"; /** * Bound property name for tab closable. */ public static final String TAB_CLOSABLE_PROPERTY = "tabClosable"; /** * Bound property name for using default show close button on tab value from UIDefaults */ public static final String USE_DEFAULT_SHOW_CLOSE_BUTTON_ON_TAB_PROPERTY = "useDefaultShowCloseButtonOnTab"; /** * Bound property name for if the active tab title is in bold */ public static final String BOLDACTIVETAB_PROPERTY = "boldActiveTab"; /** * Bound property name for gripper. */ public static final String GRIPPER_PROPERTY = "gripper"; public static final String PROPERTY_TAB_SHAPE = "tabShape"; public static final String PROPERTY_COLOR_THEME = "colorTheme"; public static final String PROPERTY_TAB_RESIZE_MODE = "tabResizeMode"; public static final String PROPERTY_TAB_LEADING_COMPONENT = "tabLeadingComponent"; public static final String PROPERTY_TAB_TRAILING_COMPONENT = "tabTrailingComponent"; public static final String PROPERTY_TAB_COLOR_PROVIDER = "tabColorProvider"; public static final String PROPERTY_CONTENT_BORDER_INSETS = "contentBorderInsets"; public static final String PROPERTY_TAB_AREA_INSETS = "tabAreaInsets"; public static final String PROPERTY_TAB_INSETS = "tabInsets"; public static final String PROPERTY_DRAG_OVER_DISABLED = "dragOverDisabled"; public static final String SCROLL_TAB_ON_WHEEL_PROPERTY = "scrollTabOnWheel"; public static final String PROPERTY_SELECTED_INDEX = "selectedIndex"; public static final String PROPERTY_SHOW_CLOSE_BUTTON_ON_MOUSE_OVER = "showCloseButtonOnMouseOver"; public static final int BUTTON_CLOSE = 0; public static final int BUTTON_EAST = 1; public static final int BUTTON_WEST = 2; public static final int BUTTON_NORTH = 3; public static final int BUTTON_SOUTH = 4; public static final int BUTTON_LIST = 5; /** * @see #getUIClassID * @see #readObject */ private static final String uiClassID = "JideTabbedPaneUI"; /** * If the gripper should be shown. Gripper is something on divider to indicate it can be dragged. */ private boolean _showGripper = false; /** * A converter to shorten */ private StringConverter _stringConverter; private boolean _boldActiveTab = false; /** * The Set for the tab closable. If there is an entry in the Set, it means the tab is NOT closable. */ private Set _closableSet = new HashSet(); private Hashtable _pageLastFocusTrackers = new Hashtable(); private Font _selectedTabFont; /** * A tab resize mode. The default resize mode means it will use the resize mode of {@link * #getDefaultTabResizeMode()} which is defined in UIDefault "JideTabbedPane.defaultResizeMode". You can change this * in UIDefault. It will affect the resize mode of all JideTabbedPanes. */ public static final int RESIZE_MODE_DEFAULT = 0; /** * A tab resize mode. The none resize mode means the tab will not resize when tabbed pane width changes. */ public static final int RESIZE_MODE_NONE = 1; /** * A tab resize mode. The fit resize mode means the tabs will shrink if the tabbed pane width shrinks so there is no * way to display the full contents of the tabs. */ public static final int RESIZE_MODE_FIT = 2; /** * A tab resize mode. All tabs will be at a fixed width. The fixed width is defined as UIDefault * "JideTabbedPane.fixedStyleRectSize" which is an integer. */ public static final int RESIZE_MODE_FIXED = 3; /** * A tab resize mode. In this mode, the select tab will have full tab width. Non-selected tab will only display the * icon. The actual width of non-selected tab is determined by UIDefault "JideTabbedPane.compressedStyleNoIconRectSize" * which is an integer. */ public static final int RESIZE_MODE_COMPRESSED = 4; private int _tabResizeMode = RESIZE_MODE_DEFAULT; /** * color style */ public static final int COLOR_THEME_DEFAULT = 0; public static final int COLOR_THEME_WIN2K = 1; public static final int COLOR_THEME_OFFICE2003 = 2; public static final int COLOR_THEME_VSNET = 3; public static final int COLOR_THEME_WINXP = 4; // color style private int _colorTheme = COLOR_THEME_DEFAULT; // tab shape public static final int SHAPE_DEFAULT = 0; public static final int SHAPE_WINDOWS = 1; public static final int SHAPE_VSNET = 2; public static final int SHAPE_BOX = 3; public static final int SHAPE_OFFICE2003 = 4; public static final int SHAPE_FLAT = 5; public static final int SHAPE_ECLIPSE = 6; public static final int SHAPE_ECLIPSE3X = 7; public static final int SHAPE_EXCEL = 8; public static final int SHAPE_ROUNDED_VSNET = 9; public static final int SHAPE_ROUNDED_FLAT = 10; public static final int SHAPE_WINDOWS_SELECTED = 11; private int _tabShape = SHAPE_DEFAULT; private Component _tabLeadingComponent = null; private Component _tabTrailingComponent = null; private boolean _hideTrailingWhileNoButtons = false; // show close button on active tab only private boolean _showCloseButtonOnSelectedTab = false; private ListCellRenderer _tabListCellRenderer; private Insets _contentBorderInsets; private Insets _tabAreaInsets; private Insets _tabInsets; private static final Logger LOGGER_EVENT = Logger.getLogger(TabEditingEvent.class.getName()); private boolean _closeTabOnMouseMiddleButton = false; private boolean _layoutTrailingComponentBeforeButtons = false; private JidePopup _tabListPopup; /** * Creates an empty TabbedPane with a default tab placement of JTabbedPane.TOP. * * @see #addTab */ public JideTabbedPane() { this(JideTabbedPane.TOP, JideTabbedPane.SCROLL_TAB_LAYOUT); } /** * Creates an empty TabbedPane with the specified tab placement of either: * JTabbedPane.TOP, JTabbedPane.BOTTOM, JTabbedPane.LEFT, or * JTabbedPane.RIGHT. * * @param tabPlacement the placement for the tabs relative to the content * @see #addTab */ public JideTabbedPane(int tabPlacement) { this(tabPlacement, JideTabbedPane.SCROLL_TAB_LAYOUT); } /** * Creates an empty JideTabbedPane with the specified tab placement and tab layout policy. Tab * placement may be either: JTabbedPane.TOP or JTabbedPane.BOTTOM Tab layout policy should * always be JTabbedPane.SCROLL_TAB_LAYOUT. JTabbedPane also supports * JTabbedPane.WRAP_TAB_LAYOUT. However the style of tabs in JideTabbedPane doesn't match * with JTabbedPane.WRAP_TAB_LAYOUT very well, so we decided not to support it. * * @param tabPlacement the placement for the tabs relative to the content * @param tabLayoutPolicy the policy for laying out tabs when all tabs will not fit on one run * @throws IllegalArgumentException if tab placement or tab layout policy are not one of the above supported values * @see #addTab */ public JideTabbedPane(int tabPlacement, int tabLayoutPolicy) { super(tabPlacement, tabLayoutPolicy); // if(tabLayoutPolicy == WRAP_TAB_LAYOUT) // tabLayoutPolicy = SCROLL_TAB_LAYOUT; setModel(new IgnoreableSingleSelectionModel()); } /** * Returns the UI object which implements the L&F for this component. * * @return a TabbedPaneUI object * @see #setUI */ @Override public TabbedPaneUI getUI() { return (TabbedPaneUI) ui; } /** * Sets the UI object which implements the L&F for this component. * * @param ui the new UI object * @see UIDefaults#getUI */ @Override public void setUI(TabbedPaneUI ui) { super.setUI(ui); } /** * Resets the UI property to a value from the current look and feel. * * @see JComponent#updateUI */ @Override public void updateUI() { if (UIDefaultsLookup.get(uiClassID) == null) { LookAndFeelFactory.installJideExtension(); } setUI((TabbedPaneUI) UIManager.getUI(JideTabbedPane.this)); } /** * Returns the name of the UI class that implements the L&F for this component. * * @return the string "TabbedPaneUI" * @see JComponent#getUIClassID * @see UIDefaults#getUI */ @Override public String getUIClassID() { return uiClassID; } /** * Checks if tab area will be hidden if there is only one tab.
If the showTabButtons option is true, * isHideOneTab will always return false so that there is a place to place those tab buttons. * * @return true if tab areas will be hidden if there is only one tab; false otherwise. */ public boolean isHideOneTab() { return !isShowTabButtons() && _hideOneTab; } /** * Sets the value if tab area will be hidden if there is only one tab. PropertyChangeEvent of * HIDE_IF_ONE_TAB_PROPERTY will be fired.
If the showTabButtons option is true, no matter what option you pass * to setHideOneTab, isHideOneTab will always return false. * * @param hideOne true to hide tab areas if there is only one tab; false otherwise. */ public void setHideOneTab(boolean hideOne) { boolean oldValue = _hideOneTab; if (oldValue != hideOne) { _hideOneTab = hideOne; firePropertyChange(HIDE_IF_ONE_TAB_PROPERTY, oldValue, _hideOneTab); } } /** * Checks if tab area is shown. * * @return true if tab area is visible; false otherwise. */ public boolean isTabShown() { return isShowTabArea() && !(isHideOneTab() && getTabCount() <= 1); } /** * Checks if tab buttons are always visible. Tab buttons are scroll left button, scroll right button and close * button which appear to the right of tabs in tab area.
If the showTabButtons is set to true, isHideOneTab * will always return false so that there is a place to place those tab buttons. * * @return true if tab buttons are always visible; false otherwise. */ public boolean isShowTabButtons() { return _showTabButtons; } /** * Sets the value if tab buttons are always visible. PropertyChangeEvent of SHOW_TAB_BUTTONS_PROPERTY will be * fired. * * @param showButtons true to always show tab buttons; false otherwise. */ public void setShowTabButtons(boolean showButtons) { boolean oldValue = _showTabButtons; if (oldValue != showButtons) { _showTabButtons = showButtons; firePropertyChange(SHOW_TAB_BUTTONS_PROPERTY, oldValue, _showTabButtons); } } private Action _closeAction; /** * Sets default close action for close button. * * @param action the close action. */ public void setCloseAction(Action action) { Action old = _closeAction; if (old != action) { _closeAction = action; firePropertyChange("closeTabAction", old, _closeAction); } } /** * Gets close action. * * @return close action */ public Action getCloseAction() { return _closeAction; } public void setAutoFocusOnTabHideClose(boolean autoFocusonTabHideClose) { _autoFocusonTabHideClose = autoFocusonTabHideClose; } public boolean isAutoFocusOnTabHideClose() { return _autoFocusonTabHideClose; } boolean _autoFocusonTabHideClose = true; /** * Resets close action to default. Default action is to remove currently selected tab. */ public void resetDefaultCloseAction() { setCloseAction(null); } private boolean _suppressStateChangedEvents = false; public void setSuppressStateChangedEvents(boolean suppress) { _suppressStateChangedEvents = suppress; } public boolean isSuppressStateChangedEvents() { return _suppressStateChangedEvents; } @Override protected void fireStateChanged() { if (_suppressStateChangedEvents) return; if (!isAutoFocusOnTabHideClose()) clearVisComp(); super.fireStateChanged(); } // setSelectedIndex will be called during moving tab. So we use this flag to suppress it. private boolean _suppressSetSelectedIndex = false; public boolean isSuppressSetSelectedIndex() { return _suppressSetSelectedIndex; } public void setSuppressSetSelectedIndex(boolean suppressSetSelectedIndex) { _suppressSetSelectedIndex = suppressSetSelectedIndex; } @Override public void setSelectedIndex(int index) { if (_suppressSetSelectedIndex) return; boolean old = isFocusCycleRoot(); setFocusCycleRoot(true); try { int oldIndex = getSelectedIndex(); if (oldIndex != index) { super.setSelectedIndex(index); firePropertyChange(PROPERTY_SELECTED_INDEX, oldIndex, index); } } finally { setFocusCycleRoot(old); } } /* * This is called by the popup menu in the scrollrect area */ public void popupSelectedIndex(int index) { setSelectedIndex(index); } public void setComponentAt(int index, Component c) { Component oldComponent = getComponentAt(index); if (oldComponent != null) { // JTabbedPane allows a null c, but doesn't really support it. PageLastFocusTracker tracker = (PageLastFocusTracker) _pageLastFocusTrackers.get(oldComponent); _pageLastFocusTrackers.remove(oldComponent); if (tracker != null) { tracker.setHeighestComponent(null); // Clear its listeners } } boolean contains = false; if (_closableSet.contains(oldComponent)) { contains = true; } super.setComponentAt(index, c); if (contains) { _closableSet.add(c); } if (!isAutoFocusOnTabHideClose()) clearVisComp(); } private boolean _autoRequestFocus = true; /** * Checks if the UI should automatically request focus on selected component when doing the layout. This method is * only used internally when the tab is being moved. * * @return true or false. Default is true. */ public boolean isAutoRequestFocus() { return _autoRequestFocus; } public void setAutoRequestFocus(boolean autoRequestFocus) { _autoRequestFocus = autoRequestFocus; } /** * Moves selected tab from current position to the position specified in tabIndex. * * @param tabIndex new index */ public void moveSelectedTabTo(int tabIndex) { int selectedIndex = getSelectedIndex(); if (selectedIndex == tabIndex) { // do nothing return; } if (tabIndex == -1 || selectedIndex == -1) return; if (isTabEditing()) stopTabEditing(); Component selectedComponent = getComponentAt(selectedIndex); boolean old = isAutoRequestFocus(); boolean shouldChangeFocus = false; // we will not let UI to auto request focus so we will have to do it here. // if the selected component has focus, we will request it after the tab is moved. if (selectedComponent != null) { if (JideSwingUtilities.isAncestorOfFocusOwner(selectedComponent) && isAutoFocusOnTabHideClose()) { shouldChangeFocus = true; } } try { _suppressStateChangedEvents = true; setAutoRequestFocus(false); if (selectedIndex - tabIndex == 1 || tabIndex - selectedIndex == 1) { Component c = getComponentAt(tabIndex); String title = getTitleAt(tabIndex); String tooltip = getToolTipTextAt(tabIndex); Icon icon = getIconAt(tabIndex); _suppressSetSelectedIndex = true; boolean closable = true; if (_closableSet != null) { closable = isTabClosableAt(tabIndex); } try { if (tabIndex > selectedIndex) insertTab(title, icon, c, tooltip, selectedIndex); else { insertTab(title, icon, c, tooltip, selectedIndex + 1); } if (!closable) { _closableSet.add(c); } } finally { _suppressSetSelectedIndex = false; } } else { Component c = getComponentAt(selectedIndex); String title = getTitleAt(selectedIndex); String tooltip = getToolTipTextAt(selectedIndex); Icon icon = getIconAt(selectedIndex); _suppressSetSelectedIndex = true; boolean closable = true; if (_closableSet != null) { closable = isTabClosableAt(tabIndex); } try { if (tabIndex > selectedIndex) insertTab(title, icon, c, tooltip, tabIndex + 1); else { insertTab(title, icon, c, tooltip, tabIndex); } if (!closable) { _closableSet.add(c); } } finally { _suppressSetSelectedIndex = false; } } if (!SystemInfo.isJdk15Above()) { // a workaround for Swing bug if (tabIndex == getTabCount() - 2) { setSelectedIndex(getTabCount() - 1); } } setAutoRequestFocus(old); setSelectedIndex(tabIndex); } finally { _suppressStateChangedEvents = false; if (shouldChangeFocus) { if (!requestFocusForVisibleComponent()) { // System.out.println("---tabpane.requestfocus41"); requestFocusInWindow(); } } } } // mtf - review if this is still needed public boolean requestFocusForVisibleComponent() { return false; /* if (true) return false; // System.out.println("---JideTabbedPane.requestFocusForVisibleComponent()"); Component visibleComponent = getSelectedComponent(); Component lastFocused = getLastFocusedComponent(visibleComponent); if (lastFocused != null && lastFocused.requestFocusInWindow()) { return true; } else { // Focus the next component in the focus cycle after the tab. Container nearestRoot = (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor(); if (nearestRoot == null) { return false; } Component comp = nearestRoot.getFocusTraversalPolicy().getComponentAfter(nearestRoot, this); return comp != null && comp.requestFocusInWindow() || JideSwingUtilities.compositeRequestFocus(visibleComponent); } */ } /** * Get the flag that if the trailing component should be hidden while no buttons are visible. *

* Be default, the flag is false. If you want to connect visibility of those two components, please set it to true. * * @return true if the trailing component would be hidden while no buttons are visible. Otherwise false. * @see #isShowTabArea() * @see #isShowTabButtons() * @see #setHideTrailingWhileNoButtons(boolean) */ public boolean isHideTrailingWhileNoButtons() { return _hideTrailingWhileNoButtons; } /** * Set the flag that if the trailing component should be hidden while no buttons are visible. * * @param hideTrailingWhileNoButtons the flag * @see #isHideTrailingWhileNoButtons() */ public void setHideTrailingWhileNoButtons(boolean hideTrailingWhileNoButtons) { _hideTrailingWhileNoButtons = hideTrailingWhileNoButtons; } /** * Gets the flag indicating if the trailing component should be layout before the default buttons. * * @return true if the trailing component should be layout to the left/up. Otherwise false. * @see #setLayoutTrailingComponentBeforeButtons(boolean) */ public boolean isLayoutTrailingComponentBeforeButtons() { return _layoutTrailingComponentBeforeButtons; } /** * Sets the flag indicating if the trailing component should be layout before the default buttons. *

* The default value is false. If you want your trailing component preceding to the default buttons, please set this * flag to true. * * @param layoutTrailingComponentBeforeButtons * the flag */ public void setLayoutTrailingComponentBeforeButtons(boolean layoutTrailingComponentBeforeButtons) { _layoutTrailingComponentBeforeButtons = layoutTrailingComponentBeforeButtons; } /* * Used to allow the tabswitching to be delayed until after drag/reorder opperations are done. */ protected class IgnoreableSingleSelectionModel extends DefaultSingleSelectionModel { private static final long serialVersionUID = -4321082126384337792L; @Override protected void fireStateChanged() { if (!_suppressStateChangedEvents) { super.fireStateChanged(); } } } @SuppressWarnings({"UnusedDeclaration"}) public void processMouseSelection(int tabIndex, MouseEvent e) { } /** * Gets tab height. * * @return height of tab */ public int getTabHeight() { if (getTabPlacement() == TOP || getTabPlacement() == BOTTOM) { return ((JideTabbedPaneUI) getUI()).getTabPanel().getHeight(); } else { return ((JideTabbedPaneUI) getUI()).getTabPanel().getWidth(); } } /** * Returns true if you want right click on unselected tab will select that tab. * * @return true if right click on unselected tab will select that tab */ public boolean isRightClickSelect() { return _rightClickSelect; } /** * Sets if you want right click on unselected tab will select that tab. * * @param rightClickSelect true if right click on unselected tab will select that tab */ public void setRightClickSelect(boolean rightClickSelect) { _rightClickSelect = rightClickSelect; } public int getTabAtLocation(int x, int y) { int tabCount = getTabCount(); int i = getUI().tabForCoordinate(this, x, y); return i < 0 || i >= tabCount ? -1 : i; } /** * If the grip is visible. * * @return true if grip is visible */ public boolean isShowGripper() { return _showGripper; } /** * Sets the visibility of grip. * * @param showGripper true to show grip */ public void setShowGripper(boolean showGripper) { boolean oldShowGripper = _showGripper; if (oldShowGripper != showGripper) { _showGripper = showGripper; firePropertyChange(GRIPPER_PROPERTY, oldShowGripper, _showGripper); } } /** * Checks if the icon will be shown on tab. * * @return true if the icon will be shown on tab. */ public boolean isShowIconsOnTab() { return _showIconsOnTab; } /** * Sets to true if the icon will be shown on tab. The value set to this method will be used only when * isUseDefaultShowIconsOnTab() returns false. * * @param showIconsOnTab true or false. */ public void setShowIconsOnTab(boolean showIconsOnTab) { boolean oldShowIconsOnTab = _showIconsOnTab; if (oldShowIconsOnTab != showIconsOnTab) { _showIconsOnTab = showIconsOnTab; firePropertyChange(SHOW_ICONS_PROPERTY, oldShowIconsOnTab, _showIconsOnTab); } } /** * If the return is true, the value set to setShowIconsOnTab() will be ignored. * * @return if use default value from UIDefaults in L&F. */ public boolean isUseDefaultShowIconsOnTab() { return _useDefaultShowIconsOnTab; } /** * Set if use the default value from UIDefaults. * * @param useDefaultShowIconsOnTab true or false. */ public void setUseDefaultShowIconsOnTab(boolean useDefaultShowIconsOnTab) { boolean oldUseDefaultShowIconsOnTab = _useDefaultShowIconsOnTab; if (oldUseDefaultShowIconsOnTab != useDefaultShowIconsOnTab) { _useDefaultShowIconsOnTab = useDefaultShowIconsOnTab; firePropertyChange(USE_DEFAULT_SHOW_ICONS_PROPERTY, oldUseDefaultShowIconsOnTab, _useDefaultShowIconsOnTab); } } /** * Checks if the close button will be shown on tab. * * @return true if close button will be shown on tab. */ public boolean isShowCloseButtonOnTab() { return _showCloseButtonOnTab; } /** * Sets to true if the close button will be shown on tab. If you ever call this method, we will automatically call * setUseDefaultShowCloseButtonOnTab(false). It will also automatically call setShowCloseButton(true) if the * showCloseButtonOnTab parameter is true. * * @param showCloseButtonOnTab true or false. */ public void setShowCloseButtonOnTab(boolean showCloseButtonOnTab) { boolean oldShowCloseButtonOnTab = _showCloseButtonOnTab; if (oldShowCloseButtonOnTab != showCloseButtonOnTab) { _showCloseButtonOnTab = showCloseButtonOnTab; firePropertyChange(SHOW_CLOSE_BUTTON_ON_TAB_PROPERTY, oldShowCloseButtonOnTab, _showCloseButtonOnTab); if (_showCloseButtonOnTab) { setShowCloseButton(true); } } setUseDefaultShowCloseButtonOnTab(false); } /** * If the return is true, the value set to setShowCloseButtonOnTab() will be ignored. * * @return if use default value from UIDefaults in L&F. */ public boolean isUseDefaultShowCloseButtonOnTab() { return _useDefaultShowCloseButtonOnTab; } /** * Set if use the default value from UIDefaults. * * @param useDefaultShowCloseButtonOnTab true or false. */ public void setUseDefaultShowCloseButtonOnTab(boolean useDefaultShowCloseButtonOnTab) { boolean oldUseDefaultShowCloseButtonOnTab = _useDefaultShowCloseButtonOnTab; if (oldUseDefaultShowCloseButtonOnTab != useDefaultShowCloseButtonOnTab) { _useDefaultShowCloseButtonOnTab = useDefaultShowCloseButtonOnTab; firePropertyChange(USE_DEFAULT_SHOW_CLOSE_BUTTON_ON_TAB_PROPERTY, oldUseDefaultShowCloseButtonOnTab, _useDefaultShowCloseButtonOnTab); } } // below is the code to allow editing the tab title directly transient protected boolean _tabEditingAllowed = false; /** * Sets the value if the tab editing is allowed. Tab editing allows user to edit the tab title directly by double * clicking on the tab. * * @param allowed true or false. */ public void setTabEditingAllowed(boolean allowed) { _tabEditingAllowed = allowed; } /** * Checks if the tab editing is allowed. * * @return true if tab editing is allowed. Otherwise false. */ public boolean isTabEditingAllowed() { return _tabEditingAllowed && getTabLayoutPolicy() == SCROLL_TAB_LAYOUT; } transient protected TabEditingValidator _tabEditValidator; public void setTabEditingValidator(TabEditingValidator tabEditValidator) { _tabEditValidator = tabEditValidator; } public TabEditingValidator getTabEditingValidator() { return _tabEditValidator; } /** * If close button is visible. * * @return true if the close button is visible. */ public boolean isShowCloseButton() { return _showCloseButton; } /** * Sets if the close button is visible. Close button can be either side by side with scroll buttons, or on each tab. * If you call setShowCloseButton(false), it will hide close buttons for both cases. * * @param showCloseButton true or false. */ public void setShowCloseButton(boolean showCloseButton) { boolean oldShowCloseButton = _showCloseButton; if (oldShowCloseButton != showCloseButton) { _showCloseButton = showCloseButton; firePropertyChange(SHOW_CLOSE_BUTTON_PROPERTY, oldShowCloseButton, _showCloseButton); } } /** * If the tab area is visible. * * @return true if the tab area is visible. */ public boolean isShowTabArea() { return _showTabArea; } /** * Sets if the tab area is visible. If not visible, you can programatically call setSelectedIndex to change ta. User * will not be able to do it by clicking on tabs since they are not visible. * * @param showTabArea true or false. */ public void setShowTabArea(boolean showTabArea) { boolean oldShowTabArea = _showTabArea; if (oldShowTabArea != showTabArea) { _showTabArea = showTabArea; firePropertyChange(SHOW_TAB_AREA_PROPERTY, oldShowTabArea, _showTabArea); } } /** * If the tab content is visible. * * @return true if the tab content is visible. */ public boolean isShowTabContent() { return _showTabContent; } /** * Sets if the tab content is visible. * * @param showTabContent true or false. */ public void setShowTabContent(boolean showTabContent) { boolean oldShowTabContent = _showTabContent; if (oldShowTabContent != showTabContent) { _showTabContent = showTabContent; firePropertyChange(SHOW_TAB_CONTENT_PROPERTY, oldShowTabContent, _showTabContent); } } /** * Gets the string converter that converts the tab title to the display title. * * @return the converter that converts the tab title to the display title. */ public StringConverter getStringConverter() { return _stringConverter; } /** * Sets the string converter. * * @param stringConverter the StringConverter. * @see #getStringConverter() */ public void setStringConverter(StringConverter stringConverter) { _stringConverter = stringConverter; } /** * Gets the display title. Display title is result of using string converter that converts from the title to a * display title. There is no setter for display title. You control the value by using a different string * converter. * * @param index the index to display * @return the display title. */ public String getDisplayTitleAt(int index) { if (_stringConverter != null) { return _stringConverter.convert(super.getTitleAt(index)); } else { return super.getTitleAt(index); } } /** * If the active tab is in bold. * * @return if the active tab is in bold. */ public boolean isBoldActiveTab() { return _boldActiveTab; } /** * Sets if the active tab is in bold. * * @param boldActiveTab the flag */ public void setBoldActiveTab(boolean boldActiveTab) { boolean old = _boldActiveTab; if (old != boldActiveTab) { _boldActiveTab = boldActiveTab; firePropertyChange(BOLDACTIVETAB_PROPERTY, old, _boldActiveTab); } } @Override public void removeTabAt(int index) { int tabCount = getTabCount(); int selected = getSelectedIndex(); boolean enforce = false; if (selected == index && selected < tabCount - 1) { // since JDK5 fixed this, we only need to enforce the event when it is not JDK5 and above. // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6368047 enforce = !SystemInfo.isJdk15Above(); } Component c = getComponentAt(index); boolean contains = false; if (_closableSet.contains(c)) { contains = true; } if (!isAutoFocusOnTabHideClose()) clearVisComp(); super.removeTabAt(index); if (contains) { _closableSet.remove(c); } if (c != null) { // JTabbedPane allows a null c, but doesn't really support it. PageLastFocusTracker tracker = (PageLastFocusTracker) _pageLastFocusTrackers.get(c); _pageLastFocusTrackers.remove(c); if (tracker != null) { tracker.setHeighestComponent(null); // Clear its listeners } } // We need to fire events if (enforce) { try { fireStateChanged(); } catch (Throwable th) { th.printStackTrace(); } } updateUI(); // force calling updateUI so that the tab buttons will be updated if (getUI() instanceof BasicJideTabbedPaneUI) { ((BasicJideTabbedPaneUI) getUI()).ensureActiveTabIsVisible(true); if (isAutoFocusOnTabHideClose()) { ((BasicJideTabbedPaneUI) getUI()).requestFocusForVisibleComponent(); } } } /** * Checks if the tab at tabIndex should show the close button. This is only a valid if showCloseButtonOnTab * attribute is true. *

* By default, this method always return true. Subclass can override this method to return a different value. * * @param tabIndex the tab index * @return the flag. * @throws IndexOutOfBoundsException if index is out of range (index < 0 || index >= tab count) */ public boolean isTabClosableAt(int tabIndex) { return !_closableSet.contains(getComponentAt(tabIndex)); } /** * Checks if the tab at tabIndex should show the close button. This is only a valid if showCloseButtonOnTab * attribute is true. *

* By default, this method always return true. Subclass can override this method to return a different value. *

* Please note, this attribute has effect only when {@link #isShowCloseButtonOnTab()} return true. * * @param tabIndex the tab index * @param closable the flag indicating if the tab is closable * @throws IndexOutOfBoundsException if index is out of range (index < 0 || index >= tab count) */ public void setTabClosableAt(int tabIndex, boolean closable) { if (closable) { _closableSet.remove(getComponentAt(tabIndex)); } else { _closableSet.add(getComponentAt(tabIndex)); } firePropertyChange(TAB_CLOSABLE_PROPERTY, !closable, closable); } protected Hashtable getPageLastFocusTrackers() { return _pageLastFocusTrackers; } /** * Gets the last focused component of a particular page. * * @param pageComponent the page component * @return the last focused component of a particular page. */ public Component getLastFocusedComponent(Component pageComponent) { if (pageComponent == null) { return null; } // System.out.println("---JideTabbedPane.getLastFocusedComponent()" + pageComponent); PageLastFocusTracker tracker = (PageLastFocusTracker) ( getPageLastFocusTrackers().get(pageComponent)); // System.out.println("---JideTabbedPane.getLastFocusedComponent()" + componentReturn); // if (false) { // Component compTest = new JPanel() { // public void requestFocus() { //// System.out.println("---.requestFocus()22"); // componentReturn.requestFocus(); // } // // public boolean isRequestFocusEnabled() { //// System.out.println("---.isRequestFocusEnabled()"); // return true; // } // // public Container getParent() { //// System.out.println("---.getParent()"); // return (Container) componentReturn; // } // }; // if (componentReturn != null) // ((Container) componentReturn).add(compTest); // return compTest; // } return ((tracker != null) ? tracker.getLastFocusedComponent() : null); } protected void clearVisComp() { // this is done so that the super removetab and fireselection do not attempt to manage focus // A very dirty hack to access a private variable is jtabpane. Note - this only works on 1.6 try { java.lang.reflect.Field field = JTabbedPane.class.getDeclaredField("visComp"); // set accessible true field.setAccessible(true); field.set(this, null); // superVisComp = (Component) field.get(this); } catch (Exception e) { // null } } /** * Overridden to add a PageLastFocusTracker to each page, used to update the page's last focused * component. */ @Override public void insertTab(String title, Icon icon, Component component, String tip, int index) { // set the component to visible false initially because the layout manager will set it to visible when // appropriate. This also limits the flicker from mixing lightweight/heavyweight components. if (component == getTabLeadingComponent() || component == getTabTrailingComponent()) { return; } if (component != null && !component.isVisible()) component.setVisible(false); super.insertTab(title, icon, component, tip, index); if (component != null) { // JTabbedPane allows a null component, but doesn't really support it. _pageLastFocusTrackers.put(component, new PageLastFocusTracker(component)); } // fireStateChanged(); } protected class PageLastFocusTracker extends JideFocusTracker { // keep track of last focused component private Component _lastFocusedComponent; private FocusListener _lastFocusedListener; protected PageLastFocusTracker(Component pageComp) { this.setHeighestComponent(pageComp); } protected Component getLastFocusedComponent() { return _lastFocusedComponent; } @Override public void setHeighestComponent(Component compHeighest) { if (compHeighest == null) { if (_lastFocusedListener != null) { this.removeFocusListener(_lastFocusedListener); _lastFocusedListener = null; } } else { if (_lastFocusedListener == null) { _lastFocusedListener = new FocusAdapter() { @Override public void focusGained(FocusEvent e) { _lastFocusedComponent = e.getComponent(); } }; this.addFocusListener(_lastFocusedListener); } } super.setHeighestComponent(compHeighest); } } /** * Gets the font for selected tab. * * @return the font for selected tab. */ public Font getSelectedTabFont() { return _selectedTabFont; } /** * Sets the font for selected tab. * * @param selectedTabFont new font for selected tab. */ public void setSelectedTabFont(Font selectedTabFont) { _selectedTabFont = selectedTabFont; } public int getColorTheme() { if (_colorTheme == COLOR_THEME_DEFAULT) { return getDefaultColorTheme(); } else { return _colorTheme; } } public int getDefaultColorTheme() { return UIDefaultsLookup.getInt("JideTabbedPane.defaultTabColorTheme"); } public void setColorTheme(int colorTheme) { int old = _colorTheme; if (old != colorTheme) { _colorTheme = colorTheme; firePropertyChange(PROPERTY_COLOR_THEME, old, colorTheme); } } public int getTabResizeMode() { if (_tabResizeMode == RESIZE_MODE_DEFAULT) { return getDefaultTabResizeMode(); } else { return _tabResizeMode; } } /** * Sets the tab resize mode. There are five resize modes. - {@link #RESIZE_MODE_DEFAULT}, {@link #RESIZE_MODE_NONE}, * {@link #RESIZE_MODE_FIT}, {@link #RESIZE_MODE_FIXED} and {@link #RESIZE_MODE_COMPRESSED}. * * @param resizeMode the new resize mode. */ public void setTabResizeMode(int resizeMode) { int old = _tabResizeMode; if (old != resizeMode) { _tabResizeMode = resizeMode; firePropertyChange(PROPERTY_TAB_RESIZE_MODE, old, resizeMode); } } public int getDefaultTabResizeMode() { return UIDefaultsLookup.getInt("JideTabbedPane.defaultResizeMode"); } public int getTabShape() { if (_tabShape == SHAPE_DEFAULT) { return getDefaultTabStyle(); } else { return _tabShape; } } public int getDefaultTabStyle() { return UIDefaultsLookup.getInt("JideTabbedPane.defaultTabShape"); } public void setTabShape(int tabShape) { int old = _tabShape; if (old != tabShape) { _tabShape = tabShape; firePropertyChange(PROPERTY_TAB_SHAPE, old, _tabShape); } } /** * Sets the tab leading component. The tab leading component will appear before the tabs in the tab area. Please * note, you must implement UIResource for the component you want to use as tab leading component. * * @param component the tab leading component * @throws IllegalArgumentException if the component doesn't implement UIResource. */ public void setTabLeadingComponent(Component component) { // if (component != null && !(component instanceof UIResource)) { // throw new IllegalArgumentException("TabLeadingComponent must implement javax.swing.plaf.UIResource interface."); // } Component old = _tabLeadingComponent; _tabLeadingComponent = component; firePropertyChange(PROPERTY_TAB_LEADING_COMPONENT, old, component); } public Component getTabLeadingComponent() { return _tabLeadingComponent; } /** * Sets the tab trailing component. The tab trailing component will appear after the tabs in the tab area. Please * note, you must implement UIResource for the component you want to use as tab trailing component. * * @param component the tab trailing component * @throws IllegalArgumentException if the component doesn't implement UIResource. */ public void setTabTrailingComponent(Component component) { // if (component != null && !(component instanceof UIResource)) { // throw new IllegalArgumentException("TabLeadingComponent must implement javax.swing.plaf.UIResource interface."); // } Component old = _tabTrailingComponent; _tabTrailingComponent = component; firePropertyChange(PROPERTY_TAB_TRAILING_COMPONENT, old, component); } @Override public Component add(Component component) { if (!(component instanceof UIResource) && component != getTabTrailingComponent() && component != getTabLeadingComponent()) { addTab(component.getName(), component); } else { addImpl(component, null, -1); } return component; } public Component getTabTrailingComponent() { return _tabTrailingComponent; } public boolean isShowCloseButtonOnSelectedTab() { return _showCloseButtonOnSelectedTab; } /** * Shows the close button on the selected tab only. You also need to setShowCloseButtonOnTab(true) and * setShowCloseButton(true) if you want to setShowCloseButtonOnSelectedTab(true). * * @param i the flag indicating if close button should be shown in the selected tab */ public void setShowCloseButtonOnSelectedTab(boolean i) { _showCloseButtonOnSelectedTab = i; } /** * Gets the flag indicating if the close button should only be displayed when the mouse is over the tab. * * @return true if the close button should only be displayed when the mouse is over the tab. Otherwise false. * @see #setShowCloseButtonOnMouseOver(boolean) * @since 3.3.3 */ public boolean isShowCloseButtonOnMouseOver() { return _showCloseButtonOnMouseOver; } /** * Sets the flag indicating if the close button should only be displayed when the mouse is over the tab. *

* The default value of the flag is false to keep default behavior not changed. * * @param showCloseButtonOnMouseOverOnly the flag * @since 3.3.3 */ public void setShowCloseButtonOnMouseOver(boolean showCloseButtonOnMouseOverOnly) { if (_showCloseButtonOnMouseOver != showCloseButtonOnMouseOverOnly) { boolean old = _showCloseButtonOnMouseOver; _showCloseButtonOnMouseOver = showCloseButtonOnMouseOverOnly; firePropertyChange(PROPERTY_SHOW_CLOSE_BUTTON_ON_MOUSE_OVER, old, _showCloseButtonOnMouseOver); } } private ColorProvider _tabColorProvider; /** * An interface to provide colors for tab background and foreground. */ public static interface ColorProvider { /** * Gets the tab background for the tab at the specified index. * * @param tabIndex the index of the tab * @return the tab background for the tab at the specified index. */ Color getBackgroundAt(int tabIndex); /** * Gets the tab foreground for the tab at the specified index. * * @param tabIndex the index of the tab * @return the tab foreground for the tab at the specified index. */ Color getForegroundAt(int tabIndex); /** * Gets the gradient ratio. We will use this ratio to provide another color in order to paint gradient. * * @param tabIndex the index of the tab * @return the gradient ratio. The value should be between 0 and 1. 0 will produce the darkest and color and 1 * will produce the lightest color. 0.5 will provide the same color. */ float getGradientRatio(int tabIndex); } /** * A ColorProvider that can supports gradient tab background. The ColorProvider can also do gradient but the other * color has to be be a lighter or darker version of the color of getBackgroundAt. GradientColorProvider allows you * to specify an independent color as the start color. */ public static interface GradientColorProvider extends ColorProvider { /** * Gets the tab background at the top (or other direction depending on the tab placement) of the tab. The * JideTabbedPaneUI will paint a gradient using this color and the color of getBackgroundAt. * * @param tabIndex the index of the tab * @return the top background color. */ Color getTopBackgroundAt(int tabIndex); } private static Color[] ONENOTE_COLORS = { new Color(138, 168, 228), // blue new Color(238, 149, 151), // pink new Color(180, 158, 222), // purple new Color(145, 186, 174), // cyan new Color(246, 176, 120), // gold new Color(255, 216, 105), // yellow new Color(183, 201, 151) // green }; public static ColorProvider ONENOTE_COLOR_PROVIDER = new OneNoteColorProvider(); private static class OneNoteColorProvider implements ColorProvider { public Color getBackgroundAt(int index) { return ONENOTE_COLORS[index % ONENOTE_COLORS.length]; } public Color getForegroundAt(int index) { return Color.BLACK; } public float getGradientRatio(int tabIndex) { return 0.86f; } } /** * Gets the tab color provider. * * @return tab color provider. */ public ColorProvider getTabColorProvider() { return _tabColorProvider; } /** * Sets the tab color provider.It allows you to set the background color of each tab. The reason to use this way * instead of {@link #setBackgroundAt(int, java.awt.Color)} method is because this way queries the color. So it can * support unlimited number of tabs. When you don't know exactly how many tabs it will be, this way can still handle * it very well. There is {@link #ONENOTE_COLOR_PROVIDER} which provides the tab color as you see in Microsoft * OneNote 2003. You can also define your own ColorProvider to fit your application color theme. * * @param tabColorProvider the tab color provider */ public void setTabColorProvider(ColorProvider tabColorProvider) { ColorProvider old = _tabColorProvider; if (old != tabColorProvider) { _tabColorProvider = tabColorProvider; firePropertyChange(PROPERTY_TAB_COLOR_PROVIDER, old, tabColorProvider); } } /** * Starts tab editing. This works only when {@link #setTabEditingAllowed(boolean)} is set to true. * * @param tabIndex the index of the tab */ public void editTabAt(int tabIndex) { boolean started = ((JideTabbedPaneUI) getUI()).editTabAt(tabIndex); if (started) { fireTabEditing(TabEditingEvent.TAB_EDITING_STARTED, tabIndex, getTitleAt(tabIndex), null); } } /** * Checks if tab is in editing mode. * * @return true if editing. */ public boolean isTabEditing() { return ((JideTabbedPaneUI) getUI()).isTabEditing(); } public void stopTabEditing() { int tabIndex = getEditingTabIndex(); if (tabIndex != -1 && tabIndex < getTabCount()) { String oldTitle = getTitleAt(tabIndex); ((JideTabbedPaneUI) getUI()).stopTabEditing(); String newTitle = getTitleAt(tabIndex); fireTabEditing(TabEditingEvent.TAB_EDITING_STOPPED, tabIndex, oldTitle, newTitle); } } public void cancelTabEditing() { int tabIndex = getEditingTabIndex(); if (tabIndex != -1) { ((JideTabbedPaneUI) getUI()).cancelTabEditing(); fireTabEditing(TabEditingEvent.TAB_EDITING_CANCELLED, tabIndex, getTitleAt(tabIndex), getTitleAt(tabIndex)); } } public int getEditingTabIndex() { return ((JideTabbedPaneUI) getUI()).getEditingTabIndex(); } protected PropertyChangeListener _focusChangeListener; protected PropertyChangeListener createFocusChangeListener() { return new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { final boolean hadFocus = JideTabbedPane.this.isAncestorOf((Component) evt.getOldValue()) || JideTabbedPane.this == evt.getOldValue(); boolean hasFocus = JideTabbedPane.this == evt.getNewValue() || JideTabbedPane.this.hasFocusComponent(); if (hasFocus != hadFocus) { repaintTabAreaAndContentBorder(); } } }; } /** * Repaints the tab area and the content border if any. This is mainly for the focus border in JideTabbedPane * Office2003 and Eclipse3x style. */ public void repaintTabAreaAndContentBorder() { int delay = 200; ((JideTabbedPaneUI) getUI()).getTabPanel().repaint(delay); Insets contentinsets = getContentBorderInsets(); if (contentinsets == null) { LookAndFeelFactory.installJideExtension(); contentinsets = getContentBorderInsets(); } if (contentinsets != null && (contentinsets.top != 0 || contentinsets.bottom != 0 || contentinsets.left != 0 || contentinsets.right != 0)) { Insets insets = new Insets(0, 0, 0, 0); BasicJideTabbedPaneUI.rotateInsets(contentinsets, insets, tabPlacement); switch (getTabPlacement()) { case TOP: insets.top += getTabHeight(); break; case BOTTOM: insets.bottom += getTabHeight(); break; case LEFT: insets.left += getTabHeight(); break; case RIGHT: insets.right += getTabHeight(); break; } if (insets.top != 0) { repaintContentBorder(0, 0, getWidth(), insets.top); } if (insets.left != 0) { repaintContentBorder(0, 0, insets.left, getHeight()); } if (insets.right != 0) { repaintContentBorder(getWidth() - insets.right, 0, insets.right, getHeight()); } if (insets.bottom != 0) { repaintContentBorder(0, getHeight() - insets.bottom, getWidth(), insets.bottom); } } } /** * Calls repaint on the specified rectangular area. * * @param x the x coordinate * @param y the y coordinate * @param width the width * @param height the height */ protected void repaintContentBorder(int x, int y, int width, int height) { repaint(x, y, width, height); } @Override public void addNotify() { super.addNotify(); if (_focusChangeListener == null) { _focusChangeListener = createFocusChangeListener(); KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("focusOwner", _focusChangeListener); } } @Override public void removeNotify() { super.removeNotify(); if (_focusChangeListener != null) { KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener("focusOwner", _focusChangeListener); _focusChangeListener = null; } } /** * Gets the tab list cell renderer. This renderer is used to render the list in the popup when tab list button is * pressed. * * @return the tab list cell renderer. * @see #setTabListCellRenderer(javax.swing.ListCellRenderer) */ public ListCellRenderer getTabListCellRenderer() { if (_tabListCellRenderer != null) { return _tabListCellRenderer; } else { return new TabListCellRenderer(); } } /** * The default tab list cell renderer used to renderer the list in the popup when tab list button is pressed. */ public static class TabListCellRenderer extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (value instanceof JideTabbedPane) { JideTabbedPane tabbedPane = (JideTabbedPane) value; String title = tabbedPane.getTitleAt(index); String tooltip = tabbedPane.getToolTipTextAt(index); Icon icon = tabbedPane.getIconForTab(index); JLabel label = (JLabel) super.getListCellRendererComponent(list, title, index, isSelected, cellHasFocus); label.setToolTipText(tooltip); Font fnt; if (tabbedPane.getSelectedIndex() == index && tabbedPane.getSelectedTabFont() != null) { fnt = tabbedPane.getSelectedTabFont(); } else { fnt = tabbedPane.getFont(); } if (tabbedPane.getSelectedIndex() == index && tabbedPane.isBoldActiveTab() && fnt.getStyle() != Font.BOLD) { fnt = fnt.deriveFont(Font.BOLD); } label.setFont(fnt); label.setIcon(icon); label.setEnabled(tabbedPane.isEnabledAt(index)); return label; } else { return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } } } /** * Sets the tab list cell renderer. This renderer is used to render the list in the popup when tab list button is * pressed. In this list cell renderer, the value will always be the JideTabbedPane. The index will tell you which * tab it is. See below for the default cell renderer we used. *

     * public static class TabListCellRenderer extends DefaultListCellRenderer {
     *     public Component getListCellRendererComponent(JList list, Object value, int index,
     * boolean isSelected, boolean cellHasFocus) {
     *         if (value instanceof JideTabbedPane) { // will always be true
     *             JideTabbedPane tabbedPane = (JideTabbedPane) value;
     *             String title = tabbedPane.getTitleAt(index);
     *             Icon icon = tabbedPane.getIconAt(index);
     *             JLabel label = (JLabel) super.getListCellRendererComponent(list, title, index,
     * isSelected, cellHasFocus);
     *             label.setIcon(icon);
     *             return label;
     *         }
     *         else {
     *             return super.getListCellRendererComponent(list, value, index, isSelected,
     * cellHasFocus);
     *         }
     *     }
     * }
     * 
* You can create your own cell renderer either extending {@link TabListCellRenderer} or starting from scratch. * * @param tabListCellRenderer the cell renderer */ public void setTabListCellRenderer(ListCellRenderer tabListCellRenderer) { _tabListCellRenderer = tabListCellRenderer; } /** * Checks if the JideTabbedPane has the focus component. If true, in some styles such as Office2003 style, we will * paint a background on the insets to indicate the tabbed pane has focus. * * @return true if the JideTabbedPane has the focus component. Otherwise false. */ public boolean hasFocusComponent() { return JideSwingUtilities.isAncestorOfFocusOwner(this); } public Insets getContentBorderInsets() { return _contentBorderInsets; } /** * Sets the content border insets. It's the inserts around the JideTabbedPane's content. The direction of the insets * is when the tabs are on top. We will rotate it automatically when the tabs are on other directions. * * @param contentBorderInsets the content border insets */ public void setContentBorderInsets(Insets contentBorderInsets) { Insets old = _contentBorderInsets; _contentBorderInsets = contentBorderInsets; firePropertyChange(PROPERTY_CONTENT_BORDER_INSETS, old, _contentBorderInsets); } public Insets getTabAreaInsets() { return _tabAreaInsets; } /** * Sets the tab area insets. It's the inserts around the tabs. The direction of the insets is when the tabs are on * top. We will rotate it automatically when the tabs are on other directions. * * @param tabAreaInsets the content border insets */ public void setTabAreaInsets(Insets tabAreaInsets) { Insets old = _tabAreaInsets; _tabAreaInsets = tabAreaInsets; firePropertyChange(PROPERTY_TAB_AREA_INSETS, old, _tabAreaInsets); } public Insets getTabInsets() { return _tabInsets; } /** * Sets the tab insets. It's the inserts around the JideTabbedPane's tab. The direction of the insets is when the * tabs are on top. We will rotate it automatically when the tabs are on other directions. * * @param tabInsets the content border insets */ public void setTabInsets(Insets tabInsets) { Insets old = _tabInsets; _tabInsets = tabInsets; firePropertyChange(PROPERTY_TAB_INSETS, old, _tabInsets); } /** * Checks the dragOverDisabled property. By default it is false. * * @return true or false. * @see #setDragOverDisabled(boolean) */ public boolean isDragOverDisabled() { return _dragOverDisabled; } /** * Sets the dragOverDisabled property. Default is false. It means when you drag something over an unselected tab, * the tab will be selected automatically. You may want to set it to true if you want to add your own drop listener * to the tabs. * * @param dragOverDisabled the flag indicating if drag over is disabled */ public void setDragOverDisabled(boolean dragOverDisabled) { boolean old = _dragOverDisabled; if (old != dragOverDisabled) { _dragOverDisabled = dragOverDisabled; firePropertyChange(PROPERTY_DRAG_OVER_DISABLED, old, dragOverDisabled); } } /** * Scroll the selected tab visible in case the tab is outside of the viewport. * * @param scrollLeft true to scroll the first tab visible first then scroll left to make the selected tab visible. * This will get a more consistent result. If false, it will simple scroll the selected tab * visible. Sometimes the tab will appear as the first visible tab or the last visible tab * depending on the previous viewport position. */ public void scrollSelectedTabToVisible(boolean scrollLeft) { ((JideTabbedPaneUI) getUI()).ensureActiveTabIsVisible(scrollLeft); } /** * Adds a TabEditingListener to this tabbedpane. * * @param l the TabEditingListener to add * @see #fireTabEditing * @see #removeTabEditingListener(TabEditingListener) * @see #getTabEditingListeners() */ public void addTabEditingListener(TabEditingListener l) { listenerList.add(TabEditingListener.class, l); } /** * Removes a TabEditingListener from this tabbedpane. * * @param l the TabEditingListener to remove * @see #fireTabEditing * @see #addTabEditingListener */ public void removeTabEditingListener(TabEditingListener l) { listenerList.remove(TabEditingListener.class, l); } /** * Returns an array of all the TabEditingListeners added to this JTabbedPane with * addTabEditingListener. * * @return all of the TabEditingListeners added or an empty array if no listeners have been added */ public TabEditingListener[] getTabEditingListeners() { return listenerList.getListeners(TabEditingListener.class); } protected void fireTabEditing(int id, int index, String oldTitle, String newTitle) { if (LOGGER_EVENT.isLoggable(Level.FINE)) { switch (id) { case TabEditingEvent.TAB_EDITING_STARTED: LOGGER_EVENT.fine("TabEditing Started at tab \"" + index + "\"; the current title is " + oldTitle); break; case TabEditingEvent.TAB_EDITING_STOPPED: LOGGER_EVENT.fine("TabEditing Stopped at tab \"" + index + "\"; the old title is " + oldTitle + "; the new title is " + newTitle); break; case TabEditingEvent.TAB_EDITING_CANCELLED: LOGGER_EVENT.fine("TabEditing Cancelled at tab \"" + index + "\"; the current title remains " + oldTitle); break; } } Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == TabEditingListener.class) { TabEditingEvent tabEditingEvent = new TabEditingEvent(this, id, index, oldTitle, newTitle); if (id == TabEditingEvent.TAB_EDITING_STARTED) { ((TabEditingListener) listeners[i + 1]).editingStarted(tabEditingEvent); } else if (id == TabEditingEvent.TAB_EDITING_CANCELLED) { ((TabEditingListener) listeners[i + 1]).editingCanceled(tabEditingEvent); } else if (id == TabEditingEvent.TAB_EDITING_STOPPED) { ((TabEditingListener) listeners[i + 1]).editingStopped(tabEditingEvent); } } } } /** * Gets the icon for the tab after looking at the UIDefault "JideTabbedPane.showIconOnTab" and {@link * #isShowIconsOnTab()}. Note that getIconAt method will always return the tab even though the icon is not displayed * because the two flags above. * * @param tabIndex the tab index. * @return the icon for the tab at the specified index. */ public Icon getIconForTab(int tabIndex) { boolean _showIconOnTab = UIDefaultsLookup.getBoolean("JideTabbedPane.showIconOnTab"); if (isUseDefaultShowIconsOnTab()) { if (_showIconOnTab) { return (!isEnabled() || !isEnabledAt(tabIndex)) ? getDisabledIconAt(tabIndex) : getIconAt(tabIndex); } else { return null; } } else if (isShowIconsOnTab()) { return (!isEnabled() || !isEnabledAt(tabIndex)) ? getDisabledIconAt(tabIndex) : getIconAt(tabIndex); } else { return null; } } /** * Checks if the selected tab will be changed on mouse wheel event. * * @return true or false. */ public boolean isScrollSelectedTabOnWheel() { return _scrollSelectedTabOnWheel; } /** * If true, the selected tab will be changed on mouse wheel. It is false by default. * * @param scrollSelectedTabOnWheel the flag */ public void setScrollSelectedTabOnWheel(boolean scrollSelectedTabOnWheel) { boolean oldValue = isScrollSelectedTabOnWheel(); if (oldValue != scrollSelectedTabOnWheel) { _scrollSelectedTabOnWheel = scrollSelectedTabOnWheel; firePropertyChange(SCROLL_TAB_ON_WHEEL_PROPERTY, oldValue, _scrollSelectedTabOnWheel); } } /** * Get the flag if clicking middle mouse button can close the tab. It is false by default. * * @return the flag. */ public boolean isCloseTabOnMouseMiddleButton() { return _closeTabOnMouseMiddleButton; } /** * Set the flag if clicking middle mouse button can close the tab. It is false by default. * * @param closeTabOnMouseMiddleButton the flag */ public void setCloseTabOnMouseMiddleButton(boolean closeTabOnMouseMiddleButton) { this._closeTabOnMouseMiddleButton = closeTabOnMouseMiddleButton; } /** * Returns the alignment of the tabs for this tabbed pane. * * @return the alignment of the tabs for this tabbed pane. * @see #setTabAlignment(int) */ public int getTabAlignment() { return _tabAlignment; } /** * Sets the tab alignment for the tabs of a tabbed pane. Currently it only supports top and bottom tab placement. * Possible values are:
  • JideTabbedPane.LEADING
  • JideTabbedPane.CENTER
The * default value, if not set, is JideTabbedPane.LEADING. * * @param tabAlignment the alignment for the tabs relative to the content * @throws IllegalArgumentException if tab alignment value isn't one of the above valid values */ public void setTabAlignment(int tabAlignment) { if (tabAlignment != LEADING && tabAlignment != CENTER) { throw new IllegalArgumentException("illegal tab alignment: must be LEADING or CENTER"); } if (_tabAlignment != tabAlignment) { int oldValue = _tabAlignment; _tabAlignment = tabAlignment; firePropertyChange("tabAlignment", oldValue, tabAlignment); revalidate(); repaint(); } } /** * Gets the resource string used in JideTabbedPane. Subclass can override it to provide their own strings. * * @param key the resource key * @return the localized string. */ public String getResourceString(String key) { return com.jidesoft.plaf.basic.Resource.getResourceBundle(getLocale()).getString(key); } /** * Creates tab list popup. * * @return the tab list popup instance. * @since 3.2.2 */ protected JidePopup createTabListPopup() { return new JidePopup(); } /** * Checks if the tab list popup is visible. * * @return true if the tab list popup is visible. Otherwise false. * @since 3.2.2 */ public boolean isTabListPopupVisible() { return _tabListPopup != null && _tabListPopup.isPopupVisible(); } /** * Hides the tab list popup if it's visible. * * @since 3.2.2 */ public void hideTabListPopup() { if (_tabListPopup != null) { if (_tabListPopup.isPopupVisible()) { _tabListPopup.hidePopupImmediately(); } _tabListPopup = null; } } /** * Shows the tab list popup by clicking on the list button. * * @param listButton the list button being clicked. * @since 3.2.2 */ public void showTabListPopup(JButton listButton) { JPanel panel = new JPanel(new BorderLayout()); panel.setBackground(UIDefaultsLookup.getColor("JideTabbedPane.tabListBackground")); panel.setOpaque(true); panel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); JList list = createTabList(panel.getInsets()); JScrollPane scroller = new JScrollPane(list); scroller.setBorder(BorderFactory.createEmptyBorder()); scroller.getViewport().setOpaque(false); scroller.setOpaque(false); panel.add(scroller); hideTabListPopup(); _tabListPopup = createTabListPopup(); _tabListPopup.setComponentOrientation(getComponentOrientation()); _tabListPopup.setPopupBorder(BorderFactory.createLineBorder(UIDefaultsLookup.getColor("JideTabbedPane.darkShadow"))); _tabListPopup.add(panel); _tabListPopup.addExcludedComponent(listButton); _tabListPopup.setDefaultFocusComponent(list); _tabListPopup.setOwner(this); _tabListPopup.removeExcludedComponent(this); Point point = calculateTabListPopupPosition(listButton); _tabListPopup.showPopup(point.x, point.y); } /** * Calculates the position where the tab list popup is to be displayed based on the list button being clicked. * * @param listButton the list button being clicked. * @return the point. * @since 3.2.2 */ protected Point calculateTabListPopupPosition(JButton listButton) { Dimension size = _tabListPopup.getPreferredSize(); Rectangle bounds = listButton.getBounds(); Point p = listButton.getLocationOnScreen(); bounds.x = p.x; bounds.y = p.y; int x; int y; switch (getTabPlacement()) { case TOP: default: if (getComponentOrientation().isLeftToRight()) { x = bounds.x + bounds.width - size.width; } else { x = bounds.x; } y = bounds.y + bounds.height + 2; break; case BOTTOM: if (getComponentOrientation().isLeftToRight()) { x = bounds.x + bounds.width - size.width; } else { x = bounds.x; } y = bounds.y - size.height - 2; break; case LEFT: x = bounds.x + bounds.width + 2; y = bounds.y + bounds.height - size.height; break; case RIGHT: x = bounds.x - size.width - 2; y = bounds.y + bounds.height - size.height; break; } Rectangle screenBounds = PortingUtils.getScreenBounds(this, true); int right = x + size.width + 3 - screenBounds.x; int bottom = y + size.height + 3 - screenBounds.y; if (right > screenBounds.x + screenBounds.width) { x -= right - screenBounds.x - screenBounds.width; // move left so that the whole popup can fit in } if (x < screenBounds.x) { x = screenBounds.x; // move right so that the whole popup can fit in } if (bottom > screenBounds.height) { y -= bottom - screenBounds.height; } if (y < screenBounds.y) { y = screenBounds.y; } return new Point(x, y); } /** * Creates the tab list. * * @param insets the insets of its parent container which helps determine the visible row count of the list. * @return the created list instance. * @since 3.2.2 */ protected JList createTabList(Insets insets) { final JList list = new JList() { // override this method to disallow deselect by ctrl-click @Override public void removeSelectionInterval(int index0, int index1) { super.removeSelectionInterval(index0, index1); if (getSelectedIndex() == -1) { setSelectedIndex(index0); } } @Override public Dimension getPreferredScrollableViewportSize() { Dimension preferredScrollableViewportSize = super.getPreferredScrollableViewportSize(); if (preferredScrollableViewportSize.width < 150) { preferredScrollableViewportSize.width = 150; } int screenWidth = PortingUtils.getScreenSize(this).width; if (preferredScrollableViewportSize.width >= screenWidth) { preferredScrollableViewportSize.width = screenWidth; } return preferredScrollableViewportSize; } @Override public Dimension getPreferredSize() { Dimension preferredSize = super.getPreferredSize(); int screenWidth = PortingUtils.getScreenSize(this).width; if (preferredSize.width >= screenWidth) { preferredSize.width = screenWidth; } return preferredSize; } }; DefaultListModel listModel = new DefaultListModel(); // drop down menu items int selectedIndex = getSelectedIndex(); int totalCount = getTabCount(); for (int i = 0; i < totalCount; i++) { listModel.addElement(this); } list.setCellRenderer(getTabListCellRenderer()); list.setModel(listModel); list.setSelectedIndex(selectedIndex); list.addKeyListener(new KeyListener() { public void keyTyped(KeyEvent e) { } public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { componentSelected(list); } } public void keyReleased(KeyEvent e) { } }); list.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { componentSelected(list); } }); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); int max = (PortingUtils.getLocalScreenSize(this).height - insets.top - insets.bottom) / list.getCellBounds(0, 0).height; if (listModel.getSize() > max) { list.setVisibleRowCount(max); } else { list.setVisibleRowCount(listModel.getSize()); } new Sticky(list); list.setBackground(UIDefaultsLookup.getColor("JideTabbedPane.tabListBackground")); return list; } private void componentSelected(JList list) { int tabIndex = list.getSelectedIndex(); if (tabIndex != -1 && isEnabledAt(tabIndex)) { if (tabIndex == getSelectedIndex() && JideSwingUtilities.isAncestorOfFocusOwner(this)) { if (isAutoFocusOnTabHideClose() && isRequestFocusEnabled()) { Runnable runnable = new Runnable() { public void run() { requestFocus(); } }; SwingUtilities.invokeLater(runnable); } } else { setSelectedIndex(tabIndex); final Component comp = getComponentAt(tabIndex); if (isAutoFocusOnTabHideClose() && !comp.isVisible() && SystemInfo.isJdk15Above() && !SystemInfo.isJdk6Above()) { comp.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent e) { // remove the listener comp.removeComponentListener(this); final Component lastFocused = getLastFocusedComponent(comp); Runnable runnable = new Runnable() { public void run() { if (lastFocused != null) { lastFocused.requestFocus(); } else if (isRequestFocusEnabled()) { requestFocus(); } } }; SwingUtilities.invokeLater(runnable); } }); } else { final Component lastFocused = getLastFocusedComponent(comp); if (lastFocused != null) { Runnable runnable = new Runnable() { public void run() { lastFocused.requestFocus(); } }; SwingUtilities.invokeLater(runnable); } else { Container container; if (comp instanceof Container) { container = (Container) comp; } else { container = comp.getFocusCycleRootAncestor(); } FocusTraversalPolicy traversalPolicy = container.getFocusTraversalPolicy(); Component focusComponent; if (traversalPolicy != null) { focusComponent = traversalPolicy.getDefaultComponent(container); if (focusComponent == null) { focusComponent = traversalPolicy.getFirstComponent(container); } } else if (comp instanceof Container) { // not sure if it is correct focusComponent = findFocusableComponent((Container) comp); } else { focusComponent = comp; } if (focusComponent != null) { final Component theComponent = focusComponent; Runnable runnable = new Runnable() { public void run() { theComponent.requestFocus(); } }; SwingUtilities.invokeLater(runnable); } } } } if (getUI() instanceof BasicJideTabbedPaneUI) { ((BasicJideTabbedPaneUI) getUI()).ensureActiveTabIsVisible(false); } hideTabListPopup(); } } private Component findFocusableComponent(Container parent) { FocusTraversalPolicy traversalPolicy = parent.getFocusTraversalPolicy(); Component focusComponent = null; if (traversalPolicy != null) { focusComponent = traversalPolicy.getDefaultComponent(parent); if (focusComponent == null) { focusComponent = traversalPolicy.getFirstComponent(parent); } } if (focusComponent != null) { return focusComponent; } int i = 0; while (i < parent.getComponentCount()) { Component comp = parent.getComponent(i); if (comp instanceof Container) { focusComponent = findFocusableComponent((Container) comp); if (focusComponent != null) { return focusComponent; } } else if (comp.isFocusable()) { return comp; } i++; } if (parent.isFocusable()) { return parent; } return null; } /** * Creates no focus buttons for JideTabbedPane. * * @param type the button type, it could be {@link #BUTTON_LIST}, {@link #BUTTON_CLOSE}, {@link #BUTTON_EAST}, * {@link #BUTTON_WEST}, {@link #BUTTON_NORTH} or {@link #BUTTON_SOUTH} * @return the button instance. */ public NoFocusButton createNoFocusButton(int type) { return new NoFocusButton(type); } public class NoFocusButton extends JButton implements MouseMotionListener, MouseListener, UIResource { private int _type; private int _index = -1; private boolean _mouseOver = false; private boolean _mousePressed = false; /** * Resets the UI property to a value from the current look and feel. * * @see JComponent#updateUI */ @Override public void updateUI() { super.updateUI(); setMargin(new Insets(0, 0, 0, 0)); setBorder(BorderFactory.createEmptyBorder()); setFocusPainted(false); setFocusable(false); setRequestFocusEnabled(false); String name = getName(); if (name != null) setToolTipText(getResourceString(name)); } public NoFocusButton() { this(BUTTON_CLOSE); } public NoFocusButton(int type) { addMouseMotionListener(this); addMouseListener(this); setFocusPainted(false); setFocusable(false); setType(type); } @Override public Dimension getPreferredSize() { return new Dimension(16, 16); } @Override public Dimension getMinimumSize() { return new Dimension(5, 5); } public int getIndex() { return _index; } public void setIndex(int index) { _index = index; } @Override public Dimension getMaximumSize() { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } @Override protected void paintComponent(Graphics g) { if (getIcon() != null) { super.paintComponent(g); return; } if (!isEnabled()) { setMouseOver(false); setMousePressed(false); } if (isMouseOver() && isMousePressed()) { g.setColor(getPressedShadowColor()); g.drawLine(0, 0, getWidth() - 1, 0); g.drawLine(0, getHeight() - 2, 0, 1); g.setColor(getShadowColor()); g.drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 2); g.drawLine(getWidth() - 1, getHeight() - 1, 0, getHeight() - 1); } else if (isMouseOver()) { g.setColor(getShadowColor()); g.drawLine(0, 0, getWidth() - 1, 0); g.drawLine(0, getHeight() - 2, 0, 1); g.setColor(getPressedShadowColor()); g.drawLine(getWidth() - 1, 1, getWidth() - 1, getHeight() - 2); g.drawLine(getWidth() - 1, getHeight() - 1, 0, getHeight() - 1); } g.setColor(getForegroundColor()); int centerX = getWidth() >> 1; int centerY = getHeight() >> 1; int type = getType(); if ((getTabPlacement() == TOP || getTabPlacement() == BOTTOM) && !JideTabbedPane.this.getComponentOrientation().isLeftToRight()) { if (type == BUTTON_EAST) { type = BUTTON_WEST; } else if (type == BUTTON_WEST) { type = BUTTON_EAST; } } switch (type) { case BUTTON_CLOSE: if (isShowCloseButtonOnMouseOver() && !isMouseOver()) { Object property = JideTabbedPane.this.getClientProperty("JideTabbedPane.mouseOverTabIndex"); if (property instanceof Integer && getIndex() >= 0 && (Integer) property != getIndex()) { return; } } if (isEnabled()) { g.drawLine(centerX - 3, centerY - 3, centerX + 3, centerY + 3); g.drawLine(centerX - 4, centerY - 3, centerX + 2, centerY + 3); g.drawLine(centerX + 3, centerY - 3, centerX - 3, centerY + 3); g.drawLine(centerX + 2, centerY - 3, centerX - 4, centerY + 3); } else { g.drawLine(centerX - 3, centerY - 3, centerX + 3, centerY + 3); g.drawLine(centerX + 3, centerY - 3, centerX - 3, centerY + 3); } break; case BUTTON_EAST: // // | // || // ||| // |||| // ||||* // |||| // ||| // || // | // { if (getTabPlacement() == TOP || getTabPlacement() == BOTTOM) { int x = centerX + 2, y = centerY; // start point. mark as * above if (isEnabled()) { g.drawLine(x - 4, y - 4, x - 4, y + 4); g.drawLine(x - 3, y - 3, x - 3, y + 3); g.drawLine(x - 2, y - 2, x - 2, y + 2); g.drawLine(x - 1, y - 1, x - 1, y + 1); g.drawLine(x, y, x, y); } else { g.drawLine(x - 4, y - 4, x, y); g.drawLine(x - 4, y - 4, x - 4, y + 4); g.drawLine(x - 4, y + 4, x, y); } } else { int x = centerX + 3, y = centerY - 2; // start point. mark as * above if (isEnabled()) { g.drawLine(x - 8, y, x, y); g.drawLine(x - 7, y + 1, x - 1, y + 1); g.drawLine(x - 6, y + 2, x - 2, y + 2); g.drawLine(x - 5, y + 3, x - 3, y + 3); g.drawLine(x - 4, y + 4, x - 4, y + 4); } else { g.drawLine(x - 8, y, x, y); g.drawLine(x - 8, y, x - 4, y + 4); g.drawLine(x - 4, y + 4, x, y); } } } break; case BUTTON_WEST: { // // | // || // ||| // |||| // *|||| // |||| // ||| // || // | // { if (getTabPlacement() == TOP || getTabPlacement() == BOTTOM) { int x = centerX - 3, y = centerY; // start point. mark as * above if (isEnabled()) { g.drawLine(x, y, x, y); g.drawLine(x + 1, y - 1, x + 1, y + 1); g.drawLine(x + 2, y - 2, x + 2, y + 2); g.drawLine(x + 3, y - 3, x + 3, y + 3); g.drawLine(x + 4, y - 4, x + 4, y + 4); } else { g.drawLine(x, y, x + 4, y - 4); g.drawLine(x, y, x + 4, y + 4); g.drawLine(x + 4, y - 4, x + 4, y + 4); } } else { int x = centerX - 5, y = centerY + 3; // start point. mark as * above if (isEnabled()) { g.drawLine(x, y, x + 8, y); g.drawLine(x + 1, y - 1, x + 7, y - 1); g.drawLine(x + 2, y - 2, x + 6, y - 2); g.drawLine(x + 3, y - 3, x + 5, y - 3); g.drawLine(x + 4, y - 4, x + 4, y - 4); } else { g.drawLine(x, y, x + 8, y); g.drawLine(x, y, x + 4, y - 4); g.drawLine(x + 8, y, x + 4, y - 4); } } } break; } case BUTTON_LIST: { int x = centerX + 2, y = centerY; // start point. mark as // * above g.drawLine(x - 6, y - 4, x - 6, y + 4); g.drawLine(x + 1, y - 4, x + 1, y + 4); g.drawLine(x - 6, y - 4, x + 1, y - 4); g.drawLine(x - 4, y - 2, x - 1, y - 2); g.drawLine(x - 4, y, x - 1, y); g.drawLine(x - 4, y + 2, x - 1, y + 2); g.drawLine(x - 6, y + 4, x + 1, y + 4); break; } } } protected Color getForegroundColor() { return UIDefaultsLookup.getColor("JideTabbedPane.foreground"); } protected Color getShadowColor() { return UIDefaultsLookup.getColor("control"); } protected Color getPressedShadowColor() { return UIDefaultsLookup.getColor("controlDkShadow"); } @Override public boolean isFocusable() { return false; } @Override public void requestFocus() { } @Override public boolean isOpaque() { return false; } public void mouseDragged(MouseEvent e) { } public void mouseMoved(MouseEvent e) { if (!isEnabled()) return; setMouseOver(true); repaint(); } public void mouseClicked(MouseEvent e) { if (!isEnabled()) return; setMouseOver(true); setMousePressed(false); } public void mousePressed(MouseEvent e) { if (!isEnabled()) return; setMousePressed(true); repaint(); } public void mouseReleased(MouseEvent e) { if (!isEnabled()) return; setMousePressed(false); setMouseOver(false); } public void mouseEntered(MouseEvent e) { if (!isEnabled()) return; setMouseOver(true); repaint(); } public void mouseExited(MouseEvent e) { if (!isEnabled()) return; setMouseOver(false); setMousePressed(false); repaint(); JideTabbedPane.this.repaint(); } public int getType() { return _type; } public void setType(int type) { _type = type; } public boolean isMouseOver() { return _mouseOver; } public void setMouseOver(boolean mouseOver) { _mouseOver = mouseOver; } public boolean isMousePressed() { return _mousePressed; } public void setMousePressed(boolean mousePressed) { _mousePressed = mousePressed; } } }