diff options
author | Artur Signell <artur@vaadin.com> | 2014-04-23 20:45:14 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2014-04-23 20:45:39 +0300 |
commit | 41cb27e85f61f5abb029a98af66217ce400b2196 (patch) | |
tree | 609df412869abde48131079d45b2981bcb210744 /server | |
parent | 9f30eb285252348c349e9a759ac71098eb74a06a (diff) | |
parent | 0d4080ba5e5931fa928675ba6c95540e34b2f281 (diff) | |
download | vaadin-framework-41cb27e85f61f5abb029a98af66217ce400b2196.tar.gz vaadin-framework-41cb27e85f61f5abb029a98af66217ce400b2196.zip |
Merge changes from origin/7.1
0d4080b ContainerEventProvider returns style names from container. Fixes #10718
6e91bdf Add test for TransactionalPropertyWrapper memory leaks
f0aaf89 Fixed resetting of ComboBox if focused and new items allowed (#13413).
e033fcd Always initialize WebBrowser for new sessions (#13571)
168de1f Revert "Drag image for text-area should contain text of text-area (#13557)"
35e2a34 Fix FieldGroup and TransactionalPropertyWrapper memory leaks (#13438)
7e5d44d Introduce a drag threshold for Drag and Drop (#13381)
f227f0c Drag image for text-area should contain text of text-area (#13557).
Change-Id: Idb01471f8ab0c7118fa884c364e6bc200d13948a
Diffstat (limited to 'server')
8 files changed, 181 insertions, 14 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index 7edcc9719c..6a2d1a125d 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -312,12 +312,18 @@ public class FieldGroup implements Serializable { "The given field is not part of this FieldBinder"); } + TransactionalPropertyWrapper<?> wrapper = null; Property fieldDataSource = field.getPropertyDataSource(); if (fieldDataSource instanceof TransactionalPropertyWrapper) { - fieldDataSource = ((TransactionalPropertyWrapper) fieldDataSource) + wrapper = (TransactionalPropertyWrapper<?>) fieldDataSource; + fieldDataSource = ((TransactionalPropertyWrapper<?>) fieldDataSource) .getWrappedProperty(); + } if (fieldDataSource == getItemProperty(propertyId)) { + if (null != wrapper) { + wrapper.detachFromProperty(); + } field.setPropertyDataSource(null); } fieldToPropertyId.remove(field); diff --git a/server/src/com/vaadin/data/util/TransactionalPropertyWrapper.java b/server/src/com/vaadin/data/util/TransactionalPropertyWrapper.java index 6b0119c503..3c52ab9afc 100644 --- a/server/src/com/vaadin/data/util/TransactionalPropertyWrapper.java +++ b/server/src/com/vaadin/data/util/TransactionalPropertyWrapper.java @@ -48,18 +48,32 @@ public class TransactionalPropertyWrapper<T> extends AbstractProperty<T> private boolean inTransaction = false; private boolean valueChangePending; private T valueBeforeTransaction; + private final ValueChangeListener listener = new ValueChangeListener() { + + @Override + public void valueChange(ValueChangeEvent event) { + fireValueChange(); + } + }; public TransactionalPropertyWrapper(Property<T> wrappedProperty) { this.wrappedProperty = wrappedProperty; if (wrappedProperty instanceof ValueChangeNotifier) { ((ValueChangeNotifier) wrappedProperty) - .addListener(new ValueChangeListener() { + .addValueChangeListener(listener); + } + } - @Override - public void valueChange(ValueChangeEvent event) { - fireValueChange(); - } - }); + /** + * Removes the ValueChangeListener from wrapped Property that was added by + * TransactionalPropertyWrapper. + * + * @since 7.1.15 + */ + public void detachFromProperty() { + if (wrappedProperty instanceof ValueChangeNotifier) { + ((ValueChangeNotifier) wrappedProperty) + .removeValueChangeListener(listener); } } diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java index bfdbea3086..069cd61253 100644 --- a/server/src/com/vaadin/server/BootstrapHandler.java +++ b/server/src/com/vaadin/server/BootstrapHandler.java @@ -156,10 +156,6 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { public boolean synchronizedHandleRequest(VaadinSession session, VaadinRequest request, VaadinResponse response) throws IOException { try { - // Update WebBrowser here only to make WebBrowser information - // available in init for LegacyApplications - session.getBrowser().updateRequestDetails(request); - List<UIProvider> uiProviders = session.getUIProviders(); UIClassSelectionEvent classSelectionEvent = new UIClassSelectionEvent( diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index b96e284e6e..6860166a11 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -750,6 +750,9 @@ public abstract class VaadinService implements Serializable { session.storeInSession(this, request.getWrappedSession()); + // Initial WebBrowser data comes from the request + session.getBrowser().updateRequestDetails(request); + // Initial locale comes from the request Locale locale = request.getLocale(); session.setLocale(locale); diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index 76460e153a..898368d53c 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -68,7 +68,7 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { try { assert UI.getCurrent() == null; - // Set browser information from the request + // Update browser information from the request session.getBrowser().updateRequestDetails(request); UI uI = getBrowserDetailsUI(request, session); diff --git a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java index 37ea255d27..b025de6f9a 100644 --- a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java +++ b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java @@ -224,8 +224,8 @@ public class ContainerEventProvider implements CalendarEditableEventProvider, } if (styleNameProperty != null && item.getItemPropertyIds().contains(styleNameProperty)) { - basicEvent.setDescription(String.valueOf(item.getItemProperty( - descriptionProperty).getValue())); + basicEvent.setStyleName(String.valueOf(item.getItemProperty( + styleNameProperty).getValue())); } event = basicEvent; } diff --git a/server/tests/src/com/vaadin/data/util/TransactionalPropertyWrapperTest.java b/server/tests/src/com/vaadin/data/util/TransactionalPropertyWrapperTest.java new file mode 100644 index 0000000000..8e83db5aef --- /dev/null +++ b/server/tests/src/com/vaadin/data/util/TransactionalPropertyWrapperTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2013 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.data.util; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.ui.TextField; + +/** + * Test verifying that TransactionalPropertyWrapper removes it's listener from + * wrapped Property + * + * @since 7.1.15 + * @author Vaadin Ltd + */ +public class TransactionalPropertyWrapperTest { + + @SuppressWarnings("serial") + public class TestingProperty<T extends Object> extends + ObjectProperty<Object> { + + private List<ValueChangeListener> listeners = new ArrayList<ValueChangeListener>(); + + public TestingProperty(Object value) { + super(value); + } + + @Override + public void addValueChangeListener(ValueChangeListener listener) { + super.addValueChangeListener(listener); + listeners.add(listener); + } + + @Override + public void removeValueChangeListener(ValueChangeListener listener) { + super.removeValueChangeListener(listener); + if (listeners.contains(listener)) { + listeners.remove(listener); + } + } + + public boolean hasListeners() { + return !listeners.isEmpty(); + } + } + + private final TextField nameField = new TextField("Name"); + private final TextField ageField = new TextField("Age"); + private final TextField unboundField = new TextField("No FieldGroup"); + private final TestingProperty<String> unboundProp = new TestingProperty<String>( + "Hello World"); + private final PropertysetItem item = new PropertysetItem(); + + @Test + public void fieldGroupBindAndUnbind() { + item.addItemProperty("name", new TestingProperty<String>( + "Just some text")); + item.addItemProperty("age", new TestingProperty<String>("42")); + + final FieldGroup binder = new FieldGroup(item); + binder.setBuffered(false); + + for (int i = 0; i < 2; ++i) { + binder.bind(nameField, "name"); + binder.bind(ageField, "age"); + unboundField.setPropertyDataSource(unboundProp); + + assertTrue("No listeners in Properties", fieldsHaveListeners(true)); + + binder.unbind(nameField); + binder.unbind(ageField); + unboundField.setPropertyDataSource(null); + + assertTrue("Listeners in Properties after unbinding", + fieldsHaveListeners(false)); + } + } + + /** + * Check that all listeners have same hasListeners() response + * + * @param expected + * expected response + * @return true if all are the same as expected. false if not + */ + private boolean fieldsHaveListeners(boolean expected) { + for (Object id : item.getItemPropertyIds()) { + TestingProperty<?> itemProperty = (TestingProperty<?>) item + .getItemProperty(id); + + if (itemProperty.hasListeners() != expected) { + return false; + } + } + return unboundProp.hasListeners() == expected; + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/calendar/ContainerDataSource.java b/server/tests/src/com/vaadin/tests/server/component/calendar/ContainerDataSource.java index 2bc95e371c..d5b0d5d9c8 100644 --- a/server/tests/src/com/vaadin/tests/server/component/calendar/ContainerDataSource.java +++ b/server/tests/src/com/vaadin/tests/server/component/calendar/ContainerDataSource.java @@ -25,6 +25,7 @@ import org.junit.Test; import com.vaadin.data.Container.Indexed; import com.vaadin.data.Container.Sortable; import com.vaadin.data.Item; +import com.vaadin.data.Property; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.data.util.IndexedContainer; import com.vaadin.ui.Calendar; @@ -327,6 +328,37 @@ public class ContainerDataSource extends TestCase { assertEquals(0, calendar.getEvents(start, end).size()); } + @Test + public void testStyleNamePropertyRetrieved() { + IndexedContainer ic = (IndexedContainer) createTestIndexedContainer(); + ic.addContainerProperty("testStyleName", String.class, ""); + for (int i = 0; i < 10; i++) { + Item item = ic.getItem(ic.getIdByIndex(i)); + @SuppressWarnings("unchecked") + Property<String> itemProperty = item + .getItemProperty("testStyleName"); + itemProperty.setValue("testStyle"); + } + + ContainerEventProvider provider = new ContainerEventProvider(ic); + provider.setCaptionProperty("testCaption"); + provider.setDescriptionProperty("testDescription"); + provider.setStartDateProperty("testStartDate"); + provider.setEndDateProperty("testEndDate"); + provider.setStyleNameProperty("testStyleName"); + + calendar.setEventProvider(provider); + java.util.Calendar cal = java.util.Calendar.getInstance(); + Date now = cal.getTime(); + cal.add(java.util.Calendar.DAY_OF_MONTH, 20); + Date then = cal.getTime(); + List<CalendarEvent> events = calendar.getEventProvider().getEvents(now, + then); + for (CalendarEvent ce : events) { + assertEquals("testStyle", ce.getStyleName()); + } + } + private static Indexed createTestBeanItemContainer() { BeanItemContainer<CalendarEvent> eventContainer = new BeanItemContainer<CalendarEvent>( CalendarEvent.class); |