//----------------------------------------------------------------------- // // 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; } } } } }