blob: 0790f20b278d61bfb4a03dfde6571497870a59dd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.examples.presentation.wrappedtabs;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ViewForm;
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.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.examples.presentation.PresentationImages;
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.PresentationUtil;
import org.eclipse.ui.presentations.StackDropResult;
import org.eclipse.ui.presentations.StackPresentation;
import org.eclipse.ui.themes.ITheme;
/**
* @since 3.0
*/
public class WrappedTabsPartPresentation extends StackPresentation {
private static class DropLocation {
int insertionPosition = 0;
IPresentablePart part;
boolean before;
}
private static final String PART_DATA = "part";
private boolean activeFocus = false;
/**
* Main widget for the presentation
*/
private Composite presentationControl;
/**
* Currently selected part
*/
private IPresentablePart current;
/**
* ToolBar that will be used to select the active presentable part
*/
private ToolBar toolBar;
/**
* ToolBar that will contain close, minimize, etc.
*/
private ToolBar upperRight;
/**
* close button
*/
private ToolItem close;
/**
* View menu button
*/
private ToolItem viewMenu;
/**
* Minimize button
*/
private ToolItem minView;
/**
* Show/hide toolbar button
*/
private ToolItem showToolbar;
private ToolBar titleIconToolbar;
/**
* Title icon
*/
private ToolItem titleIcon;
private MenuManager systemMenuManager = new MenuManager();
private ViewForm contentArea;
private Label contentDescription;
private Composite contentDescriptionWrapper;
private Composite clientArea;
private ProxyControl toolbarProxy;
/**
* Listener attached to all child parts. It responds to changes in part properties
*/
private IPropertyListener childPropertyChangeListener = new IPropertyListener() {
public void propertyChanged(Object source, int property) {
if (source instanceof IPresentablePart) {
IPresentablePart part = (IPresentablePart) source;
childPropertyChanged(part, property);
}
}
};
/**
* Drag listener for regions outside the toolbar
*/
Listener dragListener = new Listener() {
public void handleEvent(Event event) {
Point loc = new Point(event.x, event.y);
Control ctrl = (Control)event.widget;
getSite().dragStart(ctrl.toDisplay(loc), false);
}
};
/**
* Listener attached to all tool items. It removes listeners from the associated
* part when the tool item is destroyed. This is required to prevent memory leaks.
*/
private DisposeListener tabDisposeListener = new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (e.widget instanceof ToolItem) {
ToolItem item = (ToolItem)e.widget;
IPresentablePart part = getPartForTab(item);
part.removePropertyListener(childPropertyChangeListener);
}
}
};
/**
* This listener responds to selection events in all tool items.
*/
SelectionAdapter tabItemSelectionAdapter = new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
ToolItem toolItem = (ToolItem) e.widget;
IPresentablePart item = getPartForTab(toolItem);
if (item != null) {
// Clicking on the active tab should give focus to the current part
if (item == current) {
item.setFocus();
}
getSite().selectPart(item);
}
toolItem.setSelection(true);
}
};
/**
* Listener to changes made to the current theme. The presentation will
* redraw when the theme changes.
*/
private IPropertyChangeListener themeChangeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if(! presentationControl.isDisposed()) {
toolBar.setFont(PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry().get(WrappedTabsThemeConstants.TAB_FONT));
layout();
presentationControl.redraw();
}
}
};
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);
if (event.widget == toolBar) {
Point localPos = toolBar.toControl(globalPos);
ToolItem item = toolBar.getItem(localPos);
if (item != null) {
IPresentablePart part = getPartForTab(item);
getSite().selectPart(part);
showSystemMenu(globalPos);
return;
}
}
IPresentablePart part = getCurrent();
if (part != null) {
showSystemMenu(globalPos);
}
}
};
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 = new Point(e.x, e.y);
// Ignore double-clicks if we're currently over a toolbar item
if (isOverToolItem(e)) {
return;
}
if (current != null) {
current.setFocus();
}
}
public boolean isOverToolItem(MouseEvent e) {
Point p = new Point(e.x, e.y);
Control control = (Control)e.widget;
if (control instanceof ToolBar) {
ToolItem item = ((ToolBar)control).getItem(p);
if (item != null) {
return true;
}
}
return false;
}
// If we double-click on the toolbar, maximize the presentation
public void mouseDoubleClick(MouseEvent e) {
// Ignore double-clicks if we're currently over a toolbar item
if (isOverToolItem(e) && e.widget == upperRight) {
return;
}
if (getSite().getState() == IStackPresentationSite.STATE_MAXIMIZED) {
getSite().setState(IStackPresentationSite.STATE_RESTORED);
} else {
getSite().setState(IStackPresentationSite.STATE_MAXIMIZED);
}
}
};
private boolean showIconOnTabs;
private static final int SPACING_WIDTH = 2;
private static final String SHOWING_TOOLBAR = "showing_toolbar";
private static final String TAG_PART = "part";
private static final String TAG_ID = "id";
private static final String TAG_TOOLBAR = "showing_toolbar";
/**
* Creates a new bare-bones part presentation, given the parent composite and
* an IStackPresentationSite interface that will be used to communicate with
* the workbench.
*
* @param stackSite interface to the workbench
*/
public WrappedTabsPartPresentation(Composite parent,
IStackPresentationSite stackSite, boolean showIconOnTabs) {
super(stackSite);
this.showIconOnTabs = showIconOnTabs;
// Create a top-level control for the presentation.
presentationControl = new Composite(parent, SWT.NONE);
// Add a dispose listener. This will call the presentationDisposed()
// method when the widget is destroyed.
presentationControl.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
presentationDisposed();
}
});
upperRight = new ToolBar(presentationControl, SWT.RIGHT | SWT.FLAT);
//initPresentationWidget(upperRight);
titleIconToolbar = new ToolBar(presentationControl, SWT.RIGHT | SWT.FLAT);
titleIcon = new ToolItem(titleIconToolbar, SWT.PUSH);
titleIconToolbar.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
showPaneMenu();
}
});
titleIconToolbar.addListener(SWT.MenuDetect, menuListener);
titleIconToolbar.setVisible(!showIconOnTabs);
toolBar = new ToolBar(presentationControl, SWT.WRAP | SWT.RIGHT | SWT.FLAT);
toolBar.addListener(SWT.MenuDetect, menuListener);
toolBar.addMouseListener(mouseListener);
toolBar.setFont(PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry().get(WrappedTabsThemeConstants.TAB_FONT));
// Add drag listener to the toolbar
PresentationUtil.addDragListener(toolBar, new Listener() {
public void handleEvent(Event event) {
Point loc = new Point(event.x, event.y);
ToolItem item = toolBar.getItem(loc);
if (item != null) {
// Move the current part
IPresentablePart draggedItem = getPartForTab(item);
draggedItem.setFocus();
getSite().dragStart(draggedItem, toolBar.toDisplay(loc), false);
} else {
// Move the stack
getSite().dragStart(toolBar.toDisplay(loc), false);
}
}
});
presentationControl.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
Rectangle clientArea = presentationControl.getClientArea();
e.gc.setLineWidth(getBorderWidth());
e.gc.setForeground(getBorderColor());
e.gc.drawRectangle(clientArea.x, clientArea.y, clientArea.width-1, clientArea.height-1);
Rectangle contentAreaBounds = contentArea.getBounds();
int ypos = contentAreaBounds.y - 1;
e.gc.drawLine(clientArea.x, ypos, clientArea.x + clientArea.width - 1, ypos);
}
});
initPresentationWidget(presentationControl);
contentArea = new ViewForm(presentationControl, SWT.FLAT);
initPresentationWidget(contentArea);
contentDescriptionWrapper = new Composite(contentArea, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginWidth = 4;
layout.marginHeight = 2;
contentDescriptionWrapper.setLayout(layout);
GridData data = new GridData(GridData.FILL_BOTH);
data.verticalAlignment = GridData.VERTICAL_ALIGN_CENTER;
contentDescription = new Label(contentDescriptionWrapper, SWT.NONE);
initPresentationWidget(contentDescription);
contentDescription.setLayoutData(data);
clientArea = new Composite(contentArea, SWT.NONE);
clientArea.setVisible(false);
contentArea.setContent(clientArea);
toolbarProxy = new ProxyControl(contentArea);
createButtonBar();
createSystemMenu();
PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(themeChangeListener);
}
private void initPresentationWidget(Control toInitialize) {
PresentationUtil.addDragListener(toInitialize, dragListener);
toInitialize.addListener(SWT.MenuDetect, menuListener);
toInitialize.addMouseListener(mouseListener);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#restoreState(org.eclipse.ui.presentations.IPresentationSerializer, org.eclipse.ui.IMemento)
*/
public void restoreState(IPresentationSerializer serializer, IMemento savedState) {
IMemento[] parts = savedState.getChildren(TAG_PART);
for (int idx = 0; idx < parts.length; idx++) {
String id = parts[idx].getString(TAG_ID);
if (id != null) {
IPresentablePart part = serializer.getPart(id);
if (part != null) {
addPart(part, null);
Integer hasToolbar = parts[idx].getInteger(TAG_TOOLBAR);
showToolbar(part, hasToolbar != null && hasToolbar.intValue() != 0);
}
}
}
}
/* (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);
IPresentablePart[] parts = getParts();
for (int i = 0; i < parts.length; i++) {
IPresentablePart part = parts[i];
IMemento childMem = memento.createChild(TAG_PART);
childMem.putString(TAG_ID, context.getId(part));
childMem.putInteger(TAG_TOOLBAR, isShowingToolbar(part) ? 1 : 0);
}
}
public IPresentablePart[] getParts() {
ToolItem[] items = toolBar.getItems();
IPresentablePart[] result = new IPresentablePart[items.length];
for (int idx = 0; idx < items.length; idx++) {
ToolItem item = items[idx];
IPresentablePart next = getPartForTab(item);
result[idx] = next;
}
return result;
}
private final void createSystemMenu() {
getSite().addSystemActions(systemMenuManager);
systemMenuManager.add(new ChangeStackStateContributionItem(getSite()));
systemMenuManager.add(new ShowToolbarContributionItem(this));
// This example presentation includes the part list at the end of the system menu
systemMenuManager.add(new Separator());
systemMenuManager.add(new CloseContributionItem(this));
systemMenuManager.add(new CloseOthersContributionItem(this));
systemMenuManager.add(new CloseAllContributionItem(this));
systemMenuManager.add(new PartListContributionItem(this, getSite()));
}
private void createButtonBar() {
viewMenu = new ToolItem(upperRight, SWT.PUSH);
upperRight.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
Point p = new Point(event.x, event.y);
Rectangle r = viewMenu.getBounds();
if (r.contains(p)) {
showSystemMenu();
}
}
});
viewMenu.setImage(PresentationImages.getImage(PresentationImages.VIEW_MENU));
showToolbar = new ToolItem(upperRight, SWT.PUSH);
showToolbar.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
showToolbar(!isShowingToolbar());
}
});
if (getSite().supportsState(IStackPresentationSite.STATE_MINIMIZED)) {
minView = new ToolItem(upperRight, SWT.PUSH);
minView.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (current != null) {
if (getSite().getState() == IStackPresentationSite.STATE_MINIMIZED) {
getSite().setState(IStackPresentationSite.STATE_RESTORED);
} else {
getSite().setState(IStackPresentationSite.STATE_MINIMIZED);
}
}
}
});
}
close = new ToolItem(upperRight, SWT.PUSH);
close.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (current != null) {
getSite().close(new IPresentablePart[] {current});
}
}
});
close.setImage(PresentationImages.getImage(PresentationImages.CLOSE_VIEW));
updateToolbarImages();
}
private void updateToolbarImages() {
if (isShowingToolbar()) {
showToolbar.setImage(PresentationImages.getImage(PresentationImages.HIDE_TOOLBAR));
} else {
showToolbar.setImage(PresentationImages.getImage(PresentationImages.SHOW_TOOLBAR));
}
if (minView != null) {
String minImage = (getSite().getState() == IStackPresentationSite.STATE_MINIMIZED) ?
PresentationImages.RESTORE_VIEW : PresentationImages.MIN_VIEW;
minView.setImage(PresentationImages.getImage(minImage));
}
upperRight.pack(true);
upperRight.redraw();
}
public void refreshButtonBarEnablement() {
close.setEnabled(current != null && getSite().isCloseable(current));
titleIcon.setEnabled(current != null && current.getMenu() != null);
showToolbar.setEnabled(current != null && current.getToolBar() != null);
}
public void dispose() {
// Dispose the main presentation widget. This will cause
// presentationDisposed to be called, which will do the real cleanup.
presentationControl.dispose();
}
/**
* Perform any cleanup. This method should remove any listeners that were
* attached to other objects. This gets called when the presentation
* widget is disposed. This is safer than cleaning up in the dispose()
* method, since this code will run even if some unusual circumstance
* destroys the Shell without first calling dispose().
*/
protected void presentationDisposed() {
// Remove any listeners that were attached to any
// global Eclipse resources. This is necessary in order to prevent
// memory leaks.
PlatformUI.getWorkbench().getThemeManager().removePropertyChangeListener(themeChangeListener);
}
public void setBounds(Rectangle bounds) {
Rectangle newBounds = Geometry.copy(bounds);
if (newBounds.width == 0) {
// Workaround a bug in the Eclipse 3.0 release: minimized presentations will be
// given a width of 0.
newBounds.width = presentationControl.getBounds().width;
}
if (getSite().getState() == IStackPresentationSite.STATE_MINIMIZED) {
newBounds.height = computeMinimumSize().y;
}
// Set the bounds of the presentation widge
presentationControl.setBounds(newBounds);
// Update the bounds of the currently visible part
layout();
}
/**
* Lay out the presentation's widgets
*/
private void layout() {
// Determine the inner bounds of the presentation
Rectangle presentationClientArea = presentationControl.getClientArea();
presentationClientArea.x += getBorderWidth();
presentationClientArea.width -= getBorderWidth() * 2;
presentationClientArea.y += getBorderWidth();
presentationClientArea.height -= getBorderWidth() * 2;
// Position the upper-right toolbar
Point upperRightSize = upperRight.getSize();
int upperRightStartX = presentationClientArea.x + presentationClientArea.width - upperRightSize.x - SPACING_WIDTH;
Rectangle upperRightBounds = new Rectangle(upperRightStartX,
presentationClientArea.y + SPACING_WIDTH, upperRightSize.x, upperRightSize.y);
upperRight.setBounds(upperRightBounds);
int tabStart = presentationClientArea.x + SPACING_WIDTH + 1;
int verticalSpaceRequired = 0;
if (!showIconOnTabs) {
Point upperLeftSize;
upperLeftSize = titleIconToolbar.getSize();
Rectangle upperLeftBounds = new Rectangle(presentationClientArea.x + SPACING_WIDTH,
presentationClientArea.y + SPACING_WIDTH,
upperLeftSize.x, upperLeftSize.y);
titleIconToolbar.setBounds(upperLeftBounds);
tabStart = upperLeftBounds.x + upperLeftBounds.width + SPACING_WIDTH;
verticalSpaceRequired = upperLeftSize.y;
}
int availableTabWidth = upperRightStartX - tabStart - SPACING_WIDTH;
Point toolbarSize = toolBar.computeSize(availableTabWidth, SWT.DEFAULT);
int minToolbarWidth = WrappedTabsUtil.getMaximumItemWidth(toolBar);
toolBar.setBounds(tabStart,
presentationClientArea.y + SPACING_WIDTH,
availableTabWidth, toolbarSize.y);
verticalSpaceRequired = Math.max(verticalSpaceRequired, upperRightSize.y);
verticalSpaceRequired = Math.max(verticalSpaceRequired, toolbarSize.y);
int verticalOffset = presentationClientArea.y + verticalSpaceRequired + getBorderWidth() + 2 * SPACING_WIDTH;
contentArea.setBounds(presentationClientArea.x, verticalOffset,
presentationClientArea.width, presentationClientArea.height - verticalOffset);
if (isShowingToolbar()) {
contentArea.setTopLeft(contentDescriptionWrapper);
contentArea.setTopCenter(toolbarProxy.getControl());
} else {
contentArea.setTopLeft(null);
contentArea.setTopCenter(null);
}
contentArea.layout();
// Position the view's widgets
if (current != null) {
Rectangle clientRectangle = clientArea.getBounds();
Point clientAreaStart = presentationControl.getParent().toControl(
contentArea.toDisplay(clientRectangle.x, clientRectangle.y));
current.setBounds(new Rectangle(clientAreaStart.x,
clientAreaStart.y,
clientRectangle.width,
clientRectangle.height));
}
}
private int getBorderWidth() {
return PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getInt(WrappedTabsThemeConstants.BORDER_SIZE);
}
public Point computeMinimumSize() {
Point minSize = new Point(100, 16);
Point upperLeftSize = titleIconToolbar.getSize();
Point toolBarSize = toolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
int BORDER_WIDTH = getBorderWidth();
Point result = new Point(minSize.x + upperLeftSize.x + 3 * SPACING_WIDTH + 2 * BORDER_WIDTH,
Math.max(Math.max(upperLeftSize.y, minSize.y), toolBarSize.y)
+ 2 * SPACING_WIDTH + 2 * BORDER_WIDTH);
return result;
}
public void setVisible(boolean isVisible) {
// Make the presentation widget visible
presentationControl.setVisible(isVisible);
// Make the currently visible part visible
if (current != null) {
current.setVisible(isVisible);
if (current.getToolBar() != null) {
current.getToolBar().setVisible(isVisible && isShowingToolbar());
}
}
if (isVisible) {
// Restore the bounds of the currently visible part.
// IPartPresentations can be used by multiple StackPresentations,
// although only one such presentation is ever visible at a time.
// It is possible that some other presentation has changed the
// bounds of the part since it was last visible, so we need to
// update the part's bounds when the presentation becomes visible.
layout();
}
}
private void clearSelection() {
// If there was an existing part selected, make it invisible
if (current != null) {
current.setVisible(false);
}
current = null;
}
public void currentPartChanged() {
boolean layoutNeeded = false;
if (titleIcon.getImage() != current.getTitleImage()) {
titleIcon.setImage(current.getTitleImage());
titleIcon.setDisabledImage(current.getTitleImage());
titleIconToolbar.pack(true);
titleIconToolbar.redraw();
layoutNeeded = true;
}
if (!contentDescription.getText().equals(current.getTitleStatus())) {
contentDescription.setText(current.getTitleStatus());
layoutNeeded = true;
}
if (current.getToolBar() != null) {
if (isShowingToolbar()) {
current.getToolBar().setVisible(true);
layoutNeeded = true;
} else {
current.getToolBar().setVisible(false);
}
toolbarProxy.setTargetControl(current.getToolBar());
}
if (layoutNeeded) {
layout();
}
}
public void selectPart(IPresentablePart toSelect) {
// Ignore redundant selections
if (toSelect == current) {
return;
}
clearSelection();
// Select the new part
current = toSelect;
// Ordering is important here. We need to make the part
// visible before updating its bounds, or the call to setBounds
// may be ignored.
if (current != null) {
// Make the newly selected part visible
current.setVisible(true);
ToolItem[] items = toolBar.getItems();
for (int idx = 0; idx < items.length; idx++) {
ToolItem item = items[idx];
item.setSelection(getPartForTab(item) == current);
}
currentPartChanged();
}
refreshButtonBarEnablement();
updateToolbarImages();
// Update the bounds of the newly selected part
layout();
}
public Control[] getTabList(IPresentablePart part) {
return new Control[] {part.getControl()};
}
public Control getControl() {
return presentationControl;
}
private int indexOf(IPresentablePart part) {
ToolItem item = getTab(part);
if (item == null) {
return -1;
}
return toolBar.indexOf(item);
}
public void addPart(IPresentablePart newPart, Object cookie) {
if (getTab(newPart) != null) {
return;
}
int position = toolBar.getItemCount();
// If this part is being added due to a drag/drop operation,
// determine the correct insertion position
if (cookie instanceof DropLocation) {
DropLocation location = (DropLocation)cookie;
position = indexOf(location.part);
// If we can't find the tab, then fall back to the
// insertionPosition field
if (position == -1) {
position = location.insertionPosition;
} else {
if (!location.before) {
position++;
}
}
}
// Ignore the cookie for now, since we don't support drag-and-drop yet.
ToolItem toolItem = new ToolItem(toolBar, SWT.RADIO, position);
// Attach the newPart pointer to the ToolItem. This is used for getPartForTab
// to determine which part is associated with the tool item
toolItem.setData(PART_DATA, newPart);
// Attach a property change listener to the part. This will update the ToolItem
// to reflect changes in the part.
newPart.addPropertyListener(childPropertyChangeListener);
// Attach a dispose listener to the item. This removes the above property
// change listener from the part when the item is destroyed. This prevents
// memory leaks.
toolItem.addDisposeListener(tabDisposeListener);
// Listen to selection events in the new tool item
toolItem.addSelectionListener(tabItemSelectionAdapter);
// Initialize the tab for this part
initTab(toolItem, newPart);
layout();
toolBar.layout(true);
presentationControl.redraw();
}
protected void initTab(ToolItem item, IPresentablePart part) {
String tabName = getTabText(part);
if (!tabName.equals(item.getText())) {
item.setText(tabName);
}
if (!(part.getTitleToolTip().equals(item.getToolTipText()))) {
item.setToolTipText(part.getTitleToolTip());
}
if (showIconOnTabs && part.getTitleImage() != item.getImage()) {
item.setImage(part.getTitleImage());
}
}
/**
* Returns the decorated tab text for the given part. By default, we attach
* a star to indicate dirty tabs.
*
* @param part part whose text is being computed
* @return the decorated tab text for the given part
*/
protected String getTabText(IPresentablePart part) {
String result = part.getName();
if (part.isDirty()) {
result = "*" + result;
}
return result;
}
/**
* Removes the given part from the stack.
*
* @param oldPart the part to remove (not null)
*/
public void removePart(IPresentablePart oldPart) {
// If we're removing the currently selected part, clear the selection
if (oldPart == current) {
clearSelection();
refreshButtonBarEnablement();
}
ToolItem item = getTab(oldPart);
// Don't need to do anything if the part has already been removed
if (item == null) {
return;
}
// Dispose the tab. The dispose listener on the item
// will handle all the cleanup.
item.dispose();
layout();
presentationControl.redraw();
}
/**
* Called whenever a property changes for one of the parts in this
* presentation.
*
* @param part
* @param property
*/
protected void childPropertyChanged(IPresentablePart part, int property) {
ToolItem toolItem = getTab(part);
// If there is no tab for this part, just ignore the property change
if (toolItem == null) {
return;
}
initTab(toolItem, part);
if (part == current) {
currentPartChanged();
}
}
/**
* Returns the tab associated with the given part or null if none
*
* @param part the part to check for
* @return the tab associated with the given part or null if none
*/
protected final ToolItem getTab(IPresentablePart part) {
ToolItem[] items = toolBar.getItems();
for (int idx = 0; idx < items.length; idx++) {
ToolItem item = items[idx];
if (getPartForTab(item) == part) {
return item;
}
}
return null;
}
/**
* Returns the part associated with the given tab, or null if none.
*
* @param item the tab to query
* @return the part associated with the given tab or null if none
*/
protected final IPresentablePart getPartForTab(ToolItem item) {
return (IPresentablePart)item.getData(PART_DATA);
}
public StackDropResult dragOver(Control currentControl, Point location) {
Point localCoordinates = toolBar.toControl(location);
// Ignore drag operations that aren't on top of the toolbar we're using
// for tabs.
if (toolBar.getClientArea().contains(localCoordinates)) {
DropLocation dropLocation = new DropLocation();
ToolItem item = toolBar.getItem(localCoordinates);
if (item == null) {
item = toolBar.getItem(toolBar.getItemCount() - 1);
}
Rectangle itemBounds = item.getBounds();
dropLocation.before = (localCoordinates.x - itemBounds.x < itemBounds.width / 2);
dropLocation.part = getPartForTab(item);
// Also store the current index of the part we're dragging over. We will use
// the index if the part no longer exists at the time the drop occurs (ie:
// if we're dragging an item over itself)
dropLocation.insertionPosition = toolBar.indexOf(item);
Point displayCoordinates = toolBar.toDisplay(itemBounds.x, itemBounds.y);
Rectangle bounds = new Rectangle(displayCoordinates.x, displayCoordinates.y,
4, itemBounds.height);
if (!dropLocation.before) {
bounds.x += itemBounds.width;
}
return new StackDropResult(bounds, dropLocation);
}
return null;
}
public void setActive(int newState) {
activeFocus = (newState == AS_ACTIVE_FOCUS);
presentationControl.redraw();
}
public void setState(int state) {
updateToolbarImages();
}
public void showPaneMenu(Point location) {
if (current == null) {
return;
}
IPartMenu menu = current.getMenu();
if (menu == null) {
return;
}
menu.showMenu(location);
}
public void showPaneMenu() {
Rectangle bounds = titleIconToolbar.getBounds();
Point location = titleIconToolbar.getParent().toDisplay(bounds.x, bounds.y + bounds.height);
showPaneMenu(location);
}
public void showSystemMenu() {
Rectangle bounds = viewMenu.getBounds();
Point displayPos = viewMenu.getParent().toDisplay(bounds.x, bounds.y + bounds.height);
showSystemMenu(displayPos);
}
public void showSystemMenu(Point displayPos) {
Menu aMenu = systemMenuManager.createContextMenu(presentationControl);
systemMenuManager.update(true);
aMenu.setLocation(displayPos.x, displayPos.y);
aMenu.setVisible(true);
}
/* (non-Javadoc)
* @see org.eclipse.ui.presentations.StackPresentation#showPartList()
*/
public void showPartList() {
// The part list opens when the user presses ctrl-e to open the list
// of editors. In this presentation, the part list is part of the system menu,
// so opening the part list is equivalent to opening the system menu.
showSystemMenu();
}
protected void showToolbar(IPresentablePart part, boolean shouldShow) {
if (shouldShow != isShowingToolbar(part)) {
ToolItem tab = getTab(part);
tab.setData(SHOWING_TOOLBAR, shouldShow ? SHOWING_TOOLBAR : null);
if (part == current) {
Control toolbar = part.getToolBar();
if (toolbar != null) {
toolbar.setVisible(shouldShow);
}
layout();
updateToolbarImages();
if (getSite().getState() == IStackPresentationSite.STATE_MINIMIZED) {
getSite().setState(IStackPresentationSite.STATE_RESTORED);
}
}
}
}
/**
* @param selection
*/
public void showToolbar(boolean selection) {
if (current != null) {
showToolbar(current, selection);
}
}
public IPresentablePart getCurrent() {
return current;
}
private boolean isShowingToolbar(IPresentablePart part) {
ToolItem tab = getTab(part);
return tab.getData(SHOWING_TOOLBAR) != null;
}
public boolean isShowingToolbar() {
if (current == null) {
return false;
}
return isShowingToolbar(current);
}
/**
* @param parts
*/
public void close(IPresentablePart[] parts) {
getSite().close(parts);
}
private Color getBorderColor() {
ITheme current = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
if(activeFocus) {
return current.getColorRegistry().get(WrappedTabsThemeConstants.BORDER_COLOR_FOCUS);
} else {
return current.getColorRegistry().get(WrappedTabsThemeConstants.BORDER_COLOR_NOFOCUS);
}
}
}