summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VMenuBar.java14
-rw-r--r--server/src/main/java/com/vaadin/ui/MenuBar.java69
-rw-r--r--server/src/test/java/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java25
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/menubar/MenuBarConstants.java2
-rw-r--r--uitest/src/main/java/com/vaadin/tests/elements/menubar/MenuBarUI.java12
-rw-r--r--uitest/src/test/java/com/vaadin/tests/elements/menubar/MenuBarUITest.java17
6 files changed, 129 insertions, 10 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VMenuBar.java b/client/src/main/java/com/vaadin/client/ui/VMenuBar.java
index 29897f7dd6..144f6117d0 100644
--- a/client/src/main/java/com/vaadin/client/ui/VMenuBar.java
+++ b/client/src/main/java/com/vaadin/client/ui/VMenuBar.java
@@ -805,6 +805,7 @@ public class VMenuBar extends FocusableFlowPanel
protected boolean checked = false;
protected boolean selected = false;
protected String description = null;
+ protected ContentMode contentMode = null;
private String styleName;
@@ -1114,15 +1115,24 @@ public class VMenuBar extends FocusableFlowPanel
MenuBarConstants.ATTRIBUTE_ITEM_DESCRIPTION);
}
+ if (uidl.hasAttribute(
+ MenuBarConstants.ATTRIBUTE_ITEM_CONTENT_MODE)) {
+ String contentModeString = uidl.getStringAttribute(
+ MenuBarConstants.ATTRIBUTE_ITEM_CONTENT_MODE);
+ contentMode = ContentMode.valueOf(contentModeString);
+ } else {
+ contentMode = ContentMode.PREFORMATTED;
+ }
+
updateStyleNames();
}
public TooltipInfo getTooltip() {
- if (description == null) {
+ if (description == null || contentMode == null) {
return null;
}
- return new TooltipInfo(description, ContentMode.PREFORMATTED, null,
+ return new TooltipInfo(description, contentMode, null,
this);
}
diff --git a/server/src/main/java/com/vaadin/ui/MenuBar.java b/server/src/main/java/com/vaadin/ui/MenuBar.java
index 544b93ea6a..72a3671d4e 100644
--- a/server/src/main/java/com/vaadin/ui/MenuBar.java
+++ b/server/src/main/java/com/vaadin/ui/MenuBar.java
@@ -31,6 +31,7 @@ import org.jsoup.parser.Tag;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.server.Resource;
+import com.vaadin.shared.ui.ContentMode;
import com.vaadin.shared.ui.menubar.MenuBarConstants;
import com.vaadin.shared.ui.menubar.MenuBarState;
import com.vaadin.ui.Component.Focusable;
@@ -142,6 +143,14 @@ public class MenuBar extends AbstractComponent
target.addAttribute(MenuBarConstants.ATTRIBUTE_ITEM_DESCRIPTION,
description);
}
+
+ ContentMode contentMode = item.getContentMode();
+ // If the contentMode is equal to ContentMode.PREFORMATTED, we don't add any attribute.
+ if (contentMode != null && contentMode != ContentMode.PREFORMATTED) {
+ target.addAttribute(MenuBarConstants.ATTRIBUTE_ITEM_CONTENT_MODE,
+ contentMode.name());
+ }
+
if (item.isCheckable()) {
// if the "checked" attribute is present (either true or false),
// the item is checkable
@@ -457,6 +466,7 @@ public class MenuBar extends AbstractComponent
private boolean isSeparator = false;
private String styleName;
private String description;
+ private ContentMode contentMode = ContentMode.PREFORMATTED;
private boolean checkable = false;
private boolean checked = false;
@@ -782,20 +792,46 @@ public class MenuBar extends AbstractComponent
}
/**
- * Sets the items's description. See {@link #getDescription()} for more
+ * Analogous method to {@link AbstractComponent#setDescription(String)}.
+ * Sets the item's description. See {@link #getDescription()} for more
* information on what the description is.
*
* @param description
* the new description string for the component.
*/
public void setDescription(String description) {
+ setDescription(description, ContentMode.PREFORMATTED);
+ }
+
+ /**
+ * Analogous method to
+ * {@link AbstractComponent#setDescription(String, ContentMode)}. Sets
+ * the item's description using given content mode. See
+ * {@link #getDescription()} for more information on what the
+ * description is.
+ * <p>
+ * If the content {@code mode} is {@literal ContentMode.HTML} the
+ * description is displayed as HTML in tooltips or directly in certain
+ * components so care should be taken to avoid creating the possibility
+ * for HTML injection and possibly XSS vulnerabilities.
+ *
+ * @see ContentMode
+ *
+ * @param description
+ * the new description string for the component.
+ * @param mode
+ * the content mode for the description
+ * @since
+ */
+ public void setDescription(String description, ContentMode mode) {
this.description = description;
+ this.contentMode = mode;
markAsDirty();
}
/**
* <p>
- * Gets the items's description. The description can be used to briefly
+ * Gets the item's description. The description can be used to briefly
* describe the state of the item to the user. The description string
* may contain certain XML tags:
* </p>
@@ -854,6 +890,23 @@ public class MenuBar extends AbstractComponent
}
/**
+ * Gets the content mode of the description of the menu item. The
+ * description is displayed as the tooltip of the menu item in the UI.
+ * <p>
+ * If no content mode was explicitly set using the
+ * {@link #setDescription(String, ContentMode)} method, the content mode
+ * will be {@link ContentMode#PREFORMATTED}
+ * </p>
+ *
+ * @return the {@link ContentMode} of the description of this menu item
+ * @see ContentMode
+ * @since
+ */
+ public ContentMode getContentMode() {
+ return contentMode;
+ }
+
+ /**
* Gets the checkable state of the item - whether the item has checked
* and unchecked states. If an item is checkable its checked state (as
* returned by {@link #isChecked()}) is indicated in the UI.
@@ -982,6 +1035,9 @@ public class MenuBar extends AbstractComponent
DesignAttributeHandler.writeAttribute("description", attr,
item.getDescription(), def.getDescription(), String.class,
context);
+ DesignAttributeHandler.writeAttribute("contentmode", attr,
+ item.getContentMode().name(), def.getContentMode().name(), String.class,
+ context);
DesignAttributeHandler.writeAttribute("style-name", attr,
item.getStyleName(), def.getStyleName(), String.class, context);
@@ -1041,8 +1097,13 @@ public class MenuBar extends AbstractComponent
attr, boolean.class));
}
if (menuElement.hasAttr("description")) {
- menu.setDescription(DesignAttributeHandler
- .readAttribute("description", attr, String.class));
+ String description = DesignAttributeHandler.readAttribute("description", attr, String.class);
+ if (menuElement.hasAttr("contentmode")) {
+ String contentModeString = DesignAttributeHandler.readAttribute("contentmode", attr, String.class);
+ menu.setDescription(description, ContentMode.valueOf(contentModeString));
+ } else {
+ menu.setDescription(description);
+ }
}
if (menuElement.hasAttr("style-name")) {
menu.setStyleName(DesignAttributeHandler.readAttribute("style-name",
diff --git a/server/src/test/java/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
index 5a67d2bcce..68f1fad864 100644
--- a/server/src/test/java/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
+++ b/server/src/test/java/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
@@ -28,6 +28,7 @@ import com.vaadin.server.ThemeResource;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.MenuBar.MenuItem;
+import com.vaadin.shared.ui.ContentMode;
/**
* Tests declarative support for menu bars.
@@ -69,6 +70,27 @@ public class MenuBarDeclarativeTest extends DeclarativeTestBase<MenuBar> {
}
@Test
+ public void testDescriptionContentMode() {
+ String design = "<vaadin-menu-bar plain-text>"
+ + "<menu description=\"This description is implicitly preformatted\">One</menu>"
+ + "<menu description=\"This description\nis explicitly\n\npreformatted\">preformatted</menu>"
+ + "<menu contentmode=\"HTML\" description=\"<b>I</b> contain <br/> <e>html</e>\">HTML</menu>"
+ + "<menu contentmode=\"TEXT\" description=\"Just plain text\">plain text</menu>"
+ + "</vaadin-menu-bar>";
+ MenuBar menuBar = new MenuBar();
+ menuBar.addItem("One", null).setDescription("This description is implicitly preformatted");
+ menuBar.addItem("preformatted", null)
+ .setDescription("This description\nis explicitly\n\npreformatted", ContentMode.PREFORMATTED);
+ menuBar.addItem("HTML", null)
+ .setDescription("<b>I</b> contain <br/> <e>html</e>", ContentMode.HTML);
+ menuBar.addItem("plain text", null)
+ .setDescription("Just plain text", ContentMode.TEXT);
+
+ testWrite(design, menuBar);
+ testRead(design, menuBar);
+ }
+
+ @Test
// #16328
public void testTicketSpec1() throws IOException {
String design = "<vaadin-menu-bar auto-open plain-text tabindex=5> "
@@ -165,12 +187,13 @@ public class MenuBarDeclarativeTest extends DeclarativeTestBase<MenuBar> {
actual.isSeparator());
assertEquals(baseError + "Enabled", expected.isEnabled(),
actual.isEnabled());
-
assertEquals(baseError + "Text", expected.getText(), actual.getText());
assertEquals(baseError + "Description", expected.getDescription(),
actual.getDescription());
assertEquals(baseError + "Style Name", expected.getStyleName(),
actual.getStyleName());
+ assertEquals(baseError + "Content Mode", expected.getContentMode(),
+ actual.getContentMode());
if (expected.getIcon() != null) {
assertNotNull(baseError + "Icon was null", actual.getIcon());
diff --git a/shared/src/main/java/com/vaadin/shared/ui/menubar/MenuBarConstants.java b/shared/src/main/java/com/vaadin/shared/ui/menubar/MenuBarConstants.java
index 2d211824e6..4f5fcb72ff 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/menubar/MenuBarConstants.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/menubar/MenuBarConstants.java
@@ -24,6 +24,8 @@ public class MenuBarConstants implements Serializable {
@Deprecated
public static final String ATTRIBUTE_ITEM_DESCRIPTION = "description";
@Deprecated
+ public static final String ATTRIBUTE_ITEM_CONTENT_MODE = "contentmode";
+ @Deprecated
public static final String ATTRIBUTE_ITEM_ICON = "icon";
@Deprecated
public static final String ATTRIBUTE_ITEM_DISABLED = "disabled";
diff --git a/uitest/src/main/java/com/vaadin/tests/elements/menubar/MenuBarUI.java b/uitest/src/main/java/com/vaadin/tests/elements/menubar/MenuBarUI.java
index a78eae271c..d56ead71e9 100644
--- a/uitest/src/main/java/com/vaadin/tests/elements/menubar/MenuBarUI.java
+++ b/uitest/src/main/java/com/vaadin/tests/elements/menubar/MenuBarUI.java
@@ -16,6 +16,7 @@
package com.vaadin.tests.elements.menubar;
import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.ContentMode;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.MenuBar.Command;
@@ -38,8 +39,11 @@ public class MenuBarUI extends AbstractTestUI {
String secondaryLevelItemSuffix) {
MenuBar menuBar = new MenuBar();
MenuItem file = menuBar.addItem("File" + topLevelItemSuffix, null);
- file.addItem("Open" + secondaryLevelItemSuffix, new MenuBarCommand());
- file.addItem("Save" + secondaryLevelItemSuffix, new MenuBarCommand());
+ file.addItem("Open" + secondaryLevelItemSuffix, new MenuBarCommand())
+ .setDescription("<b>Preformatted</b>\ndescription");
+ file.addItem("Save" + secondaryLevelItemSuffix, new MenuBarCommand())
+ .setDescription("plain description,\n <b>HTML</b> is visible",
+ ContentMode.TEXT);
file.addItem("Save As.." + secondaryLevelItemSuffix,
new MenuBarCommand());
file.addSeparator();
@@ -52,7 +56,9 @@ public class MenuBarUI extends AbstractTestUI {
new MenuBarCommand());
file.addSeparator();
- file.addItem("Exit" + secondaryLevelItemSuffix, new MenuBarCommand());
+ file.addItem("Exit" + secondaryLevelItemSuffix, new MenuBarCommand())
+ .setDescription("<b>HTML</b><br/>description",
+ ContentMode.HTML);
MenuItem edit = menuBar.addItem("Edit" + topLevelItemSuffix, null);
edit.addItem("Copy" + secondaryLevelItemSuffix, new MenuBarCommand());
diff --git a/uitest/src/test/java/com/vaadin/tests/elements/menubar/MenuBarUITest.java b/uitest/src/test/java/com/vaadin/tests/elements/menubar/MenuBarUITest.java
index dc960f4d49..0fd42421a9 100644
--- a/uitest/src/test/java/com/vaadin/tests/elements/menubar/MenuBarUITest.java
+++ b/uitest/src/test/java/com/vaadin/tests/elements/menubar/MenuBarUITest.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.tests.elements.menubar;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -121,6 +122,22 @@ public class MenuBarUITest extends MultiBrowserTest {
assertTrue(isItemVisible("Open"));
}
+ @Test
+ public void testMenuItemTooltips() {
+ MenuBarElement first = $(MenuBarElement.class).first();
+ first.clickItem("File");
+ assertTooltip("Open", "<b>Preformatted</b>\ndescription");
+ assertTooltip("Save", "plain description, <b>HTML</b> is visible");
+ assertTooltip("Exit", "HTML\ndescription");
+ }
+
+ private void assertTooltip(String menuItem, String expectedTooltipText) {
+ testBenchElement(getMenuElement(menuItem)).showTooltip();
+ assertEquals("Unexpected tooltip when hovering '" + menuItem + "'",
+ expectedTooltipText,
+ findElement(By.className("v-tooltip-text")).getText());
+ }
+
private boolean isItemVisible(String item) {
for (WebElement webElement : getItemCaptions()) {
try {