using DevExpress.Utils; using DevExpress.XtraCharts; using OTSCommon.DBOperate.Model; using OTSIncAReportApp; using OTSIncAReportApp._1_UI.Control_DEVCharts; using OTSIncAReportApp.DataOperation.DataAccess; using OTSIncAReportApp.OTSRstMgrFunction; using OTSIncAReportApp.OTSSampleReportInfo; using OTSIncAReportApp.SysMgrTools; using OTSIncAReportGraph.Class; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace OTSIncAReportGrids { /// /// 成分分布表 颗粒成份分布表 /// public partial class CompositionDistributionGrid : UserControl { #region settings / fields // Internationalization Language lan; Hashtable table; // measurement results ResultFile result = null; OTSIncAReportApp.OTSSampleReportInfo.ReportCondition source; OTSIncAReportApp.frmReportApp m_ReportApp; frmReportConditionChoose m_condition; List list_gridheight = new List(); //List list_table_data = new List(); //List list_table_size = new List(); //List list_table_Point = new List(); //List list_fileName = new List(); List list_table_data = new List(); List list_table_size = new List(); List list_table_Point = new List(); List list_fileName = new List(); int DataNumber = 0; // current dataset index List list_ComboBox = new List(); List list_ChartControl = new List(); int gridwidth = 0; int gridhigh = 0; int GridPosition = 0; int chartposition = 0; int indexGraphicType = 0; string GraphicType = "柱状图"; // constants for column names used repeatedly private static readonly string ColRowId = "rowid"; private static readonly string ColTypeName = "TypeName"; private static readonly string ColTypeColor = "TypeColor"; private static readonly string ColCount = "con"; private static readonly string ColAreaRadio = "AreaRadio"; private static readonly string ColAvg = "av"; private static readonly string ColMax = "max"; // list of possible chart types for combo boxes private static readonly string[] ChartTypes = new string[] { "柱状图","折线图","饼图","圆环图","气泡图","簇状条形图","堆积条形图","瀑布图", "3D柱状图","3D圆环图","3D饼图","3D折线图","3D百分比堆积条形图","3D漏斗图", "3DManhattan 条形图","3D堆积条形图","3D阶梯线图" }; #endregion #region constructor / initialization public CompositionDistributionGrid(OTSIncAReportApp.frmReportApp ReportApp) { m_ReportApp = ReportApp ?? throw new ArgumentNullException(nameof(ReportApp)); result = m_ReportApp.m_rstDataMgr.ResultFilesList[m_ReportApp.m_rstDataMgr.GetWorkingResultId()]; source = m_ReportApp.m_conditionChoose.m_conditionData; m_condition = ReportApp.m_conditionChoose; InitializeComponent(); // internationalization lan = new Language(this); table = lan.GetNameTable(this.Name); } #endregion #region grid/chart building /// /// Primary method to bind one data source into a grid and optionally create chart controls. /// Refactored for clarity and reuse. /// public void BindDataGridView(string path, int num, string filename) { if (string.IsNullOrWhiteSpace(path)) return; // load translation strings once string str1 = table["str1"]?.ToString() ?? "No."; string str2 = table["str2"]?.ToString() ?? string.Empty; string str3 = table["str3"]?.ToString() ?? "Area"; string str4 = table["str4"]?.ToString() ?? "Avg"; string str5 = table["str5"]?.ToString() ?? string.Empty; string str6 = table["str6"]?.ToString() ?? "Max"; string str7 = table["str7"]?.ToString() ?? "Max"; string str8 = table["str8"]?.ToString() ?? "Name"; string str9 = table["str9"]?.ToString() ?? "Color"; string str10 = table["str10"]?.ToString() ?? "Count"; string str11 = table["str11"]?.ToString() ?? string.Empty; string str13 = table["str13"]?.ToString() ?? "Area%"; // prepare data access objects var particledata = new ParticleData(path); FieldData fielddata = new FieldData(path); // Determine diameter column based on settings string sizeMethod = m_ReportApp.m_conditionChoose.m_conditionData.GetPropItemDisplayValueByPropItemName(OTS_REPORT_PROP_GRID_ITEMS.SIZE_CAL_METHOD_TYPE).ToString(); string po; switch (sizeMethod) { case "DMAX": po = "DMAX"; break; case "DMIN": po = "DMIN"; break; case "FERET": po = "DFERET"; break; case "ECD": po = "Area"; break; default: po = "Area"; break; } // compute total area used in percentage calculation double totalArea = ComputeTotalArea(result, fielddata); // fetch data table DataTable dt = particledata.GetParticleStatisticDataListByIncA(po) ?? new DataTable(); // create and set up grid var gridView = new OTSGridView(); CreateGridColumns(gridView, str1, str8, str9, str10, str13, sizeMethod, str3, str4, str6, str7); gridView.MergeColumnNames.Add(filename); gridView.AddSpanHeader(1, gridView.Columns.Count - 1, filename); // populate rows for TypeId >=100 (custom types) and for predefined types TypeId <=100 PopulateGridRows(gridView, dt, totalArea, sizeMethod, filename, true); PopulateGridRows(gridView, dt, totalArea, sizeMethod, filename, false); gridView.Name = "gridView" + num.ToString(); Point point = SetDataGridViewStyle(gridView); list_table_Point.Add(point); gridView.Location = new Point(point.X, point.Y + (DataNumber * 300)); AddSumRow(gridView); panel1.Controls.Add(gridView); list_table_data.Add(dt); list_fileName.Add(filename); } private double ComputeTotalArea(ResultFile resultFile, FieldData fielddata) { try { if (resultFile == null || fielddata == null) return 0.0; double scanFieldSize = resultFile.GetScanFieldSizeX(); double wide = resultFile.GetImageWidth(); double high = resultFile.GetImageHeight(); int filedCount = fielddata.GetFiledCount(); double pixelSize = scanFieldSize / wide; // total scanned area = per-field width*height * number of fields (in OTS coordinates) // in original code totalArea = high * pixelSize * wide * pixelSize * filedCount; return high * pixelSize * wide * pixelSize * filedCount; } catch (Exception ex) { Debug.WriteLine("ComputeTotalArea failed: " + ex); return 0.0; } } private void CreateGridColumns(OTSGridView gridView, string headerRowId, string headerTypeName, string headerTypeColor, string headerCount, string headerAreaPct, string sizeMethod, string headerArea, string headerAvg, string headerMaxAlt, string headerMax) { gridView.Columns.Clear(); gridView.Columns.Add(ColRowId, headerRowId); gridView.Columns.Add(ColTypeName, headerTypeName); gridView.Columns.Add(ColTypeColor, headerTypeColor); gridView.Columns.Add(ColCount, headerCount); gridView.Columns.Add(ColAreaRadio, headerAreaPct); if (sizeMethod == "ECD") { gridView.Columns.Add(ColAvg, headerArea); gridView.Columns.Add(ColMax, headerMaxAlt); } else { gridView.Columns.Add(ColAvg, headerAvg); gridView.Columns.Add(ColMax, headerMax); } } private void PopulateGridRows(OTSGridView gridView, DataTable dt, double totalArea, string sizeMethod, string filename, bool customTypesFirst) { if (dt == null || gridView == null) return; // When customTypesFirst == true, process TypeId >= 100 (original code) for (int i = 0; i < dt.Rows.Count; i++) { if (customTypesFirst) { if (Convert.ToInt32(dt.Rows[i]["TypeId"]) < 100) continue; } else { if (Convert.ToInt32(dt.Rows[i]["TypeId"]) >= 100) continue; } int addRowIndex = gridView.Rows.Add(); gridView.Rows[addRowIndex].Tag = "Statistics"; gridView.Rows[addRowIndex].Cells[0].Value = addRowIndex + 1; for (int k = 1; k < gridView.ColumnCount; k++) { var colName = gridView.Columns[k].Name; if (string.Equals(colName, ColTypeColor, StringComparison.OrdinalIgnoreCase) && dt.Rows[i]["TypeColor"] != DBNull.Value && dt.Rows[i]["TypeColor"].ToString() != "") { string color = dt.Rows[i]["TypeColor"].ToString(); if (!color.Contains("#")) color = "#" + color; try { gridView.Rows[addRowIndex].Cells[k].Style.BackColor = DrawFunction.colorHx16toRGB(color); } catch { gridView.Rows[addRowIndex].Cells[k].Style.BackColor = Color.Black; } } else if (string.Equals(colName, ColAvg, StringComparison.OrdinalIgnoreCase) || string.Equals(colName, ColMax, StringComparison.OrdinalIgnoreCase)) { double value = 0; double.TryParse(dt.Rows[i][gridView.Columns[k].Name].ToString(), out value); if (sizeMethod == "ECD") { // value interpreted as area -> convert to diameter double area = value; gridView.Rows[addRowIndex].Cells[k].Value = Math.Round(Math.Sqrt(area / Math.PI) * 2, 2); } else { gridView.Rows[addRowIndex].Cells[k].Value = Math.Round(value , 2); } gridView.Rows[addRowIndex].Cells[k].Style.BackColor = Color.Azure; } else if (string.Equals(colName, ColAreaRadio, StringComparison.OrdinalIgnoreCase)) { if (totalArea == 0) { gridView.Rows[addRowIndex].Cells[k].Value = 0; } else { double areaVal = 0; double.TryParse(dt.Rows[i]["Area"].ToString(), out areaVal); gridView.Rows[addRowIndex].Cells[k].Value = Math.Round(areaVal * 100 / totalArea, customTypesFirst ? 3 : 5); } gridView.Rows[addRowIndex].Cells[k].Style.BackColor = Color.Azure; } else { gridView.Rows[addRowIndex].Cells[k].Value = dt.Rows[i][gridView.Columns[k].Name]; gridView.Rows[addRowIndex].Cells[k].Style.BackColor = Color.Azure; } } } } void AddSumRow(OTSGridView gridView) { if (gridView == null || gridView.Rows == null || gridView.Rows.Count == 0) return; int sumRowIndex = gridView.Rows.Add(); gridView.Rows[sumRowIndex].Tag = "Sum"; gridView.Rows[sumRowIndex].Cells[1].Value = "Sum"; gridView.Refresh(); long totalCount = 0; double totalArea = 0.0; for (int j = 0; j < gridView.Rows.Count - 1; j++) { if (gridView.Rows[j].Tag == null) continue; try { var cntObj = gridView.Rows[j].Cells[3].Value; if (cntObj != null && long.TryParse(cntObj.ToString(), out long cntVal)) totalCount += cntVal; var areaObj = gridView.Rows[j].Cells[4].Value; if (areaObj != null && double.TryParse(areaObj.ToString(), out double areaVal)) totalArea += areaVal; } catch { /* ignore malformed rows */ } } // assign sums gridView.Rows[sumRowIndex].Cells[3].Value = totalCount; gridView.Rows[sumRowIndex].Cells[4].Value = totalArea; gridView.Rows[sumRowIndex].Height = gridView.Rows[Math.Max(0, sumRowIndex - 1)].Height; for (int j = 1; j < gridView.Columns.Count; j++) { gridView.Rows[sumRowIndex].DefaultCellStyle.BackColor = Color.Azure; } //gridView.Rows[sumRowIndex].Height = 30; gridView.Size = new System.Drawing.Size(gridView.ColumnCount * 100 + 60, gridView.RowCount * 30); } private Point SetDataGridViewStyle(OTSGridView gridView) { // user can't change header height gridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; // user can't change row height gridView.AllowUserToResizeRows = false; gridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; var centeredStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }; gridView.DefaultCellStyle = centeredStyle; gridView.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; gridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText; gridView.Columns[0].Width = 40; gridView.Columns[1].Width = 200; gridView.Columns[0].Resizable = DataGridViewTriState.False; gridView.AllowUserToAddRows = false; gridView.AllowUserToDeleteRows = false; gridView.AllowUserToResizeRows = false; gridView.BackgroundColor = System.Drawing.SystemColors.ButtonHighlight; gridView.RowHeadersVisible = false; gridView.RowHeadersWidth = 40; gridView.RowTemplate.Height = 30; int gridViewHeight = 0; for (int i = 0; i < gridView.Rows.Count; i++) { gridViewHeight= gridViewHeight+ gridView.Rows[i].Height; } gridView.Size = new System.Drawing.Size(gridView.ColumnCount * 100 + 60, gridViewHeight); //gridView.Size = new System.Drawing.Size(gridView.ColumnCount * 100 + 60, gridView.RowCount * 30); int gridheight = gridViewHeight + 7; gridhigh = gridhigh + gridViewHeight+2; //gridwidth = gridwidth + gridView.ColumnCount * 100 + 60; chartposition = chartposition + gridView.ColumnCount * 100; GridPosition = gridView.ColumnCount * 100 + 40; list_gridheight.Add(gridheight); gridView.TabIndex = 0; gridView.ContextMenuStrip = this.contextMenuStrip1; gridView.BorderStyle = 0; gridView.ReadOnly = true; gridView.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(this.Gview_ColumnHeaderMouseClick); gridView.Sorted += new System.EventHandler(this.Gview_gz_Sorted); // set header height a bit taller for aesthetics gridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing; gridView.ColumnHeadersHeight = 40; list_table_size.Add(new Point(gridView.ColumnCount * 100 + 40, gridViewHeight+30 )); //return new Point(gridwidth - (gridView.ColumnCount * 100 + 60), gridheight + 5); return new Point(0, gridhigh- gridViewHeight-2); } #endregion #region charts public void SetGraphicType(ReportCondition sourceGridData) { if (sourceGridData == null) return; string stdId_TYPE = ""; int stdIdIndex = 0; var STDIdItm = sourceGridData.ConditionItemList.Find(s => s.iItemId == OTS_REPORT_PROP_GRID_ITEMS.GRAPHIC_TYPE); if (STDIdItm != null) { stdId_TYPE = STDIdItm.itemDisplayVal.ToString(); stdIdIndex = STDIdItm.comboDownList.IndexOf(stdId_TYPE); } indexGraphicType = stdIdIndex; GraphicType = stdId_TYPE; int high = 0; for (int i = 0; i < list_table_Point.Count; i++) { if (high < list_table_Point[i].Y) { high = list_table_Point[i].Y; } } for (int i = 0; i < list_table_data.Count; i++) { DataNumber = i; Graphics(list_table_data[i], list_fileName[i], stdId_TYPE, list_table_size[i], list_table_Point[i], high); } } private void Graphics(DataTable data, string filename, string comboBox1Text, Point a_size, Point a_Location, int location_hig) { var chartControl1 = new ChartControl(); chartControl1.Series.Clear(); Series series = new Series(filename, ViewType.Bar); if (data != null) { for (int a = 0; a < data.Rows.Count; a++) { string name = data.Rows[a]["TypeName"].ToString(); double cnt = 0; double.TryParse(data.Rows[a]["con"].ToString(), out cnt); series.Points.Add(new SeriesPoint(name, cnt)); } } series.LabelsVisibility = DefaultBoolean.True; chartControl1.Series.Add(series); chartControl1.Legend.AlignmentVertical = LegendAlignmentVertical.Top; chartControl1.Legend.AlignmentHorizontal = LegendAlignmentHorizontal.RightOutside; chartControl1.Legend.Visibility = DevExpress.Utils.DefaultBoolean.False; chartControl1.Legend.Direction = LegendDirection.TopToBottom; chartControl1.CrosshairEnabled = DefaultBoolean.True; chartControl1.CrosshairOptions.ShowValueLine = true; chartControl1.CrosshairOptions.ShowArgumentLabels = true; DevFunctions.ChangeView2(chartControl1, comboBox1Text); chartControl1.Location = new Point(a_Location.X+ a_size.X+20, a_Location.Y + 20 + (DataNumber * 300)); chartControl1.Size = new Size(a_size.X, a_size.Y); var diagram = chartControl1.Diagram as XYDiagram; if (diagram != null) { diagram.AxisX.Title.Text = "种类"; diagram.AxisX.Title.Visibility = DevExpress.Utils.DefaultBoolean.True; diagram.AxisY.Title.Text = "数量"; diagram.AxisY.Title.Visibility = DevExpress.Utils.DefaultBoolean.True; } // prepare combo box for chart type selection (re-use ChartTypes constant) var comboBox = new ComboBox(); list_ChartControl.Add(chartControl1); list_ComboBox.Add(comboBox); comboBox.Items.AddRange(ChartTypes); comboBox.Name = Convert.ToString(list_ComboBox.Count - 1); comboBox.SelectedIndex = 0; comboBox.Location = new Point(a_Location.X + a_size.X +20+ chartControl1.Size.Width - 100, a_Location.Y + (DataNumber * 300)); comboBox.Size = new Size(100, 25); comboBox.SelectedIndexChanged += ComboBox_SelectedIndexChanged; panel1.Controls.Add(chartControl1); panel1.Controls.Add(comboBox); } private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { var comboBox = sender as ComboBox; if (comboBox == null) return; if (int.TryParse(comboBox.Name, out int idx) && idx >= 0 && idx < list_ChartControl.Count) { DevFunctions.ChangeView2(list_ChartControl[idx], comboBox.Text); } } #endregion #region events / UI actions private void CompositionDistributionGrid_Load(object sender, EventArgs e) { list_table_data.Clear(); list_table_size.Clear(); list_table_Point.Clear(); list_fileName.Clear(); int ii = 0; string sou = m_condition.m_CurrentConditions[OTS_REPORT_PROP_GRID_ITEMS.DATA_SOURCE].itemDisplayVal.ToString(); if (sou.Contains("+")) { foreach (var name in sou.Split('+')) { var resultFile = m_ReportApp.m_rstDataMgr.ResultFilesList.Find(s => s.anotherFileName == name); if (resultFile != null) { DataNumber = ii; BindDataGridView(resultFile.FilePath, list_fileName.Count, resultFile.anotherFileName); ii++; } } } else { var match = m_ReportApp.m_rstDataMgr.ResultFilesList.FirstOrDefault(r => r.anotherFileName == sou); if (match != null) { BindDataGridView(match.FilePath, 0, match.anotherFileName); } } } private void ToolStripMenuItem1_Click(object sender, EventArgs e) { OTSGridView otv = (OTSGridView)((ContextMenuStrip)(sender as ToolStripMenuItem).Owner).SourceControl; CopyAll(otv); } private void ToolStripMenuItem2_Click(object sender, EventArgs e) { OTSGridView otv = (OTSGridView)((ContextMenuStrip)(sender as ToolStripMenuItem).Owner).SourceControl; CopySelected(otv); } public void CopySelected(OTSGridView in_ogv) { if (in_ogv == null) return; Clipboard.SetDataObject(in_ogv.GetClipboardContent()); } public void CopySelected() { var dgv = panel1.Controls.OfType().FirstOrDefault(); if (dgv == null) return; Clipboard.SetDataObject(dgv.GetClipboardContent()); } public void CopyAll(OTSGridView in_ogv) { if (in_ogv == null) return; in_ogv.SelectAll(); Clipboard.SetDataObject(in_ogv.GetClipboardContent()); } public void CopyAll() { var dgv = panel1.Controls.OfType().FirstOrDefault(); if (dgv == null) return; dgv.SelectAll(); Clipboard.SetDataObject(dgv.GetClipboardContent()); } private void ToolStripMenuItem3_Click(object sender, EventArgs e) { // remove only OTSGridView controls var toRemove = panel1.Controls.OfType().ToArray(); foreach (var g in toRemove) panel1.Controls.Remove(g); list_table_data.Clear(); list_table_size.Clear(); list_table_Point.Clear(); list_fileName.Clear(); string sou = source.GetPropItemDisplayValueByPropItemName(OTS_REPORT_PROP_GRID_ITEMS.DATA_SOURCE).ToString(); if (sou.Contains("+")) { int ii = 0; foreach (var name in sou.Split('+')) { var resultFile = m_ReportApp.m_rstDataMgr.ResultFilesList.Find(s => s.anotherFileName == name); if (resultFile != null) { DataNumber = ii; BindDataGridView(resultFile.FilePath, list_fileName.Count, resultFile.anotherFileName); ii++; } } } else { var match = m_ReportApp.m_rstDataMgr.ResultFilesList[m_ReportApp.m_rstDataMgr.GetWorkingResultId()]; BindDataGridView(match.FilePath, 0, match.anotherFileName); } } void Gview_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { var grid = sender as OTSGridView; if (grid == null || grid.Rows == null || grid.Rows.Count == 0) return; AddSumRow(grid); } private void Gview_gz_Sorted(object sender, EventArgs e) { var grid = sender as OTSGridView; if (grid == null || grid.Rows == null || grid.Rows.Count == 0) return; for (int i = 0; i < grid.Rows.Count; i++) { if (grid.Rows[i].Tag != null && grid.Rows[i].Tag.ToString() == "Sum") { grid.Rows.RemoveAt(i); break; } } grid.Refresh(); for (int i = 0; i < grid.Rows.Count; i++) { grid.Rows[i].Cells[0].Value = (i + 1).ToString(); } } #endregion } }