diff --git a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java index 88299585040..becdaa6be4e 100644 --- a/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java +++ b/org.eclipse.scout.rt.client/src/main/java/org/eclipse/scout/rt/client/ui/form/fields/AbstractCompositeField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -144,14 +145,18 @@ protected void initConfig() { @Override public void addField(IFormField f) { - CompositeFieldUtility.addField(f, this, getFieldsInternal()); + List writableFields = new LinkedList<>(getFieldsInternal()); + CompositeFieldUtility.addField(f, this, writableFields); + propertySupport.setPropertyNoFire(PROP_FIELDS, writableFields); addChildFieldPropertyChangeListener(f); handleFieldsChanged(); } @Override public void removeField(IFormField f) { - CompositeFieldUtility.removeField(f, this, getFieldsInternal()); + List writableFields = new LinkedList<>(getFieldsInternal()); + CompositeFieldUtility.removeField(f, this, writableFields); + propertySupport.setPropertyNoFire(PROP_FIELDS, writableFields); removeChildFieldPropertyChangeListener(f); handleFieldsChanged(); } diff --git a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/reflect/BasicPropertySupport.java b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/reflect/BasicPropertySupport.java index 24441395115..5b4574dab6d 100644 --- a/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/reflect/BasicPropertySupport.java +++ b/org.eclipse.scout.rt.platform/src/main/java/org/eclipse/scout/rt/platform/reflect/BasicPropertySupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023 BSI Business Systems Integration AG + * Copyright (c) 2010, 2026 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -16,9 +16,11 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -238,16 +240,17 @@ public boolean setPropertyListAlwaysFire(String name, List newValue) { private boolean setPropertyList(String name, List newValue, boolean alwaysFire) { Object oldValue = m_props.get(name); + newValue = optimizeList(newValue); boolean propChanged = setPropertyNoFire(name, newValue); if (propChanged || alwaysFire) { Object eventOldValue = null; if (oldValue instanceof List) { - eventOldValue = CollectionUtility.arrayList((Collection) oldValue); + eventOldValue = List.copyOf((Collection) oldValue); } // fire a copy List eventNewValue = null; if (newValue != null) { - eventNewValue = CollectionUtility.arrayList(newValue); + eventNewValue = List.copyOf(newValue); } firePropertyChangeImpl(name, eventOldValue, eventNewValue); return propChanged; @@ -255,6 +258,22 @@ private boolean setPropertyList(String name, List newValue, boolean alway return false; } + public List optimizeList(List newValue) { + if (newValue == null) { + return null; + } + if (newValue.isEmpty()) { + return Collections.emptyList(); + } + if (newValue.size() == 1) { + return Collections.singletonList(newValue.getFirst()); + } + if (newValue.size() == 2) { + return List.of(newValue.get(0), newValue.get(1)); + } + return List.copyOf(newValue); + } + @SuppressWarnings("unchecked") public List getPropertyList(String name) { return (List) m_props.get(name); @@ -270,6 +289,7 @@ public boolean setPropertySetAlwaysFire(String name, Set newValue) { private boolean setPropertySet(String name, Set newValue, boolean alwaysFire) { Object oldValue = m_props.get(name); + newValue = optimizeSet(newValue); boolean propChanged = setPropertyNoFire(name, newValue); if (propChanged || alwaysFire) { Object eventOldValue = null; @@ -287,6 +307,23 @@ private boolean setPropertySet(String name, Set newValue, boolean alwaysF return false; } + public Set optimizeSet(Set newValue) { + if (newValue == null) { + return null; + } + if (newValue.isEmpty()) { + return Collections.emptySet(); + } + if (newValue.size() == 1) { + return Collections.singleton(newValue.iterator().next()); + } + if (newValue.size() == 2) { + Iterator it = newValue.iterator(); + return Set.of(it.next(), it.next()); + } + return Set.copyOf(newValue); + } + @SuppressWarnings("unchecked") public Set getPropertySet(String name) { return (Set) m_props.get(name);