History refactor
This commit is contained in:
parent
b21d8084f0
commit
3fd671877d
@ -165,7 +165,7 @@ public abstract class BaseUi implements SharedPreferences.OnSharedPreferenceChan
|
|||||||
final ViewsCache views = ViewsCache.forView(root);
|
final ViewsCache views = ViewsCache.forView(root);
|
||||||
setOnDragListeners(views, activity);
|
setOnDragListeners(views, activity);
|
||||||
|
|
||||||
HistoryDragProcessor<OldHistoryState> historyDragProcessor = new HistoryDragProcessor<>(getCalculator());
|
HistoryDragProcessor<OldHistoryState> historyDragProcessor = new HistoryDragProcessor<>();
|
||||||
final DragListener historyDragListener = newDragListener(historyDragProcessor, activity);
|
final DragListener historyDragListener = newDragListener(historyDragProcessor, activity);
|
||||||
final DragButton historyButton = getButton(views, R.id.cpp_button_history);
|
final DragButton historyButton = getButton(views, R.id.cpp_button_history);
|
||||||
if (historyButton != null) {
|
if (historyButton != null) {
|
||||||
|
@ -22,21 +22,20 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import org.solovyev.android.calculator.history.OldHistoryState;
|
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.common.history.HistoryControl;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
* Time: 16:38
|
* Time: 16:38
|
||||||
*/
|
*/
|
||||||
public interface Calculator extends CalculatorEventContainer, HistoryControl<OldHistoryState> {
|
public interface Calculator extends CalculatorEventContainer {
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
@ -23,22 +23,14 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.squareup.otto.Subscribe;
|
import com.squareup.otto.Subscribe;
|
||||||
import jscl.AbstractJsclArithmeticException;
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import jscl.NumeralBaseException;
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import jscl.math.function.Function;
|
|
||||||
import jscl.math.function.IConstant;
|
|
||||||
import jscl.math.operator.Operator;
|
|
||||||
import jscl.text.ParseInterruptedException;
|
|
||||||
import org.solovyev.android.calculator.history.CalculatorHistory;
|
import org.solovyev.android.calculator.history.CalculatorHistory;
|
||||||
import org.solovyev.android.calculator.history.OldHistoryState;
|
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
import org.solovyev.android.calculator.model.Var;
|
import org.solovyev.android.calculator.model.Var;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
|
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
|
||||||
import org.solovyev.common.history.HistoryAction;
|
|
||||||
import org.solovyev.common.msg.ListMessageRegistry;
|
import org.solovyev.common.msg.ListMessageRegistry;
|
||||||
import org.solovyev.common.msg.Message;
|
import org.solovyev.common.msg.Message;
|
||||||
import org.solovyev.common.msg.MessageRegistry;
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
@ -47,14 +39,24 @@ import org.solovyev.common.text.Strings;
|
|||||||
import org.solovyev.common.units.ConversionException;
|
import org.solovyev.common.units.ConversionException;
|
||||||
import org.solovyev.common.units.Conversions;
|
import org.solovyev.common.units.Conversions;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import jscl.AbstractJsclArithmeticException;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import jscl.NumeralBaseException;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.function.Function;
|
||||||
|
import jscl.math.function.IConstant;
|
||||||
|
import jscl.math.operator.Operator;
|
||||||
|
import jscl.text.ParseInterruptedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
@ -507,6 +509,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
|
|||||||
CalculatorVarsRegistry.saveVariable(varsRegistry, builder, ansVar, this, false);
|
CalculatorVarsRegistry.saveVariable(varsRegistry, builder, ansVar, this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onHistoryChanged(@Nonnull CalculatorHistory.ChangedEvent e) {
|
||||||
|
getEditor().setState(e.state.getEditor());
|
||||||
|
getDisplay().setState(e.state.getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||||
|
|
||||||
@ -548,44 +555,6 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* HISTORY
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doHistoryAction(@Nonnull HistoryAction historyAction) {
|
|
||||||
final CalculatorHistory history = Locator.getInstance().getHistory();
|
|
||||||
if (history.isActionAvailable(historyAction)) {
|
|
||||||
final OldHistoryState newState = history.doAction(historyAction, getCurrentHistoryState());
|
|
||||||
if (newState != null) {
|
|
||||||
setCurrentHistoryState(newState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public OldHistoryState getCurrentHistoryState() {
|
|
||||||
return OldHistoryState.create(getEditor(), getDisplay());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCurrentHistoryState(@Nonnull OldHistoryState editorHistoryState) {
|
|
||||||
editorHistoryState.setValuesFromHistory(getEditor(), getDisplay());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* OTHER
|
|
||||||
*
|
|
||||||
**********************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private Editor getEditor() {
|
private Editor getEditor() {
|
||||||
return Locator.getInstance().getEditor();
|
return Locator.getInstance().getEditor();
|
||||||
|
@ -23,10 +23,8 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import org.solovyev.android.Check;
|
import org.solovyev.android.Check;
|
||||||
import org.solovyev.android.calculator.history.OldEditorHistoryState;
|
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
|
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
|
||||||
import org.solovyev.common.text.Strings;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -104,9 +102,9 @@ public class Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public EditorState setState(@Nonnull OldEditorHistoryState state) {
|
public EditorState setState(@Nonnull EditorState state) {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
return setText(Strings.getNotEmpty(state.getText(), ""), state.getCursorPosition());
|
return setText(state.getTextString(), state.selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -109,7 +109,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
|||||||
boolean result = false;
|
boolean result = false;
|
||||||
try {
|
try {
|
||||||
historyState.setSaved(true);
|
historyState.setSaved(true);
|
||||||
if (Collections.contains(historyState, Locator.getInstance().getHistory().getSavedOldHistory(), new Equalizer<OldHistoryState>() {
|
if (Collections.contains(historyState, Locator.getInstance().getHistory().getSavedHistory(), new Equalizer<OldHistoryState>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean areEqual(@Nullable OldHistoryState first, @Nullable OldHistoryState second) {
|
public boolean areEqual(@Nullable OldHistoryState first, @Nullable OldHistoryState second) {
|
||||||
return first != null && second != null &&
|
return first != null && second != null &&
|
||||||
@ -401,7 +401,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected abstract List<OldHistoryState> getHistoryItems();
|
protected abstract List<HistoryState> getHistoryItems();
|
||||||
|
|
||||||
protected abstract void clearHistory();
|
protected abstract void clearHistory();
|
||||||
|
|
||||||
|
@ -24,30 +24,33 @@ package org.solovyev.android.calculator.history;
|
|||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.squareup.otto.Subscribe;
|
|
||||||
import org.solovyev.android.Check;
|
|
||||||
import org.solovyev.android.calculator.*;
|
|
||||||
import org.solovyev.common.history.HistoryAction;
|
|
||||||
import org.solovyev.common.history.HistoryHelper;
|
|
||||||
import org.solovyev.common.history.SimpleHistoryHelper;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import com.squareup.otto.Subscribe;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
import org.solovyev.android.Check;
|
||||||
|
import org.solovyev.android.calculator.App;
|
||||||
|
import org.solovyev.android.calculator.CalculatorEventType;
|
||||||
|
import org.solovyev.android.calculator.Display;
|
||||||
|
import org.solovyev.android.calculator.Editor;
|
||||||
|
import org.solovyev.android.calculator.EditorState;
|
||||||
|
import org.solovyev.android.calculator.Locator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class CalculatorHistory {
|
public class CalculatorHistory {
|
||||||
|
|
||||||
private final AtomicInteger counter = new AtomicInteger(0);
|
private final AtomicInteger counter = new AtomicInteger(0);
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final HistoryHelper<OldHistoryState> history = SimpleHistoryHelper.newInstance();
|
private final HistoryList current = new HistoryList();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final OldHistory savedOldHistory = new OldHistory();
|
private final List<HistoryState> saved = new ArrayList<>();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private EditorState lastEditorState;
|
private EditorState lastEditorState;
|
||||||
|
|
||||||
@ -61,12 +64,7 @@ public class CalculatorHistory {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private static void migrateOldHistory() {
|
||||||
Check.isNotMainThread();
|
|
||||||
migrateOldHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void migrateOldHistory() {
|
|
||||||
final SharedPreferences preferences = App.getPreferences();
|
final SharedPreferences preferences = App.getPreferences();
|
||||||
final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null);
|
final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null);
|
||||||
if (TextUtils.isEmpty(xml)) {
|
if (TextUtils.isEmpty(xml)) {
|
||||||
@ -79,77 +77,60 @@ public class CalculatorHistory {
|
|||||||
}
|
}
|
||||||
for (OldHistoryState state : history.getItems()) {
|
for (OldHistoryState state : history.getItems()) {
|
||||||
state.setSaved(true);
|
state.setSaved(true);
|
||||||
state.setId(counter.incrementAndGet());
|
|
||||||
savedOldHistory.add(state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
Check.isNotMainThread();
|
||||||
|
migrateOldHistory();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
return history.isEmpty();
|
return current.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActionAvailable(@Nonnull HistoryAction action) {
|
public void addCurrentState(@Nonnull HistoryState state) {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
return history.isActionAvailable(action);
|
current.addState(state);
|
||||||
|
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, state);
|
||||||
|
// todo serso: schedule save
|
||||||
}
|
}
|
||||||
|
|
||||||
public OldHistoryState doAction(@Nonnull HistoryAction action, @Nullable OldHistoryState state) {
|
public void addSavedState(@Nonnull HistoryState state) {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
return history.doAction(action, state);
|
saved.add(state);
|
||||||
}
|
// todo serso: schedule save
|
||||||
|
|
||||||
public void addState(@Nullable OldHistoryState currentState) {
|
|
||||||
Check.isMainThread();
|
|
||||||
history.addState(currentState);
|
|
||||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public List<OldHistoryState> getStates() {
|
public List<HistoryState> getCurrentHistory() {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
return history.getStates();
|
|
||||||
|
final List<HistoryState> result = new LinkedList<>();
|
||||||
|
|
||||||
|
final List<HistoryState> states = current.asList();
|
||||||
|
for (int i = 1; i < states.size(); i++) {
|
||||||
|
final HistoryState newerState = states.get(i);
|
||||||
|
final HistoryState olderState = states.get(i - 1);
|
||||||
|
final String newerText = newerState.editor.getTextString();
|
||||||
|
final String olderText = olderState.editor.getTextString();
|
||||||
|
if (!isIntermediate(olderText, newerText)) {
|
||||||
|
result.add(0, olderState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public List<OldHistoryState> getStates(boolean includeIntermediateStates) {
|
|
||||||
Check.isMainThread();
|
|
||||||
if (includeIntermediateStates) {
|
|
||||||
return getStates();
|
|
||||||
} else {
|
|
||||||
final List<OldHistoryState> states = getStates();
|
|
||||||
|
|
||||||
final List<OldHistoryState> result = new LinkedList<>();
|
|
||||||
|
|
||||||
OldHistoryState laterState = null;
|
|
||||||
for (OldHistoryState state : org.solovyev.common.collections.Collections.reversed(states)) {
|
|
||||||
if (laterState != null) {
|
|
||||||
final String laterEditorText = laterState.getEditorState().getText();
|
|
||||||
final String editorText = state.getEditorState().getText();
|
|
||||||
if (laterEditorText != null && editorText != null && isIntermediate(laterEditorText, editorText)) {
|
|
||||||
// intermediate result => skip from add
|
|
||||||
} else {
|
|
||||||
result.add(0, state);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result.add(0, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
laterState = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isIntermediate(@Nonnull String laterEditorText,
|
private boolean isIntermediate(@Nonnull String newerText,
|
||||||
@Nonnull String editorText) {
|
@Nonnull String olderText) {
|
||||||
if (Math.abs(laterEditorText.length() - editorText.length()) <= 1) {
|
final int diff = newerText.length() - olderText.length();
|
||||||
if (laterEditorText.length() > editorText.length()) {
|
if (diff == 1) {
|
||||||
return laterEditorText.startsWith(editorText);
|
return newerText.startsWith(olderText);
|
||||||
} else {
|
} else if (diff == -1) {
|
||||||
return editorText.startsWith(laterEditorText);
|
return olderText.startsWith(newerText);
|
||||||
}
|
} else if (diff == 0) {
|
||||||
|
return newerText.equals(olderText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -157,53 +138,36 @@ public class CalculatorHistory {
|
|||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
history.clear();
|
current.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void undo() {
|
||||||
|
final HistoryState state = current.undo();
|
||||||
|
if (state == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
App.getBus().post(new ChangedEvent(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void redo() {
|
||||||
|
final HistoryState state = current.redo();
|
||||||
|
if (state == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
App.getBus().post(new ChangedEvent(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public List<OldHistoryState> getSavedOldHistory() {
|
public List<HistoryState> getSavedHistory() {
|
||||||
return Collections.unmodifiableList(savedOldHistory.getItems());
|
return Collections.unmodifiableList(saved);
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
public OldHistoryState addSavedState(@Nonnull OldHistoryState state) {
|
|
||||||
if (state.isSaved()) {
|
|
||||||
return state;
|
|
||||||
} else {
|
|
||||||
final OldHistoryState savedState = state.clone();
|
|
||||||
|
|
||||||
savedState.setId(counter.incrementAndGet());
|
|
||||||
savedState.setSaved(true);
|
|
||||||
|
|
||||||
savedOldHistory.add(savedState);
|
|
||||||
|
|
||||||
return savedState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save() {
|
|
||||||
final SharedPreferences settings = App.getPreferences();
|
|
||||||
final SharedPreferences.Editor editor = settings.edit();
|
|
||||||
editor.putString("org.solovyev.android.calculator.CalculatorModel_history", toXml());
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toXml() {
|
|
||||||
return savedOldHistory.toXml();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearSavedHistory() {
|
public void clearSavedHistory() {
|
||||||
savedOldHistory.clear();
|
saved.clear();
|
||||||
save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeSavedHistory(@Nonnull OldHistoryState historyState) {
|
public void removeSavedHistory(@Nonnull HistoryState state) {
|
||||||
historyState.setSaved(false);
|
saved.remove(state);
|
||||||
this.savedOldHistory.remove(historyState);
|
|
||||||
save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@ -219,7 +183,16 @@ public class CalculatorHistory {
|
|||||||
if (lastEditorState.sequence != e.newState.getSequence()) {
|
if (lastEditorState.sequence != e.newState.getSequence()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addState(OldHistoryState.create(lastEditorState, e.newState));
|
addCurrentState(HistoryState.newBuilder(lastEditorState, e.newState).build());
|
||||||
lastEditorState = null;
|
lastEditorState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class ChangedEvent {
|
||||||
|
@Nonnull
|
||||||
|
public final HistoryState state;
|
||||||
|
|
||||||
|
public ChangedEvent(@Nonnull HistoryState state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,41 +25,25 @@ package org.solovyev.android.calculator.history;
|
|||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import org.solovyev.android.calculator.Locator;
|
||||||
import org.solovyev.android.views.dragbutton.DragButton;
|
import org.solovyev.android.views.dragbutton.DragButton;
|
||||||
import org.solovyev.android.views.dragbutton.DragDirection;
|
import org.solovyev.android.views.dragbutton.DragDirection;
|
||||||
import org.solovyev.android.views.dragbutton.SimpleDragListener;
|
import org.solovyev.android.views.dragbutton.SimpleDragListener;
|
||||||
import org.solovyev.common.history.HistoryAction;
|
|
||||||
import org.solovyev.common.history.HistoryControl;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class HistoryDragProcessor<T> implements SimpleDragListener.DragProcessor {
|
public class HistoryDragProcessor<T> implements SimpleDragListener.DragProcessor {
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private final HistoryControl<T> historyControl;
|
|
||||||
|
|
||||||
public HistoryDragProcessor(@Nonnull HistoryControl<T> historyControl) {
|
|
||||||
this.historyControl = historyControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processDragEvent(@Nonnull DragDirection direction, @Nonnull DragButton button, @Nonnull PointF startPoint, @Nonnull MotionEvent motionEvent) {
|
public boolean processDragEvent(@Nonnull DragDirection direction, @Nonnull DragButton button, @Nonnull PointF startPoint, @Nonnull MotionEvent motionEvent) {
|
||||||
final HistoryAction action = getActionFromDirection(direction);
|
switch (direction) {
|
||||||
if (action != null) {
|
case up:
|
||||||
historyControl.doHistoryAction(action);
|
Locator.getInstance().getHistory().undo();
|
||||||
|
return true;
|
||||||
|
case down:
|
||||||
|
Locator.getInstance().getHistory().redo();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private HistoryAction getActionFromDirection(@Nonnull DragDirection direction) {
|
|
||||||
if (direction == DragDirection.up) {
|
|
||||||
return HistoryAction.undo;
|
|
||||||
} else if (direction == DragDirection.down) {
|
|
||||||
return HistoryAction.redo;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import org.solovyev.android.calculator.Locator;
|
|||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HistoryFragment extends BaseHistoryFragment {
|
public class HistoryFragment extends BaseHistoryFragment {
|
||||||
@ -43,8 +43,8 @@ public class HistoryFragment extends BaseHistoryFragment {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
protected List<OldHistoryState> getHistoryItems() {
|
protected List<HistoryState> getHistoryItems() {
|
||||||
return new ArrayList<>(Locator.getInstance().getHistory().getStates(false));
|
return Locator.getInstance().getHistory().getCurrentHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.solovyev.android.Check;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HistoryList {
|
||||||
|
|
||||||
|
private static final int MAX_HISTORY = 20;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final List<HistoryState> list = new LinkedList<>();
|
||||||
|
private int current = -1;
|
||||||
|
|
||||||
|
public void addState(@NonNull HistoryState e) {
|
||||||
|
Check.isMainThread();
|
||||||
|
while (current != list.size() - 1) {
|
||||||
|
list.remove(list.size() - 1);
|
||||||
|
}
|
||||||
|
list.add(e);
|
||||||
|
current++;
|
||||||
|
if (list.size() > MAX_HISTORY) {
|
||||||
|
current--;
|
||||||
|
list.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public HistoryState getCurrent() {
|
||||||
|
Check.isMainThread();
|
||||||
|
if (current == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.get(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public HistoryState redo() {
|
||||||
|
Check.isMainThread();
|
||||||
|
if (current < list.size() - 1) {
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
return getCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public HistoryState undo() {
|
||||||
|
Check.isMainThread();
|
||||||
|
if (current == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (current > 0) {
|
||||||
|
current--;
|
||||||
|
return getCurrent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
Check.isMainThread();
|
||||||
|
list.clear();
|
||||||
|
current = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return list.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public List<HistoryState> asList() {
|
||||||
|
return Collections.unmodifiableList(list);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package org.solovyev.android.calculator.history;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.solovyev.android.Check;
|
||||||
|
import org.solovyev.android.calculator.DisplayState;
|
||||||
|
import org.solovyev.android.calculator.EditorState;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class HistoryState {
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
protected final EditorState editor;
|
||||||
|
@Nonnull
|
||||||
|
protected final DisplayState display;
|
||||||
|
protected long time;
|
||||||
|
@Nullable
|
||||||
|
protected String comment;
|
||||||
|
|
||||||
|
private HistoryState(@Nonnull EditorState editor, @Nonnull DisplayState display) {
|
||||||
|
this.editor = editor;
|
||||||
|
this.display = display;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public static Builder newBuilder(@Nonnull EditorState editor, @Nonnull DisplayState display) {
|
||||||
|
return new Builder(editor, display);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public EditorState getEditor() {
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public DisplayState getDisplay() {
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Builder extends HistoryState {
|
||||||
|
|
||||||
|
private boolean built;
|
||||||
|
|
||||||
|
private Builder(@Nonnull EditorState editor, @Nonnull DisplayState display) {
|
||||||
|
super(editor, display);
|
||||||
|
setTime(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(long time) {
|
||||||
|
Check.isTrue(!built);
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(@Nullable String comment) {
|
||||||
|
Check.isTrue(!built);
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public HistoryState build() {
|
||||||
|
built = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -29,7 +29,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class BaseHistoryState implements Cloneable {
|
public class OldBaseHistoryState implements Cloneable {
|
||||||
|
|
||||||
@Element
|
@Element
|
||||||
private long time = new Date().getTime();
|
private long time = new Date().getTime();
|
||||||
@ -79,9 +79,9 @@ public class BaseHistoryState implements Cloneable {
|
|||||||
|
|
||||||
@SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
|
@SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
|
||||||
@Override
|
@Override
|
||||||
protected BaseHistoryState clone() {
|
protected OldBaseHistoryState clone() {
|
||||||
try {
|
try {
|
||||||
return (BaseHistoryState) super.clone();
|
return (OldBaseHistoryState) super.clone();
|
||||||
} catch (CloneNotSupportedException e) {
|
} catch (CloneNotSupportedException e) {
|
||||||
throw new UnsupportedOperationException(e);
|
throw new UnsupportedOperationException(e);
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ import org.solovyev.android.calculator.EditorState;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
@Root(name = "HistoryState")
|
@Root(name = "HistoryState")
|
||||||
public class OldHistoryState extends BaseHistoryState {
|
public class OldHistoryState extends OldBaseHistoryState {
|
||||||
|
|
||||||
@Element
|
@Element
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@ -82,35 +82,6 @@ public class OldHistoryState extends BaseHistoryState {
|
|||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
OldHistoryState that = (OldHistoryState) o;
|
|
||||||
|
|
||||||
if (this.isSaved() != that.isSaved()) return false;
|
|
||||||
if (this.getId() != that.getId()) return false;
|
|
||||||
if (!displayState.equals(that.displayState)) return false;
|
|
||||||
if (!editorState.equals(that.editorState)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = Boolean.valueOf(isSaved()).hashCode();
|
|
||||||
result = 31 * result + getId();
|
|
||||||
result = 31 * result + editorState.hashCode();
|
|
||||||
result = 31 * result + displayState.hashCode();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValuesFromHistory(@Nonnull Editor editor, @Nonnull Display display) {
|
|
||||||
this.getEditorState().setValuesFromHistory(editor);
|
|
||||||
this.getDisplayState().setValuesFromHistory(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected OldHistoryState clone() {
|
protected OldHistoryState clone() {
|
||||||
final OldHistoryState that = (OldHistoryState) super.clone();
|
final OldHistoryState that = (OldHistoryState) super.clone();
|
||||||
|
@ -44,8 +44,8 @@ public class SavedHistoryFragment extends BaseHistoryFragment {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
protected List<OldHistoryState> getHistoryItems() {
|
protected List<HistoryState> getHistoryItems() {
|
||||||
return new ArrayList<OldHistoryState>(Locator.getInstance().getHistory().getSavedOldHistory());
|
return new ArrayList<>(Locator.getInstance().getHistory().getSavedHistory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,13 +62,13 @@ public class CalculatorHistoryTest {
|
|||||||
addState(calculatorHistory, "2354");
|
addState(calculatorHistory, "2354");
|
||||||
addState(calculatorHistory, "23547");
|
addState(calculatorHistory, "23547");
|
||||||
|
|
||||||
final List<OldHistoryState> states = calculatorHistory.getStates(false);
|
final List<OldHistoryState> states = calculatorHistory.getCurrentHistory();
|
||||||
Assert.assertEquals(2, states.size());
|
Assert.assertEquals(2, states.size());
|
||||||
Assert.assertEquals("23547", states.get(1).getEditorState().getText());
|
Assert.assertEquals("23547", states.get(1).getEditorState().getText());
|
||||||
Assert.assertEquals("123+3", states.get(0).getEditorState().getText());
|
Assert.assertEquals("123+3", states.get(0).getEditorState().getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addState(@Nonnull CalculatorHistory calculatorHistory, @Nonnull String text) {
|
private void addState(@Nonnull CalculatorHistory calculatorHistory, @Nonnull String text) {
|
||||||
calculatorHistory.addState(OldHistoryState.create(EditorState.create(text, 3), DisplayState.empty()));
|
calculatorHistory.addCurrentState(OldHistoryState.create(EditorState.create(text, 3), DisplayState.empty()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user