You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MenuBarConnector.java 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright 2000-2018 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client.ui.menubar;
  17. import java.util.Iterator;
  18. import java.util.Stack;
  19. import com.google.gwt.core.client.GWT;
  20. import com.google.gwt.dom.client.Element;
  21. import com.google.gwt.user.client.Command;
  22. import com.google.gwt.user.client.Timer;
  23. import com.vaadin.client.ApplicationConnection;
  24. import com.vaadin.client.Paintable;
  25. import com.vaadin.client.TooltipInfo;
  26. import com.vaadin.client.UIDL;
  27. import com.vaadin.client.ui.AbstractComponentConnector;
  28. import com.vaadin.client.ui.Icon;
  29. import com.vaadin.client.ui.SimpleManagedLayout;
  30. import com.vaadin.client.ui.VMenuBar;
  31. import com.vaadin.shared.ui.ComponentStateUtil;
  32. import com.vaadin.shared.ui.Connect;
  33. import com.vaadin.shared.ui.menubar.MenuBarConstants;
  34. import com.vaadin.shared.ui.menubar.MenuBarState;
  35. @Connect(com.vaadin.ui.MenuBar.class)
  36. public class MenuBarConnector extends AbstractComponentConnector
  37. implements Paintable, SimpleManagedLayout {
  38. /**
  39. * This method must be implemented to update the client-side component from
  40. * UIDL data received from server.
  41. *
  42. * This method is called when the page is loaded for the first time, and
  43. * every time UI changes in the component are received from the server.
  44. */
  45. @Override
  46. public void updateFromUIDL(final UIDL uidl, final ApplicationConnection client) {
  47. if (!isRealUpdate(uidl)) {
  48. return;
  49. }
  50. getWidget().htmlContentAllowed = uidl
  51. .hasAttribute(MenuBarConstants.HTML_CONTENT_ALLOWED);
  52. getWidget().openRootOnHover = uidl
  53. .getBooleanAttribute(MenuBarConstants.OPEN_ROOT_MENU_ON_HOWER);
  54. getWidget().enabled = isEnabled();
  55. // For future connections
  56. getWidget().client = client;
  57. getWidget().uidlId = uidl.getId();
  58. Timer timer = new Timer() {
  59. @Override
  60. public void run() {
  61. // Empty the menu every time it receives new information
  62. if (!getWidget().getItems().isEmpty()) {
  63. getWidget().clearItems();
  64. }
  65. UIDL options = uidl.getChildUIDL(0);
  66. if (null != getState() && !ComponentStateUtil.isUndefinedWidth(getState())) {
  67. UIDL moreItemUIDL = options.getChildUIDL(0);
  68. StringBuffer itemHTML = new StringBuffer();
  69. if (moreItemUIDL.hasAttribute("icon")) {
  70. Icon icon = client.getIcon(moreItemUIDL.getStringAttribute("icon"));
  71. if (icon != null) {
  72. itemHTML.append(icon.getElement().getString());
  73. }
  74. }
  75. String moreItemText = moreItemUIDL.getStringAttribute("text");
  76. if ("".equals(moreItemText)) {
  77. moreItemText = "►";
  78. }
  79. itemHTML.append(moreItemText);
  80. getWidget().moreItem = GWT.create(VMenuBar.CustomMenuItem.class);
  81. getWidget().moreItem.setHTML(itemHTML.toString());
  82. getWidget().moreItem.setCommand(VMenuBar.emptyCommand);
  83. getWidget().collapsedRootItems = new VMenuBar(true,
  84. getWidget());
  85. getWidget().moreItem.setSubMenu(getWidget().collapsedRootItems);
  86. getWidget().moreItem.addStyleName(
  87. getWidget().getStylePrimaryName() + "-more-menuitem");
  88. }
  89. UIDL uidlItems = uidl.getChildUIDL(1);
  90. Iterator<Object> itr = uidlItems.getChildIterator();
  91. Stack<Iterator<Object>> iteratorStack = new Stack<Iterator<Object>>();
  92. Stack<VMenuBar> menuStack = new Stack<VMenuBar>();
  93. VMenuBar currentMenu = getWidget();
  94. while (itr.hasNext()) {
  95. UIDL item = (UIDL) itr.next();
  96. VMenuBar.CustomMenuItem currentItem = null;
  97. final int itemId = item.getIntAttribute("id");
  98. boolean itemHasCommand = item.hasAttribute("command");
  99. boolean itemIsCheckable = item.hasAttribute(MenuBarConstants.ATTRIBUTE_CHECKED);
  100. String itemHTML = getWidget().buildItemHTML(item);
  101. Command cmd = null;
  102. if (!item.hasAttribute("separator")) {
  103. if (itemHasCommand || itemIsCheckable) {
  104. // Construct a command that fires onMenuClick(int) with the
  105. // item's id-number
  106. cmd = new Command() {
  107. @Override
  108. public void execute() {
  109. getWidget().hostReference.onMenuClick(itemId);
  110. }
  111. };
  112. }
  113. }
  114. currentItem = currentMenu.addItem(itemHTML.toString(), cmd);
  115. currentItem.updateFromUIDL(item, client);
  116. if (item.getChildCount() > 0) {
  117. menuStack.push(currentMenu);
  118. iteratorStack.push(itr);
  119. itr = item.getChildIterator();
  120. currentMenu = new VMenuBar(true, currentMenu);
  121. client.getVTooltip().connectHandlersToWidget(currentMenu);
  122. // this is the top-level style that also propagates to items -
  123. // any item specific styles are set above in
  124. // currentItem.updateFromUIDL(item, client)
  125. if (ComponentStateUtil.hasStyles(getState())) {
  126. for (String style : getState().styles) {
  127. currentMenu.addStyleDependentName(style);
  128. }
  129. }
  130. currentItem.setSubMenu(currentMenu);
  131. }
  132. while (!itr.hasNext() && !iteratorStack.empty()) {
  133. boolean hasCheckableItem = false;
  134. for (VMenuBar.CustomMenuItem menuItem : currentMenu.getItems()) {
  135. hasCheckableItem = hasCheckableItem || menuItem.isCheckable();
  136. }
  137. if (hasCheckableItem) {
  138. currentMenu.addStyleDependentName("check-column");
  139. } else {
  140. currentMenu.removeStyleDependentName("check-column");
  141. }
  142. itr = iteratorStack.pop();
  143. currentMenu = menuStack.pop();
  144. }
  145. } // while
  146. }
  147. };
  148. getLayoutManager().setNeedsHorizontalLayout(this);
  149. if (getWidget().mouseDownPressed) {
  150. timer.schedule(getState().delayMs);
  151. getWidget().mouseDownPressed = false;
  152. } else {
  153. timer.run();
  154. }
  155. }// updateFromUIDL
  156. @Override
  157. public VMenuBar getWidget() {
  158. return (VMenuBar) super.getWidget();
  159. }
  160. @Override
  161. public MenuBarState getState() {
  162. return (MenuBarState) super.getState();
  163. }
  164. @Override
  165. public void layout() {
  166. getWidget().iLayout();
  167. }
  168. @Override
  169. public TooltipInfo getTooltipInfo(Element element) {
  170. TooltipInfo info = null;
  171. // Check content of widget to find tooltip for element
  172. if (element != getWidget().getElement()) {
  173. VMenuBar.CustomMenuItem item = getWidget()
  174. .getMenuItemWithElement(element);
  175. if (item != null) {
  176. info = item.getTooltip();
  177. }
  178. }
  179. // Use default tooltip if nothing found from DOM three
  180. if (info == null) {
  181. info = super.getTooltipInfo(element);
  182. }
  183. return info;
  184. }
  185. @Override
  186. public boolean hasTooltip() {
  187. /*
  188. * Item tooltips are not processed until updateFromUIDL, so we can't be
  189. * sure that there are no tooltips during onStateChange when this method
  190. * is used.
  191. */
  192. return true;
  193. }
  194. }