From: Jouni Koivuviita Date: Wed, 11 Nov 2009 08:05:38 +0000 (+0000) Subject: MenuBar fixes (again) X-Git-Tag: 6.7.0.beta1~2313 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c73e3e3a8ba21df09967896ad6b238c098809b47;p=vaadin-framework.git MenuBar fixes (again) * Fix submenu indicators for IE * Fixes #3678: enhancement: MenuBar needs a separator item svn changeset:9722/svn branch:6.2 --- diff --git a/WebContent/VAADIN/themes/base/menubar/menubar.css b/WebContent/VAADIN/themes/base/menubar/menubar.css index e3e6becd6c..45170ff99f 100644 --- a/WebContent/VAADIN/themes/base/menubar/menubar.css +++ b/WebContent/VAADIN/themes/base/menubar/menubar.css @@ -56,10 +56,22 @@ margin-right: 0; margin-top: -2px; } +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + position: relative; + margin-left: 0; +} .v-menubar-menuitem-disabled { color: #999; } .v-menubar-more-menuitem { /* Arial has the most coverage for geometric entity characters */ font-family: arial, helvetica, sans-serif; +} +.v-menubar-separator span { + display: block; + text-indent: -9999px; + height: 1px; + margin: 3px 0; + overflow: hidden; + background: #ddd; } \ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/styles.css b/WebContent/VAADIN/themes/base/styles.css index 6d075d5c50..5908dcec9f 100644 --- a/WebContent/VAADIN/themes/base/styles.css +++ b/WebContent/VAADIN/themes/base/styles.css @@ -679,6 +679,10 @@ div.v-app-loading { margin-right: 0; margin-top: -2px; } +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + position: relative; + margin-left: 0; +} .v-menubar-menuitem-disabled { color: #999; } @@ -686,6 +690,14 @@ div.v-app-loading { /* Arial has the most coverage for geometric entity characters */ font-family: arial, helvetica, sans-serif; } +.v-menubar-separator span { + display: block; + text-indent: -9999px; + height: 1px; + margin: 3px 0; + overflow: hidden; + background: #ddd; +} .v-Notification { background: #999; diff --git a/WebContent/VAADIN/themes/reindeer/menubar/menubar.css b/WebContent/VAADIN/themes/reindeer/menubar/menubar.css index 13f4fa72b0..e109a04681 100644 --- a/WebContent/VAADIN/themes/reindeer/menubar/menubar.css +++ b/WebContent/VAADIN/themes/reindeer/menubar/menubar.css @@ -41,12 +41,17 @@ background-image: url(img/menu-sel-bg.png); /** sprite-ref: verticals; sprite-alignment: repeat */ } .v-menubar-submenu .v-menubar-submenu-indicator { - background: transparent url(img/submenu-icon.png) no-repeat right bottom; + background: transparent url(img/submenu-icon.png) no-repeat right 70%; width: 16px; margin: 0 -20px 0 5px; text-indent: -999px; vertical-align: middle; } +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + margin: 0 -20px 0 0; + position: relative; + right: -4px; +} .v-menubar-submenu .v-menubar-menuitem-selected .v-menubar-submenu-indicator { background-image: url(img/submenu-icon-hover.png); } \ No newline at end of file diff --git a/WebContent/VAADIN/themes/reindeer/styles.css b/WebContent/VAADIN/themes/reindeer/styles.css index 010a2f51ba..1aa84f88d3 100644 --- a/WebContent/VAADIN/themes/reindeer/styles.css +++ b/WebContent/VAADIN/themes/reindeer/styles.css @@ -679,6 +679,10 @@ div.v-app-loading { margin-right: 0; margin-top: -2px; } +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + position: relative; + margin-left: 0; +} .v-menubar-menuitem-disabled { color: #999; } @@ -686,6 +690,14 @@ div.v-app-loading { /* Arial has the most coverage for geometric entity characters */ font-family: arial, helvetica, sans-serif; } +.v-menubar-separator span { + display: block; + text-indent: -9999px; + height: 1px; + margin: 3px 0; + overflow: hidden; + background: #ddd; +} .v-Notification { background: #999; @@ -3058,12 +3070,17 @@ td.v-datefield-calendarpanel-nextyear { background-position: left -423px; } .v-menubar-submenu .v-menubar-submenu-indicator { - background: transparent url(menubar/img/submenu-icon.png) no-repeat right bottom; + background: transparent url(menubar/img/submenu-icon.png) no-repeat right 70%; width: 16px; margin: 0 -20px 0 5px; text-indent: -999px; vertical-align: middle; } +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + margin: 0 -20px 0 0; + position: relative; + right: -4px; +} .v-menubar-submenu .v-menubar-menuitem-selected .v-menubar-submenu-indicator { background-image: url(menubar/img/submenu-icon-hover.png); } diff --git a/WebContent/VAADIN/themes/runo/menubar/menubar.css b/WebContent/VAADIN/themes/runo/menubar/menubar.css index 55890d686f..324713db6e 100644 --- a/WebContent/VAADIN/themes/runo/menubar/menubar.css +++ b/WebContent/VAADIN/themes/runo/menubar/menubar.css @@ -24,12 +24,17 @@ border-left: 1px solid #d0d4d5; } .v-menubar-submenu .v-menubar-menuitem { - padding: 2px 10px; + padding: 2px 16px 2px 10px; } .v-menubar-submenu .v-menubar-menuitem-selected { color: #fff; background: #5daee8; } .v-menubar-submenu .v-menubar-submenu-indicator { - margin-right: -3px; + margin-right: -12px; + height: 14px; +} +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + margin-right: -12px; + right: -3px; } \ No newline at end of file diff --git a/WebContent/VAADIN/themes/runo/styles.css b/WebContent/VAADIN/themes/runo/styles.css index 6d58d82006..e2a5dd418f 100644 --- a/WebContent/VAADIN/themes/runo/styles.css +++ b/WebContent/VAADIN/themes/runo/styles.css @@ -679,6 +679,10 @@ div.v-app-loading { margin-right: 0; margin-top: -2px; } +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + position: relative; + margin-left: 0; +} .v-menubar-menuitem-disabled { color: #999; } @@ -686,6 +690,14 @@ div.v-app-loading { /* Arial has the most coverage for geometric entity characters */ font-family: arial, helvetica, sans-serif; } +.v-menubar-separator span { + display: block; + text-indent: -9999px; + height: 1px; + margin: 3px 0; + overflow: hidden; + background: #ddd; +} .v-Notification { background: #999; @@ -2177,14 +2189,19 @@ div.v-tree-node-leaf { border-left: 1px solid #d0d4d5; } .v-menubar-submenu .v-menubar-menuitem { - padding: 2px 10px; + padding: 2px 16px 2px 10px; } .v-menubar-submenu .v-menubar-menuitem-selected { color: #fff; background: #5daee8; } .v-menubar-submenu .v-menubar-submenu-indicator { - margin-right: -3px; + margin-right: -12px; + height: 14px; +} +.v-ie7 .v-menubar-submenu .v-menubar-submenu-indicator { + margin-right: -12px; + right: -3px; } .v-Notification { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java index c756b32453..0e09c7a287 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java @@ -22,6 +22,7 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ContainerResizedListener; import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.Util; public class VMenuBar extends Widget implements Paintable, CloseHandler, ContainerResizedListener { @@ -156,47 +157,53 @@ public class VMenuBar extends Widget implements Paintable, String itemText = item.getStringAttribute("text"); final int itemId = item.getIntAttribute("id"); - boolean itemHasCommand = item.getBooleanAttribute("command"); + boolean itemHasCommand = item.hasAttribute("command"); // Construct html from the text and the optional icon StringBuffer itemHTML = new StringBuffer(); + Command cmd = null; - // 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;\""; + if (item.hasAttribute("separator")) { + itemHTML.append("---"); + } 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(""); } - itemHTML - .append(""); - } - if (item.hasAttribute("icon")) { - itemHTML.append("\"\""); - } - - itemHTML.append(itemText); + if (item.hasAttribute("icon")) { + itemHTML + .append("\"\""); + } - Command cmd = null; + itemHTML.append(Util.escapeHTML(itemText)); - if (itemHasCommand) { - // Construct a command that fires onMenuClick(int) with the - // item's id-number - cmd = new Command() { - public void execute() { - hostReference.onMenuClick(itemId); - } - }; + if (itemHasCommand) { + // Construct a command that fires onMenuClick(int) with the + // item's id-number + cmd = new Command() { + public void execute() { + hostReference.onMenuClick(itemId); + } + }; + } } currentItem = currentMenu.addItem(itemHTML.toString(), cmd); + currentItem.setSeparator(item.hasAttribute("separator")); currentItem.setEnabled(!item.hasAttribute("disabled")); if (item.getChildCount() > 0) { @@ -448,7 +455,7 @@ public class VMenuBar extends Widget implements Paintable, * @param item */ public void itemOver(CustomMenuItem item) { - if (subMenu || menuVisible) { + if ((subMenu || menuVisible) && !item.isSeparator()) { setSelected(item); } @@ -484,6 +491,8 @@ public class VMenuBar extends Widget implements Paintable, * @param item */ public void showChildMenu(CustomMenuItem item) { + final int shadowSpace = 10; + popup = new VOverlay(true, false, true); popup.setWidget(item.getSubMenu()); popup.addCloseHandler(this); @@ -509,14 +518,18 @@ public class VMenuBar extends Widget implements Paintable, popup.show(); if (left + popup.getOffsetWidth() >= RootPanel.getBodyElement() - .getOffsetWidth()) { + .getOffsetWidth() + - shadowSpace) { if (subMenu) { left = item.getParentMenu().getAbsoluteLeft() - - popup.getOffsetWidth(); + - popup.getOffsetWidth() - shadowSpace; } else { left = RootPanel.getBodyElement().getOffsetWidth() - - popup.getOffsetWidth(); - ApplicationConnection.getConsole().log("" + left); + - popup.getOffsetWidth() - shadowSpace; + } + // Accommodate space for shadow + if (left < shadowSpace) { + left = shadowSpace; } popup.setPopupPosition(left, top); } @@ -643,6 +656,7 @@ public class VMenuBar extends Widget implements Paintable, protected VMenuBar subMenu = null; protected VMenuBar parentMenu = null; protected boolean enabled = true; + protected boolean isSeparator = false; public CustomMenuItem(String html, Command cmd) { setElement(DOM.createTD()); @@ -655,7 +669,7 @@ public class VMenuBar extends Widget implements Paintable, } public void setSelected(boolean selected) { - if (selected) { + if (selected && !isSeparator) { addStyleDependentName("selected"); } else { removeStyleDependentName("selected"); @@ -719,6 +733,20 @@ public class VMenuBar extends Widget implements Paintable, public boolean isEnabled() { return enabled; } + + private void setSeparator(boolean separator) { + isSeparator = separator; + if (separator) { + setStyleName(CLASSNAME + "-separator"); + } else { + setStyleName(CLASSNAME + "-menuitem"); + setEnabled(enabled); + } + } + + public boolean isSeparator() { + return isSeparator; + } } /** diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java index 77523f9680..286da7a4ff 100644 --- a/src/com/vaadin/ui/MenuBar.java +++ b/src/com/vaadin/ui/MenuBar.java @@ -79,35 +79,39 @@ public class MenuBar extends AbstractComponent { while (itr.hasNext()) { MenuItem item = itr.next(); - target.startTag("item"); - - target.addAttribute("text", item.getText()); target.addAttribute("id", item.getId()); - Command command = item.getCommand(); - if (command != null) { - target.addAttribute("command", true); + if (item.isSeparator()) { + target.addAttribute("separator", true); + target.endTag("item"); } else { - target.addAttribute("command", false); - } + target.addAttribute("text", item.getText()); - Resource icon = item.getIcon(); - if (icon != null) { - target.addAttribute("icon", icon); - } + Command command = item.getCommand(); + if (command != null) { + target.addAttribute("command", true); + } - if (!item.isEnabled()) { - target.addAttribute("disabled", true); - } + Resource icon = item.getIcon(); + if (icon != null) { + target.addAttribute("icon", icon); + } - if (item.hasChildren()) { - iteratorStack.push(itr); // For later use + if (!item.isEnabled()) { + target.addAttribute("disabled", true); + } + + if (item.hasChildren()) { + iteratorStack.push(itr); // For later use + + // Go through the children + itr = item.getChildren().iterator(); + } else { + target.endTag("item"); // Item had no children, end + // description + } - // Go through the children - itr = item.getChildren().iterator(); - } else { - target.endTag("item"); // Item had no children, end description } // The end submenu. More than one submenu may end at once. @@ -115,7 +119,6 @@ public class MenuBar extends AbstractComponent { itr = iteratorStack.pop(); target.endTag("item"); } - } target.endTag("items"); @@ -382,6 +385,7 @@ public class MenuBar extends AbstractComponent { private Resource itsIcon; private MenuItem itsParent; private boolean enabled = true; + private boolean isSeparator = false; /** * Constructs a new menu item that can optionally have an icon and a @@ -410,7 +414,27 @@ public class MenuBar extends AbstractComponent { * @return True if this item has children */ public boolean hasChildren() { - return itsChildren != null; + return !isSeparator() && itsChildren != null; + } + + /** + * Adds a separator to this menu. A separator is a way to visually group + * items in a menu, to make it easier for users to find what they are + * looking for in the menu. + * + * @author Jouni Koivuviita / IT Mill Ltd. + * @since 6.2.0 + */ + public MenuBar.MenuItem addSeparator() { + MenuItem item = addItem("", null, null); + item.setSeparator(true); + return item; + } + + public MenuBar.MenuItem addSeparatorBefore(MenuItem itemToAddBefore) { + MenuItem item = addItemBefore("", null, null, itemToAddBefore); + item.setSeparator(true); + return item; } /** @@ -439,8 +463,12 @@ public class MenuBar extends AbstractComponent { */ public MenuBar.MenuItem addItem(String caption, Resource icon, MenuBar.Command command) { + if (isSeparator()) { + throw new UnsupportedOperationException( + "Cannot add items to a separator"); + } if (caption == null) { - throw new IllegalArgumentException("caption cannot be null"); + throw new IllegalArgumentException("Caption cannot be null"); } if (itsChildren == null) { @@ -483,7 +511,6 @@ public class MenuBar extends AbstractComponent { newItem = new MenuItem(caption, icon, command); newItem.setParent(this); itsChildren.add(index, newItem); - } else { newItem = addItem(caption, icon, command); } @@ -546,7 +573,10 @@ public class MenuBar extends AbstractComponent { * @return The number of child items */ public int getSize() { - return itsChildren.size(); + if (itsChildren != null) { + return itsChildren.size(); + } + return -1; } /** @@ -604,8 +634,8 @@ public class MenuBar extends AbstractComponent { if (itsChildren.isEmpty()) { itsChildren = null; } + requestRepaint(); } - requestRepaint(); } /** @@ -615,8 +645,8 @@ public class MenuBar extends AbstractComponent { if (itsChildren != null) { itsChildren.clear(); itsChildren = null; + requestRepaint(); } - requestRepaint(); } /** @@ -638,6 +668,15 @@ public class MenuBar extends AbstractComponent { return enabled; } + private void setSeparator(boolean isSeparator) { + this.isSeparator = isSeparator; + requestRepaint(); + } + + public boolean isSeparator() { + return isSeparator; + } + }// class MenuItem }// class MenuBar