Memory
This commit is contained in:
@@ -31,6 +31,7 @@ import org.solovyev.android.Check;
|
||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
||||
import org.solovyev.android.calculator.ga.Ga;
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.android.calculator.memory.Memory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -48,6 +49,8 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
||||
@Inject
|
||||
Display display;
|
||||
@Inject
|
||||
Lazy<Memory> memory;
|
||||
@Inject
|
||||
Calculator calculator;
|
||||
@Inject
|
||||
Engine engine;
|
||||
@@ -148,6 +151,9 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
||||
case like:
|
||||
launcher.openFacebook();
|
||||
break;
|
||||
case memory:
|
||||
editor.insert(memory.get().getValue());
|
||||
break;
|
||||
case erase:
|
||||
editor.erase();
|
||||
break;
|
||||
|
@@ -0,0 +1,25 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import org.solovyev.android.Check;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Runnables implements Runnable {
|
||||
@NonNull
|
||||
private final List<Runnable> list = new ArrayList<>();
|
||||
@Override
|
||||
public void run() {
|
||||
Check.isMainThread();
|
||||
for (Runnable runnable : list) {
|
||||
runnable.run();
|
||||
}
|
||||
list.clear();
|
||||
}
|
||||
|
||||
public void add(@NonNull Runnable runnable) {
|
||||
Check.isMainThread();
|
||||
list.add(runnable);
|
||||
}
|
||||
}
|
@@ -24,11 +24,10 @@ package org.solovyev.android.calculator.buttons;
|
||||
|
||||
import org.solovyev.android.Check;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum CppSpecialButton {
|
||||
|
||||
@@ -38,6 +37,7 @@ public enum CppSpecialButton {
|
||||
settings("settings"),
|
||||
settings_widget("settings_widget"),
|
||||
like("like"),
|
||||
memory("memory"),
|
||||
erase("erase"),
|
||||
paste("paste"),
|
||||
copy("copy"),
|
||||
|
@@ -69,7 +69,7 @@ public class History {
|
||||
@Nonnull
|
||||
private final List<HistoryState> saved = new ArrayList<>();
|
||||
@Nonnull
|
||||
private final List<Runnable> whenLoadedRunnables = new ArrayList<>();
|
||||
private final Runnables whenLoadedRunnables = new Runnables();
|
||||
private boolean loaded;
|
||||
@Inject
|
||||
Application application;
|
||||
@@ -231,10 +231,7 @@ public class History {
|
||||
postRecentWrite();
|
||||
}
|
||||
loaded = true;
|
||||
for (Runnable runnable : whenLoadedRunnables) {
|
||||
runnable.run();
|
||||
}
|
||||
whenLoadedRunnables.clear();
|
||||
whenLoadedRunnables.run();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -388,7 +385,6 @@ public class History {
|
||||
|
||||
public void runWhenLoaded(@NonNull Runnable runnable) {
|
||||
Check.isTrue(!loaded);
|
||||
Check.isMainThread();
|
||||
whenLoadedRunnables.add(runnable);
|
||||
}
|
||||
|
||||
|
@@ -12,13 +12,15 @@ import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import dagger.Lazy;
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
import org.solovyev.android.calculator.ActivityLauncher;
|
||||
import org.solovyev.android.calculator.Engine;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
||||
import org.solovyev.android.calculator.history.History;
|
||||
import org.solovyev.android.calculator.memory.Memory;
|
||||
import org.solovyev.android.calculator.view.AngleUnitsButton;
|
||||
import org.solovyev.android.views.dragbutton.DirectionDragButton;
|
||||
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
||||
@@ -60,6 +62,10 @@ public class KeyboardUi extends BaseKeyboardUi {
|
||||
@Inject
|
||||
Engine engine;
|
||||
@Inject
|
||||
Display display;
|
||||
@Inject
|
||||
Lazy<Memory> memory;
|
||||
@Inject
|
||||
PartialKeyboardUi partialUi;
|
||||
@Bind(R.id.cpp_button_vars)
|
||||
DirectionDragButton variablesButton;
|
||||
@@ -89,6 +95,9 @@ public class KeyboardUi extends BaseKeyboardUi {
|
||||
@Nullable
|
||||
@Bind(R.id.cpp_button_like)
|
||||
ImageButton likeButton;
|
||||
@Nullable
|
||||
@Bind(R.id.cpp_button_memory)
|
||||
DirectionDragButton memoryButton;
|
||||
|
||||
@Inject
|
||||
public KeyboardUi(@Nonnull Application application) {
|
||||
@@ -138,6 +147,7 @@ public class KeyboardUi extends BaseKeyboardUi {
|
||||
prepareButton(copyButton);
|
||||
prepareButton(pasteButton);
|
||||
prepareButton(likeButton);
|
||||
prepareButton(memoryButton);
|
||||
|
||||
if (isSimpleLayout()) {
|
||||
hideText(button1, up, down);
|
||||
@@ -212,6 +222,9 @@ public class KeyboardUi extends BaseKeyboardUi {
|
||||
case R.id.cpp_button_like:
|
||||
onClick(v, CppSpecialButton.like);
|
||||
break;
|
||||
case R.id.cpp_button_memory:
|
||||
onClick(v, CppSpecialButton.memory);
|
||||
break;
|
||||
case R.id.cpp_button_operators:
|
||||
onClick(v, CppSpecialButton.operators);
|
||||
break;
|
||||
@@ -242,6 +255,8 @@ public class KeyboardUi extends BaseKeyboardUi {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case R.id.cpp_button_memory:
|
||||
return processMemoryButton(direction);
|
||||
case R.id.cpp_button_subtraction:
|
||||
if (direction == down) {
|
||||
launcher.showOperators();
|
||||
@@ -261,6 +276,36 @@ public class KeyboardUi extends BaseKeyboardUi {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processMemoryButton(@NonNull DragDirection direction) {
|
||||
final DisplayState state = display.getState();
|
||||
if (!state.valid) {
|
||||
return false;
|
||||
}
|
||||
Generic value = state.getResult();
|
||||
if (value == null) {
|
||||
try {
|
||||
value = Expression.valueOf(state.text);
|
||||
} catch (jscl.text.ParseException e) {
|
||||
Log.w(App.TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
switch (direction) {
|
||||
case up:
|
||||
memory.get().add(value);
|
||||
return true;
|
||||
case down:
|
||||
memory.get().subtract(value);
|
||||
return true;
|
||||
case left:
|
||||
memory.get().clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean processAngleUnitsButton(@Nonnull DragDirection direction, @Nonnull DirectionDragButton button) {
|
||||
if (direction == DragDirection.left) {
|
||||
return processDefault(direction, button);
|
||||
|
@@ -0,0 +1,201 @@
|
||||
package org.solovyev.android.calculator.memory;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.JsclInteger;
|
||||
import jscl.text.ParseException;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.AppModule;
|
||||
import org.solovyev.android.calculator.Notifier;
|
||||
import org.solovyev.android.calculator.Runnables;
|
||||
import org.solovyev.android.io.FileSystem;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@Singleton
|
||||
public class Memory {
|
||||
|
||||
@NonNull
|
||||
private static final Generic EMPTY = numeric(Expression.valueOf(JsclInteger.ZERO));
|
||||
@NonNull
|
||||
private final FileSystem fileSystem;
|
||||
@NonNull
|
||||
private final File filesDir;
|
||||
@NonNull
|
||||
private final WriteTask writeTask = new WriteTask();
|
||||
@NonNull
|
||||
private final Runnables whenLoadedRunnables = new Runnables();
|
||||
@Inject
|
||||
Notifier notifier;
|
||||
@Named(AppModule.THREAD_BACKGROUND)
|
||||
@Inject
|
||||
Executor backgroundThread;
|
||||
@Inject
|
||||
Handler handler;
|
||||
@NonNull
|
||||
private Generic value = EMPTY;
|
||||
private boolean loaded;
|
||||
|
||||
@Inject
|
||||
public Memory(@NonNull @Named(AppModule.THREAD_INIT) Executor initThread, @NonNull FileSystem fileSystem, @NonNull @Named(AppModule.DIR_FILES) File filesDir) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.filesDir = filesDir;
|
||||
initThread.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Generic numeric(@NonNull Generic generic) {
|
||||
try {
|
||||
return generic.numeric();
|
||||
} catch (RuntimeException e) {
|
||||
return generic;
|
||||
}
|
||||
}
|
||||
|
||||
private void initAsync() {
|
||||
Check.isNotMainThread();
|
||||
final Generic value = loadValue();
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onLoaded(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onLoaded(@NonNull Generic value) {
|
||||
this.value = value;
|
||||
this.loaded = true;
|
||||
this.whenLoadedRunnables.run();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Generic loadValue() {
|
||||
Check.isNotMainThread();
|
||||
try {
|
||||
final CharSequence value = fileSystem.read(getFile());
|
||||
return TextUtils.isEmpty(value) ? EMPTY : numeric(Expression.valueOf(value.toString()));
|
||||
} catch (IOException | ParseException e) {
|
||||
Log.e(App.TAG, e.getMessage(), e);
|
||||
}
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
public void add(@NonNull final Generic that) {
|
||||
Check.isMainThread();
|
||||
if (!loaded) {
|
||||
postAdd(that);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setValue(value.add(that));
|
||||
} catch (RuntimeException e) {
|
||||
notifier.showMessage(e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void postAdd(@NonNull final Generic that) {
|
||||
whenLoadedRunnables.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
add(that);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void subtract(@NonNull final Generic that) {
|
||||
Check.isMainThread();
|
||||
if (!loaded) {
|
||||
postSubtract(that);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setValue(value.subtract(that));
|
||||
} catch (RuntimeException e) {
|
||||
notifier.showMessage(e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void postSubtract(@NonNull final Generic that) {
|
||||
whenLoadedRunnables.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
subtract(that);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getValue() {
|
||||
try {
|
||||
return value.toString();
|
||||
} catch (RuntimeException e) {
|
||||
Log.w(App.TAG, e.getMessage(), e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void setValue(@NonNull Generic newValue) {
|
||||
Check.isTrue(loaded);
|
||||
value = numeric(newValue);
|
||||
handler.removeCallbacks(writeTask);
|
||||
handler.postDelayed(writeTask, 3000L);
|
||||
notifier.showMessage(getValue());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
Check.isMainThread();
|
||||
if (!loaded) {
|
||||
postClear();
|
||||
return;
|
||||
}
|
||||
setValue(EMPTY);
|
||||
}
|
||||
|
||||
private void postClear() {
|
||||
whenLoadedRunnables.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private File getFile() {
|
||||
return new File(filesDir, "memory.txt");
|
||||
}
|
||||
|
||||
private class WriteTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
Check.isMainThread();
|
||||
if (!loaded) {
|
||||
return;
|
||||
}
|
||||
final String value = getValue();
|
||||
backgroundThread.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSystem.writeSilently(getFile(), value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user