aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2011-06-13 11:15:49 +0000
committerHenri Sara <henri.sara@itmill.com>2011-06-13 11:15:49 +0000
commit8727670c7a90267ad4d2bceb69d18aee5c6f4615 (patch)
tree5cd033998eb9f6892b050d973ee3999a0a35d416 /src
parent354be78fb0cbd147085ef11f88fe3c1c3cdb99b7 (diff)
downloadvaadin-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.java188
-rw-r--r--src/com/vaadin/ui/MenuBar.java126
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
- + ">&#x25BA;</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 + ">&#x25BA;</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