Added methods to insert MenuItems and MenuItemSeparators into MenuBars. Also fixed a MenuBar bug where the visible submenu of the previous MenuItem would remain open if the user highlights a MenuItem that does not have a visible submenu. Patch by: jlabanca Review by: jgw Issue: 2301 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3624 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java index 6f6957d..929fb47 100644 --- a/user/src/com/google/gwt/user/client/ui/MenuBar.java +++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -185,13 +185,7 @@ * @return the {@link MenuItem} object */ public MenuItem addItem(MenuItem item) { - addItemElement(item.getElement()); - item.setParentMenu(this); - item.setSelectionStyle(false); - items.add(item); - allItems.add(item); - updateSubmenuIcon(item); - return item; + return insertItem(item, allItems.size()); } /** @@ -262,13 +256,7 @@ * @return the {@link MenuItemSeparator} object */ public MenuItemSeparator addSeparator(MenuItemSeparator separator) { - if (vertical) { - setItemColSpan(separator, 2); - } - addItemElement(separator.getElement()); - separator.setParentMenu(this); - allItems.add(separator); - return separator; + return insertSeparator(separator, allItems.size()); } /** @@ -308,6 +296,98 @@ return autoOpen; } + /** + * Get the index of a {@link MenuItem}. + * + * @return the index of the item, or -1 if it is not contained by this MenuBar + */ + public int getItemIndex(MenuItem item) { + return allItems.indexOf(item); + } + + /** + * Get the index of a {@link MenuItemSerpator}. + * + * @return the index of the separator, or -1 if it is not contained by this + * MenuBar + */ + public int getSeparatorIndex(MenuItemSeparator item) { + return allItems.indexOf(item); + } + + /** + * Adds a menu item to the bar at a specific index. + * + * @param item the item to be inserted + * @param beforeIndex the index where the item should be inserted + * @return the {@link MenuItem} object + * @throws IndexOutOfBoundsException if <code>beforeIndex</code> is out of + * range + */ + public MenuItem insertItem(MenuItem item, int beforeIndex) + throws IndexOutOfBoundsException { + // Check the bounds + if (beforeIndex < 0 || beforeIndex > allItems.size()) { + throw new IndexOutOfBoundsException(); + } + + // Add to the list of items + allItems.add(beforeIndex, item); + int itemsIndex = 0; + for (int i = 0; i < beforeIndex; i++) { + if (allItems.get(i) instanceof MenuItem) { + itemsIndex++; + } + } + items.add(itemsIndex, item); + + // Setup the menu item + addItemElement(beforeIndex, item.getElement()); + item.setParentMenu(this); + item.setSelectionStyle(false); + updateSubmenuIcon(item); + return item; + } + + /** + * Adds a thin line to the {@link MenuBar} to separate sections of + * {@link MenuItem}s at the specified index. + * + * @param beforeIndex the index where the seperator should be inserted + * @return the {@link MenuItemSeparator} object + * @throws IndexOutOfBoundsException if <code>beforeIndex</code> is out of + * range + */ + public MenuItemSeparator insertSeparator(int beforeIndex) { + return insertSeparator(new MenuItemSeparator(), beforeIndex); + } + + /** + * Adds a thin line to the {@link MenuBar} to separate sections of + * {@link MenuItem}s at the specified index. + * + * @param separator the {@link MenuItemSeparator} to be inserted + * @param beforeIndex the index where the seperator should be inserted + * @return the {@link MenuItemSeparator} object + * @throws IndexOutOfBoundsException if <code>beforeIndex</code> is out of + * range + */ + public MenuItemSeparator insertSeparator(MenuItemSeparator separator, + int beforeIndex) throws IndexOutOfBoundsException { + // Check the bounds + if (beforeIndex < 0 || beforeIndex > allItems.size()) { + throw new IndexOutOfBoundsException(); + } + + if (vertical) { + setItemColSpan(separator, 2); + } + addItemElement(beforeIndex, separator.getElement()); + separator.setParentMenu(this); + allItems.add(beforeIndex, separator); + return separator; + } + public boolean isAnimationEnabled() { return isAnimationEnabled; } @@ -551,6 +631,11 @@ shownChildMenu = null; selectItem(null); } + } else if (autoOpen && shownChildMenu != null) { + // close submenu + shownChildMenu.onHide(); + popup.hide(); + shownChildMenu = null; } } } @@ -671,17 +756,18 @@ * Physically add the td element of a {@link MenuItem} or * {@link MenuItemSeparator} to this {@link MenuBar}. * + * @param beforeIndex the index where the seperator should be inserted * @param tdElem the td element to be added */ - private void addItemElement(Element tdElem) { - Element tr; + private void addItemElement(int beforeIndex, Element tdElem) { if (vertical) { - tr = DOM.createTR(); - DOM.appendChild(body, tr); + Element tr = DOM.createTR(); + DOM.insertChild(body, tr, beforeIndex); + DOM.appendChild(tr, tdElem); } else { - tr = DOM.getChild(body, 0); + Element tr = DOM.getChild(body, 0); + DOM.insertChild(tr, tdElem, beforeIndex); } - DOM.appendChild(tr, tdElem); } /**
diff --git a/user/test/com/google/gwt/user/client/ui/MenuBarTest.java b/user/test/com/google/gwt/user/client/ui/MenuBarTest.java index ac9601a..21beb5b 100644 --- a/user/test/com/google/gwt/user/client/ui/MenuBarTest.java +++ b/user/test/com/google/gwt/user/client/ui/MenuBarTest.java
@@ -92,6 +92,96 @@ assertNull(separator3.getParentMenu()); } + /** + * Test inserting {@link MenuItem}s and {@link MenuItemSeparator}s into the + * menu. + */ + public void testInsertItems() { + // Create a menu bar + MenuBar bar = new MenuBar(true); + + // Create a blank command + Command blankCommand = new Command() { + public void execute() { + } + }; + + // Insert first item + MenuItem item0 = bar.insertItem(new MenuItem("test", blankCommand), 0); + assertEquals(bar.getItemIndex(item0), 0); + + // Insert item at 0 + MenuItem item1 = bar.insertItem(new MenuItem("test", blankCommand), 0); + assertEquals(bar.getItemIndex(item1), 0); + assertEquals(bar.getItemIndex(item0), 1); + + // Insert item at end + MenuItem item2 = bar.insertItem(new MenuItem("test", blankCommand), 2); + assertEquals(bar.getItemIndex(item1), 0); + assertEquals(bar.getItemIndex(item0), 1); + assertEquals(bar.getItemIndex(item2), 2); + + // Insert a separator at 0 + MenuItemSeparator separator0 = bar.insertSeparator(0); + assertEquals(bar.getSeparatorIndex(separator0), 0); + assertEquals(bar.getItemIndex(item1), 1); + assertEquals(bar.getItemIndex(item0), 2); + assertEquals(bar.getItemIndex(item2), 3); + + // Insert a separator at end + MenuItemSeparator separator1 = bar.insertSeparator(4); + assertEquals(bar.getSeparatorIndex(separator0), 0); + assertEquals(bar.getItemIndex(item1), 1); + assertEquals(bar.getItemIndex(item0), 2); + assertEquals(bar.getItemIndex(item2), 3); + assertEquals(bar.getSeparatorIndex(separator1), 4); + + // Insert a separator at middle + MenuItemSeparator separator2 = bar.insertSeparator(2); + assertEquals(bar.getSeparatorIndex(separator0), 0); + assertEquals(bar.getItemIndex(item1), 1); + assertEquals(bar.getSeparatorIndex(separator2), 2); + assertEquals(bar.getItemIndex(item0), 3); + assertEquals(bar.getItemIndex(item2), 4); + assertEquals(bar.getSeparatorIndex(separator1), 5); + } + + /** + * Test inserting {@link MenuItem}s and {@link MenuItemSeparator}s into the + * menu at indexes that are out of bounds. + */ + public void testInsertItemsOutOfBounds() { + // Create a menu bar + MenuBar bar = new MenuBar(true); + + // Create a blank command + Command blankCommand = new Command() { + public void execute() { + } + }; + + // Add some items to the menu + for (int i = 0; i < 3; i++) { + bar.addItem("item", blankCommand); + } + + // Add an item at a negative index + try { + bar.insertItem(new MenuItem("test", blankCommand), -1); + fail("Expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected exception + } + + // Add an item at a high index + try { + bar.insertItem(new MenuItem("test", blankCommand), 4); + fail("Expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected exception + } + } + public void testDebugId() { Command emptyCommand = new Command() { public void execute() { @@ -149,11 +239,9 @@ }; // Add some items - MenuItem item0 = bar.addItem("item0", blankCommand); MenuItem item1 = bar.addItem("item1", blankCommand); MenuItem item2 = bar.addItem("item2", blankCommand); MenuItem item3 = bar.addItem("item3", blankCommand); - MenuItem item4 = bar.addItem("item4", blankCommand); // Test setting the selected item assertNull(bar.getSelectedItem());