From ff1dd19018d2331e2406fce92a29f75d83e670d7 Mon Sep 17 00:00:00 2001 From: serso Date: Wed, 26 Sep 2012 18:39:34 +0400 Subject: [PATCH] Fragments --- .../calculator/CalculatorEditorImpl.java | 591 +++++------ .../calculator/CalculatorEventType.java | 16 +- .../history/CalculatorHistoryImpl.java | 467 ++++----- calculatorpp/AndroidManifest.xml | 134 ++- calculatorpp/pom.xml | 669 ++++++------ .../res/layout-land/main_calculator.xml | 83 +- .../res/layout-land/main_first_pane.xml | 62 ++ .../res/layout-large-land/main_calculator.xml | 109 +- calculatorpp/res/layout/ad.xml | 6 + calculatorpp/res/layout/history_fragment.xml | 15 + .../{history_activity.xml => main_empty.xml} | 34 +- calculatorpp/res/values/dimensions.xml | 7 +- .../calculator/CalculatorActivity.java | 760 +++++++------- .../calculator/CalculatorActivityHelper.java | 58 +- .../CalculatorActivityHelperImpl.java | 273 ++--- .../calculator/CalculatorDisplayFragment.java | 67 +- .../calculator/CalculatorEditorFragment.java | 96 +- .../CalculatorKeyboardFragment.java | 985 +++++++++--------- .../android/calculator/CalculatorMenu.java | 150 +-- .../AbstractCalculatorHistoryFragment.java | 547 +++++----- .../history/CalculatorHistoryFragment.java | 78 +- .../CalculatorHistoryFragmentActivity.java | 104 +- .../CalculatorSavedHistoryFragment.java | 78 +- .../history/HistoryItemMenuItem.java | 306 +++--- .../android/fragments/FragmentUtils.java | 123 ++- pom.xml | 14 + 26 files changed, 3010 insertions(+), 2822 deletions(-) create mode 100644 calculatorpp/res/layout-land/main_first_pane.xml create mode 100644 calculatorpp/res/layout/ad.xml create mode 100644 calculatorpp/res/layout/history_fragment.xml rename calculatorpp/res/layout/{history_activity.xml => main_empty.xml} (68%) 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 40445dbe..31fb7580 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,292 +1,299 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.common.gui.CursorControl; - -/** - * 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 CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this); - - public CalculatorEditorImpl(@NotNull Calculator calculator) { - this.calculator = calculator; - this.calculator.addCalculatorEventListener(this); - } - - @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) { - //To change body of implemented methods use File | Settings | File Templates. - } - - /* - ********************************************************************** - * - * 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 CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this); + + public CalculatorEditorImpl(@NotNull Calculator calculator) { + this.calculator = calculator; + this.calculator.addCalculatorEventListener(this); + } + + @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) { + if (calculatorEventType == CalculatorEventType.use_history_state) { + final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState)data; + final EditorHistoryState editorState = calculatorHistoryState.getEditorState(); + this.setText(StringUtils.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition()); + } + } + + /* + ********************************************************************** + * + * 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(); + } + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index 0822abeb..4095a4d5 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -75,7 +75,21 @@ public enum CalculatorEventType { ********************************************************************** */ - engine_preferences_changed; + engine_preferences_changed, + + /* + ********************************************************************** + * + * HISTORY + * + ********************************************************************** + */ + + // @NotNull CalculatorHistoryState + history_state_added, + + // @NotNull CalculatorHistoryState + use_history_state; public boolean isOfType(@NotNull CalculatorEventType... types) { for (CalculatorEventType type : types) { 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 313c443b..f5029645 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,233 +1,234 @@ -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); - } - } - - @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.getNewState(); - break; - case display_state_changed: - if (sameSequence) { - if (lastEditorViewState != null) { - final CalculatorEditorViewState editorViewState = lastEditorViewState; - final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; - final CalculatorDisplayViewState displayViewState = displayChangeData.getNewState(); - 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.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.getNewState(); + break; + case display_state_changed: + if (sameSequence) { + if (lastEditorViewState != null) { + final CalculatorEditorViewState editorViewState = lastEditorViewState; + final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; + final CalculatorDisplayViewState displayViewState = displayChangeData.getNewState(); + addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); + } + } else { + lastEditorViewState = null; + } + break; + } + } + } + } +} diff --git a/calculatorpp/AndroidManifest.xml b/calculatorpp/AndroidManifest.xml index 79af9dc1..03991aca 100644 --- a/calculatorpp/AndroidManifest.xml +++ b/calculatorpp/AndroidManifest.xml @@ -1,70 +1,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/calculatorpp/pom.xml b/calculatorpp/pom.xml index 151b9511..fa08d93c 100644 --- a/calculatorpp/pom.xml +++ b/calculatorpp/pom.xml @@ -1,336 +1,335 @@ - - - - - org.solovyev.android - calculatorpp-parent - 1.3.2 - - - 4.0.0 - - org.solovyev.android - calculatorpp - apk - Calculator++ Application - - - - - - - org.solovyev.android - calculatorpp-core - 1.3.2 - - - - org.solovyev - common-core - - - - org.solovyev - common-text - - - - org.solovyev.android - android-common-core - apklib - - - - org.solovyev.android - android-common-ads - apklib - - - - org.solovyev.android - android-common-view - apklib - - - - org.solovyev.android - android-common-preferences - apklib - - - - org.solovyev.android - android-common-other - apklib - - - - org.solovyev.android - android-common-menu - apklib - - - - org.solovyev.android - android-common-sherlock - 1.0.0 - apklib - - - - - org.solovyev - jscl - - - - - - com.google.android - android - provided - - - - com.google.android - support-v4 - - - - com.actionbarsherlock - library - 4.1.0 - - - - net.sf.opencsv - opencsv - 2.0 - test - - - - org.simpleframework - simple-xml - - - - achartengine - achartengine - 0.7.0 - - - - admob - admob - 6.1.0 - - - - org.solovyev.android - billing - 0.1 - - - - - com.google.guava - guava - 11.0.2 - - - - junit - junit - test - - - - com.intellij - annotations - - - - - - - - - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - true - - - true - - - - - manifestUpdate - process-resources - - manifest-update - - - - alignApk - package - - zipalign - - - - - - - - - - - - - release - - - - performRelease - true - - - - - - - - org.codehaus.mojo - properties-maven-plugin - 1.0-alpha-2 - - - initialize - - read-project-properties - - - - ${project.basedir}/misc/env/jarsigner.properties - - - - - - - - org.apache.maven.plugins - maven-jarsigner-plugin - - - signing - - sign - verify - - package - true - - true - - - ${project.build.directory}/${project.artifactId}-${project.version}.apk - - ${sign.keystore} - ${sign.alias} - ${sign.storepass} - ${sign.keypass} - false - - - - - - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - true - - - - false - - - - false - ${project.build.directory}/${project.artifactId}-${project.version}.apk - ${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk - - - - false - true - - - - true - - - - - - manifestUpdate - process-resources - - manifest-update - - - - alignApk - package - - zipalign - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - - ${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk - apk - signed-aligned - - - ${project.build.directory}/proguard/mapping.txt - map - release - - - - - - attach-signed-aligned - package - - attach-artifact - - - - - - - - - - - + + + + + org.solovyev.android + calculatorpp-parent + 1.3.2 + + + 4.0.0 + + org.solovyev.android + calculatorpp + apk + Calculator++ Application + + + + + + + org.solovyev.android + calculatorpp-core + 1.3.2 + + + + org.solovyev + common-core + + + + org.solovyev + common-text + + + + org.solovyev.android + android-common-core + apklib + + + + org.solovyev.android + android-common-ads + apklib + + + + org.solovyev.android + android-common-view + apklib + + + + org.solovyev.android + android-common-preferences + apklib + + + + org.solovyev.android + android-common-other + apklib + + + + org.solovyev.android + android-common-menu + apklib + + + + org.solovyev.android + android-common-sherlock + apklib + + + + + org.solovyev + jscl + + + + + + com.google.android + android + provided + + + + com.google.android + support-v4 + + + + com.actionbarsherlock + library + apklib + + + + net.sf.opencsv + opencsv + 2.0 + test + + + + org.simpleframework + simple-xml + + + + achartengine + achartengine + 0.7.0 + + + + admob + admob + 6.1.0 + + + + org.solovyev.android + billing + 0.1 + + + + + com.google.guava + guava + 11.0.2 + + + + junit + junit + test + + + + com.intellij + annotations + + + + + + + + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + true + + + true + + + + + manifestUpdate + process-resources + + manifest-update + + + + alignApk + package + + zipalign + + + + + + + + + + + + + release + + + + performRelease + true + + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0-alpha-2 + + + initialize + + read-project-properties + + + + ${project.basedir}/misc/env/jarsigner.properties + + + + + + + + org.apache.maven.plugins + maven-jarsigner-plugin + + + signing + + sign + verify + + package + true + + true + + + ${project.build.directory}/${project.artifactId}-${project.version}.apk + + ${sign.keystore} + ${sign.alias} + ${sign.storepass} + ${sign.keypass} + false + + + + + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + true + + + + false + + + + false + ${project.build.directory}/${project.artifactId}-${project.version}.apk + ${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk + + + + false + true + + + + true + + + + + + manifestUpdate + process-resources + + manifest-update + + + + alignApk + package + + zipalign + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + ${project.build.directory}/${project.artifactId}-${project.version}-signed-aligned.apk + apk + signed-aligned + + + ${project.build.directory}/proguard/mapping.txt + map + release + + + + + + attach-signed-aligned + package + + attach-artifact + + + + + + + + + + + \ No newline at end of file diff --git a/calculatorpp/res/layout-land/main_calculator.xml b/calculatorpp/res/layout-land/main_calculator.xml index cadee4c2..75966ec4 100644 --- a/calculatorpp/res/layout-land/main_calculator.xml +++ b/calculatorpp/res/layout-land/main_calculator.xml @@ -1,64 +1,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/calculatorpp/res/layout-land/main_first_pane.xml b/calculatorpp/res/layout-land/main_first_pane.xml new file mode 100644 index 00000000..8b628ebf --- /dev/null +++ b/calculatorpp/res/layout-land/main_first_pane.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/calculatorpp/res/layout-large-land/main_calculator.xml b/calculatorpp/res/layout-large-land/main_calculator.xml index 25da91dc..09ac9773 100644 --- a/calculatorpp/res/layout-large-land/main_calculator.xml +++ b/calculatorpp/res/layout-large-land/main_calculator.xml @@ -1,78 +1,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/calculatorpp/res/layout/ad.xml b/calculatorpp/res/layout/ad.xml new file mode 100644 index 00000000..822165b6 --- /dev/null +++ b/calculatorpp/res/layout/ad.xml @@ -0,0 +1,6 @@ + + + diff --git a/calculatorpp/res/layout/history_fragment.xml b/calculatorpp/res/layout/history_fragment.xml new file mode 100644 index 00000000..dd666064 --- /dev/null +++ b/calculatorpp/res/layout/history_fragment.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/calculatorpp/res/layout/history_activity.xml b/calculatorpp/res/layout/main_empty.xml similarity index 68% rename from calculatorpp/res/layout/history_activity.xml rename to calculatorpp/res/layout/main_empty.xml index b5845c7d..b056e66e 100644 --- a/calculatorpp/res/layout/history_activity.xml +++ b/calculatorpp/res/layout/main_empty.xml @@ -1,21 +1,15 @@ - - - - - - - - + + + + + + \ No newline at end of file diff --git a/calculatorpp/res/values/dimensions.xml b/calculatorpp/res/values/dimensions.xml index 428505aa..44e73a6c 100644 --- a/calculatorpp/res/values/dimensions.xml +++ b/calculatorpp/res/values/dimensions.xml @@ -1,4 +1,5 @@ - - 0.5dp - @dimen/button_margin + + 0.5dp + 2.0dp + 2.5dp \ No newline at end of file diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java index 685ed6a7..848d973c 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java @@ -1,381 +1,381 @@ -/* - * 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.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.pm.ActivityInfo; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v4.app.FragmentActivity; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.util.Log; -import android.util.TypedValue; -import android.view.*; -import android.widget.TextView; -import net.robotmedia.billing.BillingController; -import net.robotmedia.billing.IBillingObserver; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.AndroidUtils; -import org.solovyev.android.FontSizeAdjuster; -import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity; -import org.solovyev.android.calculator.view.CalculatorAdditionalTitle; -import org.solovyev.android.fragments.FragmentUtils; -import org.solovyev.android.menu.ActivityMenu; -import org.solovyev.android.menu.AndroidMenuHelper; -import org.solovyev.android.menu.ListActivityMenu; -import org.solovyev.android.prefs.Preference; -import org.solovyev.android.view.ColorButton; -import org.solovyev.common.equals.EqualsTool; -import org.solovyev.common.history.HistoryAction; -import org.solovyev.common.text.StringUtils; - -public class CalculatorActivity extends FragmentActivity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener { - - @NotNull - public static final String TAG = "Calculator++"; - - private static final int HVGA_WIDTH_PIXELS = 320; - - @Nullable - private IBillingObserver billingObserver; - - @NotNull - private CalculatorPreferences.Gui.Theme theme; - - @NotNull - private CalculatorPreferences.Gui.Layout layout; - - private boolean useBackAsPrev; - - @NotNull - private ActivityMenu menu = ListActivityMenu.fromList(CalculatorMenu.class, AndroidMenuHelper.getInstance()); - - /** - * Called when the activity is first created. - */ - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - - CalculatorApplication.registerOnRemoteStackTrace(); - - final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - - this.theme = CalculatorPreferences.Gui.getTheme(preferences); - setTheme(this.theme.getThemeId()); - - super.onCreate(savedInstanceState); - setLayout(preferences); - - CalculatorKeyboardFragment.fixThemeParameters(true, theme, this.getWindow().getDecorView()); - - FragmentUtils.createFragment(this, CalculatorEditorFragment.class, R.id.editorContainer, "editor"); - FragmentUtils.createFragment(this, CalculatorDisplayFragment.class, R.id.displayContainer, "display"); - FragmentUtils.createFragment(this, CalculatorKeyboardFragment.class, R.id.keyboardContainer, "keyboard"); - - if (customTitleSupported) { - try { - getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title); - final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text); - additionalAdditionalTitleText.init(preferences); - preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText); - } catch (ClassCastException e) { - // super fix for issue with class cast in android.view.Window.setFeatureInt() (see app error reports) - Log.e(CalculatorActivity.class.getName(), e.getMessage(), e); - } - } - - billingObserver = new CalculatorBillingObserver(this); - BillingController.registerObserver(billingObserver); - - this.useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences); - firstTimeInit(preferences, this); - - // init billing controller - BillingController.checkBillingSupported(this); - - toggleOrientationChange(preferences); - - CalculatorKeyboardFragment.toggleEqualsButton(preferences, this, theme, findViewById(R.id.main_layout)); - - preferences.registerOnSharedPreferenceChangeListener(this); - } - - @NotNull - private AndroidCalculator getCalculator() { - return ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()); - } - - private synchronized void setLayout(@NotNull SharedPreferences preferences) { - layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences); - - setContentView(layout.getLayoutId()); - } - - private static void firstTimeInit(@NotNull SharedPreferences preferences, @NotNull Context context) { - final Integer appOpenedCounter = CalculatorPreferences.appOpenedCounter.getPreference(preferences); - if (appOpenedCounter != null) { - CalculatorPreferences.appOpenedCounter.putPreference(preferences, appOpenedCounter + 1); - } - - final Integer savedVersion = CalculatorPreferences.appVersion.getPreference(preferences); - - final int appVersion = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName()); - - CalculatorPreferences.appVersion.putPreference(preferences, appVersion); - - boolean dialogShown = false; - if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) { - // new start - final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text); - builder.setPositiveButton(android.R.string.ok, null); - builder.setTitle(R.string.c_first_start_text_title); - builder.create().show(); - dialogShown = true; - } else { - if (savedVersion < appVersion) { - final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences); - if (showReleaseNotes) { - final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(context, savedVersion + 1); - if (!StringUtils.isEmpty(releaseNotes)) { - final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes)); - builder.setPositiveButton(android.R.string.ok, null); - builder.setTitle(R.string.c_release_notes); - builder.create().show(); - dialogShown = true; - } - } - } - } - - - //Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!"); - if (!dialogShown) { - if (appOpenedCounter != null && appOpenedCounter > 10) { - dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context); - } - } - - if (!dialogShown) { - dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.notesppAnnounceShown, R.layout.notespp_announce, R.id.notespp_announce, context); - } - } - - private static boolean showSpecialWindow(@NotNull SharedPreferences preferences, @NotNull Preference specialWindowShownPref, int layoutId, int textViewId, @NotNull Context context) { - boolean result = false; - - final Boolean specialWindowShown = specialWindowShownPref.getPreference(preferences); - if ( specialWindowShown != null && !specialWindowShown ) { - final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); - final View view = layoutInflater.inflate(layoutId, null); - - final TextView feedbackTextView = (TextView) view.findViewById(textViewId); - feedbackTextView.setMovementMethod(LinkMovementMethod.getInstance()); - - final AlertDialog.Builder builder = new AlertDialog.Builder(context).setView(view); - builder.setPositiveButton(android.R.string.ok, null); - builder.create().show(); - - result = true; - specialWindowShownPref.putPreference(preferences, true); - } - - return result; - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - if (useBackAsPrev) { - getCalculator().doHistoryAction(HistoryAction.undo); - return true; - } - } - return super.onKeyDown(keyCode, event); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void equalsButtonClickHandler(@NotNull View v) { - getCalculator().evaluate(); - } - - /* - ********************************************************************** - * - * MENU - * - ********************************************************************** - */ - - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - return this.menu.onPrepareOptionsMenu(this, menu); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - return this.menu.onCreateOptionsMenu(this, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return menu.onOptionsItemSelected(this, item); - } - - /** - * The font sizes in the layout files are specified for a HVGA display. - * Adjust the font sizes accordingly if we are running on a different - * display. - */ - @Override - public void adjustFontSize(@NotNull TextView view) { - float fontPixelSize = view.getTextSize(); - Display display = getWindowManager().getDefaultDisplay(); - int h = Math.min(display.getWidth(), display.getHeight()); - float ratio = (float) h / HVGA_WIDTH_PIXELS; - view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontPixelSize * ratio); - } - - @Override - protected void onResume() { - super.onResume(); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - - final CalculatorPreferences.Gui.Layout newLayout = CalculatorPreferences.Gui.layout.getPreference(preferences); - final CalculatorPreferences.Gui.Theme newTheme = CalculatorPreferences.Gui.theme.getPreference(preferences); - if (!theme.equals(newTheme) || !layout.equals(newLayout)) { - AndroidUtils.restartActivity(this); - } - } - - @Override - protected void onDestroy() { - if (billingObserver != null) { - BillingController.unregisterObserver(billingObserver); - } - - super.onDestroy(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) { - if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) { - useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences); - } - - if ( CalculatorPreferences.Gui.autoOrientation.getKey().equals(key) ) { - toggleOrientationChange(preferences); - } - } - - private void toggleOrientationChange(@Nullable SharedPreferences preferences) { - preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(this) : preferences; - if (CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } - } - - /* - ********************************************************************** - * - * BUTTON HANDLERS - * - ********************************************************************** - */ - - @SuppressWarnings({"UnusedDeclaration"}) - public void elementaryButtonClickHandler(@NotNull View v) { - throw new UnsupportedOperationException("Not implemented yet!"); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void historyButtonClickHandler(@NotNull View v) { - CalculatorActivityLauncher.showHistory(this); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void eraseButtonClickHandler(@NotNull View v) { - CalculatorLocatorImpl.getInstance().getEditor().erase(); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void simplifyButtonClickHandler(@NotNull View v) { - throw new UnsupportedOperationException("Not implemented yet!"); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void moveLeftButtonClickHandler(@NotNull View v) { - getKeyboard().moveCursorLeft(); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void moveRightButtonClickHandler(@NotNull View v) { - getKeyboard().moveCursorRight(); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void pasteButtonClickHandler(@NotNull View v) { - getKeyboard().pasteButtonPressed(); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void copyButtonClickHandler(@NotNull View v) { - getKeyboard().copyButtonPressed(); - } - - @NotNull - private static CalculatorKeyboard getKeyboard() { - return CalculatorLocatorImpl.getInstance().getKeyboard(); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void clearButtonClickHandler(@NotNull View v) { - getKeyboard().clearButtonPressed(); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void digitButtonClickHandler(@NotNull View v) { - Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed()); - if (((ColorButton) v).isShowText()) { - getKeyboard().digitButtonPressed(((ColorButton) v).getText().toString()); - } - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void functionsButtonClickHandler(@NotNull View v) { - CalculatorActivityLauncher.showFunctions(this); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void operatorsButtonClickHandler(@NotNull View v) { - CalculatorActivityLauncher.showOperators(this); - } - - public static void operatorsButtonClickHandler(@NotNull Activity activity) { - CalculatorActivityLauncher.showOperators(activity); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void varsButtonClickHandler(@NotNull View v) { - CalculatorActivityLauncher.showVars(this); - } - - @SuppressWarnings({"UnusedDeclaration"}) - public void donateButtonClickHandler(@NotNull View v) { - CalculatorApplication.showDonationDialog(this); - } - +/* + * 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.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.util.TypedValue; +import android.view.*; +import android.widget.TextView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import net.robotmedia.billing.BillingController; +import net.robotmedia.billing.IBillingObserver; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.AndroidUtils; +import org.solovyev.android.FontSizeAdjuster; +import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity; +import org.solovyev.android.calculator.history.CalculatorHistoryFragment; +import org.solovyev.android.calculator.history.CalculatorSavedHistoryFragment; +import org.solovyev.android.fragments.FragmentUtils; +import org.solovyev.android.prefs.Preference; +import org.solovyev.android.view.ColorButton; +import org.solovyev.common.equals.EqualsTool; +import org.solovyev.common.history.HistoryAction; +import org.solovyev.common.text.StringUtils; + +public class CalculatorActivity extends SherlockFragmentActivity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener { + + @NotNull + public static final String TAG = "Calculator++"; + + private static final int HVGA_WIDTH_PIXELS = 320; + + @Nullable + private IBillingObserver billingObserver; + + private boolean useBackAsPrev; + + @NotNull + private CalculatorActivityHelper activityHelper; + + /** + * Called when the activity is first created. + */ + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + CalculatorApplication.registerOnRemoteStackTrace(); + + /*final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);*/ + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + + final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences); + + activityHelper = CalculatorApplication.getInstance().createCalculatorHistoryHelper(layout.getLayoutId()); + activityHelper.onCreate(this, savedInstanceState); + + super.onCreate(savedInstanceState); + + if (findViewById(R.id.main_second_pane) != null) { + activityHelper.addTab(this, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.id.main_second_pane); + activityHelper.addTab(this, "saved_history", CalculatorSavedHistoryFragment.class, null, R.string.c_saved_history, R.id.main_second_pane); + activityHelper.restoreSavedTab(this); + } + + CalculatorKeyboardFragment.fixThemeParameters(true, activityHelper.getTheme(), this.getWindow().getDecorView()); + + FragmentUtils.createFragment(this, CalculatorEditorFragment.class, R.id.editorContainer, "editor"); + FragmentUtils.createFragment(this, CalculatorDisplayFragment.class, R.id.displayContainer, "display"); + FragmentUtils.createFragment(this, CalculatorKeyboardFragment.class, R.id.keyboardContainer, "keyboard"); + + /*if (customTitleSupported) { + try { + getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title); + final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text); + additionalAdditionalTitleText.init(preferences); + preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText); + } catch (ClassCastException e) { + // super fix for issue with class cast in android.view.Window.setFeatureInt() (see app error reports) + Log.e(CalculatorActivity.class.getName(), e.getMessage(), e); + } + }*/ + + billingObserver = new CalculatorBillingObserver(this); + BillingController.registerObserver(billingObserver); + + this.useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences); + firstTimeInit(preferences, this); + + // init billing controller + BillingController.checkBillingSupported(this); + + toggleOrientationChange(preferences); + + CalculatorKeyboardFragment.toggleEqualsButton(preferences, this, activityHelper.getTheme(), findViewById(R.id.main_layout)); + + preferences.registerOnSharedPreferenceChangeListener(this); + } + + @NotNull + private AndroidCalculator getCalculator() { + return ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()); + } + + private static void firstTimeInit(@NotNull SharedPreferences preferences, @NotNull Context context) { + final Integer appOpenedCounter = CalculatorPreferences.appOpenedCounter.getPreference(preferences); + if (appOpenedCounter != null) { + CalculatorPreferences.appOpenedCounter.putPreference(preferences, appOpenedCounter + 1); + } + + final Integer savedVersion = CalculatorPreferences.appVersion.getPreference(preferences); + + final int appVersion = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName()); + + CalculatorPreferences.appVersion.putPreference(preferences, appVersion); + + boolean dialogShown = false; + if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) { + // new start + final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text); + builder.setPositiveButton(android.R.string.ok, null); + builder.setTitle(R.string.c_first_start_text_title); + builder.create().show(); + dialogShown = true; + } else { + if (savedVersion < appVersion) { + final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences); + if (showReleaseNotes) { + final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(context, savedVersion + 1); + if (!StringUtils.isEmpty(releaseNotes)) { + final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes)); + builder.setPositiveButton(android.R.string.ok, null); + builder.setTitle(R.string.c_release_notes); + builder.create().show(); + dialogShown = true; + } + } + } + } + + + //Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!"); + if (!dialogShown) { + if (appOpenedCounter != null && appOpenedCounter > 10) { + dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context); + } + } + + if (!dialogShown) { + dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.notesppAnnounceShown, R.layout.notespp_announce, R.id.notespp_announce, context); + } + } + + private static boolean showSpecialWindow(@NotNull SharedPreferences preferences, @NotNull Preference specialWindowShownPref, int layoutId, int textViewId, @NotNull Context context) { + boolean result = false; + + final Boolean specialWindowShown = specialWindowShownPref.getPreference(preferences); + if ( specialWindowShown != null && !specialWindowShown ) { + final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); + final View view = layoutInflater.inflate(layoutId, null); + + final TextView feedbackTextView = (TextView) view.findViewById(textViewId); + feedbackTextView.setMovementMethod(LinkMovementMethod.getInstance()); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context).setView(view); + builder.setPositiveButton(android.R.string.ok, null); + builder.create().show(); + + result = true; + specialWindowShownPref.putPreference(preferences, true); + } + + return result; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (useBackAsPrev) { + getCalculator().doHistoryAction(HistoryAction.undo); + return true; + } + } + return super.onKeyDown(keyCode, event); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void equalsButtonClickHandler(@NotNull View v) { + getCalculator().evaluate(); + } + + /* + ********************************************************************** + * + * MENU + * + ********************************************************************** + */ + + +/* @Override + public boolean onPrepareOptionsMenu(Menu menu) { + return this.menu.onPrepareOptionsMenu(this, menu); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + return this.menu.onCreateOptionsMenu(this, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return menu.onOptionsItemSelected(this, item); + }*/ + + /** + * The font sizes in the layout files are specified for a HVGA display. + * Adjust the font sizes accordingly if we are running on a different + * display. + */ + @Override + public void adjustFontSize(@NotNull TextView view) { + float fontPixelSize = view.getTextSize(); + Display display = getWindowManager().getDefaultDisplay(); + int h = Math.min(display.getWidth(), display.getHeight()); + float ratio = (float) h / HVGA_WIDTH_PIXELS; + view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontPixelSize * ratio); + } + + @Override + protected void onResume() { + super.onResume(); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + final CalculatorPreferences.Gui.Layout newLayout = CalculatorPreferences.Gui.layout.getPreference(preferences); + if ( newLayout.getLayoutId() != activityHelper.getLayoutId() ) { + AndroidUtils.restartActivity(this); + } + + this.activityHelper.onResume(this); + } + + @Override + protected void onDestroy() { + if (billingObserver != null) { + BillingController.unregisterObserver(billingObserver); + } + + super.onDestroy(); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) { + if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) { + useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences); + } + + if ( CalculatorPreferences.Gui.autoOrientation.getKey().equals(key) ) { + toggleOrientationChange(preferences); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + activityHelper.onSaveInstanceState(this, outState); + } + + private void toggleOrientationChange(@Nullable SharedPreferences preferences) { + preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(this) : preferences; + if (CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + } + + /* + ********************************************************************** + * + * BUTTON HANDLERS + * + ********************************************************************** + */ + + @SuppressWarnings({"UnusedDeclaration"}) + public void elementaryButtonClickHandler(@NotNull View v) { + throw new UnsupportedOperationException("Not implemented yet!"); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void historyButtonClickHandler(@NotNull View v) { + CalculatorActivityLauncher.showHistory(this); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void eraseButtonClickHandler(@NotNull View v) { + CalculatorLocatorImpl.getInstance().getEditor().erase(); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void simplifyButtonClickHandler(@NotNull View v) { + throw new UnsupportedOperationException("Not implemented yet!"); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void moveLeftButtonClickHandler(@NotNull View v) { + getKeyboard().moveCursorLeft(); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void moveRightButtonClickHandler(@NotNull View v) { + getKeyboard().moveCursorRight(); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void pasteButtonClickHandler(@NotNull View v) { + getKeyboard().pasteButtonPressed(); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void copyButtonClickHandler(@NotNull View v) { + getKeyboard().copyButtonPressed(); + } + + @NotNull + private static CalculatorKeyboard getKeyboard() { + return CalculatorLocatorImpl.getInstance().getKeyboard(); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void clearButtonClickHandler(@NotNull View v) { + getKeyboard().clearButtonPressed(); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void digitButtonClickHandler(@NotNull View v) { + Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed()); + if (((ColorButton) v).isShowText()) { + getKeyboard().digitButtonPressed(((ColorButton) v).getText().toString()); + } + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void functionsButtonClickHandler(@NotNull View v) { + CalculatorActivityLauncher.showFunctions(this); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void operatorsButtonClickHandler(@NotNull View v) { + CalculatorActivityLauncher.showOperators(this); + } + + public static void operatorsButtonClickHandler(@NotNull Activity activity) { + CalculatorActivityLauncher.showOperators(activity); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void varsButtonClickHandler(@NotNull View v) { + CalculatorActivityLauncher.showVars(this); + } + + @SuppressWarnings({"UnusedDeclaration"}) + public void donateButtonClickHandler(@NotNull View v) { + CalculatorApplication.showDonationDialog(this); + } + } \ No newline at end of file diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelper.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelper.java index d6542555..c1543e0c 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelper.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelper.java @@ -1,19 +1,39 @@ -package org.solovyev.android.calculator; - -import android.os.Bundle; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * User: serso - * Date: 9/25/12 - * Time: 10:31 PM - */ -public interface CalculatorActivityHelper { - - void onCreate(@NotNull SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState); - - void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState); - -} +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: serso + * Date: 9/25/12 + * Time: 10:31 PM + */ +public interface CalculatorActivityHelper { + + void onCreate(@NotNull SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState); + void onCreate(@NotNull Activity activity, @Nullable Bundle savedInstanceState); + + void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState); + void onSaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState); + + int getLayoutId(); + + @NotNull + CalculatorPreferences.Gui.Theme getTheme(); + + void onResume(@NotNull SherlockFragmentActivity activity); + void onResume(@NotNull Activity activity); + + void addTab(@NotNull SherlockFragmentActivity activity, + @NotNull String tag, + @NotNull Class fragmentClass, + @Nullable Bundle fragmentArgs, + int captionResId, int parentViewId); + + void restoreSavedTab(@NotNull SherlockFragmentActivity activity); +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelperImpl.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelperImpl.java index 02ca1f1e..128fb523 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelperImpl.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorActivityHelperImpl.java @@ -1,121 +1,152 @@ -package org.solovyev.android.calculator; - -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.history.CalculatorHistoryFragment; -import org.solovyev.android.sherlock.tabs.ActionBarFragmentTabListener; - -/** - * User: serso - * Date: 9/25/12 - * Time: 10:32 PM - */ -public class CalculatorActivityHelperImpl implements CalculatorActivityHelper { - - /* - ********************************************************************** - * - * CONSTANTS - * - ********************************************************************** - */ - private static final String SELECTED_NAV = "selected_nav"; - - /* - ********************************************************************** - * - * FIELDS - * - ********************************************************************** - */ - - private int layoutId; - - private boolean showActionBarTabs = true; - - private boolean homeIcon = false; - - public CalculatorActivityHelperImpl(int layoutId) { - this.layoutId = layoutId; - } - - public CalculatorActivityHelperImpl(int layoutId, boolean showActionBarTabs, boolean homeIcon) { - this.layoutId = layoutId; - this.showActionBarTabs = showActionBarTabs; - this.homeIcon = homeIcon; - } - - @Override - public void onCreate(@NotNull final SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState) { - activity.setContentView(layoutId); - - final ActionBar actionBar = activity.getSupportActionBar(); - actionBar.setDisplayUseLogoEnabled(false); - actionBar.setDisplayHomeAsUpEnabled(homeIcon); - actionBar.setDisplayShowHomeEnabled(true); - actionBar.setDisplayShowTitleEnabled(true); - - if (showActionBarTabs) { - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - - addTab(activity, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.drawable.icon); - //addTab(activity, "messages", MessengerChatsFragment.class, null, R.string.c_messages, R.drawable.msg_footer_messages_icon); - - // settings tab - final ActionBar.Tab tab = actionBar.newTab(); - tab.setTag("settings"); - tab.setText(R.string.c_settings); - //tab.setIcon(R.drawable.msg_footer_settings_icon); - tab.setTabListener(new ActionBar.TabListener() { - @Override - public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { - activity.startActivity(new Intent(activity.getApplicationContext(), CalculatorPreferencesActivity.class)); - } - - @Override - public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { - } - - @Override - public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { - } - }); - actionBar.addTab(tab); - - int navPosition = -1; - if (savedInstanceState != null) { - navPosition = savedInstanceState.getInt(SELECTED_NAV, -1); - } - - if (navPosition >= 0) { - activity.getSupportActionBar().setSelectedNavigationItem(navPosition); - } - } - } - - @Override - public void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState) { - outState.putInt(SELECTED_NAV, activity.getSupportActionBar().getSelectedNavigationIndex()); - } - - private void addTab(@NotNull SherlockFragmentActivity activity, - @NotNull String tag, - @NotNull Class fragmentClass, - @Nullable Bundle fragmentArgs, - int captionResId, - int iconResId) { - final ActionBar actionBar = activity.getSupportActionBar(); - final ActionBar.Tab tab = actionBar.newTab(); - tab.setTag(tag); - tab.setText(captionResId); - //tab.setIcon(iconResId); - tab.setTabListener(new ActionBarFragmentTabListener(activity, tag, fragmentClass, fragmentArgs, R.id.content_second_pane)); - actionBar.addTab(tab); - } -} +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.AndroidUtils; +import org.solovyev.android.fragments.FragmentUtils; +import org.solovyev.android.sherlock.tabs.ActionBarFragmentTabListener; + +import java.util.ArrayList; +import java.util.List; + +/** + * User: serso + * Date: 9/25/12 + * Time: 10:32 PM + */ +public class CalculatorActivityHelperImpl implements CalculatorActivityHelper { + + /* + ********************************************************************** + * + * CONSTANTS + * + ********************************************************************** + */ + private static final String SELECTED_NAV = "selected_nav"; + + /* + ********************************************************************** + * + * FIELDS + * + ********************************************************************** + */ + + private int layoutId; + + private boolean homeIcon = false; + + @NotNull + private final List fragmentTags = new ArrayList(); + + @NotNull + private CalculatorPreferences.Gui.Theme theme; + private int navPosition = 0; + + public CalculatorActivityHelperImpl(int layoutId) { + this.layoutId = layoutId; + } + + public CalculatorActivityHelperImpl(int layoutId, boolean homeIcon) { + this.layoutId = layoutId; + this.homeIcon = homeIcon; + } + + @Override + public void onCreate(@NotNull Activity activity, @Nullable Bundle savedInstanceState) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); + + this.theme = CalculatorPreferences.Gui.getTheme(preferences); + activity.setTheme(this.theme.getThemeId()); + + activity.setContentView(layoutId); + } + + @Override + public void onCreate(@NotNull final SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState) { + this.onCreate((Activity) activity, savedInstanceState); + + final ActionBar actionBar = activity.getSupportActionBar(); + actionBar.setDisplayUseLogoEnabled(false); + actionBar.setDisplayHomeAsUpEnabled(homeIcon); + actionBar.setDisplayShowHomeEnabled(true); + actionBar.setDisplayShowTitleEnabled(true); + + if (savedInstanceState != null) { + navPosition = savedInstanceState.getInt(SELECTED_NAV, 0); + } + } + + @Override + public void restoreSavedTab(@NotNull SherlockFragmentActivity activity) { + final ActionBar actionBar = activity.getSupportActionBar(); + if (navPosition >= 0 && navPosition < actionBar.getTabCount()) { + activity.getSupportActionBar().setSelectedNavigationItem(navPosition); + } + } + + @Override + public void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState) { + FragmentUtils.detachFragments(activity, fragmentTags); + + onSaveInstanceState((Activity) activity, outState); + outState.putInt(SELECTED_NAV, activity.getSupportActionBar().getSelectedNavigationIndex()); + } + + @Override + public void onSaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState) { + } + + @Override + public void onResume(@NotNull Activity activity) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); + + final CalculatorPreferences.Gui.Theme newTheme = CalculatorPreferences.Gui.theme.getPreference(preferences); + if (!theme.equals(newTheme)) { + AndroidUtils.restartActivity(activity); + } + } + + @Override + public void addTab(@NotNull SherlockFragmentActivity activity, + @NotNull String tag, + @NotNull Class fragmentClass, + @Nullable Bundle fragmentArgs, + int captionResId, + int parentViewId) { + activity.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + + final ActionBar actionBar = activity.getSupportActionBar(); + final ActionBar.Tab tab = actionBar.newTab(); + tab.setTag(tag); + tab.setText(captionResId); + tab.setTabListener(new ActionBarFragmentTabListener(activity, tag, fragmentClass, fragmentArgs, parentViewId)); + actionBar.addTab(tab); + + fragmentTags.add(tag); + } + + @Override + public int getLayoutId() { + return layoutId; + } + + @Override + @NotNull + public CalculatorPreferences.Gui.Theme getTheme() { + return theme; + } + + @Override + public void onResume(@NotNull SherlockFragmentActivity activity) { + onResume((Activity) activity); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplayFragment.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplayFragment.java index 91cc76ba..f4858160 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplayFragment.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorDisplayFragment.java @@ -1,34 +1,33 @@ -package org.solovyev.android.calculator; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -/** - * User: Solovyev_S - * Date: 25.09.12 - * Time: 12:03 - */ -public class CalculatorDisplayFragment extends Fragment { - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.calc_display, null); - view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return view; - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()).setDisplay(getActivity()); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - } -} +package org.solovyev.android.calculator; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.actionbarsherlock.app.SherlockFragment; + +/** + * User: Solovyev_S + * Date: 25.09.12 + * Time: 12:03 + */ +public class CalculatorDisplayFragment extends SherlockFragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.calc_display, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()).setDisplay(getActivity()); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditorFragment.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditorFragment.java index 68164601..ae7b0b21 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditorFragment.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorEditorFragment.java @@ -1,32 +1,64 @@ -package org.solovyev.android.calculator; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -/** - * User: Solovyev_S - * Date: 25.09.12 - * Time: 10:49 - */ -public class CalculatorEditorFragment extends Fragment { - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.calc_editor, null); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()).setEditor(getActivity()); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - } -} +package org.solovyev.android.calculator; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.actionbarsherlock.app.SherlockFragment; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.menu.ActivityMenu; +import org.solovyev.android.menu.ListActivityMenu; +import org.solovyev.android.sherlock.menu.SherlockMenuHelper; + +/** + * User: Solovyev_S + * Date: 25.09.12 + * Time: 10:49 + */ +public class CalculatorEditorFragment extends SherlockFragment { + + @NotNull + private ActivityMenu menu = ListActivityMenu.fromList(CalculatorMenu.class, SherlockMenuHelper.getInstance()); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.calc_editor, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()).setEditor(getActivity()); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + this.menu.onCreateOptionsMenu(this.getActivity(), menu); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + this.menu.onPrepareOptionsMenu(this.getActivity(), menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return this.menu.onOptionsItemSelected(this.getActivity(), item); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardFragment.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardFragment.java index bfd671b8..74288acc 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardFragment.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardFragment.java @@ -1,493 +1,492 @@ -package org.solovyev.android.calculator; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Vibrator; -import android.preference.PreferenceManager; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.*; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.Toast; -import jscl.AngleUnit; -import jscl.NumeralBase; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.AndroidUtils; -import org.solovyev.android.calculator.history.CalculatorHistoryState; -import org.solovyev.android.calculator.model.AndroidCalculatorEngine; -import org.solovyev.android.calculator.view.AngleUnitsButton; -import org.solovyev.android.calculator.view.NumeralBasesButton; -import org.solovyev.android.calculator.view.OnDragListenerVibrator; -import org.solovyev.android.history.HistoryDragProcessor; -import org.solovyev.android.view.ColorButton; -import org.solovyev.android.view.drag.*; -import org.solovyev.common.Announcer; -import org.solovyev.common.math.Point2d; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; - -/** - * User: Solovyev_S - * Date: 25.09.12 - * Time: 12:25 - */ -public class CalculatorKeyboardFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener { - - @Nullable - private Vibrator vibrator; - - @NotNull - private final Announcer dpclRegister = new Announcer(DragPreferencesChangeListener.class); - - @NotNull - private NumeralBaseButtons numeralBaseButtons = new NumeralBaseButtons(); - - @NotNull - private CalculatorPreferences.Gui.Theme theme; - - @NotNull - private CalculatorPreferences.Gui.Layout layout; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - vibrator = (Vibrator) this.getActivity().getSystemService(Activity.VIBRATOR_SERVICE); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); - - preferences.registerOnSharedPreferenceChangeListener(this); - - layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences); - theme = CalculatorPreferences.Gui.theme.getPreferenceNoError(preferences); - - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.calc_keyboard, null); - view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return view; - } - - @Override - public void onViewCreated(View root, Bundle savedInstanceState) { - super.onViewCreated(root, savedInstanceState); - - dpclRegister.clear(); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); - final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, this.getActivity()); - - setOnDragListeners(root, dragPreferences, preferences); - - final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor(getCalculator()), dragPreferences), vibrator, preferences); - final DragButton historyButton = getButton(root, R.id.historyButton); - if (historyButton != null) { - historyButton.setOnDragListener(historyOnDragListener); - } - - final DragButton subtractionButton = getButton(root, R.id.subtractionButton); - if (subtractionButton != null) { - subtractionButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new SimpleOnDragListener.DragProcessor() { - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { - if (dragDirection == DragDirection.down) { - CalculatorActivity.operatorsButtonClickHandler(getActivity()); - return true; - } - return false; - } - }, dragPreferences), vibrator, preferences)); - } - - - final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(), dragPreferences), vibrator, preferences); - - final DragButton rightButton = getButton(root, R.id.rightButton); - if (rightButton != null) { - rightButton.setOnDragListener(toPositionOnDragListener); - } - - final DragButton leftButton = getButton(root, R.id.leftButton); - if (leftButton != null) { - leftButton.setOnDragListener(toPositionOnDragListener); - } - - final DragButton equalsButton = getButton(root, R.id.equalsButton); - if (equalsButton != null) { - equalsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new EvalDragProcessor(), dragPreferences), vibrator, preferences)); - } - - final AngleUnitsButton angleUnitsButton = (AngleUnitsButton) getButton(root, R.id.sixDigitButton); - if (angleUnitsButton != null) { - angleUnitsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new AngleUnitsChanger(this.getActivity()), dragPreferences), vibrator, preferences)); - } - - final NumeralBasesButton clearButton = (NumeralBasesButton) getButton(root, R.id.clearButton); - if (clearButton != null) { - clearButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new NumeralBasesChanger(this.getActivity()), dragPreferences), vibrator, preferences)); - } - - final DragButton varsButton = getButton(root, R.id.varsButton); - if (varsButton != null) { - varsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new VarsDragProcessor(this.getActivity()), dragPreferences), vibrator, preferences)); - } - - final DragButton roundBracketsButton = getButton(root, R.id.roundBracketsButton); - if (roundBracketsButton != null) { - roundBracketsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new RoundBracketsDragProcessor(), dragPreferences), vibrator, preferences)); - } - - if (layout == CalculatorPreferences.Gui.Layout.simple) { - toggleButtonDirectionText(root, R.id.oneDigitButton, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.twoDigitButton, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.threeDigitButton, false, DragDirection.up, DragDirection.down); - - toggleButtonDirectionText(root, R.id.sixDigitButton, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.sevenDigitButton, false, DragDirection.left, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.eightDigitButton, false, DragDirection.left, DragDirection.up, DragDirection.down); - - toggleButtonDirectionText(root, R.id.clearButton, false, DragDirection.left, DragDirection.up, DragDirection.down); - - toggleButtonDirectionText(root, R.id.fourDigitButton, false, DragDirection.down); - toggleButtonDirectionText(root, R.id.fiveDigitButton, false, DragDirection.down); - - toggleButtonDirectionText(root, R.id.nineDigitButton, false, DragDirection.left); - - toggleButtonDirectionText(root, R.id.multiplicationButton, false, DragDirection.left); - toggleButtonDirectionText(root, R.id.plusButton, false, DragDirection.down, DragDirection.up); - } - - numeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences); - - fixThemeParameters(true, theme, this.getView()); - - toggleEqualsButton(preferences, this.getActivity(), theme, root); - - initMultiplicationButton(); - } - - @Nullable - private T getButton(@NotNull View root, int buttonId) { - return (T) root.findViewById(buttonId); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); - - preferences.unregisterOnSharedPreferenceChangeListener(this); - } - - public static void fixThemeParameters(boolean fixMagicFlames, - @NotNull CalculatorPreferences.Gui.Theme theme, - @NotNull View root) { - if (theme.getThemeType() == CalculatorPreferences.Gui.ThemeType.metro) { - - if (fixMagicFlames) { - // for metro themes we should turn off magic flames - AndroidUtils.processViewsOfType(root, ColorButton.class, new AndroidUtils.ViewProcessor() { - @Override - public void process(@NotNull ColorButton colorButton) { - colorButton.setDrawMagicFlame(false); - } - }); - } - } - } - - private void initMultiplicationButton() { - final View multiplicationButton = getView().findViewById(R.id.multiplicationButton); - if ( multiplicationButton instanceof Button) { - ((Button) multiplicationButton).setText(CalculatorLocatorImpl.getInstance().getEngine().getMultiplicationSign()); - } - } - -/* private static void setMarginsForView(@Nullable View view, int marginLeft, int marginBottom, @NotNull Context context) { - // IMPORTANT: this is workaround for probably android bug - // currently margin values set in styles are not applied for some reasons to the views (using include tag) => set them manually - - if (view != null) { - final DisplayMetrics dm = context.getResources().getDisplayMetrics(); - if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) { - final LinearLayout.LayoutParams oldParams = (LinearLayout.LayoutParams) view.getLayoutParams(); - final LinearLayout.LayoutParams newParams = new LinearLayout.LayoutParams(oldParams.width, oldParams.height, oldParams.weight); - newParams.setMargins(AndroidUtils.toPixels(dm, marginLeft), 0, 0, AndroidUtils.toPixels(dm, marginBottom)); - view.setLayoutParams(newParams); - } - } - }*/ - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - } - - private synchronized void setOnDragListeners(@NotNull View root, @NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) { - final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(getKeyboard()), dragPreferences), vibrator, preferences); - - final List dragButtonIds = new ArrayList(); - final List buttonIds = new ArrayList(); - - for (Field field : R.id.class.getDeclaredFields()) { - int modifiers = field.getModifiers(); - if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { - try { - int viewId = field.getInt(R.id.class); - final View view = root.findViewById(viewId); - if (view instanceof DragButton) { - dragButtonIds.add(viewId); - } - if (view instanceof Button) { - buttonIds.add(viewId); - } - } catch (IllegalAccessException e) { - Log.e(R.id.class.getName(), e.getMessage()); - } - } - } - - for (Integer dragButtonId : dragButtonIds) { - final DragButton button = getButton(root, dragButtonId); - if (button != null) { - button.setOnDragListener(onDragListener); - } - } - } - - - @NotNull - private SimpleOnDragListener newOnDragListener(@NotNull SimpleOnDragListener.DragProcessor dragProcessor, - @NotNull SimpleOnDragListener.Preferences dragPreferences) { - final SimpleOnDragListener onDragListener = new SimpleOnDragListener(dragProcessor, dragPreferences); - dpclRegister.addListener(onDragListener); - return onDragListener; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (key != null && key.startsWith("org.solovyev.android.calculator.DragButtonCalibrationActivity")) { - dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this.getActivity())); - } - - if (AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key)) { - numeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences); - } - - if ( CalculatorPreferences.Gui.showEqualsButton.getKey().equals(key) ) { - toggleEqualsButton(preferences, this.getActivity(), theme, getView()); - } - - if ( AndroidCalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) { - initMultiplicationButton(); - } - } - - private void toggleButtonDirectionText(@NotNull View root, int id, boolean showDirectionText, @NotNull DragDirection... dragDirections) { - final View v = getButton(root, id); - if (v instanceof DirectionDragButton ) { - final DirectionDragButton button = (DirectionDragButton)v; - for (DragDirection dragDirection : dragDirections) { - button.showDirectionText(showDirectionText, dragDirection); - } - } - } - - public static void toggleEqualsButton(@Nullable SharedPreferences preferences, - @NotNull Activity activity, - @NotNull CalculatorPreferences.Gui.Theme theme, - @NotNull View root) { - preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(activity) : preferences; - - if (AndroidUtils.getScreenOrientation(activity) == Configuration.ORIENTATION_PORTRAIT || !CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { - final Display display = activity.getWindowManager().getDefaultDisplay(); - - final DragButton button = (DragButton)activity.findViewById(R.id.equalsButton); - if (CalculatorPreferences.Gui.showEqualsButton.getPreference(preferences)) { - button.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.FILL_PARENT, 1f)); - if (display.getWidth() <= 480) { - // mobile phones - final AndroidCalculatorDisplayView calculatorDisplayView = getCalculatorDisplayView(); - if (calculatorDisplayView != null) { - calculatorDisplayView.setBackgroundDrawable(null); - } - } - } else { - button.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.FILL_PARENT, 0f)); - if (display.getWidth() <= 480) { - // mobile phones - final AndroidCalculatorDisplayView calculatorDisplayView = getCalculatorDisplayView(); - if (calculatorDisplayView != null) { - calculatorDisplayView.setBackgroundDrawable(activity.getResources().getDrawable(R.drawable.equals9)); - } - } - } - - fixThemeParameters(false, theme, root); - } - } - - - @Nullable - private static AndroidCalculatorDisplayView getCalculatorDisplayView() { - return (AndroidCalculatorDisplayView) CalculatorLocatorImpl.getInstance().getDisplay().getView(); - } - - @NotNull - private Calculator getCalculator() { - return CalculatorLocatorImpl.getInstance().getCalculator(); - } - - @NotNull - private static CalculatorKeyboard getKeyboard() { - return CalculatorLocatorImpl.getInstance().getKeyboard(); - } - - /* - ********************************************************************** - * - * STATIC CLASSES - * - ********************************************************************** - */ - - private static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor { - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { - final boolean result; - - if (dragDirection == DragDirection.left) { - getKeyboard().roundBracketsButtonPressed(); - result = true; - } else { - result = new DigitButtonDragProcessor(getKeyboard()).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); - } - - return result; - } - } - - private static class VarsDragProcessor implements SimpleOnDragListener.DragProcessor { - - @NotNull - private Context context; - - private VarsDragProcessor(Context context) { - this.context = context; - } - - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, - @NotNull DragButton dragButton, - @NotNull Point2d startPoint2d, - @NotNull MotionEvent motionEvent) { - boolean result = false; - - if (dragDirection == DragDirection.up) { - CalculatorActivityLauncher.createVar(context, CalculatorLocatorImpl.getInstance().getDisplay()); - result = true; - } - - return result; - } - } - - private static class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor { - - @NotNull - private final DigitButtonDragProcessor processor; - - @NotNull - private final Context context; - - private AngleUnitsChanger(@NotNull Context context) { - this.context = context; - this.processor = new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getKeyboard()); - } - - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, - @NotNull DragButton dragButton, - @NotNull Point2d startPoint2d, - @NotNull MotionEvent motionEvent) { - boolean result = false; - - if (dragButton instanceof AngleUnitsButton) { - if (dragDirection != DragDirection.left) { - final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection); - if (directionText != null) { - try { - - final AngleUnit angleUnits = AngleUnit.valueOf(directionText); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - - AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits); - - Toast.makeText(context, context.getString(R.string.c_angle_units_changed_to, angleUnits.name()), Toast.LENGTH_LONG).show(); - - result = true; - } catch (IllegalArgumentException e) { - Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText); - } - } - } else if (dragDirection == DragDirection.left) { - result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); - } - } - - return result; - } - } - - private static class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor { - - @NotNull - private final Context context; - - private NumeralBasesChanger(@NotNull Context context) { - this.context = context; - } - - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, - @NotNull DragButton dragButton, - @NotNull Point2d startPoint2d, - @NotNull MotionEvent motionEvent) { - boolean result = false; - - if (dragButton instanceof NumeralBasesButton) { - final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection); - if (directionText != null) { - try { - - final NumeralBase numeralBase = NumeralBase.valueOf(directionText); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - AndroidCalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase); - - Toast.makeText(context, context.getString(R.string.c_numeral_base_changed_to, numeralBase.name()), Toast.LENGTH_LONG).show(); - - result = true; - } catch (IllegalArgumentException e) { - Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText); - } - } - } - - return result; - } - } -} - +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Bundle; +import android.os.Vibrator; +import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.*; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.Toast; +import com.actionbarsherlock.app.SherlockFragment; +import jscl.AngleUnit; +import jscl.NumeralBase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.AndroidUtils; +import org.solovyev.android.calculator.history.CalculatorHistoryState; +import org.solovyev.android.calculator.model.AndroidCalculatorEngine; +import org.solovyev.android.calculator.view.AngleUnitsButton; +import org.solovyev.android.calculator.view.NumeralBasesButton; +import org.solovyev.android.calculator.view.OnDragListenerVibrator; +import org.solovyev.android.history.HistoryDragProcessor; +import org.solovyev.android.view.ColorButton; +import org.solovyev.android.view.drag.*; +import org.solovyev.common.Announcer; +import org.solovyev.common.math.Point2d; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +/** + * User: Solovyev_S + * Date: 25.09.12 + * Time: 12:25 + */ +public class CalculatorKeyboardFragment extends SherlockFragment implements SharedPreferences.OnSharedPreferenceChangeListener { + + @Nullable + private Vibrator vibrator; + + @NotNull + private final Announcer dpclRegister = new Announcer(DragPreferencesChangeListener.class); + + @NotNull + private NumeralBaseButtons numeralBaseButtons = new NumeralBaseButtons(); + + @NotNull + private CalculatorPreferences.Gui.Theme theme; + + @NotNull + private CalculatorPreferences.Gui.Layout layout; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + vibrator = (Vibrator) this.getActivity().getSystemService(Activity.VIBRATOR_SERVICE); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); + + preferences.registerOnSharedPreferenceChangeListener(this); + + layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences); + theme = CalculatorPreferences.Gui.theme.getPreferenceNoError(preferences); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.calc_keyboard, container, false); + } + + @Override + public void onViewCreated(View root, Bundle savedInstanceState) { + super.onViewCreated(root, savedInstanceState); + + dpclRegister.clear(); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); + final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, this.getActivity()); + + setOnDragListeners(root, dragPreferences, preferences); + + final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor(getCalculator()), dragPreferences), vibrator, preferences); + final DragButton historyButton = getButton(root, R.id.historyButton); + if (historyButton != null) { + historyButton.setOnDragListener(historyOnDragListener); + } + + final DragButton subtractionButton = getButton(root, R.id.subtractionButton); + if (subtractionButton != null) { + subtractionButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new SimpleOnDragListener.DragProcessor() { + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { + if (dragDirection == DragDirection.down) { + CalculatorActivity.operatorsButtonClickHandler(getActivity()); + return true; + } + return false; + } + }, dragPreferences), vibrator, preferences)); + } + + + final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(), dragPreferences), vibrator, preferences); + + final DragButton rightButton = getButton(root, R.id.rightButton); + if (rightButton != null) { + rightButton.setOnDragListener(toPositionOnDragListener); + } + + final DragButton leftButton = getButton(root, R.id.leftButton); + if (leftButton != null) { + leftButton.setOnDragListener(toPositionOnDragListener); + } + + final DragButton equalsButton = getButton(root, R.id.equalsButton); + if (equalsButton != null) { + equalsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new EvalDragProcessor(), dragPreferences), vibrator, preferences)); + } + + final AngleUnitsButton angleUnitsButton = (AngleUnitsButton) getButton(root, R.id.sixDigitButton); + if (angleUnitsButton != null) { + angleUnitsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new AngleUnitsChanger(this.getActivity()), dragPreferences), vibrator, preferences)); + } + + final NumeralBasesButton clearButton = (NumeralBasesButton) getButton(root, R.id.clearButton); + if (clearButton != null) { + clearButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new NumeralBasesChanger(this.getActivity()), dragPreferences), vibrator, preferences)); + } + + final DragButton varsButton = getButton(root, R.id.varsButton); + if (varsButton != null) { + varsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new VarsDragProcessor(this.getActivity()), dragPreferences), vibrator, preferences)); + } + + final DragButton roundBracketsButton = getButton(root, R.id.roundBracketsButton); + if (roundBracketsButton != null) { + roundBracketsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new RoundBracketsDragProcessor(), dragPreferences), vibrator, preferences)); + } + + if (layout == CalculatorPreferences.Gui.Layout.simple) { + toggleButtonDirectionText(root, R.id.oneDigitButton, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(root, R.id.twoDigitButton, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(root, R.id.threeDigitButton, false, DragDirection.up, DragDirection.down); + + toggleButtonDirectionText(root, R.id.sixDigitButton, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(root, R.id.sevenDigitButton, false, DragDirection.left, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(root, R.id.eightDigitButton, false, DragDirection.left, DragDirection.up, DragDirection.down); + + toggleButtonDirectionText(root, R.id.clearButton, false, DragDirection.left, DragDirection.up, DragDirection.down); + + toggleButtonDirectionText(root, R.id.fourDigitButton, false, DragDirection.down); + toggleButtonDirectionText(root, R.id.fiveDigitButton, false, DragDirection.down); + + toggleButtonDirectionText(root, R.id.nineDigitButton, false, DragDirection.left); + + toggleButtonDirectionText(root, R.id.multiplicationButton, false, DragDirection.left); + toggleButtonDirectionText(root, R.id.plusButton, false, DragDirection.down, DragDirection.up); + } + + numeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences); + + fixThemeParameters(true, theme, this.getView()); + + toggleEqualsButton(preferences, this.getActivity(), theme, root); + + initMultiplicationButton(); + } + + @Nullable + private T getButton(@NotNull View root, int buttonId) { + return (T) root.findViewById(buttonId); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); + + preferences.unregisterOnSharedPreferenceChangeListener(this); + } + + public static void fixThemeParameters(boolean fixMagicFlames, + @NotNull CalculatorPreferences.Gui.Theme theme, + @NotNull View root) { + if (theme.getThemeType() == CalculatorPreferences.Gui.ThemeType.metro) { + + if (fixMagicFlames) { + // for metro themes we should turn off magic flames + AndroidUtils.processViewsOfType(root, ColorButton.class, new AndroidUtils.ViewProcessor() { + @Override + public void process(@NotNull ColorButton colorButton) { + colorButton.setDrawMagicFlame(false); + } + }); + } + } + } + + private void initMultiplicationButton() { + final View multiplicationButton = getView().findViewById(R.id.multiplicationButton); + if ( multiplicationButton instanceof Button) { + ((Button) multiplicationButton).setText(CalculatorLocatorImpl.getInstance().getEngine().getMultiplicationSign()); + } + } + +/* private static void setMarginsForView(@Nullable View view, int marginLeft, int marginBottom, @NotNull Context context) { + // IMPORTANT: this is workaround for probably android bug + // currently margin values set in styles are not applied for some reasons to the views (using include tag) => set them manually + + if (view != null) { + final DisplayMetrics dm = context.getResources().getDisplayMetrics(); + if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) { + final LinearLayout.LayoutParams oldParams = (LinearLayout.LayoutParams) view.getLayoutParams(); + final LinearLayout.LayoutParams newParams = new LinearLayout.LayoutParams(oldParams.width, oldParams.height, oldParams.weight); + newParams.setMargins(AndroidUtils.toPixels(dm, marginLeft), 0, 0, AndroidUtils.toPixels(dm, marginBottom)); + view.setLayoutParams(newParams); + } + } + }*/ + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + private synchronized void setOnDragListeners(@NotNull View root, @NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) { + final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(getKeyboard()), dragPreferences), vibrator, preferences); + + final List dragButtonIds = new ArrayList(); + final List buttonIds = new ArrayList(); + + for (Field field : R.id.class.getDeclaredFields()) { + int modifiers = field.getModifiers(); + if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { + try { + int viewId = field.getInt(R.id.class); + final View view = root.findViewById(viewId); + if (view instanceof DragButton) { + dragButtonIds.add(viewId); + } + if (view instanceof Button) { + buttonIds.add(viewId); + } + } catch (IllegalAccessException e) { + Log.e(R.id.class.getName(), e.getMessage()); + } + } + } + + for (Integer dragButtonId : dragButtonIds) { + final DragButton button = getButton(root, dragButtonId); + if (button != null) { + button.setOnDragListener(onDragListener); + } + } + } + + + @NotNull + private SimpleOnDragListener newOnDragListener(@NotNull SimpleOnDragListener.DragProcessor dragProcessor, + @NotNull SimpleOnDragListener.Preferences dragPreferences) { + final SimpleOnDragListener onDragListener = new SimpleOnDragListener(dragProcessor, dragPreferences); + dpclRegister.addListener(onDragListener); + return onDragListener; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + if (key != null && key.startsWith("org.solovyev.android.calculator.DragButtonCalibrationActivity")) { + dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this.getActivity())); + } + + if (AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key)) { + numeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences); + } + + if ( CalculatorPreferences.Gui.showEqualsButton.getKey().equals(key) ) { + toggleEqualsButton(preferences, this.getActivity(), theme, getView()); + } + + if ( AndroidCalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) { + initMultiplicationButton(); + } + } + + private void toggleButtonDirectionText(@NotNull View root, int id, boolean showDirectionText, @NotNull DragDirection... dragDirections) { + final View v = getButton(root, id); + if (v instanceof DirectionDragButton ) { + final DirectionDragButton button = (DirectionDragButton)v; + for (DragDirection dragDirection : dragDirections) { + button.showDirectionText(showDirectionText, dragDirection); + } + } + } + + public static void toggleEqualsButton(@Nullable SharedPreferences preferences, + @NotNull Activity activity, + @NotNull CalculatorPreferences.Gui.Theme theme, + @NotNull View root) { + preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(activity) : preferences; + + if (AndroidUtils.getScreenOrientation(activity) == Configuration.ORIENTATION_PORTRAIT || !CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { + final Display display = activity.getWindowManager().getDefaultDisplay(); + + final DragButton button = (DragButton)activity.findViewById(R.id.equalsButton); + if (CalculatorPreferences.Gui.showEqualsButton.getPreference(preferences)) { + button.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.FILL_PARENT, 1f)); + if (display.getWidth() <= 480) { + // mobile phones + final AndroidCalculatorDisplayView calculatorDisplayView = getCalculatorDisplayView(); + if (calculatorDisplayView != null) { + calculatorDisplayView.setBackgroundDrawable(null); + } + } + } else { + button.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.FILL_PARENT, 0f)); + if (display.getWidth() <= 480) { + // mobile phones + final AndroidCalculatorDisplayView calculatorDisplayView = getCalculatorDisplayView(); + if (calculatorDisplayView != null) { + calculatorDisplayView.setBackgroundDrawable(activity.getResources().getDrawable(R.drawable.equals9)); + } + } + } + + fixThemeParameters(false, theme, root); + } + } + + + @Nullable + private static AndroidCalculatorDisplayView getCalculatorDisplayView() { + return (AndroidCalculatorDisplayView) CalculatorLocatorImpl.getInstance().getDisplay().getView(); + } + + @NotNull + private Calculator getCalculator() { + return CalculatorLocatorImpl.getInstance().getCalculator(); + } + + @NotNull + private static CalculatorKeyboard getKeyboard() { + return CalculatorLocatorImpl.getInstance().getKeyboard(); + } + + /* + ********************************************************************** + * + * STATIC CLASSES + * + ********************************************************************** + */ + + private static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor { + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { + final boolean result; + + if (dragDirection == DragDirection.left) { + getKeyboard().roundBracketsButtonPressed(); + result = true; + } else { + result = new DigitButtonDragProcessor(getKeyboard()).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); + } + + return result; + } + } + + private static class VarsDragProcessor implements SimpleOnDragListener.DragProcessor { + + @NotNull + private Context context; + + private VarsDragProcessor(Context context) { + this.context = context; + } + + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, + @NotNull DragButton dragButton, + @NotNull Point2d startPoint2d, + @NotNull MotionEvent motionEvent) { + boolean result = false; + + if (dragDirection == DragDirection.up) { + CalculatorActivityLauncher.createVar(context, CalculatorLocatorImpl.getInstance().getDisplay()); + result = true; + } + + return result; + } + } + + private static class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor { + + @NotNull + private final DigitButtonDragProcessor processor; + + @NotNull + private final Context context; + + private AngleUnitsChanger(@NotNull Context context) { + this.context = context; + this.processor = new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getKeyboard()); + } + + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, + @NotNull DragButton dragButton, + @NotNull Point2d startPoint2d, + @NotNull MotionEvent motionEvent) { + boolean result = false; + + if (dragButton instanceof AngleUnitsButton) { + if (dragDirection != DragDirection.left) { + final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection); + if (directionText != null) { + try { + + final AngleUnit angleUnits = AngleUnit.valueOf(directionText); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits); + + Toast.makeText(context, context.getString(R.string.c_angle_units_changed_to, angleUnits.name()), Toast.LENGTH_LONG).show(); + + result = true; + } catch (IllegalArgumentException e) { + Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText); + } + } + } else if (dragDirection == DragDirection.left) { + result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); + } + } + + return result; + } + } + + private static class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor { + + @NotNull + private final Context context; + + private NumeralBasesChanger(@NotNull Context context) { + this.context = context; + } + + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, + @NotNull DragButton dragButton, + @NotNull Point2d startPoint2d, + @NotNull MotionEvent motionEvent) { + boolean result = false; + + if (dragButton instanceof NumeralBasesButton) { + final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection); + if (directionText != null) { + try { + + final NumeralBase numeralBase = NumeralBase.valueOf(directionText); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + AndroidCalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase); + + Toast.makeText(context, context.getString(R.string.c_numeral_base_changed_to, numeralBase.name()), Toast.LENGTH_LONG).show(); + + result = true; + } catch (IllegalArgumentException e) { + Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText); + } + } + } + + return result; + } + } +} + diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorMenu.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorMenu.java index 6302f96a..9deb8812 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorMenu.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorMenu.java @@ -1,75 +1,75 @@ -package org.solovyev.android.calculator; - -import android.app.Activity; -import android.content.Context; -import android.util.Log; -import android.view.MenuItem; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; -import org.solovyev.android.menu.LabeledMenuItem; - -/** - * User: serso - * Date: 4/23/12 - * Time: 2:25 PM - */ -enum CalculatorMenu implements LabeledMenuItem { - - settings(R.string.c_settings) { - @Override - public void onClick(@NotNull MenuItem data, @NotNull Context context) { - CalculatorActivityLauncher.showSettings(context); - } - }, - - history(R.string.c_history) { - @Override - public void onClick(@NotNull MenuItem data, @NotNull Context context) { - CalculatorActivityLauncher.showHistory(context); - } - }, - - about(R.string.c_about) { - @Override - public void onClick(@NotNull MenuItem data, @NotNull Context context) { - CalculatorActivityLauncher.showAbout(context); - } - }, - - help(R.string.c_help) { - @Override - public void onClick(@NotNull MenuItem data, @NotNull Context context) { - CalculatorActivityLauncher.showHelp(context); - } - }, - - conversion_tool(R.string.c_conversion_tool) { - @Override - public void onClick(@NotNull MenuItem data, @NotNull Context context) { - new NumeralBaseConverterDialog(null).show(context); - } - }, - - exit(R.string.c_exit) { - @Override - public void onClick(@NotNull MenuItem data, @NotNull Context context) { - if (context instanceof Activity) { - ((Activity) context).finish(); - } else { - Log.e(CalculatorActivity.TAG, "Activity menu used with context"); - } - } - }; - - private final int captionResId; - - private CalculatorMenu(int captionResId) { - this.captionResId = captionResId; - } - - @NotNull - @Override - public String getCaption(@NotNull Context context) { - return context.getString(captionResId); - } -} +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.content.Context; +import android.util.Log; +import com.actionbarsherlock.view.MenuItem; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; +import org.solovyev.android.menu.LabeledMenuItem; + +/** + * User: serso + * Date: 4/23/12 + * Time: 2:25 PM + */ +enum CalculatorMenu implements LabeledMenuItem { + + settings(R.string.c_settings) { + @Override + public void onClick(@NotNull MenuItem data, @NotNull Context context) { + CalculatorActivityLauncher.showSettings(context); + } + }, + + history(R.string.c_history) { + @Override + public void onClick(@NotNull MenuItem data, @NotNull Context context) { + CalculatorActivityLauncher.showHistory(context); + } + }, + + about(R.string.c_about) { + @Override + public void onClick(@NotNull MenuItem data, @NotNull Context context) { + CalculatorActivityLauncher.showAbout(context); + } + }, + + help(R.string.c_help) { + @Override + public void onClick(@NotNull MenuItem data, @NotNull Context context) { + CalculatorActivityLauncher.showHelp(context); + } + }, + + conversion_tool(R.string.c_conversion_tool) { + @Override + public void onClick(@NotNull MenuItem data, @NotNull Context context) { + new NumeralBaseConverterDialog(null).show(context); + } + }, + + exit(R.string.c_exit) { + @Override + public void onClick(@NotNull MenuItem data, @NotNull Context context) { + if (context instanceof Activity) { + ((Activity) context).finish(); + } else { + Log.e(CalculatorActivity.TAG, "Activity menu used with context"); + } + } + }; + + private final int captionResId; + + private CalculatorMenu(int captionResId) { + this.captionResId = captionResId; + } + + @NotNull + @Override + public String getCaption(@NotNull Context context) { + return context.getString(captionResId); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractCalculatorHistoryFragment.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractCalculatorHistoryFragment.java index 3ec0ded2..b2c7cf35 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractCalculatorHistoryFragment.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/AbstractCalculatorHistoryFragment.java @@ -1,262 +1,285 @@ -/* - * 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.Activity; -import android.content.Context; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; -import com.actionbarsherlock.app.SherlockListFragment; -import com.google.ads.AdView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.ads.AdsController; -import org.solovyev.android.calculator.CalculatorLocatorImpl; -import org.solovyev.android.calculator.R; -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.menu.AMenuBuilder; -import org.solovyev.android.menu.MenuImpl; -import org.solovyev.common.collections.CollectionsUtils; -import org.solovyev.common.equals.Equalizer; -import org.solovyev.common.filter.Filter; -import org.solovyev.common.filter.FilterRule; -import org.solovyev.common.filter.FilterRulesChain; -import org.solovyev.common.text.StringUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * User: serso - * Date: 10/15/11 - * Time: 1:13 PM - */ -public abstract class AbstractCalculatorHistoryFragment extends SherlockListFragment { - - - public static final Comparator COMPARATOR = new Comparator() { - @Override - public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) { - if (state1.isSaved() == state2.isSaved()) { - long l = state2.getTime() - state1.getTime(); - return l > 0l ? 1 : (l < 0l ? -1 : 0); - } else if (state1.isSaved()) { - return -1; - } else if (state2.isSaved()) { - return 1; - } - return 0; - } - }; - - - @NotNull - private ArrayAdapter adapter; - - @Nullable - private AdView adView; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.history_activity, null); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - adView = AdsController.getInstance().inflateAd(this.getActivity()); - - adapter = new HistoryArrayAdapter(this.getActivity(), getLayoutId(), R.id.history_item, new ArrayList()); - setListAdapter(adapter); - - final ListView lv = getListView(); - lv.setTextFilterEnabled(true); - - lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { - public void onItemClick(final AdapterView parent, - final View view, - final int position, - final long id) { - - useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position), getActivity()); - } - }); - - lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { - @Override - public boolean onItemLongClick(AdapterView parent, View view, final int position, long id) { - final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position); - - final Context context = getActivity(); - - final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter); - - final List menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values()); - - if (historyState.isSaved()) { - menuItems.remove(HistoryItemMenuItem.save); - } else { - if (isAlreadySaved(historyState)) { - menuItems.remove(HistoryItemMenuItem.save); - } - menuItems.remove(HistoryItemMenuItem.remove); - menuItems.remove(HistoryItemMenuItem.edit); - } - - if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) { - menuItems.remove(HistoryItemMenuItem.copy_result); - } - - final AMenuBuilder menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems)); - menuBuilder.create(data).show(); - - return true; - } - }); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public void onDestroy() { - if ( this.adView != null ) { - this.adView.destroy(); - } - super.onDestroy(); - } - - protected abstract int getLayoutId(); - - @Override - public void onResume() { - super.onResume(); - - final List historyList = getHistoryList(); - try { - this.adapter.setNotifyOnChange(false); - this.adapter.clear(); - for (CalculatorHistoryState historyState : historyList) { - this.adapter.add(historyState); - } - } finally { - this.adapter.setNotifyOnChange(true); - } - - this.adapter.notifyDataSetChanged(); - } - - public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) { - assert !historyState.isSaved(); - - boolean result = false; - try { - historyState.setSaved(true); - if ( CollectionsUtils.contains(historyState, CalculatorLocatorImpl.getInstance().getHistory().getSavedHistory(), new Equalizer() { - @Override - public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) { - return first != null && second != null && - first.getTime() == second.getTime() && - first.getDisplayState().equals(second.getDisplayState()) && - first.getEditorState().equals(second.getEditorState()); - } - }) ) { - result = true; - } - } finally { - historyState.setSaved(false); - } - return result; - } - - public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState, @NotNull Activity activity) { - final EditorHistoryState editorState = historyState.getEditorState(); - CalculatorLocatorImpl.getInstance().getEditor().setText(StringUtils.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition()); - - activity.finish(); - } - - @NotNull - private List getHistoryList() { - final List calculatorHistoryStates = getHistoryItems(); - - Collections.sort(calculatorHistoryStates, COMPARATOR); - - final FilterRulesChain filterRulesChain = new FilterRulesChain(); - filterRulesChain.addFilterRule(new FilterRule() { - @Override - public boolean isFiltered(CalculatorHistoryState object) { - return object == null || StringUtils.isEmpty(object.getEditorState().getText()); - } - }); - - new Filter(filterRulesChain).filter(calculatorHistoryStates.iterator()); - - return calculatorHistoryStates; - } - - @NotNull - protected abstract List getHistoryItems(); - - @NotNull - public static String getHistoryText(@NotNull CalculatorHistoryState state) { - final StringBuilder result = new StringBuilder(); - result.append(state.getEditorState().getText()); - result.append(getIdentitySign(state.getDisplayState().getJsclOperation())); - final String expressionResult = state.getDisplayState().getEditorState().getText(); - if (expressionResult != null) { - result.append(expressionResult); - } - return result.toString(); - } - - @NotNull - private static String getIdentitySign(@NotNull JsclOperation jsclOperation) { - return jsclOperation == JsclOperation.simplify ? "≡" : "="; - } - - // todo serso: menu -/* @Override - public boolean onCreateOptionsMenu(android.view.Menu menu) { - final MenuInflater menuInflater = getMenuInflater(); - menuInflater.inflate(R.menu.history_menu, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - boolean result; - - switch (item.getItemId()) { - case R.id.history_menu_clear_history: - clearHistory(); - result = true; - break; - default: - result = super.onOptionsItemSelected(item); - } - - return result; - }*/ - - protected abstract void clearHistory(); - - @NotNull - protected ArrayAdapter getAdapter() { - return adapter; - } -} +/* + * 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.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import com.actionbarsherlock.app.SherlockListFragment; +import com.google.ads.AdView; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.ads.AdsController; +import org.solovyev.android.calculator.*; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.menu.AMenuBuilder; +import org.solovyev.android.menu.MenuImpl; +import org.solovyev.common.collections.CollectionsUtils; +import org.solovyev.common.equals.Equalizer; +import org.solovyev.common.filter.Filter; +import org.solovyev.common.filter.FilterRule; +import org.solovyev.common.filter.FilterRulesChain; +import org.solovyev.common.text.StringUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * User: serso + * Date: 10/15/11 + * Time: 1:13 PM + */ +public abstract class AbstractCalculatorHistoryFragment extends SherlockListFragment implements CalculatorEventListener { + + + public static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) { + if (state1.isSaved() == state2.isSaved()) { + long l = state2.getTime() - state1.getTime(); + return l > 0l ? 1 : (l < 0l ? -1 : 0); + } else if (state1.isSaved()) { + return -1; + } else if (state2.isSaved()) { + return 1; + } + return 0; + } + }; + + + @NotNull + private ArrayAdapter adapter; + + @Nullable + private AdView adView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.history_fragment, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + adapter = new HistoryArrayAdapter(this.getActivity(), getItemLayoutId(), R.id.history_item, new ArrayList()); + setListAdapter(adapter); + + final ListView lv = getListView(); + lv.setTextFilterEnabled(true); + + lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(final AdapterView parent, + final View view, + final int position, + final long id) { + + useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position)); + } + }); + + lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, final int position, long id) { + final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position); + + final Context context = getActivity(); + + final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter); + + final List menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values()); + + if (historyState.isSaved()) { + menuItems.remove(HistoryItemMenuItem.save); + } else { + if (isAlreadySaved(historyState)) { + menuItems.remove(HistoryItemMenuItem.save); + } + menuItems.remove(HistoryItemMenuItem.remove); + menuItems.remove(HistoryItemMenuItem.edit); + } + + if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) { + menuItems.remove(HistoryItemMenuItem.copy_result); + } + + final AMenuBuilder menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems)); + menuBuilder.create(data).show(); + + return true; + } + }); + + adView = AdsController.getInstance().inflateAd(this.getActivity(), (ViewGroup)view.findViewById(R.id.ad_parent_view), R.id.ad_parent_view); + } + + @Override + public void onDestroy() { + if ( this.adView != null ) { + this.adView.destroy(); + } + super.onDestroy(); + } + + protected abstract int getItemLayoutId(); + + @Override + public void onResume() { + super.onResume(); + + CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener(this); + + updateAdapter(); + } + + @Override + public void onPause() { + super.onPause(); + + CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener(this); + + } + + private void updateAdapter() { + final List historyList = getHistoryList(); + + final ArrayAdapter adapter = getAdapter(); + try { + adapter.setNotifyOnChange(false); + adapter.clear(); + for (CalculatorHistoryState historyState : historyList) { + adapter.add(historyState); + } + } finally { + adapter.setNotifyOnChange(true); + } + + adapter.notifyDataSetChanged(); + } + + public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) { + assert !historyState.isSaved(); + + boolean result = false; + try { + historyState.setSaved(true); + if ( CollectionsUtils.contains(historyState, CalculatorLocatorImpl.getInstance().getHistory().getSavedHistory(), new Equalizer() { + @Override + public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) { + return first != null && second != null && + first.getTime() == second.getTime() && + first.getDisplayState().equals(second.getDisplayState()) && + first.getEditorState().equals(second.getEditorState()); + } + }) ) { + result = true; + } + } finally { + historyState.setSaved(false); + } + return result; + } + + public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState) { + CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_history_state, historyState); + } + + @NotNull + private List getHistoryList() { + final List calculatorHistoryStates = getHistoryItems(); + + Collections.sort(calculatorHistoryStates, COMPARATOR); + + final FilterRulesChain filterRulesChain = new FilterRulesChain(); + filterRulesChain.addFilterRule(new FilterRule() { + @Override + public boolean isFiltered(CalculatorHistoryState object) { + return object == null || StringUtils.isEmpty(object.getEditorState().getText()); + } + }); + + new Filter(filterRulesChain).filter(calculatorHistoryStates.iterator()); + + return calculatorHistoryStates; + } + + @NotNull + protected abstract List getHistoryItems(); + + @NotNull + public static String getHistoryText(@NotNull CalculatorHistoryState state) { + final StringBuilder result = new StringBuilder(); + result.append(state.getEditorState().getText()); + result.append(getIdentitySign(state.getDisplayState().getJsclOperation())); + final String expressionResult = state.getDisplayState().getEditorState().getText(); + if (expressionResult != null) { + result.append(expressionResult); + } + return result.toString(); + } + + @NotNull + private static String getIdentitySign(@NotNull JsclOperation jsclOperation) { + return jsclOperation == JsclOperation.simplify ? "≡" : "="; + } + + // todo serso: menu +/* @Override + public boolean onCreateOptionsMenu(android.view.Menu menu) { + final MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.history_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + boolean result; + + switch (item.getItemId()) { + case R.id.history_menu_clear_history: + clearHistory(); + result = true; + break; + default: + result = super.onOptionsItemSelected(item); + } + + return result; + }*/ + + protected abstract void clearHistory(); + + @NotNull + protected ArrayAdapter getAdapter() { + return adapter; + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + if ( calculatorEventType == CalculatorEventType.history_state_added ) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + updateAdapter(); + } + }); + } + } +} 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 54adaa44..486e5a41 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 @@ -1,39 +1,39 @@ -/* - * 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 org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorLocatorImpl; -import org.solovyev.android.calculator.R; - -import java.util.ArrayList; -import java.util.List; - -/** - * User: serso - * Date: 12/18/11 - * Time: 7:39 PM - */ -public class CalculatorHistoryFragment extends AbstractCalculatorHistoryFragment { - - @Override - protected int getLayoutId() { - return R.layout.history; - } - - @NotNull - @Override - protected List getHistoryItems() { - return new ArrayList(CalculatorLocatorImpl.getInstance().getHistory().getStates()); - } - - @Override - protected void clearHistory() { - CalculatorLocatorImpl.getInstance().getHistory().clear(); - getAdapter().clear(); - } -} +/* + * 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 org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.CalculatorLocatorImpl; +import org.solovyev.android.calculator.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * User: serso + * Date: 12/18/11 + * Time: 7:39 PM + */ +public class CalculatorHistoryFragment extends AbstractCalculatorHistoryFragment { + + @Override + protected int getItemLayoutId() { + return R.layout.history; + } + + @NotNull + @Override + protected List getHistoryItems() { + return new ArrayList(CalculatorLocatorImpl.getInstance().getHistory().getStates()); + } + + @Override + protected void clearHistory() { + CalculatorLocatorImpl.getInstance().getHistory().clear(); + getAdapter().clear(); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragmentActivity.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragmentActivity.java index b2b50849..538e8cdd 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragmentActivity.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryFragmentActivity.java @@ -1,40 +1,64 @@ -/* - * 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.os.Bundle; -import com.actionbarsherlock.app.SherlockFragmentActivity; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorActivityHelper; -import org.solovyev.android.calculator.CalculatorApplication; -import org.solovyev.android.calculator.R; - -/** - * User: serso - * Date: 12/18/11 - * Time: 7:37 PM - */ -public class CalculatorHistoryFragmentActivity extends SherlockFragmentActivity { - - @NotNull - private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createCalculatorHistoryHelper(R.layout.history_activity); - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - activityHelper.onCreate(this, savedInstanceState); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - activityHelper.onSaveInstanceState(this, outState); - } -} +/* + * 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.os.Bundle; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.*; + +/** + * User: serso + * Date: 12/18/11 + * Time: 7:37 PM + */ +public class CalculatorHistoryFragmentActivity extends SherlockFragmentActivity implements CalculatorEventListener { + + @NotNull + private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createCalculatorHistoryHelper(R.layout.main_empty); + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + activityHelper.onCreate(this, savedInstanceState); + + activityHelper.addTab(this, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.id.main_layout); + activityHelper.addTab(this, "saved_history", CalculatorSavedHistoryFragment.class, null, R.string.c_saved_history, R.id.main_layout); + + CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener(this); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + activityHelper.onSaveInstanceState(this, outState); + } + + @Override + protected void onResume() { + super.onResume(); + + activityHelper.onResume(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener(this); + } + + @Override + public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { + if ( calculatorEventType == CalculatorEventType.use_history_state ) { + this.finish(); + } + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorSavedHistoryFragment.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorSavedHistoryFragment.java index 28b85fbe..da100d82 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorSavedHistoryFragment.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/CalculatorSavedHistoryFragment.java @@ -1,39 +1,39 @@ -/* - * 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 org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorLocatorImpl; -import org.solovyev.android.calculator.R; - -import java.util.ArrayList; -import java.util.List; - -/** - * User: serso - * Date: 12/18/11 - * Time: 7:40 PM - */ -public class CalculatorSavedHistoryFragment extends AbstractCalculatorHistoryFragment { - - @Override - protected int getLayoutId() { - return R.layout.saved_history; - } - - @NotNull - @Override - protected List getHistoryItems() { - return new ArrayList(CalculatorLocatorImpl.getInstance().getHistory().getSavedHistory()); - } - - @Override - protected void clearHistory() { - CalculatorLocatorImpl.getInstance().getHistory().clearSavedHistory(); - getAdapter().clear(); - } -} +/* + * 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 org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.CalculatorLocatorImpl; +import org.solovyev.android.calculator.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * User: serso + * Date: 12/18/11 + * Time: 7:40 PM + */ +public class CalculatorSavedHistoryFragment extends AbstractCalculatorHistoryFragment { + + @Override + protected int getItemLayoutId() { + return R.layout.saved_history; + } + + @NotNull + @Override + protected List getHistoryItems() { + return new ArrayList(CalculatorLocatorImpl.getInstance().getHistory().getSavedHistory()); + } + + @Override + protected void clearHistory() { + CalculatorLocatorImpl.getInstance().getHistory().clearSavedHistory(); + getAdapter().clear(); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java index 4097d4ee..0a93fac8 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/history/HistoryItemMenuItem.java @@ -1,155 +1,151 @@ -/* - * 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.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.text.ClipboardManager; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.EditText; -import android.widget.TextView; -import android.widget.Toast; -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.CalculatorLocatorImpl; -import org.solovyev.android.calculator.R; -import org.solovyev.android.menu.LabeledMenuItem; -import org.solovyev.common.text.StringUtils; - -/** -* User: serso -* Date: 12/18/11 -* Time: 3:09 PM -*/ -public enum HistoryItemMenuItem implements LabeledMenuItem { - - use(R.string.c_use) { - @Override - public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { - if (context instanceof Activity) { - AbstractCalculatorHistoryFragment.useHistoryItem(data.getHistoryState(), (Activity) context); - } else { - Log.e(HistoryItemMenuItem.class.getName(), AbstractCalculatorHistoryFragment.class + " must be passed as context!"); - } - } - }, - - copy_expression(R.string.c_copy_expression) { - @Override - public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { - final CalculatorHistoryState calculatorHistoryState = data.getHistoryState(); - final String text = calculatorHistoryState.getEditorState().getText(); - if (!StringUtils.isEmpty(text)) { - final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); - clipboard.setText(text); - Toast.makeText(context, context.getText(R.string.c_expression_copied), Toast.LENGTH_SHORT).show(); - } - } - }, - - copy_result(R.string.c_copy_result) { - @Override - public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { - final CalculatorHistoryState calculatorHistoryState = data.getHistoryState(); - final String text = calculatorHistoryState.getDisplayState().getEditorState().getText(); - if (!StringUtils.isEmpty(text)) { - final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); - clipboard.setText(text); - Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); - } - } - }, - - save(R.string.c_save) { - @Override - public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) { - final CalculatorHistoryState historyState = data.getHistoryState(); - if (!historyState.isSaved()) { - createEditHistoryDialog(data, context, true); - } else { - Toast.makeText(context, context.getText(R.string.c_history_already_saved), Toast.LENGTH_LONG).show(); - } - } - }, - - edit(R.string.c_edit) { - @Override - public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) { - final CalculatorHistoryState historyState = data.getHistoryState(); - if (historyState.isSaved()) { - createEditHistoryDialog(data, context, false); - } else { - Toast.makeText(context, context.getText(R.string.c_history_must_be_saved), Toast.LENGTH_LONG).show(); - } - } - }, - - remove(R.string.c_remove) { - @Override - public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { - final CalculatorHistoryState historyState = data.getHistoryState(); - if (historyState.isSaved()) { - data.getAdapter().remove(historyState); - CalculatorLocatorImpl.getInstance().getHistory().removeSavedHistory(historyState); - Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show(); - data.getAdapter().notifyDataSetChanged(); - } - } - }; - - private static void createEditHistoryDialog(@NotNull final HistoryItemMenuData data, @NotNull final Context context, final boolean save) { - final CalculatorHistoryState historyState = data.getHistoryState(); - - final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - final View editView = layoutInflater.inflate(R.layout.history_edit, null); - final TextView historyExpression = (TextView)editView.findViewById(R.id.history_edit_expression); - historyExpression.setText(AbstractCalculatorHistoryFragment.getHistoryText(historyState)); - - final EditText comment = (EditText)editView.findViewById(R.id.history_edit_comment); - comment.setText(historyState.getComment()); - - final AlertDialog.Builder builder = new AlertDialog.Builder(context) - .setTitle(save ? R.string.c_save_history : R.string.c_edit_history) - .setCancelable(true) - .setNegativeButton(R.string.c_cancel, null) - .setPositiveButton(R.string.c_save, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (save) { - final CalculatorHistoryState savedHistoryItem = CalculatorLocatorImpl.getInstance().getHistory().addSavedState(historyState); - savedHistoryItem.setComment(comment.getText().toString()); - CalculatorLocatorImpl.getInstance().getHistory().save(); - // we don't need to add element to the adapter as adapter of another activity must be updated and not this - //data.getAdapter().add(savedHistoryItem); - } else { - historyState.setComment(comment.getText().toString()); - CalculatorLocatorImpl.getInstance().getHistory().save(); - } - data.getAdapter().notifyDataSetChanged(); - Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show(); - } - }) - .setView(editView); - - builder.create().show(); - } - - private final int captionId; - - private HistoryItemMenuItem(int captionId) { - this.captionId = captionId; - } - - @NotNull - @Override - public String getCaption(@NotNull Context context) { - return context.getString(captionId); - } -} +/* + * 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.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.text.ClipboardManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.CalculatorLocatorImpl; +import org.solovyev.android.calculator.R; +import org.solovyev.android.menu.LabeledMenuItem; +import org.solovyev.common.text.StringUtils; + +/** +* User: serso +* Date: 12/18/11 +* Time: 3:09 PM +*/ +public enum HistoryItemMenuItem implements LabeledMenuItem { + + use(R.string.c_use) { + @Override + public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { + AbstractCalculatorHistoryFragment.useHistoryItem(data.getHistoryState()); + } + }, + + copy_expression(R.string.c_copy_expression) { + @Override + public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { + final CalculatorHistoryState calculatorHistoryState = data.getHistoryState(); + final String text = calculatorHistoryState.getEditorState().getText(); + if (!StringUtils.isEmpty(text)) { + final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); + clipboard.setText(text); + Toast.makeText(context, context.getText(R.string.c_expression_copied), Toast.LENGTH_SHORT).show(); + } + } + }, + + copy_result(R.string.c_copy_result) { + @Override + public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { + final CalculatorHistoryState calculatorHistoryState = data.getHistoryState(); + final String text = calculatorHistoryState.getDisplayState().getEditorState().getText(); + if (!StringUtils.isEmpty(text)) { + final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); + clipboard.setText(text); + Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show(); + } + } + }, + + save(R.string.c_save) { + @Override + public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) { + final CalculatorHistoryState historyState = data.getHistoryState(); + if (!historyState.isSaved()) { + createEditHistoryDialog(data, context, true); + } else { + Toast.makeText(context, context.getText(R.string.c_history_already_saved), Toast.LENGTH_LONG).show(); + } + } + }, + + edit(R.string.c_edit) { + @Override + public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) { + final CalculatorHistoryState historyState = data.getHistoryState(); + if (historyState.isSaved()) { + createEditHistoryDialog(data, context, false); + } else { + Toast.makeText(context, context.getText(R.string.c_history_must_be_saved), Toast.LENGTH_LONG).show(); + } + } + }, + + remove(R.string.c_remove) { + @Override + public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) { + final CalculatorHistoryState historyState = data.getHistoryState(); + if (historyState.isSaved()) { + data.getAdapter().remove(historyState); + CalculatorLocatorImpl.getInstance().getHistory().removeSavedHistory(historyState); + Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show(); + data.getAdapter().notifyDataSetChanged(); + } + } + }; + + private static void createEditHistoryDialog(@NotNull final HistoryItemMenuData data, @NotNull final Context context, final boolean save) { + final CalculatorHistoryState historyState = data.getHistoryState(); + + final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + final View editView = layoutInflater.inflate(R.layout.history_edit, null); + final TextView historyExpression = (TextView)editView.findViewById(R.id.history_edit_expression); + historyExpression.setText(AbstractCalculatorHistoryFragment.getHistoryText(historyState)); + + final EditText comment = (EditText)editView.findViewById(R.id.history_edit_comment); + comment.setText(historyState.getComment()); + + final AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setTitle(save ? R.string.c_save_history : R.string.c_edit_history) + .setCancelable(true) + .setNegativeButton(R.string.c_cancel, null) + .setPositiveButton(R.string.c_save, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (save) { + final CalculatorHistoryState savedHistoryItem = CalculatorLocatorImpl.getInstance().getHistory().addSavedState(historyState); + savedHistoryItem.setComment(comment.getText().toString()); + CalculatorLocatorImpl.getInstance().getHistory().save(); + // we don't need to add element to the adapter as adapter of another activity must be updated and not this + //data.getAdapter().add(savedHistoryItem); + } else { + historyState.setComment(comment.getText().toString()); + CalculatorLocatorImpl.getInstance().getHistory().save(); + } + data.getAdapter().notifyDataSetChanged(); + Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show(); + } + }) + .setView(editView); + + builder.create().show(); + } + + private final int captionId; + + private HistoryItemMenuItem(int captionId) { + this.captionId = captionId; + } + + @NotNull + @Override + public String getCaption(@NotNull Context context) { + return context.getString(captionId); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/fragments/FragmentUtils.java b/calculatorpp/src/main/java/org/solovyev/android/fragments/FragmentUtils.java index b7888a54..e3d56482 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/fragments/FragmentUtils.java +++ b/calculatorpp/src/main/java/org/solovyev/android/fragments/FragmentUtils.java @@ -1,38 +1,85 @@ -package org.solovyev.android.fragments; - -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; -import org.jetbrains.annotations.NotNull; - -/** - * User: serso - * Date: 9/25/12 - * Time: 9:29 PM - */ -public class FragmentUtils { - - public static void createFragment(@NotNull FragmentActivity activity, - @NotNull Class fragmentClass, - int parentViewId, - @NotNull String tag) { - final FragmentManager fm = activity.getSupportFragmentManager(); - - Fragment messagesFragment = fm.findFragmentByTag(tag); - - final FragmentTransaction ft = fm.beginTransaction(); - try { - if (messagesFragment == null) { - messagesFragment = Fragment.instantiate(activity, fragmentClass.getName(), null); - ft.add(parentViewId, messagesFragment, tag); - } else { - if (messagesFragment.isDetached()) { - ft.attach(messagesFragment); - } - } - } finally { - ft.commit(); - } - } -} +package org.solovyev.android.fragments; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import org.jetbrains.annotations.NotNull; +import org.solovyev.common.collections.CollectionsUtils; + +import java.util.Collections; +import java.util.List; + +/** + * User: serso + * Date: 9/25/12 + * Time: 9:29 PM + */ +public class FragmentUtils { + + public static void createFragment(@NotNull FragmentActivity activity, + @NotNull Class fragmentClass, + int parentViewId, + @NotNull String tag) { + final FragmentManager fm = activity.getSupportFragmentManager(); + + Fragment messagesFragment = fm.findFragmentByTag(tag); + + final FragmentTransaction ft = fm.beginTransaction(); + try { + if (messagesFragment == null) { + messagesFragment = Fragment.instantiate(activity, fragmentClass.getName(), null); + ft.add(parentViewId, messagesFragment, tag); + } else { + if (messagesFragment.isDetached()) { + ft.attach(messagesFragment); + } + } + } finally { + ft.commit(); + } + } + + public static void removeFragments(@NotNull SherlockFragmentActivity activity, @NotNull String... fragmentTags) { + removeFragments(activity, CollectionsUtils.asList(fragmentTags)); + } + + public static void removeFragments(@NotNull SherlockFragmentActivity activity, @NotNull List fragmentTags) { + for (String fragmentTag : fragmentTags) { + removeFragment(activity, fragmentTag); + } + } + + public static void detachFragments(@NotNull SherlockFragmentActivity activity, @NotNull String... fragmentTags) { + detachFragments(activity, CollectionsUtils.asList(fragmentTags)); + } + + public static void detachFragments(@NotNull SherlockFragmentActivity activity, @NotNull List fragmentTags) { + for (String fragmentTag : fragmentTags) { + detachFragment(activity, fragmentTag); + } + } + + public static void detachFragment(@NotNull SherlockFragmentActivity activity, @NotNull String fragmentTag) { + final Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag(fragmentTag); + if ( fragment != null ) { + if ( !fragment.isDetached() ) { + FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction(); + ft.detach(fragment); + ft.commit(); + } + } + } + + public static void removeFragment(@NotNull SherlockFragmentActivity activity, @NotNull String fragmentTag) { + final Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag(fragmentTag); + if ( fragment != null ) { + if ( fragment.isAdded()) { + FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction(); + ft.remove(fragment); + ft.commit(); + } + } + } +} diff --git a/pom.xml b/pom.xml index 1874cdfc..8d0411a9 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,20 @@ 1.0.0 + + org.solovyev.android + android-common-sherlock + 1.0.0 + apklib + + + + com.actionbarsherlock + library + 4.0.2 + apklib + + org.solovyev jscl