com.jidesoft.swing.JideTabbedPane Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jide-oss Show documentation
Show all versions of jide-oss Show documentation
JIDE Common Layer (Professional Swing Components)
/*
* @(#)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
* 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 TabEditingListener
s added to this JTabbedPane
with
* addTabEditingListener
.
*
* @return all of the TabEditingListener
s 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
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;
}
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy