This commit is contained in:
serso 2012-10-10 16:13:58 +04:00
parent cbbd8ea1e0
commit 9e237c1a2c
15 changed files with 1500 additions and 1362 deletions

View File

@ -1,309 +1,309 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.history.EditorHistoryState; import org.solovyev.android.calculator.history.EditorHistoryState;
import org.solovyev.common.gui.CursorControl; import org.solovyev.common.gui.CursorControl;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 21.09.12 * Date: 21.09.12
* Time: 11:53 * Time: 11:53
*/ */
public class CalculatorEditorImpl implements CalculatorEditor { public class CalculatorEditorImpl implements CalculatorEditor {
@Nullable @Nullable
private CalculatorEditorView view; private CalculatorEditorView view;
@NotNull @NotNull
private final Object viewLock = new Object(); private final Object viewLock = new Object();
@NotNull @NotNull
private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance(); private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance();
@NotNull @NotNull
private final Calculator calculator; private final Calculator calculator;
@NotNull @NotNull
private final CalculatorEventHolder lastEventHolder; private final CalculatorEventHolder lastEventHolder;
@NotNull @NotNull
private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this); private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this);
public CalculatorEditorImpl(@NotNull Calculator calculator) { public CalculatorEditorImpl(@NotNull Calculator calculator) {
this.calculator = calculator; this.calculator = calculator;
this.calculator.addCalculatorEventListener(this); this.calculator.addCalculatorEventListener(this);
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
} }
@Override @Override
public void setView(@Nullable CalculatorEditorView view) { public void setView(@Nullable CalculatorEditorView view) {
synchronized (viewLock) { synchronized (viewLock) {
this.view = view; this.view = view;
if ( view != null ) { if ( view != null ) {
view.setState(lastViewState); view.setState(lastViewState);
} }
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState getViewState() { public CalculatorEditorViewState getViewState() {
return lastViewState; return lastViewState;
} }
@Override @Override
public void updateViewState() { public void updateViewState() {
setViewState(this.lastViewState, false); setViewState(this.lastViewState, false);
} }
@Override @Override
public void setViewState(@NotNull CalculatorEditorViewState newViewState) { public void setViewState(@NotNull CalculatorEditorViewState newViewState) {
setViewState(newViewState, true); setViewState(newViewState, true);
} }
private void setViewState(CalculatorEditorViewState newViewState, boolean fireEvent) { private void setViewState(@NotNull CalculatorEditorViewState newViewState, boolean fireEvent) {
synchronized (viewLock) { synchronized (viewLock) {
final CalculatorEditorViewState oldViewState = this.lastViewState; final CalculatorEditorViewState oldViewState = this.lastViewState;
this.lastViewState = newViewState; this.lastViewState = newViewState;
if (this.view != null) { if (this.view != null) {
this.view.setState(newViewState); this.view.setState(newViewState);
} }
if (fireEvent) { if (fireEvent) {
calculator.fireCalculatorEvent(CalculatorEventType.editor_state_changed, new CalculatorEditorChangeEventDataImpl(oldViewState, newViewState)); calculator.fireCalculatorEvent(CalculatorEventType.editor_state_changed, new CalculatorEditorChangeEventDataImpl(oldViewState, newViewState));
} }
} }
} }
@Override @Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData,
@NotNull CalculatorEventType calculatorEventType, @NotNull CalculatorEventType calculatorEventType,
@Nullable Object data) { @Nullable Object data) {
final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData); final CalculatorEventHolder.Result result = lastEventHolder.apply(calculatorEventData);
if (result.isNewAfter()) { if (result.isNewAfter()) {
switch (calculatorEventType) { switch (calculatorEventType) {
case use_history_state: case use_history_state:
final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState)data; final CalculatorHistoryState calculatorHistoryState = (CalculatorHistoryState)data;
final EditorHistoryState editorState = calculatorHistoryState.getEditorState(); final EditorHistoryState editorState = calculatorHistoryState.getEditorState();
this.setText(StringUtils.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition()); this.setText(StringUtils.getNotEmpty(editorState.getText(), ""), editorState.getCursorPosition());
break; break;
} }
} }
} }
/* /*
********************************************************************** **********************************************************************
* *
* SELECTION * SELECTION
* *
********************************************************************** **********************************************************************
*/ */
@NotNull @NotNull
private CalculatorEditorViewState newSelectionViewState(int newSelection) { private CalculatorEditorViewState newSelectionViewState(int newSelection) {
if (this.lastViewState.getSelection() != newSelection) { if (this.lastViewState.getSelection() != newSelection) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection); final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection);
setViewState(result); setViewState(result, false);
return result; return result;
} else { } else {
return this.lastViewState; return this.lastViewState;
} }
} }
@NotNull @NotNull
public CalculatorEditorViewState setCursorOnStart() { public CalculatorEditorViewState setCursorOnStart() {
synchronized (viewLock) { synchronized (viewLock) {
return newSelectionViewState(0); return newSelectionViewState(0);
} }
} }
@NotNull @NotNull
public CalculatorEditorViewState setCursorOnEnd() { public CalculatorEditorViewState setCursorOnEnd() {
synchronized (viewLock) { synchronized (viewLock) {
return newSelectionViewState(this.lastViewState.getText().length()); return newSelectionViewState(this.lastViewState.getText().length());
} }
} }
@NotNull @NotNull
public CalculatorEditorViewState moveCursorLeft() { public CalculatorEditorViewState moveCursorLeft() {
synchronized (viewLock) { synchronized (viewLock) {
if (this.lastViewState.getSelection() > 0) { if (this.lastViewState.getSelection() > 0) {
return newSelectionViewState(this.lastViewState.getSelection() - 1); return newSelectionViewState(this.lastViewState.getSelection() - 1);
} else { } else {
return this.lastViewState; return this.lastViewState;
} }
} }
} }
@NotNull @NotNull
public CalculatorEditorViewState moveCursorRight() { public CalculatorEditorViewState moveCursorRight() {
synchronized (viewLock) { synchronized (viewLock) {
if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) { if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) {
return newSelectionViewState(this.lastViewState.getSelection() + 1); return newSelectionViewState(this.lastViewState.getSelection() + 1);
} else { } else {
return this.lastViewState; return this.lastViewState;
} }
} }
} }
@NotNull @NotNull
@Override @Override
public CursorControl asCursorControl() { public CursorControl asCursorControl() {
return cursorControlAdapter; return cursorControlAdapter;
} }
/* /*
********************************************************************** **********************************************************************
* *
* EDITOR ACTIONS * EDITOR ACTIONS
* *
********************************************************************** **********************************************************************
*/ */
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState erase() { public CalculatorEditorViewState erase() {
synchronized (viewLock) { synchronized (viewLock) {
int selection = this.lastViewState.getSelection(); int selection = this.lastViewState.getSelection();
final String text = this.lastViewState.getText(); final String text = this.lastViewState.getText();
if (selection > 0 && text.length() > 0 && selection <= text.length()) { if (selection > 0 && text.length() > 0 && selection <= text.length()) {
final StringBuilder newText = new StringBuilder(text.length() - 1); final StringBuilder newText = new StringBuilder(text.length() - 1);
newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length())); newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length()));
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1); final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1);
setViewState(result); setViewState(result);
return result; return result;
} else { } else {
return this.lastViewState; return this.lastViewState;
} }
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState clear() { public CalculatorEditorViewState clear() {
synchronized (viewLock) { synchronized (viewLock) {
return setText(""); return setText("");
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState setText(@NotNull String text) { public CalculatorEditorViewState setText(@NotNull String text) {
synchronized (viewLock) { synchronized (viewLock) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length()); final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length());
setViewState(result); setViewState(result);
return result; return result;
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState setText(@NotNull String text, int selection) { public CalculatorEditorViewState setText(@NotNull String text, int selection) {
synchronized (viewLock) { synchronized (viewLock) {
selection = correctSelection(selection, text); selection = correctSelection(selection, text);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection); final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection);
setViewState(result); setViewState(result);
return result; return result;
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState insert(@NotNull String text) { public CalculatorEditorViewState insert(@NotNull String text) {
synchronized (viewLock) { synchronized (viewLock) {
return insert(text, 0); return insert(text, 0);
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState insert(@NotNull String text, int selectionOffset) { public CalculatorEditorViewState insert(@NotNull String text, int selectionOffset) {
synchronized (viewLock) { synchronized (viewLock) {
final int selection = this.lastViewState.getSelection(); final int selection = this.lastViewState.getSelection();
final String oldText = this.lastViewState.getText(); final String oldText = this.lastViewState.getText();
int newTextLength = text.length() + oldText.length(); int newTextLength = text.length() + oldText.length();
final StringBuilder newText = new StringBuilder(newTextLength); final StringBuilder newText = new StringBuilder(newTextLength);
newText.append(oldText.substring(0, selection)); newText.append(oldText.substring(0, selection));
newText.append(text); newText.append(text);
newText.append(oldText.substring(selection)); newText.append(oldText.substring(selection));
int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength); int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection); final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection);
setViewState(result); setViewState(result);
return result; return result;
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState moveSelection(int offset) { public CalculatorEditorViewState moveSelection(int offset) {
synchronized (viewLock) { synchronized (viewLock) {
int selection = this.lastViewState.getSelection() + offset; int selection = this.lastViewState.getSelection() + offset;
return setSelection(selection); return setSelection(selection);
} }
} }
@NotNull @NotNull
@Override @Override
public CalculatorEditorViewState setSelection(int selection) { public CalculatorEditorViewState setSelection(int selection) {
synchronized (viewLock) { synchronized (viewLock) {
selection = correctSelection(selection, this.lastViewState.getText()); selection = correctSelection(selection, this.lastViewState.getText());
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection); final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection);
setViewState(result); setViewState(result, false);
return result; return result;
} }
} }
private int correctSelection(int selection, @NotNull String text) { private int correctSelection(int selection, @NotNull String text) {
return correctSelection(selection, text.length()); return correctSelection(selection, text.length());
} }
private int correctSelection(int selection, int textLength) { private int correctSelection(int selection, int textLength) {
int result = Math.max(selection, 0); int result = Math.max(selection, 0);
result = Math.min(result, textLength); result = Math.min(result, textLength);
return result; return result;
} }
private static final class CursorControlAdapter implements CursorControl { private static final class CursorControlAdapter implements CursorControl {
@NotNull @NotNull
private final CalculatorEditor calculatorEditor; private final CalculatorEditor calculatorEditor;
private CursorControlAdapter(@NotNull CalculatorEditor calculatorEditor) { private CursorControlAdapter(@NotNull CalculatorEditor calculatorEditor) {
this.calculatorEditor = calculatorEditor; this.calculatorEditor = calculatorEditor;
} }
@Override @Override
public void setCursorOnStart() { public void setCursorOnStart() {
this.calculatorEditor.setCursorOnStart(); this.calculatorEditor.setCursorOnStart();
} }
@Override @Override
public void setCursorOnEnd() { public void setCursorOnEnd() {
this.calculatorEditor.setCursorOnEnd(); this.calculatorEditor.setCursorOnEnd();
} }
@Override @Override
public void moveCursorLeft() { public void moveCursorLeft() {
this.calculatorEditor.moveCursorLeft(); this.calculatorEditor.moveCursorLeft();
} }
@Override @Override
public void moveCursorRight() { public void moveCursorRight() {
this.calculatorEditor.moveCursorRight(); this.calculatorEditor.moveCursorRight();
} }
} }
} }

View File

@ -1,70 +1,78 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
* User: serso * User: serso
* Date: 10/9/12 * Date: 10/9/12
* Time: 9:59 PM * Time: 9:59 PM
*/ */
public class CalculatorEventHolder { public class CalculatorEventHolder {
@NotNull @NotNull
private volatile CalculatorEventData lastEventData; private volatile CalculatorEventData lastEventData;
public CalculatorEventHolder(@NotNull CalculatorEventData lastEventData) { public CalculatorEventHolder(@NotNull CalculatorEventData lastEventData) {
this.lastEventData = lastEventData; this.lastEventData = lastEventData;
} }
@NotNull @NotNull
public synchronized CalculatorEventData getLastEventData() { public synchronized CalculatorEventData getLastEventData() {
return lastEventData; return lastEventData;
} }
@NotNull @NotNull
public synchronized Result apply(@NotNull CalculatorEventData newEventData) { public synchronized Result apply(@NotNull CalculatorEventData newEventData) {
final Result result = new Result(lastEventData, newEventData); final Result result = new Result(lastEventData, newEventData);
if (result.isNewAfter()) { if (result.isNewAfter()) {
this.lastEventData = newEventData; this.lastEventData = newEventData;
} }
return result; return result;
} }
public static class Result { public static class Result {
@NotNull @NotNull
private final CalculatorEventData lastEventData; private final CalculatorEventData lastEventData;
@NotNull @NotNull
private final CalculatorEventData newEventData; private final CalculatorEventData newEventData;
@Nullable @Nullable
private Boolean after = null; private Boolean after = null;
@Nullable @Nullable
private Boolean sameSequence = null; private Boolean sameSequence = null;
public Result(@NotNull CalculatorEventData lastEventData, public Result(@NotNull CalculatorEventData lastEventData,
@NotNull CalculatorEventData newEventData) { @NotNull CalculatorEventData newEventData) {
this.lastEventData = lastEventData; this.lastEventData = lastEventData;
this.newEventData = newEventData; this.newEventData = newEventData;
} }
public boolean isNewAfter() { public boolean isNewAfter() {
if (after == null) { if (after == null) {
after = newEventData.isAfter(lastEventData); after = newEventData.isAfter(lastEventData);
} }
return after; return after;
} }
public boolean isSameSequence() { public boolean isSameSequence() {
if (sameSequence == null) { if (sameSequence == null) {
sameSequence = newEventData.isSameSequence(lastEventData); sameSequence = newEventData.isSameSequence(lastEventData);
} }
return sameSequence; return sameSequence;
} }
}
} public boolean isNewAfterSequence() {
return newEventData.isAfterSequence(lastEventData);
}
public boolean isNewSameOrAfterSequence() {
return isSameSequence() || isNewAfterSequence();
}
}
}

View File

@ -1,33 +1,40 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorEventListener; import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.common.history.HistoryHelper; import org.solovyev.common.history.HistoryHelper;
import java.util.List; import java.util.List;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
* Time: 16:11 * Time: 16:11
*/ */
public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState>, CalculatorEventListener { public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState>, CalculatorEventListener {
void load(); void load();
void save(); void save();
void fromXml(@NotNull String xml); void fromXml(@NotNull String xml);
String toXml(); String toXml();
void clearSavedHistory(); void clearSavedHistory();
void removeSavedHistory(@NotNull CalculatorHistoryState historyState); void removeSavedHistory(@NotNull CalculatorHistoryState historyState);
@NotNull @NotNull
List<CalculatorHistoryState> getSavedHistory(); List<CalculatorHistoryState> getSavedHistory();
@NotNull @NotNull
CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState); CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState);
}
@NotNull
List<CalculatorHistoryState> getStates();
@NotNull
List<CalculatorHistoryState> getStates(boolean includeIntermediateStates);
}

View File

@ -1,234 +1,257 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.*;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.collections.CollectionsUtils;
import org.solovyev.common.history.HistoryHelper; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.history.SimpleHistoryHelper; import org.solovyev.common.history.HistoryHelper;
import org.solovyev.common.history.SimpleHistoryHelper;
import java.util.ArrayList;
import java.util.Collections; import java.util.ArrayList;
import java.util.List; import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger; import java.util.LinkedList;
import java.util.List;
import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed; import java.util.concurrent.atomic.AtomicInteger;
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed;
import static org.solovyev.android.calculator.CalculatorEventType.manual_calculation_requested; import static org.solovyev.android.calculator.CalculatorEventType.*;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
* Time: 16:12 * Time: 16:12
*/ */
public class CalculatorHistoryImpl implements CalculatorHistory { public class CalculatorHistoryImpl implements CalculatorHistory {
private final AtomicInteger counter = new AtomicInteger(0); private final AtomicInteger counter = new AtomicInteger(0);
@NotNull @NotNull
private final HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>(); private final HistoryHelper<CalculatorHistoryState> history = new SimpleHistoryHelper<CalculatorHistoryState>();
@NotNull @NotNull
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>(); private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>();
@NotNull @NotNull
private volatile CalculatorEventData lastEventData = CalculatorUtils.createFirstEventDataId(); private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
@NotNull @Nullable
private final Object lastEventDataLock = new Object(); private volatile CalculatorEditorViewState lastEditorViewState;
@Nullable public CalculatorHistoryImpl(@NotNull Calculator calculator) {
private volatile CalculatorEditorViewState lastEditorViewState; calculator.addCalculatorEventListener(this);
}
public CalculatorHistoryImpl(@NotNull Calculator calculator) {
calculator.addCalculatorEventListener(this); @Override
} public boolean isEmpty() {
synchronized (history) {
@Override return this.history.isEmpty();
public boolean isEmpty() { }
synchronized (history) { }
return this.history.isEmpty();
} @Override
} public CalculatorHistoryState getLastHistoryState() {
synchronized (history) {
@Override return this.history.getLastHistoryState();
public CalculatorHistoryState getLastHistoryState() { }
synchronized (history) { }
return this.history.getLastHistoryState();
} @Override
} public boolean isUndoAvailable() {
synchronized (history) {
@Override return history.isUndoAvailable();
public boolean isUndoAvailable() { }
synchronized (history) { }
return history.isUndoAvailable();
} @Override
} public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
@Override return history.undo(currentState);
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { }
synchronized (history) { }
return history.undo(currentState);
} @Override
} public boolean isRedoAvailable() {
return history.isRedoAvailable();
@Override }
public boolean isRedoAvailable() {
return history.isRedoAvailable(); @Override
} public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
synchronized (history) {
@Override return history.redo(currentState);
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { }
synchronized (history) { }
return history.redo(currentState);
} @Override
} public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
synchronized (history) {
@Override return history.isActionAvailable(historyAction);
public boolean isActionAvailable(@NotNull HistoryAction historyAction) { }
synchronized (history) { }
return history.isActionAvailable(historyAction);
} @Override
} public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
synchronized (history) {
@Override return history.doAction(historyAction, currentState);
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) {
@Override history.addState(currentState);
public void addState(@Nullable CalculatorHistoryState currentState) { CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState);
synchronized (history) { }
history.addState(currentState); }
CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, currentState);
} @NotNull
} @Override
public List<CalculatorHistoryState> getStates() {
@NotNull synchronized (history) {
@Override return history.getStates();
public List<CalculatorHistoryState> getStates() { }
synchronized (history) { }
return history.getStates();
} @NotNull
} @Override
public List<CalculatorHistoryState> getStates(boolean includeIntermediateStates) {
@Override if (includeIntermediateStates) {
public void clear() { return getStates();
synchronized (history) { } else {
this.history.clear(); final List<CalculatorHistoryState> states = getStates();
}
} final List<CalculatorHistoryState> result = new LinkedList<CalculatorHistoryState>();
@Override CalculatorHistoryState laterState = null;
@NotNull for (CalculatorHistoryState state : CollectionsUtils.reversed(states)) {
public List<CalculatorHistoryState> getSavedHistory() { if ( laterState != null ) {
return Collections.unmodifiableList(savedHistory); final String laterEditorText = laterState.getEditorState().getText();
} final String editorText = state.getEditorState().getText();
if ( laterEditorText != null && editorText != null && isIntermediate(laterEditorText, editorText)) {
@Override // intermediate result => skip from add
@NotNull } else {
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { result.add(0, state);
if (historyState.isSaved()) { }
return historyState; } else {
} else { result.add(0, state);
final CalculatorHistoryState savedState = historyState.clone(); }
savedState.setId(counter.incrementAndGet()); laterState = state;
savedState.setSaved(true); }
savedHistory.add(savedState); return result;
}
return savedState; }
}
} private boolean isIntermediate(@NotNull String laterEditorText,
@NotNull String editorText) {
@Override if ( Math.abs(laterEditorText.length() - editorText.length()) <= 1 ) {
public void load() { if ( laterEditorText.length() > editorText.length() ) {
// todo serso: create saved/loader class return laterEditorText.startsWith(editorText);
} } else {
return editorText.startsWith(laterEditorText);
@Override }
public void save() { }
// todo serso: create saved/loader class
} return false;
}
@Override
public void fromXml(@NotNull String xml) { @Override
clearSavedHistory(); public void clear() {
synchronized (history) {
HistoryUtils.fromXml(xml, this.savedHistory); this.history.clear();
for (CalculatorHistoryState historyState : savedHistory) { }
historyState.setSaved(true); }
historyState.setId(counter.incrementAndGet());
} @Override
} @NotNull
public List<CalculatorHistoryState> getSavedHistory() {
@Override return Collections.unmodifiableList(savedHistory);
public String toXml() { }
return HistoryUtils.toXml(this.savedHistory);
} @Override
@NotNull
@Override public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
public void clearSavedHistory() { if (historyState.isSaved()) {
this.savedHistory.clear(); return historyState;
} } else {
final CalculatorHistoryState savedState = historyState.clone();
@Override
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { savedState.setId(counter.incrementAndGet());
this.savedHistory.remove(historyState); savedState.setSaved(true);
}
savedHistory.add(savedState);
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, return savedState;
@NotNull CalculatorEventType calculatorEventType, }
@Nullable Object data) { }
if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) {
@Override
boolean sameSequence = false; public void load() {
boolean afterSequence = false; // todo serso: create saved/loader class
}
boolean processEvent = false;
@Override
synchronized (this.lastEventDataLock) { public void save() {
if (calculatorEventData.isAfter(this.lastEventData)) { // todo serso: create saved/loader class
}
sameSequence = calculatorEventData.isSameSequence(this.lastEventData);
if (!sameSequence) { @Override
afterSequence = calculatorEventData.isAfterSequence(this.lastEventData); public void fromXml(@NotNull String xml) {
processEvent = afterSequence; clearSavedHistory();
} else {
processEvent = true; HistoryUtils.fromXml(xml, this.savedHistory);
} for (CalculatorHistoryState historyState : savedHistory) {
} historyState.setSaved(true);
} historyState.setId(counter.incrementAndGet());
}
if (processEvent) { }
this.lastEventData = calculatorEventData;
@Override
switch (calculatorEventType) { public String toXml() {
case manual_calculation_requested: return HistoryUtils.toXml(this.savedHistory);
lastEditorViewState = (CalculatorEditorViewState) data; }
break;
case editor_state_changed: @Override
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data; public void clearSavedHistory() {
lastEditorViewState = editorChangeData.getNewValue(); this.savedHistory.clear();
break; }
case display_state_changed:
if (sameSequence) { @Override
if (lastEditorViewState != null) { public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
final CalculatorEditorViewState editorViewState = lastEditorViewState; this.savedHistory.remove(historyState);
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; }
final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue();
addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); @Override
} public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData,
} else { @NotNull CalculatorEventType calculatorEventType,
lastEditorViewState = null; @Nullable Object data) {
} if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) {
break;
} final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData);
}
} if (result.isNewAfter() && result.isNewSameOrAfterSequence() ) {
} switch (calculatorEventType) {
} case manual_calculation_requested:
lastEditorViewState = (CalculatorEditorViewState) data;
break;
case editor_state_changed:
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
lastEditorViewState = editorChangeData.getNewValue();
break;
case display_state_changed:
if (result.isSameSequence()) {
if (lastEditorViewState != null) {
final CalculatorEditorViewState editorViewState = lastEditorViewState;
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data;
final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue();
addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState));
}
} else {
lastEditorViewState = null;
}
break;
}
}
}
}
}

View File

@ -0,0 +1,53 @@
package org.solovyev.android.calculator.history;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import org.junit.BeforeClass;
import org.junit.Test;
import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl;
import org.solovyev.android.calculator.CalculatorEditorViewStateImpl;
import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.CalculatorTestUtils;
import java.util.List;
/**
* User: Solovyev_S
* Date: 10.10.12
* Time: 15:07
*/
public class CalculatorHistoryImplTest {
@BeforeClass
public static void setUp() throws Exception {
CalculatorTestUtils.staticSetUp();
}
@Test
public void testGetStates() throws Exception {
CalculatorHistory calculatorHistory = new CalculatorHistoryImpl(CalculatorLocatorImpl.getInstance().getCalculator());
addState(calculatorHistory, "1");
addState(calculatorHistory, "12");
addState(calculatorHistory, "123");
addState(calculatorHistory, "123+");
addState(calculatorHistory, "123+3");
addState(calculatorHistory, "");
addState(calculatorHistory, "2");
addState(calculatorHistory, "23");
addState(calculatorHistory, "235");
addState(calculatorHistory, "2355");
addState(calculatorHistory, "235");
addState(calculatorHistory, "2354");
addState(calculatorHistory, "23547");
final List<CalculatorHistoryState> states = calculatorHistory.getStates(false);
Assert.assertEquals(2, states.size());
Assert.assertEquals("23547", states.get(1).getEditorState().getText());
Assert.assertEquals("123+3", states.get(0).getEditorState().getText());
}
private void addState(@NotNull CalculatorHistory calculatorHistory, @NotNull String text) {
calculatorHistory.addState(CalculatorHistoryState.newInstance(CalculatorEditorViewStateImpl.newInstance(text, 3), CalculatorDisplayViewStateImpl.newDefaultInstance()));
}
}

View File

@ -1,10 +1,13 @@
<resources> <resources>
<string name="c_auto_orientation_title">Переключатель автоматического поворота экрана</string> <string name="c_auto_orientation_title">Переключатель автоматического поворота экрана</string>
<string name="c_auto_orientation_summary">Если включено, то калькулятор будет автоматически менять ориентацию экрана</string> <string name="c_auto_orientation_summary">Если включено, то калькулятор будет автоматически менять ориентацию экрана</string>
<string name="c_show_equals_button_title">Показывать клавишу равно</string> <string name="c_show_equals_button_title">Показывать клавишу равно</string>
<string name="c_show_equals_button_summary">Если включено, то клавиша равно будет показана</string> <string name="c_show_equals_button_summary">Если включено, то клавиша равно будет показана</string>
<string name="c_hide_numeral_base_digits_title">Не показывать цифры из других систем счисления</string> <string name="c_hide_numeral_base_digits_title">Не показывать цифры из других систем счисления</string>
<string name="c_hide_numeral_base_digits_summary">Если включено, то цифры из других систем счисления не будут показаны</string> <string name="c_hide_numeral_base_digits_summary">Если включено, то цифры из других систем счисления не будут показаны</string>
<string name="prefs_history_show_intermediate_calculations_title">Показывать промежуточные вычисления на экране истории</string>
<string name="prefs_history_show_intermediate_calculations_summary">Если включено, то все вычисления будут показаны на экране истории</string>
</resources> </resources>

View File

@ -1,10 +1,13 @@
<resources> <resources>
<string name="c_auto_orientation_title">Toggle screen orientation change</string> <string name="c_auto_orientation_title">Toggle screen orientation change</string>
<string name="c_auto_orientation_summary">If turned on calculator will change screen orientation automatically</string> <string name="c_auto_orientation_summary">If turned on calculator will change screen orientation automatically</string>
<string name="c_show_equals_button_title">Show equals button</string> <string name="c_show_equals_button_title">Show equals button</string>
<string name="c_show_equals_button_summary">If turned on equals button is shown</string> <string name="c_show_equals_button_summary">If turned on equals button is shown</string>
<string name="c_hide_numeral_base_digits_title">Hide numeral base digits</string> <string name="c_hide_numeral_base_digits_title">Hide numeral base digits</string>
<string name="c_hide_numeral_base_digits_summary">If turned on numeral base digits of other numeral bases will be hidden</string> <string name="c_hide_numeral_base_digits_summary">If turned on numeral base digits of other numeral bases will be hidden</string>
<string name="prefs_history_show_intermediate_calculations_title">Show intermediate calculations in history</string>
<string name="prefs_history_show_intermediate_calculations_summary">If turned on all calculations will be shown on history screen</string>
</resources> </resources>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android"
xmlns:range="http://schemas.android.com/apk/res-auto">
<PreferenceScreen
a:title="@string/c_prefs_appearance_category">
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_color_display_key"
a:summary="@string/c_calc_color_display_summary"
a:title="@string/c_calc_color_display_title"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_haptic_feedback_key"
a:summary="@string/c_calc_haptic_feedback_summary"
a:title="@string/c_calc_haptic_feedback_title"
a:defaultValue="false"/>
<ListPreference a:key="@string/p_calc_haptic_feedback_duration_key"
a:title="@string/p_calc_haptic_feedback_duration_title"
a:entries="@array/p_calc_haptic_feedback_duration_names"
a:summary="@string/p_calc_haptic_feedback_duration_summary"
a:entryValues="@array/p_calc_haptic_feedback_duration_values"/>
<ListPreference a:key="@string/p_calc_multiplication_sign_key"
a:title="@string/c_calc_multiplication_sign"
a:entries="@array/p_multiplication_sign_values"
a:summary="@string/c_calc_multiplication_sign_summary"
a:entryValues="@array/p_multiplication_sign_values"/>
<ListPreference a:key="@string/p_calc_theme_key"
a:title="@string/c_calc_theme"
a:entries="@array/p_theme_names"
a:summary="@string/c_calc_theme_summary"
a:entryValues="@array/p_theme_values"/>
<ListPreference a:key="@string/p_calc_layout_key"
a:title="@string/c_calc_layout"
a:entries="@array/p_layout_names"
a:summary="@string/c_calc_layout_summary"
a:entryValues="@array/p_layout_values"/>
<org.solovyev.android.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_distance_key"
a:title="@string/c_swipe_distance"
a:summary="@string/c_swipe_distance_summary"
a:text=" pxs"
a:defaultValue="35;350"
range:step="10"
range:boundaries="10;500"/>
<!-- <org.solovyev.android.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_duration_key"
a:title="Duration of drag event"
a:text=" ms"
a:defaultValue="40;2500"
range:steps="10"
range:boundaries="5;4000"/>
<org.solovyev.android.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_angle_key"
a:title="Angle of drag event"
a:text=" degrees"
a:defaultValue="0;45"
range:steps="5"
range:boundaries="0;45"/>-->
<android.preference.CheckBoxPreference
a:key="autoOrientation"
a:title="@string/c_auto_orientation_title"
a:summary="@string/c_auto_orientation_summary"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="showEqualsButton"
a:title="@string/c_show_equals_button_title"
a:summary="@string/c_show_equals_button_summary"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="hideNumeralBaseDigits"
a:title="@string/c_hide_numeral_base_digits_title"
a:summary="@string/c_hide_numeral_base_digits_summary"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="history_show_intermediate_calculations"
a:title="@string/prefs_history_show_intermediate_calculations_title"
a:summary="@string/prefs_history_show_intermediate_calculations_summary"/>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android"
xmlns:range="http://schemas.android.com/apk/res-auto">
<PreferenceScreen a:title="@string/c_prefs_calculations_category">
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_round_result_key"
a:summary="@string/c_calc_round_result_summary"
a:title="@string/c_calc_round_result_title"
a:defaultValue="true"/>
<org.solovyev.android.prefs.IntegerPickerDialogPreference
a:key="@string/p_calc_result_precision_key"
a:title="@string/p_calc_result_precision_title"
a:summary="@string/c_calc_result_precision_summary"
a:defaultValue="5"
range:boundaries="0;16"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_science_notation_key"
a:summary="@string/c_calc_science_notation_summary"
a:title="@string/c_calc_science_notation_title"
a:defaultValue="false"/>
<ListPreference a:key="@string/p_calc_grouping_separator_key"
a:title="@string/c_calc_grouping_separator"
a:entries="@array/p_grouping_separator_names"
a:summary="@string/c_calc_grouping_separator_summary"
a:entryValues="@array/p_grouping_separator_values"/>
<ListPreference a:key="@string/p_calc_angle_units_key"
a:title="@string/c_calc_angle_units"
a:entries="@array/p_angle_units_names"
a:summary="@string/c_angle_units_summary"
a:entryValues="@array/p_angle_units"/>
<ListPreference a:key="@string/p_calc_numeral_bases_key"
a:title="@string/c_calc_numeral_bases"
a:entries="@array/p_numeral_bases_names"
a:summary="@string/c_numeral_bases_summary"
a:entryValues="@array/p_numeral_bases"/>
<org.solovyev.android.prefs.IntegerPickerDialogPreference
a:key="@string/p_calc_max_calculation_time_key"
a:title="@string/p_calc_max_calculation_time_title"
a:summary="@string/p_calc_max_calculation_time_summary"
a:defaultValue="5"
range:boundaries="3;1000"/>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
<PreferenceScreen
a:title="@string/c_prefs_other_category">
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_show_release_notes_key"
a:summary="@string/c_calc_show_release_notes_summary"
a:title="@string/c_calc_show_release_notes_title"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_use_back_button_as_prev_key"
a:summary="@string/c_calc_use_back_button_as_prev_summary"
a:title="@string/c_calc_use_back_button_as_prev_title"
a:defaultValue="false"/>
<Preference
a:key="@string/p_clear_billing_info_key"
a:summary="@string/c_clear_billing_info_summary"
a:title="@string/c_clear_billing_info_title"/>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
xmlns:range="http://schemas.android.com/apk/res-auto">
<Preference <Preference
a:key="@string/p_calc_ad_free_key" a:key="@string/p_calc_ad_free_key"
@ -12,167 +11,4 @@
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/> <org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<PreferenceScreen a:title="@string/c_prefs_calculations_category">
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_round_result_key"
a:summary="@string/c_calc_round_result_summary"
a:title="@string/c_calc_round_result_title"
a:defaultValue="true"/>
<org.solovyev.android.prefs.IntegerPickerDialogPreference
a:key="@string/p_calc_result_precision_key"
a:title="@string/p_calc_result_precision_title"
a:summary="@string/c_calc_result_precision_summary"
a:defaultValue="5"
range:boundaries="0;16"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_science_notation_key"
a:summary="@string/c_calc_science_notation_summary"
a:title="@string/c_calc_science_notation_title"
a:defaultValue="false"/>
<ListPreference a:key="@string/p_calc_grouping_separator_key"
a:title="@string/c_calc_grouping_separator"
a:entries="@array/p_grouping_separator_names"
a:summary="@string/c_calc_grouping_separator_summary"
a:entryValues="@array/p_grouping_separator_values"/>
<ListPreference a:key="@string/p_calc_angle_units_key"
a:title="@string/c_calc_angle_units"
a:entries="@array/p_angle_units_names"
a:summary="@string/c_angle_units_summary"
a:entryValues="@array/p_angle_units"/>
<ListPreference a:key="@string/p_calc_numeral_bases_key"
a:title="@string/c_calc_numeral_bases"
a:entries="@array/p_numeral_bases_names"
a:summary="@string/c_numeral_bases_summary"
a:entryValues="@array/p_numeral_bases"/>
<org.solovyev.android.prefs.IntegerPickerDialogPreference
a:key="@string/p_calc_max_calculation_time_key"
a:title="@string/p_calc_max_calculation_time_title"
a:summary="@string/p_calc_max_calculation_time_summary"
a:defaultValue="5"
range:boundaries="3;1000"/>
</PreferenceScreen>
<PreferenceScreen
a:title="@string/c_prefs_appearance_category">
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_color_display_key"
a:summary="@string/c_calc_color_display_summary"
a:title="@string/c_calc_color_display_title"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_haptic_feedback_key"
a:summary="@string/c_calc_haptic_feedback_summary"
a:title="@string/c_calc_haptic_feedback_title"
a:defaultValue="false"/>
<ListPreference a:key="@string/p_calc_haptic_feedback_duration_key"
a:title="@string/p_calc_haptic_feedback_duration_title"
a:entries="@array/p_calc_haptic_feedback_duration_names"
a:summary="@string/p_calc_haptic_feedback_duration_summary"
a:entryValues="@array/p_calc_haptic_feedback_duration_values"/>
<ListPreference a:key="@string/p_calc_multiplication_sign_key"
a:title="@string/c_calc_multiplication_sign"
a:entries="@array/p_multiplication_sign_values"
a:summary="@string/c_calc_multiplication_sign_summary"
a:entryValues="@array/p_multiplication_sign_values"/>
<ListPreference a:key="@string/p_calc_theme_key"
a:title="@string/c_calc_theme"
a:entries="@array/p_theme_names"
a:summary="@string/c_calc_theme_summary"
a:entryValues="@array/p_theme_values"/>
<ListPreference a:key="@string/p_calc_layout_key"
a:title="@string/c_calc_layout"
a:entries="@array/p_layout_names"
a:summary="@string/c_calc_layout_summary"
a:entryValues="@array/p_layout_values"/>
<org.solovyev.android.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_distance_key"
a:title="@string/c_swipe_distance"
a:summary="@string/c_swipe_distance_summary"
a:text=" pxs"
a:defaultValue="35;350"
range:step="10"
range:boundaries="10;500"/>
<!-- <org.solovyev.android.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_duration_key"
a:title="Duration of drag event"
a:text=" ms"
a:defaultValue="40;2500"
range:steps="10"
range:boundaries="5;4000"/>
<org.solovyev.android.prefs.FloatRangeSeekBarPreference
a:key="@string/p_drag_angle_key"
a:title="Angle of drag event"
a:text=" degrees"
a:defaultValue="0;45"
range:steps="5"
range:boundaries="0;45"/>-->
<android.preference.CheckBoxPreference
a:key="autoOrientation"
a:title="@string/c_auto_orientation_title"
a:summary="@string/c_auto_orientation_summary"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="showEqualsButton"
a:title="@string/c_show_equals_button_title"
a:summary="@string/c_show_equals_button_summary"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="hideNumeralBaseDigits"
a:title="@string/c_hide_numeral_base_digits_title"
a:summary="@string/c_hide_numeral_base_digits_summary"
a:defaultValue="true"/>
</PreferenceScreen>
<PreferenceScreen
a:title="@string/c_prefs_other_category">
<org.solovyev.android.ads.AdViewPreference a:layout="@layout/admob_pref"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_show_release_notes_key"
a:summary="@string/c_calc_show_release_notes_summary"
a:title="@string/c_calc_show_release_notes_title"
a:defaultValue="true"/>
<android.preference.CheckBoxPreference
a:key="@string/p_calc_use_back_button_as_prev_key"
a:summary="@string/c_calc_use_back_button_as_prev_summary"
a:title="@string/c_calc_use_back_button_as_prev_title"
a:defaultValue="false"/>
<Preference
a:key="@string/p_clear_billing_info_key"
a:summary="@string/c_clear_billing_info_summary"
a:title="@string/c_clear_billing_info_title"/>
</PreferenceScreen>
</PreferenceScreen> </PreferenceScreen>

View File

@ -1,183 +1,189 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine; import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.plot.GraphLineColor; import org.solovyev.android.calculator.plot.GraphLineColor;
import org.solovyev.android.prefs.BooleanPreference; import org.solovyev.android.prefs.BooleanPreference;
import org.solovyev.android.prefs.IntegerPreference; import org.solovyev.android.prefs.IntegerPreference;
import org.solovyev.android.prefs.Preference; import org.solovyev.android.prefs.Preference;
import org.solovyev.android.prefs.StringPreference; import org.solovyev.android.prefs.StringPreference;
import org.solovyev.android.view.VibratorContainer; import org.solovyev.android.view.VibratorContainer;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.util.Locale; import java.util.Locale;
/** /**
* User: serso * User: serso
* Date: 4/20/12 * Date: 4/20/12
* Time: 12:42 PM * Time: 12:42 PM
*/ */
public final class CalculatorPreferences { public final class CalculatorPreferences {
private CalculatorPreferences() { private CalculatorPreferences() {
throw new AssertionError(); throw new AssertionError();
} }
public static final Preference<Integer> appVersion = new IntegerPreference("application.version", -1); public static final Preference<Integer> appVersion = new IntegerPreference("application.version", -1);
public static final Preference<Integer> appOpenedCounter = new IntegerPreference("app_opened_counter", 0); public static final Preference<Integer> appOpenedCounter = new IntegerPreference("app_opened_counter", 0);
public static class Gui { public static class Gui {
public static final Preference<Theme> theme = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_theme", Theme.metro_blue_theme, Theme.class); public static final Preference<Theme> theme = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_theme", Theme.metro_blue_theme, Theme.class);
public static final Preference<Layout> layout = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_layout", Layout.main_calculator, Layout.class); public static final Preference<Layout> layout = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_layout", Layout.main_calculator, Layout.class);
public static final Preference<Boolean> feedbackWindowShown = new BooleanPreference("feedback_window_shown", false); public static final Preference<Boolean> feedbackWindowShown = new BooleanPreference("feedback_window_shown", false);
public static final Preference<Boolean> notesppAnnounceShown = new BooleanPreference("notespp_announce_shown", false); public static final Preference<Boolean> notesppAnnounceShown = new BooleanPreference("notespp_announce_shown", false);
public static final Preference<Boolean> showReleaseNotes = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_show_release_notes", true); public static final Preference<Boolean> showReleaseNotes = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_show_release_notes", true);
public static final Preference<Boolean> usePrevAsBack = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev", false); public static final Preference<Boolean> usePrevAsBack = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev", false);
public static final Preference<Boolean> showEqualsButton = new BooleanPreference("showEqualsButton", true); public static final Preference<Boolean> showEqualsButton = new BooleanPreference("showEqualsButton", true);
public static final Preference<Boolean> autoOrientation = new BooleanPreference("autoOrientation", true); public static final Preference<Boolean> autoOrientation = new BooleanPreference("autoOrientation", true);
public static final Preference<Boolean> hideNumeralBaseDigits = new BooleanPreference("hideNumeralBaseDigits", true); public static final Preference<Boolean> hideNumeralBaseDigits = new BooleanPreference("hideNumeralBaseDigits", true);
@NotNull @NotNull
public static Theme getTheme(@NotNull SharedPreferences preferences) { public static Theme getTheme(@NotNull SharedPreferences preferences) {
return theme.getPreferenceNoError(preferences); return theme.getPreferenceNoError(preferences);
} }
@NotNull @NotNull
public static Layout getLayout(@NotNull SharedPreferences preferences) { public static Layout getLayout(@NotNull SharedPreferences preferences) {
return layout.getPreferenceNoError(preferences); return layout.getPreferenceNoError(preferences);
} }
public static enum Theme { public static enum Theme {
default_theme(ThemeType.other, R.style.default_theme), default_theme(ThemeType.other, R.style.default_theme),
violet_theme(ThemeType.other, R.style.violet_theme), violet_theme(ThemeType.other, R.style.violet_theme),
light_blue_theme(ThemeType.other, R.style.light_blue_theme), light_blue_theme(ThemeType.other, R.style.light_blue_theme),
metro_blue_theme(ThemeType.metro, R.style.metro_blue_theme), metro_blue_theme(ThemeType.metro, R.style.metro_blue_theme),
metro_purple_theme(ThemeType.metro, R.style.metro_purple_theme), metro_purple_theme(ThemeType.metro, R.style.metro_purple_theme),
metro_green_theme(ThemeType.metro, R.style.metro_green_theme); metro_green_theme(ThemeType.metro, R.style.metro_green_theme);
@NotNull @NotNull
private final ThemeType themeType; private final ThemeType themeType;
@NotNull @NotNull
private final Integer themeId; private final Integer themeId;
Theme(@NotNull ThemeType themeType, Integer themeId) { Theme(@NotNull ThemeType themeType, Integer themeId) {
this.themeType = themeType; this.themeType = themeType;
this.themeId = themeId; this.themeId = themeId;
} }
@NotNull @NotNull
public ThemeType getThemeType() { public ThemeType getThemeType() {
return themeType; return themeType;
} }
@NotNull @NotNull
public Integer getThemeId() { public Integer getThemeId() {
return themeId; return themeId;
} }
} }
public static enum ThemeType { public static enum ThemeType {
metro, metro,
other other
} }
public static enum Layout { public static enum Layout {
main_calculator(R.layout.main_calculator), main_calculator(R.layout.main_calculator),
// not used anymore // not used anymore
@Deprecated @Deprecated
main_cellphone(R.layout.main_calculator), main_cellphone(R.layout.main_calculator),
simple(R.layout.main_calculator); simple(R.layout.main_calculator);
private final int layoutId; private final int layoutId;
Layout(int layoutId) { Layout(int layoutId) {
this.layoutId = layoutId; this.layoutId = layoutId;
} }
public int getLayoutId() { public int getLayoutId() {
return layoutId; return layoutId;
} }
} }
} }
public static class Graph { public static class Graph {
public static final Preference<Boolean> interpolate = new BooleanPreference("graph_interpolate", true); public static final Preference<Boolean> interpolate = new BooleanPreference("graph_interpolate", true);
public static final Preference<GraphLineColor> lineColorReal = StringPreference.newInstance("graph_line_color_real", GraphLineColor.white, GraphLineColor.class); public static final Preference<GraphLineColor> lineColorReal = StringPreference.newInstance("graph_line_color_real", GraphLineColor.white, GraphLineColor.class);
public static final Preference<GraphLineColor> lineColorImag = StringPreference.newInstance("graph_line_color_imag", GraphLineColor.blue, GraphLineColor.class); public static final Preference<GraphLineColor> lineColorImag = StringPreference.newInstance("graph_line_color_imag", GraphLineColor.blue, GraphLineColor.class);
} }
public static class History {
static void setDefaultValues(@NotNull SharedPreferences preferences) { public static final Preference<Boolean> showIntermediateCalculations = new BooleanPreference("history_show_intermediate_calculations", false);
if (!AndroidCalculatorEngine.Preferences.groupingSeparator.isSet(preferences)) { }
final Locale locale = Locale.getDefault();
if (locale != null) {
final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator())); static void setDefaultValues(@NotNull SharedPreferences preferences) {
final String groupingSeparator; if (!AndroidCalculatorEngine.Preferences.groupingSeparator.isSet(preferences)) {
if (index >= 0) { final Locale locale = Locale.getDefault();
groupingSeparator = MathType.grouping_separator.getTokens().get(index); if (locale != null) {
} else { final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
groupingSeparator = " "; int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
} final String groupingSeparator;
if (index >= 0) {
AndroidCalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator); groupingSeparator = MathType.grouping_separator.getTokens().get(index);
} } else {
} groupingSeparator = " ";
}
if (!AndroidCalculatorEngine.Preferences.angleUnit.isSet(preferences)) {
AndroidCalculatorEngine.Preferences.angleUnit.putDefault(preferences); AndroidCalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator);
} }
}
if (!AndroidCalculatorEngine.Preferences.numeralBase.isSet(preferences)) {
AndroidCalculatorEngine.Preferences.numeralBase.putDefault(preferences); if (!AndroidCalculatorEngine.Preferences.angleUnit.isSet(preferences)) {
} AndroidCalculatorEngine.Preferences.angleUnit.putDefault(preferences);
}
if (!AndroidCalculatorEngine.Preferences.multiplicationSign.isSet(preferences)) {
if ( AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2) ) { if (!AndroidCalculatorEngine.Preferences.numeralBase.isSet(preferences)) {
// workaround ofr samsung galaxy s phones AndroidCalculatorEngine.Preferences.numeralBase.putDefault(preferences);
AndroidCalculatorEngine.Preferences.multiplicationSign.putPreference(preferences, "*"); }
}
} if (!AndroidCalculatorEngine.Preferences.multiplicationSign.isSet(preferences)) {
if ( AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2) ) {
applyDefaultPreference(preferences, Gui.theme); // workaround ofr samsung galaxy s phones
applyDefaultPreference(preferences, Gui.layout); AndroidCalculatorEngine.Preferences.multiplicationSign.putPreference(preferences, "*");
if ( Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone ) { }
Gui.layout.putDefault(preferences); }
}
applyDefaultPreference(preferences, Gui.feedbackWindowShown); applyDefaultPreference(preferences, Gui.theme);
applyDefaultPreference(preferences, Gui.notesppAnnounceShown); applyDefaultPreference(preferences, Gui.layout);
applyDefaultPreference(preferences, Gui.showReleaseNotes); if ( Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone ) {
applyDefaultPreference(preferences, Gui.usePrevAsBack); Gui.layout.putDefault(preferences);
applyDefaultPreference(preferences, Gui.showEqualsButton); }
applyDefaultPreference(preferences, Gui.autoOrientation); applyDefaultPreference(preferences, Gui.feedbackWindowShown);
applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits); applyDefaultPreference(preferences, Gui.notesppAnnounceShown);
applyDefaultPreference(preferences, Gui.showReleaseNotes);
applyDefaultPreference(preferences, Graph.interpolate); applyDefaultPreference(preferences, Gui.usePrevAsBack);
applyDefaultPreference(preferences, Graph.lineColorImag); applyDefaultPreference(preferences, Gui.showEqualsButton);
applyDefaultPreference(preferences, Graph.lineColorReal); applyDefaultPreference(preferences, Gui.autoOrientation);
applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits);
if ( !VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences) ) {
VibratorContainer.Preferences.hapticFeedbackEnabled.putPreference(preferences, true); applyDefaultPreference(preferences, Graph.interpolate);
} applyDefaultPreference(preferences, Graph.lineColorImag);
applyDefaultPreference(preferences, Graph.lineColorReal);
if ( !VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences) ) { applyDefaultPreference(preferences, History.showIntermediateCalculations);
VibratorContainer.Preferences.hapticFeedbackDuration.putPreference(preferences, 60L);
} if ( !VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences) ) {
VibratorContainer.Preferences.hapticFeedbackEnabled.putPreference(preferences, true);
} }
private static void applyDefaultPreference(@NotNull SharedPreferences preferences, @NotNull Preference<?> preference) { if ( !VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences) ) {
if (!preference.isSet(preferences)) { VibratorContainer.Preferences.hapticFeedbackDuration.putPreference(preferences, 60L);
preference.putDefault(preferences); }
}
} }
} private static void applyDefaultPreference(@NotNull SharedPreferences preferences, @NotNull Preference<?> preference) {
if (!preference.isSet(preferences)) {
preference.putDefault(preferences);
}
}
}

View File

@ -1,200 +1,203 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import com.actionbarsherlock.app.SherlockPreferenceActivity; import com.actionbarsherlock.app.SherlockPreferenceActivity;
import net.robotmedia.billing.BillingController; import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.IBillingObserver; import net.robotmedia.billing.IBillingObserver;
import net.robotmedia.billing.ResponseCode; import net.robotmedia.billing.ResponseCode;
import net.robotmedia.billing.helper.AbstractBillingObserver; import net.robotmedia.billing.helper.AbstractBillingObserver;
import net.robotmedia.billing.model.Transaction; import net.robotmedia.billing.model.Transaction;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
import org.solovyev.android.ads.AdsController; import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine; import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.view.VibratorContainer; import org.solovyev.android.view.VibratorContainer;
/** /**
* User: serso * User: serso
* Date: 7/16/11 * Date: 7/16/11
* Time: 6:37 PM * Time: 6:37 PM
*/ */
public class CalculatorPreferencesActivity extends SherlockPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver { public class CalculatorPreferencesActivity extends SherlockPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver {
public static final String CLEAR_BILLING_INFO = "clear_billing_info"; public static final String CLEAR_BILLING_INFO = "clear_billing_info";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
//noinspection deprecation //noinspection deprecation
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
//noinspection deprecation //noinspection deprecation
addPreferencesFromResource(R.xml.plot_preferences); addPreferencesFromResource(R.xml.calculations_preferences);
addPreferencesFromResource(R.xml.appearance_preferences);
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); addPreferencesFromResource(R.xml.plot_preferences);
adFreePreference.setEnabled(false); addPreferencesFromResource(R.xml.other_preferences);
// observer must be set before net.robotmedia.billing.BillingController.checkBillingSupported() final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
BillingController.registerObserver(this); adFreePreference.setEnabled(false);
BillingController.checkBillingSupported(CalculatorPreferencesActivity.this); // observer must be set before net.robotmedia.billing.BillingController.checkBillingSupported()
BillingController.registerObserver(this);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(this); BillingController.checkBillingSupported(CalculatorPreferencesActivity.this);
onSharedPreferenceChanged(preferences, AndroidCalculatorEngine.Preferences.roundResult.getKey());
onSharedPreferenceChanged(preferences, VibratorContainer.Preferences.hapticFeedbackEnabled.getKey()); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.registerOnSharedPreferenceChangeListener(this);
final Preference clearBillingInfoPreference = findPreference(CLEAR_BILLING_INFO); onSharedPreferenceChanged(preferences, AndroidCalculatorEngine.Preferences.roundResult.getKey());
if (clearBillingInfoPreference != null) { onSharedPreferenceChanged(preferences, VibratorContainer.Preferences.hapticFeedbackEnabled.getKey());
clearBillingInfoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override final Preference clearBillingInfoPreference = findPreference(CLEAR_BILLING_INFO);
public boolean onPreferenceClick(Preference preference) { if (clearBillingInfoPreference != null) {
clearBillingInfoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_clearing, Toast.LENGTH_SHORT).show(); @Override
public boolean onPreferenceClick(Preference preference) {
removeBillingInformation(CalculatorPreferencesActivity.this, PreferenceManager.getDefaultSharedPreferences(CalculatorPreferencesActivity.this));
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_clearing, Toast.LENGTH_SHORT).show();
return true;
} removeBillingInformation(CalculatorPreferencesActivity.this, PreferenceManager.getDefaultSharedPreferences(CalculatorPreferencesActivity.this));
});
} return true;
} }
});
public static void removeBillingInformation(@NotNull Context context, @NotNull SharedPreferences preferences) { }
final SharedPreferences.Editor editor = preferences.edit(); }
editor.putBoolean(AbstractBillingObserver.KEY_TRANSACTIONS_RESTORED, false);
editor.commit(); public static void removeBillingInformation(@NotNull Context context, @NotNull SharedPreferences preferences) {
final SharedPreferences.Editor editor = preferences.edit();
BillingController.dropBillingData(context); editor.putBoolean(AbstractBillingObserver.KEY_TRANSACTIONS_RESTORED, false);
} editor.commit();
private void setAdFreeAction() { BillingController.dropBillingData(context);
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); }
if (!AdsController.getInstance().isAdFree(this)) { private void setAdFreeAction() {
Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - enable preference!"); final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { if (!AdsController.getInstance().isAdFree(this)) {
public boolean onPreferenceClick(Preference preference) { Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - enable preference!");
// check billing availability adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) { public boolean onPreferenceClick(Preference preference) {
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!");
// warn about not supported billing // check billing availability
new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show(); if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) {
} else { Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!");
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!"); // warn about not supported billing
if (!AdsController.getInstance().isAdFree(CalculatorPreferencesActivity.this)) { new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show();
Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!"); } else {
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!");
// not purchased => purchasing if (!AdsController.getInstance().isAdFree(CalculatorPreferencesActivity.this)) {
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_purchasing, Toast.LENGTH_SHORT).show(); Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!");
// show purchase window for user // not purchased => purchasing
BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true); Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_purchasing, Toast.LENGTH_SHORT).show();
} else {
// disable preference // show purchase window for user
adFreePreference.setEnabled(false); BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true);
// and show message to user } else {
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_already_purchased, Toast.LENGTH_SHORT).show(); // disable preference
} adFreePreference.setEnabled(false);
} // and show message to user
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_already_purchased, Toast.LENGTH_SHORT).show();
return true; }
} }
});
adFreePreference.setEnabled(true); return true;
} else { }
Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - disable preference!"); });
adFreePreference.setEnabled(false); adFreePreference.setEnabled(true);
} } else {
} Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - disable preference!");
adFreePreference.setEnabled(false);
@Override }
protected void onDestroy() { }
BillingController.unregisterObserver(this);
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this); @Override
super.onDestroy(); protected void onDestroy() {
} BillingController.unregisterObserver(this);
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
@Override super.onDestroy();
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { }
if (AndroidCalculatorEngine.Preferences.roundResult.getKey().equals(key)) {
findPreference(AndroidCalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, AndroidCalculatorEngine.Preferences.roundResult.getDefaultValue())); @Override
} else if (VibratorContainer.Preferences.hapticFeedbackEnabled.getKey().equals(key)) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
findPreference(VibratorContainer.Preferences.hapticFeedbackDuration.getKey()).setEnabled(VibratorContainer.Preferences.hapticFeedbackEnabled.getPreference(preferences)); if (AndroidCalculatorEngine.Preferences.roundResult.getKey().equals(key)) {
} findPreference(AndroidCalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, AndroidCalculatorEngine.Preferences.roundResult.getDefaultValue()));
} } else if (VibratorContainer.Preferences.hapticFeedbackEnabled.getKey().equals(key)) {
findPreference(VibratorContainer.Preferences.hapticFeedbackDuration.getKey()).setEnabled(VibratorContainer.Preferences.hapticFeedbackEnabled.getPreference(preferences));
@Override }
public void onCheckBillingSupportedResponse(boolean supported) { }
if (supported) {
setAdFreeAction(); @Override
} else { public void onCheckBillingSupportedResponse(boolean supported) {
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); if (supported) {
adFreePreference.setEnabled(false); setAdFreeAction();
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported!"); } else {
} final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
} adFreePreference.setEnabled(false);
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported!");
@Override }
public void onPurchaseIntentOK(@NotNull String productId, @NotNull PendingIntent purchaseIntent) { }
// do nothing
} @Override
public void onPurchaseIntentOK(@NotNull String productId, @NotNull PendingIntent purchaseIntent) {
@Override // do nothing
public void onPurchaseIntentFailure(@NotNull String productId, @NotNull ResponseCode responseCode) { }
// do nothing
} @Override
public void onPurchaseIntentFailure(@NotNull String productId, @NotNull ResponseCode responseCode) {
@Override // do nothing
public void onPurchaseStateChanged(@NotNull String itemId, @NotNull Transaction.PurchaseState state) { }
if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) {
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY); @Override
if (adFreePreference != null) { public void onPurchaseStateChanged(@NotNull String itemId, @NotNull Transaction.PurchaseState state) {
switch (state) { if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) {
case PURCHASED: final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
adFreePreference.setEnabled(false); if (adFreePreference != null) {
// restart activity to disable ads switch (state) {
AndroidUtils.restartActivity(this); case PURCHASED:
break; adFreePreference.setEnabled(false);
case CANCELLED: // restart activity to disable ads
adFreePreference.setEnabled(true); AndroidUtils.restartActivity(this);
break; break;
case REFUNDED: case CANCELLED:
adFreePreference.setEnabled(true); adFreePreference.setEnabled(true);
break; break;
} case REFUNDED:
} else { adFreePreference.setEnabled(true);
} break;
} }
} } else {
}
@Override }
public void onRequestPurchaseResponse(@NotNull String itemId, @NotNull ResponseCode response) { }
// do nothing
} @Override
public void onRequestPurchaseResponse(@NotNull String itemId, @NotNull ResponseCode response) {
@Override // do nothing
public void onTransactionsRestored() { }
// do nothing
} @Override
public void onTransactionsRestored() {
@Override // do nothing
public void onErrorRestoreTransactions(@NotNull ResponseCode responseCode) { }
// do nothing
} @Override
} public void onErrorRestoreTransactions(@NotNull ResponseCode responseCode) {
// do nothing
}
}

View File

@ -1,149 +1,158 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.Calculator;
import org.solovyev.common.history.HistoryAction; import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventType;
import java.util.List; import org.solovyev.android.calculator.R;
import org.solovyev.common.history.HistoryAction;
/**
* User: serso import java.util.List;
* Date: 10/9/11
* Time: 6:35 PM /**
*/ * User: serso
public class AndroidCalculatorHistory implements CalculatorHistory { * Date: 10/9/11
* Time: 6:35 PM
@NotNull */
private final CalculatorHistoryImpl calculatorHistory; public class AndroidCalculatorHistory implements CalculatorHistory {
@NotNull @NotNull
private final Context context; private final CalculatorHistoryImpl calculatorHistory;
public AndroidCalculatorHistory(@NotNull Application application, @NotNull Calculator calculator) { @NotNull
this.context = application; private final Context context;
calculatorHistory = new CalculatorHistoryImpl(calculator);
} public AndroidCalculatorHistory(@NotNull Application application, @NotNull Calculator calculator) {
this.context = application;
@Override calculatorHistory = new CalculatorHistoryImpl(calculator);
public void load() { }
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (preferences != null) { @Override
final String value = preferences.getString(context.getString(R.string.p_calc_history), null); public void load() {
if (value != null) { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
calculatorHistory.fromXml(value); if (preferences != null) {
} final String value = preferences.getString(context.getString(R.string.p_calc_history), null);
} if (value != null) {
} calculatorHistory.fromXml(value);
}
public void save() { }
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); }
final SharedPreferences.Editor editor = settings.edit();
public void save() {
editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml()); final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editor = settings.edit();
editor.commit();
} editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml());
public void clearSavedHistory() { editor.commit();
calculatorHistory.clearSavedHistory(); }
save();
} public void clearSavedHistory() {
calculatorHistory.clearSavedHistory();
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { save();
historyState.setSaved(false); }
calculatorHistory.removeSavedHistory(historyState);
save(); public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
} historyState.setSaved(false);
calculatorHistory.removeSavedHistory(historyState);
@Override save();
public boolean isEmpty() { }
return calculatorHistory.isEmpty();
} @Override
public boolean isEmpty() {
@Override return calculatorHistory.isEmpty();
public CalculatorHistoryState getLastHistoryState() { }
return calculatorHistory.getLastHistoryState();
} @Override
public CalculatorHistoryState getLastHistoryState() {
@Override return calculatorHistory.getLastHistoryState();
public boolean isUndoAvailable() { }
return calculatorHistory.isUndoAvailable();
} @Override
public boolean isUndoAvailable() {
@Override return calculatorHistory.isUndoAvailable();
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) { }
return calculatorHistory.undo(currentState);
} @Override
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
@Override return calculatorHistory.undo(currentState);
public boolean isRedoAvailable() { }
return calculatorHistory.isRedoAvailable();
} @Override
public boolean isRedoAvailable() {
@Override return calculatorHistory.isRedoAvailable();
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) { }
return calculatorHistory.redo(currentState);
} @Override
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
@Override return calculatorHistory.redo(currentState);
public boolean isActionAvailable(@NotNull HistoryAction historyAction) { }
return calculatorHistory.isActionAvailable(historyAction);
} @Override
public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
@Override return calculatorHistory.isActionAvailable(historyAction);
public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) { }
return calculatorHistory.doAction(historyAction, currentState);
} @Override
public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
@Override return calculatorHistory.doAction(historyAction, currentState);
public void addState(@Nullable CalculatorHistoryState currentState) { }
calculatorHistory.addState(currentState);
} @Override
public void addState(@Nullable CalculatorHistoryState currentState) {
@NotNull calculatorHistory.addState(currentState);
@Override }
public List<CalculatorHistoryState> getStates() {
return calculatorHistory.getStates(); @NotNull
} @Override
public List<CalculatorHistoryState> getStates() {
@Override return calculatorHistory.getStates();
public void clear() { }
calculatorHistory.clear();
} @NotNull
@Override
@NotNull public List<CalculatorHistoryState> getStates(boolean includeIntermediateStates) {
public List<CalculatorHistoryState> getSavedHistory() { return calculatorHistory.getStates(includeIntermediateStates);
return calculatorHistory.getSavedHistory(); }
}
@Override
@NotNull public void clear() {
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) { calculatorHistory.clear();
return calculatorHistory.addSavedState(historyState); }
}
@NotNull
@Override public List<CalculatorHistoryState> getSavedHistory() {
public void fromXml(@NotNull String xml) { return calculatorHistory.getSavedHistory();
calculatorHistory.fromXml(xml); }
}
@NotNull
@Override public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
public String toXml() { return calculatorHistory.addSavedState(historyState);
return calculatorHistory.toXml(); }
}
@Override
@Override public void fromXml(@NotNull String xml) {
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { calculatorHistory.fromXml(xml);
calculatorHistory.onCalculatorEvent(calculatorEventData, calculatorEventType, data); }
}
} @Override
public String toXml() {
return calculatorHistory.toXml();
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
calculatorHistory.onCalculatorEvent(calculatorEventData, calculatorEventType, data);
}
}

View File

@ -6,8 +6,10 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import android.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorLocatorImpl; import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.CalculatorPreferences;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.about.CalculatorFragmentType; import org.solovyev.android.calculator.about.CalculatorFragmentType;
@ -33,7 +35,8 @@ public class CalculatorHistoryFragment extends AbstractCalculatorHistoryFragment
@NotNull @NotNull
@Override @Override
protected List<CalculatorHistoryState> getHistoryItems() { protected List<CalculatorHistoryState> getHistoryItems() {
return new ArrayList<CalculatorHistoryState>(CalculatorLocatorImpl.getInstance().getHistory().getStates()); final boolean showIntermediateCalculations = CalculatorPreferences.History.showIntermediateCalculations.getPreference(PreferenceManager.getDefaultSharedPreferences(getActivity()));
return new ArrayList<CalculatorHistoryState>(CalculatorLocatorImpl.getInstance().getHistory().getStates(showIntermediateCalculations));
} }
@Override @Override