blob: 29a62693d049acb287015c2be06145accb859113 [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 javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
import org.eclipse.e4.ui.model.application.MApplication;
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.menu.MDirectToolItem;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.osbp.vaaclipse.presentation.utils.GuiUtils;
import org.eclipse.osbp.vaaclipse.publicapi.resources.ResourceHelper;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import com.vaadin.server.Resource;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
@SuppressWarnings("restriction")
public class ToolBarRenderer extends BasicMenuToolbarTrimbarRenderer {
@Inject
private MApplication application;
@Inject
private EModelService modelService;
@Inject
IEventBroker eventBroker;
@PostConstruct
public void init() {
context.set(ToolBarRenderer.class, this);
}
@PreDestroy
public void contextDisposed() {
}
@Override
public void createWidget(MUIElement element,
MElementContainer<MUIElement> parent) {
if (!(element instanceof MToolBar)) {
return;
}
MToolBar toolbarModel = (MToolBar) element;
processContribution(toolbarModel);
AbstractLayout toolBarWidget;
if ((MElementContainer<?>) toolbarModel.getParent() instanceof MTrimBar) {
MTrimBar parentTrimBar = (MTrimBar) (MElementContainer<?>) toolbarModel
.getParent();
int orientation = parentTrimBar.getSide().getValue();
if (orientation == SideValue.TOP_VALUE
|| orientation == SideValue.BOTTOM_VALUE) {
toolBarWidget = new HorizontalLayout() {
@Override
public void addComponent(Component c) {
if (!c.getStyleName().contains("horizontalseparator"))
c.addStyleName("horizontaltoolbarlement");
super.addComponent(c);
}
@Override
public void addComponent(Component c, int index) {
if (!c.getStyleName().contains("horizontalseparator"))
c.addStyleName("horizontaltoolbarlement");
super.addComponent(c, index);
}
};
toolBarWidget.addStyleName("horizontaltoolbar");
} else {
toolBarWidget = new VerticalLayout() {
@Override
public void addComponent(Component c) {
if (!c.getStyleName().contains("verticalseparator"))
c.addStyleName("verticaltoolbarlement");
super.addComponent(c);
}
@Override
public void addComponent(Component c, int index) {
if (!c.getStyleName().contains("verticalseparator"))
c.addStyleName("verticaltoolbarlement");
super.addComponent(c, index);
}
};
toolBarWidget.addStyleName("verticaltoolbar");
}
Component separator = GuiUtils.createSeparator(toolbarModel);
if (separator != null)
toolBarWidget.addComponent(separator);
} else {
toolBarWidget = new HorizontalLayout();
Component separator = GuiUtils.createSeparator(toolbarModel);
if (separator != null)
toolBarWidget.addComponent(separator);
}
toolBarWidget.setSizeUndefined();
toolBarWidget.addStyleName("toolbar");
for (String css : toolbarModel.getTags()) {
toolBarWidget.addStyleName(css);
}
element.setWidget(toolBarWidget);
}
/**
* @param element
*/
private void processContribution(MToolBar toolbarModel) {
final ArrayList<MToolBarContribution> toContribute = new ArrayList<MToolBarContribution>();
ContributionsAnalyzer.XXXgatherToolBarContributions(toolbarModel,
application.getToolBarContributions(),
toolbarModel.getElementId(), toContribute);
generateContributions(toolbarModel, toContribute);
}
/**
* @param toolbarModel
* @param toContribute
*/
private void generateContributions(MToolBar toolbarModel,
ArrayList<MToolBarContribution> toContribute) {
AbstractLayout manager = (AbstractLayout) toolbarModel.getWidget();
boolean done = toContribute.size() == 0;
while (!done) {
ArrayList<MToolBarContribution> curList = new ArrayList<MToolBarContribution>(
toContribute);
int retryCount = toContribute.size();
toContribute.clear();
for (final MToolBarContribution contribution : curList) {
if (!processAddition(toolbarModel, manager, contribution)) {
toContribute.add(contribution);
}
}
// 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);
}
}
/**
* @param toolbarModel
* @param manager
* @param contribution
* @param existingSeparatorNames
* @return <code>true</code> if the contribution was successfuly processed
*/
private boolean processAddition(final MToolBar toolbarModel,
final AbstractLayout manager, MToolBarContribution contribution) {
final ToolBarContributionRecord record = new ToolBarContributionRecord(
toolbarModel, contribution, this);
if (!record.mergeIntoModel()) {
return false;
}
if (record.anyVisibleWhen()) {
final IEclipseContext parentContext = modelService
.getContainingContext(toolbarModel);
parentContext.runAndTrack(new RunAndTrack() {
@Override
public boolean changed(IEclipseContext context) {
if (toolbarModel.getWidget() == null) {
return false;
}
record.updateVisibility(parentContext.getActiveLeaf());
return true;
}
});
}
return true;
}
@Override
public void processContents(final MElementContainer<MUIElement> container) {
MToolBar toolBar = (MToolBar) (MElementContainer<?>) container;
AbstractLayout toolBarWidget = (AbstractLayout) container.getWidget();
if (toolBarWidget != null) {
for (MUIElement element : container.getChildren()) {
if (element instanceof MHandledToolItem
|| element instanceof MDirectToolItem) {
toolBarWidget.addComponent((Component) element.getWidget());
} else if (element instanceof MToolBarSeparator) {
toolBarWidget.addComponent(GuiUtils
.createSeparator(toolBar));
}
}
}
}
@Override
public void addChildGui(MUIElement child,
MElementContainer<MUIElement> element) {
if (!(child instanceof MToolBarElement && (MElementContainer<?>) element instanceof MToolBar))
return;
MToolBar toolBar = (MToolBar) (MElementContainer<?>) element;
AbstractOrderedLayout toolbarWidget = (AbstractOrderedLayout) element
.getWidget();
Component childWidget = (Component) child.getWidget();
if (toolbarWidget == null || childWidget == null)
return;
int index = indexOf(child, element)/* + 1 */; // +1 becouse the first
// element is toolbar
// drag handler
// (separator)
// if (element instanceof MToolBarSeparator) {
// toolbarWidget
// .addComponent(GuiUtils.createSeparator(toolBar), index);
// } else {
toolbarWidget.addComponent(childWidget, index);
// }
toolbarWidget.requestRepaint();
}
@Override
public void setVisible(MUIElement changedElement, boolean visible) {
((AbstractOrderedLayout) changedElement.getWidget())
.setVisible(visible);
}
@PostConstruct
public void postConstruct() {
eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
eventBroker.subscribe(UIEvents.Menu.TOPIC_ENABLED, itemUpdater);
eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN,
childrenMoveUpdater);
}
@PreDestroy
public void preDestroy() {
eventBroker.unsubscribe(itemUpdater);
eventBroker.unsubscribe(childrenMoveUpdater);
}
private EventHandler itemUpdater = new EventHandler() {
public void handleEvent(Event event) {
// Ensure that this event is for a MMenuItem
if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBar))
return;
MToolBar model = (MToolBar) event
.getProperty(UIEvents.EventTags.ELEMENT);
AbstractOrderedLayout ici = (AbstractOrderedLayout) model
.getWidget();
if (ici == null) {
return;
}
String attName = (String) event
.getProperty(UIEvents.EventTags.ATTNAME);
Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);
if (UIEvents.UILabel.ICONURI.equals(attName)) {
Resource icon = ResourceHelper
.createResource((String) newValue);
ici.setIcon(icon);
} else if (UIEvents.UILabel.TOOLTIP.equals(attName)) {
ici.setDescription((String) newValue);
} else if (UIEvents.Item.ENABLED.equals(attName)) {
ici.setEnabled((boolean) newValue);
}
}
};
private EventHandler childrenMoveUpdater = new EventHandler() {
@SuppressWarnings("unchecked")
public void handleEvent(Event event) {
// Ensure that this event is for a MMenuItem
if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MToolBar))
return;
MElementContainer<MUIElement> toolbar = (MElementContainer<MUIElement>) event
.getProperty(UIEvents.EventTags.ELEMENT);
String type = (String) event.getProperty(UIEvents.EventTags.TYPE);
// on move, we unrender an render the UI again
//
if (UIEvents.EventTypes.MOVE.equals(type)) {
for (MUIElement item : toolbar.getChildren()) {
removeChildGui(item, toolbar);
}
for (MUIElement item : toolbar.getChildren()) {
addChildGui(item, toolbar);
}
}
}
};
}