@Override
  public boolean isPartVisible(MPart part) {
    if (isInContainer(part)) {
      MUIElement element = part;
      MElementContainer<?> parent = part.getParent();
      if (parent == null) {
        // might be a shared part
        element = part.getCurSharedRef();
        if (element == null) {
          return false;
        }

        parent = element.getParent();
        if (parent == null) {
          return false;
        }
      }

      if (parent instanceof MPartStack) {
        return parent.getSelectedElement() == element;
      }

      return element.isVisible();
    }
    return false;
  }
  @Override
  public MPart showPart(MPart part, PartState partState) {
    Assert.isNotNull(part);
    Assert.isNotNull(partState);

    MPart addedPart = addPart(part);
    MPlaceholder localPlaceholder = getLocalPlaceholder(addedPart);
    // correct the placeholder setting if necessary
    if (localPlaceholder != null && addedPart.getCurSharedRef() != localPlaceholder) {
      addedPart.setCurSharedRef(localPlaceholder);
    }

    switch (partState) {
      case ACTIVATE:
        activate(addedPart);
        return addedPart;
      case VISIBLE:
        MPart activePart = getActivePart();
        if (activePart == null
            || (activePart != addedPart && getParent(activePart) == getParent(addedPart))) {
          delegateBringToTop(addedPart);
          activate(addedPart);
        } else {
          bringToTop(addedPart);
        }
        return addedPart;
      case CREATE:
        createElement(addedPart);
        return addedPart;
    }
    return addedPart;
  }
  private void addToLastContainer(String category, MPart part) {
    // OK, we haven't found an explicit placeholder;
    // If this is a multi-instance view see if there's a 'global' placeholder
    String partId = part.getElementId();
    int colonIndex = partId == null ? -1 : partId.indexOf(':');
    if (colonIndex >= 0) {
      String descId = part.getElementId().substring(0, colonIndex);
      descId += ":*"; // $NON-NLS-1$
      List<MPlaceholder> phList =
          modelService.findElements(
              workbenchWindow, descId, MPlaceholder.class, null, EModelService.PRESENTATION);
      if (phList.size() > 0) {
        MUIElement phParent = phList.get(0).getParent();
        if (phParent instanceof MPartStack) {
          MPartStack theStack = (MPartStack) phParent;
          int phIndex = theStack.getChildren().indexOf(phList.get(0));
          adjustPlaceholder(part);
          MPlaceholder placeholder = part.getCurSharedRef();
          if (placeholder == null) {
            theStack.getChildren().add(phIndex, part);
          } else {
            theStack.getChildren().add(phIndex, placeholder);
          }
          return;
        }
      }
    }

    @SuppressWarnings("unchecked")
    MElementContainer<MUIElement> lastContainer =
        (MElementContainer<MUIElement>) getLastContainer();
    MPlaceholder placeholder = part.getCurSharedRef();
    if (placeholder == null) {
      lastContainer.getChildren().add(part);
    } else {
      lastContainer.getChildren().add(placeholder);
    }

    if (category != null) {
      lastContainer.getTags().add(category);
    }
  }
 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);
     }
   }
 }
 /**
  * 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);
       }
     }
   }
 }
  /**
   * Adds a part to the current container if it isn't already in the container. The part may still
   * be added to the container if the part supports having multiple copies of itself in a given
   * container.
   *
   * @param providedPart the part to add
   * @param localPart a part that shares attributes with <code>providedPart</code>, for example, it
   *     may have been backed by the same part descriptor, this part may already be in the current
   *     container
   * @return a part that has been added to the current container, note that this may not necessarily
   *     be <code>providedPart</code>
   * @see MPartDescriptor#isAllowMultiple()
   */
  private MPart addPart(MPart providedPart, MPart localPart) {
    MPartDescriptor descriptor = modelService.getPartDescriptor(providedPart.getElementId());
    if (descriptor == null) {
      // there is no part descriptor backing the provided part, just add it to the container
      // if it's not already there
      if (!isInContainer(providedPart)) {
        adjustPlaceholder(providedPart);
        addToLastContainer(null, providedPart);
      }
    } else {
      if (providedPart != localPart && !descriptor.isAllowMultiple()) {
        // multiple copies of this part are not allowed, just return the local one
        return localPart;
      }

      // already in the container, return as is
      if (isInContainer(providedPart)) {
        return providedPart;
      }

      // corrects this part's placeholder if necessary
      adjustPlaceholder(providedPart);

      String category = descriptor.getCategory();
      if (category == null) {
        // no category, just add it to the end
        addToLastContainer(null, providedPart);
      } else {
        if ("org.eclipse.e4.primaryDataStack".equals(category)) { // $NON-NLS-1$
          MElementContainer<? extends MUIElement> container = getContainer();
          MUIElement area = modelService.find("org.eclipse.ui.editorss", container); // $NON-NLS-1$

          MPartStack activeStack = null;
          if (area instanceof MPlaceholder && ((MPlaceholder) area).getRef() instanceof MArea) {
            // Find the currently 'active' stack in the area
            MArea a = (MArea) ((MPlaceholder) area).getRef();
            MUIElement curActive = a.getSelectedElement();
            while (curActive instanceof MElementContainer<?>) {
              if (curActive instanceof MPartStack) {
                activeStack = (MPartStack) curActive;
                break;
              }
              MElementContainer<?> curContainer = (MElementContainer<?>) curActive;
              curActive = curContainer.getSelectedElement();
            }
          }

          if (activeStack != null) {
            activeStack.getChildren().add(providedPart);
          } else {
            // Find the first visible stack in the area
            List<MPartStack> sharedStacks =
                modelService.findElements(area, null, MPartStack.class, null);
            if (sharedStacks.size() > 0) {
              for (MPartStack stack : sharedStacks) {
                if (stack.isToBeRendered()) {
                  stack.getChildren().add(providedPart);
                  break;
                }
              }
            } else {
              addToLastContainer(null, providedPart);
            }
          }
        } else {
          @SuppressWarnings("rawtypes")
          List<MElementContainer> containers =
              modelService.findElements(
                  getContainer(),
                  null,
                  MElementContainer.class,
                  Collections.singletonList(category),
                  EModelService.PRESENTATION);
          if (containers.isEmpty()) {
            // couldn't find any containers with the specified tag, just add it to the
            // end
            addToLastContainer(category, providedPart);
          } else {
            // add the part to the container
            MElementContainer<MPartSashContainerElement> container = containers.get(0);
            MPlaceholder placeholder = providedPart.getCurSharedRef();
            if (placeholder == null) {
              container.getChildren().add(providedPart);
            } else {
              container.getChildren().add(placeholder);
            }
          }
        }
      }
    }
    return providedPart;
  }
  @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);
    }
  }