blob: b9ea226ea12cea4aa7b189af9551a13e2d1c43c3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 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.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.preferences.IDynamicPropertyMap;
import org.eclipse.ui.internal.preferences.PreferenceStoreAdapter;
import org.eclipse.ui.internal.preferences.PreferencesAdapter;
import org.eclipse.ui.internal.preferences.PropertyMapAdapter;
import org.eclipse.ui.internal.preferences.ThemeManagerAdapter;
import org.eclipse.ui.internal.presentations.defaultpresentation.DefaultPartList;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.presentations.IPartMenu;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IPresentationSerializer;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;
/**
* @since 3.0
*/
public final class TabbedStackPresentation extends StackPresentation {
private PresentablePartFolder folder;
private ISystemMenu systemMenu;
private ISystemMenu partList;
private PreferenceStoreAdapter apiPreferences = new PreferenceStoreAdapter(PrefUtil
.getAPIPreferenceStore());
private ThemeManagerAdapter themePreferences = new ThemeManagerAdapter(
PlatformUI.getWorkbench().getThemeManager());
private TabOrder tabs;
private TabDragHandler dragBehavior;
private boolean initializing = true;
private int ignoreSelectionChanges = 0;
private TabFolderListener tabFolderListener = new TabFolderListener() {
public void handleEvent(TabFolderEvent e) {
switch (e.type) {
case TabFolderEvent.EVENT_MINIMIZE: {
getSite().setState(IStackPresentationSite.STATE_MINIMIZED);
break;
}
case TabFolderEvent.EVENT_MAXIMIZE: {
getSite().setState(IStackPresentationSite.STATE_MAXIMIZED);
break;
}
case TabFolderEvent.EVENT_RESTORE: {
getSite().setState(IStackPresentationSite.STATE_RESTORED);
break;
}
case TabFolderEvent.EVENT_CLOSE: {
IPresentablePart part = folder.getPartForTab(e.tab);
if (part != null) {
getSite().close(new IPresentablePart[] { part });
}
break;
}
case TabFolderEvent.EVENT_SHOW_LIST: {
showPartList();
break;
}
case TabFolderEvent.EVENT_GIVE_FOCUS_TO_PART: {
IPresentablePart part = getSite().getSelectedPart();
if (part != null) {
part.setFocus();
}
break;
}
case TabFolderEvent.EVENT_PANE_MENU: {
TabbedStackPresentation.this.showPaneMenu(folder.getPartForTab(e.tab), new Point(e.x, e.y));
break;
}
case TabFolderEvent.EVENT_DRAG_START: {
AbstractTabItem beingDragged = e.tab;
Point initialLocation = new Point(e.x, e.y);
if (beingDragged == null) {
getSite().dragStart(initialLocation, false);
} else {
IPresentablePart part = folder.getPartForTab(beingDragged);
try {
dragStart = folder.indexOf(part);
getSite().dragStart(part, initialLocation, false);
} finally {
dragStart = -1;
}
}
break;
}
case TabFolderEvent.EVENT_TAB_SELECTED: {
if (ignoreSelectionChanges > 0) {
return;
}
IPresentablePart part = folder.getPartForTab(e.tab);
if (part != null) {
getSite().selectPart(part);
}
break;
}
case TabFolderEvent.EVENT_SYSTEM_MENU: {
IPresentablePart part = folder.getPartForTab(e.tab);
if (part == null) {
part = getSite().getSelectedPart();
}
if (part != null) {
showSystemMenu(new Point(e.x, e.y), part);
}
break;
}
}
}
};
private int dragStart = -1;
private Map prefs = new HashMap();
public TabbedStackPresentation(IStackPresentationSite site, AbstractTabFolder widget, ISystemMenu systemMenu) {
this(site, new PresentablePartFolder(widget), systemMenu);
}
public TabbedStackPresentation(IStackPresentationSite site, PresentablePartFolder folder, ISystemMenu systemMenu) {
this(site, folder, new LeftToRightTabOrder(folder), new ReplaceDragHandler(folder.getTabFolder()), systemMenu);
}
public TabbedStackPresentation(IStackPresentationSite site,
PresentablePartFolder newFolder, TabOrder tabs, TabDragHandler dragBehavior, ISystemMenu systemMenu) {
super(site);
this.systemMenu = systemMenu;
this.folder = newFolder;
this.tabs = tabs;
this.dragBehavior = dragBehavior;
// Add a dispose listener. This will call the presentationDisposed()
// method when the widget is destroyed.
folder.getTabFolder().getControl().addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
presentationDisposed();
}
});
folder.getTabFolder().addListener(tabFolderListener);
this.partList = new DefaultPartList(site, newFolder);
}
/**
* Restores a presentation from a previously stored state
*
* @param serializer (not null)
* @param savedState (not null)
*/
public void restoreState(IPresentationSerializer serializer,
IMemento savedState) {
tabs.restoreState(serializer, savedState);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#saveState(org.eclipse.ui.presentations.IPresentationSerializer, org.eclipse.ui.IMemento)
*/
public void saveState(IPresentationSerializer context, IMemento memento) {
super.saveState(context, memento);
tabs.saveState(context, memento);
}
/**
* Returns true iff the presentation has been disposed
*
* @return true iff the presentation has been disposed
*/
private boolean isDisposed() {
return folder == null || folder.isDisposed();
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#setBounds(org.eclipse.swt.graphics.Rectangle)
*/
public void setBounds(Rectangle bounds) {
folder.setBounds(bounds);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#computeMinimumSize()
*/
public Point computeMinimumSize() {
return folder.getTabFolder().computeSize(SWT.DEFAULT, SWT.DEFAULT);
}
/* (non-Javadoc)
* @see org.eclipse.ui.ISizeProvider#computePreferredSize(boolean, int, int, int)
*/
public int computePreferredSize(boolean width, int availableParallel,
int availablePerpendicular, int preferredResult) {
if (preferredResult != INFINITE || getSite().getState() == IStackPresentationSite.STATE_MINIMIZED) {
int minSize = 0;
if (width) {
int heightHint = availablePerpendicular == INFINITE ? SWT.DEFAULT : availablePerpendicular;
minSize = folder.getTabFolder().computeSize(SWT.DEFAULT, heightHint).x;
} else {
int widthHint = availablePerpendicular == INFINITE ? SWT.DEFAULT : availablePerpendicular;
minSize = folder.getTabFolder().computeSize(widthHint, SWT.DEFAULT).y;
}
if (getSite().getState() == IStackPresentationSite.STATE_MINIMIZED) {
return minSize;
}
return Math.max(minSize, preferredResult);
}
return INFINITE;
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#showPartList()
*/
public void showPartList() {
if (partList != null) {
final int numberOfParts = folder.getTabFolder().getItemCount();
if (numberOfParts > 0) {
partList.show(getControl(), folder.getTabFolder()
.getPartListLocation(), getSite().getSelectedPart());
}
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#dispose()
*/
public void dispose() {
// Dispose the tab folder's widgetry
folder.getTabFolder().getControl().dispose();
}
/**
* Called when the tab folder is disposed.
*/
private void presentationDisposed() {
apiPreferences.dispose();
themePreferences.dispose();
Iterator iter = prefs.values().iterator();
while(iter.hasNext()) {
PropertyMapAdapter next = (PropertyMapAdapter)iter.next();
next.dispose();
}
// if (systemMenu != null) {
// systemMenu.dispose();
// }
//
// if (partList != null) {
// partList.dispose();
// }
systemMenu = null;
partList = null;
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#setActive(int)
*/
public void setActive(int newState) {
folder.getTabFolder().setActive(newState);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#setVisible(boolean)
*/
public void setVisible(boolean isVisible) {
IPresentablePart current = getSite().getSelectedPart();
if (current != null) {
current.setVisible(isVisible);
}
folder.setVisible(isVisible);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#setState(int)
*/
public void setState(int state) {
folder.getTabFolder().setState(state);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#getControl()
*/
public Control getControl() {
return folder.getTabFolder().getControl();
}
/**
* @return AbstractTabFolder the presentation's tab folder
*/
public AbstractTabFolder getTabFolder() {
return folder.getTabFolder();
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#addPart(org.eclipse.ui.presentations.IPresentablePart, java.lang.Object)
*/
public void addPart(IPresentablePart newPart, Object cookie) {
ignoreSelectionChanges++;
try {
if (initializing) {
tabs.addInitial(newPart);
} else {
if (cookie == null) {
tabs.add(newPart);
} else {
int insertionPoint = dragBehavior
.getInsertionPosition(cookie);
tabs.insert(newPart, insertionPoint);
}
}
} finally {
ignoreSelectionChanges--;
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#movePart(org.eclipse.ui.presentations.IPresentablePart, java.lang.Object)
*/
public void movePart(IPresentablePart toMove, Object cookie) {
ignoreSelectionChanges++;
try {
int insertionPoint = dragBehavior.getInsertionPosition(cookie);
if (insertionPoint == folder.indexOf(toMove)) {
return;
}
tabs.move(toMove, insertionPoint);
} finally {
ignoreSelectionChanges--;
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#removePart(org.eclipse.ui.presentations.IPresentablePart)
*/
public void removePart(IPresentablePart oldPart) {
ignoreSelectionChanges++;
try {
tabs.remove(oldPart);
} finally {
ignoreSelectionChanges--;
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#selectPart(org.eclipse.ui.presentations.IPresentablePart)
*/
public void selectPart(IPresentablePart toSelect) {
initializing = false;
tabs.select(toSelect);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#dragOver(org.eclipse.swt.widgets.Control, org.eclipse.swt.graphics.Point)
*/
public StackDropResult dragOver(Control currentControl, Point location) {
return dragBehavior.dragOver(currentControl, location, dragStart);
}
/**
* @param part
* @param point
*/
public void showSystemMenu() {
showSystemMenu(folder.getTabFolder().getSystemMenuLocation(), getSite().getSelectedPart());
}
public void showSystemMenu(Point displayCoordinates, IPresentablePart context) {
if (context != getSite().getSelectedPart()) {
getSite().selectPart(context);
}
systemMenu.show(getControl(), displayCoordinates, context);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#showPaneMenu()
*/
public void showPaneMenu() {
IPresentablePart part = getSite().getSelectedPart();
if (part != null) {
showPaneMenu(part, folder.getTabFolder().getPaneMenuLocation());
}
}
public void showPaneMenu(IPresentablePart part, Point location) {
Assert.isTrue(!isDisposed());
IPartMenu menu = part.getMenu();
if (menu != null) {
menu.showMenu(location);
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#getTabList(org.eclipse.ui.presentations.IPresentablePart)
*/
public Control[] getTabList(IPresentablePart part) {
ArrayList list = new ArrayList();
if (folder.getTabFolder().getTabPosition() == SWT.BOTTOM) {
if (part.getControl() != null) {
list.add(part.getControl());
}
}
list.add(folder.getTabFolder().getControl());
if (part.getToolBar() != null) {
list.add(part.getToolBar());
}
if (folder.getTabFolder().getTabPosition() == SWT.TOP) {
if (part.getControl() != null) {
list.add(part.getControl());
}
}
return (Control[]) list.toArray(new Control[list.size()]);
}
public void setPartList(ISystemMenu menu) {
this.partList = menu;
}
public IDynamicPropertyMap getTheme() {
return themePreferences;
}
public IDynamicPropertyMap getApiPreferences() {
return apiPreferences;
}
public IDynamicPropertyMap getPluginPreferences(Plugin toQuery) {
String id = toQuery.getBundle().getSymbolicName();
IDynamicPropertyMap result = (IDynamicPropertyMap)prefs.get(id);
if (result != null) {
return result;
}
result = new PreferencesAdapter(toQuery.getPluginPreferences());
prefs.put(id, result);
return result;
}
/**
* Move the tabs around. This is for testing <b>ONLY</b>.
* @param part the part to move
* @param index the new index
* @since 3.2
*/
public void moveTab(IPresentablePart part, int index) {
tabs.move(part, index);
folder.layout(true);
}
/**
* Get the tab list. This is for testing <b>ONLY</b>.
* @return the presentable parts in order.
* @since 3.2
*/
public IPresentablePart[] getPartList() {
return tabs.getPartList();
}
}