@Override
  public void switchPerspective(MPerspective perspective) {
    Assert.isNotNull(perspective);
    MWindow window = getWindow();
    if (window != null && isInContainer(window, perspective)) {
      perspective.getParent().setSelectedElement(perspective);
      List<MPart> newPerspectiveParts =
          modelService.findElements(perspective, null, MPart.class, null);
      // if possible, keep the same active part across perspective switches
      if (newPerspectiveParts.contains(activePart)
          && partActivationHistory.isValid(perspective, activePart)) {
        MPart target = activePart;
        IEclipseContext activeChild = activePart.getContext().getParent().getActiveChild();
        if (activeChild != null) {
          activeChild.deactivate();
        }
        if (target.getContext() != null
            && target.getContext().get(MPerspective.class) != null
            && target.getContext().get(MPerspective.class).getContext()
                == perspective.getContext()) {
          target.getContext().activateBranch();
        } else {
          perspective.getContext().activate();
        }

        modelService.bringToTop(target);
        activate(target, true, false);
        return;
      }

      MPart newActivePart = perspective.getContext().getActiveLeaf().get(MPart.class);
      if (newActivePart == null) {
        // whatever part was previously active can no longer be found, find another one
        MPart candidate = partActivationHistory.getActivationCandidate(perspective);
        if (candidate != null) {
          modelService.bringToTop(candidate);
          activate(candidate, true, false);
          return;
        }
      }

      // there seems to be no parts in this perspective, just activate it as is then
      if (newActivePart == null) {
        modelService.bringToTop(perspective);
        perspective.getContext().activate();
      } else {
        if ((modelService.getElementLocation(newActivePart) & EModelService.IN_SHARED_AREA) != 0) {
          if (newActivePart.getParent().getSelectedElement() != newActivePart) {
            newActivePart = (MPart) newActivePart.getParent().getSelectedElement();
          }
        }
        activate(newActivePart, true, false);
      }
    }
  }
  @Override
  public boolean savePart(MPart part, boolean confirm) {
    if (!part.isDirty()) {
      return true;
    }

    if (saveHandler != null) {
      return saveHandler.save(part, confirm);
    }

    Object client = part.getObject();
    try {
      ContextInjectionFactory.invoke(client, Persist.class, part.getContext());
    } catch (InjectionException e) {
      log(
          "Failed to persist contents of part",
          "Failed to persist contents of part ({0})", //$NON-NLS-1$ //$NON-NLS-2$
          part.getElementId(),
          e);
      return false;
    } catch (RuntimeException e) {
      log(
          "Failed to persist contents of part via DI", //$NON-NLS-1$
          "Failed to persist contents of part ({0}) via DI",
          part.getElementId(),
          e); //$NON-NLS-1$
      return false;
    }
    return true;
  }
  private void cleanUpContributionCache() {
    if (!actionContributionCache.isEmpty()) {
      PluginActionContributionItem[] items =
          actionContributionCache.toArray(
              new PluginActionContributionItem[actionContributionCache.size()]);
      actionContributionCache.clear();
      for (int i = 0; i < items.length; i++) {
        items[i].dispose();
      }
    }

    if (modelPart == null || menuModel == null) {
      return;
    }
    IEclipseContext modelContext = modelPart.getContext();
    if (modelContext != null) {
      IRendererFactory factory = modelContext.get(IRendererFactory.class);
      if (factory != null) {
        AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
        if (obj instanceof MenuManagerRenderer) {
          MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
          renderer.cleanUp(menuModel);
        }
      }
    }
  }
  private void setComboList() {

    int index = cCombo.getSelectionIndex();
    if (index < 0) index = 0; // default selection is "NO OVERLAY"
    String text = cCombo.getText();

    ArrayList<String> itemList = new ArrayList<String>(10);
    itemList.add(IConstant.NO_OVERLAY);

    Collection<MPart> parts = partService.getParts();
    for (MPart part : parts) {
      if (isOverlayPart(part)) {
        if (part.getContext() != null) { // part is instantiated
          itemList.add(part.getLabel());
        }
      }
    }

    String[] items = itemList.toArray(new String[0]);
    cCombo.setItems(items);
    if (index > 0) {
      int newIndex = 0;
      for (int i = 1; i < items.length; i++) {
        if (text.equals(items[i])) {
          newIndex = i;
          break;
        }
      }
      index = newIndex;
    }
    cCombo.select(index);
    ((GcodeViewPart) part.getObject())
        .getGcodeViewGroup()
        .setOverlayGcodeProgram(getSelectedProgram(cCombo.getText()));
  }
 private void createModelFor(String id) {
   if (id == null) {
     id = getClass().getName() + '.' + System.identityHashCode(this);
   }
   menuModel = null;
   for (MMenu item : modelPart.getMenus()) {
     if (id.equals(item.getElementId())
         && item instanceof MPopupMenu
         && item.getTags().contains(ContributionsAnalyzer.MC_POPUP)) {
       menuModel = (MPopupMenu) item;
       break;
     }
   }
   if (menuModel == null) {
     menuModel = MenuFactoryImpl.eINSTANCE.createPopupMenu();
     menuModel.setElementId(id);
     menuModel.getTags().add(ContributionsAnalyzer.MC_POPUP);
     modelPart.getMenus().add(menuModel);
   }
   IRendererFactory factory = modelPart.getContext().get(IRendererFactory.class);
   AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
   if (obj instanceof MenuManagerRenderer) {
     ((MenuManagerRenderer) obj).linkModelToManager(menuModel, menu);
   }
   registerE4Support();
   cleanUpContributionCache();
 }
  private void showStandaloneViewMenu(
      ExecutionEvent event, MPart model, MMenu menuModel, Composite partContainer) {
    Shell shell = partContainer.getShell();
    Menu menu = (Menu) menuModel.getWidget();
    if (menu == null) {
      IPresentationEngine engine =
          (IPresentationEngine) HandlerUtil.getVariable(event, IPresentationEngine.class.getName());
      menu = (Menu) engine.createGui(menuModel, shell, model.getContext());
      if (menu != null) {
        final Menu tmpMenu = menu;
        partContainer.addDisposeListener(
            new DisposeListener() {
              public void widgetDisposed(DisposeEvent e) {
                tmpMenu.dispose();
              }
            });
      }
    }

    Display display = menu.getDisplay();
    Point location = display.map(partContainer, null, partContainer.getLocation());
    Point size = partContainer.getSize();
    menu.setLocation(location.x + size.x, location.y);
    menu.setVisible(true);

    while (!menu.isDisposed() && menu.isVisible()) {
      if (!display.readAndDispatch()) display.sleep();
    }

    if (!(menu.getData() instanceof MenuManager)) {
      menu.dispose();
    }
  }
 /**
  * well, this goes to the renderer.
  *
  * @param mgr
  */
 private void addMenuContributions(IMenuManager mgr) {
   IRendererFactory factory = modelPart.getContext().get(IRendererFactory.class);
   AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
   if (obj instanceof MenuManagerRenderer) {
     MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
     renderer.reconcileManagerToModel(menu, menuModel);
     renderer.processContributions(menuModel, false, true);
     // double cast because we're bad people
     renderer.processContents((MElementContainer<MUIElement>) ((Object) menuModel));
   }
 }
  private IGcodeProgram getSelectedProgram(String text) {

    LOG.debug("getSelectedProgram: text=" + text);

    Collection<MPart> parts = partService.getParts();
    for (MPart part : parts) {
      if (isOverlayPart(part)) {
        if (text.equals(part.getLabel())) {
          final IEclipseContext context = part.getContext();
          if (context != null) return context.get(IGcodeProgram.class);
        }
      }
    }

    // if part is not instantiated and therefore gcode program is not loaded, then we are here
    return null;
  }
  private void internalFixContext(MPart part, MUIElement oldSelectedElement) {
    if (oldSelectedElement == null) {
      return;
    }

    MContext parentPart = getParentWithContext(oldSelectedElement);
    if (parentPart == null) {
      // technically this shouldn't happen as there should be an MWindow somewhere
      return;
    }
    IEclipseContext parentContext = parentPart.getContext();
    IEclipseContext oldContext = getSubContext(oldSelectedElement);
    Object child = parentContext.getActiveChild();
    if (child == null || oldContext == null || child == oldContext) {
      if (part == null) {
        // TBD this should not be necessary; deactivation is missing somewhere
        IEclipseContext currentActive = parentContext.getActiveChild();
        if (currentActive != null) currentActive.deactivate();
      } else part.getContext().activate();
    }
  }
  /** Dispose of the menu extender. Should only be called when the part is disposed. */
  public void dispose() {
    clearStaticActions();
    final IMenuService menuService = (IMenuService) part.getSite().getService(IMenuService.class);
    if (menuService != null) {
      menuService.releaseContributions(menu);
    }
    Platform.getExtensionRegistry().removeRegistryChangeListener(this);
    menu.removeMenuListener(this);

    if (menuModel != null) {
      // unlink ourselves from the renderer
      IRendererFactory factory = modelPart.getContext().get(IRendererFactory.class);
      AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
      if (obj instanceof MenuManagerRenderer) {
        MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
        unlink(renderer, menuModel);
        renderer.clearModelToManager(menuModel, menu);
      }

      modelPart.getMenus().remove(menuModel);
    }
  }
  private void activate(MPart part, boolean requiresFocus, boolean activateBranch) {
    if (part == null) {
      if (constructed && activePart != null) {
        firePartDeactivated(activePart);
      }
      activePart = part;
      return;
    }

    // Delegate activations to a CompositePart's inner part (if any)
    if (part instanceof MCompositePart) {
      if (part.getContext() != null) {
        IEclipseContext pContext = part.getContext();
        if (pContext.getActiveLeaf() != null) {
          MPart inner = pContext.getActiveLeaf().get(MPart.class);
          if (inner != null) {
            part = inner;
          }
        }
      }
    }

    // only activate parts that is under our control
    if (!isInContainer(part)) {
      return;
    }

    MWindow window = getWindow();
    IEclipseContext windowContext = window.getContext();
    // check if the active part has changed or if we are no longer the active window
    if (windowContext.getParent().getActiveChild() == windowContext && part == activePart) {
      // insert it in the beginning of the activation history, it may not have been inserted
      // pending when this service was instantiated
      partActivationHistory.prepend(part);
      UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part);
      return;
    }
    if (contextService != null) {
      contextService.deferUpdates(true);
    }
    if (contextManager != null) {
      contextManager.deferUpdates(true);
    }

    MPart lastActivePart = activePart;
    activePart = part;

    if (constructed && lastActivePart != null && lastActivePart != activePart) {
      firePartDeactivated(lastActivePart);
    }

    try {
      // record any sibling into the activation history if necessary, this will allow it to be
      // reselected again in the future as it will be an activation candidate in the future,
      // this
      // prevents other unrendered elements from being selected arbitrarily which would cause
      // unwanted bundle activation
      recordStackActivation(part);

      delegateBringToTop(part);
      window.getParent().setSelectedElement(window);

      partActivationHistory.activate(part, activateBranch);

      if (requiresFocus) {
        IPresentationEngine pe = part.getContext().get(IPresentationEngine.class);
        pe.focusGui(part);
      }

      firePartActivated(part);
      UIEvents.publishEvent(UIEvents.UILifeCycle.ACTIVATE, part);
    } finally {
      if (contextService != null) {
        contextService.deferUpdates(false);
      }
      if (contextManager != null) {
        contextManager.deferUpdates(false);
      }
    }
  }
 private boolean isActiveChild(MPart part) {
   IEclipseContext context = part.getContext();
   return context != null && context.getParent().getActiveChild() == context;
 }
  @Override
  public void hidePart(MPart part, boolean force) {
    if (isInContainer(part)) {
      MPlaceholder sharedRef = part.getCurSharedRef();
      MUIElement toBeRemoved = getRemoveTarget(part);
      MElementContainer<MUIElement> parent = getParent(toBeRemoved);
      List<MUIElement> children = parent.getChildren();

      // check if we're a placeholder but not actually the shared ref of the part
      if (toBeRemoved != part && toBeRemoved instanceof MPlaceholder && sharedRef != toBeRemoved) {
        toBeRemoved.setToBeRendered(false);

        // if so, not much to do, remove ourselves if necessary but that's it
        if (force || part.getTags().contains(REMOVE_ON_HIDE_TAG)) {
          parent.getChildren().remove(toBeRemoved);
        }
        return;
      }

      boolean isActiveChild = isActiveChild(part);
      MPart activationCandidate = null;
      // check if we're the active child
      if (isActiveChild) {
        // get the activation candidate if we are
        activationCandidate = partActivationHistory.getNextActivationCandidate(getParts(), part);
      }

      MPerspective thePersp = modelService.getPerspectiveFor(toBeRemoved);
      boolean needNewSel =
          thePersp == null || !thePersp.getTags().contains("PerspClosing"); // $NON-NLS-1$
      if (needNewSel) {
        if (parent.getSelectedElement() == toBeRemoved) {
          // if we're the selected element and we're going to be hidden, need to select
          // something else
          MUIElement candidate = partActivationHistory.getSiblingSelectionCandidate(part);
          candidate =
              candidate == null
                  ? null
                  : candidate.getCurSharedRef() == null ? candidate : candidate.getCurSharedRef();
          if (candidate != null && children.contains(candidate)) {
            parent.setSelectedElement(candidate);
          } else {
            for (MUIElement child : children) {
              if (child != toBeRemoved && child.isToBeRendered()) {
                parent.setSelectedElement(child);
                break;
              }
            }
          }
        }

        if (activationCandidate == null) {
          // nothing else to activate and we're the active child, deactivate
          if (isActiveChild) {
            part.getContext().deactivate();
          }
        } else {
          // activate our candidate
          activate(activationCandidate);
        }
      }

      if (toBeRemoved != null) {
        toBeRemoved.setToBeRendered(false);
      } else {
        part.setToBeRendered(false);
      }

      if (parent.getSelectedElement() == toBeRemoved) {
        parent.setSelectedElement(null);
      }

      if (force || part.getTags().contains(REMOVE_ON_HIDE_TAG)) {
        children.remove(toBeRemoved);
      }
      // remove ourselves from the activation history also since we're being hidden
      partActivationHistory.forget(getWindow(), part, toBeRemoved == part);
    }
  }
  public Object createWidget(final MUIElement element, Object parent) {
    if (!(element instanceof MPart) || !(parent instanceof Composite)) return null;

    Widget parentWidget = (Widget) parent;
    Widget newWidget = null;
    final MPart part = (MPart) element;

    final Composite newComposite =
        new Composite((Composite) parentWidget, SWT.NONE) {

          /**
           * Field to determine whether we are currently in the midst of granting focus to the part.
           */
          private boolean beingFocused = false;

          /*
           * (non-Javadoc)
           *
           * @see org.eclipse.swt.widgets.Composite#setFocus()
           */
          @Override
          public boolean setFocus() {
            if (!beingFocused) {
              try {
                // we are currently asking the part to take focus
                beingFocused = true;

                // delegate an attempt to set the focus here to the
                // part's implementation (if there is one)
                Object object = part.getObject();
                if (object != null) {
                  IPresentationEngine pe = part.getContext().get(IPresentationEngine.class);
                  pe.focusGui(part);
                  return true;
                }
                return super.setFocus();
              } finally {
                // we are done, unset our flag
                beingFocused = false;
              }
            }

            if (logger != null) {
              String id = part.getElementId();
              if (id == null) {
                logger.warn(
                    new IllegalStateException(),
                    "Blocked recursive attempt to activate part " //$NON-NLS-1$
                        + id);
              } else {
                logger.warn(
                    new IllegalStateException(),
                    "Blocked recursive attempt to activate part"); //$NON-NLS-1$
              }
            }

            // already being focused, likely some strange recursive call,
            // just return
            return true;
          }
        };

    newComposite.setLayout(new FillLayout(SWT.VERTICAL));

    newWidget = newComposite;
    bindWidget(element, newWidget);

    // Create a context for this part
    IEclipseContext localContext = part.getContext();
    localContext.set(Composite.class.getName(), newComposite);

    IContributionFactory contributionFactory =
        (IContributionFactory) localContext.get(IContributionFactory.class.getName());
    Object newPart = contributionFactory.create(part.getContributionURI(), localContext);
    part.setObject(newPart);

    return newWidget;
  }
 /*
  * (non-Javadoc)
  *
  * @see
  * org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(
  * org.eclipse.jface.viewers.SelectionChangedEvent)
  */
 public void selectionChanged(SelectionChangedEvent e) {
   MPart part = page.findPart(activePart);
   ESelectionService selectionService =
       (ESelectionService) part.getContext().get(ESelectionService.class.getName());
   selectionService.setSelection(e.getSelection());
 }