/* * Copyright 2000-2016 Vaadin Ltd. * * 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.vaadin.tests.components.table; import java.util.Iterator; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractReindeerTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.v7.data.Container; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.util.IndexedContainer; import com.vaadin.v7.ui.Table; public class ContainerSizeChangeDuringTablePaint extends AbstractReindeerTestUI { /** * A test {@link Table} that simply acts a hook for when Vaadin starts * painting the Table. */ private static class WobblyTable extends Table { /** * A flag for the container to know when it should change the size. */ boolean isBeingPainted; public WobblyTable(String caption, Container dataSource) { super(caption, dataSource); } @Override public void paintContent(PaintTarget target) throws PaintException { isBeingPainted = true; try { super.paintContent(target); } finally { isBeingPainted = false; } } } /** * A {@link Container} that can change its size while its * {@link WobblyTable} is being painted. */ private static class WobblyContainer extends IndexedContainer { private WobblyTable table = null; private boolean shouldSabotageNextPaint = false; public void setWobblyTable(WobblyTable table) { this.table = table; } @Override public int size() { if (table != null && table.isBeingPainted && shouldSabotageNextPaint) { try { System.out.print("Firing item set change " + "event during Table paint... "); fireItemSetChange(); System.out.println("Success!"); } finally { shouldSabotageNextPaint = false; } } return super.size(); } public void sabotageNextPaint() { shouldSabotageNextPaint = true; } } private static final Object PROPERTY_1 = new Object(); private static final Object PROPERTY_2 = new Object(); private static final Object PROPERTY_3 = new Object(); @Override protected void setup(VaadinRequest request) { final WobblyContainer container = generateContainer(); final WobblyTable table = createTable(container); container.setWobblyTable(table); addComponent(table); Button button = new Button( "Add an item and also trigger an ItemSetChangeEvent in Container during next Table paint", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { // we need this to simply trigger a table paint. addItem(container, "A", "New", "Row"); container.sabotageNextPaint(); event.getButton() .setCaption("Event was fired successfully."); } }); button.setId("addRow"); addComponent(button); } private static WobblyTable createTable(IndexedContainer container) { WobblyTable t = new WobblyTable(null, container); t.setColumnHeader(PROPERTY_1, "Property 1"); t.setColumnHeader(PROPERTY_2, "Property 2"); t.setColumnHeader(PROPERTY_3, "Property 3"); t.setPageLength(container.size() + 1); return t; } private static WobblyContainer generateContainer() { WobblyContainer c = new WobblyContainer(); c.addContainerProperty(PROPERTY_1, String.class, null); c.addContainerProperty(PROPERTY_2, String.class, null); c.addContainerProperty(PROPERTY_3, String.class, null); addItem(c, "Hello", "World", "!"); return c; } @SuppressWarnings("unchecked") private static void addItem(Container c, Object... properties) { Object itemId = c.addItem(); Item item = c.getItem(itemId); int i = 0; Iterator<?> propIter = c.getContainerPropertyIds().iterator(); while (propIter.hasNext()) { Object propertyId = propIter.next(); item.getItemProperty(propertyId).setValue(properties[i]); i++; } } @Override protected String getTestDescription() { return "Container changes during the painting cycle should not lead to an IllegalStateException"; } @Override protected Integer getTicketNumber() { return 12258; } }