package org.xmind.cathy.internal.renderer; import java.util.List; import javax.inject.Inject; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.di.annotations.Optional; import org.eclipse.e4.core.di.extensions.EventTopic; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.basic.MWindowElement; import org.eclipse.e4.ui.workbench.UIEvents; import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.e4.ui.workbench.renderers.swt.CSSEngineHelper; import org.eclipse.e4.ui.workbench.renderers.swt.TrimmedPartLayout; import org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Shell; import org.osgi.service.event.Event; public class XWBWRenderer extends WBWRenderer { @Inject private Display display; @Inject private MApplication application; @Inject private EModelService modelService; /** * Hides all contents on startup, and will be set to true once the * application fully starts up. */ private boolean showingContents = false; @Override public Object createWidget(MUIElement element, Object parent) { Object widget = super.createWidget(element, parent); if (widget != null && widget instanceof Shell) { recreateLayout(element, (Shell) widget); } return widget; } protected void recreateLayout(MUIElement element, Shell shell) { Layout oldLayout = shell.getLayout(); if (oldLayout != null && oldLayout instanceof TrimmedPartLayout) { TrimmedPartLayout trimmedLayout = (TrimmedPartLayout) oldLayout; if (trimmedLayout.clientArea != null) trimmedLayout.clientArea.dispose(); if (trimmedLayout.top != null) trimmedLayout.top.dispose(); if (trimmedLayout.bottom != null) trimmedLayout.bottom.dispose(); if (trimmedLayout.left != null) trimmedLayout.left.dispose(); if (trimmedLayout.right != null) trimmedLayout.right.dispose(); } XTrimmedPartLayout layout = new XTrimmedPartLayout(shell); IEclipseContext localContext = getContext(element); // We need to retrieve specific CSS properties for our layout. CSSEngineHelper helper = new CSSEngineHelper(localContext, shell); layout.gutterTop = helper.getMarginTop(0); layout.gutterBottom = helper.getMarginBottom(0); layout.gutterLeft = helper.getMarginLeft(0); layout.gutterRight = helper.getMarginRight(0); shell.setLayout(layout); } @Override public Object getUIContainer(MUIElement element) { if (element instanceof MPart) { MUIElement parent = element.getParent(); if (parent != null) { Object parentWidget = parent.getWidget(); if (parentWidget instanceof Composite) { Layout layout = ((Composite) parentWidget).getLayout(); if (layout instanceof XTrimmedPartLayout) { return ((XTrimmedPartLayout) layout).getContainer( (Composite) parentWidget, element); } } } } return super.getUIContainer(element); } @Override public void postProcess(MUIElement shellME) { super.postProcess(shellME); MWindow window = (MWindow) shellME; MWindowElement selectedElement = window.getSelectedElement(); if (selectedElement != null) { showChild(window, selectedElement); } else if (!window.getChildren().isEmpty()) { for (MWindowElement child : window.getChildren()) { if (child.isToBeRendered() && child.isVisible()) { window.setSelectedElement(child); break; } } } } private void showChild(MWindow window, MWindowElement selectedChild) { Shell shell = (Shell) window.getWidget(); if (shell == null || shell.isDisposed()) return; if (window.getChildren().isEmpty()) return; for (MWindowElement child : window.getChildren()) { Object container = getUIContainer(child); if (container instanceof Control) { ((Control) container) .setVisible(showingContents && child == selectedChild); } } Layout layout = shell.getLayout(); if (layout instanceof TrimmedPartLayout) { TrimmedPartLayout tpl = (TrimmedPartLayout) layout; boolean primaryClientAreaVisible = tpl.clientArea != null && tpl.clientArea.isVisible(); if (tpl.top != null) tpl.top.setVisible(primaryClientAreaVisible); if (tpl.bottom != null) tpl.bottom.setVisible(primaryClientAreaVisible); if (tpl.left != null) tpl.left.setVisible(primaryClientAreaVisible); if (tpl.right != null) tpl.right.setVisible(primaryClientAreaVisible); } shell.layout(true); } @Inject @Optional public void subscribeTopicPartActivate( @EventTopic(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) { Object element = event.getProperty(UIEvents.EventTags.ELEMENT); if (element == null || !(element instanceof MWindow)) return; MWindow window = (MWindow) element; if (window.getRenderer() != XWBWRenderer.this) return; showChild(window, window.getSelectedElement()); } @Inject @Optional public void subscribeTopicChildrenRemoved( @EventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) { if (!UIEvents.isREMOVE(event)) return; Object element = event.getProperty(UIEvents.EventTags.ELEMENT); if (element == null || !(element instanceof MWindow)) return; MWindow window = (MWindow) element; if (window.getRenderer() != XWBWRenderer.this || !(window.getWidget() instanceof Shell) || !(((Shell) window.getWidget()) .getLayout() instanceof XTrimmedPartLayout)) return; XTrimmedPartLayout layout = (XTrimmedPartLayout) ((Shell) window .getWidget()).getLayout(); for (Object removed : UIEvents.asIterable(event, UIEvents.EventTags.OLD_VALUE)) { layout.removeContainer(removed); } } /** * Once the application fully starts up, set the 'showingContents' flag to * true and show all window contents. * * @param event * the UI event of the topic * {@link UIEvents.UILifeCycle#APP_STARTUP_COMPLETE} */ @Inject @Optional public void applicationStarted( @EventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Event event) { showingContents = true; if (display == null) return; display.syncExec(new Runnable() { public void run() { List<MWindow> windows = modelService.findElements(application, null, MWindow.class, null); for (MWindow window : windows) { if (window.getRenderer() == XWBWRenderer.this) { showChild(window, window.getSelectedElement()); } } } }); } }