Memory
This commit is contained in:
parent
3dabe37576
commit
84be914bd5
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
31
app/src/main/res/layout/cpp_app_button_memory.xml
Normal file
31
app/src/main/res/layout/cpp_app_button_memory.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright 2013 serso aka se.solovyev
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
~
|
||||
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~ Contact details
|
||||
~
|
||||
~ Email: se.solovyev@gmail.com
|
||||
~ Site: http://se.solovyev.org
|
||||
-->
|
||||
<org.solovyev.android.views.dragbutton.DirectionDragButton a:id="@id/cpp_button_memory"
|
||||
style="?attr/cpp_button_style_control"
|
||||
xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
a:text="@string/cpp_kb_memory_recall"
|
||||
app:directionTextDown="@string/cpp_kb_memory_minus"
|
||||
app:directionTextLeft="@string/cpp_kb_memory_clear"
|
||||
app:directionTextUp="@string/cpp_kb_memory_plus" />
|
@ -39,6 +39,7 @@
|
||||
<item name="cpp_button_settings_widget" type="id" />
|
||||
<item name="cpp_button_settings_onscreen" type="id" />
|
||||
<item name="cpp_button_like" type="id" />
|
||||
<item name="cpp_button_memory" type="id" />
|
||||
<item name="cpp_button_left" type="id" />
|
||||
<item name="cpp_button_right" type="id" />
|
||||
<item name="cpp_button_vars" type="id" />
|
||||
|
@ -5,6 +5,10 @@
|
||||
<string name="cpp_kb_operators" translatable="false">∂</string>
|
||||
<string name="cpp_kb_undo" translatable="false">↶</string>
|
||||
<string name="cpp_kb_redo" translatable="false">↷</string>
|
||||
<string name="cpp_kb_memory_recall" translatable="false">M</string>
|
||||
<string name="cpp_kb_memory_plus" translatable="false">M+</string>
|
||||
<string name="cpp_kb_memory_minus" translatable="false">M-</string>
|
||||
<string name="cpp_kb_memory_clear" translatable="false">MC</string>
|
||||
<string name="cpp_plot_add_function" translatable="false">+</string>
|
||||
<string name="cpp_plot_zoom_in" translatable="false">+</string>
|
||||
<string name="cpp_plot_zoom_reset" translatable="false">0</string>
|
||||
|
@ -128,12 +128,11 @@ public class Expression extends Generic {
|
||||
return new Expression().init(generic);
|
||||
}
|
||||
|
||||
public static Expression init(@Nonnull NumericWrapper numericWrapper) {
|
||||
final Expression expression = new Expression(1);
|
||||
Literal literal = new Literal();
|
||||
public Expression init(@Nonnull NumericWrapper numericWrapper) {
|
||||
final Literal literal = new Literal();
|
||||
literal.init(new ExpressionVariable(numericWrapper), 1);
|
||||
expression.init(literal, JsclInteger.ONE);
|
||||
return expression;
|
||||
init(literal, JsclInteger.ONE);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void separateSign(MathML element, Generic generic) {
|
||||
@ -561,21 +560,13 @@ public class Expression extends Generic {
|
||||
try {
|
||||
return integerValue().numeric();
|
||||
} catch (NotIntegerException ex) {
|
||||
final Literal literal = literalScm();
|
||||
|
||||
final Map<Variable, Generic> content = literal.content(NUMERIC_CONVERTER);
|
||||
|
||||
return substitute(content);
|
||||
return substitute(literalScm().content(NUMERIC_CONVERTER));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Generic valueOf(@Nonnull Generic generic) {
|
||||
final Expression result = newInstance(0);
|
||||
|
||||
result.init(generic);
|
||||
|
||||
return result;
|
||||
return newInstance(0).init(generic);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
Loading…
Reference in New Issue
Block a user