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;
+ }
+ }
+ }-*/;
+
+}