Reimplement motor handling so the android application relies more heavily on the...
[debian/openrocket] / android / src / net / sf / openrocket / android / motor / BurnPlotFragment.java
1 package net.sf.openrocket.android.motor;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.List;\r
5 import java.util.Vector;\r
6 \r
7 import net.sf.openrocket.R;\r
8 import android.app.Activity;\r
9 import android.graphics.Color;\r
10 import android.graphics.PointF;\r
11 import android.os.Bundle;\r
12 import android.support.v4.app.Fragment;\r
13 import android.util.Log;\r
14 import android.view.LayoutInflater;\r
15 import android.view.MotionEvent;\r
16 import android.view.ScaleGestureDetector;\r
17 import android.view.View;\r
18 import android.view.View.OnTouchListener;\r
19 import android.view.ViewGroup;\r
20 \r
21 import com.androidplot.xy.BoundaryMode;\r
22 import com.androidplot.xy.LineAndPointFormatter;\r
23 import com.androidplot.xy.LineAndPointRenderer;\r
24 import com.androidplot.xy.SimpleXYSeries;\r
25 import com.androidplot.xy.XYPlot;\r
26 import com.androidplot.xy.YValueMarker;\r
27 \r
28 public class BurnPlotFragment extends Fragment implements OnTouchListener {\r
29 \r
30         private final static String TAG = "BurnPlotFragment";\r
31 \r
32         private ExtendedThrustCurveMotor motor;\r
33 \r
34         private XYPlot mySimpleXYPlot;\r
35         private SimpleXYSeries mySeries;\r
36         private PointF minXY;\r
37         private PointF maxXY;\r
38 \r
39         private float absMinX;\r
40         private float absMaxX;\r
41 \r
42         private ScaleGestureDetector mScaleDetector;\r
43         private float mScaleFactor = 1.f;\r
44 \r
45         @Override\r
46         public void onAttach(Activity activity) {\r
47                 super.onAttach(activity);\r
48                 Log.d(TAG,"onAttach");\r
49         }\r
50 \r
51         @Override\r
52         public void onCreate(Bundle savedInstanceState) {\r
53                 Log.d(TAG,"onCreate");\r
54                 super.onCreate(savedInstanceState);\r
55         }\r
56 \r
57         @Override\r
58         public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
59                         Bundle savedInstanceState) {\r
60                 Log.d(TAG,"onCreateView");\r
61                 View v = inflater.inflate(R.layout.motor_burn, container, false);\r
62                 mySimpleXYPlot = (XYPlot) v.findViewById(R.id.xyplot);\r
63                 mySimpleXYPlot.setOnTouchListener(this);\r
64                 mScaleDetector = new ScaleGestureDetector(v.getContext(), new ScaleListener());\r
65                 return v;\r
66         }\r
67 \r
68         private static List<Double> fromArray( double[] arry ) {\r
69                 List<Double> l = new ArrayList<Double>(arry.length);\r
70                 for( double d: arry ) {\r
71                         l.add(d);\r
72                 }\r
73                 return l;\r
74         }\r
75         void init( ExtendedThrustCurveMotor motor ) {\r
76 \r
77                 mySimpleXYPlot.setUserDomainOrigin(0);\r
78                 mySimpleXYPlot.setUserRangeOrigin(0);\r
79                 mySimpleXYPlot.setRangeLabel("impuse (n)");\r
80                 mySimpleXYPlot.setDomainLabel("time (s)");\r
81                 mySimpleXYPlot.addMarker(new YValueMarker(motor.getThrustCurveMotor().getAverageThrustEstimate(),"average" ));\r
82                 mySimpleXYPlot.disableAllMarkup();\r
83 \r
84 \r
85                 try {\r
86                         mySeries = new SimpleXYSeries( \r
87                                         fromArray(motor.getThrustCurveMotor().getTimePoints()),\r
88                                         fromArray(motor.getThrustCurveMotor().getThrustPoints()),\r
89                                         motor.getThrustCurveMotor().getDesignation());\r
90                 } catch ( Exception ex ) {\r
91 \r
92                         Vector<Double> data = new Vector<Double>();\r
93                         data.add(0.0);\r
94                         data.add(0.0);\r
95                         data.add(1.0);\r
96                         data.add(1.0);\r
97                         mySeries = new SimpleXYSeries(data, SimpleXYSeries.ArrayFormat.XY_VALS_INTERLEAVED,"no data");\r
98                 }\r
99 \r
100                 mySimpleXYPlot.addSeries(mySeries, LineAndPointRenderer.class,\r
101                                 new LineAndPointFormatter(Color.rgb(0, 255, 0), Color.rgb(200, 0, 0), null));\r
102 \r
103                 //Set of internal variables for keeping track of the boundaries\r
104                 mySimpleXYPlot.calculateMinMaxVals();\r
105 \r
106                 mySimpleXYPlot.redraw();\r
107 \r
108                 minXY=new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),mySimpleXYPlot.getCalculatedMinY().floatValue());\r
109                 maxXY=new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),mySimpleXYPlot.getCalculatedMaxY().floatValue());\r
110 \r
111                 absMinX = minXY.x;\r
112                 absMaxX = maxXY.x;\r
113 \r
114         }\r
115 \r
116         private float mPosX;\r
117         private float mPosY;\r
118 \r
119         private float mLastTouchX;\r
120         private float mLastTouchY;\r
121 \r
122         private int mActivePointerId = -1;\r
123 \r
124         @Override\r
125         public boolean onTouch(View arg0, MotionEvent event) {\r
126                 mScaleDetector.onTouchEvent(event);\r
127 \r
128                 final int action = event.getAction();\r
129                 switch ( action & MotionEvent.ACTION_MASK ) {\r
130                 case MotionEvent.ACTION_DOWN: {\r
131                         final float x = event.getX();\r
132                         final float y = event.getY();\r
133 \r
134                         mLastTouchX = x;\r
135                         mLastTouchY = y;\r
136 \r
137                         mActivePointerId = event.getPointerId(0);\r
138                         break;\r
139                 }\r
140 \r
141                 case MotionEvent.ACTION_MOVE: {\r
142                         final int pointerIndex = event.findPointerIndex(mActivePointerId);\r
143                         final float x = event.getX(pointerIndex);\r
144                         final float y = event.getY(pointerIndex);\r
145 \r
146                         if (!mScaleDetector.isInProgress()) {\r
147                                 final float dx = x - mLastTouchX;\r
148                                 final float dy = y - mLastTouchY;\r
149 \r
150                                 mPosX += dx;\r
151                                 mPosY += dy;\r
152                                 scroll(dx);\r
153                                 // do scroll.\r
154 \r
155                         }\r
156                         mLastTouchX = x;\r
157                         mLastTouchY = y;\r
158 \r
159                         break;\r
160                 }\r
161 \r
162                 case MotionEvent.ACTION_UP: {\r
163                         mActivePointerId = -1;\r
164                         break;\r
165                 }\r
166 \r
167                 case MotionEvent.ACTION_CANCEL: {\r
168                         mActivePointerId = -1;\r
169                         break;\r
170                 }\r
171 \r
172                 case MotionEvent.ACTION_POINTER_UP: {\r
173                         final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;\r
174                         final int pointerId = event.getPointerId(pointerIndex);\r
175                         if (pointerId == mActivePointerId) {\r
176                                 // This was our active pointer going up.  choose a new active pointer and adjust accordingly.\r
177                                 final int newPointerIndex = pointerIndex ==0 ? 1:0;\r
178                                 mLastTouchX = event.getX(newPointerIndex);\r
179                                 mLastTouchY = event.getY(newPointerIndex);\r
180                                 mActivePointerId = event.getPointerId(newPointerIndex);\r
181                         }\r
182                         break;\r
183                 }\r
184                 }       \r
185                 return true;\r
186         }\r
187 \r
188         private void zoom(float scale) {\r
189                 Log.d(TAG,"zoom by " + scale);\r
190                 float domainSpan = absMaxX      - absMinX;\r
191                 Log.d(TAG,"domainSpan = " + domainSpan);\r
192                 float domainMidPoint = absMaxX          - domainSpan / 2.0f;\r
193                 Log.d(TAG,"domainMidPoint = " + domainMidPoint);\r
194                 float offset = domainSpan / scale;\r
195                 Log.d(TAG,"offset " + offset);\r
196                 minXY.x=domainMidPoint- offset;\r
197                 Log.d(TAG,"min X " + minXY.x);\r
198                 maxXY.x=domainMidPoint+offset;\r
199                 Log.d(TAG,"max X " + maxXY.x);\r
200                 checkBoundaries();\r
201                 mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
202                 mySimpleXYPlot.redraw();\r
203         }\r
204 \r
205         private void scroll(float pan) {\r
206                 float domainSpan = maxXY.x      - minXY.x;\r
207                 float step = domainSpan / mySimpleXYPlot.getWidth();\r
208                 float offset = pan * step;\r
209                 minXY.x+= offset;\r
210                 maxXY.x+= offset;\r
211                 checkBoundaries();\r
212                 mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
213                 mySimpleXYPlot.redraw();\r
214         }\r
215 \r
216         private void checkBoundaries() {\r
217 \r
218                 if ( minXY.x < absMinX) \r
219                         minXY.x = absMinX;\r
220                 //              else if ( minXY.x > maxNoError )\r
221                 //                      minXY.x = maxNoError;\r
222 \r
223                 if ( maxXY.x > absMaxX)\r
224                         maxXY.x = absMaxX;\r
225                 //              else if ( maxXY.x < minNoError)\r
226                 //                      maxXY.x = minNoError;\r
227         }\r
228         private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {\r
229                 @Override\r
230                 public boolean onScale( ScaleGestureDetector detector ) {\r
231                         mScaleFactor *= detector.getScaleFactor();\r
232 \r
233                         mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));\r
234                         zoom(mScaleFactor);\r
235                         return true;\r
236                 }\r
237         }\r
238 }\r
239 \r