Plotter
This commit is contained in:
		| @@ -28,7 +28,11 @@ import android.content.Context; | |||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.net.Uri; | import android.net.Uri; | ||||||
| import android.support.annotation.NonNull; | import android.support.annotation.NonNull; | ||||||
|  | import android.text.TextUtils; | ||||||
|  | import dagger.Lazy; | ||||||
|  | import jscl.math.Generic; | ||||||
|  | import jscl.math.function.Constant; | ||||||
|  | import jscl.math.function.CustomFunction; | ||||||
| import org.solovyev.android.Activities; | import org.solovyev.android.Activities; | ||||||
| import org.solovyev.android.Check; | import org.solovyev.android.Check; | ||||||
| import org.solovyev.android.calculator.about.AboutActivity; | import org.solovyev.android.calculator.about.AboutActivity; | ||||||
| @@ -38,31 +42,40 @@ import org.solovyev.android.calculator.functions.FunctionsActivity; | |||||||
| import org.solovyev.android.calculator.history.HistoryActivity; | import org.solovyev.android.calculator.history.HistoryActivity; | ||||||
| import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity; | import org.solovyev.android.calculator.matrix.CalculatorMatrixActivity; | ||||||
| import org.solovyev.android.calculator.operators.OperatorsActivity; | import org.solovyev.android.calculator.operators.OperatorsActivity; | ||||||
| import org.solovyev.android.calculator.plot.CalculatorPlotter; | import org.solovyev.android.calculator.plot.ExpressionFunction; | ||||||
| import org.solovyev.android.calculator.plot.PlotActivity; | import org.solovyev.android.calculator.plot.PlotActivity; | ||||||
| import org.solovyev.android.calculator.preferences.PreferencesActivity; | import org.solovyev.android.calculator.preferences.PreferencesActivity; | ||||||
| import org.solovyev.android.calculator.variables.CppVariable; | import org.solovyev.android.calculator.variables.CppVariable; | ||||||
| import org.solovyev.android.calculator.variables.EditVariableFragment; | import org.solovyev.android.calculator.variables.EditVariableFragment; | ||||||
| import org.solovyev.android.calculator.variables.VariablesActivity; | import org.solovyev.android.calculator.variables.VariablesActivity; | ||||||
| import org.solovyev.android.calculator.variables.VariablesFragment; | import org.solovyev.android.calculator.variables.VariablesFragment; | ||||||
|  | import org.solovyev.android.plotter.Plotter; | ||||||
| import org.solovyev.common.msg.MessageType; | import org.solovyev.common.msg.MessageType; | ||||||
| import org.solovyev.common.text.Strings; | import org.solovyev.common.text.Strings; | ||||||
|  |  | ||||||
| import jscl.math.Generic; |  | ||||||
| import jscl.math.function.Constant; |  | ||||||
|  |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| 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 javax.inject.Singleton; | import javax.inject.Singleton; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
| @Singleton | @Singleton | ||||||
| public final class ActivityLauncher implements CalculatorEventListener { | public final class ActivityLauncher implements CalculatorEventListener { | ||||||
|  |  | ||||||
|     @Inject |     @Inject | ||||||
|     Application application; |     Application application; | ||||||
|  |     @Inject | ||||||
|  |     Lazy<Plotter> plotter; | ||||||
|  |     @Inject | ||||||
|  |     Lazy<ErrorReporter> errorReporter; | ||||||
|  |     @Inject | ||||||
|  |     Lazy<Display> display; | ||||||
|  |     @Inject | ||||||
|  |     Lazy<VariablesRegistry> variablesRegistry; | ||||||
|  |     @Inject | ||||||
|  |     Notifier notifier; | ||||||
|     @Nullable |     @Nullable | ||||||
|     private CalculatorActivity activity; |     private CalculatorActivity activity; | ||||||
|  |  | ||||||
| @@ -109,7 +122,7 @@ public final class ActivityLauncher implements CalculatorEventListener { | |||||||
|                 final CppFunction.Builder builder = CppFunction.builder("", functionBody); |                 final CppFunction.Builder builder = CppFunction.builder("", functionBody); | ||||||
|                 final Generic generic = viewState.getResult(); |                 final Generic generic = viewState.getResult(); | ||||||
|                 if (generic != null) { |                 if (generic != null) { | ||||||
|                     final Set<Constant> constants = CalculatorUtils.getNotSystemConstants(generic); |                     final Set<Constant> constants = generic.getUndefinedConstants(null); | ||||||
|                     for (Constant constant : constants) { |                     for (Constant constant : constants) { | ||||||
|                         builder.withParameter(constant.getName()); |                         builder.withParameter(constant.getName()); | ||||||
|                     } |                     } | ||||||
| @@ -128,26 +141,13 @@ public final class ActivityLauncher implements CalculatorEventListener { | |||||||
|         return ((CalculatorApplication) App.getApplication()).notifier; |         return ((CalculatorApplication) App.getApplication()).notifier; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static void tryPlot() { |     public void plotDisplayedExpression() { | ||||||
|         final CalculatorPlotter plotter = Locator.getInstance().getPlotter(); |         final DisplayState state = display.get().getState(); | ||||||
|         final Display display = App.getDisplay(); |         if (!state.valid) { | ||||||
|         final DisplayState viewState = display.getState(); |  | ||||||
|  |  | ||||||
|         if (viewState.valid) { |  | ||||||
|             final String functionValue = viewState.text; |  | ||||||
|             final Generic expression = viewState.getResult(); |  | ||||||
|             if (!Strings.isEmpty(functionValue) && expression != null) { |  | ||||||
|                 if (plotter.isPlotPossibleFor(expression)) { |  | ||||||
|                     plotter.plot(expression); |  | ||||||
|                 } else { |  | ||||||
|                     getNotifier().showMessage(R.string.cpp_plot_too_many_variables, MessageType.error); |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 getNotifier().showMessage(R.string.cpp_plot_empty_function_error, MessageType.error); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             getNotifier().showMessage(R.string.not_valid_result, MessageType.error); |             getNotifier().showMessage(R.string.not_valid_result, MessageType.error); | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|  |         plot(state.getResult()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void showHistory() { |     public void showHistory() { | ||||||
| @@ -258,4 +258,44 @@ public final class ActivityLauncher implements CalculatorEventListener { | |||||||
|         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); |         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); | ||||||
|         context.startActivity(intent); |         context.startActivity(intent); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void plot(@Nullable Generic expression) { | ||||||
|  |         if (expression == null) { | ||||||
|  |             notifier.showMessage(R.string.cpp_plot_empty_function_error); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         final String content = expression.toString(); | ||||||
|  |         if (TextUtils.isEmpty(content)) { | ||||||
|  |             notifier.showMessage(R.string.cpp_plot_empty_function_error); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         final List<String> parameters = new ArrayList<>(); | ||||||
|  |         for (Constant parameter : expression.getUndefinedConstants(variablesRegistry.get())) { | ||||||
|  |             parameters.add(parameter.getName()); | ||||||
|  |         } | ||||||
|  |         if (parameters.size() > 2) { | ||||||
|  |             notifier.showMessage(R.string.cpp_plot_too_many_variables); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             final CustomFunction f = new CustomFunction.Builder().setName("").setParameterNames(parameters).setContent(content).create(); | ||||||
|  |             final ExpressionFunction ef = new ExpressionFunction(f, false); | ||||||
|  |             plotter.get().add(ef); | ||||||
|  |             showPlotter(); | ||||||
|  |         } catch (RuntimeException e) { | ||||||
|  |             errorReporter.get().onException(e); | ||||||
|  |             notifier.showMessage(e.getLocalizedMessage()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public boolean canPlot(@Nullable Generic expression) { | ||||||
|  |         if (expression == null || TextUtils.isEmpty(expression.toString())) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (expression.getUndefinedConstants(variablesRegistry.get()).size() > 2) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,9 +27,8 @@ import android.os.Handler; | |||||||
| import android.preference.PreferenceManager; | import android.preference.PreferenceManager; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.util.TimingLogger; | import android.util.TimingLogger; | ||||||
|  |  | ||||||
| import com.squareup.otto.Bus; | import com.squareup.otto.Bus; | ||||||
|  | import jscl.MathEngine; | ||||||
| import org.acra.ACRA; | import org.acra.ACRA; | ||||||
| import org.acra.ACRAConfiguration; | import org.acra.ACRAConfiguration; | ||||||
| import org.acra.sender.HttpSender; | import org.acra.sender.HttpSender; | ||||||
| @@ -38,18 +37,13 @@ import org.solovyev.android.calculator.floating.FloatingCalculatorActivity; | |||||||
| import org.solovyev.android.calculator.history.History; | import org.solovyev.android.calculator.history.History; | ||||||
| import org.solovyev.android.calculator.language.Language; | import org.solovyev.android.calculator.language.Language; | ||||||
| import org.solovyev.android.calculator.language.Languages; | import org.solovyev.android.calculator.language.Languages; | ||||||
| import org.solovyev.android.calculator.plot.AndroidCalculatorPlotter; |  | ||||||
| import org.solovyev.android.calculator.plot.CalculatorPlotterImpl; |  | ||||||
| import org.solovyev.common.msg.MessageType; | import org.solovyev.common.msg.MessageType; | ||||||
|  |  | ||||||
| import jscl.MathEngine; |  | ||||||
|  |  | ||||||
| import java.util.Locale; |  | ||||||
| import java.util.concurrent.Executor; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| import javax.inject.Named; | import javax.inject.Named; | ||||||
|  | import java.util.Locale; | ||||||
|  | import java.util.concurrent.Executor; | ||||||
|  |  | ||||||
| public class CalculatorApplication extends android.app.Application implements SharedPreferences.OnSharedPreferenceChangeListener { | public class CalculatorApplication extends android.app.Application implements SharedPreferences.OnSharedPreferenceChangeListener { | ||||||
|  |  | ||||||
| @@ -143,11 +137,7 @@ public class CalculatorApplication extends android.app.Application implements Sh | |||||||
|         languages.updateContextLocale(this, true); |         languages.updateContextLocale(this, true); | ||||||
|         App.getGa().reportInitially(preferences); |         App.getGa().reportInitially(preferences); | ||||||
|  |  | ||||||
|         Locator.getInstance().init(calculator, |         Locator.getInstance().init(calculator, engine, keyboard); | ||||||
|                 engine, |  | ||||||
|                 keyboard, |  | ||||||
|                 new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)) |  | ||||||
|         ); |  | ||||||
|  |  | ||||||
|         calculator.init(initThread); |         calculator.init(initThread); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,16 +22,13 @@ | |||||||
|  |  | ||||||
| package org.solovyev.android.calculator; | package org.solovyev.android.calculator; | ||||||
|  |  | ||||||
| import org.solovyev.android.calculator.plot.CalculatorPlotter; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
|  |  | ||||||
| public interface CalculatorLocator { | public interface CalculatorLocator { | ||||||
|  |  | ||||||
|     void init(@Nonnull Calculator calculator, |     void init(@Nonnull Calculator calculator, | ||||||
|               @Nonnull Engine engine, |               @Nonnull Engine engine, | ||||||
|               @Nonnull Keyboard keyboard, |               @Nonnull Keyboard keyboard); | ||||||
|               @Nonnull CalculatorPlotter plotter); |  | ||||||
|  |  | ||||||
|     @Nonnull |     @Nonnull | ||||||
|     Calculator getCalculator(); |     Calculator getCalculator(); | ||||||
| @@ -42,6 +39,4 @@ public interface CalculatorLocator { | |||||||
|     @Nonnull |     @Nonnull | ||||||
|     Keyboard getKeyboard(); |     Keyboard getKeyboard(); | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     CalculatorPlotter getPlotter(); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,15 +22,6 @@ | |||||||
|  |  | ||||||
| package org.solovyev.android.calculator; | package org.solovyev.android.calculator; | ||||||
|  |  | ||||||
| import jscl.math.Generic; |  | ||||||
| import jscl.math.function.Constant; |  | ||||||
| import jscl.math.function.IConstant; |  | ||||||
|  |  | ||||||
| import java.util.HashSet; |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * User: serso |  * User: serso | ||||||
|  * Date: 9/22/12 |  * Date: 9/22/12 | ||||||
| @@ -42,18 +33,4 @@ public final class CalculatorUtils { | |||||||
|         throw new AssertionError(); |         throw new AssertionError(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     public static Set<Constant> getNotSystemConstants(@Nonnull Generic expression) { |  | ||||||
|         final Set<Constant> notSystemConstants = new HashSet<Constant>(); |  | ||||||
|  |  | ||||||
|         for (Constant constant : expression.getConstants()) { |  | ||||||
|             IConstant var = Locator.getInstance().getEngine().getVariablesRegistry().get(constant.getName()); |  | ||||||
|             if (var != null && !var.isSystem() && !var.isDefined()) { |  | ||||||
|                 notSystemConstants.add(constant); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return notSystemConstants; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -57,8 +57,6 @@ public class Display { | |||||||
|     Lazy<Notifier> notifier; |     Lazy<Notifier> notifier; | ||||||
|     @Inject |     @Inject | ||||||
|     Lazy<PreferredPreferences> preferredPreferences; |     Lazy<PreferredPreferences> preferredPreferences; | ||||||
|     @Inject |  | ||||||
|     ActivityLauncher launcher; |  | ||||||
|     @Nullable |     @Nullable | ||||||
|     private DisplayView view; |     private DisplayView view; | ||||||
|     @Nonnull |     @Nonnull | ||||||
|   | |||||||
| @@ -37,17 +37,12 @@ import butterknife.ButterKnife; | |||||||
| import com.squareup.otto.Bus; | import com.squareup.otto.Bus; | ||||||
| import jscl.NumeralBase; | import jscl.NumeralBase; | ||||||
| import jscl.math.Generic; | import jscl.math.Generic; | ||||||
| import jscl.math.function.Constant; |  | ||||||
| import jscl.math.function.CustomFunction; |  | ||||||
| import org.solovyev.android.calculator.converter.ConverterFragment; | import org.solovyev.android.calculator.converter.ConverterFragment; | ||||||
| import org.solovyev.android.calculator.jscl.JsclOperation; | import org.solovyev.android.calculator.jscl.JsclOperation; | ||||||
| import org.solovyev.android.calculator.plot.ExpressionFunction; |  | ||||||
| import org.solovyev.android.plotter.Plotter; | import org.solovyev.android.plotter.Plotter; | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| public class DisplayFragment extends BaseFragment implements View.OnClickListener, | public class DisplayFragment extends BaseFragment implements View.OnClickListener, | ||||||
|         MenuItem.OnMenuItemClickListener { |         MenuItem.OnMenuItemClickListener { | ||||||
| @@ -146,8 +141,7 @@ public class DisplayFragment extends BaseFragment implements View.OnClickListene | |||||||
|                     addMenu(menu, R.string.c_convert, this); |                     addMenu(menu, R.string.c_convert, this); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             final int parameters = CalculatorUtils.getNotSystemConstants(result).size(); |             if (launcher.canPlot(result)) { | ||||||
|             if (parameters >= 0 && parameters <= 2) { |  | ||||||
|                 addMenu(menu, R.string.c_plot, this); |                 addMenu(menu, R.string.c_plot, this); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -216,21 +210,7 @@ public class DisplayFragment extends BaseFragment implements View.OnClickListene | |||||||
|                 ConverterFragment.show(getActivity(), getValue(result)); |                 ConverterFragment.show(getActivity(), getValue(result)); | ||||||
|                 return true; |                 return true; | ||||||
|             case R.string.c_plot: |             case R.string.c_plot: | ||||||
|                 if (result != null) { |                 launcher.plot(result); | ||||||
|                     try { |  | ||||||
|                         final List<String> parameters = new ArrayList<>(); |  | ||||||
|                         for (Constant parameter : CalculatorUtils.getNotSystemConstants(result)) { |  | ||||||
|                             parameters.add(parameter.getName()); |  | ||||||
|                         } |  | ||||||
|                         new CustomFunction.Builder().setParameterNames(parameters).setContent(state.text).create(); |  | ||||||
|                         final CustomFunction f = new CustomFunction.Builder().setName("").setParameterNames(parameters).setContent(result.toString()).create(); |  | ||||||
|                         final ExpressionFunction ef = new ExpressionFunction(f, false); |  | ||||||
|                         plotter.add(ef); |  | ||||||
|                         launcher.showPlotter(); |  | ||||||
|                     } catch (RuntimeException e) { |  | ||||||
|                         errorReporter.onException(e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 return true; |                 return true; | ||||||
|             default: |             default: | ||||||
|                 return false; |                 return false; | ||||||
|   | |||||||
| @@ -22,8 +22,6 @@ | |||||||
|  |  | ||||||
| package org.solovyev.android.calculator; | package org.solovyev.android.calculator; | ||||||
|  |  | ||||||
| import org.solovyev.android.calculator.plot.CalculatorPlotter; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
|  |  | ||||||
| public class Locator implements CalculatorLocator { | public class Locator implements CalculatorLocator { | ||||||
| @@ -36,8 +34,6 @@ public class Locator implements CalculatorLocator { | |||||||
|     private Calculator calculator; |     private Calculator calculator; | ||||||
|     @Nonnull |     @Nonnull | ||||||
|     private Keyboard keyboard; |     private Keyboard keyboard; | ||||||
|     @Nonnull |  | ||||||
|     private CalculatorPlotter calculatorPlotter; |  | ||||||
|  |  | ||||||
|     public Locator() { |     public Locator() { | ||||||
|     } |     } | ||||||
| @@ -50,13 +46,10 @@ public class Locator implements CalculatorLocator { | |||||||
|     @Override |     @Override | ||||||
|     public void init(@Nonnull Calculator calculator, |     public void init(@Nonnull Calculator calculator, | ||||||
|                      @Nonnull Engine engine, |                      @Nonnull Engine engine, | ||||||
|                      @Nonnull Keyboard keyboard, |                      @Nonnull Keyboard keyboard) { | ||||||
|                      @Nonnull CalculatorPlotter plotter) { |  | ||||||
|  |  | ||||||
|         this.calculator = calculator; |         this.calculator = calculator; | ||||||
|         this.engine = engine; |         this.engine = engine; | ||||||
|         this.calculatorPlotter = plotter; |  | ||||||
|  |  | ||||||
|         this.keyboard = keyboard; |         this.keyboard = keyboard; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -78,9 +71,4 @@ public class Locator implements CalculatorLocator { | |||||||
|         return keyboard; |         return keyboard; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public CalculatorPlotter getPlotter() { |  | ||||||
|         return calculatorPlotter; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,17 +24,14 @@ package org.solovyev.android.calculator; | |||||||
|  |  | ||||||
| import android.app.Application; | import android.app.Application; | ||||||
| import android.os.Handler; | import android.os.Handler; | ||||||
|  | import android.support.annotation.StringRes; | ||||||
| import android.widget.Toast; | import android.widget.Toast; | ||||||
| import org.solovyev.android.Threads; | import org.solovyev.android.Threads; | ||||||
| import org.solovyev.android.msg.AndroidMessage; |  | ||||||
| import org.solovyev.common.msg.Message; | import org.solovyev.common.msg.Message; | ||||||
| import org.solovyev.common.msg.MessageType; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import javax.annotation.Nullable; |  | ||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| import javax.inject.Singleton; | import javax.inject.Singleton; | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| @Singleton | @Singleton | ||||||
| public class Notifier { | public class Notifier { | ||||||
| @@ -48,21 +45,22 @@ public class Notifier { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void showMessage(@Nonnull Message message) { |     public void showMessage(@Nonnull Message message) { | ||||||
|         showMessageInUiThread(message.getLocalizedMessage()); |         showMessage(message.getLocalizedMessage()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nonnull List<Object> parameters) { |     public void showMessage(@StringRes int message, Object... parameters) { | ||||||
|         showMessage(new AndroidMessage(messageCode, messageType, application, parameters)); |         showMessage(application.getString(message, parameters)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void showMessage(@Nonnull Integer messageCode, @Nonnull MessageType messageType, @Nullable Object... parameters) { |     public void showMessage(@StringRes int message) { | ||||||
|         showMessage(new AndroidMessage(messageCode, messageType, application, parameters)); |         showMessage(application.getString(message)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void showMessageInUiThread(@Nonnull final String message) { |     public void showMessage(@Nonnull final String message) { | ||||||
|         if (Threads.isUiThread()) { |         if (Threads.isUiThread()) { | ||||||
|             Toast.makeText(application, message, Toast.LENGTH_SHORT).show(); |             Toast.makeText(application, message, Toast.LENGTH_SHORT).show(); | ||||||
|         } else { |             return; | ||||||
|  |         } | ||||||
|         handler.post(new Runnable() { |         handler.post(new Runnable() { | ||||||
|             @Override |             @Override | ||||||
|             public void run() { |             public void run() { | ||||||
| @@ -71,4 +69,3 @@ public class Notifier { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,13 +1,5 @@ | |||||||
| package org.solovyev.android.calculator.keyboard; | package org.solovyev.android.calculator.keyboard; | ||||||
|  |  | ||||||
| import static android.view.HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING; |  | ||||||
| import static android.view.HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING; |  | ||||||
| import static android.view.HapticFeedbackConstants.KEYBOARD_TAP; |  | ||||||
| import static org.solovyev.android.calculator.App.cast; |  | ||||||
| import static org.solovyev.android.calculator.App.getScreenMetrics; |  | ||||||
| import static org.solovyev.android.calculator.Preferences.Gui.Layout.simple; |  | ||||||
| import static org.solovyev.android.calculator.Preferences.Gui.Layout.simple_mobile; |  | ||||||
|  |  | ||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.app.Application; | import android.app.Application; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| @@ -20,15 +12,8 @@ import android.util.TypedValue; | |||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.widget.ImageView; | import android.widget.ImageView; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import org.solovyev.android.Views; | import org.solovyev.android.Views; | ||||||
| import org.solovyev.android.calculator.ActivityUi; | import org.solovyev.android.calculator.*; | ||||||
| import org.solovyev.android.calculator.App; |  | ||||||
| import org.solovyev.android.calculator.Calculator; |  | ||||||
| import org.solovyev.android.calculator.Editor; |  | ||||||
| import org.solovyev.android.calculator.Keyboard; |  | ||||||
| import org.solovyev.android.calculator.Preferences; |  | ||||||
| import org.solovyev.android.calculator.PreferredPreferences; |  | ||||||
| import org.solovyev.android.calculator.buttons.CppSpecialButton; | import org.solovyev.android.calculator.buttons.CppSpecialButton; | ||||||
| import org.solovyev.android.calculator.view.ScreenMetrics; | import org.solovyev.android.calculator.view.ScreenMetrics; | ||||||
| import org.solovyev.android.views.Adjuster; | import org.solovyev.android.views.Adjuster; | ||||||
| @@ -37,11 +22,16 @@ import org.solovyev.android.views.dragbutton.DragButton; | |||||||
| import org.solovyev.android.views.dragbutton.DragDirection; | import org.solovyev.android.views.dragbutton.DragDirection; | ||||||
| import org.solovyev.android.views.dragbutton.SimpleDragListener; | import org.solovyev.android.views.dragbutton.SimpleDragListener; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  | import javax.inject.Inject; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import static android.view.HapticFeedbackConstants.*; | ||||||
| import javax.inject.Inject; | import static org.solovyev.android.calculator.App.cast; | ||||||
|  | import static org.solovyev.android.calculator.App.getScreenMetrics; | ||||||
|  | import static org.solovyev.android.calculator.Preferences.Gui.Layout.simple; | ||||||
|  | import static org.solovyev.android.calculator.Preferences.Gui.Layout.simple_mobile; | ||||||
|  |  | ||||||
| public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPreferenceChangeListener, SimpleDragListener.DragProcessor, View.OnClickListener { | public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPreferenceChangeListener, SimpleDragListener.DragProcessor, View.OnClickListener { | ||||||
|  |  | ||||||
| @@ -67,6 +57,8 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer | |||||||
|     @Inject |     @Inject | ||||||
|     Calculator calculator; |     Calculator calculator; | ||||||
|     @Inject |     @Inject | ||||||
|  |     ActivityLauncher launcher; | ||||||
|  |     @Inject | ||||||
|     PreferredPreferences preferredPreferences; |     PreferredPreferences preferredPreferences; | ||||||
|     protected int orientation = Configuration.ORIENTATION_PORTRAIT; |     protected int orientation = Configuration.ORIENTATION_PORTRAIT; | ||||||
|     private int textSize; |     private int textSize; | ||||||
|   | |||||||
| @@ -17,7 +17,6 @@ import butterknife.Bind; | |||||||
| import butterknife.ButterKnife; | import butterknife.ButterKnife; | ||||||
| import jscl.NumeralBase; | import jscl.NumeralBase; | ||||||
| import org.solovyev.android.Check; | import org.solovyev.android.Check; | ||||||
| import org.solovyev.android.calculator.ActivityLauncher; |  | ||||||
| import org.solovyev.android.calculator.Engine; | import org.solovyev.android.calculator.Engine; | ||||||
| import org.solovyev.android.calculator.Preferences; | import org.solovyev.android.calculator.Preferences; | ||||||
| import org.solovyev.android.calculator.R; | import org.solovyev.android.calculator.R; | ||||||
| @@ -121,7 +120,7 @@ public class PartialKeyboardUi extends BaseKeyboardUi { | |||||||
|                 return true; |                 return true; | ||||||
|             case R.id.cpp_button_equals: |             case R.id.cpp_button_equals: | ||||||
|                 if (direction == down) { |                 if (direction == down) { | ||||||
|                     ActivityLauncher.tryPlot(); |                     launcher.plotDisplayedExpression(); | ||||||
|                     return true; |                     return true; | ||||||
|                 } else if (direction == up) { |                 } else if (direction == up) { | ||||||
|                     calculator.simplify(); |                     calculator.simplify(); | ||||||
|   | |||||||
| @@ -1,442 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright 2013 serso aka se.solovyev |  | ||||||
|  * |  | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *    http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  * |  | ||||||
|  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |  | ||||||
|  * Contact details |  | ||||||
|  * |  | ||||||
|  * Email: se.solovyev@gmail.com |  | ||||||
|  * Site:  http://se.solovyev.org |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| package org.solovyev.android.calculator.plot; |  | ||||||
|  |  | ||||||
| import com.google.common.base.Predicate; |  | ||||||
| import com.google.common.collect.Iterables; |  | ||||||
| import com.google.common.collect.Lists; |  | ||||||
| import jscl.math.Generic; |  | ||||||
| import jscl.math.function.Constant; |  | ||||||
| import org.solovyev.android.calculator.Calculator; |  | ||||||
| import org.solovyev.android.calculator.CalculatorEventType; |  | ||||||
| import org.solovyev.android.calculator.CalculatorUtils; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; |  | ||||||
| import javax.annotation.Nullable; |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| public class CalculatorPlotterImpl implements CalculatorPlotter { |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private final List<PlotFunction> functions = new ArrayList<PlotFunction>(); |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private final Calculator calculator; |  | ||||||
|  |  | ||||||
|     private final PlotResourceManager resourceManager = new MapPlotResourceManager(); |  | ||||||
|  |  | ||||||
|     private boolean plot3d = false; |  | ||||||
|     private boolean adjustYAxis = true; |  | ||||||
|  |  | ||||||
|     private boolean plotImag = false; |  | ||||||
|  |  | ||||||
|     private int arity = 0; |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private PlotBoundaries plotBoundaries = PlotBoundaries.newDefaultInstance(); |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private PlotData plotData = new PlotData(Collections.<PlotFunction>emptyList(), plot3d, true, plotBoundaries); |  | ||||||
|  |  | ||||||
|     public CalculatorPlotterImpl(@Nonnull Calculator calculator) { |  | ||||||
|         this.calculator = calculator; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public PlotData getPlotData() { |  | ||||||
|         return plotData; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean addFunction(@Nonnull Generic expression) { |  | ||||||
|         final List<Constant> variables = new ArrayList<Constant>(CalculatorUtils.getNotSystemConstants(expression)); |  | ||||||
|  |  | ||||||
|         if (variables.size() > 2) throw new AssertionError(); |  | ||||||
|  |  | ||||||
|         final Constant xVariable; |  | ||||||
|         if (variables.size() > 0) { |  | ||||||
|             xVariable = variables.get(0); |  | ||||||
|         } else { |  | ||||||
|             xVariable = null; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         final Constant yVariable; |  | ||||||
|         if (variables.size() > 1) { |  | ||||||
|             yVariable = variables.get(1); |  | ||||||
|         } else { |  | ||||||
|             yVariable = null; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         final XyFunction realXyFunction = new XyFunction(expression, xVariable, yVariable, false); |  | ||||||
|         final XyFunction imagXyFunction = new XyFunction(expression, xVariable, yVariable, true); |  | ||||||
|  |  | ||||||
|         // first create plot functions with default line definitions |  | ||||||
|         PlotFunction realPlotFunction = new PlotFunction(realXyFunction); |  | ||||||
|         PlotFunction imagPlotFunction = new PlotFunction(imagXyFunction); |  | ||||||
|  |  | ||||||
|         // then remove all unpinned graphs and free their line definitions |  | ||||||
|         removeAllUnpinnedExcept(realPlotFunction, imagPlotFunction); |  | ||||||
|  |  | ||||||
|         // create plot functions with freed line definitions |  | ||||||
|         realPlotFunction = newPlotFunction(realXyFunction); |  | ||||||
|         imagPlotFunction = newPlotFunction(imagXyFunction); |  | ||||||
|  |  | ||||||
|         final boolean realAdded = addFunction(realPlotFunction); |  | ||||||
|         final boolean imagAdded = addFunction(plotImag ? imagPlotFunction : PlotFunction.invisible(imagPlotFunction)); |  | ||||||
|  |  | ||||||
|         return imagAdded || realAdded; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private PlotFunction newPlotFunction(@Nonnull XyFunction xyFunction) { |  | ||||||
|         return new PlotFunction(xyFunction, resourceManager.generateAndRegister()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean addFunction(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             if (!functions.contains(plotFunction)) { |  | ||||||
|                 resourceManager.register(plotFunction.getPlotLineDef()); |  | ||||||
|                 functions.add(plotFunction); |  | ||||||
|                 onFunctionsChanged(); |  | ||||||
|                 return true; |  | ||||||
|             } else { |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private boolean removeAllUnpinnedExcept(@Nonnull final PlotFunction... exceptFunctions) { |  | ||||||
|         synchronized (functions) { |  | ||||||
|  |  | ||||||
|             boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() { |  | ||||||
|                 @Override |  | ||||||
|                 public boolean apply(@Nullable PlotFunction function) { |  | ||||||
|                     if (function != null && !function.isPinned()) { |  | ||||||
|  |  | ||||||
|                         for (PlotFunction exceptFunction : exceptFunctions) { |  | ||||||
|                             if (exceptFunction.equals(function)) { |  | ||||||
|                                 return false; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                         resourceManager.unregister(function.getPlotLineDef()); |  | ||||||
|  |  | ||||||
|                         return true; |  | ||||||
|                     } else { |  | ||||||
|                         return false; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             if (changed) { |  | ||||||
|                 onFunctionsChanged(); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return changed; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void removeAllUnpinned() { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() { |  | ||||||
|                 @Override |  | ||||||
|                 public boolean apply(@Nullable PlotFunction function) { |  | ||||||
|                     boolean removed = function != null && !function.isPinned(); |  | ||||||
|  |  | ||||||
|                     if (removed) { |  | ||||||
|                         resourceManager.unregister(function.getPlotLineDef()); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     return removed; |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             if (changed) { |  | ||||||
|                 onFunctionsChanged(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean removeFunction(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             boolean changed = functions.remove(plotFunction); |  | ||||||
|             if (changed) { |  | ||||||
|                 resourceManager.unregister(plotFunction.getPlotLineDef()); |  | ||||||
|                 onFunctionsChanged(); |  | ||||||
|             } |  | ||||||
|             return changed; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean addFunction(@Nonnull XyFunction xyFunction) { |  | ||||||
|         return addFunction(newPlotFunction(xyFunction)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) { |  | ||||||
|         return addFunction(new PlotFunction(xyFunction, functionLineDef)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) { |  | ||||||
|         final PlotFunction newFunction = new PlotFunction(xyFunction, functionLineDef); |  | ||||||
|  |  | ||||||
|         return updateFunction(newFunction); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean updateFunction(@Nonnull PlotFunction newFunction) { |  | ||||||
|         boolean changed = updateFunction0(newFunction); |  | ||||||
|         if (changed) { |  | ||||||
|             firePlotDataChangedEvent(); |  | ||||||
|         } |  | ||||||
|         return changed; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public boolean updateFunction0(@Nonnull PlotFunction newFunction) { |  | ||||||
|         boolean changed = false; |  | ||||||
|  |  | ||||||
|         synchronized (functions) { |  | ||||||
|             for (int i = 0; i < functions.size(); i++) { |  | ||||||
|                 final PlotFunction oldFunction = functions.get(i); |  | ||||||
|                 if (oldFunction.equals(newFunction)) { |  | ||||||
|  |  | ||||||
|                     resourceManager.unregister(oldFunction.getPlotLineDef()); |  | ||||||
|                     resourceManager.register(newFunction.getPlotLineDef()); |  | ||||||
|  |  | ||||||
|                     // update old function |  | ||||||
|                     functions.set(i, newFunction); |  | ||||||
|                     changed = true; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return changed; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean removeFunction(@Nonnull XyFunction xyFunction) { |  | ||||||
|         return removeFunction(new PlotFunction(xyFunction)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public PlotFunction pin(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         final PlotFunction newFunction = PlotFunction.pin(plotFunction); |  | ||||||
|         updateFunction0(newFunction); |  | ||||||
|         return newFunction; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public PlotFunction unpin(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         final PlotFunction newFunction = PlotFunction.unpin(plotFunction); |  | ||||||
|         updateFunction0(newFunction); |  | ||||||
|         return newFunction; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public PlotFunction show(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         final PlotFunction newFunction = PlotFunction.visible(plotFunction); |  | ||||||
|  |  | ||||||
|         updateFunction(newFunction); |  | ||||||
|  |  | ||||||
|         return newFunction; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public PlotFunction hide(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         final PlotFunction newFunction = PlotFunction.invisible(plotFunction); |  | ||||||
|  |  | ||||||
|         updateFunction(newFunction); |  | ||||||
|  |  | ||||||
|         return newFunction; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void clearAllFunctions() { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             resourceManager.unregisterAll(); |  | ||||||
|             functions.clear(); |  | ||||||
|             onFunctionsChanged(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nullable |  | ||||||
|     @Override |  | ||||||
|     public PlotFunction getFunctionById(@Nonnull final String functionId) { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             return Iterables.find(functions, new Predicate<PlotFunction>() { |  | ||||||
|                 @Override |  | ||||||
|                 public boolean apply(@Nullable PlotFunction function) { |  | ||||||
|                     return function != null && function.getXyFunction().getId().equals(functionId); |  | ||||||
|                 } |  | ||||||
|             }, null); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // NOTE: this method must be called from synchronized block |  | ||||||
|     private void onFunctionsChanged() { |  | ||||||
|         if (!Thread.holdsLock(functions)) throw new AssertionError(); |  | ||||||
|  |  | ||||||
|         int maxArity = 0; |  | ||||||
|         for (PlotFunction function : functions) { |  | ||||||
|             final XyFunction xyFunction = function.getXyFunction(); |  | ||||||
|  |  | ||||||
|             maxArity = Math.max(maxArity, xyFunction.getArity()); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         plot3d = maxArity > 1; |  | ||||||
|  |  | ||||||
|         if (functions.isEmpty()) { |  | ||||||
|             // no functions => new plot => default boundaries |  | ||||||
|             this.plotBoundaries = PlotBoundaries.newDefaultInstance(); |  | ||||||
|             this.adjustYAxis = true; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         arity = maxArity; |  | ||||||
|  |  | ||||||
|         firePlotDataChangedEvent(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public List<PlotFunction> getFunctions() { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             return new ArrayList<PlotFunction>(functions); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public List<PlotFunction> getVisibleFunctions() { |  | ||||||
|         synchronized (functions) { |  | ||||||
|             return Lists.newArrayList(Iterables.filter(functions, new Predicate<PlotFunction>() { |  | ||||||
|                 @Override |  | ||||||
|                 public boolean apply(@Nullable PlotFunction function) { |  | ||||||
|                     return function != null && function.isVisible(); |  | ||||||
|                 } |  | ||||||
|             })); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void plot() { |  | ||||||
|         calculator.fireCalculatorEvent(CalculatorEventType.plot_graph, null); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void plot(@Nonnull Generic expression) { |  | ||||||
|         addFunction(expression); |  | ||||||
|         plot(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean is2dPlotPossible() { |  | ||||||
|         return arity < 2; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public boolean isPlotPossibleFor(@Nonnull Generic expression) { |  | ||||||
|         boolean result = false; |  | ||||||
|  |  | ||||||
|         int size = CalculatorUtils.getNotSystemConstants(expression).size(); |  | ||||||
|         if (size == 0 || size == 1 || size == 2) { |  | ||||||
|             result = true; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void setPlot3d(boolean plot3d) { |  | ||||||
|         if (this.plot3d != plot3d) { |  | ||||||
|             this.plot3d = plot3d; |  | ||||||
|             firePlotDataChangedEvent(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void firePlotDataChangedEvent() { |  | ||||||
|         updatePlotData(); |  | ||||||
|         calculator.fireCalculatorEvent(CalculatorEventType.plot_data_changed, plotData); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void updatePlotData() { |  | ||||||
|         plotData = new PlotData(getVisibleFunctions(), plot3d, adjustYAxis, plotBoundaries); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void setPlotImag(boolean plotImag) { |  | ||||||
|         if (this.plotImag != plotImag) { |  | ||||||
|             this.plotImag = plotImag; |  | ||||||
|             if (toggleImagFunctions(this.plotImag)) { |  | ||||||
|                 firePlotDataChangedEvent(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) { |  | ||||||
|         if (!this.plotBoundaries.equals(plotBoundaries)) { |  | ||||||
|             this.plotBoundaries = plotBoundaries; |  | ||||||
|             this.adjustYAxis = false; |  | ||||||
|             updatePlotData(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) { |  | ||||||
|         if (!this.plotBoundaries.equals(plotBoundaries)) { |  | ||||||
|             this.plotBoundaries = plotBoundaries; |  | ||||||
|             this.adjustYAxis = false; |  | ||||||
|             firePlotDataChangedEvent(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private boolean toggleImagFunctions(boolean show) { |  | ||||||
|         boolean changed = false; |  | ||||||
|  |  | ||||||
|         synchronized (functions) { |  | ||||||
|             for (int i = 0; i < functions.size(); i++) { |  | ||||||
|                 final PlotFunction plotFunction = functions.get(i); |  | ||||||
|                 if (plotFunction.getXyFunction().isImag()) { |  | ||||||
|                     functions.set(i, show ? PlotFunction.visible(plotFunction) : PlotFunction.invisible(plotFunction)); |  | ||||||
|                     changed = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return changed; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,152 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright 2013 serso aka se.solovyev |  | ||||||
|  * |  | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *    http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  * |  | ||||||
|  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |  | ||||||
|  * Contact details |  | ||||||
|  * |  | ||||||
|  * Email: se.solovyev@gmail.com |  | ||||||
|  * Site:  http://se.solovyev.org |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| package org.solovyev.android.calculator.plot; |  | ||||||
|  |  | ||||||
| import android.content.Context; |  | ||||||
| import android.view.View; |  | ||||||
| import android.widget.CheckBox; |  | ||||||
| import android.widget.CompoundButton; |  | ||||||
| import android.widget.ImageButton; |  | ||||||
| import android.widget.TextView; |  | ||||||
|  |  | ||||||
| import org.solovyev.android.calculator.Locator; |  | ||||||
| import org.solovyev.android.calculator.R; |  | ||||||
| import org.solovyev.android.list.ListItem; |  | ||||||
| import org.solovyev.android.view.ViewBuilder; |  | ||||||
| import org.solovyev.android.view.ViewFromLayoutBuilder; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; |  | ||||||
| import javax.annotation.Nullable; |  | ||||||
|  |  | ||||||
| public class PlotFunctionListItem implements ListItem { |  | ||||||
|  |  | ||||||
|     private static final String PREFIX = "plot_function_"; |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private PlotFunction plotFunction; |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private ViewBuilder<View> viewBuilder; |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     private String tag; |  | ||||||
|  |  | ||||||
|     public PlotFunctionListItem(@Nonnull PlotFunction plotFunction) { |  | ||||||
|         this.plotFunction = plotFunction; |  | ||||||
|         this.viewBuilder = ViewFromLayoutBuilder.newInstance(R.layout.cpp_plot_function_list_item); |  | ||||||
|         this.tag = PREFIX + plotFunction.getXyFunction().getExpressionString(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nullable |  | ||||||
|     @Override |  | ||||||
|     public OnClickAction getOnClickAction() { |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nullable |  | ||||||
|     @Override |  | ||||||
|     public OnClickAction getOnLongClickAction() { |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public View updateView(@Nonnull Context context, @Nonnull View view) { |  | ||||||
|         final Object viewTag = view.getTag(); |  | ||||||
|         if (viewTag instanceof String) { |  | ||||||
|             if (this.tag.equals(viewTag)) { |  | ||||||
|                 return view; |  | ||||||
|             } else if (((String) viewTag).startsWith(PREFIX)) { |  | ||||||
|                 fillView(view, context); |  | ||||||
|                 return view; |  | ||||||
|             } else { |  | ||||||
|                 return build(context); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return build(context); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Nonnull |  | ||||||
|     @Override |  | ||||||
|     public View build(@Nonnull Context context) { |  | ||||||
|         final View root = buildView(context); |  | ||||||
|         fillView(root, context); |  | ||||||
|         return root; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private View buildView(@Nonnull Context context) { |  | ||||||
|         return viewBuilder.build(context); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void fillView(@Nonnull View root, @Nonnull final Context context) { |  | ||||||
|         root.setTag(tag); |  | ||||||
|  |  | ||||||
|         final CalculatorPlotter plotter = Locator.getInstance().getPlotter(); |  | ||||||
|  |  | ||||||
|         final TextView expressionTextView = (TextView) root.findViewById(R.id.cpp_plot_function_expression_textview); |  | ||||||
|         expressionTextView.setText(plotFunction.getXyFunction().getExpressionString()); |  | ||||||
|  |  | ||||||
|         final CheckBox pinnedCheckBox = (CheckBox) root.findViewById(R.id.cpp_plot_function_pinned_checkbox); |  | ||||||
|         pinnedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { |  | ||||||
|             @Override |  | ||||||
|             public void onCheckedChanged(CompoundButton buttonView, boolean pin) { |  | ||||||
|                 if (pin) { |  | ||||||
|                     if (!plotFunction.isPinned()) { |  | ||||||
|                         plotFunction = plotter.pin(plotFunction); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     if (plotFunction.isPinned()) { |  | ||||||
|                         plotFunction = plotter.unpin(plotFunction); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         pinnedCheckBox.setChecked(plotFunction.isPinned()); |  | ||||||
|  |  | ||||||
|         final CheckBox visibleCheckBox = (CheckBox) root.findViewById(R.id.cpp_plot_function_visible_checkbox); |  | ||||||
|         visibleCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { |  | ||||||
|             @Override |  | ||||||
|             public void onCheckedChanged(CompoundButton buttonView, boolean show) { |  | ||||||
|                 if (show) { |  | ||||||
|                     if (!plotFunction.isVisible()) { |  | ||||||
|                         plotFunction = plotter.show(plotFunction); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     if (plotFunction.isVisible()) { |  | ||||||
|                         plotFunction = plotter.hide(plotFunction); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         visibleCheckBox.setChecked(plotFunction.isVisible()); |  | ||||||
|  |  | ||||||
|         final ImageButton settingsButton = (ImageButton) root.findViewById(R.id.cpp_plot_function_settings_button); |  | ||||||
|         settingsButton.setOnClickListener(new View.OnClickListener() { |  | ||||||
|             @Override |  | ||||||
|             public void onClick(View v) { |  | ||||||
|                 // FIXME: 2016-02-01  |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -24,7 +24,6 @@ package org.solovyev.android.calculator; | |||||||
|  |  | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
| import com.squareup.otto.Bus; | import com.squareup.otto.Bus; | ||||||
| import org.solovyev.android.calculator.plot.CalculatorPlotter; |  | ||||||
|  |  | ||||||
| import java.util.concurrent.Executor; | import java.util.concurrent.Executor; | ||||||
|  |  | ||||||
| @@ -38,7 +37,7 @@ import static org.mockito.Mockito.mock; | |||||||
| public class AbstractCalculatorTest { | public class AbstractCalculatorTest { | ||||||
|  |  | ||||||
|     protected void setUp() throws Exception { |     protected void setUp() throws Exception { | ||||||
|         Locator.getInstance().init(new Calculator(mock(SharedPreferences.class), mock(Bus.class), mock(Executor.class), mock(Executor.class)), CalculatorTestUtils.newCalculatorEngine(), mock(Keyboard.class), mock(CalculatorPlotter.class)); |         Locator.getInstance().init(new Calculator(mock(SharedPreferences.class), mock(Bus.class), mock(Executor.class), mock(Executor.class)), CalculatorTestUtils.newCalculatorEngine(), mock(Keyboard.class)); | ||||||
|         Locator.getInstance().getEngine().init(new Executor() { |         Locator.getInstance().getEngine().init(new Executor() { | ||||||
|             @Override |             @Override | ||||||
|             public void execute(Runnable command) { |             public void execute(Runnable command) { | ||||||
|   | |||||||
| @@ -36,7 +36,6 @@ 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.operators.OperatorsRegistry; | import org.solovyev.android.calculator.operators.OperatorsRegistry; | ||||||
| import org.solovyev.android.calculator.operators.PostfixFunctionsRegistry; | import org.solovyev.android.calculator.operators.PostfixFunctionsRegistry; | ||||||
| import org.solovyev.android.calculator.plot.CalculatorPlotter; |  | ||||||
|  |  | ||||||
| import jscl.JsclMathEngine; | import jscl.JsclMathEngine; | ||||||
|  |  | ||||||
| @@ -68,7 +67,7 @@ public class CalculatorTestUtils { | |||||||
|  |  | ||||||
|     public static void staticSetUp() throws Exception { |     public static void staticSetUp() throws Exception { | ||||||
|         App.init(new CalculatorApplication(), 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 Calculator(mock(SharedPreferences.class), mock(Bus.class), mock(Executor.class), mock(Executor.class)), newCalculatorEngine(), mock(Keyboard.class), mock(CalculatorPlotter.class)); |         Locator.getInstance().init(new Calculator(mock(SharedPreferences.class), mock(Bus.class), mock(Executor.class), mock(Executor.class)), newCalculatorEngine(), mock(Keyboard.class)); | ||||||
|         Locator.getInstance().getEngine().init(new Executor() { |         Locator.getInstance().getEngine().init(new Executor() { | ||||||
|             @Override |             @Override | ||||||
|             public void execute(Runnable command) { |             public void execute(Runnable command) { | ||||||
| @@ -83,7 +82,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 Calculator(mock(SharedPreferences.class), mock(Bus.class), mock(Executor.class), mock(Executor.class)), newCalculatorEngine(), mock(Keyboard.class), mock(CalculatorPlotter.class)); |         Locator.getInstance().init(new Calculator(mock(SharedPreferences.class), mock(Bus.class), mock(Executor.class), mock(Executor.class)), newCalculatorEngine(), mock(Keyboard.class)); | ||||||
|         Locator.getInstance().getEngine().init(new Executor() { |         Locator.getInstance().getEngine().init(new Executor() { | ||||||
|             @Override |             @Override | ||||||
|             public void execute(Runnable command) { |             public void execute(Runnable command) { | ||||||
|   | |||||||
| @@ -1,17 +1,40 @@ | |||||||
| package jscl.math; | package jscl.math; | ||||||
|  |  | ||||||
| import jscl.math.function.Constant; | import jscl.math.function.Constant; | ||||||
|  | import jscl.math.function.IConstant; | ||||||
| import jscl.mathml.MathML; | import jscl.mathml.MathML; | ||||||
| import jscl.text.ParserUtils; | import jscl.text.ParserUtils; | ||||||
|  | import org.solovyev.common.math.MathRegistry; | ||||||
| import java.math.BigInteger; |  | ||||||
| import java.util.Set; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
| public abstract class Generic implements Arithmetic<Generic>, Comparable { | public abstract class Generic implements Arithmetic<Generic>, Comparable { | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|  |     public Set<Constant> getUndefinedConstants(@Nonnull MathRegistry<IConstant> constantsRegistry) { | ||||||
|  |         final Set<Constant> result = new HashSet<>(); | ||||||
|  |  | ||||||
|  |         for (Constant expressionConstant : getConstants()) { | ||||||
|  |             final IConstant registryConstant = constantsRegistry.get(expressionConstant.getName()); | ||||||
|  |             if (registryConstant == null) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             if (registryConstant.isSystem()) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             if(registryConstant.isDefined()) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             result.add(expressionConstant); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public BigInteger toBigInteger() { |     public BigInteger toBigInteger() { | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ public class CustomFunction extends Function implements IFunction { | |||||||
|     private CustomFunction(@Nonnull String name, |     private CustomFunction(@Nonnull String name, | ||||||
|                            @Nonnull List<String> parameterNames, |                            @Nonnull List<String> parameterNames, | ||||||
|                            @Nonnull String content, |                            @Nonnull String content, | ||||||
|                            @Nullable String description) { |                            @Nullable String description) throws CustomFunctionCalculationException { | ||||||
|         super(name, new Generic[parameterNames.size()]); |         super(name, new Generic[parameterNames.size()]); | ||||||
|         this.parameterNames = parameterNames; |         this.parameterNames = parameterNames; | ||||||
|         try { |         try { | ||||||
| @@ -321,7 +321,7 @@ public class CustomFunction extends Function implements IFunction { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         @Nonnull |         @Nonnull | ||||||
|         public CustomFunction create() { |         public CustomFunction create() throws CustomFunctionCalculationException { | ||||||
|             final CustomFunction customFunction = new CustomFunction(name, parameterNames, prepareContent(content), description); |             final CustomFunction customFunction = new CustomFunction(name, parameterNames, prepareContent(content), description); | ||||||
|             customFunction.setSystem(system); |             customFunction.setSystem(system); | ||||||
|             if (id != null) { |             if (id != null) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 serso
					serso