diff options
author | Henri Sara <henri.sara@itmill.com> | 2011-06-13 11:15:49 +0000 |
---|---|---|
committer | Henri Sara <henri.sara@itmill.com> | 2011-06-13 11:15:49 +0000 |
commit | 8727670c7a90267ad4d2bceb69d18aee5c6f4615 (patch) | |
tree | 5cd033998eb9f6892b050d973ee3999a0a35d416 /src | |
parent | 354be78fb0cbd147085ef11f88fe3c1c3cdb99b7 (diff) | |
download | vaadin-framework-8727670c7a90267ad4d2bceb69d18aee5c6f4615.tar.gz vaadin-framework-8727670c7a90267ad4d2bceb69d18aee5c6f4615.zip |
#4125 MenuBar supports selectable items
svn changeset:19348/svn branch:6.6
Diffstat (limited to 'src')
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java | 188 | ||||
-rw-r--r-- | src/com/vaadin/ui/MenuBar.java | 126 |
2 files changed, 270 insertions, 44 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java index 44870ef350..cab37e7c70 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java @@ -8,6 +8,7 @@ import java.util.Iterator; import java.util.List; import java.util.Stack; +import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.NodeList; @@ -66,6 +67,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, public static final String OPEN_ROOT_MENU_ON_HOWER = "ormoh"; + public static final String ATTRIBUTE_CHECKED = "checked"; + /** Widget fields **/ protected boolean subMenu; protected ArrayList<CustomMenuItem> items; @@ -228,7 +231,10 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, } itemHTML.append(moreItemText); - moreItem = new CustomMenuItem(itemHTML.toString(), emptyCommand); + moreItem = GWT.create(CustomMenuItem.class); + moreItem.setHTML(itemHTML.toString()); + moreItem.setCommand(emptyCommand); + collapsedRootItems = new VMenuBar(true, (VMenuBar) client.getPaintable(uidlId)); moreItem.setSubMenu(collapsedRootItems); @@ -245,43 +251,16 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, UIDL item = (UIDL) itr.next(); CustomMenuItem currentItem = null; - String itemText = item.getStringAttribute("text"); final int itemId = item.getIntAttribute("id"); boolean itemHasCommand = item.hasAttribute("command"); + boolean itemIsCheckable = item.hasAttribute(ATTRIBUTE_CHECKED); - // Construct html from the text and the optional icon - StringBuffer itemHTML = new StringBuffer(); - Command cmd = null; - - if (item.hasAttribute("separator")) { - itemHTML.append("<span>---</span>"); - } else { - // Add submenu indicator - if (item.getChildCount() > 0) { - // FIXME For compatibility reasons: remove in version 7 - String bgStyle = ""; - if (submenuIcon != null) { - bgStyle = " style=\"background-image: url(" - + submenuIcon - + "); text-indent: -999px; width: 1em;\""; - } - itemHTML.append("<span class=\"" + CLASSNAME - + "-submenu-indicator\"" + bgStyle - + ">►</span>"); - } - - itemHTML.append("<span class=\"" + CLASSNAME - + "-menuitem-caption\">"); - if (item.hasAttribute("icon")) { - itemHTML.append("<img src=\"" - + client.translateVaadinUri(item - .getStringAttribute("icon")) - + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />"); - } - itemHTML.append(Util.escapeHTML(itemText) + "</span>"); + String itemHTML = buildItemHTML(item); - if (itemHasCommand) { + Command cmd = null; + if (!item.hasAttribute("separator")) { + if (itemHasCommand || itemIsCheckable) { // Construct a command that fires onMenuClick(int) with the // item's id-number cmd = new Command() { @@ -309,6 +288,19 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, currentItem.setSubMenu(currentMenu); } + if (!itr.hasNext()) { + boolean hasCheckableItem = false; + for (CustomMenuItem menuItem : currentMenu.getItems()) { + hasCheckableItem = hasCheckableItem + || menuItem.isCheckable(); + } + if (hasCheckableItem) { + currentMenu.addStyleDependentName("check-column"); + } else { + currentMenu.removeStyleDependentName("check-column"); + } + } + while (!itr.hasNext() && !iteratorStack.empty()) { itr = iteratorStack.pop(); currentMenu = menuStack.pop(); @@ -320,6 +312,45 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, }// updateFromUIDL /** + * Build the HTML content for a menu item. + * + * @param item + * @return + */ + protected String buildItemHTML(UIDL item) { + // Construct html from the text and the optional icon + StringBuffer itemHTML = new StringBuffer(); + if (item.hasAttribute("separator")) { + itemHTML.append("<span>---</span>"); + } else { + // Add submenu indicator + if (item.getChildCount() > 0) { + // FIXME For compatibility reasons: remove in version 7 + String bgStyle = ""; + if (submenuIcon != null) { + bgStyle = " style=\"background-image: url(" + submenuIcon + + "); text-indent: -999px; width: 1em;\""; + } + itemHTML.append("<span class=\"" + CLASSNAME + + "-submenu-indicator\"" + bgStyle + ">►</span>"); + } + + itemHTML.append("<span class=\"" + CLASSNAME + + "-menuitem-caption\">"); + if (item.hasAttribute("icon")) { + itemHTML.append("<img src=\"" + + client.translateVaadinUri(item + .getStringAttribute("icon")) + "\" class=\"" + + Icon.CLASSNAME + "\" alt=\"\" />"); + } + String itemText = item.getStringAttribute("text"); + itemHTML.append(Util.escapeHTML(itemText)); + itemHTML.append("</span>"); + } + return itemHTML.toString(); + } + + /** * This is called by the items in the menu and it communicates the * information to the server * @@ -377,7 +408,10 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, * @return the item created */ public CustomMenuItem addItem(String html, Command cmd) { - CustomMenuItem item = new CustomMenuItem(html, cmd); + CustomMenuItem item = GWT.create(CustomMenuItem.class); + item.setHTML(html); + item.setCommand(cmd); + addItem(item); return item; } @@ -832,7 +866,28 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, protected VMenuBar parentMenu = null; protected boolean enabled = true; protected boolean isSeparator = false; + protected boolean checkable = false; + protected boolean checked = false; + + /** + * Default menu item {@link Widget} constructor for GWT.create(). + * + * Use {@link #setHTML(String)} and {@link #setCommand(Command)} after + * constructing a menu item. + */ + public CustomMenuItem() { + this("", null); + } + /** + * Creates a menu item {@link Widget}. + * + * @param html + * @param cmd + * @deprecated use the default constructor and {@link #setHTML(String)} + * and {@link #setCommand(Command)} instead + */ + @Deprecated public CustomMenuItem(String html, Command cmd) { // We need spans to allow inline-block in IE setElement(DOM.createSpan()); @@ -843,20 +898,64 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, setStyleName(CLASSNAME + "-menuitem"); sinkEvents(VTooltip.TOOLTIP_EVENTS); - - // Sink the onload event for any icons. The onload - // events are handled by the parent VMenuBar. - Util.sinkOnloadForImages(getElement()); } public void setSelected(boolean selected) { if (selected && !isSeparator) { addStyleDependentName("selected"); + // needed for IE6 to have a single style name to match for an + // element + if (checkable) { + if (checked) { + removeStyleDependentName("selected-unchecked"); + addStyleDependentName("selected-checked"); + } else { + removeStyleDependentName("selected-checked"); + addStyleDependentName("selected-unchecked"); + } + } } else { removeStyleDependentName("selected"); + // needed for IE6 to have a single style name to match for an + // element + removeStyleDependentName("selected-checked"); + removeStyleDependentName("selected-unchecked"); } } + public void setChecked(boolean checked) { + if (checkable && !isSeparator) { + this.checked = checked; + + if (checked) { + addStyleDependentName("checked"); + removeStyleDependentName("unchecked"); + } else { + addStyleDependentName("unchecked"); + removeStyleDependentName("checked"); + } + } else { + this.checked = false; + } + } + + public boolean isChecked() { + return checked; + } + + public void setCheckable(boolean checkable) { + if (checkable && !isSeparator) { + this.checkable = true; + } else { + setChecked(false); + this.checkable = false; + } + } + + public boolean isCheckable() { + return checkable; + } + /* * setters and getters for the fields */ @@ -892,6 +991,10 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, public void setHTML(String html) { this.html = html; DOM.setInnerHTML(getElement(), html); + + // Sink the onload event for any icons. The onload + // events are handled by the parent VMenuBar. + Util.sinkOnloadForImages(getElement()); } public String getText() { @@ -934,6 +1037,15 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable, setSeparator(uidl.hasAttribute("separator")); setEnabled(!uidl.hasAttribute("disabled")); + if (!isSeparator() && uidl.hasAttribute(ATTRIBUTE_CHECKED)) { + // if the selected attribute is present (either true or false), + // the item is selectable + setCheckable(true); + setChecked(uidl.getBooleanAttribute(ATTRIBUTE_CHECKED)); + } else { + setCheckable(false); + } + if (uidl.hasAttribute("style")) { String itemStyle = uidl.getStringAttribute("style"); addStyleDependentName(itemStyle); diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java index d79e070fca..493870bf82 100644 --- a/src/com/vaadin/ui/MenuBar.java +++ b/src/com/vaadin/ui/MenuBar.java @@ -123,7 +123,12 @@ public class MenuBar extends AbstractComponent { if (description != null && description.length() > 0) { target.addAttribute("description", description); } - + if (item.isSelectable()) { + // if the "checked" attribute is present (either true or false), + // the item is selectable + target.addAttribute(VMenuBar.ATTRIBUTE_CHECKED, + item.isSelected()); + } if (item.hasChildren()) { for (MenuItem child : item.getChildren()) { paintItem(target, child); @@ -167,7 +172,12 @@ public class MenuBar extends AbstractComponent { // If we got the clicked item, launch the command. if (found && tmpItem.isEnabled()) { - tmpItem.getCommand().menuSelected(tmpItem); + if (tmpItem.isSelectable()) { + tmpItem.setSelected(!tmpItem.isSelected()); + } + if (null != tmpItem.getCommand()) { + tmpItem.getCommand().menuSelected(tmpItem); + } } }// if }// changeVariables @@ -431,6 +441,8 @@ public class MenuBar extends AbstractComponent { private boolean isSeparator = false; private String styleName; private String description; + private boolean selectable = false; + private boolean selected = false; /** * Constructs a new menu item that can optionally have an icon and a @@ -505,13 +517,19 @@ public class MenuBar extends AbstractComponent { * the icon for the menu item * @param command * the command for the menu item + * @throws IllegalStateException + * If the item is selectable and thus cannot have children. */ public MenuBar.MenuItem addItem(String caption, Resource icon, - MenuBar.Command command) { + MenuBar.Command command) throws IllegalStateException { if (isSeparator()) { throw new UnsupportedOperationException( "Cannot add items to a separator"); } + if (isSelectable()) { + throw new IllegalStateException( + "A selectable item cannot have children"); + } if (caption == null) { throw new IllegalArgumentException("Caption cannot be null"); } @@ -544,11 +562,16 @@ public class MenuBar extends AbstractComponent { * the command for the menu item * @param itemToAddBefore * the item that will be after the new item - * + * @throws IllegalStateException + * If the item is selectable and thus cannot have children. */ public MenuBar.MenuItem addItemBefore(String caption, Resource icon, - MenuBar.Command command, MenuBar.MenuItem itemToAddBefore) { - + MenuBar.Command command, MenuBar.MenuItem itemToAddBefore) + throws IllegalStateException { + if (isSelectable()) { + throw new IllegalStateException( + "A selectable item cannot have children"); + } MenuItem newItem = null; if (hasChildren() && itsChildren.contains(itemToAddBefore)) { @@ -814,6 +837,97 @@ public class MenuBar extends AbstractComponent { return description; } + /** + * Gets the selectable state of the item. If an item is selectable its + * selected state (as returned by {@link #isSelected()}) is indicated in + * the UI. + * + * <p> + * An item is not selectable by default. + * </p> + * + * @return true if the item is selectable, false otherwise + * @since 6.6.2 + */ + public boolean isSelectable() { + return selectable; + } + + /** + * Sets the selectable state of the item. If an item is selectable its + * selected state (as returned by {@link #isSelected()}) is indicated in + * the UI. + * + * <p> + * An item is not selectable by default. + * </p> + * + * <p> + * Items with sub items cannot be selectable. + * </p> + * + * @param selectable + * true if the item should be selectable, false otherwise + * @throws IllegalStateException + * If the item has children + * @since 6.6.2 + */ + public void setSelectable(boolean selectable) + throws IllegalStateException { + if (hasChildren()) { + throw new IllegalStateException( + "A menu item with children cannot be selectable"); + } + this.selectable = selectable; + requestRepaint(); + } + + /** + * Gets the selected state of the item. Only used if the item is + * selectable (as indicated by {@link #isSelectable()}). The selected + * state is indicated in the UI with the item, if the item is + * selectable. + * + * <p> + * An item is not selected by default. + * </p> + * + * <p> + * Note that the CSS style corresponding to selection is "-checked". The + * style "-selected" refers to the focused menu item (mouse hover or + * keyboard selection). + * </p> + * + * @return true if the item is selected, false otherwise + * @since 6.6.2 + */ + public boolean isSelected() { + return selected; + } + + /** + * Sets the selected state of the item. Only used if the item is + * selectable (indicated by {@link #isSelectable()}). The selected state + * is indicated in the UI with the item, if the item is selectable. + * + * <p> + * An item is not selected by default. + * </p> + * + * <p> + * Note that the CSS style corresponding to selection is "-checked". The + * style "-selected" refers to the focused menu item (mouse hover or + * keyboard selection). + * </p> + * + * @return true if the item is selected, false otherwise + * @since 6.6.2 + */ + public void setSelected(boolean selected) { + this.selected = selected; + requestRepaint(); + } + }// class MenuItem }// class MenuBar |