diff options
author | Artur Signell <artur@vaadin.com> | 2013-03-06 14:55:15 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2013-03-12 12:16:33 +0000 |
commit | 36a201f22f66989bf7a78ce8afce1ee64aaa0a22 (patch) | |
tree | 2e0957f0d65734e5bfe2e9242a196b387a44d21c /client | |
parent | 6922bc5b49c5551b289a5025ccd5901e2ac3aafc (diff) | |
download | vaadin-framework-36a201f22f66989bf7a78ce8afce1ee64aaa0a22.tar.gz vaadin-framework-36a201f22f66989bf7a78ce8afce1ee64aaa0a22.zip |
Fixed focus and tab index handling for UI (#11129)
Change-Id: I80377792ade11946337e2900a7ea84209ae1d060
Diffstat (limited to 'client')
-rw-r--r-- | client/src/com/vaadin/client/ui/AbstractComponentConnector.java | 13 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/FocusUtil.java | 94 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/VUI.java | 25 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/ui/UIConnector.java | 8 |
4 files changed, 130 insertions, 10 deletions
diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index 694db6f02c..74cb85c297 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -137,10 +137,15 @@ public abstract class AbstractComponentConnector extends AbstractConnector * implementation). */ Profiler.enter("AbstractComponentConnector.onStateChanged update tab index"); - if (getState() instanceof TabIndexState - && getWidget() instanceof Focusable) { - ((Focusable) getWidget()) - .setTabIndex(((TabIndexState) getState()).tabIndex); + if (getState() instanceof TabIndexState) { + if (getWidget() instanceof Focusable) { + ((Focusable) getWidget()) + .setTabIndex(((TabIndexState) getState()).tabIndex); + } else { + VConsole.error("Tab index received for " + + Util.getSimpleName(getWidget()) + + " which does not implement Focusable"); + } } Profiler.leave("AbstractComponentConnector.onStateChanged update tab index"); diff --git a/client/src/com/vaadin/client/ui/FocusUtil.java b/client/src/com/vaadin/client/ui/FocusUtil.java new file mode 100644 index 0000000000..7c0fea5f6d --- /dev/null +++ b/client/src/com/vaadin/client/ui/FocusUtil.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2013 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; + +import com.google.gwt.user.client.ui.Focusable; +import com.google.gwt.user.client.ui.Widget; + +/** + * A helper class used to make it easier for {@link Widget}s to implement + * {@link Focusable}. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.3 + * + */ +public class FocusUtil { + + /** + * Sets the access key property + * + * @param focusable + * The widget for which we want to set the access key. + * @param key + * The access key to set + */ + public static void setAccessKey(Widget focusable, char key) { + assert (focusable != null && focusable.getElement() != null) : "Can't setAccessKey for a widget without an element"; + focusable.getElement().setPropertyString("accessKey", "" + key); + } + + /** + * Explicitly focus/unfocus the given widget. Only one widget can have focus + * at a time, and the widget that does will receive all keyboard events. + * + * @param focusable + * the widget to focus/unfocus + * @param focused + * whether this widget should take focus or release it + */ + public static void setFocus(Widget focusable, boolean focus) { + assert (focusable != null && focusable.getElement() != null) : "Can't setFocus for a widget without an element"; + + if (focus) { + focusable.getElement().focus(); + } else { + focusable.getElement().blur(); + } + } + + /** + * Sets the widget's position in the tab index. If more than one widget has + * the same tab index, each such widget will receive focus in an arbitrary + * order. Setting the tab index to <code>-1</code> will cause the widget to + * be removed from the tab order. + * + * @param focusable + * The widget + * @param tabIndex + * the widget's tab index + */ + public static void setTabIndex(Widget focusable, int tabIndex) { + assert (focusable != null && focusable.getElement() != null) : "Can't setTabIndex for a widget without an element"; + + focusable.getElement().setTabIndex(tabIndex); + } + + /** + * Gets the widget's position in the tab index. + * + * @param focusable + * The widget + * + * @return the widget's tab index + */ + public static int getTabIndex(Widget focusable) { + assert (focusable != null && focusable.getElement() != null) : "Can't getTabIndex for a widget without an element"; + + return focusable.getElement().getTabIndex(); + } +} diff --git a/client/src/com/vaadin/client/ui/VUI.java b/client/src/com/vaadin/client/ui/VUI.java index b627d4a2a9..b07593896f 100644 --- a/client/src/com/vaadin/client/ui/VUI.java +++ b/client/src/com/vaadin/client/ui/VUI.java @@ -53,7 +53,8 @@ import com.vaadin.shared.ui.ui.UIConstants; */ public class VUI extends SimplePanel implements ResizeHandler, Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable, - HasResizeHandlers, HasScrollHandlers { + com.google.gwt.user.client.ui.Focusable, HasResizeHandlers, + HasScrollHandlers { private static int MONITOR_PARENT_TIMER_INTERVAL = 1000; @@ -437,7 +438,7 @@ public class VUI extends SimplePanel implements ResizeHandler, @Override public void focus() { - getElement().focus(); + setFocus(true); } /** @@ -462,4 +463,24 @@ public class VUI extends SimplePanel implements ResizeHandler, return addHandler(scrollHandler, ScrollEvent.getType()); } + @Override + public int getTabIndex() { + return FocusUtil.getTabIndex(this); + } + + @Override + public void setAccessKey(char key) { + FocusUtil.setAccessKey(this, key); + } + + @Override + public void setFocus(boolean focused) { + FocusUtil.setFocus(this, focused); + } + + @Override + public void setTabIndex(int index) { + FocusUtil.setTabIndex(this, index); + } + } diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 0fb7439587..ac441fc625 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -329,10 +329,6 @@ public class UIConnector extends AbstractSingleComponentContainerConnector DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN | Event.ONSCROLL); - // iview is focused when created so element needs tabIndex - // 1 due 0 is at the end of natural tabbing order - DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1"); - RootPanel root = RootPanel.get(rootPanelId); // Remove the v-app-loading or any splash screen added inside the div by @@ -347,6 +343,10 @@ public class UIConnector extends AbstractSingleComponentContainerConnector root.add(getWidget()); + // Set default tab index before focus call. State change handler + // will update this later if needed. + getWidget().setTabIndex(1); + if (applicationConnection.getConfiguration().isStandalone()) { // set focus to iview element by default to listen possible keyboard // shortcuts. For embedded applications this is unacceptable as we |