JavaFX reflective access + Javadoc + @delvh
All checks were successful
zdm/undo-redo/pipeline/head This commit looks good

* Allow reflective access to the JavaFX module for javafx.base
* Add space to the unit test orders
* Improve Javadoc
* Add @delvh as developer
This commit is contained in:
Kai S. K. Engelbart 2021-12-16 10:22:37 +01:00
parent 1b6d7f3dde
commit 0f1c3e06d8
Signed by: kske
GPG Key ID: 8BEB13EC5DF7EF13
7 changed files with 56 additions and 20 deletions

View File

@ -6,6 +6,10 @@ import java.util.*;
* A change manager keeps track of subsequent changes and allows un- and redoing them. A specific * A change manager keeps track of subsequent changes and allows un- and redoing them. A specific
* change can be marked using {@link #mark()} to keep track of a saved state in the application that * change can be marked using {@link #mark()} to keep track of a saved state in the application that
* uses the manager. * uses the manager.
* <p>
* If you intend to listen to the state of a change manager, consider writing a wrapper
* implementation for an existing change manager that adds the necessary hooks. If you use JavaFX,
* take a look at the {@code dev.kske.undoredo.javafx} module.
* *
* @param <C> the change type to store in this change manager * @param <C> the change type to store in this change manager
* @author Maximilian K&auml;fer * @author Maximilian K&auml;fer

View File

@ -24,7 +24,7 @@ public final class UnlimitedChangeManager<C extends Change> implements ChangeMan
@Override @Override
public Optional<C> getLastChange() { public Optional<C> getLastChange() {
return index == -1 ? Optional.empty() : Optional.of(changes.get(index)); return index < 0 ? Optional.empty() : Optional.of(changes.get(index));
} }
@Override @Override

View File

@ -27,7 +27,7 @@ class ChangeManagerTest {
* @since 0.0.1 * @since 0.0.1
*/ */
@Test @Test
@Order(1) @Order(10)
void testAddChange() { void testAddChange() {
assertSame(0, wrapper.value); assertSame(0, wrapper.value);
manager.addChange(change); manager.addChange(change);
@ -40,7 +40,7 @@ class ChangeManagerTest {
* @since 0.0.1 * @since 0.0.1
*/ */
@Test @Test
@Order(2) @Order(20)
void testLastChange() { void testLastChange() {
assertTrue(manager.getLastChange().isEmpty()); assertTrue(manager.getLastChange().isEmpty());
manager.addChange(change); manager.addChange(change);
@ -53,7 +53,7 @@ class ChangeManagerTest {
* @since 0.0.1 * @since 0.0.1
*/ */
@Test @Test
@Order(3) @Order(30)
void testGetChanges() { void testGetChanges() {
assertTrue(manager.getChanges().isEmpty()); assertTrue(manager.getChanges().isEmpty());
manager.addChange(change); manager.addChange(change);
@ -67,7 +67,7 @@ class ChangeManagerTest {
* @since 0.0.1 * @since 0.0.1
*/ */
@Test @Test
@Order(4) @Order(40)
void testUndo() { void testUndo() {
assertFalse(manager.isUndoAvailable()); assertFalse(manager.isUndoAvailable());
assertFalse(manager.undo()); assertFalse(manager.undo());
@ -85,7 +85,7 @@ class ChangeManagerTest {
* @since 0.0.1 * @since 0.0.1
*/ */
@Test @Test
@Order(5) @Order(50)
void testRedo() { void testRedo() {
assertFalse(manager.isRedoAvailable()); assertFalse(manager.isRedoAvailable());
assertFalse(manager.redo()); assertFalse(manager.redo());
@ -106,7 +106,7 @@ class ChangeManagerTest {
* @since 0.0.1 * @since 0.0.1
*/ */
@Test @Test
@Order(6) @Order(60)
void testMark() { void testMark() {
assertTrue(manager.isAtMarkedIndex()); assertTrue(manager.isAtMarkedIndex());
manager.addChange(change); manager.addChange(change);

View File

@ -9,6 +9,11 @@ import dev.kske.undoredo.core.*;
/** /**
* Wraps an ordinary change manager into an observable change manager, providing the required * Wraps an ordinary change manager into an observable change manager, providing the required
* properties for concrete implementations. * properties for concrete implementations.
* <p>
* The properties have the same name as their corresponding {@code -property()} methods and can be
* accessed reflectively from JavaFX, e.g. through
* {@link javafx.beans.binding.Bindings#select(Object, String...)}. Alternatively, the property
* names are available as constants.
* *
* @param <C> the change type to store in this change manager * @param <C> the change type to store in this change manager
* @param <M> the type of change manager to wrap * @param <M> the type of change manager to wrap
@ -18,18 +23,29 @@ import dev.kske.undoredo.core.*;
public class ChangeManagerWrapper<C extends Change, M extends ChangeManager<C>> public class ChangeManagerWrapper<C extends Change, M extends ChangeManager<C>>
implements ObservableChangeManager<C> { implements ObservableChangeManager<C> {
public static final String LAST_CHANGE = "lastChange";
public static final String AT_MARKED_INDEX = "atMarkedIndex";
public static final String UNDO_AVAILABLE = "undoAvailable";
public static final String REDO_AVAILABLE = "redoAvailable";
protected ReadOnlyObjectWrapper<C> lastChange = protected ReadOnlyObjectWrapper<C> lastChange =
new ReadOnlyObjectWrapper<>(this, "lastChange"); new ReadOnlyObjectWrapper<>(this, LAST_CHANGE);
protected ReadOnlyBooleanWrapper atMarkedIndex = protected ReadOnlyBooleanWrapper atMarkedIndex =
new ReadOnlyBooleanWrapper(this, "atMarkedIndex"); new ReadOnlyBooleanWrapper(this, AT_MARKED_INDEX);
protected ReadOnlyBooleanWrapper undoAvailable = protected ReadOnlyBooleanWrapper undoAvailable =
new ReadOnlyBooleanWrapper(this, "undoAvailable"); new ReadOnlyBooleanWrapper(this, UNDO_AVAILABLE);
protected ReadOnlyBooleanWrapper redoAvailable = protected ReadOnlyBooleanWrapper redoAvailable =
new ReadOnlyBooleanWrapper(this, "redoAvailable"); new ReadOnlyBooleanWrapper(this, REDO_AVAILABLE);
protected final M manager; protected final M manager;
protected ChangeManagerWrapper(M manager) { /**
* Initializes a change manager wrapper.
*
* @param manager the change manager to wrap
* @since 0.0.1
*/
public ChangeManagerWrapper(M manager) {
this.manager = manager; this.manager = manager;
} }

View File

@ -7,35 +7,39 @@ import javafx.beans.property.*;
import dev.kske.undoredo.core.*; import dev.kske.undoredo.core.*;
/** /**
* A change manager that exposes its state through JavaFX properties, thereby allowing a direct
* integration of Undo-Redo with JavaFX listeners and property bindings.
*
* @param <C> the change type to store in this change manager * @param <C> the change type to store in this change manager
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since 0.0.1 * @since 0.0.1
* @see ChangeManagerWrapper
*/ */
public interface ObservableChangeManager<C extends Change> extends ChangeManager<C> { public interface ObservableChangeManager<C extends Change> extends ChangeManager<C> {
ReadOnlyObjectProperty<C> lastChangeProperty(); ReadOnlyObjectProperty<C> lastChangeProperty();
@Override @Override
default Optional<C> getLastChange() { default Optional<C> getLastChange() {
return Optional.of(lastChangeProperty().get()); return Optional.of(lastChangeProperty().get());
} }
ReadOnlyBooleanProperty atMarkedIndexProperty(); ReadOnlyBooleanProperty atMarkedIndexProperty();
@Override @Override
default boolean isAtMarkedIndex() { default boolean isAtMarkedIndex() {
return atMarkedIndexProperty().get(); return atMarkedIndexProperty().get();
} }
ReadOnlyBooleanProperty undoAvailableProperty(); ReadOnlyBooleanProperty undoAvailableProperty();
@Override @Override
default boolean isUndoAvailable() { default boolean isUndoAvailable() {
return undoAvailableProperty().get(); return undoAvailableProperty().get();
} }
ReadOnlyBooleanProperty redoAvailableProperty(); ReadOnlyBooleanProperty redoAvailableProperty();
@Override @Override
default boolean isRedoAvailable() { default boolean isRedoAvailable() {
return redoAvailableProperty().get(); return redoAvailableProperty().get();

View File

@ -8,6 +8,8 @@ module dev.kske.undoredo.javafx {
exports dev.kske.undoredo.javafx; exports dev.kske.undoredo.javafx;
requires dev.kske.undoredo.core; opens dev.kske.undoredo.javafx to javafx.base;
requires transitive dev.kske.undoredo.core;
requires transitive javafx.base; requires transitive javafx.base;
} }

10
pom.xml
View File

@ -48,6 +48,16 @@
</roles> </roles>
<timezone>Europe/Berlin</timezone> <timezone>Europe/Berlin</timezone>
</developer> </developer>
<developer>
<name>Leon Hofmeister</name>
<email>leon@kske.dev</email>
<url>https://git.kske.dev/delvh</url>
<roles>
<role>architect</role>
<role>developer</role>
</roles>
<timezone>Europe/Berlin</timezone>
</developer>
</developers> </developers>
<scm> <scm>