From 6dec84ebe934f001488797c2b90c347635b54b6f Mon Sep 17 00:00:00 2001 From: Sami Viitanen Date: Fri, 29 Jun 2012 12:07:30 +0300 Subject: [PATCH] Made MenuBar item tooltips work again (#8425) --- src/com/vaadin/terminal/gwt/client/Util.java | 28 ++++++-- .../terminal/gwt/client/ui/VOverlay.java | 28 ++++++++ .../client/ui/menubar/MenuBarConnector.java | 25 ++++++++ .../gwt/client/ui/menubar/VMenuBar.java | 64 +++++++++++++++---- 4 files changed, 125 insertions(+), 20 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index 00bf144803..4687512b47 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -29,6 +29,7 @@ import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; import com.vaadin.terminal.gwt.client.communication.MethodInvocation; +import com.vaadin.terminal.gwt.client.ui.VOverlay; public class Util { @@ -642,12 +643,16 @@ public class Util { */ public static ComponentConnector getConnectorForElement( ApplicationConnection client, Widget parent, Element element) { + + Element browseElement = element; Element rootElement = parent.getElement(); - while (element != null && element != rootElement) { + + while (browseElement != null && browseElement != rootElement) { ComponentConnector connector = ConnectorMap.get(client) - .getConnector(element); + .getConnector(browseElement); + if (connector == null) { - String ownerPid = VCaption.getCaptionOwnerPid(element); + String ownerPid = VCaption.getCaptionOwnerPid(browseElement); if (ownerPid != null) { connector = (ComponentConnector) ConnectorMap.get(client) .getConnector(ownerPid); @@ -656,17 +661,26 @@ public class Util { if (connector != null) { // check that inside the rootElement - while (element != null && element != rootElement) { - element = (Element) element.getParentElement(); + while (browseElement != null && browseElement != rootElement) { + browseElement = (Element) browseElement.getParentElement(); } - if (element != rootElement) { + if (browseElement != rootElement) { return null; } else { return connector; } } - element = (Element) element.getParentElement(); + browseElement = (Element) browseElement.getParentElement(); + } + + if (browseElement == null) { + // Element is possibly inside a VOverlay + VOverlay overlay = findWidget(element, VOverlay.class); + if (overlay != null && overlay.getOwner() != null) { + return getConnectorForElement(client, RootPanel.get(), overlay + .getOwner().getElement()); + } } return null; diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java b/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java index df655ef959..77639c0c3f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java @@ -14,6 +14,7 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.BrowserInfo; /** @@ -45,6 +46,12 @@ public class VOverlay extends PopupPanel implements CloseHandler { */ private Element shadow; + /* + * Creator of VOverlow (widget that made the instance, not the layout + * parent) + */ + private Widget owner; + /** * The HTML snippet that is used to render the actual shadow. In consists of * nine different DIV-elements with the following class names: @@ -414,4 +421,25 @@ public class VOverlay extends PopupPanel implements CloseHandler { protected boolean isSinkShadowEvents() { return sinkShadowEvents; } + + /** + * Get owner (Widget that made this VOverlay, not the layout parent) of + * VOverlay + * + * @return Owner (creator) or null if not defined + */ + public Widget getOwner() { + return owner; + } + + /** + * Set owner (Widget that made this VOverlay, not the layout parent) of + * VOverlay + * + * @param owner + * Owner (creator) of VOverlay + */ + public void setOwner(Widget owner) { + this.owner = owner; + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java b/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java index d1f77aa0ff..a18e4d734a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/menubar/MenuBarConnector.java @@ -7,9 +7,11 @@ import java.util.Iterator; import java.util.Stack; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.Command; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Paintable; +import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; @@ -120,6 +122,7 @@ public class MenuBarConnector extends AbstractComponentConnector implements iteratorStack.push(itr); itr = item.getChildIterator(); currentMenu = new VMenuBar(true, currentMenu); + client.getVTooltip().connectHandlersToWidget(currentMenu); // this is the top-level style that also propagates to items - // any item specific styles are set above in // currentItem.updateFromUIDL(item, client) @@ -160,4 +163,26 @@ public class MenuBarConnector extends AbstractComponentConnector implements public void layout() { getWidget().iLayout(); } + + @Override + public TooltipInfo getTooltipInfo(Element element) { + TooltipInfo info = null; + + // Check content of widget to find tooltip for element + if (element != getWidget().getElement()) { + + CustomMenuItem item = getWidget().getMenuItemWithElement( + (com.google.gwt.user.client.Element) element); + if (item != null) { + info = item.getTooltip(); + } + } + + // Use default tooltip if nothing found from DOM three + if (info == null) { + info = super.getTooltipInfo(element); + } + + return info; + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java index 821fa5032c..6133b7d80c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java +++ b/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java @@ -33,6 +33,7 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.LayoutManager; +import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.ui.Icon; @@ -87,8 +88,6 @@ public class VMenuBar extends SimpleFocusablePanel implements boolean enabled = true; - private String width = "notinited"; - private VLazyExecutor iconLoadedExecutioner = new VLazyExecutor(100, new ScheduledCommand() { @@ -524,6 +523,22 @@ public class VMenuBar extends SimpleFocusablePanel implements final int shadowSpace = 10; popup = new VOverlay(true, false, true); + + // Setting owner and handlers to support tooltips. Needed for tooltip + // handling of overlay widgets (will direct queries to parent menu) + if (parentMenu == null) { + popup.setOwner(this); + } else { + VMenuBar parent = parentMenu; + while (parent.getParentMenu() != null) { + parent = parent.getParentMenu(); + } + popup.setOwner(parent); + } + if (client != null) { + client.getVTooltip().connectHandlersToWidget(popup); + } + popup.setStyleName(CLASSNAME + "-popup"); popup.setWidget(item.getSubMenu()); popup.addCloseHandler(this); @@ -707,9 +722,7 @@ public class VMenuBar extends SimpleFocusablePanel implements * A class to hold information on menu items * */ - protected static class CustomMenuItem extends Widget implements HasHTML { - - private ApplicationConnection client; + public static class CustomMenuItem extends Widget implements HasHTML { protected String html = null; protected Command command = null; @@ -719,6 +732,7 @@ public class VMenuBar extends SimpleFocusablePanel implements protected boolean isSeparator = false; protected boolean checkable = false; protected boolean checked = false; + protected String description = null; /** * Default menu item {@link Widget} constructor for GWT.create(). @@ -884,7 +898,6 @@ public class VMenuBar extends SimpleFocusablePanel implements } public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; setSeparator(uidl.hasAttribute("separator")); setEnabled(!uidl.hasAttribute(ATTRIBUTE_ITEM_DISABLED)); @@ -903,17 +916,18 @@ public class VMenuBar extends SimpleFocusablePanel implements addStyleDependentName(itemStyle); } + if (uidl.hasAttribute(ATTRIBUTE_ITEM_DESCRIPTION)) { + description = uidl + .getStringAttribute(ATTRIBUTE_ITEM_DESCRIPTION); + } } - private VMenuBar findRootMenu() { - VMenuBar menubar = getParentMenu(); - - // Traverse up until root menu is found - while (menubar.getParentMenu() != null) { - menubar = menubar.getParentMenu(); + public TooltipInfo getTooltip() { + if (description == null) { + return null; } - return menubar; + return new TooltipInfo(description); } /** @@ -1405,4 +1419,28 @@ public class VMenuBar extends SimpleFocusablePanel implements return null; } + /** + * Get menu item with given DOM element + * + * @param element + * Element used in search + * @return Menu item or null if not found + */ + public CustomMenuItem getMenuItemWithElement(Element element) { + for (int i = 0; i < items.size(); i++) { + CustomMenuItem item = items.get(i); + if (DOM.isOrHasChild(item.getElement(), element)) { + return item; + } + + if (item.getSubMenu() != null) { + item = item.getSubMenu().getMenuItemWithElement(element); + if (item != null) { + return item; + } + } + } + + return null; + } } -- 2.39.5