using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Xml; using System.Xml.Serialization; using System.Xml.Schema; using System.Drawing; using Volian.Base.Library; namespace Volian.Controls.Library { [Serializable] [XmlRoot("VlnBorders")] public class VlnBorders { #region Properties private int _Rows; [XmlAttribute("Rows")] public int Rows { get { return _Rows; } set { _Rows = value; } } private int _Columns; [XmlAttribute("Columns")] public int Columns { get { return _Columns; } set { _Columns = value; } } private LinePatternArray _VerticalLines; public LinePatternArray VerticalLines { get { return _VerticalLines; } set { _VerticalLines = value; } } private LinePatternArray _HorizontalLines; public LinePatternArray HorizontalLines { get { return _HorizontalLines; } set { _HorizontalLines = value; } } #endregion #region ctor public VlnBorders() { ;} public VlnBorders(GridLinePattern defaultLinePattern, int rows, int columns) { Rows = rows; Columns = columns; HorizontalLines = new LinePatternArray(defaultLinePattern, Rows + 1, Columns); VerticalLines = new LinePatternArray(defaultLinePattern, Rows, Columns + 1); } #endregion #region SetRange - Set the border styles over a range of cells public void SetRange(int r1, int c1, int r2, int c2, GridLinePattern top, GridLinePattern middle, GridLinePattern bottom, GridLinePattern left, GridLinePattern center, GridLinePattern right) { for (int c = c1; c <= c2; c++) { if (top != GridLinePattern.Mixed) HorizontalLines[r1, c] = top; for (int r = r1 + 1; r <= r2; r++) if (middle != GridLinePattern.Mixed) HorizontalLines[r, c] = middle; if (bottom != GridLinePattern.Mixed) HorizontalLines[r2 + 1, c] = bottom; } for (int r = r1; r <= r2; r++) { if (left != GridLinePattern.Mixed) VerticalLines[r, c1] = left; for (int c = c1 + 1; c <= c2; c++) if (center != GridLinePattern.Mixed) VerticalLines[r, c] = center; if (right != GridLinePattern.Mixed) VerticalLines[r, c2 + 1] = right; } } #endregion #region Get Borders over a Range - Return Mixed if multiple values are found. public GridLinePattern RangeTopBorder(int r1, int c1, int r2, int c2) { GridLinePattern linePattern = HorizontalLines[r1, c1]; for (int c = c1; c <= c2; c++) if (linePattern != HorizontalLines[r1, c]) return GridLinePattern.Mixed; return linePattern; } public GridLinePattern RangeHorizontalBorder(int r1, int c1, int r2, int c2) { if (r1 == r2) return GridLinePattern.None; GridLinePattern linePattern = HorizontalLines[r1 + 1, c1]; for (int r = r1 + 1; r <= r2; r++) for (int c = c1; c <= c2; c++) if (linePattern != HorizontalLines[r, c]) return GridLinePattern.Mixed; return linePattern; } public GridLinePattern RangeBottomBorder(int r1, int c1, int r2, int c2) { GridLinePattern linePattern = HorizontalLines[r2 + 1, c1]; for (int c = c1; c <= c2; c++) if (linePattern != HorizontalLines[r2 + 1, c]) return GridLinePattern.Mixed; return linePattern; } public GridLinePattern RangeLeftBorder(int r1, int c1, int r2, int c2) { GridLinePattern linePattern = VerticalLines[r1, c1]; for (int r = r1; r <= r2; r++) if (linePattern != VerticalLines[r, c1]) return GridLinePattern.Mixed; return linePattern; } public GridLinePattern RangeVerticalBorder(int r1, int c1, int r2, int c2) { if (c1 == c2) return GridLinePattern.None; GridLinePattern linePattern = VerticalLines[r1, c1 + 1]; for (int c = c1 + 1; c <= c2; c++) for (int r = r1 + 1; r <= r2; r++) if (linePattern != VerticalLines[r, c]) return GridLinePattern.Mixed; return linePattern; } public GridLinePattern RangeRightBorder(int r1, int c1, int r2, int c2) { GridLinePattern linePattern = VerticalLines[r1, c2 + 1]; for (int r = r1; r <= r2; r++) if (linePattern != VerticalLines[r, c2 + 1]) return GridLinePattern.Mixed; return linePattern; } #endregion #region Insert and Remove Rows and Columns public void InsertRow(int row) { HorizontalLines.InsertRow(row); VerticalLines.InsertRow(row); } public void InsertRows(int row, int count) { HorizontalLines.InsertRows(row, count); VerticalLines.InsertRows(row, count); } public void DeleteRow(int row) { HorizontalLines.DeleteRow(row); VerticalLines.DeleteRow(row); } public void DeleteRows(int row, int count) { HorizontalLines.DeleteRows(row, count); VerticalLines.DeleteRows(row, count); } public void InsertColumn(int column) { HorizontalLines.InsertColumn(column); VerticalLines.InsertColumn(column); } public void InsertColumns(int column, int count) { HorizontalLines.InsertColumns(column, count); VerticalLines.InsertColumns(column, count); } public void DeleteColumn(int column) { HorizontalLines.DeleteColumn(column); VerticalLines.DeleteColumn(column); } public void DeleteColumns(int column, int count) { HorizontalLines.DeleteColumns(column, count); VerticalLines.DeleteColumns(column, count); } #endregion #region Serialize public string ConvertToString() { return GenericSerializer.StringSerialize(this); } public override string ToString() { return "Volian Custom Borders"; } public static VlnBorders Get(string xml) { return GenericSerializer.StringDeserialize(xml); } #endregion #region Line Pattern Static Methods public static int LineWidth(GridLinePattern linePattern) { switch (linePattern) { case GridLinePattern.Double: case GridLinePattern.Thick: return 3; case GridLinePattern.None: case GridLinePattern.Single: case GridLinePattern.Dotted: case GridLinePattern.Dashed: case GridLinePattern.Mixed: default: return 1; } } public static int LineWidth0(GridLinePattern linePattern) { switch (linePattern) { case GridLinePattern.None: return 0; case GridLinePattern.Double: case GridLinePattern.Thick: return 3; case GridLinePattern.Single: case GridLinePattern.Dotted: case GridLinePattern.Dashed: case GridLinePattern.Mixed: default: return 1; } } public static Pen LinePen(GridLinePattern linePattern, Color foreColor) { Pen pn = new Pen(foreColor, 1); switch (linePattern) { case GridLinePattern.None: pn.Width = 0; break; case GridLinePattern.Thick: pn.Width = 3; break; case GridLinePattern.Dotted: pn.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; float[] patternDot = { 1, 2 }; pn.DashPattern = patternDot; break; case GridLinePattern.Dashed: pn.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; float[] patternDash = { 6, 6 }; pn.DashPattern = patternDash; break; case GridLinePattern.Mixed: pn.Color = Color.LightGray; break; case GridLinePattern.Double: case GridLinePattern.Single: default: break; } return pn; } #endregion #region checkborderarrays // C2018-031 Adjust the Horizontal and Vertical cell border arrays if needed public void CheckAndFixBorderArraySize(int grdRows, int grdCols, GridLinePattern defaultLinePattern) { if (HorizontalLines.Columns != grdCols || HorizontalLines.Rows != grdRows + 1) HorizontalLines = new LinePatternArray(defaultLinePattern, grdRows + 1, grdCols, HorizontalLines.Lines); if (VerticalLines.Columns != grdCols + 1 || VerticalLines.Rows != grdRows) VerticalLines = new LinePatternArray(defaultLinePattern, grdRows, grdCols + 1, VerticalLines.Lines); } #endregion } [Serializable] public class LinePatternArray { #region Properties protected static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private int _Rows; [XmlAttribute("Rows")] public int Rows { get { return _Rows; } set { _Rows = value; } } private int _Columns; [XmlAttribute("Columns")] public int Columns { get { return _Columns; } set { _Columns = value; } } private GridLinePattern[] _Lines; public GridLinePattern[] Lines { get { return _Lines; } set { _Lines = value; } } #endregion #region ctor public LinePatternArray() { ;} public LinePatternArray(GridLinePattern defaultLinePattern, int rows, int columns) { Rows = rows; Columns = columns; Lines = new GridLinePattern[rows * columns]; for (int r = 0; r < Rows; r++) for (int c = 0; c < Columns; c++) Lines[r * Columns + c] = defaultLinePattern; } // C2018-031 used to automatically adjust the cell border arrays public LinePatternArray(GridLinePattern defaultLinePattern, int rows, int columns, GridLinePattern[] lnsAry) { Rows = rows; Columns = columns; Lines = new GridLinePattern[rows * columns]; for (int r = 0; r < Rows; r++) for (int c = 0; c < Columns; c++) { int idx = r * Columns + c; if (idx < lnsAry.Length) Lines[idx] = lnsAry[idx]; else Lines[idx] = defaultLinePattern; } } #endregion #region Array Access public GridLinePattern this[int r, int c] { get { int indx = r * Columns + c; if (indx < Lines.Length) return Lines[r * Columns + c]; _MyLog.WarnFormat("GridLinePattern: Lines Array Access out-of-bounds ({0}, {1}) within ({2}, {3})", r, c, Rows, Columns); return GridLinePattern.Single; } set { Lines[r * Columns + c] = value; } } #endregion #region Insert and Delete Rows and Columns public void InsertRow(int row) { InsertRows(row, 1); } public void InsertRows(int row, int count) { // Create a new Array of the correct size GridLinePattern[] newLines = new GridLinePattern[(Rows + count) * Columns]; int newRows = Rows + count; for (int r = 0; r < newRows; r++) { int rSrc = r < row ? r : r > row + count ? r - count : row; if (rSrc > Rows - 1) rSrc = Rows - 1; for (int c = 0; c < Columns; c++) { newLines[r * Columns + c] = Lines[rSrc * Columns + c]; } } Lines = newLines; Rows = newRows; } public void DeleteRow(int row) { DeleteRows(row, 1); } public void DeleteRows(int row, int count) { GridLinePattern[] newLines = new GridLinePattern[(Rows - count) * Columns]; int newRows = Rows - count; for (int r = 0; r < newRows; r++) { int rSrc = r < row ? r : r + count; for (int c = 0; c < Columns; c++) { newLines[r * Columns + c] = Lines[rSrc * Columns + c]; } } Lines = newLines; Rows = newRows; } public void InsertColumn(int column) { InsertColumns(column, 1); } public void InsertColumns(int column, int count) { // Create a new Array of the correct size GridLinePattern[] newLines = new GridLinePattern[Rows * (Columns + count)]; int newColumns = Columns + count; for (int r = 0; r < Rows; r++) { for (int c = 0; c < newColumns; c++) { int cSrc = c < column ? c : c > column + count ? c - count : column; newLines[r * newColumns + c] = Lines[r * Columns + cSrc]; } } Lines = newLines; Columns = newColumns; } public void DeleteColumn(int column) { DeleteColumns(column, 1); } public void DeleteColumns(int column, int count) { GridLinePattern[] newLines = new GridLinePattern[Rows * (Columns - count)]; int newColumns = Columns - count; for (int r = 0; r < Rows; r++) { for (int c = 0; c < newColumns; c++) { int cSrc = c < column ? c : c + count; newLines[r * newColumns + c] = Lines[r * Columns + cSrc]; } } Lines = newLines; Columns = newColumns; } #endregion } public enum GridLinePattern : int { Unknown = -1, None = 0, Single = 1, Double = 2, Thick = 3, Dotted = 4, Dashed = 5, Mixed = 6 } }