package ch.spherIC.recurvebowsight; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Handler; import android.text.Editable; import android.text.SpannableString; import android.text.Spanned; import android.text.TextWatcher; import android.text.style.TabStopSpan; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import android.widget.ViewFlipper; import ch.spherIC.recurvebowsight.components.FlightCurveChart; import ch.spherIC.recurvebowsight.components.FontArrayAdapter; import ch.spherIC.recurvebowsight.components.FontTextView; import ch.spherIC.recurvebowsight.components.RiserSpinner; import ch.spherIC.recurvebowsight.components.SightSpinner; import ch.spherIC.recurvebowsight.components.XSpinner; import ch.spherIC.recurvebowsight.components.XTextView; import ch.spherIC.recurvebowsight.configuration.MainConfigurationActivity; import ch.spherIC.recurvebowsight.database.RBSDatabaseHelper; import ch.spherIC.recurvebowsight.database.dao.ArcherySetupDao; import ch.spherIC.recurvebowsight.database.dao.RiserDao; import ch.spherIC.recurvebowsight.database.dao.SightDao; import ch.spherIC.recurvebowsight.dialog.ChooseArcherySetupDlg.ChooseArcherySetupDlgDismissListener; import ch.spherIC.recurvebowsight.logic.CalculationTask; import ch.spherIC.recurvebowsight.logic.TrajectoryCalculator; import ch.spherIC.recurvebowsight.model.IArcherySetup; import ch.spherIC.recurvebowsight.model.IRiser; import ch.spherIC.recurvebowsight.model.ISight; import ch.spherIC.recurvebowsight.model.Riser; import ch.spherIC.recurvebowsight.model.Sight; import ch.spherIC.recurvebowsight.utilities.CompatibilityUtil; import ch.spherIC.recurvebowsight.utilities.PlatformUtils; import ch.spherIC.recurvebowsight.utilities.UnitConverter; import org.achartengine.GraphicalView; import org.achartengine.model.XYSeries; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; public class RBSMainActivity extends Activity implements ChooseArcherySetupDlgDismissListener, TrajectoryCalculation { public static final DecimalFormat DF = new DecimalFormat("0.##"); public static final DecimalFormat DF_FC = new DecimalFormat("0.000"); public static final DecimalFormat DF_1 = new DecimalFormat("0.00"); public static final DecimalFormat DF_EVS = new DecimalFormat("0.#"); public static final int DLG_CHOOSE_ARCHERYSETUP = 0; public static final int DLG_USERGUIDE_PARAMS = 1; public static final int DLG_USERGUIDE_SIGHT = 2; public static final int DLG_ABOUT = 3; private static final Double ANGLE_90 = 90d; private static final int MIN_DISTANCE = 50; private static final double CENTI = 0.01; private static final double MILLI = 0.001; private static final int MAX_TRAJ_POINTS = 200; private static final String DEF_TEMP = "23"; private static final String DEF_HUMIDITY = "50"; private static final String DEF_DISTANCE = "18"; private ViewFlipper viewFlipper; private ScrollView paramsScrollView; private ScrollView sightCfgScrollView; private float lastX; private XTextView txtViewParams; private XTextView txtViewResults; private XTextView txtViewSight; private TextView arrowDiameterTxtFld; private TextView arrowCwTxtFld; private TextView arrowWeightTxtFld; private TextView bowPulloutTxtFld; private TextView arrowV0TxtFld; private TextView airTemperatureTxtFld; private TextView airRelativeHumidityTxtFld; private TextView shootingDistanzTxtFld; private TextView arrowNockHeightTxtFld; private TextView targetCenterHeightTxtFld; private XSpinner calcTimeIntervalCboBox; private XSpinner calcAccuracyCboBox; private RiserSpinner scRiserSpinner; private TextView scVvisHTxtFld; private TextView scVvisVTxtFld; private SightSpinner scSightSpinner; private XSpinner scHeVSSpinner; private TextView scHeVSTxtFld; private TextView scaVTxtFld; private TextView scaHTxtFld; private TextView scVertScaleRngTxtFld; private TextView scVertScaleMiddleTxtFld; private FontTextView scEvSValue; private Button calcSettingBtn; private XTextView flightCurveTxtFld; private boolean showInfoMenu; private IArcherySetup selectedArcherySetup; private Double startAngle; private String selectedHeVS; private ProgressDialog progressDialog; private FlightCurveChart flightCurveChart; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.rbs_main); PlatformUtils.getPlatformSelectionColor(getApplicationContext()); if (CompatibilityUtil.isTablet(getApplicationContext())) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } UnitConverter.setApplication(getApplication()); RBSDatabaseHelper.setContext(this); RBSDatabaseHelper.getInstance().initializeDB(); initializeComponents(); addTouchListeners(); addValueChangeListeners(); xTextViewUp(this.txtViewParams); this.calcTimeIntervalCboBox.setAdapter(new FontArrayAdapter(this, R.layout.rbs_spinner, getResources().getStringArray(R.array.CalculationTimeIntervals), this.calcTimeIntervalCboBox)); this.calcAccuracyCboBox.setAdapter(new FontArrayAdapter(this, R.layout.rbs_spinner, getResources().getStringArray(R.array.CalculationAccuracies), this.calcAccuracyCboBox)); List risers = RiserDao.getInstance().loadAll(); risers.add(0, new Riser(-999, getResources().getString(R.string.caption_NoSelection), "", null, null, null)); this.scRiserSpinner.setAdapter(new FontArrayAdapter(this, R.layout.rbs_spinner, risers, this.scRiserSpinner)); List sights = SightDao.getInstance().loadAll(); sights.add(0, new Sight(-999, getResources().getString(R.string.caption_NoSelection), "", null, null, "", null, null)); this.scSightSpinner.setAdapter(new FontArrayAdapter(this, R.layout.rbs_spinner, sights, this.scSightSpinner)); addRiserAndSightSpinnerListeners(); GraphicalView flightCurveChartView; LinearLayout layout; this.flightCurveChart = new FlightCurveChart(); flightCurveChartView = this.flightCurveChart.getView(this); layout = (LinearLayout) findViewById(R.id.ballisticResults); layout.addView(flightCurveChartView, 0, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1f)); } @Override protected void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("ViewFlipper.SelectedView", this.viewFlipper.getDisplayedChild()); if (this.selectedArcherySetup != null) { outState.putLong("SelectedArcherySetup", this.selectedArcherySetup.getId()); } if (this.startAngle != null) { outState.putDouble("StartAngle", this.startAngle); } if (this.scHeVSSpinner.getSelectedItem() != null) { outState.putString("SelectedHeVS", this.scHeVSSpinner.getSelectedItem().toString()); } } @Override protected void onRestoreInstanceState(final Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); int selView = savedInstanceState.getInt("ViewFlipper.SelectedView", 0); this.viewFlipper.setDisplayedChild(selView); if (savedInstanceState.containsKey("SelectedArcherySetup")) { this.selectedArcherySetup = ArcherySetupDao.getInstance().loadById(savedInstanceState.getLong("SelectedArcherySetup")); } this.startAngle = savedInstanceState.getDouble("StartAngle"); this.selectedHeVS = savedInstanceState.getString("SelectedHeVS"); deactivateAllXTextView(); switch (selView) { case 0: xTextViewUp(this.txtViewParams); break; case 1: xTextViewUp(this.txtViewResults); break; case 2: xTextViewUp(this.txtViewSight); break; default: break; } } private void initializeComponents() { this.viewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper); this.paramsScrollView = (ScrollView) findViewById(R.id.paramsScrollView); this.sightCfgScrollView = (ScrollView) findViewById(R.id.sightCfgScrollView); this.txtViewParams = (XTextView) findViewById(R.id.viewParams); this.txtViewResults = (XTextView) findViewById(R.id.viewResults); this.txtViewSight = (XTextView) findViewById(R.id.viewSight); this.arrowDiameterTxtFld = (TextView) findViewById(R.id.arrowDiameterTxtFld); this.arrowCwTxtFld = (TextView) findViewById(R.id.arrowCwTxtFld); this.arrowWeightTxtFld = (TextView) findViewById(R.id.arrowWeightTxtFld); this.bowPulloutTxtFld = (TextView) findViewById(R.id.bowPulloutTxtFld); this.arrowV0TxtFld = (TextView) findViewById(R.id.arrowV0TxtFld); this.airTemperatureTxtFld = (TextView) findViewById(R.id.airTemperatureTxtFld); this.airRelativeHumidityTxtFld = (TextView) findViewById(R.id.airRelativeHumidityTxtFld); this.shootingDistanzTxtFld = (TextView) findViewById(R.id.shootingDistanzTxtFld); this.arrowNockHeightTxtFld = (TextView) findViewById(R.id.arrowNockHeightTxtFld); this.targetCenterHeightTxtFld = (TextView) findViewById(R.id.targetCenterHeightTxtFld); this.calcTimeIntervalCboBox = (XSpinner) findViewById(R.id.deltaTimeCboBox); this.calcAccuracyCboBox = (XSpinner) findViewById(R.id.calcPrecisionCboBox); this.scRiserSpinner = (RiserSpinner) findViewById(R.id.scRiserSpinner); this.scVvisHTxtFld = (TextView) findViewById(R.id.scVvisHTxtFld); this.scVvisVTxtFld = (TextView) findViewById(R.id.scVvisVTxtFld); this.scSightSpinner = (SightSpinner) findViewById(R.id.scSightSpinner); this.scHeVSSpinner = (XSpinner) findViewById(R.id.scHeVSSpinner); this.scHeVSTxtFld = (TextView) findViewById(R.id.scHeVSTxtFld); this.scaVTxtFld = (TextView) findViewById(R.id.scaVTxtFld); this.scaHTxtFld = (TextView) findViewById(R.id.scaHTxtFld); this.scVertScaleRngTxtFld = (TextView) findViewById(R.id.scVertScaleRngTxtFld); this.scVertScaleMiddleTxtFld = (TextView) findViewById(R.id.scVertSkalaMiddleTxtFld); this.scEvSValue = (FontTextView) findViewById(R.id.scEvSValue); this.flightCurveTxtFld = (XTextView) findViewById(R.id.flightCurveTxtFld); this.calcSettingBtn = (Button) findViewById(R.id.scBtnCalc); } private void addRiserAndSightSpinnerListeners() { this.scRiserSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(final AdapterView parent, final View view, final int position, final long id) { IRiser riser = RBSMainActivity.this.scRiserSpinner.getSelectedRiser(); if (riser.getId() != -999) { RBSMainActivity.this.scVvisHTxtFld.setText(DF.format(riser.getVVisH())); RBSMainActivity.this.scVvisVTxtFld.setText(DF.format(riser.getVVisV())); } else { RBSMainActivity.this.scVvisHTxtFld.setText(""); RBSMainActivity.this.scVvisVTxtFld.setText(""); } RBSMainActivity.this.scVvisHTxtFld.setEnabled(riser.getId() == -999); RBSMainActivity.this.scVvisVTxtFld.setEnabled(riser.getId() == -999); } @Override public void onNothingSelected(final AdapterView parent) { } }); this.scSightSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(final AdapterView parent, final View view, final int position, final long id) { ISight sight = RBSMainActivity.this.scSightSpinner.getSelectedSight(); if (sight.getId() != -999) { List listHeVis = new ArrayList(); String heVis = sight.getHeVis(); StringTokenizer t = new StringTokenizer(heVis, ","); while (t.hasMoreTokens()) { listHeVis.add(t.nextToken()); } RBSMainActivity.this.scHeVSTxtFld.setVisibility(View.INVISIBLE); RBSMainActivity.this.scHeVSTxtFld.setLayoutParams(new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSTxtFld .getLayoutParams().width, RBSMainActivity.this.scHeVSTxtFld .getLayoutParams().height, 0f)); RBSMainActivity.this.scHeVSSpinner.setVisibility(View.VISIBLE); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSSpinner.getLayoutParams().width, RBSMainActivity.this.scHeVSSpinner.getLayoutParams().height, 1f); params.gravity = Gravity.FILL_VERTICAL; RBSMainActivity.this.scHeVSSpinner.setLayoutParams(params); RBSMainActivity.this.scHeVSSpinner.setAdapter(new FontArrayAdapter(RBSMainActivity.this, R.layout.rbs_spinner, listHeVis, RBSMainActivity.this.scHeVSSpinner)); if (RBSMainActivity.this.selectedHeVS == null) { if (RBSMainActivity.this.selectedArcherySetup != null && RBSMainActivity.this.selectedArcherySetup.getSight().getId() == sight.getId()) { RBSMainActivity.this.scHeVSSpinner.setSelectionByVal(DF.format(RBSMainActivity.this.selectedArcherySetup .getSightHorSetting())); } } else { RBSMainActivity.this.scHeVSSpinner.setSelectionByVal(RBSMainActivity.this.selectedHeVS); } RBSMainActivity.this.scaVTxtFld.setText(DF.format(sight.getAV())); RBSMainActivity.this.scaHTxtFld.setText(DF.format(sight.getAH())); RBSMainActivity.this.scVertScaleRngTxtFld.setText(DF.format(sight.getVertSkalaRangeMin()) + "-" + DF.format(sight.getVertSkalaRangeMax())); } else { RBSMainActivity.this.scHeVSSpinner.setVisibility(View.INVISIBLE); RBSMainActivity.this.scHeVSSpinner.setLayoutParams(new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSSpinner .getLayoutParams().width, RBSMainActivity.this.scHeVSSpinner .getLayoutParams().height, 0f)); RBSMainActivity.this.scHeVSTxtFld.setVisibility(View.VISIBLE); RBSMainActivity.this.scHeVSTxtFld.setLayoutParams(new LinearLayout.LayoutParams(RBSMainActivity.this.scHeVSTxtFld .getLayoutParams().width, RBSMainActivity.this.scHeVSTxtFld .getLayoutParams().height, 1f)); RBSMainActivity.this.scHeVSSpinner.setAdapter(new FontArrayAdapter(RBSMainActivity.this, R.layout.rbs_spinner, new ArrayList(), RBSMainActivity.this.scHeVSSpinner)); RBSMainActivity.this.scaVTxtFld.setText(""); RBSMainActivity.this.scaHTxtFld.setText(""); RBSMainActivity.this.scVertScaleRngTxtFld.setText(""); } RBSMainActivity.this.scaVTxtFld.setEnabled(sight.getId() == -999); RBSMainActivity.this.scaHTxtFld.setEnabled(sight.getId() == -999); RBSMainActivity.this.scVertScaleRngTxtFld.setEnabled(sight.getId() == -999); } @Override public void onNothingSelected(final AdapterView parent) { } }); } private void addTouchListeners() { // Scrollview muss den Swipe selbst handeln this.paramsScrollView.setOnTouchListener(new OnTouchListener() { private float downX, downY, upX, upY; @Override public boolean onTouch(final View v, final MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { this.downX = event.getX(); this.downY = event.getY(); } case MotionEvent.ACTION_UP: { this.upX = event.getX(); this.upY = event.getY(); float deltaX = this.upX - this.downX; float deltaY = this.upY - this.downY; // swipe from right to left ? if (deltaX < 0 && Math.abs(deltaX) > MIN_DISTANCE && Math.abs(deltaY) < MIN_DISTANCE) { // set the required Animation type to ViewFlipper // The Next screen will come in form Right and current Screen will go OUT to Left RBSMainActivity.this.viewFlipper.setInAnimation(RBSMainActivity.this, R.anim.in_from_right); RBSMainActivity.this.viewFlipper.setOutAnimation(RBSMainActivity.this, R.anim.out_to_left); // Show The Next Screen RBSMainActivity.this.viewFlipper.showNext(); deactivateXTextView(RBSMainActivity.this.txtViewParams); xTextViewUp(RBSMainActivity.this.txtViewResults); deactivateXTextView(RBSMainActivity.this.txtViewSight); } } } return false; } }); // Scrollview muss den Swipe selbst handeln this.sightCfgScrollView.setOnTouchListener(new OnTouchListener() { private float downX, downY, upX, upY; @Override public boolean onTouch(final View v, final MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { this.downX = event.getX(); this.downY = event.getY(); } case MotionEvent.ACTION_UP: { this.upX = event.getX(); this.upY = event.getY(); float deltaX = this.upX - this.downX; float deltaY = this.upY - this.downY; // swipe from left to right? if (deltaX > 0 && Math.abs(deltaX) > MIN_DISTANCE && Math.abs(deltaY) < MIN_DISTANCE) { // set the required Animation type to ViewFlipper // The Next screen will come in form Right and current Screen will go OUT to Left RBSMainActivity.this.viewFlipper.setInAnimation(RBSMainActivity.this, R.anim.in_from_left); RBSMainActivity.this.viewFlipper.setOutAnimation(RBSMainActivity.this, R.anim.out_to_right); // Show The Next Screen RBSMainActivity.this.viewFlipper.showPrevious(); deactivateXTextView(RBSMainActivity.this.txtViewSight); xTextViewUp(RBSMainActivity.this.txtViewResults); deactivateXTextView(RBSMainActivity.this.txtViewParams); } } } return false; } }); // Touchlistener für die oberen 3 Tabs OnTouchListener tabListener = new OnTouchListener() { @Override public boolean onTouch(final View v, final MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { deactivateAllXTextView(); xTextViewDown((XTextView) v); return true; } case MotionEvent.ACTION_UP: { RBSMainActivity.this.viewFlipper.setInAnimation(RBSMainActivity.this, R.anim.in_from_right); RBSMainActivity.this.viewFlipper.setOutAnimation(RBSMainActivity.this, R.anim.out_to_left); if (v == RBSMainActivity.this.txtViewParams) { if (RBSMainActivity.this.viewFlipper.getDisplayedChild() != 0) { RBSMainActivity.this.viewFlipper.setDisplayedChild(0); } } else if (v == RBSMainActivity.this.txtViewResults) { if (RBSMainActivity.this.viewFlipper.getDisplayedChild() != 1) { RBSMainActivity.this.viewFlipper.setDisplayedChild(1); } } else { if (RBSMainActivity.this.viewFlipper.getDisplayedChild() != 2) { RBSMainActivity.this.viewFlipper.setDisplayedChild(2); } } xTextViewUp((XTextView) v); return true; } } return false; } }; // Touchlistener an Tabs anhängen this.txtViewParams.setOnTouchListener(tabListener); this.txtViewResults.setOnTouchListener(tabListener); this.txtViewSight.setOnTouchListener(tabListener); this.calcSettingBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { calculateSettings(); } }); } private void addValueChangeListeners() { this.arrowV0TxtFld.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { } @Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { } @Override public void afterTextChanged(final Editable s) { if (!RBSMainActivity.this.arrowV0TxtFld.getText().toString().isEmpty() && !RBSMainActivity.this.shootingDistanzTxtFld.getText().toString().isEmpty()) { calculateAndSetPerformantAccuracy(Double.valueOf(RBSMainActivity.this.arrowV0TxtFld.getText().toString()), Double.valueOf(RBSMainActivity.this.shootingDistanzTxtFld.getText().toString())); } } }); this.shootingDistanzTxtFld.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { } @Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { } @Override public void afterTextChanged(final Editable s) { if (!RBSMainActivity.this.arrowV0TxtFld.getText().toString().isEmpty() && !RBSMainActivity.this.shootingDistanzTxtFld.getText().toString().isEmpty()) { calculateAndSetPerformantAccuracy(Double.valueOf(RBSMainActivity.this.arrowV0TxtFld.getText().toString()), Double.valueOf(RBSMainActivity.this.shootingDistanzTxtFld.getText().toString())); } } }); } @Override public boolean onPrepareOptionsMenu(final Menu menu) { int size = menu.size(); for (int i = size - 1; i >= 0; i--) { menu.removeItem(menu.getItem(i).getItemId()); } if (this.showInfoMenu) { this.showInfoMenu = false; getMenuInflater().inflate(R.menu.rbs_info_menu, menu); } else { getMenuInflater().inflate(R.menu.rbs_main, menu); } return true; } @Override public boolean onOptionsItemSelected(final MenuItem item) { // Handle item selection switch (item.getItemId()) { case R.id.chooseConfiguration: showDialog(DLG_CHOOSE_ARCHERYSETUP); return true; case R.id.doCalculation: calculate(); return true; case R.id.addConfiguration: Intent intent = new Intent(RBSMainActivity.this, MainConfigurationActivity.class); startActivity(intent); return true; case R.id.moreItems: this.showInfoMenu = true; closeOptionsMenu(); new Handler().post(new Runnable() { @Override public void run() { openOptionsMenu(); } }); return true; default: return super.onOptionsItemSelected(item); } } @Override public boolean onTouchEvent(final MotionEvent touchevent) { switch (touchevent.getAction()) { // when user first touches the screen to swap case MotionEvent.ACTION_DOWN: { this.lastX = touchevent.getX(); break; } case MotionEvent.ACTION_UP: { float currentX = touchevent.getX(); // if right to left swipe on screen if (this.lastX > currentX) { if (this.viewFlipper.getDisplayedChild() == 2) { break; } // set the required Animation type to ViewFlipper // The Next screen will come in form Right and current Screen will go OUT to Left this.viewFlipper.setInAnimation(this, R.anim.in_from_right); this.viewFlipper.setOutAnimation(this, R.anim.out_to_left); // Show The Next Screen this.viewFlipper.showNext(); } else if (this.lastX < currentX) { // if left to right swipe on screen // If no more View/Child to flip if (this.viewFlipper.getDisplayedChild() == 0) { break; } // set the required Animation type to ViewFlipper // The Next screen will come in form Left and current Screen will go OUT to Right this.viewFlipper.setInAnimation(this, R.anim.in_from_left); this.viewFlipper.setOutAnimation(this, R.anim.out_to_right); // Show the previous Screen this.viewFlipper.showPrevious(); } deactivateAllXTextView(); switch (this.viewFlipper.getDisplayedChild()) { case 0: xTextViewUp(this.txtViewParams); break; case 1: xTextViewUp(this.txtViewResults); break; case 2: xTextViewUp(this.txtViewSight); break; default: break; } break; } } return false; } private void xTextViewDown(final XTextView view) { view.setDrawborderColor(getResources().getColor(R.color.android_yellow_dark)); view.setTextColor(getResources().getColor(R.color.android_yellow_dark)); } private void xTextViewUp(final XTextView view) { view.setDrawborderColor(getResources().getColor(R.color.android_yellow)); view.setTextColor(getResources().getColor(R.color.android_yellow)); } private void deactivateXTextView(final XTextView view) { view.setDrawborderColor(getResources().getColor(R.color.white)); view.setTextColor(getResources().getColor(R.color.white)); } private void deactivateAllXTextView() { deactivateXTextView(this.txtViewParams); deactivateXTextView(this.txtViewResults); deactivateXTextView(this.txtViewSight); } @Override protected Dialog onCreateDialog(final int id) { return DialogFactory.createDialog(id, this); } @Override public void onArcherySetupDlgDismissed(final IArcherySetup archerySetup) { this.selectedArcherySetup = archerySetup; if (archerySetup != null && archerySetup.getId() != -999) { this.arrowDiameterTxtFld.setText(DF.format(archerySetup.getArrowDiameter())); this.arrowCwTxtFld.setText(DF.format(archerySetup.getArrowCw())); this.arrowWeightTxtFld.setText(DF.format(archerySetup.getArrowWeight())); this.bowPulloutTxtFld.setText(DF.format(archerySetup.getBowPullout())); this.arrowV0TxtFld.setText(DF.format(archerySetup.getArrowV0())); this.arrowNockHeightTxtFld.setText(DF_1.format(archerySetup.getArrowNockHeight())); this.targetCenterHeightTxtFld.setText(DF_1.format(archerySetup.getArrowCenterHeight())); this.calcTimeIntervalCboBox.setSelectionByVal(archerySetup.getDeltaTime().toString()); this.calcAccuracyCboBox.setSelectionByVal(archerySetup.getCalcPrecision().toString()); this.scRiserSpinner.setSelectedRiser(archerySetup.getRiser()); this.scRiserSpinner.fireSelectionChangedEvent(); this.scSightSpinner.setSelectedSight(archerySetup.getSight()); this.scSightSpinner.fireSelectionChangedEvent(); this.scVertScaleMiddleTxtFld.setText(DF.format(archerySetup.getSightVertSkalaMiddle())); this.airTemperatureTxtFld.setText(DEF_TEMP); this.airRelativeHumidityTxtFld.setText(DEF_HUMIDITY); this.shootingDistanzTxtFld.setText(DEF_DISTANCE); } else { this.arrowDiameterTxtFld.setText(""); this.arrowDiameterTxtFld.setText(""); this.arrowCwTxtFld.setText(""); this.arrowWeightTxtFld.setText(""); this.bowPulloutTxtFld.setText(""); this.arrowV0TxtFld.setText(""); this.arrowNockHeightTxtFld.setText(""); this.targetCenterHeightTxtFld.setText(""); this.calcTimeIntervalCboBox.setSelectionByVal(""); this.calcAccuracyCboBox.setSelectionByVal(""); this.scRiserSpinner.setSelection(0); this.scRiserSpinner.fireSelectionChangedEvent(); this.scSightSpinner.setSelection(0); this.scSightSpinner.fireSelectionChangedEvent(); this.scVertScaleMiddleTxtFld.setText(""); } } private boolean allParamFieldsValid() { return !this.arrowDiameterTxtFld.getText().toString().isEmpty() && !this.arrowCwTxtFld.getText().toString().isEmpty() && !this.arrowWeightTxtFld.getText().toString().isEmpty() && !this.bowPulloutTxtFld.getText().toString().isEmpty() && !this.arrowV0TxtFld.getText().toString().isEmpty() && !this.airTemperatureTxtFld.getText().toString().isEmpty() && !this.airRelativeHumidityTxtFld.getText().toString().isEmpty() && !this.shootingDistanzTxtFld.getText().toString().isEmpty() && !this.arrowNockHeightTxtFld.getText().toString().isEmpty() && !this.targetCenterHeightTxtFld.getText().toString().isEmpty() && this.calcTimeIntervalCboBox.getSelectedItem() != null && this.calcAccuracyCboBox.getSelectedItem() != null && allSightParamFieldsValid(); } private boolean allSightParamFieldsValid() { return !this.scVvisHTxtFld.getText().toString().isEmpty() && !this.scVvisVTxtFld.getText().toString().isEmpty() && !this.scaHTxtFld.getText().toString().isEmpty() && !this.scaVTxtFld.getText().toString().isEmpty() && !this.scVertScaleRngTxtFld.getText().toString().isEmpty() && ((this.scHeVSSpinner.getVisibility() == View.VISIBLE && this.scHeVSSpinner.getSelectedItem() != null) || (this.scHeVSTxtFld.getVisibility() == View.VISIBLE && !this.scHeVSTxtFld.getText().toString().isEmpty())) && !this.scVertScaleMiddleTxtFld.getText().toString().isEmpty(); } /** * Startet die Berechnung wenn alle notwendigen Felder gefüllt sind. */ private void calculate() { if (allParamFieldsValid()) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (getCurrentFocus() != null) { imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } this.progressDialog = ProgressDialog.show(this, null, getResources().getString(R.string.caption_Calculating), true, false); CalculationTask calcTask = new CalculationTask(); TrajectoryCalculator calculator = new TrajectoryCalculator(Double.valueOf(this.arrowDiameterTxtFld.getText().toString().trim()) * MILLI, // Double.valueOf(this.arrowCwTxtFld.getText().toString().trim()), // Double.valueOf(this.arrowWeightTxtFld.getText().toString().trim()) * MILLI, // Double.valueOf(this.arrowV0TxtFld.getText().toString().trim()), // Double.valueOf(this.shootingDistanzTxtFld.getText().toString().trim()), // Double.valueOf(this.targetCenterHeightTxtFld.getText().toString().trim()) - Double.valueOf(this.arrowNockHeightTxtFld.getText().toString().trim()), // Double.valueOf(this.airTemperatureTxtFld.getText().toString().trim()), // Double.valueOf(this.airRelativeHumidityTxtFld.getText().toString().trim()) * CENTI, // Double.valueOf(this.calcTimeIntervalCboBox.getSelectedItem().toString().trim()), // Double.valueOf(this.calcAccuracyCboBox.getSelectedItem().toString().trim()) * CENTI, // this); calculator.setStartAngle(0d); calcTask.execute(calculator); } else { Toast toast = Toast.makeText(this, getResources().getString(R.string.caption_FillAllMandatoryFields), Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } } @Override public void updateTrajectoryTxtFld(final Integer step, final Double[] flightCurveRow, final Double startAngle, final Double[] maxHCurve) { int width = this.flightCurveTxtFld.getMeasuredWidth(); Double[] r1 = flightCurveRow; switch (step) { case 0: this.flightCurveTxtFld.setText(""); this.flightCurveTxtFld.append(getResources().getString(R.string.fcChart_StartAngle) + DF_FC.format(startAngle) + " °\n\n"); this.flightCurveTxtFld.append(getResources().getString(R.string.fcChart_MaxHeight) + DF_FC.format(maxHCurve[0]) + " m / " + DF_FC.format(maxHCurve[0] + Double.valueOf(this.arrowNockHeightTxtFld.getText().toString().trim())) + " m, [t = " + DF_FC.format(maxHCurve[1]) + " s]\n\n"); this.flightCurveTxtFld.append(getResources().getString(R.string.fcChart_FlightDuration) + DF_FC.format(r1[TrajectoryCalculator.IDX_T]) + " sec\n\n"); SpannableString line = new SpannableString("t [sec]\tVx [m/s]\tVy [m/s]\tx [m]\ty [m]\n\n"); line.setSpan(new TabStopSpan.Standard(width / 5), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); line.setSpan(new TabStopSpan.Standard(width / 5 * 2), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); line.setSpan(new TabStopSpan.Standard(width / 5 * 3), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); line.setSpan(new TabStopSpan.Standard(width / 5 * 4), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); this.flightCurveTxtFld.append(line); break; case 1: line = new SpannableString(DF_FC.format(r1[TrajectoryCalculator.IDX_T]) + '\t' + DF_FC.format(r1[TrajectoryCalculator.IDX_VX]) + '\t' + DF_FC.format(r1[TrajectoryCalculator.IDX_VY]) + '\t' + DF_FC.format(r1[TrajectoryCalculator.IDX_X]) + '\t' + DF_FC.format(r1[TrajectoryCalculator.IDX_Y]) + "\n"); line.setSpan(new TabStopSpan.Standard(width / 5), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); line.setSpan(new TabStopSpan.Standard(width / 5 * 2), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); line.setSpan(new TabStopSpan.Standard(width / 5 * 3), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); line.setSpan(new TabStopSpan.Standard(width / 5 * 4), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); this.flightCurveTxtFld.append(line); break; default: break; } } @Override public void onCalculationDone(final Double[][] flightCurve, final Double startAngle, final Double[] maxHCurve) { this.startAngle = startAngle; updateFlightCurveChart(flightCurve); calculateSettings(); if (this.progressDialog != null) { this.progressDialog.dismiss(); } this.txtViewSight.doSingleTouch(); } /** * @param flightCurve */ private void updateFlightCurveChart(final Double[][] flightCurve) { XYSeries serie = new XYSeries(getApplicationContext().getResources().getString(R.string.fcChart_TitleLable)); for (int i = 0; i < flightCurve.length; i++) { serie.add(flightCurve[i][TrajectoryCalculator.IDX_X], flightCurve[i][TrajectoryCalculator.IDX_Y]); } this.flightCurveChart.getDataSet().removeSeries(0); this.flightCurveChart.getDataSet().addSeries(0, serie); this.flightCurveChart.updateRendererAfterCalculation(flightCurve[flightCurve.length - 1][TrajectoryCalculator.IDX_X], flightCurve); } /** * Berechnet die definitve Visiereinstellung anhand des berechneten Flugbahnwinkels. */ private void calculateSettings() { if (allSightParamFieldsValid() && this.selectedArcherySetup != null && this.startAngle != null) { Double x0; Double y0; Double x1; Double y1; Double x2; Double y2; Double x3; Double y3; Double r; Double s; Double vVh = Double.valueOf(this.scVvisHTxtFld.getText().toString()) + Double.valueOf(this.scaHTxtFld.getText().toString()); Double vVv = Double.valueOf(this.scVvisVTxtFld.getText().toString()) + Double.valueOf(this.scaVTxtFld.getText().toString()); Double a = Double.valueOf(this.bowPulloutTxtFld.getText().toString()) * 10; Double heVs = this.scHeVSSpinner.getVisibility() == View.VISIBLE ? Double.valueOf(this.scHeVSSpinner.getSelectedItem().toString()) : Double.valueOf(this.scHeVSTxtFld.getText().toString()); Double lhNA = this.selectedArcherySetup.getHNA() * 10; Double dltH = (Double.valueOf(this.targetCenterHeightTxtFld.getText().toString()) - Double.valueOf(this.arrowNockHeightTxtFld.getText().toString())) * Math.pow(10, 3); Double ldistH = Double.valueOf(this.shootingDistanzTxtFld.getText().toString()) * Math.pow(10, 3); Double minSkala = this.scVertScaleRngTxtFld.getText().toString().contains("-") ? Double.valueOf(this.scVertScaleRngTxtFld.getText().toString().substring(0, this.scVertScaleRngTxtFld.getText().toString() .indexOf('-'))) : 0d; Double maxSkala = this.scVertScaleRngTxtFld.getText().toString().contains("-") ? Double.valueOf(this.scVertScaleRngTxtFld.getText().toString().substring(this.scVertScaleRngTxtFld.getText().toString() .indexOf('-') + 1, this.scVertScaleRngTxtFld.getText().toString() .length())) : 0d; // PIN auf Höhe Pfeil x0 = (a + vVh + heVs) * Math.cos(Math.toRadians(this.startAngle)); y0 = (a + vVh + heVs) * Math.sin(Math.toRadians(this.startAngle)); // PIN auf Höhe Horizontalschlitten Visier x2 = x0 + vVv * Math.cos(Math.toRadians(ANGLE_90 + this.startAngle)); y2 = y0 + vVv * Math.sin(Math.toRadians(ANGLE_90 + this.startAngle)); // Schnittpunkt der Achse Horizontalschlitten Visier mit Achse Befestigungslöcher Visier x3 = (a + vVh) * Math.cos(Math.toRadians(this.startAngle)) + vVv * Math.cos(Math.toRadians(ANGLE_90 + this.startAngle)); y3 = (a + vVh) * Math.sin(Math.toRadians(this.startAngle)) + vVv * Math.sin(Math.toRadians(ANGLE_90 + this.startAngle)); // Unbekannte der Vektorgeradengleichung r = (lhNA * (x0 - x2) - x0 * y2 + x2 * y0) / (ldistH * (y0 - y2) + (dltH - lhNA) * (x2 - x0)); s = -((ldistH * (lhNA - y0) + (dltH - lhNA) * x0) / (ldistH * (y0 - y2) + (dltH - lhNA) * (x2 - x0))); // Pin auf Visierlinie x1 = r * ldistH; y1 = lhNA + r * (dltH - lhNA); // Unten (+) oder oben (-) von (x2/y2) ? Double n = ((y2 - y3) * (x1 - x3) - (x2 - x3) * (y1 - y3)) < 0 ? -1.0 : 1.0; // Abstand P1 - P2 Double d = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) * n; // Einstellung auf vert. Skala Double sV = Double.valueOf(this.scVertScaleMiddleTxtFld.getText().toString()) + d; this.scEvSValue.setText(DF_EVS.format(sV)); if (minSkala <= sV && sV <= maxSkala) { this.scEvSValue.setBackgroundDrawable(getResources().getDrawable(R.drawable.evs_ok_background)); } else { this.scEvSValue.setBackgroundDrawable(getResources().getDrawable(R.drawable.evs_nok_background)); } } else { this.scEvSValue.setText(""); Toast toast = Toast.makeText(this, getResources().getString(R.string.caption_FillAllMandatoryFields), Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } } private void calculateAndSetPerformantAccuracy(final Double v0, final Double shootingDistance) { String[] calcAccuracies = getResources().getStringArray(R.array.CalculationTimeIntervals); String calcAccuracyToSet = calcAccuracies[calcAccuracies.length - 1]; Double approxFlightTime = shootingDistance / v0; Double approxIntervalTime = approxFlightTime / MAX_TRAJ_POINTS; for (int i = 0; i < calcAccuracies.length - 1; i++) { Double accLow = Double.valueOf(calcAccuracies[i]); Double accHigh = Double.valueOf(calcAccuracies[i + 1]); if (accHigh < approxIntervalTime && approxIntervalTime <= accLow) { calcAccuracyToSet = calcAccuracies[i]; break; } } this.calcTimeIntervalCboBox.setSelectionByVal(calcAccuracyToSet); } }