blob: 776e4de41b1ce746a78e4db4f36deb714f943e7c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2006 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.util;
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.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.PresentationUtil;
/**
* @since 3.1
*/
public abstract class AbstractTabFolder {
private List listeners = new ArrayList(1);
private Control toolbar;
private int state;
public abstract Point computeSize(int widthHint, int heightHint);
public abstract AbstractTabItem add(int index, int flags);
public abstract Composite getContentParent();
public abstract void setContent(Control newContent);
public abstract AbstractTabItem[] getItems();
public abstract AbstractTabItem getSelection();
public abstract void setSelection(AbstractTabItem toSelect);
public abstract void setSelectedInfo(PartInfo info);
public abstract void enablePaneMenu(boolean enabled);
private int activeState = IStackPresentationSite.STATE_RESTORED;
private Listener menuListener = new Listener() {
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
*/
public void handleEvent(Event event) {
Point globalPos = new Point(event.x, event.y);
handleContextMenu(globalPos, event);
}
};
private Listener dragListener = new Listener() {
public void handleEvent(Event e) {
Point globalPos = ((Control)e.widget).toDisplay(e.x, e.y);
handleDragStarted(globalPos, e);
}
};
private MouseListener mouseListener = new MouseAdapter() {
// If we single-click on an empty space on the toolbar, move focus to the
// active control
public void mouseDown(MouseEvent e) {
Point p = ((Control)e.widget).toDisplay(e.x, e.y);
handleMouseDown(p, e);
}
// If we double-click on the toolbar, maximize the presentation
public void mouseDoubleClick(MouseEvent e) {
Point p = ((Control)e.widget).toDisplay(e.x, e.y);
handleDoubleClick(p, e);
}
};
public void setActive(int activeState) {
this.activeState = activeState;
}
public int getActive() {
return activeState;
}
/**
* Returns the location where the pane menu should be opened when activated
* by a keyboard shortcut (display coordinates)
*
* @return the location for the pane menu (display coordinates)
* @since 3.1
*/
public Point getPaneMenuLocation() {
return getControl().toDisplay(new Point(0,0));
}
/**
* Returns the location where the part list should be opened when activated
* by a keyboard shortcut (display coordinates)
*
* @return the location for the part list (display coordinates)
* @since 3.1
*/
public Point getPartListLocation() {
return getSystemMenuLocation();
}
/**
* Returns the location where the pane menu should be opened when activated
* by a keyboard shortcut (display coordinates)
*
* @return the location for the pane menu (display coordinates)
* @since 3.1
*/
public Point getSystemMenuLocation() {
return getControl().toDisplay(new Point(0,0));
}
/**
* Returns the parent composite that should be used for creating the toolbar.
* Any control passed into setToolbar must have this composite as its parent.
*
* @return the parent composite that should be used for creating the toolbar
*
* @since 3.1
*/
public abstract Composite getToolbarParent();
/**
* Returns the main control for this folder.
*
* @return the main control for the folder
* @since 3.1
*/
public abstract Control getControl();
public AbstractTabItem getItem(int idx) {
return getItems()[idx];
}
public AbstractTabItem getItem(Point toFind) {
AbstractTabItem[] items = getItems();
for (int i = 0; i < items.length; i++) {
AbstractTabItem item = items[i];
if (item.getBounds().contains(toFind)) {
return item;
}
}
return null;
}
public AbstractTabItem findItem(Object dataToFind) {
AbstractTabItem[] items = getItems();
for (int i = 0; i < items.length; i++) {
AbstractTabItem item = items[i];
if (item.getData() == dataToFind) {
return item;
}
}
return null;
}
/**
* Returns the index of the given item, or -1 if the given item is
* not found in this tab folder. Subclasses should override this if
* the underlying SWT widget has an equivalent method
*
* @param item item to find
* @return the index of the given item or -1
*/
public int indexOf(AbstractTabItem item) {
AbstractTabItem[] items = getItems();
for (int idx = 0; idx < items.length; idx++) {
AbstractTabItem next = items[idx];
if (next == item) {
return idx;
}
}
return -1;
}
public int getItemCount() {
return getItems().length;
}
public void setToolbar(Control toolbarControl) {
this.toolbar = toolbarControl;
}
public final Control getToolbar() {
return toolbar;
}
/**
* Sets the current state for the folder
*
* @param state one of the IStackPresentationSite.STATE_* constants
*/
public void setState(int state) {
this.state = state;
}
/**
* Returns the title area for this control (in the control's coordinate system)
*
* @return
*/
public abstract Rectangle getTabArea();
/**
* Called when the tab folder's shell becomes active or inactive. Subclasses
* can override this to change the appearance of the tabs based on activation.
*
* @param isActive
*/
public void shellActive(boolean isActive) {
}
/**
* Adds the given listener to this AbstractTabFolder
*
* @param newListener the listener to add
*/
public final void addListener(TabFolderListener newListener) {
listeners.add(newListener);
}
/**
* Removes the given listener from this AbstractTabFolder
*
* @param toRemove the listener to remove
*/
public final void removeListener(TabFolderListener toRemove) {
listeners.remove(toRemove);
}
public void flushToolbarSize() {
}
protected final void fireEvent(TabFolderEvent e) {
for (Iterator iter = listeners.iterator(); iter.hasNext();) {
TabFolderListener next = (TabFolderListener)iter.next();
next.handleEvent(e);
}
}
protected final void fireEvent(int id) {
fireEvent(new TabFolderEvent(id));
}
protected final void fireEvent(int id, AbstractTabItem w) {
fireEvent(new TabFolderEvent(id, w, 0, 0));
}
protected final void fireEvent(int id, AbstractTabItem w, Point pos) {
fireEvent(new TabFolderEvent(id, w, pos));
}
public void layout(boolean flushCache) {
}
public void setTabPosition(int tabPosition) {
}
public int getTabPosition() {
return SWT.TOP;
}
public int getState() {
return state;
}
protected void attachListeners(Control theControl, boolean recursive) {
theControl.addListener(SWT.MenuDetect, menuListener);
theControl.addMouseListener(mouseListener);
PresentationUtil.addDragListener(theControl, dragListener);
if (recursive && theControl instanceof Composite) {
Composite composite = (Composite) theControl;
Control[] children = composite.getChildren();
for (int i = 0; i < children.length; i++) {
Control control = children[i];
attachListeners(control, recursive);
}
}
}
protected void detachListeners(Control theControl, boolean recursive) {
theControl.removeListener(SWT.MenuDetect, menuListener);
theControl.removeMouseListener(mouseListener);
PresentationUtil.removeDragListener(theControl, dragListener);
if (recursive && theControl instanceof Composite) {
Composite composite = (Composite) theControl;
Control[] children = composite.getChildren();
for (int i = 0; i < children.length; i++) {
Control control = children[i];
detachListeners(control, recursive);
}
}
}
protected void handleContextMenu(Point displayPos, Event e) {
if (isOnBorder(displayPos)) {
return;
}
AbstractTabItem tab = getItem(displayPos);
fireEvent(TabFolderEvent.EVENT_SYSTEM_MENU, tab, displayPos);
}
protected void handleMouseDown(Point displayPos, MouseEvent e) {
fireEvent(TabFolderEvent.EVENT_GIVE_FOCUS_TO_PART);
}
protected void handleDoubleClick(Point displayPos, MouseEvent e) {
if (isOnBorder(displayPos)) {
return;
}
if (getState() == IStackPresentationSite.STATE_MAXIMIZED) {
fireEvent(TabFolderEvent.EVENT_RESTORE);
} else {
fireEvent(TabFolderEvent.EVENT_MAXIMIZE);
}
}
protected void handleDragStarted(Point displayPos, Event e) {
if (isOnBorder(displayPos)) {
return;
}
AbstractTabItem tab = getItem(displayPos);
fireEvent(TabFolderEvent.EVENT_DRAG_START, tab, displayPos);
}
/**
* Returns true iff the given point is on the border of the folder.
* By default, double-clicking, context menus, and drag/drop are disabled
* on the folder's border.
*
* @param toTest a point (display coordinates)
* @return true iff the point is on the presentation border
* @since 3.1
*/
public boolean isOnBorder(Point toTest) {
return false;
}
/**
* Set the folder to visible. This can be extended to propogate the
* visibility request to other components in the subclass.
*
* @param visible
* <code>true</code> - the folder is visible.
* @since 3.2
*/
public void setVisible(boolean visible) {
getControl().setVisible(visible);
}
/**
* Cause the folder to hide or show its
* Minimize and Maximize affordances.
*
* @param show
* <code>true</code> - the min/max buttons are visible.
* @since 3.3
*/
public void showMinMax(boolean show) {
}
}