/*******************************************************************************
* Copyright (c) 2011 Kai Toedter 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:
* Kai Toedter - initial API and implementation
******************************************************************************/
package com.toedter.e4.ui.workbench.generic;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.contributions.IContributionFactory;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.internal.workbench.E4Workbench;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.ui.MContext;
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.basic.MWindow;
import org.eclipse.e4.ui.services.internal.events.EventBroker;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.equinox.app.IApplication;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
@SuppressWarnings("restriction")
public class GenericPresentationEngine implements PresentationEngine {
@Inject
protected Logger logger;
protected RendererFactory rendererFactory;
@Inject
EModelService modelService;
@Inject
EventBroker eventBroker;
private final EventHandler childrenHandler = new EventHandler() {
@Override
public void handleEvent(Event event) {
Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(changedObj instanceof MElementContainer<?>)) {
return;
}
@SuppressWarnings("unchecked")
MElementContainer<MUIElement> changedElement = (MElementContainer<MUIElement>) changedObj;
String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE);
if (UIEvents.EventTypes.ADD.equals(eventType)) {
System.out.println("ADD " + changedElement);
} else if (UIEvents.EventTypes.REMOVE.equals(eventType)) {
System.out.println("REMOVE " + changedElement);
MUIElement removed = (MUIElement) event.getProperty(UIEvents.EventTags.OLD_VALUE);
removeGui(removed);
}
System.out.println(event);
}
};
private final EventHandler visibilityHandler = new EventHandler() {
@Override
public void handleEvent(Event event) {
MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
System.out.println("visibilityHandler: " + changedElement);
GenericRenderer renderer = (GenericRenderer) changedElement.getRenderer();
if (renderer == null) {
return;
}
renderer.setVisible(changedElement, changedElement.isVisible());
MElementContainer<MUIElement> parent = changedElement.getParent();
if (parent == null) {
parent = (MElementContainer<MUIElement>) ((EObject) changedElement).eContainer();
}
GenericRenderer parentRenderer = (GenericRenderer) parent.getRenderer();
if (parentRenderer != null) {
parentRenderer.doLayout(parent);
}
}
};
@Override
public Object createGui(MUIElement element, Object parentWidget, IEclipseContext parentContext) {
System.out.println("GenericPresentationEngine.createGui(): This method should not be used.");
return null;
}
@Override
public Object createGui(MUIElement element, MElementContainer<MUIElement> parent) {
// System.out.println("GenericPresentationEngine.createGui(): " +
// element);
if (element instanceof MContext) {
MContext ctxt = (MContext) element;
// Assert.isTrue(ctxt.getContext() == null,
// "Before rendering Context should be null");
if (ctxt.getContext() == null) {
IEclipseContext eclipseContext = getContext(parent).createChild(getContextName(element));
populateModelInterfaces(ctxt, eclipseContext, element.getClass().getInterfaces());
ctxt.setContext(eclipseContext);
// System.out.println("create context: " +
// eclipseContext.toString() + " parent context: "
// + parentContext.toString());
// make sure the context knows about these variables that have
// been defined in the model
for (String variable : ctxt.getVariables()) {
eclipseContext.declareModifiable(variable);
}
Map<String, String> props = ctxt.getProperties();
for (String key : props.keySet()) {
eclipseContext.set(key, props.get(key));
}
// E4Workbench.processHierarchy(element);
}
}
GenericRenderer renderer = rendererFactory.getRenderer(element);
element.setRenderer(renderer);
// TODO check if parents are needed
if (parent == null) {
System.out.println("GenericPresentationEngine.createGui(): no parent: " + element + " parent: " + parent);
}
renderer.createWidget(element, parent);
// Does not work: why?
// if (parent != null) {
// element.setParent(parent);
// }
// TODO set visible here?
element.setVisible(true);
if (element instanceof MElementContainer) {
// first create the GUI for the children
@SuppressWarnings("unchecked")
MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
for (MUIElement child : container.getChildren()) {
createGui(child);
}
// then let the renderer process them
renderer.processContents(container);
}
renderer.hookControllerLogic(element);
return element.getWidget();
}
private String getContextName(MUIElement element) {
StringBuilder builder = new StringBuilder(element.getClass().getSimpleName());
String elementId = element.getElementId();
if (elementId != null && elementId.length() != 0) {
builder.append(" (").append(elementId).append(") ");
}
builder.append("Context");
return builder.toString();
}
private static void populateModelInterfaces(MContext contextModel, IEclipseContext context, Class<?>[] interfaces) {
for (Class<?> intf : interfaces) {
context.set(intf.getName(), contextModel);
populateModelInterfaces(contextModel, context, intf.getInterfaces());
}
}
@SuppressWarnings("unchecked")
@Override
public Object createGui(final MUIElement element) {
// Obtain the necessary parent widget
MElementContainer<MUIElement> parent = element.getParent();
if (parent == null) {
parent = (MElementContainer<MUIElement>) ((EObject) element).eContainer();
}
return createGui(element, parent);
}
private IEclipseContext getContext(MUIElement parent) {
if (parent instanceof MContext) {
return ((MContext) parent).getContext();
}
return modelService.getContainingContext(parent);
}
@Override
public void removeGui(MUIElement element) {
System.out.println("GenericPresentationEngine.removeGui(): " + element);
((GenericRenderer) element.getRenderer()).removeWidget(element, null);
}
@Override
public Object run(MApplicationElement uiRoot, IEclipseContext appContext) {
System.out.println("GenericPresentationEngine.run(): " + uiRoot + ":" + appContext);
if (uiRoot instanceof MApplication) {
MApplication theApp = (MApplication) uiRoot;
for (MWindow window : theApp.getChildren()) {
createGui(window);
}
}
System.out.println("GenericPresentationEngine.run(): Finished");
return IApplication.EXIT_OK;
}
@Override
public void stop() {
System.out.println("GenericPresentationEngine.stop()");
}
@PostConstruct
public void postConstruct(IEclipseContext context) {
System.out.println("GenericPresentationEngine.postConstruct()");
// Add the presentation engine to the context
context.set(IPresentationEngine.class.getName(), this);
// TODO use parameter or registry
IContributionFactory contribFactory = context.get(IContributionFactory.class);
try {
rendererFactory = (RendererFactory) contribFactory.create(
"bundleclass://com.toedter.e4.ui.workbench.generic/"
+ "com.toedter.e4.ui.workbench.generic.GenericRendererFactory", context);
} catch (Exception e) {
logger.warn(e, "Could not create rendering factory");
}
eventBroker.subscribe(UIEvents.ElementContainer.CHILDREN, childrenHandler);
eventBroker.subscribe(UIEvents.UIElement.TOPIC_VISIBLE, visibilityHandler);
}
@Override
public void refreshGui(MElementContainer<?> element) {
GenericRenderer renderer = rendererFactory.getRenderer(element);
if (element instanceof MElementContainer<?>) {
MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
// for (MUIElement listElement : container.getChildren()) {
// refreshGui((MElementContainer<?>) listElement);
// }
renderer.doLayout(container);
}
}
@Override
public void focusGui(MUIElement element) {
// TODO Auto-generated method stub
}
}