using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using Common; using Common.Forms; using SharedDatabase; using SharedDatabase.Entities; using WorkflowConfigurator.Resources; namespace WorkflowConfigurator.UserControls { public partial class PartsCtrl : UserControl, IMyUI { bool unsavedChanges; bool suppressNotifications; bool limitedUnlock; bool completeUnlock; public EditProcessCtrl EditProcessCtrl; /// Parent control reference /// Process currentProcess; public IEnumerable SelectedParts { get { return null; /* TODO */ } } // TODO: replace ListView.SelectedListViewItemCollection partsListView.SelectedItems; public PartsCtrl() { InitializeComponent(); InitPartsListViewColumns(); unsavedChanges = false; suppressNotifications = false; Localize(); } void Localize() { addPartButton.Text = Strings.Add; removePartButton.Text = Strings.Remove; } public void UpdateProcess(Process process, Reason reason, IList allProcesses) { this.currentProcess = process; } /// /// Enable/disable/hide UI elements based on lock/unlock/complete unlock state /// /// true = unlock for released processes /// true = unlock for processes in preparation (complete unlock) public void UpdateLockState(bool unlock, bool completely) { limitedUnlock = unlock; completeUnlock = completely; addPartButton.Enabled = completely; removePartButton.Enabled = completely; partUpButton.Enabled = unlock; partDownButton.Enabled = unlock; addPartToWorkstepButton.Enabled = completely; removePartFromWorkstepButton.Enabled = completely; } public void Data2UI() { suppressNotifications = true; partsListView.Items.Clear(); int partsCount = 0; if ((this.currentProcess != null) && (this.currentProcess.Parts != null)) { /// Sort parts before displaying in a list view Part[] sortedParts = new Part[currentProcess.Parts.Count]; int i = 0; foreach (var part in this.currentProcess.Parts) sortedParts[i++] = part; Array.Sort(sortedParts, (Part part1, Part part2) => part1.StepNumber.CompareTo(part2.StepNumber)); /// Display parts in the list view, rectify StepNumber-s foreach (var part in sortedParts) { part.StepNumber = ++partsCount; /// Rectify Part.StepNumber partsListView.Items.Add(Part2Lvi(part)); } } partsLabel.Text = string.Format("{0} ({1})", Strings.Parts, partsCount); suppressNotifications = false; } /// /// Returns true when (modified) UI data are OK /// /// true when UI data are valid public bool VerifyUIData(out string message) { bool uiDataValid = true; message = string.Empty; /// TODO return uiDataValid; } public void UI2Data() { for (int i = 0; i < partsListView.Items.Count; i++) { ListViewItem lvi = partsListView.Items[i]; Part part = lvi.Tag as Part; if (part != null) { UpdatePartFromLvi(lvi, part); part.StepNumber = i + 1; } } } public void Settings2UI() { LocalSettings ls = Program.LocalSettings; if ((ls != null) && (partsListView.Columns.Count >= 6)) { partsListView.Columns[0].Width = (ls.ColWid1 > 0) ? ls.ColWid1 : 28; partsListView.Columns[1].Width = (ls.ColWid2 > 0) ? ls.ColWid2 : 28; partsListView.Columns[2].Width = (ls.ColWid3 > 0) ? ls.ColWid3 : 73; partsListView.Columns[3].Width = (ls.ColWid4 > 0) ? ls.ColWid4 : 111; partsListView.Columns[4].Width = (ls.ColWid5 > 0) ? ls.ColWid5 : 100; partsListView.Columns[5].Width = (ls.ColWid6 > 0) ? ls.ColWid6 : 50; partsListView.Columns[6].Width = (ls.ColWid7 > 0) ? ls.ColWid7 : 200; } } public void UI2Settings() { LocalSettings ls = Program.LocalSettings; if ((ls != null) && (partsListView.Columns.Count >= 6)) { ls.ColWid1 = partsListView.Columns[0].Width; ls.ColWid2 = partsListView.Columns[1].Width; ls.ColWid3 = partsListView.Columns[2].Width; ls.ColWid4 = partsListView.Columns[3].Width; ls.ColWid5 = partsListView.Columns[4].Width; ls.ColWid6 = partsListView.Columns[5].Width; ls.ColWid7 = partsListView.Columns[6].Width; } } public void ResetUnsavedFlag() { unsavedChanges = false; } public void SetUnsavedFlag() { if (suppressNotifications) return; unsavedChanges = true; EditProcessCtrl.SetUnsavedFlag(); } Control[] partsEditors; ComboBox howToObtainComboBox; ComboBox checkComboBox; /// public enum PartsColumn { HasSN, Nr, Name, HowToObtain, Check, DefaultCode, Description, CoulumnsCount } /// void InitPartsListViewColumns() { LocalSettings ls = Program.LocalSettings; partsListView.Columns.Add(Strings.Chdr_HasSN, ((ls != null) && (ls.ColWid1 > 0)) ? ls.ColWid1 : 28); partsListView.Columns.Add(Strings.Chdr_Nr, ((ls != null) && (ls.ColWid2 > 0)) ? ls.ColWid2 : 28); partsListView.Columns.Add(Strings.Chdr_Name, ((ls != null) && (ls.ColWid3 > 0)) ? ls.ColWid3 : 73); partsListView.Columns.Add(Strings.Chdr_HowToObtain, ((ls != null) && (ls.ColWid4 > 0)) ? ls.ColWid4 : 111); partsListView.Columns.Add(Strings.Chdr_Check, ((ls != null) && (ls.ColWid5 > 0)) ? ls.ColWid5 : 100); partsListView.Columns.Add("Dflt. code", ((ls != null) && (ls.ColWid6 > 0)) ? ls.ColWid6 : 50); partsListView.Columns.Add(Strings.Description, ((ls != null) && (ls.ColWid7 > 0)) ? ls.ColWid7 : 200); howToObtainComboBox = new ComboBox(); for (CodeForm cf = 0; cf < CodeForm.Count; cf++) howToObtainComboBox.Items.Add(cf.ToDescription()); checkComboBox = new ComboBox(); for (CodeType ct = 0; ct < CodeType.Count; ct++) checkComboBox.Items.Add(ct.ToDescription()); partsEditors = new Control[] { null, /// HasSN null, /// Nr. new TextBox(), /// Name howToObtainComboBox, /// How to obtain checkComboBox, /// Check new TextBox(), /// DefaultCode new TextBox(), /// Description }; foreach (var ctrl in partsEditors) { if (ctrl != null) Controls.Add(ctrl); } } /// ListViewItem Part2Lvi(Part part) { ListViewItem lvi = new ListViewItem(); lvi.Checked = (part.CodeLocation == CodeLocation.OnPart); lvi.SubItems.Add(part.StepNumber.ToString()); lvi.SubItems.Add(part.Name); lvi.SubItems.Add(((CodeForm)part.CodeForm).ToDescription()); lvi.SubItems.Add(((CodeType)part.CodeType).ToDescription()); lvi.SubItems.Add((part.DefaultCode != null) ? part.DefaultCode : string.Empty); lvi.SubItems.Add(part.Description); lvi.Tag = part; return lvi; } /// bool UpdatePartFromLvi(ListViewItem lvi, Part part) { part.CodeLocation = lvi.Checked ? CodeLocation.OnPart : CodeLocation.OnPallet; part.Name = lvi.SubItems[(int)PartsColumn.Name].Text; part.CodeForm = (sbyte)CodeForm.Barcode; for (CodeForm cf = 0; cf < CodeForm.Count; cf++) { if (lvi.SubItems[(int)PartsColumn.HowToObtain].Text == cf.ToDescription()) { part.CodeForm = (sbyte)cf; break; } } part.CodeType = (sbyte)CodeType.UniqueNr; for (CodeType ct = 0; ct < CodeType.Count; ct++) { if (lvi.SubItems[(int)PartsColumn.Check].Text == ct.ToDescription()) { part.CodeType = (sbyte)ct; break; } } part.DefaultCode = lvi.SubItems[(int)PartsColumn.DefaultCode].Text; part.Description = lvi.SubItems[(int)PartsColumn.Description].Text; return true; } /// private void partsListView_SubItemClicked(object sender, SubItemEventArgs e) { if (e.SubItem == (int)PartsColumn.HasSN) return; /// HasSN cannot be changed this way if (e.SubItem == (int)PartsColumn.Nr) return; /// Part nr. cannot be changed this way if (!completeUnlock && e.SubItem == (int)PartsColumn.Name) return; /// Part name cannot be changed when released if (limitedUnlock && (e.SubItem < (int)PartsColumn.CoulumnsCount)) { partsListView.StartEditing(partsEditors[e.SubItem], e.Item, e.SubItem); } } /// private void partsListView_SubItemEndEditing(object sender, SubItemEndEditingEventArgs e) { if (e.SubItem == (int)PartsColumn.HasSN) return; if (e.SubItem == (int)PartsColumn.Nr) return; if (e.SubItem == (int)PartsColumn.Name) { if (e.DisplayText.Length > Const.MaxPartNameLen) { MessageBox.Show(string.Format(Strings.Max_part_name_length_is_0_characters, Const.MaxPartNameLen)); e.DisplayText = e.Item.SubItems[e.SubItem].Text; e.Cancel = true; return; } (e.Item.Tag as Part).Name = e.DisplayText; EditProcessCtrl.Data2UI(); /// Redraw worksteps as well SetUnsavedFlag(); return; } else if (e.SubItem == (int)PartsColumn.Description) { (e.Item.Tag as Part).Description = e.DisplayText; EditProcessCtrl.Data2UI(); /// Redraw worksteps as well SetUnsavedFlag(); return; } else if ((e.SubItem == (int)PartsColumn.HowToObtain) && checkComboBox.Items.Contains(e.DisplayText)) { (e.Item.Tag as Part).CodeForm = (sbyte)CodeForm.Barcode; for (CodeForm cf = 0; cf < CodeForm.Count; cf++) { if (e.DisplayText == cf.ToDescription()) { (e.Item.Tag as Part).CodeForm = (sbyte)cf; SetUnsavedFlag(); return; } } } else if ((e.SubItem == (int)PartsColumn.Check) && checkComboBox.Items.Contains(e.DisplayText)) { (e.Item.Tag as Part).CodeType = (sbyte)CodeType.UniqueNr; for (CodeType ct = 0; ct < CodeType.Count; ct++) { if (e.DisplayText == ct.ToDescription()) { (e.Item.Tag as Part).CodeType = (sbyte)ct; SetUnsavedFlag(); return; } } } else if (e.SubItem == (int)PartsColumn.DefaultCode) { if (e.DisplayText != e.Item.SubItems[e.SubItem].Text) { SetUnsavedFlag(); return; } } /// Editted item is NOK - revert the change e.DisplayText = e.Item.SubItems[e.SubItem].Text; e.Cancel = true; return; } private void addPartButton_Click(object sender, EventArgs e) { Forms.PartDlg dlg = new Forms.PartDlg(Strings.New_part, currentProcess); if (dlg.ShowDialog() == DialogResult.OK) { dlg.Part.StepNumber = currentProcess.Parts.Count + 1; currentProcess.Parts.Add(dlg.Part); partsListView.Items.Add(Part2Lvi(dlg.Part)); SetUnsavedFlag(); } } private void removePartButton_Click(object sender, EventArgs e) { if (partsListView.SelectedItems.Count != 1) { MessageBox.Show(Strings.No_part_selected); return; } Part selectedPart = partsListView.SelectedItems[0].Tag as Part; foreach (var ws in currentProcess.Worksteps) { if (ws.ReferencePart == selectedPart || ws.Parts.Contains(selectedPart)) { MessageBox.Show(string.Format(Strings.Part_is_used_in_workstep_0, ws.Name)); return; } } int oriCount = currentProcess.Parts.Count; currentProcess.Parts.Remove(selectedPart); if (currentProcess.Parts.Count == oriCount) { MessageBox.Show("Part cannot be deleted", Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { EditProcessCtrl.PartsToBeDeleted.Add(selectedPart); Data2UI(); SetUnsavedFlag(); } } private void partUpButton_Click(object sender, EventArgs e) { if (partsListView.SelectedItems.Count != 1) return; if (!CheckAndRetrieveData()) return; /// Retrieve data from list view items foreach (var item in partsListView.Items) UpdatePartFromLvi(item as ListViewItem, (item as ListViewItem).Tag as Part); int ix = partsListView.SelectedIndices[0]; if (ix > 0) { int tmpStepNr = (partsListView.Items[ix].Tag as Part).StepNumber; (partsListView.Items[ix].Tag as Part).StepNumber = (partsListView.Items[ix - 1].Tag as Part).StepNumber; (partsListView.Items[ix - 1].Tag as Part).StepNumber = tmpStepNr; EditProcessCtrl.Data2UI(); /// Redraw all including worksteps partsListView.Focus(); partsListView.Items[ix - 1].Selected = true; partsListView.Items[ix - 1].EnsureVisible(); SetUnsavedFlag(); } } private void partDownButton_Click(object sender, EventArgs e) { if (partsListView.SelectedItems.Count != 1) return; if (!CheckAndRetrieveData()) return; int ix = partsListView.SelectedIndices[0]; if (ix < partsListView.Items.Count - 1) { int tmpStepNr = (partsListView.Items[ix].Tag as Part).StepNumber; (partsListView.Items[ix].Tag as Part).StepNumber = (partsListView.Items[ix + 1].Tag as Part).StepNumber; (partsListView.Items[ix + 1].Tag as Part).StepNumber = tmpStepNr; EditProcessCtrl.Data2UI(); /// Redraw all including worksteps partsListView.Focus(); partsListView.Items[ix + 1].Selected = true; partsListView.Items[ix + 1].EnsureVisible(); SetUnsavedFlag(); } } private void addPartToWorkstepButton_Click(object sender, EventArgs e) { if ((partsListView.SelectedItems.Count == 1) && EditProcessCtrl.AddPartsToCurrentWorkstep(partsListView.Items[partsListView.SelectedIndices[0]].Tag as Part)) { SetUnsavedFlag(); } } private void removePartFromWorkstepButton_Click(object sender, EventArgs e) { Part removedPart = EditProcessCtrl.RemovePartFromCurrentWorkstep(); if (removedPart != null) { SetUnsavedFlag(); } } public void ImportParts() { OpenFileDialog dlg = new OpenFileDialog(); if (dlg.ShowDialog() == DialogResult.OK) { try { using (TextReader reader = new StreamReader(dlg.FileName)) { bool partOK; int partsCount = 0; do { partOK = false; string line = reader.ReadLine(); if (line != null) { string[] items = line.Split(new char[] { ';' }); if (items.Length >= 4) { Part newPart = new Part(items[2], currentProcess, items[3]); newPart.StepNumber = ++partsCount; currentProcess.Parts.Add(newPart); partsListView.Items.Add(Part2Lvi(newPart)); partOK = true; } } } while (partOK); } } catch (Exception) { MessageBox.Show(Strings.Failed_to_import_a_list_of_parts, Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } private void partsListView_ItemChecked(object sender, ItemCheckedEventArgs e) { if (suppressNotifications) return; if (completeUnlock && (e.Item.Tag is Part)) { if (!CheckAndRetrieveData()) return; (e.Item.Tag as Part).CodeLocation = e.Item.Checked ? CodeLocation.OnPart : CodeLocation.OnPallet; EditProcessCtrl.Data2UI(); SetUnsavedFlag(); } } private void partsListView_ItemCheck(object sender, ItemCheckEventArgs e) { if (suppressNotifications) return; if (!completeUnlock) { e.NewValue = (e.NewValue == CheckState.Checked) ? CheckState.Unchecked : CheckState.Checked; } } /// /// Checks data and retrieves them from UI. /// Displays a message box with related message when data are NOK. /// /// true when data valid and retrieved from UI bool CheckAndRetrieveData() { /// Verify data in list view items string message; if (!VerifyUIData(out message)) { MessageBox.Show(string.Format(Strings.Invalid_data_0, message), Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return false; } /// Retrieve data from list view items foreach (var item in partsListView.Items) UpdatePartFromLvi(item as ListViewItem, (item as ListViewItem).Tag as Part); return true; } } }