Merging releases/1.5 into trunk
svn merge -r3205:3230 https://google-web-toolkit.googlecode.com/svn/releases/1.5 .
svn merge -r3231:3239 https://google-web-toolkit.googlecode.com/svn/releases/1.5 .
svn merge -r3240:3341 https://google-web-toolkit.googlecode.com/svn/releases/1.5 .
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3351 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/Timer.java b/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/Timer.java
index 5f2c514..32bcef7 100644
--- a/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/Timer.java
+++ b/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/Timer.java
@@ -19,6 +19,7 @@
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;
+import java.util.Formatter;
import java.util.Vector;
/**
@@ -30,7 +31,7 @@
private static final int MS_IN_HOUR = 60 * 60 * 1000;
private static final int MS_IN_MINUTE = 60 * 1000;
- private static final double MS_IN_SECOND_FLOAT = 1000.0;
+ private static final int MS_IN_SECOND = 1000;
private Vector<Task> nested;
private String name;
@@ -50,14 +51,19 @@
for (Task task : nested) {
task.perform();
}
- long duration = (System.currentTimeMillis() - start);
- long hrs = duration / MS_IN_HOUR;
- long min = (duration - (hrs * MS_IN_HOUR)) / MS_IN_MINUTE;
- double sec = (duration - (hrs * MS_IN_HOUR) - (min * MS_IN_MINUTE))
- / MS_IN_SECOND_FLOAT;
- log("timer " + name + " timed " + duration + " ms. ("
- + hrs + ":" + (min < 10 ? "0" : "") + min + ":" + sec + ")");
+ long duration_ms = (System.currentTimeMillis() - start);
+ long duration = duration_ms;
+ long hrs = duration / MS_IN_HOUR;
+ duration -= hrs * MS_IN_HOUR;
+ long min = duration / MS_IN_MINUTE;
+ duration -= min * MS_IN_MINUTE;
+ long sec = duration / MS_IN_SECOND;
+ duration -= sec * MS_IN_SECOND;
+ long msec = duration;
+
+ log("timer " + name + " timed " + duration_ms + " ms. " +
+ String.format("(%02d:%02d:%02d.%03d)", hrs, min, sec, msec));
}
public void setName(String newname) {
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/HostedModeTemplate.js b/dev/core/src/com/google/gwt/core/ext/linker/impl/HostedModeTemplate.js
index e60fd20..6fc0870 100644
--- a/dev/core/src/com/google/gwt/core/ext/linker/impl/HostedModeTemplate.js
+++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/HostedModeTemplate.js
@@ -129,9 +129,19 @@
thisScript = thisScript.previousSibling;
}
+ // Gets the part of a url up to and including the 'path' portion.
function getDirectoryOfFile(path) {
- var eq = path.lastIndexOf('/');
- return (eq >= 0) ? path.substring(0, eq + 1) : '';
+ // Truncate starting at the first '?' or '#', whichever comes first.
+ var hashIndex = path.lastIndexOf('#');
+ if (hashIndex == -1) {
+ hashIndex = path.length;
+ }
+ var queryIndex = path.indexOf('?');
+ if (queryIndex == -1) {
+ queryIndex = path.length;
+ }
+ var slashIndex = path.lastIndexOf('/', Math.min(queryIndex, hashIndex));
+ return (slashIndex >= 0) ? path.substring(0, slashIndex + 1) : '';
};
if (thisScript && thisScript.src) {
@@ -148,10 +158,7 @@
base = baseElements[baseElements.length - 1].href;
} else {
// No base tag; the base must be the same as the document location.
- var loc = $doc.location;
- var href = loc.href;
- base = getDirectoryOfFile(href.substr(0, href.length
- - loc.hash.length));
+ base = getDirectoryOfFile($doc.location.href);
}
} else if ((base.match(/^\w+:\/\//))) {
// If the URL is obviously absolute, do nothing.
diff --git a/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js b/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js
index f304cff..0f1bdd4 100644
--- a/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js
+++ b/dev/core/src/com/google/gwt/core/linker/IFrameTemplate.js
@@ -125,9 +125,19 @@
thisScript = thisScript.previousSibling;
}
+ // Gets the part of a url up to and including the 'path' portion.
function getDirectoryOfFile(path) {
- var eq = path.lastIndexOf('/');
- return (eq >= 0) ? path.substring(0, eq + 1) : '';
+ // Truncate starting at the first '?' or '#', whichever comes first.
+ var hashIndex = path.lastIndexOf('#');
+ if (hashIndex == -1) {
+ hashIndex = path.length;
+ }
+ var queryIndex = path.indexOf('?');
+ if (queryIndex == -1) {
+ queryIndex = path.length;
+ }
+ var slashIndex = path.lastIndexOf('/', Math.min(queryIndex, hashIndex));
+ return (slashIndex >= 0) ? path.substring(0, slashIndex + 1) : '';
};
if (thisScript && thisScript.src) {
@@ -144,10 +154,7 @@
base = baseElements[baseElements.length - 1].href;
} else {
// No base tag; the base must be the same as the document location.
- var loc = $doc.location;
- var href = loc.href;
- base = getDirectoryOfFile(href.substr(0, href.length
- - loc.hash.length));
+ base = getDirectoryOfFile($doc.location.href);
}
} else if ((base.match(/^\w+:\/\//))) {
// If the URL is obviously absolute, do nothing.
diff --git a/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js b/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
index b2aed9b..ca584b9 100644
--- a/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
+++ b/dev/core/src/com/google/gwt/core/linker/SingleScriptTemplate.js
@@ -90,9 +90,19 @@
thisScript = markerScript.previousSibling;
}
+ // Gets the part of a url up to and including the 'path' portion.
function getDirectoryOfFile(path) {
- var eq = path.lastIndexOf('/');
- return (eq >= 0) ? path.substring(0, eq + 1) : '';
+ // Truncate starting at the first '?' or '#', whichever comes first.
+ var hashIndex = path.lastIndexOf('#');
+ if (hashIndex == -1) {
+ hashIndex = path.length;
+ }
+ var queryIndex = path.indexOf('?');
+ if (queryIndex == -1) {
+ queryIndex = path.length;
+ }
+ var slashIndex = path.lastIndexOf('/', Math.min(queryIndex, hashIndex));
+ return (slashIndex >= 0) ? path.substring(0, slashIndex + 1) : '';
};
if (thisScript && thisScript.src) {
@@ -109,10 +119,7 @@
base = baseElements[baseElements.length - 1].href;
} else {
// No base tag; the base must be the same as the document location.
- var loc = $doc.location;
- var href = loc.href;
- base = getDirectoryOfFile(href.substr(0, href.length
- - loc.hash.length));
+ base = getDirectoryOfFile($doc.location.href);
}
} else if ((base.match(/^\w+:\/\//))) {
// If the URL is obviously absolute, do nothing.
diff --git a/dev/core/src/com/google/gwt/core/linker/XSTemplate.js b/dev/core/src/com/google/gwt/core/linker/XSTemplate.js
index 2d5153f..6c7ea70 100644
--- a/dev/core/src/com/google/gwt/core/linker/XSTemplate.js
+++ b/dev/core/src/com/google/gwt/core/linker/XSTemplate.js
@@ -113,9 +113,19 @@
thisScript = thisScript.previousSibling;
}
+ // Gets the part of a url up to and including the 'path' portion.
function getDirectoryOfFile(path) {
- var eq = path.lastIndexOf('/');
- return (eq >= 0) ? path.substring(0, eq + 1) : '';
+ // Truncate starting at the first '?' or '#', whichever comes first.
+ var hashIndex = path.lastIndexOf('#');
+ if (hashIndex == -1) {
+ hashIndex = path.length;
+ }
+ var queryIndex = path.indexOf('?');
+ if (queryIndex == -1) {
+ queryIndex = path.length;
+ }
+ var slashIndex = path.lastIndexOf('/', Math.min(queryIndex, hashIndex));
+ return (slashIndex >= 0) ? path.substring(0, slashIndex + 1) : '';
};
if (thisScript && thisScript.src) {
@@ -132,10 +142,7 @@
base = baseElements[baseElements.length - 1].href;
} else {
// No base tag; the base must be the same as the document location.
- var loc = $doc.location;
- var href = loc.href;
- base = getDirectoryOfFile(href.substr(0, href.length
- - loc.hash.length));
+ base = getDirectoryOfFile($doc.location.href);
}
} else if ((base.match(/^\w+:\/\//))) {
// If the URL is obviously absolute, do nothing.
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 49b59fa..5e8d32a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -298,9 +298,6 @@
}
allEntryPoints.addAll(JProgram.CODEGEN_TYPES_SET);
allEntryPoints.addAll(JProgram.INDEX_TYPES_SET);
- allEntryPoints.add("java.lang.Object");
- allEntryPoints.add("java.lang.String");
- allEntryPoints.add("java.lang.Iterable");
declEntryPts = allEntryPoints.toArray(new String[0]);
}
@@ -579,6 +576,13 @@
}
protected void optimize(JProgram jprogram) throws InterruptedException {
+ /*
+ * Record the beginning of optimations; this turns on certain checks that
+ * guard against problematic late construction of things like class
+ * literals.
+ */
+ jprogram.beginOptimizations();
+
boolean didChange;
do {
if (Thread.interrupted()) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
index 4f23567..a2c27fa 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
@@ -16,56 +16,29 @@
package com.google.gwt.dev.jjs.ast;
import com.google.gwt.dev.jjs.InternalCompilerException;
+import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
/**
* Java class literal expression.
+ *
+ * NOTE: This class is modeled as if it were a JFieldRef to a field declared in
+ * ClassLiteralHolder. That field contains the class object allocation
+ * initializer.
*/
public class JClassLiteral extends JLiteral {
- private static String getClassName(String fullName) {
- int pos = fullName.lastIndexOf(".");
- return fullName.substring(pos + 1);
- }
-
- private static String getPackageName(String fullName) {
- int pos = fullName.lastIndexOf(".");
- return fullName.substring(0, pos + 1);
- }
-
- private static String getTypeName(JProgram program, JType type) {
- String typeName;
- if (type instanceof JArrayType) {
- typeName = type.getJsniSignatureName().replace('/', '.');
- // Mangle the class name to match hosted mode.
- if (program.isJavaScriptObject(((JArrayType) type).getLeafType())) {
- typeName = typeName.replace(";", "$;");
- }
- } else {
- typeName = type.getName();
- // Mangle the class name to match hosted mode.
- if (program.isJavaScriptObject(type)) {
- typeName += '$';
- }
- }
- return typeName;
- }
-
- private JExpression classObjectAllocation;
- private final JType refType;
-
/**
- * These are only supposed to be constructed by JProgram.
+ * Create an expression that will evaluate, at run time, to the class literal.
+ * Cannot be called after optimizations begin.
*/
- JClassLiteral(JProgram program, JType type) {
- super(program);
- refType = type;
-
+ static JMethodCall computeClassObjectAllocation(JProgram program,
+ SourceInfo info, JType type) {
String typeName = getTypeName(program, type);
JMethod method = program.getIndexedMethod(type.getClassLiteralFactoryMethod());
assert method != null;
- JMethodCall call = new JMethodCall(program, null, null, method);
+ JMethodCall call = new JMethodCall(program, info, null, method);
call.getArgs().add(program.getLiteralString(getPackageName(typeName)));
call.getArgs().add(program.getLiteralString(getClassName(typeName)));
@@ -104,15 +77,61 @@
throw new InternalCompilerException(
"Could not find enum values() method");
}
- JsniMethodRef jsniMethodRef = new JsniMethodRef(program.program, null,
- null, valuesMethod);
+ JsniMethodRef jsniMethodRef = new JsniMethodRef(program, info, null,
+ valuesMethod);
call.getArgs().add(jsniMethodRef);
}
} else {
assert (type instanceof JArrayType || type instanceof JInterfaceType || type instanceof JPrimitiveType);
}
+ return call;
+ }
- classObjectAllocation = call;
+ private static String getClassName(String fullName) {
+ int pos = fullName.lastIndexOf(".");
+ return fullName.substring(pos + 1);
+ }
+
+ private static String getPackageName(String fullName) {
+ int pos = fullName.lastIndexOf(".");
+ return fullName.substring(0, pos + 1);
+ }
+
+ private static String getTypeName(JProgram program, JType type) {
+ String typeName;
+ if (type instanceof JArrayType) {
+ typeName = type.getJsniSignatureName().replace('/', '.');
+ // Mangle the class name to match hosted mode.
+ if (program.isJavaScriptObject(((JArrayType) type).getLeafType())) {
+ typeName = typeName.replace(";", "$;");
+ }
+ } else {
+ typeName = type.getName();
+ // Mangle the class name to match hosted mode.
+ if (program.isJavaScriptObject(type)) {
+ typeName += '$';
+ }
+ }
+ return typeName;
+ }
+
+ private final JField field;
+ private final JType refType;
+
+ /**
+ * This constructor is only used by {@link JProgram}.
+ */
+ JClassLiteral(JProgram program, JType type, JField field) {
+ super(program);
+ refType = type;
+ this.field = field;
+ }
+
+ /**
+ * Returns the field holding my allocated object.
+ */
+ public JField getField() {
+ return field;
}
public JType getRefType() {
@@ -120,12 +139,11 @@
}
public JType getType() {
- return classObjectAllocation.getType();
+ return field.getType();
}
public void traverse(JVisitor visitor, Context ctx) {
if (visitor.visit(this, ctx)) {
- classObjectAllocation = visitor.accept(classObjectAllocation);
}
visitor.endVisit(this, ctx);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
index f8511ce..fbce11c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -17,6 +17,7 @@
import com.google.gwt.dev.jjs.SourceInfo;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -24,23 +25,85 @@
*/
public class JNewArray extends JExpression implements HasSettableType {
- public List<JExpression> dims = null;
- public List<JExpression> initializers = null;
+ public static JNewArray createDims(JProgram program, SourceInfo info,
+ JArrayType arrayType, List<JExpression> dims) {
+ List<JClassLiteral> classLiterals = new ArrayList<JClassLiteral>();
+
+ // Produce all class literals that will eventually get generated.
+ int realDims = 0;
+ for (JExpression dim : dims) {
+ if (dim instanceof JAbsentArrayDimension) {
+ break;
+ }
+ ++realDims;
+ }
+
+ JType cur = arrayType;
+ for (int i = 0; i < realDims; ++i) {
+ // Walk down each type from most dims to least.
+ JClassLiteral classLit = program.getLiteralClass(cur);
+ classLiterals.add(classLit);
+ cur = ((JArrayType) cur).getElementType();
+ }
+ return new JNewArray(program, info, arrayType, dims, null, classLiterals);
+ }
+
+ public static JNewArray createInitializers(JProgram program, SourceInfo info,
+ JArrayType arrayType, List<JExpression> initializers) {
+ List<JClassLiteral> classLiterals = new ArrayList<JClassLiteral>();
+ classLiterals.add(program.getLiteralClass(arrayType));
+ return new JNewArray(program, info, arrayType, null, initializers,
+ classLiterals);
+ }
+
+ public final List<JExpression> dims;
+
+ public final List<JExpression> initializers;
+
private JArrayType arrayType;
- public JNewArray(JProgram program, SourceInfo info, JArrayType arrayType) {
+ /**
+ * The list of class literals that will be needed to support this expression.
+ */
+ private final List<JClassLiteral> classLiterals;
+
+ public JNewArray(JProgram program, SourceInfo info, JArrayType arrayType,
+ List<JExpression> dims, List<JExpression> initializers,
+ List<JClassLiteral> classLits) {
super(program, info);
this.arrayType = arrayType;
+ this.dims = dims;
+ this.initializers = initializers;
+ this.classLiterals = classLits;
}
public JArrayType getArrayType() {
return arrayType;
}
+ /**
+ * Return a class literal for the array type itself.
+ */
+ public JClassLiteral getClassLiteral() {
+ // the class literal for the array type itself is always first
+ return getClassLiterals().get(0);
+ }
+
+ /**
+ * Get the list of class literals that will be needed to support this
+ * expression. If this literal has dimension expressions in <code>dims</code>,
+ * then the literals will be the array type, followed by the array's component
+ * type, followed by array's component type's component type, etc.
+ */
+ public List<JClassLiteral> getClassLiterals() {
+ return classLiterals;
+ }
+
public JType getType() {
return arrayType;
}
+ @Override
public boolean hasSideEffects() {
if (initializers != null) {
for (int i = 0, c = initializers.size(); i < c; ++i) {
@@ -70,27 +133,14 @@
if (dims != null) {
visitor.accept(dims);
-
- // Visit all the class literals that will eventually get generated.
- JArrayType it = arrayType;
- for (JExpression dim : dims) {
- if (dim instanceof JAbsentArrayDimension) {
- break;
- }
- visitor.accept(program.getLiteralClass(it));
- if (it.getElementType() instanceof JArrayType) {
- it = (JArrayType) it.getElementType();
- } else {
- break;
- }
- }
}
if (initializers != null) {
visitor.accept(initializers);
- // Visit the class literals that will eventually get generated.
- visitor.accept(program.getLiteralClass(arrayType));
}
+
+ // Visit all the class literals that will eventually get generated.
+ visitor.accept(getClassLiterals());
}
visitor.endVisit(this, ctx);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 28b8b28..ba92608 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -59,13 +59,14 @@
"com.google.gwt.lang.Exceptions", "com.google.gwt.lang.LongLib",
"com.google.gwt.lang.Stats",}));
- public static final Set<String> INDEX_TYPES_SET = new HashSet<String>(
+ public static final Set<String> INDEX_TYPES_SET = new LinkedHashSet<String>(
Arrays.asList(new String[] {
"java.lang.Object", "java.lang.String", "java.lang.Class",
"java.lang.CharSequence", "java.lang.Comparable", "java.lang.Enum",
"java.lang.Iterable", "java.util.Iterator",
"com.google.gwt.core.client.GWT",
- "com.google.gwt.core.client.JavaScriptObject"}));
+ "com.google.gwt.core.client.JavaScriptObject",
+ "com.google.gwt.lang.ClassLiteralHolder",}));
static final Map<String, Set<String>> traceMethods = new HashMap<String, Set<String>>();
@@ -189,6 +190,8 @@
private final List<JReferenceType> allTypes = new ArrayList<JReferenceType>();
+ private final Map<JType, JClassLiteral> classLiterals = new IdentityHashMap<JType, JClassLiteral>();
+
/**
* Each entry is a HashMap(JType => JArrayType), arranged such that the number
* of dimensions is that index (plus one) at which the JArrayTypes having that
@@ -225,6 +228,11 @@
private JMethod nullMethod;
+ /**
+ * Turned on once optimizations begin.
+ */
+ private boolean optimizationsStarted = false;
+
private Map<JReferenceType, Integer> queryIds;
private final Map<JMethod, JMethod> staticToInstanceMap = new IdentityHashMap<JMethod, JMethod>();
@@ -265,6 +273,8 @@
private final JPrimitiveType typeShort = new JPrimitiveType(this, "short",
"S", "java.lang.Short", literalIntZero);
+ private JClassType typeSpecialClassLiteralHolder;
+
private JClassType typeSpecialJavaScriptObject;
private JClassType typeString;
@@ -283,6 +293,15 @@
}
/**
+ * Record the start of optimizations, which disables certain problematic
+ * constructions. In particular, new class literals cannot be created once
+ * optimization starts.
+ */
+ public void beginOptimizations() {
+ optimizationsStarted = true;
+ }
+
+ /**
* Helper to create an assignment, used to initalize fields, etc.
*/
public JExpressionStatement createAssignmentStmt(SourceInfo info,
@@ -315,6 +334,8 @@
typeClass = x;
} else if (sname.equals("com.google.gwt.core.client.JavaScriptObject")) {
typeSpecialJavaScriptObject = x;
+ } else if (sname.equals("com.google.gwt.lang.ClassLiteralHolder")) {
+ typeSpecialClassLiteralHolder = x;
}
}
@@ -518,19 +539,59 @@
return new JCharLiteral(this, c);
}
+ /**
+ * May not be called once optimizations begin; all possible class literals
+ * must be created up front.
+ */
public JClassLiteral getLiteralClass(JType type) {
- /*
- * Explicitly not interned. This is due to the underlying allocation
- * expression, which can be mutated by some optimizations. If the same
- * allocation expression could be visited multiple times within a single
- * visitor, then every visitor would have to be idempotent. In fact,
- * Pruner.CleanupRefsVisitor is not idempotent when removing arguments,
- * because they are only implicitly (positionally) correlated with recently
- * pruned parameters.
- */
- return new JClassLiteral(this, type);
+ JClassLiteral classLiteral = classLiterals.get(type);
+ if (classLiteral == null) {
+ if (optimizationsStarted) {
+ throw new InternalCompilerException(
+ "New class literals cannot be created once optimizations have started; type '"
+ + type + "'");
+ }
+
+ SourceInfo info = typeSpecialClassLiteralHolder.getSourceInfo();
+
+ // Create the allocation expression FIRST since this may be recursive on
+ // super type (this forces the super type classLit to be created first).
+ JExpression alloc = JClassLiteral.computeClassObjectAllocation(this,
+ info, type);
+
+ // Create a field in the class literal holder to hold the object.
+ JField field = new JField(this, info, type.getJavahSignatureName()
+ + "_classLit", typeSpecialClassLiteralHolder, getTypeJavaLangClass(),
+ true, Disposition.FINAL);
+ typeSpecialClassLiteralHolder.fields.add(field);
+
+ // Initialize the field.
+ JFieldRef fieldRef = new JFieldRef(this, info, null, field,
+ typeSpecialClassLiteralHolder);
+ JDeclarationStatement decl = new JDeclarationStatement(this, info,
+ fieldRef, alloc);
+ JMethodBody clinitBody = (JMethodBody) typeSpecialClassLiteralHolder.methods.get(
+ 0).getBody();
+ clinitBody.getStatements().add(decl);
+
+ classLiteral = new JClassLiteral(this, type, field);
+ classLiterals.put(type, classLiteral);
+ } else {
+ // Make sure the field hasn't been pruned.
+ JField field = classLiteral.getField();
+ if (optimizationsStarted
+ && !field.getEnclosingType().fields.contains(field)) {
+ throw new InternalCompilerException(
+ "Getting a class literal whose field holder has already been pruned; type '"
+ + type + " '");
+ }
+ }
+ return classLiteral;
}
+ /**
+ * TODO: unreferenced; remove this and JClassSeed?
+ */
public JClassSeed getLiteralClassSeed(JClassType type) {
// could be interned
return new JClassSeed(this, type);
@@ -569,12 +630,12 @@
}
public JStringLiteral getLiteralString(char[] s) {
- // should conslidate so we can build a string table in output code later?
+ // should consolidate so we can build a string table in output code later?
return new JStringLiteral(this, String.valueOf(s));
}
public JStringLiteral getLiteralString(String s) {
- // should conslidate so we can build a string table in output code later?
+ // should consolidate so we can build a string table in output code later?
return new JStringLiteral(this, s);
}
@@ -640,6 +701,10 @@
return arrayType;
}
+ public JClassType getTypeClassLiteralHolder() {
+ return typeSpecialClassLiteralHolder;
+ }
+
public int getTypeId(JClassType classType) {
Integer integer = typeIdMap.get(classType);
if (integer == null) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
index 60161d5..4c0ac80 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
@@ -121,7 +121,7 @@
// override the type of the called method with the array's type
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
initDim, arrayType);
- JLiteral classLit = program.getLiteralClass(arrayType);
+ JLiteral classLit = x.getClassLiteral();
JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
JExpression dim = x.dims.get(0);
@@ -148,7 +148,7 @@
// Walk down each type from most dims to least.
JArrayType curArrayType = (JArrayType) cur;
- JLiteral classLit = program.getLiteralClass(cur);
+ JLiteral classLit = x.getClassLiterals().get(i);
classLitList.exprs.add(classLit);
JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(curArrayType));
@@ -174,7 +174,7 @@
// override the type of the called method with the array's type
JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
initValues, arrayType);
- JLiteral classLit = program.getLiteralClass(arrayType);
+ JLiteral classLit = x.getClassLiteral();
JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
JsonArray initList = new JsonArray(program);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
index 12c7248..3ddbf42 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CloneExpressionVisitor.java
@@ -47,8 +47,11 @@
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.js.JClassSeed;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
+import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
+import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import java.util.ArrayList;
+import java.util.List;
/**
* A general purpose expression cloner.
@@ -61,11 +64,15 @@
this.program = program;
}
- public JExpression cloneExpression(JExpression expr) {
+ @SuppressWarnings("unchecked")
+ public <T extends JExpression> T cloneExpression(T expr) {
if (expr == null) {
return null;
}
+ // double check that the expression is successfully cloned
+ expression = null;
+
this.accept(expr);
if (expression == null) {
@@ -73,7 +80,19 @@
null);
}
- return expression;
+ Class<T> originalClass = (Class<T>) expr.getClass();
+ return originalClass.cast(expression);
+ }
+
+ public List<JExpression> cloneExpressions(List<JExpression> exprs) {
+ if (exprs == null) {
+ return null;
+ }
+ List<JExpression> result = new ArrayList<JExpression>();
+ for (JExpression expr : exprs) {
+ result.add(cloneExpression(expr));
+ }
+ return result;
}
@Override
@@ -117,7 +136,7 @@
@Override
public boolean visit(JClassLiteral x, Context ctx) {
- expression = program.getLiteralClass(x.getRefType());
+ expression = x;
return false;
}
@@ -187,9 +206,7 @@
newMethodCall.setCannotBePolymorphic();
}
- for (JExpression arg : x.getArgs()) {
- newMethodCall.getArgs().add(cloneExpression(arg));
- }
+ newMethodCall.getArgs().addAll(cloneExpressions(x.getArgs()));
expression = newMethodCall;
return false;
@@ -198,33 +215,16 @@
@Override
public boolean visit(JMultiExpression x, Context ctx) {
JMultiExpression multi = new JMultiExpression(program, x.getSourceInfo());
- for (JExpression expr : x.exprs) {
- multi.exprs.add(cloneExpression(expr));
- }
-
+ multi.exprs.addAll(cloneExpressions(x.exprs));
expression = multi;
return false;
}
@Override
public boolean visit(JNewArray x, Context ctx) {
- JNewArray newArray = new JNewArray(program, x.getSourceInfo(),
- x.getArrayType());
-
- if (x.dims != null) {
- newArray.dims = new ArrayList<JExpression>();
- for (JExpression dim : x.dims) {
- newArray.dims.add(cloneExpression(dim));
- }
- }
- if (x.initializers != null) {
- newArray.initializers = new ArrayList<JExpression>();
- for (JExpression initializer : x.initializers) {
- newArray.initializers.add(cloneExpression(initializer));
- }
- }
-
- expression = newArray;
+ expression = new JNewArray(program, x.getSourceInfo(), x.getArrayType(),
+ cloneExpressions(x.dims), cloneExpressions(x.initializers),
+ x.getClassLiterals());
return false;
}
@@ -276,6 +276,18 @@
}
@Override
+ public boolean visit(JsniFieldRef x, Context ctx) {
+ expression = x;
+ return false;
+ }
+
+ @Override
+ public boolean visit(JsniMethodRef x, Context ctx) {
+ expression = x;
+ return false;
+ }
+
+ @Override
public boolean visit(JStringLiteral x, Context ctx) {
expression = x;
return false;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
index 98a537a..726d7f4 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -47,6 +47,7 @@
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
+import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStatement;
@@ -1548,7 +1549,20 @@
private JLiteral tryGetConstant(JVariableRef x) {
if (!lvalues.contains(x)) {
- return x.getTarget().getConstInitializer();
+ JLiteral lit = x.getTarget().getConstInitializer();
+ if (lit != null) {
+ /*
+ * Upcast the initializer so that the semantics of any arithmetic on
+ * this value is not changed.
+ */
+ // TODO(spoon): use simplifier.cast to shorten this
+ if ((x.getType() instanceof JPrimitiveType)
+ && (lit instanceof JValueLiteral)) {
+ JPrimitiveType xTypePrim = (JPrimitiveType) x.getType();
+ lit = xTypePrim.coerceLiteral((JValueLiteral) lit);
+ }
+ return lit;
+ }
}
return null;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/FixAssignmentToUnbox.java b/dev/core/src/com/google/gwt/dev/jjs/impl/FixAssignmentToUnbox.java
index 130d511..f03b87e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/FixAssignmentToUnbox.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/FixAssignmentToUnbox.java
@@ -18,6 +18,7 @@
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
+import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JModVisitor;
@@ -34,6 +35,13 @@
* simple assignment expression. Second, this visitor replaces an assignment to
* an unboxing method (<code>unbox(x) = unbox(x) + 1</code>) with an
* assignment to the underlying box (<code>x = box(unbox(x) + 1)</code>).
+ *
+ * <p>
+ * Update: GenerateJavaAST can also leave invalid AST structures of the form
+ * <code>(Foo) x = foo</code> due to the way generics are handled. This can
+ * happen when assigning into a field of a generic type. We'll go ahead and
+ * resolve that case here as well.
+ * </p>
*/
public class FixAssignmentToUnbox extends JModVisitor {
/**
@@ -101,20 +109,30 @@
@Override
public void endVisit(JBinaryOperation x, Context ctx) {
- // unbox(x) = foo -> x = box(foo)
-
if (x.getOp() != JBinaryOperator.ASG) {
return;
}
- JExpression boxed = autoboxUtils.undoUnbox(x.getLhs());
- if (boxed == null) {
+ JExpression lhs = x.getLhs();
+ JExpression boxed = autoboxUtils.undoUnbox(lhs);
+ if (boxed != null) {
+ // Assignment-to-unbox, e.g.
+ // unbox(x) = foo -> x = box(foo)
+ JClassType boxedType = (JClassType) boxed.getType();
+
+ ctx.replaceMe(new JBinaryOperation(program, x.getSourceInfo(), boxedType,
+ JBinaryOperator.ASG, boxed, autoboxUtils.box(x.getRhs(), boxedType)));
return;
}
- JClassType boxedType = (JClassType) boxed.getType();
-
- ctx.replaceMe(new JBinaryOperation(program, x.getSourceInfo(), boxedType,
- JBinaryOperator.ASG, boxed, autoboxUtils.box(x.getRhs(), boxedType)));
+ if (lhs instanceof JCastOperation) {
+ // Assignment-to-cast-operation, e.g.
+ // (Foo) x = foo -> x = foo
+ JCastOperation cast = (JCastOperation) lhs;
+ JBinaryOperation newAsg = new JBinaryOperation(program,
+ x.getSourceInfo(), x.getType(), JBinaryOperator.ASG, cast.getExpr(),
+ x.getRhs());
+ ctx.replaceMe(newAsg);
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 1bbe0ee..b47447d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -791,43 +791,40 @@
JExpression processExpression(ArrayAllocationExpression x) {
SourceInfo info = makeSourceInfo(x);
JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
- JNewArray newArray = new JNewArray(program, info, type);
if (x.initializer != null) {
- newArray.initializers = new ArrayList<JExpression>();
+ List<JExpression> initializers = new ArrayList<JExpression>();
if (x.initializer.expressions != null) {
for (Expression expression : x.initializer.expressions) {
- newArray.initializers.add(dispProcessExpression(expression));
+ initializers.add(dispProcessExpression(expression));
}
}
+ return JNewArray.createInitializers(program, info, type, initializers);
} else {
- newArray.dims = new ArrayList<JExpression>();
+ List<JExpression> dims = new ArrayList<JExpression>();
for (Expression dimension : x.dimensions) {
// can be null if index expression was empty
if (dimension == null) {
- newArray.dims.add(program.getLiteralAbsentArrayDimension());
+ dims.add(program.getLiteralAbsentArrayDimension());
} else {
- newArray.dims.add(dispProcessExpression(dimension));
+ dims.add(dispProcessExpression(dimension));
}
}
+ return JNewArray.createDims(program, info, type, dims);
}
-
- return newArray;
}
JExpression processExpression(ArrayInitializer x) {
SourceInfo info = makeSourceInfo(x);
JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
- JNewArray newArray = new JNewArray(program, info, type);
- newArray.initializers = new ArrayList<JExpression>();
+ List<JExpression> initializers = new ArrayList<JExpression>();
if (x.expressions != null) {
for (Expression expression : x.expressions) {
- newArray.initializers.add(dispProcessExpression(expression));
+ initializers.add(dispProcessExpression(expression));
}
}
-
- return newArray;
+ return JNewArray.createInitializers(program, info, type, initializers);
}
JExpression processExpression(ArrayReference x) {
@@ -1028,6 +1025,10 @@
JExpression fieldRef = new JFieldRef(program, info, instance, field,
currentClass);
+ /*
+ * Note, this may result in an invalid AST due to an LHS cast operation.
+ * We fix this up in FixAssignmentToUnbox.
+ */
return maybeCast(type, fieldRef);
}
@@ -1923,11 +1924,12 @@
}
}
- JNewArray newArray = new JNewArray(program, call.getSourceInfo(), type);
- newArray.initializers = new ArrayList<JExpression>();
+ List<JExpression> initializers = new ArrayList<JExpression>();
for (int i = n; i < args.length; ++i) {
- newArray.initializers.add(dispProcessExpression(args[i]));
+ initializers.add(dispProcessExpression(args[i]));
}
+ JNewArray newArray = JNewArray.createInitializers(program,
+ call.getSourceInfo(), type, initializers);
callArgs.add(newArray);
}
}
@@ -2444,13 +2446,13 @@
private void writeEnumValuesMethod(JEnumType type) {
// return new E[]{A,B,C};
- JNewArray newExpr = new JNewArray(program, null, program.getTypeArray(
- type, 1));
- newExpr.initializers = new ArrayList<JExpression>();
+ List<JExpression> initializers = new ArrayList<JExpression>();
for (JEnumField field : type.enumList) {
JFieldRef fieldRef = new JFieldRef(program, null, null, field, type);
- newExpr.initializers.add(fieldRef);
+ initializers.add(fieldRef);
}
+ JNewArray newExpr = JNewArray.createInitializers(program, null,
+ program.getTypeArray(type, 1), initializers);
currentMethodBody.getStatements().add(
new JReturnStatement(program, null, newExpr));
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index 7f1cf9a..b79c1f8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -133,7 +133,6 @@
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -467,13 +466,7 @@
@Override
public void endVisit(JClassLiteral x, Context ctx) {
- JsExpression classObjectAllocation = pop(); // classObjectAllocation
-
- // My seed function name
- String nameString = x.getRefType().getJavahSignatureName() + "_classlit";
- JsName classLit = topScope.declareName(nameString);
- classLits.put(x.getRefType(), classLit);
- classObjects.put(classLit, classObjectAllocation);
+ JsName classLit = names.get(x.getField());
push(classLit.makeRef());
}
@@ -489,6 +482,11 @@
return;
}
+ if (program.getTypeClassLiteralHolder() == x) {
+ // Handled in generateClassLiterals.
+ return;
+ }
+
alreadyRan.add(x);
List<JsFunction> jsFuncs = popList(x.methods.size()); // methods
@@ -993,17 +991,17 @@
vars.add(new JsVar(globalTemp));
globalStmts.add(0, vars);
- /*
- * Long lits must got at the top, they can serve as constant field
- * initializers.
- */
+ // Long lits must go at the top, they can be constant field initializers.
generateLongLiterals(vars);
- // Generate class objects.
- vars = new JsVars();
- generateClassLiterals(vars);
- if (!vars.isEmpty()) {
- globalStmts.add(vars);
+ // Class objects, but only if there are any.
+ if (x.getDeclaredTypes().contains(x.getTypeClassLiteralHolder())) {
+ // TODO: perhaps they could be constant field initializers also?
+ vars = new JsVars();
+ generateClassLiterals(vars);
+ if (!vars.isEmpty()) {
+ globalStmts.add(vars);
+ }
}
}
@@ -1103,6 +1101,11 @@
return false;
}
+ if (program.getTypeClassLiteralHolder() == x) {
+ // Handled in generateClassLiterals.
+ return false;
+ }
+
// force super type to generate code first, this is required for prototype
// chaining to work properly
if (x.extnds != null && !alreadyRan.contains(x)) {
@@ -1223,23 +1226,26 @@
return new JsBinaryOperation(JsBinaryOperator.COMMA, lhs, rhs);
}
- private void generateClassLiteral(JType type, JsVars vars) {
- JsName jsName = classLits.get(type);
- JsExpression classObjectAlloc = classObjects.get(jsName);
+ private void generateClassLiteral(JDeclarationStatement decl, JsVars vars) {
+ JField field = (JField) decl.getVariableRef().getTarget();
+ JsName jsName = names.get(field);
+ this.accept(decl.getInitializer());
+ JsExpression classObjectAlloc = pop();
JsVar var = new JsVar(jsName);
var.setInitExpr(classObjectAlloc);
vars.add(var);
}
private void generateClassLiterals(JsVars vars) {
- // Object must go first; arrays depend on it.
- JClassType objType = program.getTypeJavaLangObject();
- if (classLits.containsKey(objType)) {
- generateClassLiteral(objType, vars);
- }
- for (JType type : classLits.keySet()) {
- if (type != objType) {
- generateClassLiteral(type, vars);
+ /*
+ * Must execute in clinit statement order, NOT field order, so that back
+ * refs to super classes are preserved.
+ */
+ JMethodBody clinitBody = (JMethodBody) program.getTypeClassLiteralHolder().methods.get(
+ 0).getBody();
+ for (JStatement stmt : clinitBody.getStatements()) {
+ if (stmt instanceof JDeclarationStatement) {
+ generateClassLiteral((JDeclarationStatement) stmt, vars);
}
}
}
@@ -1642,12 +1648,6 @@
private final Map<JBlock, JsCatch> catchMap = new IdentityHashMap<JBlock, JsCatch>();
- /**
- * Must preserve order so that superclass literals generate before subclasses.
- */
- private final Map<JType, JsName> classLits = new LinkedHashMap<JType, JsName>();
-
- private final Map<JsName, JsExpression> classObjects = new IdentityHashMap<JsName, JsExpression>();
private final Map<JClassType, JsScope> classScopes = new IdentityHashMap<JClassType, JsScope>();
/**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
index 6ceec64..a9e3662 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
@@ -24,6 +24,7 @@
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JCastOperation;
+import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JExpression;
@@ -580,6 +581,15 @@
}
@Override
+ public boolean visit(JClassLiteral x, Context ctx) {
+ // Works just like JFieldRef to a static field.
+ JField field = x.getField();
+ rescue(field.getEnclosingType(), true, false);
+ rescue(field);
+ return true;
+ }
+
+ @Override
public boolean visit(JFieldRef ref, Context ctx) {
JField target = ref.getField();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index d304a7f..10daca0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -17,6 +17,7 @@
import com.google.gwt.dev.jjs.ast.CanBeAbstract;
import com.google.gwt.dev.jjs.ast.Context;
+import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JCastOperation;
@@ -194,6 +195,8 @@
JExpression lhs = x.getLhs();
if (lhs instanceof JVariableRef) {
addAssignment(((JVariableRef) lhs).getTarget(), x.getRhs());
+ } else {
+ assert lhs instanceof JArrayRef;
}
}
}
diff --git a/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/ClassLiteralHolder.java b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/ClassLiteralHolder.java
new file mode 100644
index 0000000..882c209
--- /dev/null
+++ b/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/ClassLiteralHolder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 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.lang;
+
+/**
+ * This is a magic class the compiler uses to contain synthetic fields for all
+ * class literals. NOTE: this is not a CODE GEN class because we want it to be
+ * eagerly optimized.
+ */
+final class ClassLiteralHolder {
+}
diff --git a/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java b/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java
index e297690..e8fecb7 100644
--- a/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java
+++ b/dev/linux/src/com/google/gwt/dev/BootStrapPlatform.java
@@ -33,6 +33,11 @@
* so SWT's Browser object can use it.
*/
public static void init() {
+ String home = System.getenv("HOME");
+ if (home == null || home.length() == 0) {
+ System.err.println("The HOME environment variable must be defined.");
+ System.exit(1);
+ }
MozillaInstall mozInstall = MozillaInstall.find();
if (mozInstall == null) {
System.err.println("** Unable to find a usable Mozilla install **");
diff --git a/distro-source/core/src/release_notes.html b/distro-source/core/src/release_notes.html
index 4bbf4fb..36b4839 100644
--- a/distro-source/core/src/release_notes.html
+++ b/distro-source/core/src/release_notes.html
@@ -28,7 +28,8 @@
<body>
<h1>Google Web Toolkit Release Notes</h1>
<ul>
- <li><a href="#Release_Notes_Current">@GWT_VERSION@ (RC)</a></li>
+ <li><a href="#Release_Notes_Current">@GWT_VERSION@</a></li>
+ <li><a href="#Release_Notes_1_5_0">1.5.0 (RC)</a></li>
<li><a href="#Release_Notes_1_4_60">1.4.60</a></li>
<li><a href="#Release_Notes_1_4_59">1.4.59 (RC2)</a></li>
<li><a href="#Release_Notes_1_4_10">1.4.10 (RC)</a></li>
@@ -43,7 +44,48 @@
<hr/>
<a name="Release_Notes_Current"></a>
- <h2>Release Notes for @GWT_VERSION@ (RC)</h2>
+ <h2>Release Notes for @GWT_VERSION@</h2>
+ <h3>Support for Standards Mode</h3>
+ <p>
+ GWT 1.5 adds significantly more support for standards mode applications, but some widgets (especially those with table based layouts) may not behave as expected. The low level standards mode bugs (such as with <code>getAbsoluteLeft/Top()</code>) have been addressed, but some of the constructs that our widgets rely on do not work in standards mode. For example, you cannot set the height and width of a widget relative to its parent if its parent is a table cell, and <code>StackPanel</code> takes up much more vertical space than it should in Internet Explorer. All of our samples have been reverted back to quirks mode, and the <code>applicationCreator</code> defaults to quirks mode when creating a new GWT app.
+ </p>
+ <p>
+You can still use standards mode for your GWT app, but please be aware that you may notice some layout issues. If you are switching an app from quirks mode to standards mode, your CSS styles might be applied differently, which could also affect your application. We will continue to address standards mode support in future GWT releases.
+ </p>
+ <h3>Potentially breaking changes and fixes</h3>
+ <ul>
+ <li><code>DOM.eventGetClientX/Y()</code> now takes into account the margin and border of the body element</li>
+ <li>In hosted mode, all <code>DOM.eventGetXXX()</code> methods now assert that the requested attribute is reliable across all supported browsers. This means that attempting to retrieve an attribute for an event that does not support that attribute will now throw an assertion error instead of returning a coerced value. Most notably, the click event throws an assertion error if you attempt to get the mouse button that was clicked.</li>
+ <li>The return value of <code>DOM.eventGetXXX()</code> methods are now coerced to 0 instead of -1 in web mode. In hosted mode, an assertion error will be thrown if the attribute is not defined for the given event, as described in the previous bullet.</li>
+ <li>Opera specific code has been upgraded to work with Opera 9.5, but may not work with older versions of Opera as we only support the most recent release. Specifically, some widgets may not be able to receive focus.</li>
+ <li>Calls to <code>History.newItem()</code> now trigger an <code>onHistoryChanged()</code> event synchronously instead of asynchronously</li>
+ </ul>
+ <h3>General Enhancements</h3>
+ <ul>
+ <li>Added support for the <code>contextmenu</code> event, which allows users to detect and override the browser's default context menu</li>
+ <li>Improved performance of <code>NumberFormat</code></li>
+ <li>Added support for altering the number of decimals in a currency in <code>NumberFormat</code></li>
+ <li>Improved performance of Animations</li>
+ <li>Improved the appearance of the default GWT style themes</li>
+ <li>Improved the Showcase sample with more robust examples and more language translations</li>
+ <li><code>FormPanel</code> can now wrap an existing form and still submit it to a hidden iframe</li>
+ </ul>
+ <h3>Fixed Issues</h3>
+ <ul>
+ <li><code>DOM.getAbsoluteLeft/Top()</code> and <code>DOM.eventGetClientX/Y()</code> no longer log an exception to the console in Firefox 3</li>
+ <li>Fixed a memory leak in Internet Explorer</li>
+ <li><code>DOM.getAbsoluteLeft/Top()</code> now takes into account the margin and border of the target element in Safari 3</li>
+ <li>Fixed some bugs associated with history support</li>
+ </ul>
+ <p>
+ See the GWT issue tracker for
+ <a href="http://code.google.com/p/google-web-toolkit/issues/list?can=1&q="status:Fixed+OR+status:FixedNotReleased"+milestone:1_5_RC2&num=1000">
+ the complete list of bug fixes and enhancements</a> in this release.
+ </p>
+
+ <hr/>
+ <a name="Release_Notes_1_5_0"></a>
+ <h2>Release Notes for 1.5.0 (RC)</h2>
<p>
This release candidate is, in a word, huge. Rather than including all the details here, please see <a href="http://code.google.com/docreader/#p(google-web-toolkit-doc-1-5)t(Whatsnewin15)">What's New in GWT 1.5?</a> for full details. The main thing you'll want to know is that GWT 1.5 supports the Java 5 language features (generics, enumerated types, annotations, etc.). But check out the full notes, because there's a lot of great stuff!
</p>
diff --git a/distro-source/linux/build.xml b/distro-source/linux/build.xml
index 968bc5c..4240f6c 100755
--- a/distro-source/linux/build.xml
+++ b/distro-source/linux/build.xml
@@ -66,7 +66,7 @@
to handle permissions and symlinks correctly.
-->
<mkdir dir="${gwt.build.staging}" />
- <exec executable="tar">
+ <exec executable="tar" failonerror="true">
<arg value="-xpjf" />
<arg file="${project.dist}" />
<arg value="-C" />
diff --git a/distro-source/mac/build.xml b/distro-source/mac/build.xml
index 436fdfab1..c7a6a76 100755
--- a/distro-source/mac/build.xml
+++ b/distro-source/mac/build.xml
@@ -66,7 +66,7 @@
to handle permissions and symlinks correctly.
-->
<mkdir dir="${gwt.build.staging}" />
- <exec executable="tar">
+ <exec executable="tar" failonerror="true">
<arg value="-xpzf" />
<arg file="${project.dist}" />
<arg value="-C" />
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
index e950b20..0bd3fb9 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
@@ -36,6 +36,7 @@
addIssue(new Issue2331());
addIssue(new Issue2338());
addIssue(new Issue2339());
+ addIssue(new Issue2390());
addIssue(new Issue1169());
addIssue(new Issue2392());
addIssue(new Issue2443());
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java
new file mode 100644
index 0000000..dd0bdf9
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2008 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.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.RadioButton;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Focusing on the document body while a modal {@link PopupPanel} is visible
+ * causes Internet Explorer to disappear to the back of the UI stack. Also,
+ * modal PopupPanels do not prevent the user from focusing on input elements.
+ */
+public class Issue2390 extends AbstractIssue {
+ @Override
+ public Widget createIssue() {
+ // A label indicating where to click to focus the body
+ Label label = new Label("Click to the right of this box while the popup "
+ + "is visible >>>");
+ label.getElement().getStyle().setProperty("border", "1px solid red");
+
+ // Create a modal PopupPanel
+ final PopupPanel popup = new PopupPanel(false, true);
+ popup.setWidget(new Button("Hide Popup", new ClickListener() {
+ public void onClick(Widget sender) {
+ popup.hide();
+ }
+ }));
+
+ // Create a button to show the PopupPanel
+ Button showPopupButton = new Button("Show Popup", new ClickListener() {
+ public void onClick(Widget sender) {
+ popup.center();
+ }
+ });
+
+ // Create a bunch of input elements to test
+ // TODO(jlabanca): divide this out into a separate issue 2707
+ CheckBox checkBox = new CheckBox("CheckBox");
+ RadioButton radio1 = new RadioButton("grouping", "RadioButton1");
+ RadioButton radio2 = new RadioButton("grouping", "RadioButton2");
+ ListBox list = new ListBox();
+ list.addItem("test1");
+ list.addItem("test2");
+ list.addItem("test3");
+ list.addItem("test4");
+ TextBox textBox = new TextBox();
+
+ // Combine all of the elements into a panel
+ VerticalPanel layout = new VerticalPanel();
+ layout.add(label);
+ layout.add(showPopupButton);
+ layout.add(textBox);
+ layout.add(checkBox);
+ layout.add(radio1);
+ layout.add(radio2);
+ layout.add(list);
+ return layout;
+ }
+
+ @Override
+ public String getInstructions() {
+ return "First, make sure you have another program (such as another "
+ + "instance of the IE) running on the system. Click the button below "
+ + "to show the PopupPanel, then click to right of the red box. The "
+ + "browser should not be sent to the back of the OS UI stack because the "
+ + "document body is blurred. Also, make sure that the user cannot "
+ + "interact with the input elements while the popup is visible.";
+ }
+
+ @Override
+ public String getSummary() {
+ return "IE dissappears when clicking outside a modal PopupPanel";
+ }
+
+ @Override
+ public boolean hasCSS() {
+ return false;
+ }
+}
diff --git a/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html b/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html
index cb6e471..7df5ec8 100644
--- a/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html
+++ b/samples/dynatable/src/com/google/gwt/sample/dynatable/public/DynaTable.html
@@ -1,6 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- -->
<!-- Copyright 2008 Google Inc. -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
diff --git a/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html b/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html
index 245fbf1..eeedb3c 100644
--- a/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html
+++ b/samples/hello/src/com/google/gwt/sample/hello/public/Hello.html
@@ -1,6 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- -->
<!-- Copyright 2008 Google Inc. -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
diff --git a/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html b/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html
index 452fe60..fa1e8cc 100644
--- a/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html
+++ b/samples/i18n/src/com/google/gwt/sample/i18n/public/I18N.html
@@ -1,6 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- -->
<!-- Copyright 2008 Google Inc. -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
diff --git a/samples/json/src/com/google/gwt/sample/json/public/JSON.html b/samples/json/src/com/google/gwt/sample/json/public/JSON.html
index ebb3bf2..b3367e6 100644
--- a/samples/json/src/com/google/gwt/sample/json/public/JSON.html
+++ b/samples/json/src/com/google/gwt/sample/json/public/JSON.html
@@ -1,6 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- -->
<!-- Copyright 2008 Google Inc. -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml b/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml
index 2f4b796..d25810a 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml
@@ -1,30 +1,27 @@
<module>
- <!-- Inherit the core Web Toolkit stuff. -->
- <inherits name="com.google.gwt.core.Core"/>
- <inherits name='com.google.gwt.user.User'/>
- <inherits name="com.google.gwt.i18n.I18N"/>
- <inherits name="com.google.gwt.user.theme.standard.Standard"/>
- <inherits name="com.google.gwt.user.theme.chrome.ChromeResources"/>
- <inherits name="com.google.gwt.user.theme.dark.DarkResources"/>
+ <!-- Inherit the core Web Toolkit stuff. -->
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name='com.google.gwt.user.User'/>
+ <inherits name="com.google.gwt.i18n.I18N"/>
+ <inherits name="com.google.gwt.user.theme.standard.StandardResources"/>
+ <inherits name="com.google.gwt.user.theme.chrome.ChromeResources"/>
+ <inherits name="com.google.gwt.user.theme.dark.DarkResources"/>
- <!-- Enable debug ID. -->
- <inherits name="com.google.gwt.user.Debug"/>
- <set-property name="gwt.enableDebugId" value="true"/>
+ <!-- Enable debug ID. -->
+ <inherits name="com.google.gwt.user.Debug"/>
+ <set-property name="gwt.enableDebugId" value="true"/>
- <!-- Use a generator to create the source code -->
- <generate-with class="com.google.gwt.sample.showcase.generator.ShowcaseGenerator">
- <when-type-assignable class="com.google.gwt.sample.showcase.client.Showcase.GeneratorInfo" />
- </generate-with>
+ <!-- Use a generator to create the source code -->
+ <generate-with class="com.google.gwt.sample.showcase.generator.ShowcaseGenerator">
+ <when-type-assignable class="com.google.gwt.sample.showcase.client.Showcase.GeneratorInfo" />
+ </generate-with>
- <!-- Specify the app entry point class. -->
- <entry-point class='com.google.gwt.sample.showcase.client.Showcase'/>
+ <!-- Specify the app entry point class. -->
+ <entry-point class='com.google.gwt.sample.showcase.client.Showcase'/>
- <!-- Internationalization support. -->
- <extend-property name="locale" values="en"/>
- <extend-property name="locale" values="ar"/>
- <extend-property name="locale" values="fr"/>
- <extend-property name="locale" values="zh"/>
-
- <!-- Include style sheets. -->
- <stylesheet src="standard/Showcase.css"/>
+ <!-- Internationalization support. -->
+ <extend-property name="locale" values="en"/>
+ <extend-property name="locale" values="ar"/>
+ <extend-property name="locale" values="fr"/>
+ <extend-property name="locale" values="zh"/>
</module>
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
index 62e53e7..3f422b6 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
@@ -27,7 +27,6 @@
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckPanel;
import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.SourcesTabEvents;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TabListener;
@@ -78,7 +77,7 @@
/**
* The static loading image displayed when loading CSS or source code.
*/
- private static Image loadingImage;
+ private static String loadingImage;
/**
* An instance of the constants.
@@ -327,11 +326,11 @@
final RequestCallback callback) {
// Show the loading image
if (loadingImage == null) {
- loadingImage = new Image("images/loading.gif");
+ loadingImage = "<img src=\"images/loading.gif\">";
}
target.setDirection(HasDirection.Direction.LTR);
DOM.setStyleAttribute(target.getElement(), "textAlign", "left");
- target.setHTML(" " + loadingImage.toString());
+ target.setHTML(" " + loadingImage);
// Request the contents of the file
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
index 0819baf..e56d898 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
@@ -172,17 +172,7 @@
/**
* The {@link Application}.
*/
- private Application app;
-
- /**
- * When the user selects a {@link TreeItem} from the main menu, we
- * synchronously change the current example and add a history token for
- * history support. However, adding the history token causes the history
- * changed event to fire, which normally selects the associated menu item and
- * displays the example. We don't want to repeat this twice, so we use a
- * boolean to indicate that we want to ignore the history changed event.
- */
- private boolean ignoreNextHistoryEvent = false;
+ private Application app = new Application();
/**
* A mapping of history tokens to their associated menu items.
@@ -204,41 +194,29 @@
// Create the constants
ShowcaseConstants constants = (ShowcaseConstants) GWT.create(ShowcaseConstants.class);
+ // Swap out the style sheets for the RTL versions if needed.
+ updateStyleSheets();
+
// Create the application
- app = new Application();
setupTitlePanel(constants);
setupMainLinks(constants);
setupOptionsPanel();
setupMainMenu(constants);
- // Swap out the style sheets for the RTL versions if needed. We need to do
- // this after the app is loaded because the app will setup the layout based
- // on the width of the main menu, which is defined in the style sheet. If
- // we swap the style sheets first, the app may load without any style sheet
- // to define the main menu width, because the RTL version is still being
- // loaded. Note that we are basing the layout on the width defined in the
- // LTR version, so both versions should use the same width for the main nav
- // menu.
- updateStyleSheets();
-
// Setup a history listener to reselect the associate menu item
final HistoryListener historyListener = new HistoryListener() {
public void onHistoryChanged(String historyToken) {
- // Ignore the event if the user selected the content from the main menu
- if (ignoreNextHistoryEvent) {
- ignoreNextHistoryEvent = false;
- return;
- }
-
TreeItem item = itemTokens.get(historyToken);
- if (item != null) {
- // Select the associated TreeItem
- app.getMainMenu().setSelectedItem(item, false);
- app.getMainMenu().ensureSelectedItemVisible();
-
- // Show the associated ContentWidget
- displayContentWidget(itemWidgets.get(item));
+ if (item == null) {
+ item = app.getMainMenu().getItem(0).getChild(0);
}
+
+ // Select the associated TreeItem
+ app.getMainMenu().setSelectedItem(item, false);
+ app.getMainMenu().ensureSelectedItemVisible();
+
+ // Show the associated ContentWidget
+ displayContentWidget(itemWidgets.get(item));
}
};
History.addHistoryListener(historyListener);
@@ -248,36 +226,22 @@
public void onMenuItemSelected(TreeItem item) {
ContentWidget content = itemWidgets.get(item);
if (content != null && !content.equals(app.getContent())) {
- // Show the new example
- displayContentWidget(content);
-
- // Update the history token, but ignore the next history event
- ignoreNextHistoryEvent = true;
History.newItem(getContentWidgetToken(content));
}
}
});
- // When the style sheet has loaded, attach the app
- StyleSheetLoader.waitForStyleSheet(getCurrentReferenceStyleName(),
- new Command() {
- public void execute() {
- if (!app.isAttached()) {
- RootPanel.get().add(app);
- }
-
- // Show the initial example
- String initToken = History.getToken();
- if (initToken.length() > 0) {
- historyListener.onHistoryChanged(initToken);
- } else {
- // Use the first token available
- TreeItem firstItem = app.getMainMenu().getItem(0).getChild(0);
- app.getMainMenu().setSelectedItem(firstItem, true);
- app.getMainMenu().ensureSelectedItemVisible();
- }
- }
- });
+ // Show the initial example
+ String initToken = History.getToken();
+ if (initToken.length() > 0) {
+ historyListener.onHistoryChanged(initToken);
+ } else {
+ // Use the first token available
+ TreeItem firstItem = app.getMainMenu().getItem(0).getChild(0);
+ app.getMainMenu().setSelectedItem(firstItem, false);
+ app.getMainMenu().ensureSelectedItemVisible();
+ displayContentWidget(itemWidgets.get(firstItem));
+ }
}
/**
@@ -307,10 +271,11 @@
* Get the style name of the reference element defined in the current GWT
* theme style sheet.
*
+ * @param prefix the prefix of the reference style name
* @return the style name
*/
- private String getCurrentReferenceStyleName() {
- String gwtRef = "gwt-Reference-" + CUR_THEME;
+ private String getCurrentReferenceStyleName(String prefix) {
+ String gwtRef = prefix + "-Reference-" + CUR_THEME;
if (LocaleInfo.getCurrentLocale().isRTL()) {
gwtRef += "-rtl";
}
@@ -452,6 +417,11 @@
private void setupOptionsPanel() {
VerticalPanel vPanel = new VerticalPanel();
vPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ vPanel.getElement().setAttribute("align", "left");
+ } else {
+ vPanel.getElement().setAttribute("align", "right");
+ }
app.setOptionsWidget(vPanel);
// Add the option to change the locale
@@ -536,6 +506,7 @@
}
// Find existing style sheets that need to be removed
+ boolean styleSheetsFound = false;
final HeadElement headElem = StyleSheetLoader.getHeadElement();
final List<Element> toRemove = new ArrayList<Element>();
NodeList<Node> children = headElem.getChildNodes();
@@ -545,6 +516,7 @@
Element elem = Element.as(node);
if (elem.getTagName().equalsIgnoreCase("link")
&& elem.getPropertyString("rel").equalsIgnoreCase("stylesheet")) {
+ styleSheetsFound = true;
String href = elem.getPropertyString("href");
// If the correct style sheets are already loaded, then we should have
// nothing to remove.
@@ -557,7 +529,7 @@
}
// Return if we already have the correct style sheets
- if (toRemove.size() == 0) {
+ if (styleSheetsFound && toRemove.size() == 0) {
return;
}
@@ -572,7 +544,19 @@
// Load the GWT theme style sheet
String modulePath = GWT.getModuleBaseURL();
Command callback = new Command() {
+ /**
+ * The number of style sheets that have been loaded and executed this
+ * command.
+ */
+ private int numStyleSheetsLoaded = 0;
+
public void execute() {
+ // Wait until all style sheets have loaded before re-attaching the app
+ numStyleSheetsLoaded++;
+ if (numStyleSheetsLoaded < 2) {
+ return;
+ }
+
// Different themes use different background colors for the body
// element, but IE only changes the background of the visible content
// on the page instead of changing the background color of the entire
@@ -584,10 +568,11 @@
}
};
StyleSheetLoader.loadStyleSheet(modulePath + gwtStyleSheet,
- getCurrentReferenceStyleName(), callback);
+ getCurrentReferenceStyleName("gwt"), callback);
// Load the showcase specific style sheet after the GWT theme style sheet so
// that custom styles supercede the theme styles.
- StyleSheetLoader.loadStyleSheet(modulePath + showcaseStyleSheet);
+ StyleSheetLoader.loadStyleSheet(modulePath + showcaseStyleSheet,
+ getCurrentReferenceStyleName("Application"), callback);
}
}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties
index 6238f61..a049c0b 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants.properties
@@ -103,7 +103,7 @@
cwDisclosurePanelFormAdvancedCriteria = Advanced Criteria
cwDisclosurePanelFormDescription = Description:
cwDisclosurePanelFormGender = Gender:
-cwDisclosurePanelFormGenderOptions = male, female, both
+cwDisclosurePanelFormGenderOptions = male, female
cwDisclosurePanelFormLocation = Location:
cwDisclosurePanelFormName = Name:
cwDisclosurePanelFormTitle = <b>Enter Search Criteria</b>
@@ -128,7 +128,7 @@
cwFlexTableDetails = This is a FlexTable that supports <B>colspans</B> and <B>rowspans</B>. You can use it to format your page or as a special purpose table.
cwFlexTableRemoveRow = Remove a row
cwFlowPanelName = Flow Panel
-cwFlowPanelDescription = A Flow Panel lets its content flow naturally. Move the splitter bar to see how the content wraps around as needed.
+cwFlowPanelDescription = A Flow Panel lets its content flow naturally.
cwFlowPanelItem = Item
cwFrameName = Frames
cwFrameDescription = Embed content from other sites into your page using the Frame, a wrapper around an IFRAME element.
@@ -150,7 +150,7 @@
cwListBoxCategories = Cars, Sports, Vacation Spots
cwListBoxSelectAll = <b>Select all that apply:</b>
cwListBoxSelectCategory = <b>Select a category:</b>
-cwListBoxSports = Baseball, Basketball, Football, Hockey, Lacrosse, Polo, Soccor, Softball, Water Polo
+cwListBoxSports = Baseball, Basketball, Football, Hockey, Lacrosse, Polo, Soccer, Softball, Water Polo
cwListBoxVacations = Carribean, Grand Canyon, Paris, Italy, New York, Las Vegas
cwMenuBarName = Menu Bar
cwMenuBarDescription = The Menu Bar can be used to navigate through many options. It also supports nested sub menus.
@@ -184,13 +184,14 @@
cwRadioButtonColors = blue, red, yellow, green
cwRadioButtonSelectColor = <b>Select your favorite color:</b>
cwRadioButtonSelectSport = <b>Select your favorite sport:</b>
-cwRadioButtonSports = Baseball, Basketball, Football, Hockey, Soccor, Water Polo
+cwRadioButtonSports = Baseball, Basketball, Football, Hockey, Soccer, Water Polo
cwRichTextName = Rich Text
cwRichTextDescription = The Rich Text Area is supported on all major browsers, and will fall back gracefully to the level of functionality supported on each.
cwStackPanelName = Stack Panel
cwStackPanelDescription = The StackPanel stacks its children vertically, displaying only one at a time, with a header for each child which the user can click to display. This is useful for vertical menu systems.
cwStackPanelContactsHeader = Contacts
cwStackPanelContacts = Benoit Mandelbrot, Albert Einstein, Rene Descartes, Bob Saget, Ludwig von Beethoven, Richard Feynman, Alan Turing, John von Neumann
+cwStackPanelContactsEmails = benoit@example.com, albert@example.com, rene@example.com, bob@example.com, ludwig@example.com, richard@example.com, alan@example.com, john@example.com
cwStackPanelMailHeader = Mail
cwStackPanelMailFolders = Inbox, Drafts, Templates, Sent, Trash
cwStackPanelFiltersHeader = Filters
@@ -209,6 +210,20 @@
cwTreeDynamicLabel = <b>Dynamic Tree:</b>
cwTreeItem = Item
cwTreeStaticLabel = <b>Static Tree:</b>
+cwTreeComposers = Beethoven, Brahms, Mozart
+cwTreeConcertos = Concertos
+cwTreeQuartets = Quartets
+cwTreeSonatas = Sonatas
+cwTreeSymphonies = Symphonies
+cwTreeBeethovenWorkConcertos = No. 1 - C, No. 2 - B-Flat Major, No. 3 - C Minor, No. 4 - G Major, No. 5 - E-Flat Major
+cwTreeBeethovenWorkQuartets = Six String Quartets, Three String Quartets, Grosse Fugue for String Quartets
+cwTreeBeethovenWorkSonatas = Sonata in A Minor, Sonata in F Major
+cwTreeBeethovenWorkSymphonies = No. 2 - D Major, No. 2 - D Major, No. 3 - E-Flat Major, No. 4 - B-Flat Major, No. 5 - C Minor, No. 6 - F Major, No. 7 - A Major, No. 8 - F Major, No. 9 - D Minor
+cwTreeBrahmsWorkConcertos = Violin Concerto, Double Concerto - A Minor, Piano Concerto No. 1 - D Minor, Piano Concerto No. 2 - B-Flat Major
+cwTreeBrahmsWorkQuartets = Piano Quartet No. 1 - G Minor, Piano Quartet No. 2 - A Major, Piano Quartet No. 3 - C Minor, String Quartet No. 3 - B-Flat Minor
+cwTreeBrahmsWorkSonatas = Two Sonatas for Clarinet - F Minor, Two Sonatas for Clarinet - E-Flat Major
+cwTreeBrahmsWorkSymphonies = No. 1 - C Minor, No. 2 - D Minor, No. 3 - F Major, No. 4 - E Minor
+cwTreeMozartWorkConcertos = Piano Concerto No. 12, Piano Concerto No. 17, Clarinet Concerto, Violin Concerto No. 5, Violin Concerto No. 4
cwVerticalPanelName = Vertical Panel
cwVerticalPanelDescription = A Vertical Panel aligns its content vertically without allowing it to wrap. Resize the page to see how the content maintains its vertical alignment.
cwVerticalPanelButton = Button
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties
index d629b09..6fcfa36 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_ar.properties
@@ -96,7 +96,7 @@
cwDisclosurePanelFormAdvancedCriteria = معايير متقدمة
cwDisclosurePanelFormDescription = الوصف:
cwDisclosurePanelFormGender = الجنس:
-cwDisclosurePanelFormGenderOptions = ذكر, انثى, كلاهما
+cwDisclosurePanelFormGenderOptions = ذكر, انثى
cwDisclosurePanelFormLocation = موقع:
cwDisclosurePanelFormName = اسم:
cwDisclosurePanelFormTitle = <b>ادخال معايير البحث</b>
@@ -121,7 +121,7 @@
cwFlexTableDetails = هذا هو جدول فلكس والذي يدعم <b>colspan</b> و <b>rowspans</b>. يمكنك تنسيق الصفحة الخاصة بك كجدول من نوع خاص
cwFlexTableRemoveRow = احذف صف
cwFlowPanelName = لوحة الانسياب
-cwFlowPanelDescription = لوحة الانسياب تتيح لمحتوياتها الانسياب بشكل طبيعي. قم بتحريك شريط الانقسام لتلاحظ كيف ان المحتويات تغير توزيعها تلقائيا
+cwFlowPanelDescription = لوحة الانسياب تتيح لمحتوياتها الانسياب بشكل طبيعي.
cwFlowPanelItem = عنصر
cwFrameName = اطارات
cwFrameDescription = قم بتضمين محتويات من موقع اخر داخل الصفحة الخاصة بك باستخدام الاطار الذي يمثل غلاف حول عنصر IFRAME
@@ -184,6 +184,7 @@
cwStackPanelDescription =ان لوح التكديس يكدس محتوياته عموديا ويعرض واحدة منها فقط في الوقت الواحد مع ترويسة لكل من المحتويات والتي ممكن النقر عليها لعرضها كاملة. ان هذا مفيد للقوائم العمودية.
cwStackPanelContactsHeader = جهات الاتصال
cwStackPanelContacts = بينويت ماندلبروت , البرت اينشتاين , رينيه ديكارت , بوب ساجيت, لودفيغ فون بيتهوفن , ريتشارد فاينمان , الآن تورنج , جون فون نيومان
+cwStackPanelContactsEmails = benoit@example.com, albert@example.com, rene@example.com, bob@example.com, ludwig@example.com, richard@example.com, alan@example.com, john@example.com
cwStackPanelMailHeader = البريد
cwStackPanelMailFolders = البريد الوارد , مسودات , قوالب , أرسلت , المهملات
cwStackPanelFiltersHeader = مرشحات
@@ -216,4 +217,20 @@
cwAnimationCancel = الغاء
cwAnimationOptions = خيارات الرسوم المتحركه
cwDecoratorPanelName = لوح الزخرفة
-cwDecoratorPanelDescription = اضافة زوايا مدورة لأي ودجة باستخدام لوح الزخرفة.
\ No newline at end of file
+cwDecoratorPanelDescription = اضافة زوايا مدورة لأي ودجة باستخدام لوح الزخرفة.
+
+# TODO: get official translations
+cwTreeComposers = بيتهوفن ,برامز ,موزارت
+cwTreeConcertos = القطع الموسيقيه
+cwTreeQuartets = الرباعيات
+cwTreeSonatas = السوناتات
+cwTreeSymphonies = السمفونيات
+cwTreeBeethovenWorkConcertos = رقم 1 -- ج ,رقم 2 -- ب - شقة كبيرة ,رقم 3 -- ج طفيفة ,رقم 4 -- ز الرئيسية ,رقم 5 -- ة - شقة الرئيسية
+cwTreeBeethovenWorkQuartets = الرباعيات ستة الخيط ,الخيط الرباعيات الثلاث, Grosse فقدان الذاكرة لسلسلة الرباعيات
+cwTreeBeethovenWorkSonatas = سوناتا فى قاصر ,و في سوناتا الرئيسية
+cwTreeBeethovenWorkSymphonies = رقم 2 -- د الرئيسية ,رقم 2 -- د الرئيسية ,رقم 3 -- ة - شقة كبيرة ,رقم 4 -- ب - شقة كبيرة ,رقم 5 -- ج طفيفة ,رقم 6 -- و الرئيسية ,رقم 7 -- رئيسي ,رقم 8 -- و الرئيسية ,العدد 9 -- د طفيفة
+cwTreeBrahmsWorkConcertos = كونشرتو الكمان ,اي ضعف كونشرتو -- قاصر ,كونشرتو البيانو رقم 1 -- مد طفيفة ,كونشرتو البيانو رقم 2 -- ب - شقة الرئيسية
+cwTreeBrahmsWorkQuartets = الرباعيه البيانو رقم 1 -- ز طفيفة ,المجموعة الرباعيه بيانو رقم 2 -- رئيسي ,المجموعة الرباعيه البيانو رقم 3 -- ج طفيفة ,رباعي رقم 3 -- ب - شقة بسيطة
+cwTreeBrahmsWorkSonatas = اثنين السوناتات لكلارينيت -- و قاصر ,لاثنين من السوناتات كلارينيت -- ة - شقة الرئيسية
+cwTreeBrahmsWorkSymphonies = رقم 1 -- ج طفيفة ,رقم 2 -- د طفيفة ,رقم 3 -- و الرئيسية ,رقم 4 -- ة طفيفة
+cwTreeMozartWorkConcertos = كونشرتو البيانو رقم 12 , كونشرتو البيانو رقم 17 , كونشرتو الكلارينت , كونشرتو الكمان رقم 5 , رقم 4 كونشرتو الكمان
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties
index 47569c1..183d0c9 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_fr.properties
@@ -44,7 +44,7 @@
cwBasicTextDescription = GWT inclut le complément standard des widgets de saisie de texte, ou chacun de ceux-ci supportent les evenements du clavier et de selectionnement que vous pouvez utliliser pour contrôler la saisie de texte. En particulier, notez que la plage de sélection pour chaque widget est mise à jour chaque fois que vous appuyez sur une touche.
cwBasicTextAreaLabel = <b>Zone de texte:</b>
cwBasicTextNormalLabel = <b>Zone de texte normale:</b>
-cwBasicTextPasswordLabel = <b>Zone de texte <<mot de passe>>:</b>
+cwBasicTextPasswordLabel = <b>Zone de texte «mot de passe»:</b>
cwBasicTextReadOnly = lecture seulement
cwBasicTextSelected = Sélectionné
cwCheckBoxName = Case à cocher
@@ -103,7 +103,7 @@
cwDisclosurePanelFormAdvancedCriteria = Critères avancés
cwDisclosurePanelFormDescription = Description:
cwDisclosurePanelFormGender = Sexe:
-cwDisclosurePanelFormGenderOptions = masculin, féminin, les deux
+cwDisclosurePanelFormGenderOptions = masculin, féminin
cwDisclosurePanelFormLocation = Lieu:
cwDisclosurePanelFormName = Nom:
cwDisclosurePanelFormTitle = <b>Saisissez des critères de recherche</b>
@@ -128,7 +128,7 @@
cwFlexTableDetails = Ceci est un tableau flexible qui prend en charge les <B>plages de colonne</B> et les <B>plages de ligne</B>. Vous pouvez l'utiliser pour mettre en forme votre page ou en tant que tableau réservé à un but précis.
cwFlexTableRemoveRow = Supprimer une ligne
cwFlowPanelName = Panneau déroulant
-cwFlowPanelDescription = Dans un panneau déroulant, le contenu défile de manière continue. Déplacez la barre de fractionnement pour voir comment le contenu est renvoyé à la ligne si nécessaire.
+cwFlowPanelDescription = Dans un panneau déroulant, le contenu défile de manière continue.
cwFlowPanelItem = Élément
cwFrameName = Cadres
cwFrameDescription = Intégrez le contenu d'autres sites dans votre page à l'aide de l'encadrement, une enveloppe autour d'un élément IFRAME.
@@ -191,6 +191,7 @@
cwStackPanelDescription = Le StackPanel piles verticalement ses enfants, affichant seulement un à la fois, avec une tête pour chaque enfant dont l'utilisateur peut cliquer pour défiler le panneau correspondant à l'en-tête. Cette option est utile pour les systèmes de menu verticale.
cwStackPanelContactsHeader = Contacts
cwStackPanelContacts = Benoit Mandelbrot, Albert Einstein, René Descartes, Bob Saget, Ludwig von Beethoven, Richard Feynman, Alan Turing, John de von Neumann
+cwStackPanelContactsEmails = benoit@example.com, albert@example.com, rene@example.com, bob@example.com, ludwig@example.com, richard@example.com, alan@example.com, john@example.com
cwStackPanelMailHeader = Mail
cwStackPanelMailFolders = Boîte de réception, Brouillons, Formulaires, Messages envoyés, Corbeille
cwStackPanelFiltersHeader = Filtres
@@ -215,3 +216,19 @@
cwVerticalSplitPanelName = Panneau à fractionnement vertical
cwVerticalSplitPanelDescription = Donne aux utilisateurs la possibilité de décider de la manière dont l'espace doit être alloué.
cwVerticalSplitPanelText = Voici un texte permettant de voir comment le contenu situé de chaque côté de la barre de fractionnement se défile.
+
+# TODO: get official translations
+cwTreeComposers = Beethoven, Brahms, Mozart
+cwTreeConcertos = Concertos
+cwTreeQuartets = Quatuors
+cwTreeSonatas = Sonates
+cwTreeSymphonies = Symphonies
+cwTreeBeethovenWorkConcertos = n ° 1 - C, n ° 2 - B-Flat Major, n ° 3 - C Minor, n ° 4 - G Major, n ° 5 - mi bémol majeur
+cwTreeBeethovenWorkQuartets = Six Quatuors à cordes, Trois Quatuors à cordes, Grosse Fugue pour Quatuors à cordes
+cwTreeBeethovenWorkSonatas = Sonate en la mineur, Sonate en fa majeur
+cwTreeBeethovenWorkSymphonies = n ° 2 - D Major, n ° 2 - D Major, n ° 3 - E-Flat Major, n ° 4 - B-Flat Major, n ° 5 - C Minor, n ° 6 - F Major, n ° 7 - Un grand, n ° 8 - F Major, n ° 9 - ré mineur
+cwTreeBrahmsWorkConcertos = Concerto pour violon, Double Concerto - A minor, Concerto pour piano n ° 1 - D minor, Concerto pour piano n ° 2 - si bémol majeur
+cwTreeBrahmsWorkQuartets = Quatuor pour piano n ° 1 - G Minor, Quatuor pour piano n ° 2 - Un grand, Quatuor pour piano n ° 3 - C Minor, Quatuor à cordes n ° 3 - B-flat minor
+cwTreeBrahmsWorkSonatas = Deux Sonates pour clarinette - F Minor, deux sonates pour clarinette - mi bémol majeur
+cwTreeBrahmsWorkSymphonies = n ° 1 - C Minor, n ° 2 - ré mineur, n ° 3 - F Major, n ° 4 - E Minor
+cwTreeMozartWorkConcertos = Concerto pour piano n ° 12, Concerto pour piano n ° 17, Concerto pour clarinette, Concerto pour violon n ° 5, Concerto pour violon n ° 4
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties
index e0f7857..47586d7 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseConstants_zh.properties
@@ -96,7 +96,7 @@
cwDisclosurePanelFormAdvancedCriteria = 高级条件
cwDisclosurePanelFormDescription = 说明:
cwDisclosurePanelFormGender = 性别:
-cwDisclosurePanelFormGenderOptions = 男, 女, 男女都有
+cwDisclosurePanelFormGenderOptions = 男, 女
cwDisclosurePanelFormLocation = 位置:
cwDisclosurePanelFormName = 姓名:
cwDisclosurePanelFormTitle = <b>输入搜索条件</b>
@@ -121,7 +121,7 @@
cwFlexTableDetails = 这是一个可支持 <B>colspans</B> 和 <B>rowspans</B> 的 FlexTable。 您可以用它来布局页面或作为其它特殊用途的表。
cwFlexTableRemoveRow = 删除行
cwFlowPanelName = 自然布局面板
-cwFlowPanelDescription = 自然布局面板(FlowPanel)可让其中的内容自然布局。移动分隔条看看内容是如何根据需要换行的。
+cwFlowPanelDescription = 自然布局面板(FlowPanel)可让其中的内容自然布局。
cwFlowPanelItem = 项目
cwFrameName = 框
cwFrameDescription = 框(Frame)是对IFRAME的封装,可以用来在您的网页嵌入其他网站的内容。
@@ -184,6 +184,7 @@
cwStackPanelDescription = 栈面板(StackPanel)会纵向排列子部件,任意时刻只显示某一部件的内容,其他子部件则只显示其标题,用户可以通过点击标题切换。这是一种十分有用的垂直菜单系统。
cwStackPanelContactsHeader = 通讯录
cwStackPanelContacts = 曼德尔布洛特, 爱因斯坦, 笛卡尔, 萨吉特, 贝多芬, 费曼, 阿兰图灵, 冯诺依曼
+cwStackPanelContactsEmails = benoit@example.com, albert@example.com, rene@example.com, bob@example.com, ludwig@example.com, richard@example.com, alan@example.com, john@example.com
cwStackPanelMailHeader =邮件
cwStackPanelMailFolders = 收件箱, 草稿箱, 范本, 发送, 垃圾箱
cwStackPanelFiltersHeader =过滤器
@@ -209,6 +210,7 @@
cwVerticalSplitPanelDescription = 垂直拆分面板(VerticalSplitPanel)允许用户自由决定如何分配空间。
cwVerticalSplitPanelText = 以下文字显示了分隔条两侧的内容是如何流动的。
+# TODO: get official translations
cwAnimationName = 动画
cwAnimationDescription = 动画使你的程序具备时间效果。
cwAnimationStart = 开始
@@ -216,3 +218,17 @@
cwAnimationOptions = 动画选项
cwDecoratorPanelName = 装饰面板
cwDecoratorPanelDescription = 装饰面板(DecoratorPanel)可以给任何部件添加圆角。
+cwTreeComposers =贝多芬, 布拉姆斯, 莫札特
+cwTreeConcertos =协奏曲
+cwTreeQuartets =四重奏
+cwTreeSonatas =奏鸣曲
+cwTreeSymphonies =交响乐
+cwTreeBeethovenWorkConcertos =第1号-○, 第2号- B大调大, 第3号- C小调, 第4号- G大, 第5号-电子商务大调
+cwTreeBeethovenWorkQuartets =六弦四重奏, 弦乐四重奏三, grosse赋格曲为弦乐四重奏
+cwTreeBeethovenWorkSonatas =奏鸣曲在未成年人, 调奏鸣曲F大
+cwTreeBeethovenWorkSymphonies =第2号-D大, 第2号- D大, 第3号- E大调大, 第4号- B大调大, 第5号- C小调, 第6号- F大, 号7 -一大, 第8号- F大, 第9号- D小调
+cwTreeBrahmsWorkConcertos =小提琴协奏曲, -未成年人, 钢琴协奏曲第1号- D小调, 钢琴协奏曲第2号-的B大调
+cwTreeBrahmsWorkQuartets =钢琴四重奏第1号-G小调钢琴四重奏第2号-的一个主要, 钢琴四重奏第3号- C小调, 弦乐四重奏第3号-的B小调
+cwTreeBrahmsWorkSonatas = 2奏鸣曲单簧管-F小调, 2单簧管奏鸣曲- E大调大
+cwTreeBrahmsWorkSymphonies =第1号-C小调, 第2号- D小调, 第3号- F大, 第4号- E小调
+cwTreeMozartWorkConcertos =钢琴协奏曲第12号, 钢琴协奏曲第17号, 单簧管协奏曲, 小提琴协奏曲第5号, 小提琴协奏曲第4号
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java
index 88cc1bd..db1e90a 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java
@@ -156,7 +156,7 @@
// Add a field to set the value
valueBox = new TextBox();
valueBox.setWidth("17em");
- valueBox.setText("13 September 1999");
+ valueBox.setText("13 September 1999 12:34:56");
valueBox.addKeyboardListener(new KeyboardListenerAdapter() {
@Override
public void onKeyUp(Widget sender, char keyCode, int modifiers) {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDictionaryExample.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDictionaryExample.java
index 68aab16..a6d78fe 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDictionaryExample.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDictionaryExample.java
@@ -86,6 +86,8 @@
+ " name: \"Amelie Crutcher\",\n"
+ " timeZone: \"EST\",\n" + " userID: \"123\",\n"
+ " lastLogOn: \"2/2/2006\"\n" + "};</pre>\n");
+ source.getElement().setDir("ltr");
+ source.getElement().getStyle().setProperty("textAlign", "left");
layout.add(new HTML(constants.cwDictionaryExampleLinkText()));
layout.add(source);
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java
index e0ba7a3..1b8cc3b 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java
@@ -23,11 +23,12 @@
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DecoratedStackPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeImages;
import com.google.gwt.user.client.ui.TreeItem;
@@ -48,6 +49,8 @@
ContentWidget.CwConstants {
String[] cwStackPanelContacts();
+ String[] cwStackPanelContactsEmails();
+
String cwStackPanelContactsHeader();
String cwStackPanelDescription();
@@ -74,6 +77,8 @@
public interface Images extends TreeImages {
AbstractImagePrototype contactsgroup();
+ AbstractImagePrototype defaultContact();
+
AbstractImagePrototype drafts();
AbstractImagePrototype filtersgroup();
@@ -139,7 +144,95 @@
DecoratedStackPanel stackPanel = new DecoratedStackPanel();
stackPanel.setWidth("200px");
- // Add links to Mail folders
+ // Add the Mail folders
+ String mailHeader = getHeaderString(constants.cwStackPanelMailHeader(),
+ images.mailgroup());
+ stackPanel.add(createMailItem(images), mailHeader, true);
+
+ // Add a list of filters
+ String filtersHeader = getHeaderString(
+ constants.cwStackPanelFiltersHeader(), images.filtersgroup());
+ stackPanel.add(createFiltersItem(), filtersHeader, true);
+
+ // Add a list of contacts
+ String contactsHeader = getHeaderString(
+ constants.cwStackPanelContactsHeader(), images.contactsgroup());
+ stackPanel.add(createContactsItem(images), contactsHeader, true);
+
+ // Return the stack panel
+ stackPanel.ensureDebugId("cwStackPanel");
+ return stackPanel;
+ }
+
+ /**
+ * Create the list of Contacts.
+ *
+ * @param images the {@link Images} used in the Contacts
+ * @return the list of contacts
+ */
+ @ShowcaseSource
+ private VerticalPanel createContactsItem(Images images) {
+ // Create a popup to show the contact info when a contact is clicked
+ HorizontalPanel contactPopupContainer = new HorizontalPanel();
+ contactPopupContainer.setSpacing(5);
+ contactPopupContainer.add(images.defaultContact().createImage());
+ final HTML contactInfo = new HTML();
+ contactPopupContainer.add(contactInfo);
+ final PopupPanel contactPopup = new PopupPanel(true, false);
+ contactPopup.setWidget(contactPopupContainer);
+
+ // Create the list of contacts
+ VerticalPanel contactsPanel = new VerticalPanel();
+ contactsPanel.setSpacing(4);
+ String[] contactNames = constants.cwStackPanelContacts();
+ String[] contactEmails = constants.cwStackPanelContactsEmails();
+ for (int i = 0; i < contactNames.length; i++) {
+ final String contactName = contactNames[i];
+ final String contactEmail = contactEmails[i];
+ final HTML contactLink = new HTML("<a href=\"javascript:undefined;\">"
+ + contactName + "</a>");
+ contactsPanel.add(contactLink);
+
+ // Open the contact info popup when the user clicks a contact
+ contactLink.addClickListener(new ClickListener() {
+ public void onClick(Widget sender) {
+ // Set the info about the contact
+ contactInfo.setHTML(contactName + "<br><i>" + contactEmail + "</i>");
+
+ // Show the popup of contact info
+ int left = contactLink.getAbsoluteLeft() + 14;
+ int top = contactLink.getAbsoluteTop() + 14;
+ contactPopup.setPopupPosition(left, top);
+ contactPopup.show();
+ }
+ });
+ }
+ return contactsPanel;
+ }
+
+ /**
+ * Create the list of filters for the Filters item.
+ *
+ * @return the list of filters
+ */
+ @ShowcaseSource
+ private VerticalPanel createFiltersItem() {
+ VerticalPanel filtersPanel = new VerticalPanel();
+ filtersPanel.setSpacing(4);
+ for (String filter : constants.cwStackPanelFilters()) {
+ filtersPanel.add(new CheckBox(filter));
+ }
+ return filtersPanel;
+ }
+
+ /**
+ * Create the {@link Tree} of Mail options.
+ *
+ * @param images the {@link Images} used in the Mail options
+ * @return the {@link Tree} of mail options
+ */
+ @ShowcaseSource
+ private Tree createMailItem(Images images) {
Tree mailPanel = new Tree(images);
TreeItem mailPanelRoot = mailPanel.addItem("foo@example.com");
String[] mailFolders = constants.cwStackPanelMailFolders();
@@ -149,33 +242,7 @@
mailPanelRoot.addItem(images.sent().getHTML() + " " + mailFolders[3]);
mailPanelRoot.addItem(images.trash().getHTML() + " " + mailFolders[4]);
mailPanelRoot.setState(true);
- String mailHeader = getHeaderString(constants.cwStackPanelMailHeader(),
- images.mailgroup());
- stackPanel.add(mailPanel, mailHeader, true);
-
- // Add a list of filters
- VerticalPanel filtersPanel = new VerticalPanel();
- filtersPanel.setSpacing(4);
- for (String filter : constants.cwStackPanelFilters()) {
- filtersPanel.add(new CheckBox(filter));
- }
- String filtersHeader = getHeaderString(
- constants.cwStackPanelFiltersHeader(), images.filtersgroup());
- stackPanel.add(filtersPanel, filtersHeader, true);
-
- // Add links to each contact
- VerticalPanel contactsPanel = new VerticalPanel();
- contactsPanel.setSpacing(4);
- for (String contact : constants.cwStackPanelContacts()) {
- contactsPanel.add(new Label(contact));
- }
- String contactsHeader = getHeaderString(
- constants.cwStackPanelContactsHeader(), images.contactsgroup());
- stackPanel.add(contactsPanel, contactsHeader, true);
-
- // Return the stack panel
- stackPanel.ensureDebugId("cwStackPanel");
- return stackPanel;
+ return mailPanel;
}
/**
@@ -198,6 +265,6 @@
hPanel.add(headerText);
// Return the HTML string for the panel
- return hPanel.toString();
+ return hPanel.getElement().getString();
}
}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
index b185c22..942a881 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
@@ -41,15 +41,43 @@
@ShowcaseSource
public static interface CwConstants extends Constants,
ContentWidget.CwConstants {
+ String[] cwTreeBeethovenWorkConcertos();
+
+ String[] cwTreeBeethovenWorkQuartets();
+
+ String[] cwTreeBeethovenWorkSonatas();
+
+ String[] cwTreeBeethovenWorkSymphonies();
+
+ String[] cwTreeBrahmsWorkConcertos();
+
+ String[] cwTreeBrahmsWorkQuartets();
+
+ String[] cwTreeBrahmsWorkSonatas();
+
+ String[] cwTreeBrahmsWorkSymphonies();
+
+ String[] cwTreeComposers();
+
+ String cwTreeConcertos();
+
String cwTreeDescription();
String cwTreeDynamicLabel();
String cwTreeItem();
+ String[] cwTreeMozartWorkConcertos();
+
String cwTreeName();
+ String cwTreeQuartets();
+
+ String cwTreeSonatas();
+
String cwTreeStaticLabel();
+
+ String cwTreeSymphonies();
}
/**
@@ -123,6 +151,22 @@
}
/**
+ * Add a new section of music created by a specific composer.
+ *
+ * @param parent the parent {@link TreeItem} where the section will be added
+ * @param label the label of the new section of music
+ * @param composerWorks an array of works created by the composer
+ */
+ @ShowcaseSource
+ private void addMusicSection(TreeItem parent, String label,
+ String[] composerWorks) {
+ TreeItem section = parent.addItem(label);
+ for (String work : composerWorks) {
+ section.addItem(work);
+ }
+ }
+
+ /**
* Create a dynamic tree that will add a random number of children to each
* node as it is clicked.
*
@@ -180,63 +224,39 @@
@ShowcaseSource
private Tree createStaticTree() {
// Create the tree
+ String[] composers = constants.cwTreeComposers();
+ String concertosLabel = constants.cwTreeConcertos();
+ String quartetsLabel = constants.cwTreeQuartets();
+ String sonatasLabel = constants.cwTreeSonatas();
+ String symphoniesLabel = constants.cwTreeSymphonies();
Tree staticTree = new Tree();
// Add some of Beethoven's music
- TreeItem c1 = staticTree.addItem("Beethoven");
- TreeItem c1g1 = c1.addItem("Concertos");
- c1g1.addItem("No. 1 - C");
- c1g1.addItem("No. 2 - B-Flat Major");
- c1g1.addItem("No. 3 - C Minor");
- c1g1.addItem("No. 4 - G Major");
- c1g1.addItem("No. 5 - E-Flat Major");
- TreeItem c1g2 = c1.addItem("Quartets");
- c1g2.addItem("Six String Quartets");
- c1g2.addItem("Three String Quartets");
- c1g2.addItem("Grosse Fugue for String Quartets");
- TreeItem c1g3 = c1.addItem("Sonatas");
- c1g3.addItem("Sonata in A Minor");
- c1g3.addItem("Sonata in F Major");
- TreeItem c1g4 = c1.addItem("Symphonies");
- c1g4.addItem("No. 2 - D Major");
- c1g4.addItem("No. 2 - D Major");
- c1g4.addItem("No. 3 - E-Flat Major");
- c1g4.addItem("No. 4 - B-Flat Major");
- c1g4.addItem("No. 5 - C Minor");
- c1g4.addItem("No. 6 - F Major");
- c1g4.addItem("No. 7 - A Major");
- c1g4.addItem("No. 8 - F Major");
- c1g4.addItem("No. 9 - D Minor");
+ TreeItem beethovenItem = staticTree.addItem(composers[0]);
+ addMusicSection(beethovenItem, concertosLabel,
+ constants.cwTreeBeethovenWorkConcertos());
+ addMusicSection(beethovenItem, quartetsLabel,
+ constants.cwTreeBeethovenWorkQuartets());
+ addMusicSection(beethovenItem, sonatasLabel,
+ constants.cwTreeBeethovenWorkSonatas());
+ addMusicSection(beethovenItem, symphoniesLabel,
+ constants.cwTreeBeethovenWorkSymphonies());
// Add some of Brahms's music
- TreeItem c2 = staticTree.addItem("Brahms");
- TreeItem c2g1 = c2.addItem("Concertos");
- c2g1.addItem("Violin Concerto");
- c2g1.addItem("Double Concerto - A Minor");
- c2g1.addItem("Piano Concerto No. 1 - D Minor");
- c2g1.addItem("Piano Concerto No. 2 - B-Flat Major");
- TreeItem c2g2 = c2.addItem("Quartets");
- c2g2.addItem("Piano Quartet No. 1 - G Minor");
- c2g2.addItem("Piano Quartet No. 2 - A Major");
- c2g2.addItem("Piano Quartet No. 3 - C Minor");
- c2g2.addItem("String Quartet No. 3 - B-Flat Minor");
- TreeItem c2g3 = c2.addItem("Sonatas");
- c2g3.addItem("Two Sonatas for Clarinet - F Minor");
- c2g3.addItem("Two Sonatas for Clarinet - E-Flat Major");
- TreeItem c2g4 = c2.addItem("Symphonies");
- c2g4.addItem("No. 1 - C Minor");
- c2g4.addItem("No. 2 - D Minor");
- c2g4.addItem("No. 3 - F Major");
- c2g4.addItem("No. 4 - E Minor");
+ TreeItem brahmsItem = staticTree.addItem(composers[1]);
+ addMusicSection(brahmsItem, concertosLabel,
+ constants.cwTreeBrahmsWorkConcertos());
+ addMusicSection(brahmsItem, quartetsLabel,
+ constants.cwTreeBrahmsWorkQuartets());
+ addMusicSection(brahmsItem, sonatasLabel,
+ constants.cwTreeBrahmsWorkSonatas());
+ addMusicSection(brahmsItem, symphoniesLabel,
+ constants.cwTreeBrahmsWorkSymphonies());
// Add some of Mozart's music
- TreeItem c3 = staticTree.addItem("Mozart");
- TreeItem c3g1 = c3.addItem("Concertos");
- c3g1.addItem("Piano Concerto No. 12");
- c3g1.addItem("Piano Concerto No. 17");
- c3g1.addItem("Clarinet Concerto");
- c3g1.addItem("Violin Concerto No. 5");
- c3g1.addItem("Violin Concerto No. 4");
+ TreeItem mozartItem = staticTree.addItem(composers[2]);
+ addMusicSection(mozartItem, concertosLabel,
+ constants.cwTreeMozartWorkConcertos());
// Return the tree
return staticTree;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/defaultContact.jpg b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/defaultContact.jpg
new file mode 100644
index 0000000..751970d
--- /dev/null
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/defaultContact.jpg
Binary files differ
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java
index 0428f7e..26f55e4 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java
@@ -177,6 +177,20 @@
}
/**
+ * Initialize the options panel after the {@link AbsolutePanel} has been
+ * attached to the page.
+ */
+ @ShowcaseSource
+ @Override
+ public void onInitializeComplete() {
+ DeferredCommand.addCommand(new Command() {
+ public void execute() {
+ updateSelectedItem();
+ }
+ });
+ }
+
+ /**
* Create an options panel that allows users to select a widget and reposition
* it.
*
@@ -215,7 +229,7 @@
// Move the item as the user changes the value in the left and top boxes
KeyboardListenerAdapter repositionListener = new KeyboardListenerAdapter() {
@Override
- public void onKeyPress(Widget sender, char keyCode, int modifiers) {
+ public void onKeyUp(Widget sender, char keyCode, int modifiers) {
repositionItem();
}
};
@@ -232,24 +246,19 @@
*/
@ShowcaseSource
private void repositionItem() {
- // Use a DeferredCommand to allow the key to take effect in the browser
- DeferredCommand.addCommand(new Command() {
- public void execute() {
- // Get the selected item to move
- String name = listBox.getValue(listBox.getSelectedIndex());
- Widget item = widgetMap.get(name);
+ // Get the selected item to move
+ String name = listBox.getValue(listBox.getSelectedIndex());
+ Widget item = widgetMap.get(name);
- // Reposition the item
- try {
- int top = Integer.parseInt(topPosBox.getText());
- int left = Integer.parseInt(leftPosBox.getText());
- absolutePanel.setWidgetPosition(item, left, top);
- } catch (NumberFormatException e) {
- // Ignore invalid user input
- return;
- }
- }
- });
+ // Reposition the item
+ try {
+ int top = Integer.parseInt(topPosBox.getText());
+ int left = Integer.parseInt(leftPosBox.getText());
+ absolutePanel.setWidgetPosition(item, left, top);
+ } catch (NumberFormatException e) {
+ // Ignore invalid user input
+ return;
+ }
}
/**
@@ -260,7 +269,7 @@
private void updateSelectedItem() {
String name = listBox.getValue(listBox.getSelectedIndex());
Widget item = widgetMap.get(name);
- topPosBox.setText((absolutePanel.getWidgetTop(item) - 1) + "");
- leftPosBox.setText((absolutePanel.getWidgetLeft(item) - 1) + "");
+ topPosBox.setText(absolutePanel.getWidgetTop(item) + "");
+ leftPosBox.setText(absolutePanel.getWidgetLeft(item) + "");
}
}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
index 668aade..581d88a 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
@@ -16,13 +16,13 @@
package com.google.gwt.sample.showcase.client.content.popups;
import com.google.gwt.i18n.client.Constants;
+import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.sample.showcase.client.ContentWidget;
import com.google.gwt.sample.showcase.client.Showcase;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
@@ -35,8 +35,8 @@
/**
* Example file.
*/
-@ShowcaseStyle({".gwt-DialogBox", "html>body .gwt-DialogBox", "* html .gwt-DialogBox",
- ".cw-DialogBox"})
+@ShowcaseStyle({".gwt-DialogBox", "html>body .gwt-DialogBox",
+ "* html .gwt-DialogBox", ".cw-DialogBox"})
public class CwDialogBox extends ContentWidget {
/**
* The constants used in this Content Widget.
@@ -143,7 +143,6 @@
// Create a table to layout the content
VerticalPanel dialogContents = new VerticalPanel();
- dialogContents.setWidth("100%");
dialogContents.setSpacing(4);
dialogBox.setWidget(dialogContents);
@@ -159,22 +158,6 @@
dialogContents.setCellHorizontalAlignment(image,
HasHorizontalAlignment.ALIGN_CENTER);
- // Add option to make transparent
- final CheckBox opacityOption = new CheckBox(
- constants.cwDialogBoxMakeTransparent());
- dialogContents.add(opacityOption);
-
- // Listen for changes in opacity option
- opacityOption.addClickListener(new ClickListener() {
- public void onClick(Widget sender) {
- if (opacityOption.isChecked()) {
- dialogBox.addStyleName("cw-DialogBox");
- } else {
- dialogBox.removeStyleName("cw-DialogBox");
- }
- }
- });
-
// Add a close button at the bottom of the dialog
Button closeButton = new Button(constants.cwDialogBoxClose(),
new ClickListener() {
@@ -183,8 +166,14 @@
}
});
dialogContents.add(closeButton);
- dialogContents.setCellHorizontalAlignment(closeButton,
- HasHorizontalAlignment.ALIGN_RIGHT);
+ if (LocaleInfo.getCurrentLocale().isRTL()) {
+ dialogContents.setCellHorizontalAlignment(closeButton,
+ HasHorizontalAlignment.ALIGN_LEFT);
+
+ } else {
+ dialogContents.setCellHorizontalAlignment(closeButton,
+ HasHorizontalAlignment.ALIGN_RIGHT);
+ }
// Return the dialog box
return dialogBox;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java
index 4cb08d3..ed969a1 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java
@@ -88,7 +88,7 @@
final FlexTable flexTable = new FlexTable();
FlexCellFormatter cellFormatter = flexTable.getFlexCellFormatter();
flexTable.addStyleName("cw-FlexTable");
- flexTable.setWidth("350px");
+ flexTable.setWidth("32em");
flexTable.setCellSpacing(5);
flexTable.setCellPadding(3);
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/Showcase.html b/samples/showcase/src/com/google/gwt/sample/showcase/public/Showcase.html
index e88d337..0f4f1c9 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/Showcase.html
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/Showcase.html
@@ -1,4 +1,3 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<head>
<title>Showcase of GWT Features</title>
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase.css b/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase.css
index f9e205d..838ef65 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase.css
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase.css
@@ -1,6 +1,11 @@
/**
* Applied to the main layout of the page.
*/
+.Application-Reference-chrome {
+ height: 5px;
+ width: 5px;
+ zoom: 1;
+}
.Application-top {
width: 100%;
margin-bottom: 10px;
@@ -43,6 +48,7 @@
width: 36px;
height: 16px;
margin: 3px 0px 0px 10px;
+ padding: 0px;
}
.Application-options .gwt-ToggleButton-down,
.Application-options .gwt-ToggleButton-down-hovering {
@@ -71,7 +77,7 @@
.Application-content-title {
padding: 4px 0px 3px 6px;
text-align: left;
- background: url(../gwt/chrome/images/hborder.png) repeat-x 0px -2003px;
+ background: #530a0a url(../gwt/chrome/images/hborder.png) repeat-x 0px -2003px;
border-bottom: 2px solid #e3e3e3;
}
.Application-content-title .gwt-TabBarItem {
@@ -116,11 +122,6 @@
cursor: hand;
}
-.cw-DialogBox {
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-
.cw-DictionaryExample-headerRow td {
color: #7aa5d6;
text-decoration: underline;
@@ -163,10 +164,3 @@
font-weight: bold;
font-size: 1.4em;
}
-
-/**
- * Make all buttons the same size.
- */
-.gwt-Button {
- width: 10em;
-}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase_rtl.css b/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase_rtl.css
index cd9ea6b..08614c6 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase_rtl.css
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/chrome/Showcase_rtl.css
@@ -1,6 +1,11 @@
/**
* Applied to the main layout of the page.
*/
+.Application-Reference-chrome-rtl {
+ height: 5px;
+ width: 5px;
+ zoom: 1;
+}
.Application-top {
width: 100%;
margin-bottom: 10px;
@@ -43,6 +48,7 @@
width: 36px;
height: 16px;
margin: 3px 10px 0px 0px;
+ padding: 0px;
}
.Application-options .gwt-ToggleButton-down,
.Application-options .gwt-ToggleButton-down-hovering {
@@ -71,7 +77,7 @@
.Application-content-title {
padding: 4px 6px 3px 0px;
text-align: right;
- background: url(../gwt/chrome/images/hborder.png) repeat-x 0px -2003px;
+ background: #530a0a url(../gwt/chrome/images/hborder.png) repeat-x 0px -2003px;
border-bottom: 2px solid #e3e3e3;
}
.Application-content-title .gwt-TabBarItem {
@@ -116,11 +122,6 @@
cursor: hand;
}
-.cw-DialogBox {
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-
.cw-DictionaryExample-headerRow td {
color: #7aa5d6;
text-decoration: underline;
@@ -163,10 +164,3 @@
font-weight: bold;
font-size: 1.4em;
}
-
-/**
- * Make all buttons the same size.
- */
-.gwt-Button {
- width: 10em;
-}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase.css b/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase.css
index 29abf5a..1af6ef0 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase.css
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase.css
@@ -1,6 +1,11 @@
/**
* Applied to the main layout of the page.
*/
+.Application-Reference-dark {
+ height: 5px;
+ width: 5px;
+ zoom: 1;
+}
.Application-top {
width: 100%;
margin-bottom: 10px;
@@ -43,6 +48,7 @@
width: 36px;
height: 16px;
margin: 3px 0px 0px 10px;
+ padding: 0px;
}
.Application-options .gwt-ToggleButton-down,
.Application-options .gwt-ToggleButton-down-hovering {
@@ -118,11 +124,6 @@
cursor: hand;
}
-.cw-DialogBox {
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-
.cw-DictionaryExample-headerRow td {
color: #7aa5d6;
text-decoration: underline;
@@ -170,10 +171,3 @@
font-weight: bold;
font-size: 1.4em;
}
-
-/**
- * Make all buttons the same size.
- */
-.gwt-Button {
- width: 10em;
-}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase_rtl.css b/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase_rtl.css
index af24b2b..04f9e6e 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase_rtl.css
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/dark/Showcase_rtl.css
@@ -1,6 +1,11 @@
/**
* Applied to the main layout of the page.
*/
+.Application-Reference-dark-rtl {
+ height: 5px;
+ width: 5px;
+ zoom: 1;
+}
.Application-top {
width: 100%;
margin-bottom: 10px;
@@ -43,6 +48,7 @@
width: 36px;
height: 16px;
margin: 3px 10px 0px 0px;
+ padding: 0px;
}
.Application-options .gwt-ToggleButton-down,
.Application-options .gwt-ToggleButton-down-hovering {
@@ -118,11 +124,6 @@
cursor: hand;
}
-.cw-DialogBox {
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-
.cw-DictionaryExample-headerRow td {
color: #7aa5d6;
text-decoration: underline;
@@ -170,10 +171,3 @@
font-weight: bold;
font-size: 1.4em;
}
-
-/**
- * Make all buttons the same size.
- */
-.gwt-Button {
- width: 10em;
-}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase.css b/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase.css
index 3bcc86a..c31a010 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase.css
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase.css
@@ -1,6 +1,11 @@
/**
* Applied to the main layout of the page.
*/
+.Application-Reference-standard {
+ height: 5px;
+ width: 5px;
+ zoom: 1;
+}
.Application-top {
width: 100%;
margin-bottom: 10px;
@@ -43,6 +48,7 @@
width: 36px;
height: 16px;
margin: 3px 0px 0px 10px;
+ padding: 0px;
}
.Application-options .gwt-ToggleButton-down,
.Application-options .gwt-ToggleButton-down-hovering {
@@ -71,7 +77,7 @@
.Application-content-title {
padding: 4px 0px 3px 6px;
text-align: left;
- background: url(../gwt/standard/images/hborder.png) repeat-x 0px -2003px;
+ background: #e3e8f3 url(../gwt/standard/images/hborder.png) repeat-x 0px -2003px;
border-bottom: 2px solid #bbcdf3;
}
.Application-content-title .gwt-TabBarItem {
@@ -116,11 +122,6 @@
cursor: hand;
}
-.cw-DialogBox {
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-
.cw-DictionaryExample-headerRow td {
color: #7aa5d6;
text-decoration: underline;
@@ -163,10 +164,3 @@
font-weight: bold;
font-size: 1.4em;
}
-
-/**
- * Make all buttons the same size.
- */
-.gwt-Button {
- width: 10em;
-}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase_rtl.css b/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase_rtl.css
index bfa9acc..2ab88f2 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase_rtl.css
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/public/standard/Showcase_rtl.css
@@ -1,6 +1,11 @@
/**
* Applied to the main layout of the page.
*/
+.Application-Reference-standard-rtl {
+ height: 5px;
+ width: 5px;
+ zoom: 1;
+}
.Application-top {
width: 100%;
margin-bottom: 10px;
@@ -43,6 +48,7 @@
width: 36px;
height: 16px;
margin: 3px 10px 0px 0px;
+ padding: 0px;
}
.Application-options .gwt-ToggleButton-down,
.Application-options .gwt-ToggleButton-down-hovering {
@@ -71,7 +77,7 @@
.Application-content-title {
padding: 4px 6px 3px 0px;
text-align: right;
- background: url(../gwt/standard/images/hborder.png) repeat-x 0px -2003px;
+ background: #e3e8f3 url(../gwt/standard/images/hborder.png) repeat-x 0px -2003px;
border-bottom: 2px solid #bbcdf3;
}
.Application-content-title .gwt-TabBarItem {
@@ -116,11 +122,6 @@
cursor: hand;
}
-.cw-DialogBox {
- opacity: 0.8;
- filter: alpha(opacity=80);
-}
-
.cw-DictionaryExample-headerRow td {
color: #7aa5d6;
text-decoration: underline;
@@ -163,10 +164,3 @@
font-weight: bold;
font-size: 1.4em;
}
-
-/**
- * Make all buttons the same size.
- */
-.gwt-Button {
- width: 10em;
-}
diff --git a/samples/simplerpc/src/com/google/gwt/sample/simplerpc/public/SimpleRPC.html b/samples/simplerpc/src/com/google/gwt/sample/simplerpc/public/SimpleRPC.html
index e7f5be8..5e4e762 100644
--- a/samples/simplerpc/src/com/google/gwt/sample/simplerpc/public/SimpleRPC.html
+++ b/samples/simplerpc/src/com/google/gwt/sample/simplerpc/public/SimpleRPC.html
@@ -1,6 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- -->
<!-- Copyright 2008 Google Inc. -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
diff --git a/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html b/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html
index a861394..6c2ba07 100644
--- a/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html
+++ b/samples/simplexml/src/com/google/gwt/sample/simplexml/public/SimpleXML.html
@@ -1,6 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- -->
<!-- Copyright 2008 Google Inc. -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); you -->
diff --git a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
index 5a637c5..029eff9 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
@@ -30,7 +30,9 @@
// getBoundingClientRect().left is off by the document element's
// border-left-width.
var style = $wnd.getComputedStyle($doc.documentElement, '')
- return elem.getBoundingClientRect().left + parseInt(style.borderLeftWidth);
+ return elem.getBoundingClientRect().left +
+ parseInt(style.borderLeftWidth) +
+ $doc.body.scrollLeft;
} else {
// We cannot use DOMImpl here because offsetLeft/Top return erroneous
// values when overflow is not visible. We have to difference screenX
@@ -52,7 +54,9 @@
// getBoundingClientRect().top is off by the document element's
// border-top-width.
var style = $wnd.getComputedStyle($doc.documentElement, '')
- return elem.getBoundingClientRect().top + parseInt(style.borderTopWidth);
+ return elem.getBoundingClientRect().top +
+ parseInt(style.borderTopWidth) +
+ $doc.body.scrollTop;
} else {
// We cannot use DOMImpl here because offsetLeft/Top return erroneous
// values when overflow is not visible. We have to difference screenX
diff --git a/user/src/com/google/gwt/dom/client/InputElement.java b/user/src/com/google/gwt/dom/client/InputElement.java
index 6b4b44e..3acdfcb 100644
--- a/user/src/com/google/gwt/dom/client/InputElement.java
+++ b/user/src/com/google/gwt/dom/client/InputElement.java
@@ -54,7 +54,7 @@
* the following values: "button", "checkbox", "radio", "reset", or "submit".
*/
public final native void click() /*-{
- this.click;
+ this.click();
}-*/;
/**
diff --git a/user/src/com/google/gwt/i18n/client/NumberFormat.java b/user/src/com/google/gwt/i18n/client/NumberFormat.java
index 8ceccc8..56c2dda 100644
--- a/user/src/com/google/gwt/i18n/client/NumberFormat.java
+++ b/user/src/com/google/gwt/i18n/client/NumberFormat.java
@@ -589,49 +589,65 @@
*/
public double parse(String text, int[] inOutPos) throws NumberFormatException {
int start = inOutPos[0];
- boolean gotPositive, gotNegative;
double ret = 0.0;
- gotPositive = (text.indexOf(positivePrefix, inOutPos[0]) == inOutPos[0]);
- gotNegative = (text.indexOf(negativePrefix, inOutPos[0]) == inOutPos[0]);
+ boolean gotPositivePrefix = text.startsWith(positivePrefix, inOutPos[0]);
+ boolean gotNegativePrefix = text.startsWith(negativePrefix, inOutPos[0]);
+ boolean gotPositiveSuffix = text.endsWith(positiveSuffix);
+ boolean gotNegativeSuffix = text.endsWith(negativeSuffix);
+ boolean gotPositive = gotPositivePrefix && gotPositiveSuffix;
+ boolean gotNegative = gotNegativePrefix && gotNegativeSuffix;
+ // Handle conflicts where we get both patterns, which usually
+ // happens when one is a prefix of the other (such as the positive
+ // pattern having empty prefix/suffixes).
if (gotPositive && gotNegative) {
if (positivePrefix.length() > negativePrefix.length()) {
gotNegative = false;
} else if (positivePrefix.length() < negativePrefix.length()) {
gotPositive = false;
+ } else if (positiveSuffix.length() > negativeSuffix.length()) {
+ gotNegative = false;
+ } else if (positiveSuffix.length() < negativeSuffix.length()) {
+ gotPositive = false;
+ } else {
+ // can't tell patterns apart, must be positive
+ gotNegative = false;
}
+ } else if (!gotPositive && !gotNegative) {
+ throw new NumberFormatException(text
+ + " does not have either positive or negative affixes");
}
+ // Contains just the value to parse, stripping any prefix or suffix
+ String valueOnly = null;
if (gotPositive) {
inOutPos[0] += positivePrefix.length();
- } else if (gotNegative) {
+ valueOnly = text.substring(inOutPos[0],
+ text.length() - positiveSuffix.length());
+ } else {
inOutPos[0] += negativePrefix.length();
+ valueOnly = text.substring(inOutPos[0],
+ text.length() - negativeSuffix.length());
}
- // Process digits or Inf, and find decimal position.
- if (text.indexOf(numberConstants.infinity(), inOutPos[0]) == inOutPos[0]) {
+ // Process digits or special values, and find decimal position.
+ if (valueOnly.equals(numberConstants.infinity())) {
inOutPos[0] += numberConstants.infinity().length();
ret = Double.POSITIVE_INFINITY;
- } else if (text.indexOf(numberConstants.notANumber(), inOutPos[0]) == inOutPos[0]) {
+ } else if (valueOnly.equals(numberConstants.notANumber())) {
inOutPos[0] += numberConstants.notANumber().length();
ret = Double.NaN;
} else {
- ret = parseNumber(text, inOutPos);
+ int[] tempPos = {0};
+ ret = parseNumber(valueOnly, tempPos);
+ inOutPos[0] += tempPos[0];
}
// Check for suffix.
if (gotPositive) {
- if (!(text.indexOf(positiveSuffix, inOutPos[0]) == inOutPos[0])) {
- inOutPos[0] = start;
- return 0.0;
- }
inOutPos[0] += positiveSuffix.length();
} else if (gotNegative) {
- if (!(text.indexOf(negativeSuffix, inOutPos[0]) == inOutPos[0])) {
- inOutPos[0] = start;
- return 0.0;
- }
inOutPos[0] += negativeSuffix.length();
}
@@ -657,10 +673,14 @@
}
String exponentDigits = String.valueOf(exponent);
- for (int i = exponentDigits.length(); i < minExponentDigits; ++i) {
+ int len = exponentDigits.length();
+ for (int i = len; i < minExponentDigits; ++i) {
result.append(numberConstants.zeroDigit());
}
- result.append(exponentDigits);
+ int zeroDelta = numberConstants.zeroDigit().charAt(0) - '0';
+ for (int i = 0; i < len; ++i) {
+ result.append((char) (exponentDigits.charAt(i) + zeroDelta));
+ }
}
/**
@@ -721,16 +741,18 @@
return newIntPart.toString();
}
-
/**
* This method parses affix part of pattern.
*
* @param pattern pattern string that need to be parsed
* @param start start position to parse
* @param affix store the parsed result
+ * @param inNegativePattern true if we are parsing the negative pattern and
+ * therefore only care about the prefix and suffix
* @return how many characters parsed
*/
- private int parseAffix(String pattern, int start, StringBuffer affix) {
+ private int parseAffix(String pattern, int start, StringBuffer affix,
+ boolean inNegativePattern) {
affix.delete(0, affix.length());
boolean inQuote = false;
int len = pattern.length();
@@ -767,21 +789,25 @@
}
break;
case PATTERN_PERCENT:
- if (multiplier != 1) {
- throw new IllegalArgumentException(
- "Too many percent/per mille characters in pattern \""
- + pattern + '"');
+ if (!inNegativePattern) {
+ if (multiplier != 1) {
+ throw new IllegalArgumentException(
+ "Too many percent/per mille characters in pattern \""
+ + pattern + '"');
+ }
+ multiplier = 100;
}
- multiplier = 100;
affix.append(numberConstants.percent());
break;
case PATTERN_PER_MILLE:
- if (multiplier != 1) {
- throw new IllegalArgumentException(
- "Too many percent/per mille characters in pattern \""
- + pattern + '"');
+ if (!inNegativePattern) {
+ if (multiplier != 1) {
+ throw new IllegalArgumentException(
+ "Too many percent/per mille characters in pattern \""
+ + pattern + '"');
+ }
+ multiplier = 1000;
}
- multiplier = 1000;
affix.append(numberConstants.perMill());
break;
case PATTERN_MINUS:
@@ -881,22 +907,23 @@
int pos = 0;
StringBuffer affix = new StringBuffer();
- pos += parseAffix(pattern, pos, affix);
+ pos += parseAffix(pattern, pos, affix, false);
positivePrefix = affix.toString();
- int posPartLen = parseTrunk(pattern, pos);
- pos += posPartLen;
- pos += parseAffix(pattern, pos, affix);
+ pos += parseTrunk(pattern, pos, false);
+ pos += parseAffix(pattern, pos, affix, false);
positiveSuffix = affix.toString();
if (pos < pattern.length() && pattern.charAt(pos) == PATTERN_SEPARATOR) {
++pos;
- pos += parseAffix(pattern, pos, affix);
+ pos += parseAffix(pattern, pos, affix, true);
negativePrefix = affix.toString();
- // The assumption made here is that negative part is identical to
- // positive part. User must make sure pattern is correctly constructed.
- pos += posPartLen;
- pos += parseAffix(pattern, pos, affix);
+ // the negative pattern is only used for prefix/suffix
+ pos += parseTrunk(pattern, pos, true);
+ pos += parseAffix(pattern, pos, affix, true);
negativeSuffix = affix.toString();
+ } else {
+ negativePrefix = numberConstants.minusSign() + positivePrefix;
+ negativeSuffix = positiveSuffix;
}
}
@@ -905,9 +932,11 @@
*
* @param pattern pattern string that need to be parsed
* @param start where parse started
+ * @param ignorePattern true if we are only parsing this for length
+ * and correctness, such as in the negative portion of the pattern
* @return how many characters parsed
*/
- private int parseTrunk(String pattern, int start) {
+ private int parseTrunk(String pattern, int start, boolean ignorePattern) {
int decimalPos = -1;
int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
byte groupingCount = -1;
@@ -949,23 +978,27 @@
decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
break;
case PATTERN_EXPONENT:
- if (useExponentialNotation) {
- throw new IllegalArgumentException("Multiple exponential "
- + "symbols in pattern \"" + pattern + '"');
+ if (!ignorePattern) {
+ if (useExponentialNotation) {
+ throw new IllegalArgumentException("Multiple exponential "
+ + "symbols in pattern \"" + pattern + '"');
+ }
+ useExponentialNotation = true;
+ minExponentDigits = 0;
}
- useExponentialNotation = true;
- minExponentDigits = 0;
// Use lookahead to parse out the exponential part
// of the pattern, then jump into phase 2.
while ((pos + 1) < len
- && pattern.charAt(pos + 1) == numberConstants.zeroDigit().charAt(
- 0)) {
+ && pattern.charAt(pos + 1) == PATTERN_ZERO_DIGIT) {
++pos;
- ++minExponentDigits;
+ if (!ignorePattern) {
+ ++minExponentDigits;
+ }
}
- if ((digitLeftCount + zeroDigitCount) < 1 || minExponentDigits < 1) {
+ if (!ignorePattern && (digitLeftCount + zeroDigitCount) < 1
+ || minExponentDigits < 1) {
throw new IllegalArgumentException("Malformed exponential "
+ "pattern \"" + pattern + '"');
}
@@ -995,6 +1028,11 @@
|| groupingCount == 0) {
throw new IllegalArgumentException("Malformed pattern \"" + pattern + '"');
}
+
+ if (ignorePattern) {
+ return pos - start;
+ }
+
int totalDigits = digitLeftCount + zeroDigitCount + digitRightCount;
maximumFractionDigits = (decimalPos >= 0 ? (totalDigits - decimalPos) : 0);
@@ -1026,7 +1064,7 @@
return pos - start;
}
-
+
/**
* This method formats a <code>double</code> in exponential format.
*
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar.properties
index 669623e..c024507 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_AE.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_AE.properties
index 669623e..c024507 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_AE.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_AE.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_BH.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_BH.properties
index a9ff19e..433ba31 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_BH.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_BH.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_DZ.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_DZ.properties
index 3a47a3b..e4f4cba 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_DZ.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_DZ.properties
@@ -4,10 +4,10 @@
zeroDigit = 0
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_EG.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_EG.properties
index d576e42..11f1d2a 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_EG.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_EG.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_IQ.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_IQ.properties
index 5561a52..3e7faf6 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_IQ.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_IQ.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_JO.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_JO.properties
index 47422ff..679a70b 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_JO.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_JO.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_KW.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_KW.properties
index 97a3fcb..f3190e1 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_KW.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_KW.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LB.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LB.properties
index 8996e37..bc7b7a7 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LB.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LB.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LY.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LY.properties
index f0af397..19d12f0 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LY.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_LY.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_MA.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_MA.properties
index 7b66127..2f16985 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_MA.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_MA.properties
@@ -4,10 +4,10 @@
zeroDigit = 0
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_OM.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_OM.properties
index ccc9781..30c093c 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_OM.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_OM.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_QA.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_QA.properties
index a175010..e64f947 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_QA.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_QA.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #0.###;#0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SA.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SA.properties
index 8f076a1..b9f2167 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SA.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SA.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #0.###;#0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SD.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SD.properties
index 1c6867a..d5837da 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SD.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SD.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #,##0.###;#,##0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SY.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SY.properties
index 472846c..05310b2 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SY.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_SY.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #0.###;#0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_TN.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_TN.properties
index 2f63968..01b2ae4 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_TN.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_TN.properties
@@ -4,10 +4,10 @@
zeroDigit = 0
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #0.###;#0.###-
diff --git a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_YE.properties b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_YE.properties
index d01ddfb..0690065 100644
--- a/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_YE.properties
+++ b/user/src/com/google/gwt/i18n/client/constants/NumberConstants_ar_YE.properties
@@ -4,10 +4,10 @@
zeroDigit = \u0660
plusSign = +
minusSign = -
-exponentialSymbol = E
+exponentialSymbol = \u0627\u0633
perMill = \u2030
infinity = \u221E
-notANumber = NaN
+notANumber = \u0644\u064a\u0633 \u0631\u0642\u0645
monetarySeparator = \u066B
monetaryGroupingSeparator = \u066C
decimalPattern = #0.###;#0.###-
diff --git a/user/src/com/google/gwt/user/History.gwt.xml b/user/src/com/google/gwt/user/History.gwt.xml
index 3637cad..a6bfaec 100644
--- a/user/src/com/google/gwt/user/History.gwt.xml
+++ b/user/src/com/google/gwt/user/History.gwt.xml
@@ -1,5 +1,5 @@
<!-- -->
-<!-- Copyright 2007 Google Inc. -->
+<!-- Copyright 2008 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 -->
<!-- may obtain a copy of the License at -->
@@ -46,10 +46,4 @@
<when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
<when-property-is name="user.agent" value="safari"/>
</replace-with>
-
- <!-- Opera has yet another history implementation. -->
- <replace-with class="com.google.gwt.user.client.impl.HistoryImplOpera">
- <when-type-is class="com.google.gwt.user.client.impl.HistoryImpl"/>
- <when-property-is name="user.agent" value="opera"/>
- </replace-with>
</module>
diff --git a/user/src/com/google/gwt/user/Tree.gwt.xml b/user/src/com/google/gwt/user/Tree.gwt.xml
new file mode 100644
index 0000000..626f52e
--- /dev/null
+++ b/user/src/com/google/gwt/user/Tree.gwt.xml
@@ -0,0 +1,25 @@
+<!-- -->
+<!-- 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 -->
+<!-- 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. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+
+<!-- Deferred binding rules for Tree. -->
+<module>
+ <inherits name="com.google.gwt.core.Core"/>
+ <inherits name="com.google.gwt.user.UserAgent"/>
+
+ <!-- IE-specific implementation -->
+ <replace-with class="com.google.gwt.user.client.ui.TreeItem.TreeItemImplIE6">
+ <when-type-is class="com.google.gwt.user.client.ui.TreeItem.TreeItemImpl"/>
+ <when-property-is name="user.agent" value="ie6"/>
+ </replace-with>
+</module>
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index 99baf1c..9c8035f 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -38,6 +38,7 @@
<inherits name="com.google.gwt.user.CaptionPanel" />
<inherits name="com.google.gwt.user.Window" />
<inherits name="com.google.gwt.user.Accessibility"/>
+ <inherits name="com.google.gwt.user.Tree"/>
<super-source path="translatable"/>
<source path="client"/>
diff --git a/user/src/com/google/gwt/user/Window.gwt.xml b/user/src/com/google/gwt/user/Window.gwt.xml
index ad8d23d..ec8571b 100644
--- a/user/src/com/google/gwt/user/Window.gwt.xml
+++ b/user/src/com/google/gwt/user/Window.gwt.xml
@@ -20,6 +20,11 @@
<inherits name="com.google.gwt.core.Core"/>
<inherits name="com.google.gwt.user.UserAgent"/>
+ <replace-with class="com.google.gwt.user.client.impl.WindowImplIE">
+ <when-type-is class="com.google.gwt.user.client.impl.WindowImpl"/>
+ <when-property-is name="user.agent" value="ie6"/>
+ </replace-with>
+
<replace-with class="com.google.gwt.user.client.impl.WindowImplOpera">
<when-type-is class="com.google.gwt.user.client.impl.WindowImpl"/>
<when-property-is name="user.agent" value="opera"/>
diff --git a/user/src/com/google/gwt/user/client/DOM.java b/user/src/com/google/gwt/user/client/DOM.java
index ab29f1a..f931cbe 100644
--- a/user/src/com/google/gwt/user/client/DOM.java
+++ b/user/src/com/google/gwt/user/client/DOM.java
@@ -401,8 +401,12 @@
*
* @param evt the event to be tested
* @return <code>true</code> if ALT was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static boolean eventGetAltKey(Event evt) {
+ public static boolean eventGetAltKey(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
| Event.KEYEVENTS | Event.ONCONTEXTMENU, "altKey");
return impl.eventGetAltKey(evt);
@@ -414,8 +418,10 @@
* @param evt the event to be tested
* @return a bit-field, defined by {@link Event#BUTTON_LEFT},
* {@link Event#BUTTON_MIDDLE}, and {@link Event#BUTTON_RIGHT}
+ * @throws AssertionError if event type is not one of
+ * {@link Event#ONMOUSEDOWN} or {@link Event#ONMOUSEUP}
*/
- public static int eventGetButton(Event evt) {
+ public static int eventGetButton(Event evt) throws AssertionError {
assertEventType(evt, Event.ONMOUSEDOWN | Event.ONMOUSEUP, "button");
return impl.eventGetButton(evt);
}
@@ -425,8 +431,12 @@
*
* @param evt the event to be tested
* @return the mouse x-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static int eventGetClientX(Event evt) {
+ public static int eventGetClientX(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
| Event.ONMOUSEWHEEL | Event.ONCONTEXTMENU, "clientX");
return impl.eventGetClientX(evt);
@@ -437,8 +447,12 @@
*
* @param evt the event to be tested
* @return the mouse y-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static int eventGetClientY(Event evt) {
+ public static int eventGetClientY(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
| Event.ONMOUSEWHEEL | Event.ONCONTEXTMENU, "clientY");
return impl.eventGetClientY(evt);
@@ -449,8 +463,12 @@
*
* @param evt the event to be tested
* @return <code>true</code> if CTRL was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static boolean eventGetCtrlKey(Event evt) {
+ public static boolean eventGetCtrlKey(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
| Event.KEYEVENTS | Event.ONCONTEXTMENU, "ctrlKey");
return impl.eventGetCtrlKey(evt);
@@ -485,8 +503,10 @@
*
* @param evt the event to be tested
* @return the element from which the mouse pointer was moved
+ * @throws AssertionError if event type is not one of
+ * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT}
*/
- public static Element eventGetFromElement(Event evt) {
+ public static Element eventGetFromElement(Event evt) throws AssertionError {
assertEventType(evt, Event.ONMOUSEOVER | Event.ONMOUSEOUT, "fromElement");
return impl.eventGetFromElement(evt);
}
@@ -502,9 +522,10 @@
*
* @param evt the event to be tested
* @return the Unicode character or key code.
+ * @throws AssertionError if event type is not one of {@link Event#KEYEVENTS}
* @see com.google.gwt.user.client.ui.KeyboardListener
*/
- public static int eventGetKeyCode(Event evt) {
+ public static int eventGetKeyCode(Event evt) throws AssertionError {
assertEventType(evt, Event.KEYEVENTS, "keyCode");
return impl.eventGetKeyCode(evt);
}
@@ -514,9 +535,13 @@
*
* @param evt the event to be tested
* @return <code>true</code> if META was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static boolean eventGetMetaKey(Event evt) {
- assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
+ public static boolean eventGetMetaKey(Event evt) throws AssertionError {
+ assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
| Event.KEYEVENTS | Event.ONCONTEXTMENU, "metaKey");
return impl.eventGetMetaKey(evt);
}
@@ -535,8 +560,10 @@
*
* @param evt the event to be examined.
* @return The velocity of the mouse wheel.
+ * @throws AssertionError if event type is not {@link Event#ONMOUSEWHEEL}
*/
- public static int eventGetMouseWheelVelocityY(Event evt) {
+ public static int eventGetMouseWheelVelocityY(Event evt)
+ throws AssertionError {
assertEventType(evt, Event.ONMOUSEWHEEL, "mouseWheelVelocityY");
return impl.eventGetMouseWheelVelocityY(evt);
}
@@ -546,8 +573,9 @@
*
* @param evt the event to be tested
* @return <code>true</code> if this key event was an auto-repeat
+ * @throws AssertionError if event type is not {@link Event#ONKEYDOWN}
*/
- public static boolean eventGetRepeat(Event evt) {
+ public static boolean eventGetRepeat(Event evt) throws AssertionError {
assertEventType(evt, Event.ONKEYDOWN, "repeat");
return impl.eventGetRepeat(evt);
}
@@ -557,8 +585,12 @@
*
* @param evt the event to be tested
* @return the mouse x-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL},
+ * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static int eventGetScreenX(Event evt) {
+ public static int eventGetScreenX(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.ONCLICK
| Event.ONDBLCLICK | Event.ONCONTEXTMENU, "screenX");
return impl.eventGetScreenX(evt);
@@ -569,8 +601,12 @@
*
* @param evt the event to be tested
* @return the mouse y-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL},
+ * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static int eventGetScreenY(Event evt) {
+ public static int eventGetScreenY(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONMOUSEWHEEL | Event.ONCLICK
| Event.ONDBLCLICK | Event.ONCONTEXTMENU, "screenY");
return impl.eventGetScreenY(evt);
@@ -581,8 +617,12 @@
*
* @param evt the event to be tested
* @return <code>true</code> if shift was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public static boolean eventGetShiftKey(Event evt) {
+ public static boolean eventGetShiftKey(Event evt) throws AssertionError {
assertEventType(evt, Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK
| Event.KEYEVENTS | Event.ONCONTEXTMENU, "shiftKey");
return impl.eventGetShiftKey(evt);
@@ -604,8 +644,10 @@
*
* @param evt the event to be tested
* @return the element to which the mouse pointer was moved
+ * @throws AssertionError if event type is not one of
+ * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT}
*/
- public static Element eventGetToElement(Event evt) {
+ public static Element eventGetToElement(Event evt) throws AssertionError {
assertEventType(evt, Event.ONMOUSEOVER | Event.ONMOUSEOUT, "toElement");
return impl.eventGetToElement(evt);
}
@@ -644,8 +686,9 @@
*
* @param evt the event whose key code is to be set
* @param key the new key code
+ * @throws AssertionError if event type is not one of {@link Event#KEYEVENTS}
*/
- public static void eventSetKeyCode(Event evt, char key) {
+ public static void eventSetKeyCode(Event evt, char key) throws AssertionError {
assertEventType(evt, Event.KEYEVENTS, "keyCode");
impl.eventSetKeyCode(evt, key);
}
@@ -657,7 +700,7 @@
* @param evt the event to stringize
* @return a string form of the event
*/
- public static String eventToString(Event evt) {
+ public static String eventToString(Event evt) {
return impl.eventToString(evt);
}
diff --git a/user/src/com/google/gwt/user/client/Event.java b/user/src/com/google/gwt/user/client/Event.java
index c0637a0..1a4e326 100644
--- a/user/src/com/google/gwt/user/client/Event.java
+++ b/user/src/com/google/gwt/user/client/Event.java
@@ -19,12 +19,27 @@
import com.google.gwt.core.client.JavaScriptObject;
/**
+ * <p>
* An opaque handle to a native DOM Event. An <code>Event</code> cannot be
* created directly. Instead, use the <code>Event</code> type when returning a
* native DOM event from JSNI methods. An <code>Event</code> passed back into
* JSNI becomes the original DOM event the <code>Event</code> was created
* from, and can be accessed in JavaScript code as expected. This is typically
* done by calling methods in the {@link com.google.gwt.user.client.DOM} class.
+ * </p>
+ *
+ * <h3>Event Attributes</h3>
+ * <p>
+ * In hosted mode, most accessors (eg. Event{@link #getKeyCode()} and
+ * {@link Event#getButton()}) assert that the requested attribute is reliable
+ * across all supported browsers. This means that attempting to retrieve an
+ * attribute for an {@link Event} that does not support that attribute will
+ * throw an {@link AssertionError}. For example, an {@link Event} of type
+ * {@link Event#ONCLICK} will throw an {@link AssertionError} if you attempt
+ * to get the mouse button that was clicked using {@link Event#getButton()}
+ * because the mouse button attribute is not defined for {@link Event#ONCLICK}
+ * on Internet Explorer.
+ * </p>
*/
public class Event extends JavaScriptObject {
@@ -159,24 +174,11 @@
| ONMOUSEOVER | ONMOUSEOUT;
/**
- * Value returned by DOM.getEventXXX methods when the actual integer value is
- * undefined. For example, DOM.getEventKeyCode returns UNDEFINED for
- * non-keyboard events.
+ * Value returned by accessors when the actual integer value is undefined. In
+ * hosted mode, most accessors assert that the requested attribute is reliable
+ * across all supported browsers.
*
- * If assertions are enabled in hosted mode (using the -ea or
- * -enableassertion compiler flag), DOM.getEventXXX will throw assertion
- * errors instead of returning UNDEFINED. The assertions in each
- * DOM.getEventXXX ensure that the attribute you are retrieving is defined for
- * all supported browsers.
- *
- * If you disable assertions, some events in some browsers will return
- * UNDEFINED. However, other browsers may return meaningless data instead of
- * UNDEFINED if the attribute does not have meaning in the context of the
- * Event. In addition, some methods might return the value 0, which equals
- * UNDEFINED, when in fact 0 is a valid return type (for example, clientX
- * could be 0). As a result, it is NOT safe to rely on the return type of
- * DOM.getEventXXX methods when assertions are disabled, because the return
- * values may not have meaning in the context of the event.
+ * @see Event
*/
@Deprecated
public static final int UNDEFINED = 0;
@@ -258,8 +260,12 @@
* Gets whether the ALT key was depressed when the given event occurred.
*
* @return <code>true</code> if ALT was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getAltKey() {
+ public final boolean getAltKey() throws AssertionError {
return DOM.eventGetAltKey(this);
}
@@ -268,8 +274,10 @@
*
* @return a bit-field, defined by {@link Event#BUTTON_LEFT},
* {@link Event#BUTTON_MIDDLE}, and {@link Event#BUTTON_RIGHT}
+ * @throws AssertionError if event type is not one of
+ * {@link Event#ONMOUSEDOWN} or {@link Event#ONMOUSEUP}
*/
- public final int getButton() {
+ public final int getButton() throws AssertionError {
return DOM.eventGetButton(this);
}
@@ -277,8 +285,12 @@
* Gets the mouse x-position within the browser window's client area.
*
* @return the mouse x-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final int getClientX() {
+ public final int getClientX() throws AssertionError {
return DOM.eventGetClientX(this);
}
@@ -286,8 +298,12 @@
* Gets the mouse y-position within the browser window's client area.
*
* @return the mouse y-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#ONMOUSEWHEEL}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final int getClientY() {
+ public final int getClientY() throws AssertionError {
return DOM.eventGetClientY(this);
}
@@ -295,8 +311,12 @@
* Gets whether the CTRL key was depressed when the given event occurred.
*
* @return <code>true</code> if CTRL was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getCtrlKey() {
+ public final boolean getCtrlKey() throws AssertionError {
return DOM.eventGetCtrlKey(this);
}
@@ -315,8 +335,10 @@
* {@link Event#ONMOUSEOVER}).
*
* @return the element from which the mouse pointer was moved
+ * @throws AssertionError if event type is not one of
+ * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT}
*/
- public final Element getFromElement() {
+ public final Element getFromElement() throws AssertionError {
return DOM.eventGetFromElement(this);
}
@@ -330,9 +352,10 @@
* </p>
*
* @return the Unicode character or key code.
+ * @throws AssertionError if event type is not one of {@link Event#KEYEVENTS}
* @see com.google.gwt.user.client.ui.KeyboardListener
*/
- public final int getKeyCode() {
+ public final int getKeyCode() throws AssertionError {
return DOM.eventGetKeyCode(this);
}
@@ -340,8 +363,12 @@
* Gets whether the META key was depressed when the given event occurred.
*
* @return <code>true</code> if META was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getMetaKey() {
+ public final boolean getMetaKey() throws AssertionError {
return DOM.eventGetMetaKey(this);
}
@@ -358,8 +385,9 @@
* </p>
*
* @return The velocity of the mouse wheel.
+ * @throws AssertionError if event type is not {@link Event#ONMOUSEWHEEL}
*/
- public final int getMouseWheelVelocityY() {
+ public final int getMouseWheelVelocityY() throws AssertionError {
return DOM.eventGetMouseWheelVelocityY(this);
}
@@ -367,8 +395,9 @@
* Gets the key-repeat state of this event.
*
* @return <code>true</code> if this key event was an auto-repeat
+ * @throws AssertionError if event type is not {@link Event#ONKEYDOWN}
*/
- public final boolean getRepeat() {
+ public final boolean getRepeat() throws AssertionError {
return DOM.eventGetRepeat(this);
}
@@ -376,8 +405,12 @@
* Gets the mouse x-position on the user's display.
*
* @return the mouse x-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL},
+ * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final int getScreenX() {
+ public final int getScreenX() throws AssertionError {
return DOM.eventGetScreenX(this);
}
@@ -385,8 +418,12 @@
* Gets the mouse y-position on the user's display.
*
* @return the mouse y-position
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONMOUSEWHEEL},
+ * {@link Event#ONCLICK}, {@link Event#ONDBLCLICK}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final int getScreenY() {
+ public final int getScreenY() throws AssertionError {
return DOM.eventGetScreenY(this);
}
@@ -394,8 +431,12 @@
* Gets whether the shift key was depressed when the given event occurred.
*
* @return <code>true</code> if shift was depressed when the event occurred
+ * @throws AssertionError if event type is not one of
+ * {@link Event#MOUSEEVENTS}, {@link Event#ONCLICK},
+ * {@link Event#ONDBLCLICK}, {@link Event#KEYEVENTS}, or
+ * {@link Event#ONCONTEXTMENU}
*/
- public final boolean getShiftKey() {
+ public final boolean getShiftKey() throws AssertionError {
return DOM.eventGetShiftKey(this);
}
@@ -425,8 +466,10 @@
* {@link Event#ONMOUSEOUT}).
*
* @return the element to which the mouse pointer was moved
+ * @throws AssertionError if event type is not one of
+ * {@link Event#ONMOUSEOVER} or {@link Event#ONMOUSEOUT}
*/
- public final Element getToElement() {
+ public final Element getToElement() throws AssertionError {
return DOM.eventGetToElement(this);
}
diff --git a/user/src/com/google/gwt/user/client/History.java b/user/src/com/google/gwt/user/client/History.java
index 0bbf840..ff8d1e6 100644
--- a/user/src/com/google/gwt/user/client/History.java
+++ b/user/src/com/google/gwt/user/client/History.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -16,11 +16,8 @@
package com.google.gwt.user.client;
import com.google.gwt.core.client.GWT;
-import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.user.client.impl.HistoryImpl;
-import java.util.ArrayList;
-
/**
* This class allows you to interact with the browser's history stack. Each
* "item" on the stack is represented by a single string, referred to as a
@@ -39,10 +36,24 @@
* <h3>Example</h3>
* {@example com.google.gwt.examples.HistoryExample}
* </p>
+ *
+ * <p>
+ * <h3>URL Encoding</h3>
+ * Any valid characters may be used in the history token and will survive
+ * round-trips through newItem to getToken()/onHistoryChanged(), but most will
+ * be encoded in the user-visible URL. The following US-ASCII characters are not
+ * encoded on any currently supported browser (but may be in the future due to
+ * future browser changes):
+ * <ul>
+ * <li>a-z
+ * <li>A-Z
+ * <li>0-9
+ * <li>;,/?:@&=+$-_.!~*()
+ * </ul>
+ * </p>
*/
public class History {
- private static ArrayList<HistoryListener> historyListeners = new ArrayList<HistoryListener>();
private static HistoryImpl impl;
static {
@@ -55,7 +66,8 @@
GWT.log(
"Unable to initialize the history subsystem; did you "
+ "include the history frame in your host page? Try "
- + "<iframe src=\"javascript:''\" id='__gwt_historyFrame' style='position:absolute;width:0;height:0;border:0'>"
+ + "<iframe src=\"javascript:''\" id='__gwt_historyFrame' "
+ + "style='position:absolute;width:0;height:0;border:0'>"
+ "</iframe>", null);
}
}
@@ -66,11 +78,13 @@
* @param listener the listener to be added
*/
public static void addHistoryListener(HistoryListener listener) {
- historyListeners.add(listener);
+ HistoryImpl.addHistoryListener(listener);
}
/**
* Programmatic equivalent to the user pressing the browser's 'back' button.
+ *
+ * Note that this does not work correctly on Safari 2.
*/
public static native void back() /*-{
$wnd.history.back();
@@ -94,29 +108,33 @@
* @return the initial token, or the empty string if none is present.
*/
public static String getToken() {
- return impl != null ? impl.getToken() : "";
+ return impl != null ? HistoryImpl.getToken() : "";
}
/**
* Adds a new browser history entry. In hosted mode, the 'back' and 'forward'
* actions are accessible via the standard Alt-Left and Alt-Right keystrokes.
- * Calling this method will cause {@link #onHistoryChanged} to be called as
- * well.
+ * Calling this method will cause {@link HistoryListener#onHistoryChanged} to
+ * be called as well.
*
* @param historyToken the token to associate with the new history item
*/
public static void newItem(String historyToken) {
- if (impl != null) {
- impl.newItem(historyToken);
- }
+ newItem(historyToken, true);
}
- public static void onHistoryChanged(String historyToken) {
- UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
- if (handler != null) {
- fireHistoryChangedAndCatch(historyToken, handler);
- } else {
- fireHistoryChangedImpl(historyToken);
+ /**
+ * Adds a new browser history entry. In hosted mode, the 'back' and 'forward'
+ * actions are accessible via the standard Alt-Left and Alt-Right keystrokes.
+ * Calling this method will cause {@link HistoryListener#onHistoryChanged} to
+ * be called as well if and only if issueEvent is true.
+ *
+ * @param historyToken the token to associate with the new history item
+ * @param issueEvent true if an onHistoryChanged event should be issued
+ */
+ public static void newItem(String historyToken, boolean issueEvent) {
+ if (impl != null) {
+ impl.newItem(historyToken, issueEvent);
}
}
@@ -126,21 +144,6 @@
* @param listener the listener to be removed
*/
public static void removeHistoryListener(HistoryListener listener) {
- historyListeners.remove(listener);
- }
-
- private static void fireHistoryChangedAndCatch(String historyToken,
- UncaughtExceptionHandler handler) {
- try {
- fireHistoryChangedImpl(historyToken);
- } catch (Throwable e) {
- handler.onUncaughtException(e);
- }
- }
-
- private static void fireHistoryChangedImpl(String historyToken) {
- for (HistoryListener listener : historyListeners) {
- listener.onHistoryChanged(historyToken);
- }
+ HistoryImpl.removeHistoryListener(listener);
}
}
diff --git a/user/src/com/google/gwt/user/client/Window.java b/user/src/com/google/gwt/user/client/Window.java
index aadbc63..56b4ae9 100644
--- a/user/src/com/google/gwt/user/client/Window.java
+++ b/user/src/com/google/gwt/user/client/Window.java
@@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -40,7 +41,7 @@
*/
public static class Location {
private static Map<String, String> paramMap;
- private static Map<String, String> unmodifiableParamMap;
+ private static Map<String, List<String>> listParamMap;
/**
* Assigns the window to a new URL. All GWT state will be lost.
@@ -57,9 +58,9 @@
* @return the string to the right of the URL's hash.
*/
- public static native String getHash() /*-{
- return $wnd.location.hash;
- }-*/;
+ public static String getHash() {
+ return impl.getHash();
+ }
/**
* Gets the URL's host and port name.
@@ -89,7 +90,9 @@
}-*/;
/**
- * Gets the URL's parameter of the specified name.
+ * Gets the URL's parameter of the specified name. Note that if multiple
+ * parameters have been specified with the same name, the last one will
+ * be returned.
*
* @param name the name of the URL's parameter
* @return the value of the URL's parameter
@@ -104,15 +107,13 @@
* changing the map would not change the window's location, the map returned
* is immutable.
*
- * @return a map from URL query parameter names to values
+ * @return a map from URL query parameter names to a list of values
*/
- public static Map<String, String> getParameterMap() {
- ensureParameterMap();
-
- if (unmodifiableParamMap == null) {
- unmodifiableParamMap = Collections.unmodifiableMap(paramMap);
+ public static Map<String, List<String>> getParameterMap() {
+ if (listParamMap == null) {
+ listParamMap = buildListParamMap(getQueryString());
}
- return unmodifiableParamMap;
+ return listParamMap;
}
/**
@@ -147,9 +148,9 @@
*
* @return the URL's query string
*/
- public static native String getQueryString() /*-{
- return $wnd.location.search;
- }-*/;
+ public static String getQueryString() {
+ return impl.getQueryString();
+ }
/**
* Reloads the current browser window. All GWT state will be lost.
@@ -168,6 +169,41 @@
$wnd.location.replace(newURL);
}-*/;
+ /**
+ * Builds the immutable map from String to List<String> that we'll return
+ * in getParameterMap(). Package-protected for testing.
+ * @return a map from the
+ */
+ static Map<String,List<String>> buildListParamMap(String queryString) {
+ Map<String,List<String>> out = new HashMap<String, List<String>>();
+
+ if (queryString != null && queryString.length() > 1) {
+ String qs = queryString.substring(1);
+
+ for (String kvPair : qs.split("&")) {
+ String[] kv = kvPair.split("=", 2);
+ if (kv[0].length() == 0) {
+ continue;
+ }
+
+ List<String> values = out.get(kv[0]);
+ if (values == null) {
+ values = new ArrayList<String>();
+ out.put(kv[0], values);
+ }
+ values.add(kv.length > 1 ? URL.decode(kv[1]) : "");
+ }
+ }
+
+ for (Map.Entry<String, List<String>> entry : out.entrySet()) {
+ entry.setValue(Collections.unmodifiableList(entry.getValue()));
+ }
+
+ out = Collections.unmodifiableMap(out);
+
+ return out;
+ }
+
private static void ensureParameterMap() {
if (paramMap == null) {
paramMap = new HashMap<String, String>();
@@ -175,7 +211,7 @@
if (queryString != null && queryString.length() > 1) {
String qs = queryString.substring(1);
for (String kvPair : qs.split("&")) {
- String[] kv = kvPair.split("=");
+ String[] kv = kvPair.split("=", 2);
if (kv.length > 1) {
paramMap.put(kv[0], URL.decode(kv[1]));
} else {
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
index 7d5ca88..a16ef2a 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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,27 +15,102 @@
*/
package com.google.gwt.user.client.impl;
-import com.google.gwt.user.client.History;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
+import com.google.gwt.user.client.HistoryListener;
+
+import java.util.ArrayList;
/**
* Native implementation associated with
* {@link com.google.gwt.user.client.History}.
+ *
+ * User classes should not use this class directly.
*/
public abstract class HistoryImpl {
- protected static void onHistoryChanged(String historyToken) {
- History.onHistoryChanged(historyToken);
+ private static ArrayList<HistoryListener> historyListeners = new ArrayList<HistoryListener>();
+
+ /**
+ * Adds a listener to be informed of changes to the browser's history stack.
+ *
+ * @param listener the listener to be added
+ */
+ public static void addHistoryListener(HistoryListener listener) {
+ historyListeners.add(listener);
}
- public native String getToken() /*-{
- return $wnd.__gwt_historyToken;
+ public static native String getToken() /*-{
+ return $wnd.__gwt_historyToken || "";
}-*/;
+ /**
+ * Removes a history listener.
+ *
+ * @param listener the listener to be removed
+ */
+ public static void removeHistoryListener(HistoryListener listener) {
+ historyListeners.remove(listener);
+ }
+
+ protected static native void setToken(String token) /*-{
+ $wnd.__gwt_historyToken = token;
+ }-*/;
+
+ private static void fireHistoryChanged(String historyToken) {
+ UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
+ if (handler != null) {
+ fireHistoryChangedAndCatch(historyToken, handler);
+ } else {
+ fireHistoryChangedImpl(historyToken);
+ }
+ }
+
+ private static void fireHistoryChangedAndCatch(String historyToken,
+ UncaughtExceptionHandler handler) {
+ try {
+ fireHistoryChangedImpl(historyToken);
+ } catch (Throwable e) {
+ handler.onUncaughtException(e);
+ }
+ }
+
+ private static void fireHistoryChangedImpl(String historyToken) {
+ // TODO: replace this copy when a more general solution to event handlers
+ // wanting to remove themselves from the listener list is implemented.
+
+ // This is necessary to avoid a CurrentModificationException in hosted
+ // mode, as the listeners may try to remove themselves from the list while
+ // it is being iterated, such as in HistoryTest.
+ HistoryListener[] listenersToInvoke = historyListeners.toArray(new HistoryListener[historyListeners.size()]);
+ for (HistoryListener listener : listenersToInvoke) {
+ listener.onHistoryChanged(historyToken);
+ }
+ }
+
public abstract boolean init();
- public abstract void newItem(String historyToken);
+ public final void newItem(String historyToken, boolean issueEvent) {
+ historyToken = (historyToken == null) ? "" : historyToken;
+ if (!historyToken.equals(getToken())) {
+ setToken(historyToken);
+ nativeUpdate(historyToken);
+ if (issueEvent) {
+ fireHistoryChangedImpl(historyToken);
+ }
+ }
+ }
- protected native String decodeFragment(String encodedFragment) /*-{
+ public final void newItemOnEvent(String historyToken) {
+ historyToken = (historyToken == null) ? "" : historyToken;
+ if (!historyToken.equals(getToken())) {
+ setToken(historyToken);
+ nativeUpdateOnEvent(historyToken);
+ fireHistoryChanged(historyToken);
+ }
+ }
+
+ protected native String decodeFragment(String encodedFragment) /*-{
// decodeURI() does *not* decode the '#' character.
return decodeURI(encodedFragment.replace("%23", "#"));
}-*/;
@@ -45,7 +120,7 @@
return encodeURI(fragment).replace("#", "%23");
}-*/;
- protected native void setToken(String token) /*-{
- $wnd.__gwt_historyToken = token;
- }-*/;
+ protected abstract void nativeUpdate(String historyToken);
+
+ protected abstract void nativeUpdateOnEvent(String historyToken);
}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java b/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
index a26fcd0..956a978 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -36,7 +36,7 @@
}
}-*/;
- private Element historyFrame;
+ protected Element historyFrame;
@Override
public boolean init() {
@@ -53,24 +53,35 @@
if (tokenElement != null) {
setToken(getTokenElementContent(tokenElement));
} else {
- newItemImpl(historyFrame, getToken(), true);
+ navigateFrame(getToken());
}
injectGlobalHandler();
return true;
}
- @Override
- public void newItem(String historyToken) {
- newItemImpl(historyFrame, historyToken, false);
- }
-
protected abstract String getTokenElementContent(Element tokenElement);
protected abstract void initHistoryToken();
protected abstract void injectGlobalHandler();
- protected abstract void newItemImpl(Element historyFrame,
- String historyToken, boolean forceAdd);
+ @Override
+ protected final void nativeUpdate(String historyToken) {
+ /*
+ * Must update the location hash since it isn't already correct.
+ */
+ updateHash(historyToken);
+ navigateFrame(historyToken);
+ }
+
+ @Override
+ protected final void nativeUpdateOnEvent(String historyToken) {
+ updateHash(historyToken);
+ }
+
+ protected abstract void navigateFrame(String historyToken);
+
+ protected abstract void updateHash(String historyToken);
+
}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
index eacc70d..69624ec 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
@@ -23,7 +23,7 @@
* {@link com.google.gwt.user.client.impl.HistoryImplFrame}.
*/
class HistoryImplIE6 extends HistoryImplFrame {
-
+
/**
* Sanitizes an untrusted string to be used in an HTML context. NOTE: This
* method of escaping strings should only be used on Internet Explorer.
@@ -40,12 +40,12 @@
/**
* For IE6, reading from $wnd.location.hash drops part of the fragment if the
- * fragment contains a '?'. To avoid this bug, we use location.href instead.
+ * fragment contains a '?'. To avoid this bug, we use location.href instead.
*/
@SuppressWarnings("unused")
private static native String getLocationHash() /*-{
var href = $wnd.location.href;
- var hashLoc = href.indexOf("#");
+ var hashLoc = href.lastIndexOf("#");
return (hashLoc > 0) ? href.substring(hashLoc) : "";
}-*/;
@@ -65,54 +65,42 @@
@Override
protected native void initHistoryToken() /*-{
+ // Assume an empty token.
+ var token = '';
// Get the initial token from the url's hash component.
var hash = @com.google.gwt.user.client.impl.HistoryImplIE6::getLocationHash()();
if (hash.length > 0) {
try {
- $wnd.__gwt_historyToken = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
+ token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
} catch (e) {
- // Clear the bad hash and __gwt_historyToken
- // (this can't have been a valid token).
+ // Clear the bad hash (this can't have been a valid token).
$wnd.location.hash = '';
- $wnd.__gwt_historyToken = '';
}
- return;
}
-
- // There was no hash. Just start off with an empty token.
- $wnd.__gwt_historyToken = '';
+ @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
}-*/;
@Override
protected native void injectGlobalHandler() /*-{
var historyImplRef = this;
-
+
$wnd.__gwt_onHistoryLoad = function(token) {
- // Change the URL and notify the application that its history frame
- // is changing.
-
- if (token != $wnd.__gwt_historyToken) {
- $wnd.__gwt_historyToken = token;
- $wnd.location.hash = historyImplRef.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(token);
-
- @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)(token);
- }
+ historyImplRef.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token);
};
}-*/;
- @Override
- protected native void newItemImpl(Element historyFrame, String historyToken, boolean forceAdd) /*-{
- historyToken = @com.google.gwt.user.client.impl.HistoryImplIE6::escapeHtml(Ljava/lang/String;)(historyToken || "");
- var encodedGwtHistoryToken = @com.google.gwt.user.client.impl.HistoryImplIE6::escapeHtml(Ljava/lang/String;)($wnd.__gwt_historyToken || "");
-
- if (forceAdd || (encodedGwtHistoryToken != historyToken)) {
- var doc = historyFrame.contentWindow.document;
- doc.open();
- doc.write('<html><body onload="if(parent.__gwt_onHistoryLoad)parent.__gwt_onHistoryLoad(__gwt_historyToken.innerText)"><div id="__gwt_historyToken">' + historyToken + '</div></body></html>');
- doc.close();
- }
+ protected native void navigateFrame(String token) /*-{
+ var escaped = @com.google.gwt.user.client.impl.HistoryImplIE6::escapeHtml(Ljava/lang/String;)(token);
+ var doc = this.@com.google.gwt.user.client.impl.HistoryImplFrame::historyFrame.contentWindow.document;
+ doc.open();
+ doc.write('<html><body onload="if(parent.__gwt_onHistoryLoad)parent.__gwt_onHistoryLoad(__gwt_historyToken.innerText)"><div id="__gwt_historyToken">' + escaped + '</div></body></html>');
+ doc.close();
}-*/;
-
+
+ protected native void updateHash(String token) /*-{
+ $wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(token);
+ }-*/;
+
private native void initUrlCheckTimer() /*-{
// This is the URL check timer. It detects when an unexpected change
// occurs in the document's URL (e.g. when the user enters one manually
@@ -122,6 +110,7 @@
// bar in the UI to stop working under these circumstances.
var historyImplRef = this;
var urlChecker = function() {
+ $wnd.setTimeout(urlChecker, 250);
var hash = @com.google.gwt.user.client.impl.HistoryImplIE6::getLocationHash()();
if (hash.length > 0) {
var token = '';
@@ -132,12 +121,12 @@
// if someone entered or linked to a bad url.
$wnd.location.reload();
}
-
- if ($wnd.__gwt_historyToken && (token != $wnd.__gwt_historyToken)) {
+
+ var historyToken = @com.google.gwt.user.client.impl.HistoryImpl::getToken()();
+ if (historyToken && (token != historyToken)) {
$wnd.location.reload();
}
}
- $wnd.setTimeout(urlChecker, 250);
};
urlChecker();
}-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java b/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java
index 3f1a189..b0b7b3b 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplMozilla.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -19,17 +19,26 @@
* History implementation for Mozilla-based browsers.
*/
class HistoryImplMozilla extends HistoryImplStandard {
-
+
@Override
- public native void newItem(String historyToken) /*-{
- // When the historyToken is blank or null, we are not able to set
- // $wnd.location.hash to the empty string, due to a bug in Mozilla.
- // Every time $wnd.location.hash is set to the empty string, one of the
- // characters at the end of the URL stored in $wnd.location is 'eaten'.
- // To get around this bug, we generate the module's URL, and we append a '#'
- // character onto the end. Without the '#' character at the end of the URL,
- // Mozilla would reload the page from the server.
- if (historyToken == null || historyToken.length == 0) {
+ protected String decodeFragment(String encodedFragment) {
+ // Mozilla browsers pre-decode the result of location.hash, so there's no
+ // need to decode it again (which would in fact be incorrect).
+ return encodedFragment;
+ }
+
+ /**
+ * When the historyToken is blank or null, we are not able to set
+ * $wnd.location.hash to the empty string, due to a bug in Mozilla. Every time
+ * $wnd.location.hash is set to the empty string, one of the characters at the
+ * end of the URL stored in $wnd.location is 'eaten'. To get around this bug,
+ * we generate the module's URL, and we append a '#' character onto the end.
+ * Without the '#' character at the end of the URL, Mozilla would reload the
+ * page from the server.
+ */
+ @Override
+ protected native void nativeUpdate(String historyToken) /*-{
+ if (historyToken.length == 0) {
var s = $wnd.location.href;
// Pull off any hash.
var i = s.indexOf('#');
@@ -41,11 +50,4 @@
$wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
}
}-*/;
-
- @Override
- protected String decodeFragment(String encodedFragment) {
- // Mozilla browsers pre-decode the result of location.hash, so there's no
- // need to decode it again (which would in fact be incorrect).
- return encodedFragment;
- }
}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplOpera.java b/user/src/com/google/gwt/user/client/impl/HistoryImplOpera.java
deleted file mode 100644
index 57ddb0b..0000000
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplOpera.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2008 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.impl;
-
-/**
- * History implementation for Opera.
- */
-class HistoryImplOpera extends HistoryImplStandard {
-
- @Override
- public native void newItem(String historyToken) /*-{
- historyToken = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken || "");
-
- // Opera adds a new stack item each time location.hash is set. All other
- // browsers check whether the value actually changes, which we duplicate.
- var prevHistoryToken = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)($wnd.__gwt_historyToken || "");
- if (prevHistoryToken != historyToken) {
- $wnd.location.hash = historyToken;
- }
- }-*/;
-}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
index 81b2325..a37a6c2 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
@@ -51,35 +51,35 @@
if (isOldSafari) {
initImpl();
return true;
+ } else {
+ return super.init();
}
-
- return super.init();
}
@Override
- public void newItem(String historyToken) {
+ protected void nativeUpdate(String historyToken) {
if (isOldSafari) {
- newItemImpl(historyToken);
- return;
+ nativeUpdateImpl(historyToken);
+ } else {
+ super.nativeUpdate(historyToken);
}
-
- super.newItem(historyToken);
}
private native void initImpl() /*-{
- $wnd.__gwt_historyToken = '';
+ var token = '';
// Get the initial token from the url's hash component.
var hash = $wnd.location.hash;
if (hash.length > 0) {
- $wnd.__gwt_historyToken =
- this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
+ token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
}
- @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)($wnd.__gwt_historyToken);
+ @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
+
+ @com.google.gwt.user.client.impl.HistoryImpl::fireHistoryChangedImpl(Ljava/lang/String;)($wnd.__gwt_historyToken);
}-*/;
- private native void newItemImpl(String historyToken) /*-{
+ private native void nativeUpdateImpl(String historyToken) /*-{
// Use a bizarre meta refresh trick to update the url's hash, without
// creating a history entry.
var meta = $doc.createElement('meta');
@@ -92,9 +92,5 @@
window.setTimeout(function() {
$doc.body.removeChild(meta);
}, 1);
-
- // Update the global history token and fire the history event.
- $wnd.__gwt_historyToken = historyToken;
- @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)($wnd.__gwt_historyToken);
}-*/;
}
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java b/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
index 7278862..0fb2b83 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
@@ -22,27 +22,27 @@
@Override
public native boolean init() /*-{
- $wnd.__gwt_historyToken = '';
+ var token = '';
// Get the initial token from the url's hash component.
var hash = $wnd.location.hash;
- if (hash.length > 0)
- $wnd.__gwt_historyToken = hash.substring(1);
+ if (hash.length > 0) {
+ token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
+ }
+
+ @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
// Create the timer that checks the browser's url hash every 1/4 s.
var historyImpl = this;
$wnd.__checkHistory = function() {
+ $wnd.setTimeout($wnd.__checkHistory, 250);
+
var token = '', hash = $wnd.location.hash;
if (hash.length > 0) {
token = historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1));
}
- if (token != $wnd.__gwt_historyToken) {
- $wnd.__gwt_historyToken = token;
- @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)(token);
- }
-
- $wnd.setTimeout($wnd.__checkHistory, 250);
+ historyImpl.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token);
};
// Kick off the timer.
@@ -50,11 +50,16 @@
return true;
}-*/;
- @Override
- public native void newItem(String historyToken) /*-{
- if (historyToken == null) {
- historyToken = "";
- }
+ /**
+ * The standard updateHash implementation assigns to location.hash() with an
+ * encoded history token.
+ */
+ protected native void nativeUpdate(String historyToken) /*-{
$wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
}-*/;
+
+ @Override
+ protected void nativeUpdateOnEvent(String historyToken) {
+ // Do nothing, the hash is already updated.
+ }
}
diff --git a/user/src/com/google/gwt/user/client/impl/WindowImpl.java b/user/src/com/google/gwt/user/client/impl/WindowImpl.java
index 61efc5a..d5d9fa6 100644
--- a/user/src/com/google/gwt/user/client/impl/WindowImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/WindowImpl.java
@@ -33,6 +33,14 @@
return @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.clientWidth;
}-*/;
+ public native String getHash() /*-{
+ return $wnd.location.hash;
+ }-*/;
+
+ public native String getQueryString() /*-{
+ return $wnd.location.search;
+ }-*/;
+
public native int getScrollLeft() /*-{
return @com.google.gwt.user.client.impl.DocumentRootImpl::documentRoot.scrollLeft;
}-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/WindowImplIE.java b/user/src/com/google/gwt/user/client/impl/WindowImplIE.java
new file mode 100644
index 0000000..9f66ac0
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/impl/WindowImplIE.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 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.impl;
+
+/**
+ * IE implementation of {@link com.google.gwt.user.client.impl.WindowImpl}.
+ */
+public class WindowImplIE extends WindowImpl {
+
+ /**
+ * For IE6, reading from $wnd.location.hash drops part of the fragment if the
+ * fragment contains a '?'. To avoid this bug, we use location.href instead.
+ */
+ @Override
+ public native String getHash() /*-{
+ var href = $wnd.location.href;
+ var hashLoc = href.lastIndexOf("#");
+ return (hashLoc > 0) ? href.substring(hashLoc) : "";
+ }-*/;
+
+ /**
+ * For IE6, reading from $wnd.location.search gets confused if hash contains
+ * a '?'. To avoid this bug, we use location.href instead.
+ */
+ @Override
+ public native String getQueryString() /*-{
+ var href = $wnd.location.href;
+ var hashLoc = href.lastIndexOf("#");
+ if (hashLoc >= 0) {
+ // strip off any hash first
+ href = href.substring(0, hashLoc);
+ }
+ var questionLoc = href.lastIndexOf("?");
+ return (questionLoc > 0) ? href.substring(questionLoc) : "";
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java b/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java
index 355e75d..17ce5b8 100644
--- a/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java
+++ b/user/src/com/google/gwt/user/client/ui/AbstractImagePrototype.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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,8 @@
*/
package com.google.gwt.user.client.ui;
+import com.google.gwt.dom.client.Element;
+
/**
* An opaque representation of a particular image such that the image can be
* accessed either as an HTML fragment or as an {@link Image} object. An image
@@ -34,6 +36,11 @@
* </p>
*
* <p>
+ * This class also provide methods for working with raw elements, using
+ * {@link #createElement()} and {@link #applyTo(ImagePrototypeElement)}.
+ * </p>
+ *
+ * <p>
* This class is also a useful way to encapsulate complex HTML that represents
* an image without actually instantiating <code>Image</code> objects. When
* constructing large HTML fragments, especially those that contain many images,
@@ -43,6 +50,15 @@
public abstract class AbstractImagePrototype {
/**
+ * This corresponds to the top Element of the DOM structure created by
+ * {@link #createElement()}.
+ */
+ public static class ImagePrototypeElement extends Element {
+ protected ImagePrototypeElement() {
+ };
+ }
+
+ /**
* Transforms an existing {@link Image} into the image represented by this
* prototype.
*
@@ -51,10 +67,38 @@
public abstract void applyTo(Image image);
/**
+ * Transforms an existing {@link ImagePrototypeElement} into the image
+ * represented by this prototype.
+ *
+ * @param imageElement an <code>ImagePrototypeElement</code> created by
+ * {@link #createElement()}
+ */
+ public void applyTo(ImagePrototypeElement imageElement) {
+ // Because this is a new method on an existing base class, we need to throw
+ // UnsupportedOperationException to avoid static errors.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Creates a new {@link Element} based on the image represented by this
+ * prototype. The DOM structure may not necessarily a simple
+ * <code><img></code> element. It may be a more complex structure that
+ * should be treated opaquely.
+ *
+ * @return the <code>ImagePrototypeElement</code> corresponding to the image
+ * represented by this prototype
+ */
+ public ImagePrototypeElement createElement() {
+ // Because this is a new method on an existing base class, we need to throw
+ // UnsupportedOperationException to avoid static errors.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* Creates a new {@link Image} instance based on the image represented by this
* prototype.
*
- * @return a new <code>Image</code> based on this prototype
+ * @return a new {@link Image} based on this prototype
*/
public abstract Image createImage();
diff --git a/user/src/com/google/gwt/user/client/ui/DecoratedPopupPanel.java b/user/src/com/google/gwt/user/client/ui/DecoratedPopupPanel.java
index fe59e0f..275daa5 100644
--- a/user/src/com/google/gwt/user/client/ui/DecoratedPopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DecoratedPopupPanel.java
@@ -24,6 +24,23 @@
* A {@link PopupPanel} that wraps its content in a 3x3 grid, which allows users
* to add rounded corners.
* </p>
+ *
+ * <h3>Setting the Size:</h3>
+ * <p>
+ * If you set the width or height of the {@link DecoratedPopupPanel}, you need
+ * to set the height and width of the middleCenter cell to 100% so that the
+ * middleCenter cell takes up all of the available space. If you do not set the
+ * width and height of the {@link DecoratedPopupPanel}, it will wrap its
+ * contents tightly.
+ * </p>
+ *
+ * <pre>
+ * .gwt-DecoratedPopupPanel .popupMiddleCenter {
+ * height: 100%;
+ * width: 100%;
+ * }
+ * </pre>
+ *
* <h3>CSS Style Rules</h3>
* <ul class='css'>
* <li>.gwt-DecoratedPopupPanel { the outside of the popup }</li>
diff --git a/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java b/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java
index 2fdb849..a361b46 100644
--- a/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java
@@ -34,6 +34,21 @@
* 8-bit transparencies (anti-aliasing and shadows) in ie6, which does not
* support them normally.
* </p>
+ * <h3>Setting the Size:</h3>
+ * <p>
+ * If you set the width or height of the {@link DecoratorPanel}, you need to
+ * set the height and width of the middleCenter cell to 100% so that the
+ * middleCenter cell takes up all of the available space. If you do not set the
+ * width and height of the {@link DecoratorPanel}, it will wrap its contents
+ * tightly.
+ * </p>
+ *
+ * <pre>
+ * .gwt-DecoratorPanel .middleCenter {
+ * height: 100%;
+ * width: 100%;
+ * }
+ * </pre>
*
* <h3>CSS Style Rules</h3>
* <ul class='css'>
diff --git a/user/src/com/google/gwt/user/client/ui/Label.java b/user/src/com/google/gwt/user/client/ui/Label.java
index 07faf0b..a58d854 100644
--- a/user/src/com/google/gwt/user/client/ui/Label.java
+++ b/user/src/com/google/gwt/user/client/ui/Label.java
@@ -147,7 +147,7 @@
}
public boolean getWordWrap() {
- return getElement().getStyle().getProperty("whiteSpace").equals("nowrap");
+ return !getElement().getStyle().getProperty("whiteSpace").equals("nowrap");
}
@Override
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 1b3d77e..6e8a642 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -144,16 +144,6 @@
}
/**
- * Creates an empty horizontal menu bar that uses the specified image bundle
- * for menu images.
- *
- * @param images a bundle that provides images for this menu
- */
- public MenuBar(MenuBarImages images) {
- this(false, images);
- }
-
- /**
* Creates an empty menu bar.
*
* @param vertical <code>true</code> to orient the menu bar vertically
@@ -179,6 +169,16 @@
}
/**
+ * Creates an empty horizontal menu bar that uses the specified image bundle
+ * for menu images.
+ *
+ * @param images a bundle that provides images for this menu
+ */
+ public MenuBar(MenuBarImages images) {
+ this(false, images);
+ }
+
+ /**
* Adds a menu item to the bar.
*
* @param item the item to be added
@@ -355,6 +355,7 @@
} else {
moveToPrevItem();
}
+ eatEvent(event);
break;
case KeyboardListener.KEY_RIGHT:
if (LocaleInfo.getCurrentLocale().isRTL()) {
@@ -362,19 +363,24 @@
} else {
moveToNextItem();
}
+ eatEvent(event);
break;
case KeyboardListener.KEY_UP:
moveUp();
+ eatEvent(event);
break;
case KeyboardListener.KEY_DOWN:
moveDown();
+ eatEvent(event);
break;
case KeyboardListener.KEY_ESCAPE:
closeAllParents();
+ eatEvent(event);
break;
case KeyboardListener.KEY_ENTER:
if (!selectFirstItemIfNoneSelected()) {
doItemAction(selectedItem, true);
+ eatEvent(event);
}
break;
} // end switch(keyCode)
@@ -747,6 +753,11 @@
}
}
+ private void eatEvent(Event event) {
+ DOM.eventCancelBubble(event, true);
+ DOM.eventPreventDefault(event);
+ }
+
private MenuItem findItem(Element hItem) {
for (MenuItem item : items) {
if (DOM.isOrHasChild(item.getElement(), hItem)) {
diff --git a/user/src/com/google/gwt/user/client/ui/PopupPanel.java b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
index beab417..9591092 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -744,9 +744,9 @@
*
* @param elt The Element on which <code>blur()</code> will be invoked
*/
- private native void blur(Element elt)
- /*-{
- if (elt.blur) {
+ private native void blur(Element elt) /*-{
+ // Issue 2390: blurring the body causes IE to disappear to the background
+ if (elt.blur && elt != $doc.body) {
elt.blur();
}
}-*/;
diff --git a/user/src/com/google/gwt/user/client/ui/Tree.java b/user/src/com/google/gwt/user/client/ui/Tree.java
index 0b1c511..334f166 100644
--- a/user/src/com/google/gwt/user/client/ui/Tree.java
+++ b/user/src/com/google/gwt/user/client/ui/Tree.java
@@ -20,6 +20,7 @@
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.AbstractImagePrototype.ImagePrototypeElement;
import java.util.ArrayList;
import java.util.HashMap;
@@ -110,11 +111,11 @@
return baseUrl;
}
}
-
- private static final int OTHER_KEY_UP = 63232;
+
private static final int OTHER_KEY_DOWN = 63233;
private static final int OTHER_KEY_LEFT = 63234;
private static final int OTHER_KEY_RIGHT = 63235;
+ private static final int OTHER_KEY_UP = 63232;
static native boolean shouldTreeDelegateFocusToElement(Element elem) /*-{
var name = elem.nodeName;
@@ -124,8 +125,8 @@
(name == "OPTION") ||
(name == "BUTTON") ||
(name == "LABEL"));
- }-*/;
-
+ }-*/;
+
private static boolean isArrowKey(int code) {
switch (code) {
case OTHER_KEY_DOWN:
@@ -179,17 +180,15 @@
private Element focusable;
private FocusListenerCollection focusListeners;
private TreeImages images;
+ private String indentValue;
private boolean isAnimationEnabled = false;
private KeyboardListenerCollection keyboardListeners;
+ private boolean lastWasKeyDown;
+
private TreeListenerCollection listeners;
private MouseListenerCollection mouseListeners = null;
private TreeItem root;
- private boolean lastWasKeyDown;
-
- private Image leafImage;
- private Image openImage;
- private Image closedImage;
- private String indentValue;
+ private boolean useLeafImages;
/**
* Constructs an empty tree.
@@ -379,7 +378,7 @@
@SuppressWarnings("fallthrough")
public void onBrowserEvent(Event event) {
int eventType = DOM.eventGetType(event);
-
+
switch (eventType) {
case Event.ONKEYDOWN: {
// If nothing's selected, select the first item.
@@ -391,8 +390,8 @@
return;
}
}
-
- // Intentional fallthrough.
+
+ // Intentional fallthrough.
case Event.ONKEYPRESS:
case Event.ONKEYUP:
// Issue 1890: Do not block history navigation via alt+left/right
@@ -402,7 +401,7 @@
}
break;
}
-
+
switch (eventType) {
case Event.ONCLICK: {
Element e = DOM.eventGetTarget(event);
@@ -410,7 +409,8 @@
// The click event should have given focus to this element already.
// Avoid moving focus back up to the tree (so that focusable widgets
// attached to TreeItems can receive keyboard events).
- } else {
+ } else if (curSelection != null
+ && curSelection.getContentElem().isOrHasChild(e)) {
setFocus(true);
}
break;
@@ -471,13 +471,13 @@
break;
}
-
+
case Event.ONKEYDOWN: {
keyboardNavigation(event);
- lastWasKeyDown = true;
+ lastWasKeyDown = true;
break;
}
-
+
case Event.ONKEYPRESS: {
if (!lastWasKeyDown) {
keyboardNavigation(event);
@@ -485,7 +485,7 @@
lastWasKeyDown = false;
break;
}
-
+
case Event.ONKEYUP: {
if (DOM.eventGetKeyCode(event) == KeyboardListener.KEY_TAB) {
ArrayList<Element> chain = new ArrayList<Element>();
@@ -495,12 +495,12 @@
setSelectedItem(item, true);
}
}
-
+
lastWasKeyDown = false;
break;
}
}
-
+
switch (eventType) {
case Event.ONKEYDOWN:
case Event.ONKEYUP:
@@ -519,7 +519,7 @@
// We must call SynthesizedWidget's implementation for all other events.
super.onBrowserEvent(event);
}
-
+
public boolean remove(Widget w) {
// Validate.
TreeItem item = childWidgets.get(w);
@@ -754,7 +754,7 @@
* @param treeItem the tree item
*/
void showClosedImage(TreeItem treeItem) {
- showImage(treeItem, closedImage);
+ showImage(treeItem, images.treeClosed());
}
/**
@@ -763,8 +763,8 @@
* @param treeItem the tree item
*/
void showLeafImage(TreeItem treeItem) {
- if (leafImage != null) {
- showImage(treeItem, leafImage);
+ if (useLeafImages) {
+ showImage(treeItem, images.treeLeaf());
} else {
DOM.setStyleAttribute(treeItem.getElement(), "paddingLeft", indentValue);
}
@@ -776,7 +776,7 @@
* @param treeItem the tree item
*/
void showOpenImage(TreeItem treeItem) {
- showImage(treeItem, openImage);
+ showImage(treeItem, images.treeOpen());
}
/**
@@ -937,7 +937,7 @@
// Handle keyboard events if keyboard navigation is enabled
if (isKeyboardNavigationEnabled(curSelection)) {
int code = DOM.eventGetKeyCode(event);
-
+
switch (standardizeKeycode(code)) {
case KeyboardListener.KEY_UP: {
moveSelectionUp(curSelection);
@@ -1122,9 +1122,10 @@
}
private void setImages(TreeImages images, boolean useLeafImages) {
- if (useLeafImages) {
- leafImage = images.treeLeaf().createImage();
- } else {
+ this.images = images;
+ this.useLeafImages = useLeafImages;
+
+ if (!useLeafImages) {
Image image = images.treeLeaf().createImage();
DOM.setStyleAttribute(image.getElement(), "visibility", "hidden");
RootPanel.get().add(image);
@@ -1132,18 +1133,19 @@
image.removeFromParent();
indentValue = (size) + "px";
}
-
- openImage = images.treeOpen().createImage();
- closedImage = images.treeClosed().createImage();
}
- private void showImage(TreeItem treeItem, Image image) {
- Element element = treeItem.getImageHolderElement();
- Element child = DOM.getFirstChild(element);
- if (child != null) {
- DOM.removeChild(element, child);
+ private void showImage(TreeItem treeItem, AbstractImagePrototype proto) {
+ Element holder = treeItem.getImageHolderElement();
+ Element child = DOM.getFirstChild(holder);
+ if (child == null) {
+ // If no image element has been created yet, create one from the
+ // prototype.
+ DOM.appendChild(holder, proto.createElement().<Element> cast());
+ } else {
+ // Otherwise, simply apply the prototype to the existing element.
+ proto.applyTo(child.<ImagePrototypeElement> cast());
}
- DOM.appendChild(element, DOM.clone(image.getElement(), true));
}
private void updateAriaAttributes() {
@@ -1216,4 +1218,3 @@
DOM.getElementAttribute(curSelectionContentElem, "id"));
}
}
-
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/client/ui/TreeItem.java b/user/src/com/google/gwt/user/client/ui/TreeItem.java
index f68728b..724beab 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeItem.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeItem.java
@@ -38,6 +38,91 @@
*/
public class TreeItem extends UIObject implements HasHTML {
/**
+ * Implementation class for {@link TreeItem}.
+ */
+ public static class TreeItemImpl {
+ public TreeItemImpl() {
+ initializeClonableElements();
+ }
+
+ void convertToFullNode(TreeItem item) {
+ if (item.imageHolder == null) {
+ // Extract the Elements from the object
+ Element itemTable = DOM.clone(BASE_INTERNAL_ELEM, true);
+ DOM.appendChild(item.getElement(), itemTable);
+ Element tr = DOM.getFirstChild(DOM.getFirstChild(itemTable));
+ Element tdImg = DOM.getFirstChild(tr);
+ Element tdContent = DOM.getNextSibling(tdImg);
+
+ // Undoes padding from table element.
+ DOM.setStyleAttribute(item.getElement(), "padding", "0px");
+ DOM.appendChild(tdContent, item.contentElem);
+ item.imageHolder = tdImg;
+ }
+ }
+
+ /**
+ * Setup clonable elements.
+ */
+ void initializeClonableElements() {
+ if (GWT.isClient()) {
+ // Create the base table element that will be cloned.
+ BASE_INTERNAL_ELEM = DOM.createTable();
+ Element contentElem = DOM.createSpan();
+ Element tbody = DOM.createTBody(), tr = DOM.createTR();
+ Element tdImg = DOM.createTD(), tdContent = DOM.createTD();
+ DOM.appendChild(BASE_INTERNAL_ELEM, tbody);
+ DOM.appendChild(tbody, tr);
+ DOM.appendChild(tr, tdImg);
+ DOM.appendChild(tr, tdContent);
+ DOM.setStyleAttribute(tdImg, "verticalAlign", "middle");
+ DOM.setStyleAttribute(tdContent, "verticalAlign", "middle");
+ DOM.appendChild(tdContent, contentElem);
+ DOM.setStyleAttribute(contentElem, "display", "inline");
+ setStyleName(contentElem, "gwt-TreeItem");
+ DOM.setStyleAttribute(BASE_INTERNAL_ELEM, "whiteSpace", "nowrap");
+
+ // Create the base element that will be cloned
+ BASE_BARE_ELEM = DOM.createDiv();
+
+ // Simulates padding from table element.
+ DOM.setStyleAttribute(BASE_BARE_ELEM, "padding", "3px");
+ DOM.appendChild(BASE_BARE_ELEM, contentElem);
+ Accessibility.setRole(contentElem, Accessibility.ROLE_TREEITEM);
+ }
+ }
+ }
+
+ /**
+ * IE specific implementation class for {@link TreeItem}.
+ */
+ public static class TreeItemImplIE6 extends TreeItemImpl {
+ @Override
+ void convertToFullNode(TreeItem item) {
+ super.convertToFullNode(item);
+ DOM.setStyleAttribute(item.getElement(), "marginBottom", "0px");
+ }
+
+ @Override
+ void initializeClonableElements() {
+ super.initializeClonableElements();
+ if (GWT.isClient()) {
+ // Remove the padding from the cells and re-add it to the table element
+ DOM.setElementPropertyInt(BASE_INTERNAL_ELEM, "cellPadding", 0);
+ DOM.setElementPropertyInt(BASE_INTERNAL_ELEM, "cellSpacing", 0);
+ BASE_INTERNAL_ELEM.getStyle().setPropertyPx("paddingBottom", 3);
+
+ // We can't use a 3px padding all around because IE will wrap the
+ // childSpan to the next line, so we need to add a 3px margin on the top
+ // and bottom instead. However, margins overlap, so we need a 6px bottom
+ // margin.
+ DOM.setStyleAttribute(BASE_BARE_ELEM, "margin", "3px 0px 6px 0px");
+ DOM.setStyleAttribute(BASE_BARE_ELEM, "padding", "0px 3px");
+ }
+ }
+ }
+
+ /**
* An {@link Animation} used to open the child elements. If a {@link TreeItem}
* is in the process of opening, it will immediately be opened and the new
* {@link TreeItem} will use this animation.
@@ -99,20 +184,20 @@
@Override
protected void onStart() {
scrollHeight = 0;
-
+
// If the TreeItem is already open, we can get its scrollHeight
// immediately.
if (!opening) {
scrollHeight = curItem.childSpanElem.getScrollHeight();
}
DOM.setStyleAttribute(curItem.childSpanElem, "overflow", "hidden");
-
+
// If the TreeItem is already open, onStart will set its height to its
- // natural height. If the TreeItem is currently closed, onStart will set
+ // natural height. If the TreeItem is currently closed, onStart will set
// its height to 1px (see onUpdate below), and then we make the TreeItem
// visible so we can get its correct scrollHeight.
super.onStart();
-
+
// If the TreeItem is currently closed, we need to make it visible before
// we can get its height.
if (opening) {
@@ -149,7 +234,7 @@
static final int IMAGE_PAD = 7;
/**
- * The duration of the animation.
+ * The duration of the animation.
*/
private static final int ANIMATION_DURATION = 200;
@@ -174,36 +259,9 @@
* The base tree item element that will be cloned.
*/
private static Element BASE_BARE_ELEM;
- /**
- * Static constructor to set up clonable elements.
- */
- static {
- if (GWT.isClient()) {
- // Create the base table element that will be cloned.
- BASE_INTERNAL_ELEM = DOM.createTable();
- Element contentElem = DOM.createSpan();
- Element tbody = DOM.createTBody(), tr = DOM.createTR();
- Element tdImg = DOM.createTD(), tdContent = DOM.createTD();
- DOM.appendChild(BASE_INTERNAL_ELEM, tbody);
- DOM.appendChild(tbody, tr);
- DOM.appendChild(tr, tdImg);
- DOM.appendChild(tr, tdContent);
- DOM.setStyleAttribute(tdImg, "verticalAlign", "middle");
- DOM.setStyleAttribute(tdContent, "verticalAlign", "middle");
- DOM.appendChild(tdContent, contentElem);
- DOM.setStyleAttribute(contentElem, "display", "inline");
- setStyleName(contentElem, "gwt-TreeItem");
- DOM.setStyleAttribute(BASE_INTERNAL_ELEM, "whiteSpace", "nowrap");
- // Create the base element that will be cloned
- BASE_BARE_ELEM = DOM.createDiv();
+ private static TreeItemImpl impl = GWT.create(TreeItemImpl.class);
- // Simulates padding from table element.
- DOM.setStyleAttribute(BASE_BARE_ELEM, "padding", "3px");
- DOM.appendChild(BASE_BARE_ELEM, contentElem);
- Accessibility.setRole(contentElem, Accessibility.ROLE_TREEITEM);
- }
- }
private ArrayList<TreeItem> children;
private Element contentElem, childSpanElem, imageHolder;
private boolean open;
@@ -641,7 +699,6 @@
childSpanElem = DOM.createDiv();
DOM.appendChild(getElement(), childSpanElem);
DOM.setStyleAttribute(childSpanElem, "whiteSpace", "nowrap");
- DOM.setStyleAttribute(childSpanElem, "overflow", "hidden");
children = new ArrayList<TreeItem>();
}
@@ -725,20 +782,7 @@
}
private void convertToFullNode() {
- if (imageHolder == null) {
- // Extract the Elements from the object
- Element itemTable = DOM.clone(BASE_INTERNAL_ELEM, true);
- DOM.appendChild(getElement(), itemTable);
- Element tr = DOM.getFirstChild(DOM.getFirstChild(itemTable));
- Element tdImg = DOM.getFirstChild(tr);
- Element tdContent = DOM.getNextSibling(tdImg);
-
- // Undoes padding from table element.
- DOM.setStyleAttribute(getElement(), "padding", "0px");
- DOM.setStyleAttribute(getElement(), "paddingLeft", "0px");
- DOM.appendChild(tdContent, contentElem);
- imageHolder = tdImg;
- }
+ impl.convertToFullNode(this);
}
private void updateStateRecursiveHelper() {
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java
index cba3204..5a835f3 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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,9 +15,9 @@
*/
package com.google.gwt.user.client.ui.impl;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
/**
* Uses a combination of a clear image and a background image to clip all except
@@ -32,16 +32,16 @@
int height) {
String style = "url(" + url + ") no-repeat " + (-left + "px ")
+ (-top + "px");
- DOM.setStyleAttribute(img, "background", style);
- DOM.setStyleAttribute(img, "width", width + "px");
- DOM.setStyleAttribute(img, "height", height + "px");
+ img.getStyle().setProperty("background", style);
+ img.getStyle().setPropertyPx("width", width);
+ img.getStyle().setPropertyPx("height", height);
}
public Element createStructure(String url, int left, int top, int width,
int height) {
- Element tmp = DOM.createSpan();
- DOM.setInnerHTML(tmp, getHTML(url, left, top, width, height));
- return DOM.getFirstChild(tmp);
+ Element tmp = Document.get().createSpanElement();
+ tmp.setInnerHTML(getHTML(url, left, top, width, height));
+ return tmp.getFirstChildElement();
}
public String getHTML(String url, int left, int top, int width, int height) {
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java
index db96a9f..6c83175 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ClippedImageImplIE6.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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,9 +15,8 @@
*/
package com.google.gwt.user.client.ui.impl;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Element;
/**
* Implements the clipped image as a IMG inside a custom tag because we can't
@@ -46,23 +45,23 @@
public void adjust(Element clipper, String url, int left, int top, int width,
int height) {
- DOM.setStyleAttribute(clipper, "width", width + "px");
- DOM.setStyleAttribute(clipper, "height", height + "px");
+ clipper.getStyle().setPropertyPx("width", width);
+ clipper.getStyle().setPropertyPx("height", height);
// Update the nested image's url.
- Element img = DOM.getFirstChild(clipper);
- DOM.setStyleAttribute(img, "filter",
+ Element img = clipper.getFirstChildElement();
+ img.getStyle().setProperty("filter",
"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url
+ "',sizingMethod='crop')");
- DOM.setStyleAttribute(img, "marginLeft", -left + "px");
- DOM.setStyleAttribute(img, "marginTop", -top + "px");
+ img.getStyle().setPropertyPx("marginLeft", -left);
+ img.getStyle().setPropertyPx("marginTop", -top);
// AlphaImageLoader requires that we size the image explicitly.
// It really only needs to be enough to show the revealed portion.
int imgWidth = left + width;
int imgHeight = top + height;
- DOM.setElementPropertyInt(img, "width", imgWidth);
- DOM.setElementPropertyInt(img, "height", imgHeight);
+ img.setPropertyInt("width", imgWidth);
+ img.setPropertyInt("height", imgHeight);
}
@Override
diff --git a/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java b/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java
index a5ddb21..6bb5ab5 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/ClippedImagePrototype.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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,9 +15,9 @@
*/
package com.google.gwt.user.client.ui.impl;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.AbstractImagePrototype;
+import com.google.gwt.user.client.ui.Image;
/**
* Implementation of {@link AbstractImagePrototype} for a clipped image. This
@@ -28,11 +28,11 @@
private static final ClippedImageImpl impl = GWT.create(ClippedImageImpl.class);
+ private int height = 0;
private int left = 0;
private int top = 0;
- private int width = 0;
- private int height = 0;
private String url = null;
+ private int width = 0;
public ClippedImagePrototype(String url, int left, int top, int width,
int height) {
@@ -49,6 +49,16 @@
}
@Override
+ public void applyTo(ImagePrototypeElement imageElement) {
+ impl.adjust(imageElement, url, left, top, width, height);
+ }
+
+ @Override
+ public ImagePrototypeElement createElement() {
+ return (ImagePrototypeElement) impl.createStructure(url, left, top, width, height);
+ }
+
+ @Override
public Image createImage() {
return new Image(url, left, top, width, height);
}
diff --git a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
index f35c453..c9c95ab 100644
--- a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
+++ b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome.css
@@ -14,8 +14,12 @@
* so we need to use the AlphaImageLoader in IE6 only.
*/
-body, table td, a, div, .p, pre {
- font-family: Arial, sans-serif;
+body, table td, select {
+ font-family: Arial Unicode MS, Arial, sans-serif;
+ font-size: small;
+}
+pre {
+ font-family: "courier new", courier;
font-size: small;
}
body {
@@ -305,6 +309,7 @@
}
.gwt-MenuBar-horizontal .gwt-MenuItemSeparator .menuSeparatorInner {
width: 1px;
+ height: 1px;
background: white;
}
.gwt-MenuBar-vertical {
@@ -436,7 +441,7 @@
}
.gwt-DecoratedPopupPanel .popupMiddleCenter {
padding: 3px;
- background: white;
+ background: #e3e3e3;
}
.gwt-DecoratedPopupPanel .popupTopCenter {
background: url(images/hborder.png) repeat-x;
diff --git a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
index e5b1a0b..f6b3ed3 100644
--- a/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
+++ b/user/src/com/google/gwt/user/theme/chrome/public/gwt/chrome/chrome_rtl.css
@@ -14,8 +14,12 @@
* so we need to use the AlphaImageLoader in IE6 only.
*/
-body, table td, a, div, .p, pre {
- font-family: Arial, sans-serif;
+body, table td, select {
+ font-family: Arial Unicode MS, Arial, sans-serif;
+ font-size: small;
+}
+pre {
+ font-family: "courier new", courier;
font-size: small;
}
body {
@@ -305,6 +309,7 @@
}
.gwt-MenuBar-horizontal .gwt-MenuItemSeparator .menuSeparatorInner {
width: 1px;
+ height: 1px;
background: white;
}
.gwt-MenuBar-vertical {
@@ -436,7 +441,7 @@
}
.gwt-DecoratedPopupPanel .popupMiddleCenter {
padding: 3px;
- background: white;
+ background: #e3e3e3;
}
.gwt-DecoratedPopupPanel .popupTopCenter {
background: url(images/hborder.png) repeat-x;
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
index 240ce81c..44e114a 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark.css
@@ -14,11 +14,15 @@
* so we need to use the AlphaImageLoader in IE6 only.
*/
-body, table td, a, div, .p, pre {
- font-family: Arial, sans-serif;
+body, table td, select {
+ font-family: Arial Unicode MS, Arial, sans-serif;
font-size: small;
color: #bec7cc;
}
+pre {
+ font-family: "courier new", courier;
+ font-size: small;
+}
body {
margin: 0px;
border: 0px;
@@ -82,7 +86,7 @@
.gwt-DecoratorPanel .topRight,
.gwt-DecoratorPanel .bottomLeft,
.gwt-DecoratorPanel .bottomRight {
- background: #1e1e1e;
+ background: #00CCFF;
zoom: 1;
}
.gwt-DecoratorPanel .topLeftInner,
@@ -95,24 +99,24 @@
}
.gwt-DialogBox .Caption {
- background: #888888;
+ background: #222222;
padding: 4px 4px 4px 8px;
+ color: #00CCFF;
cursor: default;
- border-bottom: 1px solid #222222;
- border-top: 5px solid #222222;
- color: black;
+ border-bottom: 1px solid #888888;
+ border-top: 5px solid #00CCFF;
}
.gwt-DialogBox .dialogContent {
}
.gwt-DialogBox .dialogMiddleCenter {
padding: 3px;
- background: #4d4d4d;
+ background: #666666;
}
html>body .gwt-DialogBox .dialogBottomCenter {
background: url(images/hborder.png) repeat-x 0px -4px;
}
* html .gwt-DialogBox .dialogBottomCenter {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DialogBox .dialogMiddleLeft {
background: url(images/vborder.png) repeat-y;
@@ -121,7 +125,7 @@
background: url(images/vborder.png) repeat-y -4px 0px;
}
* html .gwt-DialogBox .dialogMiddleRight {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DialogBox .dialogTopLeftInner {
width: 5px;
@@ -194,7 +198,7 @@
cursor: hand;
}
.gwt-DisclosurePanel .content {
- border-left: 3px solid #1e1e1e;
+ border-left: 3px solid #00CCFF;
padding: 4px 0px 4px 8px;
margin-left: 6px;
}
@@ -214,18 +218,17 @@
.gwt-HorizontalSplitPanel .hsplitter {
cursor: move;
border: 0px;
- background: #1E1E1E;
+ background: #00CCFF;
}
.gwt-VerticalSplitPanel {
}
.gwt-VerticalSplitPanel .vsplitter {
cursor: move;
border: 0px;
- background: #1E1E1E;
+ background: #00CCFF;
}
.gwt-HTML {
- color: #BEC7CC;
}
.gwt-Hyperlink {
@@ -265,10 +268,11 @@
margin: 0px;
border: 0px;
border-left: 1px solid #bec7cc;
- background: white;
+ background: #000;
}
.gwt-MenuBar-horizontal .gwt-MenuItemSeparator .menuSeparatorInner {
width: 1px;
+ height: 1px;
background: #000;
}
.gwt-MenuBar-vertical {
@@ -391,7 +395,7 @@
}
.gwt-PopupPanel {
- border: 3px solid #222222;
+ border: 3px solid #00CCFF;
padding: 3px;
background: #4D4D4D;
}
@@ -400,7 +404,8 @@
}
.gwt-DecoratedPopupPanel .popupMiddleCenter {
padding: 3px;
- background: #4D4D4D;
+ background: #00CCFF;
+ color: black;
}
.gwt-DecoratedPopupPanel .popupTopCenter {
background: url(images/hborder.png) repeat-x;
@@ -409,7 +414,7 @@
background: url(images/hborder.png) repeat-x 0px -4px;
}
* html .gwt-DecoratedPopupPanel .popupBottomCenter {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DecoratedPopupPanel .popupMiddleLeft {
background: url(images/vborder.png) repeat-y;
@@ -418,7 +423,7 @@
background: url(images/vborder.png) repeat-y -4px 0px;
}
* html .gwt-DecoratedPopupPanel .popupMiddleRight {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DecoratedPopupPanel .popupTopLeftInner {
width: 5px;
@@ -610,7 +615,7 @@
}
.gwt-StackPanel {
- border-bottom: 1px solid #000;
+ border-bottom: 1px solid #00CCFF;
}
.gwt-StackPanel .gwt-StackPanelItem {
cursor: pointer;
@@ -618,22 +623,22 @@
font-weight: bold;
font-size: 1.3em;
padding: 4px;
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #222;
}
.gwt-StackPanel .gwt-StackPanelContent {
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #666;
padding: 2px 2px 10px 5px;
}
.gwt-DecoratedStackPanel {
- border-bottom: 1px solid #000;
+ border-bottom: 1px solid #00CCFF;
}
.gwt-DecoratedStackPanel .gwt-StackPanelContent {
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #666;
padding: 2px 2px 10px 5px;
@@ -644,7 +649,7 @@
font-weight: bold;
font-size: 1.3em;
padding: 4px;
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #222;
}
@@ -679,7 +684,7 @@
background: url(images/hborder.png) repeat-x 0px -4px;
}
* html .gwt-SuggestBoxPopup .suggestPopupBottomCenter {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-SuggestBoxPopup .suggestPopupMiddleLeft {
background: url(images/vborder.png) repeat-y;
@@ -688,7 +693,7 @@
background: url(images/vborder.png) repeat-y -4px 0px;
}
* html .gwt-SuggestBoxPopup .suggestPopupMiddleRight {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-SuggestBoxPopup .suggestPopupTopLeftInner {
width: 5px;
@@ -768,16 +773,17 @@
color: #bec7cc;
font-weight: bold;
text-align: center;
- background: #222;
+ background: #222222;
}
.gwt-TabBar .gwt-TabBarItem-selected {
cursor: default;
- background: #000;
+ color: black;
+ background: #00CCFF;
}
.gwt-TabPanel {
}
.gwt-TabPanelBottom {
- border-color: #000;
+ border-color: #00CCFF;
border-style: solid;
border-width: 3px 2px 2px;
overflow: hidden;
@@ -795,24 +801,92 @@
border-collapse: collapse;
margin-left: 6px;
}
+.gwt-DecoratedTabBar .tabTopCenter {
+ padding: 0px;
+ background: #222222;
+}
.gwt-DecoratedTabBar .tabTopLeft,
-.gwt-DecoratedTabBar .tabTopRight,
+.gwt-DecoratedTabBar .tabTopRight {
+ padding: 0px;
+ zoom: 1;
+}
.gwt-DecoratedTabBar .tabTopLeftInner,
.gwt-DecoratedTabBar .tabTopRightInner {
- display: none;
+ width: 6px;
+ height: 6px;
+}
+html>body .gwt-DecoratedTabBar .tabTopLeft {
+ background: url(images/corner.png) no-repeat 0px -55px;
+}
+html>body .gwt-DecoratedTabBar .tabTopRight {
+ background: url(images/corner.png) no-repeat -6px -55px;
+}
+* html .gwt-DecoratedTabBar .tabTopLeftInner {
+ width: 5px;
+ height: 61px;
+ margin-top: -55px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+* html .gwt-DecoratedTabBar .tabTopRightInner {
+ width: 12px;
+ height: 61px;
+ margin-top: -55px;
+ margin-left: -6px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+.gwt-DecoratedTabBar .tabMiddleLeft,
+.gwt-DecoratedTabBar .tabMiddleRight {
+ width: 6px;
+ padding: 0px;
+ background: #222222;
+}
+.gwt-DecoratedTabBar .tabMiddleLeftInner,
+.gwt-DecoratedTabBar .tabMiddleRightInner {
+ width: 1px;
+ height: 1px;
}
.gwt-DecoratedTabBar .tabMiddleCenter {
- padding: 4px 6px;
+ padding: 0px 4px 2px 4px;
cursor: pointer;
cursor: hand;
- color: #bec7cc;
font-weight: bold;
text-align: center;
- background: #222;
+ background: #222222;
+}
+.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopCenter {
+ background: #00CCFF;
+}
+html>body .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopLeft {
+ background-position: 0px -61px;
+}
+html>body .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopRight {
+ background-position: -6px -61px;
+}
+* html .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopLeftInner {
+ width: 5px;
+ height: 67px;
+ margin-top: -61px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+* html .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopRightInner {
+ width: 12px;
+ height: 67px;
+ margin-top: -61px;
+ margin-left: -6px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabMiddleLeft,
+.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabMiddleRight {
+ background: #00CCFF;
}
.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabMiddleCenter {
cursor: default;
- background: #000;
+ color: black;
+ background: #00CCFF;
}
.gwt-TextArea {
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
index c27326c..356e11e 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/dark_rtl.css
@@ -14,11 +14,15 @@
* so we need to use the AlphaImageLoader in IE6 only.
*/
-body, table td, a, div, .p, pre {
- font-family: Arial, sans-serif;
+body, table td, select {
+ font-family: Arial Unicode MS, Arial, sans-serif;
font-size: small;
color: #bec7cc;
}
+pre {
+ font-family: "courier new", courier;
+ font-size: small;
+}
body {
margin: 0px;
border: 0px;
@@ -82,7 +86,7 @@
.gwt-DecoratorPanel .topRight,
.gwt-DecoratorPanel .bottomLeft,
.gwt-DecoratorPanel .bottomRight {
- background: #1e1e1e;
+ background: #00CCFF;
zoom: 1;
}
.gwt-DecoratorPanel .topLeftInner,
@@ -95,24 +99,24 @@
}
.gwt-DialogBox .Caption {
- background: #888888;
+ background: #222222;
padding: 4px 8px 4px 4px;
+ color: #00CCFF;
cursor: default;
- border-bottom: 1px solid #222222;
- border-top: 5px solid #222222;
- color: black;
+ border-bottom: 1px solid #888888;
+ border-top: 5px solid #00CCFF;
}
.gwt-DialogBox .dialogContent {
}
.gwt-DialogBox .dialogMiddleCenter {
padding: 3px;
- background: #4d4d4d;
+ background: #666666;
}
html>body .gwt-DialogBox .dialogBottomCenter {
background: url(images/hborder.png) repeat-x 0px -4px;
}
* html .gwt-DialogBox .dialogBottomCenter {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DialogBox .dialogMiddleLeft {
background: url(images/vborder.png) repeat-y;
@@ -121,7 +125,7 @@
background: url(images/vborder.png) repeat-y -4px 0px;
}
* html .gwt-DialogBox .dialogMiddleRight {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DialogBox .dialogTopLeftInner {
width: 5px;
@@ -194,7 +198,7 @@
cursor: hand;
}
.gwt-DisclosurePanel .content {
- border-right: 3px solid #1e1e1e;
+ border-right: 3px solid #00CCFF;
padding: 4px 8px 4px 0px;
margin-right: 6px;
}
@@ -214,18 +218,17 @@
.gwt-HorizontalSplitPanel .hsplitter {
cursor: move;
border: 0px;
- background: #1E1E1E;
+ background: #00CCFF;
}
.gwt-VerticalSplitPanel {
}
.gwt-VerticalSplitPanel .vsplitter {
cursor: move;
border: 0px;
- background: #1E1E1E;
+ background: #00CCFF;
}
.gwt-HTML {
- color: #BEC7CC;
}
.gwt-Hyperlink {
@@ -265,10 +268,11 @@
margin: 0px;
border: 0px;
border-right: 1px solid #bec7cc;
- background: white;
+ background: #000;
}
.gwt-MenuBar-horizontal .gwt-MenuItemSeparator .menuSeparatorInner {
width: 1px;
+ height: 1px;
background: #000;
}
.gwt-MenuBar-vertical {
@@ -391,7 +395,7 @@
}
.gwt-PopupPanel {
- border: 3px solid #222222;
+ border: 3px solid #00CCFF;
padding: 3px;
background: #4D4D4D;
}
@@ -400,7 +404,8 @@
}
.gwt-DecoratedPopupPanel .popupMiddleCenter {
padding: 3px;
- background: #4D4D4D;
+ background: #00CCFF;
+ color: black;
}
.gwt-DecoratedPopupPanel .popupTopCenter {
background: url(images/hborder.png) repeat-x;
@@ -409,7 +414,7 @@
background: url(images/hborder.png) repeat-x 0px -4px;
}
* html .gwt-DecoratedPopupPanel .popupBottomCenter {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DecoratedPopupPanel .popupMiddleLeft {
background: url(images/vborder.png) repeat-y;
@@ -418,7 +423,7 @@
background: url(images/vborder.png) repeat-y -4px 0px;
}
* html .gwt-DecoratedPopupPanel .popupMiddleRight {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-DecoratedPopupPanel .popupTopLeftInner {
width: 5px;
@@ -538,7 +543,6 @@
filter: alpha(opacity=40);
zoom: 1;
}
-
.gwt-PushButton .html-face {
color: #000;
}
@@ -611,7 +615,7 @@
}
.gwt-StackPanel {
- border-bottom: 1px solid #000;
+ border-bottom: 1px solid #00CCFF;
}
.gwt-StackPanel .gwt-StackPanelItem {
cursor: pointer;
@@ -619,22 +623,22 @@
font-weight: bold;
font-size: 1.3em;
padding: 4px;
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #222;
}
.gwt-StackPanel .gwt-StackPanelContent {
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #666;
padding: 2px 5px 10px 2px;
}
.gwt-DecoratedStackPanel {
- border-bottom: 1px solid #000;
+ border-bottom: 1px solid #00CCFF;
}
.gwt-DecoratedStackPanel .gwt-StackPanelContent {
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #666;
padding: 2px 5px 10px 2px;
@@ -645,7 +649,7 @@
font-weight: bold;
font-size: 1.3em;
padding: 4px;
- border: 1px solid #000;
+ border: 1px solid #00CCFF;
border-bottom: 0px;
background: #222;
}
@@ -680,7 +684,7 @@
background: url(images/hborder.png) repeat-x 0px -4px;
}
* html .gwt-SuggestBoxPopup .suggestPopupBottomCenter {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/hborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-SuggestBoxPopup .suggestPopupMiddleLeft {
background: url(images/vborder.png) repeat-y;
@@ -689,7 +693,7 @@
background: url(images/vborder.png) repeat-y -4px 0px;
}
* html .gwt-SuggestBoxPopup .suggestPopupMiddleRight {
- filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_black_shadow.png',sizingMethod='scale');
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/ie6/vborder_blue_shadow.png',sizingMethod='scale');
}
.gwt-SuggestBoxPopup .suggestPopupTopLeftInner {
width: 5px;
@@ -769,16 +773,17 @@
color: #bec7cc;
font-weight: bold;
text-align: center;
- background: #222;
+ background: #222222;
}
.gwt-TabBar .gwt-TabBarItem-selected {
cursor: default;
- background: #000;
+ color: black;
+ background: #00CCFF;
}
.gwt-TabPanel {
}
.gwt-TabPanelBottom {
- border-color: #000;
+ border-color: #00CCFF;
border-style: solid;
border-width: 3px 2px 2px;
overflow: hidden;
@@ -796,24 +801,92 @@
border-collapse: collapse;
margin-right: 6px;
}
+.gwt-DecoratedTabBar .tabTopCenter {
+ padding: 0px;
+ background: #222222;
+}
.gwt-DecoratedTabBar .tabTopLeft,
-.gwt-DecoratedTabBar .tabTopRight,
+.gwt-DecoratedTabBar .tabTopRight {
+ padding: 0px;
+ zoom: 1;
+}
.gwt-DecoratedTabBar .tabTopLeftInner,
.gwt-DecoratedTabBar .tabTopRightInner {
- display: none;
+ width: 6px;
+ height: 6px;
+}
+html>body .gwt-DecoratedTabBar .tabTopLeft {
+ background: url(images/corner.png) no-repeat 0px -55px;
+}
+html>body .gwt-DecoratedTabBar .tabTopRight {
+ background: url(images/corner.png) no-repeat -6px -55px;
+}
+* html .gwt-DecoratedTabBar .tabTopLeftInner {
+ width: 5px;
+ height: 61px;
+ margin-top: -55px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+* html .gwt-DecoratedTabBar .tabTopRightInner {
+ width: 12px;
+ height: 61px;
+ margin-top: -55px;
+ margin-left: -6px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+.gwt-DecoratedTabBar .tabMiddleLeft,
+.gwt-DecoratedTabBar .tabMiddleRight {
+ width: 6px;
+ padding: 0px;
+ background: #222222;
+}
+.gwt-DecoratedTabBar .tabMiddleLeftInner,
+.gwt-DecoratedTabBar .tabMiddleRightInner {
+ width: 1px;
+ height: 1px;
}
.gwt-DecoratedTabBar .tabMiddleCenter {
- padding: 4px 6px;
+ padding: 0px 4px 2px 4px;
cursor: pointer;
cursor: hand;
- color: #bec7cc;
font-weight: bold;
text-align: center;
- background: #222;
+ background: #222222;
+}
+.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopCenter {
+ background: #00CCFF;
+}
+html>body .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopLeft {
+ background-position: 0px -61px;
+}
+html>body .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopRight {
+ background-position: -6px -61px;
+}
+* html .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopLeftInner {
+ width: 5px;
+ height: 67px;
+ margin-top: -61px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+* html .gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabTopRightInner {
+ width: 12px;
+ height: 67px;
+ margin-top: -61px;
+ margin-left: -6px;
+ overflow: hidden;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='gwt/dark/images/corner.png',sizingMethod='crop');
+}
+.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabMiddleLeft,
+.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabMiddleRight {
+ background: #00CCFF;
}
.gwt-DecoratedTabBar .gwt-TabBarItem-selected .tabMiddleCenter {
cursor: default;
- background: #000;
+ color: black;
+ background: #00CCFF;
}
.gwt-TextArea {
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/corner.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/corner.png
index adcfc5b..5cad585 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/corner.png
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/corner.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/hborder.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/hborder.png
index ee96541..c53fd07 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/hborder.png
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/hborder.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topleft.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topleft.png
index fe2a423..ad6244c 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topleft.png
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topleft.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topright.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topright.png
index b148126..80518c8 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topright.png
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/corner_dialog_topright.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/hborder_black_shadow.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/hborder_black_shadow.png
deleted file mode 100644
index 5855d78..0000000
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/hborder_black_shadow.png
+++ /dev/null
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/hborder_blue_shadow.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/hborder_blue_shadow.png
new file mode 100644
index 0000000..2ac1ba3
--- /dev/null
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/hborder_blue_shadow.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/vborder_black_shadow.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/vborder_black_shadow.png
deleted file mode 100644
index d2db264..0000000
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/vborder_black_shadow.png
+++ /dev/null
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/vborder_blue_shadow.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/vborder_blue_shadow.png
new file mode 100644
index 0000000..461c1ff
--- /dev/null
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/ie6/vborder_blue_shadow.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/vborder.png b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/vborder.png
index 0fa3a07..c0c2552 100644
--- a/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/vborder.png
+++ b/user/src/com/google/gwt/user/theme/dark/public/gwt/dark/images/vborder.png
Binary files differ
diff --git a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
index 4f2aa6b..256d82a 100644
--- a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
+++ b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard.css
@@ -14,8 +14,12 @@
* so we need to use the AlphaImageLoader in IE6 only.
*/
-body, table td, a, div, .p, pre {
- font-family: Arial, sans-serif;
+body, table td, select {
+ font-family: Arial Unicode MS, Arial, sans-serif;
+ font-size: small;
+}
+pre {
+ font-family: "courier new", courier;
font-size: small;
}
body {
@@ -305,6 +309,7 @@
}
.gwt-MenuBar-horizontal .gwt-MenuItemSeparator .menuSeparatorInner {
width: 1px;
+ height: 1px;
background: white;
}
.gwt-MenuBar-vertical {
@@ -436,7 +441,7 @@
}
.gwt-DecoratedPopupPanel .popupMiddleCenter {
padding: 3px;
- background: white;
+ background: #d0e4f6;
}
.gwt-DecoratedPopupPanel .popupTopCenter {
background: url(images/hborder.png) repeat-x;
diff --git a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
index e86c67d..c0d076e 100644
--- a/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
+++ b/user/src/com/google/gwt/user/theme/standard/public/gwt/standard/standard_rtl.css
@@ -14,8 +14,12 @@
* so we need to use the AlphaImageLoader in IE6 only.
*/
-body, table td, a, div, .p, pre {
- font-family: Arial, sans-serif;
+body, table td, select {
+ font-family: Arial Unicode MS, Arial, sans-serif;
+ font-size: small;
+}
+pre {
+ font-family: "courier new", courier;
font-size: small;
}
body {
@@ -305,6 +309,7 @@
}
.gwt-MenuBar-horizontal .gwt-MenuItemSeparator .menuSeparatorInner {
width: 1px;
+ height: 1px;
background: white;
}
.gwt-MenuBar-vertical {
@@ -436,7 +441,7 @@
}
.gwt-DecoratedPopupPanel .popupMiddleCenter {
padding: 3px;
- background: white;
+ background: #d0e4f6;
}
.gwt-DecoratedPopupPanel .popupTopCenter {
background: url(images/hborder.png) repeat-x;
diff --git a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
index 246fc64..5a23afa 100644
--- a/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
+++ b/user/src/com/google/gwt/user/tools/AppHtml.htmlsrc
@@ -1,15 +1,10 @@
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-"http://www.w3.org/TR/html4/loose.dtd">
-
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
<!-- above set at the top of the file will set -->
<!-- the browser's rendering engine into -->
-<!-- "Standards Mode", which gives better cross -->
-<!-- browser compatibility to the application. -->
-<!-- Omitting this line leaves most browsers in -->
-<!-- "Quirks mode", emulating the bugs in older -->
-<!-- browser versions. -->
+<!-- "Quirks Mode". Replacing this declaration -->
+<!-- with a "Standards Mode" doctype is supported, -->
+<!-- but may lead to some differences in layout. -->
<html>
<head>
diff --git a/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc b/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
index 8f0ed45..4228170 100644
--- a/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
+++ b/user/src/com/google/gwt/user/tools/Module.gwt.xmlsrc
@@ -7,8 +7,8 @@
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
- <!-- <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> -->
- <!-- <inherits name="com.google.gwt.user.theme.dark.Dark"/> -->
+ <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
+ <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits -->
@extraModuleInherits
diff --git a/user/super/com/google/gwt/emul/java/lang/Long.java b/user/super/com/google/gwt/emul/java/lang/Long.java
index 359fc44..fb7f338 100644
--- a/user/super/com/google/gwt/emul/java/lang/Long.java
+++ b/user/super/com/google/gwt/emul/java/lang/Long.java
@@ -109,6 +109,10 @@
if (orig == null) {
throw new NumberFormatException("null");
}
+ if (orig.length() == 0) {
+ throw NumberFormatException.forInputString(orig);
+ }
+
if (intRadix < Character.MIN_RADIX || intRadix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + intRadix + " out of range");
}
diff --git a/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/GWTTestCase.java b/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/GWTTestCase.java
index ed205b2..9b592c8 100644
--- a/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/GWTTestCase.java
+++ b/user/super/com/google/gwt/junit/translatable/com/google/gwt/junit/client/GWTTestCase.java
@@ -172,6 +172,13 @@
public abstract String getModuleName();
+ @Override
+ public void runBare() throws Throwable {
+ setUp();
+ runTest();
+ // No tearDown call here; we do it from reportResults.
+ }
+
// CHECKSTYLE_OFF
protected JUnitResult __getOrCreateTestResult() {
if (result == null) {
@@ -249,6 +256,12 @@
* @param ex The results of this test.
*/
private void reportResultsAndRunNextMethod(Throwable ex) {
+ try {
+ tearDown();
+ } catch (Throwable e) {
+ // ignore any exceptions thrown from tearDown
+ }
+
JUnitResult myResult = __getOrCreateTestResult();
if (ex != null) {
ExceptionWrapper ew = new ExceptionWrapper(ex);
diff --git a/user/test/com/google/gwt/dev/jjs/test/ClassObjectTest.java b/user/test/com/google/gwt/dev/jjs/test/ClassObjectTest.java
index 35342dc..8cb569a 100644
--- a/user/test/com/google/gwt/dev/jjs/test/ClassObjectTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/ClassObjectTest.java
@@ -44,6 +44,7 @@
}
}
+ @Override
public String getModuleName() {
return "com.google.gwt.dev.jjs.CompilerSuite";
}
@@ -68,15 +69,15 @@
}
public void testAssertionStatus() {
- boolean assertionStatus = ClassObjectTest.class.desiredAssertionStatus();
+ boolean assertionStatus = ClassObjectTest.class.desiredAssertionStatus();
try {
assert false;
assertFalse(assertionStatus);
} catch (AssertionError e) {
- assertTrue(assertionStatus);
+ assertTrue(assertionStatus);
}
}
-
+
public void testClass() {
Object o = new Foo();
assertEquals(Foo.class, o.getClass());
@@ -92,6 +93,12 @@
assertNull(o.getClass().getEnumConstants());
}
+ public void testCloneClassLiteral() {
+ // getBarClass() should inline, causing a clone of a class literal
+ assertEquals("com.google.gwt.dev.jjs.test.ClassObjectTest$Bar",
+ getBarClass().getName());
+ }
+
public void testEnum() {
Object o = Bar.BAR;
assertEquals(Bar.class, o.getClass());
@@ -148,4 +155,7 @@
assertNull(int.class.getEnumConstants());
}
+ private Class<? extends Bar> getBarClass() {
+ return Bar.class;
+ }
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java b/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java
index ab2868e..172be30 100644
--- a/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/NativeLongTest.java
@@ -124,6 +124,11 @@
assertTrue(15 == l);
}
+ public void testInlinedIntInitializer() {
+ long sum = 0; // int, not long!
+ assertEquals("0", "" + (sum / INT_FOUR));
+ }
+
public void testLogicalAnd() {
assertEquals(LONG_1234, LONG_1234 & -LONG_ONE);
assertEquals(0x12341234L, LONG_1234 & LONG_FFFFFFFF);
diff --git a/user/test/com/google/gwt/emultest/java/lang/LongTest.java b/user/test/com/google/gwt/emultest/java/lang/LongTest.java
index 273e98b..879c696 100644
--- a/user/test/com/google/gwt/emultest/java/lang/LongTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/LongTest.java
@@ -22,6 +22,7 @@
*/
public class LongTest extends GWTTestCase {
+ @Override
public String getModuleName() {
return "com.google.gwt.emultest.EmulSuite";
}
@@ -87,6 +88,72 @@
assertEquals(20, Long.numberOfTrailingZeros(-0x7ff00000L));
}
+ public void testParse() {
+ assertEquals(0L, Long.parseLong("0"));
+ assertEquals(100000000000L, Long.parseLong("100000000000"));
+ assertEquals(-100000000000L, Long.parseLong("-100000000000"));
+ assertEquals(10L, Long.parseLong("010"));
+ try {
+ Long.parseLong("10L");
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+ try {
+ Long.parseLong("");
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+ try {
+ // Issue 2636
+ new Long("");
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+ try {
+ Long.parseLong("deadbeefbeef");
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+ try {
+ Long.parseLong("123456789ab123456789ab123456789ab123456789ab", 12);
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+
+ assertEquals(0L, Long.parseLong("0", 12));
+ assertEquals(73686780563L, Long.parseLong("123456789ab", 12));
+ assertEquals(-73686780563L, Long.parseLong("-123456789ab", 12));
+ try {
+ Long.parseLong("c", 12);
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+
+ assertEquals(0L, Long.parseLong("0", 16));
+ assertEquals(-1L, Long.parseLong("-1", 16));
+ assertEquals(1L, Long.parseLong("1", 16));
+ assertEquals(0xdeadbeefdeadL, Long.parseLong("deadbeefdead", 16));
+ assertEquals(-0xdeadbeefdeadL, Long.parseLong("-deadbeefdead", 16));
+ try {
+ Long.parseLong("deadbeefdeadbeefdeadbeefdeadbeef", 16);
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+ try {
+ Long.parseLong("g", 16);
+ fail("expected NumberFormatException");
+ } catch (NumberFormatException ex) {
+ // expected
+ }
+ }
+
public void testReverse() {
assertEquals(0L, Long.reverse(0L));
assertEquals(-1L, Long.reverse(-1L));
diff --git a/user/test/com/google/gwt/i18n/I18NSuite.java b/user/test/com/google/gwt/i18n/I18NSuite.java
index d8ebab6..3ed627e 100644
--- a/user/test/com/google/gwt/i18n/I18NSuite.java
+++ b/user/test/com/google/gwt/i18n/I18NSuite.java
@@ -24,6 +24,7 @@
import com.google.gwt.i18n.client.I18NTest;
import com.google.gwt.i18n.client.LocaleInfoTest;
import com.google.gwt.i18n.client.LocaleInfo_ar_Test;
+import com.google.gwt.i18n.client.NumberFormat_ar_Test;
import com.google.gwt.i18n.client.NumberFormat_en_Test;
import com.google.gwt.i18n.client.NumberFormat_fr_Test;
import com.google.gwt.i18n.client.NumberParse_en_Test;
@@ -52,6 +53,7 @@
suite.addTestSuite(I18N2Test.class);
suite.addTestSuite(LocaleInfo_ar_Test.class);
suite.addTestSuite(LocaleInfoTest.class);
+ suite.addTestSuite(NumberFormat_ar_Test.class);
suite.addTestSuite(NumberFormat_en_Test.class);
suite.addTestSuite(NumberFormat_fr_Test.class);
suite.addTestSuite(NumberParse_en_Test.class);
diff --git a/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java b/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java
new file mode 100644
index 0000000..2a82111
--- /dev/null
+++ b/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 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.i18n.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Validate NumberFormat handles Arabic numbers properly.
+ */
+public class NumberFormat_ar_Test extends GWTTestCase {
+
+ /**
+ * Use a module which forces the Arabic locale.
+ */
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.i18n.I18NTest_ar";
+ }
+
+ public void testDefault() {
+ NumberFormat fmt = NumberFormat.getDecimalFormat();
+ assertEquals("\u0663\u066B\u0661\u0664", fmt.format(3.14));
+ assertEquals("\u0663\u066B\u0661\u0664-", fmt.format(-3.14));
+ }
+
+ public void testExponent() {
+ NumberFormat fmt = NumberFormat.getScientificFormat();
+ assertEquals("\u0663\u066B\u0661\u0664\u0627\u0633\u0660",
+ fmt.format(3.14));
+ assertEquals("\u0663\u066B\u0661\u0664\u0627\u0633\u0662",
+ fmt.format(314.0));
+ assertEquals("-\u0663\u066B\u0661\u0664\u0627\u0633\u0662",
+ fmt.format(-314.0));
+ }
+
+ public void testParse() {
+ NumberFormat fmt = NumberFormat.getDecimalFormat();
+ assertEquals(3.14, fmt.parse("\u0663\u066B\u0661\u0664"));
+ assertEquals(-3.14, fmt.parse("\u0663\u066B\u0661\u0664-"));
+ assertEquals(314.0, fmt.parse("\u0663\u0661\u0664"));
+ }
+}
diff --git a/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java b/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
index ed6e727..3c0c60b 100644
--- a/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
+++ b/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
@@ -245,6 +245,28 @@
assertEquals("1234567890", str);
}
+ public void testNegative() {
+ String str;
+
+ // verify default negative pattern
+ str = NumberFormat.getFormat("#,##0.0").format(-0.15);
+ assertEquals("-0.2", str);
+ str = NumberFormat.getFormat("#,##0.0%").format(-0.1534);
+ assertEquals("-15.3%", str);
+ str = NumberFormat.getFormat("X #,##0.0%").format(-0.1534);
+ assertEquals("-X 15.3%", str);
+
+ // verify we can specify percent/permille suffixes in both parts
+ str = NumberFormat.getFormat("#,##0.0%;#,##0.0%-").format(-0.152);
+ assertEquals("15.2%-", str);
+ str = NumberFormat.getFormat("#,##0.0\u2030;#,##0.0\u2030-").format(-0.152);
+ assertEquals("152.0\u2030-", str);
+
+ // verify negative portion is only used for prefix/suffix
+ str = NumberFormat.getFormat("#,##0.00;-# X").format(-1014.336);
+ assertEquals("-1,014.34 X", str);
+ }
+
public void testPerMill() {
String str;
diff --git a/user/test/com/google/gwt/i18n/client/NumberParse_en_Test.java b/user/test/com/google/gwt/i18n/client/NumberParse_en_Test.java
index 047dded..92eb536 100644
--- a/user/test/com/google/gwt/i18n/client/NumberParse_en_Test.java
+++ b/user/test/com/google/gwt/i18n/client/NumberParse_en_Test.java
@@ -26,6 +26,7 @@
/**
* Must refer to a valid module that inherits from com.google.gwt.junit.JUnit.
*/
+ @Override
public String getModuleName() {
return "com.google.gwt.i18n.I18NTest_en";
}
diff --git a/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java b/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java
index f861b9f..f3e32a1 100644
--- a/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java
+++ b/user/test/com/google/gwt/junit/client/GWTTestCaseTest.java
@@ -20,6 +20,12 @@
*/
package com.google.gwt.junit.client;
+import static com.google.gwt.junit.client.GWTTestCaseTest.SetUpTearDownState.INITIAL;
+import static com.google.gwt.junit.client.GWTTestCaseTest.SetUpTearDownState.IS_SETUP;
+import static com.google.gwt.junit.client.GWTTestCaseTest.SetUpTearDownState.IS_TORNDOWN;
+
+import com.google.gwt.user.client.Timer;
+
import junit.framework.AssertionFailedError;
/**
@@ -28,6 +34,19 @@
*/
public class GWTTestCaseTest extends GWTTestCase {
+ /**
+ * Tracks whether or not setup and teardown have run.
+ */
+ protected enum SetUpTearDownState {
+ INITIAL, IS_SETUP, IS_TORNDOWN
+ }
+
+ /**
+ * If non-null, records an error related to setup/teardown that could not have
+ * been caught during normal test execution.
+ */
+ private static String outOfBandError = null;
+
private static void assertNotEquals(double a, double b, double delta) {
boolean failed = false;
try {
@@ -58,6 +77,11 @@
}
}
+ /**
+ * Tracks whether this test has been setup and torn down.
+ */
+ protected SetUpTearDownState setupTeardownFlag = INITIAL;
+
public String getModuleName() {
return "com.google.gwt.junit.JUnit";
}
@@ -332,4 +356,74 @@
fail("Unexpected exception during assertTrue(String, boolean) testing");
}
+
+ public void testSetUpTearDown() throws Exception {
+ assertSame(IS_SETUP, setupTeardownFlag);
+ tearDown();
+ assertSame(IS_TORNDOWN, setupTeardownFlag);
+ setUp();
+ assertSame(IS_SETUP, setupTeardownFlag);
+ gwtTearDown();
+ assertSame(IS_TORNDOWN, setupTeardownFlag);
+ gwtSetUp();
+ assertSame(IS_SETUP, setupTeardownFlag);
+ }
+
+ public void testSetUpTearDownAsync() {
+ assertSame(IS_SETUP, setupTeardownFlag);
+ delayTestFinish(1000);
+ new Timer() {
+ @Override
+ public void run() {
+ assertSame(IS_SETUP, setupTeardownFlag);
+ finishTest();
+ if (setupTeardownFlag != IS_TORNDOWN) {
+ recordOutofBandError("Bad async success tearDown behavior not catchable by JUnit");
+ }
+ }
+ }.schedule(1);
+ }
+
+ public void testSetUpTearDownAsyncHadNoOutOfBandErrors() {
+ assertNoOutOfBandErrorsAsync();
+ }
+
+ @Override
+ protected void gwtSetUp() throws Exception {
+ setupTeardownFlag = IS_SETUP;
+ }
+
+ @Override
+ protected void gwtTearDown() throws Exception {
+ if (setupTeardownFlag != IS_SETUP) {
+ // Must use window alert to grind the test to a halt in this failure.
+ recordOutofBandError("Bad tearDown behavior not catchable by JUnit");
+ }
+ setupTeardownFlag = IS_TORNDOWN;
+ }
+
+ protected static void recordOutofBandError(String outOfBandError) {
+ GWTTestCaseTest.outOfBandError = outOfBandError;
+ }
+
+ /**
+ * Call this method to asynchronously check for out of band errors in the
+ * previous test.
+ */
+ protected void assertNoOutOfBandErrorsAsync() {
+ // Give things a chance to settle down.
+ delayTestFinish(10000);
+ new Timer() {
+ @Override
+ public void run() {
+ if (outOfBandError != null) {
+ String msg = outOfBandError;
+ outOfBandError = null;
+ fail(msg);
+ }
+ finishTest();
+ }
+
+ }.schedule(1000);
+ }
}
diff --git a/user/test/com/google/gwt/junit/client/TestManualAsync.java b/user/test/com/google/gwt/junit/client/TestManualAsync.java
index 514da85..f4d62c5 100644
--- a/user/test/com/google/gwt/junit/client/TestManualAsync.java
+++ b/user/test/com/google/gwt/junit/client/TestManualAsync.java
@@ -15,30 +15,29 @@
*/
package com.google.gwt.junit.client;
+import static com.google.gwt.junit.client.GWTTestCaseTest.SetUpTearDownState.IS_SETUP;
+import static com.google.gwt.junit.client.GWTTestCaseTest.SetUpTearDownState.IS_TORNDOWN;
+
import com.google.gwt.user.client.Timer;
/**
- * This test must be run manually to inspect for correct results. Five of these
- * tests are designed to fail in specific ways, the other five should succeed.
- * The name of each test method indicates how it should behave.
+ * This test must be run manually to inspect for correct results. Many of these
+ * tests are designed to fail in specific ways, the rest should succeed. The
+ * name of each test method indicates how it should behave.
*/
-public class TestManualAsync extends GWTTestCase {
-
- public String getModuleName() {
- return "com.google.gwt.junit.JUnit";
- }
+public class TestManualAsync extends GWTTestCaseTest {
/**
- * Fails normally
+ * Fails normally.
*/
public void testDelayFail() {
delayTestFinish(100);
- fail();
+ fail("Expected failure");
finishTest();
}
/**
- * Completes normally
+ * Completes normally.
*/
public void testDelayNormal() {
delayTestFinish(100);
@@ -46,32 +45,32 @@
}
/**
- * Fails normally
+ * Fails normally.
*/
public void testFail() {
- fail();
+ fail("Expected failure");
}
/**
- * Async fails
+ * Async fails.
*/
public void testFailAsync() {
delayTestFinish(200);
new Timer() {
public void run() {
- fail();
+ fail("Expected failure");
}
}.schedule(100);
}
/**
- * Completes normally
+ * Completes normally.
*/
public void testNormal() {
}
/**
- * Completes async
+ * Completes async.
*/
public void testNormalAsync() {
delayTestFinish(200);
@@ -83,11 +82,13 @@
}
/**
- * Completes async
+ * Completes async.
*/
public void testRepeatingNormal() {
delayTestFinish(200);
new Timer() {
+ private int i = 0;
+
public void run() {
if (++i < 4) {
delayTestFinish(200);
@@ -96,24 +97,81 @@
finishTest();
}
}
-
- private int i = 0;
}.scheduleRepeating(100);
}
/**
- * Completes normally
+ * Fails async.
+ */
+ public void testSetUpTearDownFailAsync() {
+ assertEquals(IS_SETUP, setupTeardownFlag);
+ delayTestFinish(1000);
+ new Timer() {
+ @Override
+ public void run() {
+ fail("Expected failure");
+ }
+ }.schedule(1);
+
+ new Timer() {
+ @Override
+ public void run() {
+ /*
+ * The failing test should have triggered tearDown.
+ */
+ if (setupTeardownFlag != IS_TORNDOWN) {
+ recordOutofBandError("Bad async failure tearDown behavior not catchable by JUnit");
+ }
+ }
+ }.schedule(100);
+ }
+
+ /**
+ * Completes async.
+ */
+ public void testSetUpTearDownFailAsyncHadNoOutOfBandErrors() {
+ assertNoOutOfBandErrorsAsync();
+ }
+
+ /**
+ * Times out async.
+ */
+ public void testSetUpTearDownTimeoutAsync() {
+ assertSame(IS_SETUP, setupTeardownFlag);
+ delayTestFinish(1);
+ new Timer() {
+ @Override
+ public void run() {
+ /*
+ * The failing test should have triggered tearDown.
+ */
+ if (setupTeardownFlag != IS_TORNDOWN) {
+ recordOutofBandError("Bad async timeout tearDown behavior not catchable by JUnit");
+ }
+ }
+ }.schedule(100);
+ }
+
+ /**
+ * Completes async.
+ */
+ public void testSetUpTearDownTimeoutAsyncHadNoOutOfBandErrors() {
+ assertNoOutOfBandErrorsAsync();
+ }
+
+ /**
+ * Completes normally.
*/
public void testSpuriousFinishTest() {
try {
finishTest();
- fail();
- } catch (IllegalArgumentException e) {
+ fail("Unexpected failure");
+ } catch (IllegalStateException e) {
}
}
/**
- * Times out
+ * Times out.
*/
public void testTimeoutAsync() {
delayTestFinish(100);
diff --git a/user/test/com/google/gwt/user/UISuite.java b/user/test/com/google/gwt/user/UISuite.java
index fe04a70..90e2c08 100644
--- a/user/test/com/google/gwt/user/UISuite.java
+++ b/user/test/com/google/gwt/user/UISuite.java
@@ -44,6 +44,7 @@
import com.google.gwt.user.client.ui.GridTest;
import com.google.gwt.user.client.ui.HTMLPanelTest;
import com.google.gwt.user.client.ui.HiddenTest;
+import com.google.gwt.user.client.ui.HistoryTest;
import com.google.gwt.user.client.ui.HorizontalPanelTest;
import com.google.gwt.user.client.ui.HyperlinkTest;
import com.google.gwt.user.client.ui.ImageTest;
@@ -113,7 +114,7 @@
// suite.addTestSuite(FormPanelTest.class);
suite.addTestSuite(GridTest.class);
suite.addTestSuite(HiddenTest.class);
- // suite.addTestSuite(HistoryTest.class);
+ suite.addTestSuite(HistoryTest.class);
suite.addTestSuite(HorizontalPanelTest.class);
suite.addTestSuite(HTMLPanelTest.class);
suite.addTestSuite(HyperlinkTest.class);
diff --git a/user/test/com/google/gwt/user/client/WindowTest.java b/user/test/com/google/gwt/user/client/WindowTest.java
index 7a72cef..e8fa3da 100644
--- a/user/test/com/google/gwt/user/client/WindowTest.java
+++ b/user/test/com/google/gwt/user/client/WindowTest.java
@@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* Test Case for {@link Cookies}.
@@ -75,6 +76,41 @@
assertEquals(host, hostName + ":" + port);
assertEquals(href, protocol + "//" + host + path + query + hash);
}
+
+ public void testLocationParsing() {
+ Map<String, List<String>> map;
+
+ // typical case
+ map = Window.Location.buildListParamMap("?fuzzy=bunnies&foo=bar&num=42");
+ assertEquals(map.size(), 3);
+ assertEquals(map.get("foo").get(0), "bar");
+ assertEquals(map.get("fuzzy").get(0), "bunnies");
+
+ // multiple values for the same parameter
+ map = Window.Location.buildListParamMap(
+ "?fuzzy=bunnies&foo=bar&num=42&foo=baz");
+ assertEquals(map.size(), 3);
+ assertEquals(map.get("foo").get(0), "bar");
+ assertEquals(map.get("foo").get(1), "baz");
+
+ // no query parameters.
+ map = Window.Location.buildListParamMap("");
+ assertEquals(map.size(), 0);
+
+ // blank keys should be ignored, but blank values are OK. Also,
+ // keys can contain whitespace. (but the browser may give whitespace
+ // back as escaped).
+ map = Window.Location.buildListParamMap(
+ "?&& &a&b=&c=c&d=d=d&=e&f=2&f=1&");
+ assertEquals(map.size(), 6);
+ assertEquals(map.get(" ").get(0), "");
+ assertEquals(map.get("a").get(0), "");
+ assertEquals(map.get("b").get(0), "");
+ assertEquals(map.get("c").get(0), "c");
+ assertEquals(map.get("d").get(0), "d=d");
+ assertEquals(map.get("f").get(0), "2");
+ assertEquals(map.get("f").get(1), "1");
+ }
/**
* Tests the ability of the Window to get the client size correctly with and
diff --git a/user/test/com/google/gwt/user/client/ui/HistoryTest.java b/user/test/com/google/gwt/user/client/ui/HistoryTest.java
index b06914a..aff7103 100644
--- a/user/test/com/google/gwt/user/client/ui/HistoryTest.java
+++ b/user/test/com/google/gwt/user/client/ui/HistoryTest.java
@@ -18,6 +18,9 @@
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
+import com.google.gwt.user.client.Timer;
+
+import java.util.ArrayList;
/**
* Tests for the history system.
@@ -26,53 +29,48 @@
*/
public class HistoryTest extends GWTTestCase {
- @Override
- public String getModuleName() {
- return "com.google.gwt.user.User";
- }
-
private static native String getCurrentLocationHash() /*-{
var href = $wnd.location.href;
-
+
splitted = href.split("#");
if (splitted.length != 2) {
return null;
}
-
+
hashPortion = splitted[1];
-
+
return hashPortion;
}-*/;
-
- public void testTokenEscaping() {
- final String shouldBeEncoded = "% ^[]|\"<>{}\\`";
- final String shouldBeEncodedAs = "%25%20%5E%5B%5D%7C%22%3C%3E%7B%7D%5C%60";
-
- delayTestFinish(5000);
- History.addHistoryListener(new HistoryListener() {
- public void onHistoryChanged(String token) {
- assertEquals(shouldBeEncodedAs, getCurrentLocationHash());
- assertEquals(shouldBeEncoded, token);
- finishTest();
- History.removeHistoryListener(this);
+
+ /*
+ * Copied from HistoryImplSafari.
+ */
+ private static native boolean isSafari2() /*-{
+ var exp = / AppleWebKit\/([\d]+)/;
+ var result = exp.exec(navigator.userAgent);
+ if (result) {
+ // The standard history implementation works fine on WebKit >= 522
+ // (Safari 3 beta).
+ if (parseInt(result[1]) >= 522) {
+ return false;
}
- });
- History.newItem(shouldBeEncoded);
- }
+ }
- public void testTokenNonescaping() {
- final String shouldNotChange = "abc;,/?:@&=+$-_.!~*'()ABC123foo";
-
- delayTestFinish(5000);
- History.addHistoryListener(new HistoryListener() {
- public void onHistoryChanged(String token) {
- assertEquals(shouldNotChange, getCurrentLocationHash());
- assertEquals(shouldNotChange, token);
- finishTest();
- History.removeHistoryListener(this);
- }
- });
- History.newItem(shouldNotChange);
+ // The standard history implementation works just fine on the iPhone, which
+ // unfortunately reports itself as WebKit/420+.
+ if (navigator.userAgent.indexOf('iPhone') != -1) {
+ return false;
+ }
+
+ return true;
+ }-*/;
+
+ private HistoryListener historyListener;
+ private Timer timer;
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
}
/* Tests against issue #572: Double unescaping of history tokens. */
@@ -80,23 +78,77 @@
final String escToken = "%24%24%24";
delayTestFinish(5000);
- History.addHistoryListener(new HistoryListener() {
+ addHistoryListenerImpl(new HistoryListener() {
public void onHistoryChanged(String token) {
assertEquals(escToken, token);
finishTest();
- History.removeHistoryListener(this);
}
});
History.newItem(escToken);
}
/*
+ * Tests against issue #879: Ensure that empty history tokens do not add
+ * additional characters after the '#' symbol in the URL.
+ */
+ public void testEmptyHistoryTokens() {
+ delayTestFinish(5000);
+
+ addHistoryListenerImpl(new HistoryListener() {
+ public void onHistoryChanged(String historyToken) {
+
+ if (historyToken == null) {
+ fail("historyToken should not be null");
+ }
+
+ if (historyToken.equals("foobar")) {
+ History.newItem("");
+ } else {
+ assertEquals(0, historyToken.length());
+ finishTest();
+ }
+ }
+ });
+
+ // We must first start out with a non-blank history token. Adding a blank
+ // history token in the initial state will not cause an onHistoryChanged
+ // event to fire.
+ History.newItem("foobar");
+ }
+
+ /**
+ * Verify that no events are issued via newItem if there were not reqeuested.
+ */
+ public void testNoEvents() {
+ addHistoryListenerImpl(new HistoryListener() {
+ {
+ timer = new Timer() {
+ public void run() {
+ finishTest();
+ }
+ };
+ timer.schedule(500);
+ }
+
+ public void onHistoryChanged(String historyToken) {
+ fail("onHistoryChanged should not have been called");
+ }
+ });
+ delayTestFinish(5000);
+ History.newItem("testNoEvents", false);
+ }
+
+ /*
* Ensure that non-url-safe strings (such as those containing spaces) are
* encoded/decoded correctly, and that programmatic 'back' works.
*/
public void testHistory() {
+ if (isSafari2()) {
+ // History.back() is broken on Safari2, so we skip this test.
+ return;
+ }
delayTestFinish(5000);
- History.addHistoryListener(new HistoryListener() {
+ addHistoryListenerImpl(new HistoryListener() {
private int state = 0;
public void onHistoryChanged(String historyToken) {
@@ -123,10 +175,9 @@
case 2: {
if (!historyToken.equals("foo bar")) {
- fail("Expecting token 'foo bar', but got: " + historyToken);
+ fail("Expecting token 'foo bar' after back, but got: " + historyToken);
}
finishTest();
- History.removeHistoryListener(this);
break;
}
}
@@ -136,58 +187,110 @@
History.newItem("foo bar");
}
- /*
- * Tests against issue #879: Ensure that empty history tokens do not add
- * additional characters after the '#' symbol in the URL.
+ /**
+ * Verify that {@link HistoryListener#onHistoryChanged(String)} is only
+ * called once per {@link History#newItem(String)}.
*/
- public void testEmptyHistoryTokens() {
- delayTestFinish(5000);
+ public void testHistoryChangedCount() {
+ timer = new Timer() {
+ private int count = 0;
- History.addHistoryListener(new HistoryListener() {
- public void onHistoryChanged(String historyToken) {
-
- if (historyToken == null) {
- fail("historyToken should not be null");
- }
-
- if (historyToken.equals("foobar")) {
- History.newItem("");
+ public void run() {
+ if (count++ == 0) {
+ // verify that duplicates don't issue another event
+ History.newItem("testHistoryChangedCount");
+ timer.schedule(500);
} else {
- assertEquals(0, historyToken.length());
finishTest();
- History.removeHistoryListener(this);
}
}
- });
+ };
+ addHistoryListenerImpl(new HistoryListener() {
+ final ArrayList<Object> counter = new ArrayList<Object>();
- // We must first start out with a non-blank history token. Adding a blank
- // history token in the initial state will not cause an onHistoryChanged
- // event to fire.
- History.newItem("foobar");
+ public void onHistoryChanged(String historyToken) {
+ counter.add(null);
+ if (counter.size() != 1) {
+ fail("onHistoryChanged called multiple times");
+ }
+ // wait 500ms to see if we get called multiple times
+ timer.schedule(500);
+ }
+ });
+ delayTestFinish(5000);
+ History.newItem("testHistoryChangedCount");
+ }
+
+ public void testTokenEscaping() {
+ final String shouldBeEncoded = "% ^[]|\"<>{}\\";
+ final String shouldBeEncodedAs = "%25%20%5E%5B%5D%7C%22%3C%3E%7B%7D%5C";
+
+ delayTestFinish(5000);
+ addHistoryListenerImpl(new HistoryListener() {
+ public void onHistoryChanged(String token) {
+ if (!isSafari2()) {
+ // Safari2 does not update the URL, so we don't verify it
+ assertEquals(shouldBeEncodedAs, getCurrentLocationHash());
+ }
+ assertEquals(shouldBeEncoded, token);
+ finishTest();
+ }
+ });
+ History.newItem(shouldBeEncoded);
+ }
+
+ public void testTokenNonescaping() {
+ final String shouldNotChange = "abc;,/?:@&=+$-_.!~*()ABC123foo";
+
+ delayTestFinish(5000);
+ addHistoryListenerImpl(new HistoryListener() {
+ public void onHistoryChanged(String token) {
+ if (!isSafari2()) {
+ // Safari2 does not update the URL, so we don't verify it
+ assertEquals(shouldNotChange, getCurrentLocationHash());
+ }
+ assertEquals(shouldNotChange, token);
+ finishTest();
+ }
+ });
+ History.newItem(shouldNotChange);
}
/*
* Test against issue #2500. IE6 has a bug that causes it to not report any
- * part of the current fragment after a '?' when read from location.hash;
- * make sure that on affected browsers, we're not relying on this.
+ * part of the current fragment after a '?' when read from location.hash; make
+ * sure that on affected browsers, we're not relying on this.
*/
public void testTokenWithQuestionmark() {
delayTestFinish(5000);
final String token = "foo?bar";
- History.addHistoryListener(new HistoryListener() {
+ addHistoryListenerImpl(new HistoryListener() {
public void onHistoryChanged(String historyToken) {
-
if (historyToken == null) {
fail("historyToken should not be null");
}
-
assertEquals(token, historyToken);
- History.removeHistoryListener(this);
finishTest();
}
});
-
History.newItem(token);
}
+
+ @Override
+ protected void gwtTearDown() throws Exception {
+ if (historyListener != null) {
+ History.removeHistoryListener(historyListener);
+ historyListener = null;
+ }
+ if (timer != null) {
+ timer.cancel();
+ timer = null;
+ }
+ }
+
+ private void addHistoryListenerImpl(HistoryListener historyListener) {
+ this.historyListener = historyListener;
+ History.addHistoryListener(historyListener);
+ }
}
diff --git a/user/test/com/google/gwt/user/client/ui/ImageTest.java b/user/test/com/google/gwt/user/client/ui/ImageTest.java
index e9cab05..320b47f 100644
--- a/user/test/com/google/gwt/user/client/ui/ImageTest.java
+++ b/user/test/com/google/gwt/user/client/ui/ImageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -38,6 +38,7 @@
return imgState.@com.google.gwt.user.client.ui.Image.State::getStateName() ();
}-*/;
+ @Override
public String getModuleName() {
return "com.google.gwt.user.UserTest";
}
@@ -95,7 +96,11 @@
}
public void onLoad(Widget sender) {
- if (++onLoadEventCount == 2) {
+ ++onLoadEventCount;
+ if (onLoadEventCount == 1) {
+ // Set the url after the first image loads
+ image.setUrl("counting-forwards.png");
+ } else if (onLoadEventCount == 2) {
assertEquals(0, image.getOriginLeft());
assertEquals(0, image.getOriginTop());
assertEquals(32, image.getWidth());
@@ -107,7 +112,6 @@
});
RootPanel.get().add(image);
- image.setUrl("counting-forwards.png");
delayTestFinish(5000);
}