blob: 370f8019f17133eb5b37e3a80d0c92788ca6fb60 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.presentations.r21.widgets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.internal.layout.SizeCache;
import org.eclipse.ui.internal.presentations.util.ProxyControl;
import org.eclipse.ui.presentations.IStackPresentationSite;
/**
* This class implements the tab folders that contains can contain two toolbars and
* status text. Wherever possible, the toolbars are aligned with the tabs.
* If there is not enough room beside the tabs, the toolbars are aligned with the status text. This
* is the same tab folder that is used to arrange views and editors in Eclipse.
* <p>
* This is closely related to DefaultPartPresentation, but they have different responsibilities. This
* is essentially a CTabFolder that can manage a toolbar. It should not depend on
* data structures from the workbench, and its public interface should only use SWT objects or
* listeners. DefaultPartPresentation uses a PaneFolder to arrange views or editors. Knowledge
* of higher-level data structures should go there.
* </p>
* <p>
* Although it is not actually a control, the public interface is much like
* an SWT control. Implementation-wise, this is actually a combination of a CTabFolder and
* a ViewForm. It encapsulates the details of moving the toolbar between the CTabFolder and
* the ViewForm, and provides a simpler interface to the ViewForm/CTabFolder.
* </p>
*
* @since 3.0
*/
public final class R21PaneFolder {
// Tab folder and associated proxy controls
private CTabFolder tabFolder;
// private Control titleAreaProxy;
// View form and associated proxy controls
private ViewForm viewForm;
private ProxyControl contentProxy;
private ProxyControl viewFormTopLeftProxy;
private ProxyControl viewFormTopRightProxy;
private ProxyControl viewFormTopCenterProxy;
// Cached sizes of the top-right and top-center controls
private SizeCache topRightCache = new SizeCache();
private SizeCache topCenterCache = new SizeCache();
private SizeCache topLeftCache = new SizeCache();
private int tabPos;
private boolean putTrimOnTop = false;
/**
* List of PaneFolderButtonListener
*/
private List buttonListeners = new ArrayList(1);
private int state = IStackPresentationSite.STATE_RESTORED;
/**
* State of the folder at the last mousedown event. This is used to prevent
* a mouseup over the minimize or maximize buttons from undoing a state change
* that was caused by the mousedown.
*/
private int mousedownState = -1;
// // CTabFolder listener
// private CTabFolder2Adapter expandListener = new CTabFolder2Adapter() {
// public void minimize(CTabFolderEvent event) {
// event.doit = false;
// notifyButtonListeners(IStackPresentationSite.STATE_MINIMIZED);
// }
//
// public void restore(CTabFolderEvent event) {
// event.doit = false;
// notifyButtonListeners(IStackPresentationSite.STATE_RESTORED);
// }
//
// public void maximize(CTabFolderEvent event) {
// event.doit = false;
// notifyButtonListeners(IStackPresentationSite.STATE_MAXIMIZED);
// }
//
// /* (non-Javadoc)
// * @see org.eclipse.swt.custom.CTabFolder2Adapter#close(org.eclipse.swt.custom.CTabFolderEvent)
// */
// public void close(CTabFolderEvent event) {
// event.doit = false;
// notifyCloseListeners((CTabItem)event.item);
// }
//
// public void showList(CTabFolderEvent event) {
// notifyShowListeners(event);
// }
//
// };
//
private MouseListener mouseListener = new MouseAdapter() {
public void mouseDown(MouseEvent e) {
mousedownState = getState();
}
public void mouseDoubleClick(MouseEvent e) {
}
};
/**
* Creates a pane folder. This will create exactly one child control in the
* given parent.
*
* @param parent
* @param flags
*/
public R21PaneFolder(Composite parent, int flags) {
// Initialize tab folder
{
tabFolder = new CTabFolder(parent, flags);
// // Create a proxy control to measure the title area of the tab folder
// titleAreaProxy = new Composite(tabFolder, SWT.NONE);
// titleAreaProxy.setVisible(false);
// tabFolder.setTopRight(titleAreaProxy, SWT.FILL);
// tabFolder.addCTabFolder2Listener(expandListener);
//
tabFolder.addMouseListener(mouseListener);
}
// Initialize view form
{
viewForm = new ViewForm(tabFolder, SWT.NONE);
// Only attach these to the viewForm when there's actuall a control to display
viewFormTopLeftProxy = new ProxyControl(viewForm);
viewFormTopCenterProxy = new ProxyControl(viewForm);
viewFormTopRightProxy = new ProxyControl(viewForm);
contentProxy = new ProxyControl(viewForm);
viewForm.setContent(contentProxy.getControl());
}
}
/**
* Return the main control for this pane folder
*
* @return Composite the control
*/
public Composite getControl() {
return tabFolder;
}
/**
* Sets the top-center control (usually a toolbar), or null if none.
* Note that the control can have any parent.
*
* @param topCenter the top-center control or null if none
*/
public void setTopCenter(Control topCenter) {
topCenterCache.setControl(topCenter);
if (topCenter != null) {
if (!putTrimOnTop) {
viewFormTopCenterProxy.setTarget(topCenterCache);
viewForm.setTopCenter(viewFormTopCenterProxy.getControl());
}
} else {
if (!putTrimOnTop) {
viewForm.setTopCenter(null);
}
}
}
/**
* Sets the top-right control (usually a dropdown), or null if none
*
* @param topRight
*/
public void setTopRight(Control topRight) {
topRightCache.setControl(topRight);
if (topRight != null) {
if (!putTrimOnTop) {
viewFormTopRightProxy.setTarget(topRightCache);
viewForm.setTopRight(viewFormTopRightProxy.getControl());
}
} else {
if (!putTrimOnTop) {
viewForm.setTopRight(null);
}
}
}
/**
* Sets the top-left control (usually a title label), or null if none
*
* @param topLeft
*/
public void setTopLeft(Control topLeft) {
if (topLeftCache.getControl() != topLeft) {
topLeftCache.setControl(topLeft);
// The top-left control always goes directly in the ViewForm
if (topLeft != null) {
viewFormTopLeftProxy.setTarget(topLeftCache);
viewForm.setTopLeft(viewFormTopLeftProxy.getControl());
} else {
viewFormTopLeftProxy.setTargetControl(null);
viewForm.setTopLeft(null);
}
}
}
/**
* Flush all of this folder's size caches to ensure they will be re-computed
* on the next layout.
*/
public void flush() {
topLeftCache.flush();
topRightCache.flush();
topCenterCache.flush();
}
/**
* Layout the receiver, flusing the cache if needed.
*
* @param flushCache
*/
public void layout(boolean flushCache) {
// Flush the cached sizes if necessary
if (flushCache)
flush();
Rectangle tabFolderClientArea = tabFolder.getClientArea();
// Hide tabs if there is only one
if (tabFolder.getItemCount() < 2) {
//Rectangle tabFolderBounds = tabFolder.getBounds();
int delta = getTabHeight() + 1;
tabFolderClientArea.height += delta;
if (getTabPosition() == SWT.TOP) {
tabFolderClientArea.y -= delta;
}
}
viewForm.setBounds(tabFolderClientArea);
viewFormTopRightProxy.layout();
viewFormTopLeftProxy.layout();
viewFormTopCenterProxy.layout();
}
/**
* Returns the client area for this PaneFolder, relative to the pane folder's control.
*
* @return Rectangle the client area
*/
public Rectangle getClientArea() {
Rectangle bounds = contentProxy.getControl().getBounds();
Rectangle formArea = viewForm.getBounds();
bounds.x += formArea.x;
bounds.y += formArea.y;
return bounds;
}
/**
* Returns the current state of the folder (as shown on the button icons)
*
* @return one of the IStackPresentationSite.STATE_* constants
*/
public int getState() {
return state;
}
/**
* @param buttonId one of the IStackPresentationSite.STATE_* constants
*/
protected void notifyButtonListeners(int buttonId) {
if (mousedownState == getState()) {
Iterator iter = buttonListeners.iterator();
while (iter.hasNext()) {
R21PaneFolderButtonListener listener = (R21PaneFolderButtonListener) iter
.next();
listener.stateButtonPressed(buttonId);
}
}
}
/**
* Notifies all listeners that the user clicked on the chevron
*
* @param event
*/
protected void notifyShowListeners(CTabFolderEvent event) {
Iterator iter = buttonListeners.iterator();
while (iter.hasNext()) {
R21PaneFolderButtonListener listener = (R21PaneFolderButtonListener) iter
.next();
listener.showList(event);
}
}
/**
* Notifies all listeners that the close button was pressed
*
* @param tabItem
*/
protected void notifyCloseListeners(CTabItem tabItem) {
Iterator iter = buttonListeners.iterator();
while (iter.hasNext()) {
R21PaneFolderButtonListener listener = (R21PaneFolderButtonListener) iter
.next();
listener.closeButtonPressed(tabItem);
}
}
/**
* @param listener
*/
public void addButtonListener(R21PaneFolderButtonListener listener) {
buttonListeners.add(listener);
}
/**
* @param listener
*/
public void removeButtonListener(R21PaneFolderButtonListener listener) {
buttonListeners.remove(listener);
}
/**
* @param newTabPosition
*/
public void setTabPosition(int newTabPosition) {
tabPos = newTabPosition;
tabFolder.setTabPosition(tabPos);
}
/**
* @return int the postion of the tab
*/
public int getTabPosition() {
return tabPos;
}
/**
* @return boolean <code>true</code> if the receiver has been disposed
*/
public boolean isDisposed() {
return tabFolder == null || tabFolder.isDisposed();
}
/**
* @param style
* @param index
* @return CTabItem the created item
*/
public CTabItem createItem(int style, int index) {
return new CTabItem(tabFolder, style, index);
}
// The remainder of the methods in this class redirect directly to CTabFolder methods
/**
* @param selection
*/
public void setSelection(int selection) {
tabFolder.setSelection(selection);
}
/**
* @param i
* @param j
* @param k
* @param l
* @return Rectangle the trim rectangle
*/
public Rectangle computeTrim(int i, int j, int k, int l) {
return tabFolder.computeTrim(i, j, k, l);
}
/**
* @param fgColor
*/
public void setSelectionForeground(Color fgColor) {
tabFolder.setSelectionForeground(fgColor);
}
/**
* @param idx
* @return CTabItem the indexed item
*/
public CTabItem getItem(int idx) {
return tabFolder.getItem(idx);
}
/**
* @return int the selected items index
*/
public int getSelectionIndex() {
return tabFolder.getSelectionIndex();
}
/**
* @return int the height of the tabs
*/
public int getTabHeight() {
return tabFolder.getTabHeight();
}
/**
* @param toFind
* @return int the index of the item to find
*/
public int indexOf(CTabItem toFind) {
return tabFolder.indexOf(toFind);
}
/**
* @param height
*/
public void setTabHeight(int height) {
tabFolder.setTabHeight(height);
}
/**
* @return int the item count
*/
public int getItemCount() {
return tabFolder.getItemCount();
}
/**
* @return CTabItem the items
*/
public CTabItem[] getItems() {
return tabFolder.getItems();
}
/**
* @param toGet
* @return CTabItem the indexed item
*/
public CTabItem getItem(Point toGet) {
return tabFolder.getItem(toGet);
}
/**
* @return CTabItem the selected item
*/
public CTabItem getSelection() {
return tabFolder.getSelection();
}
}