Revision: 9055
Author: p...@google.com
Date: Wed Oct 13 10:19:59 2010
Log: Cherry picking bug fixes from trunk into release branch: 991801,
989801, 995801, 988801
http://code.google.com/p/google-web-toolkit/source/detail?r=9055
Added:
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBasedWidgetImplSafari.java
Modified:
/releases/2.1/samples/dynatablerf/build.xml
/releases/2.1/user/src/com/google/gwt/activity/shared/ActivityManager.java
/releases/2.1/user/src/com/google/gwt/activity/shared/ActivityMapper.java
/releases/2.1/user/src/com/google/gwt/logging/client/LoggingPopup.java
/releases/2.1/user/src/com/google/gwt/user/cellview/CellView.gwt.xml
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBrowser.css
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBrowser.java
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellList.java
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTable.java
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTree.java
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTreeNodeView.java
/releases/2.1/user/test/com/google/gwt/activity/shared/ActivityManagerTest.java
=======================================
--- /dev/null
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBasedWidgetImplSafari.java
Wed Oct 13 10:19:59 2010
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.user.cellview.client;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+
+/**
+ * Webkit specified Impl used by cell based widgets.
+ */
+public class CellBasedWidgetImplSafari extends CellBasedWidgetImplStandard
{
+
+ @Override
+ public void resetFocus(ScheduledCommand command) {
+ // Webkit will not focus an element that was created in this event
loop.
+ Scheduler.get().scheduleDeferred(command);
+ }
+}
=======================================
--- /releases/2.1/samples/dynatablerf/build.xml Thu Oct 7 11:13:29 2010
+++ /releases/2.1/samples/dynatablerf/build.xml Wed Oct 13 10:19:59 2010
@@ -13,5 +13,6 @@
<include name="apache/log4j/log4j-1.2.16.jar" />
<include name="slf4j/slf4j-api/slf4j-api-1.6.1.jar" />
<include name="slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar" />
+ <include name="javax/xml/bind/jaxb-api-2.1.jar" />
</fileset>
</project>
=======================================
---
/releases/2.1/user/src/com/google/gwt/activity/shared/ActivityManager.java
Wed Oct 6 08:01:28 2010
+++
/releases/2.1/user/src/com/google/gwt/activity/shared/ActivityManager.java
Wed Oct 13 10:19:59 2010
@@ -54,7 +54,7 @@
public void setWidget(IsWidget view) {
if (this.activity == ActivityManager.this.currentActivity) {
startingNext = false;
- display.setWidget(view);
+ showWidget(view);
}
}
}
@@ -94,11 +94,17 @@
/**
* Deactive the current activity, find the next one from our
ActivityMapper,
* and start it.
- *
+ * <p>
+ * The current activity's widget will be hidden immediately, which can
cause
+ * flicker if the next activity provides its widget asynchronously. That
can
+ * be minimized by decent caching. Perenially slow activities might
mitigate
+ * this by providing a widget immediately, with some kind of "loading"
+ * treatment.
+ *
* @see PlaceChangeEvent.Handler#onPlaceChange(PlaceChangeEvent)
*/
public void onPlaceChange(PlaceChangeEvent event) {
- Activity nextActivity = mapper.getActivity(event.getNewPlace());
+ Activity nextActivity = getNextActivity(event);
Throwable caughtOnStop = null;
Throwable caughtOnStart = null;
@@ -118,11 +124,7 @@
currentActivity = NULL_ACTIVITY;
startingNext = false;
} else if (!currentActivity.equals(NULL_ACTIVITY)) {
- /*
- * TODO until caching is in place, relying on stopped activities to
be
- * good citizens to reduce flicker. This makes me very nervous.
- */
- // display.showActivityWidget(null);
+ showWidget(null);
/*
* Kill off the activity's handlers, so it doesn't have to worry
about
@@ -146,7 +148,7 @@
currentActivity = nextActivity;
if (currentActivity.equals(NULL_ACTIVITY)) {
- display.setWidget(null);
+ showWidget(null);
return;
}
@@ -155,7 +157,7 @@
/*
* Now start the thing. Wrap the actual display with a per-call
instance
* that protects the display from canceled or stopped activities, and
which
- * maintain our startingNext state.
+ * maintains our startingNext state.
*/
try {
currentActivity.start(new ProtectedDisplay(currentActivity),
@@ -179,7 +181,7 @@
/**
* Reject the place change if the current activity is not willing to
stop.
- *
+ *
* @see
PlaceChangeRequestEvent.Handler#onPlaceChangeRequest(PlaceChangeRequestEvent)
*/
public void onPlaceChangeRequest(PlaceChangeRequestEvent event) {
@@ -195,7 +197,7 @@
* If you are disposing of an ActivityManager, it is important to call
* setDisplay(null) to get it to deregister from the event bus, so that
it can
* be garbage collected.
- *
+ *
* @param display
*/
public void setDisplay(AcceptsOneWidget display) {
@@ -206,6 +208,24 @@
updateHandlers(willBeActive);
}
}
+
+ private Activity getNextActivity(PlaceChangeEvent event) {
+ if (display == null) {
+ /*
+ * Display may have been nulled during PlaceChangeEvent dispatch.
Don't
+ * bother the mapper, just return a null to ensure we shut down the
+ * current activity
+ */
+ return null;
+ }
+ return mapper.getActivity(event.getNewPlace());
+ }
+
+ private void showWidget(IsWidget view) {
+ if (display != null) {
+ display.setWidget(view);
+ }
+ }
private void updateHandlers(boolean activate) {
if (activate) {
=======================================
---
/releases/2.1/user/src/com/google/gwt/activity/shared/ActivityMapper.java
Wed Oct 6 08:01:28 2010
+++
/releases/2.1/user/src/com/google/gwt/activity/shared/ActivityMapper.java
Wed Oct 13 10:19:59 2010
@@ -27,5 +27,10 @@
* an {...@link ActivityManager}.
*/
public interface ActivityMapper {
+ /**
+ * Returns the activity to run for the given {...@link Place}, or null.
+ *
+ * @param place a Place object
+ */
Activity getActivity(Place place);
}
=======================================
--- /releases/2.1/user/src/com/google/gwt/logging/client/LoggingPopup.java
Tue Jun 22 06:26:45 2010
+++ /releases/2.1/user/src/com/google/gwt/logging/client/LoggingPopup.java
Wed Oct 13 10:19:59 2010
@@ -138,7 +138,7 @@
super(false, false);
VerticalPanel mainPanel = new VerticalPanel();
mainPanel.setBorderWidth(1);
- mainPanel.getElement().setAttribute("style", "background-color:white");
+ mainPanel.getElement().getStyle().setBackgroundColor("white");
final HTML titleBar = new HTML("<center><b>Logging</b></center>");
mainPanel.add(titleBar);
@@ -184,12 +184,12 @@
@Override
public void add(Widget w) {
logArea.add(w);
+
scrollPanel.setScrollPosition(scrollPanel.getElement().getScrollHeight());
}
@Override
public void setWidget(Widget w) {
logArea.clear();
- logArea.add(w);
- }
-
-}
+ add(w);
+ }
+}
=======================================
--- /releases/2.1/user/src/com/google/gwt/user/cellview/CellView.gwt.xml
Thu Sep 23 12:26:00 2010
+++ /releases/2.1/user/src/com/google/gwt/user/cellview/CellView.gwt.xml
Wed Oct 13 10:19:59 2010
@@ -24,7 +24,6 @@
<replace-with
class="com.google.gwt.user.cellview.client.CellBasedWidgetImplStandard">
<when-type-is
class="com.google.gwt.user.cellview.client.CellBasedWidgetImpl"/>
<any>
- <when-property-is name="user.agent" value="safari"/>
<when-property-is name="user.agent" value="opera"/>
<when-property-is name="user.agent" value="gecko"/>
<when-property-is name="user.agent" value="gecko1_8"/>
@@ -40,6 +39,14 @@
</any>
</replace-with>
+ <!-- Safari-specific CellBasedWidgetImpl implementation. -->
+ <replace-with
class="com.google.gwt.user.cellview.client.CellBasedWidgetImplSafari">
+ <when-type-is
class="com.google.gwt.user.cellview.client.CellBasedWidgetImpl"/>
+ <any>
+ <when-property-is name="user.agent" value="safari"/>
+ </any>
+ </replace-with>
+
<!-- IE-specific CellTable implementation. -->
<replace-with
class="com.google.gwt.user.cellview.client.CellTable.ImplTrident">
<when-type-is
class="com.google.gwt.user.cellview.client.CellTable.Impl"/>
=======================================
---
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBrowser.css
Wed Sep 22 12:58:01 2010
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBrowser.css
Wed Oct 13 10:19:59 2010
@@ -40,6 +40,7 @@
@sprite .cellBrowserSelectedItem {
gwt-image: 'cellBrowserSelectedBackground';
background-color: #628cd5;
+ background-repeat: repeat-x;
color: white;
height: auto;
overflow: hidden;
@@ -48,6 +49,7 @@
@sprite .cellBrowserOpenItem {
gwt-image: 'cellBrowserOpenBackground';
background-color: #7b7b7b;
+ background-repeat: repeat-x;
color: white;
height: auto;
overflow: hidden;
=======================================
---
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBrowser.java
Wed Oct 6 14:58:29 2010
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellBrowser.java
Wed Oct 13 10:19:59 2010
@@ -101,14 +101,16 @@
/**
* The background used for open items.
*/
- @ImageOptions(repeatStyle = RepeatStyle.Horizontal, flipRtl = true)
+ // Use RepeatStyle.BOTH to ensure that we do not bundle the image.
+ @ImageOptions(repeatStyle = RepeatStyle.Both, flipRtl = true)
ImageResource cellBrowserOpenBackground();
/**
* The background used for selected items.
*/
+ // Use RepeatStyle.BOTH to ensure that we do not bundle the image.
@Source("cellTreeSelectedBackground.png")
- @ImageOptions(repeatStyle = RepeatStyle.Horizontal, flipRtl = true)
+ @ImageOptions(repeatStyle = RepeatStyle.Both, flipRtl = true)
ImageResource cellBrowserSelectedBackground();
/**
=======================================
---
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellList.java
Wed Oct 13 06:23:15 2010
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellList.java
Wed Oct 13 10:19:59 2010
@@ -378,6 +378,9 @@
// If the event causes us to page, then the index will be out of
bounds.
return;
}
+
+ // Get the cell parent before doing selection in case the list is
redrawn.
+ Element cellParent = getCellParent(target);
T value = getDisplayedItem(indexOnPage);
if (isMouseDown && !cell.handlesSelection()) {
doSelection(event, value, indexOnPage);
@@ -390,7 +393,7 @@
}
// Fire the event to the cell if the list has not been refreshed.
- fireEventToCell(event, getCellParent(target), value);
+ fireEventToCell(event, cellParent, value);
}
}
=======================================
---
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTable.java
Wed Oct 13 06:40:20 2010
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTable.java
Wed Oct 13 10:19:59 2010
@@ -905,7 +905,8 @@
boolean isMouseDown = "mousedown".equals(eventType);
int row = tr.getSectionRowIndex();
if ("mouseover".equals(eventType)) {
- if (hoveringRow != null) {
+ // Unstyle the old row if it is still part of the table.
+ if (hoveringRow != null && tbody.isOrHasChild(hoveringRow)) {
setRowStyleName(hoveringRow, style.cellTableHoveredRow(),
style.cellTableHoveredRowCell(), false);
}
=======================================
---
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTree.java
Wed Oct 6 14:58:29 2010
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTree.java
Wed Oct 13 10:19:59 2010
@@ -18,6 +18,7 @@
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
@@ -494,6 +495,11 @@
*/
private boolean isAnimationEnabled;
+ /**
+ * The deferred command used to keyboard select a node.
+ */
+ private ScheduledCommand keyboardSelectCommand;
+
/**
* The {...@link CellTreeNodeView} whose children are currently being
selected
* using the keyboard.
@@ -667,7 +673,7 @@
collectElementChain(chain, getElement(), target);
boolean isMouseDown = "mousedown".equals(eventType);
- CellTreeNodeView<?> nodeView = findItemByChain(chain, 0, rootNode);
+ final CellTreeNodeView<?> nodeView = findItemByChain(chain, 0,
rootNode);
if (nodeView != null && nodeView != rootNode) {
if (isMouseDown) {
Element showMoreElem = nodeView.getShowMoreElement();
@@ -683,11 +689,21 @@
}
// Forward the event to the cell
- if (nodeView.getCellParent().isOrHasChild(target)) {
+ if (nodeView.getSelectionElement().isOrHasChild(target)) {
// Move the keyboard focus to the clicked item.
if ("focus".equals(eventType) || isMouseDown) {
- isFocused = true;
- keyboardSelect(nodeView, false);
+ // Wait until any pending blur event has fired.
+ final boolean targetsCellParent =
nodeView.getCellParent().isOrHasChild(target);
+ keyboardSelectCommand = new ScheduledCommand() {
+ public void execute() {
+ if (keyboardSelectCommand == this
&& !nodeView.isDestroyed()) {
+ isFocused = true;
+ keyboardSelectCommand = null;
+ keyboardSelect(nodeView, !targetsCellParent);
+ }
+ }
+ };
+ Scheduler.get().scheduleDeferred(keyboardSelectCommand);
}
nodeView.fireEventToCell(event);
@@ -858,7 +874,8 @@
void resetFocus() {
CellBasedWidgetImpl.get().resetFocus(new Scheduler.ScheduledCommand() {
public void execute() {
- if (isFocused && !keyboardSelectedNode.resetFocusOnCell()) {
+ if (isFocused && !keyboardSelectedNode.isDestroyed()
+ && !keyboardSelectedNode.resetFocusOnCell()) {
keyboardSelectedNode.setKeyboardSelected(true, true);
}
}
=======================================
---
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTreeNodeView.java
Wed Oct 6 14:58:29 2010
+++
/releases/2.1/user/src/com/google/gwt/user/cellview/client/CellTreeNodeView.java
Wed Oct 13 10:19:59 2010
@@ -974,6 +974,9 @@
}
// Forward the event to the cell.
+ if (!cellParent.isOrHasChild(Element.as(event.getEventTarget()))) {
+ return;
+ }
Set<String> consumedEvents = parentCell.getConsumedEvents();
if (consumedEvents != null && consumedEvents.contains(eventType)) {
boolean cellWasEditing = parentCell.isEditing(cellParent, value,
key);
@@ -1005,6 +1008,17 @@
protected Element getImageElement() {
return getImageElement(getElement());
}
+
+ /**
+ * Returns the element that selection styles are applied to. The element
+ * includes the open/close image and the rendered value and spans the
width of
+ * the tree.
+ *
+ * @return the selection element
+ */
+ protected Element getSelectionElement() {
+ return getSelectionElement(getElement());
+ }
/**
* Returns the key for the value of this node using the parent's
@@ -1039,7 +1053,7 @@
animationFrame = Document.get().createDivElement();
animationFrame.getStyle().setPosition(Position.RELATIVE);
animationFrame.getStyle().setOverflow(Overflow.HIDDEN);
- animationFrame.setId("animFrame");
+ animationFrame.getStyle().setDisplay(Display.NONE);
getElement().appendChild(animationFrame);
}
return animationFrame;
=======================================
---
/releases/2.1/user/test/com/google/gwt/activity/shared/ActivityManagerTest.java
Wed Oct 6 08:01:28 2010
+++
/releases/2.1/user/test/com/google/gwt/activity/shared/ActivityManagerTest.java
Wed Oct 13 10:19:59 2010
@@ -189,11 +189,7 @@
assertNull(asyncActivity2.display);
eventBus.fireEvent(new PlaceChangeEvent(place2));
- /*
- * TODO until caching is in place, relying on stopped activities to be
good
- * citizens to reduce flicker. This makes me very nervous.
- */
- // assertNull(realDisplay.widget);
+ assertNull(realDisplay.widget);
assertFalse(asyncActivity1.canceled);
assertTrue(asyncActivity1.stopped);
assertFalse(asyncActivity2.stopped);
@@ -354,6 +350,60 @@
assertNotNull(activity2.display);
assertEquals(0, eventBus.getCount(Event.TYPE));
}
+
+ /**
+ * http://code.google.com/p/google-web-toolkit/issues/detail?id=5375
+ */
+ public void testNullDisplayOnPlaceChange() {
+ manager.setDisplay(realDisplay);
+
+ // Start an activity
+ manager.onPlaceChange(new PlaceChangeEvent(place1));
+
+ /*
+ * Now we're going to place2. During PlaceChangeEvent dispatch,
+ * someone kills the manager's display.
+ */
+ manager.setDisplay(null);
+
+ // Now the place change event reaches the manager
+ manager.onPlaceChange(new PlaceChangeEvent(place2));
+
+ assertNull(activity2.display);
+ assertTrue(activity1.stopped);
+ }
+
+ public void testNullDisplayBeforeAsyncStart() {
+ final AsyncActivity asyncActivity1 = new AsyncActivity(new MyView());
+ final AsyncActivity asyncActivity2 = new AsyncActivity(new MyView());
+
+ ActivityMapper map = new ActivityMapper() {
+ public Activity getActivity(Place place) {
+ if (place.equals(place1)) {
+ return asyncActivity1;
+ }
+ if (place.equals(place2)) {
+ return asyncActivity2;
+ }
+
+ return null;
+ }
+ };
+
+ manager = new ActivityManager(map, eventBus);
+ manager.setDisplay(realDisplay);
+
+ // Start an activity
+ manager.onPlaceChange(new PlaceChangeEvent(place1));
+
+ // Kill the manager
+ manager.setDisplay(null);
+
+ // The activity is ready to play
+ asyncActivity1.finish();
+
+ // Ta da, no NPE
+ }
public void testRejected() {
manager.setDisplay(realDisplay);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors