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: * TabDisplayerUI.java
043: *
044: * Created on March 16, 2004, 5:55 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.MouseEvent;
055: import java.util.HashMap;
056: import java.util.Map;
057: import org.netbeans.swing.tabcontrol.plaf.TabControlButton;
058: import org.netbeans.swing.tabcontrol.plaf.TabControlButtonFactory;
059:
060: /**
061: * The basic UI of a tab displayer component. Defines the API of the UI for
062: * TabDisplayers, which may be called by TabDisplayer.
063: *
064: * @author Tim Boudreau
065: * @see org.netbeans.swing.tabcontrol.plaf.AbstractTabDisplayerUI
066: * @see org.netbeans.swing.tabcontrol.plaf.BasicTabDisplayerUI
067: */
068: public abstract class TabDisplayerUI extends ComponentUI {
069: protected SingleSelectionModel selectionModel = null;
070: protected final TabDisplayer displayer;
071:
072: /**
073: * Creates a new instance of TabDisplayerUI
074: */
075: protected TabDisplayerUI(TabDisplayer displayer) {
076: this .displayer = displayer;
077: }
078:
079: public void installUI(JComponent c) {
080: assert c == displayer;
081: selectionModel = displayer.getSelectionModel();
082:
083: //Will only be non-null if we are in the middle of an L&F change - don't
084: //replace it so listeners are not clobbered
085: if (selectionModel == null) {
086: selectionModel = createSelectionModel();
087: }
088:
089: installSelectionModel();
090: }
091:
092: public void uninstallUI(JComponent c) {
093: assert c == displayer;
094: }
095:
096: /**
097: * Get a shape representing the exact outline of the numbered tab. The
098: * implementations in the package will return instances of
099: * <code>EqualPolygon</code> from this method; other implementations may
100: * return what they want, but for performance reasons, it is highly
101: * desirable that the shape object returned honor <code>equals()</code> and
102: * <code>hashCode()</code>, as there are significant optimizations in
103: * NetBeans' drag and drop support that depend on this.
104: */
105: public abstract Polygon getExactTabIndication(int index);
106:
107: /**
108: * Get a shape representing the area of visual feedback during a drag and
109: * drop operation, which represents where a tab will be inserted if a drop
110: * operation is performed over the indicated tab. <p>The implementations in
111: * the package will return instances of <code>EqualPolygon</code> from this
112: * method; other implementations may return what they want, but for
113: * performance reasons, it is highly desirable that the shape object
114: * returned honor <code>equals()</code> and <code>hashCode()</code>, as
115: * there are significant optimizations in NetBeans' drag and drop support
116: * that depened on this.
117: *
118: * @return Shape representing feedback shape
119: */
120: public abstract Polygon getInsertTabIndication(int index);
121:
122: /**
123: * Returns the index of the tab at the passed point, or -1 if no tab is at
124: * that location. Note that this method may return -1 for coordinates which
125: * are within a tab as returned by getTabRect(), but are not within the
126: * visible shape of the tab as the UI paints it.
127: */
128: public abstract int tabForCoordinate(Point p);
129:
130: /**
131: * Configure the passed rectangle with the shape of the tab at the given
132: * index.
133: */
134: public abstract Rectangle getTabRect(int index,
135: final Rectangle destination);
136:
137: /**
138: * Returns an image suitable for use in drag and drop operations,
139: * representing the tab at this index. The default implementation returns null.
140: *
141: * @param index A tab index
142: * @throws IllegalArgumentException if no tab is at the passed index
143: */
144: public Image createImageOfTab(int index) {
145: return null;
146: }
147:
148: /**
149: * Create the selection model which will handle selection for the
150: * TabDisplayer. SPI method located here because TabDisplayer.setSelectionModel
151: * is package private.
152: */
153: protected abstract SingleSelectionModel createSelectionModel();
154:
155: /**
156: * Allows ActionListeners attached to the container to determine if the
157: * event should be acted on. Delegates to <code>displayer.postActionEvent()</code>.
158: * This method will create a TabActionEvent with the passed string as an
159: * action command, and cause the displayer to fire this event. It will
160: * return true if no listener on the displayer consumed the TabActionEvent;
161: * consuming the event is the way a listener can veto a change, or provide
162: * special handling for it.
163: *
164: * @param command The action command - this should be TabDisplayer.COMMAND_SELECT
165: * or TabDisplayer.COMMAND_CLOSE, but private contracts
166: * between custom UIs and components are also an option.
167: * @param tab The index of the tab upon which the action should act, or
168: * -1 if non-applicable
169: * @param event A mouse event which initiated the action, or null
170: * @return true if the event posted was not consumed by any listener
171: */
172: protected final boolean shouldPerformAction(String command,
173: int tab, MouseEvent event) {
174: TabActionEvent evt = new TabActionEvent(displayer, command,
175: tab, event);
176: displayer.postActionEvent(evt);
177: return !evt.isConsumed();
178: }
179:
180: /**
181: * Instruct the UI to ensure that the tab at the given index is visible.
182: * Some UIs allow scrolling or otherwise hiding tabs. The default
183: * implementation is a no-op.
184: *
185: * @param index The index of the tab that should be made visible, which
186: * should be within the range of 0 to the count of tabs in the
187: * model
188: */
189: public void makeTabVisible(int index) {
190: //do nothing
191: }
192:
193: /**
194: * Installs the selection model into the tab control via a package private
195: * method.
196: */
197: private void installSelectionModel() {
198: displayer.setSelectionModel(selectionModel);
199: }
200:
201: /**
202: * The index a tab would acquire if dropped at a given point
203: *
204: * @param p A point
205: * @return An index which may be equal to the size of the data model
206: */
207: public abstract int dropIndexOfPoint(Point p);
208:
209: public abstract void registerShortcuts(JComponent comp);
210:
211: public abstract void unregisterShortcuts(JComponent comp);
212:
213: protected abstract void requestAttention(int tab);
214:
215: protected abstract void cancelRequestAttention(int tab);
216:
217: /**
218: * @since 1.9
219: * @return An icon for various buttons displayed in tab control (close/pin/scroll left/right etc), see TabControlButton class.
220: */
221: public Icon getButtonIcon(int buttonId, int buttonState) {
222: Icon res = null;
223: initIcons();
224: String[] paths = buttonIconPaths.get(buttonId);
225: if (null != paths && buttonState >= 0
226: && buttonState < paths.length) {
227: res = TabControlButtonFactory.getIcon(paths[buttonState]);
228: }
229: return res;
230: }
231:
232: public void postTabAction(TabActionEvent e) {
233: if (shouldPerformAction(e.getActionCommand(), e.getTabIndex(),
234: e.getMouseEvent())) {
235:
236: //TODO do something here??
237: }
238: }
239:
240: private static Map<Integer, String[]> buttonIconPaths;
241:
242: private static void initIcons() {
243: if (null == buttonIconPaths) {
244: buttonIconPaths = new HashMap<Integer, String[]>(10);
245:
246: //close button
247: String[] iconPaths = new String[4];
248: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_bigclose_enabled.png"; // NOI18N
249: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_bigclose_pressed.png"; // NOI18N
250: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
251: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_bigclose_rollover.png"; // NOI18N
252: buttonIconPaths.put(TabControlButton.ID_CLOSE_BUTTON,
253: iconPaths);
254:
255: //slide/pin button
256: iconPaths = new String[4];
257: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_slideright_enabled.png"; // NOI18N
258: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_slideright_pressed.png"; // NOI18N
259: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
260: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_slideright_rollover.png"; // NOI18N
261: buttonIconPaths.put(TabControlButton.ID_SLIDE_RIGHT_BUTTON,
262: iconPaths);
263:
264: iconPaths = new String[4];
265: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_slideleft_enabled.png"; // NOI18N
266: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_slideleft_pressed.png"; // NOI18N
267: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
268: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_slideleft_rollover.png"; // NOI18N
269: buttonIconPaths.put(TabControlButton.ID_SLIDE_LEFT_BUTTON,
270: iconPaths);
271:
272: iconPaths = new String[4];
273: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_slidebottom_enabled.png"; // NOI18N
274: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_slidebottom_pressed.png"; // NOI18N
275: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
276: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_slidebottom_rollover.png"; // NOI18N
277: buttonIconPaths.put(TabControlButton.ID_SLIDE_DOWN_BUTTON,
278: iconPaths);
279:
280: iconPaths = new String[4];
281: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_pin_enabled.png"; // NOI18N
282: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_pin_pressed.png"; // NOI18N
283: iconPaths[TabControlButton.STATE_DISABLED] = iconPaths[TabControlButton.STATE_DEFAULT];
284: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_pin_rollover.png"; // NOI18N
285: buttonIconPaths.put(TabControlButton.ID_PIN_BUTTON,
286: iconPaths);
287:
288: //left button
289: iconPaths = new String[4];
290: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_scrollleft_enabled.png"; // NOI18N
291: iconPaths[TabControlButton.STATE_DISABLED] = "org/netbeans/swing/tabcontrol/resources/metal_scrollleft_disabled.png"; // NOI18N
292: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_scrollleft_rollover.png"; // NOI18N
293: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_scrollleft_pressed.png"; // NOI18N
294: buttonIconPaths.put(TabControlButton.ID_SCROLL_LEFT_BUTTON,
295: iconPaths);
296:
297: //right button
298: iconPaths = new String[4];
299: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_scrollright_enabled.png"; // NOI18N
300: iconPaths[TabControlButton.STATE_DISABLED] = "org/netbeans/swing/tabcontrol/resources/metal_scrollright_disabled.png"; // NOI18N
301: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_scrollright_rollover.png"; // NOI18N
302: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_scrollright_pressed.png"; // NOI18N
303: buttonIconPaths.put(
304: TabControlButton.ID_SCROLL_RIGHT_BUTTON, iconPaths);
305:
306: //drop down button
307: iconPaths = new String[4];
308: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_popup_enabled.png"; // NOI18N
309: iconPaths[TabControlButton.STATE_DISABLED] = "org/netbeans/swing/tabcontrol/resources/metal_popup_disabled.png"; // NOI18N
310: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_popup_rollover.png"; // NOI18N
311: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_popup_pressed.png"; // NOI18N
312: buttonIconPaths.put(TabControlButton.ID_DROP_DOWN_BUTTON,
313: iconPaths);
314:
315: //maximize/restore button
316: iconPaths = new String[4];
317: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_maximize_enabled.png"; // NOI18N
318: iconPaths[TabControlButton.STATE_DISABLED] = "org/netbeans/swing/tabcontrol/resources/metal_maximize_disabled.png"; // NOI18N
319: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_maximize_rollover.png"; // NOI18N
320: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_maximize_pressed.png"; // NOI18N
321: buttonIconPaths.put(TabControlButton.ID_MAXIMIZE_BUTTON,
322: iconPaths);
323:
324: iconPaths = new String[4];
325: iconPaths[TabControlButton.STATE_DEFAULT] = "org/netbeans/swing/tabcontrol/resources/metal_restore_enabled.png"; // NOI18N
326: iconPaths[TabControlButton.STATE_DISABLED] = "org/netbeans/swing/tabcontrol/resources/metal_restore_disabled.png"; // NOI18N
327: iconPaths[TabControlButton.STATE_ROLLOVER] = "org/netbeans/swing/tabcontrol/resources/metal_restore_rollover.png"; // NOI18N
328: iconPaths[TabControlButton.STATE_PRESSED] = "org/netbeans/swing/tabcontrol/resources/metal_restore_pressed.png"; // NOI18N
329: buttonIconPaths.put(TabControlButton.ID_RESTORE_BUTTON,
330: iconPaths);
331: }
332: }
333:
334: }
|