//----------------------------------------------------------------------- // // 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 UserInterface.GUI.OBD { using System; using System.Collections.Generic; using System.Threading; using System.Windows.Forms; using global::SharedObjects; using global::SharedObjects.GUI; using global::SharedObjects.Misc; using global::UserInterface.GUI.Objects; /// /// Common class for some controls, should have been abstract /// but can't be due to shortcomings in Visual Studio Designer. /// public class AbstractUserControl : UserControl, IDataEventCallback { /// /// Gets application Tree instance. /// protected IApplicationTree applicationTree { get; private set; } /// /// Gets node in tree that "owns" this control. /// protected PanelTreeNode owningNode { get; private set; } /// /// Gets or sets logging instance. /// protected ILogging iLogging { get; set; } /// /// Gets current vehicle instance. /// protected XmlClass.vehicle vehicle { get; private set; } /// /// Gets dictionary of ECU:s. /// protected SortedDictionary ecuData { get; private set; } /// /// Initializes a new instance of the class. /// protected AbstractUserControl() { this.ecuData = new SortedDictionary(); this.iLogging = null; this.vehicle = null; this.applicationTree = null; } /// /// Initializes a new instance of the class. /// /// Event logging instance. /// Vehicle instance. /// Application Tree instance. protected AbstractUserControl(ILogging iLogging, XmlClass.vehicle vehicle, IApplicationTree applicationTree) { this.ecuData = new SortedDictionary(); this.iLogging = iLogging; this.vehicle = vehicle; this.applicationTree = applicationTree; } /// /// Set the owning node for this panel. /// /// Node in tree that "owns" this panel. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "owningNode", Justification = "Reviewed, intentional.")] public void setOwningNode(PanelTreeNode owningNode) { this.owningNode = owningNode; } /// /// Trig a get data event. /// public virtual void getDataEvent() { throw new NotImplementedException("Override this function!"); } /// /// Set the Application Tree instance. /// /// Application tree instance. protected void setApplicationTree(IApplicationTree applicationTree) { this.applicationTree = applicationTree; } /// /// Get data display panel instance by ECU source address. /// /// ECU source address. /// Freeze frame number. /// ECU data panel instance. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")] protected EcuDataPanel getDataPanelByAddress(uint sourceAddress, int frameNumber) { EcuDataPanel ecuDataPanel = null; if (this.applicationTree.InvokeRequired) { try { ecuDataPanel = (EcuDataPanel)this.applicationTree.Invoke(new getDataPanelByAddressFunc(this.getDataPanelByAddress), new object[] { sourceAddress, frameNumber }); } catch (ThreadAbortException) { throw; } catch (System.Reflection.TargetParameterCountException ex) { MessageBox.Show( "Exception: " + ex.Message + "\r\n", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } catch (System.ObjectDisposedException) { // Ignore. } } else { if (!this.ecuData.ContainsKey(sourceAddress)) { string ecuName = this.getEcuName(sourceAddress); ecuDataPanel = new EcuDataPanel(this.iLogging, this.applicationTree, ecuName, this); ecuDataPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); PanelTreeNode dataNode; if (frameNumber == -1) { dataNode = new PanelTreeNode(ecuName, "application_form_magnify.png", "application_form_magnify.png", ecuDataPanel); } else { EmptyControl emptyControl = new EmptyControl(); dataNode = new PanelTreeNode(ecuName, "application_cascade.png", "application_cascade.png", emptyControl); PanelTreeNode dataNode1 = new PanelTreeNode("Frame #" + frameNumber, "application_form_magnify.png", "application_form_magnify.png", ecuDataPanel, frameNumber); dataNode.Nodes.Add(dataNode1); dataNode.Expand(); } this.owningNode.Nodes.Add(dataNode); this.owningNode.Expand(); this.ecuData.Add(sourceAddress, dataNode); } else { if (frameNumber == -1) { ecuDataPanel = (EcuDataPanel)(this.ecuData[sourceAddress].userControl); } else { ecuDataPanel = null; foreach (PanelTreeNode panel in this.ecuData[sourceAddress].Nodes) { if (panel.frameNumber == frameNumber) { ecuDataPanel = (EcuDataPanel)panel.userControl; } } if (ecuDataPanel == null) { string ecuName = this.getEcuName(sourceAddress); ecuDataPanel = new EcuDataPanel(this.iLogging, this.applicationTree, ecuName, this); ecuDataPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); PanelTreeNode dataNode1 = new PanelTreeNode("Frame #" + frameNumber, "application_form_magnify.png", "application_form_magnify.png", ecuDataPanel, frameNumber); this.ecuData[sourceAddress].Nodes.Add(dataNode1); this.ecuData[sourceAddress].Expand(); } } } } return ecuDataPanel; } /// /// Get the name of the ECU for the given address. /// /// ECU address. /// ECU name. private string getEcuName(uint sourceAddress) { string ecuName = null; uint mask; if (sourceAddress < 0x800 && sourceAddress > 0xff) { mask = 0x07; } else { mask = 0xff; } foreach (XmlClass.vehicle.ecuData ecu in this.vehicle.ecus) { uint id = Utils.hexParse(ecu.id); if ((id & mask) == (sourceAddress & mask)) { ecuName = ecu.name; break; } } if (ecuName == null) { ecuName = "ECU 0x" + sourceAddress.ToString("x2"); } return ecuName; } /// /// Get panel instance by ECU source address. /// /// ECU source address. /// Freeze frame number. /// EcuDataPanel instance. private delegate EcuDataPanel getDataPanelByAddressFunc(uint sourceAddress, int frameNumber); } }