tbf/TBF/BenchControl/DataEntry/DataStream/CycleBeginningForm.cs

567 lines
26 KiB
C#

///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using log4net;
using TBF.BenchControl.RegisterReaders.DataStream.MefImport;
using TBF.Resources;
namespace TBF.BenchControl.DataEntry.DataStream
{
public enum CommErr
{
None = 0,
CommFailed, /// 1
HeadDisabledByUser, /// 2
}
public partial class CycleBeginningForm : Form, GenericDevices.IHasCompleted
{
private static readonly ILog log = LogManager.GetLogger(typeof(CycleBeginningForm));
public static Color InitialColor = Color.LightGray;
public static Color DisabledColor = Color.DarkGray;
public static Color OptoOKColor = Color.Green;
public static Color OptoNokColor = Color.Red;
public static Color BusyColor = Color.Yellow;
/// <summary> Number of water meters </summary>
IList<Results.Entities.WaterMeter> waterMeters;
MefImport mefImport;
/// To be retrieved after the form is closed
public string PurchaseOrder;
public string[] SNText;
public bool[] Disabled;
/// Set to 'true' when the form closes
public bool Completed { get { return formCompleted; } }
bool formCompleted;
Thread thread;
public int DataStreamsCount;
int busyIx;
/// <summary> Number of text boxes for serial numbers </summary>
Label[] labels;
CheckBoxImage[] checkBoxes;
PictureBox[] pictures;
TextBox[] serialNrBoxes;
IList<TextBox> enabledSerialNrBoxes;
/// <summary> Parameterless constructor for common functionality </summary>
public CycleBeginningForm()
{
InitializeComponent();
ControlBox = false;
labels = new Label[]
{
label1, label2, label3, label4, label5, label6, label7, label8, label9, label10, label11, label12,
label13, label14, label15, label16, label17, label18, label19, label20, label21, label22, label23, label24,
};
checkBoxes = new CheckBoxImage[]
{
checkBoxImage1, checkBoxImage2, checkBoxImage3, checkBoxImage4, checkBoxImage5, checkBoxImage6,
checkBoxImage7, checkBoxImage8, checkBoxImage9, checkBoxImage10, checkBoxImage11, checkBoxImage12,
checkBoxImage13, checkBoxImage14, checkBoxImage15, checkBoxImage16, checkBoxImage17, checkBoxImage18,
checkBoxImage19, checkBoxImage20, checkBoxImage21, checkBoxImage22, checkBoxImage23, checkBoxImage24,
};
pictures = new PictureBox[]
{
pictureBox1, pictureBox2, pictureBox3, pictureBox4, pictureBox5, pictureBox6,
pictureBox7, pictureBox8, pictureBox9, pictureBox10, pictureBox11, pictureBox12,
pictureBox13, pictureBox14, pictureBox15, pictureBox16, pictureBox17, pictureBox18,
pictureBox19, pictureBox20, pictureBox21, pictureBox22, pictureBox23, pictureBox24,
};
serialNrBoxes = new TextBox[]
{
serialNrBox1, serialNrBox2, serialNrBox3, serialNrBox4, serialNrBox5, serialNrBox6,
serialNrBox7, serialNrBox8, serialNrBox9, serialNrBox10, serialNrBox11, serialNrBox12,
serialNrBox13, serialNrBox14, serialNrBox15, serialNrBox16, serialNrBox17, serialNrBox18,
serialNrBox19, serialNrBox20, serialNrBox21, serialNrBox22, serialNrBox23, serialNrBox24,
};
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public CycleBeginningForm(IList<Results.Entities.WaterMeter> waterMeters, MefImport mefImport)
: this()
{
this.waterMeters = waterMeters;
this.mefImport = mefImport;
SNText = new string[waterMeters.Count];
Disabled = new bool[waterMeters.Count];
Localize();
PrepareOrderCombo(orderComboBox);
int wmsCount = Math.Min(mefImport.DataStreamIFace.GetMetersCount(), waterMeters.Count);
int right, bottom;
enabledSerialNrBoxes = ShuffleTextBoxes(wmsCount, Config.Data.LineSize, out right, out bottom);
Height = bottom + 60;
DataStreamsCount = enabledSerialNrBoxes.Count;
SetCheckBoxStates(Program.LocalSettings.OptoHeadsEnabled);
busyIx = -1;
formCompleted = false;
StartForceCloseHandler();
/// Attach to handlers
OpenConnStartedHandler += delegate(object sender, OpenConnectionEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<OpenConnectionEventArgs>(DoOnOpenConnStarted), sender, args); }
else { DoOnOpenConnStarted(sender, args); }
};
OpenConnCompletedHandler += delegate(object sender, OpenConnectionEventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<OpenConnectionEventArgs>(DoOnOpenConnCompleted), sender, args); }
else { DoOnOpenConnCompleted(sender, args); }
};
///
/// Start communication with water meters in the worker thread
///
thread = new Thread(Worker);
thread.CurrentCulture = CultureInfo.CurrentCulture;
thread.CurrentUICulture = CultureInfo.CurrentUICulture;
thread.Start();
}
void Localize()
{
Text = Strings.Opening_connections_with_water_meters;
orderGroupBox.Text = Strings.Purchase_order;
okButton.Text = Strings.OkBtnText;
retryButton.Text = Strings.RetryBtnText;
}
/// <summary>
/// Load Purchase order combo box items from the LocalSettings PurchaseOrderHistory array
/// </summary>
/// <param name="orderComboBox">Puchase order ComboBox</param>
void PrepareOrderCombo(ComboBox orderComboBox)
{
for (int i = 0; i < Program.LocalSettings.PurchaseOrderHistoryCount; i++)
{
orderComboBox.Items.Add(Program.LocalSettings.PurchaseOrderHistory[i]);
}
if (orderComboBox.Items.Count > 0)
{
orderComboBox.Text = orderComboBox.Items[0].ToString();
}
}
/// <summary>
/// Makes layout of labels/text boxes on the screen the same
/// as the layout of watermeters on the test bench.
/// To be used only once in the constructor or in the form load handler.
/// </summary>
/// <param name="wmsCount">Number of water meters</param>
/// <param name="lineSize">Number of water meters in one line</param>
/// <param name="right">Right coordinate of the rightmost TextBox</param>
/// <param name="bottom">Bottom coordinate of the bottommost TextBox</param>
/// <returns>List of enabled text boxes</returns>
IList<TextBox> ShuffleTextBoxes(int wmsCount, int lineSize, out int right, out int bottom)
{
int uiBoxesCount = serialNrBoxes.Length;
IList<TextBox> enabledSerialNrBoxes = new List<TextBox>();
if (wmsCount < uiBoxesCount && lineSize > 0)
{
int nrLines = (wmsCount + lineSize - 1) / lineSize;
int gap = (uiBoxesCount - wmsCount) / nrLines;
int dest = 0;
for (int l = 0; l < nrLines; l++)
{
for (int i = 0; i < lineSize; i++)
{
int origin = l * lineSize + l * gap + i;
labels[dest] = labels[origin];
checkBoxes[dest] = checkBoxes[origin];
pictures[dest] = pictures[origin];
serialNrBoxes[dest] = serialNrBoxes[origin];
labels[dest].Visible = true;
checkBoxes[dest].Visible = true;
pictures[dest].Visible = true;
serialNrBoxes[dest].Visible = true;
labels[dest].Text = (dest + 1).ToString();
enabledSerialNrBoxes.Add(serialNrBoxes[dest]);
dest++;
if (dest >= wmsCount) break;
}
if (dest >= wmsCount) break;
}
}
else
{
int activatedWMsCount = Math.Min(wmsCount, uiBoxesCount);
for (int i = 0; i < activatedWMsCount; i++)
{
labels[i].Visible = true;
checkBoxes[i].Visible = true;
pictures[i].Visible = true;
serialNrBoxes[i].Visible = true;
labels[i].Text = (i + 1).ToString();
enabledSerialNrBoxes.Add(serialNrBoxes[i]);
}
}
int xMax = 0;
int yMax = 0;
foreach (var tb in enabledSerialNrBoxes)
{
if (tb.Left + tb.Width > xMax) xMax = tb.Left + tb.Width;
if (tb.Top + tb.Height > yMax) yMax = tb.Top + tb.Height;
}
right = xMax;
bottom = yMax;
return enabledSerialNrBoxes;
}
///
/// Set checkbox states accroding to TBF program level configuration
///
void SetCheckBoxStates(long optoHeadsConfig)
{
for (int i = 0; i < DataStreamsCount; i++)
{
if ((optoHeadsConfig & (1L << i)) == 0)
{
/// Opto head is disabled in configuration
checkBoxes[i].Checked = false;
checkBoxes[i].Enabled = false;
pictures[i].BackColor = DisabledColor;
serialNrBoxes[i].Text = Strings.Disabled_in_configuration;
SNText[i] = string.Empty;
Disabled[i] = waterMeters[i].Disabled = true;
}
else
{
/// Opto head is enabled
checkBoxes[i].Checked = true;
checkBoxes[i].Enabled = true;
Disabled[i] = waterMeters[i].Disabled = false;
if (string.IsNullOrEmpty(SNText[i]))
{
serialNrBoxes[i].Text = string.Empty;
pictures[i].BackColor = InitialColor;
}
else
{
serialNrBoxes[i].Text = SNText[i];
pictures[i].BackColor = OptoOKColor;
}
}
}
}
/// <summary>
/// Worker thread
/// </summary>
void Worker()
{
do
{
for (int wmNr0 = 0; wmNr0 < DataStreamsCount; wmNr0++)
{
if (formCompleted) break;
bool isLast = (wmNr0 == DataStreamsCount - 1);
if (!Disabled[wmNr0])
{
OnOpenConnStarted(this, new OpenConnectionEventArgs(wmNr0, isLast, waterMeters[wmNr0]));
string waterMeterID;
bool connected = mefImport.OpenConnection(wmNr0, "", out waterMeterID);
log.WarnFormat("{0} : mefImport.OpenConnection({1}, ...) returned {2}, ID={3}", Name, wmNr0, connected, waterMeterID);
if (!formCompleted)
{
OnOpenConnCompleted(this, new OpenConnectionEventArgs(wmNr0, isLast, waterMeters[wmNr0], connected, waterMeterID));
}
}
else
{
if (!formCompleted)
{
OnOpenConnCompleted(this, new OpenConnectionEventArgs(wmNr0, isLast, waterMeters[wmNr0]));
}
}
}
}
while (!formCompleted);
}
private void checkBoxImage1_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage1); }
private void checkBoxImage2_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage2); }
private void checkBoxImage3_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage3); }
private void checkBoxImage4_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage4); }
private void checkBoxImage5_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage5); }
private void checkBoxImage6_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage6); }
private void checkBoxImage7_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage7); }
private void checkBoxImage8_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage8); }
private void checkBoxImage9_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage9); }
private void checkBoxImage10_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage10); }
private void checkBoxImage11_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage11); }
private void checkBoxImage12_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage12); }
private void checkBoxImage13_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage13); }
private void checkBoxImage14_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage14); }
private void checkBoxImage15_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage15); }
private void checkBoxImage16_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage16); }
private void checkBoxImage17_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage17); }
private void checkBoxImage18_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage18); }
private void checkBoxImage19_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage19); }
private void checkBoxImage20_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage20); }
private void checkBoxImage21_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage21); }
private void checkBoxImage22_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage22); }
private void checkBoxImage23_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage23); }
private void checkBoxImage24_Click(object sender, EventArgs e) { ProcessCheckBoxClick(checkBoxImage24); }
void ProcessCheckBoxClick(CheckBoxImage checkBox)
{
for (int ix = 0; ix < DataStreamsCount; ix++)
{
if (checkBoxes[ix] == checkBox)
{
Disabled[ix] = waterMeters[ix].Disabled ? true : !checkBoxes[ix].Checked;
CheckAllOK();
break;
}
}
}
private void serialNrBox1_TextChanged(object sender, EventArgs e) { checkBoxImage1.Checked = true; }
private void serialNrBox2_TextChanged(object sender, EventArgs e) { checkBoxImage2.Checked = true; }
private void serialNrBox3_TextChanged(object sender, EventArgs e) { checkBoxImage3.Checked = true; }
private void serialNrBox4_TextChanged(object sender, EventArgs e) { checkBoxImage4.Checked = true; }
private void serialNrBox5_TextChanged(object sender, EventArgs e) { checkBoxImage5.Checked = true; }
private void serialNrBox6_TextChanged(object sender, EventArgs e) { checkBoxImage6.Checked = true; }
private void serialNrBox7_TextChanged(object sender, EventArgs e) { checkBoxImage7.Checked = true; }
private void serialNrBox8_TextChanged(object sender, EventArgs e) { checkBoxImage8.Checked = true; }
private void serialNrBox9_TextChanged(object sender, EventArgs e) { checkBoxImage9.Checked = true; }
private void serialNrBox10_TextChanged(object sender, EventArgs e) { checkBoxImage10.Checked = true; }
private void serialNrBox11_TextChanged(object sender, EventArgs e) { checkBoxImage11.Checked = true; }
private void serialNrBox12_TextChanged(object sender, EventArgs e) { checkBoxImage12.Checked = true; }
private void serialNrBox13_TextChanged(object sender, EventArgs e) { checkBoxImage13.Checked = true; }
private void serialNrBox14_TextChanged(object sender, EventArgs e) { checkBoxImage14.Checked = true; }
private void serialNrBox15_TextChanged(object sender, EventArgs e) { checkBoxImage15.Checked = true; }
private void serialNrBox16_TextChanged(object sender, EventArgs e) { checkBoxImage16.Checked = true; }
private void serialNrBox17_TextChanged(object sender, EventArgs e) { checkBoxImage17.Checked = true; }
private void serialNrBox18_TextChanged(object sender, EventArgs e) { checkBoxImage18.Checked = true; }
private void serialNrBox19_TextChanged(object sender, EventArgs e) { checkBoxImage19.Checked = true; }
private void serialNrBox20_TextChanged(object sender, EventArgs e) { checkBoxImage20.Checked = true; }
private void serialNrBox21_TextChanged(object sender, EventArgs e) { checkBoxImage21.Checked = true; }
private void serialNrBox22_TextChanged(object sender, EventArgs e) { checkBoxImage22.Checked = true; }
private void serialNrBox23_TextChanged(object sender, EventArgs e) { checkBoxImage23.Checked = true; }
private void serialNrBox24_TextChanged(object sender, EventArgs e) { checkBoxImage24.Checked = true; }
private void serialNrBox1_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox1); }
private void serialNrBox2_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox2); }
private void serialNrBox3_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox3); }
private void serialNrBox4_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox4); }
private void serialNrBox5_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox5); }
private void serialNrBox6_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox6); }
private void serialNrBox7_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox7); }
private void serialNrBox8_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox8); }
private void serialNrBox9_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox9); }
private void serialNrBox10_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox10); }
private void serialNrBox11_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox11); }
private void serialNrBox12_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox12); }
private void serialNrBox13_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox13); }
private void serialNrBox14_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox14); }
private void serialNrBox15_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox15); }
private void serialNrBox16_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox16); }
private void serialNrBox17_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox17); }
private void serialNrBox18_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox18); }
private void serialNrBox19_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox19); }
private void serialNrBox20_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox20); }
private void serialNrBox21_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox21); }
private void serialNrBox22_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox22); }
private void serialNrBox23_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox23); }
private void serialNrBox24_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrBox24); }
/// <summary>
/// Process a key press within any enabled text boxe
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <param name="currentFocusOwner">TextBox control which received the event</param>
private void ProcKeyPress(object sender, KeyPressEventArgs e, TextBox currentFocusOwner)
{
if (e.KeyChar == '+')
{
/// Process '+' key ..... Form completed
okButton_Click(sender, e);
}
if (e.KeyChar == '\r')
{
/// Process <enter> key ..... Next text field
if (enabledSerialNrBoxes.Count < 2) return; /// There is just one enabled textbox
for (int i = 0; i < enabledSerialNrBoxes.Count; i++)
{
if (enabledSerialNrBoxes[i] == currentFocusOwner)
{
/// Change focus to the next enabled text box
enabledSerialNrBoxes[(i + 1) % enabledSerialNrBoxes.Count].Focus();
return;
}
}
}
}
private void allCheckBox_CheckedChanged(object sender, EventArgs e)
{
foreach (var cb in checkBoxes)
{
cb.Checked = allCheckBox.Checked;
}
}
#region Forced close handling
public void StartForceCloseHandler()
{
UiBridge.Bridge.CloseModelessFormHandler += delegate(object sender, EventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<EventArgs>(OnForceClose), sender, args); }
else OnForceClose(sender, args);
};
}
private void OnForceClose(object sender, EventArgs args)
{
DialogResult = DialogResult.Cancel;
Close();
}
#endregion
/// <summary>
/// Called when communication with one watermeter is completed
/// </summary>
public static void OnOpenConnStarted(object sender, OpenConnectionEventArgs data)
{
if (OpenConnStartedHandler == null) return;
try { OpenConnStartedHandler(sender, data); }
catch (Exception e) { log.Error("OpenConnStartedHandler(...) failed", e); }
}
public static event EventHandler<OpenConnectionEventArgs> OpenConnStartedHandler;
void DoOnOpenConnStarted(object sender, OpenConnectionEventArgs data)
{
busyIx = data.WMNr0;
pictures[busyIx].BackColor = BusyColor;
}
/// <summary>
/// Called when communication with one watermeter is completed
/// </summary>
public static void OnOpenConnCompleted(object sender, OpenConnectionEventArgs data)
{
if (OpenConnCompletedHandler == null) return;
try { OpenConnCompletedHandler(sender, data); }
catch (Exception e) { log.Error("OpenConnCompletedHandler(...) failed", e); }
}
public static event EventHandler<OpenConnectionEventArgs> OpenConnCompletedHandler;
void DoOnOpenConnCompleted(object sender, OpenConnectionEventArgs data)
{
busyIx = -1;
int ix = data.WMNr0;
if (data.Wm != null)
{
if (data.Wm.Disabled)
{
/// Disabled in configuration
SNText[ix] = Strings.Disabled_in_configuration;
pictures[ix].BackColor = DisabledColor;
}
else
{
serialNrBoxes[ix].Text = SNText[ix] = string.IsNullOrEmpty(data.WaterMeterID) ? string.Empty : data.WaterMeterID;
pictures[ix].BackColor = data.Connected ? OptoOKColor : OptoNokColor;
}
}
else
{
serialNrBoxes[ix].Text = SNText[ix] = string.Empty;
pictures[ix].BackColor = OptoNokColor;
}
CheckAllOK();
}
void CheckAllOK()
{
bool allOk = true;
for (int i = 0; i < DataStreamsCount; i++)
{
if (!Disabled[i] && string.IsNullOrEmpty(SNText[i]))
{
allOk = false;
break;
}
}
if (allOk) okButton_Click(this, null);
}
void okButton_Click(object sender, EventArgs e)
{
formCompleted = true;
PurchaseOrder = orderComboBox.Text;
for (int i = 0; i < DataStreamsCount; i++)
{
if (SNText != null && SNText.Length > i) SNText[i] = serialNrBoxes[i].Text;
if (Disabled != null && Disabled.Length > i) Disabled[i] = !checkBoxes[i].Checked;
if (waterMeters != null && waterMeters.Count > i && waterMeters[i] != null && !waterMeters[i].Disabled)
{
waterMeters[i].SerialNr = serialNrBoxes[i].Text;
waterMeters[i].Disabled = !checkBoxes[i].Checked;
}
}
Program.LocalSettings.UpdateHistory(orderComboBox.Text, ref Program.LocalSettings.PurchaseOrderHistory);
Program.LocalSettings.LastSNTexts = SNText;
Close();
}
void retryButton_Click(object sender, EventArgs e)
{
SetCheckBoxStates(Program.LocalSettings.OptoHeadsEnabled);
}
}
}