using System; using System.ComponentModel; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Windows.Forms; using System.Drawing; using C1.Win.C1FlexGrid; namespace Volian.Controls.Library { public delegate void BorderSelectionPanelEvent(object sender, EventArgs args); public partial class BorderSelectionPanel : Panel { #region Events public event BorderSelectionPanelEvent BordersChanged; private void OnBordersChanged(object sender, EventArgs args) { if (BordersChanged != null) BordersChanged(sender, args); } #endregion #region Properties private bool _HasRows = true; public bool HasRows { get { return _HasRows; } set { _HasRows = value; if (!value) _InsideHorizontalBorder = GridLinePattern.None; } } private bool _HasColumns = true; public bool HasColumns { get { return _HasColumns; } set { _HasColumns = value; if (!value) _InsideVerticalBorder = GridLinePattern.None; } } private GridLinePattern _SelectedBorder = GridLinePattern.Single; internal GridLinePattern SelectedBorder { get { return _SelectedBorder; } set { _SelectedBorder = value; } } private GridLinePattern _TopBorder = GridLinePattern.Single; internal GridLinePattern TopBorder { get { return _TopBorder; } set { _TopBorder = _TopBorder == value ? GridLinePattern.None : value; Redraw(); } } private GridLinePattern _BottomBorder = GridLinePattern.Single; internal GridLinePattern BottomBorder { get { return _BottomBorder; } set { _BottomBorder = _BottomBorder == value ? GridLinePattern.None : value; Redraw(); } } private GridLinePattern _LeftBorder = GridLinePattern.Single; internal GridLinePattern LeftBorder { get { return _LeftBorder; } set { _LeftBorder = _LeftBorder == value ? GridLinePattern.None : value; ; Redraw(); } } private GridLinePattern _RightBorder = GridLinePattern.Single; internal GridLinePattern RightBorder { get { return _RightBorder; } set { _RightBorder = _RightBorder == value ? GridLinePattern.None : value; Redraw(); } } private GridLinePattern _InsideVerticalBorder = GridLinePattern.Single; internal GridLinePattern InsideVerticalBorder { get { return _InsideVerticalBorder; } set { _InsideVerticalBorder = _InsideVerticalBorder == value ? GridLinePattern.None : value; Redraw(); } } private GridLinePattern _InsideHorizontalBorder = GridLinePattern.Single; internal GridLinePattern InsideHorizontalBorder { get { return _InsideHorizontalBorder; } set { _InsideHorizontalBorder = _InsideHorizontalBorder == value ? GridLinePattern.None : value; Redraw(); } } public GridLinePattern OutlineBorder { set { _TopBorder = _BottomBorder = _LeftBorder = _RightBorder = value; Redraw(); } } public GridLinePattern InsideBorders { set { _InsideHorizontalBorder = _InsideVerticalBorder = value; Redraw(); } } public GridLinePattern AllBorders { set { _InsideHorizontalBorder = _InsideVerticalBorder = _TopBorder = _BottomBorder = _LeftBorder = _RightBorder = value; Redraw(); } } /// /// Refresh Borders and raise an event /// private void Redraw() { Invalidate(); OnBordersChanged(this, new EventArgs()); } #endregion #region Initialize Borders public void InitializeBorder(GridLinePattern linePattern) { _InsideHorizontalBorder = _InsideVerticalBorder = _TopBorder = _BottomBorder = _LeftBorder = _RightBorder = linePattern; HasRows = true; HasColumns = true; Invalidate(); } public void InitializeBorder(GridLinePattern linePattern, bool hasRows, bool hasColumns) { _InsideHorizontalBorder = _InsideVerticalBorder = _TopBorder = _BottomBorder = _LeftBorder = _RightBorder = linePattern; HasRows = hasRows; HasColumns = hasColumns; Invalidate(); } public void InitializeBorder(GridLinePattern linePattern, int rows, int columns) { _InsideHorizontalBorder = _InsideVerticalBorder = _TopBorder = _BottomBorder = _LeftBorder = _RightBorder = linePattern; HasRows = rows > 0; HasColumns = columns > 0; Invalidate(); } public void InitializeBorder(VlnBorders myBorders, int r1, int c1, int r2, int c2) { _TopBorder = myBorders.RangeTopBorder(r1, c1, r2, c2); _InsideHorizontalBorder = myBorders.RangeHorizontalBorder(r1, c1, r2, c2); _BottomBorder = myBorders.RangeBottomBorder(r1, c1, r2, c2); _LeftBorder = myBorders.RangeLeftBorder(r1, c1, r2, c2); _InsideVerticalBorder = myBorders.RangeVerticalBorder(r1, c1, r2, c2); _RightBorder = myBorders.RangeRightBorder(r1, c1, r2, c2); HasRows = r2 > r1; HasColumns = c2 > c1; Invalidate(); } public void InitializeBorder(VlnFlexGrid myFlexGrid, CellRange myRange) { //if (myRange.r1 == 0 && myRange.c1 == 0 && myRange.r2 == 2 && myRange.c2 == 2) //Console.WriteLine("here"); _TopBorder = GridLinePattern.Unknown; _InsideHorizontalBorder = GridLinePattern.Unknown; _BottomBorder = GridLinePattern.Unknown; _LeftBorder = GridLinePattern.Unknown; _InsideVerticalBorder = GridLinePattern.Unknown; _RightBorder = GridLinePattern.Unknown; for (int r = myRange.r1; r <= myRange.r2; r++) for (int c = myRange.c1; c <= myRange.c2; c++) { CellRange cr = myFlexGrid.GetMergedRange(r, c); if (r == myRange.r1) // Top Border _TopBorder = CombinePattern(_TopBorder, myFlexGrid.MyBorders.HorizontalLines[cr.r1, cr.c1]); if (c == myRange.c1) // Left Border _LeftBorder = CombinePattern(_LeftBorder, myFlexGrid.MyBorders.VerticalLines[cr.r1, cr.c1]); if (r == myRange.r2) // Bottom Border _BottomBorder = CombinePattern(_BottomBorder, myFlexGrid.MyBorders.HorizontalLines[cr.r2+1, cr.c2]); if (c == myRange.c2) // Right Border _RightBorder = CombinePattern(_RightBorder, myFlexGrid.MyBorders.VerticalLines[cr.r2, cr.c2+1]); if (r == cr.r1 && c == cr.c1) // Look for inside lines { if (cr.r1 > myRange.r1 && cr.r1 < myRange.r2) // Inside Horizontal Top _InsideHorizontalBorder = CombinePattern(_InsideHorizontalBorder, myFlexGrid.MyBorders.HorizontalLines[cr.r1, cr.c1]); if (cr.r2+1 > myRange.r1 && cr.r2 < myRange.r2) // Inside Horizontal Bottom _InsideHorizontalBorder = CombinePattern(_InsideHorizontalBorder, myFlexGrid.MyBorders.HorizontalLines[cr.r2 +1, cr.c2]); if (cr.c1 > myRange.c1 && cr.c1 < myRange.c2) // Inside Vertical Left _InsideVerticalBorder = CombinePattern(_InsideVerticalBorder, myFlexGrid.MyBorders.VerticalLines[cr.r1, cr.c1]); if (cr.c2+1 > myRange.c1 && cr.c2 < myRange.c2) // Inside Vertical Right _InsideVerticalBorder = CombinePattern(_InsideVerticalBorder, myFlexGrid.MyBorders.VerticalLines[cr.r2, cr.c2 + 1]); } c = cr.c2;//Skip to the end of the merged cells } HasRows = (_InsideHorizontalBorder != GridLinePattern.Unknown); if (!HasRows) _InsideHorizontalBorder = GridLinePattern.None; HasColumns = (_InsideVerticalBorder != GridLinePattern.Unknown); if (!HasColumns) _InsideVerticalBorder = GridLinePattern.None; Invalidate(); } private GridLinePattern CombinePattern(GridLinePattern oldPattern, GridLinePattern newPattern) { if (oldPattern == GridLinePattern.Unknown) return newPattern; if (oldPattern == newPattern) return oldPattern; return GridLinePattern.Mixed; } #endregion #region ctor public BorderSelectionPanel() { InitializeComponent(); this.Paint += new PaintEventHandler(BorderSelectionPanel_Paint); this.MouseDown += new MouseEventHandler(BorderSelectionPanel_MouseDown); } public BorderSelectionPanel(IContainer container) { container.Add(this); InitializeComponent(); this.Paint += new PaintEventHandler(BorderSelectionPanel_Paint); this.MouseDown += new MouseEventHandler(BorderSelectionPanel_MouseDown); } #endregion #region Event Handlers private void BorderSelectionPanel_MouseDown(object sender, MouseEventArgs e) { if (e.X < 20) LeftBorder = SelectedBorder; else if (e.X > Width - 20) RightBorder = SelectedBorder; if (e.Y < 20) TopBorder = SelectedBorder; else if (e.Y > Height - 20) BottomBorder = SelectedBorder; int dx = Math.Abs(e.X - Width / 2); int dy = Math.Abs(e.Y - Height / 2); if (HasRows && dy < 10) InsideHorizontalBorder = SelectedBorder; if (HasColumns && dx < 10) InsideVerticalBorder = SelectedBorder; } private void BorderSelectionPanel_Paint(object sender, PaintEventArgs e) { int margin = 10; int x1 = margin; int y1 = margin; int x2 = Width - margin - 1; int y2 = Height - margin - 1; int w2 = Width - 1; int h2 = Height - 1; int w1 = Width - 2 * margin - 1; int h1 = Height - 2 * margin - 1; int offset = 4; DrawBackground(e, x1, y1, x2, y2, w1, h1, w2, h2, offset, HasRows, HasColumns); DrawBorder(e, x1, y1, x2, y2); } private static void DrawBackground(PaintEventArgs e, int x1, int y1, int x2, int y2, int w1, int h1, int w2, int h2, int offset,bool hasRows, bool hasColumns) { e.Graphics.FillRectangle(Brushes.White, offset, offset, w2 - 2* offset, h2 - 2* offset); // Old Backgound - Shows corners //e.Graphics.DrawLine(Pens.LightBlue, x1, offset, x1, y1); //e.Graphics.DrawLine(Pens.LightBlue, x2, offset, x2, y1); //e.Graphics.DrawLine(Pens.LightBlue, x1, y2, x1, h2 - offset); //e.Graphics.DrawLine(Pens.LightBlue, x2, y2, x2, h2 - offset); //e.Graphics.DrawLine(Pens.LightBlue, offset, y1, x1, y1); //e.Graphics.DrawLine(Pens.LightBlue, x2, y1, w2 - offset, y1); //e.Graphics.DrawLine(Pens.LightBlue, offset, y2, x1, y2); //e.Graphics.DrawLine(Pens.LightBlue, x2, y2, w2 - offset, y2); // Horizontal Lines e.Graphics.DrawLine(Pens.LightBlue, offset, y1, w2 - offset, y1); if (hasRows) e.Graphics.DrawLine(Pens.LightBlue, x1 + offset, (y1 + y2) / 2, x2 - offset , (y1 + y2) / 2); e.Graphics.DrawLine(Pens.LightBlue, offset, y2, w2 - offset, y2); // Vertical Lines e.Graphics.DrawLine(Pens.LightBlue, x1, offset, x1, h2 - offset); if (hasColumns) e.Graphics.DrawLine(Pens.LightBlue, (x1 + x2) / 2, y1+offset, (x1 + x2) / 2, y2 - offset); e.Graphics.DrawLine(Pens.LightBlue, x2, offset, x2, h2 - offset); } private void DrawBorder(PaintEventArgs e, int x1, int y1, int x2, int y2) { DrawLineDown(e.Graphics, LeftBorder, x1, y1, x1, y2, TopBorder, BottomBorder); DrawLineRight(e.Graphics, BottomBorder, x1, y2, x2, y2, LeftBorder, RightBorder); DrawLineUp(e.Graphics, RightBorder, x2, y2, x2, y1, BottomBorder, TopBorder); DrawLineLeft(e.Graphics, TopBorder, x2, y1, x1, y1, RightBorder, LeftBorder); DrawLineVertical(e.Graphics, InsideVerticalBorder, (x1 + x2) / 2, y1, (x1 + x2) / 2, y2, TopBorder, BottomBorder); DrawLineHorizontal(e.Graphics, InsideHorizontalBorder, x1, (y1 + y2) / 2, x2, (y1 + y2) / 2, LeftBorder, RightBorder); } private void DrawLineDown(Graphics graphics, GridLinePattern linePattern, int x1, int y1, int x2, int y2, GridLinePattern startPattern, GridLinePattern endPattern) { if (linePattern == GridLinePattern.None) return; int dyi1 = 0;int dyi2 = 0;int dxi1 = 0;int dxi2 = 0; int dyo1 = 0;int dyo2 = 0;int dxo1 = 0;int dxo2 = 0; if (LineWidth(linePattern) == 3) { dxo2 = dxo1 = -1; dyi2 = dyo1 = LineWidth(startPattern) == 3 ? -1 : 0; dyi1 =dyo2 = LineWidth(endPattern) == 3 ? 1 : 0; dxi1 = -dxo1; dxi2 = -dxo2; dyi1 = -dyo1; dyi2 = -dyo2; if (linePattern == GridLinePattern.Thick) dyo2++; // Fix for bug in Graphics. Seems to happen when line is thick. } GridSplitLine mySplit = InsideHorizontalBorder == GridLinePattern.Double ? GridSplitLine.Inside : GridSplitLine.None; DrawTheLine(graphics, linePattern, mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); } private void DrawLineRight(Graphics graphics, GridLinePattern linePattern, int x1, int y1, int x2, int y2, GridLinePattern startPattern, GridLinePattern endPattern) { if (linePattern == GridLinePattern.None) return; int dyi1 = 0; int dyi2 = 0; int dxi1 = 0; int dxi2 = 0; int dyo1 = 0; int dyo2 = 0; int dxo1 = 0; int dxo2 = 0; if (LineWidth(linePattern) == 3) { dyo2 = dyo1 = 1; dxi2 = dxo1 = LineWidth(startPattern) == 3 ? -1 : 0; dxi1 = dxo2 = LineWidth(endPattern) == 3 ? 1 : 0; dxi1 = -dxo1;dxi2 = -dxo2;dyi1 = -dyo1;dyi2 = -dyo2; if (linePattern == GridLinePattern.Thick) dxo2++; // Fix for bug in Graphics. Seems to happen when line is thick. } GridSplitLine mySplit = InsideVerticalBorder == GridLinePattern.Double ? GridSplitLine.Inside : GridSplitLine.None; DrawTheLine(graphics, linePattern,mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); } private void DrawLineUp(Graphics graphics, GridLinePattern linePattern, int x1, int y1, int x2, int y2, GridLinePattern startPattern, GridLinePattern endPattern) { if (linePattern == GridLinePattern.None) return; int dyi1 = 0; int dyi2 = 0; int dxi1 = 0; int dxi2 = 0; int dyo1 = 0; int dyo2 = 0; int dxo1 = 0; int dxo2 = 0; if (LineWidth(linePattern) == 3) { dxo2 = dxo1 = 1; dyo1 = LineWidth(startPattern) == 3 ? 1 : 0; dyo2 = LineWidth(endPattern) == 3 ? -1 : 0; if (linePattern == GridLinePattern.Thick) dyo1++; // Fix for bug in Graphics. Seems to happen when line is thick. dxi1 = -dxo1; dxi2 = -dxo2; dyi1 = -dyo1; dyi2 = -dyo2; } GridSplitLine mySplit = InsideHorizontalBorder == GridLinePattern.Double ? GridSplitLine.Inside : GridSplitLine.None; DrawTheLine(graphics, linePattern, mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); } private void DrawLineLeft(Graphics graphics, GridLinePattern linePattern, int x1, int y1, int x2, int y2, GridLinePattern startPattern, GridLinePattern endPattern) { if (linePattern == GridLinePattern.None) return; int dyi1 = 0; int dyi2 = 0; int dxi1 = 0; int dxi2 = 0; int dyo1 = 0; int dyo2 = 0; int dxo1 = 0; int dxo2 = 0; if (LineWidth(linePattern) == 3) { dyo2 = dyo1 = -1; dxo1 = LineWidth(startPattern) == 3 ? 1 : 0; dxo2 = LineWidth(endPattern) == 3 ? -1 : 0; if (linePattern == GridLinePattern.Thick) dxo1++; // Fix for bug in Graphics. Seems to happen when line is thick. dxi1 = -dxo1; dxi2 = -dxo2; dyi1 = -dyo1; dyi2 = -dyo2; } GridSplitLine mySplit = InsideVerticalBorder == GridLinePattern.Double ? GridSplitLine.Inside : GridSplitLine.None; DrawTheLine(graphics, linePattern, mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); } private void DrawLineVertical(Graphics graphics, GridLinePattern linePattern, int x1, int y1, int x2, int y2, GridLinePattern startPattern, GridLinePattern endPattern) { if (linePattern == GridLinePattern.None) return; int dyi1 = 0; int dyi2 = 0; int dxi1 = 0; int dxi2 = 0; int dyo1 = 0; int dyo2 = 0; int dxo1 = 0; int dxo2 = 0; if (LineWidth(linePattern) == 3) { dxo2 = dxo1 = 1; dyo1 = LineWidth(startPattern) == 3 ? 1 : 0; dyo2 = LineWidth(endPattern) == 3 ? -1 : 0; if (linePattern == GridLinePattern.Thick) dyo1++; // Fix for bug in Graphics. Seems to happen when line is thick. dxi1 = -dxo1;dyi1 = dyo1;dxi2 = -dxo2;dyi2 = dyo2; } else { dyo1 = LineWidth(startPattern) == 3 ? 1 : 0; dyo2 = LineWidth(endPattern) == 3 ? -1 : 0; } GridSplitLine mySplit = InsideHorizontalBorder == GridLinePattern.Double ? GridSplitLine.Both : GridSplitLine.None; DrawTheLine(graphics, linePattern, mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); } private void DrawLineHorizontal(Graphics graphics, GridLinePattern linePattern,int x1, int y1, int x2, int y2, GridLinePattern startPattern, GridLinePattern endPattern) { if (linePattern == GridLinePattern.None) return; int dyi1 = 0; int dyi2 = 0; int dxi1 = 0; int dxi2 = 0; int dyo1 = 0; int dyo2 = 0; int dxo1 = 0; int dxo2 = 0; if (LineWidth(linePattern) == 3) { dyo2 = dyo1 = -1; dxo1 = LineWidth(startPattern) == 3 ? 1 : 0; dxo2 = LineWidth(endPattern) == 3 ? -1 : 0; if (linePattern == GridLinePattern.Thick) dxo1++; // Fix for bug in Graphics. Seems to happen when line is thick. dxi1 = dxo1;dyi1 = -dyo1;dxi2 = dxo2;dyi2 = -dyo2; } else { dxo1 = LineWidth(startPattern) == 3 ? 1 : 0; dxo2 = LineWidth(endPattern) == 3 ? -1 : 0; } GridSplitLine mySplit = InsideVerticalBorder == GridLinePattern.Double ? GridSplitLine.Both:GridSplitLine.None; DrawTheLine(graphics, linePattern,mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); } private int LineWidth(GridLinePattern linePattern) { return VlnBorders.LineWidth(linePattern); } [Flags] private enum GridSplitLine:int { None=0,Inside=1,Outside=2,Both=3 } private static void DrawTheLine(Graphics graphics, GridLinePattern linePattern, GridSplitLine mySplit, int x1, int y1, int x2, int y2,int dxi1, int dyi1, int dxi2, int dyi2, int dxo1, int dyo1, int dxo2, int dyo2) { Pen pn = VlnBorders.LinePen(linePattern,Color.Black); switch (linePattern) { case GridLinePattern.None: break; case GridLinePattern.Double: DrawDoubleLines(graphics, pn, mySplit, x1, y1, x2, y2, dxi1, dyi1, dxi2, dyi2, dxo1, dyo1, dxo2, dyo2); break; case GridLinePattern.Thick: pn.Width = 3; if (x1 == x2) // Vertical graphics.DrawLine(pn, x1, y1 + dyo1, x2, y2 + dyo2); else // Horizontal graphics.DrawLine(pn, x1 + dxo1, y1, x2 + dxo2, y2); break; case GridLinePattern.Single: case GridLinePattern.Mixed: case GridLinePattern.Dashed: case GridLinePattern.Dotted: default: graphics.DrawLine(pn, x1 + dxo1, y1 + dyo1, x2 + dxo2, y2 + dyo2); break; } } private static void DrawDoubleLines(Graphics graphics, Pen pn, GridSplitLine mySplit, int x1, int y1, int x2, int y2, int dxi1, int dyi1, int dxi2, int dyi2, int dxo1, int dyo1, int dxo2, int dyo2) { if ((mySplit & GridSplitLine.Inside) > 0) { if (x1 == x2) { int yh = (y1 + dyi1 + y2 + dyi2) / 2; int dh = y2 > y1 ? 1 : -1; graphics.DrawLine(pn, x1 + dxi1, y1 + dyi1, x2 + dxi2, yh - dh); // Inside Line graphics.DrawLine(pn, x1 + dxi1, yh + dh, x2 + dxi2, y2 + dyi2); // Inside Line } else { int xh = (x1 + dxi1 + x2 + dxi2) / 2; int dh = x2 > x1 ? 1 : -1; graphics.DrawLine(pn, x1 + dxi1, y1 + dyi1, xh - dh, y2 + dyi2); // Inside Line graphics.DrawLine(pn, xh + dh, y1 + dyi1, x2 + dxi2, y2 + dyi2); // Inside Line } } else graphics.DrawLine(pn, x1 + dxi1, y1 + dyi1, x2 + dxi2, y2 + dyi2); // Inside Line if ((mySplit & GridSplitLine.Outside) > 0) { if (x1 == x2) { int yh = (y1 + dyo1 + y2 + dyo2) / 2; int dh = y2 > y1 ? 1 : -1; graphics.DrawLine(pn, x1 + dxo1, y1 + dyo1, x2 + dxo2, yh - dh); // Outside Line graphics.DrawLine(pn, x1 + dxo1, yh + dh, x2 + dxo2, y2 + dyo2); // Outside Line } else { int xh = (x1 + dxo1 + x2 + dxo2) / 2; int dh = x2 > x1 ? 1 : -1; graphics.DrawLine(pn, x1 + dxo1, y1 + dyo1, xh - dh, y2 + dyo2); // Outside Line graphics.DrawLine(pn, xh + dh, y1 + dyo1, x2 + dxo2, y2 + dyo2); // Outside Line } } else graphics.DrawLine(pn, x1 + dxo1, y1 + dyo1, x2 + dxo2, y2 + dyo2); // Outside Line } #endregion } }