tbf/TBF/UI/ResultsMI/ResultsTabPageCtrl.cs

621 lines
23 KiB
C#

///
/// Copyright (c) 2013-2022 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using log4net;
using NHibernate;
using Common;
using Results;
using Results.Forms;
using SharedDatabase.Entities;
using TBF.Resources;
using TBF.UiBridge;
namespace TBF.UI.ResultsMI
{
public partial class ResultsTabPageCtrl : UserControl
{
static readonly ILog log = LogManager.GetLogger(typeof(ResultsTabPageCtrl));
static readonly Color NotCompletedColor = Color.White;
static readonly Color OkColor = Color.LightGreen;
static readonly Color NokColor = Color.LightPink;
static readonly Color RejectColor = Color.Magenta;
static readonly Color ProductionTracing = Color.RoyalBlue;
static readonly Color WrongDirection = Color.Gold;
static readonly Color WrongQ2FactorsColor = Color.Red;
public MetersArrangement MetersArrangement;
public TestsArrangement TestsArrangement;
public int NrMetersInOneGroup;
public bool ShowDisabledPositions;
public int MinWidth;
public int MinHeight;
public IList<WMeterRsltItemSpec> RsltItems_Screen_SingleWM;
public IList<WMeterRsltItemSpec> RsltItems_Screen_CombinedWM;
public IList<WMeterRsltItemSpec> RsltItems_Screen_HeatM;
MetersKind metersKind;
IList<WMeterRsltItemSpec> currentItems;
IOneWMResultsCtrl[] wmRsltsCtrl; /// An array of controls with water meter results.
IOneWMResultsCtrl firstEnabledControl;
DateTime lastRedraw;
DateTime lastSizeChange;
int metersInOneGroup;
int nrGroups;
Timer timer;
/// <summary>
/// Constructor
/// </summary>
public ResultsTabPageCtrl()
{
InitializeComponent();
wmRsltsCtrl = new IOneWMResultsCtrl[0]; /// No water meters displayed => array with zero length
firstEnabledControl = null; /// No water meters displayed => firstListView is null
currentItems = new List<WMeterRsltItemSpec>();
nrGroups = 1;
metersInOneGroup = 1;
if (Program.LocalSettings != null)
{
MetersArrangement = Program.LocalSettings.ResultsConfigMeters;
TestsArrangement = Program.LocalSettings.ResultsConfigTests;
NrMetersInOneGroup = Math.Max(1, Program.LocalSettings.ResultsConfigMetersInOneGroup);
ShowDisabledPositions = Program.LocalSettings.ShowDisabledPositions;
MinWidth = Program.LocalSettings.ResultsConfigMinWidth;
MinHeight = Program.LocalSettings.ResultsConfigMinHeight;
RsltItems_Screen_SingleWM = WMeterRsltItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Screen_SingleWM);
RsltItems_Screen_CombinedWM = WMeterRsltItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Screen_CombinedWM);
RsltItems_Screen_HeatM = WMeterRsltItemSpec.FromStrArray(Program.LocalSettings.RsltItems_Screen_HeatM);
currentItems = GetRsltItems(metersKind);
}
Bridge.ProcedureSelectedHandler += delegate(object sender, ProcedureSelectedEventArgs args)
{
if (InvokeRequired)
Invoke(new EventHandler<ProcedureSelectedEventArgs>(OnProcedureSelected), sender, args);
else
OnProcedureSelected(sender, args);
};
Bridge.TestCompletedHandler += delegate(object sender, TestCompletedEventArgs args)
{
if (InvokeRequired)
Invoke(new EventHandler<TestCompletedEventArgs>(OnTestCompleted), sender, args);
else
OnTestCompleted(sender, args);
};
Bridge.ButtonsEtcHandler += delegate(object sndr, ButtonsEtcEventArgs args)
{
if (InvokeRequired)
Invoke(new EventHandler<ButtonsEtcEventArgs>(OnButtonsEtc), sndr, args);
else
OnButtonsEtc(sndr, args);
};
lastSizeChange = DateTime.Now;
/// Create a timer with one second interval.
timer = new Timer();
timer.Interval = 1000; /// ms
timer.Tick += new EventHandler(OnTimer);
timer.Start();
}
void OnProcedureSelected(object sender, ProcedureSelectedEventArgs args)
{
BatchResults batchResults = TBF.Rig.Sequences.ProcessData.BatchRslts;
metersKind = batchResults.Batch.Compound ? MetersKind.Combined : (batchResults.Batch.HeatMeter ? MetersKind.HeatMeter : MetersKind.Single);
UpdateItems(GetRsltItems(metersKind));
if ((batchResults != null) && (Program.LocalSettings != null))
{
Results.Utils.GetCounterStates(batchResults.Batch, Program.LocalSettings.Counters);
}
if (IsLayoutChangedDueToData(batchResults)) CreateControlsAndFillPanel(batchResults);
UpdateResults(batchResults);
}
void OnTestCompleted(object sender, TestCompletedEventArgs args)
{
BatchResults batchResults = TBF.Rig.Sequences.ProcessData.BatchRslts;
if ((batchResults != null) && (Program.LocalSettings != null))
{
Results.Utils.GetCounterStates(batchResults.Batch, Program.LocalSettings.Counters);
}
if (IsLayoutChangedDueToData(batchResults)) CreateControlsAndFillPanel(batchResults);
UpdateResults(TBF.Rig.Sequences.ProcessData.BatchRslts);
}
void OnButtonsEtc(object sender, UiBridge.ButtonsEtcEventArgs args)
{
reloadPreviousResultsButton.Enabled = ((args.Flags & UiBridge.ButtonsEtc.ProcedureCmbBoxEn) != 0);
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
fixPreviousResultsButton.Visible = ((args.Flags & UiBridge.ButtonsEtc.ProcedureCmbBoxEn) != 0);
#endif
}
private void ResultsTabPageCtrl_Load(object sender, EventArgs e)
{
// Localization
configureButton.Text = Strings.Configure;
columnWidthsButton.Text = Strings.Save_column_widths;
showPreviousResultsButton.Text = Strings.Previous_results;
reloadPreviousResultsButton.Text = Strings.Reload_previous_results;
fixPreviousResultsButton.Text = Strings.Fix;
pictureBox1.BackColor = OkColor;
label1.Text = Strings.Passed;
pictureBox2.BackColor = NokColor;
label2.Text = Strings.Failed;
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
label2.Text += " (zopakovať)";
pictureBox3.BackColor = RejectColor;
pictureBox3.Visible = true;
label3.Text = "Vyradiť";
label3.Visible = true;
pictureBox4.BackColor = WrongDirection;
pictureBox4.Visible = true;
label4.Text = "Otočiť smer";
label4.Visible = true;
pictureBox5.BackColor = ProductionTracing;
pictureBox5.Visible = true;
label5.Text = "Vrátiť na predch. krok";
label5.Visible = true;
#endif
if ((TBF.Rig.Sequences.ProcessData.BatchRslts != null) && (Program.LocalSettings != null))
{
Results.Utils.GetCounterStates(TBF.Rig.Sequences.ProcessData.BatchRslts.Batch, Program.LocalSettings.Counters);
}
CreateControlsAndFillPanel(TBF.Rig.Sequences.ProcessData.BatchRslts);
UpdateResults(TBF.Rig.Sequences.ProcessData.BatchRslts);
}
IList<WMeterRsltItemSpec> GetRsltItems(MetersKind metersKind)
{
IList<WMeterRsltItemSpec> srcItems;
switch (metersKind)
{
default:
case MetersKind.Single: srcItems = RsltItems_Screen_SingleWM; break;
case MetersKind.Combined: srcItems = RsltItems_Screen_CombinedWM; break;
case MetersKind.HeatMeter: srcItems = RsltItems_Screen_HeatM; break;
}
IList<WMeterRsltItemSpec> copiedItems = new List<WMeterRsltItemSpec>();
if (srcItems != null)
{
foreach (var it in srcItems) copiedItems.Add(it.Clone());
}
return copiedItems;
}
/// <summary>
/// Handle button at the top of this form: Invoke a configuration dialog
/// </summary>
private void configureButton_Click(object sender, EventArgs e)
{
ResultsArrangementDlg dlg = new ResultsArrangementDlg()
{
MetersKind = metersKind,
TestsArrangement = TestsArrangement,
MetersArrangement = MetersArrangement,
NrMetersInOneGroup = NrMetersInOneGroup,
ShowDisabledPositions = ShowDisabledPositions,
MinWidth = MinWidth,
MinHeight = MinHeight,
SelectedItems = GetRsltItems(metersKind)
};
DialogResult dr = dlg.ShowDialog();
if (dr == DialogResult.OK && dlg.Unlocked)
{
bool isLayoutChangedDueToConfig = false;
if ((MetersArrangement != dlg.MetersArrangement) ||
(TestsArrangement != dlg.TestsArrangement) ||
(NrMetersInOneGroup != dlg.NrMetersInOneGroup) ||
(ShowDisabledPositions != dlg.ShowDisabledPositions) ||
(MinWidth != dlg.MinWidth) ||
(MinHeight != dlg.MinHeight))
{
Program.LocalSettings.ResultsConfigMeters = MetersArrangement = dlg.MetersArrangement;;
Program.LocalSettings.ResultsConfigTests = TestsArrangement = dlg.TestsArrangement;
Program.LocalSettings.ResultsConfigMetersInOneGroup = NrMetersInOneGroup = dlg.NrMetersInOneGroup;
Program.LocalSettings.ShowDisabledPositions = ShowDisabledPositions = dlg.ShowDisabledPositions;
Program.LocalSettings.ResultsConfigMinWidth = MinWidth = dlg.MinWidth;
Program.LocalSettings.ResultsConfigMinHeight = MinHeight = dlg.MinHeight;
isLayoutChangedDueToConfig = true;
}
switch (metersKind)
{
default:
case MetersKind.Single:
RsltItems_Screen_SingleWM = dlg.SelectedItems;
Program.LocalSettings.RsltItems_Screen_SingleWM = WMeterRsltItemSpec.ToStrArray(RsltItems_Screen_SingleWM);
break;
case MetersKind.Combined:
RsltItems_Screen_CombinedWM = dlg.SelectedItems;
Program.LocalSettings.RsltItems_Screen_CombinedWM = WMeterRsltItemSpec.ToStrArray(RsltItems_Screen_CombinedWM);
break;
case MetersKind.HeatMeter:
RsltItems_Screen_HeatM = dlg.SelectedItems;
Program.LocalSettings.RsltItems_Screen_HeatM = WMeterRsltItemSpec.ToStrArray(RsltItems_Screen_HeatM);
break;
}
UpdateItems(dlg.SelectedItems);
Program.LocalSettings.Save();
if ((TBF.Rig.Sequences.ProcessData.BatchRslts != null) && (Program.LocalSettings != null))
{
Results.Utils.GetCounterStates(TBF.Rig.Sequences.ProcessData.BatchRslts.Batch, Program.LocalSettings.Counters);
}
if (isLayoutChangedDueToConfig)
{
CreateControlsAndFillPanel(TBF.Rig.Sequences.ProcessData.BatchRslts);
}
UpdateResults(TBF.Rig.Sequences.ProcessData.BatchRslts);
}
}
/// <summary>
/// Handle button at the top of this form: Propagate column widths
/// </summary>
private void columnWidthsButton_Click(object sender, EventArgs e)
{
if (firstEnabledControl == null) return;
/// Get column widths from the first control
Program.LocalSettings.RsltsClmnWidths = new int[firstEnabledControl.Columns.Count];
for (int i = 0; i < firstEnabledControl.Columns.Count; i++)
{
Program.LocalSettings.RsltsClmnWidths[i] = firstEnabledControl.Columns[i].Width;
}
Program.LocalSettings.Save();
if ((TBF.Rig.Sequences.ProcessData.BatchRslts != null) && (Program.LocalSettings != null))
{
Results.Utils.GetCounterStates(TBF.Rig.Sequences.ProcessData.BatchRslts.Batch, Program.LocalSettings.Counters);
}
UpdateColumnWidths(Program.LocalSettings.RsltsClmnWidths);
}
///
/// Handle other buttons at the top of this form
///
private void showPreviousResultsButton_Click(object sender, EventArgs e)
{
new PreviousResultsDlg().ShowDialog();
}
private void reloadPreviousResultsButton_Click(object sender, EventArgs e)
{
new PreviousResultsDlg(PreviousResultsMode.Reload).ShowDialog();
}
private void fixPreviousResultsButton_Click(object sender, EventArgs e)
{
new PreviousResultsDlg(PreviousResultsMode.Fix).ShowDialog();
}
///
/// Handle double-click inside a water meter results control
///
void OnDoubleClick(object sender, WaterMeterEventArgs args)
{
if (TBF.Rig.Sequences.ProcessData.BatchRslts.Batch != null &&
TBF.Rig.Sequences.ProcessData.BatchRslts.Batch.WaterMeters != null)
{
foreach (var wm in TBF.Rig.Sequences.ProcessData.BatchRslts.Batch.WaterMeters)
{
if (wm.WMPosition == args.WMPosition)
{
ShowMoreWMResults(wm);
return;
}
}
}
MessageBox.Show(Strings.No_water_meter);
}
void UpdateColumnWidths(int[] columnWidths)
{
foreach (var ctrl in wmRsltsCtrl) ctrl.Update(columnWidths);
}
void UpdateScrollpositions(int scrollStart)
{
/// TODO
}
void UpdateItems(IList<WMeterRsltItemSpec> items)
{
bool updateItems = false;
if (currentItems.Count != items.Count)
{
/// Current and new item counts are different
updateItems = true;
}
else
{
/// Current and new item counts are the same
for (int i = 0; i < currentItems.Count; i++)
{
if (currentItems[i] != items[i])
{
updateItems = true;
break;
}
}
}
if (updateItems)
{
/// Update items in all controls
currentItems = items;
foreach (var oneCtrl in wmRsltsCtrl) oneCtrl.Update(items);
}
}
bool IsLayoutChangedDueToData(BatchResults results)
{
if (results == null || results.Batch == null || results.Batch.WaterMeters == null || results.Batch.WaterMeters.Count == 0)
{
/// 'results' contain no water meters, wmRsltsCtrl.Lenght == 0 expected
return (wmRsltsCtrl.Length != 0); /// true when there are currently water meters on screen
}
///
/// Determine water meter positions count
///
int displayedWatermetersCount = 0;
for (int i = 0; i < results.Batch.WaterMeters.Count; i++)
{
if (results.Batch.WaterMeters[i] != null)
{
if (ShowDisabledPositions || !results.Batch.WaterMeters[i].Disabled)
{
displayedWatermetersCount++;
}
}
}
return (displayedWatermetersCount != wmRsltsCtrl.Length);
}
/// <summary>
/// Re-draw the results. Apply new settings if they changed.
/// </summary>
void CreateControlsAndFillPanel(BatchResults results)
{
if ((results == null) || (results.WMPositionsCount == 0))
{
/// There are no water meters at all
DeleteHandlers();
flowLayoutPanel.Controls.Clear();
wmRsltsCtrl = new OneWMResultsRowsCtrl[0];
firstEnabledControl = null;
return;
}
///
/// Determine water meter positions count
///
int displayedControlsCount = 0;
for (int i = 0; i < results.Batch.WaterMeters.Count; i++)
{
if (results.Batch.WaterMeters[i] != null)
{
if (ShowDisabledPositions || !results.Batch.WaterMeters[i].Disabled)
{
displayedControlsCount++;
}
}
}
///
/// Calculate geometry
///
metersInOneGroup = Math.Max(1, Math.Min(displayedControlsCount, NrMetersInOneGroup));
nrGroups = Math.Max(1, (displayedControlsCount + metersInOneGroup - 1) / metersInOneGroup);
int oneWidth;
int oneHeight;
///
if (MetersArrangement == MetersArrangement.Horizontally)
{
flowLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
oneWidth = Math.Max(MinWidth, flowLayoutPanel.Width / metersInOneGroup - 6);
oneHeight = Math.Max(MinHeight, flowLayoutPanel.Height / nrGroups - 6);
}
else
{
flowLayoutPanel.FlowDirection = FlowDirection.TopDown;
oneWidth = Math.Max(MinWidth, flowLayoutPanel.Width / nrGroups - 6);
oneHeight = Math.Max(MinHeight, flowLayoutPanel.Height / metersInOneGroup - 6);
}
///
/// Create controls and fill the FlowLayoutPanel
///
flowLayoutPanel.SuspendLayout();
DeleteHandlers();
flowLayoutPanel.Controls.Clear();
flowLayoutPanel.WrapContents = true;
flowLayoutPanel.AutoScroll = true;
wmRsltsCtrl = new IOneWMResultsCtrl[displayedControlsCount];
int ix = 0;
firstEnabledControl = null;
for (int i = 0; i < results.Batch.WaterMeters.Count; i++)
{
if (results.Batch.WaterMeters[i] != null)
{
if (!results.Batch.WaterMeters[i].Disabled || ShowDisabledPositions)
{
/// Create one water meter position / control
wmRsltsCtrl[ix] = (TestsArrangement == TestsArrangement.Rows)
? new OneWMResultsRowsCtrl() as IOneWMResultsCtrl
: new OneWMResultsColumnsCtrl() as IOneWMResultsCtrl;
wmRsltsCtrl[ix].Width = oneWidth;
wmRsltsCtrl[ix].Height = oneHeight;
wmRsltsCtrl[ix].Update(currentItems);
wmRsltsCtrl[ix].WMResultsClickedHandler += HandleDoubleClick;
flowLayoutPanel.Controls.Add(wmRsltsCtrl[ix] as UserControl);
if ((firstEnabledControl == null) && !results.Batch.WaterMeters[i].Disabled) firstEnabledControl = wmRsltsCtrl[ix];
ix++;
}
}
}
UpdateColumnWidths(Program.LocalSettings.RsltsClmnWidths);
flowLayoutPanel.ResumeLayout();
}
void HandleDoubleClick(object s, WaterMeterEventArgs args)
{
if (InvokeRequired)
{
Invoke(new EventHandler<WaterMeterEventArgs>(OnDoubleClick), s, args);
}
else
{
OnDoubleClick(s, args);
}
}
/// <summary>
/// Delete handler subscriptions from controls (memory leak if not done???).
/// To be done before flowLayoutPanel.Controls.Clear().
/// </summary>
void DeleteHandlers()
{
foreach (var ctrl in flowLayoutPanel.Controls)
{
if (ctrl is IOneWMResultsCtrl)
{
(ctrl as IOneWMResultsCtrl).WMResultsClickedHandler -= HandleDoubleClick;
}
}
}
void UpdateResults(BatchResults batchResults)
{
if (batchResults != null && batchResults.Batch != null && batchResults.Batch.WaterMeters != null)
{
int ctrlIx = 0;
for (int i = 0; i < batchResults.Batch.WaterMeters.Count; i++)
{
if (!batchResults.Batch.WaterMeters[i].Disabled || ShowDisabledPositions)
{
if (ctrlIx < wmRsltsCtrl.Length) wmRsltsCtrl[ctrlIx++].Update(batchResults.Batch.WaterMeters[i]);
}
}
}
}
void ShowMoreWMResults(Results.Entities.WaterMeter wm)
{
if ((SharedDatabase.TracingDB.SessionFactory == null) || string.IsNullOrEmpty(wm.SerialNr))
{
new MoreWMResultsDlg(wm, null).ShowDialog();
}
else
{
using (ISession session = SharedDatabase.TracingDB.SessionFactory.OpenSession())
{
IList<ReferenceRecord> refRecords = session.QueryOver<ReferenceRecord>()
.Where(x => (x.Code1 == wm.SerialNr))
.OrderBy(x => x.Timestamp).Desc
.List();
new MoreWMResultsDlg(wm, refRecords).ShowDialog();
}
}
}
private void flowLayoutPanel_SizeChanged(object sender, EventArgs e)
{
lastSizeChange = DateTime.Now;
}
private void OnTimer(object source, EventArgs e)
{
if (DateTime.Compare(lastSizeChange, lastRedraw) > 0)
{
/// The last size change was more recent then the last redraw
DateTime now = DateTime.Now;
if (DateTime.Compare(lastSizeChange + new TimeSpan(0, 0, 1), now) < 0)
{
/// More then 1 second since the last panel size change
/// Calculate geometry
int oneWidth;
int oneHeight;
///
if (MetersArrangement == MetersArrangement.Horizontally)
{
flowLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
oneWidth = Math.Max(MinWidth, flowLayoutPanel.Width / metersInOneGroup - 6);
oneHeight = Math.Max(MinHeight, flowLayoutPanel.Height / nrGroups - 6);
}
else
{
flowLayoutPanel.FlowDirection = FlowDirection.TopDown;
oneWidth = Math.Max(MinWidth, flowLayoutPanel.Width / nrGroups - 6);
oneHeight = Math.Max(MinHeight, flowLayoutPanel.Height / metersInOneGroup - 6);
}
/// Update size of controls
flowLayoutPanel.SuspendLayout();
///
foreach (var oneCtrl in wmRsltsCtrl)
{
oneCtrl.Width = oneWidth;
oneCtrl.Height = oneHeight;
}
///
flowLayoutPanel.ResumeLayout();
}
}
}
}
}