public void handleEvent(Event event) {
          if (psTB.isDisposed()) {
            return;
          }

          MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);

          if (psME == null || !(changedElement instanceof MPerspective)) return;

          String attName = (String) event.getProperty(UIEvents.EventTags.ATTNAME);
          Object newValue = event.getProperty(UIEvents.EventTags.NEW_VALUE);

          MWindow perspWin = modelService.getTopLevelWindowFor(changedElement);
          MWindow switcherWin = modelService.getTopLevelWindowFor(psME);
          if (perspWin != switcherWin) return;

          MPerspective perspective = (MPerspective) changedElement;
          if (!perspective.isToBeRendered()) return;

          for (ToolItem ti : psTB.getItems()) {
            if (ti.getData() == perspective) {
              updateToolItem(ti, attName, newValue);
            }
          }

          // update the size
          fixSize();
        }
  @Override
  public int countRenderableChildren(MUIElement element) {
    if (!(element instanceof MElementContainer<?>)) {
      return 0;
    }

    @SuppressWarnings("unchecked")
    MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
    int count = 0;
    List<MUIElement> kids = container.getChildren();
    for (MUIElement kid : kids) {
      if (kid.isToBeRendered()) {
        count++;
      }
    }

    if (element instanceof MPerspective) {
      MPerspective perspective = (MPerspective) element;
      for (MWindow window : perspective.getWindows()) {
        if (window.isToBeRendered()) {
          count++;
        }
      }
    }
    return count;
  }
  @Override
  public void detach(MPartSashContainerElement element, int x, int y, int width, int height) {
    // If we're showing through a placehoilder then detach it...
    if (element.getCurSharedRef() != null) {
      element = element.getCurSharedRef();
    }

    // Determine the correct parent for the new window
    MWindow window = getTopLevelWindowFor(element);
    MPerspective thePersp = getPerspectiveFor(element);

    MTrimmedWindow newWindow = MBasicFactory.INSTANCE.createTrimmedWindow();

    newWindow.setX(x);
    newWindow.setY(y);
    newWindow.setWidth(width);
    newWindow.setHeight(height);

    element.getParent().getChildren().remove(element);
    MWindowElement uiRoot = wrapElementForWindow(element);
    newWindow.getChildren().add(uiRoot);

    if (thePersp != null) {
      thePersp.getWindows().add(newWindow);
    } else if (window != null) {
      window.getWindows().add(newWindow);
    }
  }
        public void handleEvent(Event event) {
          if (psTB.isDisposed()) {
            return;
          }

          Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);

          if (psME == null || !(changedObj instanceof MPerspectiveStack)) return;

          MWindow perspWin = modelService.getTopLevelWindowFor((MUIElement) changedObj);
          MWindow switcherWin = modelService.getTopLevelWindowFor(psME);
          if (perspWin != switcherWin) return;

          if (UIEvents.isADD(event)) {
            for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.NEW_VALUE)) {
              MPerspective added = (MPerspective) o;
              // Adding invisible elements is a NO-OP
              if (!added.isToBeRendered()) continue;

              addPerspectiveItem(added);
            }
          } else if (UIEvents.isREMOVE(event)) {
            for (Object o : UIEvents.asIterable(event, UIEvents.EventTags.OLD_VALUE)) {
              MPerspective removed = (MPerspective) o;
              // Removing invisible elements is a NO-OP
              if (!removed.isToBeRendered()) continue;

              removePerspectiveItem(removed);
            }
          }
        }
  @Override
  public void removePerspectiveModel(MPerspective persp, MWindow window) {
    // pick a new perspective to become active (if any)
    MUIElement psElement = persp.getParent();
    MPerspectiveStack ps = (MPerspectiveStack) psElement;
    boolean foundNewSelection = false;
    if (ps.getSelectedElement() == persp) {
      for (MPerspective p : ps.getChildren()) {
        if (p != persp && p.isToBeRendered()) {
          ps.setSelectedElement(p);
          foundNewSelection = true;
          break;
        }
      }

      if (!foundNewSelection) {
        ps.setSelectedElement(null);
      }
    }

    // Remove transient elements (minimized stacks, detached windows)
    resetPerspectiveModel(persp, window, false);

    // unrender the perspective and remove it
    persp.setToBeRendered(false);
    ps.getChildren().remove(persp);
  }
 private void switchPerspective(MPerspective perspective) {
   if (perspective.isToBeRendered() && perspective.getWidget() == null)
     engine.createGui(perspective);
   partService.switchPerspective(perspective);
   this.activePerspective = perspective;
   if (perspective.getElementId() != null) {
     String perspectiveId = perspective.getElementId().trim();
     application.getContext().set("activePerspective", perspectiveId);
   }
 }
  @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);
      }
    }
  }
  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));
    }
  }
 @Inject
 void setPart(@Optional @Named(IServiceConstants.ACTIVE_PART) MPart p) {
   if (activePart != p) {
     if (p != null) {
       MPerspective persp = modelService.getPerspectiveFor(p);
       boolean inCurrentPerspective =
           persp == null || persp == persp.getParent().getSelectedElement();
       if (inCurrentPerspective) {
         activate(p, true, true);
       }
     } else {
       activate(p, true, true);
     }
   }
 }
  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);
    }
  }
  boolean isInContainer(MElementContainer<?> container, MUIElement element) {
    for (Object object : container.getChildren()) {
      if (object == element) {
        return true;
      } else if (object instanceof MElementContainer<?>) {
        if (isInContainer((MElementContainer<?>) object, element)) {
          return true;
        }
      } else if (object instanceof MPlaceholder) {
        MUIElement ref = ((MPlaceholder) object).getRef();
        if (ref == element) {
          return true;
        } else if (ref instanceof MElementContainer<?>) {
          if (isInContainer((MElementContainer<?>) ref, element)) {
            return true;
          }
        }
      } else if (object instanceof MPerspective) {
        MPerspective persp = (MPerspective) object;
        for (MWindow dw : persp.getWindows()) {
          if (isInContainer(dw, element)) return true;
        }
      } else if (object instanceof MWindow) {
        MWindow win = (MWindow) object;
        for (MWindow dw : win.getWindows()) {
          if (isInContainer(dw, element)) return true;
        }
      }
    }

    if (container instanceof MWindow) {
      MWindow win = (MWindow) container;
      for (MWindow dw : win.getWindows()) {
        if (isInContainer(dw, element)) return true;
      }
    }

    if (container instanceof MPerspective) {
      MPerspective persp = (MPerspective) container;
      for (MWindow dw : persp.getWindows()) {
        if (isInContainer(dw, element)) return true;
      }
    }

    return false;
  }
        @Override
        public void handleEvent(Event event) {
          Object changedObj = event.getProperty(EventTags.ELEMENT);

          if (!(changedObj instanceof MPerspectiveStack)) {
            return;
          }

          final MPerspectiveStack changedElement = (MPerspectiveStack) changedObj;

          String eventType = (String) event.getProperty(UIEvents.EventTags.TYPE);
          String tag = (String) event.getProperty(UIEvents.EventTags.NEW_VALUE);
          String oldVal = (String) event.getProperty(UIEvents.EventTags.OLD_VALUE);

          if (UIEvents.EventTypes.ADD.equals(eventType) && Tags.ICONS_ONLY.equals(tag)) {
            for (Map.Entry<MPerspective, TwoStateToolbarButton> entry :
                perspective_button.entrySet()) {
              MPerspective perspective = entry.getKey();
              TwoStateToolbarButton button = entry.getValue();

              button.setLabelAndIcon(null, Commons.trim(perspective.getIconURI()));

              ContextMenu menu = button2ContextMenu.get(button);
              //					menu.removeItem(showTextItem);
              //					showTextItem = menu.addItem("Show Text");
              //					showTextItem.addStyleName("close-perspective-item"); //bugfixing style for ie9
              // (context menu addon has bug for ie9)
            }
          } else if (UIEvents.EventTypes.REMOVE.equals(eventType)
              && Tags.ICONS_ONLY.equals(oldVal)) {
            for (Map.Entry<MPerspective, TwoStateToolbarButton> entry :
                perspective_button.entrySet()) {
              MPerspective perspective = entry.getKey();
              TwoStateToolbarButton button = entry.getValue();
              button.setLabelAndIcon(
                  Commons.trim(perspective.getLabel()), Commons.trim(perspective.getIconURI()));

              ContextMenu menu = button2ContextMenu.get(button);
              //					menu.removeItem(showTextItem);
              //					showTextItem = menu.addItem("Hide Text");
              //					showTextItem.addStyleName("close-perspective-item"); //bugfixing style for ie9
              // (context menu addon has bug for ie9)
            }
          }
        }
  private void closePerspective(MPerspective persp) {
    MWindow win = modelService.getTopLevelWindowFor(persp);
    WorkbenchPage page = (WorkbenchPage) win.getContext().get(IWorkbenchPage.class);
    String perspectiveId = persp.getElementId();
    IPerspectiveDescriptor desc = getDescriptorFor(perspectiveId);
    page.closePerspective(desc, perspectiveId, true, false);

    // removePerspectiveItem(persp);
  }
  private void changeShowText(boolean showText) {
    ToolItem[] items = psTB.getItems();
    for (int i = 0; i < items.length; i++) {
      MPerspective persp = (MPerspective) items[i].getData();
      if (persp != null)
        if (showText) {
          if (persp.getLabel() != null) items[i].setText(persp.getLocalizedLabel());
          items[i].setToolTipText(persp.getLocalizedTooltip());
        } else {
          Image image = items[i].getImage();
          if (image != null) {
            items[i].setText(""); // $NON-NLS-1$
            items[i].setToolTipText(persp.getLocalizedLabel());
          }
        }
    }

    // update the size
    fixSize();
  }
  @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));
    }
  }
  @Override
  public int getElementLocation(MUIElement element) {
    if (element == null) {
      return NOT_IN_UI;
    }

    // If the element is shared then use its current placeholder
    if (element.getCurSharedRef() != null) {
      element = element.getCurSharedRef();
    }

    int location = NOT_IN_UI;
    MUIElement curElement = element;
    while (curElement != null) {
      Object container = ((EObject) curElement).eContainer();
      if (!(container instanceof MUIElement)) return NOT_IN_UI;

      if (container instanceof MApplication) {
        if (location != NOT_IN_UI) return location;
        return OUTSIDE_PERSPECTIVE;
      } else if (container instanceof MPerspective) {
        MPerspective perspective = (MPerspective) container;
        MUIElement perspParent = perspective.getParent();
        if (perspParent == null) {
          location = NOT_IN_UI;
        } else if (perspective.getParent().getSelectedElement() == perspective) {
          location |= IN_ACTIVE_PERSPECTIVE;
        } else {
          location |= IN_ANY_PERSPECTIVE;
        }
      } else if (container instanceof MTrimBar) {
        location = IN_TRIM;
      } else if (container instanceof MArea) {
        location = IN_SHARED_AREA;
      }

      curElement = (MUIElement) container;
    }

    return NOT_IN_UI;
  }
        public void handleEvent(Event event) {
          if (psTB.isDisposed()) {
            return;
          }

          MUIElement changedElement = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);

          if (psME == null || !(changedElement instanceof MPerspective)) return;

          MWindow perspWin = modelService.getTopLevelWindowFor(changedElement);
          MWindow switcherWin = modelService.getTopLevelWindowFor(psME);
          if (perspWin != switcherWin) return;

          MPerspective persp = (MPerspective) changedElement;
          if (!persp.getParent().isToBeRendered()) return;

          if (changedElement.isToBeRendered()) {
            addPerspectiveItem(persp);
          } else {
            removePerspectiveItem(persp);
          }
        }
  private void openMenuFor(ToolItem item, MPerspective persp) {
    final Menu menu = new Menu(psTB);
    menu.setData(persp);
    if (persp.getParent().getSelectedElement() == persp) {
      addSaveAsItem(menu);
      addResetItem(menu);
    }

    if (persp.isVisible()) {
      addCloseItem(menu);
    }

    new MenuItem(menu, SWT.SEPARATOR);
    // addDockOnSubMenu(menu);
    addShowTextItem(menu);

    Rectangle bounds = item.getBounds();
    Point point = psTB.toDisplay(bounds.x, bounds.y + bounds.height);
    menu.setLocation(point.x, point.y);
    menu.setVisible(true);
    menu.addMenuListener(
        new MenuListener() {

          public void menuHidden(MenuEvent e) {
            psTB.getDisplay()
                .asyncExec(
                    new Runnable() {

                      public void run() {
                        menu.dispose();
                      }
                    });
          }

          public void menuShown(MenuEvent e) {
            // Nothing to do
          }
        });
  }
  @Override
  public void processContents(MElementContainer<MUIElement> element) {
    if (element.getChildren().isEmpty()) return;

    MPerspectiveStack perspectiveStack = (MPerspectiveStack) (MElementContainer<?>) element;
    MPerspective selectedPerspective = perspectiveStack.getSelectedElement();

    if (selectedPerspective == null) {
      selectedPerspective = (MPerspective) findFirstRenderableAndVisibleElement(perspectiveStack);
      if (selectedPerspective != null) switchPerspective(selectedPerspective);
    } else if (!selectedPerspective.isToBeRendered() || !selectedPerspective.isVisible()) {
      selectedPerspective = (MPerspective) findFirstRenderableAndVisibleElement(perspectiveStack);
      if (selectedPerspective != null) switchPerspective(selectedPerspective);
      else perspectiveStack.setSelectedElement(null);
    } else {
      // reset selected element (set selected element handler will work)
      perspectiveStack.setSelectedElement(null);
      switchPerspective(selectedPerspective);
    }

    refreshPerspectiveStackVisibility(perspectiveStack);
  }
  @PostConstruct
  void createWidget(Composite parent, MToolControl toolControl) {
    psME = toolControl;
    MUIElement meParent = psME.getParent();
    int orientation = SWT.HORIZONTAL;
    if (meParent instanceof MTrimBar) {
      MTrimBar bar = (MTrimBar) meParent;
      if (bar.getSide() == SideValue.RIGHT || bar.getSide() == SideValue.LEFT)
        orientation = SWT.VERTICAL;
    }
    comp = new Composite(parent, SWT.NONE);
    RowLayout layout = new RowLayout(SWT.HORIZONTAL);
    layout.marginLeft = layout.marginRight = 8;
    layout.marginBottom = 4;
    layout.marginTop = 6;
    comp.setLayout(layout);
    psTB = new ToolBar(comp, SWT.FLAT | SWT.WRAP | SWT.RIGHT + orientation);
    comp.addPaintListener(
        new PaintListener() {

          public void paintControl(PaintEvent e) {
            paint(e);
          }
        });
    toolParent = ((Control) toolControl.getParent().getWidget());
    toolParent.addPaintListener(
        new PaintListener() {

          public void paintControl(PaintEvent e) {
            if (borderColor == null) borderColor = e.display.getSystemColor(SWT.COLOR_BLACK);
            e.gc.setForeground(borderColor);
            Rectangle bounds = ((Control) e.widget).getBounds();
            e.gc.drawLine(0, bounds.height - 1, bounds.width, bounds.height - 1);
          }
        });

    comp.addDisposeListener(
        new DisposeListener() {
          public void widgetDisposed(DisposeEvent e) {
            dispose();
          }
        });

    psTB.addMenuDetectListener(
        new MenuDetectListener() {
          public void menuDetected(MenuDetectEvent e) {
            ToolBar tb = (ToolBar) e.widget;
            Point p = new Point(e.x, e.y);
            p = psTB.getDisplay().map(null, psTB, p);
            ToolItem item = tb.getItem(p);
            if (item == null) E4Util.message("  ToolBar menu"); // $NON-NLS-1$
            else {
              MPerspective persp = (MPerspective) item.getData();
              if (persp == null) E4Util.message("  Add button Menu"); // $NON-NLS-1$
              else openMenuFor(item, persp);
            }
          }
        });

    psTB.addDisposeListener(
        new DisposeListener() {
          public void widgetDisposed(DisposeEvent e) {
            disposeTBImages();
          }
        });

    psTB.getAccessible()
        .addAccessibleListener(
            new AccessibleAdapter() {
              public void getName(AccessibleEvent e) {
                if (0 <= e.childID && e.childID < psTB.getItemCount()) {
                  ToolItem item = psTB.getItem(e.childID);
                  if (item != null) {
                    e.result = item.getToolTipText();
                  }
                }
              }
            });

    hookupDnD(psTB);

    final ToolItem createItem = new ToolItem(psTB, SWT.PUSH);
    createItem.setImage(getOpenPerspectiveImage());
    createItem.setToolTipText(WorkbenchMessages.OpenPerspectiveDialogAction_tooltip);
    createItem.addSelectionListener(
        new SelectionListener() {
          public void widgetSelected(SelectionEvent e) {
            selectPerspective();
          }

          public void widgetDefaultSelected(SelectionEvent e) {
            selectPerspective();
          }
        });
    new ToolItem(psTB, SWT.SEPARATOR);

    MPerspectiveStack stack = getPerspectiveStack();
    if (stack != null) {
      // Create an item for each perspective that should show up
      for (MPerspective persp : stack.getChildren()) {
        if (persp.isToBeRendered()) {
          addPerspectiveItem(persp);
        }
      }
    }
  }
  private ToolItem addPerspectiveItem(MPerspective persp) {
    int perspIndex = persp.getParent().getChildren().indexOf(persp);

    int index = perspIndex + 2; // HACK !! accounts for the 'open' and the
    // separator
    final ToolItem psItem =
        index < psTB.getItemCount()
            ? new ToolItem(psTB, SWT.RADIO, index)
            : new ToolItem(psTB, SWT.RADIO);
    psItem.setData(persp);
    IPerspectiveDescriptor descriptor = getDescriptorFor(persp.getElementId());
    boolean foundImage = false;
    if (descriptor != null) {
      ImageDescriptor desc = descriptor.getImageDescriptor();
      if (desc != null) {
        final Image image = desc.createImage(false);
        if (image != null) {
          psItem.setImage(image);

          psItem.addListener(
              SWT.Dispose,
              new Listener() {
                public void handleEvent(org.eclipse.swt.widgets.Event event) {
                  image.dispose();
                }
              });
          foundImage = true;
          psItem.setToolTipText(persp.getLocalizedLabel());
        }
      }
    }
    if (!foundImage
        || PrefUtil.getAPIPreferenceStore()
            .getBoolean(IWorkbenchPreferenceConstants.SHOW_TEXT_ON_PERSPECTIVE_BAR)) {
      psItem.setText(persp.getLocalizedLabel());
      psItem.setToolTipText(persp.getLocalizedTooltip());
    }

    psItem.setSelection(persp == persp.getParent().getSelectedElement());

    psItem.addSelectionListener(
        new SelectionListener() {
          public void widgetSelected(SelectionEvent e) {
            MPerspective persp = (MPerspective) e.widget.getData();
            persp.getParent().setSelectedElement(persp);
          }

          public void widgetDefaultSelected(SelectionEvent e) {
            MPerspective persp = (MPerspective) e.widget.getData();
            persp.getParent().setSelectedElement(persp);
          }
        });

    psItem.addListener(
        SWT.MenuDetect,
        new Listener() {
          public void handleEvent(org.eclipse.swt.widgets.Event event) {
            MPerspective persp = (MPerspective) event.widget.getData();
            openMenuFor(psItem, persp);
          }
        });

    // update the size
    fixSize();

    return psItem;
  }
  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);
        }
      }
    }
  }
 @CanExecute
 public boolean canExecute(MPerspective myPerspective) {
   if (!myPerspective.getElementId().equals(PART_ID)) return true;
   return false;
 }
  private Component createPerspectiveButton(final MPerspective perspective) {
    if (!perspective.isVisible()) return null;
    boolean iconsOnly = perspectiveStackForSwitcher.getTags().contains(Tags.ICONS_ONLY);
    String label = iconsOnly ? null : Commons.trim(perspective.getLabel());
    String iconURI = Commons.trim(perspective.getIconURI());

    final TwoStateToolbarButton button = new TwoStateToolbarButton(label, iconURI);

    if (perspective.getTooltip() != null) {
      button.setDescription(perspective.getLocalizedTooltip());
    }

    button.addListener(
        new ClickListener() {

          public void buttonClick(ClickEvent event) {
            MPerspectiveStack perspectiveStack =
                (MPerspectiveStack) (MElementContainer<?>) perspective.getParent();
            switchPerspective(perspective);
          }
        });

    // TODO: replace VerticalLayout on more thin layout (for example SimpleLayout addon which
    // consist of just one div)
    //		 VerticalLayout wrapperLayout = new VerticalLayout();
    //		 wrapperLayout.setSizeUndefined();
    //		 wrapperLayout.addComponent(button);
    //		 wrapperLayout.addListener(new LayoutEvents.LayoutClickListener() {
    //
    //			 @Override
    //			 public void layoutClick(LayoutClickEvent event)
    //			 {
    //				 if (LayoutClickEvent.BUTTON_RIGHT == event.getButton())
    //				 {
    //					 lastClickedPerspective = perspective;
    ////					 menu.open(event.getClientX(), event.getClientY());
    //				 }
    //			 }
    //		 });

    // Create context menu
    // Context menu
    ContextMenu menu = new ContextMenu();
    contextMenu2Button.put(menu, button);
    button2ContextMenu.put(button, menu);

    final ContextMenuItem showTextItem;

    final ContextMenuItem closeItem = menu.addItem("Close");
    // closeItem.setSeparatorVisible(true);

    if (iconsOnly) showTextItem = menu.addItem("Show Text");
    else showTextItem = menu.addItem("Hide Text");

    // showTextItem.addStyleName("close-perspective-item"); //bugfixing style for ie9 (context menu
    // addon has bug for ie9)

    menu.addItemClickListener(
        new ContextMenu.ContextMenuItemClickListener() {

          @Override
          public void contextMenuItemClicked(ContextMenuItemClickEvent event) {
            ContextMenuItem clickedItem = (ContextMenuItem) event.getSource();

            if (clickedItem == closeItem) {
              if (perspective == activePerspective) {
                MPerspective prevRenderableAndVisiblePerspective = null,
                    nextRenderableAndVisiblePerspective = null;
                boolean startSearch = false;
                for (MPerspective p : perspectiveStackForSwitcher.getChildren()) {
                  if (startSearch && p.isToBeRendered() && p.isVisible()) {
                    nextRenderableAndVisiblePerspective = p;
                    break;
                  }

                  if (p == perspective) startSearch = true;

                  if (!startSearch && p.isToBeRendered() && p.isVisible()) {
                    prevRenderableAndVisiblePerspective = p;
                  }
                }

                MPerspective newSelectedPerspective =
                    nextRenderableAndVisiblePerspective != null
                        ? nextRenderableAndVisiblePerspective
                        : prevRenderableAndVisiblePerspective;

                if (newSelectedPerspective != null) switchPerspective(newSelectedPerspective);
              }

              perspective.setToBeRendered(false);
            } else if (clickedItem == showTextItem) {
              if (perspectiveStackForSwitcher.getTags().contains(Tags.ICONS_ONLY))
                perspectiveStackForSwitcher.getTags().remove(Tags.ICONS_ONLY);
              else perspectiveStackForSwitcher.getTags().add(Tags.ICONS_ONLY);
            }
          }
        });

    menu.setAsContextMenuOf(button);

    perspective_button.put(perspective, button);
    // return wrapperLayout;
    return button;
  }
  @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);
    }
  }
  private void safeRemoveGui(MUIElement element) {
    if (removeRoot == null) removeRoot = element;
    renderedElements.remove(element);

    // We call 'hideChild' *before* checking if the actual element
    // has been rendered in order to pick up cases of 'lazy loading'
    MUIElement parent = element.getParent();
    AbstractPartRenderer parentRenderer = parent != null ? getRendererFor(parent) : null;
    if (parentRenderer != null) {
      parentRenderer.hideChild(element.getParent(), element);
    }

    AbstractPartRenderer renderer = getRendererFor(element);

    // If the element hasn't been rendered then this is a NO-OP
    if (renderer != null) {

      if (element instanceof MElementContainer<?>) {
        MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
        MUIElement selectedElement = container.getSelectedElement();
        List<MUIElement> children = container.getChildren();
        for (MUIElement child : children) {
          // remove stuff in the "back" first
          if (child != selectedElement) {
            removeGui(child);
          }
        }

        if (selectedElement != null && children.contains(selectedElement)) {
          // now remove the selected element
          removeGui(selectedElement);
        }
      }

      if (element instanceof MPerspective) {
        MPerspective perspective = (MPerspective) element;
        for (MWindow subWindow : perspective.getWindows()) {
          removeGui(subWindow);
        }
      } else if (element instanceof MWindow) {
        MWindow window = (MWindow) element;
        for (MWindow subWindow : window.getWindows()) {
          removeGui(subWindow);
        }

        if (window instanceof MTrimmedWindow) {
          MTrimmedWindow trimmedWindow = (MTrimmedWindow) window;
          for (MUIElement trimBar : trimmedWindow.getTrimBars()) {
            removeGui(trimBar);
          }
        }
      }

      if (element instanceof MContribution) {
        MContribution contribution = (MContribution) element;
        Object client = contribution.getObject();
        IEclipseContext parentContext = renderer.getContext(element);
        if (parentContext != null && client != null) {
          try {
            ContextInjectionFactory.invoke(client, PersistState.class, parentContext, null);
          } catch (Exception e) {
            if (logger != null) {
              logger.error(e);
            }
          }
        }
      }

      renderer.disposeWidget(element);

      // unset the client object
      if (element instanceof MContribution) {
        MContribution contribution = (MContribution) element;
        Object client = contribution.getObject();
        IEclipseContext parentContext = renderer.getContext(element);
        if (parentContext != null && client != null) {
          try {
            ContextInjectionFactory.uninject(client, parentContext);
          } catch (Exception e) {
            if (logger != null) {
              logger.error(e);
            }
          }
        }
        contribution.setObject(null);
      }

      // dispose the context
      if (element instanceof MContext) {
        clearContext((MContext) element);
      }
    }

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