blob: 956ad41725ec1b70305beecb69fc5cc1c1f068c0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2016 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
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 426460, 441150
* Andrey Loskutov <loskutov@gmx.de> - Bug 466524
* Simon Scholz <simon.scholz@vogella.com> - Bug 506306
*******************************************************************************/
package org.eclipse.e4.ui.workbench.renderers.swt;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.contributions.IContributionFactory;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
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.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
/**
* Default SWT renderer responsible for an MPart. See
* {@link WorkbenchRendererFactory}
*/
public class ContributedPartRenderer extends SWTPartRenderer {
@Inject
private IPresentationEngine engine;
@Inject
@Optional
private Logger logger;
private MPart partToActivate;
private Listener activationListener = new Listener() {
@Override
public void handleEvent(Event event) {
// we only want to activate the part if the activated widget is
// actually bound to a model element
MPart part = (MPart) event.widget.getData(OWNING_ME);
if (part != null) {
try {
partToActivate = part;
activate(partToActivate);
} finally {
partToActivate = null;
}
}
}
};
@Override
public Object createWidget(final MUIElement element, Object parent) {
if (!(element instanceof MPart) || !(parent instanceof Composite)) {
return null;
}
// retrieve context for this part
final MPart part = (MPart) element;
IEclipseContext localContext = part.getContext();
Widget parentWidget = (Widget) parent;
// retrieve existing Composite, e.g., for the e4 compatibility case
Composite partComposite = localContext.getLocal(Composite.class);
// does the part already have a composite in its contexts?
if (partComposite == null) {
final Composite newComposite = new Composite((Composite) parentWidget, SWT.NONE) {
/**
* Field to determine whether we are currently in the midst of
* granting focus to the part.
*/
private boolean beingFocused = false;
@Override
public boolean setFocus() {
if (!beingFocused) {
try {
// we are currently asking the part to take focus
beingFocused = true;
// delegate an attempt to set the focus here to the
// part's implementation (if there is one)
Object object = part.getObject();
if (object != null && isEnabled()) {
IPresentationEngine pe = part.getContext().get(IPresentationEngine.class);
pe.focusGui(part);
return true;
}
return super.setFocus();
} finally {
// we are done, unset our flag
beingFocused = false;
}
}
// already being focused, likely some strange recursive
// call,
// just return
return true;
}
};
newComposite.setLayout(new FillLayout(SWT.VERTICAL));
partComposite = newComposite;
}
bindWidget(element, partComposite);
localContext.set(Composite.class, partComposite);
IContributionFactory contributionFactory = localContext.get(IContributionFactory.class);
Object newPart = contributionFactory.create(part.getContributionURI(), localContext);
part.setObject(newPart);
return partComposite;
}
/**
* @param part
* @param description
*/
public static void setDescription(MPart part, String description) {
if (!(part.getWidget() instanceof Composite))
return;
Composite c = (Composite) part.getWidget();
// Do we already have a label?
if (c.getChildren().length == 3) {
Label label = (Label) c.getChildren()[0];
if (description == null)
description = ""; //$NON-NLS-1$
// hide the label if there is no text to show
boolean hasText = !description.equals(""); //$NON-NLS-1$
label.setVisible(hasText);
label.setText(description);
label.setToolTipText(description);
// also hide the separator
c.getChildren()[1].setVisible(hasText);
c.layout();
} else if (c.getChildren().length == 1) {
c.setLayout(new Layout() {
@Override
protected Point computeSize(Composite composite, int wHint,
int hHint, boolean flushCache) {
return new Point(0, 0);
}
@Override
protected void layout(Composite composite, boolean flushCache) {
Rectangle bounds = composite.getBounds();
if (composite.getChildren().length == 1) {
composite.getChildren()[0].setBounds(composite
.getBounds());
} else if (composite.getChildren().length == 3) {
Label label = (Label) composite.getChildren()[0];
Label separator = (Label) composite.getChildren()[1];
Control partCtrl = composite.getChildren()[2];
// if the label is empty, give it a zero size
int labelHeight = !label.getText().isEmpty() ? label
.computeSize(bounds.width, SWT.DEFAULT).y : 0;
label.setBounds(0, 0, bounds.width, labelHeight);
int separatorHeight = labelHeight > 0 ? separator
.computeSize(bounds.width, SWT.DEFAULT).y : 0;
separator.setBounds(0, labelHeight, bounds.width,
separatorHeight);
partCtrl.setBounds(0, labelHeight + separatorHeight,
bounds.width, bounds.height - labelHeight
- separatorHeight);
}
}
});
Label separator = new Label(c, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.moveAbove(null);
Label label = new Label(c, SWT.NONE);
label.setText(description);
label.setToolTipText(description);
label.moveAbove(null);
c.layout();
}
}
@Override
protected boolean requiresFocus(MPart element) {
if (element == partToActivate) {
return true;
}
return super.requiresFocus(element);
}
@Override
public void hookControllerLogic(final MUIElement me) {
super.hookControllerLogic(me);
if (!(me instanceof MPart)) {
return;
}
Widget widget = (Widget) me.getWidget();
if (widget instanceof Composite) {
widget.addListener(SWT.Activate, activationListener);
}
}
@Override
public Object getUIContainer(MUIElement element) {
if (element instanceof MToolBar) {
MUIElement container = modelService.getContainer(element);
MUIElement parent = container.getParent();
if (parent == null) {
MPlaceholder placeholder = container.getCurSharedRef();
if (placeholder != null) {
return placeholder.getParent().getWidget();
}
} else {
return parent.getWidget();
}
}
return super.getUIContainer(element);
}
@Override
public void disposeWidget(MUIElement element) {
if (element instanceof MPart) {
MPart part = (MPart) element;
MToolBar toolBar = part.getToolbar();
if (toolBar != null) {
Widget widget = (Widget) toolBar.getWidget();
if (widget != null) {
unbindWidget(toolBar);
widget.dispose();
}
}
for (MMenu menu : part.getMenus()) {
engine.removeGui(menu);
}
}
Composite parent = null;
if (element.getWidget() instanceof Composite) {
parent = ((Composite) element.getWidget()).getParent();
}
if (parent != null) {
try {
parent.setRedraw(false);
super.disposeWidget(element);
} finally {
parent.setRedraw(true);
}
} else {
super.disposeWidget(element);
}
}
}