blob: 23d48114167a52fbd596a0c0ea306675505bccd1 [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 javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.CanExecute;
import org.eclipse.e4.core.services.contributions.IContributionFactory;
import org.eclipse.e4.core.services.events.IEventBroker;
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.menu.MDirectMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MItem;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuItem;
//import org.eclipse.e4.ui.model.application.ui.menu.MOpaqueMenuItem;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.osbp.vaaclipse.presentation.utils.Commons;
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.MenuBar;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
@SuppressWarnings("restriction")
public class MenuItemRenderer extends ItemRenderer {
@Inject
IContributionFactory contributionFactory;
@Inject
IEventBroker eventBroker;
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 MMenuItem))
return;
MMenuItem itemModel = (MMenuItem) event
.getProperty(UIEvents.EventTags.ELEMENT);
MenuItem ici = (MenuItem) itemModel.getWidget();
if (ici == null) {
return;
}
String attName = (String) event
.getProperty(UIEvents.EventTags.ATTNAME);
String newValue = (String) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
if (UIEvents.UILabel.LABEL.equals(attName)) {
ici.setText(newValue);
} else if (UIEvents.UILabel.ICONURI.equals(attName)) {
Resource icon = ResourceHelper.createResource(newValue);
ici.setIcon(icon);
} else if (UIEvents.UILabel.TOOLTIP.equals(attName)) {
ici.setDescription(newValue);
}
}
};
private EventHandler enabledUpdater = new EventHandler() {
public void handleEvent(Event event) {
// Ensure that this event is for a MMenuItem
if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
return;
MMenuItem itemModel = (MMenuItem) event
.getProperty(UIEvents.EventTags.ELEMENT);
MenuItem ici = (MenuItem) itemModel.getWidget();
if (ici != null) {
Boolean newValue = (Boolean) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
ici.setEnabled(newValue);
}
}
};
private EventHandler selectedUpdater = new EventHandler() {
public void handleEvent(Event event) {
// Ensure that this event is for a MMenuItem
if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MMenuItem))
return;
MMenuItem itemModel = (MMenuItem) event
.getProperty(UIEvents.EventTags.ELEMENT);
MenuItem ici = (MenuItem) itemModel.getWidget();
if (ici != null) {
Boolean newValue = (Boolean) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
ici.setChecked(newValue);
}
}
};
@PostConstruct
public void postConstruct() {
eventBroker.subscribe(UIEvents.UILabel.TOPIC_ALL, itemUpdater);
eventBroker.subscribe(UIEvents.Item.TOPIC_ENABLED, enabledUpdater);
eventBroker.subscribe(UIEvents.Item.TOPIC_SELECTED, selectedUpdater);
eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN,
childrenMoveUpdater);
eventBroker.subscribe(UIEvents.UILabel.TOPIC_LOCALIZED_LABEL,
localizeLabel);
eventBroker.subscribe(UIEvents.UILabel.TOPIC_LOCALIZED_TOOLTIP,
localizeTooltip);
eventBroker.subscribe(UIEvents.UILabel.TOPIC_LABEL, localizeLabel);
eventBroker.subscribe(UIEvents.UILabel.TOPIC_TOOLTIP, localizeTooltip);
}
@PreDestroy
public void preDestroy() {
eventBroker.unsubscribe(itemUpdater);
eventBroker.unsubscribe(enabledUpdater);
eventBroker.unsubscribe(selectedUpdater);
eventBroker.unsubscribe(childrenMoveUpdater);
eventBroker.unsubscribe(localizeLabel);
eventBroker.unsubscribe(localizeTooltip);
}
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 MMenu))
return;
MElementContainer<MUIElement> menu = (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 : menu.getChildren()) {
removeChildGui(item, menu);
}
for (MUIElement item : menu.getChildren()) {
createWidget(item, menu);
}
}
}
};
@Override
public void createWidget(MUIElement element,
MElementContainer<MUIElement> parent) {
if (!element.isToBeRendered())
return;
if (element instanceof MMenuItem) {
MMenuItem model = (MMenuItem) element;
// --------------------
// Prepare the text
String text = prepareText(model);
text = text.replaceAll("&", "");
// Prepare the icon
Resource icon = model.getIconURI() != null ? ResourceHelper
.createResource(model.getIconURI()) : null;
// Prepare the command
Command command = null;
if (model instanceof MDirectMenuItem) {
final MDirectMenuItem item = (MDirectMenuItem) model;
item.setObject(contributionFactory.create(
item.getContributionURI(), getContext(item)));
command = createEventHandler(item);
} else if (model instanceof MHandledMenuItem) {
final MHandledMenuItem item = (MHandledMenuItem) model;
command = createParametrizedCommandEventHandler(item);
}
MUIElement nextRenderableAndVisible = findNextRendarableAndVisible(
element, parent);
MenuItem item = null;
if (nextRenderableAndVisible == null)
item = ((MenuItem) parent.getWidget()).addItem(text, icon,
command);
else
item = ((MenuItem) parent.getWidget()).addItemBefore(text,
icon, command,
(MenuItem) nextRenderableAndVisible.getWidget());
// -----------------
element.setWidget(item);
updateItemEnablement(model);
item.setEnabled(model.isEnabled());
// set the check mode
switch (model.getType()) {
case CHECK:
item.setCheckable(true);
item.setChecked(model.isSelected());
break;
default:
item.setCheckable(false);
break;
}
registerEnablementUpdaters(model);
}
}
protected void updateItemEnablement(MItem item) {
if (!(item.getWidget() instanceof MenuItem))
return;
MenuItem widget = (MenuItem) item.getWidget();
if (widget == null)
return;
item.setEnabled(canExecute(item));
}
public boolean canExecute(MItem item) {
if (item instanceof MHandledItem)
return canExecute((MHandledItem) item);
else if (item instanceof MDirectMenuItem)
return canExecute((MDirectMenuItem) item);
else
return false;
}
private boolean canExecute(MDirectMenuItem item) {
final IEclipseContext eclipseContext = getContext(item);
eclipseContext.set(MItem.class, item);
setupContext(eclipseContext, item);
return (Boolean) ContextInjectionFactory.invoke(item, CanExecute.class,
eclipseContext, true);
}
@Override
public void hookControllerLogic(MUIElement me) {
// the listener already attached (when created - vaadin API issue)
}
@Override
protected void setupContext(IEclipseContext context, MItem item) {
context.set(MMenuItem.class, (MMenuItem) item);
if (item instanceof MDirectMenuItem)
context.set(MDirectMenuItem.class, (MDirectMenuItem) item);
else if (item instanceof MHandledMenuItem)
context.set(MHandledMenuItem.class, (MHandledMenuItem) item);
// TODO luna - check this
// else if (item instanceof MOpaqueMenuItem)
// context.set(MOpaqueMenuItem.class, (MOpaqueMenuItem) item);
}
@Override
public void setVisible(MUIElement changedElement, boolean visible) {
((MenuItem) changedElement.getWidget()).setVisible(visible);
}
@Override
public void removeChildGui(MUIElement element,
MElementContainer<MUIElement> parent) {
MenuItem childItem = (MenuItem) element.getWidget();
if (parent.getWidget() instanceof MenuBar) {
MenuBar bar = (MenuBar) parent.getWidget();
bar.removeItem(childItem);
} else if (parent.getWidget() instanceof MenuItem) {
MenuItem parentItem = (MenuItem) parent.getWidget();
parentItem.removeChild(childItem);
}
}
private EventHandler localizeLabel = new EventHandler() {
@Override
public void handleEvent(Event event) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(element instanceof MMenuItem))
return;
MMenuItem item = (MMenuItem) element;
final MenuItem menuItem = (MenuItem) item.getWidget();
String newValue = (String) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
String label = Commons.trim(newValue);
if (menuItem != null) {
menuItem.setText(label);
}
}
};
private EventHandler localizeTooltip = new EventHandler() {
@Override
public void handleEvent(Event event) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(element instanceof MMenuItem))
return;
MMenuItem item = (MMenuItem) element;
final MenuItem menuItem = (MenuItem) item.getWidget();
String newValue = (String) event
.getProperty(UIEvents.EventTags.NEW_VALUE);
if (menuItem != null) {
menuItem.setDescription(newValue);
}
}
};
}