Remove dependencies
This commit is contained in:
parent
9bcc4d4d9f
commit
ba6480d101
@ -60,14 +60,11 @@ android {
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile 'org.solovyev:common-core:1.0.7'
|
||||
compile 'org.solovyev:common-text:1.0.7'
|
||||
compile 'org.solovyev:common-security:1.0.7'
|
||||
compile 'org.solovyev:common-msg:1.0.7'
|
||||
compile 'com.android.support:support-v4:23.1.1'
|
||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||
compile 'com.android.support:cardview-v7:23.1.1'
|
||||
compile 'com.android.support:design:23.1.1'
|
||||
compile 'com.android.support:support-v4:23.2.0'
|
||||
compile 'com.android.support:appcompat-v7:23.2.0'
|
||||
compile 'com.android.support:cardview-v7:23.2.0'
|
||||
compile 'com.android.support:design:23.2.0'
|
||||
compile('ch.acra:acra:4.7.0') {
|
||||
exclude group: 'org.json'
|
||||
}
|
||||
@ -76,11 +73,6 @@ dependencies {
|
||||
compile ':square-otto:1.3.9-SNAPSHOT'
|
||||
apt ':square-otto-compiler:1.3.9-SNAPSHOT'
|
||||
apt 'com.squareup:javapoet:1.5.1'
|
||||
compile 'org.solovyev.android:android-common-lists:1.1.18@aar'
|
||||
compile 'org.solovyev.android:android-common-core:1.1.18@aar'
|
||||
compile 'org.solovyev.android:android-common-other:1.1.18@aar'
|
||||
compile 'org.solovyev.android:android-common-views:1.1.18@aar'
|
||||
compile 'org.solovyev.android:android-common-menus:1.1.18@aar'
|
||||
compile(project(':jscl')) {
|
||||
exclude(module: 'xercesImpl')
|
||||
}
|
||||
@ -99,7 +91,6 @@ dependencies {
|
||||
exclude(module: 'stax-api')
|
||||
exclude(module: 'xpp3')
|
||||
}
|
||||
compile 'commons-cli:commons-cli:1.2'
|
||||
compile 'com.jakewharton:butterknife:7.0.1'
|
||||
compile 'org.solovyev.android.views:linear-layout-manager:0.5@aar'
|
||||
|
||||
@ -115,7 +106,7 @@ dependencies {
|
||||
testCompile 'org.skyscreamer:jsonassert:1.2.3'
|
||||
testCompile(name: 'org.apache.http.legacy', ext: 'jar')
|
||||
|
||||
androidTestCompile 'com.android.support:support-annotations:23.1.1'
|
||||
androidTestCompile 'com.android.support:support-annotations:23.2.0'
|
||||
androidTestCompile 'com.android.support.test:runner:0.4.1'
|
||||
androidTestCompile 'com.android.support.test:rules:0.4.1'
|
||||
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||
@ -167,7 +158,7 @@ signing {
|
||||
}
|
||||
|
||||
gradle.taskGraph.afterTask { Task task ->
|
||||
if (task.project.name == 'android-app') {
|
||||
if (task.project.name == 'app') {
|
||||
if (task.name == 'mergeReleaseResources') {
|
||||
cleanGoogleServicesResources('release')
|
||||
} else if (task.name == 'mergeDebugResources') {
|
||||
@ -178,13 +169,7 @@ gradle.taskGraph.afterTask { Task task ->
|
||||
|
||||
private void cleanGoogleServicesResources(buildType) {
|
||||
ant.delete(includeEmptyDirs: 'true') {
|
||||
fileset(dir: file('./build/intermediates/res/merged/' + buildType), includes: '**/common_signin*')
|
||||
}
|
||||
ant.delete(includeEmptyDirs: 'true') {
|
||||
fileset(dir: file('./build/intermediates/res/merged/' + buildType), includes: '**/ic_plusone*')
|
||||
}
|
||||
ant.delete(includeEmptyDirs: 'true') {
|
||||
fileset(dir: file('./build/intermediates/res/merged/' + buildType), includes: '**/powered_by_google*')
|
||||
fileset(dir: file('./build/intermediates/res/merged/' + buildType), includes: '**/common_*')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@
|
||||
-dontwarn com.actionbarsherlock.BuildConfig
|
||||
-dontwarn com.google.android.gms.internal.**
|
||||
-dontwarn com.google.android.gms.common.internal.**
|
||||
-dontwarn com.google.android.gms.common.GooglePlayServicesUtil
|
||||
|
||||
-keep class com.squareup.leakcanary.** { *; }
|
||||
-dontwarn com.squareup.leakcanary.**
|
||||
|
@ -66,6 +66,7 @@
|
||||
-dontwarn com.actionbarsherlock.BuildConfig
|
||||
-dontwarn com.google.android.gms.internal.**
|
||||
-dontwarn com.google.android.gms.common.internal.**
|
||||
-dontwarn com.google.android.gms.common.GooglePlayServicesUtil
|
||||
|
||||
-keep class com.squareup.leakcanary.** { *; }
|
||||
-dontwarn com.squareup.leakcanary.**
|
||||
@ -95,7 +96,7 @@
|
||||
## ASSERTIONS
|
||||
|
||||
-assumenosideeffects class org.solovyev.android.Check {
|
||||
*;
|
||||
public static *;
|
||||
}
|
||||
|
||||
## ACRA
|
||||
|
@ -139,15 +139,6 @@
|
||||
android:label="@string/cpp_purchase_title"
|
||||
android:theme="@style/Cpp.Theme.Translucent" />
|
||||
|
||||
<!-- todo serso: strings-->
|
||||
<activity
|
||||
android:name=".matrix.CalculatorMatrixActivity"
|
||||
android:label="@string/c_plot_graph">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- ONSCREEN CONFIG -->
|
||||
|
||||
<activity
|
||||
|
@ -33,7 +33,6 @@ 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.Check;
|
||||
import org.solovyev.android.calculator.about.AboutActivity;
|
||||
import org.solovyev.android.calculator.functions.CppFunction;
|
||||
@ -85,7 +84,7 @@ public final class ActivityLauncher {
|
||||
|
||||
private static void show(@Nonnull Context context, @NonNull Intent intent) {
|
||||
final boolean detached = !(context instanceof Activity);
|
||||
Activities.addIntentFlags(intent, detached, context);
|
||||
App.addIntentFlags(intent, detached, context);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
@ -24,17 +24,14 @@ package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.*;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
@ -55,7 +52,6 @@ import android.widget.TextView;
|
||||
import com.squareup.otto.Bus;
|
||||
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.floating.FloatingCalculatorService;
|
||||
import org.solovyev.android.calculator.ga.Ga;
|
||||
import org.solovyev.android.calculator.language.Languages;
|
||||
@ -350,13 +346,13 @@ public final class App {
|
||||
|
||||
final StringBuilder helpText = new StringBuilder();
|
||||
helpText.append("Size: ");
|
||||
if (Views.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE, c)) {
|
||||
if (isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE, c)) {
|
||||
helpText.append("xlarge");
|
||||
} else if (Views.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE, c)) {
|
||||
} else if (isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE, c)) {
|
||||
helpText.append("large");
|
||||
} else if (Views.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_NORMAL, c)) {
|
||||
} else if (isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_NORMAL, c)) {
|
||||
helpText.append("normal");
|
||||
} else if (Views.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_SMALL, c)) {
|
||||
} else if (isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_SMALL, c)) {
|
||||
helpText.append("small");
|
||||
} else {
|
||||
helpText.append("unknown");
|
||||
@ -393,4 +389,117 @@ public final class App {
|
||||
static boolean isFloatingCalculator(@NonNull Context context) {
|
||||
return unwrap(context) instanceof FloatingCalculatorService;
|
||||
}
|
||||
|
||||
public static int getAppVersionCode(@Nonnull Context context) {
|
||||
try {
|
||||
return getAppVersionCode(context, context.getPackageName());
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Check.shouldNotHappen();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getAppVersionCode(@Nonnull Context context, @Nonnull String appPackageName) throws PackageManager.NameNotFoundException {
|
||||
return context.getPackageManager().getPackageInfo(appPackageName, 0).versionCode;
|
||||
}
|
||||
public static boolean isUiThread() {
|
||||
return Looper.myLooper() == Looper.getMainLooper();
|
||||
}
|
||||
|
||||
public static boolean isLayoutSizeAtLeast(int size, @Nonnull Configuration configuration) {
|
||||
int cur = configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
|
||||
if (cur == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) return false;
|
||||
return cur >= size;
|
||||
}
|
||||
|
||||
public static void restartActivity(@Nonnull Activity activity) {
|
||||
final Intent intent = activity.getIntent();
|
||||
activity.finish();
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method runs through view and all it's children recursively and process them via viewProcessor
|
||||
*
|
||||
* @param view parent view to be processed, if view is ViewGroup then all it's children will be processed
|
||||
* @param viewProcessor object which processes views
|
||||
*/
|
||||
public static void processViews(@Nonnull View view, @Nonnull ViewProcessor<View> viewProcessor) {
|
||||
processViewsOfType0(view, null, viewProcessor);
|
||||
}
|
||||
|
||||
static <T> void processViewsOfType0(@Nonnull View view, @Nullable Class<T> viewClass, @Nonnull ViewProcessor<T> viewProcessor) {
|
||||
if (view instanceof ViewGroup) {
|
||||
final ViewGroup viewGroup = (ViewGroup) view;
|
||||
|
||||
if (viewClass == null || viewClass.isAssignableFrom(ViewGroup.class)) {
|
||||
//noinspection unchecked
|
||||
viewProcessor.process((T) viewGroup);
|
||||
}
|
||||
|
||||
for (int index = 0; index < viewGroup.getChildCount(); index++) {
|
||||
processViewsOfType0(viewGroup.getChildAt(index), viewClass, viewProcessor);
|
||||
}
|
||||
} else if (viewClass == null || viewClass.isAssignableFrom(view.getClass())) {
|
||||
//noinspection unchecked
|
||||
viewProcessor.process((T) view);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void processViewsOfType(@Nonnull View view, @Nonnull Class<T> viewClass, @Nonnull ViewProcessor<T> viewProcessor) {
|
||||
processViewsOfType0(view, viewClass, viewProcessor);
|
||||
}
|
||||
|
||||
public interface ViewProcessor<V> {
|
||||
void process(@Nonnull V view);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static int getScreenOrientation(@Nonnull Activity activity) {
|
||||
final android.view.Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
if (display.getWidth() <= display.getHeight()) {
|
||||
return Configuration.ORIENTATION_PORTRAIT;
|
||||
} else {
|
||||
return Configuration.ORIENTATION_LANDSCAPE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addIntentFlags(@Nonnull Intent intent, boolean detached, @Nonnull Context context) {
|
||||
int flags = 0;
|
||||
if (!(context instanceof Activity)) {
|
||||
flags = flags | Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
}
|
||||
if (detached) {
|
||||
flags = flags | Intent.FLAG_ACTIVITY_NO_HISTORY;
|
||||
}
|
||||
intent.setFlags(flags);
|
||||
}
|
||||
|
||||
public static void enableComponent(@Nonnull Context context,
|
||||
@Nonnull Class<?> componentClass,
|
||||
boolean enable) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
|
||||
final int componentState;
|
||||
if (enable) {
|
||||
componentState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
|
||||
} else {
|
||||
componentState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
|
||||
}
|
||||
|
||||
pm.setComponentEnabledSetting(new ComponentName(context, componentClass), componentState, PackageManager.DONT_KILL_APP);
|
||||
}
|
||||
|
||||
public static boolean isComponentEnabled(@Nonnull Context context,
|
||||
@Nonnull Class<? extends Context> componentClass) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
|
||||
int componentEnabledSetting = pm.getComponentEnabledSetting(new ComponentName(context, componentClass));
|
||||
return componentEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || componentEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
public static int toPixels(@Nonnull DisplayMetrics dm, float dps) {
|
||||
final float scale = dm.density;
|
||||
return (int) (dps * scale + 0.5f);
|
||||
}
|
||||
}
|
@ -9,22 +9,20 @@ import android.os.Looper;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.GeneratedHandlerFinder;
|
||||
|
||||
import org.solovyev.android.UiThreadExecutor;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import jscl.JsclMathEngine;
|
||||
import org.solovyev.android.calculator.language.Languages;
|
||||
import org.solovyev.android.checkout.Billing;
|
||||
import org.solovyev.android.checkout.Checkout;
|
||||
import org.solovyev.android.checkout.Inventory;
|
||||
import org.solovyev.android.checkout.ProductTypes;
|
||||
import org.solovyev.android.checkout.Products;
|
||||
import org.solovyev.android.checkout.RobotmediaDatabase;
|
||||
import org.solovyev.android.checkout.RobotmediaInventory;
|
||||
import org.solovyev.android.checkout.*;
|
||||
import org.solovyev.android.plotter.Plot;
|
||||
import org.solovyev.android.plotter.Plotter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
@ -32,15 +30,6 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import jscl.JsclMathEngine;
|
||||
|
||||
@Module
|
||||
public class AppModule {
|
||||
|
||||
@ -151,8 +140,17 @@ public class AppModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(THREAD_UI)
|
||||
Executor provideUiThread() {
|
||||
return new UiThreadExecutor();
|
||||
Executor provideUiThread(@NonNull final Handler handler) {
|
||||
return new Executor() {
|
||||
@Override
|
||||
public void execute(@NonNull Runnable command) {
|
||||
if (App.isUiThread()) {
|
||||
command.run();
|
||||
} else {
|
||||
handler.post(command);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -18,10 +18,9 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.solovyev.android.Activities;
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.history.History;
|
||||
import org.solovyev.android.calculator.language.Language;
|
||||
import org.solovyev.android.calculator.language.Languages;
|
||||
@ -31,9 +30,6 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
import static org.solovyev.android.calculator.App.cast;
|
||||
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
@ -101,7 +97,7 @@ public class BaseActivity extends AppCompatActivity {
|
||||
public boolean restartIfLayoutChanged() {
|
||||
final Preferences.Gui.Layout newLayout = Preferences.Gui.layout.getPreference(preferences);
|
||||
if (newLayout != layout) {
|
||||
Activities.restartActivity(this);
|
||||
App.restartActivity(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -112,7 +108,7 @@ public class BaseActivity extends AppCompatActivity {
|
||||
final int themeId = theme.getThemeFor(this);
|
||||
final int newThemeId = newTheme.getThemeFor(this);
|
||||
if (themeId != newThemeId) {
|
||||
Activities.restartActivity(this);
|
||||
App.restartActivity(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -121,7 +117,7 @@ public class BaseActivity extends AppCompatActivity {
|
||||
public boolean restartIfLanguageChanged() {
|
||||
final Language current = languages.getCurrent();
|
||||
if (!current.equals(language)) {
|
||||
Activities.restartActivity(this);
|
||||
App.restartActivity(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -255,11 +251,13 @@ public class BaseActivity extends AppCompatActivity {
|
||||
|
||||
protected void fixFonts(@Nonnull View root) {
|
||||
// some devices ship own fonts which causes issues with rendering. Let's use our own font for all text views
|
||||
Views.processViewsOfType(root, TextView.class, new Views.ViewProcessor<TextView>() {
|
||||
App.processViewsOfType(root, TextView.class, new App.ViewProcessor<TextView>() {
|
||||
@Override
|
||||
public void process(@Nonnull TextView view) {
|
||||
setFont(view, typeface);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -28,27 +28,22 @@ import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.util.TimingLogger;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
|
||||
import jscl.MathEngine;
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ACRAConfiguration;
|
||||
import org.acra.sender.HttpSender;
|
||||
import org.solovyev.android.Android;
|
||||
import org.solovyev.android.calculator.floating.FloatingCalculatorActivity;
|
||||
import org.solovyev.android.calculator.history.History;
|
||||
import org.solovyev.android.calculator.language.Language;
|
||||
import org.solovyev.android.calculator.language.Languages;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import jscl.MathEngine;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class CalculatorApplication extends android.app.Application implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@ -192,7 +187,7 @@ public class CalculatorApplication extends android.app.Application implements Sh
|
||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||
if (Preferences.Onscreen.showAppIcon.getKey().equals(key)) {
|
||||
boolean showAppIcon = Preferences.Onscreen.showAppIcon.getPreference(prefs);
|
||||
Android.enableComponent(this, FloatingCalculatorActivity.class, showAppIcon);
|
||||
App.enableComponent(this, FloatingCalculatorActivity.class, showAppIcon);
|
||||
notifier.showMessage(R.string.cpp_this_change_may_require_reboot, MessageType.info);
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ import org.solovyev.android.calculator.about.ReleaseNotesFragment;
|
||||
import org.solovyev.android.calculator.functions.FunctionsFragment;
|
||||
import org.solovyev.android.calculator.history.RecentHistoryFragment;
|
||||
import org.solovyev.android.calculator.history.SavedHistoryFragment;
|
||||
import org.solovyev.android.calculator.matrix.EditMatrixFragment;
|
||||
import org.solovyev.android.calculator.operators.OperatorsFragment;
|
||||
import org.solovyev.android.calculator.variables.VariablesFragment;
|
||||
|
||||
@ -43,9 +42,6 @@ public enum FragmentTab {
|
||||
functions(FunctionsFragment.class, R.string.c_functions),
|
||||
operators(OperatorsFragment.class, R.string.c_operators),
|
||||
about(AboutFragment.class, R.string.cpp_about),
|
||||
|
||||
// todo serso: strings
|
||||
matrix_edit(EditMatrixFragment.class, R.string.c_release_notes),
|
||||
release_notes(ReleaseNotesFragment.class, R.string.c_release_notes);
|
||||
|
||||
@Nonnull
|
||||
|
@ -26,7 +26,6 @@ import android.app.Application;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.widget.Toast;
|
||||
import org.solovyev.android.Threads;
|
||||
import org.solovyev.common.msg.Message;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -57,7 +56,7 @@ public class Notifier {
|
||||
}
|
||||
|
||||
public void showMessage(@Nonnull final String message) {
|
||||
if (Threads.isUiThread()) {
|
||||
if (App.isUiThread()) {
|
||||
Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.StyleRes;
|
||||
import android.support.v7.view.ContextThemeWrapper;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.calculator.about.AboutActivity;
|
||||
import org.solovyev.android.calculator.functions.FunctionsActivity;
|
||||
@ -46,26 +47,15 @@ import org.solovyev.android.calculator.operators.OperatorsActivity;
|
||||
import org.solovyev.android.calculator.preferences.PreferencesActivity;
|
||||
import org.solovyev.android.calculator.variables.VariablesActivity;
|
||||
import org.solovyev.android.calculator.wizard.WizardActivity;
|
||||
import org.solovyev.android.prefs.BooleanPreference;
|
||||
import org.solovyev.android.prefs.IntegerPreference;
|
||||
import org.solovyev.android.prefs.NumberToStringPreference;
|
||||
import org.solovyev.android.prefs.Preference;
|
||||
import org.solovyev.android.prefs.StringPreference;
|
||||
import org.solovyev.android.prefs.*;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
|
||||
import static org.solovyev.android.Android.isPhoneModel;
|
||||
import static org.solovyev.android.DeviceModel.samsung_galaxy_s;
|
||||
import static org.solovyev.android.DeviceModel.samsung_galaxy_s_2;
|
||||
import static org.solovyev.android.prefs.IntegerPreference.DEF_VALUE;
|
||||
|
||||
public final class Preferences {
|
||||
@ -143,13 +133,6 @@ public final class Preferences {
|
||||
Engine.Preferences.angleUnit.tryPutDefault(preferences, editor);
|
||||
Engine.Preferences.numeralBase.tryPutDefault(preferences, editor);
|
||||
|
||||
if (!Engine.Preferences.multiplicationSign.isSet(preferences)) {
|
||||
if (isPhoneModel(samsung_galaxy_s) || isPhoneModel(samsung_galaxy_s_2)) {
|
||||
// workaround ofr samsung galaxy s phones
|
||||
Engine.Preferences.multiplicationSign.putPreference(editor, "*");
|
||||
}
|
||||
}
|
||||
|
||||
Gui.theme.tryPutDefault(preferences, editor);
|
||||
Gui.layout.tryPutDefault(preferences, editor);
|
||||
Gui.showReleaseNotes.tryPutDefault(preferences, editor);
|
||||
|
@ -25,22 +25,18 @@ package org.solovyev.android.calculator;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
import org.solovyev.android.calculator.errors.FixableError;
|
||||
import org.solovyev.android.calculator.errors.FixableErrorType;
|
||||
import org.solovyev.android.calculator.errors.FixableErrorsActivity;
|
||||
import org.solovyev.android.msg.AndroidMessage;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
public class PreferredPreferences {
|
||||
@ -103,9 +99,7 @@ public class PreferredPreferences {
|
||||
|
||||
public void setAngleUnits(@Nonnull AngleUnit angleUnit) {
|
||||
Engine.Preferences.angleUnit.putPreference(preferences, angleUnit);
|
||||
notifier.showMessage(
|
||||
new AndroidMessage(R.string.c_angle_units_changed_to, MessageType.info, application,
|
||||
angleUnit.name()));
|
||||
notifier.showMessage(R.string.c_angle_units_changed_to, angleUnit.name());
|
||||
}
|
||||
|
||||
public void setPreferredNumeralBase() {
|
||||
@ -114,9 +108,7 @@ public class PreferredPreferences {
|
||||
|
||||
public void setNumeralBase(@Nonnull NumeralBase numeralBase) {
|
||||
Engine.Preferences.numeralBase.putPreference(preferences, numeralBase);
|
||||
notifier.showMessage(
|
||||
new AndroidMessage(R.string.c_numeral_base_changed_to, MessageType.info,
|
||||
application, numeralBase.name()));
|
||||
notifier.showMessage(R.string.c_numeral_base_changed_to, numeralBase.name());
|
||||
}
|
||||
|
||||
public boolean isShowWarningDialog() {
|
||||
|
@ -9,8 +9,6 @@ import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import org.solovyev.android.Android;
|
||||
import org.solovyev.android.calculator.wizard.CalculatorWizards;
|
||||
import org.solovyev.android.wizard.Wizard;
|
||||
import org.solovyev.android.wizard.Wizards;
|
||||
@ -20,9 +18,7 @@ import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.solovyev.android.calculator.release.ReleaseNotes.hasReleaseNotes;
|
||||
import static org.solovyev.android.wizard.WizardUi.continueWizard;
|
||||
import static org.solovyev.android.wizard.WizardUi.createLaunchIntent;
|
||||
import static org.solovyev.android.wizard.WizardUi.startWizard;
|
||||
import static org.solovyev.android.wizard.WizardUi.*;
|
||||
|
||||
@Singleton
|
||||
public class StartupHelper {
|
||||
@ -45,12 +41,12 @@ public class StartupHelper {
|
||||
if (!App.isMonkeyRunner(activity)) {
|
||||
handleOnMainActivityOpened(activity, editor, opened == null ? 0 : opened);
|
||||
}
|
||||
UiPreferences.appVersion.putPreference(editor, Android.getAppVersionCode(activity));
|
||||
UiPreferences.appVersion.putPreference(editor, App.getAppVersionCode(activity));
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private void handleOnMainActivityOpened(@NonNull final AppCompatActivity activity, @NonNull SharedPreferences.Editor editor, int opened) {
|
||||
final int currentVersion = Android.getAppVersionCode(activity);
|
||||
final int currentVersion = App.getAppVersionCode(activity);
|
||||
final Wizards wizards = App.getWizards();
|
||||
final Wizard wizard = wizards.getWizard(CalculatorWizards.FIRST_TIME_WIZARD);
|
||||
if (wizard.isStarted() && !wizard.isFinished()) {
|
||||
|
@ -22,24 +22,22 @@
|
||||
|
||||
package org.solovyev.android.calculator.errors;
|
||||
|
||||
import static org.solovyev.android.calculator.App.cast;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import org.solovyev.android.Activities;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.PreferredPreferences;
|
||||
import org.solovyev.common.msg.Message;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import static org.solovyev.android.calculator.App.cast;
|
||||
|
||||
public class FixableErrorsActivity extends AppCompatActivity {
|
||||
|
||||
@ -62,7 +60,7 @@ public class FixableErrorsActivity extends AppCompatActivity {
|
||||
public static void show(@Nonnull Context context, @Nonnull ArrayList<FixableError> errors) {
|
||||
final Intent intent = new Intent(context, FixableErrorsActivity.class);
|
||||
intent.putExtra(EXTRA_ERRORS, errors);
|
||||
Activities.addIntentFlags(intent, false, context);
|
||||
App.addIntentFlags(intent, false, context);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.Display;
|
||||
import org.solovyev.android.calculator.Editor;
|
||||
@ -99,7 +98,7 @@ public class FloatingCalculatorService extends Service implements FloatingViewLi
|
||||
|
||||
//noinspection deprecation
|
||||
final int maxWidth = 2 * Math.min(dd.getWidth(), dd.getHeight()) / 3;
|
||||
final int desiredWidth = Views.toPixels(dm, 300);
|
||||
final int desiredWidth = App.toPixels(dm, 300);
|
||||
|
||||
final int width = Math.min(maxWidth, desiredWidth);
|
||||
final int height = getHeight(width);
|
||||
|
@ -9,7 +9,6 @@ import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import jscl.math.function.Function;
|
||||
import org.solovyev.android.Activities;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.Engine;
|
||||
@ -32,7 +31,7 @@ public class EditFunctionFragment extends BaseFunctionFragment {
|
||||
public static void show(@Nullable CppFunction function, @Nonnull Context context) {
|
||||
if (!(context instanceof FunctionsActivity)) {
|
||||
final Intent intent = new Intent(context, FunctionsActivity.getClass(context));
|
||||
Activities.addIntentFlags(intent, false, context);
|
||||
App.addIntentFlags(intent, false, context);
|
||||
intent.putExtra(FunctionsActivity.EXTRA_FUNCTION, function);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
|
@ -12,16 +12,7 @@ import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.ActivityLauncher;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.BaseActivity;
|
||||
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.*;
|
||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
||||
import org.solovyev.android.calculator.view.ScreenMetrics;
|
||||
import org.solovyev.android.views.Adjuster;
|
||||
@ -30,15 +21,12 @@ import org.solovyev.android.views.dragbutton.DragButton;
|
||||
import org.solovyev.android.views.dragbutton.DragDirection;
|
||||
import org.solovyev.android.views.dragbutton.SimpleDragListener;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.inject.Inject;
|
||||
|
||||
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 android.view.HapticFeedbackConstants.*;
|
||||
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;
|
||||
@ -93,7 +81,7 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer
|
||||
cast(activity.getApplication()).getComponent().inject(this);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
orientation = Views.getScreenOrientation(activity);
|
||||
orientation = App.getScreenOrientation(activity);
|
||||
layout = Preferences.Gui.layout.getPreferenceNoError(preferences);
|
||||
textSize = calculateTextSize();
|
||||
}
|
||||
|
@ -1,44 +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.matrix;
|
||||
|
||||
import org.solovyev.android.calculator.BaseActivity;
|
||||
import org.solovyev.android.calculator.FragmentTab;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.view.Tabs;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CalculatorMatrixActivity extends BaseActivity {
|
||||
|
||||
public CalculatorMatrixActivity() {
|
||||
super(R.string.c_plot_graph);
|
||||
// FIXME: 2016-03-01 string
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateTabs(@Nonnull Tabs tabs) {
|
||||
super.populateTabs(tabs);
|
||||
tabs.addTab(FragmentTab.matrix_edit);
|
||||
}
|
||||
}
|
@ -1,111 +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.matrix;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import org.solovyev.android.calculator.BaseFragment;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.view.IntegerRange;
|
||||
import org.solovyev.android.view.Picker;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class EditMatrixFragment extends BaseFragment implements Picker.OnChangedListener<Integer> {
|
||||
private static final int MAX_COUNT = 10;
|
||||
private static final int MIN_COUNT = 2;
|
||||
private static final int DEFAULT_ROWS = 2;
|
||||
private static final int DEFAULT_COLS = 2;
|
||||
|
||||
private static final String MATRIX = "matrix";
|
||||
|
||||
public EditMatrixFragment() {
|
||||
super(R.layout.matrix_edit_fragment);
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, @Nullable Bundle in) {
|
||||
super.onViewCreated(root, in);
|
||||
|
||||
final Picker<Integer> matrixRowsCountPicker = (Picker<Integer>) root.findViewById(R.id.matrix_rows_count_picker);
|
||||
initPicker(matrixRowsCountPicker);
|
||||
final Picker<Integer> matrixColsCountPicker = (Picker<Integer>) root.findViewById(R.id.matrix_cols_count_picker);
|
||||
initPicker(matrixColsCountPicker);
|
||||
|
||||
MatrixUi matrix = null;
|
||||
if (in != null) {
|
||||
final Object matrixObject = in.getSerializable(MATRIX);
|
||||
if (matrixObject instanceof MatrixUi) {
|
||||
matrix = (MatrixUi) matrixObject;
|
||||
}
|
||||
}
|
||||
|
||||
final MatrixView matrixView = getMatrixView(root);
|
||||
if (matrix == null) {
|
||||
matrixView.setMatrixDimensions(DEFAULT_ROWS, DEFAULT_COLS);
|
||||
} else {
|
||||
matrixView.setMatrix(matrix.getBakingArray());
|
||||
}
|
||||
matrixRowsCountPicker.setCurrent(matrixView.getRows());
|
||||
matrixColsCountPicker.setCurrent(matrixView.getCols());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@Nonnull Bundle out) {
|
||||
super.onSaveInstanceState(out);
|
||||
|
||||
out.putSerializable(MATRIX, new MatrixUi(getMatrixView(getView()).toMatrix()));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private MatrixView getMatrixView(@Nonnull View root) {
|
||||
return (MatrixView) root.findViewById(R.id.matrix_layout);
|
||||
}
|
||||
|
||||
private void initPicker(@Nonnull Picker<Integer> picker) {
|
||||
picker.setRange(new IntegerRange(MIN_COUNT, MAX_COUNT, 1, 0, null));
|
||||
picker.setOnChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(@Nonnull Picker picker, @Nonnull Integer value) {
|
||||
switch (picker.getId()) {
|
||||
case R.id.matrix_rows_count_picker:
|
||||
onRowsCountChange(value);
|
||||
break;
|
||||
case R.id.matrix_cols_count_picker:
|
||||
onColsCountChange(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void onColsCountChange(@Nonnull Integer newCols) {
|
||||
getMatrixView(getView()).setMatrixCols(newCols);
|
||||
}
|
||||
|
||||
private void onRowsCountChange(@Nonnull Integer newRows) {
|
||||
getMatrixView(getView()).setMatrixRows(newRows);
|
||||
}
|
||||
}
|
@ -1,128 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/18/13
|
||||
* Time: 9:03 PM
|
||||
*/
|
||||
public abstract class AbstractGraphCalculator implements GraphCalculator {
|
||||
|
||||
@Nonnull
|
||||
protected final GraphData next = GraphData.newEmptyInstance();
|
||||
|
||||
@Nonnull
|
||||
private final GraphData endGraph = GraphData.newEmptyInstance();
|
||||
|
||||
@Nonnull
|
||||
private final GraphData startGraph = GraphData.newEmptyInstance();
|
||||
|
||||
@Override
|
||||
public final void computeGraph(@Nonnull XyFunction f,
|
||||
float xMin,
|
||||
float xMax,
|
||||
@Nonnull GraphData graph,
|
||||
@Nonnull GraphsData graphsData,
|
||||
@Nonnull Graph2dDimensions dimensions) {
|
||||
if (f.getArity() == 0) {
|
||||
final float v = (float) f.eval();
|
||||
graph.clear();
|
||||
graph.push(xMin, v);
|
||||
graph.push(xMax, v);
|
||||
return;
|
||||
}
|
||||
|
||||
float yMin = graphsData.getLastYMin();
|
||||
float yMax = graphsData.getLastYMax();
|
||||
|
||||
// prepare graph
|
||||
if (!graph.empty()) {
|
||||
if (xMin >= graphsData.getLastXMin()) {
|
||||
// |------[---erased---|------data----|---erased--]------ old data
|
||||
// |-------------------[------data----]------------------ new data
|
||||
// xMin xMax
|
||||
//
|
||||
// OR
|
||||
//
|
||||
// |------[---erased---|------data----]----------- old data
|
||||
// |-------------------[------data----<---->]----- new data
|
||||
// xMin xMax
|
||||
graph.eraseBefore(xMin);
|
||||
if (xMax <= graphsData.getLastXMax()) {
|
||||
graph.eraseAfter(xMax);
|
||||
// nothing to compute
|
||||
} else {
|
||||
xMin = graph.getLastX();
|
||||
compute(f, xMin, xMax, yMin, yMax, endGraph, dimensions);
|
||||
}
|
||||
} else {
|
||||
// |--------------------[-----data----|---erased----]-- old data
|
||||
// |------[<------------>-----data----]---------------- new data
|
||||
// xMin xMax
|
||||
//
|
||||
// OR
|
||||
//
|
||||
// |--------------------[------data--]----|----------- old data
|
||||
// |-------[<----------->------data--<--->]-----------new data
|
||||
// xMin xMax
|
||||
|
||||
if (xMax <= graphsData.getLastXMax()) {
|
||||
graph.eraseAfter(xMax);
|
||||
xMax = graph.getFirstX();
|
||||
compute(f, xMin, xMax, yMin, yMax, startGraph, dimensions);
|
||||
} else {
|
||||
compute(f, xMin, graph.getFirstX(), yMin, yMax, startGraph, dimensions);
|
||||
compute(f, graph.getLastX(), xMax, yMin, yMax, endGraph, dimensions);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
compute(f, xMin, xMax, yMin, yMax, graph, dimensions);
|
||||
}
|
||||
|
||||
if (!endGraph.empty()) {
|
||||
// first add ending because it's fast
|
||||
graph.append(endGraph);
|
||||
}
|
||||
|
||||
if (!startGraph.empty()) {
|
||||
startGraph.append(graph);
|
||||
graph.swap(startGraph);
|
||||
}
|
||||
|
||||
|
||||
next.clear();
|
||||
endGraph.clear();
|
||||
startGraph.clear();
|
||||
}
|
||||
|
||||
protected abstract void compute(@Nonnull XyFunction f,
|
||||
float xMin,
|
||||
float xMax,
|
||||
float yMin,
|
||||
float yMax,
|
||||
@Nonnull GraphData graph,
|
||||
@Nonnull Graph2dDimensions dimensions);
|
||||
}
|
@ -1,202 +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.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.solovyev.android.calculator.Preferences;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/12/13
|
||||
* Time: 11:03 PM
|
||||
*/
|
||||
public class AndroidCalculatorPlotter implements CalculatorPlotter, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@Nonnull
|
||||
private final CalculatorPlotter plotter;
|
||||
|
||||
public AndroidCalculatorPlotter(@Nonnull Context context,
|
||||
@Nonnull CalculatorPlotter plotter) {
|
||||
this.plotter = plotter;
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
onSharedPreferenceChanged(preferences, Preferences.Graph.plotImag.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public PlotData getPlotData() {
|
||||
return plotter.getPlotData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFunction(@Nonnull Generic expression) {
|
||||
return plotter.addFunction(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFunction(@Nonnull PlotFunction plotFunction) {
|
||||
return plotter.addFunction(plotFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFunction(@Nonnull XyFunction xyFunction) {
|
||||
return plotter.addFunction(xyFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) {
|
||||
return plotter.addFunction(xyFunction, functionLineDef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateFunction(@Nonnull PlotFunction newFunction) {
|
||||
return plotter.updateFunction(newFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef) {
|
||||
return plotter.updateFunction(xyFunction, functionLineDef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFunction(@Nonnull PlotFunction plotFunction) {
|
||||
return plotter.removeFunction(plotFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFunction(@Nonnull XyFunction xyFunction) {
|
||||
return plotter.removeFunction(xyFunction);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PlotFunction pin(@Nonnull PlotFunction plotFunction) {
|
||||
return plotter.pin(plotFunction);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PlotFunction unpin(@Nonnull PlotFunction plotFunction) {
|
||||
return plotter.unpin(plotFunction);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PlotFunction show(@Nonnull PlotFunction plotFunction) {
|
||||
return plotter.show(plotFunction);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PlotFunction hide(@Nonnull PlotFunction plotFunction) {
|
||||
return plotter.hide(plotFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAllFunctions() {
|
||||
plotter.clearAllFunctions();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PlotFunction getFunctionById(@Nonnull String functionId) {
|
||||
return plotter.getFunctionById(functionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public List<PlotFunction> getFunctions() {
|
||||
return plotter.getFunctions();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public List<PlotFunction> getVisibleFunctions() {
|
||||
return plotter.getVisibleFunctions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void plot() {
|
||||
plotter.plot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void plot(@Nonnull Generic expression) {
|
||||
plotter.plot(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is2dPlotPossible() {
|
||||
return plotter.is2dPlotPossible();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlotPossibleFor(@Nonnull Generic expression) {
|
||||
return plotter.isPlotPossibleFor(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlot3d(boolean plot3d) {
|
||||
plotter.setPlot3d(plot3d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllUnpinned() {
|
||||
plotter.removeAllUnpinned();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlotImag(boolean plotImag) {
|
||||
plotter.setPlotImag(plotImag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) {
|
||||
plotter.savePlotBoundaries(plotBoundaries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries) {
|
||||
plotter.setPlotBoundaries(plotBoundaries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (Preferences.Graph.plotImag.getKey().equals(key)) {
|
||||
setPlotImag(Preferences.Graph.plotImag.getPreference(preferences));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,86 +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.graphics.DashPathEffect;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/5/13
|
||||
* Time: 7:37 PM
|
||||
*/
|
||||
public enum AndroidPlotLineStyle {
|
||||
|
||||
solid(PlotLineStyle.solid) {
|
||||
@Override
|
||||
public void applyToPaint(@Nonnull Paint paint) {
|
||||
paint.setPathEffect(null);
|
||||
}
|
||||
},
|
||||
|
||||
dashed(PlotLineStyle.dashed) {
|
||||
@Override
|
||||
public void applyToPaint(@Nonnull Paint paint) {
|
||||
paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0));
|
||||
}
|
||||
},
|
||||
|
||||
dotted(PlotLineStyle.dotted) {
|
||||
@Override
|
||||
public void applyToPaint(@Nonnull Paint paint) {
|
||||
paint.setPathEffect(new DashPathEffect(new float[]{5, 1}, 0));
|
||||
}
|
||||
},
|
||||
|
||||
dash_dotted(PlotLineStyle.dash_dotted) {
|
||||
@Override
|
||||
public void applyToPaint(@Nonnull Paint paint) {
|
||||
paint.setPathEffect(new DashPathEffect(new float[]{10, 20, 5, 1}, 0));
|
||||
}
|
||||
};
|
||||
|
||||
@Nonnull
|
||||
private final PlotLineStyle plotLineStyle;
|
||||
|
||||
AndroidPlotLineStyle(@Nonnull PlotLineStyle plotLineStyle) {
|
||||
this.plotLineStyle = plotLineStyle;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AndroidPlotLineStyle valueOf(@Nonnull PlotLineStyle plotLineStyle) {
|
||||
for (AndroidPlotLineStyle androidPlotLineStyle : values()) {
|
||||
if (androidPlotLineStyle.plotLineStyle == plotLineStyle) {
|
||||
return androidPlotLineStyle;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void applyToPaint(@Nonnull Paint paint);
|
||||
|
||||
}
|
@ -1,423 +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.graphics.Color;
|
||||
import android.opengl.Matrix;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ZoomButtonsController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
|
||||
public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final float DISTANCE = 15f;
|
||||
private boolean useHighQuality3d = Build.VERSION.SDK_INT >= 5;
|
||||
private float lastTouchX, lastTouchY;
|
||||
private TouchHandler touchHandler;
|
||||
private ZoomButtonsController zoomController = new ZoomButtonsController(this);
|
||||
private float zoomLevel = 1;
|
||||
private float zoomTarget;
|
||||
private float zoomStep = 0;
|
||||
private float currentZoom;
|
||||
@Nonnull
|
||||
private List<Graph3d> graphs = new ArrayList<Graph3d>();
|
||||
@Nonnull
|
||||
private GraphViewHelper graphViewHelper = GraphViewHelper.newDefaultInstance();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
@Nonnull
|
||||
private Graph2dDimensions dimensions = new Graph2dDimensions(this);
|
||||
private float[] matrix1 = new float[16], matrix2 = new float[16], matrix3 = new float[16];
|
||||
private float angleX, angleY;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
private boolean dirty;
|
||||
|
||||
public CalculatorGraph3dView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public CalculatorGraph3dView(Context context) {
|
||||
super(context);
|
||||
touchHandler = new TouchHandler(this);
|
||||
init();
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
private void init() {
|
||||
startLooping();
|
||||
zoomController.setOnZoomListener(this);
|
||||
|
||||
Matrix.setIdentityM(matrix1, 0);
|
||||
Matrix.rotateM(matrix1, 0, -75, 1, 0, 0);
|
||||
}
|
||||
|
||||
protected void onSizeChanged(int w, int h, int ow, int oh) {
|
||||
dimensions.setViewDimensions(w, h);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void glDraw() {
|
||||
|
||||
if (zoomStep < 0 && zoomLevel > zoomTarget) {
|
||||
zoomLevel += zoomStep;
|
||||
} else if (zoomStep > 0 && zoomLevel < zoomTarget) {
|
||||
zoomLevel += zoomStep;
|
||||
} else if (zoomStep != 0) {
|
||||
zoomStep = 0;
|
||||
zoomLevel = zoomTarget;
|
||||
dirty = true;
|
||||
if (!shouldRotate()) {
|
||||
stopLooping();
|
||||
}
|
||||
}
|
||||
|
||||
super.glDraw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
zoomController.setVisible(false);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
void setRotation(float x, float y) {
|
||||
angleX = x;
|
||||
angleY = y;
|
||||
}
|
||||
|
||||
boolean shouldRotate() {
|
||||
final float limit = .5f;
|
||||
return angleX < -limit || angleX > limit || angleY < -limit || angleY > limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@Nonnull PlotViewDef plotViewDef) {
|
||||
this.graphViewHelper = GraphViewHelper.newInstance(plotViewDef, Collections.<PlotFunction>emptyList());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<PlotFunction> getPlotFunctions() {
|
||||
return this.graphViewHelper.getPlotFunctions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlotFunctions(@Nonnull List<PlotFunction> plotFunctions) {
|
||||
for (PlotFunction plotFunction : plotFunctions) {
|
||||
final int arity = plotFunction.getXyFunction().getArity();
|
||||
if (arity != 0 && arity != 1 && arity != 2) {
|
||||
throw new IllegalArgumentException("Function must have arity 0 or 1 or 2 for 3d plot!");
|
||||
}
|
||||
}
|
||||
|
||||
this.graphViewHelper = this.graphViewHelper.copy(plotFunctions);
|
||||
zoomLevel = 1;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXRange(float xMin, float xMax) {
|
||||
dimensions.setXRange(PlotBoundaries.DEFAULT_MIN_NUMBER, PlotBoundaries.DEFAULT_MAX_NUMBER);
|
||||
dimensions.setXY(dimensions.getX0(), 0);
|
||||
|
||||
zoomLevel = 1;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setYRange(float yMin, float yMax) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXMin() {
|
||||
return dimensions.getXMin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXMax() {
|
||||
return dimensions.getXMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYMin() {
|
||||
return dimensions.getYMin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYMax() {
|
||||
return dimensions.getYMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateGraphs() {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdjustYAxis(boolean adjustYAxis) {
|
||||
// not supported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 gl, int width, int height) {
|
||||
gl.glDisable(GL10.GL_DITHER);
|
||||
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
|
||||
|
||||
final int backgroundColor = graphViewHelper.getPlotViewDef().getBackgroundColor();
|
||||
gl.glClearColor(Color.red(backgroundColor) / 255f, Color.green(backgroundColor) / 255f, Color.blue(backgroundColor) / 255f, Color.alpha(backgroundColor) / 255f);
|
||||
|
||||
gl.glShadeModel(useHighQuality3d ? GL10.GL_SMOOTH : GL10.GL_FLAT);
|
||||
gl.glDisable(GL10.GL_LIGHTING);
|
||||
ensureGraphsSize((GL11) gl);
|
||||
dirty = true;
|
||||
angleX = .5f;
|
||||
angleY = 0;
|
||||
|
||||
gl.glViewport(0, 0, width, height);
|
||||
initFrustum(gl, DISTANCE * zoomLevel);
|
||||
currentZoom = zoomLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawFrame(GL10 gl10) {
|
||||
GL11 gl = (GL11) gl10;
|
||||
if (currentZoom != zoomLevel) {
|
||||
initFrustum(gl, DISTANCE * zoomLevel);
|
||||
currentZoom = zoomLevel;
|
||||
}
|
||||
if (dirty) {
|
||||
ensureGraphsSize(gl);
|
||||
|
||||
final Graph2dDimensions dimensionsCopy = dimensions.copy();
|
||||
dimensionsCopy.setGraphDimensions(dimensions.getGWidth() * zoomLevel / 4, dimensions.getGHeight() * zoomLevel / 4);
|
||||
|
||||
for (int i = 0; i < graphViewHelper.getPlotFunctions().size(); i++) {
|
||||
graphs.get(i).update(gl, graphViewHelper.getPlotFunctions().get(i), dimensionsCopy);
|
||||
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
/*if (fps.incFrame()) {
|
||||
Calculator.log("f/s " + fps.getValue());
|
||||
}*/
|
||||
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glLoadIdentity();
|
||||
|
||||
gl.glTranslatef(0, 0, -DISTANCE * zoomLevel);
|
||||
|
||||
Matrix.setIdentityM(matrix2, 0);
|
||||
float ax = Math.abs(angleX);
|
||||
float ay = Math.abs(angleY);
|
||||
if (ay * 3 < ax) {
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
} else if (ax * 3 < ay) {
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
} else {
|
||||
if (ax > ay) {
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
} else {
|
||||
Matrix.rotateM(matrix2, 0, angleY, 1, 0, 0);
|
||||
Matrix.rotateM(matrix2, 0, angleX, 0, 1, 0);
|
||||
}
|
||||
}
|
||||
Matrix.multiplyMM(matrix3, 0, matrix2, 0, matrix1, 0);
|
||||
gl.glMultMatrixf(matrix3, 0);
|
||||
System.arraycopy(matrix3, 0, matrix1, 0, 16);
|
||||
for (Graph3d graph : graphs) {
|
||||
graph.draw(gl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ensureGraphsSize(@Nonnull GL11 gl) {
|
||||
while (graphViewHelper.getPlotFunctions().size() > graphs.size()) {
|
||||
graphs.add(new Graph3d(gl, useHighQuality3d));
|
||||
}
|
||||
}
|
||||
|
||||
private void initFrustum(GL10 gl, float distance) {
|
||||
gl.glMatrixMode(GL10.GL_PROJECTION);
|
||||
gl.glLoadIdentity();
|
||||
float near = distance * (1 / 3f);
|
||||
float far = distance * 3f;
|
||||
float dimen = near / 5f;
|
||||
float h = dimen * height / width;
|
||||
gl.glFrustumf(-dimen, dimen, -h, h, near, far);
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW);
|
||||
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
|
||||
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
private void printMatrix(float[] m, String name) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
b.append(m[i]).append(' ');
|
||||
}
|
||||
//Calculator.log(name + ' ' + b.toString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* ZOOM
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public void onVisibilityChanged(boolean visible) {
|
||||
}
|
||||
|
||||
public void onZoom(boolean zoomIn) {
|
||||
boolean changed = false;
|
||||
if (zoomIn) {
|
||||
if (canZoomIn(zoomLevel)) {
|
||||
zoomTarget = zoomLevel * .625f;
|
||||
zoomStep = -zoomLevel / 40;
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if (canZoomOut(zoomLevel)) {
|
||||
zoomTarget = zoomLevel * 1.6f;
|
||||
zoomStep = zoomLevel / 20;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
zoomController.setZoomInEnabled(canZoomIn(zoomTarget));
|
||||
zoomController.setZoomOutEnabled(canZoomOut(zoomTarget));
|
||||
if (!shouldRotate()) {
|
||||
setRotation(0, 0);
|
||||
}
|
||||
startLooping();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canZoomIn(float zoom) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canZoomOut(float zoom) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* TOUCH
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public void onTouchDown(float x, float y) {
|
||||
zoomController.setVisible(true);
|
||||
stopLooping();
|
||||
lastTouchX = x;
|
||||
lastTouchY = y;
|
||||
}
|
||||
|
||||
public void onTouchMove(float x, float y) {
|
||||
float deltaX = x - lastTouchX;
|
||||
float deltaY = y - lastTouchY;
|
||||
if (deltaX > 1 || deltaX < -1 || deltaY > 1 || deltaY < -1) {
|
||||
setRotation(deltaX, deltaY);
|
||||
glDraw();
|
||||
lastTouchX = x;
|
||||
lastTouchY = y;
|
||||
}
|
||||
}
|
||||
|
||||
public void onTouchUp(float x, float y) {
|
||||
float vx = touchHandler.getXVelocity();
|
||||
float vy = touchHandler.getYVelocity();
|
||||
// Calculator.log("velocity " + vx + ' ' + vy);
|
||||
setRotation(vx / 100, vy / 100);
|
||||
if (shouldRotate()) {
|
||||
startLooping();
|
||||
}
|
||||
}
|
||||
|
||||
public void onTouchZoomDown(float x1, float y1, float x2, float y2) {
|
||||
|
||||
}
|
||||
|
||||
public void onTouchZoomMove(float x1, float y1, float x2, float y2) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return touchHandler != null ? touchHandler.handleTouchEvent(event) : super.onTouchEvent(event);
|
||||
}
|
||||
}
|
@ -1,98 +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 java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Generic;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/12/13
|
||||
* Time: 8:23 PM
|
||||
*/
|
||||
public interface CalculatorPlotter {
|
||||
|
||||
@Nonnull
|
||||
PlotData getPlotData();
|
||||
|
||||
boolean addFunction(@Nonnull Generic expression);
|
||||
|
||||
boolean addFunction(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
boolean addFunction(@Nonnull XyFunction xyFunction);
|
||||
|
||||
boolean addFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
|
||||
|
||||
boolean updateFunction(@Nonnull PlotFunction newFunction);
|
||||
|
||||
boolean updateFunction(@Nonnull XyFunction xyFunction, @Nonnull PlotLineDef functionLineDef);
|
||||
|
||||
boolean removeFunction(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
boolean removeFunction(@Nonnull XyFunction xyFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction pin(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction unpin(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction show(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
@Nonnull
|
||||
PlotFunction hide(@Nonnull PlotFunction plotFunction);
|
||||
|
||||
void clearAllFunctions();
|
||||
|
||||
@Nullable
|
||||
PlotFunction getFunctionById(@Nonnull String functionId);
|
||||
|
||||
@Nonnull
|
||||
List<PlotFunction> getFunctions();
|
||||
|
||||
@Nonnull
|
||||
List<PlotFunction> getVisibleFunctions();
|
||||
|
||||
void plot();
|
||||
|
||||
void plot(@Nonnull Generic expression);
|
||||
|
||||
boolean is2dPlotPossible();
|
||||
|
||||
boolean isPlotPossibleFor(@Nonnull Generic expression);
|
||||
|
||||
void setPlot3d(boolean plot3d);
|
||||
|
||||
void removeAllUnpinned();
|
||||
|
||||
void setPlotImag(boolean plotImag);
|
||||
|
||||
void savePlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
|
||||
|
||||
void setPlotBoundaries(@Nonnull PlotBoundaries plotBoundaries);
|
||||
}
|
@ -1,38 +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;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/18/13
|
||||
* Time: 7:44 PM
|
||||
*/
|
||||
interface FunctionEvaluator {
|
||||
int getArity();
|
||||
|
||||
double eval();
|
||||
|
||||
double eval(double x);
|
||||
|
||||
double eval(double x, double y);
|
||||
}
|
@ -1,418 +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
|
||||
*/
|
||||
|
||||
// This is a OpenGL ES 1.0 dynamic font rendering system. It loads actual font
|
||||
// files, generates a font map (texture) from them, and allows rendering of
|
||||
// text strings.
|
||||
//
|
||||
// NOTE: the rendering portions of this class uses a sprite batcher in order
|
||||
// provide decent speed rendering. Also, rendering assumes a BOTTOM-LEFT
|
||||
// origin, and the (x,y) positions are relative to that, as well as the
|
||||
// bottom-left of the string to render.
|
||||
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.opengl.GLUtils;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
public class GLText {
|
||||
|
||||
//--Constants--//
|
||||
public final static int CHAR_START = 32; // First Character (ASCII Code)
|
||||
public final static int CHAR_END = 126; // Last Character (ASCII Code)
|
||||
public final static int CHAR_CNT = (((CHAR_END - CHAR_START) + 1) + 1); // Character Count (Including Character to use for Unknown)
|
||||
|
||||
public final static int CHAR_NONE = 32; // Character to Use for Unknown (ASCII Code)
|
||||
public final static int CHAR_UNKNOWN = (CHAR_CNT - 1); // Index of the Unknown Character
|
||||
|
||||
public final static int FONT_SIZE_MIN = 6; // Minumum Font Size (Pixels)
|
||||
public final static int FONT_SIZE_MAX = 180; // Maximum Font Size (Pixels)
|
||||
|
||||
public final static int CHAR_BATCH_SIZE = 100; // Number of Characters to Render Per Batch
|
||||
final float[] charWidths; // Width of Each Character (Actual; Pixels)
|
||||
//--Members--//
|
||||
GL10 gl; // GL10 Instance
|
||||
AssetManager assets; // Asset Manager
|
||||
SpriteBatch batch; // Batch Renderer
|
||||
int fontPadX, fontPadY; // Font Padding (Pixels; On Each Side, ie. Doubled on Both X+Y Axis)
|
||||
float fontHeight; // Font Height (Actual; Pixels)
|
||||
float fontAscent; // Font Ascent (Above Baseline; Pixels)
|
||||
float fontDescent; // Font Descent (Below Baseline; Pixels)
|
||||
int textureId; // Font Texture ID [NOTE: Public for Testing Purposes Only!]
|
||||
int textureSize; // Texture Size for Font (Square) [NOTE: Public for Testing Purposes Only!]
|
||||
TextureRegion textureRgn; // Full Texture Region
|
||||
float charWidthMax; // Character Width (Maximum; Pixels)
|
||||
float charHeight; // Character Height (Maximum; Pixels)
|
||||
TextureRegion[] charRgn; // Region of Each Character (Texture Coordinates)
|
||||
int cellWidth, cellHeight; // Character Cell Width/Height
|
||||
int rowCnt, colCnt; // Number of Rows/Columns
|
||||
|
||||
float scaleX, scaleY; // Font Scale (X,Y Axis)
|
||||
float spaceX; // Additional (X,Y Axis) Spacing (Unscaled)
|
||||
|
||||
|
||||
//--Constructor--//
|
||||
// D: save GL instance + asset manager, create arrays, and initialize the members
|
||||
// A: gl - OpenGL ES 10 Instance
|
||||
public GLText(GL10 gl, AssetManager assets) {
|
||||
this.gl = gl; // Save the GL10 Instance
|
||||
this.assets = assets; // Save the Asset Manager Instance
|
||||
|
||||
batch = new SpriteBatch(gl, CHAR_BATCH_SIZE); // Create Sprite Batch (with Defined Size)
|
||||
|
||||
charWidths = new float[CHAR_CNT]; // Create the Array of Character Widths
|
||||
charRgn = new TextureRegion[CHAR_CNT]; // Create the Array of Character Regions
|
||||
|
||||
// initialize remaining members
|
||||
fontPadX = 0;
|
||||
fontPadY = 0;
|
||||
|
||||
fontHeight = 0.0f;
|
||||
fontAscent = 0.0f;
|
||||
fontDescent = 0.0f;
|
||||
|
||||
textureId = -1;
|
||||
textureSize = 0;
|
||||
|
||||
charWidthMax = 0;
|
||||
charHeight = 0;
|
||||
|
||||
cellWidth = 0;
|
||||
cellHeight = 0;
|
||||
rowCnt = 0;
|
||||
colCnt = 0;
|
||||
|
||||
scaleX = 1.0f; // Default Scale = 1 (Unscaled)
|
||||
scaleY = 1.0f; // Default Scale = 1 (Unscaled)
|
||||
spaceX = 0.0f;
|
||||
}
|
||||
|
||||
//--Load Font--//
|
||||
// description
|
||||
// this will load the specified font file, create a texture for the defined
|
||||
// character range, and setup all required values used to render with it.
|
||||
// arguments:
|
||||
// file - Filename of the font (.ttf, .otf) to use. In 'Assets' folder.
|
||||
// size - Requested pixel size of font (height)
|
||||
// padX, padY - Extra padding per character (X+Y Axis); to prevent overlapping characters.
|
||||
public boolean load(String file, int size, int padX, int padY) {
|
||||
|
||||
// setup requested values
|
||||
fontPadX = padX; // Set Requested X Axis Padding
|
||||
fontPadY = padY; // Set Requested Y Axis Padding
|
||||
|
||||
// load the font and setup paint instance for drawing
|
||||
Typeface tf = Typeface.createFromAsset(assets, file); // Create the Typeface from Font File
|
||||
Paint paint = new Paint(); // Create Android Paint Instance
|
||||
paint.setAntiAlias(true); // Enable Anti Alias
|
||||
paint.setTextSize(size); // Set Text Size
|
||||
paint.setColor(0xffffffff); // Set ARGB (White, Opaque)
|
||||
paint.setTypeface(tf); // Set Typeface
|
||||
|
||||
// get font metrics
|
||||
Paint.FontMetrics fm = paint.getFontMetrics(); // Get Font Metrics
|
||||
fontHeight = (float) Math.ceil(Math.abs(fm.bottom) + Math.abs(fm.top)); // Calculate Font Height
|
||||
fontAscent = (float) Math.ceil(Math.abs(fm.ascent)); // Save Font Ascent
|
||||
fontDescent = (float) Math.ceil(Math.abs(fm.descent)); // Save Font Descent
|
||||
|
||||
// determine the width of each character (including unknown character)
|
||||
// also determine the maximum character width
|
||||
char[] s = new char[2]; // Create Character Array
|
||||
charWidthMax = charHeight = 0; // Reset Character Width/Height Maximums
|
||||
float[] w = new float[2]; // Working Width Value
|
||||
int cnt = 0; // Array Counter
|
||||
for (char c = CHAR_START; c <= CHAR_END; c++) { // FOR Each Character
|
||||
s[0] = c; // Set Character
|
||||
paint.getTextWidths(s, 0, 1, w); // Get Character Bounds
|
||||
charWidths[cnt] = w[0]; // Get Width
|
||||
if (charWidths[cnt] > charWidthMax) // IF Width Larger Than Max Width
|
||||
charWidthMax = charWidths[cnt]; // Save New Max Width
|
||||
cnt++; // Advance Array Counter
|
||||
}
|
||||
s[0] = CHAR_NONE; // Set Unknown Character
|
||||
paint.getTextWidths(s, 0, 1, w); // Get Character Bounds
|
||||
charWidths[cnt] = w[0]; // Get Width
|
||||
if (charWidths[cnt] > charWidthMax) // IF Width Larger Than Max Width
|
||||
charWidthMax = charWidths[cnt]; // Save New Max Width
|
||||
cnt++; // Advance Array Counter
|
||||
|
||||
// set character height to font height
|
||||
charHeight = fontHeight; // Set Character Height
|
||||
|
||||
// find the maximum size, validate, and setup cell sizes
|
||||
cellWidth = (int) charWidthMax + (2 * fontPadX); // Set Cell Width
|
||||
cellHeight = (int) charHeight + (2 * fontPadY); // Set Cell Height
|
||||
int maxSize = cellWidth > cellHeight ? cellWidth : cellHeight; // Save Max Size (Width/Height)
|
||||
if (maxSize < FONT_SIZE_MIN || maxSize > FONT_SIZE_MAX) // IF Maximum Size Outside Valid Bounds
|
||||
return false; // Return Error
|
||||
|
||||
// set texture size based on max font size (width or height)
|
||||
// NOTE: these values are fixed, based on the defined characters. when
|
||||
// changing start/end characters (CHAR_START/CHAR_END) this will need adjustment too!
|
||||
if (maxSize <= 24) // IF Max Size is 18 or Less
|
||||
textureSize = 256; // Set 256 Texture Size
|
||||
else if (maxSize <= 40) // ELSE IF Max Size is 40 or Less
|
||||
textureSize = 512; // Set 512 Texture Size
|
||||
else if (maxSize <= 80) // ELSE IF Max Size is 80 or Less
|
||||
textureSize = 1024; // Set 1024 Texture Size
|
||||
else // ELSE IF Max Size is Larger Than 80 (and Less than FONT_SIZE_MAX)
|
||||
textureSize = 2048; // Set 2048 Texture Size
|
||||
|
||||
// create an empty bitmap (alpha only)
|
||||
Bitmap bitmap = Bitmap.createBitmap(textureSize, textureSize, Bitmap.Config.ALPHA_8); // Create Bitmap
|
||||
Canvas canvas = new Canvas(bitmap); // Create Canvas for Rendering to Bitmap
|
||||
bitmap.eraseColor(0x00000000); // Set Transparent Background (ARGB)
|
||||
|
||||
// calculate rows/columns
|
||||
// NOTE: while not required for anything, these may be useful to have :)
|
||||
colCnt = textureSize / cellWidth; // Calculate Number of Columns
|
||||
rowCnt = (int) Math.ceil((float) CHAR_CNT / (float) colCnt); // Calculate Number of Rows
|
||||
|
||||
// render each of the characters to the canvas (ie. build the font map)
|
||||
float x = fontPadX; // Set Start Position (X)
|
||||
float y = (cellHeight - 1) - fontDescent - fontPadY; // Set Start Position (Y)
|
||||
for (char c = CHAR_START; c <= CHAR_END; c++) { // FOR Each Character
|
||||
s[0] = c; // Set Character to Draw
|
||||
canvas.drawText(s, 0, 1, x, y, paint); // Draw Character
|
||||
x += cellWidth; // Move to Next Character
|
||||
if ((x + cellWidth - fontPadX) > textureSize) { // IF End of Line Reached
|
||||
x = fontPadX; // Set X for New Row
|
||||
y += cellHeight; // Move Down a Row
|
||||
}
|
||||
}
|
||||
s[0] = CHAR_NONE; // Set Character to Use for NONE
|
||||
canvas.drawText(s, 0, 1, x, y, paint); // Draw Character
|
||||
|
||||
// generate a new texture
|
||||
int[] textureIds = new int[1]; // Array to Get Texture Id
|
||||
gl.glGenTextures(1, textureIds, 0); // Generate New Texture
|
||||
textureId = textureIds[0]; // Save Texture Id
|
||||
|
||||
// setup filters for texture
|
||||
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); // Bind Texture
|
||||
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); // Set Minification Filter
|
||||
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); // Set Magnification Filter
|
||||
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); // Set U Wrapping
|
||||
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); // Set V Wrapping
|
||||
|
||||
// load the generated bitmap onto the texture
|
||||
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); // Load Bitmap to Texture
|
||||
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); // Unbind Texture
|
||||
|
||||
// release the bitmap
|
||||
bitmap.recycle(); // Release the Bitmap
|
||||
|
||||
// setup the array of character texture regions
|
||||
x = 0; // Initialize X
|
||||
y = 0; // Initialize Y
|
||||
for (int c = 0; c < CHAR_CNT; c++) { // FOR Each Character (On Texture)
|
||||
charRgn[c] = new TextureRegion(textureSize, textureSize, x, y, cellWidth - 1, cellHeight - 1); // Create Region for Character
|
||||
x += cellWidth; // Move to Next Char (Cell)
|
||||
if (x + cellWidth > textureSize) {
|
||||
x = 0; // Reset X Position to Start
|
||||
y += cellHeight; // Move to Next Row (Cell)
|
||||
}
|
||||
}
|
||||
|
||||
// create full texture region
|
||||
textureRgn = new TextureRegion(textureSize, textureSize, 0, 0, textureSize, textureSize); // Create Full Texture Region
|
||||
|
||||
// return success
|
||||
return true; // Return Success
|
||||
}
|
||||
|
||||
//--Begin/End Text Drawing--//
|
||||
// D: call these methods before/after (respectively all draw() calls using a text instance
|
||||
// NOTE: color is set on a per-batch basis, and fonts should be 8-bit alpha only!!!
|
||||
// A: red, green, blue - RGB values for font (default = 1.0)
|
||||
// alpha - optional alpha value for font (default = 1.0)
|
||||
// R: [none]
|
||||
public void begin() {
|
||||
begin(1.0f, 1.0f, 1.0f, 1.0f); // Begin with White Opaque
|
||||
}
|
||||
|
||||
public void begin(float alpha) {
|
||||
begin(1.0f, 1.0f, 1.0f, alpha); // Begin with White (Explicit Alpha)
|
||||
}
|
||||
|
||||
public void begin(float red, float green, float blue, float alpha) {
|
||||
gl.glColor4f(red, green, blue, alpha); // Set Color+Alpha
|
||||
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); // Bind the Texture
|
||||
batch.beginBatch(); // Begin Batch
|
||||
}
|
||||
|
||||
public void end() {
|
||||
batch.endBatch(); // End Batch
|
||||
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Restore Default Color/Alpha
|
||||
}
|
||||
|
||||
//--Draw Text--//
|
||||
// D: draw text at the specified x,y position
|
||||
// A: text - the string to draw
|
||||
// x, y - the x,y position to draw text at (bottom left of text; including descent)
|
||||
// R: [none]
|
||||
public void draw(String text, float x, float y) {
|
||||
float chrHeight = cellHeight * scaleY; // Calculate Scaled Character Height
|
||||
float chrWidth = cellWidth * scaleX; // Calculate Scaled Character Width
|
||||
int len = text.length(); // Get String Length
|
||||
x += (chrWidth / 2.0f) - (fontPadX * scaleX); // Adjust Start X
|
||||
y += (chrHeight / 2.0f) - (fontPadY * scaleY); // Adjust Start Y
|
||||
for (int i = 0; i < len; i++) { // FOR Each Character in String
|
||||
int c = (int) text.charAt(i) - CHAR_START; // Calculate Character Index (Offset by First Char in Font)
|
||||
if (c < 0 || c >= CHAR_CNT) // IF Character Not In Font
|
||||
c = CHAR_UNKNOWN; // Set to Unknown Character Index
|
||||
batch.drawSprite(x, y, chrWidth, chrHeight, charRgn[c]); // Draw the Character
|
||||
x += (charWidths[c] + spaceX) * scaleX; // Advance X Position by Scaled Character Width
|
||||
}
|
||||
}
|
||||
|
||||
//--Draw Text Centered--//
|
||||
// D: draw text CENTERED at the specified x,y position
|
||||
// A: text - the string to draw
|
||||
// x, y - the x,y position to draw text at (bottom left of text)
|
||||
// R: the total width of the text that was drawn
|
||||
public float drawC(String text, float x, float y) {
|
||||
float len = getLength(text); // Get Text Length
|
||||
draw(text, x - (len / 2.0f), y - (getCharHeight() / 2.0f)); // Draw Text Centered
|
||||
return len; // Return Length
|
||||
}
|
||||
|
||||
public float drawCX(String text, float x, float y) {
|
||||
float len = getLength(text); // Get Text Length
|
||||
draw(text, x - (len / 2.0f), y); // Draw Text Centered (X-Axis Only)
|
||||
return len; // Return Length
|
||||
}
|
||||
|
||||
public void drawCY(String text, float x, float y) {
|
||||
draw(text, x, y - (getCharHeight() / 2.0f)); // Draw Text Centered (Y-Axis Only)
|
||||
}
|
||||
|
||||
//--Set Scale--//
|
||||
// D: set the scaling to use for the font
|
||||
// A: scale - uniform scale for both x and y axis scaling
|
||||
// sx, sy - separate x and y axis scaling factors
|
||||
// R: [none]
|
||||
public void setScale(float scale) {
|
||||
scaleX = scaleY = scale; // Set Uniform Scale
|
||||
}
|
||||
|
||||
public void setScale(float sx, float sy) {
|
||||
scaleX = sx; // Set X Scale
|
||||
scaleY = sy; // Set Y Scale
|
||||
}
|
||||
|
||||
//--Get Scale--//
|
||||
// D: get the current scaling used for the font
|
||||
// A: [none]
|
||||
// R: the x/y scale currently used for scale
|
||||
public float getScaleX() {
|
||||
return scaleX; // Return X Scale
|
||||
}
|
||||
|
||||
public float getScaleY() {
|
||||
return scaleY; // Return Y Scale
|
||||
}
|
||||
|
||||
//--Get Space--//
|
||||
// D: get the current spacing used for the font
|
||||
// A: [none]
|
||||
// R: the x/y space currently used for scale
|
||||
public float getSpace() {
|
||||
return spaceX; // Return X Space
|
||||
}
|
||||
|
||||
//--Set Space--//
|
||||
// D: set the spacing (unscaled; ie. pixel size) to use for the font
|
||||
// A: space - space for x axis spacing
|
||||
// R: [none]
|
||||
public void setSpace(float space) {
|
||||
spaceX = space; // Set Space
|
||||
}
|
||||
|
||||
//--Get Length of a String--//
|
||||
// D: return the length of the specified string if rendered using current settings
|
||||
// A: text - the string to get length for
|
||||
// R: the length of the specified string (pixels)
|
||||
public float getLength(String text) {
|
||||
float len = 0.0f; // Working Length
|
||||
int strLen = text.length(); // Get String Length (Characters)
|
||||
for (int i = 0; i < strLen; i++) { // For Each Character in String (Except Last
|
||||
int c = (int) text.charAt(i) - CHAR_START; // Calculate Character Index (Offset by First Char in Font)
|
||||
len += (charWidths[c] * scaleX); // Add Scaled Character Width to Total Length
|
||||
}
|
||||
len += (strLen > 1 ? ((strLen - 1) * spaceX) * scaleX : 0); // Add Space Length
|
||||
return len; // Return Total Length
|
||||
}
|
||||
|
||||
//--Get Width/Height of Character--//
|
||||
// D: return the scaled width/height of a character, or max character width
|
||||
// NOTE: since all characters are the same height, no character index is required!
|
||||
// NOTE: excludes spacing!!
|
||||
// A: chr - the character to get width for
|
||||
// R: the requested character size (scaled)
|
||||
public float getCharWidth(char chr) {
|
||||
int c = chr - CHAR_START; // Calculate Character Index (Offset by First Char in Font)
|
||||
return (charWidths[c] * scaleX); // Return Scaled Character Width
|
||||
}
|
||||
|
||||
public float getCharWidthMax() {
|
||||
return (charWidthMax * scaleX); // Return Scaled Max Character Width
|
||||
}
|
||||
|
||||
public float getCharHeight() {
|
||||
return (charHeight * scaleY); // Return Scaled Character Height
|
||||
}
|
||||
|
||||
//--Get Font Metrics--//
|
||||
// D: return the specified (scaled) font metric
|
||||
// A: [none]
|
||||
// R: the requested font metric (scaled)
|
||||
public float getAscent() {
|
||||
return (fontAscent * scaleY); // Return Font Ascent
|
||||
}
|
||||
|
||||
public float getDescent() {
|
||||
return (fontDescent * scaleY); // Return Font Descent
|
||||
}
|
||||
|
||||
public float getHeight() {
|
||||
return (fontHeight * scaleY); // Return Font Height (Actual)
|
||||
}
|
||||
|
||||
//--Draw Font Texture--//
|
||||
// D: draw the entire font texture (NOTE: for testing purposes only)
|
||||
// A: width, height - the width and height of the area to draw to. this is used
|
||||
// to draw the texture to the top-left corner.
|
||||
public void drawTexture(int width, int height) {
|
||||
batch.beginBatch(textureId); // Begin Batch (Bind Texture)
|
||||
batch.drawSprite(textureSize / 2, height - (textureSize / 2), textureSize, textureSize, textureRgn); // Draw
|
||||
batch.endBatch(); // End Batch
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,242 +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.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGL11;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
import javax.microedition.khronos.egl.EGLSurface;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
|
||||
abstract class GLView extends SurfaceView implements SurfaceHolder.Callback {
|
||||
protected int width, height;
|
||||
private boolean hasSurface;
|
||||
private boolean paused;
|
||||
private EGL10 egl;
|
||||
private EGLDisplay display;
|
||||
private EGLConfig config;
|
||||
private EGLSurface surface;
|
||||
private EGLContext eglContext;
|
||||
private GL11 gl;
|
||||
private volatile boolean looping;
|
||||
@Nonnull
|
||||
private final Handler uiHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case 1:
|
||||
glDraw();
|
||||
break;
|
||||
default:
|
||||
Log.e("GLView", "Incorrect message id: " + msg.what);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public GLView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public GLView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private static Bitmap getRawPixels(GL10 gl, int width, int height) {
|
||||
int size = width * height;
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(size * 4);
|
||||
buf.order(ByteOrder.nativeOrder());
|
||||
gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buf);
|
||||
int data[] = new int[size];
|
||||
buf.asIntBuffer().get(data);
|
||||
buf = null;
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
|
||||
bitmap.setPixels(data, size - width, -width, 0, 0, width, height);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static void bitmapBGRtoRGB(Bitmap bitmap, int width, int height) {
|
||||
int size = width * height;
|
||||
short data[] = new short[size];
|
||||
ShortBuffer buf = ShortBuffer.wrap(data);
|
||||
bitmap.copyPixelsToBuffer(buf);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
//BGR-565 to RGB-565
|
||||
short v = data[i];
|
||||
data[i] = (short) (((v & 0x1f) << 11) | (v & 0x7e0) | ((v & 0xf800) >> 11));
|
||||
}
|
||||
buf.rewind();
|
||||
bitmap.copyPixelsFromBuffer(buf);
|
||||
}
|
||||
|
||||
abstract void onDrawFrame(GL10 gl);
|
||||
|
||||
abstract void onSurfaceCreated(GL10 gl, int width, int height);
|
||||
|
||||
@Nonnull
|
||||
public Bitmap captureScreenshot() {
|
||||
if (gl != null) {
|
||||
final Bitmap result = getRawPixels(gl, width, height);
|
||||
bitmapBGRtoRGB(result, width, height);
|
||||
return result;
|
||||
} else {
|
||||
return Bitmap.createBitmap(width == 0 ? 1 : width, height == 0 ? 1 : height, Bitmap.Config.RGB_565);
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
final SurfaceHolder holder = getHolder();
|
||||
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
|
||||
holder.addCallback(this);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
paused = false;
|
||||
if (hasSurface) {
|
||||
initGL();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
deinitGL();
|
||||
}
|
||||
|
||||
private void initGL() {
|
||||
egl = (EGL10) EGLContext.getEGL();
|
||||
display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
int[] ver = new int[2];
|
||||
egl.eglInitialize(display, ver);
|
||||
|
||||
int[] configSpec = {EGL10.EGL_NONE};
|
||||
EGLConfig[] configOut = new EGLConfig[1];
|
||||
int[] nConfig = new int[1];
|
||||
egl.eglChooseConfig(display, configSpec, configOut, 1, nConfig);
|
||||
config = configOut[0];
|
||||
eglContext = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);
|
||||
surface = egl.eglCreateWindowSurface(display, config, getHolder(), null);
|
||||
egl.eglMakeCurrent(display, surface, surface, eglContext);
|
||||
gl = (GL11) eglContext.getGL();
|
||||
onSurfaceCreated(gl, width, height);
|
||||
requestDraw();
|
||||
}
|
||||
|
||||
private void deinitGL() {
|
||||
paused = true;
|
||||
if (display != null) {
|
||||
egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
|
||||
egl.eglDestroySurface(display, surface);
|
||||
egl.eglDestroyContext(display, eglContext);
|
||||
egl.eglTerminate(display);
|
||||
|
||||
egl = null;
|
||||
config = null;
|
||||
eglContext = null;
|
||||
surface = null;
|
||||
display = null;
|
||||
gl = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void glDraw() {
|
||||
if (hasSurface && !paused) {
|
||||
onDrawFrame(gl);
|
||||
if (!egl.eglSwapBuffers(display, surface)) {
|
||||
paused = true;
|
||||
}
|
||||
if (egl.eglGetError() == EGL11.EGL_CONTEXT_LOST) {
|
||||
paused = true;
|
||||
}
|
||||
if (paused) {
|
||||
reinitGL();
|
||||
}
|
||||
if (looping) {
|
||||
requestDraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
}
|
||||
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
final boolean hadSurface = hasSurface;
|
||||
boolean doInit = !hadSurface && !paused;
|
||||
hasSurface = true;
|
||||
if (doInit) {
|
||||
initGL();
|
||||
} else if (hadSurface) {
|
||||
reinitGL();
|
||||
}
|
||||
}
|
||||
|
||||
private void reinitGL() {
|
||||
deinitGL();
|
||||
paused = false;
|
||||
initGL();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
hasSurface = false;
|
||||
deinitGL();
|
||||
}
|
||||
|
||||
public void startLooping() {
|
||||
if (!looping) {
|
||||
looping = true;
|
||||
glDraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopLooping() {
|
||||
if (looping) {
|
||||
looping = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLooping() {
|
||||
return looping;
|
||||
}
|
||||
|
||||
public void requestDraw() {
|
||||
uiHandler.sendEmptyMessage(1);
|
||||
}
|
||||
}
|
@ -1,265 +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.view.View;
|
||||
|
||||
import org.solovyev.common.math.Point2d;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/18/13
|
||||
* Time: 7:59 PM
|
||||
*/
|
||||
public class Graph2dDimensions {
|
||||
|
||||
// |<--------------gWidth-------------->|
|
||||
// xMin xMax
|
||||
// -------------------|------------------------------------|--------------------
|
||||
// |<-------------vWidthPxs------------>|
|
||||
//
|
||||
/*
|
||||
*
|
||||
*
|
||||
* yMax ------0------------------------------------|--> xPxs
|
||||
* ^ |
|
||||
* | |
|
||||
* v | y
|
||||
* H | ^
|
||||
* e | |
|
||||
* i | |
|
||||
* g | |
|
||||
* h |------------------0-----------------|--> x
|
||||
* t | |
|
||||
* | | |
|
||||
* | | |
|
||||
* v | |
|
||||
* yMin ------- -
|
||||
* | |
|
||||
* v
|
||||
* yPxs
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
@Nonnull
|
||||
private GraphView graphView;
|
||||
|
||||
// view width and height in pixels
|
||||
private int vWidthPxs;
|
||||
private int vHeightPxs;
|
||||
|
||||
// current position of camera in graph coordinates
|
||||
private float x0;
|
||||
private float y0;
|
||||
|
||||
// graph width and height in function units (NOT screen pixels)
|
||||
private float gWidth = 20;
|
||||
private float gHeight = 20;
|
||||
|
||||
public Graph2dDimensions(@Nonnull GraphView graphView) {
|
||||
this.graphView = graphView;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
Point2d toGraphCoordinates(float xPxs, float yPxs) {
|
||||
return new Point2d(scaleXPxs(xPxs) + getXMin(), (getGHeight() - scaleYPxs(yPxs)) + getYMin());
|
||||
}
|
||||
|
||||
private float scaleXPxs(float pxs) {
|
||||
return pxs * getXGraphToViewScale();
|
||||
}
|
||||
|
||||
private float scaleYPxs(float pxs) {
|
||||
return pxs * getYGraphToViewScale();
|
||||
}
|
||||
|
||||
// X
|
||||
|
||||
public float getXMin() {
|
||||
return x0 - gWidth / 2;
|
||||
}
|
||||
|
||||
float getXMax(float minX) {
|
||||
return minX + gWidth;
|
||||
}
|
||||
|
||||
public float getXMax() {
|
||||
return getXMax(getXMin());
|
||||
}
|
||||
|
||||
// Y
|
||||
|
||||
public float getYMin() {
|
||||
return y0 - gHeight / 2;
|
||||
}
|
||||
|
||||
public float getYMax() {
|
||||
return getYMax(getYMin());
|
||||
}
|
||||
|
||||
public float getYMax(float yMin) {
|
||||
return yMin + gHeight;
|
||||
}
|
||||
|
||||
float getXGraphToViewScale() {
|
||||
if (vWidthPxs != 0) {
|
||||
return gWidth / ((float) vWidthPxs);
|
||||
} else {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
float getYGraphToViewScale() {
|
||||
if (vHeightPxs != 0) {
|
||||
return gHeight / ((float) vHeightPxs);
|
||||
} else {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float getViewAspectRatio() {
|
||||
if (vWidthPxs != 0) {
|
||||
return ((float) vHeightPxs) / vWidthPxs;
|
||||
} else {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public int getVWidthPxs() {
|
||||
return vWidthPxs;
|
||||
}
|
||||
|
||||
public int getVHeightPxs() {
|
||||
return vHeightPxs;
|
||||
}
|
||||
|
||||
public float getX0() {
|
||||
return x0;
|
||||
}
|
||||
|
||||
public float getY0() {
|
||||
return y0;
|
||||
}
|
||||
|
||||
public float getGWidth() {
|
||||
return gWidth;
|
||||
}
|
||||
|
||||
float getGHeight() {
|
||||
return gHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* SETTERS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public void setXRange(float xMin, float xMax) {
|
||||
setXRange0(xMin, xMax);
|
||||
|
||||
this.graphView.invalidateGraphs();
|
||||
}
|
||||
|
||||
private void setXRange0(float xMin, float xMax) {
|
||||
this.gWidth = xMax - xMin;
|
||||
this.x0 = xMin + gWidth / 2;
|
||||
}
|
||||
|
||||
public void setYRange(float yMin, float yMax) {
|
||||
setYRange0(yMin, yMax);
|
||||
|
||||
this.graphView.invalidateGraphs();
|
||||
}
|
||||
|
||||
private void setYRange0(float yMin, float yMax) {
|
||||
this.gHeight = yMax - yMin;
|
||||
this.y0 = yMin + gHeight / 2;
|
||||
}
|
||||
|
||||
public void setRanges(float xMin, float xMax, float yMin, float yMax) {
|
||||
setXRange0(xMin, xMax);
|
||||
setYRange0(yMin, yMax);
|
||||
|
||||
this.graphView.invalidateGraphs();
|
||||
}
|
||||
|
||||
public void setViewDimensions(@Nonnull View view) {
|
||||
this.vWidthPxs = view.getWidth();
|
||||
this.vHeightPxs = view.getHeight();
|
||||
|
||||
this.graphView.invalidateGraphs();
|
||||
}
|
||||
|
||||
|
||||
public void setGraphDimensions(float gWidth, float gHeight) {
|
||||
this.gWidth = gWidth;
|
||||
this.gHeight = gHeight;
|
||||
|
||||
this.graphView.invalidateGraphs();
|
||||
}
|
||||
|
||||
public void setViewDimensions(int vWidthPxs, int vHeightPxs) {
|
||||
this.vWidthPxs = vWidthPxs;
|
||||
this.vHeightPxs = vHeightPxs;
|
||||
|
||||
this.graphView.invalidateGraphs();
|
||||
}
|
||||
|
||||
void setXY(float x0, float y0) {
|
||||
this.x0 = x0;
|
||||
this.y0 = y0;
|
||||
}
|
||||
|
||||
public void increaseXY(float dx, float dy) {
|
||||
this.x0 += dx;
|
||||
this.y0 += dy;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Graph2dDimensions copy() {
|
||||
final Graph2dDimensions copy = new Graph2dDimensions(this.graphView);
|
||||
|
||||
copy.vWidthPxs = this.vWidthPxs;
|
||||
copy.vHeightPxs = this.vHeightPxs;
|
||||
copy.x0 = this.x0;
|
||||
copy.y0 = this.y0;
|
||||
copy.gWidth = this.gWidth;
|
||||
copy.gHeight = this.gHeight;
|
||||
|
||||
return copy;
|
||||
}
|
||||
}
|
@ -1,378 +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.graphics.Color;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
|
||||
class Graph3d {
|
||||
|
||||
// vertices count per polygon (triangle = 3)
|
||||
public static final int VERTICES_COUNT = 3;
|
||||
|
||||
// color components count per color
|
||||
public static final int COLOR_COMPONENTS_COUNT = 4;
|
||||
|
||||
// linear polygons count
|
||||
private final int n;
|
||||
|
||||
private final boolean useHighQuality3d;
|
||||
private ShortBuffer verticeIdx;
|
||||
private FloatBuffer vertexBuf;
|
||||
private ByteBuffer colorBuf;
|
||||
private int vertexVbo, colorVbo, vertexElementVbo;
|
||||
private boolean useVBO;
|
||||
private int polygonsⁿ;
|
||||
|
||||
Graph3d(GL11 gl, boolean useHighQuality3d) {
|
||||
this.useHighQuality3d = useHighQuality3d;
|
||||
this.n = useHighQuality3d ? 36 : 24;
|
||||
|
||||
short[] b = new short[n * n];
|
||||
int p = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
short v = 0;
|
||||
for (int j = 0; j < n; v += n + n, j += 2) {
|
||||
b[p++] = (short) (v + i);
|
||||
b[p++] = (short) (v + n + n - 1 - i);
|
||||
}
|
||||
v = (short) (n * (n - 2));
|
||||
i++;
|
||||
for (int j = n - 1; j >= 0; v -= n + n, j -= 2) {
|
||||
b[p++] = (short) (v + n + n - 1 - i);
|
||||
b[p++] = (short) (v + i);
|
||||
}
|
||||
}
|
||||
verticeIdx = buildBuffer(b);
|
||||
|
||||
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
|
||||
useVBO = extensions.indexOf("vertex_buffer_object") != -1;
|
||||
//Calculator.log("VBOs support: " + useVBO + " version " + gl.glGetString(GL10.GL_VERSION));
|
||||
|
||||
if (useVBO) {
|
||||
int[] out = new int[3];
|
||||
gl.glGenBuffers(3, out, 0);
|
||||
vertexVbo = out[0];
|
||||
colorVbo = out[1];
|
||||
vertexElementVbo = out[2];
|
||||
}
|
||||
}
|
||||
|
||||
private static FloatBuffer buildBuffer(float[] b) {
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(b.length << 2);
|
||||
bb.order(ByteOrder.nativeOrder());
|
||||
FloatBuffer sb = bb.asFloatBuffer();
|
||||
sb.put(b);
|
||||
sb.position(0);
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static ShortBuffer buildBuffer(short[] b) {
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(b.length << 1);
|
||||
bb.order(ByteOrder.nativeOrder());
|
||||
ShortBuffer sb = bb.asShortBuffer();
|
||||
sb.put(b);
|
||||
sb.position(0);
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static ByteBuffer buildBuffer(byte[] b) {
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(b.length << 1);
|
||||
bb.order(ByteOrder.nativeOrder());
|
||||
bb.put(b);
|
||||
bb.position(0);
|
||||
return bb;
|
||||
}
|
||||
|
||||
public void update(@Nonnull GL11 gl, @Nonnull PlotFunction fpd, @Nonnull Graph2dDimensions dimensions) {
|
||||
final XyFunction function = fpd.getXyFunction();
|
||||
final PlotLineDef lineDef = fpd.getPlotLineDef();
|
||||
final int NTICK = useHighQuality3d ? 5 : 0;
|
||||
|
||||
//Calculator.log("update VBOs " + vertexVbo + ' ' + colorVbo + ' ' + vertexElementVbo);
|
||||
polygonsⁿ = n * n + 6 + 8 + NTICK * 6;
|
||||
|
||||
// triangle polygon => 3 vertices per polygon
|
||||
final float vertices[] = new float[polygonsⁿ * VERTICES_COUNT];
|
||||
|
||||
float maxAbsZ = fillFunctionPolygonVertices(function, dimensions, vertices);
|
||||
final byte[] colors = prepareFunctionPolygonColors(lineDef, vertices, maxAbsZ);
|
||||
|
||||
|
||||
int base = n * n * 3;
|
||||
int colorBase = n * n * 4;
|
||||
final int baseSize = 2;
|
||||
|
||||
fillBasePolygonVectors(vertices, colors, base, colorBase, baseSize);
|
||||
|
||||
base += 8 * 3;
|
||||
colorBase += 8 * 4;
|
||||
|
||||
fillAxisPolygonVectors(vertices, colors, base, colorBase);
|
||||
|
||||
base += 6 * 3;
|
||||
colorBase += 6 * 4;
|
||||
|
||||
fillAxisGridPolygonVectors(NTICK, vertices, colors, base, colorBase);
|
||||
|
||||
vertexBuf = buildBuffer(vertices);
|
||||
colorBuf = buildBuffer(colors);
|
||||
|
||||
if (useVBO) {
|
||||
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexVbo);
|
||||
gl.glBufferData(GL11.GL_ARRAY_BUFFER, vertexBuf.capacity() * 4, vertexBuf, GL11.GL_STATIC_DRAW);
|
||||
vertexBuf = null;
|
||||
|
||||
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, colorVbo);
|
||||
gl.glBufferData(GL11.GL_ARRAY_BUFFER, colorBuf.capacity(), colorBuf, GL11.GL_STATIC_DRAW);
|
||||
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
|
||||
colorBuf = null;
|
||||
|
||||
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, vertexElementVbo);
|
||||
gl.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, verticeIdx.capacity() * 2, verticeIdx, GL11.GL_STATIC_DRAW);
|
||||
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillAxisGridPolygonVectors(int NTICK, float[] vertices, byte[] colors, int base, int colorBase) {
|
||||
int p = base;
|
||||
final float tick = .03f;
|
||||
final float offset = .01f;
|
||||
for (int i = 1; i <= NTICK; ++i) {
|
||||
vertices[p] = i - tick;
|
||||
vertices[p + 1] = -offset;
|
||||
vertices[p + 2] = -offset;
|
||||
|
||||
vertices[p + 3] = i + tick;
|
||||
vertices[p + 4] = offset;
|
||||
vertices[p + 5] = offset;
|
||||
p += 6;
|
||||
|
||||
vertices[p] = -offset;
|
||||
vertices[p + 1] = i - tick;
|
||||
vertices[p + 2] = -offset;
|
||||
|
||||
vertices[p + 3] = offset;
|
||||
vertices[p + 4] = i + tick;
|
||||
vertices[p + 5] = offset;
|
||||
p += 6;
|
||||
|
||||
vertices[p] = -offset;
|
||||
vertices[p + 1] = -offset;
|
||||
vertices[p + 2] = i - tick;
|
||||
|
||||
vertices[p + 3] = offset;
|
||||
vertices[p + 4] = offset;
|
||||
vertices[p + 5] = i + tick;
|
||||
p += 6;
|
||||
|
||||
}
|
||||
for (int i = colorBase + NTICK * 6 * 4 - 1; i >= colorBase; --i) {
|
||||
colors[i] = (byte) 255;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillAxisPolygonVectors(float[] vertices, byte[] colors, int base, int colorBase) {
|
||||
final float unit = 2;
|
||||
final float axis[] = {
|
||||
0, 0, 0,
|
||||
unit, 0, 0,
|
||||
0, 0, 0,
|
||||
0, unit, 0,
|
||||
0, 0, 0,
|
||||
0, 0, unit,
|
||||
};
|
||||
System.arraycopy(axis, 0, vertices, base, 6 * 3);
|
||||
for (int i = colorBase; i < colorBase + 6 * 4; i += 4) {
|
||||
colors[i] = (byte) 255;
|
||||
colors[i + 1] = (byte) 255;
|
||||
colors[i + 2] = (byte) 255;
|
||||
colors[i + 3] = (byte) 255;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillBasePolygonVectors(float[] vertices, byte[] colors, int base, int colorBase, int baseSize) {
|
||||
int p = base;
|
||||
for (int i = -baseSize; i <= baseSize; i += 2 * baseSize) {
|
||||
vertices[p] = i;
|
||||
vertices[p + 1] = -baseSize;
|
||||
vertices[p + 2] = 0;
|
||||
p += 3;
|
||||
vertices[p] = i;
|
||||
vertices[p + 1] = baseSize;
|
||||
vertices[p + 2] = 0;
|
||||
p += 3;
|
||||
vertices[p] = -baseSize;
|
||||
vertices[p + 1] = i;
|
||||
vertices[p + 2] = 0;
|
||||
p += 3;
|
||||
vertices[p] = baseSize;
|
||||
vertices[p + 1] = i;
|
||||
vertices[p + 2] = 0;
|
||||
p += 3;
|
||||
}
|
||||
|
||||
for (int i = colorBase; i < colorBase + 8 * 4; i += 4) {
|
||||
colors[i] = (byte) 255;
|
||||
colors[i + 1] = (byte) 255;
|
||||
colors[i + 2] = (byte) 255;
|
||||
colors[i + 3] = (byte) 255;
|
||||
}
|
||||
}
|
||||
|
||||
private float fillFunctionPolygonVertices(XyFunction function, @Nonnull Graph2dDimensions dimensions, float[] vertices) {
|
||||
final int arity = function.getArity();
|
||||
|
||||
final float xMin = dimensions.getXMin();
|
||||
final float xMax = dimensions.getXMax();
|
||||
|
||||
final float yMin = dimensions.getXMin();
|
||||
final float yMax = dimensions.getXMax();
|
||||
|
||||
float Δx = (xMax - xMin) / (n - 1);
|
||||
float Δy = (yMax - yMin) / (n - 1);
|
||||
|
||||
float y = yMin;
|
||||
float x = xMin - Δx;
|
||||
|
||||
float maxAbsZ = 0;
|
||||
|
||||
float z = 0;
|
||||
if (arity == 0) {
|
||||
z = (float) function.eval();
|
||||
}
|
||||
|
||||
int k = 0;
|
||||
for (int i = 0; i < n; i++, y += Δy) {
|
||||
float xinc = (i & 1) == 0 ? Δx : -Δx;
|
||||
|
||||
x += xinc;
|
||||
|
||||
if (arity == 1) {
|
||||
z = (float) function.eval(y);
|
||||
}
|
||||
|
||||
for (int j = 0; j < n; j++, x += xinc, k += VERTICES_COUNT) {
|
||||
|
||||
if (arity == 2) {
|
||||
z = (float) function.eval(y, x);
|
||||
}
|
||||
|
||||
vertices[k] = x;
|
||||
vertices[k + 1] = y;
|
||||
vertices[k + 2] = z;
|
||||
|
||||
if (!Float.isNaN(z)) {
|
||||
final float absZ = Math.abs(z);
|
||||
if (absZ > maxAbsZ) {
|
||||
maxAbsZ = absZ;
|
||||
}
|
||||
} else {
|
||||
vertices[k + 2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxAbsZ;
|
||||
}
|
||||
|
||||
private byte[] prepareFunctionPolygonColors(PlotLineDef lineDef, float[] vertices, float maxAbsZ) {
|
||||
// 4 color components per polygon (color[i] = red, color[i+1] = green, color[i+2] = blue, color[i+3] = alpha )
|
||||
final byte colors[] = new byte[polygonsⁿ * COLOR_COMPONENTS_COUNT];
|
||||
|
||||
final int lineColor = lineDef.getLineColor();
|
||||
final int colorComponentsCount = n * n * COLOR_COMPONENTS_COUNT;
|
||||
for (int i = 0, j = VERTICES_COUNT - 1; i < colorComponentsCount; i += COLOR_COMPONENTS_COUNT, j += VERTICES_COUNT) {
|
||||
final float z = vertices[j];
|
||||
|
||||
if (!Float.isNaN(z)) {
|
||||
if (lineDef.getLineColorType() == PlotLineColorType.color_map) {
|
||||
final float color = z / maxAbsZ;
|
||||
final float abs = Math.abs(color);
|
||||
colors[i] = floatToByte(color);
|
||||
colors[i + 1] = floatToByte(1 - abs * .3f);
|
||||
colors[i + 2] = floatToByte(-color);
|
||||
} else {
|
||||
colors[i] = (byte) Color.red(lineColor);
|
||||
colors[i + 1] = (byte) Color.green(lineColor);
|
||||
colors[i + 2] = (byte) Color.blue(lineColor);
|
||||
}
|
||||
colors[i + 3] = (byte) 255;
|
||||
} else {
|
||||
colors[i] = 0;
|
||||
colors[i + 1] = 0;
|
||||
colors[i + 2] = 0;
|
||||
colors[i + 3] = 0;
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
private byte floatToByte(float v) {
|
||||
if (v <= 0) {
|
||||
return (byte) 0;
|
||||
} else {
|
||||
if (v >= 1) {
|
||||
return (byte) 255;
|
||||
} else {
|
||||
return (byte) (v * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(GL11 gl) {
|
||||
if (useVBO) {
|
||||
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexVbo);
|
||||
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
|
||||
|
||||
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, colorVbo);
|
||||
gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, 0);
|
||||
|
||||
gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
|
||||
// gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, N*N);
|
||||
|
||||
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, vertexElementVbo);
|
||||
gl.glDrawElements(GL10.GL_LINE_STRIP, n * n, GL10.GL_UNSIGNED_SHORT, 0);
|
||||
gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
} else {
|
||||
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuf);
|
||||
gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, colorBuf);
|
||||
gl.glDrawElements(GL10.GL_LINE_STRIP, n * n, GL10.GL_UNSIGNED_SHORT, verticeIdx);
|
||||
}
|
||||
final int N2 = n * n;
|
||||
gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, N2);
|
||||
gl.glDrawArrays(GL10.GL_LINES, N2, polygonsⁿ - N2);
|
||||
}
|
||||
|
||||
public boolean isUseHighQuality3d() {
|
||||
return useHighQuality3d;
|
||||
}
|
||||
}
|
@ -1,40 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/18/13
|
||||
* Time: 8:58 PM
|
||||
*/
|
||||
public interface GraphCalculator {
|
||||
|
||||
void computeGraph(@Nonnull XyFunction f,
|
||||
float xMin,
|
||||
float xMax,
|
||||
@Nonnull GraphData graph,
|
||||
@Nonnull GraphsData graphsData,
|
||||
@Nonnull Graph2dDimensions dimensions);
|
||||
}
|
@ -1,123 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/18/13
|
||||
* Time: 8:58 PM
|
||||
*/
|
||||
public class GraphCalculatorImpl extends AbstractGraphCalculator {
|
||||
|
||||
@Override
|
||||
protected void compute(@Nonnull XyFunction f,
|
||||
float xMin,
|
||||
float xMax,
|
||||
float yMin,
|
||||
float yMax,
|
||||
@Nonnull GraphData graph,
|
||||
@Nonnull Graph2dDimensions dimensions) {
|
||||
graph.push(xMin, (float) f.eval(xMin));
|
||||
|
||||
final float xScale = dimensions.getXGraphToViewScale();
|
||||
final float yScale = dimensions.getYGraphToViewScale();
|
||||
final float maxStep = 15.8976f * xScale;
|
||||
final float minStep = .05f * xScale;
|
||||
|
||||
float yTheta = yScale;
|
||||
yTheta = yTheta * yTheta;
|
||||
|
||||
|
||||
float leftX;
|
||||
float leftY;
|
||||
|
||||
float rightX = graph.getLastX();
|
||||
float rightY = graph.getLastY();
|
||||
|
||||
while (true) {
|
||||
leftX = rightX;
|
||||
leftY = rightY;
|
||||
|
||||
if (leftX > xMax) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (next.empty()) {
|
||||
float x = leftX + maxStep;
|
||||
next.push(x, (float) f.eval(x));
|
||||
}
|
||||
|
||||
rightX = next.getLastX();
|
||||
rightY = next.getLastY();
|
||||
next.pop();
|
||||
|
||||
if (Float.isNaN(leftY) || Float.isNaN(rightY)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float dx = rightX - leftX;
|
||||
float middleX = (leftX + rightX) / 2;
|
||||
float middleY = (float) f.eval(middleX);
|
||||
|
||||
boolean middleIsOutside = (middleY < leftY && middleY < rightY) || (leftY < middleY && rightY < middleY);
|
||||
|
||||
if (dx < minStep) {
|
||||
// Calculator.log("minStep");
|
||||
if (middleIsOutside) {
|
||||
graph.push(rightX, Float.NaN);
|
||||
}
|
||||
graph.push(rightX, rightY);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (middleIsOutside && ((leftY < yMin && rightY > yMax) || (leftY > yMax && rightY < yMin))) {
|
||||
graph.push(rightX, Float.NaN);
|
||||
graph.push(rightX, rightY);
|
||||
// Calculator.log("+-inf");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!middleIsOutside) {
|
||||
if (distance2(leftX, leftY, rightX, rightY, middleY) < yTheta) {
|
||||
graph.push(rightX, rightY);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
next.push(rightX, rightY);
|
||||
next.push(middleX, middleY);
|
||||
rightX = leftX;
|
||||
rightY = leftY;
|
||||
}
|
||||
}
|
||||
|
||||
// distance as above when x==(x1+x2)/2.
|
||||
private float distance2(float x1, float y1, float x2, float y2, float y) {
|
||||
final float dx = x2 - x1;
|
||||
final float dy = y2 - y1;
|
||||
final float up = dx * (y1 + y2 - y - y);
|
||||
return up * up / (dx * dx + dy * dy);
|
||||
}
|
||||
}
|
@ -1,187 +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 javax.annotation.Nonnull;
|
||||
|
||||
class GraphData {
|
||||
|
||||
private int size = 0;
|
||||
|
||||
private int allocatedSize = 4;
|
||||
private float[] xs = new float[allocatedSize];
|
||||
private float[] ys = new float[allocatedSize];
|
||||
|
||||
private GraphData() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
static GraphData newEmptyInstance() {
|
||||
return new GraphData();
|
||||
}
|
||||
|
||||
void swap(@Nonnull GraphData that) {
|
||||
float savedXs[] = that.xs;
|
||||
float savedYs[] = that.ys;
|
||||
int savedSize = that.size;
|
||||
int savedAllocatedSize = that.allocatedSize;
|
||||
|
||||
that.xs = this.xs;
|
||||
that.ys = this.ys;
|
||||
that.size = this.size;
|
||||
that.allocatedSize = this.allocatedSize;
|
||||
|
||||
this.xs = savedXs;
|
||||
this.ys = savedYs;
|
||||
this.size = savedSize;
|
||||
this.allocatedSize = savedAllocatedSize;
|
||||
}
|
||||
|
||||
void push(float x, float y) {
|
||||
if (size >= allocatedSize) {
|
||||
makeSpaceAtTheEnd(size + 1);
|
||||
}
|
||||
|
||||
xs[size] = x;
|
||||
ys[size] = y;
|
||||
++size;
|
||||
}
|
||||
|
||||
private void makeSpaceAtTheEnd(int newSize) {
|
||||
int oldAllocatedSize = allocatedSize;
|
||||
while (newSize > allocatedSize) {
|
||||
allocatedSize += allocatedSize;
|
||||
}
|
||||
|
||||
if (oldAllocatedSize != allocatedSize) {
|
||||
float[] a = new float[allocatedSize];
|
||||
System.arraycopy(xs, 0, a, 0, this.size);
|
||||
xs = a;
|
||||
a = new float[allocatedSize];
|
||||
System.arraycopy(ys, 0, a, 0, this.size);
|
||||
ys = a;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float getLastX() {
|
||||
return xs[size - 1];
|
||||
}
|
||||
|
||||
float getLastY() {
|
||||
return ys[size - 1];
|
||||
}
|
||||
|
||||
float getFirstX() {
|
||||
return xs[0];
|
||||
}
|
||||
|
||||
float getFirstY() {
|
||||
return ys[0];
|
||||
}
|
||||
|
||||
void pop() {
|
||||
--size;
|
||||
}
|
||||
|
||||
boolean empty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
void eraseBefore(float x) {
|
||||
int i = 0;
|
||||
while (i < size && xs[i] < x) {
|
||||
++i;
|
||||
}
|
||||
// step back as xs[i] >= x and xs[i-1] < x
|
||||
--i;
|
||||
|
||||
if (i > 0) {
|
||||
size -= i;
|
||||
System.arraycopy(xs, i, xs, 0, size);
|
||||
System.arraycopy(ys, i, ys, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
void eraseAfter(float x) {
|
||||
int i = size - 1;
|
||||
while (i >= 0 && x < xs[i]) {
|
||||
--i;
|
||||
}
|
||||
|
||||
// step next as xs[i] > x and xs[i+1] <= x
|
||||
++i;
|
||||
|
||||
if (i < size - 1) {
|
||||
size = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int findPositionAfter(float x, float y) {
|
||||
int i = 0;
|
||||
while (i < size && xs[i] <= x) {
|
||||
++i;
|
||||
}
|
||||
|
||||
if (Float.isNaN(y)) {
|
||||
while (i < size && Float.isNaN(ys[i])) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void append(GraphData that) {
|
||||
makeSpaceAtTheEnd(size + that.size);
|
||||
int position = that.findPositionAfter(xs[size - 1], ys[size - 1]);
|
||||
System.arraycopy(that.xs, position, xs, size, that.size - position);
|
||||
System.arraycopy(that.ys, position, ys, size, that.size - position);
|
||||
size += that.size - position;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(size).append(": ");
|
||||
for (int i = 0; i < size; ++i) {
|
||||
b.append(xs[i]).append(", ");
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public float[] getXs() {
|
||||
return xs;
|
||||
}
|
||||
|
||||
public float[] getYs() {
|
||||
return ys;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
}
|
@ -1,65 +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.graphics.Bitmap;
|
||||
import android.widget.ZoomButtonsController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public interface GraphView extends ZoomButtonsController.OnZoomListener, TouchHandler.TouchHandlerListener {
|
||||
|
||||
void init(@Nonnull PlotViewDef plotViewDef);
|
||||
|
||||
@Nonnull
|
||||
List<PlotFunction> getPlotFunctions();
|
||||
|
||||
void setPlotFunctions(@Nonnull List<PlotFunction> plotFunctions);
|
||||
|
||||
void onDestroy();
|
||||
|
||||
void onPause();
|
||||
|
||||
void onResume();
|
||||
|
||||
@Nonnull
|
||||
Bitmap captureScreenshot();
|
||||
|
||||
void setXRange(float xMin, float xMax);
|
||||
|
||||
void setYRange(float yMin, float yMax);
|
||||
|
||||
float getXMin();
|
||||
|
||||
float getXMax();
|
||||
|
||||
float getYMin();
|
||||
|
||||
float getYMax();
|
||||
|
||||
void invalidateGraphs();
|
||||
|
||||
void setAdjustYAxis(boolean adjustYAxis);
|
||||
}
|
@ -1,81 +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 java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/5/13
|
||||
* Time: 8:06 PM
|
||||
*/
|
||||
public class GraphViewHelper {
|
||||
|
||||
@Nonnull
|
||||
private PlotViewDef plotViewDef = PlotViewDef.newDefaultInstance();
|
||||
|
||||
@Nonnull
|
||||
private List<PlotFunction> plotFunctions = Collections.emptyList();
|
||||
|
||||
private GraphViewHelper() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GraphViewHelper newDefaultInstance() {
|
||||
return new GraphViewHelper();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GraphViewHelper newInstance(@Nonnull PlotViewDef plotViewDef,
|
||||
@Nonnull List<PlotFunction> plotFunctions) {
|
||||
final GraphViewHelper result = new GraphViewHelper();
|
||||
|
||||
result.plotViewDef = plotViewDef;
|
||||
result.plotFunctions = Collections.unmodifiableList(plotFunctions);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public GraphViewHelper copy(@Nonnull List<PlotFunction> plotFunctions) {
|
||||
final GraphViewHelper result = new GraphViewHelper();
|
||||
|
||||
result.plotViewDef = plotViewDef;
|
||||
result.plotFunctions = Collections.unmodifiableList(plotFunctions);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<PlotFunction> getPlotFunctions() {
|
||||
return plotFunctions;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public PlotViewDef getPlotViewDef() {
|
||||
return plotViewDef;
|
||||
}
|
||||
}
|
@ -1,110 +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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/18/13
|
||||
* Time: 8:32 PM
|
||||
*/
|
||||
public class GraphsData {
|
||||
|
||||
@Nonnull
|
||||
private final GraphView graphView;
|
||||
|
||||
@Nonnull
|
||||
private List<GraphData> graphs;
|
||||
|
||||
private float lastXMin;
|
||||
private float lastXMax;
|
||||
|
||||
private float lastYMin;
|
||||
|
||||
private float lastYMax;
|
||||
|
||||
public GraphsData(@Nonnull GraphView graphView) {
|
||||
this.graphView = graphView;
|
||||
graphs = new ArrayList<GraphData>(graphView.getPlotFunctions().size());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (GraphData graph : graphs) {
|
||||
graph.clear();
|
||||
}
|
||||
|
||||
while (graphView.getPlotFunctions().size() > graphs.size()) {
|
||||
graphs.add(GraphData.newEmptyInstance());
|
||||
}
|
||||
|
||||
lastYMin = 0;
|
||||
lastYMax = 0;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<GraphData> getGraphs() {
|
||||
return graphs;
|
||||
}
|
||||
|
||||
public float getLastXMin() {
|
||||
return lastXMin;
|
||||
}
|
||||
|
||||
public void setLastXMin(float lastXMin) {
|
||||
this.lastXMin = lastXMin;
|
||||
}
|
||||
|
||||
public float getLastXMax() {
|
||||
return lastXMax;
|
||||
}
|
||||
|
||||
public void setLastXMax(float lastXMax) {
|
||||
this.lastXMax = lastXMax;
|
||||
}
|
||||
|
||||
public float getLastYMin() {
|
||||
return lastYMin;
|
||||
}
|
||||
|
||||
public float getLastYMax() {
|
||||
return lastYMax;
|
||||
}
|
||||
|
||||
void checkBoundaries(float graphHeight, float yMin, float yMax) {
|
||||
if (yMin < lastYMin || yMax > lastYMax) {
|
||||
float halfGraphHeight = graphHeight / 2;
|
||||
clear();
|
||||
lastYMin = yMin - halfGraphHeight;
|
||||
lastYMax = yMax + halfGraphHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public GraphData get(int i) {
|
||||
return this.graphs.get(i);
|
||||
}
|
||||
}
|
@ -1,140 +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 java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/19/13
|
||||
* Time: 12:48 AM
|
||||
*/
|
||||
public class MapPlotResourceManager implements PlotResourceManager {
|
||||
|
||||
@Nonnull
|
||||
private final List<PlotLineDef> preparedLineDefs = new ArrayList<PlotLineDef>(PlotLineStyle.values().length * PlotLineColor.values().length);
|
||||
@Nonnull
|
||||
private Map<PlotLineDef, List<PlotLineDef>> registeredLineDefsMap = new HashMap<PlotLineDef, List<PlotLineDef>>();
|
||||
|
||||
public MapPlotResourceManager() {
|
||||
for (PlotLineStyle plotLineStyle : PlotLineStyle.values()) {
|
||||
for (PlotLineColor plotLineColor : PlotLineColor.values()) {
|
||||
preparedLineDefs.add(PlotLineDef.newInstance(plotLineColor.getColor(), plotLineStyle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PlotLineDef generateAndRegister() {
|
||||
synchronized (this) {
|
||||
for (PlotLineDef lineDef : preparedLineDefs) {
|
||||
final List<PlotLineDef> registeredLineDefs = registeredLineDefsMap.get(lineDef);
|
||||
if (registeredLineDefs == null || registeredLineDefs.isEmpty()) {
|
||||
register(lineDef);
|
||||
return lineDef;
|
||||
}
|
||||
}
|
||||
|
||||
return preparedLineDefs.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void addLineDef(@Nonnull final PlotLineDef toBeAdded) {
|
||||
if (!Thread.holdsLock(this)) throw new AssertionError();
|
||||
|
||||
List<PlotLineDef> registeredLineDefs = registeredLineDefsMap.get(toBeAdded);
|
||||
if (registeredLineDefs == null) {
|
||||
registeredLineDefs = new ArrayList<PlotLineDef>();
|
||||
registeredLineDefsMap.put(toBeAdded, registeredLineDefs);
|
||||
}
|
||||
|
||||
try {
|
||||
Iterables.find(registeredLineDefs, new Predicate<PlotLineDef>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PlotLineDef lineDef) {
|
||||
return lineDef == toBeAdded;
|
||||
}
|
||||
});
|
||||
|
||||
// already added
|
||||
|
||||
} catch (NoSuchElementException e) {
|
||||
registeredLineDefs.add(toBeAdded);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void removeLineDef(@Nonnull final PlotLineDef toBeRemoved) {
|
||||
if (!Thread.holdsLock(this)) throw new AssertionError();
|
||||
|
||||
List<PlotLineDef> registeredLineDefs = registeredLineDefsMap.get(toBeRemoved);
|
||||
|
||||
if (registeredLineDefs != null) {
|
||||
Iterables.removeIf(registeredLineDefs, new Predicate<PlotLineDef>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PlotLineDef lineDef) {
|
||||
return lineDef == toBeRemoved;
|
||||
}
|
||||
});
|
||||
|
||||
if (registeredLineDefs.isEmpty()) {
|
||||
registeredLineDefsMap.remove(toBeRemoved);
|
||||
}
|
||||
|
||||
} else {
|
||||
registeredLineDefsMap.remove(toBeRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(@Nonnull PlotLineDef lineDef) {
|
||||
synchronized (this) {
|
||||
addLineDef(lineDef);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(@Nonnull PlotLineDef lineDef) {
|
||||
synchronized (this) {
|
||||
removeLineDef(lineDef);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterAll() {
|
||||
synchronized (this) {
|
||||
registeredLineDefsMap.clear();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,124 +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 java.io.Serializable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/19/13
|
||||
* Time: 4:51 PM
|
||||
*/
|
||||
public final class PlotBoundaries implements Serializable {
|
||||
|
||||
public static final float DEFAULT_MIN_NUMBER = -10f;
|
||||
|
||||
public static final float DEFAULT_MAX_NUMBER = 10f;
|
||||
|
||||
|
||||
private float xMin;
|
||||
private float xMax;
|
||||
private float yMin;
|
||||
private float yMax;
|
||||
|
||||
public PlotBoundaries() {
|
||||
}
|
||||
|
||||
PlotBoundaries(float xMin, float xMax, float yMin, float yMax) {
|
||||
this.xMin = Math.min(xMin, xMax);
|
||||
this.xMax = Math.max(xMin, xMax);
|
||||
this.yMin = Math.min(yMin, yMax);
|
||||
this.yMax = Math.max(yMin, yMax);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotBoundaries newInstance(float xMin, float xMax, float yMin, float yMax) {
|
||||
return new PlotBoundaries(xMin, xMax, yMin, yMax);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotBoundaries newInstance(float xMin, float xMax) {
|
||||
return newInstance(xMin, xMax, DEFAULT_MIN_NUMBER, DEFAULT_MAX_NUMBER);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotBoundaries newDefaultInstance() {
|
||||
PlotBoundaries plotBoundaries = new PlotBoundaries();
|
||||
plotBoundaries.xMin = DEFAULT_MIN_NUMBER;
|
||||
plotBoundaries.yMin = DEFAULT_MIN_NUMBER;
|
||||
plotBoundaries.xMax = DEFAULT_MAX_NUMBER;
|
||||
plotBoundaries.yMax = DEFAULT_MAX_NUMBER;
|
||||
return plotBoundaries;
|
||||
}
|
||||
|
||||
public float getXMin() {
|
||||
return xMin;
|
||||
}
|
||||
|
||||
public float getXMax() {
|
||||
return xMax;
|
||||
}
|
||||
|
||||
public float getYMin() {
|
||||
return yMin;
|
||||
}
|
||||
|
||||
public float getYMax() {
|
||||
return yMax;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlotBoundaries{" +
|
||||
"yMax=" + yMax +
|
||||
", yMin=" + yMin +
|
||||
", xMax=" + xMax +
|
||||
", xMin=" + xMin +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PlotBoundaries)) return false;
|
||||
|
||||
PlotBoundaries that = (PlotBoundaries) o;
|
||||
|
||||
if (Float.compare(that.xMax, xMax) != 0) return false;
|
||||
if (Float.compare(that.xMin, xMin) != 0) return false;
|
||||
if (Float.compare(that.yMax, yMax) != 0) return false;
|
||||
return Float.compare(that.yMin, yMin) == 0;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (xMin != +0.0f ? Float.floatToIntBits(xMin) : 0);
|
||||
result = 31 * result + (xMax != +0.0f ? Float.floatToIntBits(xMax) : 0);
|
||||
result = 31 * result + (yMin != +0.0f ? Float.floatToIntBits(yMin) : 0);
|
||||
result = 31 * result + (yMax != +0.0f ? Float.floatToIntBits(yMax) : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,73 +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 java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/12/13
|
||||
* Time: 10:01 PM
|
||||
*/
|
||||
public class PlotData {
|
||||
|
||||
@Nonnull
|
||||
private final List<PlotFunction> functions;
|
||||
|
||||
private final boolean plot3d;
|
||||
|
||||
private final boolean adjustYAxis;
|
||||
|
||||
@Nonnull
|
||||
private final PlotBoundaries boundaries;
|
||||
|
||||
public PlotData(@Nonnull List<PlotFunction> functions,
|
||||
boolean plot3d,
|
||||
boolean adjustYAxis,
|
||||
@Nonnull PlotBoundaries boundaries) {
|
||||
this.functions = functions;
|
||||
this.plot3d = plot3d;
|
||||
this.adjustYAxis = adjustYAxis;
|
||||
this.boundaries = boundaries;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<PlotFunction> getFunctions() {
|
||||
return functions;
|
||||
}
|
||||
|
||||
public boolean isPlot3d() {
|
||||
return plot3d;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public PlotBoundaries getBoundaries() {
|
||||
return boundaries;
|
||||
}
|
||||
|
||||
public boolean isAdjustYAxis() {
|
||||
return adjustYAxis;
|
||||
}
|
||||
}
|
@ -1,139 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/12/13
|
||||
* Time: 8:45 PM
|
||||
*/
|
||||
public class PlotFunction {
|
||||
|
||||
@Nonnull
|
||||
private XyFunction xyFunction;
|
||||
|
||||
@Nonnull
|
||||
private PlotLineDef plotLineDef;
|
||||
|
||||
private boolean pinned = false;
|
||||
|
||||
private boolean visible = true;
|
||||
|
||||
public PlotFunction(@Nonnull XyFunction xyFunction) {
|
||||
this.xyFunction = xyFunction;
|
||||
this.plotLineDef = PlotLineDef.newDefaultInstance();
|
||||
}
|
||||
|
||||
public PlotFunction(@Nonnull XyFunction xyFunction,
|
||||
@Nonnull PlotLineDef plotLineDef) {
|
||||
this.xyFunction = xyFunction;
|
||||
this.plotLineDef = plotLineDef;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction changePlotLineDef(@Nonnull PlotFunction that, @Nonnull PlotLineDef newPlotLineDef) {
|
||||
final PlotFunction copy = that.copy();
|
||||
copy.plotLineDef = newPlotLineDef;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction pin(@Nonnull PlotFunction that) {
|
||||
return togglePinned(that, true);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction togglePinned(@Nonnull PlotFunction that, boolean pinned) {
|
||||
final PlotFunction copy = that.copy();
|
||||
copy.pinned = pinned;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction unpin(@Nonnull PlotFunction that) {
|
||||
return togglePinned(that, false);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction visible(@Nonnull PlotFunction that) {
|
||||
return toggleVisible(that, true);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction toggleVisible(@Nonnull PlotFunction that, boolean visible) {
|
||||
final PlotFunction copy = that.copy();
|
||||
copy.visible = visible;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotFunction invisible(@Nonnull PlotFunction that) {
|
||||
return toggleVisible(that, false);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private PlotFunction copy() {
|
||||
final PlotFunction copy = new PlotFunction(this.xyFunction, this.plotLineDef);
|
||||
|
||||
copy.pinned = this.pinned;
|
||||
copy.visible = this.visible;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public XyFunction getXyFunction() {
|
||||
return xyFunction;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public PlotLineDef getPlotLineDef() {
|
||||
return plotLineDef;
|
||||
}
|
||||
|
||||
public boolean isPinned() {
|
||||
return pinned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PlotFunction)) return false;
|
||||
|
||||
PlotFunction that = (PlotFunction) o;
|
||||
|
||||
return xyFunction.equals(that.xyFunction);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return xyFunction.hashCode();
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
}
|
@ -1,68 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/4/12
|
||||
* Time: 10:08 PM
|
||||
*/
|
||||
public enum PlotLineColor {
|
||||
|
||||
// Color.WHITE
|
||||
white(0xFFBBBBBB),
|
||||
|
||||
blue(0xFF10648C),
|
||||
|
||||
// Color.RED
|
||||
red(0xFFFF0000),
|
||||
|
||||
// Color.GREEN
|
||||
green(0xFF00FF00),
|
||||
|
||||
// Color.GRAY
|
||||
grey(0xFF888888);
|
||||
|
||||
private final int color;
|
||||
|
||||
PlotLineColor(int color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineColor valueOf(int color) {
|
||||
for (PlotLineColor plotLineColor : PlotLineColor.values()) {
|
||||
if (plotLineColor.color == color) {
|
||||
return plotLineColor;
|
||||
}
|
||||
}
|
||||
|
||||
return PlotLineColor.white;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return this.color;
|
||||
}
|
||||
}
|
@ -1,34 +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;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/5/13
|
||||
* Time: 10:45 PM
|
||||
*/
|
||||
public enum PlotLineColorType {
|
||||
|
||||
monochrome,
|
||||
color_map
|
||||
}
|
@ -1,186 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/5/13
|
||||
* Time: 7:41 PM
|
||||
*/
|
||||
public class PlotLineDef {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private static final Float DEFAULT_LINE_WIDTH = 2f;
|
||||
|
||||
private static final int WHITE = 0xFFFFFFFF;
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private PlotLineColorType lineColorType = PlotLineColorType.monochrome;
|
||||
|
||||
private int lineColor = WHITE;
|
||||
|
||||
@Nonnull
|
||||
private PlotLineStyle lineStyle = PlotLineStyle.solid;
|
||||
|
||||
private float lineWidth = DEFAULT_LINE_WIDTH;
|
||||
|
||||
private PlotLineDef() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef newInstance(int lineColor, @Nonnull PlotLineStyle lineStyle) {
|
||||
final PlotLineDef result = new PlotLineDef();
|
||||
result.lineColor = lineColor;
|
||||
result.lineStyle = lineStyle;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef newInstance(int lineColor, @Nonnull PlotLineStyle lineStyle, float lineWidth) {
|
||||
final PlotLineDef result = new PlotLineDef();
|
||||
result.lineColor = lineColor;
|
||||
result.lineStyle = lineStyle;
|
||||
result.lineWidth = lineWidth;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef newInstance(int lineColor, @Nonnull PlotLineStyle lineStyle, float lineWidth, @Nonnull PlotLineColorType lineColorType) {
|
||||
final PlotLineDef result = new PlotLineDef();
|
||||
result.lineColor = lineColor;
|
||||
result.lineColorType = lineColorType;
|
||||
result.lineStyle = lineStyle;
|
||||
result.lineWidth = lineWidth;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef changeLineColor(@Nonnull PlotLineDef plotLineDef, int newLineColor) {
|
||||
final PlotLineDef result = plotLineDef.copy();
|
||||
result.lineColor = newLineColor;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef changeLineWidth(@Nonnull PlotLineDef plotLineDef, int newLineWidth) {
|
||||
final PlotLineDef result = plotLineDef.copy();
|
||||
result.lineWidth = newLineWidth;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef changeLineColorType(@Nonnull PlotLineDef plotLineDef, @Nonnull PlotLineColorType newPlotLineColorType) {
|
||||
final PlotLineDef result = plotLineDef.copy();
|
||||
result.lineColorType = newPlotLineColorType;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef changeLineStyle(@Nonnull PlotLineDef plotLineDef, @Nonnull PlotLineStyle newPlotLineStyle) {
|
||||
final PlotLineDef result = plotLineDef.copy();
|
||||
result.lineStyle = newPlotLineStyle;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef changeColor(@Nonnull PlotLineDef plotLineDef, int newLineColor) {
|
||||
final PlotLineDef result = plotLineDef.copy();
|
||||
result.lineColor = newLineColor;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotLineDef newDefaultInstance() {
|
||||
return new PlotLineDef();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private PlotLineDef copy() {
|
||||
final PlotLineDef copy = new PlotLineDef();
|
||||
copy.lineColor = lineColor;
|
||||
copy.lineColorType = lineColorType;
|
||||
copy.lineStyle = lineStyle;
|
||||
copy.lineWidth = lineWidth;
|
||||
return copy;
|
||||
}
|
||||
|
||||
public int getLineColor() {
|
||||
return lineColor;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public PlotLineStyle getLineStyle() {
|
||||
return lineStyle;
|
||||
}
|
||||
|
||||
public float getLineWidth() {
|
||||
return lineWidth;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public PlotLineColorType getLineColorType() {
|
||||
return lineColorType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PlotLineDef)) return false;
|
||||
|
||||
PlotLineDef that = (PlotLineDef) o;
|
||||
|
||||
if (lineColor != that.lineColor) return false;
|
||||
if (Float.compare(that.lineWidth, lineWidth) != 0) return false;
|
||||
if (lineColorType != that.lineColorType) return false;
|
||||
return lineStyle == that.lineStyle;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = lineColorType.hashCode();
|
||||
result = 31 * result + lineColor;
|
||||
result = 31 * result + lineStyle.hashCode();
|
||||
result = 31 * result + (lineWidth != +0.0f ? Float.floatToIntBits(lineWidth) : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,38 +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;
|
||||
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/5/13
|
||||
* Time: 7:37 PM
|
||||
*/
|
||||
public enum PlotLineStyle {
|
||||
|
||||
solid,
|
||||
dashed,
|
||||
dotted,
|
||||
dash_dotted
|
||||
|
||||
}
|
@ -1,42 +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 javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/13/13
|
||||
* Time: 8:19 PM
|
||||
*/
|
||||
interface PlotResourceManager {
|
||||
|
||||
@Nonnull
|
||||
PlotLineDef generateAndRegister();
|
||||
|
||||
void register(@Nonnull PlotLineDef lineDef);
|
||||
|
||||
void unregister(@Nonnull PlotLineDef lineDef);
|
||||
|
||||
void unregisterAll();
|
||||
}
|
@ -1,101 +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 javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.JsclInteger;
|
||||
import jscl.math.NumericWrapper;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.math.numeric.Complex;
|
||||
import jscl.math.numeric.Numeric;
|
||||
import jscl.math.numeric.Real;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/5/11
|
||||
* Time: 8:58 PM
|
||||
*/
|
||||
public final class PlotUtils {
|
||||
|
||||
private static final Complex NaN = Complex.valueOf(Double.NaN, 0d);
|
||||
|
||||
// not intended for instantiation
|
||||
private PlotUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Complex calculatorExpression(@Nonnull Generic expression) {
|
||||
try {
|
||||
return unwrap(expression.numeric());
|
||||
} catch (RuntimeException e) {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Complex calculatorExpression(@Nonnull Generic expression, @Nonnull Constant xVar, double x) {
|
||||
try {
|
||||
return unwrap(expression.substitute(xVar, Expression.valueOf(x)).numeric());
|
||||
} catch (RuntimeException e) {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Complex calculatorExpression(@Nonnull Generic expression, @Nonnull Constant xVar, double x, @Nonnull Constant yVar, double y) {
|
||||
try {
|
||||
Generic tmp = expression.substitute(xVar, Expression.valueOf(x));
|
||||
tmp = tmp.substitute(yVar, Expression.valueOf(y));
|
||||
return unwrap(tmp.numeric());
|
||||
} catch (RuntimeException e) {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Complex unwrap(@Nullable Generic numeric) {
|
||||
if (numeric instanceof JsclInteger) {
|
||||
return Complex.valueOf(((JsclInteger) numeric).intValue(), 0d);
|
||||
} else if (numeric instanceof NumericWrapper) {
|
||||
return unwrap(((NumericWrapper) numeric).content());
|
||||
} else {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Complex unwrap(@Nullable Numeric content) {
|
||||
if (content instanceof Real) {
|
||||
return Complex.valueOf(((Real) content).doubleValue(), 0d);
|
||||
} else if (content instanceof Complex) {
|
||||
return ((Complex) content);
|
||||
} else {
|
||||
throw new ArithmeticException();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,99 +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.graphics.Color;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/5/13
|
||||
* Time: 9:11 PM
|
||||
*/
|
||||
public class PlotViewDef {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final int DEFAULT_AXIS_COLOR = 0xff00a000;
|
||||
private static final int DEFAULT_GRID_COLOR = 0xff004000;
|
||||
private static final int DEFAULT_BACKGROUND_COLOR = Color.BLACK;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private int axisColor = DEFAULT_AXIS_COLOR;
|
||||
|
||||
private int axisLabelsColor = DEFAULT_AXIS_COLOR;
|
||||
|
||||
private int gridColor = DEFAULT_GRID_COLOR;
|
||||
|
||||
private int backgroundColor = DEFAULT_BACKGROUND_COLOR;
|
||||
|
||||
private PlotViewDef() {
|
||||
}
|
||||
|
||||
private PlotViewDef(int axisColor, int axisLabelColor, int gridColor, int backgroundColor) {
|
||||
this.axisColor = axisColor;
|
||||
this.axisLabelsColor = axisLabelColor;
|
||||
this.gridColor = gridColor;
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotViewDef newDefaultInstance() {
|
||||
return new PlotViewDef();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PlotViewDef newInstance(int axisColor, int axisLabelColor, int gridColor, int backgroundColor) {
|
||||
return new PlotViewDef(axisColor, axisLabelColor, gridColor, backgroundColor);
|
||||
}
|
||||
|
||||
public int getAxisColor() {
|
||||
return axisColor;
|
||||
}
|
||||
|
||||
public int getAxisLabelsColor() {
|
||||
return axisLabelsColor;
|
||||
}
|
||||
|
||||
public int getGridColor() {
|
||||
return gridColor;
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
}
|
@ -1,143 +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 javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
public class SpriteBatch {
|
||||
|
||||
//--Constants--//
|
||||
final static int VERTEX_SIZE = 4; // Vertex Size (in Components) ie. (X,Y,U,V)
|
||||
final static int VERTICES_PER_SPRITE = 4; // Vertices Per Sprite
|
||||
final static int INDICES_PER_SPRITE = 6; // Indices Per Sprite
|
||||
|
||||
//--Members--//
|
||||
GL10 gl; // GL Instance
|
||||
Vertices vertices; // Vertices Instance Used for Rendering
|
||||
float[] vertexBuffer; // Vertex Buffer
|
||||
int bufferIndex; // Vertex Buffer Start Index
|
||||
int maxSprites; // Maximum Sprites Allowed in Buffer
|
||||
int numSprites; // Number of Sprites Currently in Buffer
|
||||
|
||||
//--Constructor--//
|
||||
// D: prepare the sprite batcher for specified maximum number of sprites
|
||||
// A: gl - the gl instance to use for rendering
|
||||
// maxSprites - the maximum allowed sprites per batch
|
||||
public SpriteBatch(GL10 gl, int maxSprites) {
|
||||
this.gl = gl; // Save GL Instance
|
||||
this.vertexBuffer = new float[maxSprites * VERTICES_PER_SPRITE * VERTEX_SIZE]; // Create Vertex Buffer
|
||||
this.vertices = new Vertices(gl, maxSprites * VERTICES_PER_SPRITE, maxSprites * INDICES_PER_SPRITE, false, true, false); // Create Rendering Vertices
|
||||
this.bufferIndex = 0; // Reset Buffer Index
|
||||
this.maxSprites = maxSprites; // Save Maximum Sprites
|
||||
this.numSprites = 0; // Clear Sprite Counter
|
||||
|
||||
short[] indices = new short[maxSprites * INDICES_PER_SPRITE]; // Create Temp Index Buffer
|
||||
int len = indices.length; // Get Index Buffer Length
|
||||
short j = 0; // Counter
|
||||
for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) { // FOR Each Index Set (Per Sprite)
|
||||
indices[i + 0] = (short) (j + 0); // Calculate Index 0
|
||||
indices[i + 1] = (short) (j + 1); // Calculate Index 1
|
||||
indices[i + 2] = (short) (j + 2); // Calculate Index 2
|
||||
indices[i + 3] = (short) (j + 2); // Calculate Index 3
|
||||
indices[i + 4] = (short) (j + 3); // Calculate Index 4
|
||||
indices[i + 5] = (short) (j + 0); // Calculate Index 5
|
||||
}
|
||||
vertices.setIndices(indices, 0, len); // Set Index Buffer for Rendering
|
||||
}
|
||||
|
||||
//--Begin Batch--//
|
||||
// D: signal the start of a batch. set the texture and clear buffer
|
||||
// NOTE: the overloaded (non-texture) version assumes that the texture is already bound!
|
||||
// A: textureId - the ID of the texture to use for the batch
|
||||
// R: [none]
|
||||
public void beginBatch(int textureId) {
|
||||
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); // Bind the Texture
|
||||
numSprites = 0; // Empty Sprite Counter
|
||||
bufferIndex = 0; // Reset Buffer Index (Empty)
|
||||
}
|
||||
|
||||
public void beginBatch() {
|
||||
numSprites = 0; // Empty Sprite Counter
|
||||
bufferIndex = 0; // Reset Buffer Index (Empty)
|
||||
}
|
||||
|
||||
//--End Batch--//
|
||||
// D: signal the end of a batch. render the batched sprites
|
||||
// A: [none]
|
||||
// R: [none]
|
||||
public void endBatch() {
|
||||
if (numSprites > 0) { // IF Any Sprites to Render
|
||||
vertices.setVertices(vertexBuffer, 0, bufferIndex); // Set Vertices from Buffer
|
||||
vertices.bind(); // Bind Vertices
|
||||
vertices.draw(GL10.GL_TRIANGLES, 0, numSprites * INDICES_PER_SPRITE); // Render Batched Sprites
|
||||
vertices.unbind(); // Unbind Vertices
|
||||
}
|
||||
}
|
||||
|
||||
//--Draw Sprite to Batch--//
|
||||
// D: batch specified sprite to batch. adds vertices for sprite to vertex buffer
|
||||
// NOTE: MUST be called after beginBatch(), and before endBatch()!
|
||||
// NOTE: if the batch overflows, this will render the current batch, restart it,
|
||||
// and then batch this sprite.
|
||||
// A: x, y - the x,y position of the sprite (center)
|
||||
// width, height - the width and height of the sprite
|
||||
// region - the texture region to use for sprite
|
||||
// R: [none]
|
||||
public void drawSprite(float x, float y, float width, float height, TextureRegion region) {
|
||||
if (numSprites == maxSprites) { // IF Sprite Buffer is Full
|
||||
endBatch(); // End Batch
|
||||
// NOTE: leave current texture bound!!
|
||||
numSprites = 0; // Empty Sprite Counter
|
||||
bufferIndex = 0; // Reset Buffer Index (Empty)
|
||||
}
|
||||
|
||||
float halfWidth = width / 2.0f; // Calculate Half Width
|
||||
float halfHeight = height / 2.0f; // Calculate Half Height
|
||||
float x1 = x - halfWidth; // Calculate Left X
|
||||
float y1 = y - halfHeight; // Calculate Bottom Y
|
||||
float x2 = x + halfWidth; // Calculate Right X
|
||||
float y2 = y + halfHeight; // Calculate Top Y
|
||||
|
||||
vertexBuffer[bufferIndex++] = x1; // Add X for Vertex 0
|
||||
vertexBuffer[bufferIndex++] = y1; // Add Y for Vertex 0
|
||||
vertexBuffer[bufferIndex++] = region.u1; // Add U for Vertex 0
|
||||
vertexBuffer[bufferIndex++] = region.v2; // Add V for Vertex 0
|
||||
|
||||
vertexBuffer[bufferIndex++] = x2; // Add X for Vertex 1
|
||||
vertexBuffer[bufferIndex++] = y1; // Add Y for Vertex 1
|
||||
vertexBuffer[bufferIndex++] = region.u2; // Add U for Vertex 1
|
||||
vertexBuffer[bufferIndex++] = region.v2; // Add V for Vertex 1
|
||||
|
||||
vertexBuffer[bufferIndex++] = x2; // Add X for Vertex 2
|
||||
vertexBuffer[bufferIndex++] = y2; // Add Y for Vertex 2
|
||||
vertexBuffer[bufferIndex++] = region.u2; // Add U for Vertex 2
|
||||
vertexBuffer[bufferIndex++] = region.v1; // Add V for Vertex 2
|
||||
|
||||
vertexBuffer[bufferIndex++] = x1; // Add X for Vertex 3
|
||||
vertexBuffer[bufferIndex++] = y2; // Add Y for Vertex 3
|
||||
vertexBuffer[bufferIndex++] = region.u1; // Add U for Vertex 3
|
||||
vertexBuffer[bufferIndex++] = region.v1; // Add V for Vertex 3
|
||||
|
||||
numSprites++; // Increment Sprite Count
|
||||
}
|
||||
}
|
@ -1,111 +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
|
||||
*/
|
||||
|
||||
// This is based on the OpenGL ES 1.0 sample application from the Android Developer website:
|
||||
// http://developer.android.com/resources/tutorials/opengl/opengl-es10.html
|
||||
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.content.Context;
|
||||
import android.opengl.GLSurfaceView;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
public class TexampleRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
private GLText glText; // A GLText Instance
|
||||
private Context context; // Context (from Activity)
|
||||
|
||||
private int width = 100; // Updated to the Current Width + Height in onSurfaceChanged()
|
||||
private int height = 100;
|
||||
|
||||
public TexampleRenderer(Context context) {
|
||||
super();
|
||||
this.context = context; // Save Specified Context
|
||||
}
|
||||
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
// Set the background frame color
|
||||
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
// Create the GLText
|
||||
glText = new GLText(gl, context.getAssets());
|
||||
|
||||
// Load the font from file (set size + padding), creates the texture
|
||||
// NOTE: after a successful call to this the font is ready for rendering!
|
||||
glText.load("Roboto-Regular.ttf", 14, 2, 2); // Create Font (Height: 14 Pixels / X+Y Padding 2 Pixels)
|
||||
}
|
||||
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
// Redraw background color
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Set to ModelView mode
|
||||
gl.glMatrixMode(GL10.GL_MODELVIEW); // Activate Model View Matrix
|
||||
gl.glLoadIdentity(); // Load Identity Matrix
|
||||
|
||||
// enable texture + alpha blending
|
||||
// NOTE: this is required for text rendering! we could incorporate it into
|
||||
// the GLText class, but then it would be called multiple times (which impacts performance).
|
||||
gl.glEnable(GL10.GL_TEXTURE_2D); // Enable Texture Mapping
|
||||
gl.glEnable(GL10.GL_BLEND); // Enable Alpha Blend
|
||||
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); // Set Alpha Blend Function
|
||||
|
||||
// TEST: render the entire font texture
|
||||
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Set Color to Use
|
||||
glText.drawTexture(width, height); // Draw the Entire Texture
|
||||
|
||||
// TEST: render some strings with the font
|
||||
glText.begin(1.0f, 1.0f, 1.0f, 1.0f); // Begin Text Rendering (Set Color WHITE)
|
||||
glText.draw("Test String :)", 0, 0); // Draw Test String
|
||||
glText.draw("Line 1", 50, 50); // Draw Test String
|
||||
glText.draw("Line 2", 100, 100); // Draw Test String
|
||||
glText.end(); // End Text Rendering
|
||||
|
||||
glText.begin(0.0f, 0.0f, 1.0f, 1.0f); // Begin Text Rendering (Set Color BLUE)
|
||||
glText.draw("More Lines...", 50, 150); // Draw Test String
|
||||
glText.draw("The End.", 50, 150 + glText.getCharHeight()); // Draw Test String
|
||||
glText.end(); // End Text Rendering
|
||||
|
||||
// disable texture + alpha
|
||||
gl.glDisable(GL10.GL_BLEND); // Disable Alpha Blend
|
||||
gl.glDisable(GL10.GL_TEXTURE_2D); // Disable Texture Mapping
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
gl.glViewport(0, 0, width, height);
|
||||
|
||||
// Setup orthographic projection
|
||||
gl.glMatrixMode(GL10.GL_PROJECTION); // Activate Projection Matrix
|
||||
gl.glLoadIdentity(); // Load Identity Matrix
|
||||
gl.glOrthof( // Set Ortho Projection (Left,Right,Bottom,Top,Front,Back)
|
||||
0, width,
|
||||
0, height,
|
||||
1.0f, -1.0f
|
||||
);
|
||||
|
||||
// Save width and height
|
||||
this.width = width; // Save Current Width
|
||||
this.height = height; // Save Current Height
|
||||
}
|
||||
}
|
@ -1,42 +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;
|
||||
|
||||
class TextureRegion {
|
||||
|
||||
//--Members--//
|
||||
public float u1, v1; // Top/Left U,V Coordinates
|
||||
public float u2, v2; // Bottom/Right U,V Coordinates
|
||||
|
||||
//--Constructor--//
|
||||
// D: calculate U,V coordinates from specified texture coordinates
|
||||
// A: texWidth, texHeight - the width and height of the texture the region is for
|
||||
// x, y - the top/left (x,y) of the region on the texture (in pixels)
|
||||
// width, height - the width and height of the region on the texture (in pixels)
|
||||
public TextureRegion(float texWidth, float texHeight, float x, float y, float width, float height) {
|
||||
this.u1 = x / texWidth; // Calculate U1
|
||||
this.v1 = y / texHeight; // Calculate V1
|
||||
this.u2 = this.u1 + (width / texWidth); // Calculate U2
|
||||
this.v2 = this.v1 + (height / texHeight); // Calculate V2
|
||||
}
|
||||
}
|
@ -1,118 +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.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
|
||||
import org.solovyev.android.Views;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
class TouchHandler {
|
||||
|
||||
@Nonnull
|
||||
private final VelocityTracker velocityTracker = VelocityTracker.obtain();
|
||||
private boolean afterZoom;
|
||||
@Nonnull
|
||||
private TouchHandlerListener listener;
|
||||
|
||||
TouchHandler(@Nonnull TouchHandlerListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public boolean handleTouchEvent(@Nonnull MotionEvent event) {
|
||||
// Calculator.log("touch " + event + ' ' + event.getPointerCount() + event.getPointerId(0));
|
||||
|
||||
final int fullAction = event.getAction();
|
||||
final int action = fullAction & MotionEvent.ACTION_MASK;
|
||||
final int pointer = (fullAction & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
|
||||
int pointerCount = Views.getPointerCountFromMotionEvent(event);
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
afterZoom = false;
|
||||
velocityTracker.clear();
|
||||
velocityTracker.addMovement(event);
|
||||
listener.onTouchDown(x, y);
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (pointerCount == 1) {
|
||||
if (afterZoom) {
|
||||
velocityTracker.clear();
|
||||
listener.onTouchDown(x, y);
|
||||
afterZoom = false;
|
||||
}
|
||||
velocityTracker.addMovement(event);
|
||||
listener.onTouchMove(x, y);
|
||||
} else if (pointerCount == 2) {
|
||||
listener.onTouchZoomMove(x, y, Views.getXFromMotionEvent(event, 1), Views.getYFromMotionEvent(event, 1));
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
velocityTracker.addMovement(event);
|
||||
velocityTracker.computeCurrentVelocity(1000);
|
||||
listener.onTouchUp(x, y);
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (pointerCount == 2) {
|
||||
listener.onTouchZoomDown(x, y, Views.getXFromMotionEvent(event, 1), Views.getYFromMotionEvent(event, 1));
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (pointerCount == 2) {
|
||||
afterZoom = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public float getXVelocity() {
|
||||
return velocityTracker.getXVelocity();
|
||||
}
|
||||
|
||||
public float getYVelocity() {
|
||||
return velocityTracker.getYVelocity();
|
||||
}
|
||||
|
||||
interface TouchHandlerListener {
|
||||
void onTouchDown(float x, float y);
|
||||
|
||||
void onTouchMove(float x, float y);
|
||||
|
||||
void onTouchUp(float x, float y);
|
||||
|
||||
void onTouchZoomDown(float x1, float y1, float x2, float y2);
|
||||
|
||||
void onTouchZoomMove(float x1, float y1, float x2, float y2);
|
||||
}
|
||||
}
|
@ -1,282 +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 java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
public class Vertices {
|
||||
|
||||
//--Constants--//
|
||||
final static int POSITION_CNT_2D = 2; // Number of Components in Vertex Position for 2D
|
||||
final static int POSITION_CNT_3D = 3; // Number of Components in Vertex Position for 3D
|
||||
final static int COLOR_CNT = 4; // Number of Components in Vertex Color
|
||||
final static int TEXCOORD_CNT = 2; // Number of Components in Vertex Texture Coords
|
||||
final static int NORMAL_CNT = 3; // Number of Components in Vertex Normal
|
||||
|
||||
final static int INDEX_SIZE = Short.SIZE / 8; // Index Byte Size (Short.SIZE = bits)
|
||||
public final int positionCnt; // Number of Position Components (2=2D, 3=3D)
|
||||
public final int vertexStride; // Vertex Stride (Element Size of a Single Vertex)
|
||||
public final int vertexSize; // Bytesize of a Single Vertex
|
||||
//--Members--//
|
||||
// NOTE: all members are constant, and initialized in constructor!
|
||||
final GL10 gl; // GL Instance
|
||||
final boolean hasColor; // Use Color in Vertices
|
||||
final boolean hasTexCoords; // Use Texture Coords in Vertices
|
||||
final boolean hasNormals; // Use Normals in Vertices
|
||||
final IntBuffer vertices; // Vertex Buffer
|
||||
final ShortBuffer indices; // Index Buffer
|
||||
final int[] tmpBuffer; // Temp Buffer for Vertex Conversion
|
||||
public int numVertices; // Number of Vertices in Buffer
|
||||
public int numIndices; // Number of Indices in Buffer
|
||||
|
||||
//--Constructor--//
|
||||
// D: create the vertices/indices as specified (for 2d/3d)
|
||||
// A: gl - the gl instance to use
|
||||
// maxVertices - maximum vertices allowed in buffer
|
||||
// maxIndices - maximum indices allowed in buffer
|
||||
// hasColor - use color values in vertices
|
||||
// hasTexCoords - use texture coordinates in vertices
|
||||
// hasNormals - use normals in vertices
|
||||
// use3D - (false, default) use 2d positions (ie. x/y only)
|
||||
// (true) use 3d positions (ie. x/y/z)
|
||||
public Vertices(GL10 gl, int maxVertices, int maxIndices, boolean hasColor, boolean hasTexCoords, boolean hasNormals) {
|
||||
this(gl, maxVertices, maxIndices, hasColor, hasTexCoords, hasNormals, false); // Call Overloaded Constructor
|
||||
}
|
||||
|
||||
public Vertices(GL10 gl, int maxVertices, int maxIndices, boolean hasColor, boolean hasTexCoords, boolean hasNormals, boolean use3D) {
|
||||
this.gl = gl; // Save GL Instance
|
||||
this.hasColor = hasColor; // Save Color Flag
|
||||
this.hasTexCoords = hasTexCoords; // Save Texture Coords Flag
|
||||
this.hasNormals = hasNormals; // Save Normals Flag
|
||||
this.positionCnt = use3D ? POSITION_CNT_3D : POSITION_CNT_2D; // Set Position Component Count
|
||||
this.vertexStride = this.positionCnt + (hasColor ? COLOR_CNT : 0) + (hasTexCoords ? TEXCOORD_CNT : 0) + (hasNormals ? NORMAL_CNT : 0); // Calculate Vertex Stride
|
||||
this.vertexSize = this.vertexStride * 4; // Calculate Vertex Byte Size
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(maxVertices * vertexSize); // Allocate Buffer for Vertices (Max)
|
||||
buffer.order(ByteOrder.nativeOrder()); // Set Native Byte Order
|
||||
this.vertices = buffer.asIntBuffer(); // Save Vertex Buffer
|
||||
|
||||
if (maxIndices > 0) { // IF Indices Required
|
||||
buffer = ByteBuffer.allocateDirect(maxIndices * INDEX_SIZE); // Allocate Buffer for Indices (MAX)
|
||||
buffer.order(ByteOrder.nativeOrder()); // Set Native Byte Order
|
||||
this.indices = buffer.asShortBuffer(); // Save Index Buffer
|
||||
} else // ELSE Indices Not Required
|
||||
indices = null; // No Index Buffer
|
||||
|
||||
numVertices = 0; // Zero Vertices in Buffer
|
||||
numIndices = 0; // Zero Indices in Buffer
|
||||
|
||||
this.tmpBuffer = new int[maxVertices * vertexSize / 4]; // Create Temp Buffer
|
||||
}
|
||||
|
||||
//--Set Vertices--//
|
||||
// D: set the specified vertices in the vertex buffer
|
||||
// NOTE: optimized to use integer buffer!
|
||||
// A: vertices - array of vertices (floats) to set
|
||||
// offset - offset to first vertex in array
|
||||
// length - number of floats in the vertex array (total)
|
||||
// for easy setting use: vtx_cnt * (this.vertexSize / 4)
|
||||
// R: [none]
|
||||
public void setVertices(float[] vertices, int offset, int length) {
|
||||
this.vertices.clear(); // Remove Existing Vertices
|
||||
int last = offset + length; // Calculate Last Element
|
||||
for (int i = offset, j = 0; i < last; i++, j++) // FOR Each Specified Vertex
|
||||
tmpBuffer[j] = Float.floatToRawIntBits(vertices[i]); // Set Vertex as Raw Integer Bits in Buffer
|
||||
this.vertices.put(tmpBuffer, 0, length); // Set New Vertices
|
||||
this.vertices.flip(); // Flip Vertex Buffer
|
||||
this.numVertices = length / this.vertexStride; // Save Number of Vertices
|
||||
//this.numVertices = length / ( this.vertexSize / 4 ); // Save Number of Vertices
|
||||
}
|
||||
|
||||
//--Set Indices--//
|
||||
// D: set the specified indices in the index buffer
|
||||
// A: indices - array of indices (shorts) to set
|
||||
// offset - offset to first index in array
|
||||
// length - number of indices in array (from offset)
|
||||
// R: [none]
|
||||
public void setIndices(short[] indices, int offset, int length) {
|
||||
this.indices.clear(); // Clear Existing Indices
|
||||
this.indices.put(indices, offset, length); // Set New Indices
|
||||
this.indices.flip(); // Flip Index Buffer
|
||||
this.numIndices = length; // Save Number of Indices
|
||||
}
|
||||
|
||||
//--Bind--//
|
||||
// D: perform all required binding/state changes before rendering batches.
|
||||
// USAGE: call once before calling draw() multiple times for this buffer.
|
||||
// A: [none]
|
||||
// R: [none]
|
||||
public void bind() {
|
||||
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // Enable Position in Vertices
|
||||
vertices.position(0); // Set Vertex Buffer to Position
|
||||
gl.glVertexPointer(positionCnt, GL10.GL_FLOAT, vertexSize, vertices); // Set Vertex Pointer
|
||||
|
||||
if (hasColor) { // IF Vertices Have Color
|
||||
gl.glEnableClientState(GL10.GL_COLOR_ARRAY); // Enable Color in Vertices
|
||||
vertices.position(positionCnt); // Set Vertex Buffer to Color
|
||||
gl.glColorPointer(COLOR_CNT, GL10.GL_FLOAT, vertexSize, vertices); // Set Color Pointer
|
||||
}
|
||||
|
||||
if (hasTexCoords) { // IF Vertices Have Texture Coords
|
||||
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable Texture Coords in Vertices
|
||||
vertices.position(positionCnt + (hasColor ? COLOR_CNT : 0)); // Set Vertex Buffer to Texture Coords (NOTE: position based on whether color is also specified)
|
||||
gl.glTexCoordPointer(TEXCOORD_CNT, GL10.GL_FLOAT, vertexSize, vertices); // Set Texture Coords Pointer
|
||||
}
|
||||
|
||||
if (hasNormals) {
|
||||
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); // Enable Normals in Vertices
|
||||
vertices.position(positionCnt + (hasColor ? COLOR_CNT : 0) + (hasTexCoords ? TEXCOORD_CNT : 0)); // Set Vertex Buffer to Normals (NOTE: position based on whether color/texcoords is also specified)
|
||||
gl.glNormalPointer(GL10.GL_FLOAT, vertexSize, vertices); // Set Normals Pointer
|
||||
}
|
||||
}
|
||||
|
||||
//--Draw--//
|
||||
// D: draw the currently bound vertices in the vertex/index buffers
|
||||
// USAGE: can only be called after calling bind() for this buffer.
|
||||
// A: primitiveType - the type of primitive to draw
|
||||
// offset - the offset in the vertex/index buffer to start at
|
||||
// numVertices - the number of vertices (indices) to draw
|
||||
// R: [none]
|
||||
public void draw(int primitiveType, int offset, int numVertices) {
|
||||
if (indices != null) { // IF Indices Exist
|
||||
indices.position(offset); // Set Index Buffer to Specified Offset
|
||||
gl.glDrawElements(primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, indices); // Draw Indexed
|
||||
} else { // ELSE No Indices Exist
|
||||
gl.glDrawArrays(primitiveType, offset, numVertices); // Draw Direct (Array)
|
||||
}
|
||||
}
|
||||
|
||||
//--Unbind--//
|
||||
// D: clear binding states when done rendering batches.
|
||||
// USAGE: call once before calling draw() multiple times for this buffer.
|
||||
// A: [none]
|
||||
// R: [none]
|
||||
public void unbind() {
|
||||
if (hasColor) // IF Vertices Have Color
|
||||
gl.glDisableClientState(GL10.GL_COLOR_ARRAY); // Clear Color State
|
||||
|
||||
if (hasTexCoords) // IF Vertices Have Texture Coords
|
||||
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Clear Texture Coords State
|
||||
|
||||
if (hasNormals) // IF Vertices Have Normals
|
||||
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); // Clear Normals State
|
||||
}
|
||||
|
||||
//--Draw Full--//
|
||||
// D: draw the vertices in the vertex/index buffers
|
||||
// NOTE: unoptimized version! use bind()/draw()/unbind() for batches
|
||||
// A: primitiveType - the type of primitive to draw
|
||||
// offset - the offset in the vertex/index buffer to start at
|
||||
// numVertices - the number of vertices (indices) to draw
|
||||
// R: [none]
|
||||
public void drawFull(int primitiveType, int offset, int numVertices) {
|
||||
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // Enable Position in Vertices
|
||||
vertices.position(0); // Set Vertex Buffer to Position
|
||||
gl.glVertexPointer(positionCnt, GL10.GL_FLOAT, vertexSize, vertices); // Set Vertex Pointer
|
||||
|
||||
if (hasColor) { // IF Vertices Have Color
|
||||
gl.glEnableClientState(GL10.GL_COLOR_ARRAY); // Enable Color in Vertices
|
||||
vertices.position(positionCnt); // Set Vertex Buffer to Color
|
||||
gl.glColorPointer(COLOR_CNT, GL10.GL_FLOAT, vertexSize, vertices); // Set Color Pointer
|
||||
}
|
||||
|
||||
if (hasTexCoords) { // IF Vertices Have Texture Coords
|
||||
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable Texture Coords in Vertices
|
||||
vertices.position(positionCnt + (hasColor ? COLOR_CNT : 0)); // Set Vertex Buffer to Texture Coords (NOTE: position based on whether color is also specified)
|
||||
gl.glTexCoordPointer(TEXCOORD_CNT, GL10.GL_FLOAT, vertexSize, vertices); // Set Texture Coords Pointer
|
||||
}
|
||||
|
||||
if (indices != null) { // IF Indices Exist
|
||||
indices.position(offset); // Set Index Buffer to Specified Offset
|
||||
gl.glDrawElements(primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, indices); // Draw Indexed
|
||||
} else { // ELSE No Indices Exist
|
||||
gl.glDrawArrays(primitiveType, offset, numVertices); // Draw Direct (Array)
|
||||
}
|
||||
|
||||
if (hasTexCoords) // IF Vertices Have Texture Coords
|
||||
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Clear Texture Coords State
|
||||
|
||||
if (hasColor) // IF Vertices Have Color
|
||||
gl.glDisableClientState(GL10.GL_COLOR_ARRAY); // Clear Color State
|
||||
}
|
||||
|
||||
//--Set Vertex Elements--//
|
||||
// D: use these methods to alter the values (position, color, textcoords, normals) for vertices
|
||||
// WARNING: these do NOT validate any values, ensure that the index AND specified
|
||||
// elements EXIST before using!!
|
||||
// A: x, y, z - the x,y,z position to set in buffer
|
||||
// r, g, b, a - the r,g,b,a color to set in buffer
|
||||
// u, v - the u,v texture coords to set in buffer
|
||||
// nx, ny, nz - the x,y,z normal to set in buffer
|
||||
// R: [none]
|
||||
void setVtxPosition(int vtxIdx, float x, float y) {
|
||||
int index = vtxIdx * vertexStride; // Calculate Actual Index
|
||||
vertices.put(index + 0, Float.floatToRawIntBits(x)); // Set X
|
||||
vertices.put(index + 1, Float.floatToRawIntBits(y)); // Set Y
|
||||
}
|
||||
|
||||
void setVtxPosition(int vtxIdx, float x, float y, float z) {
|
||||
int index = vtxIdx * vertexStride; // Calculate Actual Index
|
||||
vertices.put(index + 0, Float.floatToRawIntBits(x)); // Set X
|
||||
vertices.put(index + 1, Float.floatToRawIntBits(y)); // Set Y
|
||||
vertices.put(index + 2, Float.floatToRawIntBits(z)); // Set Z
|
||||
}
|
||||
|
||||
void setVtxColor(int vtxIdx, float r, float g, float b, float a) {
|
||||
int index = (vtxIdx * vertexStride) + positionCnt; // Calculate Actual Index
|
||||
vertices.put(index + 0, Float.floatToRawIntBits(r)); // Set Red
|
||||
vertices.put(index + 1, Float.floatToRawIntBits(g)); // Set Green
|
||||
vertices.put(index + 2, Float.floatToRawIntBits(b)); // Set Blue
|
||||
vertices.put(index + 3, Float.floatToRawIntBits(a)); // Set Alpha
|
||||
}
|
||||
|
||||
void setVtxColor(int vtxIdx, float r, float g, float b) {
|
||||
int index = (vtxIdx * vertexStride) + positionCnt; // Calculate Actual Index
|
||||
vertices.put(index + 0, Float.floatToRawIntBits(r)); // Set Red
|
||||
vertices.put(index + 1, Float.floatToRawIntBits(g)); // Set Green
|
||||
vertices.put(index + 2, Float.floatToRawIntBits(b)); // Set Blue
|
||||
}
|
||||
|
||||
void setVtxColor(int vtxIdx, float a) {
|
||||
int index = (vtxIdx * vertexStride) + positionCnt; // Calculate Actual Index
|
||||
vertices.put(index + 3, Float.floatToRawIntBits(a)); // Set Alpha
|
||||
}
|
||||
|
||||
void setVtxTexCoords(int vtxIdx, float u, float v) {
|
||||
int index = (vtxIdx * vertexStride) + positionCnt + (hasColor ? COLOR_CNT : 0); // Calculate Actual Index
|
||||
vertices.put(index + 0, Float.floatToRawIntBits(u)); // Set U
|
||||
vertices.put(index + 1, Float.floatToRawIntBits(v)); // Set V
|
||||
}
|
||||
|
||||
void setVtxNormal(int vtxIdx, float x, float y, float z) {
|
||||
int index = (vtxIdx * vertexStride) + positionCnt + (hasColor ? COLOR_CNT : 0) + (hasTexCoords ? TEXCOORD_CNT : 0); // Calculate Actual Index
|
||||
vertices.put(index + 0, Float.floatToRawIntBits(x)); // Set X
|
||||
vertices.put(index + 1, Float.floatToRawIntBits(y)); // Set Y
|
||||
vertices.put(index + 2, Float.floatToRawIntBits(z)); // Set Z
|
||||
}
|
||||
}
|
@ -1,247 +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 jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class XyFunction implements FunctionEvaluator {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nonnull
|
||||
private final String id;
|
||||
@Nonnull
|
||||
private final FunctionEvaluator evaluator;
|
||||
@Nonnull
|
||||
private Generic expression;
|
||||
@Nonnull
|
||||
private String expressionString;
|
||||
@Nullable
|
||||
private Constant xVariable;
|
||||
@Nullable
|
||||
private String xVariableName;
|
||||
@Nullable
|
||||
private Constant yVariable;
|
||||
private boolean imag;
|
||||
@Nullable
|
||||
private String yVariableName;
|
||||
private int arity;
|
||||
|
||||
public XyFunction(@Nonnull Generic expression,
|
||||
@Nullable Constant xVariable,
|
||||
@Nullable Constant yVariable,
|
||||
boolean imag) {
|
||||
this.expression = expression;
|
||||
this.xVariable = xVariable;
|
||||
this.yVariable = yVariable;
|
||||
this.imag = imag;
|
||||
|
||||
if (imag) {
|
||||
this.expressionString = "Im(" + expression.toString() + ")";
|
||||
this.evaluator = new ImaginaryEvaluator(this);
|
||||
} else {
|
||||
this.expressionString = expression.toString();
|
||||
this.evaluator = new RealEvaluator(this);
|
||||
}
|
||||
this.xVariableName = xVariable == null ? null : xVariable.getName();
|
||||
this.yVariableName = yVariable == null ? null : yVariable.getName();
|
||||
|
||||
this.arity = 2;
|
||||
if (this.yVariableName == null) {
|
||||
this.arity--;
|
||||
}
|
||||
if (this.xVariableName == null) {
|
||||
this.arity--;
|
||||
}
|
||||
|
||||
this.id = this.expressionString + "_" + Strings.getNotEmpty(this.xVariableName, "") + "_" + Strings.getNotEmpty(this.yVariableName, "");
|
||||
|
||||
}
|
||||
|
||||
public boolean isImag() {
|
||||
return imag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArity() {
|
||||
return arity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval() {
|
||||
return evaluator.eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x) {
|
||||
return evaluator.eval(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x, double y) {
|
||||
return evaluator.eval(x, y);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Generic getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Constant getXVariable() {
|
||||
return xVariable;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Constant getYVariable() {
|
||||
return yVariable;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getExpressionString() {
|
||||
return expressionString;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getXVariableName() {
|
||||
return xVariableName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getYVariableName() {
|
||||
return yVariableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof XyFunction)) return false;
|
||||
|
||||
final XyFunction that = (XyFunction) o;
|
||||
|
||||
return id.equals(that.id);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static abstract class AbstractEvaluator implements FunctionEvaluator {
|
||||
|
||||
@Nonnull
|
||||
protected final XyFunction xyFunction;
|
||||
|
||||
@Nullable
|
||||
private Double constant = null;
|
||||
|
||||
public AbstractEvaluator(@Nonnull XyFunction xyFunction) {
|
||||
this.xyFunction = xyFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double eval() {
|
||||
if (constant == null) {
|
||||
constant = eval0();
|
||||
}
|
||||
return constant;
|
||||
}
|
||||
|
||||
protected abstract double eval0();
|
||||
|
||||
@Override
|
||||
public final int getArity() {
|
||||
return xyFunction.getArity();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class RealEvaluator extends AbstractEvaluator {
|
||||
|
||||
private RealEvaluator(@Nonnull XyFunction xyFunction) {
|
||||
super(xyFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval0() {
|
||||
return PlotUtils.calculatorExpression(xyFunction.expression).realPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x) {
|
||||
return PlotUtils.calculatorExpression(xyFunction.expression, xyFunction.xVariable, x).realPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x, double y) {
|
||||
return PlotUtils.calculatorExpression(xyFunction.expression, xyFunction.xVariable, x, xyFunction.yVariable, y).realPart();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImaginaryEvaluator extends AbstractEvaluator {
|
||||
|
||||
private ImaginaryEvaluator(@Nonnull XyFunction xyFunction) {
|
||||
super(xyFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval0() {
|
||||
return PlotUtils.calculatorExpression(xyFunction.expression).imaginaryPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x) {
|
||||
return PlotUtils.calculatorExpression(xyFunction.expression, xyFunction.xVariable, x).imaginaryPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(double x, double y) {
|
||||
return PlotUtils.calculatorExpression(xyFunction.expression, xyFunction.xVariable, x, xyFunction.yVariable, y).imaginaryPart();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,77 +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;
|
||||
|
||||
class ZoomTracker {
|
||||
|
||||
public static final String TAG = "ZoomTracker";
|
||||
private static final float EPS = 1.5f;
|
||||
private static final float MIN_DISTANCE = distance(0f, 50f);
|
||||
float xValue;
|
||||
float yValue;
|
||||
private float initialXDistance;
|
||||
private float initialYDistance;
|
||||
private float initialXValue;
|
||||
private float initialYValue;
|
||||
|
||||
private static float distance(float x1, float x2) {
|
||||
final float dx = x1 - x2;
|
||||
return dx * dx;
|
||||
}
|
||||
|
||||
void start(float xValue, float yValue,
|
||||
float x1, float y1,
|
||||
float x2, float y2) {
|
||||
|
||||
initialXDistance = distance(x1, x2);
|
||||
initialYDistance = distance(y1, y2);
|
||||
|
||||
initialXValue = xValue;
|
||||
initialYValue = yValue;
|
||||
|
||||
this.xValue = xValue;
|
||||
this.yValue = yValue;
|
||||
}
|
||||
|
||||
boolean update(float x1, float y1, float x2, float y2) {
|
||||
boolean result = false;
|
||||
|
||||
if (initialXDistance > MIN_DISTANCE) {
|
||||
final float xDistance = distance(x1, x2);
|
||||
if (xDistance > EPS) {
|
||||
xValue = initialXDistance / xDistance * initialXValue;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (initialYDistance > MIN_DISTANCE) {
|
||||
final float yDistance = distance(y1, y2);
|
||||
if (yDistance > EPS) {
|
||||
yValue = initialYDistance / yDistance * initialYValue;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,19 +1,16 @@
|
||||
package org.solovyev.android.calculator.release;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.CalculatorApplication;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.about.TextHelper;
|
||||
import org.solovyev.common.text.Strings;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static org.solovyev.android.Android.getAppVersionCode;
|
||||
|
||||
public final class ReleaseNotes {
|
||||
|
||||
@Nonnull
|
||||
@ -26,7 +23,7 @@ public final class ReleaseNotes {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
|
||||
final String releaseNotesForTitle = context.getString(R.string.c_release_notes_for_title);
|
||||
final int currentVersionCode = getAppVersionCode(context);
|
||||
final int currentVersionCode = App.getAppVersionCode(context);
|
||||
|
||||
final TextHelper textHelper = new TextHelper(context.getResources(), CalculatorApplication.class.getPackage().getName());
|
||||
|
||||
@ -53,7 +50,7 @@ public final class ReleaseNotes {
|
||||
public static List<Integer> getReleaseNotesVersions(@Nonnull Context context, int minVersion) {
|
||||
final List<Integer> releaseNotes = new ArrayList<>();
|
||||
|
||||
final int currentVersionCode = getAppVersionCode(context);
|
||||
final int currentVersionCode = App.getAppVersionCode(context);
|
||||
final TextHelper textHelper = new TextHelper(context.getResources(), CalculatorApplication.class.getPackage().getName());
|
||||
|
||||
for (int versionCode = currentVersionCode; versionCode >= minVersion; versionCode--) {
|
||||
@ -70,7 +67,7 @@ public final class ReleaseNotes {
|
||||
}
|
||||
|
||||
public static boolean hasReleaseNotes(@Nonnull Context context, int minVersion) {
|
||||
final int currentVersionCode = getAppVersionCode(context);
|
||||
final int currentVersionCode = App.getAppVersionCode(context);
|
||||
final TextHelper textHelper = new TextHelper(context.getResources(), CalculatorApplication.class.getPackage().getName());
|
||||
|
||||
for (int versionCode = currentVersionCode; versionCode >= minVersion; versionCode--) {
|
||||
|
@ -45,7 +45,6 @@ import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import dagger.Lazy;
|
||||
import jscl.math.function.IConstant;
|
||||
import org.solovyev.android.Activities;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.entities.EntityRemovalDialog;
|
||||
@ -125,7 +124,7 @@ public class EditVariableFragment extends BaseDialogFragment implements View.OnF
|
||||
public static void showDialog(@Nullable CppVariable variable, @Nonnull Context context) {
|
||||
if (!(context instanceof VariablesActivity)) {
|
||||
final Intent intent = new Intent(context, VariablesActivity.getClass(context));
|
||||
Activities.addIntentFlags(intent, false, context);
|
||||
App.addIntentFlags(intent, false, context);
|
||||
intent.putExtra(VariablesActivity.EXTRA_VARIABLE, variable);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
|
@ -8,7 +8,7 @@ import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.keyboard.BaseFloatingKeyboard;
|
||||
import org.solovyev.android.calculator.view.EditTextLongClickEraser;
|
||||
@ -145,7 +145,7 @@ public class GreekFloatingKeyboard extends BaseFloatingKeyboard implements View.
|
||||
|
||||
private void changeCase(@NonNull Button button) {
|
||||
final boolean upperCase = button.getText().equals("↑");
|
||||
Views.processViewsOfType(user.getKeyboard(), Button.class, new Views.ViewProcessor<Button>() {
|
||||
App.processViewsOfType(user.getKeyboard(), Button.class, new App.ViewProcessor<Button>() {
|
||||
@Override
|
||||
public void process(@Nonnull Button key) {
|
||||
final String letter = key.getText().toString();
|
||||
|
@ -41,7 +41,6 @@ import android.text.TextUtils;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.widget.RemoteViews;
|
||||
import org.solovyev.android.Check;
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.Preferences.SimpleTheme;
|
||||
import org.solovyev.android.calculator.buttons.CppButton;
|
||||
@ -182,7 +181,7 @@ public class CalculatorWidget extends AppWidgetProvider {
|
||||
return getDefaultLayout(theme);
|
||||
}
|
||||
|
||||
final int widgetMinHeight = Views.toPixels(resources.getDisplayMetrics(), options.getInt(OPTION_APPWIDGET_MIN_HEIGHT, 0));
|
||||
final int widgetMinHeight = App.toPixels(resources.getDisplayMetrics(), options.getInt(OPTION_APPWIDGET_MIN_HEIGHT, 0));
|
||||
final int lockScreenMinHeight = resources.getDimensionPixelSize(R.dimen.min_expanded_height_lock_screen);
|
||||
final boolean expanded = widgetMinHeight >= lockScreenMinHeight;
|
||||
if (expanded) {
|
||||
|
@ -30,18 +30,15 @@ import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import org.solovyev.android.Views;
|
||||
import org.solovyev.android.calculator.App;
|
||||
import org.solovyev.android.calculator.Preferences;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.keyboard.BaseKeyboardUi;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ChooseThemeWizardStep extends WizardFragment implements AdapterView.OnItemSelectedListener {
|
||||
|
||||
@Nonnull
|
||||
@ -89,7 +86,7 @@ public class ChooseThemeWizardStep extends WizardFragment implements AdapterView
|
||||
preview.removeAllViews();
|
||||
final ContextThemeWrapper context = new ContextThemeWrapper(getActivity(), theme.theme);
|
||||
LayoutInflater.from(context).inflate(R.layout.cpp_wizard_step_choose_theme_preview, preview);
|
||||
Views.processViews(preview, new Views.ViewProcessor<View>() {
|
||||
App.processViews(preview, new App.ViewProcessor<View>() {
|
||||
@Override
|
||||
public void process(@Nonnull View view) {
|
||||
BaseKeyboardUi.adjustButton(view);
|
||||
|
@ -1,84 +0,0 @@
|
||||
<?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
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
xmlns:picker="http://schemas.android.com/apk/res-auto"
|
||||
a:id="@+id/main_fragment_layout"
|
||||
style="@style/CppFragment"
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="match_parent">
|
||||
|
||||
<org.solovyev.android.calculator.AdView style="@style/CppAd" />
|
||||
|
||||
<LinearLayout
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="match_parent"
|
||||
a:orientation="vertical">
|
||||
|
||||
<org.solovyev.android.view.Picker
|
||||
a:id="@+id/matrix_cols_count_picker"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="wrap_content"
|
||||
a:layout_gravity="center"
|
||||
picker:orientation="horizontal" />
|
||||
|
||||
<LinearLayout
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="match_parent"
|
||||
a:gravity="center"
|
||||
a:orientation="horizontal">
|
||||
|
||||
<org.solovyev.android.view.Picker
|
||||
a:id="@+id/matrix_rows_count_picker"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="wrap_content" />
|
||||
|
||||
<ScrollView
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="match_parent"
|
||||
a:scrollbars="vertical">
|
||||
|
||||
<HorizontalScrollView
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="wrap_content"
|
||||
a:minHeight="300dp">
|
||||
|
||||
<org.solovyev.android.calculator.matrix.MatrixView
|
||||
a:id="@+id/matrix_layout"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="match_parent"
|
||||
a:minWidth="300dp" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -15,4 +15,23 @@
|
||||
<string name="dimensions_y_min" translatable="false">Y min</string>
|
||||
<string name="dimensions_y_max" translatable="false">Y max</string>
|
||||
<string name="cpp_function_body" translatable="false">f(x, y)</string>
|
||||
<string-array name="cpp_prefs_precisions" translatable="false">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>6</item>
|
||||
<item>7</item>
|
||||
<item>8</item>
|
||||
<item>9</item>
|
||||
<item>10</item>
|
||||
<item>11</item>
|
||||
<item>12</item>
|
||||
<item>13</item>
|
||||
<item>14</item>
|
||||
<item>15</item>
|
||||
<item>16</item>
|
||||
</string-array>
|
||||
</resources>
|
@ -22,8 +22,7 @@
|
||||
~ Site: http://se.solovyev.org
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
xmlns:range="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<android.preference.CheckBoxPreference
|
||||
a:defaultValue="true"
|
||||
@ -31,12 +30,12 @@
|
||||
a:summary="@string/c_calc_round_result_summary"
|
||||
a:title="@string/c_calc_round_result_title" />
|
||||
|
||||
<org.solovyev.android.prefs.IntegerPickerDialogPreference
|
||||
a:defaultValue="5"
|
||||
<ListPreference
|
||||
a:entries="@array/cpp_prefs_precisions"
|
||||
a:entryValues="@array/cpp_prefs_precisions"
|
||||
a:key="engine.output.precision"
|
||||
a:summary="@string/c_calc_result_precision_summary"
|
||||
a:title="@string/p_calc_result_precision_title"
|
||||
range:boundaries="0;16" />
|
||||
a:title="@string/p_calc_result_precision_title" />
|
||||
|
||||
<android.preference.CheckBoxPreference
|
||||
a:defaultValue="false"
|
||||
|
@ -24,7 +24,6 @@ apply plugin: 'java'
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
compile 'org.solovyev:common-core:1.0.7'
|
||||
compile 'org.solovyev:common-msg:1.0.7'
|
||||
compile 'com.google.code.findbugs:annotations:2.0.1'
|
||||
compile 'xerces:xercesImpl:2.8.0'
|
||||
|
Loading…
Reference in New Issue
Block a user