001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: /*
042: * TabbedContainerUI.java
043: *
044: * Created on March 14, 2004, 3:25 PM
045: */
046:
047: package org.netbeans.swing.tabcontrol;
048:
049: import org.netbeans.swing.tabcontrol.event.TabActionEvent;
050:
051: import javax.swing.*;
052: import javax.swing.plaf.ComponentUI;
053: import java.awt.*;
054: import java.awt.event.HierarchyEvent;
055: import java.awt.event.MouseEvent;
056:
057: /**
058: * Basic UI for tabbed containers. Note this is distinct from the UI for the
059: * embedded tab displayer component - that where all the interesting painting
060: * logic is.
061: * <p>
062: * To provide an implementation of TabbedContainerUI, it is a far better idea to
063: * subclass
064: * <a href="plaf/AbstractTabbedContainerUI.html">AbstractTabbedContainerUI</a>,
065: * <a href="plaf/BasicTabbedContainerUI.html">BasicTabbedContainerUI</a>, or
066: * <a href="plaf/BasicScrollingTabbedContainerUI.html">BasicScrollingTabbedContainerUI</a>.
067: *
068: * @author Tim Boudreau
069: */
070: public abstract class TabbedContainerUI extends ComponentUI {
071: /** The TabbedContainer this instance is acting as a ui delegate for.
072: * <strong>do not alter the value in this field. </strong>
073: */
074: protected TabbedContainer container = null;
075:
076: /**
077: * Creates a new instance of TabbedContainerUI
078: */
079: public TabbedContainerUI(TabbedContainer container) {
080: this .container = container;
081: }
082:
083: public void installUI(JComponent c) {
084: assert c == container;
085: }
086:
087: /**
088: * This method is called if TabbedContainer.updateUI() gets called after
089: * a UI delegate has been installed (in other words, the user did something
090: * like switch look and feels or switch the Windows desktop theme).
091: * <p>
092: * Normally, the only UI delegate that exists for TabbedContainer is
093: * DefaultTabbedContainerUI, so it makes no sense to replace one with
094: * another, since they do the same thing.
095: * <p>
096: * However, this method can be used to update the tab displayer component's
097: * UI. Subclasses are expected to override this method to call
098: * updateUI() on the displayer, or do whatever is appropriate to ensure that
099: * the UI will look right after the change - or to return true from this
100: * method, in which the entire UI delegate for the tabbed container will
101: * be replaced.
102: * @return false
103: */
104: protected boolean uichange() {
105: return false;
106: }
107:
108: /**
109: * Accessor method for TabbedContainer
110: * @see uichange
111: */
112: final boolean shouldReplaceUI() {
113: return uichange();
114: }
115:
116: /** Get the bounds of a tab. Note that for non-rectangular tabs
117: * this may not correspond exactly to the area in which it will
118: * respond to mouse clicks.
119: *
120: * @param tab A tab index
121: * @param r A rectangle to configure with the information, or null
122: * @return The passed rectangle, or a new one if null was passed
123: */
124: public abstract Rectangle getTabRect(int tab, Rectangle r);
125:
126: /** Get the tab at a given point in the coordinate space of the
127: * container.
128: *
129: * @param p A point
130: * @return The tab index at this point, or -1 if no tab
131: */
132: public abstract int tabForCoordinate(Point p);
133:
134: /** Make a tab visible. No-op except in the case of scrolling tabs,
135: * in which case the tab may be scrolled offscreen.
136: *
137: * @param index A tab index
138: */
139: public abstract void makeTabVisible(int index);
140:
141: /**
142: * Allows ActionListeners attached to the container to determine if the
143: * event should be acted on. Delegates to <code>displayer.postActionEvent()</code>.
144: * This method will create a TabActionEvent with the passed string as an
145: * action command, and cause the displayer to fire this event. It will
146: * return true if no listener on the displayer consumed the TabActionEvent;
147: * consuming the event is the way a listener can veto a change, or provide
148: * special handling for it.
149: *
150: * @param command The action command - this should be TabDisplayer.COMMAND_SELECT
151: * or TabDisplayer.COMMAND_CLOSE, but private contracts
152: * between custom UIs and components are also an option.
153: * @param tab The index of the tab upon which the action should act, or
154: * -1 if non-applicable
155: * @param event A mouse event which initiated the action, or null
156: * @return true if the event posted was not consumed by any listener
157: */
158: protected final boolean shouldPerformAction(String command,
159: int tab, MouseEvent event) {
160: TabActionEvent evt = new TabActionEvent(container, command,
161: tab, event);
162: container.postActionEvent(evt);
163: return !evt.isConsumed();
164: }
165:
166: /**
167: * Get the selection model that tracks and determines which tab is selected.
168: *
169: * @return The selection model (in the default implementation, this is the selection model of the
170: * embedded tab displayer)
171: */
172: public abstract SingleSelectionModel getSelectionModel();
173:
174: /** Create an image suitable for use in drag and drop operations, of a tab */
175: public abstract Image createImageOfTab(int idx);
176:
177: /** Get a polygon matching the shape of the tab */
178: public abstract Polygon getExactTabIndication(int idx);
179:
180: /** Get a polygon indicating the insertion of a tab before the passed
181: * index, unless the index is equal to the model size, in which case
182: * it will return an indication for inserting a tab at the end.
183: *
184: * @param idx A tab index
185: * @return A shape representing the shape of the tab as it is displayed onscreen,
186: * in the coordinate space of the displayer
187: */
188: public abstract Polygon getInsertTabIndication(int idx);
189:
190: /** Get a rectangle matching the area in which content is displayed */
191: public abstract Rectangle getContentArea();
192:
193: /** Get a rectangle matching the area in which tabs are displayed */
194: public abstract Rectangle getTabsArea();
195:
196: /**
197: * Index at which a tab would be inserted if a suitable object were dropped
198: * at this point.
199: *
200: * @param p A point
201: * @return A tab index which may be equal to the size of the model (past the
202: * last tab index) if the tab should be inserted at the end.
203: */
204: public abstract int dropIndexOfPoint(Point p);
205:
206: public abstract void setShowCloseButton(boolean val);
207:
208: public abstract boolean isShowCloseButton();
209:
210: protected abstract void requestAttention(int tab);
211:
212: protected abstract void cancelRequestAttention(int tab);
213:
214: }
|