Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago Improve VMenuBar click handling logic (#11356)
* Improve VMenuBar click handling logic
During `updateFromUIDL` inside MenuBarConnector we empty and re-instantiate the components of MenuBar. When we are modifying the Menubar from the BlurEventListener of another component, we ,by this, remove widgets, therefore clickEvent is not fired and the action of the MenuItem is not proceed as a result. (The BlurEvent is fired before the click event in the chain of events. )
To improve the situation, we catch onMouseDown event , which is fired before BlurEvent,by assigning mouseDown flag to true. Then if no click event has yet happened, we delay the execution of update inside `updateFromUIDL` by default 500 ms. Then if click event occurs, it proceeds normally. The time can be increased/decreased using setter.
There is no delay, if we are clicking on the MenuBar as usual or no Blur listener is set.
This change allows setting descriptions
* Remove accidentally committed comment
* Don't update the state on the getDelayMs call 5 years ago |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /*
- * Copyright 2000-2018 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.client.ui.menubar;
-
- 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.google.gwt.user.client.Timer;
- import com.vaadin.client.ApplicationConnection;
- import com.vaadin.client.Paintable;
- import com.vaadin.client.TooltipInfo;
- import com.vaadin.client.UIDL;
- import com.vaadin.client.annotations.OnStateChange;
- import com.vaadin.client.ui.AbstractComponentConnector;
- import com.vaadin.client.ui.Icon;
- import com.vaadin.client.ui.SimpleManagedLayout;
- import com.vaadin.client.ui.VMenuBar;
- import com.vaadin.shared.ui.ComponentStateUtil;
- import com.vaadin.shared.ui.Connect;
- import com.vaadin.shared.ui.menubar.MenuBarConstants;
- import com.vaadin.shared.ui.menubar.MenuBarState;
-
- @Connect(com.vaadin.ui.MenuBar.class)
- public class MenuBarConnector extends AbstractComponentConnector
- implements Paintable, SimpleManagedLayout {
-
- /**
- * This method must be implemented to update the client-side component from
- * UIDL data received from server.
- *
- * This method is called when the page is loaded for the first time, and
- * every time UI changes in the component are received from the server.
- */
- @Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- if (!isRealUpdate(uidl)) {
- return;
- }
-
- VMenuBar widget = getWidget();
- widget.htmlContentAllowed = uidl
- .hasAttribute(MenuBarConstants.HTML_CONTENT_ALLOWED);
-
- widget.openRootOnHover = uidl
- .getBooleanAttribute(MenuBarConstants.OPEN_ROOT_MENU_ON_HOWER);
-
- widget.enabled = isEnabled();
-
- // For future connections
- widget.client = client;
- widget.uidlId = uidl.getId();
- Timer timer = new Timer() {
-
- @Override
- public void run() {
- // Empty the menu every time it receives new information
- if (!widget.getItems().isEmpty()) {
- widget.clearItems();
- }
-
- UIDL options = uidl.getChildUIDL(0);
-
- if (null != getState()
- && !ComponentStateUtil.isUndefinedWidth(getState())) {
- UIDL moreItemUIDL = options.getChildUIDL(0);
- StringBuilder itemHTML = new StringBuilder();
-
- if (moreItemUIDL.hasAttribute("icon")) {
- Icon icon = client.getIcon(
- moreItemUIDL.getStringAttribute("icon"));
- if (icon != null) {
- itemHTML.append(icon.getElement().getString());
- }
- }
-
- String moreItemText = moreItemUIDL
- .getStringAttribute("text");
- if ("".equals(moreItemText)) {
- moreItemText = "►";
- }
- itemHTML.append(moreItemText);
-
- widget.moreItem = GWT.create(VMenuBar.CustomMenuItem.class);
- widget.moreItem.setHTML(itemHTML.toString());
- widget.moreItem.setCommand(VMenuBar.emptyCommand);
-
- widget.collapsedRootItems = new VMenuBar(true, widget);
- widget.moreItem.setSubMenu(widget.collapsedRootItems);
- widget.moreItem.addStyleName(
- widget.getStylePrimaryName() + "-more-menuitem");
- }
-
- UIDL uidlItems = uidl.getChildUIDL(1);
- Iterator<Object> itr = uidlItems.iterator();
- Stack<Iterator<Object>> iteratorStack = new Stack<>();
- Stack<VMenuBar> menuStack = new Stack<>();
- VMenuBar currentMenu = widget;
-
- while (itr.hasNext()) {
- UIDL item = (UIDL) itr.next();
- VMenuBar.CustomMenuItem currentItem = null;
-
- final int itemId = item.getIntAttribute("id");
-
- boolean itemHasCommand = item.hasAttribute("command");
- boolean itemIsCheckable = item
- .hasAttribute(MenuBarConstants.ATTRIBUTE_CHECKED);
-
- String itemHTML = widget.buildItemHTML(item);
-
- Command cmd = null;
- if (!item.hasAttribute("separator")) {
- if (itemHasCommand || itemIsCheckable) {
- // Construct a command that fires onMenuClick(int)
- // with the
- // item's id-number
- cmd = () -> widget.hostReference
- .onMenuClick(itemId);
- }
- }
-
- currentItem = currentMenu.addItem(itemHTML, cmd);
- currentItem.setId("" + itemId);
- currentItem.updateFromUIDL(item, client);
-
- String domId = getState().id;
- if (domId != null && !domId.isEmpty()) {
- currentItem.getElement().setId(domId+"-"+itemId);
- }
-
- if (item.getChildCount() > 0) {
- menuStack.push(currentMenu);
- iteratorStack.push(itr);
- itr = item.iterator();
- 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)
- if (ComponentStateUtil.hasStyles(getState())) {
- for (String style : getState().styles) {
- currentMenu.addStyleDependentName(style);
- }
- }
- currentItem.setSubMenu(currentMenu);
- }
-
- while (!itr.hasNext() && !iteratorStack.empty()) {
- boolean hasCheckableItem = false;
- for (VMenuBar.CustomMenuItem menuItem : currentMenu
- .getItems()) {
- hasCheckableItem = hasCheckableItem
- || menuItem.isCheckable();
- }
- if (hasCheckableItem) {
- currentMenu.addStyleDependentName("check-column");
- } else {
- currentMenu
- .removeStyleDependentName("check-column");
- }
-
- itr = iteratorStack.pop();
- currentMenu = menuStack.pop();
- }
- }
- }
- };
- getLayoutManager().setNeedsHorizontalLayout(MenuBarConnector.this);
- if (widget.mouseDownPressed) {
- timer.schedule(getState().delayMs);
- widget.mouseDownPressed = false;
- } else {
- timer.run();
- }
- }
-
- @Override
- public VMenuBar getWidget() {
- return (VMenuBar) super.getWidget();
- }
-
- @Override
- public MenuBarState getState() {
- return (MenuBarState) super.getState();
- }
-
- @Override
- 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()) {
-
- VMenuBar.CustomMenuItem item = getWidget()
- .getMenuItemWithElement(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;
- }
-
- @Override
- public boolean hasTooltip() {
- /*
- * Item tooltips are not processed until updateFromUIDL, so we can't be
- * sure that there are no tooltips during onStateChange when this method
- * is used.
- */
- return true;
- }
-
- @OnStateChange("enabled")
- void updateEnabled() {
- if (getState().enabled) {
- getWidget().getElement().removeAttribute("aria-disabled");
- } else {
- getWidget().getElement().setAttribute("aria-disabled", "true");
- }
- }
-
- @OnStateChange("tabIndex")
- void updateTabIndex() {
- getWidget().getElement().setAttribute("tabindex",
- String.valueOf(getState().tabIndex));
- }
- }
|