//-----------------------------------------------------------------------
//
// Copyright © 2012 Nils Hammar. All rights reserved.
//
//-----------------------------------------------------------------------
/*
* Software to access vehicle information via the OBD-II connector.
*
* Copyright © 2012 Nils Hammar
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Alternative licensing is possible, see the licensing document.
*
* The above text may not be removed or modified.
*/
namespace Gauges
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using global::Gauges.TelltalePanel;
using global::SharedObjects.DataMgmt;
using global::SharedObjects.Misc;
///
/// Class for editing details for a telltale.
///
public partial class TelltaleDetails : Form
{
///
/// Gets telltale item instance.
///
public XmlClass.telltaleitem telltaleitem { get; private set; }
///
/// Gets PID name.
///
public string pidName { get; private set; }
///
/// Gets Sensor name.
///
public string sensorName { get; private set; }
///
/// Gets Sensor bit.
///
public int sensorBit { get; private set; }
///
/// Gets PID name.
///
public string digitalPidName { get; private set; }
///
/// List of PID groups.
///
private IList pidgrouplist;
///
/// List of PIDs in PID Group with bit sensors.
///
private IList pidgrouppids;
///
/// List of sensors on current PID.
///
private IList pidsensors;
///
/// Current PID group.
///
private XmlClass.pidgroup pidgroup;
///
/// Current PID.
///
private XmlClass.pidgroup.pidlist pid;
///
/// Current sensor.
///
private XmlClass.pidgroup.pidlist.sensordata sensor;
///
/// Array of used telltales, used to avoid double-booking telltales.
///
private uint[] usedItems;
///
/// Current data source instance.
///
private IDataSource iDataSource;
///
/// Data file directory path.
///
private string dataFileDir;
///
/// Current color palette.
///
private PaletteCreator palette;
///
/// Initializes a new instance of the class.
///
/// Data file directory.
/// Data source instance.
/// Telltale item.
/// Array of used telltales, used to avoid double-booking telltales.
/// Initial color palette.
public TelltaleDetails(
string dataFileDir,
IDataSource iDataSource,
XmlClass.telltaleitem telltaleitem,
uint[] usedItems,
PaletteCreator palette)
{
this.dataFileDir = dataFileDir;
this.iDataSource = iDataSource;
this.telltaleitem = telltaleitem;
this.usedItems = usedItems;
this.palette = palette;
this.sensorBit = -1;
IList providedPidGroups = this.iDataSource.restrictedPidgroups;
this.pidgrouplist = new List();
if (this.telltaleitem == null)
{
this.telltaleitem = new XmlClass.telltaleitem();
}
this.InitializeComponent();
this.pidgrouppids = new List();
for (int i1 = -99; i1 < 100; i1++)
{
this.priorityComboBox.Items.Add(i1.ToString());
}
this.priorityComboBox.SelectedIndex = 99 + this.telltaleitem.telltalePriority;
this.telltaleGroupNumTB.Text = this.telltaleitem.telltaleGroupNumber.ToString();
this.telltaleTextTB.Text = this.telltaleitem.telltaletext;
this.pidGroupsCB.Items.Clear();
this.itemCB.Items.Clear();
this.sensorLB.Items.Clear();
this.pidGroupsCB.SelectedIndex = -1;
int pidGrpIx = -1;
int i = 0;
foreach (XmlClass.pidgroup pidGrp in providedPidGroups)
{
bool hasBit = false;
if (pidGrp.pids != null)
{
foreach (XmlClass.pidgroup.pidlist pid in pidGrp.pids)
{
if (pid != null)
{
foreach (XmlClass.pidgroup.pidlist.sensordata sensor in pid.sensors)
{
if (sensor.unit == "bit")
{
hasBit = true;
break;
}
}
}
if (hasBit)
{
break;
}
}
}
if (hasBit)
{
this.pidGroupsCB.Items.Add(pidGrp.name);
this.pidgrouplist.Add(pidGrp);
if (this.telltaleitem != null
&& this.telltaleitem.pidgroupid == pidGrp.id)
{
pidGrpIx = i;
}
i++;
}
}
if (this.pidGroupsCB.Items.Count > 0)
{
if (pidGrpIx >= 0 && pidGrpIx < this.pidGroupsCB.Items.Count)
{
this.pidGroupsCB.SelectedIndex = pidGrpIx;
}
else
{
this.pidGroupsCB.SelectedIndex = 0;
}
}
this.setIconImage(this.telltaleitem.telltaleicon);
if (this.telltaleitem != null)
{
this.primaryColorBox.BackColor = string.IsNullOrEmpty(this.telltaleitem.primaryColor) ? Color.Transparent : Color.FromName(this.telltaleitem.primaryColor);
this.secondaryColorBox.BackColor = string.IsNullOrEmpty(this.telltaleitem.secondaryColor) ? Color.Transparent : Color.FromName(this.telltaleitem.secondaryColor);
this.flashColorBox.BackColor = string.IsNullOrEmpty(this.telltaleitem.flashColor) ? Color.Transparent : Color.FromName(this.telltaleitem.flashColor);
}
else
{
this.primaryColorBox.BackColor = Color.Transparent;
this.secondaryColorBox.BackColor = Color.Transparent;
this.flashColorBox.BackColor = Color.Transparent;
}
}
///
/// Numeric validation of input data.
///
/// Sending object.
/// Event data.
/// Parsed numeric value.
private static uint numericIntValidation(object sender, CancelEventArgs e)
{
TextBox tb = (TextBox)sender;
uint scaleSteps = 0;
try
{
scaleSteps = Convert.ToUInt32(tb.Text);
}
catch
{
MessageBox.Show(
"Field must be numeric.",
"Data Failure",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
e.Cancel = true;
}
return scaleSteps;
}
///
/// Test for float value.
///
/// Sending object.
/// Event data.
/// Parsed float value.
private static float numericFloatValidation(object sender, CancelEventArgs e)
{
TextBox tb = (TextBox)sender;
float value = 0;
try
{
value = Convert.ToSingle(tb.Text);
}
catch
{
MessageBox.Show(
"Field must be numeric.",
"Data Failure",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
e.Cancel = true;
}
return value;
}
///
/// PidGroup checkbox change.
///
/// Current PID group.
/// Combobox that changed.
/// List of valid PID groups.
/// Offset value in combo box index.
/// New PID group or 'null' if not applicable.
private static XmlClass.pidgroup pidGroupChange(
XmlClass.pidgroup pidgroup,
ComboBox cb,
IList pidgrouplist,
int offset)
{
if (cb.SelectedIndex >= offset && cb.SelectedIndex < cb.Items.Count)
{
pidgroup = pidgrouplist[cb.SelectedIndex - offset];
}
else
{
if (offset == 1)
{
pidgroup = null;
}
}
return pidgroup;
}
///
/// Update Item Combo Box.
///
/// Current PID group.
/// Items combobox.
/// PID value.
/// Actual available list of PIDs in PID group. (out data)
private static void updateItemCB(XmlClass.pidgroup pidgroup, ComboBox itemCB, uint telltalePid_int, IList pidgrouppids)
{
int pidIx = -1;
int i = 0;
foreach (XmlClass.pidgroup.pidlist pidItem in pidgroup.pids)
{
bool hasBit = false;
foreach (XmlClass.pidgroup.pidlist.sensordata sensor in pidItem.sensors)
{
if (sensor.unit == "bit")
{
hasBit = true;
break;
}
}
if (hasBit)
{
itemCB.Items.Add(pidItem.name);
pidgrouppids.Add(pidItem);
if (telltalePid_int == pidItem.pid_int)
{
pidIx = i;
}
i++;
}
}
if (pidIx >= 0 && pidIx < itemCB.Items.Count)
{
itemCB.SelectedIndex = pidIx;
}
else
{
if (itemCB.Items.Count > 0)
{
itemCB.SelectedIndex = 0;
}
}
}
///
/// Change data for item combo box.
///
/// Item combo box instance.
/// Sensor combo box instance.
/// List of current PIDs supporting telltales.
/// Telltale item instance.
/// Selected PID.
/// List of valid sensors for selected pid.
/// PID name.
private static string itemCbChange(
ComboBox cb,
ListBox sensorCB,
IList pids,
XmlClass.telltaleitem telltaleitem,
ref XmlClass.pidgroup.pidlist pid,
IList pidsensors)
{
string pidName = string.Empty;
sensorCB.Items.Clear();
pid = pids[cb.SelectedIndex];
pidName = pid.name;
int sensorIx = -1;
int i = 0;
foreach (XmlClass.pidgroup.pidlist.sensordata sensorItem in pid.sensors)
{
try
{
if (sensorItem.unit == "bit")
{
string sensorInfo = string.Empty;
if (sensorItem.name != null)
{
sensorInfo += sensorItem.name + " ";
}
sensorInfo += "(" + sensorItem.unit + ")";
sensorCB.Items.Add(sensorInfo);
pidsensors.Add(sensorItem);
int sensorBit = Convert.ToInt32(sensorItem.startbit);
if (telltaleitem != null
&& telltaleitem.sensor_unit != null
&& telltaleitem.sensor_unit.Equals(sensorItem.unit)
&& telltaleitem.sensor_offset == sensorItem.offset
&& (sensorBit == -1 || telltaleitem.sensor_bit == sensorBit))
{
sensorIx = i;
}
i++;
}
}
catch
{
}
}
if (sensorIx >= 0 && sensorIx < sensorCB.Items.Count)
{
sensorCB.SelectedIndex = sensorIx;
}
else
{
if (sensorCB.Items.Count > 0)
{
sensorCB.SelectedIndex = 0;
}
}
return pidName;
}
///
/// OK button clicked.
///
/// Sending object.
/// Event data.
private void okButton_Click(object sender, EventArgs e)
{
if (this.primaryColorBox.BackColor != Color.Transparent
&& this.secondaryColorBox.BackColor != Color.Transparent
&& this.flashColorBox.BackColor != Color.Transparent)
{
this.telltaleitem.pidgroupid = this.pidgroup.id;
this.telltaleitem.pid_int = this.pid.pid_int;
this.telltaleitem.sensor_unit = this.sensor.unit;
this.telltaleitem.sensor_offset = this.sensor.offset;
this.telltaleitem.sensor_bit = this.sensorBit;
this.telltaleitem.telltaletext = this.telltaleTextTB.Text;
this.telltaleitem.telltalePriority = this.priorityComboBox.SelectedIndex - 99;
this.telltaleitem.primaryColor = this.primaryColorBox.BackColor.Name;
this.telltaleitem.secondaryColor = this.secondaryColorBox.BackColor.Name;
this.telltaleitem.flashColor = this.flashColorBox.BackColor.Name;
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show("Colors must be assigned.", "Incomplete Configuration.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
///
/// Cancel button clicked.
///
/// Sending object.
/// Event data.
private void cancelButton_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
///
/// PID group changed.
///
/// Sending object.
/// Event data.
private void pidGroupsCB_SelectedIndexChanged(object sender, EventArgs e)
{
this.pidgroup = pidGroupChange(
this.pidgroup,
(ComboBox)sender,
this.pidgrouplist,
0);
this.itemCB.Items.Clear();
this.sensorLB.Items.Clear();
this.pidName = string.Empty;
this.pidgrouppids = new List();
if (this.pidgroup != null)
{
updateItemCB(this.pidgroup, this.itemCB, this.telltaleitem.pid_int, this.pidgrouppids);
}
this.setOkButtonEnable();
}
///
/// Check if conditions are right to enable the OK button and enable it if that's the case.
///
private void setOkButtonEnable()
{
this.okButton.Enabled =
(this.pidgroup != null)
&& (this.pid != null)
&& (this.sensor != null)
&& !string.IsNullOrEmpty(this.telltaleitem.telltaleicon);
}
///
/// Item combo box changed.
///
/// Sending object.
/// Event data.
private void itemCB_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cb = (ComboBox)sender;
if (this.pidgroup != null
&& cb.SelectedIndex >= 0
&& cb.SelectedIndex < cb.Items.Count
&& cb.SelectedIndex < this.pidgrouppids.Count)
{
this.pidsensors = new List();
this.pidName = itemCbChange(cb, this.sensorLB, this.pidgrouppids, this.telltaleitem, ref this.pid, this.pidsensors);
}
this.setOkButtonEnable();
}
///
/// Sensor list box changed.
///
/// Sending object.
/// Event data.
private void sensorLB_SelectedIndexChanged(object sender, EventArgs e)
{
ListBox cb = (ListBox)sender;
if (cb.SelectedIndex >= 0 && cb.SelectedIndex < this.sensorLB.Items.Count)
{
this.sensor = this.pidsensors[cb.SelectedIndex];
this.sensorName = cb.Text;
this.sensorBit = -1;
try
{
this.sensorBit = Convert.ToInt32(this.sensor.startbit);
}
catch
{
}
}
this.setOkButtonEnable();
}
///
/// Sensor combo box changed.
///
/// Sending object.
/// Event data.
private void sensorCB_SelectedIndexChanged(object sender, EventArgs e)
{
ComboBox cb = (ComboBox)sender;
if (cb.SelectedIndex >= 0 && cb.SelectedIndex < this.itemCB.Items.Count)
{
this.sensor = this.pid.sensors[cb.SelectedIndex];
this.sensorName = cb.Text;
this.sensorBit = -1;
try
{
this.sensorBit = Convert.ToInt32(this.sensor.startbit);
}
catch
{
}
this.telltaleitem.sensor_bit = this.sensorBit;
}
this.setOkButtonEnable();
}
///
/// Select telltale.
///
/// Sending object.
/// Event data.
private void button1_Click(object sender, EventArgs e)
{
TelltaleAreaSelector gs = new TelltaleAreaSelector(this.telltaleitem.telltaleGroupNumber, this.usedItems);
try
{
if (gs.ShowDialog() == System.Windows.Forms.DialogResult.OK && gs.selectedItem != null)
{
this.telltaleitem.telltaleGroupNumber = (uint)gs.selectedItem;
this.telltaleGroupNumTB.Text = this.telltaleitem.telltaleGroupNumber.ToString();
}
}
finally
{
gs.Dispose();
}
}
///
/// Update the icon.
///
/// Sending object.
/// Event data.
private void selectIconButton_Click(object sender, EventArgs e)
{
TelltaleIconSelector telltaleIconSelector = new TelltaleIconSelector(this.dataFileDir, this.iDataSource, this.telltaleitem.telltaleicon);
try
{
if (telltaleIconSelector.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string newFile = telltaleIconSelector.selectedIcon;
try
{
this.setIconImage(newFile);
this.telltaleitem.telltaleicon = newFile;
}
finally
{
this.setOkButtonEnable();
}
}
}
finally
{
telltaleIconSelector.Dispose();
}
}
///
/// Set the image.
///
/// Icon image file name.
private void setIconImage(string newFile)
{
if (newFile != null)
{
try
{
Image img = Image.FromFile(this.dataFileDir + "Icons\\" + newFile);
float scale = 0.9F;
int height = this.iconPictureBox.Height;
int width = this.iconPictureBox.Width;
Bitmap bmp = Utils.getScaledImage(img, height, width, scale);
this.iconPictureBox.Image = bmp;
}
catch
{
MessageBox.Show(
"Unable to open icon file '" + this.dataFileDir + "Icons\\" + newFile + "'",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Hand);
}
}
}
///
/// Color button clicked.
///
/// Sending object.
/// Event data.
private void primaryColorButton_Click(object sender, EventArgs e)
{
using (ColorSelector colorSelector = new ColorSelector(this.primaryColorBox.BackColor, this.palette))
{
if (colorSelector.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.primaryColorBox.BackColor = colorSelector.Color;
}
}
}
///
/// Color button clicked.
///
/// Sending object.
/// Event data.
private void secondaryColorButton_Click(object sender, EventArgs e)
{
using (ColorSelector colorSelector = new ColorSelector(this.secondaryColorBox.BackColor, this.palette))
{
if (colorSelector.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.secondaryColorBox.BackColor = colorSelector.Color;
}
}
}
///
/// Color button clicked.
///
/// Sending object.
/// Event data.
private void flashColorButton_Click(object sender, EventArgs e)
{
using (ColorSelector colorSelector = new ColorSelector(this.flashColorBox.BackColor, this.palette))
{
if (colorSelector.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.flashColorBox.BackColor = colorSelector.Color;
}
}
}
}
}