This commit is contained in:
serso 2016-01-12 10:49:50 +01:00
parent a57d4aab57
commit 6d91013858
26 changed files with 417 additions and 266 deletions

View File

@ -40,7 +40,10 @@ import android.support.v4.app.FragmentTransaction;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.util.Log;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.UiThreadExecutor; import org.solovyev.android.UiThreadExecutor;
import org.solovyev.android.Views; import org.solovyev.android.Views;
@ -49,7 +52,13 @@ import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService; import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
import org.solovyev.android.calculator.view.ScreenMetrics; import org.solovyev.android.calculator.view.ScreenMetrics;
import org.solovyev.android.calculator.wizard.CalculatorWizards; import org.solovyev.android.calculator.wizard.CalculatorWizards;
import org.solovyev.android.checkout.*; import org.solovyev.android.checkout.Billing;
import org.solovyev.android.checkout.Checkout;
import org.solovyev.android.checkout.Inventory;
import org.solovyev.android.checkout.ProductTypes;
import org.solovyev.android.checkout.Products;
import org.solovyev.android.checkout.RobotmediaDatabase;
import org.solovyev.android.checkout.RobotmediaInventory;
import org.solovyev.android.wizard.Wizards; import org.solovyev.android.wizard.Wizards;
import org.solovyev.common.listeners.JEvent; import org.solovyev.common.listeners.JEvent;
import org.solovyev.common.listeners.JEventListener; import org.solovyev.common.listeners.JEventListener;
@ -57,11 +66,13 @@ import org.solovyev.common.listeners.JEventListeners;
import org.solovyev.common.listeners.Listeners; import org.solovyev.common.listeners.Listeners;
import org.solovyev.common.threads.DelayedExecutor; import org.solovyev.common.threads.DelayedExecutor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* User: serso * User: serso
@ -119,7 +130,12 @@ public final class App {
@Nonnull @Nonnull
private static Wizards wizards; private static Wizards wizards;
@Nonnull @Nonnull
private static final Executor initializer = Executors.newSingleThreadExecutor(); private static final Executor initThread = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(@Nonnull Runnable r) {
return new Thread(r, "Init");
}
});
private App() { private App() {
throw new AssertionError(); throw new AssertionError();
@ -251,8 +267,8 @@ public final class App {
} }
@Nonnull @Nonnull
public static Executor getInitializer() { public static Executor getInitThread() {
return initializer; return initThread;
} }
@Nonnull @Nonnull

View File

@ -33,12 +33,16 @@ import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import jscl.math.Generic;
import org.solovyev.android.Activities; import org.solovyev.android.Activities;
import org.solovyev.android.calculator.about.CalculatorAboutActivity; import org.solovyev.android.calculator.about.CalculatorAboutActivity;
import org.solovyev.android.calculator.function.FunctionEditDialogFragment; import org.solovyev.android.calculator.function.FunctionEditDialogFragment;
import org.solovyev.android.calculator.history.CalculatorHistoryActivity; import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
import org.solovyev.android.calculator.math.edit.*; import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity;
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsActivity;
import org.solovyev.android.calculator.math.edit.CalculatorVarsActivity;
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
import org.solovyev.android.calculator.math.edit.VarEditDialogFragment;
import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity; import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity;
import org.solovyev.android.calculator.plot.CalculatorPlotActivity; import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
import org.solovyev.android.calculator.plot.CalculatorPlotter; import org.solovyev.android.calculator.plot.CalculatorPlotter;
@ -47,9 +51,12 @@ import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType; import org.solovyev.common.msg.MessageType;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
import jscl.math.Generic;
/** /**
* User: serso * User: serso
@ -131,8 +138,8 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
public static void tryCreateVar(@Nonnull final Context context) { public static void tryCreateVar(@Nonnull final Context context) {
final Display display = Locator.getInstance().getDisplay(); final Display display = Locator.getInstance().getDisplay();
final DisplayState viewState = display.getState(); final DisplayState viewState = display.getState();
if (viewState.isValid()) { if (viewState.valid) {
final String varValue = viewState.getText(); final String varValue = viewState.text;
if (!Strings.isEmpty(varValue)) { if (!Strings.isEmpty(varValue)) {
if (CalculatorVarsFragment.isValidValue(varValue)) { if (CalculatorVarsFragment.isValidValue(varValue)) {
if (context instanceof AppCompatActivity) { if (context instanceof AppCompatActivity) {
@ -158,12 +165,10 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
final Display display = Locator.getInstance().getDisplay(); final Display display = Locator.getInstance().getDisplay();
final DisplayState viewState = display.getState(); final DisplayState viewState = display.getState();
if (viewState.isValid()) { if (viewState.valid) {
final String functionValue = viewState.getText(); final String functionValue = viewState.text;
if (!Strings.isEmpty(functionValue)) { if (!Strings.isEmpty(functionValue)) {
FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newFromDisplay(viewState), context); FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newFromDisplay(viewState), context);
} else { } else {
getNotifier().showMessage(R.string.empty_function_error, MessageType.error); getNotifier().showMessage(R.string.empty_function_error, MessageType.error);
} }
@ -182,8 +187,8 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
final Display display = Locator.getInstance().getDisplay(); final Display display = Locator.getInstance().getDisplay();
final DisplayState viewState = display.getState(); final DisplayState viewState = display.getState();
if (viewState.isValid()) { if (viewState.valid) {
final String functionValue = viewState.getText(); final String functionValue = viewState.text;
final Generic expression = viewState.getResult(); final Generic expression = viewState.getResult();
if (!Strings.isEmpty(functionValue) && expression != null) { if (!Strings.isEmpty(functionValue) && expression != null) {
if (plotter.isPlotPossibleFor(expression)) { if (plotter.isPlotPossibleFor(expression)) {

View File

@ -90,7 +90,7 @@ public class CalculatorApplication extends android.app.Application implements Sh
Locator.getInstance().getCalculator().init(); Locator.getInstance().getCalculator().init();
App.getInitializer().execute(new Runnable() { App.getInitThread().execute(new Runnable() {
@Override @Override
public void run() { public void run() {
warmUpEngine(); warmUpEngine();

View File

@ -123,7 +123,7 @@ public enum CalculatorDisplayMenuItem implements LabeledMenuItem<DisplayState> {
public final boolean isItemVisible(@Nonnull DisplayState displayViewState) { public final boolean isItemVisible(@Nonnull DisplayState displayViewState) {
//noinspection ConstantConditions //noinspection ConstantConditions
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation()); return displayViewState.valid && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
} }
protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) {

View File

@ -24,13 +24,15 @@ package org.solovyev.android.calculator;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.view.View; import android.view.View;
import org.solovyev.android.menu.ContextMenuBuilder; import org.solovyev.android.menu.ContextMenuBuilder;
import org.solovyev.android.menu.ListContextMenu; import org.solovyev.android.menu.ListContextMenu;
import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 21.09.12 * Date: 21.09.12
@ -52,7 +54,7 @@ public class CalculatorDisplayOnClickListener implements View.OnClickListener {
final DisplayState displayViewState = cd.getState(); final DisplayState displayViewState = cd.getState();
if (displayViewState.isValid()) { if (displayViewState.valid) {
final List<CalculatorDisplayMenuItem> filteredMenuItems = new ArrayList<CalculatorDisplayMenuItem>(CalculatorDisplayMenuItem.values().length); final List<CalculatorDisplayMenuItem> filteredMenuItems = new ArrayList<CalculatorDisplayMenuItem>(CalculatorDisplayMenuItem.values().length);
for (CalculatorDisplayMenuItem menuItem : CalculatorDisplayMenuItem.values()) { for (CalculatorDisplayMenuItem menuItem : CalculatorDisplayMenuItem.values()) {
if (menuItem.isItemVisible(displayViewState)) { if (menuItem.isItemVisible(displayViewState)) {
@ -65,10 +67,8 @@ public class CalculatorDisplayOnClickListener implements View.OnClickListener {
} }
} else { } else {
final String errorMessage = displayViewState.getErrorMessage(); final String errorMessage = displayViewState.text;
if (errorMessage != null) { Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_evaluation_error, errorMessage, activity);
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_evaluation_error, errorMessage, activity);
}
} }
} }
} }

View File

@ -23,16 +23,9 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.text.TextUtils; import android.text.TextUtils;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.model.Var; import org.solovyev.android.calculator.model.Var;
import org.solovyev.android.calculator.text.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
@ -45,14 +38,24 @@ import org.solovyev.common.text.Strings;
import org.solovyev.common.units.ConversionException; import org.solovyev.common.units.ConversionException;
import org.solovyev.common.units.Conversions; import org.solovyev.common.units.Conversions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
@ -486,11 +489,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@Subscribe @Subscribe
public void onDisplayChanged(@Nonnull Display.ChangedEvent e) { public void onDisplayChanged(@Nonnull Display.ChangedEvent e) {
final DisplayState newState = e.newState; final DisplayState newState = e.newState;
if (!newState.isValid()) { if (!newState.valid) {
return; return;
} }
final String result = newState.getStringResult(); final String text = newState.text;
if (TextUtils.isEmpty(result)) { if (TextUtils.isEmpty(text)) {
return; return;
} }
final CalculatorMathRegistry<IConstant> varsRegistry = Locator.getInstance().getEngine().getVarsRegistry(); final CalculatorMathRegistry<IConstant> varsRegistry = Locator.getInstance().getEngine().getVarsRegistry();
@ -498,7 +501,7 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
final Var.Builder builder = ansVar != null ? new Var.Builder(ansVar) : new Var.Builder(); final Var.Builder builder = ansVar != null ? new Var.Builder(ansVar) : new Var.Builder();
builder.setName(CalculatorVarsRegistry.ANS); builder.setName(CalculatorVarsRegistry.ANS);
builder.setValue(result); builder.setValue(text);
builder.setDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description)); builder.setDescription(CalculatorMessages.getBundle().getString(CalculatorMessages.ans_description));
CalculatorVarsRegistry.saveVariable(varsRegistry, builder, ansVar, this, false); CalculatorVarsRegistry.saveVariable(varsRegistry, builder, ansVar, this, false);

View File

@ -116,14 +116,12 @@ public class CalculatorKeyboard {
} }
public void copyButtonPressed() { public void copyButtonPressed() {
final DisplayState displayViewState = Locator.getInstance().getDisplay().getState(); final DisplayState displayState = Locator.getInstance().getDisplay().getState();
if (displayViewState.isValid()) { if (!displayState.valid) {
final CharSequence text = displayViewState.getText(); return;
if (!Strings.isEmpty(text)) {
Locator.getInstance().getClipboard().setText(text);
Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
}
} }
Locator.getInstance().getClipboard().setText(displayState.text);
Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied));
} }
public void moveCursorLeft() { public void moveCursorLeft() {

View File

@ -22,12 +22,11 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.solovyev.common.text.Strings; import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
/** /**
* User: serso * User: serso
@ -115,13 +114,11 @@ public enum CalculatorSpecialButton {
return; return;
} }
final DisplayState displayViewState = Locator.getInstance().getDisplay().getState(); final DisplayState displayState = Locator.getInstance().getDisplay().getState();
if (displayViewState.isValid()) { if (!displayState.valid) {
final CharSequence text = displayViewState.getText(); return;
if (!Strings.isEmpty(text)) {
Locator.getInstance().getEditor().setText(text.toString());
}
} }
Locator.getInstance().getEditor().setText(displayState.text);
} }
}, },
clear("clear") { clear("clear") {

View File

@ -23,47 +23,43 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.text.TextUtils; import android.text.TextUtils;
import jscl.math.Generic;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import jscl.math.Generic;
public class DisplayState { public class DisplayState {
private static final String JSON_TEXT = "t";
@Nonnull @Nonnull
private static final String JSON_OPERATION = "o"; public final String text;
public final boolean valid;
public final long sequence;
@Nonnull @Nonnull
private JsclOperation operation = JsclOperation.numeric; private transient JsclOperation operation = JsclOperation.numeric;
@Nullable @Nullable
private transient Generic result; private transient Generic result;
@Nullable private DisplayState(@Nonnull String text, boolean valid, long sequence) {
private String stringResult = ""; this.text = text;
this.valid = valid;
private boolean valid = true; this.sequence = sequence;
@Nullable
private String errorMessage;
private long sequence;
private DisplayState() {
} }
private DisplayState(@Nonnull JSONObject json) { DisplayState(@Nonnull JSONObject json) {
operation = JsclOperation.values()[json.optInt(JSON_OPERATION, JsclOperation.numeric.ordinal())]; this(json.optString(JSON_TEXT), true, EditorState.NO_SEQUENCE);
} }
@Nonnull @Nonnull
public static DisplayState empty() { public static DisplayState empty() {
return new DisplayState(); return new DisplayState("", true, EditorState.NO_SEQUENCE);
} }
@Nonnull @Nonnull
public static DisplayState create(@Nonnull JSONObject json) { public static DisplayState create(@Nonnull JSONObject json) {
return new DisplayState(json); return new DisplayState(json);
@ -73,11 +69,8 @@ public class DisplayState {
public static DisplayState createError(@Nonnull JsclOperation operation, public static DisplayState createError(@Nonnull JsclOperation operation,
@Nonnull String errorMessage, @Nonnull String errorMessage,
long sequence) { long sequence) {
final DisplayState state = new DisplayState(); final DisplayState state = new DisplayState(errorMessage, false, sequence);
state.valid = false;
state.errorMessage = errorMessage;
state.operation = operation; state.operation = operation;
state.sequence = sequence;
return state; return state;
} }
@ -86,49 +79,30 @@ public class DisplayState {
@Nullable Generic result, @Nullable Generic result,
@Nonnull String stringResult, @Nonnull String stringResult,
long sequence) { long sequence) {
final DisplayState state = new DisplayState(); final DisplayState state = new DisplayState(stringResult, true, sequence);
state.valid = true;
state.result = result; state.result = result;
state.stringResult = stringResult;
state.operation = operation; state.operation = operation;
state.sequence = sequence;
return state; return state;
} }
@Nonnull
public String getText() {
return Strings.getNotEmpty(isValid() ? stringResult : errorMessage, "");
}
@Nullable @Nullable
public Generic getResult() { public Generic getResult() {
return this.result; return this.result;
} }
public boolean isValid() {
return this.valid;
}
@Nullable
public String getErrorMessage() {
return this.errorMessage;
}
@Nullable
public String getStringResult() {
return stringResult;
}
@Nonnull @Nonnull
public JsclOperation getOperation() { public JsclOperation getOperation() {
return this.operation; return this.operation;
} }
public long getSequence() { public boolean same(@Nonnull DisplayState that) {
return sequence; return TextUtils.equals(text, that.text) && operation == that.operation;
} }
public boolean same(@Nonnull DisplayState that) { @Nonnull
return TextUtils.equals(stringResult, that.stringResult) && TextUtils.equals(errorMessage, that.errorMessage) && operation == that.operation; public JSONObject toJson() throws JSONException {
final JSONObject json = new JSONObject();
json.put(JSON_TEXT, text);
return json;
} }
} }

View File

@ -89,7 +89,7 @@ public class DisplayView extends AutoResizeTextView {
Check.isMainThread(); Check.isMainThread();
state = newState; state = newState;
if (state.isValid()) { if (state.valid) {
setText(highlightText(state)); setText(highlightText(state));
setTextColor(getTextColor().normal); setTextColor(getTextColor().normal);
} else { } else {
@ -100,7 +100,7 @@ public class DisplayView extends AutoResizeTextView {
@NonNull @NonNull
private CharSequence highlightText(@Nonnull DisplayState state) { private CharSequence highlightText(@Nonnull DisplayState state) {
final String text = state.getStringResult(); final String text = state.text;
if (TextUtils.isEmpty(text)) { if (TextUtils.isEmpty(text)) {
return ""; return "";
} }

View File

@ -33,9 +33,7 @@ import javax.annotation.Nullable;
public class EditorState { public class EditorState {
public static final long NO_SEQUENCE = -1; public static final long NO_SEQUENCE = -1;
@Nonnull
private static final String JSON_TEXT = "t"; private static final String JSON_TEXT = "t";
@Nonnull
private static final String JSON_SELECTION = "s"; private static final String JSON_SELECTION = "s";
private static long counter = NO_SEQUENCE + 1; private static long counter = NO_SEQUENCE + 1;

View File

@ -311,7 +311,7 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
public static Input newFromDisplay(@Nonnull DisplayState viewState) { public static Input newFromDisplay(@Nonnull DisplayState viewState) {
final Input result = new Input(); final Input result = new Input();
result.content = viewState.getText(); result.content = viewState.text;
final Generic generic = viewState.getResult(); final Generic generic = viewState.getResult();
if (generic != null) { if (generic != null) {
final Set<Constant> constants = CalculatorUtils.getNotSystemConstants(generic); final Set<Constant> constants = CalculatorUtils.getNotSystemConstants(generic);

View File

@ -30,18 +30,38 @@ import android.os.Bundle;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.support.v4.app.ListFragment; import android.support.v4.app.ListFragment;
import android.text.ClipboardManager; import android.text.ClipboardManager;
import android.view.*; import android.view.ContextMenu;
import android.widget.*; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.melnykov.fab.FloatingActionButton; import com.melnykov.fab.FloatingActionButton;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.CalculatorActivity;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.FragmentUi;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static android.view.Menu.NONE; import static android.view.Menu.NONE;
import static org.solovyev.android.calculator.CalculatorEventType.clear_history_requested; import static org.solovyev.android.calculator.CalculatorEventType.clear_history_requested;
@ -71,7 +91,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
@Nonnull @Nonnull
public static String getHistoryText(@Nonnull HistoryState state) { public static String getHistoryText(@Nonnull HistoryState state) {
return state.editor.getTextString() + getIdentitySign(state.display.getOperation()) + state.display.getText(); return state.editor.getTextString() + getIdentitySign(state.display.getOperation()) + state.display.text;
} }
@Nonnull @Nonnull
@ -185,7 +205,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
} }
return true; return true;
case R.string.c_copy_result: case R.string.c_copy_result:
final String displayText = state.display.getText(); final String displayText = state.display.text;
if (!Strings.isEmpty(displayText)) { if (!Strings.isEmpty(displayText)) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE); final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
clipboard.setText(displayText); clipboard.setText(displayText);
@ -200,7 +220,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
return true; return true;
case R.string.c_remove: case R.string.c_remove:
getAdapter().remove(state); getAdapter().remove(state);
Locator.getInstance().getHistory().removeSavedHistory(state); Locator.getInstance().getHistory().removeSaved(state);
Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show(); Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show();
getAdapter().notifyDataSetChanged(); getAdapter().notifyDataSetChanged();
return true; return true;
@ -226,7 +246,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
/*if (save) { /*if (save) {
final HistoryState savedHistoryItem = Locator.getInstance().getHistory().addSavedState(state); final HistoryState savedHistoryItem = Locator.getInstance().getHistory().addSaved(state);
savedHistoryItem.setComment(comment.getText().toString()); savedHistoryItem.setComment(comment.getText().toString());
Locator.getInstance().getHistory().save(); Locator.getInstance().getHistory().save();
// we don't need to add element to the adapter as adapter of another activity must be updated and not this // we don't need to add element to the adapter as adapter of another activity must be updated and not this
@ -245,7 +265,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
} }
private boolean shouldHaveCopyResult(@Nonnull HistoryState state) { private boolean shouldHaveCopyResult(@Nonnull HistoryState state) {
return !state.display.isValid() || !Strings.isEmpty(state.display.getText()); return !state.display.valid || !Strings.isEmpty(state.display.text);
} }
@Override @Override

View File

@ -23,32 +23,48 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.Display;
import org.solovyev.android.calculator.DisplayState;
import org.solovyev.android.calculator.Editor;
import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.io.FileLoader;
import org.solovyev.android.io.FileSaver; import org.solovyev.android.io.FileSaver;
import javax.annotation.Nonnull; import java.io.File;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class CalculatorHistory { public class CalculatorHistory {
public static final String TAG = App.subTag("History");
@Nonnull @Nonnull
private final HistoryList current = new HistoryList(); private final HistoryList current = new HistoryList();
@Nonnull @Nonnull
private final List<HistoryState> saved = new ArrayList<>(); private final List<HistoryState> saved = new ArrayList<>();
@Nullable @Nullable
private EditorState lastEditorState; private EditorState lastEditorState;
private boolean initialized;
public CalculatorHistory() { public CalculatorHistory() {
App.getBus().register(this); App.getBus().register(this);
App.getInitializer().execute(new Runnable() { App.getInitThread().execute(new Runnable() {
@Override @Override
public void run() { public void run() {
init(); init();
@ -57,54 +73,97 @@ public class CalculatorHistory {
} }
private static void migrateOldHistory() { private static void migrateOldHistory() {
final SharedPreferences preferences = App.getPreferences(); try {
final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null); final SharedPreferences preferences = App.getPreferences();
if (TextUtils.isEmpty(xml)) { final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null);
return; if (TextUtils.isEmpty(xml)) {
return;
}
final OldHistory history = OldHistory.fromXml(xml);
if (history == null) {
// strange, history seems to be broken. Avoid clearing the preference
return;
}
final List<HistoryState> states = new ArrayList<>();
for (OldHistoryState state : history.getItems()) {
final OldEditorHistoryState oldEditorState = state.getEditorState();
final OldDisplayHistoryState oldDisplayState = state.getDisplayState();
final String editorText = oldEditorState.getText();
final EditorState editor = EditorState.create(Strings.nullToEmpty(editorText), oldEditorState.getCursorPosition());
final DisplayState display = oldDisplayState.isValid()
? DisplayState.createValid(oldDisplayState.getJsclOperation(), null, Strings.nullToEmpty(oldDisplayState.getEditorState().getText()), EditorState.NO_SEQUENCE)
: DisplayState.createError(oldDisplayState.getJsclOperation(), "", EditorState.NO_SEQUENCE);
states.add(HistoryState.newBuilder(editor, display).build());
}
final JSONArray json = HistoryList.toJson(states);
FileSaver.save(getSavedHistoryFile(), json.toString());
} catch (Exception e) {
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
} }
final OldHistory history = OldHistory.fromXml(xml); }
if (history == null) {
// strange, history seems to be broken. Avoid clearing the preference @NonNull
return; private static File getSavedHistoryFile() {
return new File(App.getApplication().getFilesDir(), "history-saved.json");
}
@NonNull
private static File getCurrentHistoryFile() {
return new File(App.getApplication().getFilesDir(), "history-current.json");
}
@Nonnull
private static List<HistoryState> loadStates(@Nonnull File file) {
final CharSequence json = FileLoader.load(file);
if (TextUtils.isEmpty(json)) {
return Collections.emptyList();
} }
final List<HistoryState> states = new ArrayList<>(); try {
for (OldHistoryState state : history.getItems()) { return HistoryList.fromJson(new JSONArray(json.toString()));
final OldEditorHistoryState oldEditorState = state.getEditorState(); } catch (JSONException e) {
final OldDisplayHistoryState oldDisplayState = state.getDisplayState(); Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
final String editorText = oldEditorState.getText();
final EditorState editor = EditorState.create(Strings.nullToEmpty(editorText), oldEditorState.getCursorPosition());
final DisplayState display = oldDisplayState.isValid()
? DisplayState.createValid(oldDisplayState.getJsclOperation(), null, Strings.nullToEmpty(oldDisplayState.getEditorState().getText()), EditorState.NO_SEQUENCE)
: DisplayState.createError(oldDisplayState.getJsclOperation(), "", EditorState.NO_SEQUENCE);
states.add(HistoryState.newBuilder(editor, display).build());
} }
return Collections.emptyList();
} }
private void init() { private void init() {
Check.isNotMainThread(); Check.isNotMainThread();
migrateOldHistory(); migrateOldHistory();
final List<HistoryState> currentStates = loadStates(getCurrentHistoryFile());
final List<HistoryState> savedStates = loadStates(getSavedHistoryFile());
App.getHandler().post(new Runnable() {
@Override
public void run() {
current.addAll(currentStates);
saved.addAll(savedStates);
initialized = true;
}
});
} }
public boolean isEmpty() { public void addCurrent(@Nonnull HistoryState state) {
Check.isMainThread();
return current.isEmpty();
}
public void addCurrentState(@Nonnull HistoryState state) {
Check.isMainThread(); Check.isMainThread();
current.add(state); current.add(state);
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, state); Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, state);
// todo serso: schedule save onCurrentChanged();
} }
public void addSavedState(@Nonnull HistoryState state) { public void addSaved(@Nonnull HistoryState state) {
Check.isMainThread(); Check.isMainThread();
saved.add(state); saved.add(state);
// todo serso: schedule save onSavedChanged();
}
private void onCurrentChanged() {
// todo serso: implement
}
private void onSavedChanged() {
// todo serso: implement
} }
@Nonnull @Nonnull
public List<HistoryState> getCurrentHistory() { public List<HistoryState> getCurrent() {
Check.isMainThread(); Check.isMainThread();
final List<HistoryState> result = new LinkedList<>(); final List<HistoryState> result = new LinkedList<>();
@ -122,6 +181,12 @@ public class CalculatorHistory {
return result; return result;
} }
@Nonnull
public List<HistoryState> getSaved() {
Check.isMainThread();
return Collections.unmodifiableList(saved);
}
private boolean isIntermediate(@Nonnull String newerText, private boolean isIntermediate(@Nonnull String newerText,
@Nonnull String olderText) { @Nonnull String olderText) {
final int diff = newerText.length() - olderText.length(); final int diff = newerText.length() - olderText.length();
@ -136,9 +201,16 @@ public class CalculatorHistory {
return false; return false;
} }
public void clear() { public void clearCurrent() {
Check.isMainThread(); Check.isMainThread();
current.clear(); current.clear();
onCurrentChanged();
}
public void clearSaved() {
Check.isMainThread();
saved.clear();
onSavedChanged();
} }
public void undo() { public void undo() {
@ -146,7 +218,7 @@ public class CalculatorHistory {
if (state == null) { if (state == null) {
return; return;
} }
onCurrentStateChanged(state); applyHistoryState(state);
} }
public void redo() { public void redo() {
@ -154,41 +226,46 @@ public class CalculatorHistory {
if (state == null) { if (state == null) {
return; return;
} }
onCurrentStateChanged(state); applyHistoryState(state);
} }
private void onCurrentStateChanged(@Nonnull HistoryState state) { private void applyHistoryState(@Nonnull HistoryState state) {
App.getEditor().setState(state.editor); App.getEditor().setState(state.editor);
App.getDisplay().setState(state.display); App.getDisplay().setState(state.display);
} }
@Nonnull public void removeSaved(@Nonnull HistoryState state) {
public List<HistoryState> getSavedHistory() { Check.isMainThread();
return Collections.unmodifiableList(saved);
}
public void clearSavedHistory() {
saved.clear();
}
public void removeSavedHistory(@Nonnull HistoryState state) {
saved.remove(state); saved.remove(state);
onSavedChanged();
}
public void removeCurrent(@Nonnull HistoryState state) {
Check.isMainThread();
current.remove(state);
onCurrentChanged();
} }
@Subscribe @Subscribe
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) { public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
if (!initialized) {
return;
}
lastEditorState = e.newState; lastEditorState = e.newState;
} }
@Subscribe @Subscribe
public void onDisplayChanged(@Nonnull Display.ChangedEvent e) { public void onDisplayChanged(@Nonnull Display.ChangedEvent e) {
if (!initialized) {
return;
}
if (lastEditorState == null) { if (lastEditorState == null) {
return; return;
} }
if (lastEditorState.sequence != e.newState.getSequence()) { if (lastEditorState.sequence != e.newState.sequence) {
return; return;
} }
addCurrentState(HistoryState.newBuilder(lastEditorState, e.newState).build()); addCurrent(HistoryState.newBuilder(lastEditorState, e.newState).build());
lastEditorState = null; lastEditorState = null;
} }
} }

View File

@ -44,12 +44,12 @@ public class HistoryFragment extends BaseHistoryFragment {
@Nonnull @Nonnull
@Override @Override
protected List<HistoryState> getHistoryItems() { protected List<HistoryState> getHistoryItems() {
return Locator.getInstance().getHistory().getCurrentHistory(); return Locator.getInstance().getHistory().getCurrent();
} }
@Override @Override
protected void clearHistory() { protected void clearHistory() {
Locator.getInstance().getHistory().clear(); Locator.getInstance().getHistory().clearCurrent();
getAdapter().clear(); getAdapter().clear();
} }
} }

View File

@ -1,56 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.history;
import android.widget.ArrayAdapter;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 12/18/11
* Time: 3:10 PM
*/
public class HistoryItemMenuData {
@Nonnull
private final ArrayAdapter<OldHistoryState> adapter;
@Nonnull
private final OldHistoryState historyState;
public HistoryItemMenuData(@Nonnull OldHistoryState historyState, ArrayAdapter<OldHistoryState> adapter) {
this.historyState = historyState;
this.adapter = adapter;
}
@Nonnull
public OldHistoryState getHistoryState() {
return historyState;
}
@Nonnull
public ArrayAdapter<OldHistoryState> getAdapter() {
return adapter;
}
}

View File

@ -2,8 +2,14 @@ package org.solovyev.android.calculator.history;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -32,6 +38,26 @@ public class HistoryList {
} }
} }
public void addAll(@NonNull List<HistoryState> states) {
for (HistoryState state : states) {
add(state);
}
}
public void remove(@NonNull HistoryState state) {
Check.isMainThread();
for (int i = 0; i < list.size(); i++) {
final HistoryState candidate = list.get(i);
if (candidate.same(state)) {
list.remove(i);
if (current >= i) {
current--;
}
break;
}
}
}
private boolean isCurrent(@NonNull HistoryState state) { private boolean isCurrent(@NonNull HistoryState state) {
final HistoryState current = getCurrent(); final HistoryState current = getCurrent();
if (current == null) { if (current == null) {
@ -86,4 +112,35 @@ public class HistoryList {
public List<HistoryState> asList() { public List<HistoryState> asList() {
return Collections.unmodifiableList(list); return Collections.unmodifiableList(list);
} }
@NonNull
public static JSONArray toJson(@NonNull List<HistoryState> states) {
final JSONArray array = new JSONArray();
for (int i = 0; i < states.size(); i++) {
final HistoryState state = states.get(i);
try {
array.put(i, state.toJson());
} catch (JSONException e) {
Log.e(CalculatorHistory.TAG, e.getMessage(), e);
}
}
return array;
}
@NonNull
public static List<HistoryState> fromJson(@NonNull JSONArray array) {
final List<HistoryState> states = new ArrayList<>(array.length());
for (int i = 0; i < array.length(); i++) {
final JSONObject json = array.optJSONObject(i);
if (json == null) {
continue;
}
try {
states.add(HistoryState.create(json));
} catch (JSONException e) {
Log.e(CalculatorHistory.TAG, e.getMessage(), e);
}
}
return states;
}
} }

View File

@ -1,6 +1,7 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import android.support.annotation.Nullable; import android.text.TextUtils;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.solovyev.android.Check; import org.solovyev.android.Check;
@ -11,17 +12,18 @@ import javax.annotation.Nonnull;
public class HistoryState { public class HistoryState {
@Nonnull
private static final String JSON_EDITOR = "e"; private static final String JSON_EDITOR = "e";
@Nonnull
private static final String JSON_DISPLAY = "d"; private static final String JSON_DISPLAY = "d";
private static final String JSON_TIME = "t";
private static final String JSON_COMMENT = "c";
@Nonnull @Nonnull
public final EditorState editor; public final EditorState editor;
@Nonnull @Nonnull
public final DisplayState display; public final DisplayState display;
protected long time; protected long time;
@Nullable @Nonnull
protected String comment; protected String comment = "";
private HistoryState(@Nonnull EditorState editor, @Nonnull DisplayState display) { private HistoryState(@Nonnull EditorState editor, @Nonnull DisplayState display) {
this.editor = editor; this.editor = editor;
@ -30,6 +32,8 @@ public class HistoryState {
private HistoryState(@Nonnull JSONObject json) throws JSONException { private HistoryState(@Nonnull JSONObject json) throws JSONException {
this(EditorState.create(json.getJSONObject(JSON_EDITOR)), DisplayState.create(json.getJSONObject(JSON_DISPLAY))); this(EditorState.create(json.getJSONObject(JSON_EDITOR)), DisplayState.create(json.getJSONObject(JSON_DISPLAY)));
this.time = json.optLong(JSON_TIME, 0L);
this.comment = json.optString(JSON_COMMENT, "");
} }
@Nonnull @Nonnull
@ -37,6 +41,23 @@ public class HistoryState {
return new Builder(editor, display); return new Builder(editor, display);
} }
@Nonnull
public static HistoryState create(@Nonnull JSONObject json) throws JSONException {
return new HistoryState(json);
}
@Nonnull
public JSONObject toJson() throws JSONException {
final JSONObject json = new JSONObject();
json.put(JSON_EDITOR, editor.toJson());
json.put(JSON_DISPLAY, display.toJson());
json.put(JSON_TIME, time);
if (!TextUtils.isEmpty(comment)) {
json.put(JSON_COMMENT, comment);
}
return json;
}
@Nonnull @Nonnull
public EditorState getEditor() { public EditorState getEditor() {
return editor; return editor;
@ -51,7 +72,7 @@ public class HistoryState {
return time; return time;
} }
@Nullable @Nonnull
public String getComment() { public String getComment() {
return comment; return comment;
} }
@ -74,7 +95,7 @@ public class HistoryState {
this.time = time; this.time = time;
} }
public void setComment(@Nullable String comment) { public void setComment(@Nonnull String comment) {
Check.isTrue(!built); Check.isTrue(!built);
this.comment = comment; this.comment = comment;
} }

View File

@ -45,12 +45,12 @@ public class SavedHistoryFragment extends BaseHistoryFragment {
@Nonnull @Nonnull
@Override @Override
protected List<HistoryState> getHistoryItems() { protected List<HistoryState> getHistoryItems() {
return new ArrayList<>(Locator.getInstance().getHistory().getSavedHistory()); return new ArrayList<>(Locator.getInstance().getHistory().getSaved());
} }
@Override @Override
protected void clearHistory() { protected void clearHistory() {
Locator.getInstance().getHistory().clearSavedHistory(); Locator.getInstance().getHistory().clearSaved();
getAdapter().clear(); getAdapter().clear();
} }
} }

View File

@ -40,19 +40,29 @@ import android.text.SpannedString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.Views; import org.solovyev.android.Views;
import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.CalculatorButton;
import org.solovyev.android.calculator.DisplayState;
import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.Preferences.SimpleTheme; import org.solovyev.android.calculator.Preferences.SimpleTheme;
import org.solovyev.android.calculator.R;
import java.util.EnumMap;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.EnumMap;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT; import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT;
import static android.content.Intent.ACTION_CONFIGURATION_CHANGED; import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static android.os.Build.VERSION_CODES.JELLY_BEAN; import static android.os.Build.VERSION_CODES.JELLY_BEAN;
import static org.solovyev.android.calculator.CalculatorBroadcaster.*; import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_DISPLAY_STATE_CHANGED;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_EDITOR_STATE_CHANGED;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_INIT;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_THEME_CHANGED;
import static org.solovyev.android.calculator.CalculatorReceiver.newButtonClickedIntent; import static org.solovyev.android.calculator.CalculatorReceiver.newButtonClickedIntent;
public class CalculatorWidget extends AppWidgetProvider { public class CalculatorWidget extends AppWidgetProvider {
@ -208,9 +218,9 @@ public class CalculatorWidget extends AppWidgetProvider {
} }
private void updateDisplayState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull DisplayState displayState, @Nonnull SimpleTheme theme) { private void updateDisplayState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull DisplayState displayState, @Nonnull SimpleTheme theme) {
final boolean error = !displayState.isValid(); final boolean error = !displayState.valid;
if (!error) { if (!error) {
views.setTextViewText(R.id.calculator_display, displayState.getText()); views.setTextViewText(R.id.calculator_display, displayState.text);
} }
views.setTextColor(R.id.calculator_display, ContextCompat.getColor(context, theme.getDisplayTextColor(error))); views.setTextColor(R.id.calculator_display, ContextCompat.getColor(context, theme.getDisplayTextColor(error)));
} }

View File

@ -1,7 +1,5 @@
package org.solovyev.android.io; package org.solovyev.android.io;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
@ -10,14 +8,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
abstract class BaseFileLoader { public abstract class BaseIoLoader {
@NonNull
protected final Context context;
public BaseFileLoader(@NonNull Context context) {
this.context = context;
}
@Nullable @Nullable
public CharSequence load() { public CharSequence load() {

View File

@ -8,12 +8,12 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
public abstract class BaseFileSaver implements Runnable { public abstract class BaseIoSaver implements Runnable {
@NonNull @NonNull
private final CharSequence data; private final CharSequence data;
protected BaseFileSaver(@NonNull CharSequence data) { protected BaseIoSaver(@NonNull CharSequence data) {
this.data = data; this.data = data;
} }

View File

@ -0,0 +1,31 @@
package org.solovyev.android.io;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FileLoader extends BaseIoLoader {
@NonNull
private final File file;
public FileLoader(@NonNull File file) {
this.file = file;
}
@Nullable
public static CharSequence load(@NonNull File file) {
final FileLoader loader = new FileLoader(file);
return loader.load();
}
@Nullable
@Override
protected InputStream getInputStream() throws IOException {
return new FileInputStream(file);
}
}

View File

@ -6,7 +6,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
public class FileSaver extends BaseFileSaver { public class FileSaver extends BaseIoSaver {
@NonNull @NonNull
private final File file; private final File file;

View File

@ -23,20 +23,28 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import jscl.JsclMathEngine;
import org.junit.Assert; import org.junit.Assert;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.plot.CalculatorPlotter; import org.solovyev.android.calculator.plot.CalculatorPlotter;
import javax.annotation.Nonnull; import java.io.ByteArrayInputStream;
import javax.annotation.Nullable; import java.io.ByteArrayOutputStream;
import java.io.*; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.JsclMathEngine;
/** /**
* User: serso * User: serso
* Date: 10/7/12 * Date: 10/7/12
@ -103,7 +111,7 @@ public class CalculatorTestUtils {
if (latch.await(TIMEOUT, TimeUnit.SECONDS)) { if (latch.await(TIMEOUT, TimeUnit.SECONDS)) {
Assert.assertNotNull(calculatorEventListener.getResult()); Assert.assertNotNull(calculatorEventListener.getResult());
Assert.assertEquals(expected, calculatorEventListener.getResult().getText()); Assert.assertEquals(expected, calculatorEventListener.getResult().text);
} else { } else {
Assert.fail("Too long wait for: " + expression); Assert.fail("Too long wait for: " + expression);
} }
@ -158,7 +166,7 @@ public class CalculatorTestUtils {
if (latch.await(TIMEOUT, TimeUnit.SECONDS)) { if (latch.await(TIMEOUT, TimeUnit.SECONDS)) {
Assert.assertNotNull(calculatorEventListener.getResult()); Assert.assertNotNull(calculatorEventListener.getResult());
Assert.assertFalse(calculatorEventListener.getResult().isValid()); Assert.assertFalse(calculatorEventListener.getResult().valid);
} else { } else {
Assert.fail("Too long wait for: " + expression); Assert.fail("Too long wait for: " + expression);
} }

View File

@ -29,9 +29,10 @@ import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.DisplayState; import org.solovyev.android.calculator.DisplayState;
import org.solovyev.android.calculator.EditorState; import org.solovyev.android.calculator.EditorState;
import javax.annotation.Nonnull;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 10.10.12 * Date: 10.10.12
@ -62,13 +63,13 @@ public class CalculatorHistoryTest {
addState(calculatorHistory, "2354"); addState(calculatorHistory, "2354");
addState(calculatorHistory, "23547"); addState(calculatorHistory, "23547");
final List<HistoryState> states = calculatorHistory.getCurrentHistory(); final List<HistoryState> states = calculatorHistory.getCurrent();
Assert.assertEquals(2, states.size()); Assert.assertEquals(2, states.size());
Assert.assertEquals("23547", states.get(1).getEditor().getTextString()); Assert.assertEquals("23547", states.get(1).editor.getTextString());
Assert.assertEquals("123+3", states.get(0).getEditor().getTextString()); Assert.assertEquals("123+3", states.get(0).editor.getTextString());
} }
private void addState(@Nonnull CalculatorHistory calculatorHistory, @Nonnull String text) { private void addState(@Nonnull CalculatorHistory calculatorHistory, @Nonnull String text) {
calculatorHistory.addCurrentState(HistoryState.newBuilder(EditorState.create(text, 3), DisplayState.empty())); calculatorHistory.addCurrent(HistoryState.newBuilder(EditorState.create(text, 3), DisplayState.empty()));
} }
} }