summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur.signell@itmill.com>2011-11-04 09:01:09 +0000
committerArtur Signell <artur.signell@itmill.com>2011-11-04 09:01:09 +0000
commita4d0d363bb6b8d9d2d5eeebe12ee39e97483d4e8 (patch)
treed091e4c14600038a7a43234d97dd742eb964201c
parent9d528ff42cc42673124db07173163b900b638e20 (diff)
downloadvaadin-framework-a4d0d363bb6b8d9d2d5eeebe12ee39e97483d4e8.tar.gz
vaadin-framework-a4d0d363bb6b8d9d2d5eeebe12ee39e97483d4e8.zip
#7780 Don't do partial repaints if the item set has changed during an expand or collapse
svn changeset:21901/svn branch:6.7
-rw-r--r--src/com/vaadin/ui/TreeTable.java22
-rw-r--r--tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.html92
-rw-r--r--tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.java242
3 files changed, 242 insertions, 114 deletions
diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java
index aa72793636..9cba7362ac 100644
--- a/src/com/vaadin/ui/TreeTable.java
+++ b/src/com/vaadin/ui/TreeTable.java
@@ -11,6 +11,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.logging.Logger;
import com.google.gwt.user.client.ui.Tree;
import com.vaadin.data.Container;
@@ -50,6 +51,9 @@ import com.vaadin.ui.treetable.HierarchicalContainerOrderedWrapper;
@ClientWidget(VTreeTable.class)
public class TreeTable extends Table implements Hierarchical {
+ private static final Logger logger = Logger.getLogger(TreeTable.class
+ .getName());
+
private interface ContainerStrategy extends Serializable {
public int size();
@@ -220,6 +224,9 @@ public class TreeTable extends Table implements Hierarchical {
boolean removed = openItems.remove(itemId);
if (!removed) {
openItems.add(itemId);
+ logger.finest("Item " + itemId + " is now expanded");
+ } else {
+ logger.finest("Item " + itemId + " is now collapsed");
}
clearPreorderCache();
}
@@ -312,6 +319,16 @@ public class TreeTable extends Table implements Hierarchical {
private ContainerStrategy cStrategy;
private Object focusedRowId = null;
private Object hierarchyColumnId;
+
+ /**
+ * The item id that was expanded or collapsed during this request. Reset at
+ * the end of paint and only used for determining if a partial or full paint
+ * should be done.
+ *
+ * Can safely be reset to null whenever a change occurs that would prevent a
+ * partial update from rendering the correct result, e.g. rows added or
+ * removed during an expand operation.
+ */
private Object toggledItemId;
private boolean animationsEnabled;
private boolean clearFocusedRowPending;
@@ -361,6 +378,7 @@ public class TreeTable extends Table implements Hierarchical {
if (variables.containsKey("toggleCollapsed")) {
String object = (String) variables.get("toggleCollapsed");
Object itemId = itemIdMapper.get(object);
+ toggledItemId = itemId;
toggleChildVisibility(itemId);
if (variables.containsKey("selectCollapsed")) {
// ensure collapsed is selected unless opened with selection
@@ -497,7 +515,6 @@ public class TreeTable extends Table implements Hierarchical {
// ensure that page still has first item in page, DON'T clear the
// caches.
setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false);
- toggledItemId = itemId;
requestRepaint();
if (isCollapsed(itemId)) {
@@ -535,6 +552,9 @@ public class TreeTable extends Table implements Hierarchical {
@Override
public void containerItemSetChange(
com.vaadin.data.Container.ItemSetChangeEvent event) {
+ // Can't do partial repaints if items are added or removed during the
+ // expand/collapse request
+ toggledItemId = null;
getContainerStrategy().containerItemSetChange(event);
super.containerItemSetChange(event);
}
diff --git a/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.html b/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.html
new file mode 100644
index 0000000000..01bbb75361
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.html
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.treetable.DynamicallyModified?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>initial</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>47,5</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>proj1-collapsed</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>48,8</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>proj1-two-children</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[5]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>49,7</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>proj2-collapsed</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[5]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>47,7</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>proj2-three-children</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[5]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>45,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[5]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>45,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>48,6</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableDynamicallyModified::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>48,6</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>proj1-one-child-proj2-four-children</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.java b/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.java
index db4e93b1f6..3d76211154 100644
--- a/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.java
+++ b/tests/testbench/com/vaadin/tests/components/treetable/DynamicallyModified.java
@@ -1,113 +1,129 @@
-package com.vaadin.tests.components.treetable;
-
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-
-import com.vaadin.tests.components.TestBase;
-import com.vaadin.ui.Tree;
-import com.vaadin.ui.Tree.CollapseEvent;
-import com.vaadin.ui.Tree.ExpandEvent;
-import com.vaadin.ui.TreeTable;
-
-public class DynamicallyModified extends TestBase implements
- Tree.ExpandListener, Tree.CollapseListener {
- protected static final String NAME_PROPERTY = "Name";
- protected static final String HOURS_PROPERTY = "Hours done";
- protected static final String MODIFIED_PROPERTY = "Last Modified";
-
- protected TreeTable treetable;
-
- @Override
- protected void setup() {
- getLayout().setWidth("100%");
-
- // Calendar
- Calendar cal = Calendar.getInstance();
- cal.set(2011, 10, 30, 14, 40, 26);
-
- // Create the treetable
- treetable = new TreeTable();
- treetable.setWidth("100%");
- treetable.addListener((Tree.ExpandListener) this);
- treetable.addListener((Tree.CollapseListener) this);
-
- addComponent(treetable);
-
- // Add Table columns
- treetable.addContainerProperty(NAME_PROPERTY, String.class, "");
- treetable.addContainerProperty(HOURS_PROPERTY, Integer.class, 0);
- treetable.addContainerProperty(MODIFIED_PROPERTY, Date.class,
- cal.getTime());
-
- // Populate table
- Object allProjects = treetable.addItem(new Object[] { "All Projects",
- 18, cal.getTime() }, null);
- Object year2010 = treetable.addItem(
- new Object[] { "Year 2010", 18, cal.getTime() }, null);
- Object customerProject1 = treetable.addItem(new Object[] {
- "Customer Project 1", 13, cal.getTime() }, null);
- Object customerProject1Implementation = treetable.addItem(new Object[] {
- "Implementation", 5, cal.getTime() }, null);
- Object customerProject1Planning = treetable.addItem(new Object[] {
- "Planning", 2, cal.getTime() }, null);
- Object customerProject1Prototype = treetable.addItem(new Object[] {
- "Prototype", 5, cal.getTime() }, null);
- Object customerProject2 = treetable.addItem(new Object[] {
- "Customer Project 2", 5, cal.getTime() }, null);
- Object customerProject2Planning = treetable.addItem(new Object[] {
- "Planning", 5, cal.getTime() }, null);
-
- // Set hierarchy
- treetable.setParent(year2010, allProjects);
- treetable.setParent(customerProject1, year2010);
- treetable.setParent(customerProject1Implementation, customerProject1);
- treetable.setParent(customerProject1Planning, customerProject1);
- treetable.setParent(customerProject1Prototype, customerProject1);
- treetable.setParent(customerProject2, year2010);
- treetable.setParent(customerProject2Planning, customerProject2);
-
- // Disallow children from leaves
- treetable.setChildrenAllowed(customerProject1Implementation, false);
- treetable.setChildrenAllowed(customerProject1Planning, false);
- treetable.setChildrenAllowed(customerProject1Prototype, false);
- treetable.setChildrenAllowed(customerProject2Planning, false);
-
- // Expand all
- treetable.setCollapsed(allProjects, false);
- treetable.setCollapsed(year2010, false);
- treetable.setCollapsed(customerProject1, false);
- treetable.setCollapsed(customerProject2, false);
- }
-
- @Override
- protected String getDescription() {
- return "Expanding and collapsing nodes should actually expand and collapse them even when modifying the container in a collapse listener.";
- }
-
- @Override
- protected Integer getTicketNumber() {
- return 7780;
- }
-
- public void nodeExpand(ExpandEvent event) {
-
- }
-
- public void nodeCollapse(CollapseEvent event) {
-
- Collection<Object> childs = (Collection<Object>) treetable
- .getChildren(event.getItemId());
-
- if (childs == null) {
- return;
- }
- Object[] arr = childs.toArray();
-
- for (Object obj : arr) {
- System.out.println("remove " + obj.toString());
- treetable.removeItem(obj);
- }
-
- }
-}
+package com.vaadin.tests.components.treetable;
+
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Tree;
+import com.vaadin.ui.Tree.CollapseEvent;
+import com.vaadin.ui.Tree.ExpandEvent;
+import com.vaadin.ui.TreeTable;
+
+public class DynamicallyModified extends TestBase implements
+ Tree.ExpandListener, Tree.CollapseListener {
+ protected static final String NAME_PROPERTY = "Name";
+ protected static final String HOURS_PROPERTY = "Hours done";
+ protected static final String MODIFIED_PROPERTY = "Last Modified";
+
+ protected TreeTable treetable;
+
+ @Override
+ protected void setup() {
+ getLayout().setWidth("100%");
+
+ // Calendar
+ Calendar cal = Calendar.getInstance();
+ cal.set(2011, 10, 30, 14, 40, 26);
+
+ // Create the treetable
+ treetable = new TreeTable();
+ treetable.setWidth("100%");
+ treetable.addListener((Tree.ExpandListener) this);
+ treetable.addListener((Tree.CollapseListener) this);
+
+ addComponent(treetable);
+
+ // Add Table columns
+ treetable.addContainerProperty(NAME_PROPERTY, String.class, "");
+ treetable.addContainerProperty(HOURS_PROPERTY, Integer.class, 0);
+ treetable.addContainerProperty(MODIFIED_PROPERTY, Date.class,
+ cal.getTime());
+
+ // Populate table
+ Object allProjects = treetable.addItem(new Object[] { "All Projects",
+ 18, cal.getTime() }, null);
+ Object year2010 = treetable.addItem(
+ new Object[] { "Year 2010", 18, cal.getTime() }, null);
+ Object customerProject1 = treetable.addItem(new Object[] {
+ "Customer Project 1", 13, cal.getTime() }, null);
+ Object customerProject1Implementation = treetable.addItem(new Object[] {
+ "Implementation", 5, cal.getTime() }, null);
+ Object customerProject1Planning = treetable.addItem(new Object[] {
+ "Planning", 2, cal.getTime() }, null);
+ Object customerProject1Prototype = treetable.addItem(new Object[] {
+ "Prototype", 5, cal.getTime() }, null);
+ Object customerProject2 = treetable.addItem(new Object[] {
+ "Customer Project 2", 5, cal.getTime() }, null);
+ Object customerProject2Planning = treetable.addItem(new Object[] {
+ "Planning", 5, cal.getTime() }, null);
+
+ // Set hierarchy
+ treetable.setParent(year2010, allProjects);
+ treetable.setParent(customerProject1, year2010);
+ treetable.setParent(customerProject1Implementation, customerProject1);
+ treetable.setParent(customerProject1Planning, customerProject1);
+ treetable.setParent(customerProject1Prototype, customerProject1);
+ treetable.setParent(customerProject2, year2010);
+ treetable.setParent(customerProject2Planning, customerProject2);
+
+ // Disallow children from leaves
+ treetable.setChildrenAllowed(customerProject1Implementation, false);
+ treetable.setChildrenAllowed(customerProject1Planning, false);
+ treetable.setChildrenAllowed(customerProject1Prototype, false);
+ treetable.setChildrenAllowed(customerProject2Planning, false);
+
+ // Expand all
+ treetable.setCollapsed(allProjects, false);
+ treetable.setCollapsed(year2010, false);
+ treetable.setCollapsed(customerProject1, false);
+ treetable.setCollapsed(customerProject2, false);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Collaps 'Customer Project 1' will cause the first child if it to be removed. Expanding 'Custom Project 2' will cause a new child to be added. These events should be rendered correctly.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 7780;
+ }
+
+ private int newChild = 1;
+
+ public void nodeExpand(ExpandEvent event) {
+ Object expandedItemId = event.getItemId();
+ // 7 == "Customer Project 1"
+ if (expandedItemId != Integer.valueOf(7)) {
+ return;
+ }
+ Object newChildId = treetable.addItem(new Object[] {
+ "New child " + newChild++, 5, new Date() }, null);
+ treetable.setParent(newChildId, expandedItemId);
+ treetable.setChildrenAllowed(newChildId, false);
+ }
+
+ public void nodeCollapse(CollapseEvent event) {
+
+ Object collapsedItemId = event.getItemId();
+
+ // 3 == "Customer Project 1"
+ if (collapsedItemId != Integer.valueOf(3)) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ Collection<Object> childs = (Collection<Object>) treetable
+ .getChildren(event.getItemId());
+
+ if (childs == null) {
+ return;
+ }
+ Object[] arr = childs.toArray();
+
+ if (arr.length > 0) {
+ treetable.removeItem(arr[0]);
+ }
+
+ }
+} \ No newline at end of file