private MContext getParentWithContext(MUIElement part) {
    MElementContainer<MUIElement> parent = part.getParent();
    MUIElement intermediate = parent;
    if (intermediate == null) {
      intermediate = part;
    } else {
      while (parent != null) {
        if (parent instanceof MContext) {
          if (((MContext) parent).getContext() != null) return (MContext) parent;
        }
        intermediate = parent;
        parent = parent.getParent();
      }
    }

    MPlaceholder placeholder = modelService.findPlaceholderFor(getWindow(), intermediate);
    parent = placeholder.getParent();
    while (parent != null) {
      if (parent instanceof MContext) {
        if (((MContext) parent).getContext() != null) return (MContext) parent;
      }
      parent = parent.getParent();
    }
    return null;
  }
 private MPlaceholder createSharedPart(MPart sharedPart) {
   // Create and return a reference to the shared part
   MPlaceholder sharedPartRef = modelService.createModelElement(MPlaceholder.class);
   sharedPartRef.setElementId(sharedPart.getElementId());
   sharedPartRef.setRef(sharedPart);
   return sharedPartRef;
 }
 private MElementContainer<MUIElement> findContainer(
     MElementContainer<MUIElement> container, MUIElement element) {
   for (MUIElement child : container.getChildren()) {
     if (child == element) {
       return container;
     } else if (child instanceof MPlaceholder) {
       MPlaceholder placeholder = (MPlaceholder) child;
       MUIElement ref = placeholder.getRef();
       if (ref == element) {
         return container;
       } else if (ref instanceof MElementContainer<?>) {
         @SuppressWarnings("unchecked")
         MElementContainer<MUIElement> ref2 = (MElementContainer<MUIElement>) ref;
         MElementContainer<MUIElement> match = findContainer(ref2, element);
         if (match != null) {
           return match;
         }
       }
     } else if (child instanceof MElementContainer<?>) {
       @SuppressWarnings("unchecked")
       MElementContainer<MUIElement> child2 = (MElementContainer<MUIElement>) child;
       MElementContainer<MUIElement> match = findContainer(child2, element);
       if (match != null) {
         return match;
       }
     }
   }
   return null;
 }
  private Object safeCreateGui(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 safeCreateGui(element, parent, parentContext);
  }
  @Override
  public MUIElement cloneElement(MUIElement element, MSnippetContainer snippetContainer) {
    EObject eObj = (EObject) element;
    MUIElement clone = (MUIElement) EcoreUtil.copy(eObj);

    // null out all the references
    List<MPlaceholder> phList = findElements(clone, null, MPlaceholder.class, null);
    for (MPlaceholder ph : phList) {
      // Skip placeholders in the sharedArea
      int location = getElementLocation(ph);
      if ((location & IN_SHARED_AREA) != 0) {
        continue;
      }

      ph.setRef(null);
    }

    if (snippetContainer != null) {
      MUIElement snippet = findSnippet(snippetContainer, element.getElementId());
      if (snippet != null) {
        snippetContainer.getSnippets().remove(snippet);
      }
      snippetContainer.getSnippets().add(clone);
    }

    // Cache the original element in the clone's transientData
    clone.getTransientData().put(CLONED_FROM_KEY, element);

    return clone;
  }
  @Override
  public MPlaceholder findPlaceholderFor(MWindow window, MUIElement element) {
    List<MPlaceholder> phList = findPerspectiveElements(window, null, MPlaceholder.class, null);
    List<MPlaceholder> elementRefs = new ArrayList<>();
    for (MPlaceholder ph : phList) {
      if (ph.getRef() == element) {
        elementRefs.add(ph);
      }
    }

    if (elementRefs.size() == 0) {
      return null;
    }

    if (elementRefs.size() == 1) {
      return elementRefs.get(0);
    }

    // If there is more than one placeholder then return the one in the shared area
    for (MPlaceholder refPh : elementRefs) {
      int loc = getElementLocation(refPh);
      if ((loc & IN_SHARED_AREA) != 0) {
        return refPh;
      }
    }

    // Just return the first one
    return elementRefs.get(0);
  }
  private void resetPerspectiveModel(
      MPerspective persp, MWindow window, boolean removeSharedPlaceholders) {
    if (persp == null) {
      return;
    }

    if (removeSharedPlaceholders) {
      // Remove any views (Placeholders) from the shared area
      EPartService ps = window.getContext().get(EPartService.class);
      List<MArea> areas = findElements(window, null, MArea.class, null);
      if (areas.size() == 1) {
        MArea area = areas.get(0);

        // Strip out the placeholders in visible stacks
        List<MPlaceholder> phList = findElements(area, null, MPlaceholder.class, null);
        for (MPlaceholder ph : phList) {
          ps.hidePart((MPart) ph.getRef());
          ph.getParent().getChildren().remove(ph);
        }

        // Prevent shared stacks ids from clashing with the ones in the perspective
        List<MPartStack> stacks = findElements(area, null, MPartStack.class, null);
        for (MPartStack stack : stacks) {
          String generatedId = "PartStack@" + Integer.toHexString(stack.hashCode()); // $NON-NLS-1$
          stack.setElementId(generatedId);
        }

        // Also remove any min/max tags on the area (or its placeholder)
        MUIElement areaPresentation = area;
        if (area.getCurSharedRef() != null) {
          areaPresentation = area.getCurSharedRef();
        }

        areaPresentation.getTags().remove(IPresentationEngine.MAXIMIZED);
        areaPresentation.getTags().remove(IPresentationEngine.MINIMIZED);
        areaPresentation.getTags().remove(IPresentationEngine.MINIMIZED_BY_ZOOM);
      }
    }

    // Remove any minimized stacks for this perspective
    List<MTrimBar> bars = findElements(window, null, MTrimBar.class, null);
    List<MToolControl> toRemove = new ArrayList<>();
    for (MTrimBar bar : bars) {
      for (MUIElement barKid : bar.getChildren()) {
        if (!(barKid instanceof MToolControl)) {
          continue;
        }
        String id = barKid.getElementId();
        if (id != null && id.contains(persp.getElementId())) {
          toRemove.add((MToolControl) barKid);
        }
      }
    }

    for (MToolControl toolControl : toRemove) {
      // Close any open fast view
      toolControl.setToBeRendered(false);
      toolControl.getParent().getChildren().remove(toolControl);
    }
  }
  // -------------------------------------------------------
  // -------------------------------------------------------
  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 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);
        }
      }
    }
  }
 /**
  * Returns the parent container of the specified element. If one cannot be found, a check will be
  * performed to see whether the element is being represented by a placeholder, if it is, the
  * placeholder's parent will be returned, if any.
  *
  * @param element the element to query
  * @return the element's parent container, or the parent container of the specified element's
  *     current placeholder, if it has one
  */
 private MElementContainer<MUIElement> getParent(MUIElement element) {
   MElementContainer<MUIElement> parent = element.getParent();
   if (parent == null) {
     MPlaceholder placeholder = element.getCurSharedRef();
     if (placeholder == null) {
       @SuppressWarnings("unchecked")
       MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) getContainer();
       return findContainer(container, element);
     }
     return placeholder.getParent();
   }
   return parent;
 }
 private void disconnectReferencedElementsFromPerspectiveWidgets(
     MElementContainer<? extends MUIElement> container) {
   for (MUIElement e : container.getChildren()) {
     if (e instanceof MPlaceholder) {
       MPlaceholder ph = (MPlaceholder) e;
       if (ph.isToBeRendered()) {
         ComponentContainer phComponent = (ComponentContainer) ph.getWidget();
         Component refComponent = (Component) ph.getRef().getWidget();
         phComponent.removeComponent(refComponent);
       }
     }
   }
 }
 /**
  * Records the specified parent part's selected element in the activation history if the parent is
  * a stack.
  *
  * @param part the part whose parent's selected element should be checked for activation history
  *     recording
  */
 private void recordStackActivation(MPart part) {
   MElementContainer<? extends MUIElement> parent = part.getParent();
   if (parent instanceof MGenericStack) {
     recordSelectedActivation(parent);
   } else if (parent == null) {
     MPlaceholder placeholder = part.getCurSharedRef();
     if (placeholder != null) {
       parent = placeholder.getParent();
       if (parent instanceof MGenericStack) {
         recordSelectedActivation(parent);
       }
     }
   }
 }
 private void adjustPlaceholder(MPart part) {
   if (isShared(part)) {
     MPlaceholder placeholder = part.getCurSharedRef();
     // if this part doesn't have any placeholders, we need to make one
     if (placeholder == null
         // alternatively, if it has one but it's not in the current container, then we
         // need to spawn another one as we don't want to reuse the same one and end up
         // shifting that placeholder to the current container during the add operation
         || (placeholder.getParent() != null && !isInContainer(placeholder))) {
       placeholder = createSharedPart(part);
       part.setCurSharedRef(placeholder);
     }
   }
 }
 @Override
 public Object getUIContainer(MUIElement element) {
   if (element instanceof MToolBar) {
     MUIElement container = (MUIElement) ((EObject) element).eContainer();
     MUIElement parent = container.getParent();
     if (parent == null) {
       MPlaceholder placeholder = container.getCurSharedRef();
       if (placeholder != null) {
         return placeholder.getParent().getWidget();
       }
     } else {
       return parent.getWidget();
     }
   }
   return super.getUIContainer(element);
 }
  @Override
  public <T extends MUIElement> void move(
      T element, MElementContainer<? super T> newParent, int index, boolean leavePlaceholder) {
    // Cache where we were
    MElementContainer<MUIElement> curParent = element.getParent();
    int curIndex = curParent.getChildren().indexOf(element);

    // Move the model element
    if (index == -1) {
      newParent.getChildren().add(element);
    } else {
      newParent.getChildren().add(index, element);
    }

    if (leavePlaceholder) {
      MPlaceholder ph = MAdvancedFactory.INSTANCE.createPlaceholder();
      ph.setRef(element);
      curParent.getChildren().add(curIndex, ph);
    }
  }
 private void handleNullRefPlaceHolders(MUIElement element, MWindow refWin, boolean resolve) {
   // use appContext as MApplication.getContext() is null during the processing of
   // the model processor classes
   EPlaceholderResolver resolver = appContext.get(EPlaceholderResolver.class);
   // Re-resolve any placeholder references
   List<MPlaceholder> phList = findElements(element, null, MPlaceholder.class, null);
   List<MPlaceholder> nullRefList = new ArrayList<>();
   for (MPlaceholder ph : phList) {
     if (resolve) {
       resolver.resolvePlaceholderRef(ph, refWin);
     }
     if (ph.getRef() == null) {
       nullRefList.add(ph);
     }
   }
   for (MPlaceholder ph : nullRefList) {
     replacePlaceholder(ph);
   }
   return;
 }
        @Override
        public void handleEvent(Event event) {
          // no need to do anything if we have no listeners
          if (!listeners.isEmpty()) {
            Object oldSelected = event.getProperty(UIEvents.EventTags.OLD_VALUE);
            if (oldSelected instanceof MPlaceholder) {
              oldSelected = ((MPlaceholder) oldSelected).getRef();
            }

            MPlaceholder placeholder = null;
            Object selected = event.getProperty(UIEvents.EventTags.NEW_VALUE);
            if (selected instanceof MPlaceholder) {
              placeholder = (MPlaceholder) selected;
              selected = placeholder.getRef();
            }

            MPart oldSelectedPart = oldSelected instanceof MPart ? (MPart) oldSelected : null;
            MPart selectedPart = selected instanceof MPart ? (MPart) selected : null;

            if (oldSelectedPart != null && getParts().contains(selectedPart)) {
              firePartHidden(oldSelectedPart);
            }

            if (selectedPart != null
                && selectedPart.isToBeRendered()
                && getParts().contains(selectedPart)) {
              // ask the renderer to create this part
              if (placeholder == null) {
                if (selectedPart.getParent().getRenderer() != null) {
                  engine.createGui(selectedPart);
                  firePartVisible(selectedPart);
                  firePartBroughtToTop(selectedPart);
                }
              } else if (placeholder.getParent().getRenderer() != null) {
                engine.createGui(placeholder);
                firePartVisible(selectedPart);
                firePartBroughtToTop(selectedPart);
              }
            }
          }
        }
  @Override
  public void hideLocalPlaceholders(MWindow window, MPerspective perspective) {
    List<MPlaceholder> globals =
        findElements(window, null, MPlaceholder.class, null, OUTSIDE_PERSPECTIVE | IN_SHARED_AREA);

    // Iterate across the perspective(s) removing any 'local' placeholders
    List<MPerspective> persps = new ArrayList<>();
    if (perspective != null) {
      persps.add(perspective);
    } else {
      persps = findElements(window, null, MPerspective.class, null);
    }

    for (MPerspective persp : persps) {
      List<MPlaceholder> locals =
          findElements(persp, null, MPlaceholder.class, null, IN_ANY_PERSPECTIVE);
      for (MPlaceholder local : locals) {
        for (MPlaceholder global : globals) {
          if (global.getRef() == local.getRef()) {
            local.setToBeRendered(false);
            MElementContainer<MUIElement> localParent = local.getParent();
            setStackVisibility(localParent);
          }
        }
      }
    }
  }
  @Override
  public void bringToTop(MPart part) {
    if (isInContainer(part)) {
      MUIElement currentElement = part;
      MElementContainer<MUIElement> parent = part.getParent();
      if (parent == null) {
        currentElement = modelService.findPlaceholderFor(getWindow(), part);
        parent = currentElement.getParent();
      }

      // If the part is in the same stack as the currently active part then activate it
      // instead
      MElementContainer<MUIElement> activeParent =
          activePart != null ? activePart.getParent() : null;
      if (activePart != null && activeParent == null) {
        MPlaceholder activePH = modelService.findPlaceholderFor(getWindow(), activePart);
        if (activePH != null) {
          activeParent = activePH.getParent();
        }
      }
      if (parent == activeParent && part != activePart) {
        activate(part);
        return;
      }

      MUIElement oldSelectedElement = parent.getSelectedElement();

      delegateBringToTop(part);

      // check to make sure that the currently selected element is actually valid
      if (oldSelectedElement != currentElement
          && parent.getChildren().contains(oldSelectedElement)
          && parent instanceof MGenericStack<?>) {
        if (oldSelectedElement instanceof MPlaceholder) {
          oldSelectedElement = ((MPlaceholder) oldSelectedElement).getRef();
        }
        internalFixContext(part, oldSelectedElement);
      }
    }
  }
  @Override
  public boolean isPartOrPlaceholderInPerspective(String elementId, MPerspective perspective) {
    List<MPart> findElements = modelService.findElements(perspective, elementId, MPart.class, null);
    if (!findElements.isEmpty()) {
      MPart part = findElements.get(0);

      // if that is a shared part, check the placeholders
      if (workbenchWindow.getSharedElements().contains(part)) {
        List<MPlaceholder> placeholders =
            modelService.findElements(perspective, elementId, MPlaceholder.class, null);
        for (MPlaceholder mPlaceholder : placeholders) {
          if (mPlaceholder.isVisible() && mPlaceholder.isToBeRendered()) {
            return true;
          }
        }
        return false;
      }
      // not a shared part
      return part.isVisible() && part.isToBeRendered();
    }
    return false;
  }
  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 replacePlaceholder(MPlaceholder ph) {
   MPart part = createModelElement(MPart.class);
   part.setElementId(ph.getElementId());
   part.getTransientData()
       .put(
           IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY,
           ImageDescriptor.getMissingImageDescriptor().createImage());
   String label = (String) ph.getTransientData().get(TAG_LABEL);
   if (label != null) {
     part.setLabel(label);
   } else {
     part.setLabel(getLabel(ph.getElementId()));
   }
   part.setContributionURI(COMPATIBILITY_VIEW_URI);
   part.setCloseable(true);
   MElementContainer<MUIElement> curParent = ph.getParent();
   int curIndex = curParent.getChildren().indexOf(ph);
   curParent.getChildren().remove(curIndex);
   curParent.getChildren().add(curIndex, part);
   if (curParent.getSelectedElement() == ph) {
     curParent.setSelectedElement(part);
   }
 }
  public Object createWidget(final MUIElement element, Object parent) {
    MPlaceholder ph = (MPlaceholder) element;
    final MUIElement ref = ph.getRef();
    ref.setCurSharedRef(ph);

    List<MPlaceholder> renderedRefs = renderedMap.get(ref);
    if (renderedRefs == null) {
      renderedRefs = new ArrayList<MPlaceholder>();
      renderedMap.put(ref, renderedRefs);
    }

    if (!renderedRefs.contains(ph)) renderedRefs.add(ph);

    Composite newComp = new Composite((Composite) parent, SWT.NONE);
    newComp.setLayout(new FillLayout());

    Control refWidget = (Control) ref.getWidget();
    if (refWidget == null) {
      ref.setToBeRendered(true);
      refWidget = (Control) renderingEngine.createGui(ref, newComp, getContextForParent(ref));
    } else {
      if (refWidget.getParent() != newComp) {
        refWidget.setParent(newComp);
      }
    }

    if (ref instanceof MContext) {
      IEclipseContext context = ((MContext) ref).getContext();
      IEclipseContext newParentContext = getContext(ph);
      if (context.getParent() != newParentContext) {
        context.setParent(newParentContext);
      }
    }

    return newComp;
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer#disposeWidget
   * (org.eclipse.e4.ui.model.application.ui.MUIElement)
   */
  @Override
  public void disposeWidget(MUIElement element) {
    MPlaceholder ph = (MPlaceholder) element;
    MUIElement refElement = ph.getRef();
    Control refCtrl = (Control) refElement.getWidget();

    // Remove the element ref from the rendered list
    List<MPlaceholder> refs = renderedMap.get(refElement);
    refs.remove(ph);

    IEclipseContext curContext = modelService.getContainingContext(ph);

    if (refs.size() == 0) {
      // Ensure that the image is the 'original' image for this
      // part. See bug 347471 for details
      if (refElement instanceof MPart) {
        MPart thePart = (MPart) refElement;
        String imageURI = thePart.getIconURI();
        thePart.setIconURI(null);
        thePart.setIconURI(imageURI);
      }

      renderingEngine.removeGui(refElement);
    } else {
      // Ensure that the dispose of the element reference doesn't cascade
      // to dispose the 'real' part
      if (refCtrl != null && !refCtrl.isDisposed()) {
        MPlaceholder currentRef = refElement.getCurSharedRef();
        if (currentRef == ph) {
          // Find another *rendered* ref to pass the part on to
          for (MPlaceholder aPH : refs) {
            Composite phComp = (Composite) aPH.getWidget();
            if (phComp == null || phComp.isDisposed()) continue;

            // Reparent the context(s) (if any)
            IEclipseContext newParentContext = modelService.getContainingContext(aPH);
            List<MContext> allContexts =
                modelService.findElements(refElement, null, MContext.class, null);
            for (MContext ctxtElement : allContexts) {
              IEclipseContext theContext = ctxtElement.getContext();
              // this may be null if it hasn't been rendered yet
              if (theContext != null) {
                if (theContext.getParent() == curContext) {
                  // about to reparent the context, if we're
                  // the active child of the current parent,
                  // deactivate ourselves first
                  if (curContext.getActiveChild() == theContext) {
                    theContext.deactivate();
                  }
                  theContext.setParent(newParentContext);
                }
              }
            }

            // reset the 'cur' ref
            refElement.setCurSharedRef(aPH);

            // Reparent the widget
            refCtrl.setParent(phComp);
            break;
          }
        } else if (currentRef != null) {
          Composite phComp = (Composite) currentRef.getWidget();
          if (phComp == null || phComp.isDisposed()) {
            super.disposeWidget(element);
            return;
          }

          // Reparent the context(s) (if any)
          IEclipseContext newParentContext = modelService.getContainingContext(currentRef);
          List<MContext> allContexts =
              modelService.findElements(refElement, null, MContext.class, null);
          for (MContext ctxtElement : allContexts) {
            IEclipseContext theContext = ctxtElement.getContext();
            // this may be null if it hasn't been rendered yet
            if (theContext != null && theContext.getParent() == curContext) {
              // about to reparent the context, if we're the
              // active child of the current parent, deactivate
              // ourselves first
              if (curContext.getActiveChild() == theContext) {
                theContext.deactivate();
              }
              theContext.setParent(newParentContext);
            }
          }
        }
      }
    }

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

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

      ComponentContainer phComponent = (ComponentContainer) ph.getWidget();
      Component refComponent = (Component) ph.getRef().getWidget();
      phComponent.addComponent(refComponent);

      element = ref;

      // top right folder
      MPartStack topLeftStack = HierarchyUtils.findTopLeftFolder(ph.getRef());
      if (topLeftStack != null) {
        if (ph.getTags().contains(IPresentationEngine.MAXIMIZED))
          ((StackWidget) topLeftStack.getWidget()).setState(1);
        else if (ph.getTags().contains(IPresentationEngine.MINIMIZED))
          ((StackWidget) topLeftStack.getWidget()).setState(-1);
        else ((StackWidget) topLeftStack.getWidget()).setState(0);
      }
    }

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

    // Show any floating windows
    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 MElementContainer<?>) {
      MElementContainer<?> container = (MElementContainer<?>) element;
      List<MUIElement> kids = new ArrayList<MUIElement>(container.getChildren());
      for (MUIElement childElement : kids) {
        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);
        }
      }
    }
  }
  private <T> void findElementsRecursive(
      MApplicationElement searchRoot,
      Class<T> clazz,
      Selector matcher,
      List<T> elements,
      int searchFlags) {
    Assert.isLegal(searchRoot != null);
    if (searchFlags == 0) {
      return;
    }

    // are *we* a match ?
    boolean classMatch = clazz == null ? true : clazz.isInstance(searchRoot);
    if (classMatch && matcher.select(searchRoot)) {
      if (!elements.contains(searchRoot)) {
        @SuppressWarnings("unchecked")
        T element = (T) searchRoot;
        elements.add(element);
      }
    }
    if (searchRoot instanceof MApplication && (searchFlags == ANYWHERE)) {
      MApplication app = (MApplication) searchRoot;

      List<MApplicationElement> children = new ArrayList<>();
      if (clazz != null) {
        if (clazz.equals(MHandler.class)) {
          children.addAll(app.getHandlers());
        } else if (clazz.equals(MCommand.class)) {
          children.addAll(app.getCommands());
        } else if (clazz.equals(MBindingContext.class)) {
          children.addAll(app.getBindingContexts());
        } else if (clazz.equals(MBindingTable.class) || clazz.equals(MKeyBinding.class)) {
          children.addAll(app.getBindingTables());
        }
        // } else { only look for these if specifically asked.
        // children.addAll(app.getHandlers());
        // children.addAll(app.getCommands());
        // children.addAll(app.getBindingContexts());
        // children.addAll(app.getBindingTables());
      }

      for (MApplicationElement child : children) {
        findElementsRecursive(child, clazz, matcher, elements, searchFlags);
      }
    }

    if (searchRoot instanceof MBindingContext && (searchFlags == ANYWHERE)) {
      MBindingContext bindingContext = (MBindingContext) searchRoot;
      for (MBindingContext child : bindingContext.getChildren()) {
        findElementsRecursive(child, clazz, matcher, elements, searchFlags);
      }
    }

    if (searchRoot instanceof MBindingTable) {
      MBindingTable bindingTable = (MBindingTable) searchRoot;
      for (MKeyBinding child : bindingTable.getBindings()) {
        findElementsRecursive(child, clazz, matcher, elements, searchFlags);
      }
    }

    // Check regular containers
    if (searchRoot instanceof MElementContainer<?>) {
      /*
       * Bug 455281: If given a window with a primary perspective stack,
       * and we're not told to look outside of the perspectives (i.e.,
       * searchFlags is missing OUTSIDE_PERSPECTIVE), then just search the
       * primary perspective stack instead. This ignores special areas
       * like the compat layer's stack holding the Help, CheatSheets, and
       * Intro.
       */
      MElementContainer<?> searchContainer = (MElementContainer<?>) searchRoot;
      MPerspectiveStack primaryStack = null;
      if (searchRoot instanceof MWindow
          && (searchFlags & OUTSIDE_PERSPECTIVE) == 0
          && (primaryStack = getPrimaryPerspectiveStack((MWindow) searchRoot)) != null) {
        searchContainer = primaryStack;
      }
      if (searchContainer instanceof MPerspectiveStack) {
        if ((searchFlags & IN_ANY_PERSPECTIVE) != 0) {
          // Search *all* the perspectives
          MElementContainer<? extends MUIElement> container = searchContainer;
          List<? extends MUIElement> children = container.getChildren();
          for (MUIElement child : children) {
            findElementsRecursive(child, clazz, matcher, elements, searchFlags);
          }
        } else if ((searchFlags & IN_ACTIVE_PERSPECTIVE) != 0) {
          // Only search the currently active perspective, if any
          MPerspective active = ((MPerspectiveStack) searchContainer).getSelectedElement();
          if (active != null) {
            findElementsRecursive(active, clazz, matcher, elements, searchFlags);
          }
        } else if ((searchFlags & IN_SHARED_AREA) != 0) {
          // Only recurse through the shared areas
          List<MArea> areas = findElements(searchContainer, null, MArea.class, null);
          for (MArea area : areas) {
            findElementsRecursive(area, clazz, matcher, elements, searchFlags);
          }
        }
      } else {
        @SuppressWarnings("unchecked")
        MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) searchRoot;
        List<MUIElement> children = container.getChildren();
        for (MUIElement child : children) {
          findElementsRecursive(child, clazz, matcher, elements, searchFlags);
        }
      }
    }

    // Search Trim
    if (searchRoot instanceof MTrimmedWindow && (searchFlags & IN_TRIM) != 0) {
      MTrimmedWindow tw = (MTrimmedWindow) searchRoot;
      List<MTrimBar> bars = tw.getTrimBars();
      for (MTrimBar bar : bars) {
        findElementsRecursive(bar, clazz, matcher, elements, searchFlags);
      }
    }

    // Search Detached Windows
    if (searchRoot instanceof MWindow) {
      MWindow window = (MWindow) searchRoot;
      for (MWindow dw : window.getWindows()) {
        findElementsRecursive(dw, clazz, matcher, elements, searchFlags);
      }

      MMenu menu = window.getMainMenu();
      if (menu != null && (searchFlags & IN_MAIN_MENU) != 0) {
        findElementsRecursive(menu, clazz, matcher, elements, searchFlags);
      }
      // Check for Handlers
      if (searchFlags == ANYWHERE && MHandler.class.equals(clazz)) {
        for (MHandler child : window.getHandlers()) {
          findElementsRecursive(child, clazz, matcher, elements, searchFlags);
        }
      }
    }

    if (searchRoot instanceof MPerspective) {
      MPerspective persp = (MPerspective) searchRoot;
      for (MWindow dw : persp.getWindows()) {
        findElementsRecursive(dw, clazz, matcher, elements, searchFlags);
      }
    }
    // Search shared elements
    if (searchRoot instanceof MPlaceholder) {
      MPlaceholder ph = (MPlaceholder) searchRoot;

      // Don't search in shared areas unless the flag is set
      if (ph.getRef() != null
          && (!(ph.getRef() instanceof MArea) || (searchFlags & IN_SHARED_AREA) != 0)) {
        findElementsRecursive(ph.getRef(), clazz, matcher, elements, searchFlags);
      }
    }

    if (searchRoot instanceof MPart && (searchFlags & IN_PART) != 0) {
      MPart part = (MPart) searchRoot;

      for (MMenu menu : part.getMenus()) {
        findElementsRecursive(menu, clazz, matcher, elements, searchFlags);
      }

      MToolBar toolBar = part.getToolbar();
      if (toolBar != null) {
        findElementsRecursive(toolBar, clazz, matcher, elements, searchFlags);
      }
      if (MHandler.class.equals(clazz)) {
        for (MHandler child : part.getHandlers()) {
          findElementsRecursive(child, clazz, matcher, elements, searchFlags);
        }
      }
    }
  }
  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);
        }
      }
    }
  }