001: /*
002: * Copyright (C) 2004 NNL Technology AB
003: * Visit www.infonode.net for information about InfoNode(R)
004: * products and how to contact NNL Technology AB.
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
019: * MA 02111-1307, USA.
020: */
021:
022: // $Id: TabWindow.java,v 1.57 2007/01/28 21:25:10 jesper Exp $
023: package net.infonode.docking;
024:
025: import net.infonode.docking.drag.DockingWindowDragSource;
026: import net.infonode.docking.drag.DockingWindowDragger;
027: import net.infonode.docking.drag.DockingWindowDraggerProvider;
028: import net.infonode.docking.internal.WriteContext;
029: import net.infonode.docking.internalutil.*;
030: import net.infonode.docking.model.TabWindowItem;
031: import net.infonode.docking.model.ViewWriter;
032: import net.infonode.docking.properties.TabWindowProperties;
033: import net.infonode.properties.base.Property;
034: import net.infonode.properties.propertymap.PropertyMap;
035: import net.infonode.properties.propertymap.PropertyMapTreeListener;
036: import net.infonode.properties.propertymap.PropertyMapWeakListenerManager;
037: import net.infonode.properties.util.PropertyChangeListener;
038: import net.infonode.tabbedpanel.TabAdapter;
039: import net.infonode.tabbedpanel.TabEvent;
040: import net.infonode.tabbedpanel.TabRemovedEvent;
041: import net.infonode.util.ArrayUtil;
042: import net.infonode.util.Direction;
043:
044: import javax.swing.*;
045: import java.awt.*;
046: import java.awt.event.MouseEvent;
047: import java.io.IOException;
048: import java.io.ObjectOutputStream;
049: import java.util.Map;
050:
051: /**
052: * A docking window containing a tabbed panel.
053: *
054: * @author $Author: jesper $
055: * @version $Revision: 1.57 $
056: */
057: public class TabWindow extends AbstractTabWindow {
058: private static final ButtonInfo[] buttonInfos = {
059: new UndockButtonInfo(
060: TabWindowProperties.UNDOCK_BUTTON_PROPERTIES),
061: new DockButtonInfo(
062: TabWindowProperties.DOCK_BUTTON_PROPERTIES),
063: new MinimizeButtonInfo(
064: TabWindowProperties.MINIMIZE_BUTTON_PROPERTIES),
065: new MaximizeButtonInfo(
066: TabWindowProperties.MAXIMIZE_BUTTON_PROPERTIES),
067: new RestoreButtonInfo(
068: TabWindowProperties.RESTORE_BUTTON_PROPERTIES),
069: new CloseButtonInfo(
070: TabWindowProperties.CLOSE_BUTTON_PROPERTIES) };
071:
072: private AbstractButton[] buttons = new AbstractButton[buttonInfos.length];
073:
074: private PropertyChangeListener minimumSizePropertiesListener = new PropertyChangeListener() {
075: public void propertyChanged(Property property,
076: Object valueContainer, Object oldValue, Object newValue) {
077: revalidate();
078: }
079: };
080: private PropertyMapTreeListener buttonFactoryListener = new PropertyMapTreeListener() {
081: public void propertyValuesChanged(Map changes) {
082: doUpdateButtonVisibility(changes);
083: }
084: };
085:
086: /**
087: * Creates an empty tab window.
088: */
089: public TabWindow() {
090: this ((DockingWindow) null);
091: }
092:
093: /**
094: * Creates a tab window with a tab containing the child window.
095: *
096: * @param window the child window
097: */
098: public TabWindow(DockingWindow window) {
099: this (window == null ? null : new DockingWindow[] { window });
100: }
101:
102: /**
103: * Creates a tab window with tabs for the child windows.
104: *
105: * @param windows the child windows
106: */
107: public TabWindow(DockingWindow[] windows) {
108: this (windows, null);
109: }
110:
111: protected TabWindow(DockingWindow[] windows,
112: TabWindowItem windowItem) {
113: super (true, windowItem == null ? new TabWindowItem()
114: : windowItem);
115:
116: setTabWindowProperties(((TabWindowItem) getWindowItem())
117: .getTabWindowProperties());
118:
119: PropertyMapWeakListenerManager.addWeakPropertyChangeListener(
120: getTabWindowProperties().getMap(),
121: TabWindowProperties.RESPECT_CHILD_WINDOW_MINIMUM_SIZE,
122: minimumSizePropertiesListener);
123:
124: new DockingWindowDragSource(getTabbedPanel(),
125: new DockingWindowDraggerProvider() {
126: public DockingWindowDragger getDragger(
127: MouseEvent mouseEvent) {
128: if (!getWindowProperties().getDragEnabled())
129: return null;
130:
131: Point p = SwingUtilities
132: .convertPoint((Component) mouseEvent
133: .getSource(), mouseEvent
134: .getPoint(), getTabbedPanel());
135:
136: return getTabbedPanel().tabAreaContainsPoint(p) ? (getChildWindowCount() == 1 ? getChildWindow(0)
137: : TabWindow.this )
138: .startDrag(getRootWindow())
139: : null;
140: }
141: });
142:
143: initMouseListener();
144: init();
145:
146: getTabbedPanel().addTabListener(new TabAdapter() {
147: public void tabAdded(TabEvent event) {
148: doUpdateButtonVisibility(null);
149: }
150:
151: public void tabRemoved(TabRemovedEvent event) {
152: doUpdateButtonVisibility(null);
153: }
154: });
155:
156: if (windows != null) {
157: for (int i = 0; i < windows.length; i++)
158: addTab(windows[i]);
159: }
160:
161: PropertyMapWeakListenerManager.addWeakTreeListener(
162: getTabWindowProperties().getMap(),
163: buttonFactoryListener);
164: }
165:
166: public TabWindowProperties getTabWindowProperties() {
167: return ((TabWindowItem) getWindowItem())
168: .getTabWindowProperties();
169: }
170:
171: protected void tabSelected(WindowTab tab) {
172: super .tabSelected(tab);
173:
174: if (getUpdateModel()) {
175: ((TabWindowItem) getWindowItem())
176: .setSelectedItem(tab == null ? null
177: : getWindowItem().getChildWindowContaining(
178: tab.getWindow().getWindowItem()));
179: }
180: }
181:
182: protected void update() {
183: }
184:
185: protected void updateButtonVisibility() {
186: doUpdateButtonVisibility(null);
187: }
188:
189: private void doUpdateButtonVisibility(Map changes) {
190: //System.out.println("%% Updating tab window buttons!");
191: //System.out.println(getTabbedPanel().getTabCount() + " " + getTabbedPanel().getSelectedTab() + " " + isMaximizable() + " " + isUndockable() + " " + isMinimizable() + " " + isClosable());
192: if (InternalDockingUtil.updateButtons(buttonInfos, buttons,
193: null, this , getTabWindowProperties().getMap(), changes)) {
194: updateTabAreaComponents();
195: }
196:
197: super .updateButtonVisibility();
198: }
199:
200: protected int getTabAreaComponentCount() {
201: return ArrayUtil.countNotNull(buttons);
202: }
203:
204: protected void getTabAreaComponents(int index,
205: JComponent[] components) {
206: for (int i = 0; i < buttons.length; i++)
207: if (buttons[i] != null)
208: components[index++] = buttons[i];
209: }
210:
211: protected void optimizeWindowLayout() {
212: if (getWindowParent() == null)
213: return;
214:
215: if (getTabbedPanel().getTabCount() == 0)
216: internalClose();
217: else if (getTabbedPanel().getTabCount() == 1
218: && (getWindowParent().showsWindowTitle() || !getChildWindow(
219: 0).needsTitleWindow())) {
220: getWindowParent().internalReplaceChildWindow(
221: this ,
222: getChildWindow(0).getBestFittedWindow(
223: getWindowParent()));
224: }
225: }
226:
227: public int addTab(DockingWindow w, int index) {
228: int actualIndex = super .addTab(w, index);
229: setSelectedTab(actualIndex);
230: return actualIndex;
231: }
232:
233: protected int addTabNoSelect(DockingWindow window, int index) {
234: DockingWindow beforeWindow = index == getChildWindowCount() ? null
235: : getChildWindow(index);
236:
237: int i = super .addTabNoSelect(window, index);
238:
239: if (getUpdateModel()) {
240: addWindowItem(window, beforeWindow == null ? -1
241: : getWindowItem().getWindowIndex(
242: getWindowItem().getChildWindowContaining(
243: beforeWindow.getWindowItem())));
244: }
245:
246: return i;
247: }
248:
249: protected void updateWindowItem(RootWindow rootWindow) {
250: super .updateWindowItem(rootWindow);
251: ((TabWindowItem) getWindowItem())
252: .setParentTabWindowProperties(rootWindow == null ? TabWindowItem.emptyProperties
253: : rootWindow.getRootWindowProperties()
254: .getTabWindowProperties());
255: }
256:
257: protected PropertyMap getPropertyObject() {
258: return getTabWindowProperties().getMap();
259: }
260:
261: protected PropertyMap createPropertyObject() {
262: return new TabWindowProperties().getMap();
263: }
264:
265: protected int getEdgeDepth(Direction dir) {
266: return dir == getTabbedPanel().getProperties()
267: .getTabAreaOrientation() ? 1 : super .getEdgeDepth(dir);
268: }
269:
270: protected int getChildEdgeDepth(DockingWindow window, Direction dir) {
271: return dir == getTabbedPanel().getProperties()
272: .getTabAreaOrientation() ? 0 : 1 + super
273: .getChildEdgeDepth(window, dir);
274: }
275:
276: protected DockingWindow getOptimizedWindow() {
277: return getChildWindowCount() == 1 ? getChildWindow(0)
278: .getOptimizedWindow() : super .getOptimizedWindow();
279: }
280:
281: protected boolean acceptsSplitWith(DockingWindow window) {
282: return super .acceptsSplitWith(window)
283: && (getChildWindowCount() != 1 || getChildWindow(0) != window);
284: }
285:
286: protected DockingWindow getBestFittedWindow(
287: DockingWindow parentWindow) {
288: return getChildWindowCount() == 1
289: && (!getChildWindow(0).needsTitleWindow() || parentWindow
290: .showsWindowTitle()) ? getChildWindow(0)
291: .getBestFittedWindow(parentWindow) : this ;
292: }
293:
294: protected void write(ObjectOutputStream out, WriteContext context,
295: ViewWriter viewWriter) throws IOException {
296: out.writeInt(WindowIds.TAB);
297: viewWriter.writeWindowItem(getWindowItem(), out, context);
298: super.write(out, context, viewWriter);
299: }
300:
301: }
|