blob: 8b37da2ddd0d80e3276757cd841b9c07fb10411d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Rushan R. Gilmullin and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Rushan R. Gilmullin - initial API and implementation
*******************************************************************************/
package org.eclipse.osbp.vaaclipse.presentation.renderers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.e4.core.commands.ExpressionContext;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.SideValue;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
import org.eclipse.e4.ui.services.internal.events.EventBroker;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.osbp.vaaclipse.api.VaadinExecutorService;
import org.eclipse.osbp.vaaclipse.presentation.widgets.TrimmedWindowContent;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;
@SuppressWarnings("restriction")
public class TrimBarRenderer extends VaadinRenderer {
@Inject
MApplication app;
@Inject
EventBroker eventBroker;
@Inject
EModelService modelService;
@Inject
VaadinExecutorService execService;
private HashMap<MTrimBar, ArrayList<ArrayList<MTrimElement>>> pendingCleanup = new HashMap<MTrimBar, ArrayList<ArrayList<MTrimElement>>>();
@PostConstruct
public void subsrcribe() {
}
@PreDestroy
public void unsubscribe() {
}
@Override
public void createWidget(MUIElement element,
MElementContainer<MUIElement> parent) {
if (!(element instanceof MTrimBar)) {
return;
}
MTrimBar mTrimBar = (MTrimBar) element;
int orientation = mTrimBar.getSide().getValue();
AbstractLayout trimBar = null;
if (orientation == SideValue.BOTTOM_VALUE) {
trimBar = new CssLayout();
trimBar.addStyleName("horizontaltrimbar");
} else if (orientation == SideValue.TOP_VALUE) {
trimBar = new CssLayout();
trimBar.addStyleName("toptrimbar");
} else if (orientation == SideValue.LEFT_VALUE
|| orientation == SideValue.RIGHT_VALUE) {
trimBar = new VerticalLayout();
trimBar.addStyleName("verticaltrimbar");
}
trimBar.setSizeUndefined();
if (orientation == SideValue.BOTTOM_VALUE
|| orientation == SideValue.TOP_VALUE) {
trimBar.setWidth("100%");
}
element.setWidget(trimBar);
}
@Override
public void processContents(MElementContainer<MUIElement> container) {
final MTrimBar trimBar = (MTrimBar) ((MElementContainer<?>) container);
int orientation = trimBar.getSide().getValue();
AbstractLayout trimBarWidget = (AbstractLayout) container.getWidget();
if (orientation == SideValue.TOP_VALUE
|| orientation == SideValue.BOTTOM_VALUE)
trimBarWidget.setHeight(-1, Unit.PIXELS);
else
trimBarWidget.setWidth(-1, Unit.PIXELS);
boolean isFirst = true;
trimBarWidget.removeAllComponents();
for (MUIElement element : container.getChildren()) {
if (element.isToBeRendered()) {
ComponentContainer subToolbar = (ComponentContainer) element
.getWidget();
subToolbar.setVisible(element.isVisible());
if (subToolbar != null) {
if (orientation == SideValue.TOP_VALUE
|| orientation == SideValue.BOTTOM_VALUE)
subToolbar.addStyleName("horizontaltrimelement");
else
subToolbar.addStyleName("verticaltrimelement");
subToolbar.setSizeUndefined();
trimBarWidget.addComponent(subToolbar);
isFirst = false;
}
}
}
// ---
IEclipseContext ctx = getContext(container);
final ExpressionContext eContext = new ExpressionContext(ctx);
// visible when support for original trimbar elements (without
// contributed)
for (final MTrimElement child : trimBar.getChildren()) {
if (child.getVisibleWhen() != null) {
ctx.runAndTrack(new RunAndTrack() {
@Override
public boolean changed(IEclipseContext context) {
if (!trimBar.isToBeRendered() || !trimBar.isVisible()
|| trimBar.getWidget() == null) {
return false;
}
final boolean rc = ContributionsAnalyzer.isVisible(
(MCoreExpression) child.getVisibleWhen(),
eContext);
execService.invokeLater(new Runnable() {
@Override
public void run() {
child.setToBeRendered(rc);
}
});
return true;
}
});
}
}
// contributions
ArrayList<MTrimContribution> toContribute = new ArrayList<MTrimContribution>();
ContributionsAnalyzer.gatherTrimContributions(trimBar,
app.getTrimContributions(), trimBar.getElementId(),
toContribute, eContext);
addTrimContributions(trimBar, toContribute, ctx, eContext);
refreshVisibility(trimBar);
}
private void refreshVisibility(MTrimBar trimBar) {
AbstractLayout trimBarWidget = (AbstractLayout) trimBar.getWidget();
int orientation = trimBar.getSide().getValue();
trimBarWidget.setVisible(trimBarWidget.getComponentCount() != 0);
if (orientation == SideValue.TOP_VALUE) {
MWindow window = modelService.getTopLevelWindowFor(trimBar);
TrimmedWindowContent windowContent = (TrimmedWindowContent) ((Panel) window
.getWidget()).getContent();
Component topbar = windowContent.getTopbar();
if (topbar != null)
topbar.setVisible(trimBarWidget.getComponentCount() != 0);
}
}
private void addTrimContributions(final MTrimBar trimModel,
ArrayList<MTrimContribution> toContribute, IEclipseContext ctx,
final ExpressionContext eContext) {
HashSet<String> existingToolbarIds = new HashSet<String>();
for (MTrimElement item : trimModel.getChildren()) {
String id = item.getElementId();
if (item instanceof MToolBar && id != null) {
existingToolbarIds.add(id);
}
}
boolean done = toContribute.size() == 0;
while (!done) {
ArrayList<MTrimContribution> curList = new ArrayList<MTrimContribution>(
toContribute);
int retryCount = toContribute.size();
toContribute.clear();
for (final MTrimContribution contribution : curList) {
final ArrayList<MTrimElement> toRemove = new ArrayList<MTrimElement>();
if (!ContributionsAnalyzer.processAddition(trimModel,
contribution, toRemove, existingToolbarIds)) {
toContribute.add(contribution);
} else {
if (contribution.getVisibleWhen() != null) {
ctx.runAndTrack(new RunAndTrack() {
@Override
public boolean changed(IEclipseContext context) {
if (!trimModel.isToBeRendered()
|| !trimModel.isVisible()
|| trimModel.getWidget() == null) {
return false;
}
final boolean rc = ContributionsAnalyzer
.isVisible(contribution, eContext);
execService.invokeLater(new Runnable() {
@Override
public void run() {
for (MTrimElement child : toRemove) {
child.setToBeRendered(rc);
}
}
});
return true;
}
});
}
ArrayList<ArrayList<MTrimElement>> lists = pendingCleanup
.get(trimModel);
if (lists == null) {
lists = new ArrayList<ArrayList<MTrimElement>>();
pendingCleanup.put(trimModel, lists);
}
lists.add(toRemove);
}
}
// We're done if the retryList is now empty (everything done) or
// if the list hasn't changed at all (no hope)
done = (toContribute.size() == 0)
|| (toContribute.size() == retryCount);
}
}
@Override
public void addChildGui(MUIElement child,
MElementContainer<MUIElement> element) {
if (!(child instanceof MTrimElement && (MElementContainer<?>) element instanceof MTrimBar))
return;
MTrimBar trimBar = (MTrimBar) (MElementContainer<?>) element;
final Component childWidget = (Component) child.getWidget();
childWidget.setVisible(child.isVisible());
childWidget.setSizeUndefined();
int orientation = trimBar.getSide().getValue();
if (orientation == SideValue.TOP_VALUE
|| orientation == SideValue.BOTTOM_VALUE)
childWidget.addStyleName("horizontaltrimelement");
else
childWidget.addStyleName("verticaltrimelement");
int index = indexOf(child, element);
if (element.getWidget() instanceof CssLayout) {
CssLayout trimWidget = (CssLayout) element.getWidget();
trimWidget.addComponent(childWidget, index);
trimWidget.markAsDirty();
} else if (element.getWidget() instanceof AbstractOrderedLayout) {
AbstractOrderedLayout trimWidget = (AbstractOrderedLayout) element
.getWidget();
trimWidget.addComponent(childWidget, index);
trimWidget.markAsDirty();
}
refreshVisibility(trimBar);
}
@Override
public void removeChildGui(MUIElement child,
MElementContainer<MUIElement> element) {
if (!(child instanceof MTrimElement && (MElementContainer<?>) element instanceof MTrimBar))
return;
super.removeChildGui(child, element);
Component trimWidget = (Component) element.getWidget();
MTrimBar trimBar = (MTrimBar) (MElementContainer<?>) element;
refreshVisibility(trimBar);
trimWidget.markAsDirty();
}
}