alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.swing.tabcontrol;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleRole;
import javax.swing.event.ChangeEvent;
import org.netbeans.swing.tabcontrol.event.TabActionEvent;
import org.netbeans.swing.tabcontrol.plaf.AquaEditorTabDisplayerUI;
import org.netbeans.swing.tabcontrol.plaf.AquaViewTabDisplayerUI;
import org.netbeans.swing.tabcontrol.plaf.BasicSlidingTabDisplayerUI;
import org.netbeans.swing.tabcontrol.plaf.WinClassicEditorTabDisplayerUI;
import org.netbeans.swing.tabcontrol.plaf.WinClassicViewTabDisplayerUI;

import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleSelection;
import javax.swing.event.ChangeListener;
import org.netbeans.swing.tabcontrol.plaf.ToolbarTabDisplayerUI;
import org.netbeans.swing.tabcontrol.plaf.WinXPEditorTabDisplayerUI;
import org.netbeans.swing.tabcontrol.plaf.WinXPViewTabDisplayerUI;


/**
 * A Component which displays tabs supplied by a TabDataModel.  This is 
 * essentially the upper (or lower) portion of a tabbed pane, without the
 * part that displays components.  It can be used to provide tab-like
 * selection over a data model containing anything, not just components.
 * 

* It has a three display modes (more fully described in the overview for * TabbedContainer), to provide different * styles of tab display, such as scrolling tabs and others. *

* TabDisplayer is completely model driven - the class itself is little more * than an aggregation point for a data model, a selection model, and so forth. * The logic that allows it to operate is implemented in the UI delegates, * which are installed by (and can be replaced via) the standard Swing * UIManager mechanisms. *

* Some TabDisplayer UI's support an orientation property, which is provided * via the client property PROP_ORIENTATION. * * @author Tim Boudreau */ public final class TabDisplayer extends JComponent implements Accessible { private boolean initialized = false; private TabDataModel model; private SingleSelectionModel sel = null; private boolean active; private final int type; /** * Displayer type for view tabs, which do not scroll and simply divide the * available space between themselves. The value of this field is mapped to * TabbedContainer.TYPE_VIEW */ public static final int TYPE_VIEW = TabbedContainer.TYPE_VIEW; /** * Displayer type for editor tabs, which scroll (typically - depends on what * the UI does). The value of this field is mapped to * TabbedContainer.TYPE_EDITOR */ public static final int TYPE_EDITOR = TabbedContainer.TYPE_EDITOR; public static final int TYPE_SLIDING = TabbedContainer.TYPE_SLIDING; public static final int TYPE_TOOLBAR = TabbedContainer.TYPE_TOOLBAR; /** * Property indicating the tab displayer should be painted as * "active". This is typically used to indicate keyboard focus. * The valud of this field is mapped to TabbedContainer.PROP_ACTIVE */ public static final String PROP_ACTIVE = TabbedContainer.PROP_ACTIVE; /** * Action command indicating that the action event signifies the user * clicking the Close button on a tab. */ public static final String COMMAND_CLOSE = TabbedContainer.COMMAND_CLOSE; /** * Action command indicating that the action event fired signifies the user * selecting a tab */ public static final String COMMAND_SELECT = TabbedContainer.COMMAND_SELECT; /** * Action command indicating that the action event fired signifies the user * requesting a popup menu over a tab */ public static final String COMMAND_POPUP_REQUEST = TabbedContainer.COMMAND_POPUP_REQUEST; /** * Action command indicating that the action event fired signifies the user * has double clicked a tab */ public static final String COMMAND_MAXIMIZE = TabbedContainer.COMMAND_MAXIMIZE; /** * Action command indicating that the action event fired signifies the user * has shift-clicked the close button on a tab */ public static final String COMMAND_CLOSE_ALL = TabbedContainer.COMMAND_CLOSE_ALL; //NOI18N /** * Action command indicating that the action event fired signifies the user * has alt-clicked the close button on a tab */ public static final String COMMAND_CLOSE_ALL_BUT_THIS = TabbedContainer.COMMAND_CLOSE_ALL_BUT_THIS; //NOI18N /** * Action command indicating that the action event signifies the user * clicking the Pin button on a tab. */ public static final String COMMAND_ENABLE_AUTO_HIDE = TabbedContainer.COMMAND_ENABLE_AUTO_HIDE; //NOI18N /** * Action command indicating that the action event signifies the user * clicking the Pin button on a tab. */ public static final String COMMAND_DISABLE_AUTO_HIDE = TabbedContainer.COMMAND_DISABLE_AUTO_HIDE; //NOI18N /** * UIManager key for the UI Delegate to be used for "editor" style TabbedContainers */ public static final String EDITOR_TAB_DISPLAYER_UI_CLASS_ID = "EditorTabDisplayerUI"; //NOI18N /** * UIManager key for the UI Delegate to be used for "view" style TabbedContainers */ public static final String VIEW_TAB_DISPLAYER_UI_CLASS_ID = "ViewTabDisplayerUI"; //NOI18N /** * UIManager key for the UI delegate to be used in "sliding" style * containers */ public static final String SLIDING_TAB_DISPLAYER_UI_CLASS_ID = "SlidingTabDisplayerUI"; //NOI18N /** * UIManager key for the UI delegate to be used for toolbar style tabs */ public static final String TOOLBAR_TAB_DISPLAYER_UI_CLASS_ID = "ToolbarTabDisplayerUI"; //NOI18N /** Client property to indicate the orientation, which determines what * side the tabs are displayed on. Currently this is only honored by * the sliding tabs ui delegate. */ public static final String PROP_ORIENTATION = "orientation"; //NOI18N /** Client property value to display tabs on the left side of the control. */ public static final Object ORIENTATION_EAST = "east"; //NOI18N /** Client property value to display tabs on the right side of the control */ public static final Object ORIENTATION_WEST = "west"; //NOI18N /** Client property value to display tabs on the top edge of the control */ public static final Object ORIENTATION_NORTH = "north"; //NOI18N /** Client property value to display tabs on the bottom edge of the control */ public static final Object ORIENTATION_SOUTH = "south"; //NOI18N /** Client property value for pin button to have neutral orientation */ public static final Object ORIENTATION_CENTER = "center"; //NOI18N /** * Utility field holding list of ActionListeners. */ private transient List actionListenerList; /** Info about global positioning of this tab control * or null if no global location info is needed */ private LocationInformer locationInformer = null; public TabDisplayer () { this (new DefaultTabDataModel(), TYPE_VIEW); } /** * Creates a new instance of TabDisplayer */ public TabDisplayer(TabDataModel model, int type) { this (model, type, null); } /** * Creates a new instance of TabDisplayer */ public TabDisplayer(TabDataModel model, int type, LocationInformer locationInformer) { switch (type) { case TYPE_VIEW: case TYPE_EDITOR: case TYPE_SLIDING: case TYPE_TOOLBAR: break; default : throw new IllegalArgumentException("Unknown UI type: " + type); //NOI18N } this.model = model; this.type = type; this.locationInformer = locationInformer; putClientProperty (PROP_ORIENTATION, ORIENTATION_NORTH); initialized = true; updateUI(); setFocusable(false); } public final TabDisplayerUI getUI() { return (TabDisplayerUI) ui; } /** Overridden to block the call from the superclass constructor, which * comes before the type property is initialized. Provides * a reasonable fallback UI for use on unknown look and feels. */ public final void updateUI() { if (!initialized) { return; } if (type == TYPE_TOOLBAR) { setUI (new ToolbarTabDisplayerUI(this)); return; } else if (type == TYPE_SLIDING) { setUI (new BasicSlidingTabDisplayerUI(this)); return; } ComponentUI ui = null; if (UIManager.get(getUIClassID()) != null) { //Avoid Error stack trace try { ui = UIManager.getUI(this); } catch (Error error) { System.err.println("Could not load a UI for " + getUIClassID() + " - missing class?"); } } else { ui = findUIStandalone(); } if (ui == null) { ui = getType() == TYPE_VIEW ? WinClassicViewTabDisplayerUI.createUI(this) : WinClassicEditorTabDisplayerUI.createUI(this); } setUI((TabDisplayerUI) ui); } /** * Allows the tabcontrol to find the correct UI if the plaf library is * not present (no UI class defined in UIManager). */ private ComponentUI findUIStandalone() { ComponentUI result = null; String lf = UIManager.getLookAndFeel().getID(); switch (type) { case TYPE_VIEW : if ("Aqua".equals(lf)) { //NOI18N result = AquaViewTabDisplayerUI.createUI(this); } else if ("Windows".equals(lf)) { //NOI18N result = isXPLF() ? WinXPViewTabDisplayerUI.createUI(this) : WinClassicViewTabDisplayerUI.createUI(this); } break; case TYPE_EDITOR : if ("Aqua".equals(lf)) { //NOI18N result = AquaEditorTabDisplayerUI.createUI(this); } else if ("Windows".equals(lf)) { //NOI18N result = isXPLF() ? WinXPEditorTabDisplayerUI.createUI(this) : WinClassicEditorTabDisplayerUI.createUI(this); } break; } return result; } /** Finds if windows LF with XP theme is active. * @return true if windows LF and XP theme is active, false otherwise */ private static boolean isXPLF () { Boolean isXP = (Boolean)Toolkit.getDefaultToolkit(). getDesktopProperty("win.xpstyle.themeActive"); //NOI18N return isXP == null ? false : isXP.booleanValue(); } /** Returns an different UIClassID depending on the value of the type * property. */ public String getUIClassID() { switch (getType()) { case TYPE_VIEW : return VIEW_TAB_DISPLAYER_UI_CLASS_ID; case TYPE_EDITOR : return EDITOR_TAB_DISPLAYER_UI_CLASS_ID; case TYPE_SLIDING : return SLIDING_TAB_DISPLAYER_UI_CLASS_ID; case TYPE_TOOLBAR : return TOOLBAR_TAB_DISPLAYER_UI_CLASS_ID; default : throw new IllegalArgumentException ("Unknown UI type: " + getType()); } } /** * Returns whether this control uses the view tab look or the scrolling * editor tab look. This is set in the constructor. */ public final int getType() { return type; } public final Dimension getPreferredSize() { return getUI().getPreferredSize(this); } public final Dimension getMinimumSize() { return getUI().getMinimumSize(this); } /** * Accessor only for TabDisplayerUI when installing the UI */ void setSelectionModel(SingleSelectionModel sel) { this.sel = sel; } /** Get the selection model, which determines which tab is selected. * To change the selection, get the selection model and call * setSelectedIndex(). */ public SingleSelectionModel getSelectionModel() { return sel; } /** Get the data model that defines the contents which are displayed */ public final TabDataModel getModel() { return model; } /** Set the active state of the component */ public final void setActive(boolean active) { if (active != this.active) { this.active = active; firePropertyChange(PROP_ACTIVE, !active, active); //NOI18N } } /** Gets the "active" state of this component. If the component * is active, most UIs will paint the selected tab differently to indicate * that focus is somewhere in the container */ public final boolean isActive() { return active; } /** * Gets tooltip for the tab corresponding to the mouse event, or if no * tab, delegates to the default implementation. */ public final String getToolTipText(MouseEvent event) { if (ui != null) { Point p = event.getPoint(); if (event.getSource() != this) { Component c = (Component) event.getSource(); p = SwingUtilities.convertPoint(c, p, this); } int index = getUI().tabForCoordinate(p); if (index != -1) { return getModel().getTab(index).tip; } } return super.getToolTipText(event); } /** Make a tab visible. In the case of scrolling UIs, a tab is not * always visible. This call will make it scroll into view */ public final void makeTabVisible(int index) { getUI().makeTabVisible(index); } /** Get the rectangle that a given tab occupies */ public final Rectangle getTabRect(int tab, Rectangle dest) { if (dest == null) { dest = new Rectangle(); } getUI().getTabRect(tab, dest); return dest; } public final Image getDragImage(int index) { return getUI().createImageOfTab(index); } /** * Register an ActionListener. TabbedContainer and TabDisplayer guarantee * that the type of event fired will always be TabActionEvent. There are * two special things about TabActionEvent:

  1. There are methods on * TabActionEvent to find the index of the tab the event was performed on, * and if present, retrieve the mouse event that triggered it, for clients * that wish to provide different handling for different mouse buttons
  2. *
  3. TabActionEvents can be consumed. If a listener consumes the event, * the UI will take no action - the selection will not be changed, the tab * will not be closed. Consuming the event means taking responsibility for * doing whatever would normally happen automatically. This is useful for, * for example, showing a dialog and possibly aborting closing a tab if it * contains unsaved data, for instance.
Action events will be * fired before any action has been taken to alter the * state of the control to match the action, so that they may be vetoed or * modified by consuming the event. * * @param listener The listener to register. */ public final synchronized void addActionListener(ActionListener listener) { if (actionListenerList == null) { actionListenerList = new ArrayList(); } actionListenerList.add(listener); } /** * Removes ActionListener from the list of listeners. * * @param listener The listener to remove. */ public final synchronized void removeActionListener(ActionListener listener) { if (actionListenerList != null) { actionListenerList.remove(listener); } } public String getCommandAtPoint(Point p) { return getUI().getCommandAtPoint (p); } public void registerShortcuts(JComponent comp) { getUI().registerShortcuts(comp); } public void unregisterShortcuts(JComponent comp) { getUI().unregisterShortcuts(comp); } /** * Notifies all registered listeners about the event. * * @param event The event to be fired */ protected final void postActionEvent(TabActionEvent event) { List list; synchronized (this) { if (actionListenerList == null) { return; } list = Collections.unmodifiableList(actionListenerList); } for (int i = 0; i < list.size(); i++) { ((ActionListener) list.get(i)).actionPerformed(event); } } public int tabForCoordinate(Point p) { return getUI().tabForCoordinate(p); } public LocationInformer getLocationInformer() { return locationInformer; } public AccessibleContext getAccessibleContext() { if (accessibleContext == null) { accessibleContext = new AccessibleTabDisplayer(); } return accessibleContext; } protected class AccessibleTabDisplayer extends AccessibleJComponent implements AccessibleSelection, ChangeListener { /** * Constructs an AccessibleTabDisplayer */ public AccessibleTabDisplayer() { super(); getModel().addChangeListener(this); } public void stateChanged(ChangeEvent e) { Object o = e.getSource(); firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY, null, o); } /** * Get the role of this object. * * @return an instance of AccessibleRole describing the role of * the object */ public AccessibleRole getAccessibleRole() { return AccessibleRole.PAGE_TAB_LIST; } /** * Returns the number of accessible children in the object. * * @return the number of accessible children in the object. */ public int getAccessibleChildrenCount() { return getModel().size(); } /** * Return the specified Accessible child of the object. * * @param i zero-based index of child * @return the Accessible child of the object * @exception IllegalArgumentException if index is out of bounds */ public Accessible getAccessibleChild(int i) { if (i < 0 || i >= getModel().size()) { return null; } TabData data = getModel().getTab(i); if (data.getComponent() instanceof Accessible) { return (Accessible)data.getComponent(); } return null; } /** * Gets the AccessibleSelection associated with * this object. In the implementation of the Java * Accessibility API for this class, * returns this object, which is responsible for implementing the * AccessibleSelection interface on behalf of itself. * * @return this object */ public AccessibleSelection getAccessibleSelection() { return this; } /** * Returns the Accessible child contained at * the local coordinate Point, if one exists. * Otherwise returns the currently selected tab. * * @return the Accessible at the specified * location, if it exists */ public Accessible getAccessibleAt(Point p) { int tab = tabForCoordinate(p); if (tab == -1) { tab = getSelectionModel().getSelectedIndex(); } return getAccessibleChild(tab); } /** * Returns the number of Accessible children currently selected. * If no children are selected, the return value will be 0. * * @return the number of items currently selected. */ public int getAccessibleSelectionCount() { return 1; } /** * Returns an Accessible representing the specified selected child * of the object. If there isn't a selection, or there are * fewer children selected than the integer passed in, the return * value will be null. *

Note that the index represents the i-th selected child, which * is different from the i-th child. * * @param i the zero-based index of selected children * @return the i-th selected child * @see #getAccessibleSelectionCount */ public Accessible getAccessibleSelection(int i) { // always just one selected.. -> ignore i int index = getSelectionModel().getSelectedIndex(); return getAccessibleChild(index); } /** * Determines if the current child of this object is selected. * * @return true if the current child of this object is selected; else false. * @param i the zero-based index of the child in this Accessible object. * @see AccessibleContext#getAccessibleChild */ public boolean isAccessibleChildSelected(int i) { return i == getSelectionModel().getSelectedIndex(); } /** * Adds the specified Accessible child of the object to the object's * selection. If the object supports multiple selections, * the specified child is added to any existing selection, otherwise * it replaces any existing selection in the object. If the * specified child is already selected, this method has no effect. * * @param i the zero-based index of the child * @see AccessibleContext#getAccessibleChild */ public void addAccessibleSelection(int i) { //TODO? } /** * Removes the specified child of the object from the object's * selection. If the specified item isn't currently selected, this * method has no effect. * * @param i the zero-based index of the child * @see AccessibleContext#getAccessibleChild */ public void removeAccessibleSelection(int i) { //TODO? } /** * Clears the selection in the object, so that no children in the * object are selected. */ public void clearAccessibleSelection() { //TODO? } /** * Causes every child of the object to be selected * if the object supports multiple selections. */ public void selectAllAccessibleSelection() { //TODO? } } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.