tbf/WorkflowConfigurator/UserControls/PartsCtrl.cs

546 lines
20 KiB
C#
Raw Permalink Normal View History

2022-01-06 14:41:50 +00:00
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<Part> 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<Process> allProcesses)
{
this.currentProcess = process;
}
/// <summary>
/// Enable/disable/hide UI elements based on lock/unlock/complete unlock state
/// </summary>
/// <param name="unlock">true = unlock for released processes</param>
/// <param name="completely">true = unlock for processes in preparation (complete unlock)</param>
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;
}
/// <summary>
/// Returns true when (modified) UI data are OK
/// </summary>
/// <returns>true when UI data are valid</returns>
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;
2022-01-06 14:41:50 +00:00
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;
2022-01-06 14:41:50 +00:00
ComboBox checkComboBox;
///
public enum PartsColumn
{
HasSN,
Nr,
Name,
HowToObtain,
2022-01-06 14:41:50 +00:00
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());
2022-01-06 14:41:50 +00:00
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
2022-01-06 14:41:50 +00:00
};
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());
2022-01-06 14:41:50 +00:00
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;
}
}
2022-01-06 14:41:50 +00:00
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;
}
2022-01-06 14:41:50 +00:00
(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;
}
}
}
2022-01-06 14:41:50 +00:00
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;
}
}
/// <summary>
/// Checks data and retrieves them from UI.
/// Displays a message box with related message when data are NOK.
/// </summary>
/// <returns>true when data valid and retrieved from UI</returns>
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;
}
}
}