blob: 0024a15b6d0af4f3d0cb06b1f272433364add4a2 [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;
import java.util.ArrayList;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.Geometry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
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.swt.widgets.Menu;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.PresentationUtil;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;
/**
* A stack presentation using native widgets.
* <p>
* EXPERIMENTAL
* </p>
*
* @since 3.0
*/
public class NativeStackPresentation extends StackPresentation {
private TabFolder tabFolder;
private Listener dragListener;
private IPresentablePart current;
private MenuManager systemMenuManager = new MenuManager();
private static IPreferenceStore preferenceStore = WorkbenchPlugin.getDefault()
.getPreferenceStore();
// don't reset this dynamically, so just keep the information static.
// see bug:
// 75422 [Presentations] Switching presentation to R21 switches immediately, but only partially
private static int tabPos = preferenceStore.getInt(IWorkbenchPreferenceConstants.VIEW_TAB_POSITION);
private final static String TAB_DATA = NativeStackPresentation.class
.getName()
+ ".partId"; //$NON-NLS-1$
private MouseListener mouseListener = new MouseAdapter() {
public void mouseDown(MouseEvent e) {
// // PR#1GDEZ25 - If selection will change in mouse up ignore mouse down.
// // Else, set focus.
// TabItem newItem = tabFolder.getItem(new Point(e.x, e.y));
// if (newItem != null) {
// TabItem oldItem = tabFolder.getSelection();
// if (newItem != oldItem)
// return;
// }
if (current != null) {
current.setFocus();
}
}
};
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 pos = new Point(event.x, event.y);
// TabItem item = tabFolder.getItem(pos);
TabItem item = null;
IPresentablePart part = null;
if (item != null) {
part = getPartForTab(item);
}
showPaneMenu(part, pos);
}
};
private Listener selectionListener = new Listener() {
public void handleEvent(Event e) {
IPresentablePart item = getPartForTab((TabItem) e.item);
if (item != null) {
getSite().selectPart(item);
// item.setFocus();
}
}
};
private Listener resizeListener = new Listener() {
public void handleEvent(Event e) {
setControlSize();
}
};
private IPropertyListener childPropertyChangeListener = new IPropertyListener() {
public void propertyChanged(Object source, int property) {
if (isDisposed()) {
return;
}
if (source instanceof IPresentablePart) {
IPresentablePart part = (IPresentablePart) source;
childPropertyChanged(part, property);
}
}
};
private DisposeListener tabDisposeListener = new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (e.widget instanceof TabItem) {
TabItem item = (TabItem) e.widget;
IPresentablePart part = getPartForTab(item);
part.removePropertyListener(childPropertyChangeListener);
}
}
};
public NativeStackPresentation(Composite parent,
IStackPresentationSite stackSite) {
super(stackSite);
tabFolder = new TabFolder(parent, tabPos);
// listener to switch between visible tabItems
tabFolder.addListener(SWT.Selection, selectionListener);
// listener to resize visible components
tabFolder.addListener(SWT.Resize, resizeListener);
// listen for mouse down on tab to set focus.
tabFolder.addMouseListener(mouseListener);
tabFolder.addListener(SWT.MenuDetect, menuListener);
dragListener = new Listener() {
public void handleEvent(Event event) {
Point localPos = new Point(event.x, event.y);
// TabItem tabUnderPointer = tabFolder.getItem(localPos);
TabItem tabUnderPointer = null;
if (tabUnderPointer == null) {
return;
}
IPresentablePart part = getPartForTab(tabUnderPointer);
if (getSite().isPartMoveable(part)) {
getSite().dragStart(part, tabFolder.toDisplay(localPos),
false);
}
}
};
PresentationUtil.addDragListener(tabFolder, dragListener);
}
/**
* Returns the index of the tab for the given part, or returns tabFolder.getItemCount()
* if there is no such tab.
*
* @param part part being searched for
* @return the index of the tab for the given part, or the number of tabs
* if there is no such tab
*/
private final int indexOf(IPresentablePart part) {
if (part == null) {
return tabFolder.getItemCount();
}
TabItem[] items = tabFolder.getItems();
for (int idx = 0; idx < items.length; idx++) {
IPresentablePart tabPart = getPartForTab(items[idx]);
if (part == tabPart) {
return idx;
}
}
return items.length;
}
/**
* Returns the tab for the given part, or null if there is no such tab
*
* @param part the part being searched for
* @return the tab for the given part, or null if there is no such tab
*/
protected final TabItem getTab(IPresentablePart part) {
TabItem[] items = tabFolder.getItems();
int idx = indexOf(part);
if (idx < items.length) {
return items[idx];
}
return null;
}
/**
* @param part
* @param property
*/
protected void childPropertyChanged(IPresentablePart part, int property) {
TabItem tab = getTab(part);
initTab(tab, part);
}
protected final IPresentablePart getPartForTab(TabItem item) {
IPresentablePart part = (IPresentablePart) item.getData(TAB_DATA);
return part;
}
protected TabFolder getTabFolder() {
return tabFolder;
}
public boolean isDisposed() {
return tabFolder == null || tabFolder.isDisposed();
}
/**
* Set the size of a page in the folder.
*/
private void setControlSize() {
if (current == null || tabFolder == null) {
return;
}
// Rectangle bounds;
// @issue as above, the mere presence of a theme should not change the behaviour
// if ((mapTabToPart.size() > 1)
// || ((tabThemeDescriptor != null) && (mapTabToPart.size() >= 1)))
// bounds = calculatePageBounds(tabFolder);
// else
// bounds = tabFolder.getBounds();
current.setBounds(calculatePageBounds(tabFolder));
//current.moveAbove(tabFolder);
}
public static Rectangle calculatePageBounds(TabFolder folder) {
if (folder == null) {
return new Rectangle(0, 0, 0, 0);
}
Rectangle bounds = folder.getBounds();
Rectangle offset = folder.getClientArea();
bounds.x += offset.x;
bounds.y += offset.y;
bounds.width = offset.width;
bounds.height = offset.height;
return bounds;
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#dispose()
*/
public void dispose() {
if (isDisposed()) {
return;
}
PresentationUtil.removeDragListener(tabFolder, dragListener);
//systemMenuManager.dispose();
tabFolder.dispose();
tabFolder = null;
}
private TabItem createPartTab(IPresentablePart part, int tabIndex) {
TabItem tabItem = new TabItem(tabFolder, SWT.NONE, tabIndex);
tabItem.setData(TAB_DATA, part);
part.addPropertyListener(childPropertyChangeListener);
tabItem.addDisposeListener(tabDisposeListener);
initTab(tabItem, part);
return tabItem;
}
/**
* Initializes a tab for the given part. Sets the text, icon, tool tip,
* etc. This will also be called whenever a relevant property changes
* in the part to reflect those changes in the tab. Subclasses may override
* to change the appearance of tabs for a particular part.
*
* @param tabItem tab for the part
* @param part the part being displayed
*/
protected void initTab(TabItem tabItem, IPresentablePart part) {
tabItem.setText(part.getName());
tabItem.setToolTipText(part.getTitleToolTip());
Image tabImage = part.getTitleImage();
if (tabImage != tabItem.getImage()) {
tabItem.setImage(tabImage);
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.StackPresentation#addPart(org.eclipse.ui.internal.skins.IPresentablePart, org.eclipse.ui.internal.skins.IPresentablePart)
*/
public void addPart(IPresentablePart newPart, Object cookie) {
createPartTab(newPart, tabFolder.getItemCount());
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.StackPresentation#removePart(org.eclipse.ui.internal.skins.IPresentablePart)
*/
public void removePart(IPresentablePart oldPart) {
TabItem item = getTab(oldPart);
if (item == null) {
return;
}
oldPart.setVisible(false);
item.dispose();
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.StackPresentation#selectPart(org.eclipse.ui.internal.skins.IPresentablePart)
*/
public void selectPart(IPresentablePart toSelect) {
if (toSelect == current) {
return;
}
if (current != null) {
current.setVisible(false);
}
current = toSelect;
if (current != null) {
tabFolder.setSelection(indexOf(current));
current.setVisible(true);
setControlSize();
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#setBounds(org.eclipse.swt.graphics.Rectangle)
*/
public void setBounds(Rectangle bounds) {
tabFolder.setBounds(bounds);
setControlSize();
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#computeMinimumSize()
*/
public Point computeMinimumSize() {
return Geometry.getSize(tabFolder.computeTrim(0, 0, 0, 0));
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#setVisible(boolean)
*/
public void setVisible(boolean isVisible) {
if (current != null) {
current.setVisible(isVisible);
}
tabFolder.setVisible(isVisible);
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#setState(int)
*/
public void setState(int state) {
// tabFolder.setMinimized(state == IPresentationSite.STATE_MINIMIZED);
// tabFolder.setMaximized(state == IPresentationSite.STATE_MAXIMIZED);
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#getSystemMenuManager()
*/
public IMenuManager getSystemMenuManager() {
return systemMenuManager;
}
/**
* @param part
* @param point
*/
protected void showPaneMenu(IPresentablePart part, Point point) {
systemMenuManager.update(false);
Menu aMenu = systemMenuManager.createContextMenu(tabFolder.getParent());
aMenu.setLocation(point.x, point.y);
aMenu.setVisible(true);
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.Presentation#getControl()
*/
public Control getControl() {
return tabFolder;
}
/* (non-Javadoc)
* @see org.eclipse.ui.internal.skins.StackPresentation#dragOver(org.eclipse.swt.widgets.Control, org.eclipse.swt.graphics.Point)
*/
public StackDropResult dragOver(Control currentControl, Point location) {
// Determine which tab we're currently dragging over
// Point localPos = tabFolder.toControl(location);
// final TabItem tabUnderPointer = tabFolder.getItem(localPos);
final TabItem tabUnderPointer = null;
// This drop target only deals with tabs... if we're not dragging over
// a tab, exit.
if (tabUnderPointer == null) {
return null;
}
// return new StackDropResult(Geometry.toDisplay(tabFolder, tabUnderPointer.getBounds()),
// tabFolder.indexOf(tabUnderPointer));
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#showSystemMenu()
*/
public void showSystemMenu() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#showPaneMenu()
*/
public void showPaneMenu() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#getTabList(IPresentablePart)
*/
public Control[] getTabList(IPresentablePart part) {
ArrayList list = new ArrayList();
if (getControl() != null) {
list.add(getControl());
}
if (part.getToolBar() != null) {
list.add(part.getToolBar());
}
if (part.getControl() != null) {
list.add(part.getControl());
}
return (Control[]) list.toArray(new Control[list.size()]);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#getCurrentPart()
*/
public IPresentablePart getCurrentPart() {
return current;
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#setActive(int)
*/
public void setActive(int newState) {
}
}