/* * Ext GWT - Ext for GWT * Copyright(c) 2007-2009, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ package com.extjs.gxt.ui.client.widget.menu; import com.extjs.gxt.ui.client.GXT; import com.extjs.gxt.ui.client.aria.FocusFrame; import com.extjs.gxt.ui.client.event.ComponentEvent; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.MenuEvent; import com.extjs.gxt.ui.client.util.KeyNav; import com.extjs.gxt.ui.client.widget.Container; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Accessibility; /** * A horizontal menu bar. */ public class MenuBar extends Container<MenuBarItem> { private MenuBarItem active; public MenuBar() { baseStyle = "x-menubar"; enableLayout = true; attachChildren = false; } @Override public boolean add(MenuBarItem item) { return super.add(item); } @Override public boolean insert(MenuBarItem item, int index) { return super.insert(item, index); } @Override public void onComponentEvent(ComponentEvent ce) { super.onComponentEvent(ce); int type = ce.getEventTypeInt(); switch (type) { case Event.ONMOUSEOVER: onMouseOver(ce); break; case Event.ONMOUSEOUT: onMouseOut(ce); break; case Event.ONCLICK: onClick(ce); break; case Event.ONFOCUS: if (active == null && getItemCount() > 0) { setActiveItem(getItem(0), false); } break; case Event.ONBLUR: if (active != null && !active.expanded) { onDeactivate(active); } break; } } @Override public boolean remove(MenuBarItem item) { return super.remove(item); } /** * Sets the active item. * * @param item the item to activate * @param expand true to expand the item's menu */ public void setActiveItem(MenuBarItem item, boolean expand) { if (active != item) { if (active != null) { onDeactivate(active); } onActivate(item); if (GXT.isAriaEnabled()) { FocusFrame.get().frame(active); } if (expand) { expand(item); } } } /** * Toggles the given item. * * @param item the item to toggle */ public void toggle(MenuBarItem item) { if (item == active) { if (item.expanded) { collapse(item); } else { expand(item); } } else { setActiveItem(item, true); } } protected void collapse(MenuBarItem item) { item.menu.hide(); item.expanded = false; } protected void expand(MenuBarItem item) { item.menu.setFocusOnShow(false); item.menu.show(item.getElement(), "tl-bl", new int[] {0, 1}); item.expanded = true; } protected void onActivate(MenuBarItem item) { active = item; Accessibility.setState(getElement(), "aria-activedescendant", item.getId()); item.addStyleName(item.getBaseStyle() + "-active"); item.addStyleName(item.getBaseStyle() + "-over"); } protected void onDeactivate(MenuBarItem item) { if (item.expanded = true) { item.menu.hide(); item.expanded = false; } item.removeStyleName(item.getBaseStyle() + "-active"); item.removeStyleName(item.getBaseStyle() + "-over"); FocusFrame.get().unframe(); if (active == item) { active = null; } } @Override protected void onInsert(final MenuBarItem item, int index) { super.onInsert(item, index); item.menu.addListener(Events.Hide, new Listener<MenuEvent>() { public void handleEvent(MenuEvent be) { onDeactivate(item); focus(); setActiveItem(item, false); } }); item.menu.addListener(Events.AutoHide, new Listener<MenuEvent>() { public void handleEvent(MenuEvent be) { if (item.getElement().isOrHasChild(be.getTarget())) { be.setCancelled(true); } } }); } protected void onKeyPress(ComponentEvent ce) { switch (ce.getKeyCode()) { case KeyCodes.KEY_DOWN: onDown(ce); break; case KeyCodes.KEY_LEFT: onLeft(ce); break; case KeyCodes.KEY_RIGHT: onRight(ce); break; } } protected void onLeft(ComponentEvent ce) { if (active != null && getItemCount() > 1) { int idx = indexOf(active); if (idx != 0) { setActiveItem(getItem(idx - 1), true); } else { setActiveItem(getItem(getItemCount() - 1), true); } } } protected void onMouseOver(ComponentEvent ce) { MenuBarItem item = findItem(ce.getTarget()); if (item != null && item != active) { setActiveItem(item, active != null && active.expanded); } } @Override protected void onRender(Element target, int index) { super.onRender(target, index); setElement(DOM.createDiv(), target, index); el().setTabIndex(0); el().setElementAttribute("hideFocus", "true"); if (GXT.isAriaEnabled()) { Accessibility.setRole(getElement(), Accessibility.ROLE_MENUBAR); } new KeyNav<ComponentEvent>(this) { @Override public void onKeyPress(ComponentEvent ce) { MenuBar.this.onKeyPress(ce); } }; layout(); sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.ONFOCUS | Event.ONBLUR); } @Override protected void onResize(int width, int height) { } protected void onRight(ComponentEvent ce) { if (active != null && getItemCount() > 1) { int idx = indexOf(active); if (idx != getItemCount() - 1) { setActiveItem(getItem(idx + 1), true); } else { setActiveItem(getItem(0), true); } } } private void onClick(ComponentEvent ce) { ce.stopEvent(); MenuBarItem item = findItem(ce.getTarget()); if (item != null) { toggle(item); } } private void onDown(ComponentEvent ce) { if (active != null && getItemCount() > 0) { if (active.expanded) { active.menu.focus(); active.menu.setActiveItem(active.menu.getItem(0), false); } else { expand(active); } } } private void onMouseOut(ComponentEvent ce) { MenuBarItem item = findItem((Element) ce.getEvent().getRelatedEventTarget().cast()); if (item == null && active != null && !active.expanded) { onDeactivate(active); } } }