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