001: /*
002: * GWT-Ext Widget Library
003: * Copyright(c) 2007-2008, GWT-Ext.
004: * licensing@gwt-ext.com
005: *
006: * http://www.gwt-ext.com/license
007: */
008:
009: package com.gwtext.client.widgets.menu;
010:
011: import com.google.gwt.core.client.JavaScriptObject;
012: import com.google.gwt.user.client.Element;
013: import com.google.gwt.user.client.ui.Widget;
014: import com.gwtext.client.core.Ext;
015: import com.gwtext.client.util.JavaScriptObjectHelper;
016: import com.gwtext.client.widgets.menu.event.MenuListener;
017:
018: /**
019: * A menu object. This is the container to which you add all other menu items.
020: */
021: public class Menu extends Widget {
022: protected String id;
023: protected JavaScriptObject config;
024: protected JavaScriptObject jsObj;
025:
026: public Menu() {
027: id = Ext.generateId();
028: config = JavaScriptObjectHelper.createObject();
029: JavaScriptObjectHelper.setAttribute(config, "id", id);
030: }
031:
032: public void setId(String id) {
033: JavaScriptObjectHelper.setAttribute(config, "id", id);
034: this .id = id;
035: }
036:
037: public Menu(JavaScriptObject jsObj) {
038: id = JavaScriptObjectHelper.getAttribute(jsObj, "id");
039: setElement(getElement(jsObj));
040: }
041:
042: protected native Element getElement(JavaScriptObject jsObj) /*-{
043: //var el = jsObj.el;
044: var el = jsObj.getEl().dom;
045: if(el == null || el === undefined) {
046: return null;
047: //forms buttons are detached when initially added
048: //throw new Error('Widget ' + jsObj + ' has no element property set');
049: } else {
050: //There's an inconsistency in Ext where most elements have the property 'el' set to Ext's Element
051: //with the exception of Menu->Item, Menu->Separator, Menu->TextItem, Toolbar.Item and subclasses
052: //(Toolbar.Separator, Toolbar.Spacer, Toolbar.TextItem) where the 'el' property is set to
053: //the DOM element itself. Therefore retruning 'el' if 'el' is not Ext's Element. See details in issue 39.
054: return el.dom || el ;
055: }
056: }-*/;
057:
058: public Element getElement() {
059: if (super .getElement() == null) {
060:
061: if (jsObj == null) {
062: jsObj = create(config);
063: }
064: setElement(getElement(jsObj));
065: }
066: return super .getElement();
067: }
068:
069: public JavaScriptObject getOrCreateJsObj() {
070:
071: if (jsObj != null) {
072: return jsObj;
073: } else {
074: //create object here
075: jsObj = create(config);
076: return jsObj;
077: }
078: }
079:
080: protected static native JavaScriptObject getComponent(String id)/*-{
081: try {
082: var cmp = $wnd.Ext.menu.MenuMgr.get(id);
083: return (cmp === undefined || cmp == null) ? null : cmp;
084: }catch(e){
085: return null;
086: }
087: }-*/;
088:
089: private static Menu instance(JavaScriptObject jsObj) {
090: return new Menu(jsObj);
091: }
092:
093: protected JavaScriptObject create(String id, JavaScriptObject config) {
094: JavaScriptObjectHelper.setAttribute(config, "id", id);
095: return create(config);
096: }
097:
098: protected native JavaScriptObject create(JavaScriptObject menuConfig)/*-{
099: return new $wnd.Ext.menu.Menu(menuConfig);
100: }-*/;
101:
102: /**
103: * Adds an Element object to the menu.
104: *
105: * @param element the element to add
106: */
107: public native void addElement(Element element) /*-{
108: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
109: menu.addElement(element);
110: }-*/;
111:
112: /**
113: * Adds an Ext.Element object to the menu.
114: *
115: * @param elemID the element ID
116: */
117: public native void addElement(String elemID) /*-{
118: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
119: menu.addElement(elemID);
120: }-*/;
121:
122: /**
123: * Adds an {@link Item} to the menu.
124: *
125: * @param item the item to add
126: */
127: public native void addItem(BaseItem item) /*-{
128: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
129: var itemJS = item.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
130: menu.addItem(itemJS);
131: }-*/;
132:
133: /**
134: * Adds a separator bar to the menu.
135: */
136: public native void addSeparator() /*-{
137: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
138: menu.addSeparator();
139: }-*/;
140:
141: /**
142: * Creates a new {@link TextItem} with the supplied text and adds it to the menu.
143: *
144: * @param text the text to add
145: */
146: public native void addText(String text) /*-{
147: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
148: menu.addText(text);
149: }-*/;
150:
151: /**
152: * Gets an Item.
153: *
154: * @param itemId the item Id
155: * @return the item
156: */
157: public native BaseItem getItem(String itemId) /*-{
158: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
159: var item = menu.items.get(itemId);
160: if(item == null || item === undefined) {
161: return null;
162: } else {
163: //todo2 ext2 doesnt have xtypes for baseitem and subclasses
164: var itemJ = @com.gwtext.client.widgets.ComponentFactory::getComponent(Lcom/google/gwt/core/client/JavaScriptObject;)(item);
165: return itemJ =! null ? itemJ : @com.gwtext.client.widgets.menu.BaseItem::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(item);
166: }
167: }-*/;
168:
169: //TODO
170: public native BaseItem[] getItems() /*-{
171: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
172: var item = menu.items.items;
173: return @com.gwtext.client.util.JavaScriptObjectHelper::convertToJavaComponentArray(Lcom/google/gwt/core/client/JavaScriptObject;)(items);
174: }-*/;
175:
176: /**
177: * Hides this menu.
178: */
179: public native void hide() /*-{
180: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
181: menu.hide();
182: }-*/;
183:
184: /**
185: * Hides this menu and optionally all parent menus.
186: *
187: * @param deep true to hide all parent menus recursively, if any (defaults to false)
188: */
189: public native void hide(boolean deep) /*-{
190: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
191: menu.hide(deep);
192: }-*/;
193:
194: /**
195: * Inserts an e{@link Item} to the menu at a specified index.
196: *
197: * @param index the index to insert
198: * @param item the item to insert
199: */
200: public native void insert(int index, BaseItem item) /*-{
201: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
202: var itemJS = item.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
203: menu.insert(index, itemJS);
204: }-*/;
205:
206: /**
207: * Returns true if the menu is currently displayed, else false.
208: *
209: * @return true if visible
210: */
211: public native boolean isVisible() /*-{
212: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
213: menu.isVisible();
214: }-*/;
215:
216: /**
217: * Removes an {@link Item} from the menu and destroys the object.
218: *
219: * @param item the item to remove
220: */
221: public native void remove(BaseItem item) /*-{
222: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
223: var itemJS = item.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
224: menu.remove(itemJS);
225: }-*/;
226:
227: /**
228: * Removes and destroys all items in the menu
229: */
230: public native void removeAll() /*-{
231: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
232: menu.removeAll();
233: }-*/;
234:
235: /**
236: * Displays this menu relative to another element.
237: *
238: * @param id the element ID to align to
239: */
240: public native void show(String id) /*-{
241: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
242: menu.show(id);
243: }-*/;
244:
245: /**
246: * Displays this menu at a specific xy position.
247: *
248: * @param x the X position
249: * @param y the Y position
250: */
251: public void showAt(int x, int y) {
252: int[] xyPosition = new int[] { x, y };
253: showAt(xyPosition);
254: }
255:
256: /**
257: * Displays this menu at a specific xy position.
258: *
259: * @param xy the xy position
260: */
261: public void showAt(int[] xy) {
262: showAt(getOrCreateJsObj(), JavaScriptObjectHelper
263: .convertToJavaScriptArray(xy), null);
264: }
265:
266: /**
267: * Displays this menu at a specific xy position.
268: *
269: * @param x the X position
270: * @param y the Y position
271: * @param parentMenu the menu's parent menu, if applicable
272: */
273: public void showAt(int x, int y, Menu parentMenu) {
274: int[] xyPosition = new int[] { x, y };
275: showAt(getOrCreateJsObj(), JavaScriptObjectHelper
276: .convertToJavaScriptArray(xyPosition), parentMenu
277: .getOrCreateJsObj());
278: }
279:
280: private static native void showAt(JavaScriptObject menu,
281: JavaScriptObject xyPosition, JavaScriptObject parentMenu) /*-{
282: menu.showAt(xyPosition, parentMenu);
283: }-*/;
284:
285: /**
286: * Add a menu listener.
287: *
288: * @param listener the listener
289: */
290: public native void addListener(MenuListener listener)/*-{
291: var menu = this.@com.gwtext.client.widgets.menu.Menu::getOrCreateJsObj()();
292: var menuJ = this;
293:
294: menu.addListener('beforehide',
295: function(source) {
296: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::doBeforeHide(Lcom/gwtext/client/widgets/menu/Menu;)(menuJ);
297: }
298: );
299:
300: menu.addListener('beforeshow',
301: function(source) {
302: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::doBeforeShow(Lcom/gwtext/client/widgets/menu/Menu;)(menuJ);
303: }
304: );
305:
306: menu.addListener('click',
307: function(source, menuItem, event) {
308: var menuItemId = (menuItem == null || menuItem === undefined) ? null : menuItem.id;
309: var e = @com.gwtext.client.core.EventObject::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(event);
310: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::onClick(Lcom/gwtext/client/widgets/menu/Menu;Ljava/lang/String;Lcom/gwtext/client/core/EventObject;)(menuJ, menuItemId, e);
311: }
312: );
313:
314: menu.addListener('hide',
315: function(source) {
316: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::onHide(Lcom/gwtext/client/widgets/menu/Menu;)(menuJ);
317: }
318: );
319:
320: menu.addListener('itemclick',
321: function(item, event) {
322: var e = @com.gwtext.client.core.EventObject::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(event);
323: //var itemJ = @com.gwtext.client.widgets.ComponentFactory::getComponent(Lcom/google/gwt/core/client/JavaScriptObject;)(item);
324: var itemJ = @com.gwtext.client.widgets.menu.BaseItem::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(item);
325: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::onItemClick(Lcom/gwtext/client/widgets/menu/BaseItem;Lcom/gwtext/client/core/EventObject;)(itemJ, e);
326: }
327: );
328:
329: //TODO getting undefined for menuitemid onmouseover
330: menu.addListener('mouseout',
331: //todo order inconsistent
332: function(source, event, menuItem) {
333: var menuItemJ = null;
334: if(menuItem != null && !(menuItem === undefined)) {
335: // menuItemJ = @com.gwtext.client.widgets.ComponentFactory::getComponent(Lcom/google/gwt/core/client/JavaScriptObject;)(menuItem);
336: menuItemJ = @com.gwtext.client.widgets.menu.BaseItem::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(menuItem)
337: }
338: var e = @com.gwtext.client.core.EventObject::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(event);
339: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::onMouseOut(Lcom/gwtext/client/widgets/menu/Menu;Lcom/gwtext/client/widgets/menu/BaseItem;Lcom/gwtext/client/core/EventObject;)(menuJ, menuItemJ, e);
340: }
341: );
342:
343: //TODO getting undefined for menuitemid onmouseover
344: menu.addListener('mouseover',
345: function(source, event, menuItem) {
346: var menuItemJ = null;
347: if(menuItem != null && !(menuItem === undefined)) {
348: //menuItemJ = @com.gwtext.client.widgets.ComponentFactory::getComponent(Lcom/google/gwt/core/client/JavaScriptObject;)(menuItem);
349: menuItemJ = @com.gwtext.client.widgets.menu.BaseItem::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(menuItem);
350: }
351: var e = @com.gwtext.client.core.EventObject::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(event);
352: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::onMouseOver(Lcom/gwtext/client/widgets/menu/Menu;Lcom/gwtext/client/widgets/menu/BaseItem;Lcom/gwtext/client/core/EventObject;)(menuJ, menuItemJ, e);
353: }
354: );
355:
356: menu.addListener('show',
357: function(source) {
358: return listener.@com.gwtext.client.widgets.menu.event.MenuListener::onShow(Lcom/gwtext/client/widgets/menu/Menu;)(menuJ);
359: }
360: );
361: }-*/;
362:
363: // --- config properties ---
364:
365: /**
366: * True to allow multiple menus to be displayed at the same time (defaults to false).
367: *
368: * @param allowOtherMenus true to allow multiple menus
369: */
370: public void setAllowOtherMenus(boolean allowOtherMenus) {
371: JavaScriptObjectHelper.setAttribute(config, "allowOtherMenus",
372: allowOtherMenus);
373: }
374:
375: /**
376: * The default {@link com.gwtext.client.core.ExtElement#alignTo} anchor position value for this menu relative to its
377: * element of origin (defaults to "tl-bl").
378: *
379: * @param anchorPosition defaults to t-b?
380: */
381: public void setDefaultAlign(String anchorPosition) {
382: JavaScriptObjectHelper.setAttribute(config, "defaultAlign",
383: anchorPosition);
384: }
385:
386: /**
387: * The minimum width of the menu in pixels (defaults to 120).
388: *
389: * @param minWidth the min width
390: */
391: public void setMinWidth(int minWidth) {
392: JavaScriptObjectHelper.setAttribute(config, "minWidth",
393: minWidth);
394: }
395:
396: /**
397: * True for the default effect.
398: *
399: * @param shadow true for shadow
400: */
401: public void setShadow(boolean shadow) {
402: JavaScriptObjectHelper.setAttribute(config, "shadow", shadow);
403: }
404:
405: /**
406: * "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right shadow (defaults to "sides")
407: *
408: * @param shadow the shadow settings
409: */
410: public void setShadow(String shadow) {
411: JavaScriptObjectHelper.setAttribute(config, "shadow", shadow);
412: }
413:
414: /**
415: * The Ext.Element.alignTo anchor position value to use for submenus of this menu (defaults to "tl-tr?").
416: *
417: * @param anchorPosition the anchor position
418: */
419: public void setSubMenuAlign(String anchorPosition) {
420: JavaScriptObjectHelper.setAttribute(config, "subMenuAlign",
421: anchorPosition);
422: }
423:
424: }
|