create changelog entry
[debian/openrocket] / android / src / net / sf / openrocket / android / motor / BurnPlotFragment.java
index 1f0c72254a59a5907368260cd284969ca7025bc2..eff07756a696c5a4d7e2b202b879d95cb8de07ae 100644 (file)
@@ -1,46 +1,34 @@
 package net.sf.openrocket.android.motor;\r
 \r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.Vector;\r
-\r
-import net.sf.openrocket.R;\r
 import net.sf.openrocket.android.db.DbAdapter;\r
 import net.sf.openrocket.android.util.AndroidLogWrapper;\r
+\r
+import org.achartengine.GraphicalView;\r
+import org.achartengine.chart.LineChart;\r
+import org.achartengine.chart.PointStyle;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.model.XYSeries;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYSeriesRenderer;\r
+\r
 import android.graphics.Color;\r
-import android.graphics.Paint;\r
-import android.graphics.PointF;\r
+import android.graphics.Paint.Align;\r
 import android.os.Bundle;\r
 import android.support.v4.app.Fragment;\r
 import android.view.LayoutInflater;\r
-import android.view.MotionEvent;\r
-import android.view.ScaleGestureDetector;\r
 import android.view.View;\r
-import android.view.View.OnTouchListener;\r
 import android.view.ViewGroup;\r
 \r
-import com.androidplot.xy.BoundaryMode;\r
-import com.androidplot.xy.LineAndPointFormatter;\r
-import com.androidplot.xy.LineAndPointRenderer;\r
-import com.androidplot.xy.SimpleXYSeries;\r
-import com.androidplot.xy.XYPlot;\r
-import com.androidplot.xy.YValueMarker;\r
-\r
-public class BurnPlotFragment extends Fragment implements OnTouchListener {\r
+public class BurnPlotFragment extends Fragment {\r
 \r
        private ExtendedThrustCurveMotor motor;\r
        private long motorId;\r
 \r
-       private XYPlot mySimpleXYPlot;\r
-       private SimpleXYSeries mySeries;\r
-       private PointF minXY;\r
-       private PointF maxXY;\r
-\r
-       private float absMinX;\r
-       private float absMaxX;\r
-\r
-       private ScaleGestureDetector mScaleDetector;\r
-       private float mScaleFactor = 1.f;\r
+       /** The encapsulated graphical view. */\r
+       private GraphicalView mView;\r
+       /** The chart to be drawn. */\r
+       private XYChart mChart;\r
 \r
        public static BurnPlotFragment newInstance( long motorId ) {\r
                BurnPlotFragment frag = new BurnPlotFragment();\r
@@ -84,190 +72,87 @@ public class BurnPlotFragment extends Fragment implements OnTouchListener {
        public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
                        Bundle savedInstanceState) {\r
                AndroidLogWrapper.d(BurnPlotFragment.class,"onCreateView");\r
-               View v = inflater.inflate(R.layout.motor_burn, container, false);\r
-               mySimpleXYPlot = (XYPlot) v.findViewById(R.id.xyplot);\r
-               mySimpleXYPlot.setOnTouchListener(this);\r
-               mScaleDetector = new ScaleGestureDetector(v.getContext(), new ScaleListener());\r
+               \r
                init(motor);\r
-               return v;\r
-       }\r
-\r
-       private static List<Double> fromArray( double[] arry ) {\r
-               List<Double> l = new ArrayList<Double>(arry.length);\r
-               for( double d: arry ) {\r
-                       l.add(d);\r
-               }\r
-               return l;\r
+               mView = new GraphicalView(container.getContext(), mChart);\r
+               return mView;\r
        }\r
 \r
        private void init( ExtendedThrustCurveMotor motor ) {\r
 \r
-               mySimpleXYPlot.setUserDomainOrigin(0);\r
-               mySimpleXYPlot.setUserRangeOrigin(0);\r
-               mySimpleXYPlot.setRangeLabel("impuse (n)");\r
-               mySimpleXYPlot.setDomainLabel("time (s)");\r
-               YValueMarker average = new YValueMarker(motor.getThrustCurveMotor().getAverageThrustEstimate(),"average" );\r
-               average.getLinePaint().setColor(Color.BLACK);\r
-               average.getTextPaint().setColor(Color.BLACK);\r
-               mySimpleXYPlot.addMarker( average );\r
-               mySimpleXYPlot.disableAllMarkup();\r
-\r
-               try {\r
-                       mySeries = new SimpleXYSeries( \r
-                                       fromArray(motor.getThrustCurveMotor().getTimePoints()),\r
-                                       fromArray(motor.getThrustCurveMotor().getThrustPoints()), \r
-                                       motor.getThrustCurveMotor().getManufacturer().getDisplayName() + " " + motor.getThrustCurveMotor().getDesignation()\r
-                                       );\r
-               } catch ( Exception ex ) {\r
-\r
-                       Vector<Double> data = new Vector<Double>();\r
-                       data.add(0.0);\r
-                       data.add(0.0);\r
-                       data.add(1.0);\r
-                       data.add(1.0);\r
-                       mySeries = new SimpleXYSeries(data, SimpleXYSeries.ArrayFormat.XY_VALS_INTERLEAVED,"no data");\r
-               }\r
-\r
-               LineAndPointFormatter formatter= new LineAndPointFormatter(Color.RED, Color.GREEN, Color.GREEN);\r
-\r
-               formatter.getLinePaint().setShadowLayer(0, 0, 0, 0);\r
-               formatter.getVertexPaint().setShadowLayer(0, 0, 0, 0);\r
-               mySimpleXYPlot.addSeries(mySeries, LineAndPointRenderer.class,formatter);\r
-\r
-               //Set of internal variables for keeping track of the boundaries\r
-               mySimpleXYPlot.calculateMinMaxVals();\r
-\r
-               mySimpleXYPlot.redraw();\r
-\r
-               minXY=new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),mySimpleXYPlot.getCalculatedMinY().floatValue());\r
-               maxXY=new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),mySimpleXYPlot.getCalculatedMaxY().floatValue());\r
-\r
-               absMinX = minXY.x;\r
-               absMaxX = maxXY.x;\r
-\r
-       }\r
-\r
-       private float mPosX;\r
-       private float mPosY;\r
-\r
-       private float mLastTouchX;\r
-       private float mLastTouchY;\r
-\r
-       private int mActivePointerId = -1;\r
-\r
-       @Override\r
-       public boolean onTouch(View arg0, MotionEvent event) {\r
-               mScaleDetector.onTouchEvent(event);\r
-\r
-               final int action = event.getAction();\r
-               switch ( action & MotionEvent.ACTION_MASK ) {\r
-               case MotionEvent.ACTION_DOWN: {\r
-                       final float x = event.getX();\r
-                       final float y = event.getY();\r
-\r
-                       mLastTouchX = x;\r
-                       mLastTouchY = y;\r
-\r
-                       mActivePointerId = event.getPointerId(0);\r
-                       break;\r
-               }\r
-\r
-               case MotionEvent.ACTION_MOVE: {\r
-                       final int pointerIndex = event.findPointerIndex(mActivePointerId);\r
-                       final float x = event.getX(pointerIndex);\r
-                       final float y = event.getY(pointerIndex);\r
-\r
-                       if (!mScaleDetector.isInProgress()) {\r
-                               final float dx = x - mLastTouchX;\r
-                               final float dy = y - mLastTouchY;\r
-\r
-                               mPosX += dx;\r
-                               mPosY += dy;\r
-                               scroll(dx);\r
-                               // do scroll.\r
-\r
+               XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(1);\r
+\r
+               renderer.setAxisTitleTextSize(16);\r
+               renderer.setChartTitleTextSize(20);\r
+               renderer.setLabelsTextSize(15);\r
+               renderer.setLegendTextSize(15);\r
+               renderer.setPointSize(5f);\r
+               renderer.setXLabels(10);\r
+               renderer.setYLabels(10);\r
+               renderer.setShowGrid(true);\r
+               renderer.setZoomButtonsVisible(false);\r
+               renderer.setZoomEnabled(false,false);\r
+               renderer.setPanEnabled(false,false);\r
+               renderer.setMargins(new int[] { 50, 40, 10, 20 });\r
+               renderer.setShowLegend(false);\r
+               renderer.setAxesColor(Color.LTGRAY);\r
+               renderer.setLabelsColor(Color.LTGRAY);\r
+\r
+               renderer.setChartTitle(motor.getManufacturer() + " " + motor.getDesignation());\r
+\r
+               renderer.setXTitle("time (s)");\r
+               renderer.setXLabelsAlign(Align.RIGHT);\r
+\r
+               renderer.setYTitle("impuse (n)");\r
+               renderer.setYLabelsAlign(Align.RIGHT,0);\r
+\r
+               XYSeriesRenderer r = new XYSeriesRenderer();\r
+               r.setColor(Color.RED);\r
+               r.setPointStyle(PointStyle.CIRCLE);\r
+               r.setFillPoints(true);\r
+               renderer.addSeriesRenderer(r);\r
+               // setting the YAximMin to 0 locks the origins.\r
+               renderer.setYAxisMin(0.0, 0);\r
+\r
+               // TODO get markers working in achartengine\r
+               //YValueMarker average = new YValueMarker(motor.getThrustCurveMotor().getAverageThrustEstimate(),"average" );\r
+               //average.getLinePaint().setColor(Color.BLACK);\r
+               //average.getTextPaint().setColor(Color.BLACK);\r
+               //mySimpleXYPlot.addMarker( average );\r
+\r
+               XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();\r
+\r
+               XYSeries series = new XYSeries(motor.getDesignation(), 0);\r
+               \r
+               double[] timePoints = motor.getTimePoints();\r
+               double[] thrustPoints = motor.getThrustPoints();\r
+\r
+               // We are going to abuse this loop to also compute the Y axis max.\r
+               int maxy = 0;\r
+               int datasize = timePoints.length;\r
+               for( int i = 0; i<datasize; i++ ) {\r
+                       series.add(timePoints[i], thrustPoints[i]);\r
+                       int ceil =(int) Math.ceil(thrustPoints[i]);\r
+                       if ( ceil > maxy ) {\r
+                               maxy = ceil;\r
                        }\r
-                       mLastTouchX = x;\r
-                       mLastTouchY = y;\r
-\r
-                       break;\r
                }\r
-\r
-               case MotionEvent.ACTION_UP: {\r
-                       mActivePointerId = -1;\r
-                       break;\r
-               }\r
-\r
-               case MotionEvent.ACTION_CANCEL: {\r
-                       mActivePointerId = -1;\r
-                       break;\r
-               }\r
-\r
-               case MotionEvent.ACTION_POINTER_UP: {\r
-                       final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;\r
-                       final int pointerId = event.getPointerId(pointerIndex);\r
-                       if (pointerId == mActivePointerId) {\r
-                               // This was our active pointer going up.  choose a new active pointer and adjust accordingly.\r
-                               final int newPointerIndex = pointerIndex ==0 ? 1:0;\r
-                               mLastTouchX = event.getX(newPointerIndex);\r
-                               mLastTouchY = event.getY(newPointerIndex);\r
-                               mActivePointerId = event.getPointerId(newPointerIndex);\r
-                       }\r
-                       break;\r
+               renderer.setYAxisMax(maxy);\r
+               \r
+               // Find the X axis max.  compute it as next larger integer if t_max > 2 else round up to next tenth.\r
+               double maxx = timePoints[datasize-1];\r
+               if ( maxx >= 2.0 ) {\r
+                       maxx = Math.ceil(maxx);\r
+               } else {\r
+                       maxx = Math.ceil(maxx*10.0) /10.0;\r
                }\r
-               }       \r
-               return true;\r
-       }\r
-\r
-       private void zoom(float scale) {\r
-               AndroidLogWrapper.d(BurnPlotFragment.class,"zoom by " + scale);\r
-               float domainSpan = absMaxX      - absMinX;\r
-               AndroidLogWrapper.d(BurnPlotFragment.class,"domainSpan = " + domainSpan);\r
-               float domainMidPoint = absMaxX          - domainSpan / 2.0f;\r
-               AndroidLogWrapper.d(BurnPlotFragment.class,"domainMidPoint = " + domainMidPoint);\r
-               float offset = domainSpan / scale;\r
-               AndroidLogWrapper.d(BurnPlotFragment.class,"offset " + offset);\r
-               minXY.x=domainMidPoint- offset;\r
-               AndroidLogWrapper.d(BurnPlotFragment.class,"min X " + minXY.x);\r
-               maxXY.x=domainMidPoint+offset;\r
-               AndroidLogWrapper.d(BurnPlotFragment.class,"max X " + maxXY.x);\r
-               checkBoundaries();\r
-               mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
-               mySimpleXYPlot.redraw();\r
-       }\r
-\r
-       private void scroll(float pan) {\r
-               float domainSpan = maxXY.x      - minXY.x;\r
-               float step = domainSpan / mySimpleXYPlot.getWidth();\r
-               float offset = pan * step;\r
-               minXY.x+= offset;\r
-               maxXY.x+= offset;\r
-               checkBoundaries();\r
-               mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
-               mySimpleXYPlot.redraw();\r
-       }\r
+               renderer.setXAxisMax(maxx);\r
+               \r
+               dataset.addSeries(series);\r
 \r
-       private void checkBoundaries() {\r
+               mChart = new LineChart(dataset, renderer);\r
 \r
-               if ( minXY.x < absMinX) \r
-                       minXY.x = absMinX;\r
-               //              else if ( minXY.x > maxNoError )\r
-               //                      minXY.x = maxNoError;\r
-\r
-               if ( maxXY.x > absMaxX)\r
-                       maxXY.x = absMaxX;\r
-               //              else if ( maxXY.x < minNoError)\r
-               //                      maxXY.x = minNoError;\r
        }\r
-       private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {\r
-               @Override\r
-               public boolean onScale( ScaleGestureDetector detector ) {\r
-                       mScaleFactor *= detector.getScaleFactor();\r
 \r
-                       mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));\r
-                       zoom(mScaleFactor);\r
-                       return true;\r
-               }\r
-       }\r
 }\r
 \r