From 9e237c1a2cb6b28ba37dcae6d969910dbf7d343e Mon Sep 17 00:00:00 2001 From: serso Date: Wed, 10 Oct 2012 16:13:58 +0400 Subject: [PATCH] Changes --- .../calculator/CalculatorEditorImpl.java | 618 +++++++++--------- .../calculator/CalculatorEventHolder.java | 148 +++-- .../calculator/history/CalculatorHistory.java | 73 ++- .../history/CalculatorHistoryImpl.java | 491 +++++++------- .../history/CalculatorHistoryImplTest.java | 53 ++ .../res/values-ru/text_preferences.xml | 21 +- calculatorpp/res/values/text_preferences.xml | 21 +- .../res/xml/appearance_preferences.xml | 99 +++ .../res/xml/calculations_preferences.xml | 56 ++ calculatorpp/res/xml/other_preferences.xml | 29 + calculatorpp/res/xml/preferences.xml | 166 +---- .../calculator/CalculatorPreferences.java | 372 +++++------ .../CalculatorPreferencesActivity.java | 403 ++++++------ .../history/AndroidCalculatorHistory.java | 307 ++++----- .../history/CalculatorHistoryFragment.java | 5 +- 15 files changed, 1500 insertions(+), 1362 deletions(-) create mode 100644 calculatorpp-core/src/test/java/org/solovyev/android/calculator/history/CalculatorHistoryImplTest.java create mode 100644 calculatorpp/res/xml/appearance_preferences.xml create mode 100644 calculatorpp/res/xml/calculations_preferences.xml create mode 100644 calculatorpp/res/xml/other_preferences.xml diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEditorImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEditorImpl.java index 570a119f..4636f8c2 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEditorImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEditorImpl.java @@ -1,309 +1,309 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.history.CalculatorHistoryState; -import org.solovyev.android.calculator.history.EditorHistoryState; -import org.solovyev.common.gui.CursorControl; -import org.solovyev.common.text.StringUtils; - -/** - * User: Solovyev_S - * Date: 21.09.12 - * Time: 11:53 - */ -public class CalculatorEditorImpl implements CalculatorEditor { - - @Nullable - private CalculatorEditorView view; - - @NotNull - private final Object viewLock = new Object(); - - @NotNull - private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance(); - - @NotNull - private final Calculator calculator; - - @NotNull - private final CalculatorEventHolder lastEventHolder; - - @NotNull - private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this); - - public CalculatorEditorImpl(@NotNull Calculator calculator) { - this.calculator = calculator; - this.calculator.addCalculatorEventListener(this); - this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); - } - - @Override - public void setView(@Nullable CalculatorEditorView view) { - synchronized (viewLock) { - this.view = view; - - if ( view != null ) { - view.setState(lastViewState); - } - } - } - - @NotNull - @Override - public CalculatorEditorViewState getViewState() { - return lastViewState; - } - - @Override - public void updateViewState() { - setViewState(this.lastViewState, false); - } - - @Override - public void setViewState(@NotNull CalculatorEditorViewState newViewState) { - setViewState(newViewState, true); - } - - private void setViewState(CalculatorEditorViewState newViewState, boolean fireEvent) { - synchronized (viewLock) { - final CalculatorEditorViewState oldViewState = this.lastViewState; - - this.lastViewState = newViewState; - if (this.view != null) { - this.view.setState(newViewState); - } - - if (fireEvent) { - calculator.fireCalculatorEvent(CalculatorEventType.editor_state_changed, new CalculatorEditorChangeEventDataImpl(oldViewState, newViewState)); - } - } - } - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorEventType calculatorEventType, - @Nullable Object data) { - final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData); - - if (result.isNewAfter()) { - switch (calculatorEventType) { - case use_history_state: - final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState)data; - final EditorHistoryState editorState = calculatorHistoryState.getEditorState(); - this.setText(StringUtils.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition()); - break; - } - } - } - - /* - ********************************************************************** - * - * SELECTION - * - ********************************************************************** - */ - - @NotNull - private CalculatorEditorViewState newSelectionViewState(int newSelection) { - if (this.lastViewState.getSelection() != newSelection) { - final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection); - setViewState(result); - return result; - } else { - return this.lastViewState; - } - } - - @NotNull - public CalculatorEditorViewState setCursorOnStart() { - synchronized (viewLock) { - return newSelectionViewState(0); - } - } - - - @NotNull - public CalculatorEditorViewState setCursorOnEnd() { - synchronized (viewLock) { - return newSelectionViewState(this.lastViewState.getText().length()); - } - } - - @NotNull - public CalculatorEditorViewState moveCursorLeft() { - synchronized (viewLock) { - if (this.lastViewState.getSelection() > 0) { - return newSelectionViewState(this.lastViewState.getSelection() - 1); - } else { - return this.lastViewState; - } - } - } - - @NotNull - public CalculatorEditorViewState moveCursorRight() { - synchronized (viewLock) { - if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) { - return newSelectionViewState(this.lastViewState.getSelection() + 1); - } else { - return this.lastViewState; - } - } - } - - @NotNull - @Override - public CursorControl asCursorControl() { - return cursorControlAdapter; - } - - /* - ********************************************************************** - * - * EDITOR ACTIONS - * - ********************************************************************** - */ - - @NotNull - @Override - public CalculatorEditorViewState erase() { - synchronized (viewLock) { - int selection = this.lastViewState.getSelection(); - final String text = this.lastViewState.getText(); - if (selection > 0 && text.length() > 0 && selection <= text.length()) { - final StringBuilder newText = new StringBuilder(text.length() - 1); - newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length())); - - final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1); - setViewState(result); - return result; - } else { - return this.lastViewState; - } - } - } - - @NotNull - @Override - public CalculatorEditorViewState clear() { - synchronized (viewLock) { - return setText(""); - } - } - - @NotNull - @Override - public CalculatorEditorViewState setText(@NotNull String text) { - synchronized (viewLock) { - final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length()); - setViewState(result); - return result; - } - } - - @NotNull - @Override - public CalculatorEditorViewState setText(@NotNull String text, int selection) { - synchronized (viewLock) { - selection = correctSelection(selection, text); - - final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection); - setViewState(result); - return result; - } - } - - @NotNull - @Override - public CalculatorEditorViewState insert(@NotNull String text) { - synchronized (viewLock) { - return insert(text, 0); - } - } - - @NotNull - @Override - public CalculatorEditorViewState insert(@NotNull String text, int selectionOffset) { - synchronized (viewLock) { - final int selection = this.lastViewState.getSelection(); - final String oldText = this.lastViewState.getText(); - - int newTextLength = text.length() + oldText.length(); - final StringBuilder newText = new StringBuilder(newTextLength); - - newText.append(oldText.substring(0, selection)); - newText.append(text); - newText.append(oldText.substring(selection)); - - int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength); - final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection); - setViewState(result); - return result; - } - } - - @NotNull - @Override - public CalculatorEditorViewState moveSelection(int offset) { - synchronized (viewLock) { - int selection = this.lastViewState.getSelection() + offset; - - return setSelection(selection); - } - } - - @NotNull - @Override - public CalculatorEditorViewState setSelection(int selection) { - synchronized (viewLock) { - selection = correctSelection(selection, this.lastViewState.getText()); - - final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection); - setViewState(result); - return result; - } - } - - private int correctSelection(int selection, @NotNull String text) { - return correctSelection(selection, text.length()); - } - - private int correctSelection(int selection, int textLength) { - int result = Math.max(selection, 0); - result = Math.min(result, textLength); - return result; - } - - private static final class CursorControlAdapter implements CursorControl { - - @NotNull - private final CalculatorEditor calculatorEditor; - - private CursorControlAdapter(@NotNull CalculatorEditor calculatorEditor) { - this.calculatorEditor = calculatorEditor; - } - - @Override - public void setCursorOnStart() { - this.calculatorEditor.setCursorOnStart(); - } - - @Override - public void setCursorOnEnd() { - this.calculatorEditor.setCursorOnEnd(); - } - - @Override - public void moveCursorLeft() { - this.calculatorEditor.moveCursorLeft(); - } - - @Override - public void moveCursorRight() { - this.calculatorEditor.moveCursorRight(); - } - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.history.CalculatorHistoryState; +import org.solovyev.android.calculator.history.EditorHistoryState; +import org.solovyev.common.gui.CursorControl; +import org.solovyev.common.text.StringUtils; + +/** + * User: Solovyev_S + * Date: 21.09.12 + * Time: 11:53 + */ +public class CalculatorEditorImpl implements CalculatorEditor { + + @Nullable + private CalculatorEditorView view; + + @NotNull + private final Object viewLock = new Object(); + + @NotNull + private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance(); + + @NotNull + private final Calculator calculator; + + @NotNull + private final CalculatorEventHolder lastEventHolder; + + @NotNull + private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this); + + public CalculatorEditorImpl(@NotNull Calculator calculator) { + this.calculator = calculator; + this.calculator.addCalculatorEventListener(this); + this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); + } + + @Override + public void setView(@Nullable CalculatorEditorView view) { + synchronized (viewLock) { + this.view = view; + + if ( view != null ) { + view.setState(lastViewState); + } + } + } + + @NotNull + @Override + public CalculatorEditorViewState getViewState() { + return lastViewState; + } + + @Override + public void updateViewState() { + setViewState(this.lastViewState, false); + } + + @Override + public void setViewState(@NotNull CalculatorEditorViewState newViewState) { + setViewState(newViewState, true); + } + + private void setViewState(@NotNull CalculatorEditorViewState newViewState, boolean fireEvent) { + synchronized (viewLock) { + final CalculatorEditorViewState oldViewState = this.lastViewState; + + this.lastViewState = newViewState; + if (this.view != null) { + this.view.setState(newViewState); + } + + if (fireEvent) { + calculator.fireCalculatorEvent(CalculatorEventType.editor_state_changed, new CalculatorEditorChangeEventDataImpl(oldViewState, newViewState)); + } + } + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, + @NotNull CalculatorEventType calculatorEventType, + @Nullable Object data) { + final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData); + + if (result.isNewAfter()) { + switch (calculatorEventType) { + case use_history_state: + final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState)data; + final EditorHistoryState editorState = calculatorHistoryState.getEditorState(); + this.setText(StringUtils.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition()); + break; + } + } + } + + /* + ********************************************************************** + * + * SELECTION + * + ********************************************************************** + */ + + @NotNull + private CalculatorEditorViewState newSelectionViewState(int newSelection) { + if (this.lastViewState.getSelection() != newSelection) { + final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection); + setViewState(result, false); + return result; + } else { + return this.lastViewState; + } + } + + @NotNull + public CalculatorEditorViewState setCursorOnStart() { + synchronized (viewLock) { + return newSelectionViewState(0); + } + } + + + @NotNull + public CalculatorEditorViewState setCursorOnEnd() { + synchronized (viewLock) { + return newSelectionViewState(this.lastViewState.getText().length()); + } + } + + @NotNull + public CalculatorEditorViewState moveCursorLeft() { + synchronized (viewLock) { + if (this.lastViewState.getSelection() > 0) { + return newSelectionViewState(this.lastViewState.getSelection() - 1); + } else { + return this.lastViewState; + } + } + } + + @NotNull + public CalculatorEditorViewState moveCursorRight() { + synchronized (viewLock) { + if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) { + return newSelectionViewState(this.lastViewState.getSelection() + 1); + } else { + return this.lastViewState; + } + } + } + + @NotNull + @Override + public CursorControl asCursorControl() { + return cursorControlAdapter; + } + + /* + ********************************************************************** + * + * EDITOR ACTIONS + * + ********************************************************************** + */ + + @NotNull + @Override + public CalculatorEditorViewState erase() { + synchronized (viewLock) { + int selection = this.lastViewState.getSelection(); + final String text = this.lastViewState.getText(); + if (selection > 0 && text.length() > 0 && selection <= text.length()) { + final StringBuilder newText = new StringBuilder(text.length() - 1); + newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length())); + + final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1); + setViewState(result); + return result; + } else { + return this.lastViewState; + } + } + } + + @NotNull + @Override + public CalculatorEditorViewState clear() { + synchronized (viewLock) { + return setText(""); + } + } + + @NotNull + @Override + public CalculatorEditorViewState setText(@NotNull String text) { + synchronized (viewLock) { + final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length()); + setViewState(result); + return result; + } + } + + @NotNull + @Override + public CalculatorEditorViewState setText(@NotNull String text, int selection) { + synchronized (viewLock) { + selection = correctSelection(selection, text); + + final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection); + setViewState(result); + return result; + } + } + + @NotNull + @Override + public CalculatorEditorViewState insert(@NotNull String text) { + synchronized (viewLock) { + return insert(text, 0); + } + } + + @NotNull + @Override + public CalculatorEditorViewState insert(@NotNull String text, int selectionOffset) { + synchronized (viewLock) { + final int selection = this.lastViewState.getSelection(); + final String oldText = this.lastViewState.getText(); + + int newTextLength = text.length() + oldText.length(); + final StringBuilder newText = new StringBuilder(newTextLength); + + newText.append(oldText.substring(0, selection)); + newText.append(text); + newText.append(oldText.substring(selection)); + + int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength); + final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection); + setViewState(result); + return result; + } + } + + @NotNull + @Override + public CalculatorEditorViewState moveSelection(int offset) { + synchronized (viewLock) { + int selection = this.lastViewState.getSelection() + offset; + + return setSelection(selection); + } + } + + @NotNull + @Override + public CalculatorEditorViewState setSelection(int selection) { + synchronized (viewLock) { + selection = correctSelection(selection, this.lastViewState.getText()); + + final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection); + setViewState(result, false); + return result; + } + } + + private int correctSelection(int selection, @NotNull String text) { + return correctSelection(selection, text.length()); + } + + private int correctSelection(int selection, int textLength) { + int result = Math.max(selection, 0); + result = Math.min(result, textLength); + return result; + } + + private static final class CursorControlAdapter implements CursorControl { + + @NotNull + private final CalculatorEditor calculatorEditor; + + private CursorControlAdapter(@NotNull CalculatorEditor calculatorEditor) { + this.calculatorEditor = calculatorEditor; + } + + @Override + public void setCursorOnStart() { + this.calculatorEditor.setCursorOnStart(); + } + + @Override + public void setCursorOnEnd() { + this.calculatorEditor.setCursorOnEnd(); + } + + @Override + public void moveCursorLeft() { + this.calculatorEditor.moveCursorLeft(); + } + + @Override + public void moveCursorRight() { + this.calculatorEditor.moveCursorRight(); + } + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventHolder.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventHolder.java index 59c7cca6..6af64344 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventHolder.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventHolder.java @@ -1,70 +1,78 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: serso - * Date: 10/9/12 - * Time: 9:59 PM - */ -public class CalculatorEventHolder { - - @NotNull - private volatile CalculatorEventData lastEventData; - - public CalculatorEventHolder(@NotNull CalculatorEventData lastEventData) { - this.lastEventData = lastEventData; - } - - @NotNull - public synchronized CalculatorEventData getLastEventData() { - return lastEventData; - } - - @NotNull - public synchronized Result apply(@NotNull CalculatorEventData newEventData) { - final Result result = new Result(lastEventData, newEventData); - - if (result.isNewAfter()) { - this.lastEventData = newEventData; - } - - return result; - } - - public static class Result { - - @NotNull - private final CalculatorEventData lastEventData; - - @NotNull - private final CalculatorEventData newEventData; - - @Nullable - private Boolean after = null; - - @Nullable - private Boolean sameSequence = null; - - public Result(@NotNull CalculatorEventData lastEventData, - @NotNull CalculatorEventData newEventData) { - this.lastEventData = lastEventData; - this.newEventData = newEventData; - } - - public boolean isNewAfter() { - if (after == null) { - after = newEventData.isAfter(lastEventData); - } - return after; - } - - public boolean isSameSequence() { - if (sameSequence == null) { - sameSequence = newEventData.isSameSequence(lastEventData); - } - return sameSequence; - } - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: serso + * Date: 10/9/12 + * Time: 9:59 PM + */ +public class CalculatorEventHolder { + + @NotNull + private volatile CalculatorEventData lastEventData; + + public CalculatorEventHolder(@NotNull CalculatorEventData lastEventData) { + this.lastEventData = lastEventData; + } + + @NotNull + public synchronized CalculatorEventData getLastEventData() { + return lastEventData; + } + + @NotNull + public synchronized Result apply(@NotNull CalculatorEventData newEventData) { + final Result result = new Result(lastEventData, newEventData); + + if (result.isNewAfter()) { + this.lastEventData = newEventData; + } + + return result; + } + + public static class Result { + + @NotNull + private final CalculatorEventData lastEventData; + + @NotNull + private final CalculatorEventData newEventData; + + @Nullable + private Boolean after = null; + + @Nullable + private Boolean sameSequence = null; + + public Result(@NotNull CalculatorEventData lastEventData, + @NotNull CalculatorEventData newEventData) { + this.lastEventData = lastEventData; + this.newEventData = newEventData; + } + + public boolean isNewAfter() { + if (after == null) { + after = newEventData.isAfter(lastEventData); + } + return after; + } + + public boolean isSameSequence() { + if (sameSequence == null) { + sameSequence = newEventData.isSameSequence(lastEventData); + } + return sameSequence; + } + + public boolean isNewAfterSequence() { + return newEventData.isAfterSequence(lastEventData); + } + + public boolean isNewSameOrAfterSequence() { + return isSameSequence() || isNewAfterSequence(); + } + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java index 9d99943e..5fe2a9ab 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistory.java @@ -1,33 +1,40 @@ -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorEventListener; -import org.solovyev.common.history.HistoryHelper; - -import java.util.List; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:11 - */ -public interface CalculatorHistory extends HistoryHelper, CalculatorEventListener { - - void load(); - - void save(); - - void fromXml(@NotNull String xml); - - String toXml(); - - void clearSavedHistory(); - - void removeSavedHistory(@NotNull CalculatorHistoryState historyState); - - @NotNull - List getSavedHistory(); - - @NotNull - CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState); -} +package org.solovyev.android.calculator.history; + +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.CalculatorEventListener; +import org.solovyev.common.history.HistoryHelper; + +import java.util.List; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:11 + */ +public interface CalculatorHistory extends HistoryHelper, CalculatorEventListener { + + void load(); + + void save(); + + void fromXml(@NotNull String xml); + + String toXml(); + + void clearSavedHistory(); + + void removeSavedHistory(@NotNull CalculatorHistoryState historyState); + + @NotNull + List getSavedHistory(); + + @NotNull + CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState); + + @NotNull + List getStates(); + + @NotNull + List getStates(boolean includeIntermediateStates); + +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java index ebca6c62..0f0b9ac8 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryImpl.java @@ -1,234 +1,257 @@ -package org.solovyev.android.calculator.history; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; -import org.solovyev.common.history.HistoryAction; -import org.solovyev.common.history.HistoryHelper; -import org.solovyev.common.history.SimpleHistoryHelper; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed; -import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed; -import static org.solovyev.android.calculator.CalculatorEventType.manual_calculation_requested; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 16:12 - */ -public class CalculatorHistoryImpl implements CalculatorHistory { - - private final AtomicInteger counter = new AtomicInteger(0); - - @NotNull - private final HistoryHelper history = new SimpleHistoryHelper(); - - @NotNull - private final List savedHistory = new ArrayList(); - - @NotNull - private volatile CalculatorEventData lastEventData = CalculatorUtils.createFirstEventDataId(); - - @NotNull - private final Object lastEventDataLock = new Object(); - - @Nullable - private volatile CalculatorEditorViewState lastEditorViewState; - - public CalculatorHistoryImpl(@NotNull Calculator calculator) { - calculator.addCalculatorEventListener(this); - } - - @Override - public boolean isEmpty() { - synchronized (history) { - return this.history.isEmpty(); - } - } - - @Override - public CalculatorHistoryState getLastHistoryState() { - synchronized (history) { - return this.history.getLastHistoryState(); - } - } - - @Override - public boolean isUndoAvailable() { - synchronized (history) { - return history.isUndoAvailable(); - } - } - - @Override - public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { - synchronized (history) { - return history.undo(currentState); - } - } - - @Override - public boolean isRedoAvailable() { - return history.isRedoAvailable(); - } - - @Override - public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { - synchronized (history) { - return history.redo(currentState); - } - } - - @Override - public boolean isActionAvailable(@NotNull HistoryAction historyAction) { - synchronized (history) { - return history.isActionAvailable(historyAction); - } - } - - @Override - public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { - synchronized (history) { - return history.doAction(historyAction, currentState); - } - } - - @Override - public void addState(@Nullable CalculatorHistoryState currentState) { - synchronized (history) { - history.addState(currentState); - CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState); - } - } - - @NotNull - @Override - public List getStates() { - synchronized (history) { - return history.getStates(); - } - } - - @Override - public void clear() { - synchronized (history) { - this.history.clear(); - } - } - - @Override - @NotNull - public List getSavedHistory() { - return Collections.unmodifiableList(savedHistory); - } - - @Override - @NotNull - public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { - if (historyState.isSaved()) { - return historyState; - } else { - final CalculatorHistoryState savedState = historyState.clone(); - - savedState.setId(counter.incrementAndGet()); - savedState.setSaved(true); - - savedHistory.add(savedState); - - return savedState; - } - } - - @Override - public void load() { - // todo serso: create saved/loader class - } - - @Override - public void save() { - // todo serso: create saved/loader class - } - - @Override - public void fromXml(@NotNull String xml) { - clearSavedHistory(); - - HistoryUtils.fromXml(xml, this.savedHistory); - for (CalculatorHistoryState historyState : savedHistory) { - historyState.setSaved(true); - historyState.setId(counter.incrementAndGet()); - } - } - - @Override - public String toXml() { - return HistoryUtils.toXml(this.savedHistory); - } - - @Override - public void clearSavedHistory() { - this.savedHistory.clear(); - } - - @Override - public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { - this.savedHistory.remove(historyState); - } - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorEventType calculatorEventType, - @Nullable Object data) { - if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) { - - boolean sameSequence = false; - boolean afterSequence = false; - - boolean processEvent = false; - - synchronized (this.lastEventDataLock) { - if (calculatorEventData.isAfter(this.lastEventData)) { - - sameSequence = calculatorEventData.isSameSequence(this.lastEventData); - if (!sameSequence) { - afterSequence = calculatorEventData.isAfterSequence(this.lastEventData); - processEvent = afterSequence; - } else { - processEvent = true; - } - } - } - - if (processEvent) { - this.lastEventData = calculatorEventData; - - switch (calculatorEventType) { - case manual_calculation_requested: - lastEditorViewState = (CalculatorEditorViewState) data; - break; - case editor_state_changed: - final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data; - lastEditorViewState = editorChangeData.getNewValue(); - break; - case display_state_changed: - if (sameSequence) { - if (lastEditorViewState != null) { - final CalculatorEditorViewState editorViewState = lastEditorViewState; - final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; - final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue(); - addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); - } - } else { - lastEditorViewState = null; - } - break; - } - } - } - } -} +package org.solovyev.android.calculator.history; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.*; +import org.solovyev.common.collections.CollectionsUtils; +import org.solovyev.common.history.HistoryAction; +import org.solovyev.common.history.HistoryHelper; +import org.solovyev.common.history.SimpleHistoryHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.solovyev.android.calculator.CalculatorEventType.*; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 16:12 + */ +public class CalculatorHistoryImpl implements CalculatorHistory { + + private final AtomicInteger counter = new AtomicInteger(0); + + @NotNull + private final HistoryHelper history = new SimpleHistoryHelper(); + + @NotNull + private final List savedHistory = new ArrayList(); + + @NotNull + private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); + + @Nullable + private volatile CalculatorEditorViewState lastEditorViewState; + + public CalculatorHistoryImpl(@NotNull Calculator calculator) { + calculator.addCalculatorEventListener(this); + } + + @Override + public boolean isEmpty() { + synchronized (history) { + return this.history.isEmpty(); + } + } + + @Override + public CalculatorHistoryState getLastHistoryState() { + synchronized (history) { + return this.history.getLastHistoryState(); + } + } + + @Override + public boolean isUndoAvailable() { + synchronized (history) { + return history.isUndoAvailable(); + } + } + + @Override + public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { + synchronized (history) { + return history.undo(currentState); + } + } + + @Override + public boolean isRedoAvailable() { + return history.isRedoAvailable(); + } + + @Override + public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { + synchronized (history) { + return history.redo(currentState); + } + } + + @Override + public boolean isActionAvailable(@NotNull HistoryAction historyAction) { + synchronized (history) { + return history.isActionAvailable(historyAction); + } + } + + @Override + public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { + synchronized (history) { + return history.doAction(historyAction, currentState); + } + } + + @Override + public void addState(@Nullable CalculatorHistoryState currentState) { + synchronized (history) { + history.addState(currentState); + CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState); + } + } + + @NotNull + @Override + public List getStates() { + synchronized (history) { + return history.getStates(); + } + } + + @NotNull + @Override + public List getStates(boolean includeIntermediateStates) { + if (includeIntermediateStates) { + return getStates(); + } else { + final List states = getStates(); + + final List result = new LinkedList(); + + CalculatorHistoryState laterState = null; + for (CalculatorHistoryState state : CollectionsUtils.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; + } + } + + private boolean isIntermediate(@NotNull String laterEditorText, + @NotNull String editorText) { + if ( Math.abs(laterEditorText.length() - editorText.length()) <= 1 ) { + if ( laterEditorText.length() > editorText.length() ) { + return laterEditorText.startsWith(editorText); + } else { + return editorText.startsWith(laterEditorText); + } + } + + return false; + } + + @Override + public void clear() { + synchronized (history) { + this.history.clear(); + } + } + + @Override + @NotNull + public List getSavedHistory() { + return Collections.unmodifiableList(savedHistory); + } + + @Override + @NotNull + public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { + if (historyState.isSaved()) { + return historyState; + } else { + final CalculatorHistoryState savedState = historyState.clone(); + + savedState.setId(counter.incrementAndGet()); + savedState.setSaved(true); + + savedHistory.add(savedState); + + return savedState; + } + } + + @Override + public void load() { + // todo serso: create saved/loader class + } + + @Override + public void save() { + // todo serso: create saved/loader class + } + + @Override + public void fromXml(@NotNull String xml) { + clearSavedHistory(); + + HistoryUtils.fromXml(xml, this.savedHistory); + for (CalculatorHistoryState historyState : savedHistory) { + historyState.setSaved(true); + historyState.setId(counter.incrementAndGet()); + } + } + + @Override + public String toXml() { + return HistoryUtils.toXml(this.savedHistory); + } + + @Override + public void clearSavedHistory() { + this.savedHistory.clear(); + } + + @Override + public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { + this.savedHistory.remove(historyState); + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, + @NotNull CalculatorEventType calculatorEventType, + @Nullable Object data) { + if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) { + + final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData); + + if (result.isNewAfter() && result.isNewSameOrAfterSequence() ) { + switch (calculatorEventType) { + case manual_calculation_requested: + lastEditorViewState = (CalculatorEditorViewState) data; + break; + case editor_state_changed: + final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data; + lastEditorViewState = editorChangeData.getNewValue(); + break; + case display_state_changed: + if (result.isSameSequence()) { + if (lastEditorViewState != null) { + final CalculatorEditorViewState editorViewState = lastEditorViewState; + final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; + final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue(); + addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); + } + } else { + lastEditorViewState = null; + } + break; + } + } + } + } +} diff --git a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/history/CalculatorHistoryImplTest.java b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/history/CalculatorHistoryImplTest.java new file mode 100644 index 00000000..d056c51d --- /dev/null +++ b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/history/CalculatorHistoryImplTest.java @@ -0,0 +1,53 @@ +package org.solovyev.android.calculator.history; + +import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; +import org.junit.BeforeClass; +import org.junit.Test; +import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl; +import org.solovyev.android.calculator.CalculatorEditorViewStateImpl; +import org.solovyev.android.calculator.CalculatorLocatorImpl; +import org.solovyev.android.calculator.CalculatorTestUtils; + +import java.util.List; + +/** + * User: Solovyev_S + * Date: 10.10.12 + * Time: 15:07 + */ +public class CalculatorHistoryImplTest { + + @BeforeClass + public static void setUp() throws Exception { + CalculatorTestUtils.staticSetUp(); + } + + @Test + public void testGetStates() throws Exception { + CalculatorHistory calculatorHistory = new CalculatorHistoryImpl(CalculatorLocatorImpl.getInstance().getCalculator()); + + addState(calculatorHistory, "1"); + addState(calculatorHistory, "12"); + addState(calculatorHistory, "123"); + addState(calculatorHistory, "123+"); + addState(calculatorHistory, "123+3"); + addState(calculatorHistory, ""); + addState(calculatorHistory, "2"); + addState(calculatorHistory, "23"); + addState(calculatorHistory, "235"); + addState(calculatorHistory, "2355"); + addState(calculatorHistory, "235"); + addState(calculatorHistory, "2354"); + addState(calculatorHistory, "23547"); + + final List states = calculatorHistory.getStates(false); + Assert.assertEquals(2, states.size()); + Assert.assertEquals("23547", states.get(1).getEditorState().getText()); + Assert.assertEquals("123+3", states.get(0).getEditorState().getText()); + } + + private void addState(@NotNull CalculatorHistory calculatorHistory, @NotNull String text) { + calculatorHistory.addState(CalculatorHistoryState.newInstance(CalculatorEditorViewStateImpl.newInstance(text, 3), CalculatorDisplayViewStateImpl.newDefaultInstance())); + } +} diff --git a/calculatorpp/res/values-ru/text_preferences.xml b/calculatorpp/res/values-ru/text_preferences.xml index d45767c6..d9e529e3 100644 --- a/calculatorpp/res/values-ru/text_preferences.xml +++ b/calculatorpp/res/values-ru/text_preferences.xml @@ -1,10 +1,13 @@ - - Переключатель автоматического поворота экрана - Если включено, то калькулятор будет автоматически менять ориентацию экрана - - Показывать клавишу равно - Если включено, то клавиша равно будет показана - - Не показывать цифры из других систем счисления - Если включено, то цифры из других систем счисления не будут показаны + + Переключатель автоматического поворота экрана + Если включено, то калькулятор будет автоматически менять ориентацию экрана + + Показывать клавишу равно + Если включено, то клавиша равно будет показана + + Не показывать цифры из других систем счисления + Если включено, то цифры из других систем счисления не будут показаны + + Показывать промежуточные вычисления на экране истории + Если включено, то все вычисления будут показаны на экране истории \ No newline at end of file diff --git a/calculatorpp/res/values/text_preferences.xml b/calculatorpp/res/values/text_preferences.xml index 1c38fd3a..b9f6f3f9 100644 --- a/calculatorpp/res/values/text_preferences.xml +++ b/calculatorpp/res/values/text_preferences.xml @@ -1,10 +1,13 @@ - - Toggle screen orientation change - If turned on calculator will change screen orientation automatically - - Show equals button - If turned on equals button is shown - - Hide numeral base digits - If turned on numeral base digits of other numeral bases will be hidden + + Toggle screen orientation change + If turned on calculator will change screen orientation automatically + + Show equals button + If turned on equals button is shown + + Hide numeral base digits + If turned on numeral base digits of other numeral bases will be hidden + + Show intermediate calculations in history + If turned on all calculations will be shown on history screen \ No newline at end of file diff --git a/calculatorpp/res/xml/appearance_preferences.xml b/calculatorpp/res/xml/appearance_preferences.xml new file mode 100644 index 00000000..7bfb81d7 --- /dev/null +++ b/calculatorpp/res/xml/appearance_preferences.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/calculatorpp/res/xml/calculations_preferences.xml b/calculatorpp/res/xml/calculations_preferences.xml new file mode 100644 index 00000000..6d5feb3e --- /dev/null +++ b/calculatorpp/res/xml/calculations_preferences.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/calculatorpp/res/xml/other_preferences.xml b/calculatorpp/res/xml/other_preferences.xml new file mode 100644 index 00000000..4ff5a4b0 --- /dev/null +++ b/calculatorpp/res/xml/other_preferences.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/calculatorpp/res/xml/preferences.xml b/calculatorpp/res/xml/preferences.xml index 66141e9e..069bbf87 100644 --- a/calculatorpp/res/xml/preferences.xml +++ b/calculatorpp/res/xml/preferences.xml @@ -1,7 +1,6 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java index 644d82f0..e3f5c4cc 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferences.java @@ -1,183 +1,189 @@ -package org.solovyev.android.calculator; - -import android.content.SharedPreferences; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.AndroidUtils; -import org.solovyev.android.calculator.math.MathType; -import org.solovyev.android.calculator.model.AndroidCalculatorEngine; -import org.solovyev.android.calculator.plot.GraphLineColor; -import org.solovyev.android.prefs.BooleanPreference; -import org.solovyev.android.prefs.IntegerPreference; -import org.solovyev.android.prefs.Preference; -import org.solovyev.android.prefs.StringPreference; -import org.solovyev.android.view.VibratorContainer; - -import java.text.DecimalFormatSymbols; -import java.util.Locale; - -/** - * User: serso - * Date: 4/20/12 - * Time: 12:42 PM - */ -public final class CalculatorPreferences { - - private CalculatorPreferences() { - throw new AssertionError(); - } - - public static final Preference appVersion = new IntegerPreference("application.version", -1); - public static final Preference appOpenedCounter = new IntegerPreference("app_opened_counter", 0); - - public static class Gui { - - public static final Preference theme = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_theme", Theme.metro_blue_theme, Theme.class); - public static final Preference layout = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_layout", Layout.main_calculator, Layout.class); - public static final Preference feedbackWindowShown = new BooleanPreference("feedback_window_shown", false); - public static final Preference notesppAnnounceShown = new BooleanPreference("notespp_announce_shown", false); - public static final Preference showReleaseNotes = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_show_release_notes", true); - public static final Preference usePrevAsBack = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev", false); - public static final Preference showEqualsButton = new BooleanPreference("showEqualsButton", true); - public static final Preference autoOrientation = new BooleanPreference("autoOrientation", true); - public static final Preference hideNumeralBaseDigits = new BooleanPreference("hideNumeralBaseDigits", true); - - @NotNull - public static Theme getTheme(@NotNull SharedPreferences preferences) { - return theme.getPreferenceNoError(preferences); - } - - @NotNull - public static Layout getLayout(@NotNull SharedPreferences preferences) { - return layout.getPreferenceNoError(preferences); - } - - public static enum Theme { - - default_theme(ThemeType.other, R.style.default_theme), - violet_theme(ThemeType.other, R.style.violet_theme), - light_blue_theme(ThemeType.other, R.style.light_blue_theme), - metro_blue_theme(ThemeType.metro, R.style.metro_blue_theme), - metro_purple_theme(ThemeType.metro, R.style.metro_purple_theme), - metro_green_theme(ThemeType.metro, R.style.metro_green_theme); - - @NotNull - private final ThemeType themeType; - - @NotNull - private final Integer themeId; - - Theme(@NotNull ThemeType themeType, Integer themeId) { - this.themeType = themeType; - this.themeId = themeId; - } - - @NotNull - public ThemeType getThemeType() { - return themeType; - } - - @NotNull - public Integer getThemeId() { - return themeId; - } - } - - public static enum ThemeType { - metro, - other - } - - public static enum Layout { - main_calculator(R.layout.main_calculator), - - // not used anymore - @Deprecated - main_cellphone(R.layout.main_calculator), - - simple(R.layout.main_calculator); - - private final int layoutId; - - Layout(int layoutId) { - this.layoutId = layoutId; - } - - public int getLayoutId() { - return layoutId; - } - } - } - - public static class Graph { - public static final Preference interpolate = new BooleanPreference("graph_interpolate", true); - public static final Preference lineColorReal = StringPreference.newInstance("graph_line_color_real", GraphLineColor.white, GraphLineColor.class); - public static final Preference lineColorImag = StringPreference.newInstance("graph_line_color_imag", GraphLineColor.blue, GraphLineColor.class); - } - - - static void setDefaultValues(@NotNull SharedPreferences preferences) { - if (!AndroidCalculatorEngine.Preferences.groupingSeparator.isSet(preferences)) { - final Locale locale = Locale.getDefault(); - if (locale != null) { - final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale); - int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator())); - final String groupingSeparator; - if (index >= 0) { - groupingSeparator = MathType.grouping_separator.getTokens().get(index); - } else { - groupingSeparator = " "; - } - - AndroidCalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator); - } - } - - if (!AndroidCalculatorEngine.Preferences.angleUnit.isSet(preferences)) { - AndroidCalculatorEngine.Preferences.angleUnit.putDefault(preferences); - } - - if (!AndroidCalculatorEngine.Preferences.numeralBase.isSet(preferences)) { - AndroidCalculatorEngine.Preferences.numeralBase.putDefault(preferences); - } - - if (!AndroidCalculatorEngine.Preferences.multiplicationSign.isSet(preferences)) { - if ( AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2) ) { - // workaround ofr samsung galaxy s phones - AndroidCalculatorEngine.Preferences.multiplicationSign.putPreference(preferences, "*"); - } - } - - applyDefaultPreference(preferences, Gui.theme); - applyDefaultPreference(preferences, Gui.layout); - if ( Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone ) { - Gui.layout.putDefault(preferences); - } - applyDefaultPreference(preferences, Gui.feedbackWindowShown); - applyDefaultPreference(preferences, Gui.notesppAnnounceShown); - applyDefaultPreference(preferences, Gui.showReleaseNotes); - applyDefaultPreference(preferences, Gui.usePrevAsBack); - applyDefaultPreference(preferences, Gui.showEqualsButton); - applyDefaultPreference(preferences, Gui.autoOrientation); - applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits); - - applyDefaultPreference(preferences, Graph.interpolate); - applyDefaultPreference(preferences, Graph.lineColorImag); - applyDefaultPreference(preferences, Graph.lineColorReal); - - if ( !VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences) ) { - VibratorContainer.Preferences.hapticFeedbackEnabled.putPreference(preferences, true); - } - - if ( !VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences) ) { - VibratorContainer.Preferences.hapticFeedbackDuration.putPreference(preferences, 60L); - } - - } - - private static void applyDefaultPreference(@NotNull SharedPreferences preferences, @NotNull Preference preference) { - if (!preference.isSet(preferences)) { - preference.putDefault(preferences); - } - } - -} +package org.solovyev.android.calculator; + +import android.content.SharedPreferences; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.AndroidUtils; +import org.solovyev.android.calculator.math.MathType; +import org.solovyev.android.calculator.model.AndroidCalculatorEngine; +import org.solovyev.android.calculator.plot.GraphLineColor; +import org.solovyev.android.prefs.BooleanPreference; +import org.solovyev.android.prefs.IntegerPreference; +import org.solovyev.android.prefs.Preference; +import org.solovyev.android.prefs.StringPreference; +import org.solovyev.android.view.VibratorContainer; + +import java.text.DecimalFormatSymbols; +import java.util.Locale; + +/** + * User: serso + * Date: 4/20/12 + * Time: 12:42 PM + */ +public final class CalculatorPreferences { + + private CalculatorPreferences() { + throw new AssertionError(); + } + + public static final Preference appVersion = new IntegerPreference("application.version", -1); + public static final Preference appOpenedCounter = new IntegerPreference("app_opened_counter", 0); + + public static class Gui { + + public static final Preference theme = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_theme", Theme.metro_blue_theme, Theme.class); + public static final Preference layout = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_layout", Layout.main_calculator, Layout.class); + public static final Preference feedbackWindowShown = new BooleanPreference("feedback_window_shown", false); + public static final Preference notesppAnnounceShown = new BooleanPreference("notespp_announce_shown", false); + public static final Preference showReleaseNotes = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_show_release_notes", true); + public static final Preference usePrevAsBack = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev", false); + public static final Preference showEqualsButton = new BooleanPreference("showEqualsButton", true); + public static final Preference autoOrientation = new BooleanPreference("autoOrientation", true); + public static final Preference hideNumeralBaseDigits = new BooleanPreference("hideNumeralBaseDigits", true); + + @NotNull + public static Theme getTheme(@NotNull SharedPreferences preferences) { + return theme.getPreferenceNoError(preferences); + } + + @NotNull + public static Layout getLayout(@NotNull SharedPreferences preferences) { + return layout.getPreferenceNoError(preferences); + } + + public static enum Theme { + + default_theme(ThemeType.other, R.style.default_theme), + violet_theme(ThemeType.other, R.style.violet_theme), + light_blue_theme(ThemeType.other, R.style.light_blue_theme), + metro_blue_theme(ThemeType.metro, R.style.metro_blue_theme), + metro_purple_theme(ThemeType.metro, R.style.metro_purple_theme), + metro_green_theme(ThemeType.metro, R.style.metro_green_theme); + + @NotNull + private final ThemeType themeType; + + @NotNull + private final Integer themeId; + + Theme(@NotNull ThemeType themeType, Integer themeId) { + this.themeType = themeType; + this.themeId = themeId; + } + + @NotNull + public ThemeType getThemeType() { + return themeType; + } + + @NotNull + public Integer getThemeId() { + return themeId; + } + } + + public static enum ThemeType { + metro, + other + } + + public static enum Layout { + main_calculator(R.layout.main_calculator), + + // not used anymore + @Deprecated + main_cellphone(R.layout.main_calculator), + + simple(R.layout.main_calculator); + + private final int layoutId; + + Layout(int layoutId) { + this.layoutId = layoutId; + } + + public int getLayoutId() { + return layoutId; + } + } + } + + public static class Graph { + public static final Preference interpolate = new BooleanPreference("graph_interpolate", true); + public static final Preference lineColorReal = StringPreference.newInstance("graph_line_color_real", GraphLineColor.white, GraphLineColor.class); + public static final Preference lineColorImag = StringPreference.newInstance("graph_line_color_imag", GraphLineColor.blue, GraphLineColor.class); + } + + public static class History { + public static final Preference showIntermediateCalculations = new BooleanPreference("history_show_intermediate_calculations", false); + } + + + + static void setDefaultValues(@NotNull SharedPreferences preferences) { + if (!AndroidCalculatorEngine.Preferences.groupingSeparator.isSet(preferences)) { + final Locale locale = Locale.getDefault(); + if (locale != null) { + final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale); + int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator())); + final String groupingSeparator; + if (index >= 0) { + groupingSeparator = MathType.grouping_separator.getTokens().get(index); + } else { + groupingSeparator = " "; + } + + AndroidCalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator); + } + } + + if (!AndroidCalculatorEngine.Preferences.angleUnit.isSet(preferences)) { + AndroidCalculatorEngine.Preferences.angleUnit.putDefault(preferences); + } + + if (!AndroidCalculatorEngine.Preferences.numeralBase.isSet(preferences)) { + AndroidCalculatorEngine.Preferences.numeralBase.putDefault(preferences); + } + + if (!AndroidCalculatorEngine.Preferences.multiplicationSign.isSet(preferences)) { + if ( AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2) ) { + // workaround ofr samsung galaxy s phones + AndroidCalculatorEngine.Preferences.multiplicationSign.putPreference(preferences, "*"); + } + } + + applyDefaultPreference(preferences, Gui.theme); + applyDefaultPreference(preferences, Gui.layout); + if ( Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone ) { + Gui.layout.putDefault(preferences); + } + applyDefaultPreference(preferences, Gui.feedbackWindowShown); + applyDefaultPreference(preferences, Gui.notesppAnnounceShown); + applyDefaultPreference(preferences, Gui.showReleaseNotes); + applyDefaultPreference(preferences, Gui.usePrevAsBack); + applyDefaultPreference(preferences, Gui.showEqualsButton); + applyDefaultPreference(preferences, Gui.autoOrientation); + applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits); + + applyDefaultPreference(preferences, Graph.interpolate); + applyDefaultPreference(preferences, Graph.lineColorImag); + applyDefaultPreference(preferences, Graph.lineColorReal); + applyDefaultPreference(preferences, History.showIntermediateCalculations); + + if ( !VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences) ) { + VibratorContainer.Preferences.hapticFeedbackEnabled.putPreference(preferences, true); + } + + if ( !VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences) ) { + VibratorContainer.Preferences.hapticFeedbackDuration.putPreference(preferences, 60L); + } + + } + + private static void applyDefaultPreference(@NotNull SharedPreferences preferences, @NotNull Preference preference) { + if (!preference.isSet(preferences)) { + preference.putDefault(preferences); + } + } + +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferencesActivity.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferencesActivity.java index 8b454cef..53481434 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferencesActivity.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorPreferencesActivity.java @@ -1,200 +1,203 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -package org.solovyev.android.calculator; - -import android.app.AlertDialog; -import android.app.PendingIntent; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.Preference; -import android.preference.PreferenceManager; -import android.util.Log; -import android.widget.Toast; -import com.actionbarsherlock.app.SherlockPreferenceActivity; -import net.robotmedia.billing.BillingController; -import net.robotmedia.billing.IBillingObserver; -import net.robotmedia.billing.ResponseCode; -import net.robotmedia.billing.helper.AbstractBillingObserver; -import net.robotmedia.billing.model.Transaction; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.AndroidUtils; -import org.solovyev.android.ads.AdsController; -import org.solovyev.android.calculator.model.AndroidCalculatorEngine; -import org.solovyev.android.view.VibratorContainer; - -/** - * User: serso - * Date: 7/16/11 - * Time: 6:37 PM - */ -public class CalculatorPreferencesActivity extends SherlockPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver { - - public static final String CLEAR_BILLING_INFO = "clear_billing_info"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - //noinspection deprecation - addPreferencesFromResource(R.xml.preferences); - //noinspection deprecation - addPreferencesFromResource(R.xml.plot_preferences); - - final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); - adFreePreference.setEnabled(false); - - // observer must be set before net.robotmedia.billing.BillingController.checkBillingSupported() - BillingController.registerObserver(this); - - BillingController.checkBillingSupported(CalculatorPreferencesActivity.this); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - preferences.registerOnSharedPreferenceChangeListener(this); - onSharedPreferenceChanged(preferences, AndroidCalculatorEngine.Preferences.roundResult.getKey()); - onSharedPreferenceChanged(preferences, VibratorContainer.Preferences.hapticFeedbackEnabled.getKey()); - - final Preference clearBillingInfoPreference = findPreference(CLEAR_BILLING_INFO); - if (clearBillingInfoPreference != null) { - clearBillingInfoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - - Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_clearing, Toast.LENGTH_SHORT).show(); - - removeBillingInformation(CalculatorPreferencesActivity.this, PreferenceManager.getDefaultSharedPreferences(CalculatorPreferencesActivity.this)); - - return true; - } - }); - } - } - - public static void removeBillingInformation(@NotNull Context context, @NotNull SharedPreferences preferences) { - final SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean(AbstractBillingObserver.KEY_TRANSACTIONS_RESTORED, false); - editor.commit(); - - BillingController.dropBillingData(context); - } - - private void setAdFreeAction() { - final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); - - if (!AdsController.getInstance().isAdFree(this)) { - Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - enable preference!"); - - adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - public boolean onPreferenceClick(Preference preference) { - - // check billing availability - if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) { - Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!"); - // warn about not supported billing - new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show(); - } else { - Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!"); - if (!AdsController.getInstance().isAdFree(CalculatorPreferencesActivity.this)) { - Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!"); - - // not purchased => purchasing - Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_purchasing, Toast.LENGTH_SHORT).show(); - - // show purchase window for user - BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true); - } else { - // disable preference - adFreePreference.setEnabled(false); - // and show message to user - Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_already_purchased, Toast.LENGTH_SHORT).show(); - } - } - - return true; - } - }); - adFreePreference.setEnabled(true); - } else { - Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - disable preference!"); - adFreePreference.setEnabled(false); - } - } - - @Override - protected void onDestroy() { - BillingController.unregisterObserver(this); - PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); - super.onDestroy(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (AndroidCalculatorEngine.Preferences.roundResult.getKey().equals(key)) { - findPreference(AndroidCalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, AndroidCalculatorEngine.Preferences.roundResult.getDefaultValue())); - } else if (VibratorContainer.Preferences.hapticFeedbackEnabled.getKey().equals(key)) { - findPreference(VibratorContainer.Preferences.hapticFeedbackDuration.getKey()).setEnabled(VibratorContainer.Preferences.hapticFeedbackEnabled.getPreference(preferences)); - } - } - - @Override - public void onCheckBillingSupportedResponse(boolean supported) { - if (supported) { - setAdFreeAction(); - } else { - final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); - adFreePreference.setEnabled(false); - Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported!"); - } - } - - @Override - public void onPurchaseIntentOK(@NotNull String productId, @NotNull PendingIntent purchaseIntent) { - // do nothing - } - - @Override - public void onPurchaseIntentFailure(@NotNull String productId, @NotNull ResponseCode responseCode) { - // do nothing - } - - @Override - public void onPurchaseStateChanged(@NotNull String itemId, @NotNull Transaction.PurchaseState state) { - if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) { - final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); - if (adFreePreference != null) { - switch (state) { - case PURCHASED: - adFreePreference.setEnabled(false); - // restart activity to disable ads - AndroidUtils.restartActivity(this); - break; - case CANCELLED: - adFreePreference.setEnabled(true); - break; - case REFUNDED: - adFreePreference.setEnabled(true); - break; - } - } else { - } - } - } - - @Override - public void onRequestPurchaseResponse(@NotNull String itemId, @NotNull ResponseCode response) { - // do nothing - } - - @Override - public void onTransactionsRestored() { - // do nothing - } - - @Override - public void onErrorRestoreTransactions(@NotNull ResponseCode responseCode) { - // do nothing - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +package org.solovyev.android.calculator; + +import android.app.AlertDialog; +import android.app.PendingIntent; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceManager; +import android.util.Log; +import android.widget.Toast; +import com.actionbarsherlock.app.SherlockPreferenceActivity; +import net.robotmedia.billing.BillingController; +import net.robotmedia.billing.IBillingObserver; +import net.robotmedia.billing.ResponseCode; +import net.robotmedia.billing.helper.AbstractBillingObserver; +import net.robotmedia.billing.model.Transaction; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.AndroidUtils; +import org.solovyev.android.ads.AdsController; +import org.solovyev.android.calculator.model.AndroidCalculatorEngine; +import org.solovyev.android.view.VibratorContainer; + +/** + * User: serso + * Date: 7/16/11 + * Time: 6:37 PM + */ +public class CalculatorPreferencesActivity extends SherlockPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver { + + public static final String CLEAR_BILLING_INFO = "clear_billing_info"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //noinspection deprecation + addPreferencesFromResource(R.xml.preferences); + //noinspection deprecation + addPreferencesFromResource(R.xml.calculations_preferences); + addPreferencesFromResource(R.xml.appearance_preferences); + addPreferencesFromResource(R.xml.plot_preferences); + addPreferencesFromResource(R.xml.other_preferences); + + final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); + adFreePreference.setEnabled(false); + + // observer must be set before net.robotmedia.billing.BillingController.checkBillingSupported() + BillingController.registerObserver(this); + + BillingController.checkBillingSupported(CalculatorPreferencesActivity.this); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + preferences.registerOnSharedPreferenceChangeListener(this); + onSharedPreferenceChanged(preferences, AndroidCalculatorEngine.Preferences.roundResult.getKey()); + onSharedPreferenceChanged(preferences, VibratorContainer.Preferences.hapticFeedbackEnabled.getKey()); + + final Preference clearBillingInfoPreference = findPreference(CLEAR_BILLING_INFO); + if (clearBillingInfoPreference != null) { + clearBillingInfoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + + Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_clearing, Toast.LENGTH_SHORT).show(); + + removeBillingInformation(CalculatorPreferencesActivity.this, PreferenceManager.getDefaultSharedPreferences(CalculatorPreferencesActivity.this)); + + return true; + } + }); + } + } + + public static void removeBillingInformation(@NotNull Context context, @NotNull SharedPreferences preferences) { + final SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean(AbstractBillingObserver.KEY_TRANSACTIONS_RESTORED, false); + editor.commit(); + + BillingController.dropBillingData(context); + } + + private void setAdFreeAction() { + final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); + + if (!AdsController.getInstance().isAdFree(this)) { + Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - enable preference!"); + + adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + + // check billing availability + if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) { + Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!"); + // warn about not supported billing + new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show(); + } else { + Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!"); + if (!AdsController.getInstance().isAdFree(CalculatorPreferencesActivity.this)) { + Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!"); + + // not purchased => purchasing + Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_purchasing, Toast.LENGTH_SHORT).show(); + + // show purchase window for user + BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true); + } else { + // disable preference + adFreePreference.setEnabled(false); + // and show message to user + Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_already_purchased, Toast.LENGTH_SHORT).show(); + } + } + + return true; + } + }); + adFreePreference.setEnabled(true); + } else { + Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - disable preference!"); + adFreePreference.setEnabled(false); + } + } + + @Override + protected void onDestroy() { + BillingController.unregisterObserver(this); + PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); + super.onDestroy(); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + if (AndroidCalculatorEngine.Preferences.roundResult.getKey().equals(key)) { + findPreference(AndroidCalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, AndroidCalculatorEngine.Preferences.roundResult.getDefaultValue())); + } else if (VibratorContainer.Preferences.hapticFeedbackEnabled.getKey().equals(key)) { + findPreference(VibratorContainer.Preferences.hapticFeedbackDuration.getKey()).setEnabled(VibratorContainer.Preferences.hapticFeedbackEnabled.getPreference(preferences)); + } + } + + @Override + public void onCheckBillingSupportedResponse(boolean supported) { + if (supported) { + setAdFreeAction(); + } else { + final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); + adFreePreference.setEnabled(false); + Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported!"); + } + } + + @Override + public void onPurchaseIntentOK(@NotNull String productId, @NotNull PendingIntent purchaseIntent) { + // do nothing + } + + @Override + public void onPurchaseIntentFailure(@NotNull String productId, @NotNull ResponseCode responseCode) { + // do nothing + } + + @Override + public void onPurchaseStateChanged(@NotNull String itemId, @NotNull Transaction.PurchaseState state) { + if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) { + final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); + if (adFreePreference != null) { + switch (state) { + case PURCHASED: + adFreePreference.setEnabled(false); + // restart activity to disable ads + AndroidUtils.restartActivity(this); + break; + case CANCELLED: + adFreePreference.setEnabled(true); + break; + case REFUNDED: + adFreePreference.setEnabled(true); + break; + } + } else { + } + } + } + + @Override + public void onRequestPurchaseResponse(@NotNull String itemId, @NotNull ResponseCode response) { + // do nothing + } + + @Override + public void onTransactionsRestored() { + // do nothing + } + + @Override + public void onErrorRestoreTransactions(@NotNull ResponseCode responseCode) { + // do nothing + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java index 6ccf8932..81670ca5 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AndroidCalculatorHistory.java @@ -1,149 +1,158 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - * or visit http://se.solovyev.org - */ - -package org.solovyev.android.calculator.history; - -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; -import org.solovyev.common.history.HistoryAction; - -import java.util.List; - -/** - * User: serso - * Date: 10/9/11 - * Time: 6:35 PM - */ -public class AndroidCalculatorHistory implements CalculatorHistory { - - @NotNull - private final CalculatorHistoryImpl calculatorHistory; - - @NotNull - private final Context context; - - public AndroidCalculatorHistory(@NotNull Application application, @NotNull Calculator calculator) { - this.context = application; - calculatorHistory = new CalculatorHistoryImpl(calculator); - } - - @Override - public void load() { - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - if (preferences != null) { - final String value = preferences.getString(context.getString(R.string.p_calc_history), null); - if (value != null) { - calculatorHistory.fromXml(value); - } - } - } - - public void save() { - final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - final SharedPreferences.Editor editor = settings.edit(); - - editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml()); - - editor.commit(); - } - - public void clearSavedHistory() { - calculatorHistory.clearSavedHistory(); - save(); - } - - public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { - historyState.setSaved(false); - calculatorHistory.removeSavedHistory(historyState); - save(); - } - - @Override - public boolean isEmpty() { - return calculatorHistory.isEmpty(); - } - - @Override - public CalculatorHistoryState getLastHistoryState() { - return calculatorHistory.getLastHistoryState(); - } - - @Override - public boolean isUndoAvailable() { - return calculatorHistory.isUndoAvailable(); - } - - @Override - public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { - return calculatorHistory.undo(currentState); - } - - @Override - public boolean isRedoAvailable() { - return calculatorHistory.isRedoAvailable(); - } - - @Override - public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { - return calculatorHistory.redo(currentState); - } - - @Override - public boolean isActionAvailable(@NotNull HistoryAction historyAction) { - return calculatorHistory.isActionAvailable(historyAction); - } - - @Override - public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { - return calculatorHistory.doAction(historyAction, currentState); - } - - @Override - public void addState(@Nullable CalculatorHistoryState currentState) { - calculatorHistory.addState(currentState); - } - - @NotNull - @Override - public List getStates() { - return calculatorHistory.getStates(); - } - - @Override - public void clear() { - calculatorHistory.clear(); - } - - @NotNull - public List getSavedHistory() { - return calculatorHistory.getSavedHistory(); - } - - @NotNull - public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { - return calculatorHistory.addSavedState(historyState); - } - - @Override - public void fromXml(@NotNull String xml) { - calculatorHistory.fromXml(xml); - } - - @Override - public String toXml() { - return calculatorHistory.toXml(); - } - - @Override - public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { - calculatorHistory.onCalculatorEvent(calculatorEventData, calculatorEventType, data); - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + * or visit http://se.solovyev.org + */ + +package org.solovyev.android.calculator.history; + +import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.Calculator; +import org.solovyev.android.calculator.CalculatorEventData; +import org.solovyev.android.calculator.CalculatorEventType; +import org.solovyev.android.calculator.R; +import org.solovyev.common.history.HistoryAction; + +import java.util.List; + +/** + * User: serso + * Date: 10/9/11 + * Time: 6:35 PM + */ +public class AndroidCalculatorHistory implements CalculatorHistory { + + @NotNull + private final CalculatorHistoryImpl calculatorHistory; + + @NotNull + private final Context context; + + public AndroidCalculatorHistory(@NotNull Application application, @NotNull Calculator calculator) { + this.context = application; + calculatorHistory = new CalculatorHistoryImpl(calculator); + } + + @Override + public void load() { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + if (preferences != null) { + final String value = preferences.getString(context.getString(R.string.p_calc_history), null); + if (value != null) { + calculatorHistory.fromXml(value); + } + } + } + + public void save() { + final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + final SharedPreferences.Editor editor = settings.edit(); + + editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml()); + + editor.commit(); + } + + public void clearSavedHistory() { + calculatorHistory.clearSavedHistory(); + save(); + } + + public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { + historyState.setSaved(false); + calculatorHistory.removeSavedHistory(historyState); + save(); + } + + @Override + public boolean isEmpty() { + return calculatorHistory.isEmpty(); + } + + @Override + public CalculatorHistoryState getLastHistoryState() { + return calculatorHistory.getLastHistoryState(); + } + + @Override + public boolean isUndoAvailable() { + return calculatorHistory.isUndoAvailable(); + } + + @Override + public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { + return calculatorHistory.undo(currentState); + } + + @Override + public boolean isRedoAvailable() { + return calculatorHistory.isRedoAvailable(); + } + + @Override + public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { + return calculatorHistory.redo(currentState); + } + + @Override + public boolean isActionAvailable(@NotNull HistoryAction historyAction) { + return calculatorHistory.isActionAvailable(historyAction); + } + + @Override + public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { + return calculatorHistory.doAction(historyAction, currentState); + } + + @Override + public void addState(@Nullable CalculatorHistoryState currentState) { + calculatorHistory.addState(currentState); + } + + @NotNull + @Override + public List getStates() { + return calculatorHistory.getStates(); + } + + @NotNull + @Override + public List getStates(boolean includeIntermediateStates) { + return calculatorHistory.getStates(includeIntermediateStates); + } + + @Override + public void clear() { + calculatorHistory.clear(); + } + + @NotNull + public List getSavedHistory() { + return calculatorHistory.getSavedHistory(); + } + + @NotNull + public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { + return calculatorHistory.addSavedState(historyState); + } + + @Override + public void fromXml(@NotNull String xml) { + calculatorHistory.fromXml(xml); + } + + @Override + public String toXml() { + return calculatorHistory.toXml(); + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + calculatorHistory.onCalculatorEvent(calculatorEventData, calculatorEventType, data); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragment.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragment.java index e38f3485..a579a577 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragment.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragment.java @@ -6,8 +6,10 @@ package org.solovyev.android.calculator.history; +import android.preference.PreferenceManager; import org.jetbrains.annotations.NotNull; import org.solovyev.android.calculator.CalculatorLocatorImpl; +import org.solovyev.android.calculator.CalculatorPreferences; import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.about.CalculatorFragmentType; @@ -33,7 +35,8 @@ public class CalculatorHistoryFragment extends AbstractCalculatorHistoryFragment @NotNull @Override protected List getHistoryItems() { - return new ArrayList(CalculatorLocatorImpl.getInstance().getHistory().getStates()); + final boolean showIntermediateCalculations = CalculatorPreferences.History.showIntermediateCalculations.getPreference(PreferenceManager.getDefaultSharedPreferences(getActivity())); + return new ArrayList(CalculatorLocatorImpl.getInstance().getHistory().getStates(showIntermediateCalculations)); } @Override