using DevExpress.
XtraCharts;
using DevExpress.XtraEditors;
using RecipesDLL;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public partial class CIPBatchDashboardForm : XtraForm
{
private CIPMaster_Report _data;
private Dictionary<string, LabelControl> valueLabels = new Dictionary<string,
LabelControl>();
private ChartControl chartControl1;
private ChartControl pieChart;
public CIPBatchDashboardForm(CIPMaster_Report data)
{
InitializeComponent();
_data = data;
LoadDashboard();
}
private void InitializeComponent()
{
this.Text = "CIP Dashboard";
this.Size = new Size(1240, 700);
this.StartPosition = FormStartPosition.CenterScreen;
// Khởi tạo dictionary
valueLabels = new Dictionary<string, LabelControl>();
// Biểu đồ bên dưới
chartControl1 = new ChartControl { Dock = DockStyle.Fill };
pieChart = new ChartControl { Dock = DockStyle.Fill };
var chartSplit = new SplitContainerControl
{
Dock = DockStyle.Fill,
//Orientation = Orientation.Vertical,
SplitterPosition = this.Width / 2
};
chartSplit.Panel1.Controls.Add(chartControl1);
chartSplit.Panel2.Controls.Add(pieChart);
var spacer = new Panel
{
Height = 10,
Dock = DockStyle.Top,
BackColor = this.BackColor
};
var panelTop = new FlowLayoutPanel
{
Dock = DockStyle.Top,
Height = 280,
Padding = new Padding(10),
AutoScroll = false,
FlowDirection = FlowDirection.LeftToRight,
//BackColor = Color.White,
WrapContents = false
};
var groupSystem = CreateGroup("System Info");
var groupProduction = CreateGroup("Production Info");
var groupTime = CreateGroup("Time/Status");
panelTop.Controls.Add(groupSystem);
panelTop.Controls.Add(groupProduction);
panelTop.Controls.Add(groupTime);
var colorMap = new Dictionary<string, Color>
{
{ "ID", Color.LightSteelBlue },
{ "LineNo", Color.LightCyan },
{ "RouteNo", Color.LightPink },
{ "RouteName", Color.Moccasin },
{ "RecipeName", Color.Honeydew },
{ "OrderID", Color.LavenderBlush },
{ "BatchNo", Color.Bisque },
{ "StartTime", Color.LightYellow },
{ "EndTime", Color.MistyRose },
{ "Status", Color.WhiteSmoke }
};
string[] sysInfo = { "ID", "LineNo", "RouteNo", "RouteName" };
string[] prodInfo = { "RecipeName", "OrderID", "BatchNo" };
string[] timeInfo = { "StartTime", "EndTime", "Status" };
AddToGroup(sysInfo, groupSystem, colorMap);
AddToGroup(prodInfo, groupProduction, colorMap);
AddToGroup(timeInfo, groupTime, colorMap);
this.Controls.Add(chartSplit);
this.Controls.Add(spacer);
this.Controls.Add(panelTop);
}
private Panel CreateRoundedPanel(string title, Color backColor)
{
var panel = new Panel
{
Size = new Size(110, 110),
BackColor = Color.White,
Padding = new Padding(5),
Margin = new Padding(5)
};
panel.Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, panel.Width,
panel.Height, 20, 20));
//panel.Paint += (s, e) =>
//{
// ControlPaint.DrawBorder(e.Graphics, panel.ClientRectangle,
Color.LightGray, ButtonBorderStyle.Solid);
//};
var label = new LabelControl
{
Dock = DockStyle.Fill,
Appearance = {
TextOptions = {
HAlignment = DevExpress.Utils.HorzAlignment.Center,
VAlignment = DevExpress.Utils.VertAlignment.Center
},
Font = new Font("Segoe UI", 10F, FontStyle.Bold),
BackColor = backColor
},
AutoSizeMode = LabelAutoSizeMode.None,
Text = $"{title}\n--",
Padding = new Padding(5)
};
panel.Controls.Add(label);
return panel;
}
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn(int nLeftRect, int nTopRect,
int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse);
private void LoadDashboard()
{
valueLabels["ID"].Text = $"ID\n{_data.ID}";
valueLabels["LineNo"].Text = $"LineNo\n{_data.LineNo}";
valueLabels["RouteNo"].Text = $"RouteNo\n{_data.RouteNo}";
valueLabels["RouteName"].Text = $"RouteName\n{_data.RouteName}";
valueLabels["RecipeName"].Text = $"Recipe\n{_data.RecipeName}";
valueLabels["OrderID"].Text = $"OrderID\n{_data.OrderID}";
valueLabels["BatchNo"].Text = $"Batch\n{_data.BatchNo}";
valueLabels["StartTime"].Text = $"Start\n{_data.StartTimeLDT:HH:mm:ss}";
valueLabels["EndTime"].Text = $"End\n{_data.EndTimeLDT:HH:mm:ss}";
var statusText = _data.Status == 1 ? "✔️ Completed" : "❌ Not Completed";
valueLabels["Status"].Text = $"Status\n{statusText}";
valueLabels["Status"].Appearance.ForeColor = (_data.Status == 1) ?
Color.ForestGreen : Color.Red;
DrawCharts();
}
private void DrawCharts()
{
chartControl1.Series.Clear();
pieChart.Series.Clear();
// Line chart: ReturnTemp, ReturnCond, FlowRate
var tempSeries = new Series("Temperature", ViewType.Spline);
var concSeries = new Series("Concentration", ViewType.Spline);
var flowSeries = new Series("Flow Rate", ViewType.Spline);
string[] steps = { "PR", "CR", "IR1", "AR", "IR2", "HWR", "FR" };
foreach (var step in steps)
{
tempSeries.Points.Add(new SeriesPoint(step,
GetDoubleValue($"{step}_ReturnTemp")));
concSeries.Points.Add(new SeriesPoint(step,
GetDoubleValue($"{step}_ReturnCond")));
flowSeries.Points.Add(new SeriesPoint(step, _data.FlowRate)); // flow
same for all
}
chartControl1.Series.AddRange(new Series[] { tempSeries, concSeries,
flowSeries });
chartControl1.Legend.Visibility = DevExpress.Utils.DefaultBoolean.True;
var pieSeries = new Series("Circulation Time", ViewType.Pie);
foreach (var step in steps)
{
DateTime? start = GetDate($"{step}_StartTime");
DateTime? stop = GetDate($"{step}_StopTime");
if (start.HasValue && stop.HasValue && stop > start)
{
double minutes = (stop.Value - start.Value).TotalMinutes;
if (minutes > 0)
pieSeries.Points.Add(new SeriesPoint(step, minutes));
}
}
pieSeries.Label.TextPattern = "{A}: {VP:P1}";
pieSeries.LegendTextPattern = "{A}: {V:0.##} min";
pieChart.Series.Add(pieSeries);
pieChart.Legend.Visibility = DevExpress.Utils.DefaultBoolean.True;
}
private double GetDoubleValue(string propertyName)
{
var prop = typeof(CIPMaster_Report).GetProperty(propertyName);
if (prop == null) return 0;
var val = prop.GetValue(_data);
return val != null ? Convert.ToDouble(val) : 0;
}
private DateTime? GetDate(string propertyName)
{
var prop = typeof(CIPMaster_Report).GetProperty(propertyName);
if (prop == null) return null;
var val = prop.GetValue(_data);
return val != null ? (DateTime?)val : null;
}
private GroupControl CreateGroup(string title)
{
return new GroupControl
{
Text = title,
BackColor = Color.White,
Size = new Size(400, 300),
AppearanceCaption = { Font = new Font("Segoe UI", 10F,
FontStyle.Bold) },
Padding = new Padding(5)
};
}
private void AddToGroup(string[] keys, GroupControl group, Dictionary<string,
Color> colorMap)
{
var layout = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
FlowDirection = FlowDirection.LeftToRight,
WrapContents = true,
AutoScroll = false
};
foreach (var key in keys)
{
var panel = CreateRoundedPanel(key, colorMap[key]);
valueLabels[key] = (LabelControl)panel.Controls[0];
panel.Margin = new Padding(5);
layout.Controls.Add(panel);
}
group.Controls.Add(layout);
}