diff options
| author | Jens Lidestrom | 2019-12-30 20:01:16 +0000 |
|---|---|---|
| committer | Jens Lideström | 2022-01-06 18:44:21 +0000 |
| commit | c807f128d0b6a181cbaaa2e94dc641960a5f8e74 (patch) | |
| tree | 13e2ecb2850a5cbd19671612a4d86b24091b88f4 | |
| parent | cbbc3c87a6470d729ec909d8492d55cdcf91be94 (diff) | |
| download | eclipse.platform.ui-c807f128d0b6a181cbaaa2e94dc641960a5f8e74.tar.gz eclipse.platform.ui-c807f128d0b6a181cbaaa2e94dc641960a5f8e74.tar.xz eclipse.platform.ui-c807f128d0b6a181cbaaa2e94dc641960a5f8e74.zip | |
Bug 148327 - Add factory methods for enum convertersY20220107-0600
And use it in snippet.
Change-Id: I99ec7510c035cc07c68067570e0ead5bd7a7449d
Signed-off-by: Jens Lidestrom <jens@lidestrom.se>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/155307
Tested-by: Platform Bot <platform-bot@eclipse.org>
Tested-by: Lars Vogel <Lars.Vogel@vogella.com>
Reviewed-by: Lars Vogel <Lars.Vogel@vogella.com>
4 files changed, 196 insertions, 6 deletions
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/EnumConverters.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/EnumConverters.java new file mode 100644 index 00000000000..e837b4d5113 --- /dev/null +++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/conversion/EnumConverters.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2020 Jens Lidestrom and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Jens Lidestrom - initial API and implementation (Bug 148327) + ******************************************************************************/ + +package org.eclipse.core.databinding.conversion; + +import java.util.Objects; + +/** + * Contains static methods the create converters for working with {@link Enum}s. + * + * @since 1.11 + */ +public class EnumConverters { + /** + * Creates a converter which converts from {@link Enum#ordinal}s to enum values + * of the given type. Invalid ordinal values are converted to {@code null}. + * + * @param enumToType to type; not null + * @return the created converter + */ + public static <T extends Enum<T>> IConverter<Integer, T> fromOrdinal(Class<T> enumToType) { + Objects.requireNonNull(enumToType); + T[] ordinals = enumToType.getEnumConstants(); + return IConverter.create(Integer.class, enumToType, + i -> i == null || i < 0 || i >= ordinals.length ? null : ordinals[i]); + } + + /** + * Creates a converter which converts from the {@link #toString} values of enums + * values to enum values themselves. Invalid string values are converted to + * {@code null}. + * + * @param enumToType to type; not null + * @return the created converter + */ + public static <T extends Enum<T>> IConverter<String, T> fromString(Class<T> enumToType) { + Objects.requireNonNull(enumToType); + return IConverter.create(String.class, enumToType, text -> { + if (text == null) { + return null; + } + + try { + return Enum.valueOf(enumToType, text); + } catch (IllegalArgumentException e) { + return null; + } + }); + } + + /** + * Creates a converter which converts from {@link Enum#ordinal}s to enum values + * of the given type. {@code null} in the converter input is converted to + * {@code null}. + * + * @param enumFromType from type; not null + * @return the created converter + */ + public static <T extends Enum<T>> IConverter<T, Integer> toOrdinal(Class<T> enumFromType) { + Objects.requireNonNull(enumFromType); + return IConverter.create(enumFromType, Integer.class, e -> e == null ? null : e.ordinal()); + } + + /** + * Creates a converter which converts to the {@link #toString} values of the + * enum constants. {@code null} in the converter input is converted to + * {@code null}. + * + * @param enumFromType from type; not null + * @return the created converter + */ + public static <T extends Enum<T>> IConverter<T, String> toString(Class<T> enumFromType) { + Objects.requireNonNull(enumFromType); + return IConverter.create(enumFromType, String.class, e -> e == null ? null : e.toString()); + } +} diff --git a/examples/org.eclipse.jface.examples.databinding/META-INF/MANIFEST.MF b/examples/org.eclipse.jface.examples.databinding/META-INF/MANIFEST.MF index d5a1436b82c..aff2fe36cd6 100644 --- a/examples/org.eclipse.jface.examples.databinding/META-INF/MANIFEST.MF +++ b/examples/org.eclipse.jface.examples.databinding/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jface.examples.databinding -Bundle-Version: 1.2.100.qualifier +Bundle-Version: 1.3.0.qualifier Eclipse-BundleShape: dir Bundle-ClassPath: . Bundle-Vendor: %providerName diff --git a/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet034ComboViewerAndEnum.java b/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet034ComboViewerAndEnum.java index 0248f303a16..816aff8fae1 100644 --- a/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet034ComboViewerAndEnum.java +++ b/examples/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet034ComboViewerAndEnum.java @@ -15,8 +15,14 @@ package org.eclipse.jface.examples.databinding.snippets; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.UpdateValueStrategy; +import org.eclipse.core.databinding.beans.typed.BeanProperties; import org.eclipse.core.databinding.beans.typed.PojoProperties; +import org.eclipse.core.databinding.conversion.EnumConverters; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.jface.databinding.swt.DisplayRealm; import org.eclipse.jface.databinding.swt.typed.WidgetProperties; @@ -26,6 +32,7 @@ import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; @@ -73,8 +80,9 @@ public class Snippet034ComboViewerAndEnum { * need to implement the JavaBeans property change listener methods. */ static class Person { - String name; - Gender gender; + private String name; + private Gender gender; + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); public Person(String name, Gender gender) { this.name = name; @@ -85,8 +93,10 @@ public class Snippet034ComboViewerAndEnum { return name; } - public void setName(String name) { - this.name = name; + public void setName(String newName) { + String old = this.name; + this.name = newName; + propertyChangeSupport.firePropertyChange("name", old, name); } public Gender getGender() { @@ -94,8 +104,19 @@ public class Snippet034ComboViewerAndEnum { } public void setGender(Gender newGender) { + Gender old = this.gender; this.gender = newGender; + propertyChangeSupport.firePropertyChange("gender", old, gender); } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(propertyName, listener); + } + } /** The GUI view. */ @@ -103,6 +124,7 @@ public class Snippet034ComboViewerAndEnum { private Person viewModel; private Text name; private ComboViewer gender; + private Label genderText; public View(Person viewModel) { this.viewModel = viewModel; @@ -120,6 +142,7 @@ public class Snippet034ComboViewerAndEnum { name = new Text(shell, SWT.BORDER); gender = new ComboViewer(shell, SWT.READ_ONLY); + genderText = new Label(shell, SWT.NONE); // Here's the first key to binding a combo to an Enum: // First give it an ArrayContentProvider, @@ -138,10 +161,15 @@ public class Snippet034ComboViewerAndEnum { bindingContext.bindValue(ViewerProperties.singleSelection(Gender.class).observe(gender), PojoProperties.value(Person.class, "gender").observe(viewModel)); + // The EnumConverters class is convenient when binding an enum in a situation + // where a Viewer can not be used + bindingContext.bindValue(WidgetProperties.text().observe(genderText), + BeanProperties.value(Person.class, "gender", Gender.class).observe(viewModel), null, + UpdateValueStrategy.create(EnumConverters.toString(Gender.class))); + shell.pack(); shell.open(); return shell; } } - } diff --git a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/EnumConvertersTest.java b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/EnumConvertersTest.java new file mode 100644 index 00000000000..8d242f7064a --- /dev/null +++ b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/EnumConvertersTest.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2020 Jens Lidestrom and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Jens Lidestrom - initial API and implementation (Bug 558842) + ******************************************************************************/ + +package org.eclipse.core.tests.internal.databinding; + +import static org.junit.Assert.assertEquals; + +import org.eclipse.core.databinding.conversion.EnumConverters; +import org.eclipse.core.databinding.conversion.IConverter; +import org.junit.Test; + +/** + * Test for {@link EnumConverters}. + */ +public class EnumConvertersTest { + + enum TestEnum { + A, B; + + @Override + public String toString() { + // To be able to tell apart from the enum name + return name().toLowerCase(); + } + } + + @Test + public void testFromOrdinal() { + IConverter<Integer, TestEnum> fromOrdinal = EnumConverters.fromOrdinal(TestEnum.class); + assertEquals(TestEnum.A, fromOrdinal.convert(0)); + assertEquals(null, fromOrdinal.convert(null)); + assertEquals(null, fromOrdinal.convert(100)); + assertEquals(Integer.class, fromOrdinal.getFromType()); + assertEquals(TestEnum.class, fromOrdinal.getToType()); + } + + @Test + public void testFromString() { + IConverter<String, TestEnum> fromOrdinal = EnumConverters.fromString(TestEnum.class); + assertEquals(TestEnum.A, fromOrdinal.convert("A")); + assertEquals(null, fromOrdinal.convert("a")); + assertEquals(null, fromOrdinal.convert(null)); + assertEquals(String.class, fromOrdinal.getFromType()); + assertEquals(TestEnum.class, fromOrdinal.getToType()); + } + + @Test + public void testToString() { + IConverter<TestEnum, String> fromOrdinal = EnumConverters.toString(TestEnum.class); + assertEquals("a", fromOrdinal.convert(TestEnum.A)); + assertEquals(null, fromOrdinal.convert(null)); + assertEquals(TestEnum.class, fromOrdinal.getFromType()); + assertEquals(String.class, fromOrdinal.getToType()); + } + + @Test + public void testToOrdinal() { + IConverter<TestEnum, Integer> converter = EnumConverters.toOrdinal(TestEnum.class); + assertEquals(0, (int) converter.convert(TestEnum.A)); + assertEquals(null, converter.convert(null)); + assertEquals(TestEnum.class, converter.getFromType()); + assertEquals(Integer.class, converter.getToType()); + } +} |
