2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.core.windows.view.ui.slides;
44
import java.awt.Component;
45
import java.awt.Graphics2D;
46
import java.awt.GraphicsConfiguration;
47
import java.awt.GraphicsEnvironment;
48
import java.awt.Image;
49
import java.awt.Point;
50
import java.awt.Rectangle;
51
import java.awt.Shape;
52
import java.awt.event.ActionEvent;
53
import java.awt.event.ActionListener;
54
import java.awt.image.BufferedImage;
55
import java.beans.PropertyChangeListener;
56
import java.util.ArrayList;
57
import java.util.Collections;
58
import java.util.List;
59
import javax.swing.Action;
60
import javax.swing.DefaultSingleSelectionModel;
61
import javax.swing.Icon;
62
import javax.swing.ImageIcon;
63
import javax.swing.JLabel;
64
import javax.swing.SingleSelectionModel;
65
import javax.swing.event.ChangeListener;
66
import org.netbeans.core.windows.Constants;
67
import org.netbeans.core.windows.WindowManagerImpl;
68
import org.netbeans.core.windows.actions.ActionUtils;
69
import org.netbeans.core.windows.view.ui.Tabbed;
70
import org.netbeans.swing.tabcontrol.SlideBarDataModel;
71
import org.netbeans.swing.tabcontrol.TabData;
72
import org.netbeans.swing.tabcontrol.TabDataModel;
73
import org.openide.util.ChangeSupport;
74
import org.openide.windows.TopComponent;
77
* Adapts SlideBar to match Tabbed interface, which is used by TabbedHandler
78
* for talking to component containers. SlideBar is driven indirectly,
79
* through modifications of its model.
81
* @author Dafe Simonek
85
* Adapts SlideBar to match Tabbed interface, which is used by TabbedHandler
86
* for talking to component containers. SlideBar is driven indirectly,
87
* through modifications of its model.
89
* @author Dafe Simonek
91
public final class TabbedSlideAdapter implements Tabbed {
93
/** data model of informations about top components in container */
94
private TabDataModel dataModel;
95
/** selection model which contains selection info in container */
96
private SingleSelectionModel selModel;
97
/** Visual component for displaying box for sliding windows */
98
private SlideBar slideBar;
99
/** List of action listeners */
100
private List<ActionListener> actionListeners;
101
private final ChangeSupport cs = new ChangeSupport(this);
103
/** Creates a new instance of SlideBarTabs */
104
public TabbedSlideAdapter(String side) {
105
dataModel = new SlideBarDataModel.Impl();
107
selModel = new DefaultSingleSelectionModel();
108
slideBar = new SlideBar(this, (SlideBarDataModel)dataModel, selModel);
111
public void requestAttention (TopComponent tc) {
112
slideBar.setBlinking(tc, true);
115
public void cancelRequestAttention (TopComponent tc) {
116
slideBar.setBlinking(tc, false);
120
private void setSide (String side) {
121
int orientation = SlideBarDataModel.WEST;
122
if (Constants.LEFT.equals(side)) {
123
orientation = SlideBarDataModel.WEST;
124
} else if (Constants.RIGHT.equals(side)) {
125
orientation = SlideBarDataModel.EAST;
126
} else if (Constants.BOTTOM.equals(side)) {
127
orientation = SlideBarDataModel.SOUTH;
129
((SlideBarDataModel)dataModel).setOrientation(orientation);
132
public final synchronized void addActionListener(ActionListener listener) {
133
if (actionListeners == null) {
134
actionListeners = new ArrayList<ActionListener>();
136
actionListeners.add(listener);
140
* Remove an action listener.
142
* @param listener The listener to remove.
144
public final synchronized void removeActionListener(ActionListener listener) {
145
if (actionListeners != null) {
146
actionListeners.remove(listener);
147
if (actionListeners.isEmpty()) {
148
actionListeners = null;
153
final void postActionEvent(ActionEvent event) {
154
List<ActionListener> list;
155
synchronized (this) {
156
if (actionListeners == null)
158
list = Collections.unmodifiableList(actionListeners);
160
for (int i = 0; i < list.size(); i++) {
161
list.get(i).actionPerformed(event);
165
public void addChangeListener(ChangeListener listener) {
166
cs.addChangeListener(listener);
169
public void removeChangeListener(ChangeListener listener) {
170
cs.removeChangeListener(listener);
173
final void postSelectionEvent() {
177
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
178
slideBar.addPropertyChangeListener(name, listener);
181
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
182
slideBar.removePropertyChangeListener(name, listener);
185
public void addTopComponent(String name, Icon icon, TopComponent tc, String toolTip) {
186
dataModel.addTab(dataModel.size(), new TabData(tc, icon, name, toolTip));
189
public TopComponent getSelectedTopComponent() {
190
int index = selModel.getSelectedIndex();
191
return index < 0 ? null : (TopComponent)dataModel.getTab(index).getComponent();
194
public TopComponent getTopComponentAt(int index) {
195
return (TopComponent)dataModel.getTab(index).getComponent();
198
public TopComponent[] getTopComponents() {
199
int size = dataModel.size();
200
TopComponent[] result = new TopComponent[size];
201
for (int i=0; i < size; i++) {
202
result[i] = (TopComponent) dataModel.getTab(i).getComponent();
207
public void setActive(boolean active) {
208
slideBar.setActive(active);
211
public void setIconAt(int index, Icon icon) {
212
dataModel.setIcon(index, icon);
215
public void setTitleAt(int index, String title) {
216
dataModel.setText(index, title);
219
public void setToolTipTextAt(int index, String toolTip) {
220
// XXX - not supported yet
223
public void setTopComponents(TopComponent[] tcs, TopComponent selected) {
224
TabData[] data = new TabData[tcs.length];
226
for(int i = 0; i < tcs.length; i++) {
227
TopComponent tc = tcs[i];
228
Image icon = tc.getIcon();
229
String displayName = WindowManagerImpl.getInstance().getTopComponentDisplayName(tc);
230
data[i] = new TabData(
232
icon == null ? null : new ImageIcon(icon),
233
displayName == null ? "" : displayName, // NOI18N
234
tc.getToolTipText());
235
if (selected == tcs[i]) {
240
dataModel.setTabs(data);
241
setSelectedComponent(selected);
244
public int getTabCount() {
245
return dataModel.size();
248
public int indexOf(Component tc) {
249
int size = dataModel.size();
250
for (int i=0; i < size; i++) {
251
if (tc == dataModel.getTab(i).getComponent()) return i;
256
public void insertComponent(String name, Icon icon, Component comp, String toolTip, int position) {
257
dataModel.addTab(position, new TabData(comp, icon, name, toolTip));
260
public void removeComponent(Component comp) {
261
int i = indexOf(comp);
262
dataModel.removeTab(i);
265
public void setSelectedComponent(Component comp) {
266
int newIndex = indexOf(comp);
267
if (selModel.getSelectedIndex() != newIndex) {
268
selModel.setSelectedIndex(newIndex);
270
if (comp instanceof TopComponent) {
271
//Inelegant to do this here, but it guarantees blinking stops
272
TopComponent tc = (TopComponent) comp;
273
tc.cancelRequestAttention();
277
public int tabForCoordinate(Point p) {
278
return slideBar.tabForCoordinate(p.x, p.y);
281
public Component getComponent() {
285
/*************** No DnD support yet **************/
287
public Object getConstraintForLocation(Point location, boolean attachingPossible) {
288
int tab = slideBar.nextTabForCoordinate(location.x, location.y);
289
return Integer.valueOf(tab);
292
public Shape getIndicationForLocation(Point location, TopComponent startingTransfer, Point startingPoint, boolean attachingPossible) {
294
// int tab = tabForCoordinate(location);
295
int nextTab = slideBar.nextTabForCoordinate(location.x, location.y);
296
SlideBarDataModel sbdm = (SlideBarDataModel)dataModel;
297
if (getTabCount() != 0) {
299
Rectangle rect = getTabBounds(0);
300
if (sbdm.getOrientation() == SlideBarDataModel.SOUTH) {
302
rect.width = rect.width / 2;
305
rect.height = rect.height / 2;
308
} else if (nextTab < getTabCount()) {
309
Rectangle rect1 = getTabBounds(nextTab - 1);
310
Rectangle rect2 = getTabBounds(nextTab);
311
Rectangle result = new Rectangle();
312
if (sbdm.getOrientation() == SlideBarDataModel.SOUTH) {
314
result.height = rect1.height;
315
result.x = rect1.x + (rect1.width / 2);
316
result.width = rect2.x + (rect2.width / 2) - result.x;
319
result.width = rect1.width;
320
result.y = rect1.y + (rect1.height / 2);
321
result.height = rect2.y + (rect2.height / 2) - result.y;
324
} else if (nextTab == getTabCount()) {
325
Rectangle rect = getTabBounds(getTabCount() - 1);
326
if (sbdm.getOrientation() == SlideBarDataModel.SOUTH) {
327
rect.x = rect.x + rect.width;
329
rect.y = rect.y + rect.height;
334
Rectangle rect = slideBar.getBounds();
335
if (sbdm.getOrientation() == SlideBarDataModel.SOUTH) {
336
return new Rectangle(10, 0, 50, 20);
338
return new Rectangle(0, 10, 20, 50);
341
public Image createImageOfTab(int tabIndex) {
342
TabData dt = slideBar.getModel().getTab(tabIndex);
343
if (dt.getComponent() instanceof TopComponent) {
345
JLabel lbl = new JLabel(dt.getText());
346
int width = lbl.getFontMetrics(lbl.getFont()).stringWidth(dt.getText());
347
int height = lbl.getFontMetrics(lbl.getFont()).getHeight();
348
Image img = ((TopComponent)dt.getComponent()).getIcon();
349
lbl.setIcon(new ImageIcon(img));
350
width = width + (img.getWidth(null) == -1 ? 16 : img.getWidth(null)) + 6;
351
height = Math.max(height + 5, img.getHeight(null) == -1 ? 21 : 5 + img.getHeight(null));
353
GraphicsConfiguration config = GraphicsEnvironment.getLocalGraphicsEnvironment()
354
.getDefaultScreenDevice().getDefaultConfiguration();
357
BufferedImage image = config.createCompatibleImage(width, height);
358
Graphics2D g = image.createGraphics();
359
g.setColor(lbl.getForeground());
360
g.setFont(lbl.getFont());
361
g.drawImage(img, 0, 0, null);
362
g.drawString(dt.getText(), 18, height / 2);
370
/** Add action for disabling slide */
371
public Action[] getPopupActions(Action[] defaultActions, int tabIndex) {
372
boolean isMDI = WindowManagerImpl.getInstance().getEditorAreaState() == Constants.EDITOR_AREA_JOINED;
373
Action[] result = new Action[defaultActions.length + (isMDI ? 1 : 0)];
374
System.arraycopy(defaultActions, 0, result, 0, defaultActions.length);
376
result[defaultActions.length] =
377
new ActionUtils.AutoHideWindowAction(slideBar, tabIndex, true);
382
public Rectangle getTabBounds(int tabIndex) {
383
return slideBar.getTabBounds(tabIndex);