new plotter

This commit is contained in:
Sergey Solovyev 2013-01-14 17:52:22 +04:00
parent 8fb1272bd2
commit f08e03761b
15 changed files with 187 additions and 54 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -298,6 +298,8 @@
<string name="cpp_dash_dotted_line_style">Dash dotted (-.-.-)</string>
<string name="cpp_plotter">Function plotter</string>
<string name="cpp_plot_screenshot">Capture screenshot</string>
<string name="cpp_plot_screenshot_saved">Screenshot successfully saved: %1$s!</string>
<string name="cpp_plot_unable_to_save_screenshot">Screenshot cannot be saved as sdcard is not mounted. Mount sdcard and try again!</string>
</resources>

View File

@ -6,7 +6,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;
import org.jetbrains.annotations.NotNull;
@ -67,14 +66,10 @@ public final class AndroidUtils2 {
public static String saveBitmap(@NotNull Bitmap bitmap,
@NotNull String path,
@NotNull String fileName) {
final File sdcardPath = Environment.getExternalStorageDirectory();
final File filePath = new File(sdcardPath, path);
final File filePath = new File(path);
filePath.mkdirs();
final String fullFileName = fileName + "_" + System.currentTimeMillis() + ".png";
final File file = new File(path, fullFileName);
final File file = new File(path, fileName);
if (!file.exists()) {
final String name = file.getAbsolutePath();

View File

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.android.vending.BILLING"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--TODO: REMOVE IN PRODUCTION-->
<!--<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>-->

View File

@ -23,6 +23,11 @@
a:icon="@drawable/ab_list"
a:showAsAction="always"/>
<item a:id="@+id/menu_plot_schreeshot"
a:title="@string/cpp_plot_screenshot"
a:icon="@drawable/ab_camera"
a:showAsAction="always"/>
<item a:id="@+id/menu_plot_settings"
a:title="@string/c_settings"
a:icon="@drawable/ab_settings"

View File

@ -2,8 +2,10 @@ package org.solovyev.android.calculator.plot;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.view.View;
@ -13,17 +15,30 @@ import com.actionbarsherlock.view.MenuItem;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.android.AndroidUtils2;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventHolder;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorFragment;
import org.solovyev.android.calculator.CalculatorUtils;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.menu.AMenuItem;
import org.solovyev.android.menu.ActivityMenu;
import org.solovyev.android.menu.IdentifiableMenuItem;
import org.solovyev.android.menu.ListActivityMenu;
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
import org.solovyev.common.JPredicate;
import org.solovyev.common.msg.MessageType;
import java.io.File;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@ -68,6 +83,10 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
@NotNull
private PlotData plotData = new PlotData(Collections.<PlotFunction>emptyList(), false);
@NotNull
private PlotBoundaries initialPlotBoundaries;
@NotNull
private ActivityMenu<Menu, MenuItem> fragmentMenu;
@ -85,8 +104,8 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
public void onCreate(Bundle in) {
super.onCreate(in);
// todo serso: init variable properly
boolean paneFragment = true;
@ -96,6 +115,19 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
this.bgColor = getResources().getColor(android.R.color.transparent);
}
final PlotBoundaries savedPlotBoundaries;
if (in != null) {
savedPlotBoundaries = (PlotBoundaries) in.getSerializable(PLOT_BOUNDARIES);
} else {
savedPlotBoundaries = null;
}
if (savedPlotBoundaries != null) {
initialPlotBoundaries = savedPlotBoundaries;
} else {
initialPlotBoundaries = PlotBoundaries.newDefaultInstance();
}
setHasOptionsMenu(true);
}
@ -117,8 +149,8 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
super.onResume();
plotData = Locator.getInstance().getPlotter().getPlotData();
createChart(plotData);
createGraphicalView(getView(), plotData);
createChart(plotData, initialPlotBoundaries);
createGraphicalView(getView(), plotData, initialPlotBoundaries);
getSherlockActivity().invalidateOptionsMenu();
}
@ -140,11 +172,11 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
public void run() {
getSherlockActivity().invalidateOptionsMenu();
createChart(plotData);
createChart(plotData, initialPlotBoundaries);
final View view = getView();
if (view != null) {
createGraphicalView(view, plotData);
createGraphicalView(view, plotData, initialPlotBoundaries);
}
}
});
@ -152,16 +184,16 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
protected abstract void onError();
protected abstract void createGraphicalView(@NotNull View view, @NotNull PlotData plotData);
protected abstract void createGraphicalView(@NotNull View view, @NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries);
protected abstract void createChart(@NotNull PlotData plotData);
protected abstract void createChart(@NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries);
protected double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
protected double getMaxXValue(@Nullable PlotBoundaries plotBoundaries) {
return plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.getXMax();
}
protected double getMinValue(@Nullable PlotBoundaries plotBoundaries) {
protected double getMinXValue(@Nullable PlotBoundaries plotBoundaries) {
return plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.getXMin();
}
@ -232,8 +264,23 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
};
menuItems.add(plot2dMenuItem);
final IdentifiableMenuItem<MenuItem> captureScreenshotMenuItem = new IdentifiableMenuItem<MenuItem>() {
@NotNull
@Override
public Integer getItemId() {
return R.id.menu_plot_schreeshot;
}
@Override
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
captureScreehshot();
}
};
menuItems.add(captureScreenshotMenuItem);
final boolean plot3dVisible = !plotData.isPlot3d() && is3dPlotSupported();
final boolean plot2dVisible = plotData.isPlot3d() && Locator.getInstance().getPlotter().is2dPlotPossible();
final boolean captureScreenshotVisible = isScreenshotSupported();
fragmentMenu = ListActivityMenu.fromResource(R.menu.plot_menu, menuItems, SherlockMenuHelper.getInstance(), new JPredicate<AMenuItem<MenuItem>>() {
@Override
public boolean apply(@Nullable AMenuItem<MenuItem> menuItem) {
@ -241,6 +288,8 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
return !plot3dVisible;
} else if ( menuItem == plot2dMenuItem ) {
return !plot2dVisible;
} else if ( menuItem == captureScreenshotMenuItem ) {
return !captureScreenshotVisible;
}
return false;
}
@ -252,6 +301,33 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment
}
}
protected abstract boolean isScreenshotSupported();
@NotNull
protected abstract Bitmap getScreehshot();
private void captureScreehshot() {
if ( isScreenshotSupported() ) {
final Bitmap screenshot = getScreehshot();
final String screenShotFileName = generateScreenshotFileName();
final File externalFilesDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (externalFilesDir != null) {
final String path = externalFilesDir.getPath();
AndroidUtils2.saveBitmap(screenshot, path, screenShotFileName);
Locator.getInstance().getNotifier().showMessage(R.string.cpp_plot_screenshot_saved, MessageType.info, path + "/" + screenShotFileName);
} else {
Locator.getInstance().getNotifier().showMessage(R.string.cpp_plot_unable_to_save_screenshot, MessageType.error);
}
}
}
private String generateScreenshotFileName() {
final Date now = new Date();
final String timestamp = new SimpleDateFormat("yyyy.MM.dd HH.mm.ss.S").format(now);
return "cpp-screenshot-" + timestamp + ".png";
}
protected abstract boolean is3dPlotSupported();
@Override

View File

@ -1,5 +1,6 @@
package org.solovyev.android.calculator.plot;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
@ -35,7 +36,7 @@ public class CalculatorArityPlotFragment extends AbstractCalculatorPlotFragment
}
@Override
protected void createGraphicalView(@NotNull View root, @NotNull PlotData plotData) {
protected void createGraphicalView(@NotNull View root, @NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries) {
// remove old
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
@ -74,12 +75,25 @@ public class CalculatorArityPlotFragment extends AbstractCalculatorPlotFragment
graphView.init(FunctionViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
graphView.setFunctionPlotDefs(arityFunctions);
graphView.setXRange((float)plotBoundaries.getXMin(), (float)plotBoundaries.getXMax());
graphContainer.addView((View) graphView);
}
@Override
protected void createChart(@NotNull PlotData plotData) {
protected void createChart(@NotNull PlotData plotData, @NotNull PlotBoundaries plotBoundaries) {
}
@Override
protected boolean isScreenshotSupported() {
return true;
}
@NotNull
@Override
protected Bitmap getScreehshot() {
assert this.graphView != null;
return this.graphView.captureScreenshot();
}
@Override

View File

@ -11,9 +11,13 @@ import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils2;
import javax.microedition.khronos.egl.*;
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;
import java.nio.ByteBuffer;
@ -36,10 +40,11 @@ abstract class GLView extends SurfaceView implements SurfaceHolder.Callback {
abstract void onSurfaceCreated(GL10 gl, int width, int height);
public String captureScreenshot() {
Bitmap bitmap = getRawPixels(gl, width, height);
bitmapBGRtoRGB(bitmap, width, height);
return AndroidUtils2.saveBitmap(bitmap, GraphView.SCREENSHOT_DIR, "calculator");
@NotNull
public Bitmap captureScreenshot() {
final Bitmap result = getRawPixels(gl, width, height);
bitmapBGRtoRGB(result, width, height);
return result;
}
private static Bitmap getRawPixels(GL10 gl, int width, int height) {

View File

@ -4,7 +4,12 @@ package org.solovyev.android.calculator.plot;
import android.content.Context;
import android.graphics.*;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@ -12,7 +17,6 @@ import android.widget.Scroller;
import android.widget.ZoomButtonsController;
import org.javia.arity.Function;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils2;
import java.util.ArrayList;
import java.util.Collections;
@ -67,11 +71,19 @@ public class Graph2dView extends View implements GraphView {
textPaint.setAntiAlias(true);
}
public String captureScreenshot() {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
@NotNull
public Bitmap captureScreenshot() {
final Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(result);
onDraw(canvas);
return AndroidUtils2.saveBitmap(bitmap, GraphView.SCREENSHOT_DIR, "calculator");
return result;
}
@Override
public void setXRange(float xMin, float xMax) {
this.gwidth = xMax - xMin;
this.currentX = xMax - this.gwidth / 2;
}
private void clearAllGraphs() {
@ -517,11 +529,11 @@ public class Graph2dView extends View implements GraphView {
}
private boolean canZoomIn() {
return gwidth > 1f;
return true;
}
private boolean canZoomOut() {
return gwidth < 50;
return true;
}
private void invalidateGraphs() {

View File

@ -4,7 +4,12 @@ package org.solovyev.android.calculator.plot;
import android.content.Context;
import android.graphics.*;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@ -12,7 +17,6 @@ import android.widget.Scroller;
import android.widget.ZoomButtonsController;
import org.javia.arity.Function;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils2;
import java.util.ArrayList;
import java.util.Collections;
@ -94,11 +98,18 @@ public class Graph2dViewNew extends View implements GraphView {
height = this.getHeight();
}
public String captureScreenshot() {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
@NotNull
public Bitmap captureScreenshot() {
final Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(result);
onDraw(canvas);
return AndroidUtils2.saveBitmap(bitmap, GraphView.SCREENSHOT_DIR, "calculator");
return result;
}
@Override
public void setXRange(float xMin, float xMax) {
this.x0 = xMin + graphWidth / 2;
this.graphWidth = xMax - xMin;
}
private void clearAllGraphs() {

View File

@ -101,11 +101,11 @@ public class Graph3dView extends GLView implements GraphView {
}
private boolean canZoomIn(float zoom) {
return zoom > .2f;
return true;
}
private boolean canZoomOut(float zoom) {
return zoom < 5;
return true;
}
@Override
@ -190,6 +190,11 @@ public class Graph3dView extends GLView implements GraphView {
isDirty = true;
}
@Override
public void setXRange(float xMin, float xMax) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void onSurfaceCreated(GL10 gl, int width, int height) {
gl.glDisable(GL10.GL_DITHER);

View File

@ -2,6 +2,7 @@
package org.solovyev.android.calculator.plot;
import android.graphics.Bitmap;
import android.widget.ZoomButtonsController;
import org.jetbrains.annotations.NotNull;
@ -18,7 +19,13 @@ public interface GraphView extends ZoomButtonsController.OnZoomListener, TouchHa
public void onPause();
public void onResume();
public String captureScreenshot();
@NotNull
public Bitmap captureScreenshot();
void setXRange(float xMin, float xMax);
/* void increaseDensity();
void decreaseDensity();*/
/*
**********************************************************************