Version für alte Androidversionen der Visiereinstellung für Recurvebogen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RBSMainActivity.java 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. package ch.spherIC.recurvebowsight;
  2. import android.app.Activity;
  3. import android.app.AlertDialog;
  4. import android.app.Dialog;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.text.SpannableString;
  10. import android.text.Spanned;
  11. import android.text.style.TabStopSpan;
  12. import android.view.Gravity;
  13. import android.view.Menu;
  14. import android.view.MenuItem;
  15. import android.view.MotionEvent;
  16. import android.view.View;
  17. import android.view.View.OnClickListener;
  18. import android.view.View.OnTouchListener;
  19. import android.view.inputmethod.InputMethodManager;
  20. import android.widget.AdapterView;
  21. import android.widget.AdapterView.OnItemSelectedListener;
  22. import android.widget.Button;
  23. import android.widget.LinearLayout;
  24. import android.widget.ScrollView;
  25. import android.widget.TextView;
  26. import android.widget.Toast;
  27. import android.widget.ViewFlipper;
  28. import ch.spherIC.recurvebowsight.components.FontArrayAdapter;
  29. import ch.spherIC.recurvebowsight.components.FontTextView;
  30. import ch.spherIC.recurvebowsight.components.RiserSpinner;
  31. import ch.spherIC.recurvebowsight.components.SightSpinner;
  32. import ch.spherIC.recurvebowsight.components.XSpinner;
  33. import ch.spherIC.recurvebowsight.components.XTextView;
  34. import ch.spherIC.recurvebowsight.database.RBSDatabaseHelper;
  35. import ch.spherIC.recurvebowsight.database.dao.ArcherySetupDao;
  36. import ch.spherIC.recurvebowsight.database.dao.RiserDao;
  37. import ch.spherIC.recurvebowsight.database.dao.SightDao;
  38. import ch.spherIC.recurvebowsight.dialog.ChooseArcherySetupDlg.ChooseArcherySetupDlgDismissListener;
  39. import ch.spherIC.recurvebowsight.logic.CalculationTask;
  40. import ch.spherIC.recurvebowsight.logic.TrajectoryCalculator;
  41. import ch.spherIC.recurvebowsight.model.IArcherySetup;
  42. import ch.spherIC.recurvebowsight.model.IRiser;
  43. import ch.spherIC.recurvebowsight.model.ISight;
  44. import ch.spherIC.recurvebowsight.model.Riser;
  45. import ch.spherIC.recurvebowsight.model.Sight;
  46. import java.text.DecimalFormat;
  47. import java.util.ArrayList;
  48. import java.util.List;
  49. import java.util.StringTokenizer;
  50. public class RBSMainActivity extends Activity implements ChooseArcherySetupDlgDismissListener, TrajectoryCalculation {
  51. public static final DecimalFormat DF = new DecimalFormat("0.##");
  52. public static final DecimalFormat DF_FC = new DecimalFormat("0.000");
  53. public static final DecimalFormat DF_1 = new DecimalFormat("0.00");
  54. public static final DecimalFormat DF_EVS = new DecimalFormat("0.#");
  55. public static final int DLG_CHOOSE_ARCHERYSETUP = 0;
  56. public static final int DLG_USERGUIDE_PARAMS = 1;
  57. public static final int DLG_USERGUIDE_SIGHT = 2;
  58. public static final int DLG_ABOUT = 3;
  59. private static final Double ANGLE_90 = 90d;
  60. private static final int MIN_DISTANCE = 50;
  61. private static final double CENTI = 0.01;
  62. private static final double MILLI = 0.001;
  63. private ViewFlipper viewFlipper;
  64. private ScrollView paramsScrollView;
  65. private ScrollView sightCfgScrollView;
  66. private float lastX;
  67. private XTextView txtViewParams;
  68. private XTextView txtViewResults;
  69. private XTextView txtViewSight;
  70. private TextView arrowDiameterTxtFld;
  71. private TextView arrowCwTxtFld;
  72. private TextView arrowWeightTxtFld;
  73. private TextView bowPulloutTxtFld;
  74. private TextView arrowV0TxtFld;
  75. private TextView airTemperatureTxtFld;
  76. private TextView airRelativeHumidityTxtFld;
  77. private TextView shootingDistanzTxtFld;
  78. private TextView arrowNockHeightTxtFld;
  79. private TextView targetCenterHeightTxtFld;
  80. private XSpinner calcTimeIntervalCboBox;
  81. private XSpinner calcAccuracyCboBox;
  82. private RiserSpinner scRiserSpinner;
  83. private TextView scVvisHTxtFld;
  84. private TextView scVvisVTxtFld;
  85. private SightSpinner scSightSpinner;
  86. private XSpinner scHeVSSpinner;
  87. private TextView scHeVSTxtFld;
  88. private TextView scaVTxtFld;
  89. private TextView scaHTxtFld;
  90. private TextView scVertScaleRngTxtFld;
  91. private TextView scVertScaleMiddleTxtFld;
  92. private FontTextView scEvSValue;
  93. private Button calcSettingBtn;
  94. private XTextView flightCurveTxtFld;
  95. private boolean showInfoMenu;
  96. private IArcherySetup selectedArcherySetup;
  97. private Double startAngle;
  98. private String selectedHeVS;
  99. private AlertDialog calculationAlert;
  100. @Override
  101. public void onCreate(final Bundle savedInstanceState) {
  102. super.onCreate(savedInstanceState);
  103. setContentView(R.layout.rbs_main);
  104. PlatformUtils.getPlatformSelectionColor(getApplicationContext());
  105. this.calculationAlert = new AlertDialog.Builder(this).create();
  106. this.calculationAlert.setCancelable(false); // This blocks the 'BACK' button
  107. this.calculationAlert.setMessage(getApplicationContext().getResources().getString(R.string.caption_Calculating));
  108. UnitConverter.setApplication(getApplication());
  109. RBSDatabaseHelper.setContext(this);
  110. RBSDatabaseHelper.getInstance().initializeDB();
  111. initializeComponents();
  112. addTouchListeners();
  113. xTextViewUp(this.txtViewParams);
  114. this.calcTimeIntervalCboBox.setAdapter(new FontArrayAdapter<String>(this, R.layout.rbs_spinner,
  115. getResources().getStringArray(R.array.CalculationTimeIntervals),
  116. this.calcTimeIntervalCboBox));
  117. this.calcAccuracyCboBox.setAdapter(new FontArrayAdapter<String>(this, R.layout.rbs_spinner,
  118. getResources().getStringArray(R.array.CalculationAccuracies),
  119. this.calcAccuracyCboBox));
  120. List<IRiser> risers = RiserDao.getInstance().loadAll();
  121. risers.add(0, new Riser(-999, getResources().getString(R.string.caption_NoSelection), "", null, null, null));
  122. this.scRiserSpinner.setAdapter(new FontArrayAdapter<IRiser>(this, R.layout.rbs_spinner, risers,
  123. this.scRiserSpinner));
  124. List<ISight> sights = SightDao.getInstance().loadAll();
  125. sights.add(0,
  126. new Sight(-999, getResources().getString(R.string.caption_NoSelection), "", null, null, "", null, null));
  127. this.scSightSpinner.setAdapter(new FontArrayAdapter<ISight>(this, R.layout.rbs_spinner, sights,
  128. this.scSightSpinner));
  129. addRiserAndSightSpinnerListeners();
  130. }
  131. @Override
  132. protected void onSaveInstanceState(final Bundle outState) {
  133. super.onSaveInstanceState(outState);
  134. outState.putInt("ViewFlipper.SelectedView", this.viewFlipper.getDisplayedChild());
  135. if (this.selectedArcherySetup != null) {
  136. outState.putLong("SelectedArcherySetup", this.selectedArcherySetup.getId());
  137. }
  138. if (this.startAngle != null) {
  139. outState.putDouble("StartAngle", this.startAngle);
  140. }
  141. if (this.scHeVSSpinner.getSelectedItem() != null) {
  142. outState.putString("SelectedHeVS", this.scHeVSSpinner.getSelectedItem().toString());
  143. }
  144. }
  145. @Override
  146. protected void onRestoreInstanceState(final Bundle savedInstanceState) {
  147. super.onRestoreInstanceState(savedInstanceState);
  148. int selView = savedInstanceState.getInt("ViewFlipper.SelectedView", 0);
  149. this.viewFlipper.setDisplayedChild(selView);
  150. if (savedInstanceState.containsKey("SelectedArcherySetup")) {
  151. this.selectedArcherySetup = ArcherySetupDao.getInstance().loadById(savedInstanceState.getLong("SelectedArcherySetup"));
  152. }
  153. this.startAngle = savedInstanceState.getDouble("StartAngle");
  154. this.selectedHeVS = savedInstanceState.getString("SelectedHeVS");
  155. deactivateAllXTextView();
  156. switch (selView) {
  157. case 0:
  158. xTextViewUp(this.txtViewParams);
  159. break;
  160. case 1:
  161. xTextViewUp(this.txtViewResults);
  162. break;
  163. case 2:
  164. xTextViewUp(this.txtViewSight);
  165. break;
  166. default:
  167. break;
  168. }
  169. }
  170. private void initializeComponents() {
  171. this.viewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);
  172. this.paramsScrollView = (ScrollView) findViewById(R.id.paramsScrollView);
  173. this.sightCfgScrollView = (ScrollView) findViewById(R.id.sightCfgScrollView);
  174. this.txtViewParams = (XTextView) findViewById(R.id.viewParams);
  175. this.txtViewResults = (XTextView) findViewById(R.id.viewResults);
  176. this.txtViewSight = (XTextView) findViewById(R.id.viewSight);
  177. this.arrowDiameterTxtFld = (TextView) findViewById(R.id.arrowDiameterTxtFld);
  178. this.arrowCwTxtFld = (TextView) findViewById(R.id.arrowCwTxtFld);
  179. this.arrowWeightTxtFld = (TextView) findViewById(R.id.arrowWeightTxtFld);
  180. this.bowPulloutTxtFld = (TextView) findViewById(R.id.bowPulloutTxtFld);
  181. this.arrowV0TxtFld = (TextView) findViewById(R.id.arrowV0TxtFld);
  182. this.airTemperatureTxtFld = (TextView) findViewById(R.id.airTemperatureTxtFld);
  183. this.airRelativeHumidityTxtFld = (TextView) findViewById(R.id.airRelativeHumidityTxtFld);
  184. this.shootingDistanzTxtFld = (TextView) findViewById(R.id.shootingDistanzTxtFld);
  185. this.arrowNockHeightTxtFld = (TextView) findViewById(R.id.arrowNockHeightTxtFld);
  186. this.targetCenterHeightTxtFld = (TextView) findViewById(R.id.targetCenterHeightTxtFld);
  187. this.calcTimeIntervalCboBox = (XSpinner) findViewById(R.id.deltaTimeCboBox);
  188. this.calcAccuracyCboBox = (XSpinner) findViewById(R.id.calcPrecisionCboBox);
  189. this.scRiserSpinner = (RiserSpinner) findViewById(R.id.scRiserSpinner);
  190. this.scVvisHTxtFld = (TextView) findViewById(R.id.scVvisHTxtFld);
  191. this.scVvisVTxtFld = (TextView) findViewById(R.id.scVvisVTxtFld);
  192. this.scSightSpinner = (SightSpinner) findViewById(R.id.scSightSpinner);
  193. this.scHeVSSpinner = (XSpinner) findViewById(R.id.scHeVSSpinner);
  194. this.scHeVSTxtFld = (TextView) findViewById(R.id.scHeVSTxtFld);
  195. this.scaVTxtFld = (TextView) findViewById(R.id.scaVTxtFld);
  196. this.scaHTxtFld = (TextView) findViewById(R.id.scaHTxtFld);
  197. this.scVertScaleRngTxtFld = (TextView) findViewById(R.id.scVertScaleRngTxtFld);
  198. this.scVertScaleMiddleTxtFld = (TextView) findViewById(R.id.scVertSkalaMiddleTxtFld);
  199. this.scEvSValue = (FontTextView) findViewById(R.id.scEvSValue);
  200. this.flightCurveTxtFld = (XTextView) findViewById(R.id.flightCurveTxtFld);
  201. this.calcSettingBtn = (Button) findViewById(R.id.scBtnCalc);
  202. }
  203. private void addRiserAndSightSpinnerListeners() {
  204. this.scRiserSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
  205. @Override
  206. public void onItemSelected(final AdapterView<?> parent, final View view, final int position,
  207. final long id) {
  208. IRiser riser = RBSMainActivity.this.scRiserSpinner.getSelectedRiser();
  209. if (riser.getId() != -999) {
  210. RBSMainActivity.this.scVvisHTxtFld.setText(DF.format(riser.getVVisH()));
  211. RBSMainActivity.this.scVvisVTxtFld.setText(DF.format(riser.getVVisV()));
  212. } else {
  213. RBSMainActivity.this.scVvisHTxtFld.setText("");
  214. RBSMainActivity.this.scVvisVTxtFld.setText("");
  215. }
  216. RBSMainActivity.this.scVvisHTxtFld.setEnabled(riser.getId() == -999);
  217. RBSMainActivity.this.scVvisVTxtFld.setEnabled(riser.getId() == -999);
  218. }
  219. @Override
  220. public void onNothingSelected(final AdapterView<?> parent) { }
  221. });
  222. this.scSightSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
  223. @Override
  224. public void onItemSelected(final AdapterView<?> parent, final View view, final int position,
  225. final long id) {
  226. ISight sight = RBSMainActivity.this.scSightSpinner.getSelectedSight();
  227. if (sight.getId() != -999) {
  228. List<String> listHeVis = new ArrayList<String>();
  229. String heVis = sight.getHeVis();
  230. StringTokenizer t = new StringTokenizer(heVis, ",");
  231. while (t.hasMoreTokens()) {
  232. listHeVis.add(t.nextToken());
  233. }
  234. RBSMainActivity.this.scHeVSTxtFld.setVisibility(View.INVISIBLE);
  235. RBSMainActivity.this.scHeVSTxtFld.setLayoutParams(new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSTxtFld.getLayoutParams().width,
  236. RBSMainActivity.this.scHeVSTxtFld.getLayoutParams().height,
  237. 0f));
  238. RBSMainActivity.this.scHeVSSpinner.setVisibility(View.VISIBLE);
  239. LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSSpinner.getLayoutParams().width,
  240. RBSMainActivity.this.scHeVSSpinner.getLayoutParams().height,
  241. 1f);
  242. params.gravity = Gravity.FILL_VERTICAL;
  243. RBSMainActivity.this.scHeVSSpinner.setLayoutParams(params);
  244. RBSMainActivity.this.scHeVSSpinner.setAdapter(new FontArrayAdapter<String>(RBSMainActivity.this,
  245. R.layout.rbs_spinner,
  246. listHeVis,
  247. RBSMainActivity.this.scHeVSSpinner));
  248. if (RBSMainActivity.this.selectedHeVS == null) {
  249. if (RBSMainActivity.this.selectedArcherySetup != null
  250. && RBSMainActivity.this.selectedArcherySetup.getSight().getId() == sight.getId()) {
  251. RBSMainActivity.this.scHeVSSpinner.setSelectionByVal(DF.format(RBSMainActivity.this.selectedArcherySetup.getSightHorSetting()));
  252. }
  253. } else {
  254. RBSMainActivity.this.scHeVSSpinner.setSelectionByVal(RBSMainActivity.this.selectedHeVS);
  255. }
  256. RBSMainActivity.this.scaVTxtFld.setText(DF.format(sight.getAV()));
  257. RBSMainActivity.this.scaHTxtFld.setText(DF.format(sight.getAH()));
  258. RBSMainActivity.this.scVertScaleRngTxtFld.setText(DF.format(sight.getVertSkalaRangeMin()) + "-"
  259. + DF.format(sight.getVertSkalaRangeMax()));
  260. } else {
  261. RBSMainActivity.this.scHeVSSpinner.setVisibility(View.INVISIBLE);
  262. RBSMainActivity.this.scHeVSSpinner.setLayoutParams(new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSSpinner.getLayoutParams().width,
  263. RBSMainActivity.this.scHeVSSpinner.getLayoutParams().height,
  264. 0f));
  265. RBSMainActivity.this.scHeVSTxtFld.setVisibility(View.VISIBLE);
  266. RBSMainActivity.this.scHeVSTxtFld.setLayoutParams(new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSTxtFld.getLayoutParams().width,
  267. RBSMainActivity.this.scHeVSTxtFld.getLayoutParams().height,
  268. 1f));
  269. RBSMainActivity.this.scHeVSSpinner.setAdapter(new FontArrayAdapter<String>(RBSMainActivity.this,
  270. R.layout.rbs_spinner,
  271. new ArrayList<String>(),
  272. RBSMainActivity.this.scHeVSSpinner));
  273. RBSMainActivity.this.scaVTxtFld.setText("");
  274. RBSMainActivity.this.scaHTxtFld.setText("");
  275. RBSMainActivity.this.scVertScaleRngTxtFld.setText("");
  276. }
  277. RBSMainActivity.this.scaVTxtFld.setEnabled(sight.getId() == -999);
  278. RBSMainActivity.this.scaHTxtFld.setEnabled(sight.getId() == -999);
  279. RBSMainActivity.this.scVertScaleRngTxtFld.setEnabled(sight.getId() == -999);
  280. }
  281. @Override
  282. public void onNothingSelected(final AdapterView<?> parent) { }
  283. });
  284. }
  285. private void addTouchListeners() {
  286. // Scrollview muss den Swipe selbst handeln
  287. this.paramsScrollView.setOnTouchListener(new OnTouchListener() {
  288. private float downX, downY, upX, upY;
  289. @Override
  290. public boolean onTouch(final View v, final MotionEvent event) {
  291. switch (event.getAction()) {
  292. case MotionEvent.ACTION_DOWN: {
  293. this.downX = event.getX();
  294. this.downY = event.getY();
  295. }
  296. case MotionEvent.ACTION_UP: {
  297. this.upX = event.getX();
  298. this.upY = event.getY();
  299. float deltaX = this.upX - this.downX;
  300. float deltaY = this.upY - this.downY;
  301. // swipe from right to left ?
  302. if (deltaX < 0 && Math.abs(deltaX) > MIN_DISTANCE && Math.abs(deltaY) < MIN_DISTANCE) {
  303. // set the required Animation type to ViewFlipper
  304. // The Next screen will come in form Right and current Screen will go OUT to Left
  305. RBSMainActivity.this.viewFlipper.setInAnimation(RBSMainActivity.this, R.anim.in_from_right);
  306. RBSMainActivity.this.viewFlipper.setOutAnimation(RBSMainActivity.this, R.anim.out_to_left);
  307. // Show The Next Screen
  308. RBSMainActivity.this.viewFlipper.showNext();
  309. deactivateXTextView(RBSMainActivity.this.txtViewParams);
  310. xTextViewUp(RBSMainActivity.this.txtViewResults);
  311. deactivateXTextView(RBSMainActivity.this.txtViewSight);
  312. }
  313. }
  314. }
  315. return false;
  316. }
  317. });
  318. // Scrollview muss den Swipe selbst handeln
  319. this.sightCfgScrollView.setOnTouchListener(new OnTouchListener() {
  320. private float downX, downY, upX, upY;
  321. @Override
  322. public boolean onTouch(final View v, final MotionEvent event) {
  323. switch (event.getAction()) {
  324. case MotionEvent.ACTION_DOWN: {
  325. this.downX = event.getX();
  326. this.downY = event.getY();
  327. }
  328. case MotionEvent.ACTION_UP: {
  329. this.upX = event.getX();
  330. this.upY = event.getY();
  331. float deltaX = this.upX - this.downX;
  332. float deltaY = this.upY - this.downY;
  333. // swipe from left to right?
  334. if (deltaX > 0 && Math.abs(deltaX) > MIN_DISTANCE && Math.abs(deltaY) < MIN_DISTANCE) {
  335. // set the required Animation type to ViewFlipper
  336. // The Next screen will come in form Right and current Screen will go OUT to Left
  337. RBSMainActivity.this.viewFlipper.setInAnimation(RBSMainActivity.this, R.anim.in_from_left);
  338. RBSMainActivity.this.viewFlipper.setOutAnimation(RBSMainActivity.this, R.anim.out_to_right);
  339. // Show The Next Screen
  340. RBSMainActivity.this.viewFlipper.showPrevious();
  341. deactivateXTextView(RBSMainActivity.this.txtViewSight);
  342. xTextViewUp(RBSMainActivity.this.txtViewResults);
  343. deactivateXTextView(RBSMainActivity.this.txtViewParams);
  344. }
  345. }
  346. }
  347. return false;
  348. }
  349. });
  350. // Touchlistener für die oberen 3 Tabs
  351. OnTouchListener tabListener = new OnTouchListener() {
  352. @Override
  353. public boolean onTouch(final View v, final MotionEvent event) {
  354. switch (event.getAction()) {
  355. case MotionEvent.ACTION_DOWN: {
  356. deactivateAllXTextView();
  357. xTextViewDown((XTextView) v);
  358. return true;
  359. }
  360. case MotionEvent.ACTION_UP: {
  361. RBSMainActivity.this.viewFlipper.setInAnimation(RBSMainActivity.this, R.anim.in_from_right);
  362. RBSMainActivity.this.viewFlipper.setOutAnimation(RBSMainActivity.this, R.anim.out_to_left);
  363. if (v == RBSMainActivity.this.txtViewParams) {
  364. if (RBSMainActivity.this.viewFlipper.getDisplayedChild() != 0) {
  365. RBSMainActivity.this.viewFlipper.setDisplayedChild(0);
  366. }
  367. } else if (v == RBSMainActivity.this.txtViewResults) {
  368. if (RBSMainActivity.this.viewFlipper.getDisplayedChild() != 1) {
  369. RBSMainActivity.this.viewFlipper.setDisplayedChild(1);
  370. }
  371. } else {
  372. if (RBSMainActivity.this.viewFlipper.getDisplayedChild() != 2) {
  373. RBSMainActivity.this.viewFlipper.setDisplayedChild(2);
  374. }
  375. }
  376. xTextViewUp((XTextView) v);
  377. return true;
  378. }
  379. }
  380. return false;
  381. }
  382. };
  383. // Touchlistener an Tabs anhängen
  384. this.txtViewParams.setOnTouchListener(tabListener);
  385. this.txtViewResults.setOnTouchListener(tabListener);
  386. this.txtViewSight.setOnTouchListener(tabListener);
  387. this.calcSettingBtn.setOnClickListener(new OnClickListener() {
  388. @Override
  389. public void onClick(final View v) {
  390. calculateSettings();
  391. }
  392. });
  393. }
  394. @Override
  395. public boolean onPrepareOptionsMenu(final Menu menu) {
  396. int size = menu.size();
  397. for (int i = size - 1; i >= 0; i--) {
  398. menu.removeItem(menu.getItem(i).getItemId());
  399. }
  400. if (this.showInfoMenu) {
  401. this.showInfoMenu = false;
  402. getMenuInflater().inflate(R.menu.rbs_info_menu, menu);
  403. } else {
  404. getMenuInflater().inflate(R.menu.rbs_main, menu);
  405. }
  406. return true;
  407. }
  408. @Override
  409. public boolean onOptionsItemSelected(final MenuItem item) {
  410. // Handle item selection
  411. switch (item.getItemId()) {
  412. case R.id.chooseConfiguration:
  413. showDialog(DLG_CHOOSE_ARCHERYSETUP);
  414. return true;
  415. case R.id.doCalculation:
  416. calculate();
  417. return true;
  418. case R.id.addConfiguration:
  419. // ************************************************************************
  420. // ** TEST WEISE AB HIER***************************************************
  421. // ************************************************************************
  422. // this.listView1 = (ListView) findViewById(R.id.listView1);
  423. //
  424. // String[] values = new String[] { "Riser", "Sight", "General Config" };
  425. //
  426. // final ArrayList<String> list = new ArrayList<String>(Arrays.asList(values));
  427. // final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
  428. // this.listView1.setAdapter(adapter);
  429. // this.listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  430. //
  431. // @Override
  432. // public void onItemClick(final AdapterView<?> parent, final View view, final int position,
  433. // final long id) {
  434. // final String item = (String) parent.getItemAtPosition(position);
  435. // if (item.equals("Riser")) {
  436. Intent intent = new Intent(RBSMainActivity.this, RiserSightConfigurationActivity.class);
  437. startActivity(intent);
  438. // }
  439. // }
  440. // });
  441. return true;
  442. case R.id.moreItems:
  443. this.showInfoMenu = true;
  444. closeOptionsMenu();
  445. new Handler().post(new Runnable() {
  446. @Override
  447. public void run() {
  448. openOptionsMenu();
  449. }
  450. });
  451. return true;
  452. default:
  453. return super.onOptionsItemSelected(item);
  454. }
  455. }
  456. @Override
  457. public boolean onTouchEvent(final MotionEvent touchevent) {
  458. switch (touchevent.getAction()) {
  459. // when user first touches the screen to swap
  460. case MotionEvent.ACTION_DOWN: {
  461. this.lastX = touchevent.getX();
  462. break;
  463. }
  464. case MotionEvent.ACTION_UP: {
  465. float currentX = touchevent.getX();
  466. // if right to left swipe on screen
  467. if (this.lastX > currentX) {
  468. if (this.viewFlipper.getDisplayedChild() == 2) {
  469. break;
  470. }
  471. // set the required Animation type to ViewFlipper
  472. // The Next screen will come in form Right and current Screen will go OUT to Left
  473. this.viewFlipper.setInAnimation(this, R.anim.in_from_right);
  474. this.viewFlipper.setOutAnimation(this, R.anim.out_to_left);
  475. // Show The Next Screen
  476. this.viewFlipper.showNext();
  477. } else if (this.lastX < currentX) { // if left to right swipe on screen
  478. // If no more View/Child to flip
  479. if (this.viewFlipper.getDisplayedChild() == 0) {
  480. break;
  481. }
  482. // set the required Animation type to ViewFlipper
  483. // The Next screen will come in form Left and current Screen will go OUT to Right
  484. this.viewFlipper.setInAnimation(this, R.anim.in_from_left);
  485. this.viewFlipper.setOutAnimation(this, R.anim.out_to_right);
  486. // Show the previous Screen
  487. this.viewFlipper.showPrevious();
  488. }
  489. deactivateAllXTextView();
  490. switch (this.viewFlipper.getDisplayedChild()) {
  491. case 0:
  492. xTextViewUp(this.txtViewParams);
  493. break;
  494. case 1:
  495. xTextViewUp(this.txtViewResults);
  496. break;
  497. case 2:
  498. xTextViewUp(this.txtViewSight);
  499. break;
  500. default:
  501. break;
  502. }
  503. break;
  504. }
  505. }
  506. return false;
  507. }
  508. private void xTextViewDown(final XTextView view) {
  509. view.setDrawborderColor(getResources().getColor(R.color.android_yellow_dark));
  510. view.setTextColor(getResources().getColor(R.color.android_yellow_dark));
  511. }
  512. private void xTextViewUp(final XTextView view) {
  513. view.setDrawborderColor(getResources().getColor(R.color.android_yellow));
  514. view.setTextColor(getResources().getColor(R.color.android_yellow));
  515. }
  516. private void deactivateXTextView(final XTextView view) {
  517. view.setDrawborderColor(getResources().getColor(R.color.white));
  518. view.setTextColor(getResources().getColor(R.color.white));
  519. }
  520. private void deactivateAllXTextView() {
  521. deactivateXTextView(this.txtViewParams);
  522. deactivateXTextView(this.txtViewResults);
  523. deactivateXTextView(this.txtViewSight);
  524. }
  525. @Override
  526. protected Dialog onCreateDialog(final int id) {
  527. return DialogFactory.createDialog(id, this);
  528. }
  529. @Override
  530. public void onArcherySetupDlgDismissed(final IArcherySetup archerySetup) {
  531. this.selectedArcherySetup = archerySetup;
  532. if (archerySetup != null && archerySetup.getId() != -999) {
  533. this.arrowDiameterTxtFld.setText(DF.format(archerySetup.getArrowDiameter()));
  534. this.arrowCwTxtFld.setText(DF.format(archerySetup.getArrowCw()));
  535. this.arrowWeightTxtFld.setText(DF.format(archerySetup.getArrowWeight()));
  536. this.bowPulloutTxtFld.setText(DF.format(archerySetup.getBowPullout()));
  537. this.arrowV0TxtFld.setText(DF.format(archerySetup.getArrowV0()));
  538. this.arrowNockHeightTxtFld.setText(DF_1.format(archerySetup.getArrowNockHeight()));
  539. this.targetCenterHeightTxtFld.setText(DF_1.format(archerySetup.getArrowCenterHeight()));
  540. this.calcTimeIntervalCboBox.setSelectionByVal(archerySetup.getDeltaTime().toString());
  541. this.calcAccuracyCboBox.setSelectionByVal(archerySetup.getCalcPrecision().toString());
  542. this.scRiserSpinner.setSelectedRiser(archerySetup.getRiser());
  543. this.scRiserSpinner.fireSelectionChangedEvent();
  544. this.scSightSpinner.setSelectedSight(archerySetup.getSight());
  545. this.scSightSpinner.fireSelectionChangedEvent();
  546. this.scVertScaleMiddleTxtFld.setText(DF.format(archerySetup.getSightVertSkalaMiddle()));
  547. this.airTemperatureTxtFld.setText("25");
  548. this.airRelativeHumidityTxtFld.setText("50");
  549. this.shootingDistanzTxtFld.setText("18");
  550. } else {
  551. this.arrowDiameterTxtFld.setText("");
  552. this.arrowDiameterTxtFld.setText("");
  553. this.arrowCwTxtFld.setText("");
  554. this.arrowWeightTxtFld.setText("");
  555. this.bowPulloutTxtFld.setText("");
  556. this.arrowV0TxtFld.setText("");
  557. this.arrowNockHeightTxtFld.setText("");
  558. this.targetCenterHeightTxtFld.setText("");
  559. this.calcTimeIntervalCboBox.setSelectionByVal("");
  560. this.calcAccuracyCboBox.setSelectionByVal("");
  561. this.scRiserSpinner.setSelection(0);
  562. this.scRiserSpinner.fireSelectionChangedEvent();
  563. this.scSightSpinner.setSelection(0);
  564. this.scSightSpinner.fireSelectionChangedEvent();
  565. this.scVertScaleMiddleTxtFld.setText("");
  566. }
  567. }
  568. private boolean allParamFieldsValid() {
  569. return !this.arrowDiameterTxtFld.getText().toString().isEmpty()
  570. && !this.arrowCwTxtFld.getText().toString().isEmpty()
  571. && !this.arrowWeightTxtFld.getText().toString().isEmpty()
  572. && !this.bowPulloutTxtFld.getText().toString().isEmpty()
  573. && !this.arrowV0TxtFld.getText().toString().isEmpty()
  574. && !this.airTemperatureTxtFld.getText().toString().isEmpty()
  575. && !this.airRelativeHumidityTxtFld.getText().toString().isEmpty()
  576. && !this.shootingDistanzTxtFld.getText().toString().isEmpty()
  577. && !this.arrowNockHeightTxtFld.getText().toString().isEmpty()
  578. && !this.targetCenterHeightTxtFld.getText().toString().isEmpty()
  579. && this.calcTimeIntervalCboBox.getSelectedItem() != null
  580. && this.calcAccuracyCboBox.getSelectedItem() != null
  581. && allSightParamFieldsValid();
  582. }
  583. private boolean allSightParamFieldsValid() {
  584. return !this.scVvisHTxtFld.getText().toString().isEmpty()
  585. && !this.scVvisVTxtFld.getText().toString().isEmpty()
  586. && !this.scaHTxtFld.getText().toString().isEmpty()
  587. && !this.scaVTxtFld.getText().toString().isEmpty()
  588. && !this.scVertScaleRngTxtFld.getText().toString().isEmpty()
  589. && ((this.scHeVSSpinner.getVisibility() == View.VISIBLE && this.scHeVSSpinner.getSelectedItem() != null)
  590. || (this.scHeVSTxtFld.getVisibility() == View.VISIBLE && !this.scHeVSTxtFld.getText().toString().isEmpty()))
  591. && !this.scVertScaleMiddleTxtFld.getText().toString().isEmpty();
  592. }
  593. /**
  594. * Startet die Berechnung wenn alle notwendigen Felder gefüllt sind.
  595. */
  596. private void calculate() {
  597. if (allParamFieldsValid()) {
  598. InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
  599. if (getCurrentFocus() != null) {
  600. imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
  601. }
  602. CalculationTask calcTask = new CalculationTask();
  603. TrajectoryCalculator calculator = new TrajectoryCalculator(Double.valueOf(this.arrowDiameterTxtFld.getText().toString().trim()) * MILLI, //
  604. Double.valueOf(this.arrowCwTxtFld.getText().toString().trim()), //
  605. Double.valueOf(this.arrowWeightTxtFld.getText().toString().trim()) * MILLI, //
  606. Double.valueOf(this.arrowV0TxtFld.getText().toString().trim()), //
  607. Double.valueOf(this.shootingDistanzTxtFld.getText().toString().trim()), //
  608. Double.valueOf(this.targetCenterHeightTxtFld.getText().toString().trim())
  609. - Double.valueOf(this.arrowNockHeightTxtFld.getText().toString().trim()), //
  610. Double.valueOf(this.airTemperatureTxtFld.getText().toString().trim()), //
  611. Double.valueOf(this.airRelativeHumidityTxtFld.getText().toString().trim())
  612. * CENTI, //
  613. Double.valueOf(this.calcTimeIntervalCboBox.getSelectedItem().toString().trim()), //
  614. Double.valueOf(this.calcAccuracyCboBox.getSelectedItem().toString().trim())
  615. * CENTI, //
  616. this);
  617. calculator.setStartAngle(0d);
  618. calcTask.execute(calculator);
  619. this.calculationAlert.show();
  620. } else {
  621. Toast toast = Toast.makeText(this, getResources().getString(R.string.caption_FillAllMandatoryFields), Toast.LENGTH_LONG);
  622. toast.setGravity(Gravity.CENTER, 0, 0);
  623. toast.show();
  624. }
  625. }
  626. @Override
  627. public void onCalculationDone(final Double[][] flightCurve, final Double startAngle, final Double[] maxHCurve) {
  628. this.startAngle = startAngle;
  629. fillFlightCurveTxtFld(flightCurve, startAngle, maxHCurve);
  630. calculateSettings();
  631. if (this.calculationAlert != null) {
  632. this.calculationAlert.dismiss();
  633. }
  634. this.txtViewSight.doSingleTouch();
  635. }
  636. private void fillFlightCurveTxtFld(final Double[][] flightCurve, final Double startAngle,
  637. final Double[] maxHCurve) {
  638. this.flightCurveTxtFld.setText("");
  639. this.flightCurveTxtFld.append("Abschusswinkel:\n" + DF_FC.format(startAngle) + " °\n\n");
  640. this.flightCurveTxtFld.append("Max. Höhe der Flugbahn:\n" + DF_FC.format(maxHCurve[0])
  641. + " m / " + DF_FC.format(maxHCurve[0] + Double.valueOf(this.arrowNockHeightTxtFld.getText().toString().trim()))
  642. + " m, [t = " + DF_FC.format(maxHCurve[1]) + " s]\n\n");
  643. this.flightCurveTxtFld.append("Flugzeit:\n"
  644. + DF_FC.format(flightCurve[flightCurve.length - 1][TrajectoryCalculator.IDX_T])
  645. + " sec\n\n");
  646. int width = this.flightCurveTxtFld.getMeasuredWidth();
  647. SpannableString line = new SpannableString("t [sec]\tVx [m/s]\tVy [m/s]\tx [m]\ty [m]\n\n");
  648. line.setSpan(new TabStopSpan.Standard(width / 5), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  649. line.setSpan(new TabStopSpan.Standard(width / 5 * 2), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  650. line.setSpan(new TabStopSpan.Standard(width / 5 * 3), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  651. line.setSpan(new TabStopSpan.Standard(width / 5 * 4), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  652. this.flightCurveTxtFld.append(line);
  653. for (int i = 0; i < flightCurve.length; i++) {
  654. Double[] r1 = flightCurve[i];
  655. line = new SpannableString(DF_FC.format(r1[TrajectoryCalculator.IDX_T]) + '\t'
  656. + DF_FC.format(r1[TrajectoryCalculator.IDX_VX]) + '\t'
  657. + DF_FC.format(r1[TrajectoryCalculator.IDX_VY]) + '\t'
  658. + DF_FC.format(r1[TrajectoryCalculator.IDX_X]) + '\t'
  659. + DF_FC.format(r1[TrajectoryCalculator.IDX_Y]) + "\n");
  660. line.setSpan(new TabStopSpan.Standard(width / 5), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  661. line.setSpan(new TabStopSpan.Standard(width / 5 * 2), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  662. line.setSpan(new TabStopSpan.Standard(width / 5 * 3), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  663. line.setSpan(new TabStopSpan.Standard(width / 5 * 4), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
  664. this.flightCurveTxtFld.append(line);
  665. }
  666. }
  667. /**
  668. * Berechnet die definitve Visiereinstellung anhand des berechneten Flugbahnwinkels.
  669. */
  670. private void calculateSettings() {
  671. if (allSightParamFieldsValid() && this.selectedArcherySetup != null && this.startAngle != null) {
  672. Double x0;
  673. Double y0;
  674. Double x1;
  675. Double y1;
  676. Double x2;
  677. Double y2;
  678. Double x3;
  679. Double y3;
  680. Double r;
  681. Double s;
  682. Double vVh = Double.valueOf(this.scVvisHTxtFld.getText().toString()) + Double.valueOf(this.scaHTxtFld.getText().toString());
  683. Double vVv = Double.valueOf(this.scVvisVTxtFld.getText().toString()) + Double.valueOf(this.scaVTxtFld.getText().toString());
  684. Double a = Double.valueOf(this.bowPulloutTxtFld.getText().toString()) * 10;
  685. Double heVs = this.scHeVSSpinner.getVisibility() == View.VISIBLE ? Double.valueOf(this.scHeVSSpinner.getSelectedItem().toString()) : Double.valueOf(this.scHeVSTxtFld.getText().toString());
  686. Double lhNA = this.selectedArcherySetup.getHNA() * 10;
  687. Double dltH = (Double.valueOf(this.targetCenterHeightTxtFld.getText().toString())
  688. - Double.valueOf(this.arrowNockHeightTxtFld.getText().toString())) * Math.pow(10, 3);
  689. Double ldistH = Double.valueOf(this.shootingDistanzTxtFld.getText().toString()) * Math.pow(10, 3);
  690. Double minSkala = this.scVertScaleRngTxtFld.getText().toString().contains("-") ? Double.valueOf(this.scVertScaleRngTxtFld.getText().toString().substring(0,
  691. this.scVertScaleRngTxtFld.getText().toString().indexOf('-'))) : 0d;
  692. Double maxSkala = this.scVertScaleRngTxtFld.getText().toString().contains("-") ? Double.valueOf(this.scVertScaleRngTxtFld.getText().toString().substring(this.scVertScaleRngTxtFld.getText().toString().indexOf('-') + 1,
  693. this.scVertScaleRngTxtFld.getText().toString().length())) : 0d;
  694. // PIN auf Höhe Pfeil
  695. x0 = (a + vVh + heVs) * Math.cos(Math.toRadians(this.startAngle));
  696. y0 = (a + vVh + heVs) * Math.sin(Math.toRadians(this.startAngle));
  697. // PIN auf Höhe Horizontalschlitten Visier
  698. x2 = x0 + vVv * Math.cos(Math.toRadians(ANGLE_90 + this.startAngle));
  699. y2 = y0 + vVv * Math.sin(Math.toRadians(ANGLE_90 + this.startAngle));
  700. // Schnittpunkt der Achse Horizontalschlitten Visier mit Achse Befestigungslöcher Visier
  701. x3 = (a + vVh) * Math.cos(Math.toRadians(this.startAngle)) + vVv * Math.cos(Math.toRadians(ANGLE_90 + this.startAngle));
  702. y3 = (a + vVh) * Math.sin(Math.toRadians(this.startAngle)) + vVv * Math.sin(Math.toRadians(ANGLE_90 + this.startAngle));
  703. // Unbekannte der Vektorgeradengleichung
  704. r = (lhNA * (x0 - x2) - x0 * y2 + x2 * y0) / (ldistH * (y0 - y2) + (dltH - lhNA) * (x2 - x0));
  705. s = -((ldistH * (lhNA - y0) + (dltH - lhNA) * x0) / (ldistH * (y0 - y2) + (dltH - lhNA) * (x2 - x0)));
  706. // Pin auf Visierlinie
  707. x1 = r * ldistH;
  708. y1 = lhNA + r * (dltH - lhNA);
  709. // Unten (+) oder oben (-) von (x2/y2) ?
  710. Double n = ((y2 - y3) * (x1 - x3) - (x2 - x3) * (y1 - y3)) < 0 ? -1.0 : 1.0;
  711. // Abstand P1 - P2
  712. Double d = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) * n;
  713. // Einstellung auf vert. Skala
  714. Double sV = Double.valueOf(this.scVertScaleMiddleTxtFld.getText().toString()) + d;
  715. this.scEvSValue.setText(DF_EVS.format(sV));
  716. if (minSkala <= sV && sV <= maxSkala) {
  717. this.scEvSValue.setBackgroundDrawable(getResources().getDrawable(R.drawable.evs_ok_background));
  718. } else {
  719. this.scEvSValue.setBackgroundDrawable(getResources().getDrawable(R.drawable.evs_nok_background));
  720. }
  721. } else {
  722. this.scEvSValue.setText("");
  723. Toast toast = Toast.makeText(this, getResources().getString(R.string.caption_FillAllMandatoryFields), Toast.LENGTH_LONG);
  724. toast.setGravity(Gravity.CENTER, 0, 0);
  725. toast.show();
  726. }
  727. }
  728. }