]> source.dussan.org Git - vaadin-framework.git/commitdiff
#6440: mode to open root nodes by mouse over only
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 13 Apr 2011 11:20:07 +0000 (11:20 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 13 Apr 2011 11:20:07 +0000 (11:20 +0000)
svn changeset:18266/svn branch:6.6

src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
src/com/vaadin/ui/MenuBar.java
tests/src/com/vaadin/tests/components/menubar/MenuBarTest.java

index 56b7d198e062952f8483f167a42d0d7e9aceb55e..c609eb846b5c554085f2195264e9efbb8a9cb59a 100644 (file)
@@ -8,8 +8,10 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Stack;
 
+import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.dom.client.NodeList;
 import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.event.dom.client.FocusEvent;
@@ -25,6 +27,7 @@ import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.ui.HasHTML;
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.RootPanel;
@@ -36,6 +39,7 @@ 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.VConsole;
 import com.vaadin.terminal.gwt.client.VTooltip;
 
 public class VMenuBar extends SimpleFocusablePanel implements Paintable,
@@ -63,6 +67,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
     // associated
     protected static final Command emptyCommand = null;
 
+    public static final String OPEN_ROOT_MENU_ON_HOWER = "ormoh";
+
     /** Widget fields **/
     protected boolean subMenu;
     protected ArrayList<CustomMenuItem> items;
@@ -85,6 +91,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
                 }
             });
 
+    private boolean openRootOnHover;
+
     public VMenuBar() {
         // Create an empty horizontal menubar
         this(false, null);
@@ -182,6 +190,9 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
         if (client.updateComponent(this, uidl, true)) {
             return;
         }
+
+        openRootOnHover = uidl.getBooleanAttribute(OPEN_ROOT_MENU_ON_HOWER);
+
         enabled = !uidl.getBooleanAttribute("disabled");
 
         // For future connections
@@ -478,6 +489,8 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
                 break;
 
             case Event.ONMOUSEOVER:
+                LazyCloser.cancelClosing();
+
                 if (isEnabled() && targetItem.isEnabled()) {
                     itemOver(targetItem);
                 }
@@ -485,6 +498,7 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
 
             case Event.ONMOUSEOUT:
                 itemOut(targetItem);
+                LazyCloser.schedule();
                 break;
             }
         } else if (subMenu && DOM.eventGetType(e) == Event.ONCLICK && subMenu) {
@@ -542,8 +556,12 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
      * @param item
      */
     public void itemOver(CustomMenuItem item) {
-        if ((subMenu || menuVisible) && !item.isSeparator()) {
+        if ((openRootOnHover || subMenu || menuVisible) && !item.isSeparator()) {
             setSelected(item);
+            if (!subMenu && openRootOnHover && !menuVisible) {
+                menuVisible = true; // start opening menus
+                LazyCloser.prepare(this);
+            }
         }
 
         if (menuVisible && visibleChildMenu != item.getSubMenu()
@@ -571,6 +589,49 @@ public class VMenuBar extends SimpleFocusablePanel implements Paintable,
         }
     }
 
+    /**
+     * Used to autoclose submenus when they the menu is in a mode which opens
+     * root menus on mouse hover.
+     */
+    private static class LazyCloser extends Timer {
+        static LazyCloser INSTANCE;
+        private VMenuBar activeRoot;
+
+        @Override
+        public void run() {
+            activeRoot.hideChildren();
+            activeRoot.setSelected(null);
+            activeRoot.menuVisible = false;
+            activeRoot = null;
+        }
+
+        public static void cancelClosing() {
+            if (INSTANCE != null) {
+                INSTANCE.cancel();
+            }
+        }
+
+        public static void prepare(VMenuBar vMenuBar) {
+            if (INSTANCE == null) {
+                INSTANCE = new LazyCloser();
+            }
+            if (INSTANCE.activeRoot == vMenuBar) {
+                INSTANCE.cancel();
+            } else if (INSTANCE.activeRoot != null) {
+                INSTANCE.cancel();
+                INSTANCE.run();
+            }
+            INSTANCE.activeRoot = vMenuBar;
+        }
+
+        public static void schedule() {
+            if (INSTANCE != null && INSTANCE.activeRoot != null) {
+                INSTANCE.schedule(750);
+            }
+        }
+
+    }
+
     /**
      * Shows the child menu of an item. The caller must ensure that the item has
      * a submenu.
index b7da82675e0d0dcefcfbc71f060f4c05c44f237f..d629e912c92c368c10f901bb45effc08dcdda2f4 100644 (file)
@@ -49,6 +49,8 @@ public class MenuBar extends AbstractComponent {
 
     private MenuItem moreItem;
 
+    private boolean openRootOnHover;
+
     /** Paint (serialise) the component for the client. */
     @Override
     public void paintContent(PaintTarget target) throws PaintException {
@@ -56,6 +58,8 @@ public class MenuBar extends AbstractComponent {
         // Superclass writes any common attributes in the paint target.
         super.paintContent(target);
 
+        target.addAttribute(VMenuBar.OPEN_ROOT_MENU_ON_HOWER, openRootOnHover);
+
         target.startTag("options");
 
         if (submenuIcon != null) {
@@ -364,6 +368,31 @@ public class MenuBar extends AbstractComponent {
     public MenuItem getMoreMenuItem() {
         return moreItem;
     }
+    
+    /**
+     * Using this method menubar can be put into a special mode where the root
+     * level menu opens without clicking on the menu. In this mode the menu also
+     * closes itself if the mouse is moved out of the opened menu.
+     * 
+     * @param b
+     */
+    public void setOpenRootOnHover(boolean b) {
+        if(b != openRootOnHover) {
+            openRootOnHover = b;
+            requestRepaint();
+        }
+    }
+
+    /**
+     * Detects whether the menubar is in a mode where root menus are
+     * automatically opened when the mouse cursor is moved over the menubar.
+     * Normally root menu opens only by clicking on the menu.
+     * 
+     * @return true if the root menus open without click
+     */
+    public boolean isOpenRootOnHover() {
+        return openRootOnHover;
+    }
 
     /**
      * This interface contains the layer for menu commands of the
index 1b11c24f7881a64842ce3dd011e23c2acbf2e952..2a84b1d0fa5868486cbee224d6bc0c3f58eb284f 100644 (file)
@@ -19,6 +19,7 @@ public class MenuBarTest extends AbstractComponentTest<MenuBar> {
     private int subLevels = -1;\r
     private int subMenuDensity = -1;\r
     private Integer subMenuSeparatorDensity = null;\r
+    private Boolean openRootMenuOnHover = false;\r
     private int iconInterval = -1;\r
     private Integer iconSize;\r
     private Integer disabledDensity;\r
@@ -38,6 +39,9 @@ public class MenuBarTest extends AbstractComponentTest<MenuBar> {
         createSubMenuDensitySelect(CATEGORY_MENU_ITEMS);\r
         createSubMenuSeparatorDensitySelect(CATEGORY_MENU_ITEMS);\r
 \r
+        createBooleanAction("OpenRootMenuOnHover", CATEGORY_FEATURES,\r
+                openRootMenuOnHover, setOpenRootOnHover);\r
+\r
         createMenuItemIconIntervalSelect(CATEGORY_MENU_ITEM_STATES);\r
         createMenuIconsSizeSelect(CATEGORY_MENU_ITEM_STATES);\r
         createMenuItemDisabledDensitySelect(CATEGORY_MENU_ITEM_STATES);\r
@@ -185,6 +189,15 @@ public class MenuBarTest extends AbstractComponentTest<MenuBar> {
         }\r
     };\r
 \r
+    private Command<MenuBar, Boolean> setOpenRootOnHover = new Command<MenuBar, Boolean>() {\r
+\r
+        public void execute(MenuBar c, Boolean value, Object data) {\r
+            openRootMenuOnHover = value;\r
+            c.setOpenRootOnHover(value);\r
+        }\r
+\r
+    };\r
+\r
     private Command<MenuBar, Integer> selectIcon = new Command<MenuBar, Integer>() {\r
 \r
         public void execute(MenuBar c, Integer value, Object data) {\r