Fix for issue #897; prevents IE from throwing an exception when trying to set focus on a hidden/detached widget. Also does some yummy refactoring goodness. Review by: knorton, jgw (postmortem) git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1059 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/Focus.gwt.xml b/user/src/com/google/gwt/user/Focus.gwt.xml index 35e95b0..300320a 100644 --- a/user/src/com/google/gwt/user/Focus.gwt.xml +++ b/user/src/com/google/gwt/user/Focus.gwt.xml
@@ -20,7 +20,7 @@ <inherits name="com.google.gwt.core.Core"/> <inherits name="com.google.gwt.user.UserAgent"/> - <!-- Safari and old mozillae need a different implementation --> + <!-- Safari, old Mozilla, and Opera need a different implementation --> <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplOld"> <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/> <any> @@ -29,4 +29,13 @@ <when-property-is name="user.agent" value="opera"/> </any> </replace-with> + + <!-- IE's implementation traps exceptions on invalid setFocus() --> + <replace-with class="com.google.gwt.user.client.ui.impl.FocusImplIE6"> + <when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/> + <any> + <when-property-is name="user.agent" value="ie6"/> + </any> + </replace-with> + </module>
diff --git a/user/src/com/google/gwt/user/client/ui/FocusPanel.java b/user/src/com/google/gwt/user/client/ui/FocusPanel.java index b2f3f1a..843bb9a 100644 --- a/user/src/com/google/gwt/user/client/ui/FocusPanel.java +++ b/user/src/com/google/gwt/user/client/ui/FocusPanel.java
@@ -15,7 +15,6 @@ */ package com.google.gwt.user.client.ui; -import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.impl.FocusImpl; @@ -27,7 +26,7 @@ public class FocusPanel extends SimplePanel implements HasFocus, SourcesClickEvents, SourcesMouseEvents, SourcesMouseWheelEvents { - static final FocusImpl impl = (FocusImpl) GWT.create(FocusImpl.class); + static final FocusImpl impl = FocusImpl.getFocusImplForPanel(); private ClickListenerCollection clickListeners; private FocusListenerCollection focusListeners;
diff --git a/user/src/com/google/gwt/user/client/ui/FocusWidget.java b/user/src/com/google/gwt/user/client/ui/FocusWidget.java index 9ff3b9b..195d39e 100644 --- a/user/src/com/google/gwt/user/client/ui/FocusWidget.java +++ b/user/src/com/google/gwt/user/client/ui/FocusWidget.java
@@ -1,5 +1,5 @@ /* - * Copyright 2006 Google Inc. + * Copyright 2007 Google Inc. * * 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 @@ -26,14 +26,7 @@ public abstract class FocusWidget extends Widget implements SourcesClickEvents, SourcesFocusEvents, HasFocus { - /** - * <code>FocusImpl</code> contains browser specific focus code for focusable - * widgets. This <code>FocusImpl</code> instance is intentionally _not_ - * rebound, as the base implementation works on all browsers for truly - * focusable widgets. The special cases are only needed for things that aren't - * naturally focusable on some browsers, such as DIVs. - */ - private static final FocusImpl impl = new FocusImpl(); + private static final FocusImpl impl = FocusImpl.getFocusImplForWidget(); /** * Gets the FocusImpl instance.
diff --git a/user/src/com/google/gwt/user/client/ui/impl/FocusImpl.java b/user/src/com/google/gwt/user/client/ui/impl/FocusImpl.java index 2426cb4..9e71e69 100644 --- a/user/src/com/google/gwt/user/client/ui/impl/FocusImpl.java +++ b/user/src/com/google/gwt/user/client/ui/impl/FocusImpl.java
@@ -1,5 +1,5 @@ /* - * Copyright 2006 Google Inc. + * Copyright 2007 Google Inc. * * 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 @@ -15,6 +15,7 @@ */ package com.google.gwt.user.client.ui.impl; +import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Element; /** @@ -22,6 +23,42 @@ * that aren't naturally focusable in all browsers, such as DIVs. */ public class FocusImpl { + + private static FocusImpl implPanel = (FocusImpl) GWT.create(FocusImpl.class); + + /** + * This instance may not be a {@link FocusImplOld}, because that special case + * is only needed for things that aren't naturally focusable on some browsers, + * such as DIVs. This exact class works for truly focusable widgets on those + * browsers. + * + * The compiler will optimize out the conditional. + */ + private static FocusImpl implWidget = (implPanel instanceof FocusImplOld) + ? new FocusImpl() : implPanel; + + /** + * Returns the focus implementation class for creating and manipulating + * focusable elements that aren't naturally focusable in all browsers, such as + * DIVs. + */ + public static FocusImpl getFocusImplForPanel() { + return implPanel; + } + + /** + * Returns the focus implementation class for manipulating focusable elements + * that are naturally focusable in all browsers, such as text boxes. + */ + public static FocusImpl getFocusImplForWidget() { + return implWidget; + } + + /** + * Not externally instantiable or extensible. + */ + FocusImpl() { + } public native void blur(Element elem) /*-{ elem.blur();
diff --git a/user/src/com/google/gwt/user/client/ui/impl/FocusImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/FocusImplIE6.java new file mode 100644 index 0000000..88c58d8 --- /dev/null +++ b/user/src/com/google/gwt/user/client/ui/impl/FocusImplIE6.java
@@ -0,0 +1,38 @@ +/* + * Copyright 2007 Google Inc. + * + * 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.google.gwt.user.client.ui.impl; + +import com.google.gwt.user.client.Element; + +/** + * Implementation of {@link com.google.gwt.user.client.ui.impl.FocusImpl} + * for IE that traps invalid focus attempts to match other browsers. + */ +public class FocusImplIE6 extends FocusImpl { + + public native void focus(Element elem) /*-{ + try { + elem.focus(); + } catch (e) { + // Only trap the exception if the attempt was mostly legit + if (!elem || !elem.focus) { + // Rethrow the probable NPE or invalid type + throw e; + } + } + }-*/; + +}