Revision: 9602
Author: p...@google.com
Date: Mon Jan 24 12:09:10 2011
Log: Improve canvas for browsers (and permutations) with partial canvas support.

Review at http://gwt-code-reviews.appspot.com/1296801

http://code.google.com/p/google-web-toolkit/source/detail?r=9602

Added:
 /trunk/user/src/com/google/gwt/dom/client/PartialSupport.java
Deleted:
 /trunk/user/src/com/google/gwt/user/client/IsSupported.java
Modified:
 /trunk/user/src/com/google/gwt/canvas/Canvas.gwt.xml
 /trunk/user/src/com/google/gwt/canvas/client/Canvas.java
 /trunk/user/test/com/google/gwt/canvas/client/CanvasTest.java
 /trunk/user/test/com/google/gwt/canvas/dom/client/Context2dTest.java

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/dom/client/PartialSupport.java Mon Jan 24 12:09:10 2011
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 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.dom.client;
+
+/**
+ * Annotation for classes that are only supported on a limited set of browsers.
+ *
+ * <p>
+ * By convention, classes annotated with PartialSupport will provide two static
+ * methods:
+ * <ol>
+ * <li> <code>static boolean isSupported()</code> that returns whether the
+ *   feature is supported. </li>
+ * <li> <code>static YourType createIfSupported()</code> factory method that
+ *   returns a new feature if supported, or null otherwise. </li>
+ * </ol>
+ * </p>
+ */
+public @interface PartialSupport {
+
+}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/IsSupported.java Thu Jan 13 05:38:38 2011
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2010 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;
-
-/**
- * Interface for classes that are only supported on a limited set of browsers.
- *
- * <p>
- * <span style="color:red">Experimental API: This API is still under development
- * and is subject to change.
- * </span>
- * </p>
- *
- * By convention, classes that implement IsSupported will provide a static
- * method <code>boolean isSupported()</code> that checks whether the feature is
- * supported at runtime.
- */
-public interface IsSupported {
-
-}
=======================================
--- /trunk/user/src/com/google/gwt/canvas/Canvas.gwt.xml Tue Nov 30 06:11:17 2010 +++ /trunk/user/src/com/google/gwt/canvas/Canvas.gwt.xml Mon Jan 24 12:09:10 2011
@@ -16,5 +16,30 @@
 <module>
   <inherits name="com.google.gwt.user.User"/>
   <inherits name="com.google.gwt.canvas.dom.DOM"/>
+
+  <!-- Define the support property -->
+  <define-property name="canvasElementSupport" values="maybe,no" />
+
+  <!-- Give default support value of no -->
+  <set-property name="canvasElementSupport" value="no" />
+
+  <set-property name="canvasElementSupport" value="maybe">
+    <any>
+      <when-property-is name="user.agent" value="safari" />
+      <when-property-is name="user.agent" value="gecko1_8" />
+      <when-property-is name="user.agent" value="opera" />
+    </any>
+  </set-property>
+
+ <replace-with class="com.google.gwt.canvas.client.Canvas.CanvasElementSupportDetectedMaybe"> + <when-type-is class="com.google.gwt.canvas.client.Canvas.CanvasElementSupportDetector" />
+    <when-property-is name="canvasElementSupport" value="maybe" />
+  </replace-with>
+
+ <replace-with class="com.google.gwt.canvas.client.Canvas.CanvasElementSupportDetectedNo"> + <when-type-is class="com.google.gwt.canvas.client.Canvas.CanvasElementSupportDetector" />
+    <when-property-is name="canvasElementSupport" value="no" />
+  </replace-with>
+
   <source path="client"/>
 </module>
=======================================
--- /trunk/user/src/com/google/gwt/canvas/client/Canvas.java Thu Jan 13 05:38:38 2011 +++ /trunk/user/src/com/google/gwt/canvas/client/Canvas.java Mon Jan 24 12:09:10 2011
@@ -17,9 +17,10 @@

 import com.google.gwt.canvas.dom.client.Context;
 import com.google.gwt.canvas.dom.client.Context2d;
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.CanvasElement;
 import com.google.gwt.dom.client.Document;
-import com.google.gwt.user.client.IsSupported;
+import com.google.gwt.dom.client.PartialSupport;
 import com.google.gwt.user.client.ui.FocusWidget;

 /**
@@ -31,25 +32,55 @@
  * </span>
  * </p>
  *
- * This widget may not be supported on all browsers, see {@link IsSupported}
+ * This widget may not be supported on all browsers.
  */
-public class Canvas extends FocusWidget implements IsSupported {
+@PartialSupport
+public class Canvas extends FocusWidget {
+  private static CanvasElementSupportDetector detector;
+
+  /**
+   * Return a new {@link Canvas} if supported,  and null otherwise.
+   *
+   * @return a new {@link Canvas} if supported, and null otherwise
+   */
+  public static Canvas createIfSupported() {
+    if (detector == null) {
+      detector = GWT.create(CanvasElementSupportDetector.class);
+    }
+    if (!detector.isSupportedCompileTime()) {
+      return null;
+    }
+    CanvasElement element = Document.get().createCanvasElement();
+    if (!detector.isSupportedRunTime(element)) {
+      return null;
+    }
+    return new Canvas(element);
+  }

   /**
* Runtime check for whether the canvas element is supported in this browser.
-   * See {@link IsSupported}
    *
    * @return whether the canvas element is supported
    */
-  public static final native boolean isSupported() /*-{
-    return !!$doc.createElement('canvas').getContext;
-  }-*/;
+  public static boolean isSupported() {
+    if (detector == null) {
+      detector = GWT.create(CanvasElementSupportDetector.class);
+    }
+    if (!detector.isSupportedCompileTime()) {
+      return false;
+    }
+    CanvasElement element = Document.get().createCanvasElement();
+    if (!detector.isSupportedRunTime(element)) {
+      return false;
+    }
+    return true;
+  }

   /**
-   * Creates a Canvas.
+ * Protected constructor. Use {@link #createIfSupported()} to create a Canvas.
    */
-  public Canvas() {
-    setElement(Document.get().createCanvasElement());
+  private Canvas(CanvasElement element) {
+    setElement(element);
   }

   /**
@@ -142,4 +173,67 @@
   public String toDataUrl(String type) {
     return getCanvasElement().toDataUrl(type);
   }
-}
+
+  /**
+   * Detector for browser support of {@link CanvasElement}.
+   */
+  private static class CanvasElementSupportDetector {
+    /**
+     * Using a run-time check, return true if the {@link CanvasElement} is
+     * supported.
+     *
+     * @return true if supported, false otherwise.
+     */
+    static native boolean isSupportedRunTime(CanvasElement element) /*-{
+      return !!element.getContext;
+    }-*/;
+
+    /**
+ * Using a compile-time check, return true if {@link CanvasElement} might
+     * be supported.
+     *
+     * @return true if might be supported, false otherwise.
+     */
+    boolean isSupportedCompileTime() {
+      // will be true in CanvasElementSupportDetectedMaybe
+      // will be false in CanvasElementSupportDetectedNo
+      return false;
+    }
+  }
+
+  /**
+   * Detector for permutations that might support {@link CanvasElement}.
+   */
+  @SuppressWarnings("unused")
+  private static class CanvasElementSupportDetectedMaybe
+      extends CanvasElementSupportDetector {
+    /**
+ * Using a compile-time check, return true if {@link CanvasElement} might be
+     * supported.
+     *
+     * @return true if might be supported, false otherwise.
+     */
+    @Override
+    boolean isSupportedCompileTime() {
+      return true;
+    }
+  }
+
+  /**
+   * Detector for permutations that do not support {@link CanvasElement}.
+   */
+  @SuppressWarnings("unused")
+  private static class CanvasElementSupportDetectedNo
+      extends CanvasElementSupportDetector {
+    /**
+ * Using a compile-time check, return true if {@link CanvasElement} might be
+     * supported.
+     *
+     * @return true if might be supported, false otherwise.
+     */
+    @Override
+    boolean isSupportedCompileTime() {
+      return false;
+    }
+  }
+}
=======================================
--- /trunk/user/test/com/google/gwt/canvas/client/CanvasTest.java Wed Dec 1 10:08:22 2010 +++ /trunk/user/test/com/google/gwt/canvas/client/CanvasTest.java Mon Jan 24 12:09:10 2011
@@ -45,10 +45,11 @@

   @Override
   protected void gwtSetUp() throws Exception {
-    canvas1 = new Canvas();
-    canvas2 = new Canvas();
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    canvas1 = Canvas.createIfSupported();
+    canvas2 = Canvas.createIfSupported();
+
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     RootPanel.get().add(canvas1);
@@ -57,24 +58,29 @@

   @Override
   protected void gwtTearDown() throws Exception {
+    if (canvas1 == null) {
+      return; // don't continue if not supported
+    }
+
     RootPanel.get().remove(canvas1);
     RootPanel.get().remove(canvas2);
   }

   /*
- * If the canvas has no pixels (i.e. either its horizontal dimension or its vertical dimension - * is zero) then the method must return the string "data:,". (This is the shortest data: URL;
-   * it represents the empty string in a text/plain resource.)
-   *
+ * If the canvas has no pixels (i.e. either its horizontal dimension or its
+   * vertical dimension is zero) then the method must return the string
+ * "data:,". (This is the shortest data: URL; it represents the empty string
+   * in a text/plain resource.)
+   *
    * Due to browser inconsistencies, we just check for data:something.
    */
   public void testBlankDataUrl() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

- // Safari 3.0 does not support toDataURL(), so the following tests are disabled for
-    // Safari 3.0 and before.
+    // Safari 3.0 does not support toDataURL(), so the following tests are
+    // disabled for Safari 3.0 and before.
     if (isWebkit525OrBefore()) {
       return;
     }
@@ -87,12 +93,34 @@
     canvas1.setCoordinateSpaceWidth(0);

     String dataUrl = canvas1.toDataUrl();
- assertTrue("toDataURL() should return data:something", dataUrl.startsWith("data:"));
+    assertTrue("toDataURL() should return data:something",
+        dataUrl.startsWith("data:"));
+  }
+
+  public void testDataUrlWithType() {
+    if (canvas1 == null) {
+      return; // don't continue if not supported
+    }
+
+    // Safari 3.0 does not support toDataURL(), so the following tests are
+    // disabled for Safari 3.0 and before.
+    if (isWebkit525OrBefore()) {
+      return;
+    }
+
+    canvas1.setHeight("10px");
+    canvas1.setWidth("10px");
+    canvas1.setCoordinateSpaceHeight(10);
+    canvas1.setCoordinateSpaceWidth(10);
+
+    String dataUrl = canvas1.toDataUrl("image/png");
+    assertTrue("toDataURL(image/png) should return data:image/png[data]",
+        dataUrl.startsWith("data:image/png"));
   }

   public void testHeightAndWidth() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     canvas1.setHeight("40px");
@@ -117,8 +145,8 @@
   }

   public void testInternalHeightAndWidth() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     canvas1.setHeight("40px");
@@ -147,24 +175,14 @@
     assertEquals(161, canvas1.getCoordinateSpaceWidth());
   }

-  public void testDataUrlWithType() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
-    }
-
- // Safari 3.0 does not support toDataURL(), so the following tests are disabled for
-    // Safari 3.0 and before.
-    if (isWebkit525OrBefore()) {
-      return;
-    }
-
-    canvas1.setHeight("10px");
-    canvas1.setWidth("10px");
-    canvas1.setCoordinateSpaceHeight(10);
-    canvas1.setCoordinateSpaceWidth(10);
-
-    String dataUrl = canvas1.toDataUrl("image/png");
-    assertTrue("toDataURL(image/png) should return data:image/png[data]",
-        dataUrl.startsWith("data:image/png"));
+  public void testIsSupported() {
+    if (canvas1 == null) {
+      assertFalse(
+ "isSupported() should be false when createIfSupported() returns null",
+          Canvas.isSupported());
+    } else {
+      assertTrue(
+ "isSupported() should be true when createIfSupported() returns non-null", Canvas.isSupported());
+    }
   }
 }
=======================================
--- /trunk/user/test/com/google/gwt/canvas/dom/client/Context2dTest.java Tue Dec 7 11:12:47 2010 +++ /trunk/user/test/com/google/gwt/canvas/dom/client/Context2dTest.java Mon Jan 24 12:09:10 2011
@@ -54,10 +54,11 @@

   @Override
   protected void gwtSetUp() throws Exception {
-    canvas1 = new Canvas();
-    canvas2 = new Canvas();
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    canvas1 = Canvas.createIfSupported();
+    canvas2 = Canvas.createIfSupported();
+
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     RootPanel.get().add(canvas1);
@@ -71,8 +72,8 @@
   }

   public void testArc() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     canvas1.setHeight("40px");
@@ -95,8 +96,8 @@
   }

   public void testFillRect() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

// Safari 3.0 does not support getImageData(), so the following tests are disabled for
@@ -150,8 +151,8 @@
   }

   public void testFillStyle() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     // get the 2d contexts
@@ -193,8 +194,8 @@
   }

   public void testFont() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     Context2d context = canvas1.getContext2d();
@@ -203,8 +204,8 @@
   }

   public void testGlobalAlpha() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     Context2d context = canvas1.getContext2d();
@@ -214,8 +215,8 @@

   // This test currently fails on IE9 and is disabled.
   public void disabled_testGlobalComposite() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     Context2d context = canvas1.getContext2d();
@@ -226,8 +227,8 @@
   }

   public void testGradient() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

// Safari 3.0 does not support getImageData(), so the following tests are disabled for
@@ -272,8 +273,8 @@
   }

   public void testImageData() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

// Firefox 3.0 does not support createImageData(), so the following tests are disabled
@@ -342,8 +343,8 @@
   }

   public void testIsPointInPath() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     canvas1.setHeight("40px");
@@ -363,8 +364,8 @@
   }

   public void testLines() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     canvas1.setHeight("40px");
@@ -390,8 +391,8 @@
   }

   public void testMiter() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     Context2d context = canvas1.getContext2d();
@@ -400,8 +401,8 @@
   }

   public void testPixelManipulation() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

// Safari 3.0 does not support getImageData(), so the following tests are disabled for
@@ -431,8 +432,8 @@
   }

   public void testShadows() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

// Firefox 3.0 returns the incorrect shadowBlur value so the following tests are disabled
@@ -459,8 +460,8 @@
   }

   public void testStrokeStyle() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     // get the 2d contexts
@@ -502,8 +503,8 @@
   }

   public void testText() {
-    if (!canvas1.isSupported()) {
-      return; // disable tests if not supported
+    if (canvas1 == null) {
+      return; // don't continue if not supported
     }

     canvas1.setHeight("40px");

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to