package uk.org.smithfamily.mslogger.dialog; import uk.org.smithfamily.mslogger.ApplicationSettings; import uk.org.smithfamily.mslogger.R; import uk.org.smithfamily.mslogger.ecuDef.Constant; import uk.org.smithfamily.mslogger.ecuDef.CurveEditor; import uk.org.smithfamily.mslogger.ecuDef.DialogField; import uk.org.smithfamily.mslogger.ecuDef.DialogPanel; import uk.org.smithfamily.mslogger.ecuDef.MSDialog; import uk.org.smithfamily.mslogger.ecuDef.Megasquirt; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TableRow.LayoutParams; /** * Helper class used for dialogs */ public class DialogHelper { /** * This function verify if the user entered value is in range for the specifing constant * Show an alert dialog if it's not with indication to the user on how to fix it * * @param context The context the function was called * @param constant The constant to look for min and max value * @param cell The cell the user was typing in */ public static void verifyOutOfBoundValue(Context context, Constant constant, final EditText cell) { double currentValue = Double.parseDouble(cell.getText().toString()); double minValue = Double.parseDouble(constant.getLow()); double maxValue = Double.parseDouble(constant.getHigh()); String message = ""; if (currentValue < minValue) { message = "Constant " + constant.getName() + " value is lower then the minimum allowed (" + currentValue + " < " + minValue + ")"; } if (currentValue > maxValue) { message = "Constant " + constant.getName() + " value is higher then the maximum allowed (" + currentValue + " > " + maxValue + ")"; } if (!message.equals("")) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(message) .setIcon(android.R.drawable.ic_dialog_alert) .setTitle("Value is out of bound") .setCancelable(true) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { cell.requestFocus(); } }); AlertDialog alert = builder.create(); alert.show(); } } /** * This function build the custom std_* dialog that aren't defined in the ini * * @param dialogName The name of the dialog to build * * @return The dialog */ public static MSDialog getStdDialog(String dialogName) { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); // We already build that dialog, just return it if (ecu.getDialogByName(dialogName) != null) { return ecu.getDialogByName(dialogName); } // Accel Enrichment Wizard if (dialogName.equals("std_accel")) { return buildStdAccel(); } else if (dialogName.equals("std_injection")) { return buildStdInjection(); } // Warmup Enrichment else if (dialogName.equals("std_warmup")) { return buildStdWarmup(); } // Real-time Display else if (dialogName.equals("std_realtime")) { return buildStdRealtime(); } // Constants else if (dialogName.equals("std_constants")) { return buildStdConstants(); } // MS3 Real-time Clock else if (dialogName.equals("std_ms3Rtc")) { return buildStdRtc(); } // Trigger wizard else if (dialogName.equals("std_trigwiz")) { return buildStdTriggerWizard(); } return null; } /** * This function return an instance of a custom dialog that cannot be covered by a simple MSDialog * * @param context The context the dialog will be used in * @param dialogName The name of the dialog to build * * @return The custom dialog instance */ public static Dialog getStdCustomDialog(Context context, String dialogName) { if (dialogName.equals("std_ms3SdConsole")) { SDCardConsole sdCardConsole = new SDCardConsole(context); return sdCardConsole; } return null; } /** * Helper function that will build the std_accel dialog * * @return An instance of MSDialog with all fields in them */ private static MSDialog buildStdAccel() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); // MAP curve CurveEditor curve = new CurveEditor("std_accel_mae_curve", "MAP Based AE"); ecu.addCurve(curve); curve.setxLabel("Rate"); curve.setyLabel("PW Adder"); curve.setxAxis(new double[] {0, 288, 57.6}); curve.setyAxis(new double[] {0, 14.4, 4.8}); String xConstant = ""; String yConstant = ""; // MS2, MS3 if (ecu.isConstantExists("maeRates")) { xConstant = "maeRates"; yConstant = "maeBins"; } // MS1 else { xConstant = "maeRates4"; yConstant = "maeBins4"; } curve.setXBins(ecu.getVector(xConstant), xConstant, 0, false); curve.setYBins(ecu.getVector(yConstant), yConstant); // TPS Curve curve = new CurveEditor("std_accel_tae_curve", "TPS Based AE"); ecu.addCurve(curve); curve.setxLabel("Rate"); curve.setyLabel("PW Adder"); curve.setxAxis(new double[] {0, 1848, 369.6}); curve.setyAxis(new double[] {0, 12, 4}); // MS2, MS3 if (ecu.isConstantExists("taeBins")) { xConstant = "taeRates"; yConstant = "taeBins"; } // MS1 else { xConstant = "taeRates4"; yConstant = "taeBins4"; } curve.setXBins(ecu.getVector(xConstant), xConstant, 0, false); curve.setYBins(ecu.getVector(yConstant), yConstant); // std_accel dialog MSDialog dialogAccel = new MSDialog("std_accel", "Accel Enrichment Wizard", "yAxis"); ecu.addDialog(dialogAccel); dialogAccel.addPanel(new DialogPanel("std_accel_north", "")); //dialogAccel.addPanel(new DialogPanel("std_accel_seek_bar_panel", "")); dialogAccel.addPanel(new DialogPanel("std_accel_south", "")); // North panel with the two curves MSDialog dialogNorth = new MSDialog("std_accel_north","",""); ecu.addDialog(dialogNorth); dialogNorth.addPanel(new DialogPanel("std_accel_mae_curve", "West")); dialogNorth.addPanel(new DialogPanel("std_accel_tae_curve", "East")); // South panel with the two columns with all the constants for TPS and MAP MSDialog dialogSouth = new MSDialog("std_accel_south", "", ""); ecu.addDialog(dialogSouth); dialogSouth.addPanel(new DialogPanel("std_accel_map", "West")); dialogSouth.addPanel(new DialogPanel("std_accel_tps", "East")); // Seek bar section MSDialog dialogCenterSeekBar = new MSDialog("std_accel_seek_bar_panel", "", ""); ecu.addDialog(dialogCenterSeekBar); dialogCenterSeekBar.addField(new DialogField("std_accel_seek_bar", "null", false, false, "")); // MAP section MSDialog dialogMap = new MSDialog("std_accel_map","","null"); ecu.addDialog(dialogMap); dialogMap.addField(new DialogField("MAPdot Threshold", "mapThresh", false, false, "")); dialogMap.addField(new DialogField("Accel Time", "taeTime", false, false, "")); // Not all MS version have support for taper time if (ecu.getConstantByName("aeTaperTime") != null) { dialogMap.addField(new DialogField("Accel Taper Time", "aeTaperTime", false, false, "")); } // Not all MS version have support for end pulsewidth if (ecu.getConstantByName("aeEndPW") != null) { dialogMap.addField(new DialogField("End Pulsewidth", "aeEndPW", false, false, "")); } // TPS section MSDialog dialogSouthTps = new MSDialog("std_accel_tps","","null"); ecu.addDialog(dialogSouthTps); dialogSouthTps.addField(new DialogField("TPSdot Threshold", "tpsThresh", false, false, "")); dialogSouthTps.addField(new DialogField("Decel Fuel Amount", "tdePct", false, false, "")); dialogSouthTps.addField(new DialogField("Cold Accel Enrichment", "taeColdA", false, false, "")); dialogSouthTps.addField(new DialogField("Cold Accel Multiplier", "taeColdM", false, false, "")); return dialogAccel; } /** * * @return */ private static MSDialog buildStdInjection() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); MSDialog dialog = new MSDialog("std_injection", "Calculate Required Fuel", ""); ecu.addDialog(dialog); dialog.addField(new DialogField("std_required_fuel", "null", false, false, "")); dialog.addField(new DialogField("Control Algorithm", "algorithm", false, false, "")); // Custom constant for number of squirts per engine cycle since this should modify // the divider constant but save the result as "divider = nCylinders / MSLogger_nSquirts" Constant constant = new Constant(1,"MSLogger_nSquirts","bits","",0,"[0:4]","",1.000000,0.000000,0,0,0,new String[] {"1","2","3","4","5","6","7","8"}); ecu.addConstant(constant); dialog.addField(new DialogField("Squirts Per Engine Cycle", "MSLogger_nSquirts", false, false, "")); dialog.addField(new DialogField("Injector Staging", "alternate", false, false, "")); dialog.addField(new DialogField("Engine Stroke/Rotary", "twoStroke", false, false, "")); dialog.addField(new DialogField("No. Cylinders/Rotors", "nCylinders", false, false, "")); dialog.addField(new DialogField("Injector Port Type", "injType", false, false, "")); dialog.addField(new DialogField("Number of Injectors", "nInjectors", false, false, "")); dialog.addField(new DialogField("Engine Type", "engineType", false, false, "")); return dialog; } /** * * @return */ private static MSDialog buildStdWarmup() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); MSDialog dialog = new MSDialog("std_warmup", "", ""); ecu.addDialog(dialog); CurveEditor curve = new CurveEditor("std_warmup_curve", "Warmup Wizard"); ecu.addCurve(curve); curve.setxLabel("Coolant Temp"); curve.setyLabel("Enrichment"); curve.setxAxis(new double[] {-60, 200, 20}); curve.setyAxis(new double[] {0, 240, 20}); String units = "�F"; int[] temp = { 103, 301, 500, 698, 896, 1094, 1292, 1508, 1706, 1797 }; String scale = "0.1"; String translate = "0"; if (ecu.isSet("CELCIUS")) { units = "�C"; scale = "0.05555"; translate = "-320"; } Constant xConstant = new Constant(1, "MSLogger_temp", "array", "", 0, "[ 10]", units, scale, translate, 0, 0, 0); ecu.addConstant(xConstant); curve.setXBins(temp, "MSLogger_temp", 0, false); curve.setYBins(ecu.getVector("wueBins9"), "wueBins9"); dialog.addPanel(new DialogPanel("std_warmup_curve", "")); return dialog; } /** * * @return */ private static MSDialog buildStdConstants() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); MSDialog dialog = new MSDialog("std_constants", "", ""); ecu.addDialog(dialog); MSDialog weastPanel = new MSDialog("std_constants_west", "", ""); weastPanel.addField(new DialogField("std_required_fuel", "null", false, false, "")); weastPanel.addField(new DialogField("Injector Opening Time", "injOpen1", false, false, "")); weastPanel.addField(new DialogField("Battery Voltage Correction", "battFac1", false, false, "")); weastPanel.addField(new DialogField("PWM Current Limit", "injPwmP1", false, false, "")); weastPanel.addField(new DialogField("PWM Time", "injPwmT1", false, false, "")); weastPanel.addField(new DialogField("Fast Idle Threshold", "fastIdleT1", false, false, "")); weastPanel.addField(new DialogField("Barometric Correction", "baroCorr1", false, false, "")); MSDialog eastPanel = new MSDialog("std_constants_east", "", ""); eastPanel.addField(new DialogField("Control Algorithm", "", false, false, "")); // Custom constant for number of squirts per engine cycle since this should modify // the divider constant but save the result as "divider = nCylinders / MSLogger_nSquirts" Constant constant = new Constant(1,"MSLogger_nSquirts","bits","",0,"[0:4]","",1.000000,0.000000,0,0,0,new String[] {"1","2","3","4","5","6","7","8"}); ecu.addConstant(constant); eastPanel.addField(new DialogField("Squirts Per Engine Cycle", "MSLogger_nSquirts", false, false, "")); eastPanel.addField(new DialogField("Injector Staging", "alternate1", false, false, "")); eastPanel.addField(new DialogField("Engine Stroke", "twoStroke1", false, false, "")); eastPanel.addField(new DialogField("Number of Cylinders", "nCylinders1", false, false, "")); eastPanel.addField(new DialogField("Number of Injectors", "nInjectors1", false, false, "")); eastPanel.addField(new DialogField("MAP Type", "mapType1", false, false, "")); eastPanel.addField(new DialogField("Engine Type", "engineType1", false, false, "")); dialog.addPanel(new DialogPanel("std_constants_west", "West")); dialog.addPanel(new DialogPanel("std_constants_east", "East")); return dialog; } /** * * @return */ private static MSDialog buildStdRealtime() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); MSDialog dialog = new MSDialog("std_realtime", "", ""); ecu.addDialog(dialog); return dialog; } /** * * @return */ private static MSDialog buildStdRtc() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); MSDialog dialog = new MSDialog("std_ms3Rtc", "MS3 Real-time Clock", ""); ecu.addDialog(dialog); return dialog; } /** * * @return */ private static MSDialog buildStdTriggerWizard() { Megasquirt ecu = ApplicationSettings.INSTANCE.getEcuDefinition(); MSDialog dialog = new MSDialog("std_trigwiz", "Trigger Wizard", ""); ecu.addDialog(dialog); // TODO: need numeric indicator added here dialog.addField(new DialogField("Match above value with timing light reading.", "null", false, false, "")); dialog.addField(new DialogField("Ignition Offset Angle", "triggerOffset", false, false, "")); return dialog; } /** * Build a custom layout panel and return it * * @param panelName The panel of the panel to build * * @return The relative layout instance with the custom components inside */ public static RelativeLayout getCustomPanel(Context context, String panelName) { if (panelName.equals("dataLogFieldSelector")) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); LinearLayout datalogFieldSelectorLayout = (LinearLayout) inflater.inflate(R.layout.sd_card_datalog_field_selector, null); // Wrap into relative layout RelativeLayout containerPanelLayout = new RelativeLayout(context); RelativeLayout.LayoutParams tlp = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); containerPanelLayout.setLayoutParams(tlp); containerPanelLayout.addView(datalogFieldSelectorLayout); Button selectAll = (Button) datalogFieldSelectorLayout.findViewById(R.id.select_all); selectAll.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { } }); Button deselectAll = (Button) datalogFieldSelectorLayout.findViewById(R.id.deselect_all); deselectAll.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { } }); Button selectOne = (Button) datalogFieldSelectorLayout.findViewById(R.id.select_one); selectOne.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { } }); Button deselectOne = (Button) datalogFieldSelectorLayout.findViewById(R.id.deselect_one); deselectOne.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { } }); return containerPanelLayout; } return null; } }