Package at.bestsolution.efxclipse.runtime.workbench.renderers.base

Source Code of at.bestsolution.efxclipse.runtime.workbench.renderers.base.BasePerspectiveStackRenderer

/*******************************************************************************
* Copyright (c) 2012 BestSolution.at 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:
*     Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
*******************************************************************************/
package at.bestsolution.efxclipse.runtime.workbench.renderers.base;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.events.IEventBroker;
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.MGenericStack;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack;
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.UIEvents;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

import at.bestsolution.efxclipse.runtime.workbench.base.rendering.AbstractRenderer;
import at.bestsolution.efxclipse.runtime.workbench.base.rendering.RendererFactory;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WCallback;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WLayoutedWidget;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WPerspectiveStack;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WPerspectiveStack.WStackItem;
import at.bestsolution.efxclipse.runtime.workbench.renderers.base.widget.WPlaceholderWidget;

@SuppressWarnings("restriction")
public abstract class BasePerspectiveStackRenderer<N, I, IC> extends BaseRenderer<MPerspectiveStack, WPerspectiveStack<N, I, IC>> {
  @Inject
  RendererFactory factory;

  boolean inLazyInit;

  @PostConstruct
  void init(IEventBroker eventBroker) {
    eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, new EventHandler() {

      @Override
      public void handleEvent(Event event) {
        Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
        if (changedObj instanceof MPerspectiveStack) {
          MPerspectiveStack parent = (MPerspectiveStack) changedObj;
          if (BasePerspectiveStackRenderer.this == parent.getRenderer()) {
            String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE);

            if (UIEvents.EventTypes.ADD.equals(eventType)) {
              MUIElement element = (MUIElement) event.getProperty(UIEvents.EventTags.NEW_VALUE);
              handleChildAddition(parent, (MPerspective) element);
            } else if (UIEvents.EventTypes.REMOVE.equals(eventType)) {
              MUIElement element = (MUIElement) event.getProperty(UIEvents.EventTags.OLD_VALUE);
              handleChildRemove(parent, (MPerspective) element);
            }
          }
        }
      }
    });
    eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, new EventHandler() {

      @Override
      public void handleEvent(Event event) {
        Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
        if (changedObj instanceof MPerspectiveStack) {
          MPerspectiveStack parent = (MPerspectiveStack) changedObj;
          if (BasePerspectiveStackRenderer.this == parent.getRenderer()) {
            String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE);
            if (UIEvents.EventTypes.SET.equals(eventType)) {
              MUIElement newValue = (MUIElement) event.getProperty(UIEvents.EventTags.NEW_VALUE);
              MUIElement oldValue = (MUIElement) event.getProperty(UIEvents.EventTags.OLD_VALUE);
              handleSelectedElement(parent, (MPerspective) oldValue, (MPerspective) newValue);
            }
          }
        }
      }
    });
    eventBroker.subscribe(UIEvents.UIElement.TOPIC_VISIBLE, new EventHandler() {

      @Override
      public void handleEvent(Event event) {
        MUIElement changedObj = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);
        if (changedObj.isToBeRendered()) {
          MUIElement parent = changedObj.getParent();
          // Can be null for e.g. detached windows!!!
          if( parent != null ) {
            if (BasePerspectiveStackRenderer.this == parent.getRenderer()) {
              MPerspectiveStack stack = (MPerspectiveStack) parent;
              String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE);
              if (UIEvents.EventTypes.SET.equals(eventType)) {
                Boolean newValue = (Boolean) event.getProperty(UIEvents.EventTags.NEW_VALUE);
                if (newValue.booleanValue()) {
                  // TODO Is childRendered not dangerous to call
                  // here??
                  childRendered(stack, changedObj);
                } else {
                  hideChild(stack, changedObj);
                }
              }
            }
          }
        }
      }
    });
  }

  @Override
  protected void initWidget(final MPerspectiveStack element, final WPerspectiveStack<N, I, IC> widget) {
    super.initWidget(element, widget);
    widget.setMouseSelectedItemCallback(new WCallback<WStackItem<I, IC>, Void>() {

      @Override
      public Void call(WStackItem<I, IC> param) {
        if (param.getDomElement() != null) {
          activatationJob((MPerspective) param.getDomElement(), true);
        }

        return null;
      }
    });
    widget.setKeySelectedItemCallback(new WCallback<WStackItem<I, IC>, Void>() {

      @Override
      public Void call(WStackItem<I, IC> param) {
        if (param.getDomElement() != null) {
          activatationJob((MPerspective) param.getDomElement(), false);
        }

        return null;
      }
    });

    widget.registerActivationCallback(new WCallback<Boolean, Void>() {

      @Override
      public Void call(Boolean param) {
        if (param.booleanValue() && element.getSelectedElement() != null) {
          activatationJob((MPerspective) element.getSelectedElement(), true);
        }
        return null;
      }
    });
  }

  private void activatationJob(final MPerspective p, final boolean focus) {

  }

  @Override
  public void doProcessContent(MPerspectiveStack element) {
    WPerspectiveStack<N, I, IC> stack = getWidget(element);
    List<WStackItem<I, IC>> items = new ArrayList<WStackItem<I, IC>>();
    WStackItem<I, IC> initalItem = null;

    for (MPerspective e : element.getChildren()) {
      // Precreate the rendering context for the subitem
      AbstractRenderer<MPerspective, ?> renderer = factory.getRenderer(e);
      if (renderer != null && e.isToBeRendered() && e.isVisible()) {
        WStackItem<I, IC> item = createStackItem(stack, e, renderer);
        items.add(item);

        if (e == element.getSelectedElement()) {
          initalItem = item;
        }
      }
    }

    if (!items.isEmpty()) {
      if (initalItem == null || items.size() == 1 || items.get(0) == initalItem) {
        stack.addItems(items);
      } else {
        stack.addItem(initalItem);
        if (items.get(items.size() - 1) == initalItem) {
          stack.addItems(0, items.subList(0, items.size() - 1));
        } else {
          int idx = items.indexOf(initalItem);
          stack.addItems(0, items.subList(0, idx));
          stack.addItems(items.subList(idx + 1, items.size()));
        }

      }
    }

    if (element.getSelectedElement() != null) {
      handleSelectedElement(element, null, element.getSelectedElement());
    } else if (!element.getChildren().isEmpty()) {
      // TODO Should this be done through the part service????
      element.setSelectedElement(element.getChildren().get(0));
    }
  }

  private WStackItem<I, IC> createStackItem(WPerspectiveStack<N, I, IC> stack, final MPerspective e, AbstractRenderer<MPerspective, ?> renderer) {
    IEclipseContext context = renderer.setupRenderingContext(e);
    WStackItem<I, IC> item = ContextInjectionFactory.make(stack.getStackItemClass(), context);
    item.setDomElement(e);
    item.setInitCallback(new WCallback<WStackItem<I, IC>, IC>() {

      @SuppressWarnings("unchecked")
      @Override
      public IC call(WStackItem<I, IC> param) {
        inLazyInit = true;
        try {
          WLayoutedWidget<MPerspective> widget = engineCreateWidget(e);
          if (widget != null) {
            return (IC) widget.getStaticLayoutNode();
          }
          return null;
        } finally {
          inLazyInit = false;
        }
      }
    });
    item.setOnCloseCallback(new WCallback<WStackItem<I, IC>, Boolean>() {

      @Override
      public Boolean call(WStackItem<I, IC> param) {
        return !handleStackItemClose(e, param);
      }
    });

    return item;
  }

  void handleChildAddition(MPerspectiveStack parent, MPerspective element) {
    if (element.isToBeRendered() && element.isVisible()) {
      int idx = getRenderedIndex(parent, element);

      AbstractRenderer<MPerspective, ?> renderer = factory.getRenderer(element);
      WPerspectiveStack<N, I, IC> stack = getWidget(parent);
      WStackItem<I, IC> item = createStackItem(getWidget(parent), element, renderer);

      stack.addItems(idx, Collections.singletonList(item));
    }
  }

  void handleChildRemove(MPerspectiveStack parent, MPerspective element) {
    if (element.isToBeRendered() && element.isVisible()) {
      hideChild(parent, element);
    }
  }

  void handleSelectedElement(MPerspectiveStack parent, MPerspective oldElement, MPerspective newElement) {
    hideElementRecursive(oldElement);
    WPerspectiveStack<N, I, IC> stack = getWidget(parent);
    int idx = 0;
    for (WStackItem<I, IC> i : stack.getItems()) {
      if (i.getDomElement() == newElement) {
        stack.selectItem(idx);
        // TODO Should we do the traversal before???
        showElementRecursive(newElement);
        return;
      }
      idx++;
    }
   
    // Looks like the child is not part of the UI yet (most likely because it got removed using IPR#removeGUI)
    childRendered(parent, newElement);
    stack.selectItem(parent.getChildren().indexOf(newElement));
    // TODO Should we do the traversal before???
    showElementRecursive(newElement);
  }

  boolean handleStackItemClose(MPerspective e, WStackItem<I, IC> item) {
    return true;
  }

  @Override
  public void childRendered(MPerspectiveStack parentElement, MUIElement element) {
    if (inLazyInit || inContentProcessing(parentElement) || !element.isVisible()) {
      return;
    }

    WPerspectiveStack<N, I, IC> stack = getWidget(parentElement);
    for (WStackItem<I, IC> i : stack.getItems()) {
      if (i.getDomElement() == element) {
        return;
      }
    }

    int idx = getRenderedIndex(parentElement, element);
    AbstractRenderer<MPerspective, ?> renderer = factory.getRenderer(element);
    stack.addItems(idx, Collections.singletonList(createStackItem(stack, (MPerspective) element, renderer)));
  }

  @Override
  public void hideChild(MPerspectiveStack container, MUIElement changedObj) {
    WPerspectiveStack<N, I, IC> stack = getWidget(container);
    if (stack == null) {
      return;
    }

    WStackItem<I, IC> item = null;

    for (WStackItem<I, IC> i : stack.getItems()) {
      if (i.getDomElement() == changedObj) {
        item = i;
        break;
      }
    }

    if (item != null) {
      List<WStackItem<I, IC>> l = Collections.singletonList(item);
      stack.removeItems(l);
    }
  }
 
  private void hideElementRecursive(MUIElement element) {
    if (element == null || element.getWidget() == null) {
      return;
    }
   
    if (element instanceof MPlaceholder) {
      MPlaceholder ph = (MPlaceholder) element;
      element = ph.getRef();
    }

    // Hide any floating windows
    if (element instanceof MWindow && element.getWidget() != null) {
      element.setVisible(false);
    }
   
    if (element instanceof MGenericStack<?>) {
      // For stacks only the currently selected elements are being hidden
      MGenericStack<?> container = (MGenericStack<?>) element;
      MUIElement curSel = container.getSelectedElement();
      hideElementRecursive(curSel);
    } else if (element instanceof MElementContainer<?>) {
      MElementContainer<?> container = (MElementContainer<?>) element;
      for (MUIElement childElement : container.getChildren()) {
        hideElementRecursive(childElement);
      }

      // OK, now process detached windows
      if (element instanceof MWindow) {
        for (MWindow w : ((MWindow) element).getWindows()) {
          hideElementRecursive(w);
        }
      } else if (element instanceof MPerspective) {
        for (MWindow w : ((MPerspective) element).getWindows()) {
          hideElementRecursive(w);
        }
      }
    }
  }

  private void showElementRecursive(MUIElement element) {
    if (!element.isToBeRendered()) {
      return;
    }

    if (element instanceof MPlaceholder && element.getWidget() != null) {
      MPlaceholder ph = (MPlaceholder) element;
      MUIElement ref = ph.getRef();

      if (ref.getCurSharedRef() != ph) {
        ref.setCurSharedRef(ph);
        WPlaceholderWidget placeholder = (WPlaceholderWidget) ph.getWidget();
        @SuppressWarnings("unchecked")
        WLayoutedWidget<MUIElement> content = (WLayoutedWidget<MUIElement>) ref.getWidget();
        placeholder.setContent(content);
      }

      element = ref;
    }

    if (element instanceof MContext) {
      IEclipseContext context = ((MContext) element).getContext();
      if (context != null) {
        IEclipseContext newParentContext = modelService.getContainingContext(element);
        if (context.getParent() != newParentContext) {
          context.setParent(newParentContext);
        }
      }
    }

    if (element instanceof MWindow && element.getWidget() != null) {
      int visCount = 0;
      for (MUIElement kid : ((MWindow) element).getChildren()) {
        if (kid.isToBeRendered() && kid.isVisible())
          visCount++;
      }
      if (visCount > 0)
        element.setVisible(true);
    }
   
    if (element instanceof MGenericStack) {
      MGenericStack<?> container = (MGenericStack<?>) element;
      MUIElement curSel = container.getSelectedElement();
      if (curSel == null && container.getChildren().size() > 0) {
        curSel = container.getChildren().get(0);
      }
      if (curSel != null) {
        showElementRecursive(curSel);
      }
    } else if (element instanceof MElementContainer<?>) {
      MElementContainer<?> container = (MElementContainer<?>) element;
      for (MUIElement childElement : container.getChildren().toArray(new MUIElement[0])) {
        showElementRecursive(childElement);
      }
     
      // OK, now process detached windows
      if (element instanceof MWindow) {
        for (MWindow w : ((MWindow) element).getWindows()) {
            showElementRecursive(w);
        }
      } else if (element instanceof MPerspective) {
        for (MWindow w : ((MPerspective) element).getWindows()) {
          showElementRecursive(w);
        }
      }
    }
  }
}
TOP

Related Classes of at.bestsolution.efxclipse.runtime.workbench.renderers.base.BasePerspectiveStackRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.