package at.bestsolution.e4.ui.internal.workbench.swing; import java.awt.Container; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Named; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; 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.internal.workbench.Activator; import org.eclipse.e4.ui.internal.workbench.E4Workbench; import org.eclipse.e4.ui.internal.workbench.Policy; 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.advanced.MPlaceholder; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.workbench.IPresentationEngine; import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.emf.ecore.EObject; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import at.bestsolution.e4.ui.workbench.swing.AbstractPartRenderer; import at.bestsolution.e4.ui.workbench.swing.IRendererFactory; @SuppressWarnings("restriction") public class PartRenderingEngine implements IPresentationEngine { public static final String engineURI = "platform:/plugin/at.bestsolution.e4.ui.workbench.swing/" + "at.bestsolution.e4.ui.internal.workbench.swing.PartRenderingEngine"; private static final String defaultFactoryUrl = "platform:/plugin/at.bestsolution.e4.ui.workbench.renderers.swing/" + "at.bestsolution.e4.ui.workbench.renderers.swing.WorkbenchRendererFactory"; private String factoryUrl; private IRendererFactory curFactory = null; private IEclipseContext appContext; private List<MUIElement> renderedElements = new ArrayList<MUIElement>(); private MUIElement removeRoot = null; @Inject private EModelService modelService; @Inject private Logger logger; private MApplication theApp; @Inject public PartRenderingEngine( @Named(E4Workbench.RENDERER_FACTORY_URI) @Optional String factoryUrl) { if (factoryUrl == null) { factoryUrl = defaultFactoryUrl; } this.factoryUrl = factoryUrl; } @PostConstruct void initialize(IEclipseContext context) { this.appContext = context; // Add the renderer to the context context.set(IPresentationEngine.class.getName(), this); IRendererFactory factory = null; IContributionFactory contribFactory = context .get(IContributionFactory.class); try { factory = (IRendererFactory) contribFactory.create(factoryUrl, context); } catch (Exception e) { logger.warn(e, "Could not create rendering factory"); } // Try to load the default one if (factory == null) { try { factory = (IRendererFactory) contribFactory.create( defaultFactoryUrl, context); } catch (Exception e) { logger.error(e, "Could not create default rendering factory"); } } if (factory == null) { throw new IllegalStateException( "Could not create any rendering factory. Aborting ..."); } curFactory = factory; context.set(IRendererFactory.class, curFactory); } public Object createGui(MUIElement element, Object parentWidget, IEclipseContext parentContext) { if (!element.isToBeRendered()) return null; if (!renderedElements.contains(element)) renderedElements.add(element); // no creates while processing a remove if (removeRoot != null) { return null; } if (element.getWidget() != null) { if (element.getWidget() instanceof JComponent && parentWidget instanceof Container) { JComponent ctrl = (JComponent) element.getWidget(); if (ctrl.getParent() != parentWidget) { ctrl.getParent().remove(ctrl); ((Container) parentWidget).add(ctrl); // TODO Do we have to call validate here? } } // Now that we have a widget let the parent (if any) know if (element.getParent() instanceof MUIElement) { MElementContainer<MUIElement> parentElement = element .getParent(); AbstractPartRenderer parentRenderer = getRendererFor(parentElement); if (parentRenderer != null) parentRenderer.childRendered(parentElement, element); } return element.getWidget(); } if (element instanceof MContext) { MContext ctxt = (MContext) element; // Assert.isTrue(ctxt.getContext() == null, // "Before rendering Context should be null"); if (ctxt.getContext() == null) { IEclipseContext lclContext = parentContext .createChild(getContextName(element)); populateModelInterfaces(ctxt, lclContext, element.getClass() .getInterfaces()); ctxt.setContext(lclContext); // System.out.println("New Context: " + lclContext.toString() // + " parent: " + parentContext.toString()); // make sure the context knows about these variables that have // been defined in the model for (String variable : ctxt.getVariables()) { lclContext.declareModifiable(variable); } Map<String, String> props = ctxt.getProperties(); for (String key : props.keySet()) { lclContext.set(key, props.get(key)); } E4Workbench.processHierarchy(element); } } // Create a control appropriate to the part Object newWidget = createWidget(element, parentWidget); // Remember that we've created the control if (newWidget != null) { AbstractPartRenderer renderer = getRendererFor(element); // Have the renderer hook up any widget specific listeners renderer.hookControllerLogic(element); // Process its internal structure through the renderer that created // it if (element instanceof MElementContainer) { renderer.processContents((MElementContainer<MUIElement>) element); } // Allow a final chance to set up renderer.postProcess(element); // Now that we have a widget let the parent (if any) know if (element.getParent() instanceof MUIElement) { MElementContainer<MUIElement> parentElement = element .getParent(); AbstractPartRenderer parentRenderer = getRendererFor(parentElement); if (parentRenderer != null) parentRenderer.childRendered(parentElement, element); } } else { // failed to create the widget, dispose its context if necessary if (element instanceof MContext) { MContext ctxt = (MContext) element; IEclipseContext lclContext = ctxt.getContext(); if (lclContext != null) { lclContext.dispose(); ctxt.setContext(null); } } } return newWidget; } protected AbstractPartRenderer getRendererFor(MUIElement element) { return (AbstractPartRenderer) element.getRenderer(); } 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) { Activator.trace(Policy.DEBUG_CONTEXTS, "Adding " + intf.getName() + " for " //$NON-NLS-1$ //$NON-NLS-2$ + contextModel.getClass().getName(), null); context.set(intf.getName(), contextModel); populateModelInterfaces(contextModel, context, intf.getInterfaces()); } } protected Object createWidget(MUIElement element, Object parent) { AbstractPartRenderer renderer = getRenderer(element, parent); if (renderer != null) { // Remember which renderer is responsible for this widget element.setRenderer(renderer); Object newWidget = renderer.createWidget(element, parent); if (newWidget != null) { renderer.bindWidget(element, newWidget); return newWidget; } } return null; } private AbstractPartRenderer getRenderer(MUIElement uiElement, Object parent) { return curFactory.getRenderer(uiElement, parent); } public Object createGui(MUIElement element) { // Obtain the necessary parent widget Object parent = null; MUIElement parentME = element.getParent(); if (parentME == null) parentME = (MUIElement) ((EObject) element).eContainer(); if (parentME != null) { AbstractPartRenderer renderer = getRendererFor(parentME); if (renderer != null) { // if (!element.isVisible()) { // parent = getLimboShell(); // } else { parent = renderer.getUIContainer(element); // } } } // Obtain the necessary parent context IEclipseContext parentContext = null; if (element.getCurSharedRef() != null) { MPlaceholder ph = element.getCurSharedRef(); parentContext = getContext(ph.getParent()); } else if (parentContext == null && element.getParent() != null) { parentContext = getContext(element.getParent()); } else if (parentContext == null && element.getParent() == null) { parentContext = getContext((MUIElement) ((EObject) element) .eContainer()); } return createGui(element, parent, parentContext); } private IEclipseContext getContext(MUIElement parent) { if (parent instanceof MContext) { return ((MContext) parent).getContext(); } return modelService.getContainingContext(parent); } public void removeGui(MUIElement element) { // TODO Auto-generated method stub } public Object run(MApplicationElement uiRoot, IEclipseContext appContext) { System.setProperty("apple.awt.brushMetalLook", "true"); try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (ClassNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (InstantiationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IllegalAccessException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (UnsupportedLookAndFeelException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } theApp = null; if (uiRoot instanceof MApplication) { theApp = (MApplication) uiRoot; MWindow selected = theApp.getSelectedElement(); if (selected == null) { for (MWindow window : theApp.getChildren()) { createGui(window); } } else { // render the selected one first createGui(selected); for (MWindow window : theApp.getChildren()) { if (selected != window) { createGui(window); } } } IApplicationContext ac = appContext.get(IApplicationContext.class); if (ac != null) ac.applicationRunning(); } while ((!theApp.getChildren().isEmpty() && someAreVisible(theApp .getChildren()))) { try { Thread.sleep(1000); // We could do better by using a lock and // call lock.wait()/lock.notify() when a // window is closed } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return IApplication.EXIT_OK; } protected boolean someAreVisible(List<MWindow> windows) { for (MWindow win : windows) { if (win.isToBeRendered() && win.isVisible() && win.getWidget() != null) { return true; } } return false; } public void stop() { // TODO Auto-generated method stub } }