History tests
This commit is contained in:
parent
1e8be31ab5
commit
6734bfeaa4
@ -95,7 +95,6 @@ public final class App {
|
||||
private static volatile Application application;
|
||||
@Nonnull
|
||||
private static Executor uiThreadExecutor;
|
||||
private static volatile boolean initialized;
|
||||
@Nonnull
|
||||
private static SharedPreferences preferences;
|
||||
@Nonnull
|
||||
@ -132,9 +131,6 @@ public final class App {
|
||||
|
||||
public static void init(@Nonnull CalculatorApplication application,
|
||||
@Nonnull Languages languages) {
|
||||
if (initialized) {
|
||||
throw new IllegalStateException("Already initialized!");
|
||||
}
|
||||
App.application = application;
|
||||
App.preferences = PreferenceManager.getDefaultSharedPreferences(application);
|
||||
App.uiThreadExecutor = application.uiThread;
|
||||
@ -163,14 +159,6 @@ public final class App {
|
||||
App.editor = application.editor;
|
||||
App.display = application.display;
|
||||
App.bus = application.bus;
|
||||
|
||||
App.initialized = true;
|
||||
}
|
||||
|
||||
private static void checkInit() {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException("App should be initialized!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,11 +1,11 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import dagger.Component;
|
||||
import org.solovyev.android.calculator.history.BaseHistoryFragment;
|
||||
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = AppModule.class)
|
||||
public interface AppComponent {
|
||||
@ -13,4 +13,5 @@ public interface AppComponent {
|
||||
void inject(CalculatorEditorFragment fragment);
|
||||
void inject(BaseUi ui);
|
||||
void inject(CalculatorOnscreenService service);
|
||||
void inject(BaseHistoryFragment fragment);
|
||||
}
|
||||
|
@ -6,21 +6,17 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.solovyev.android.UiThreadExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
@Module
|
||||
public class AppModule {
|
||||
@ -43,6 +39,12 @@ public class AppModule {
|
||||
return new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Application provideApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Bus provideBus(Handler handler) {
|
||||
|
@ -80,19 +80,6 @@ public enum CalculatorEventType {
|
||||
|
||||
engine_preferences_changed,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* HISTORY
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
// @Nonnull CalculatorHistoryState
|
||||
history_state_added,
|
||||
|
||||
clear_history_requested,
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
|
@ -30,43 +30,24 @@ import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.text.ClipboardManager;
|
||||
import android.view.ContextMenu;
|
||||
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 android.view.*;
|
||||
import android.widget.*;
|
||||
import com.melnykov.fab.FloatingActionButton;
|
||||
|
||||
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 com.squareup.otto.Bus;
|
||||
import com.squareup.otto.Subscribe;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static android.view.Menu.NONE;
|
||||
import static org.solovyev.android.calculator.CalculatorEventType.clear_history_requested;
|
||||
|
||||
public abstract class BaseHistoryFragment extends ListFragment implements CalculatorEventListener {
|
||||
public abstract class BaseHistoryFragment extends ListFragment {
|
||||
|
||||
@Nonnull
|
||||
private final DialogInterface.OnClickListener clearDialogListener = new DialogInterface.OnClickListener() {
|
||||
@ -79,14 +60,16 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
||||
}
|
||||
}
|
||||
};
|
||||
@Inject
|
||||
History history;
|
||||
@Inject
|
||||
Bus bus;
|
||||
@Nonnull
|
||||
private HistoryArrayAdapter adapter;
|
||||
@Nonnull
|
||||
private FragmentUi ui;
|
||||
@Nullable
|
||||
private AlertDialog clearDialog;
|
||||
@Inject
|
||||
History history;
|
||||
|
||||
protected BaseHistoryFragment(@Nonnull CalculatorFragmentType fragmentType) {
|
||||
ui = new FragmentUi(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId(), false);
|
||||
@ -114,6 +97,8 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
((CalculatorApplication) getActivity().getApplication()).getComponent().inject(this);
|
||||
bus.register(this);
|
||||
ui.onCreate(this);
|
||||
}
|
||||
|
||||
@ -139,7 +124,12 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(clear_history_requested, null);
|
||||
clearDialog = new AlertDialog.Builder(getActivity()).setTitle(R.string.cpp_clear_history_title)
|
||||
.setMessage(R.string.cpp_clear_history_message)
|
||||
.setPositiveButton(R.string.cpp_clear_history, clearDialogListener)
|
||||
.setNegativeButton(R.string.c_cancel, clearDialogListener)
|
||||
.create();
|
||||
clearDialog.show();
|
||||
}
|
||||
});
|
||||
|
||||
@ -159,7 +149,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.ui.onResume(this);
|
||||
ui.onResume(this);
|
||||
|
||||
updateAdapter();
|
||||
}
|
||||
@ -285,6 +275,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
bus.unregister(this);
|
||||
if (clearDialog != null) {
|
||||
clearDialog.dismiss();
|
||||
clearDialog = null;
|
||||
@ -323,31 +314,13 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case history_state_added:
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateAdapter();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case clear_history_requested:
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearDialog = new AlertDialog.Builder(getActivity()).setTitle(R.string.cpp_clear_history_title)
|
||||
.setMessage(R.string.cpp_clear_history_message)
|
||||
.setPositiveButton(R.string.cpp_clear_history, clearDialogListener)
|
||||
.setNegativeButton(R.string.c_cancel, clearDialogListener)
|
||||
.create();
|
||||
clearDialog.show();
|
||||
}
|
||||
});
|
||||
break;
|
||||
@Subscribe
|
||||
void onHistoryChanged(@Nonnull History.ChangedEvent e) {
|
||||
if (e.recent != isRecentHistory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
protected abstract boolean isRecentHistory();
|
||||
}
|
||||
|
@ -22,30 +22,24 @@
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.AppModule;
|
||||
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.calculator.model.AndroidCalculatorEngine;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.io.FileLoader;
|
||||
import org.solovyev.android.io.FileSaver;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -53,16 +47,13 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import static java.lang.Character.isDigit;
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public class History {
|
||||
|
||||
public static final String TAG = App.subTag("History");
|
||||
private static final ChangedEvent CHANGED_EVENT_RECENT = new ChangedEvent(true);
|
||||
private static final ChangedEvent CHANGED_EVENT_SAVED = new ChangedEvent(false);
|
||||
@NonNull
|
||||
private final Runnable writeRecent = new WriteTask(true);
|
||||
@NonNull
|
||||
@ -71,17 +62,22 @@ public class History {
|
||||
private final RecentHistory recent = new RecentHistory();
|
||||
@Nonnull
|
||||
private final List<HistoryState> saved = new ArrayList<>();
|
||||
@Nonnull
|
||||
private final Bus bus;
|
||||
@Inject
|
||||
Handler handler;
|
||||
@Inject
|
||||
SharedPreferences preferences;
|
||||
@Nullable
|
||||
private EditorState lastEditorState;
|
||||
@Inject
|
||||
Editor editor;
|
||||
@Inject
|
||||
Application application;
|
||||
private boolean initialized;
|
||||
|
||||
@Inject
|
||||
public History(Bus bus, @Named(AppModule.THREAD_INIT) Executor initThread) {
|
||||
bus.register(this);
|
||||
public History(@NonNull Bus bus, @Nonnull @Named(AppModule.THREAD_INIT) Executor initThread) {
|
||||
this.bus = bus;
|
||||
this.bus.register(this);
|
||||
initThread.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -90,23 +86,6 @@ public class History {
|
||||
});
|
||||
}
|
||||
|
||||
private void migrateOldHistory() {
|
||||
try {
|
||||
final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null);
|
||||
if (TextUtils.isEmpty(xml)) {
|
||||
return;
|
||||
}
|
||||
final List<HistoryState> states = convertOldHistory(xml);
|
||||
if (states == null) {
|
||||
return;
|
||||
}
|
||||
final JSONArray json = RecentHistory.toJson(states);
|
||||
FileSaver.save(getSavedHistoryFile(), json.toString());
|
||||
} catch (Exception e) {
|
||||
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static List<HistoryState> convertOldHistory(@NonNull String xml) {
|
||||
final OldHistory history = OldHistory.fromXml(xml);
|
||||
@ -129,13 +108,13 @@ public class History {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static File getSavedHistoryFile() {
|
||||
return new File(App.getApplication().getFilesDir(), "history-saved.json");
|
||||
private File getSavedHistoryFile() {
|
||||
return new File(application.getFilesDir(), "history-saved.json");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static File getRecentHistoryFile() {
|
||||
return new File(App.getApplication().getFilesDir(), "history-recent.json");
|
||||
private File getRecentHistoryFile() {
|
||||
return new File(application.getFilesDir(), "history-recent.json");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -144,7 +123,7 @@ public class History {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final CharSequence json = FileLoader.load(file);
|
||||
if (TextUtils.isEmpty(json)) {
|
||||
if (isEmpty(json)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
@ -155,6 +134,44 @@ public class History {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static boolean isIntermediate(@Nonnull String olderText,
|
||||
@Nonnull String newerText) {
|
||||
if (isEmpty(olderText)) {
|
||||
return true;
|
||||
}
|
||||
if (isEmpty(newerText)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int diff = newerText.length() - olderText.length();
|
||||
if (diff >= 1) {
|
||||
return newerText.startsWith(olderText);
|
||||
} else if (diff <= 1) {
|
||||
return olderText.startsWith(newerText);
|
||||
} else if (diff == 0) {
|
||||
return olderText.equals(newerText);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void migrateOldHistory() {
|
||||
try {
|
||||
final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null);
|
||||
if (isEmpty(xml)) {
|
||||
return;
|
||||
}
|
||||
final List<HistoryState> states = convertOldHistory(xml);
|
||||
if (states == null) {
|
||||
return;
|
||||
}
|
||||
final JSONArray json = RecentHistory.toJson(states);
|
||||
FileSaver.save(getSavedHistoryFile(), json.toString());
|
||||
} catch (Exception e) {
|
||||
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
Check.isNotMainThread();
|
||||
migrateOldHistory();
|
||||
@ -175,7 +192,6 @@ public class History {
|
||||
public void addRecent(@Nonnull HistoryState state) {
|
||||
Check.isMainThread();
|
||||
recent.add(state);
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.history_state_added, state);
|
||||
onRecentChanged();
|
||||
}
|
||||
|
||||
@ -188,11 +204,13 @@ public class History {
|
||||
private void onRecentChanged() {
|
||||
handler.removeCallbacks(writeRecent);
|
||||
handler.postDelayed(writeRecent, 500);
|
||||
bus.post(CHANGED_EVENT_RECENT);
|
||||
}
|
||||
|
||||
private void onSavedChanged() {
|
||||
handler.removeCallbacks(writeSaved);
|
||||
handler.postDelayed(writeSaved, 500);
|
||||
bus.post(CHANGED_EVENT_SAVED);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -201,8 +219,6 @@ public class History {
|
||||
|
||||
final List<HistoryState> result = new LinkedList<>();
|
||||
|
||||
final String groupingSeparator = AndroidCalculatorEngine.Preferences.groupingSeparator.getPreference(App.getPreferences());
|
||||
|
||||
final List<HistoryState> states = recent.asList();
|
||||
final int statesCount = states.size();
|
||||
for (int i = 1; i < statesCount; i++) {
|
||||
@ -210,13 +226,14 @@ public class History {
|
||||
final HistoryState newerState = states.get(i);
|
||||
final String olderText = olderState.editor.getTextString();
|
||||
final String newerText = newerState.editor.getTextString();
|
||||
if (!isIntermediate(olderText, newerText, groupingSeparator)) {
|
||||
if (!isIntermediate(olderText, newerText)) {
|
||||
result.add(0, olderState);
|
||||
}
|
||||
}
|
||||
if (statesCount > 0) {
|
||||
// try add last state if not empty
|
||||
final HistoryState state = states.get(statesCount - 1);
|
||||
if (!TextUtils.isEmpty(state.editor.getTextString())) {
|
||||
if (!isEmpty(state.editor.getTextString())) {
|
||||
result.add(0, state);
|
||||
}
|
||||
}
|
||||
@ -229,53 +246,6 @@ public class History {
|
||||
return new ArrayList<>(saved);
|
||||
}
|
||||
|
||||
private static boolean isIntermediate(@Nonnull String olderText,
|
||||
@Nonnull String newerText,
|
||||
@NonNull String groupingSeparator) {
|
||||
if (TextUtils.isEmpty(olderText)) {
|
||||
return true;
|
||||
}
|
||||
if (TextUtils.isEmpty(newerText)) {
|
||||
return false;
|
||||
}
|
||||
olderText = trimGroupingSeparators(olderText, groupingSeparator);
|
||||
newerText = trimGroupingSeparators(newerText, groupingSeparator);
|
||||
|
||||
final int diff = newerText.length() - olderText.length();
|
||||
if (diff >= 1) {
|
||||
return newerText.startsWith(olderText);
|
||||
} else if (diff <= 1) {
|
||||
return olderText.startsWith(newerText);
|
||||
} else if (diff == 0) {
|
||||
return olderText.equals(newerText);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String trimGroupingSeparators(@NonNull String text, @NonNull String groupingSeparator) {
|
||||
if (TextUtils.isEmpty(groupingSeparator)) {
|
||||
return text;
|
||||
}
|
||||
Check.isTrue(groupingSeparator.length() == 1);
|
||||
final StringBuilder sb = new StringBuilder(text.length());
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
if (i == 0 || i == text.length() - 1) {
|
||||
// grouping separator can't be the first and the last character
|
||||
sb.append(text.charAt(i));
|
||||
continue;
|
||||
}
|
||||
if (isDigit(text.charAt(i - 1)) && text.charAt(i) == groupingSeparator.charAt(0) && isDigit(text.charAt(i + 1))) {
|
||||
// grouping separator => skip
|
||||
continue;
|
||||
}
|
||||
sb.append(text.charAt(i));
|
||||
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void clearRecent() {
|
||||
Check.isMainThread();
|
||||
recent.clear();
|
||||
@ -321,27 +291,25 @@ public class History {
|
||||
onRecentChanged();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
lastEditorState = e.newState;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onDisplayChanged(@Nonnull Display.ChangedEvent e) {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
if (lastEditorState == null) {
|
||||
final EditorState editorState = editor.getState();
|
||||
final DisplayState displayState = e.newState;
|
||||
if (editorState.sequence != displayState.sequence) {
|
||||
return;
|
||||
}
|
||||
if (lastEditorState.sequence != e.newState.sequence) {
|
||||
return;
|
||||
addRecent(HistoryState.newBuilder(editorState, displayState).build());
|
||||
}
|
||||
|
||||
public static class ChangedEvent {
|
||||
public final boolean recent;
|
||||
|
||||
public ChangedEvent(boolean recent) {
|
||||
this.recent = recent;
|
||||
}
|
||||
addRecent(HistoryState.newBuilder(lastEditorState, e.newState).build());
|
||||
lastEditorState = null;
|
||||
}
|
||||
|
||||
private class WriteTask implements Runnable {
|
||||
|
@ -25,9 +25,8 @@ package org.solovyev.android.calculator.history;
|
||||
import org.solovyev.android.calculator.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class RecentHistoryFragment extends BaseHistoryFragment {
|
||||
|
||||
@ -51,4 +50,9 @@ public class RecentHistoryFragment extends BaseHistoryFragment {
|
||||
history.clearRecent();
|
||||
getAdapter().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRecentHistory() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,8 @@ package org.solovyev.android.calculator.history;
|
||||
import org.solovyev.android.calculator.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class SavedHistoryFragment extends BaseHistoryFragment {
|
||||
|
||||
@ -51,4 +50,9 @@ public class SavedHistoryFragment extends BaseHistoryFragment {
|
||||
history.clearSaved();
|
||||
getAdapter().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRecentHistory() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.solovyev.android;
|
||||
|
||||
import android.os.Build;
|
||||
import org.junit.runners.model.InitializationError;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
@ -7,7 +8,7 @@ import org.robolectric.manifest.AndroidManifest;
|
||||
import org.robolectric.res.Fs;
|
||||
|
||||
public class CalculatorTestRunner extends RobolectricGradleTestRunner {
|
||||
private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC = 18;
|
||||
public static final int SUPPORTED_SDK = Build.VERSION_CODES.LOLLIPOP;
|
||||
|
||||
public CalculatorTestRunner(Class<?> testClass) throws InitializationError {
|
||||
super(testClass);
|
||||
@ -21,7 +22,7 @@ public class CalculatorTestRunner extends RobolectricGradleTestRunner {
|
||||
return new AndroidManifest(Fs.fileFromPath(manifestFilePath), Fs.fileFromPath(resourcesFilePath), Fs.fileFromPath(assetsFilePath)) {
|
||||
@Override
|
||||
public int getTargetSdkVersion() {
|
||||
return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC;
|
||||
return SUPPORTED_SDK;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -22,9 +22,12 @@
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import org.mockito.Mockito;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
@ -33,7 +36,7 @@ import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||
public class AbstractCalculatorTest {
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
Locator.getInstance().init(new CalculatorImpl(null, eventExecutor), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
|
||||
Locator.getInstance().init(new CalculatorImpl(Mockito.mock(Bus.class), Mockito.mock(Executor.class)), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
|
||||
Locator.getInstance().getEngine().init();
|
||||
}
|
||||
|
||||
|
@ -23,32 +23,25 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import jscl.JsclMathEngine;
|
||||
import org.junit.Assert;
|
||||
import org.mockito.Mockito;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.fakes.RoboSharedPreferences;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.android.calculator.language.Languages;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.*;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.JsclMathEngine;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
@ -60,8 +53,8 @@ public class CalculatorTestUtils {
|
||||
public static final int TIMEOUT = 3;
|
||||
|
||||
public static void staticSetUp() throws Exception {
|
||||
App.init(RuntimeEnvironment.application, new Languages(new RoboSharedPreferences(new HashMap<String, Map<String, Object>>(), "test", 0)));
|
||||
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
|
||||
App.init(new CalculatorApplication(), new Languages(new RoboSharedPreferences(new HashMap<String, Map<String, Object>>(), "test", 0)));
|
||||
Locator.getInstance().init(new CalculatorImpl(Mockito.mock(Bus.class), Mockito.mock(Executor.class)), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
|
||||
Locator.getInstance().getEngine().init();
|
||||
|
||||
final DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols();
|
||||
@ -71,7 +64,7 @@ public class CalculatorTestUtils {
|
||||
}
|
||||
|
||||
public static void staticSetUp(@Nullable Context context) throws Exception {
|
||||
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
|
||||
Locator.getInstance().init(new CalculatorImpl(Mockito.mock(Bus.class), Mockito.mock(Executor.class)), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
|
||||
Locator.getInstance().getEngine().init();
|
||||
|
||||
if (context != null) {
|
||||
|
@ -22,9 +22,11 @@
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.preference.PreferenceManager;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -41,7 +43,7 @@ public class EditorTest extends AbstractCalculatorTest {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.editor = new Editor(null);
|
||||
this.editor = new Editor(PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -22,61 +22,172 @@
|
||||
|
||||
package org.solovyev.android.calculator.history;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import com.squareup.otto.Bus;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.solovyev.android.CalculatorTestRunner;
|
||||
import org.solovyev.android.calculator.CalculatorTestUtils;
|
||||
import org.solovyev.android.calculator.BuildConfig;
|
||||
import org.solovyev.android.calculator.DisplayState;
|
||||
import org.solovyev.android.calculator.Editor;
|
||||
import org.solovyev.android.calculator.EditorState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@RunWith(CalculatorTestRunner.class)
|
||||
@Config(constants = BuildConfig.class, sdk = CalculatorTestRunner.SUPPORTED_SDK)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
public class HistoryTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
CalculatorTestUtils.staticSetUp();
|
||||
private History history;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
history = new History(Mockito.mock(Bus.class), Mockito.mock(Executor.class));
|
||||
history.handler = Mockito.mock(Handler.class);
|
||||
history.preferences = Mockito.mock(SharedPreferences.class);
|
||||
history.editor = Mockito.mock(Editor.class);
|
||||
history.application = RuntimeEnvironment.application;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStates() throws Exception {
|
||||
History history = new History(Mockito.any(Bus.class), new Executor() {
|
||||
@Override
|
||||
public void execute(@Nonnull Runnable command) {
|
||||
command.run();
|
||||
}
|
||||
});
|
||||
|
||||
addState(history, "1");
|
||||
addState(history, "12");
|
||||
addState(history, "123");
|
||||
addState(history, "123+");
|
||||
addState(history, "123+3");
|
||||
addState(history, "");
|
||||
addState(history, "2");
|
||||
addState(history, "23");
|
||||
addState(history, "235");
|
||||
addState(history, "2355");
|
||||
addState(history, "235");
|
||||
addState(history, "2354");
|
||||
addState(history, "23547");
|
||||
addState("1");
|
||||
addState("12");
|
||||
addState("123");
|
||||
addState("123+");
|
||||
addState("123+3");
|
||||
addState("");
|
||||
addState("2");
|
||||
addState("23");
|
||||
addState("235");
|
||||
addState("2355");
|
||||
addState("235");
|
||||
addState("2354");
|
||||
addState("23547");
|
||||
|
||||
final List<HistoryState> states = history.getRecent();
|
||||
Assert.assertEquals(2, states.size());
|
||||
Assert.assertEquals("23547", states.get(1).editor.getTextString());
|
||||
Assert.assertEquals("123+3", states.get(0).editor.getTextString());
|
||||
assertEquals(2, states.size());
|
||||
assertEquals("23547", states.get(0).editor.getTextString());
|
||||
assertEquals("123+3", states.get(1).editor.getTextString());
|
||||
}
|
||||
|
||||
private void addState(@Nonnull History history, @Nonnull String text) {
|
||||
@Test
|
||||
public void testRecentHistoryShouldNotContainEmptyStates() throws Exception {
|
||||
addState("");
|
||||
addState("1");
|
||||
addState("12");
|
||||
addState("");
|
||||
addState("");
|
||||
addState("34");
|
||||
addState("");
|
||||
|
||||
final List<HistoryState> states = history.getRecent();
|
||||
assertEquals(2, states.size());
|
||||
assertEquals("34", states.get(0).editor.getTextString());
|
||||
assertEquals("12", states.get(1).editor.getTextString());
|
||||
}
|
||||
|
||||
private void addState(@Nonnull String text) {
|
||||
history.addRecent(HistoryState.newBuilder(EditorState.create(text, 3), DisplayState.empty()));
|
||||
}
|
||||
|
||||
private static final String oldXml1 = "<history>\n" +
|
||||
" <historyItems class=\"java.util.ArrayList\">\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>3</cursorPosition>\n" +
|
||||
" <text>1+1</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>Error</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>simplify</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" </historyItems>\n" +
|
||||
"</history>";
|
||||
private static final String oldXml2 = "<history>\n" +
|
||||
" <historyItems class=\"java.util.ArrayList\">\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>3</cursorPosition>\n" +
|
||||
" <text>1+1</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>Error</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>simplify</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>2</cursorPosition>\n" +
|
||||
" <text>5/6</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>3</cursorPosition>\n" +
|
||||
" <text>5/6</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>numeric</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>1</cursorPosition>\n" +
|
||||
" <text></text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>Error</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>elementary</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>4+5/35sin(41)+dfdsfsdfs</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>1</cursorPosition>\n" +
|
||||
" <text>4+5/35sin(41)+dfdsfsdfs</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>numeric</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" </historyItems>\n" +
|
||||
"</history>";
|
||||
|
||||
@Test
|
||||
public void testShouldConvertOldHistory() throws Exception {
|
||||
List<HistoryState> states = History.convertOldHistory(oldXml1);
|
||||
assertNotNull(states);
|
||||
assertEquals(1, states.size());
|
||||
|
||||
HistoryState state = states.get(0);
|
||||
assertEquals(100000000, state.time);
|
||||
}
|
||||
}
|
||||
|
@ -34,85 +34,6 @@ public class HistoryUtilsTest {
|
||||
private static final String emptyHistory = "<history>\n" +
|
||||
" <historyItems class=\"java.util.ArrayList\"/>\n" +
|
||||
"</history>";
|
||||
private static final String toXml1 = "<history>\n" +
|
||||
" <historyItems class=\"java.util.ArrayList\">\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>3</cursorPosition>\n" +
|
||||
" <text>1+1</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>Error</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>simplify</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" </historyItems>\n" +
|
||||
"</history>";
|
||||
private static final String toXml2 = "<history>\n" +
|
||||
" <historyItems class=\"java.util.ArrayList\">\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>3</cursorPosition>\n" +
|
||||
" <text>1+1</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>Error</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>simplify</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>2</cursorPosition>\n" +
|
||||
" <text>5/6</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>3</cursorPosition>\n" +
|
||||
" <text>5/6</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>numeric</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>1</cursorPosition>\n" +
|
||||
" <text></text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>Error</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>elementary</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" <calculatorHistoryState>\n" +
|
||||
" <time>100000000</time>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>0</cursorPosition>\n" +
|
||||
" <text>4+5/35sin(41)+dfdsfsdfs</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <displayState>\n" +
|
||||
" <editorState>\n" +
|
||||
" <cursorPosition>1</cursorPosition>\n" +
|
||||
" <text>4+5/35sin(41)+dfdsfsdfs</text>\n" +
|
||||
" </editorState>\n" +
|
||||
" <jsclOperation>numeric</jsclOperation>\n" +
|
||||
" </displayState>\n" +
|
||||
" </calculatorHistoryState>\n" +
|
||||
" </historyItems>\n" +
|
||||
"</history>";
|
||||
|
||||
@Test
|
||||
public void testFromXml() throws Exception {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user