/** * Sencha GXT 3.0.0b - Sencha for GWT * Copyright(c) 2007-2012, Sencha, Inc. * licensing@sencha.com * * http://www.sencha.com/products/gxt/license/ */ package com.sencha.gxt.desktop.client.widget; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ImageResource; 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.sencha.gxt.core.client.Style.AnchorAlignment; import com.sencha.gxt.core.client.XTemplates; import com.sencha.gxt.core.client.dom.XDOM; import com.sencha.gxt.core.client.dom.XElement; import com.sencha.gxt.core.client.util.BaseEventPreview; import com.sencha.gxt.desktop.client.theme.base.startmenu.StartMenuDefaultAppearance; import com.sencha.gxt.widget.core.client.Component; import com.sencha.gxt.widget.core.client.ComponentHelper; 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.ShowEvent; import com.sencha.gxt.widget.core.client.menu.Menu; import com.sencha.gxt.widget.core.client.menu.MenuItem; /** * Provides a desktop start menu. A desktop start menu is a component with a * heading, a main menu and a tool menu. The heading is typically displayed at * the top of the start menu, and the main menu and tool menu are displayed side * by side below the heading. * <p/> * For more information on the use of the appearance pattern, see <a * href='http://www.sencha.com/blog/ext-gwt-3-appearance-design'>Sencha GXT 3.0 * Appearance Design</a> * * @see StartMainMenu * @see StartToolMenu * @see StartHeadingMenuItem */ public class StartMenu extends Component { /** * Defines the appearance interface for a start menu. * <p/> * The appearance interface defines the interaction between the widget and an * appearance instance. The concrete implementation of the appearance * interface typically incorporates the external HTML and CSS source using the * {@link XTemplates} and {@link CssResource} interfaces. */ public interface Appearance { public void setHeading(XElement parent, MenuItem heading); public void setMainMenu(XElement parent, Menu mainMenu); public void setToolMenu(XElement parent, Menu toolMenu); void render(SafeHtmlBuilder builder); } private StartHeadingMenuItem heading; private StartMainMenu mainMenu; private StartToolMenu toolMenu; private BaseEventPreview eventPreview; private boolean showing; /** * Creates a start menu with the default appearance. */ public StartMenu() { this(GWT.<StartMenuDefaultAppearance> create(StartMenuDefaultAppearance.class)); } /** * Creates a start menu with the specified appearance. * * @param appearance the start menu appearance */ public StartMenu(StartMenuDefaultAppearance appearance) { SafeHtmlBuilder builder = new SafeHtmlBuilder(); appearance.render(builder); XElement element = XDOM.create(builder.toSafeHtml()); setElement(element); appearance.setHeading(element, getHeading()); appearance.setMainMenu(element, getMainMenu()); appearance.setToolMenu(element, getToolMenu()); sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK); } /** * Adds an item to the "main menu" area of the start menu. The main menu * typically appears on the left side of the start menu and includes items for * desktop applications. * * @param menuItem the item to add to the main menu area of the start menu */ public void add(StartMainMenuItem menuItem) { getMainMenu().add(menuItem); } /** * Adds an item to the "tool menu" area of the start menu. The tool menu * typically appears on the right side of the start menu and includes items * that manage the state of the desktop. * * @param startToolMenuItem the item to add to the tool menu area of the start * menu */ public void addTool(StartToolMenuItem startToolMenuItem) { getToolMenu().add(startToolMenuItem); } /** * Adds a separator to the "tool menu" area of the start menu. */ public void addToolSeparator() { // TODO: Provide implementation } /** * Hides the start menu. */ public void hide() { if (showing) { if (fireCancellableEvent(new BeforeHideEvent())) { showing = false; onHide(); RootPanel.get().remove(this); eventPreview.remove(); fireEvent(new HideEvent()); } } } /** * Sets the text to be displayed in the start menu heading. The heading * typically appears above the main menu and tool menu. * * @param text the start menu heading text */ public void setHeading(String text) { getHeading().setText(text); } /** * Sets the icon to be displayed in the start menu heading. The heading * typically appears above main menu and tool menu. * * @param icon the start menu heading icon */ public void setIcon(ImageResource icon) { getHeading().setIcon(icon); } /** * 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 offsets the menu align offsets */ public void show(Element elem, AnchorAlignment alignment, int[] offsets) { if (fireCancellableEvent(new BeforeShowEvent())) { showing = true; RootPanel.get().add(this); getElement().makePositionable(true); onShow(); getElement().updateZIndex(0); doAutoSize(); getElement().alignTo(elem, alignment, offsets); // TODO: Add support for scrolling as in Menu.show getElement().show(); getEventPreview().add(); focus(); fireEvent(new ShowEvent()); } } @Override protected void doAttachChildren() { super.doAttachChildren(); ComponentHelper.doAttach(heading); ComponentHelper.doAttach(mainMenu); ComponentHelper.doAttach(toolMenu); } protected void doAutoSize() { String w = getElement().getStyle().getWidth(); if (showing && "".equals(w)) { // TODO: get main menu container from appearance as in Menu.doAutoSize getMainMenu().getElement().setWidth(195, true); } } @Override protected void doDetachChildren() { super.doDetachChildren(); ComponentHelper.doDetach(heading); ComponentHelper.doDetach(mainMenu); ComponentHelper.doDetach(toolMenu); } private BaseEventPreview getEventPreview() { if (eventPreview == null) { eventPreview = new BaseEventPreview() { protected boolean onAutoHide(NativePreviewEvent pe) { // TODO: Add support for sub-menus as in Menu.onAutoHide hide(); return true; } @Override protected void onPreviewKeyPress(NativePreviewEvent pe) { if (pe.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) { hide(); } }; }; eventPreview.getIgnoreList().add(getMainMenu().getElement()); eventPreview.getIgnoreList().add(getToolMenu().getElement()); } return eventPreview; } private StartHeadingMenuItem getHeading() { if (heading == null) { heading = new StartHeadingMenuItem(); } return heading; } private StartMainMenu getMainMenu() { if (mainMenu == null) { mainMenu = new StartMainMenu(this); } return mainMenu; } private StartToolMenu getToolMenu() { if (toolMenu == null) { toolMenu = new StartToolMenu(this); } return toolMenu; } }