diff --git a/android-app-core/res/drawable-hdpi/ab_camera.png b/android-app-core/res/drawable-hdpi/ab_camera.png new file mode 100644 index 00000000..4936d150 Binary files /dev/null and b/android-app-core/res/drawable-hdpi/ab_camera.png differ diff --git a/android-app-core/res/drawable-ldpi/ab_camera.png b/android-app-core/res/drawable-ldpi/ab_camera.png new file mode 100644 index 00000000..4d3a6a5d Binary files /dev/null and b/android-app-core/res/drawable-ldpi/ab_camera.png differ diff --git a/android-app-core/res/drawable-mdpi/ab_camera.png b/android-app-core/res/drawable-mdpi/ab_camera.png new file mode 100644 index 00000000..f8cf93c7 Binary files /dev/null and b/android-app-core/res/drawable-mdpi/ab_camera.png differ diff --git a/android-app-core/res/drawable-xhdpi/ab_camera.png b/android-app-core/res/drawable-xhdpi/ab_camera.png new file mode 100644 index 00000000..7875aa3f Binary files /dev/null and b/android-app-core/res/drawable-xhdpi/ab_camera.png differ diff --git a/android-app-core/res/values/text_strings.xml b/android-app-core/res/values/text_strings.xml index dfe5a77d..2d2428c6 100644 --- a/android-app-core/res/values/text_strings.xml +++ b/android-app-core/res/values/text_strings.xml @@ -298,6 +298,8 @@ Dash dotted (-.-.-) Function plotter - + Capture screenshot + Screenshot successfully saved: %1$s! + Screenshot cannot be saved as sdcard is not mounted. Mount sdcard and try again! \ No newline at end of file diff --git a/android-app-core/src/main/java/org/solovyev/android/AndroidUtils2.java b/android-app-core/src/main/java/org/solovyev/android/AndroidUtils2.java index bfc6b5ed..ad7fba62 100644 --- a/android-app-core/src/main/java/org/solovyev/android/AndroidUtils2.java +++ b/android-app-core/src/main/java/org/solovyev/android/AndroidUtils2.java @@ -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,20 +66,16 @@ 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(); FileOutputStream fos = null; try { - fos = new FileOutputStream(name); + fos = new FileOutputStream(name); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); } catch (FileNotFoundException e) { diff --git a/android-app/AndroidManifest.xml b/android-app/AndroidManifest.xml index 4b1d1037..e0b077ba 100644 --- a/android-app/AndroidManifest.xml +++ b/android-app/AndroidManifest.xml @@ -5,6 +5,7 @@ + diff --git a/android-app/res/menu/plot_menu.xml b/android-app/res/menu/plot_menu.xml index 7bd50e8d..e4e3af02 100644 --- a/android-app/res/menu/plot_menu.xml +++ b/android-app/res/menu/plot_menu.xml @@ -23,6 +23,11 @@ a:icon="@drawable/ab_list" a:showAsAction="always"/> + + emptyList(), false); - @NotNull + @NotNull + private PlotBoundaries initialPlotBoundaries; + + + @NotNull private ActivityMenu fragmentMenu; // thread which calculated data for graph view @@ -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,7 +115,20 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment this.bgColor = getResources().getColor(android.R.color.transparent); } - setHasOptionsMenu(true); + 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); } @Override @@ -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(); } @@ -227,13 +259,28 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment @Override public void onClick(@NotNull MenuItem data, @NotNull Context context) { - Locator.getInstance().getPlotter().setPlot3d(false); + Locator.getInstance().getPlotter().setPlot3d(false); } }; menuItems.add(plot2dMenuItem); + final IdentifiableMenuItem captureScreenshotMenuItem = new IdentifiableMenuItem() { + @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>() { @Override public boolean apply(@Nullable AMenuItem menuItem) { @@ -241,7 +288,9 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment return !plot3dVisible; } else if ( menuItem == plot2dMenuItem ) { return !plot2dVisible; - } + } else if ( menuItem == captureScreenshotMenuItem ) { + return !captureScreenshotVisible; + } return false; } }); @@ -252,7 +301,34 @@ public abstract class AbstractCalculatorPlotFragment extends CalculatorFragment } } - protected abstract boolean is3dPlotSupported(); + 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 public void onPrepareOptionsMenu(Menu menu) { diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorArityPlotFragment.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorArityPlotFragment.java index c664d988..de49d5e9 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorArityPlotFragment.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/CalculatorArityPlotFragment.java @@ -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,15 +75,28 @@ 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 + @Override + protected boolean isScreenshotSupported() { + return true; + } + + @NotNull + @Override + protected Bitmap getScreehshot() { + assert this.graphView != null; + return this.graphView.captureScreenshot(); + } + + @Override protected boolean is3dPlotSupported() { return true; } diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/GLView.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/GLView.java index f8184816..3a9fa2b8 100755 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/GLView.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/GLView.java @@ -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) { diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dView.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dView.java index dab68d0e..d818fbe9 100755 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dView.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dView.java @@ -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,14 +71,22 @@ 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; } - private void clearAllGraphs() { + @Override + public void setXRange(float xMin, float xMax) { + this.gwidth = xMax - xMin; + this.currentX = xMax - this.gwidth / 2; + + } + + private void clearAllGraphs() { for (GraphData graph : graphs) { graph.clear(); } @@ -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() { diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dViewNew.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dViewNew.java index 15cb4d1d..90d9da70 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dViewNew.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph2dViewNew.java @@ -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,14 +98,21 @@ 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; } - private void clearAllGraphs() { + @Override + public void setXRange(float xMin, float xMax) { + this.x0 = xMin + graphWidth / 2; + this.graphWidth = xMax - xMin; + } + + private void clearAllGraphs() { for (GraphData graph : graphs) { graph.clear(); } diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph3dView.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph3dView.java index 0001594a..4afcca5d 100755 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph3dView.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/Graph3dView.java @@ -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,7 +190,12 @@ public class Graph3dView extends GLView implements GraphView { isDirty = true; } - @Override + @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); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); diff --git a/android-app/src/main/java/org/solovyev/android/calculator/plot/GraphView.java b/android-app/src/main/java/org/solovyev/android/calculator/plot/GraphView.java index 473feea2..58b32eb5 100755 --- a/android-app/src/main/java/org/solovyev/android/calculator/plot/GraphView.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/plot/GraphView.java @@ -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();*/ /* **********************************************************************