/// /// Copyright (c) 2013-2017 Sensus Metering Systems /// Author: Milan Hanajík /// using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using log4net; using NHibernate; using Config.Entities; using Results.Forms; using TBF.BenchControl; using TBF.BenchControl.Generic; using TBF.Resources; using TBF.UiControls; namespace TBF { public partial class ComponentsManagerDlg : Form, IParentOfListViewEx { static readonly ILog log = LogManager.GetLogger(typeof(ComponentsManagerDlg)); /// /// List of components (=component configuration instances) /// IList cmpntEntities; IList toBeDeletedEntities; ISession session; SelectComponentClassDlg selectComponentTypeDlg; /// Constructed once, the selection is kept between dialog usages CfgUpdateFlags flags; /// Or-ed from particular Flags from ComponentParametersDlg /// /// ListViewEx columns /// enum Column { Number, Name, ClassName, ParentName, DebugMode, Logging, Parameters, ColumnsCount, } SortOrder sortOrder = SortOrder.Ascending; int sortColumn = -1; /// 0-based index of column to be used for sorting /// Editors used by listViewEx ComboBox debugCB; ComboBox logCB; bool unlocked; public ComponentsManagerDlg() { toBeDeletedEntities = new List(); InitializeComponent(); flags = CfgUpdateFlags.None; selectComponentTypeDlg = new SelectComponentClassDlg(); /// SharedDlgButtons configuration sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists }; sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down | SharedButtons.Buttons.Edit | SharedButtons.Buttons.Copy | SharedButtons.Buttons.Export | SharedButtons.Buttons.Import; sharedButtons.Unlocked += Unlocked; sharedButtons.OKClicked += okButton_Click; sharedButtons.CancelClicked += cancelButton_Click; sharedButtons.AddClicked += addButton_Click; sharedButtons.RemoveClicked += removeButton_Click; sharedButtons.UpClicked += upButton_Click; sharedButtons.DownClicked += downButton_Click; sharedButtons.EditClicked += editButton_Click; sharedButtons.CopyClicked += copyButton_Click; sharedButtons.ExportClicked += exportButton_Click; sharedButtons.ImportClicked += importButton_Click; } private void ComponentsManagerDlg_Load(object sender, EventArgs e) { TBF.LocalSettings ls = Program.LocalSettings; Width = (ls.ComponentsDlgWidth > 0) ? ls.ComponentsDlgWidth : 850; Height = (ls.ComponentsDlgHeight > 0) ? ls.ComponentsDlgHeight : 500; Left = (ls.ComponentsDlgLeft != 0) ? ls.ComponentsDlgLeft : 200; Top = (ls.ComponentsDlgTop != 0) ? ls.ComponentsDlgTop : 100; Text = Strings.Test_Bench_Components_Configuration; listViewEx.Columns.Add(Strings.Nr, (ls.ComponentsColumnCount > 0) ? ls.ComponentsColumnWidths[0] : 40); listViewEx.Columns.Add(Strings.Name, (ls.ComponentsColumnCount > 1) ? ls.ComponentsColumnWidths[1] : 80); listViewEx.Columns.Add(Strings.Type, (ls.ComponentsColumnCount > 2) ? ls.ComponentsColumnWidths[2] : 120); listViewEx.Columns.Add(Strings.Parent, (ls.ComponentsColumnCount > 3) ? ls.ComponentsColumnWidths[3] : 55); listViewEx.Columns.Add(Strings.Mode, (ls.ComponentsColumnCount > 4) ? ls.ComponentsColumnWidths[4] : 55); listViewEx.Columns.Add(Strings.Logging, (ls.ComponentsColumnCount > 5) ? ls.ComponentsColumnWidths[5] : 55); listViewEx.Columns.Add(Strings.Parameters, (ls.ComponentsColumnCount > 6) ? ls.ComponentsColumnWidths[6] : 600); listViewEx.HeaderStyle = ColumnHeaderStyle.Clickable; debugCB = new ComboBox(); for (DebugMode level = 0; level < DebugMode.Count; level++) debugCB.Items.Add(level.ToDescription()); splitContainer.Panel1.Controls.Add(debugCB); logCB = new ComboBox(); for (LogLevel level = 0; level < LogLevel.Count; level++) logCB.Items.Add(level.ToDescription()); splitContainer.Panel1.Controls.Add(logCB); listViewEx.SubItemClicked += new Results.Forms.SubItemEventHandler(listViewEx_SubItemClicked); listViewEx.SubItemEndEditing += new Results.Forms.SubItemEndEditingEventHandler(listViewEx_SubItemEndEditing); sharedButtons.DisableButtons(UiControls.SharedButtons.Buttons.Remove | UiControls.SharedButtons.Buttons.Edit); session = Config.FluentCommon.CreateSession(Users.Entities.DBKind.Config); cmpntEntities = session.QueryOver() .OrderBy(x => x.ItemNr).Asc .List(); RedrawAll(); } void listViewEx_SubItemClicked(object sender, Results.Forms.SubItemEventArgs e) { if (unlocked && e.SubItem == (int)Column.DebugMode) { listViewEx.StartEditing(debugCB, e.Item, e.SubItem); } else if (unlocked && e.SubItem == (int)Column.Logging) { listViewEx.StartEditing(logCB, e.Item, e.SubItem); } } void listViewEx_SubItemEndEditing(object sender, Results.Forms.SubItemEndEditingEventArgs e) { Component cmpnt = (Component)e.Item.Tag; if (e.SubItem == (int)Column.DebugMode) { for (DebugMode level = 0; level < DebugMode.Count; level++) { if (debugCB.Text.Equals(level.ToDescription())) { cmpnt.Mode = level; flags |= CfgUpdateFlags.RestartRqrd; return; } } e.DisplayText = cmpnt.Mode.ToString(); } else if (e.SubItem == (int)Column.Logging) { for (LogLevel level = 0; level < LogLevel.Count; level++) { if (logCB.Text.Equals(level.ToDescription())) { cmpnt.Logging = level; flags |= CfgUpdateFlags.RestartRqrd; return; } } e.DisplayText = cmpnt.Logging.ToString(); } } private void Unlocked(object sender, EventArgs e) { unlocked = true; if (listViewEx.SelectedItems.Count == 1) { int ix = listViewEx.SelectedIndices[0]; Focus(); listViewEx.Items[ix].Selected = true; listViewEx.Items[ix].EnsureVisible(); } } void RedrawAll() { listViewEx.Items.Clear(); foreach (var cmpnt in cmpntEntities) DrawOne(cmpnt); } void DrawOne(Component cmpnt) { ListViewItem lvi = new ListViewItem(cmpnt.ItemNr.ToString()); lvi.Tag = cmpnt; lvi.SubItems.Add(cmpnt.Name); lvi.SubItems.Add(string.IsNullOrEmpty(cmpnt.ClassName) ? string.Empty : cmpnt.ClassName); lvi.SubItems.Add(string.IsNullOrEmpty(cmpnt.ParentName) ? string.Empty : cmpnt.ParentName); IComponentCfg cmpCfg = TbfComponents.CmpntCfgFromCmpntEntity(cmpnt); if (cmpCfg != null) { lvi.SubItems.Add(cmpCfg.DebugLevel.ToDescription()); lvi.SubItems.Add(cmpCfg.LogLevel.ToDescription()); lvi.SubItems.Add(cmpCfg.ToString(-1)); } else { lvi.SubItems.Add("---"); lvi.SubItems.Add("---"); lvi.SubItems.Add("Not a component"); } listViewEx.Items.Add(lvi); } /// /// Save DB changes, return true when DB changes saved OK /// bool SaveDBChanges(ISession session) { using (ITransaction transaction = session.BeginTransaction()) { try { foreach (var cmpnt in toBeDeletedEntities) session.Delete(cmpnt); int itemNr = 1; foreach (var cmpnt in cmpntEntities) { cmpnt.ItemNr = itemNr++; session.SaveOrUpdate(cmpnt); } transaction.Commit(); session.Flush(); return true; } catch (Exception exc) { transaction.Rollback(); log.ErrorFormat("Exception when saving components : {1}", exc.Message); return false; } } } /// /// Save the dialog position and ListViewEx column widths /// void SaveUISettings() { Program.LocalSettings.ComponentsDlgLeft = Location.X; Program.LocalSettings.ComponentsDlgTop = Location.Y; Program.LocalSettings.ComponentsDlgWidth = Size.Width; Program.LocalSettings.ComponentsDlgHeight = Size.Height; Program.LocalSettings.Save(); /// Update the column widths Program.LocalSettings.ComponentsColumnWidths = new int[(int)Column.ColumnsCount]; for (int i = 0; i < (int)Column.ColumnsCount; i++) { Program.LocalSettings.ComponentsColumnWidths[i] = listViewEx.Columns[i].Width; } Program.LocalSettings.Save(); } /// /// OK /// private void okButton_Click(object sender, EventArgs e) { if ((flags & CfgUpdateFlags.AnyChange) != 0 || (flags & CfgUpdateFlags.RestartRqrd) != 0) { SaveDBChanges(session); flags = CfgUpdateFlags.None; /// Changes saved } SaveUISettings(); DialogResult = DialogResult.OK; Close(); return; } /// Cancel private void cancelButton_Click(object sender, EventArgs e) { SaveUISettings(); if ((flags & CfgUpdateFlags.AnyChange) != 0 || (flags & CfgUpdateFlags.RestartRqrd) != 0) { DialogResult dr = MessageBox.Show(Strings.Changes_will_be_lost_Do_you_want_to_proceed, Strings.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dr != DialogResult.Yes) return; } flags = CfgUpdateFlags.None; /// Abandoning changes confirmed DialogResult = DialogResult.Cancel; Close(); return; } /// Add a new component private void addButton_Click(object sender, EventArgs e) { selectComponentTypeDlg.SelectedScriptName = null; DialogResult dialogRslt = selectComponentTypeDlg.ShowDialog(); if (dialogRslt != DialogResult.OK) return; IComponentFactory factory = selectComponentTypeDlg.SlctdCmpntFactory; IComponentCfg cfg = factory.DefaultConfig(); if (selectComponentTypeDlg.SelectedScriptName == null) { IComponentCfgCtrl cfgControl = cfg.GetControl(); cfgControl.Config = cfg; cfgControl.Config.ItemNr = (cmpntEntities.Count > 0) ? (cmpntEntities[cmpntEntities.Count - 1].ItemNr + 1) : 1; ComponentParametersDlg cfgForm = new ComponentParametersDlg(); cfgForm.TbfComponents = cmpntEntities; cfgForm.ComponentCfgCtrl = cfgControl; cfgForm.UnlockAfterStart = true; dialogRslt = cfgForm.ShowDialog(); if (dialogRslt != DialogResult.OK) return; flags |= CfgUpdateFlags.RestartRqrd; AddOne(cfgForm.Config.CreateDbEntity()); } else { using (TextReader reader = new StreamReader(selectComponentTypeDlg.SelectedScriptName)) { int zeroBasedIdx = 0; string line = reader.ReadLine(); while (line != null) { line.Trim(); if (line.Length > 0) { string[] words = line.Split(new char[] { ' ', '\t' }); if (UpdateCfg(ref cfg, words, ref zeroBasedIdx)) { flags |= CfgUpdateFlags.RestartRqrd; cfg.ItemNr = (cmpntEntities.Count > 0) ? (cmpntEntities[cmpntEntities.Count - 1].ItemNr + 1) : 1; AddOne(cfg.CreateDbEntity()); } zeroBasedIdx++; } line = reader.ReadLine(); } } } } void AddOne(Component cmpnt) { cmpntEntities.Add(cmpnt); DrawOne(cmpnt); } /// Delete the component private void removeButton_Click(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count != 1) return; int ix = listViewEx.SelectedIndices[0]; if (ix < 0) return; Component selectedCmpnt = (Component)listViewEx.Items[ix].Tag; if (selectedCmpnt.Id != 0) toBeDeletedEntities.Add(selectedCmpnt); cmpntEntities.Remove(selectedCmpnt); flags |= CfgUpdateFlags.AnyChange; RedrawAll(); } /// DoubleClick -> Edit the component private void listViewEx_MouseDoubleClick(object sender, MouseEventArgs e) { editButton_Click(sender, e); } /// Edit a component private void editButton_Click(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count != 1) return; ListViewItem lvi = listViewEx.SelectedItems[0]; IComponentCfg cfg = TbfComponents.CmpntCfgFromCmpntEntity((Component)lvi.Tag); if (cfg != null) { ComponentParametersDlg cfgForm = new ComponentParametersDlg(); cfgForm.TbfComponents = cmpntEntities; cfgForm.ComponentCfgCtrl = cfg.GetControl(); cfgForm.ComponentCfgCtrl.Config = cfg; DialogResult dr = cfgForm.ShowDialog(); if (dr != DialogResult.OK) return; flags |= cfgForm.Flags; sharedButtons.UnlockButtons(); /// Unlock this dialog buttons as changes were enabled unlocked = true; /// in the ComponentParametersDlg. Component modified = cfgForm.Config.CreateDbEntity(); Component original = (Component)lvi.Tag; original.Name = modified.Name; original.ClassName = modified.ClassName; original.ParentName = modified.ParentName; original.Mode = modified.Mode; original.Logging = modified.Logging; original.Parameters = modified.Parameters; RedrawAll(); } } /// Copy a component private void copyButton_Click(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count != 1) return; ListViewItem lvi = listViewEx.SelectedItems[0]; IComponentCfg cfg = TbfComponents.CmpntCfgFromCmpntEntity((Component)lvi.Tag); if (cfg != null) { cfg.Name += Strings.New_name_copy; if (selectComponentTypeDlg.SelectedScriptName == null) { IComponentCfgCtrl cfgControl = cfg.GetControl(); cfgControl.Config = cfg; cfgControl.Config.ItemNr = (cmpntEntities.Count > 0) ? (cmpntEntities[cmpntEntities.Count - 1].ItemNr + 1) : 1; ComponentParametersDlg cfgForm = new ComponentParametersDlg(); cfgForm.TbfComponents = cmpntEntities; cfgForm.ComponentCfgCtrl = cfgControl; cfgForm.UnlockAfterStart = true; if (cfgForm.ShowDialog() != DialogResult.OK) return; flags |= CfgUpdateFlags.RestartRqrd; AddOne(cfgForm.Config.CreateDbEntity()); } } } /// Export a component to a file private void exportButton_Click(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count != 1) return; Component component = listViewEx.SelectedItems[0].Tag as Component; if (component == null) return; SaveFileDialog dlg = new SaveFileDialog(); if (dlg.ShowDialog() == DialogResult.OK) { component.Export(new StreamWriter(dlg.FileName, false, System.Text.Encoding.UTF8)); } } /// Import a component form a file private void importButton_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); if (dlg.ShowDialog() != DialogResult.OK) return; /// Import a procedure from a file Component newComponent = Component.Import(new StreamReader(dlg.FileName, System.Text.Encoding.UTF8)); IComponentCfg cfg = TbfComponents.CmpntCfgFromCmpntEntity(newComponent); if (cfg != null) { IComponentCfgCtrl cfgControl = cfg.GetControl(); cfgControl.Config = cfg; cfgControl.Config.Name = cfgControl.Config.Name + " imported"; cfgControl.Config.ItemNr = (cmpntEntities.Count > 0) ? (cmpntEntities[cmpntEntities.Count - 1].ItemNr + 1) : 1; ComponentParametersDlg cfgForm = new ComponentParametersDlg(); cfgForm.TbfComponents = cmpntEntities; cfgForm.ComponentCfgCtrl = cfgControl; cfgForm.UnlockAfterStart = true; if (cfgForm.ShowDialog() != DialogResult.OK) return; flags |= CfgUpdateFlags.RestartRqrd; AddOne(cfgForm.Config.CreateDbEntity()); } } private void upButton_Click(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count != 1) return; int ix = listViewEx.SelectedIndices[0]; if (ix < 1) return; Component item1 = (Component)(listViewEx.Items[ix - 1].Tag); Component item2 = (Component)(listViewEx.Items[ix].Tag); (item1 as IHasItemNr).ItemNr++; (item2 as IHasItemNr).ItemNr--; cmpntEntities.RemoveAt(ix); cmpntEntities.Insert(ix - 1, item2); flags |= CfgUpdateFlags.AnyChange; RedrawAll(); Focus(); listViewEx.Items[ix - 1].Selected = true; listViewEx.Items[ix - 1].EnsureVisible(); } private void downButton_Click(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count != 1) return; int ix = listViewEx.SelectedIndices[0]; if (ix >= listViewEx.Items.Count - 1) return; Component item1 = (Component)(listViewEx.Items[ix].Tag); Component item2 = (Component)(listViewEx.Items[ix + 1].Tag); (item1 as IHasItemNr).ItemNr++; (item2 as IHasItemNr).ItemNr--; cmpntEntities.RemoveAt(ix + 1); cmpntEntities.Insert(ix, item2); flags |= CfgUpdateFlags.AnyChange; RedrawAll(); Focus(); listViewEx.Items[ix + 1].Selected = true; listViewEx.Items[ix + 1].EnsureVisible(); } private void componentsListView_SelectedIndexChanged(object sender, EventArgs e) { if (listViewEx.SelectedIndices.Count == 1) { sharedButtons.EnableButtons(UiControls.SharedButtons.Buttons.Remove | UiControls.SharedButtons.Buttons.Edit); } else { sharedButtons.DisableButtons(UiControls.SharedButtons.Buttons.Remove | UiControls.SharedButtons.Buttons.Edit); } } public void UpdateButtonStates(SharedButtons.SelectedItemPos selectedItemPos) { if (selectedItemPos == SharedButtons.SelectedItemPos.None) { sharedButtons.DisableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); } else if (selectedItemPos == SharedButtons.SelectedItemPos.First) { sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Down); sharedButtons.DisableButtons(SharedButtons.Buttons.Up); } else if (selectedItemPos == SharedButtons.SelectedItemPos.Last) { sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up); sharedButtons.DisableButtons(SharedButtons.Buttons.Down); } else if (selectedItemPos == SharedButtons.SelectedItemPos.FirstAndLast) { sharedButtons.EnableButtons(SharedButtons.Buttons.Remove); sharedButtons.DisableButtons(SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); } else { sharedButtons.EnableButtons(SharedButtons.Buttons.Remove | SharedButtons.Buttons.Up | SharedButtons.Buttons.Down); } } private void ComponentsManagerDlg_FormClosing(object sender, FormClosingEventArgs e) { SaveUISettings(); if ((flags & CfgUpdateFlags.AnyChange) != 0 || (flags & CfgUpdateFlags.RestartRqrd) != 0) { DialogResult dr = MessageBox.Show(Strings.Do_you_want_to_save_changes, Strings.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dr == DialogResult.Yes) { SaveDBChanges(session); } } } /// /// Updates component configuration from a script file /// /// /// /// /// true = udated component configuration should be saved, new component should be created bool UpdateCfg(ref IComponentCfg cfg, string[] words, ref int zeroBasedIdx) { string name = words[words.Length - 1]; /// The last word is the component name cfg.Name = name.Replace("#", (zeroBasedIdx + 1).ToString()); if (cfg is BenchControl.Elde.Valve.ValveCfg) { int bitNr = zeroBasedIdx; if (words.Length >= 2 && words[0].StartsWith("D") && int.TryParse(words[0].Substring(1), out bitNr)) { zeroBasedIdx = bitNr; } if (name != "-") { (cfg as BenchControl.Elde.Valve.ValveCfg).BitPosition = bitNr; (cfg as BenchControl.Elde.Valve.ValveCfg).Category = name.Contains("L") ? ValveCategory.Bench : name.Contains("I") ? ValveCategory.Output : name.Contains("Z") ? ValveCategory.Feeding : ValveCategory.None; return true; } } else if (cfg is BenchControl.Elde.FlowMeter.FlowMeterCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; (cfg as BenchControl.Elde.FlowMeter.FlowMeterCfg).Idx1 = zeroBasedIdx + 1; return true; } else if (cfg is BenchControl.Elde.TempMeter.TempMeterCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; (cfg as BenchControl.Elde.TempMeter.TempMeterCfg).Idx0 = zeroBasedIdx; return true; } else if (cfg is BenchControl.Elde.PressureMeter.PressureMeterCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; (cfg as BenchControl.Elde.PressureMeter.PressureMeterCfg).Idx0 = zeroBasedIdx; return true; } else if (cfg is BenchControl.Elde.RegulValve.RegulValveCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; (cfg as BenchControl.Elde.RegulValve.RegulValveCfg).Idx1 = zeroBasedIdx + 1; return true; } else if (cfg is BenchControl.Elde.RegisterReader.RegisterReaderCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; (cfg as BenchControl.Elde.RegisterReader.RegisterReaderCfg).Position = zeroBasedIdx + 1; return true; } else if (cfg is BenchControl.Elde.FixedStartRegisterReader.RegisterReaderCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; return true; } else if (cfg is BenchControl.TestMethods.iPerlCommunication.iPerlHead.IperlHeadCfg) { return true; } else if (cfg is BenchControl.WaterMeters.WaterMeter.WaterMeterCfg) { return true; } return false; } private void listViewEx_ColumnClick(object sender, ColumnClickEventArgs e) { if (e.Column == sortColumn) { sortOrder = (sortOrder == SortOrder.Ascending) ? SortOrder.Descending : SortOrder.Ascending; } else { /// Clicked on another column header => set sortOrder to SortOrder.Ascending sortColumn = e.Column; sortOrder = SortOrder.Ascending; } if (sortColumn == (int)Column.Number) { listViewEx.ListViewItemSorter = new LviIntColumnComparer(sortColumn, sortOrder); } else { listViewEx.ListViewItemSorter = new LviTextColumnComparer(sortColumn, sortOrder); } listViewEx.SetSortIcon(sortColumn, sortOrder); listViewEx.Sort(); } } }