diff options
9 files changed, 395 insertions, 3 deletions
diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/.classpath b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.classpath new file mode 100644 index 000000000..eca7bdba8 --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/.gitignore b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.gitignore new file mode 100644 index 000000000..5e56e040e --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/.project b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.project new file mode 100644 index 000000000..e0460244c --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.fx.core.databinding.tests</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/.settings/org.eclipse.jdt.core.prefs b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..0c68a61dc --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/META-INF/MANIFEST.MF b/bundles/runtime/org.eclipse.fx.core.databinding.tests/META-INF/MANIFEST.MF new file mode 100644 index 000000000..ddd91a645 --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/META-INF/MANIFEST.MF @@ -0,0 +1,45 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: org.eclipse.fx.core.databinding.tests +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.junit;bundle-version="4.11.0", + org.eclipse.core.databinding;bundle-version="1.4.1", + org.eclipse.core.databinding.property;bundle-version="1.4.200", + org.eclipse.fx.core.databinding;bundle-version="0.9.0" +Import-Package: javafx.animation;version="2.2.0", + javafx.application;version="2.2.0", + javafx.beans;version="2.2.0", + javafx.beans.binding;version="2.2.0", + javafx.beans.property;version="2.2.0", + javafx.beans.property.adapter;version="2.2.0", + javafx.beans.value;version="2.2.0", + javafx.collections;version="2.2.0", + javafx.collections.transformation;version="8.0.0", + javafx.concurrent;version="2.2.0", + javafx.css;version="8.0.0", + javafx.embed.swing;version="2.2.0", + javafx.embed.swt;version="2.2.0", + javafx.event;version="2.2.0", + javafx.fxml;version="2.2.0", + javafx.geometry;version="2.2.0", + javafx.print;version="8.0.0", + javafx.scene;version="2.2.0", + javafx.scene.canvas;version="2.2.0", + javafx.scene.chart;version="2.2.0", + javafx.scene.control;version="2.2.0", + javafx.scene.control.cell;version="2.2.0", + javafx.scene.effect;version="2.2.0", + javafx.scene.image;version="2.2.0", + javafx.scene.input;version="2.2.0", + javafx.scene.layout;version="2.2.0", + javafx.scene.media;version="2.2.0", + javafx.scene.paint;version="2.2.0", + javafx.scene.shape;version="2.2.0", + javafx.scene.text;version="2.2.0", + javafx.scene.transform;version="2.2.0", + javafx.scene.web;version="2.2.0", + javafx.stage;version="2.2.0", + javafx.util;version="2.2.0", + javafx.util.converter;version="2.2.0" diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/build.properties b/bundles/runtime/org.eclipse.fx.core.databinding.tests/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/src/org/eclipse/fx/core/databinding/tests/AdapterFactoryTests.java b/bundles/runtime/org.eclipse.fx.core.databinding.tests/src/org/eclipse/fx/core/databinding/tests/AdapterFactoryTests.java new file mode 100644 index 000000000..e56a094a1 --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/src/org/eclipse/fx/core/databinding/tests/AdapterFactoryTests.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2012 BestSolution.at and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation + *******************************************************************************/ +package org.eclipse.fx.core.databinding.tests; + +import javafx.util.Callback; + +import org.eclipse.core.databinding.observable.list.IObservableList; +import org.eclipse.core.databinding.observable.list.WritableList; +import org.eclipse.fx.core.databinding.AdapterFactory; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * + */ +@RunWith(RealmRunner.class) +public class AdapterFactoryTests { + + @Test + public void convertObservableList() { + WritableList l = new WritableList(); + l.add("1"); + l.add("2"); + l.add("3"); + l.add("1"); + + IObservableList target = AdapterFactory.convertObservableList(l, new Callback<String, Integer>() { + + @Override + public Integer call(String param) { + return Integer.parseInt(param); + } + }); + assertEquals(l.size(), target.size()); + assertEquals(((Integer)target.get(0)).intValue(), 1); + assertEquals(((Integer)target.get(1)).intValue(), 2); + assertEquals(((Integer)target.get(2)).intValue(), 3); + assertEquals(((Integer)target.get(3)).intValue(), 1); + l.add("4"); + assertEquals(l.size(), target.size()); + assertEquals(((Integer)target.get(4)).intValue(), 4); + l.remove("2"); + assertEquals(l.size(), target.size()); + assertEquals(((Integer)target.get(1)).intValue(), 3); + l.add(1,"2"); + assertEquals(((Integer)target.get(1)).intValue(), 2); + } +} diff --git a/bundles/runtime/org.eclipse.fx.core.databinding.tests/src/org/eclipse/fx/core/databinding/tests/RealmRunner.java b/bundles/runtime/org.eclipse.fx.core.databinding.tests/src/org/eclipse/fx/core/databinding/tests/RealmRunner.java new file mode 100644 index 000000000..2f787d0ee --- /dev/null +++ b/bundles/runtime/org.eclipse.fx.core.databinding.tests/src/org/eclipse/fx/core/databinding/tests/RealmRunner.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2013 __COMPANY/CONTRIBUTOR__ and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * tomschindl<__EMAIL__> - initial API and implementation + *******************************************************************************/ +package org.eclipse.fx.core.databinding.tests; + +import org.eclipse.core.databinding.observable.Realm; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.InitializationError; + +/** + * + */ +public class RealmRunner extends BlockJUnit4ClassRunner { + static class DummyRealm extends Realm { + + @Override + public boolean isCurrent() { + return true; + } + + } + + /** + * @param klass + * @throws InitializationError + */ + public RealmRunner(Class<?> klass) throws InitializationError { + super(klass); + } + + @Override + public void run(RunNotifier notifier) { + Realm.runWithDefault(new DummyRealm(), new Runnable() { + + @Override + public void run() { + RealmRunner.super.run(notifier); + } + }); + } +} diff --git a/bundles/runtime/org.eclipse.fx.core.databinding/src/org/eclipse/fx/core/databinding/AdapterFactory.java b/bundles/runtime/org.eclipse.fx.core.databinding/src/org/eclipse/fx/core/databinding/AdapterFactory.java index ec02eec4b..a3a358e48 100755 --- a/bundles/runtime/org.eclipse.fx.core.databinding/src/org/eclipse/fx/core/databinding/AdapterFactory.java +++ b/bundles/runtime/org.eclipse.fx.core.databinding/src/org/eclipse/fx/core/databinding/AdapterFactory.java @@ -17,6 +17,7 @@ import java.util.Collections; import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
+import java.util.Map;
import java.util.Spliterator;
import java.util.function.Consumer;
@@ -28,15 +29,19 @@ import javafx.beans.value.WritableValue; import javafx.collections.ListChangeListener;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
+import javafx.util.Callback;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.DisposeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IDisposeListener;
+import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IListChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
+import org.eclipse.core.databinding.observable.list.ListDiffVisitor;
+import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
@@ -537,9 +542,13 @@ public class AdapterFactory { /**
* Bind an javafx observable value to a eclipse db observable
- * @param fxObs the javafx observable
- * @param dbObs the eclipse db observable
- * @param initialSync the initial sync direction
+ *
+ * @param fxObs
+ * the javafx observable
+ * @param dbObs
+ * the eclipse db observable
+ * @param initialSync
+ * the initial sync direction
*/
@SuppressWarnings("unchecked")
public static <E, F extends ObservableValue<E> & WritableValue<E>> void bind(F fxObs, IObservableValue dbObs, InitialSync initialSync) {
@@ -552,6 +561,190 @@ public class AdapterFactory { do_bind(fxObs, wrapped);
}
+ /**
+ * Creates an <b>readonly</b> observable list which is backed by the source list but the values are converted using the
+ * converter
+ *
+ * @param source
+ * the source list
+ * @param converter
+ * the converter
+ * @return observable list with converter value
+ */
+ @SuppressWarnings("unchecked")
+ public static <S, T> IObservableList convertObservableList(IObservableList source, Callback<S, T> converter) {
+ ReadonlyWritableList target = new ReadonlyWritableList(source.getRealm());
+
+ try {
+ target.modifiable = true;
+ for (Object o : source) {
+ target.add(converter.call((S)o));
+ }
+ } finally {
+ target.modifiable = false;
+ }
+
+ source.addListChangeListener(new IListChangeListener() {
+
+ @Override
+ public void handleListChange(ListChangeEvent event) {
+ event.diff.accept(new ListDiffVisitor() {
+
+ @Override
+ public void handleRemove(int index, Object element) {
+ try {
+ target.modifiable = true;
+ target.remove(index);
+ } finally {
+ target.modifiable = false;
+ }
+ }
+
+ @Override
+ public void handleAdd(int index, Object element) {
+ try {
+ target.modifiable = true;
+ target.add(index, converter.call((S) element));
+ } finally {
+ target.modifiable = false;
+ }
+ }
+
+ @Override
+ public void handleReplace(int index, Object oldElement, Object newElement) {
+ try {
+ target.modifiable = true;
+ target.set(index, converter.call((S) newElement));
+ } finally {
+ target.modifiable = false;
+ }
+ }
+
+ @Override
+ public void handleMove(int oldIndex, int newIndex, Object element) {
+ try {
+ target.modifiable = true;
+ target.move(oldIndex, newIndex);
+ } finally {
+ target.modifiable = false;
+ }
+ }
+ });
+ }
+ });
+
+ return target;
+ }
+
+ static class ReadonlyWritableList extends WritableList {
+ boolean modifiable;
+
+ public ReadonlyWritableList(Realm r) {
+ super(r);
+ }
+
+ @Override
+ public Object set(int index, Object element) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.set(index, element);
+ }
+
+ @Override
+ public Object move(int oldIndex, int newIndex) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.move(oldIndex, newIndex);
+ }
+
+ @Override
+ public Object remove(int index) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.remove(index);
+ }
+
+ @Override
+ public boolean add(Object element) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.add(element);
+ }
+
+ @Override
+ public void add(int index, Object element) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ super.add(index, element);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public boolean addAll(Collection c) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.addAll(c);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public boolean addAll(int index, Collection c) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.addAll(index, c);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.remove(o);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public boolean removeAll(Collection c) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.removeAll(c);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public boolean retainAll(Collection c) {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ return super.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ if( ! this.modifiable ) {
+ throw new UnsupportedOperationException("Unmodifiable list"); //$NON-NLS-1$
+ }
+ super.clear();
+ }
+ }
+
+ static <S, T> T convertIt(S object, Callback<S, T> converter, Map<S, T> cache) {
+ T t = cache.get(object);
+ if (t == null) {
+ t =
+ cache.put(object, t);
+ }
+ return t;
+ }
+
private static <E, F extends ObservableValue<E> & WritableValue<E>> void do_bind(final F fxObs, final F dbObs) {
fxObs.addListener(new ChangeListener<E>() {
boolean syncing;
|