Description:
It would be useful if you could add seperators to MenuBar's, a feature in most modern GUI's. You are able to add in items to a menubar that trigger a dummy command, but they are still selected.
Fix:
A new method in MenuBar called addSeparator, which adds an unselectable MenuItemSeparator to the MenuBar. MenuItemSeparators can also be removed, just like normal MenuItems.
Patch by:jlabanca
Review by:ecc
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1740 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 beb3546..5bbfdd5 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -41,6 +41,10 @@
* <li>.gwt-MenuBar-vertical { dependent style applied to vertical menu bars }</li>
* <li>.gwt-MenuBar .gwt-MenuItem { menu items }</li>
* <li>.gwt-MenuBar .gwt-MenuItem-selected { selected menu items }</li>
+ * <li>.gwt-MenuBar .gwt-MenuItemSeparator { section breaks between menu items }
+ * </li>
+ * <li>.gwt-MenuBar .gwt-MenuItemSeparator .content { inner component of
+ * section separators } </li>
* </ul>
*
* <p>
@@ -50,8 +54,17 @@
*/
public class MenuBar extends Widget implements PopupListener {
- private Element body;
+ /**
+ * List of all {@link MenuItem}s and {@link MenuItemSeparator}s.
+ */
+ private ArrayList<UIObject> allItems = new ArrayList<UIObject>();
+
+ /**
+ * List of {@link MenuItem}s, not including {@link MenuItemSeparator}s.
+ */
private ArrayList<MenuItem> items = new ArrayList<MenuItem>();
+
+ private Element body;
private MenuBar parentMenu;
private PopupPanel popup;
private MenuItem selectedItem;
@@ -101,21 +114,15 @@
* Adds a menu item to the bar.
*
* @param item the item to be added
+ * @return the {@link MenuItem} object
*/
- public void addItem(MenuItem item) {
- Element tr;
- if (vertical) {
- tr = DOM.createTR();
- DOM.appendChild(body, tr);
- } else {
- tr = DOM.getChild(body, 0);
- }
-
- DOM.appendChild(tr, item.getElement());
-
+ public MenuItem addItem(MenuItem item) {
+ addItemElement(item.getElement());
item.setParentMenu(this);
item.setSelectionStyle(false);
items.add(item);
+ allItems.add(item);
+ return item;
}
/**
@@ -128,9 +135,7 @@
* @return the {@link MenuItem} object created
*/
public MenuItem addItem(String text, boolean asHTML, Command cmd) {
- MenuItem item = new MenuItem(text, asHTML, cmd);
- addItem(item);
- return item;
+ return addItem(new MenuItem(text, asHTML, cmd));
}
/**
@@ -143,9 +148,7 @@
* @return the {@link MenuItem} object created
*/
public MenuItem addItem(String text, boolean asHTML, MenuBar popup) {
- MenuItem item = new MenuItem(text, asHTML, popup);
- addItem(item);
- return item;
+ return addItem(new MenuItem(text, asHTML, popup));
}
/**
@@ -157,9 +160,7 @@
* @return the {@link MenuItem} object created
*/
public MenuItem addItem(String text, Command cmd) {
- MenuItem item = new MenuItem(text, cmd);
- addItem(item);
- return item;
+ return addItem(new MenuItem(text, cmd));
}
/**
@@ -171,9 +172,31 @@
* @return the {@link MenuItem} object created
*/
public MenuItem addItem(String text, MenuBar popup) {
- MenuItem item = new MenuItem(text, popup);
- addItem(item);
- return item;
+ return addItem(new MenuItem(text, popup));
+ }
+
+ /**
+ * Adds a thin line to the {@link MenuBar} to separate sections of
+ * {@link MenuItem}s.
+ *
+ * @return the {@link MenuItemSeparator} object created
+ */
+ public MenuItemSeparator addSeparator() {
+ return addSeparator(new MenuItemSeparator());
+ }
+
+ /**
+ * Adds a thin line to the {@link MenuBar} to separate sections of
+ * {@link MenuItem}s.
+ *
+ * @param separator the {@link MenuItemSeparator} to be added
+ * @return the {@link MenuItemSeparator} object
+ */
+ public MenuItemSeparator addSeparator(MenuItemSeparator separator) {
+ addItemElement(separator.getElement());
+ separator.setParentMenu(this);
+ allItems.add(separator);
+ return separator;
}
/**
@@ -184,7 +207,19 @@
while (DOM.getChildCount(container) > 0) {
DOM.removeChild(container, DOM.getChild(container, 0));
}
+
+ // Set the parent of all items to null
+ for (UIObject item : allItems) {
+ if (item instanceof MenuItemSeparator) {
+ ((MenuItemSeparator) item).setParentMenu(null);
+ } else {
+ ((MenuItem) item).setParentMenu(null);
+ }
+ }
+
+ // Clear out all of the items and separators
items.clear();
+ allItems.clear();
}
/**
@@ -246,14 +281,21 @@
* @param item the item to be removed
*/
public void removeItem(MenuItem item) {
- int idx = items.indexOf(item);
- if (idx == -1) {
- return;
+ if (removeItemElement(item)) {
+ items.remove(item);
+ item.setParentMenu(null);
}
+ }
- Element container = getItemContainerElement();
- DOM.removeChild(container, DOM.getChild(container, idx));
- items.remove(idx);
+ /**
+ * Removes the specified {@link MenuItemSeparator} from the bar.
+ *
+ * @param separator the separator to be removed
+ */
+ public void removeSeparator(MenuItemSeparator separator) {
+ if (removeItemElement(separator)) {
+ separator.setParentMenu(null);
+ }
}
/**
@@ -442,6 +484,23 @@
}
/**
+ * Physically add the td element of a {@link MenuItem} or
+ * {@link MenuItemSeparator} to this {@link MenuBar}.
+ *
+ * @param tdElem the td element to be added
+ */
+ private void addItemElement(Element tdElem) {
+ Element tr;
+ if (vertical) {
+ tr = DOM.createTR();
+ DOM.appendChild(body, tr);
+ } else {
+ tr = DOM.getChild(body, 0);
+ }
+ DOM.appendChild(tr, tdElem);
+ }
+
+ /**
* Closes this menu (if it is a popup).
*/
private void close() {
@@ -489,4 +548,23 @@
selectItem(items.get(0));
}
}
+
+ /**
+ * Removes the specified item from the {@link MenuBar} and the physical DOM
+ * structure.
+ *
+ * @param item the item to be removed
+ * @return true if the item was removed
+ */
+ private boolean removeItemElement(UIObject item) {
+ int idx = allItems.indexOf(item);
+ if (idx == -1) {
+ return false;
+ }
+
+ Element container = getItemContainerElement();
+ DOM.removeChild(container, DOM.getChild(container, idx));
+ allItems.remove(idx);
+ return true;
+ }
}
diff --git a/user/src/com/google/gwt/user/client/ui/MenuItemSeparator.java b/user/src/com/google/gwt/user/client/ui/MenuItemSeparator.java
new file mode 100644
index 0000000..4973c2d
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/MenuItemSeparator.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+
+/**
+ * A separator that can be placed in a
+ * {@link com.google.gwt.user.client.ui.MenuBar}.
+ */
+public class MenuItemSeparator extends UIObject {
+
+ private static final String STYLENAME_DEFAULT = "gwt-MenuItemSeparator";
+
+ private MenuBar parentMenu;
+
+ /**
+ * Constructs a new {@link MenuItemSeparator}.
+ */
+ public MenuItemSeparator() {
+ setElement(DOM.createTD());
+ setStyleName(STYLENAME_DEFAULT);
+
+ // Add an inner element for styling purposes
+ Element div = DOM.createDiv();
+ DOM.appendChild(getElement(), div);
+ setStyleName(div, "content");
+ }
+
+ /**
+ * Gets the menu that contains this item.
+ *
+ * @return the parent menu, or <code>null</code> if none exists.
+ */
+ public MenuBar getParentMenu() {
+ return parentMenu;
+ }
+
+ void setParentMenu(MenuBar parentMenu) {
+ this.parentMenu = parentMenu;
+ }
+}
diff --git a/user/test/com/google/gwt/user/UISuite.java b/user/test/com/google/gwt/user/UISuite.java
index 5ae643d..e5eb432 100644
--- a/user/test/com/google/gwt/user/UISuite.java
+++ b/user/test/com/google/gwt/user/UISuite.java
@@ -32,6 +32,7 @@
import com.google.gwt.user.client.ui.ImageTest;
import com.google.gwt.user.client.ui.LinearPanelTest;
import com.google.gwt.user.client.ui.ListBoxTest;
+import com.google.gwt.user.client.ui.MenuBarTest;
import com.google.gwt.user.client.ui.NamedFrameTest;
import com.google.gwt.user.client.ui.PanelTest;
import com.google.gwt.user.client.ui.PopupTest;
@@ -79,6 +80,7 @@
suite.addTestSuite(ImageTest.class);
suite.addTestSuite(LinearPanelTest.class);
suite.addTestSuite(ListBoxTest.class);
+ suite.addTestSuite(MenuBarTest.class);
suite.addTestSuite(NamedFrameTest.class);
suite.addTestSuite(PanelTest.class);
suite.addTestSuite(PopupTest.class);
diff --git a/user/test/com/google/gwt/user/client/ui/MenuBarTest.java b/user/test/com/google/gwt/user/client/ui/MenuBarTest.java
new file mode 100644
index 0000000..7ee2468
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/ui/MenuBarTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.Command;
+
+import java.util.List;
+
+/**
+ * Tests the DockPanel widget.
+ */
+public class MenuBarTest extends GWTTestCase {
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ /**
+ * Test adding and removing {@link MenuItem}s and {@link MenuItemSeparator}s
+ * from a menu.
+ */
+ public void testAddRemoveItems() {
+ // Create a menu bar
+ MenuBar bar = new MenuBar(true);
+
+ // Create a blank command
+ Command blankCommand = new Command() {
+ public void execute() {
+ }
+ };
+
+ // Add an item, default to text
+ MenuItem item0 = bar.addItem("<b>test</b>", blankCommand);
+ assertEquals("<b>test</b>", item0.getText());
+ assertEquals(blankCommand, item0.getCommand());
+ assertEquals(bar, item0.getParentMenu());
+
+ // Add a separator
+ MenuItemSeparator separator0 = bar.addSeparator();
+ assertEquals(bar, separator0.getParentMenu());
+
+ // Add another item, force to html
+ MenuItem item1 = bar.addItem("<b>test1</b>", true, blankCommand);
+ assertEquals("test1", item1.getText());
+ assertEquals(blankCommand, item1.getCommand());
+ assertEquals(bar, item1.getParentMenu());
+
+ // Get all items
+ List<MenuItem> items = bar.getItems();
+ assertEquals(item0, items.get(0));
+ assertEquals(item1, items.get(1));
+
+ // Remove an item
+ bar.removeItem(item0);
+ assertEquals(item1, items.get(0));
+ assertNull(item0.getParentMenu());
+
+ // Remove the separator
+ bar.removeSeparator(separator0);
+ assertEquals(item1, items.get(0));
+ assertNull(separator0.getParentMenu());
+
+ // Add a bunch of items and clear them all
+ MenuItem item2 = bar.addItem("test2", true, blankCommand);
+ MenuItemSeparator separator1 = bar.addSeparator();
+ MenuItem item3 = bar.addItem("test3", true, blankCommand);
+ MenuItemSeparator separator2 = bar.addSeparator();
+ MenuItem item4 = bar.addItem("test4", true, blankCommand);
+ MenuItemSeparator separator3 = bar.addSeparator();
+ bar.clearItems();
+ assertEquals(0, bar.getItems().size());
+ assertNull(item2.getParentMenu());
+ assertNull(item3.getParentMenu());
+ assertNull(item4.getParentMenu());
+ assertNull(separator1.getParentMenu());
+ assertNull(separator2.getParentMenu());
+ assertNull(separator3.getParentMenu());
+ }
+}