android_calculator-4: Extend history functionality

This commit is contained in:
Sergey Solovyev 2011-12-18 02:16:30 +04:00
parent 38152fe80d
commit 9d785e4b1e
9 changed files with 138 additions and 43 deletions

View File

@ -26,6 +26,7 @@ import jscl.AngleUnit;
import jscl.NumeralBase; import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
@ -90,6 +91,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE); vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
CalculatorHistory.instance.load(this, preferences);
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance); calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
dpclRegister.clear(); dpclRegister.clear();

View File

@ -38,6 +38,21 @@ import java.util.List;
*/ */
public class CalculatorHistoryActivity extends ListActivity { public class CalculatorHistoryActivity extends ListActivity {
private static final Comparator<CalculatorHistoryState> COMPARATOR = new Comparator<CalculatorHistoryState>() {
@Override
public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) {
if (state1.isSaved() == state2.isSaved()) {
return state2.getTime().compareTo(state1.getTime());
} else if (state1.isSaved()) {
return -1;
} else if (state2.isSaved()) {
return 1;
}
return 0;
}
};
@NotNull @NotNull
private HistoryArrayAdapter adapter; private HistoryArrayAdapter adapter;
@ -84,7 +99,7 @@ public class CalculatorHistoryActivity extends ListActivity {
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override @Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position); final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position);
final Context context = CalculatorHistoryActivity.this; final Context context = CalculatorHistoryActivity.this;
@ -96,23 +111,23 @@ public class CalculatorHistoryActivity extends ListActivity {
public void onClick(DialogInterface dialog, int item) { public void onClick(DialogInterface dialog, int item) {
if (item == 0) { if (item == 0) {
if (!historyState.isSaved()) { if (!historyState.isSaved()) {
historyState.setSaved(true); final CalculatorHistoryState savedHistoryItem = CalculatorHistory.instance.addSavedState(historyState);
CalculatorHistory.instance.getSavedHistory().addState(historyState);
CalculatorHistory.instance.save(context); CalculatorHistory.instance.save(context);
adapter.add(savedHistoryItem);
adapter.sort(COMPARATOR);
CalculatorHistoryActivity.this.adapter.notifyDataSetChanged(); CalculatorHistoryActivity.this.adapter.notifyDataSetChanged();
Toast.makeText(context, "History item was successfully saved!", Toast.LENGTH_LONG).show(); Toast.makeText(context, "History item was successfully saved!", Toast.LENGTH_LONG).show();
} else { } else {
Toast.makeText(context, "History item was already saved!", Toast.LENGTH_LONG).show(); Toast.makeText(context, "History item was already saved!", Toast.LENGTH_LONG).show();
} }
} else if (item == 1) { } else if (item == 1) {
adapter.remove(historyState);
adapter.sort(COMPARATOR);
if (historyState.isSaved()) { if (historyState.isSaved()) {
historyState.setSaved(false); CalculatorHistory.instance.removeSavedHistory(historyState, context, PreferenceManager.getDefaultSharedPreferences(context));
CalculatorHistory.instance.save(context);
CalculatorHistory.instance.getSavedHistory().clear();
CalculatorHistory.instance.load(context, PreferenceManager.getDefaultSharedPreferences(context));
CalculatorHistoryActivity.this.adapter.notifyDataSetChanged();
Toast.makeText(context, "History item was removed!", Toast.LENGTH_LONG).show(); Toast.makeText(context, "History item was removed!", Toast.LENGTH_LONG).show();
} }
CalculatorHistoryActivity.this.adapter.notifyDataSetChanged();
} }
} }
}); });
@ -124,21 +139,9 @@ public class CalculatorHistoryActivity extends ListActivity {
private static List<CalculatorHistoryState> getHistoryList() { private static List<CalculatorHistoryState> getHistoryList() {
final List<CalculatorHistoryState> calculatorHistoryStates = new ArrayList<CalculatorHistoryState>(CalculatorHistory.instance.getStates()); final List<CalculatorHistoryState> calculatorHistoryStates = new ArrayList<CalculatorHistoryState>(CalculatorHistory.instance.getStates());
calculatorHistoryStates.addAll(CalculatorHistory.instance.getSavedHistory().getStates()); calculatorHistoryStates.addAll(CalculatorHistory.instance.getSavedHistory());
Collections.sort(calculatorHistoryStates, new Comparator<CalculatorHistoryState>() { Collections.sort(calculatorHistoryStates, COMPARATOR);
@Override
public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) {
if ( state1.isSaved() == state2.isSaved() ) {
return state2.getTime().compareTo(state1.getTime());
} else if ( state1.isSaved() ) {
return -1;
} else if ( state2.isSaved() ) {
return 1;
}
return 0;
}
});
final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>(); final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>();
filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() { filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() {
@ -218,9 +221,18 @@ public class CalculatorHistoryActivity extends ListActivity {
} }
private void clearHistory() { private void clearHistory() {
final List<CalculatorHistoryState> historyStates = new ArrayList<CalculatorHistoryState>(CalculatorHistory.instance.getStates());
CalculatorHistory.instance.clear(); CalculatorHistory.instance.clear();
for (CalculatorHistoryState historyState : historyStates) {
adapter.remove(historyState);
}
if (adapter.getCount() > 0) {
adapter.sort(COMPARATOR);
adapter.notifyDataSetChanged();
} else {
Toast.makeText(this, R.string.c_history_is_empty, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.c_history_is_empty, Toast.LENGTH_SHORT).show();
this.finish(); this.finish();
} }
} }
}

View File

@ -18,7 +18,7 @@ import java.util.Date;
* Date: 10/15/11 * Date: 10/15/11
* Time: 1:45 PM * Time: 1:45 PM
*/ */
public class AbstractHistoryState { public class AbstractHistoryState implements Cloneable{
@Element @Element
@NotNull @NotNull
@ -56,4 +56,18 @@ public class AbstractHistoryState {
public void setSaved(boolean saved) { public void setSaved(boolean saved) {
this.saved = saved; this.saved = saved;
} }
@Override
protected AbstractHistoryState clone() {
AbstractHistoryState clone;
try {
clone = (AbstractHistoryState)super.clone();
clone.time = new Date(this.time.getTime());
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(e);
}
return clone;
}
} }

View File

@ -21,7 +21,7 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
*/ */
@Root @Root
public class CalculatorDisplayHistoryState { public class CalculatorDisplayHistoryState implements Cloneable {
@Transient @Transient
private boolean valid = true; private boolean valid = true;
@ -122,4 +122,17 @@ public class CalculatorDisplayHistoryState {
", jsclOperation=" + jsclOperation + ", jsclOperation=" + jsclOperation +
'}'; '}';
} }
@Override
protected CalculatorDisplayHistoryState clone() {
try {
final CalculatorDisplayHistoryState clone = (CalculatorDisplayHistoryState) super.clone();
clone.editorState = this.editorState.clone();
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
} }

View File

@ -16,6 +16,8 @@ import org.solovyev.common.utils.history.HistoryAction;
import org.solovyev.common.utils.history.HistoryHelper; import org.solovyev.common.utils.history.HistoryHelper;
import org.solovyev.common.utils.history.SimpleHistoryHelper; import org.solovyev.common.utils.history.SimpleHistoryHelper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -31,7 +33,7 @@ public enum CalculatorHistory implements HistoryHelper<CalculatorHistoryState> {
private final HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>(); private final HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
@NotNull @NotNull
private final HistoryHelper<CalculatorHistoryState> savedHistory = new SimpleHistoryHelper<CalculatorHistoryState>(); private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState> ();
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
@ -89,15 +91,13 @@ public enum CalculatorHistory implements HistoryHelper<CalculatorHistoryState> {
this.history.clear(); this.history.clear();
} }
@NotNull
public HistoryHelper<CalculatorHistoryState> getSavedHistory() {
return savedHistory;
}
public void load(@Nullable Context context, @Nullable SharedPreferences preferences) { public void load(@Nullable Context context, @Nullable SharedPreferences preferences) {
if (context != null && preferences != null) { if (context != null && preferences != null) {
final String value = preferences.getString(context.getString(R.string.p_calc_history), null); final String value = preferences.getString(context.getString(R.string.p_calc_history), null);
HistoryUtils.fromXml(value, this.savedHistory); HistoryUtils.fromXml(value, this.savedHistory);
for (CalculatorHistoryState historyState : savedHistory) {
historyState.setSaved(true);
}
} }
} }
@ -110,4 +110,31 @@ public enum CalculatorHistory implements HistoryHelper<CalculatorHistoryState> {
editor.commit(); editor.commit();
} }
@NotNull
public List<CalculatorHistoryState> getSavedHistory() {
return Collections.unmodifiableList(savedHistory);
}
@NotNull
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
if (historyState.isSaved()) {
return historyState;
} else {
final CalculatorHistoryState savedState = historyState.clone();
savedState.setSaved(true);
savedHistory.add(savedState);
return savedState;
}
}
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState, @NotNull Context context, @NotNull SharedPreferences preferences) {
historyState.setSaved(false);
save(context);
this.savedHistory.clear();
load(context, preferences);
}
} }

View File

@ -76,6 +76,7 @@ public class CalculatorHistoryState extends AbstractHistoryState {
CalculatorHistoryState that = (CalculatorHistoryState) o; CalculatorHistoryState that = (CalculatorHistoryState) o;
if (this.isSaved() != that.isSaved()) return false;
if (!displayState.equals(that.displayState)) return false; if (!displayState.equals(that.displayState)) return false;
if (!editorState.equals(that.editorState)) return false; if (!editorState.equals(that.editorState)) return false;
@ -84,7 +85,8 @@ public class CalculatorHistoryState extends AbstractHistoryState {
@Override @Override
public int hashCode() { public int hashCode() {
int result = editorState.hashCode(); int result = Boolean.valueOf(isSaved()).hashCode();
result = 31 * result + editorState.hashCode();
result = 31 * result + displayState.hashCode(); result = 31 * result + displayState.hashCode();
return result; return result;
} }
@ -93,4 +95,14 @@ public class CalculatorHistoryState extends AbstractHistoryState {
this.getEditorState().setValuesFromHistory(editor); this.getEditorState().setValuesFromHistory(editor);
this.getDisplayState().setValuesFromHistory(display); this.getDisplayState().setValuesFromHistory(display);
} }
@Override
protected CalculatorHistoryState clone() {
final CalculatorHistoryState clone = (CalculatorHistoryState)super.clone();
clone.editorState = this.editorState.clone();
clone.displayState = this.displayState.clone();
return clone;
}
} }

View File

@ -11,7 +11,7 @@ import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root; import org.simpleframework.xml.Root;
@Root @Root
public class EditorHistoryState { public class EditorHistoryState implements Cloneable{
@Element @Element
private int cursorPosition; private int cursorPosition;
@ -75,4 +75,13 @@ public class EditorHistoryState {
", text='" + text + '\'' + ", text='" + text + '\'' +
'}'; '}';
} }
@Override
protected EditorHistoryState clone() {
try {
return (EditorHistoryState)super.clone();
} catch (CloneNotSupportedException e) {
throw new UnsupportedOperationException(e);
}
}
} }

View File

@ -10,9 +10,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.simpleframework.xml.Serializer; import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister; import org.simpleframework.xml.core.Persister;
import org.solovyev.common.utils.history.HistoryHelper;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.List;
/** /**
* User: serso * User: serso
@ -26,13 +26,13 @@ class HistoryUtils {
throw new AssertionError(); throw new AssertionError();
} }
public static void fromXml(@Nullable String xml, @NotNull HistoryHelper<CalculatorHistoryState> calculatorHistory) { public static void fromXml(@Nullable String xml, @NotNull List<CalculatorHistoryState> historyItems) {
if (xml != null) { if (xml != null) {
final Serializer serializer = new Persister(); final Serializer serializer = new Persister();
try { try {
final History history = serializer.read(History.class, xml); final History history = serializer.read(History.class, xml);
for (CalculatorHistoryState historyItem : history.getHistoryItems()) { for (CalculatorHistoryState historyItem : history.getHistoryItems()) {
calculatorHistory.addState(historyItem); historyItems.add(historyItem);
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -41,9 +41,9 @@ class HistoryUtils {
} }
@NotNull @NotNull
public static String toXml(@NotNull HistoryHelper<CalculatorHistoryState> calculatorHistory) { public static String toXml(@NotNull List<CalculatorHistoryState> historyItems) {
final History history = new History(); final History history = new History();
for (CalculatorHistoryState historyState : calculatorHistory.getStates()) { for (CalculatorHistoryState historyState : historyItems) {
if (historyState.isSaved()) { if (historyState.isSaved()) {
history.getHistoryItems().add(historyState); history.getHistoryItems().add(historyState);
} }

View File

@ -18,7 +18,9 @@ import org.solovyev.common.utils.EqualsTool;
import org.solovyev.common.utils.history.HistoryHelper; import org.solovyev.common.utils.history.HistoryHelper;
import org.solovyev.common.utils.history.SimpleHistoryHelper; import org.solovyev.common.utils.history.SimpleHistoryHelper;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
/** /**
* User: serso * User: serso
@ -136,12 +138,12 @@ public class HistoryUtilsTest {
state.setTime(date); state.setTime(date);
history.addState(state); history.addState(state);
Assert.assertEquals(emptyHistory, HistoryUtils.toXml(history)); Assert.assertEquals(emptyHistory, HistoryUtils.toXml(history.getStates()));
state.setSaved(true); state.setSaved(true);
Assert.assertEquals(toXml1, HistoryUtils.toXml(history)); Assert.assertEquals(toXml1, HistoryUtils.toXml(history.getStates()));
calculatorDisplay = new TestCalculatorDisplay(); calculatorDisplay = new TestCalculatorDisplay();
calculatorDisplay.setErrorMessage(null); calculatorDisplay.setErrorMessage(null);
@ -188,11 +190,15 @@ public class HistoryUtilsTest {
state.setTime(date); state.setTime(date);
history.addState(state); history.addState(state);
String xml = HistoryUtils.toXml(history); String xml = HistoryUtils.toXml(history.getStates());
Assert.assertEquals(toXml2, xml); Assert.assertEquals(toXml2, xml);
final List<CalculatorHistoryState> fromXml = new ArrayList<CalculatorHistoryState>();
final HistoryHelper<CalculatorHistoryState> historyFromXml = new SimpleHistoryHelper<CalculatorHistoryState>(); final HistoryHelper<CalculatorHistoryState> historyFromXml = new SimpleHistoryHelper<CalculatorHistoryState>();
HistoryUtils.fromXml(xml, historyFromXml); HistoryUtils.fromXml(xml, fromXml);
for (CalculatorHistoryState historyState : fromXml) {
historyFromXml.addState(historyState);
}
Assert.assertEquals(history.getStates().size(), historyFromXml.getStates().size()); Assert.assertEquals(history.getStates().size(), historyFromXml.getStates().size());