blob: 07d4df5aee7467ef5fb73f9eaf2430779314a93f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 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.internal;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
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.MenuItem;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.misc.UIStats;
import org.eclipse.ui.part.WorkbenchPart;
/**
* Provides the common behavior for both views
* and editor panes.
*/
public abstract class PartPane extends LayoutPart
implements Listener
{
public static final String PROP_ZOOMED = "zoomed"; //$NON-NLS-1$
private boolean isZoomed = false;
private MenuManager paneMenuManager;
protected IWorkbenchPartReference partReference;
protected WorkbenchPage page;
protected Composite control;
public static class Sashes {
public Sash left;
public Sash right;
public Sash top;
public Sash bottom;
}
/**
* Construct a pane for a part.
*/
public PartPane(IWorkbenchPartReference partReference, WorkbenchPage workbenchPage) {
super(partReference.getId());
this.partReference = partReference;
this.page = workbenchPage;
((WorkbenchPartReference)partReference).setPane(this);
}
/**
* Factory method for creating the SWT Control hierarchy for this Pane's child.
*/
protected void createChildControl() {
final IWorkbenchPart part[] = new IWorkbenchPart[]{partReference.getPart(false)};
if(part[0] == null)
return;
if(control == null)
return;
final Composite content = new Composite(control, SWT.NONE);
content.setLayout(new FillLayout());
String error = WorkbenchMessages.format("PartPane.unableToCreate", new Object[] {partReference.getTitle()}); //$NON-NLS-1$
Platform.run(new SafeRunnable(error) {
public void run() {
try {
UIStats.start(UIStats.CREATE_PART_CONTROL,id);
part[0].createPartControl(content);
} finally {
UIStats.end(UIStats.CREATE_PART_CONTROL,id);
}
}
public void handleException(Throwable e) {
// Log error.
Workbench wb = (Workbench)PlatformUI.getWorkbench();
if (!wb.isStarting())
super.handleException(e);
// Dispose old part.
Control children[] = content.getChildren();
for (int i = 0; i < children.length; i++){
children[i].dispose();
}
// Create new part.
IWorkbenchPart newPart = createErrorPart((WorkbenchPart)part[0]);
part[0].getSite().setSelectionProvider(null);
newPart.createPartControl(content);
((WorkbenchPartReference)partReference).setPart(newPart);
part[0] = newPart;
}
});
page.addPart(partReference);
page.firePartOpened(part[0]);
}
public void addSizeMenuItem (Menu menu, int index) {
//Add size menu
MenuItem item = new MenuItem(menu, SWT.CASCADE, index);
item.setText(WorkbenchMessages.getString("PartPane.size")); //$NON-NLS-1$
Menu sizeMenu = new Menu(menu);
item.setMenu(sizeMenu);
addSizeItems(sizeMenu);
}
/**
*
*/
public void createControl(Composite parent) {
if (getControl() != null)
return;
// Create view form.
control = new Composite(parent, SWT.NONE);
control.setLayout(new FillLayout());
// the part should never be visible by default. It will be made visible
// by activation. This allows us to have views appear in tabs without
// becoming active by default.
control.setVisible(false);
// Create a title bar.
createTitleBar();
// Create content.
createChildControl();
// When the pane or any child gains focus, notify the workbench.
control.addListener(SWT.Activate, this);
}
protected abstract WorkbenchPart createErrorPart(WorkbenchPart oldPart);
/**
* Create a title bar for the pane if required.
*/
protected abstract void createTitleBar();
/**
* @private
*/
public void dispose() {
super.dispose();
if ((control != null) && (!control.isDisposed())) {
control.removeListener(SWT.Activate, this);
control.dispose();
control = null;
}
if ((paneMenuManager != null)) {
paneMenuManager.dispose();
paneMenuManager = null;
}
}
/**
* User has requested to close the pane.
* Take appropriate action depending on type.
*/
abstract public void doHide();
/**
* Zooms in on the part contained in this pane.
*/
protected void doZoom() {
if (getWindow() instanceof IWorkbenchWindow)
page.toggleZoom(partReference);
}
/**
* Gets the presentation bounds.
*/
public Rectangle getBounds() {
return getControl().getBounds();
}
/**
* Get the control.
*/
public Control getControl() {
return control;
}
/*
* @see LayoutPart#getMinimumHeight()
*/
public int getMinimumHeight() {
if (control == null || control.isDisposed())
return super.getMinimumHeight();
// account for the borders
return control.computeTrim(0, 0, 0, 0).height;
}
/**
* Answer the part child.
*/
public IWorkbenchPartReference getPartReference() {
return partReference;
}
/**
* @see Listener
*/
public void handleEvent(Event event) {
if (event.type == SWT.Activate)
requestActivation();
}
/**
* Return whether the pane is zoomed or not
*/
public boolean isZoomed() {
return isZoomed;
}
/**
* Move the control over another one.
*/
public void moveAbove(Control refControl) {
if (getControl() != null)
getControl().moveAbove(refControl);
}
/**
* Notify the workbook page that the part pane has
* been activated by the user.
*/
protected void requestActivation() {
this.page.requestActivation(partReference.getPart(true));
}
/**
* Sets the parent for this part.
*/
public void setContainer(ILayoutContainer container) {
super.setContainer(container);
}
/**
* Shows the receiver if <code>visible</code> is true otherwise hide it.
*/
public void setVisible(boolean makeVisible) {
super.setVisible(makeVisible);
if(makeVisible) //Make sure that the part is restored.
partReference.getPart(true);
}
/**
* Sets focus to this part.
*/
public void setFocus() {
requestActivation();
IWorkbenchPart part = partReference.getPart(true);
if (part != null) {
part.setFocus();
}
}
/**
* Sets the workbench page of the view.
*/
public void setWorkbenchPage(WorkbenchPage workbenchPage) {
this.page = workbenchPage;
}
/**
* Set whether the pane is zoomed or not
*/
public void setZoomed(boolean isZoomed) {
if (this.isZoomed == isZoomed)
return; // do nothing if we're already in the right state.
super.setZoomed(isZoomed);
this.isZoomed = isZoomed;
final Object[] listeners = getPropertyListeners().getListeners();
if (listeners.length > 0) {
Boolean oldValue = isZoomed ? Boolean.FALSE : Boolean.TRUE;
Boolean zoomed = isZoomed ? Boolean.TRUE : Boolean.FALSE;
PropertyChangeEvent event = new PropertyChangeEvent(this, PROP_ZOOMED, oldValue, zoomed);
for (int i = 0; i < listeners.length; ++i)
((IPropertyChangeListener)listeners[i]).propertyChange(event);
}
}
/**
* Informs the pane that it's window shell has
* been activated.
*/
/* package */ abstract void shellActivated();
/**
* Informs the pane that it's window shell has
* been deactivated.
*/
/* package */ abstract void shellDeactivated();
/**
* Indicate focus in part.
*/
public abstract void showFocus(boolean inFocus);
/**
* @see IPartDropTarget::targetPartFor
*/
public LayoutPart targetPartFor(LayoutPart dragSource) {
return this;
}
/**
* Show a title label menu for this pane.
*/
public abstract void showPaneMenu();
/**
* Show the context menu for this part.
*/
public abstract void showViewMenu();
/**
* Return the sashes around this part.
*/
protected abstract Sashes findSashes();
/**
* Enable the user to resize this part using
* the keyboard to move the specified sash
*/
protected void moveSash(final Sash sash) {
moveSash(sash, this);
}
public static void moveSash(final Sash sash, final LayoutPart toGetFocusWhenDone) {
final KeyListener listener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.character == SWT.ESC || e.character == '\r') {
if(toGetFocusWhenDone != null)
toGetFocusWhenDone.setFocus();
}
}
};
sash.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
sash.addKeyListener(listener);
}
public void focusLost(FocusEvent e) {
sash.setBackground(null);
sash.removeKeyListener(listener);
}
});
sash.setFocus();
}
/**
* Add a menu item to the Size Menu
*/
protected void addSizeItem(Menu sizeMenu, String labelMessage, final Sash sash) {
MenuItem item = new MenuItem(sizeMenu, SWT.NONE);
item.setText(labelMessage); //$NON-NLS-1$
item.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
moveSash(sash);
}
});
item.setEnabled(!isZoomed() && sash != null);
}
/**
* Returns the workbench page of this pane.
*/
public WorkbenchPage getPage() {
return page;
}
/**
* Add the Left,Right,Up,Botton menu items to the Size menu.
*/
protected void addSizeItems(Menu sizeMenu) {
Sashes sashes = findSashes();
addSizeItem(sizeMenu,
WorkbenchMessages.getString("PartPane.sizeLeft"), sashes.left); //$NON-NLS-1$
addSizeItem(sizeMenu,
WorkbenchMessages.getString("PartPane.sizeRight"), sashes.right); //$NON-NLS-1$
addSizeItem(sizeMenu,
WorkbenchMessages.getString("PartPane.sizeTop"), sashes.top); //$NON-NLS-1$
addSizeItem(sizeMenu,
WorkbenchMessages.getString("PartPane.sizeBottom"), sashes.bottom); //$NON-NLS-1$
}
/**
* Pin this part.
*/
protected void doDock() {
// do nothing
}
/**
* Set the busy state of the pane.
*/
public void setBusy(boolean isBusy) {
//Do nothing by default
}
/**
* Show a highlight for the receiver if it is
* not currently the part in the front of its
* presentation.
*
*/
public void showHighlight(){
//No nothing by default
}
/**
* Ensure that we are not in the zoomed before reparenting.
* TODO: I am certain this isn't correct but I'll be damned if I know what is.
*/
public void reparent(Composite newParent) {
if (isZoomed())
setZoomed(false);
super.reparent(newParent);
}
}