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/
|
||||
/.settings/
|
||||
# Maven build directories
|
||||
target/
|
||||
|
||||
# Eclipse settings directories
|
||||
.settings/
|
||||
|
6
.project
6
.project
@ -5,11 +5,6 @@
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
@ -17,7 +12,6 @@
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</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
|
||||
* @since 0.0.1
|
||||
*/
|
||||
package dev.kske.undoredo;
|
||||
package dev.kske.undoredo.core;
|
@ -5,7 +5,7 @@
|
||||
* @author Kai S. K. Engelbart
|
||||
* @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>
|
||||
<artifactId>undo-redo</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Undo-Redo</name>
|
||||
<description>A Java library for managing changes in an editor history.</description>
|
||||
<url>https://git.kske.dev/kske/event-bus</url>
|
||||
|
||||
<modules>
|
||||
<module>core</module>
|
||||
</modules>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
@ -165,8 +170,12 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M5</version>
|
||||
<configuration>
|
||||
<argLine>--add-opens dev.kske.undoredo.core/dev.kske.undoredo.core=ALL-UNNAMED</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
|
Reference in New Issue
Block a user