Merge pull request 'Basic API Structure' (#2) from f/basics into develop
All checks were successful
zdm/undo-redo/pipeline/head This commit looks good
All checks were successful
zdm/undo-redo/pipeline/head This commit looks good
Reviewed-on: https://git.kske.dev/zdm/undo-redo/pulls/2 Reviewed-by: kske <kai@kske.dev> Reviewed-by: delvh <leon@kske.dev>
This commit is contained in:
commit
4b07626155
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
/target/
|
# Maven build directories
|
||||||
/.settings/
|
target/
|
||||||
|
|
||||||
|
# Eclipse settings directories
|
||||||
|
.settings/
|
||||||
|
6
.project
6
.project
@ -5,11 +5,6 @@
|
|||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
<buildSpec>
|
<buildSpec>
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
<buildCommand>
|
||||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
<arguments>
|
<arguments>
|
||||||
@ -17,7 +12,6 @@
|
|||||||
</buildCommand>
|
</buildCommand>
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
</natures>
|
</natures>
|
||||||
</projectDescription>
|
</projectDescription>
|
||||||
|
40
Jenkinsfile
vendored
Normal file
40
Jenkinsfile
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
|
||||||
|
options {
|
||||||
|
ansiColor('xterm')
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
sh 'mvn -DskipTests clean package'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Test') {
|
||||||
|
steps {
|
||||||
|
sh 'mvn test'
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
junit '*/target/surefire-reports/*.xml'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('SonarQube Analysis') {
|
||||||
|
when {
|
||||||
|
branch 'develop'
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
withSonarQubeEnv('KSKE SonarQube') {
|
||||||
|
sh 'mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
success {
|
||||||
|
archiveArtifacts artifacts: '*/target/undo-redo-*.jar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
core/.project
Normal file
23
core/.project
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>undo-redo-core</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
15
core/pom.xml
Normal file
15
core/pom.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>undo-redo-core</artifactId>
|
||||||
|
<name>Undo-Redo Core</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>dev.kske</groupId>
|
||||||
|
<artifactId>undo-redo</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
</project>
|
33
core/src/main/java/dev/kske/undoredo/core/Change.java
Normal file
33
core/src/main/java/dev/kske/undoredo/core/Change.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package dev.kske.undoredo.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base interface for changes to be registered in an undo manager.
|
||||||
|
*
|
||||||
|
* @author Maximilian Käfer
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public interface Change {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the action implemented by this change.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
void apply();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inverts this change.
|
||||||
|
*
|
||||||
|
* @implSpec This method is not supposed to alter the state of this change, but rather to create
|
||||||
|
* a new complementary change.
|
||||||
|
* @return the inverted change
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
Change invert();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether the application of this change would result in an identical state
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean isIdentity();
|
||||||
|
}
|
73
core/src/main/java/dev/kske/undoredo/core/ChangeManager.java
Normal file
73
core/src/main/java/dev/kske/undoredo/core/ChangeManager.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package dev.kske.undoredo.core;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* uses the manager.
|
||||||
|
*
|
||||||
|
* @param <C> the change type to store in this change manager
|
||||||
|
* @author Maximilian Käfer
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public interface ChangeManager<C extends Change> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given change and appends it to the change list.
|
||||||
|
*
|
||||||
|
* @param change the change to add
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
void addChange(C change);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undoes the current change.
|
||||||
|
*
|
||||||
|
* @return whether an action was performed
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
boolean undo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the change that was undone before.
|
||||||
|
*
|
||||||
|
* @return whether an action was performed
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean redo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the current change.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
void mark();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether the current change is marked
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean isAtMarkedIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether a change is present that can be undone
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean isUndoAvailable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return whether a change is present that can be redone
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
boolean isRedoAvailable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an unmodifiable view of the changes stored in this change manager.
|
||||||
|
*
|
||||||
|
* @return all stored changes
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
List<C> getChanges();
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package dev.kske.undoredo.core;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <C> the change type to store in this change manager
|
||||||
|
* @author Maximilian Käfer
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
public final class UnlimitedChangeManager<C extends Change> implements ChangeManager<C> {
|
||||||
|
|
||||||
|
private final List<C> changes = new ArrayList<>();
|
||||||
|
|
||||||
|
private int index = -1;
|
||||||
|
private int markedIndex = -1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChange(C change) {
|
||||||
|
change.apply();
|
||||||
|
changes.add(change);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean undo() {
|
||||||
|
if (isUndoAvailable()) {
|
||||||
|
changes.get(index).invert().apply();
|
||||||
|
--index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean redo() {
|
||||||
|
if (isRedoAvailable()) {
|
||||||
|
changes.get(index + 1).apply();
|
||||||
|
++index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mark() {
|
||||||
|
markedIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAtMarkedIndex() {
|
||||||
|
return markedIndex == index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUndoAvailable() {
|
||||||
|
return index > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRedoAvailable() {
|
||||||
|
return index < changes.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<C> getChanges() {
|
||||||
|
return Collections.unmodifiableList(changes);
|
||||||
|
}
|
||||||
|
}
|
@ -5,4 +5,4 @@
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
package dev.kske.undoredo;
|
package dev.kske.undoredo.core;
|
@ -5,7 +5,7 @@
|
|||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
module dev.kske.undoredo {
|
module dev.kske.undoredo.core {
|
||||||
|
|
||||||
exports dev.kske.undoredo;
|
exports dev.kske.undoredo.core;
|
||||||
}
|
}
|
104
core/src/test/java/dev/kske/undoredo/core/ChangeManagerTest.java
Normal file
104
core/src/test/java/dev/kske/undoredo/core/ChangeManagerTest.java
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package dev.kske.undoredo.core;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
class ChangeManagerTest {
|
||||||
|
|
||||||
|
ChangeManager<IntChange> manager;
|
||||||
|
IntWrapper wrapper;
|
||||||
|
IntChange change;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void prepareChangeManager() {
|
||||||
|
manager = new UnlimitedChangeManager<>();
|
||||||
|
wrapper = new IntWrapper();
|
||||||
|
change = new IntChange(wrapper, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests adding a change.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
void testAddChange() {
|
||||||
|
assertSame(0, wrapper.value);
|
||||||
|
manager.addChange(change);
|
||||||
|
assertSame(1, wrapper.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the consistency of the change list.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
void testGetChanges() {
|
||||||
|
assertTrue(manager.getChanges().isEmpty());
|
||||||
|
manager.addChange(change);
|
||||||
|
assertSame(1, manager.getChanges().size());
|
||||||
|
assertEquals(change, manager.getChanges().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test undoing a change.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
void testUndo() {
|
||||||
|
assertFalse(manager.isUndoAvailable());
|
||||||
|
assertFalse(manager.undo());
|
||||||
|
manager.addChange(change);
|
||||||
|
assertTrue(manager.isUndoAvailable());
|
||||||
|
assertTrue(manager.undo());
|
||||||
|
assertFalse(manager.isUndoAvailable());
|
||||||
|
assertFalse(manager.undo());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests redoing a change.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(4)
|
||||||
|
void testRedo() {
|
||||||
|
assertFalse(manager.isRedoAvailable());
|
||||||
|
assertFalse(manager.redo());
|
||||||
|
manager.addChange(change);
|
||||||
|
assertFalse(manager.isRedoAvailable());
|
||||||
|
assertFalse(manager.redo());
|
||||||
|
manager.undo();
|
||||||
|
assertTrue(manager.isRedoAvailable());
|
||||||
|
assertTrue(manager.redo());
|
||||||
|
assertFalse(manager.isRedoAvailable());
|
||||||
|
assertFalse(manager.redo());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests marking a change.
|
||||||
|
*
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Order(5)
|
||||||
|
void testMark() {
|
||||||
|
assertTrue(manager.isAtMarkedIndex());
|
||||||
|
manager.addChange(change);
|
||||||
|
assertFalse(manager.isAtMarkedIndex());
|
||||||
|
manager.mark();
|
||||||
|
assertTrue(manager.isAtMarkedIndex());
|
||||||
|
manager.undo();
|
||||||
|
assertFalse(manager.isAtMarkedIndex());
|
||||||
|
}
|
||||||
|
}
|
31
core/src/test/java/dev/kske/undoredo/core/IntChange.java
Normal file
31
core/src/test/java/dev/kske/undoredo/core/IntChange.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package dev.kske.undoredo.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
class IntChange implements Change {
|
||||||
|
|
||||||
|
private final IntWrapper wrapper;
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
IntChange(IntWrapper wrapper, int value) {
|
||||||
|
this.wrapper = wrapper;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply() {
|
||||||
|
wrapper.value += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Change invert() {
|
||||||
|
return new IntChange(wrapper, -value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIdentity() {
|
||||||
|
return value == 0;
|
||||||
|
}
|
||||||
|
}
|
10
core/src/test/java/dev/kske/undoredo/core/IntWrapper.java
Normal file
10
core/src/test/java/dev/kske/undoredo/core/IntWrapper.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package dev.kske.undoredo.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kai S. K. Engelbart
|
||||||
|
* @since 0.0.1
|
||||||
|
*/
|
||||||
|
class IntWrapper {
|
||||||
|
|
||||||
|
int value;
|
||||||
|
}
|
9
pom.xml
9
pom.xml
@ -6,11 +6,16 @@
|
|||||||
<groupId>dev.kske</groupId>
|
<groupId>dev.kske</groupId>
|
||||||
<artifactId>undo-redo</artifactId>
|
<artifactId>undo-redo</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<name>Undo-Redo</name>
|
<name>Undo-Redo</name>
|
||||||
<description>A Java library for managing changes in an editor history.</description>
|
<description>A Java library for managing changes in an editor history.</description>
|
||||||
<url>https://git.kske.dev/kske/event-bus</url>
|
<url>https://git.kske.dev/kske/event-bus</url>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>core</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
<name>Apache License, Version 2.0</name>
|
<name>Apache License, Version 2.0</name>
|
||||||
@ -165,8 +170,12 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<version>3.0.0-M5</version>
|
<version>3.0.0-M5</version>
|
||||||
|
<configuration>
|
||||||
|
<argLine>--add-opens dev.kske.undoredo.core/dev.kske.undoredo.core=ALL-UNNAMED</argLine>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user