Skip to content

Instantly share code, notes, and snippets.

@ondrej-kvasnovsky
Last active February 5, 2017 19:08
Show Gist options
  • Save ondrej-kvasnovsky/ef3106c331edfff7dd4d9066bc6f1e4f to your computer and use it in GitHub Desktop.
Save ondrej-kvasnovsky/ef3106c331edfff7dd4d9066bc6f1e4f to your computer and use it in GitHub Desktop.
History Manager (undo / redo)
package com.kangoapp.view.history;
import java.util.ArrayDeque;
import java.util.Deque;
public class History<ENTITY> {
private Deque<ENTITY> backStack = new ArrayDeque<>();
private Deque<ENTITY> forwardStack;
private ENTITY current;
private int max;
public History(int max) {
this.max = max;
}
public void record(ENTITY entity) {
if (backStack.size() >= max) {
backStack.pollFirst();
}
if (!entity.equals(current)) {
current = entity;
backStack.add(entity);
forwardStack = new ArrayDeque<>();
}
}
public ENTITY back() {
ENTITY back = backStack.pollLast();
if (back != null) {
forwardStack.add(current);
}
if (current.equals(back)) {
back = backStack.pollLast();
}
if (back != null) {
current = back;
}
return back;
}
public ENTITY forward() {
ENTITY forward = forwardStack.pollLast();
if (forward != null) {
backStack.add(current);
}
if (current.equals(forward)) {
forward = forwardStack.pollLast();
}
if (forward != null) {
current = forward;
}
return forward;
}
public ENTITY getCurrent() {
return current;
}
}
package com.kangoapp.view.history;
public class HistoryManager {
private final History<String> history = new History<>(1000);
private boolean addHistoryRecord = true;
public HistoryManager() {
history.record("");
}
public History<String> getHistory() {
return history;
}
public boolean isAddHistoryRecord() {
return addHistoryRecord;
}
public void setAddHistoryRecord(boolean addHistoryRecord) {
this.addHistoryRecord = addHistoryRecord;
}
public void enableHistoryRecording() {
this.addHistoryRecord = true;
}
public void disableHistoryRecording() {
this.addHistoryRecord = false;
}
public void record(String text) {
history.record(text);
}
public String back() {
return history.back();
}
public String forward() {
return history.forward();
}
}
package com.kangoapp.view.history;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class HistoryTest {
private History<String> history;
@Before
public void setUp() throws Exception {
history = new History<>(5);
}
@Test
public void testRecord() throws Exception {
history.record("");
history.record("a");
history.record("b");
history.record("c");
history.record("d");
Assert.assertEquals("c", history.back());
Assert.assertEquals("b", history.back());
Assert.assertEquals("a", history.back());
Assert.assertEquals("", history.back());
Assert.assertEquals(null, history.back());
Assert.assertEquals(null, history.back());
Assert.assertEquals("a", history.forward());
Assert.assertEquals("b", history.forward());
Assert.assertEquals("c", history.forward());
Assert.assertEquals("d", history.forward());
Assert.assertEquals(null, history.forward());
Assert.assertEquals(null, history.forward());
Assert.assertEquals("c", history.back());
Assert.assertEquals("b", history.back());
Assert.assertEquals("a", history.back());
}
@Test
public void testMax() throws Exception {
history.record("");
history.record("a");
history.record("b");
history.record("c");
history.record("d");
history.record("e");
history.record("f");
Assert.assertEquals("e", history.back());
Assert.assertEquals("d", history.back());
Assert.assertEquals("c", history.back());
Assert.assertEquals("b", history.back());
Assert.assertEquals(null, history.back());
Assert.assertEquals(null, history.back());
Assert.assertEquals("c", history.forward());
Assert.assertEquals("d", history.forward());
Assert.assertEquals("e", history.forward());
Assert.assertEquals("f", history.forward());
Assert.assertEquals(null, history.forward());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment