Adds an option to MenuBar that prevents it from stealing keyboard focus on hover. SuggestBox now uses this option.
http://gwt-code-reviews.appspot.com/132816/show
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7443 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java
index bb2ddcf..5ee9e29 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -191,6 +191,7 @@
private MenuItem selectedItem;
private MenuBar shownChildMenu;
private boolean vertical, autoOpen;
+ private boolean focusOnHover = true;
/**
* Creates an empty horizontal menu bar.
@@ -481,6 +482,16 @@
}
/**
+ * Check whether or not this widget will steal keyboard focus when the mouse
+ * hovers over it.
+ *
+ * @return true if enabled, false if disabled
+ */
+ public boolean isFocusOnHoverEnabled() {
+ return focusOnHover;
+ }
+
+ /**
* Moves the menu selection down to the next item. If there is no selection,
* selects the first item. If there are no items at all, does nothing.
*/
@@ -496,7 +507,7 @@
&& !selectedItem.getSubMenu().getItems().isEmpty()
&& (shownChildMenu == null || shownChildMenu.getSelectedItem() == null)) {
if (shownChildMenu == null) {
- doItemAction(selectedItem, false);
+ doItemAction(selectedItem, false, true);
}
selectedItem.getSubMenu().focus();
} else if (parentMenu != null) {
@@ -535,7 +546,7 @@
FocusPanel.impl.focus(getElement());
// Fire an item's command when the user clicks on it.
if (item != null) {
- doItemAction(item, true);
+ doItemAction(item, true, true);
}
break;
}
@@ -597,7 +608,7 @@
break;
case KeyCodes.KEY_ENTER:
if (!selectFirstItemIfNoneSelected()) {
- doItemAction(selectedItem, true);
+ doItemAction(selectedItem, true, true);
eatEvent(event);
}
break;
@@ -623,7 +634,7 @@
// When the menu popup closes, remember that no item is
// currently showing a popup menu.
- onHide();
+ onHide(autoClosed);
CloseEvent.fire(MenuBar.this, sender);
shownChildMenu = null;
popup = null;
@@ -720,6 +731,18 @@
}
/**
+ * Enable or disable auto focus when the mouse hovers over the MenuBar. This
+ * allows the MenuBar to respond to keyboard events without the user having to
+ * click on it, but it will steal focus from other elements on the page.
+ * Enabled by default.
+ *
+ * @param enabled true to enable, false to disable
+ */
+ public void setFocusOnHoverEnabled(boolean enabled) {
+ focusOnHover = enabled;
+ }
+
+ /**
* Returns a list containing the <code>MenuItem</code> objects in the menu
* bar. If there are no items in the menu bar, then an empty <code>List</code>
* object will be returned.
@@ -787,7 +810,7 @@
* <code>true</code> if the item's command should be fired, <code>false</code>
* otherwise.
*/
- void doItemAction(final MenuItem item, boolean fireCommand) {
+ void doItemAction(final MenuItem item, boolean fireCommand, boolean focus) {
// Ensure that the item is selected.
selectItem(item);
@@ -803,7 +826,7 @@
// hide any open submenus of this item
if (shownChildMenu != null) {
- shownChildMenu.onHide();
+ shownChildMenu.onHide(focus);
popup.hide();
shownChildMenu = null;
selectItem(null);
@@ -814,19 +837,19 @@
openPopup(item);
} else if (item.getSubMenu() != shownChildMenu) {
// close the other submenu and open this one
- shownChildMenu.onHide();
+ shownChildMenu.onHide(focus);
popup.hide();
openPopup(item);
} else if (fireCommand && !autoOpen) {
// close this submenu
- shownChildMenu.onHide();
+ shownChildMenu.onHide(focus);
popup.hide();
shownChildMenu = null;
selectItem(item);
}
} else if (autoOpen && shownChildMenu != null) {
// close submenu
- shownChildMenu.onHide();
+ shownChildMenu.onHide(focus);
popup.hide();
shownChildMenu = null;
}
@@ -844,7 +867,7 @@
// Style the item selected when the mouse enters.
selectItem(item);
- if (focus) {
+ if (focus && focusOnHover) {
focus();
}
@@ -853,7 +876,7 @@
// when the mouse enters.
if (item != null) {
if ((shownChildMenu != null) || (parentMenu != null) || autoOpen) {
- doItemAction(item, false);
+ doItemAction(item, false, focusOnHover);
}
}
}
@@ -933,6 +956,7 @@
private void close() {
if (parentMenu != null) {
parentMenu.popup.hide();
+ parentMenu.focus();
}
}
@@ -1007,7 +1031,7 @@
&& !selectedItem.getSubMenu().getItems().isEmpty()
&& (shownChildMenu == null || shownChildMenu.getSelectedItem() == null)) {
if (shownChildMenu == null) {
- doItemAction(selectedItem, false);
+ doItemAction(selectedItem, false, true);
}
selectedItem.getSubMenu().focus();
} else if (parentMenu != null) {
@@ -1040,11 +1064,13 @@
* This method is called when a menu bar is hidden, so that it can hide any
* child popups that are currently being shown.
*/
- private void onHide() {
+ private void onHide(boolean focus) {
if (shownChildMenu != null) {
- shownChildMenu.onHide();
+ shownChildMenu.onHide(focus);
popup.hide();
- focus();
+ if (focus) {
+ focus();
+ }
}
}
@@ -1199,7 +1225,7 @@
selectItem(itemToBeSelected);
if (shownChildMenu != null) {
- doItemAction(itemToBeSelected, false);
+ doItemAction(itemToBeSelected, false, true);
}
}
@@ -1224,7 +1250,7 @@
selectItem(itemToBeSelected);
if (shownChildMenu != null) {
- doItemAction(itemToBeSelected, false);
+ doItemAction(itemToBeSelected, false, true);
}
}
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestBox.java b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
index 060cf8e..8e0d537 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestBox.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
@@ -480,6 +480,7 @@
// Make sure that CSS styles specified for the default Menu classes
// do not affect this menu
setStyleName("");
+ setFocusOnHoverEnabled(false);
}
public void doSelectedItemAction() {
@@ -487,7 +488,7 @@
// selected, the menu must be showing.
MenuItem selectedItem = getSelectedItem();
if (selectedItem != null) {
- doItemAction(selectedItem, true);
+ doItemAction(selectedItem, true, false);
}
}