Package com.sencha.gxt.widget.core.client.menu

Source Code of com.sencha.gxt.widget.core.client.menu.Menu

/**
* Sencha GXT 3.1.0-beta - Sencha for GWT
* Copyright(c) 2007-2014, Sencha, Inc.
* licensing@sencha.com
*
* http://www.sencha.com/products/gxt/license/
*/
package com.sencha.gxt.widget.core.client.menu;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.GXT;
import com.sencha.gxt.core.client.Style;
import com.sencha.gxt.core.client.Style.Anchor;
import com.sencha.gxt.core.client.Style.AnchorAlignment;
import com.sencha.gxt.core.client.Style.HideMode;
import com.sencha.gxt.core.client.Style.Side;
import com.sencha.gxt.core.client.dom.XDOM;
import com.sencha.gxt.core.client.dom.XElement;
import com.sencha.gxt.core.client.resources.CommonStyles;
import com.sencha.gxt.core.client.util.BaseEventPreview;
import com.sencha.gxt.core.client.util.ClickRepeater;
import com.sencha.gxt.core.client.util.ClickRepeaterEvent;
import com.sencha.gxt.core.client.util.ClickRepeaterEvent.ClickRepeaterHandler;
import com.sencha.gxt.core.client.util.KeyNav;
import com.sencha.gxt.core.client.util.Point;
import com.sencha.gxt.widget.core.client.Component;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.container.InsertContainer;
import com.sencha.gxt.widget.core.client.event.BeforeHideEvent;
import com.sencha.gxt.widget.core.client.event.BeforeShowEvent;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.MaximizeEvent;
import com.sencha.gxt.widget.core.client.event.MaximizeEvent.MaximizeHandler;
import com.sencha.gxt.widget.core.client.event.MinimizeEvent;
import com.sencha.gxt.widget.core.client.event.MinimizeEvent.MinimizeHandler;
import com.sencha.gxt.widget.core.client.event.ShowEvent;
import com.sencha.gxt.widget.core.client.form.Field;

/**
* A menu widget.
*/
public class Menu extends InsertContainer implements HasBeforeSelectionHandlers<Item>, HasSelectionHandlers<Item> {

  public static interface MenuAppearance {

    void applyDateMenu(XElement element);

    XElement createItem(XElement parent, String childId, boolean needsIndent);

    XElement getBottomScroller(XElement parent);

    XElement getGroup(XElement element, String id, String group);

    NodeList<Element> getGroups(XElement element);

    XElement getMenuList(XElement element);

    NodeList<Element> getScrollers(XElement element);

    XElement getTopScroller(XElement parent);

    boolean hasScrollers(XElement parent);

    String noSeparatorClass();

    void onScrollerOut(XElement target);

    String plainClass();

    void render(SafeHtmlBuilder builder);

  }

  private final MenuAppearance appearance;
  protected BaseEventPreview eventPreview;
  protected KeyNav keyNav;
  protected Item parentItem;
  protected boolean plain;
  protected boolean showSeparator = true;

  private int activeMax;
  private boolean constrainViewport = true;
  private String defaultAlign = "tl-bl?";
  private boolean enableScrolling = true;
  private boolean focusOnShow = true;
  private int maxHeight = Style.DEFAULT;
  private int minWidth = 120;
  private int scrollerHeight = 8;
  private int scrollIncrement = 24;
  private boolean showing;
  private String subMenuAlign = "tl-tr?";
  private XElement ul;
  protected Item activeItem;

  public Menu() {
    this(GWT.<MenuAppearance> create(MenuAppearance.class));
  }

  public Menu(MenuAppearance appearance) {
    this.appearance = appearance;

    SafeHtmlBuilder builder = new SafeHtmlBuilder();
    appearance.render(builder);

    setElement((Element) XDOM.create(builder.toSafeHtml()));
    getElement().makePositionable(true);

    ul = appearance.getMenuList(getElement());

    monitorWindowResize = true;
    shim = true;
    setShadow(true);
    setDeferHeight(true);

    eventPreview = new BaseEventPreview() {

      @Override
      protected boolean onPreview(NativePreviewEvent pe) {
        Menu.this.onPreviewEvent(pe);
        return super.onPreview(pe);
      }

      @Override
      protected void onPreviewKeyPress(NativePreviewEvent pe) {
        super.onPreviewKeyPress(pe);
        onEscape(pe);
      }
    };

    // add menu to ignore list
    eventPreview.getIgnoreList().add(getElement());
    eventPreview.setAutoHide(false);

    getElement().setTabIndex(0);
    getElement().setAttribute("hideFocus", "true");
    getElement().addClassName(CommonStyles.get().ignore());

    keyNav = new KeyNav(this) {
      public void onDown(NativeEvent evt) {
        onKeyDown(evt);
      }

      public void onEnter(NativeEvent evt) {
        onKeyEnter(evt);
      }

      public void onLeft(NativeEvent evt) {
        onKeyLeft(evt);
      }

      public void onRight(NativeEvent evt) {
        onKeyRight(evt);
      }

      public void onUp(NativeEvent evt) {
        onKeyUp(evt);
      }

    };

    sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK | Event.ONMOUSEWHEEL);
  }

  @Override
  public HandlerRegistration addBeforeSelectionHandler(BeforeSelectionHandler<Item> handler) {
    return addHandler(handler, BeforeSelectionEvent.getType());
  }

  /**
   * Fires when the {@link Menu} is maximized.
   *
   * @param handler sets the {@link MaximizeHandler}
   * @return the {@link HandlerRegistration}.
   */
  public HandlerRegistration addMaximizeHandler(MaximizeHandler handler) {
    return addHandler(handler, MaximizeEvent.getType());
  }

  /**
   * Fires when the {@link Menu} is minimized.
   *
   * @param handler sets the {@link MinimizeHandler}.
   * @return the {@link HandlerRegistration}.
   */
  public HandlerRegistration addMinimizeHandler(MinimizeHandler handler) {
    return addHandler(handler, MinimizeEvent.getType());
  }

  @Override
  public HandlerRegistration addSelectionHandler(SelectionHandler<Item> handler) {
    return addHandler(handler, SelectionEvent.getType());
  }
 
  /**
   * Returns the appearance object for this instance
   * @return the appearance impl used by this component
   */
  public MenuAppearance getAppearance() {
    return appearance;
  }

  /**
   * Returns the default alignment.
   *
   * @return the default align
   */
  public String getDefaultAlign() {
    return defaultAlign;
  }

  /**
   * Returns the max height of the menu or -1 if not set.
   *
   * @return the max height in pixels
   */
  public int getMaxHeight() {
    return maxHeight;
  }

  /**
   * Returns the menu's minimum width.
   *
   * @return the width
   */
  public int getMinWidth() {
    return minWidth;
  }

  /**
   * Returns the menu's parent item.
   *
   * @return the parent item
   */
  public Item getParentItem() {
    return parentItem;
  }

  /**
   * Returns the sub menu alignment.
   *
   * @return the alignment
   */
  public String getSubMenuAlign() {
    return subMenuAlign;
  }

  /**
   * Hides the menu.
   */
  public void hide() {
    hide(false);
  }

  /**
   * Hides this menu and optionally all parent menus
   *
   * @param deep true to close all parent menus
   */
  public void hide(final boolean deep) {
    if (showing) {
      if (fireCancellableEvent(new BeforeHideEvent())) {

        if (activeItem != null) {
          activeItem.deactivate();
          activeItem = null;
        }

        onHide();

        // EXTGWT-3339 - IE hide menu via focus on another element
        if (GXT.isIE()) {
          Scheduler.get().scheduleDeferred(new ScheduledCommand() {
            @Override
            public void execute() {
              RootPanel.get().remove(Menu.this);
            }
          });
        } else {
          RootPanel.get().remove(Menu.this);
        }

        eventPreview.remove();
        showing = false;
        hidden = true;
        fireEvent(new HideEvent());
        if (deep && parentItem != null && parentItem.getParent() instanceof Menu) {
          ((Menu) parentItem.getParent()).hide(true);
        }

      }
    }
  }

  /**
   * Returns true if constrain to viewport is enabled.
   *
   * @return the constrain to viewport state
   */
  public boolean isConstrainViewport() {
    return constrainViewport;
  }

  /**
   * Returns true if vertical scrolling is enabled.
   *
   * @return true for scrolling
   */
  public boolean isEnableScrolling() {
    return enableScrolling;
  }

  /**
   * Returns true if the menu will be focused when displayed.
   *
   * @return true if focused
   */
  public boolean isFocusOnShow() {
    return focusOnShow;
  }

  @Override
  public boolean isVisible() {
    return showing;
  }

  @Override
  public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);
    switch (event.getTypeInt()) {
      case Event.ONCLICK:
        onClick(event);
        break;
      case Event.ONMOUSEMOVE:
        onMouseMove(event);
        break;
      case Event.ONMOUSEOUT:
        onMouseOut(event);
        break;
      case Event.ONMOUSEOVER:
        onMouseOver(event);
        break;
      case Event.ONMOUSEWHEEL:
        if (enableScrolling) {
          scrollMenu(event.getMouseWheelVelocityY() < 0);
        }
    }
  }

  /**
   * Sets the active item. The widget must be of type <code>Item</code> to be activated. All other types are ignored.
   *
   * @param widget the widget to set active
   * @param autoExpand true to auto expand the item
   */
  public void setActiveItem(Widget widget, boolean autoExpand) {
    if (widget == null) {
      deactivateActiveItem();
      return;
    }
    if (widget instanceof Item) {
      Item item = (Item) widget;
      if (item != activeItem) {
        deactivateActiveItem();

        this.activeItem = item;
        item.activate(autoExpand);
        item.getElement().scrollIntoView(ul, false);
        focus();

      } else if (autoExpand) {
        item.expandMenu(autoExpand);
      }
    }
  }

  /**
   * Sets whether the menu should be constrained to the viewport when shown. Only applies when using
   * {@link #showAt(int, int)}.
   *
   * @param constrainViewport true to constrain
   */
  public void setConstrainViewport(boolean constrainViewport) {
    this.constrainViewport = constrainViewport;
  }

  /**
   * Sets the default {@link XElement#alignTo} anchor position value for this menu relative to its element of origin
   * (defaults to "tl-bl?").
   *
   * @param defaultAlign the default align
   */
  public void setDefaultAlign(String defaultAlign) {
    this.defaultAlign = defaultAlign;
  }

  /**
   * True to enable vertical scrolling of the children in the menu (defaults to true).
   *
   * @param enableScrolling true to for scrolling
   */
  public void setEnableScrolling(boolean enableScrolling) {
    this.enableScrolling = enableScrolling;
  }

  /**
   * True to set the focus on the menu when it is displayed.
   *
   * @param focusOnShow true to focus
   */
  public void setFocusOnShow(boolean focusOnShow) {
    this.focusOnShow = focusOnShow;
  }

  /**
   * Sets the max height of the menu (defaults to -1). Only applies when {@link #setEnableScrolling(boolean)} is set to
   * true.
   *
   * @param maxHeight the max height
   */
  public void setMaxHeight(int maxHeight) {
    this.maxHeight = maxHeight;
  }

  /**
   * Sets he minimum width of the menu in pixels (defaults to 120).
   *
   * @param minWidth the minimum width
   */
  public void setMinWidth(int minWidth) {
    this.minWidth = minWidth;
  }

  /**
   * The {@link XElement#alignTo} anchor position value to use for submenus of this menu (defaults to "tl-tr-?").
   *
   * @param subMenuAlign the sub alignment
   */
  public void setSubMenuAlign(String subMenuAlign) {
    this.subMenuAlign = subMenuAlign;
  }

  /**
   * Displays this menu relative to another element.
   *
   * @param elem the element to align to
   * @param alignment the {@link XElement#alignTo} anchor position to use in aligning to the element (defaults to
   *          defaultAlign)
   */
  public void show(Element elem, AnchorAlignment alignment) {
    show(elem, alignment, 0, 0);
  }

  /**
   * Displays this menu relative to another element.
   *
   * @param elem the element to align to
   * @param alignment the {@link XElement#alignTo} anchor position to use in aligning to the element (defaults to
   *          defaultAlign)
   * @param offsetX X offset
   * @param offsetY Y offset
   */
  public void show(Element elem, AnchorAlignment alignment, int offsetX, int offsetY) {
    if (!fireCancellableEvent(new BeforeShowEvent())) {
      return;
    }

    getElement().makePositionable(true);
    RootPanel.get().add(this);

    onShow();
    getElement().updateZIndex(0);

    showing = true;
    doAutoSize();

    getElement().alignTo(elem, alignment, offsetX, offsetY);

    if (enableScrolling) {
      constrainScroll(getElement().getY());
    }
    getElement().show();

    eventPreview.add();

    if (focusOnShow) {
      focus();
    }
    fireEvent(new ShowEvent());
  }

  /**
   * Displays this menu relative to the widget using the default alignment.
   *
   * @param widget the align widget
   */
  public void show(Widget widget) {
    show(widget.getElement(), new AnchorAlignment(Anchor.TOP_LEFT, Anchor.BOTTOM_LEFT));
  }

  /**
   * Displays this menu at a specific xy position.
   *
   * @param x the x coordinate
   * @param y the y coordinate
   */
  public void showAt(int x, int y) {
    if (!fireCancellableEvent(new BeforeShowEvent())) {
      return;
    }

    getElement().makePositionable(true);
    RootPanel.get().add(this);

    onShow();
    getElement().updateZIndex(0);

    showing = true;
    doAutoSize();

    if (constrainViewport) {
      Point p = getElement().adjustForConstraints(new Point(x, y));
      x = p.getX();
      y = p.getY();
    }
    setPagePosition(x + XDOM.getBodyScrollLeft(), y + XDOM.getBodyScrollTop());
    if (enableScrolling) {
      constrainScroll(y);
    }

    getElement().show();
    eventPreview.add();

    if (focusOnShow) {
      focus();
    }

    fireEvent(new ShowEvent());
  }

  protected void constrainScroll(int y) {
    ul.getStyle().setProperty("height", "auto");
    int full = ul.getOffsetHeight();

    int max = maxHeight != Style.DEFAULT ? maxHeight : (XDOM.getViewHeight(false) - y);
    if (full > max && max > 0) {
      activeMax = max - 10 - scrollerHeight * 2;
      ul.setHeight(activeMax, true);
      createScrollers();
    } else {
      ul.setHeight(full, true);
      NodeList<Element> nodes = appearance.getScrollers(getElement());
      for (int i = 0; i < nodes.getLength(); i++) {
        nodes.getItem(i).getStyle().setDisplay(Display.NONE);
      }
    }
    ul.setScrollTop(0);
  }

  protected void createScrollers() {
    if (appearance.hasScrollers(getElement())) {
      // Scrollers already created
      return;
    }

    ClickRepeaterHandler handler = new ClickRepeaterHandler() {

      @Override
      public void onClick(ClickRepeaterEvent event) {
        onScroll(event);
      }

    };

    XElement topScroller = appearance.getTopScroller(getElement());
    ClickRepeater cr = new ClickRepeater(this, topScroller);
    cr.addClickHandler(handler);

    XElement bottomScroller = appearance.getBottomScroller(getElement());
    cr = new ClickRepeater(this, bottomScroller);
    cr.addClickHandler(handler);
  }

  protected void deactivateActiveItem() {
    if (activeItem != null) {
      activeItem.deactivate();
      activeItem = null;
    }
  }

  protected void doAutoSize() {
    // has a width been set?
    String w = getElement().getStyle().getWidth();
    if (showing && "".equals(w)) {
      int width = getContainerTarget().getOffsetWidth() + getElement().getFrameWidth(Side.LEFT, Side.RIGHT);
      getElement().setWidth(Math.max(width, minWidth), true);
    }
  }

  @Override
  protected void doPhysicalAttach(Widget child, int beforeIndex) {
    boolean needsIndent = (child instanceof Field) || (child instanceof ContentPanel)
        || (child instanceof AdapterMenuItem && ((AdapterMenuItem) child).isNeedsIndent());
    XElement div = appearance.createItem(getElement(), child.getElement().getId(), needsIndent);

    div.appendChild(child.getElement());
    if (child instanceof Component) {
      Component c = (Component) child;
      if (!c.isEnabled()) {
        c.disable();
      }
    }
    getContainerTarget().insertChild(div, beforeIndex);

  }

  @Override
  protected void doPhysicalDetach(Widget child) {
    Element parentElement = child.getElement().getParentElement();
    if (parentElement != null) {
      parentElement.removeFromParent();
    }
    super.doPhysicalDetach(child);
  }

  @Override
  protected XElement getContainerTarget() {
    return ul;
  }

  @Override
  protected void onAfterFirstAttach() {
    super.onAfterFirstAttach();
    if (plain) {
      getElement().addClassName(appearance.plainClass());
    }
    if (!showSeparator) {
      getElement().addClassName(appearance.noSeparatorClass());
    }
  }

  /**
   * Provides information about external events occurring in the DOM, allow the menu to decide to hide if necessary
   */
  protected void onPreviewEvent(NativePreviewEvent pe) {
    int type = pe.getTypeInt();
    switch (type) {
      case Event.ONMOUSEDOWN:
      case Event.ONMOUSEWHEEL:
      case Event.ONSCROLL:
      case Event.ONKEYPRESS:
        XElement target = pe.getNativeEvent().getEventTarget().cast();

        // ignore targets within a parent with x-ignore, such as the listview in
        // a combo
        if (target.findParent(".x-ignore", 10) != null) {
          return;
        }

        // is the target part of the sub menu chain, if yes, dont out hide
        Item active = activeItem != null ? activeItem : getParentItem();
        while (active != null) {
          if (active instanceof MenuItem) {
            MenuItem menuItem = (MenuItem) active;
            if (menuItem.getParent().getElement().isOrHasChild(target)) {
              return;
            }
            if (menuItem.getSubMenu() != null && menuItem.getSubMenu().isVisible()) {
              if (menuItem.getSubMenu().getElement().isOrHasChild(target)) {
                return;
              }
              active = menuItem.getSubMenu().activeItem;
            } else {
              active = null;
            }

          } else {
            active = null;
          }

        }

        if (!getElement().isOrHasChild(target)) {
          hide(true);
          return;
        }
    }
    return;
  }

  protected void onClick(Event ce) {
    Widget item = findWidget((Element) ce.getEventTarget().cast());
    if (item != null && item instanceof Item) {
      ((Item) item).onClick(ce);
    }
  }

  protected void onEscape(NativePreviewEvent pe) {
    if (pe.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
      if (activeItem != null && !activeItem.onEscape()) {
        return;
      }
      pe.getNativeEvent().preventDefault();
      pe.getNativeEvent().stopPropagation();
      hide(false);
    }
  }

  @Override
  protected void onHide() {
    super.onHide();
    deactivateActiveItem();
  }

  protected void onKeyDown(NativeEvent evt) {
    evt.stopPropagation();
    evt.preventDefault();
    if (tryActivate(getWidgetIndex(activeItem) + 1, 1) == null) {
      tryActivate(0, 1);
    }
  }

  protected void onKeyEnter(NativeEvent evt) {
    if (activeItem != null) {
      evt.stopPropagation();
      activeItem.onClick(evt);
    }
  }

  protected void onKeyLeft(NativeEvent evt) {
    hide();
    if (parentItem != null && parentItem.getParent() instanceof Menu) {
      ((Menu) parentItem.getParent()).focus();
    } else {
      Menu menu = Menu.this;
      while (menu.parentItem != null && menu.parentItem.getParent() instanceof Menu) {
        menu = (Menu) menu.parentItem.getParent();
      }
      menu.fireEvent(new MinimizeEvent());
    }
  }

  protected void onKeyRight(NativeEvent evt) {
    if (activeItem != null) {
      activeItem.expandMenu(true);
    }
    if (activeItem instanceof MenuItem) {
      MenuItem mi = (MenuItem) activeItem;
      if (mi.subMenu != null && mi.subMenu.isVisible()) {
        return;
      }
    }
    Menu menu = Menu.this;
    while (menu.parentItem != null && menu.parentItem.getParent() instanceof Menu) {
      menu = (Menu) menu.parentItem.getParent();
    }
    menu.fireEvent(new MaximizeEvent());
  }

  protected void onKeyUp(NativeEvent evt) {
    evt.stopPropagation();
    evt.preventDefault();
    if (tryActivate(getWidgetIndex(activeItem) - 1, -1) == null) {
      tryActivate(getWidgetCount() - 1, -1);
    }
  }

  protected void onMouseMove(Event ce) {
    Widget c = findWidget((Element) ce.getEventTarget().cast());
    if (c != null && c instanceof Item) {
      Item item = (Item) c;
      if (activeItem != item && item.canActivate && item.isEnabled()) {
        setActiveItem(item, true);
      }
    }
  }

  protected void onMouseOut(Event ce) {
    EventTarget to = ce.getRelatedEventTarget();
    if (activeItem != null && (to == null || (Element.is(to) && !activeItem.getElement().isOrHasChild(Element.as(to))))
        && activeItem.shouldDeactivate(ce)) {
      if (to != null && Element.is(to)) {
        XElement xto = to.cast();
        if (xto.findParent("." + CommonStyles.get().ignore(), 3) != null) {
          return;
        }
      }
      deactivateActiveItem();
    }
  }

  protected void onMouseOver(Event ce) {
    EventTarget from = ce.getRelatedEventTarget();
    if (from == null || (Element.is(from) && !getElement().isOrHasChild(Element.as(from)))) {
      Widget c = findWidget((Element) ce.getEventTarget().cast());
      if (c != null && c instanceof Item) {
        Item item = (Item) c;
        if (activeItem != item && item.canActivate && item.isEnabled()) {
          setActiveItem(item, true);
        }
      }
    }
  }

  protected void onScroll(ClickRepeaterEvent ce) {
    XElement target = ce.getSource().getEl();
    boolean top = appearance.getTopScroller(getElement()).equals(target);
    scrollMenu(top);

    if (top ? ul.getScrollTop() <= 0 : ul.getScrollTop() + activeMax >= ul.getPropertyInt("scrollHeight")) {
      appearance.onScrollerOut(target);
    }
  }

  @Override
  protected void onWidgetHide(Widget widget) {
    super.onWidgetHide(widget);
    Element p = widget.getElement().getParentElement();
    if (widget instanceof Component) {
      p.addClassName(((Component) widget).getHideMode().value());
    } else {
      p.addClassName(HideMode.DISPLAY.value());
    }
  }

  @Override
  protected void onWidgetShow(Widget widget) {
    super.onWidgetShow(widget);
    Element p = widget.getElement().getParentElement();
    if (widget instanceof Component) {
      p.removeClassName(((Component) widget).getHideMode().value());
    } else {
      p.removeClassName(HideMode.DISPLAY.value());
    }
  }

  @Override
  protected void onWindowResize(int width, int height) {
    super.onWindowResize(width, height);
    hide(true);
  }

  protected void scrollMenu(boolean top) {
    ul.setScrollTop(ul.getScrollTop() + scrollIncrement * (top ? -1 : 1));
  }

  protected Item tryActivate(int start, int step) {
    for (int i = start, len = getWidgetCount(); i >= 0 && i < len; i += step) {
      Widget w = getWidget(i);
      if (w instanceof Item) {
        Item item = (Item) w;
        if (item.canActivate && item.isEnabled()) {
          setActiveItem(item, false);
          return item;
        }
      }
    }
    return null;
  }

}
TOP

Related Classes of com.sencha.gxt.widget.core.client.menu.Menu

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