5295 lines
174 KiB
C#

using System;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Xml;
using System.IO;
using Volian.Controls.Library;
using VEPROMS.CSLA.Library;
using C1.Win.C1FlexGrid;
using C1.Win.C1SpellChecker;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using Volian.Base.Library;
using JR.Utils.GUI.Forms;
namespace Volian.Controls.Library
{
public delegate void VlnFlexGridEvent(object sender, EventArgs args);
public delegate void VlnFlexGridCursorMovementEvent(object sender, VlnFlexGridCursorMovementEventArgs args);
public delegate string VlnFlexGridPasteEvent(object sender, VlnFlexGridPasteEventArgs args);
public delegate void VlnFlexGridkeyEvent(object sender, KeyEventArgs args);
public partial class vlnPanel : Panel
{
private int _Opacity = 128;
//public int Opacity
//{
// get { return _Opacity; }
// set { _Opacity = value; }
//}
public vlnPanel()
{
InitializeComponent();
}
public vlnPanel(IContainer container)
{
container.Add(this);
InitializeComponent();
}
//protected override CreateParams CreateParams
//{
// get
// {
// CreateParams prams = base.CreateParams;
// prams.ExStyle |= 0x020; // transparent
// return prams;
// }
//}
//protected override void OnPaint(PaintEventArgs pe)
//{
// pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(_Opacity, this.BackColor)), this.ClientRectangle);
//}
}
public partial class VlnFlexGrid : C1.Win.C1FlexGrid.C1FlexGrid
{
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private bool _Disposed = false;
private static int _CountCreated = 0;
private static int _CountDisposed = 0;
private static int _CountFinalized = 0;
private static int IncrementCountCreated
{ get { return ++_CountCreated; } }
private int _CountWhenCreated = IncrementCountCreated;
public static int CountCreated
{ get { return _CountCreated; } }
public static int CountNotDisposed
{ get { return _CountCreated - _CountDisposed; } }
public static int CountNotFinalized
{ get { return _CountCreated - _CountFinalized; } }
private bool _Finalized = false;
~VlnFlexGrid()
{
if(!_Finalized) _CountFinalized++;
_Finalized = true;
}
private C1SpellChecker _SpellChecker;
public C1SpellChecker SpellChecker
{
get { return _SpellChecker; }
set { _SpellChecker = value; }
}
//public string GridStackTrace
//{
// get
// {
// string st = Volian.Base.Library.vlnStackTrace.GetStack();
// st = StripFunnyCharacters(st);
// return st;
// Console.WriteLine(st);
// return st.Replace(@"\","|");
// }
// set
// {
// ;
// }
//}
//private string StripFunnyCharacters(string st)
//{
// StringBuilder sb = new StringBuilder();
// foreach (char c in st)
// {
// if ((c < ' ' || c > 255) && !"\r\n\t".Contains(c.ToString()))
// sb.Append(string.Format("x{0:X4}", (int)c));
// else
// sb.Append(c);
// }
// return sb.ToString();
//}
private DocVersionInfo _MyDVI = null;
public DocVersionInfo MyDVI
{
get
{
ItemInfo procInfo = _MyItemInfo.MyProcedure as ItemInfo; //_MyEditItem.MyItemInfo.MyProcedure as ItemInfo;
if (procInfo == null)
_MyDVI = null;
else
_MyDVI = procInfo.ActiveParent as DocVersionInfo;
return _MyDVI;
}
}
private static UserInfo _MyUserInfo = null;
public static UserInfo MyUserInfo
{
get { return _MyUserInfo; }
set
{
_MyUserInfo = value;
GridItem.MyUserInfo = value;
}
}
// C2021-005 used by the table cell editor to pass font size information
private float _SelectedFontSize;
public float SelectedFontSize
{
get { return _SelectedFontSize; }
set
{
if (Parent is GridItem)
{
_SelectedFontSize = (float)value;
// initialize the font size dropdown
(Parent as GridItem).MyStepPanel.MyStepTabPanel.MyStepTabRibbon.SetFontSizeDropDownText(value);
_DoubleClickedCell = false;
}
}
}
public bool IsDirty
{
get
{
return IsGridChanged(this._MyItemInfo.MyContent.MyGrid.Data, this.GetXMLData(), true);
}
}
private bool IsGridChanged(string oldXml, string newXml, bool checkFormat)
{
if (this.TableCellEditor.Text.Contains("<NewID>"))
return false;
XmlDocument XdOld = new XmlDocument();
oldXml = _ReplaceTextFont.Replace(oldXml, "$1" + FontChangeFmt + "$4"); // B2021-032: use original font
XdOld.LoadXml(AdjustHeightAndWidthForDPI(oldXml));
XmlDocument XdNew = new XmlDocument();
XdNew.LoadXml(AdjustHeightAndWidthForDPI(newXml));
//check volian borders 1st
if (checkFormat && XdNew.SelectSingleNode("C1FlexGrid/Control/MyBorderDetailString").InnerText != XdOld.SelectSingleNode("C1FlexGrid/Control/MyBorderDetailString").InnerText)
return true;
//check row/col sizes 2nd
if (checkFormat && ( GetRowColSizeString(XdNew) != GetRowColSizeString(XdOld)))
return true;
//check for cell data changes 3rd
if (GetCellDataString(XdNew) != GetCellDataString(XdOld))
return true;
//check for cell format changes 4th
if (checkFormat && GetCellFormatString(XdNew) != GetCellFormatString(XdOld))
return true;
//check for text alignment changes 5th
// put check in for bug fix B2014-106
if (checkFormat && GetCellTextAlignString(XdNew) != GetCellTextAlignString(XdOld))
return true;
//check for merged cells 6th
if (GetCellMergeString(XdNew) != GetCellMergeString(XdOld))
return true;
// C2021-004 check volian shading 7th
XmlNode oldNode = XdOld.SelectSingleNode("C1FlexGrid/Control/MyShadingDetailString"); // old shading information
XmlNode newNode = XdNew.SelectSingleNode("C1FlexGrid/Control/MyShadingDetailString"); // new shading information
if ((oldNode == null || oldNode.InnerText == null) ||
checkFormat && newNode.InnerText != oldNode.InnerText)
return true;
return false;
}
private string GetRowColSizeString(XmlDocument xd)
{
string defCW = xd.SelectSingleNode("C1FlexGrid/ColumnInfo/DefaultSize").InnerText;
string defRH = xd.SelectSingleNode("C1FlexGrid/RowInfo/DefaultSize").InnerText;
int cols = ColumnCount(xd);
int rows = RowCount(xd);
List<string> rh = new List<string>();
for (int i = 0; i < rows; i++)
rh.Add(defRH);
List<string> cw = new List<string>();
for (int i = 0; i < cols; i++)
cw.Add(defCW);
XmlNodeList nlr = xd.SelectNodes("C1FlexGrid/Rows/Row");
foreach (XmlNode nr in nlr)
{
int idx = int.Parse(nr.Attributes.GetNamedItem("index").InnerText);
rh[idx] = nr.SelectSingleNode("Height").InnerText;
}
XmlNodeList nlc = xd.SelectNodes("C1FlexGrid/Columns/Column");
foreach (XmlNode nc in nlc)
{
int idx = int.Parse(nc.Attributes.GetNamedItem("index").InnerText);
cw[idx] = nc.SelectSingleNode("Width").InnerText;
}
string rhcw = "RowHeights: ";
string sep = string.Empty;
foreach (string s in rh)
{
rhcw += sep + s;
sep = ",";
}
rhcw += " - ColWidths: ";
sep = string.Empty;
foreach (string s in cw)
{
rhcw += sep + s;
sep = ",";
}
return rhcw;
}
private int ColumnCount(XmlDocument xd)
{
XmlNode xn = xd.SelectSingleNode("C1FlexGrid/ColumnInfo/Count");
int cols = 0;
if (xn != null)
cols = int.Parse(xn.InnerText);
else
{
XmlNodeList nl = xd.SelectNodes("C1FlexGrid/Columns/Column");
cols = nl.Count;
}
return cols;
}
private int RowCount(XmlDocument xd)
{
XmlNode xn = xd.SelectSingleNode("C1FlexGrid/RowInfo/Count");
int rows = 0;
if (xn != null)
rows = int.Parse(xn.InnerText);
else
{
XmlNodeList nl = xd.SelectNodes("C1FlexGrid/Rows/Row");
rows = nl.Count;
}
return rows;
}
private string GetCellDataString(XmlDocument xd)
{
int cols = ColumnCount(xd);
int rows = RowCount(xd);
List<string> datum = new List<string>();
for (int i = 0; i < rows * cols; i++)
datum.Add("|");
XmlNodeList nl = xd.SelectNodes("C1FlexGrid/Cells/Cell/Data");
string data = string.Empty;
foreach (XmlNode xn in nl)
{
RichTextBox rtb = new RichTextBox();
rtb.Rtf = xn.InnerText;
XmlAttribute xa = xn.ParentNode.Attributes.GetNamedItem("index") as XmlAttribute;
string[] rc = xa.InnerText.Split(',');
int r = int.Parse(rc[0]);
int c = int.Parse(rc[1]);
int index = r * cols + c;
datum[index] = "|" + (rtb.Text == "" ? "" : rtb.Text);
}
foreach (string s in datum)
data += s;
return data;
}
private string GetCellFormatString(XmlDocument xd)
{
int cols = ColumnCount(xd);
int rows = RowCount(xd);
List<string> datum = new List<string>();
for (int i = 0; i < rows * cols; i++)
datum.Add("|");
XmlNodeList nl = xd.SelectNodes("C1FlexGrid/Cells/Cell/Data");
string data = string.Empty;
foreach (XmlNode xn in nl)
{
RichTextBox rtb = new RichTextBox();
rtb.Rtf = xn.InnerText;
XmlAttribute xa = xn.ParentNode.Attributes.GetNamedItem("index") as XmlAttribute;
string[] rc = xa.InnerText.Split(',');
int r = int.Parse(rc[0]);
int c = int.Parse(rc[1]);
int index = r * cols + c;
datum[index] = "|" + (rtb.Text == "" ? "" : rtb.Rtf);
}
foreach (string s in datum)
data += s;
return data;
}
private string GetCellMergeString(XmlDocument xd)
{
if(xd.SelectSingleNode("C1FlexGrid/MergedRanges") == null)
return string.Empty;
return xd.SelectSingleNode("C1FlexGrid/MergedRanges").InnerXml;
}
private string GetCellTextAlignString(XmlDocument xd)
{
// Note that I could not save (and later compare) the entire Definition string
// because the xml for the old and new table was always different.
// The old xml table data would have, for example "white" for the background color, while
// the new xml table data would have "255,255,255" for the background color.
// Therefore this check is specific for only the TextAlign setting - jsj 9-30-2014
XmlNodeList nl = xd.SelectNodes("C1FlexGrid/Styles/Style/Definition");
string data = string.Empty;
foreach (XmlNode xn in nl)
{
string str = xn.InnerText;
string[] splStr = str.Split(';');
foreach (string s in splStr)
if (s.StartsWith("TextAlign:"))
data += "|" + s; // only save the TextAlign setting
}
return data;
}
private static GridCopyInfo _MyCopyInfo;
public static GridCopyInfo MyCopyInfo
{
get
{
if (_MyCopyInfo == null)
_MyCopyInfo = new GridCopyInfo();
return _MyCopyInfo;
}
}
private Color _DefaultCellBackgroundcolor;
public Color DefaultCellBackgroundcolor
{
get { return _DefaultCellBackgroundcolor; }
}
private Color _DefaultFixedBackgroundColor;
public Color DefaultFixedBackgroundColor
{
get { return _DefaultFixedBackgroundColor; }
}
public void CopyToCopiedFlexGrid(GridCopyOption myCopyOption)
{
MyCopyInfo.MyCopiedFlexGrid = new VlnFlexGrid(); //make a copy of the grid being copied
using (StringReader sr = new StringReader(this.GetXMLData()))
{
MyCopyInfo.MyCopiedFlexGrid.ReadXml(sr);
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None;
sr.Close();
}
MyCopyInfo.MyCopyOption = myCopyOption;
OnCopyOptionChanged(this, new EventArgs());
switch (MyCopyInfo.MyCopyOption)
{
case GridCopyOption.Row:
MyCopyInfo.MyCopiedCellRange = MyCopyInfo.MyCopiedFlexGrid.GetCellRange(Selection.r1, 0, Selection.r2, Cols.Count - 1);
break;
case GridCopyOption.Column:
MyCopyInfo.MyCopiedCellRange = MyCopyInfo.MyCopiedFlexGrid.GetCellRange(0, Selection.c1, Rows.Count - 1, Selection.c2);
break;
case GridCopyOption.Selection:
MyCopyInfo.MyCopiedCellRange = MyCopyInfo.MyCopiedFlexGrid.GetCellRange(Selection.r1, Selection.c1, Selection.r2, Selection.c2);
break;
default:
break;
}
}
public event VlnFlexGridEvent CopyOptionChanged;
public void OnCopyOptionChanged(object sender, EventArgs args)
{
if (CopyOptionChanged != null) CopyOptionChanged(sender, args);
}
[XmlElement("MyBorders")]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public string MyBorderDetailString
{
get
{
return MyBorders.ConvertToString();
}
set
{
if (value != null)
_MyBorders = VlnBorders.Get(value);
else
_MyBorders = null;
}
}
private VlnBorders _MyBorders;
[XmlIgnore]
public VlnBorders MyBorders
{
get
{
if (_MyBorders == null)
_MyBorders = new VlnBorders(GridLinePattern.Single, Rows.Count, Cols.Count);
return _MyBorders;
}
set { _MyBorders = value; }
}
private ItemInfo _MyItemInfo;
public ItemInfo GetMyItemInfo()
{
return _MyItemInfo;
}
//public ItemInfo MyItemInfo
//{
// get { return _MyItemInfo; }
// set { _MyItemInfo = value; }
//}
public bool TopRowHasBorder()
{
for (int c = 0; c < Cols.Count; c++)
if (MyBorders.HorizontalLines[0, c] != GridLinePattern.None) return true;
return false;
}
public void SetBorders(CellRange myRange,
GridLinePattern top, GridLinePattern middle, GridLinePattern bottom,
GridLinePattern left, GridLinePattern center, GridLinePattern right)
{
for (int r = myRange.r1; r <= myRange.r2; r++)
for (int c = myRange.c1; c <= myRange.c2; c++)
{
CellRange cr = GetMergedRange(r, c);
if (r == myRange.r1) // Top Border
if(top != GridLinePattern.Mixed) MyBorders.HorizontalLines[cr.r1, cr.c1]=top;
if (c == myRange.c1) // Left Border
if(left != GridLinePattern.Mixed) MyBorders.VerticalLines[cr.r1, cr.c1]=left;
if (r == myRange.r2) // Bottom Border
if(bottom != GridLinePattern.Mixed) MyBorders.HorizontalLines[cr.r2 + 1, cr.c2]=bottom;
if (c == myRange.c2) // Right Border
if(right != GridLinePattern.Mixed) MyBorders.VerticalLines[cr.r2, cr.c2 + 1] = right;
if (r == cr.r1 && c == cr.c1) // Look for inside lines
{
if (cr.r1 > myRange.r1 && cr.r1 <= myRange.r2) // Inside Horizontal Top
if (middle != GridLinePattern.Mixed)
{
MyBorders.HorizontalLines[cr.r1, cr.c1] = middle;
MyBorders.HorizontalLines[cr.r1, cr.c2] = middle;
}
if (cr.r2 > myRange.r1 && cr.r2 < myRange.r2) // Inside Horizontal Bottom
if(middle != GridLinePattern.Mixed) MyBorders.HorizontalLines[cr.r2 + 1, cr.c2]=middle;
if (cr.c1 > myRange.c1 && cr.c1 <= myRange.c2) // Inside Vertical Left
if (center != GridLinePattern.Mixed)
{
MyBorders.VerticalLines[cr.r1, cr.c1] = center;
MyBorders.VerticalLines[cr.r2, cr.c1] = center;
}
if (cr.c2 > myRange.c1 && cr.c2 < myRange.c2) // Inside Vertical Right
if(center != GridLinePattern.Mixed) MyBorders.VerticalLines[cr.r2, cr.c2 + 1]=center;
}
c = cr.c2;//Skip to the end of the merged cells
}
}
public void PasteBorders(int r, int c, int br, int bc)
{
MyBorders.HorizontalLines[r, c] = MyCopyInfo.MyCopiedFlexGrid.MyBorders.HorizontalLines[br,bc];
MyBorders.VerticalLines[r, c] = MyCopyInfo.MyCopiedFlexGrid.MyBorders.VerticalLines[br, bc];
MyBorders.HorizontalLines[r+1, c] = MyCopyInfo.MyCopiedFlexGrid.MyBorders.HorizontalLines[br+1, bc];
MyBorders.VerticalLines[r, c+1] = MyCopyInfo.MyCopiedFlexGrid.MyBorders.VerticalLines[br, bc+1];
}
#region Table Cell Shading
[XmlElement("MyShading")]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public string MyShadingDetailString
{
get
{
return MyShading.ConvertToString();
}
set
{
if (value != null)
_MyShading = VlnGridCellShading.Get(value);
else
_MyShading = null;
}
}
private VlnGridCellShading _MyShading = null;
[XmlIgnore]
public VlnGridCellShading MyShading
{
get
{
if (_MyShading == null || _MyShading.TableShadingInfo.CellShadingColor.Length == 0)
_MyShading = new VlnGridCellShading(Color.White, Rows.Count, Cols.Count);
return _MyShading;
}
set { _MyShading = value; }
}
public void SetShading(CellRange myRange, Color shading)
{
Console.WriteLine("SetShading toString {0}", shading.ToString());
//Console.WriteLine("SetShading toArgb {0}", shading.ToArgb());
//Console.WriteLine("SetShading Name {0}", shading.Name);
for (int r = myRange.r1; r <= myRange.r2; r++)
for (int c = myRange.c1; c <= myRange.c2; c++)
{
CellRange cr = GetMergedRange(r, c);
MyShading.TableShadingInfo[cr.r1, cr.c1] = MyShading.GetARGBstring(shading);
c = cr.c2; //Skip to the end of the merged cells
}
}
public void SetShading(CellRange myRange, ShadingOption fmtShadingOpt)
{
Console.WriteLine("SetShading toString {0}", fmtShadingOpt.ToString());
for (int r = myRange.r1; r <= myRange.r2; r++)
for (int c = myRange.c1; c <= myRange.c2; c++)
{
CellRange cr = GetMergedRange(r, c);
MyShading.TableShadingInfo[cr.r1, cr.c1] = fmtShadingOpt.GetARBGstringForTableCells();
c = cr.c2; //Skip to the end of the merged cells
}
}
public void ShowTableCellShading()
{
for (int r = 0; r < Rows.Count; r++)
for (int c = 0; c < Cols.Count; c++)
{
CellRange cr = GetMergedRange(r, c);
Color clr = MyShading.GetColor(cr.r1, cr.c1);
cr.StyleNew.BackColor = clr;
}
}
public void PasteShading(int r, int c, int sr, int sc)
{
MyShading.TableShadingInfo[r, c] = MyCopyInfo.MyCopiedFlexGrid.MyShading.TableShadingInfo[sr, sc];
}
#endregion[XmlIgnore]
public bool HasVScroll
{
get
{
return RTBAPI.HasVertScroll(this);
}
}
[XmlIgnore]
public bool HasHScroll
{
get
{
return RTBAPI.HasHorzScroll(this);
}
}
public event VlnFlexGridEvent OpenAnnotations;
public void OnOpenAnnotations(object sender, EventArgs args)
{
if (OpenAnnotations != null) OpenAnnotations(sender, args);
}
public event VlnFlexGridCursorMovementEvent CursorMovement;
internal void OnCursorMovement(object sender, VlnFlexGridCursorMovementEventArgs args)
{
if (CursorMovement != null) CursorMovement(sender, args);
}
public event VlnFlexGridPasteEvent AdjustPastedText;
internal string OnAdjustPastedText(object sender, VlnFlexGridPasteEventArgs args)
{
if (AdjustPastedText != null) return AdjustPastedText(sender, args);
return args.Text;
}
public event VlnFlexGridkeyEvent EnterKeyPressed;
public void OnEnterKeyPressed(object sender, KeyEventArgs args)
{
if (EnterKeyPressed != null) EnterKeyPressed(sender, args);
}
private TableCellEditor _tableCellEditor;
public TableCellEditor TableCellEditor
{
get { return _tableCellEditor; }
set { _tableCellEditor = value; }
}
private TableClipBoardFuncts _clpbrdCpyPste;
private int _minColSplitWidth = 10;
//private int _minRowSplitHeight = 23;
//private int _minSplitColWidth = 10;
//private int _minSplitRowHeight = 20;
private E_ViewMode _vwMode = E_ViewMode.Edit;
[XmlIgnore]
internal E_ViewMode VwMode
{
get { return _vwMode; }
set
{
_vwMode = value;
AllowEditing = _vwMode == E_ViewMode.Edit;
}
}
private bool _IsRoTable = false;
public bool IsRoTable
{
get { return _IsRoTable; }
set { _IsRoTable = value; }
}
private int _RODbId;
public int RODbId
{
get { return _RODbId; }
set { _RODbId = value; }
}
private string _ROID;
public string ROID
{
get { return _ROID; }
set { _ROID = value; }
}
private float? _DPI = null;
public float? DPI
{
get
{
if (_DPI == null)
_DPI = 120;
return _DPI;
}
set
{
if (DPI != value)
{
_DPI = value;
}
}
}
#region Grid Initialize
public VlnFlexGrid()
{
InitializeComponent();
SetupGrid(4, 3); // use a default row and column count
}
public VlnFlexGrid(int rows, int cols)
{
InitializeComponent();
SetupGrid(rows, cols);
}
public VlnFlexGrid(IContainer container)
{
container.Add(this);
InitializeComponent();
SetupGrid(1, 1);
}
public VlnFlexGrid(ContentItem ci)
{
InitializeComponent();
SetupGrid(4, 3); // use a default row and column count
_MyItemInfo = ci.MyItem.MyItemInfo;
}
//public VlnFlexGrid(IContainer container)
//{
// container.Add(this);
// InitializeComponent();
// _tableCellEditor = new TableCellEditor(this);
// _tableCellEditor.ContentsResized += new ContentsResizedEventHandler(_tableCellEditor_ContentsResized);
//}
//void _tableCellEditor_ContentsResized(object sender, ContentsResizedEventArgs e)
//{
// if (_tableCellEditor._initializingEdit) return;
// CellRange cr = GetMergedRange(Row, Col);
// int oH = cr.UserData == null? 0 : (int)cr.UserData;
// int nH = _tableCellEditor.ContentsRectangle.Height;
// int Hadj = (nH - oH);
// cr.UserData = _tableCellEditor.ContentsRectangle.Height;
// int cellHeight = GetCellHeight(Row,Col);
// int cellheightNLines = cellHeight / (Rows.DefaultSize - 3);
// int nHNLines = nH / (Rows.DefaultSize - 3);
// if (Hadj != 0)
// {
// int curHeight = (Rows[Row].Height == -1) ? Rows.DefaultSize : Rows[Row].Height;
// //if (Hadj > 0 && cellHeight <= oH)
// if (Hadj > 0 && cellheightNLines < nHNLines)
// curHeight += (Rows.DefaultSize - 3);
// if (Hadj < 0 && CanReduceRow())
// curHeight -= (Rows.DefaultSize-3);
// Rows[Row].Height = curHeight;
// AdjustGridControlSize();
// }
// //cr.UserData = _tableCellEditor.ContentsRectangle.Height;
// //int mh = GetMaxRowHeight();
// ////Rows[Row].Height = mh + 2;
// //int h = 0;
// //if (cr.r1 == cr.r2 && cr.c1 == cr.c2)
// // h = Rows[Row].Height - 2;
// //else
// //{
// // for (int r = cr.r1; r <= cr.r2; r++)
// // h += Rows[r].Height - 2;
// //}
// //Rows[Row].Height += (mh - h);
// ////AdjustGridControlSize();
//}
private int GetCellHeight(int row, int col)
{
return GetRangeHeight(GetMergedRange(row, col))-3;
}
public int GetRangeHeight(CellRange cr)
{
int height = 0;
for (int r = cr.r1; r <= cr.r2; r++)
height += (Rows[r].Height == -1) ? Rows.DefaultSize : Rows[r].Height;
return height;
}
public int GetRangeTop(CellRange cr)
{
int top = 0;
for (int r = 0; r < cr.r1; r++)
top += (Rows[r].Height == -1) ? Rows.DefaultSize : Rows[r].Height;
return top;
}
public int GetRangeWidth(CellRange cr)
{
int width = 0;
for (int c = cr.c1; c <= cr.c2; c++)
width += (Cols[c].Width == -1) ? Cols.DefaultSize : Cols[c].Width;
return width;
}
public int GetRangeLeft(CellRange cr)
{
int left = 0;
for (int c = 0; c < cr.c1; c++)
left += (Cols[c].Width == -1) ? Cols.DefaultSize : Cols[c].Width;
return left;
}
public int GetRangeRowsMin(CellRange cr)
{
int rowsMin = 1 + cr.r2 - cr.r1;
for (int c = cr.c1; c <= cr.c2; c++)
{
int rows = 0;
for (int r = cr.r1; r <= cr.r2; r++)
{
CellRange chk = GetMergedRange(r, c);
if (chk.r1 == r && chk.c1 == c)
rows++;
}
rowsMin = Math.Min(rowsMin, rows);
}
return rowsMin;
}
public int GetRangeRowsMax(CellRange cr)
{
int rowsMax = 0;
for (int c = cr.c1; c <= cr.c2; c++)
{
int rows = 0;
for (int r = cr.r1; r <= cr.r2; r++)
{
CellRange chk = GetMergedRange(r, c);
if (chk.r1 == r && chk.c1 == c)
rows++;
}
rowsMax = Math.Max(rowsMax, rows);
}
return rowsMax;
}
public int GetRangeColsMin(CellRange cr)
{
int colsMin = 1 + cr.c2 - cr.c1;
for (int r = cr.r1; r <= cr.r2; r++)
{
int cols = 0;
for (int c = cr.c1; c <= cr.c2; c++)
{
CellRange chk = GetMergedRange(r, c);
if (chk.r1 == r && chk.c1 == c)
cols++;
}
colsMin = Math.Min(colsMin, cols);
}
return colsMin;
}
public int GetRangeColsMax(CellRange cr)
{
int colsMax = 0;
for (int c = cr.c1; c <= cr.c2; c++)
{
int cols = 0;
for (int r = cr.r1; r <= cr.r2; r++)
{
CellRange chk = GetMergedRange(r, c);
if (chk.r1 == r && chk.c1 == c)
cols++;
}
colsMax = Math.Max(colsMax, cols);
}
return colsMax;
}
public string GetRangeRowList(CellRange cr)
{
StringBuilder sb = new StringBuilder();
string sep = "";
for (int r = cr.r1; r <= cr.r2; r++)
{
CellRange crm = GetMergedRange(r, cr.c1);
if (crm.r1 == r)
{
sb.Append(sep + r.ToString());
sep = ".";
}
r = crm.r2;
}
return sb.ToString();
}
private int BlankRowSpace()
{
int curRowHeight = (Rows[Row].Height == -1) ? Rows.DefaultSize - 3 : Rows[Row].Height - 3;
if (curRowHeight <= (Rows.DefaultSize - 3)) return 0; // never have row less than default height
int blankRowSpace = curRowHeight;
for (int c = 0; c < Cols.Count; c++)
{
CellRange cr = GetMergedRange(Row, c);
if (Row >= cr.r1 && Row <= cr.r2)
{
int cellHeight = GetCellHeight(Row, c);
int dataHeight = (cr.UserData == null) ? cellHeight : (int)cr.UserData;
int ud = dataHeight / (Rows.DefaultSize - 3);
//if (cellHeight < dataHeight)
// Console.WriteLine("r {0}, c {1}, cell{2}, data{3}", Row, c, cellHeight, dataHeight);
blankRowSpace = Math.Min(blankRowSpace, Math.Max(0,cellHeight - dataHeight));
}
}
//Console.WriteLine("BlankRowSpace {0}", blankRowSpace);
return blankRowSpace;
}
private int GetCellWidth(int row, int col)
{
int width = 0;
CellRange cr = GetMergedRange(row, col);
for (int c = cr.c1; c <= cr.c2; c++)
{
width += (Cols[c].Width == -1) ? Cols.DefaultSize - 3 : Cols[c].Width -3;
}
return width;
}
private int BlankColSpace()
{
int curColWidth = (Cols[Col].Width == -1) ? Cols.DefaultSize - 3 : Cols[Col].Width-3;
//int curRowHeightNLines = curRowHeight / (Rows.DefaultSize - 3);
if (curColWidth <= Cols.DefaultSize - 3) return 0; // never have col less than default width
int blankColSpace = curColWidth;
for (int r = 0; r < Rows.Count; r++)
{
using (StepRTB srtb = new StepRTB())
{
CellRange cr = GetMergedRange(r, Col);
srtb.Rtf = GetCellRTFString(cr.r1, cr.c1);
if (Col >= cr.c1 && Col <= cr.c2)
{
int cellWidth = GetCellWidth(r, Col);
//srtb.Width = cellWidth;
srtb.AdjustWidthForContent();
//Application.DoEvents();
//int mergeCellHeightNLines = cellHeight / (Rows.DefaultSize - 3);
//int dataHeight = (cr.UserData == null) ? cellHeight : (int)cr.UserData;
//int ud = dataHeight / (Rows.DefaultSize - 3);
//if (cellHeight < dataHeight)
// Console.WriteLine("r {0}, c {1}, cell{2}, data{3}", Row, c, cellHeight, dataHeight);
//blankColSpace = Math.Min(blankColSpace, Math.Max(0, cellWidth - srtb.MaxTextWidth));
blankColSpace = Math.Min(blankColSpace, Math.Max(0, cellWidth - srtb.Width));
}
}
}
//Console.WriteLine("BlankRowSpace {0}", blankRowSpace);
return blankColSpace;
}
//private bool CanReduceRow()
//{
// int curRowHeight = (Rows[Row].Height == -1) ? Rows.DefaultSize - 3 : Rows[Row].Height - 3;
// int curRowHeightNLines = curRowHeight / (Rows.DefaultSize - 3);
// bool bReduce = (curRowHeight > (Rows.DefaultSize - 3));
// if (bReduce)
// {
// for (int c = 0; c < Cols.Count; c++)
// {
// CellRange cr = GetMergedRange(Row, c);
// if (Row >= cr.r1 && Row <= cr.r2)
// {
// int mergeCellHeightNLines = GetCellHeight(Row, c) / (Rows.DefaultSize - 3);
// //int ud = (cr.UserData == null) ? 0 : (int)cr.UserData;
// //if ((c != Col) && curRowHeight <= ud && ud >= mergeCellHeight)
// // bReduce = false;
// int ud = ((cr.UserData == null) ? 0 : (int)cr.UserData) / (Rows.DefaultSize - 3);
// if ((c != Col) && curRowHeightNLines <= ud && ud >= mergeCellHeightNLines)
// bReduce = false;
// }
// }
// }
// //Console.WriteLine("canreduce {0}, {1}", Row, bReduce);
// return bReduce;
//}
//private int GetMaxRowHeight()
//{
// int maxRTFHeight = _minRowSplitHeight; //Rows.DefaultSize;// the smallest a row can be
// Console.WriteLine("=================================================================");
// for (int c = 0; c < Cols.Count; c++)
// {
// CellRange cr = GetMergedRange(Row, c);//GetCellRange(Row, c);
// maxRTFHeight = Math.Max(maxRTFHeight, (int)cr.UserData);
// if (c == 0)
// Console.WriteLine("Height in Row[{0}] = {1}", Row, Rows[Row].Height);
// Console.WriteLine("UserData Cell[{0},{1}] = {2}", Row, c, cr.UserData);
// }
// return maxRTFHeight;
//}
private bool IsInMergeRange(int row, int col)
{
//foreach (CellRange cr in this.MergedRanges)
//{
// if (cr.Contains(row, col))
// return true; // in a merged range
//}
CellRange cr = GetMergedRange(row, col);
return (cr.r1 == row && cr.c1 == col);
}
private bool _ReadingXml = false;
public bool ReadingXml
{
get { return _ReadingXml; }
}
private static Regex _ReplaceVESymbFix = new Regex(@"({\\f[0-9]+[^ ]* )(FreeMono)(;})"); // FreeMono is now used for the edit screen only. VESymbFix and Consolas are used for printing
private static Regex _ReplaceArialUnicodeMS = new Regex(@"({\\f[0-9]+[^ ]* )(" + Volian.Base.Library.vlnFont.ProportionalSymbolFont + @")(;})"); // C2017-036 get best available proportional font for symbols
// B2017-173 VESymFix font was being replaced by the table's default font, causing empty squares for the symbols (pre FreeMono font) in tables
//C2017-036 Added FreeSerif which may be used if Arial Unicode MS is not available
private static Regex _ReplaceTextFont = new Regex(@"({\\f[0-9]+[^ ]* )(?((?!FreeMono)(?!FreeSerif)(?!Arial Unicode MS)(?!VESymbFix))([^;]*)|(!!!!))(;})"); // FreeMono is now used for the edit screen only. VESymbFix and Consolas are used for printing
private bool FontIsFixed(Font myFont)
{
Graphics grph = Graphics.FromHwnd(this.Handle);
SizeF sfW = grph.MeasureString("W", myFont);
SizeF sfE = grph.MeasureString("!", myFont);
if (sfW.Width == sfE.Width) return true;
return false;
}
// B2021-032: Changes (summary of changes after approval) occur when table does not change. This occurs if the font
// of the table changed in the format so that when the font was used the first time, the save code saw it
// as a difference. Save the new font, so that it can be used when doing the comparison before saving data.
private string _fontChangeFmt = null;
public string FontChangeFmt { get => _fontChangeFmt; set => _fontChangeFmt = value; }
public void LoadGrid(ItemInfo itemInfo)
{
int profileDepth = ProfileTimer.Push(">>>> VlnFlexGrid.LoadGrid");
// B2021-140 reset the shading information before loading in the next table
// Need to do this because we use static for the tables when we print
MyShading = null;
MyShadingDetailString = null;
_MyItemInfo = itemInfo;
string str = itemInfo.MyContent.MyGrid.Data;
VE_Font vefont = _MyItemInfo.GetItemFont();
// the following code is used to be sure that the font used for symbols is the correct font
// based on whether the font for non-symbol text is fixed or proportional. Each steprtb has
// a font for the non-symbol AND the symbol text, and these must be the correct association, i.e.
// for fixed fonts, the symbol font is 'VESymbFix', for proportional fonts, the symbol font is
// 'Arial Unicode MS'. The underlying flexgrid stores the fonts, and if the table font was
// reset for some reason (for example from the drop-down font selection in the user interface),
// this code 'cleans' up if there is a mismatch.
FontFamily ff = null;
if (StepRTB.MyFontFamily != null)
{
ff = StepRTB.MyFontFamily;
if (StepRTB.MySymbolFontName != "FreeMono") // FreeMono is now used for the edit screen only. VESymbFix and Consolas are used for printing
str = _ReplaceVESymbFix.Replace(str, "$1" + StepRTB.MySymbolFontName + "$3");
if (StepRTB.MySymbolFontName != Volian.Base.Library.vlnFont.ProportionalSymbolFont) // C2017-036 get best available proportional font for symbols
str = _ReplaceArialUnicodeMS.Replace(str, "$1" + StepRTB.MySymbolFontName + "$3");
str = _ReplaceTextFont.Replace(str, "$1" + ff.Name + "$4");
}
else
{
ff = vefont.WindowsFont.FontFamily;
if (FontIsFixed(vefont.WindowsFont))
str = _ReplaceArialUnicodeMS.Replace(str, "$1" + "FreeMono" + "$3"); // FreeMono is now used for the edit screen only. VESymbFix and Consolas are used for printing
else
str = _ReplaceVESymbFix.Replace(str, "$1" + Volian.Base.Library.vlnFont.ProportionalSymbolFont + "$3"); // C2017-036 get best available proportional font for symbols
str = _ReplaceTextFont.Replace(str, "$1" + ff.Name + "$4");
}
FontChangeFmt = ff.Name; // B2021-032
// To prevent scroll bars from being flashed on/off
// - save an image of the current grid
// - set Visible to false
// - draw the saved grid image
// - do the the load/reload of the grid
// - set Visible back to true.
Visible = false;
if (Parent is GridItem)
{
try
{
System.Drawing.Image img = this.CreateImage();
using (Graphics gr = (Parent as GridItem).CreateGraphics())
{
gr.DrawImage(img, Left, Top);
}
}
catch (Exception ex)
{
_MyLog.WarnFormat("Table Content Corrupted");
}
}
Clear();
MergedRanges.Clear();
_ReadingXml = true;
//Console.WriteLine("LoadGrid - Before ReadXML");
ReadXml(str);
//Console.WriteLine("LoadGrid - After ReadXML");
_ReadingXml = false;
Select(-1, -1); // this keeps the cell from being selected when the grid is first displayed
Visible = true;
ProfileTimer.Pop(profileDepth);
}
private void ReadXml(string str)
{
// Get the height/width adjusted for the DPI. Depending on if the DPI setting for the current user's
// monitor is different than the DPI setting saved in the grid record, table height/width of rows/columns
// will be incorrect, i.e. lots of extra white space. The reason behind this is that the height/width
// of table cells are stored as dots (from the monitor) in the underlying component one flexgrid.
try
{
str = AdjustHeightAndWidthForDPI(str);
str = Regex.Replace(str, "&(?![a-z])", "&amp;"); //B2021-142 fix &'s in text screen - so they are considered text instead of xml
using (StringReader sr = new StringReader(str))
{
ReadXml(sr);
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None;
sr.Close();
}
}
catch
{
;
}
}
private string AdjustHeightAndWidthForDPI(string str)
{
// create a graphics to get the DPI and then compare it to the DPI that is stored in the grid.
// if they are the same, we don't need to do anything.
int DPIscreen = 0;
using (Graphics gr = this.CreateGraphics())
{
DPIscreen = (int)gr.DpiX;
}
XmlDocument xd = new XmlDocument();
str = Regex.Replace(str, "&(?![a-z])", "&amp;"); //B2021-142 fix &'s in text screen - so they are considered text instead of xml
xd.LoadXml(str);
XmlNode xn = xd.SelectSingleNode("//DPI");
if (xn != null && xn.InnerText != DPIscreen.ToString())
{
int DPIgrid = int.Parse(xn.InnerText);
xn.InnerText = DPIscreen.ToString();
// adjust heights and widths based on the difference in DPIs between that what was saved
// in the database(grid) and the current DPI from the screen. Without doing this the
// heights/widths will be 'off', i.e. lots of white space.
XmlNodeList xnl = xd.SelectNodes("//Height");
foreach (XmlNode xni in xnl)
{
int measurement = int.Parse(xni.InnerText);
if (measurement != -1)
xni.InnerText = ((measurement * DPIscreen) / DPIgrid).ToString();
}
xnl = xd.SelectNodes("//Width");
foreach (XmlNode xni in xnl)
{
int measurement = int.Parse(xni.InnerText);
if (measurement != -1)
xni.InnerText = ((measurement * DPIscreen) / DPIgrid).ToString();
}
xnl = xd.SelectNodes("//DefaultSize");
foreach (XmlNode xni in xnl)
{
int measurement = int.Parse(xni.InnerText);
if (measurement != -1)
xni.InnerText = ((measurement * DPIscreen) / DPIgrid).ToString();
}
str = xd.OuterXml;
}
return str;
}
private void SetupGrid(int numrows, int numcols) //C1FlexGrid NewGrid()
{
// setup the default size of each cell in the table/grid
this.Cols.DefaultSize = (int) DPI;
this.Rows.DefaultSize = 20;
// setup the number of rows and columns
this.Rows.Count = numrows;
this.Cols.Count = numcols;
// make all the cell editable
this.Rows.Fixed = 0;
this.Cols.Fixed = 0;
this.DrawMode = DrawModeEnum.OwnerDraw;
this.ScrollBars = ScrollBars.None;
// grid styles
this.Styles.EmptyArea.BackColor = Color.Transparent;
this.Styles.EmptyArea.Border.Style = BorderStyleEnum.None;
this.Styles.Normal.Border.Color = Color.Black;
this.Styles.Normal.TextAlign = C1.Win.C1FlexGrid.TextAlignEnum.LeftTop;
//SetupCellStyles();
this.FocusRect = FocusRectEnum.Solid;
this.Styles.Highlight.BackColor = Color.LightCyan;
this.Styles.Highlight.ForeColor = Color.Black;
this.Styles.Focus.BackColor = Color.LightCyan;
this.HighLight = HighLightEnum.WithFocus;
_DefaultCellBackgroundcolor = this.StyleBackColor;
_DefaultFixedBackgroundColor = this.Styles.Fixed.BackColor;
this.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.Custom;
this.AllowResizing = C1.Win.C1FlexGrid.AllowResizingEnum.Both;
_tableCellEditor = new TableCellEditor(this);
_tableCellEditor.HeightChanged += new StepRTBEvent(_tableCellEditor_HeightChanged);
_clpbrdCpyPste = new TableClipBoardFuncts();
_SpellChecker = _tableCellEditor.SpellCheckerInstance;
this.AfterResizeRow += new C1.Win.C1FlexGrid.RowColEventHandler(this.Grid_AfterResize);
this.StartEdit += new C1.Win.C1FlexGrid.RowColEventHandler(this._StartEdit);
this.AfterEdit += new C1.Win.C1FlexGrid.RowColEventHandler(this._AfterEdit);
this.AfterScroll += new C1.Win.C1FlexGrid.RangeEventHandler(this._AfterScroll);
this.AfterResizeColumn += new C1.Win.C1FlexGrid.RowColEventHandler(this.Grid_AfterResize);
this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this._KeyPress);
this.OwnerDrawCell += new OwnerDrawCellEventHandler(this.Grid_OwnerDrawCell);
this.KeyDown += new KeyEventHandler(VlnFlexGrid_KeyDown);
this.KeyUp +=new KeyEventHandler(VlnFlexGrid_KeyUp);
TableCellEditor.EditMode = TableCellEditor.Visible; // need to comment out for compile for only jsj - 07FEB2011
this.MouseDown += new MouseEventHandler(VlnFlexGrid_MouseDown);
this.MouseUp += VlnFlexGrid_MouseUp;
this.DoubleClick += VlnFlexGrid_DoubleClick;
}
private bool _DoubleClickedCell = false; // C2021-005 need to know if user double-clicked on a cell
private void VlnFlexGrid_DoubleClick(object sender, EventArgs e)
{
// if user did a double click then don't try to get the font size - go directly to editing the table cell text
_DoubleClickedCell = true;
}
// C2021-005 needed the mouseup event to control the table cell selecting and grabbing of the font size
public bool _GettingFontSize = false;
private void VlnFlexGrid_MouseUp(object sender, MouseEventArgs e)
{
// C2021-005 Get the font size if user didn't double click and on a table
if (!_DoubleClickedCell && Parent != null && Parent is GridItem && Cols.Fixed == 0 && Rows.Fixed == 0)
(Parent as GridItem).MyStepPanel.MyStepTabPanel.MyStepTabRibbon.SetFontSizeDropDown();
}
private bool _FirstEntry = false;
public bool FirstEntry
{
get { return _FirstEntry; }
set { _FirstEntry = value; }
}
void VlnFlexGrid_MouseDown(object sender, MouseEventArgs e)
{
int left = 0;
int top = 0;
int col = 0;
int row = 0;
int strow = Selection.r1;
int stcol = Selection.c1;
int erow = Selection.r2;
int ecol = Selection.c2;
while (e.X > left && col < Cols.Count)
{
left += Cols[col].Width > 0 ? Cols[col].Width : Cols.DefaultSize;
col++;
}
while (e.Y > top && row < Rows.Count)
{
top += Rows[row].Height > 0 ? Rows[row].Height : Rows.DefaultSize;
row++;
}
col--;
row--;
//Console.WriteLine("Mousedown Selection {0}", Selection);
//Console.WriteLine("Mousedown Row, Col [{0},{1}]", row, col);
erow = Math.Max(erow, row);
ecol = Math.Max(ecol, col);
if (_FirstEntry)
Select(row, col);
else
Select(strow, stcol, erow, ecol);
_FirstEntry = false;
}
void _tableCellEditor_HeightChanged(object sender, EventArgs args)
{
// B2022-028: images in table cells - don't come into this code if it is an image in a table cell:
if (_tableCellEditor is StepRTB && (_tableCellEditor as StepRTB).ImageWidth > 0) return;
if (_tableCellEditor._initializingEdit || !_tableCellEditor.Visible) return;
int curHeight = GetCellHeight(Row, Col);//(Rows[Row].Height == -1) ? Rows.DefaultSize : Rows[Row].Height;
CellRange cr = GetMergedRange(Row, Col);
int oH = cr.UserData == null ? curHeight : (int)cr.UserData;
int nH = _tableCellEditor.Height; //.ContentsRectangle.Height;
int nW = _tableCellEditor.Width; // Width
int Hadj = (nH - curHeight);//oH);
cr.UserData = _tableCellEditor.Height; //.ContentsRectangle.Height;
//int cellHeight = GetCellHeight(Row, Col);
//int cellheightNLines = cellHeight / (Rows.DefaultSize - 3);
//int nHNLines = nH / (Rows.DefaultSize - 3);
if (Hadj != 0)
{
//if (Hadj > 0 && cellHeight <= oH)
//if (Hadj > 0 && cellheightNLines < nHNLines)
// curHeight += (Rows.DefaultSize - 3);
//if (Hadj < 0 && CanReduceRow())
// curHeight -= (Rows.DefaultSize - 3);
int blankRowSpace = BlankRowSpace();
if (Hadj < 0)
Hadj = -Math.Min(-Hadj, blankRowSpace);
//if (Hadj > 0)
// Console.WriteLine("r {0}, nh {1}, curh{2}", Row, nH, curHeight);
if (Hadj != 0)
{
int newHeight = Hadj + ((Rows[Row].Height < 0) ? Rows.DefaultSize : Rows[Row].Height);
//Rows[Row].Height += Hadj;//= curHeight;
Rows[Row].Height = newHeight;
AdjustGridControlSize();
}
}
}
void VlnFlexGrid_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control)
{
if (e.Alt)
{
switch (e.KeyCode)
{
case Keys.M:
OnOpenAnnotations(this, new EventArgs());
e.Handled = true;
break;
default:
break;
}
}
}
}
void VlnFlexGrid_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left:
if (e.Shift) return;
_tableCellEditor.StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlLeft : E_ArrowKeys.Left);
e.Handled = true;
break;
case Keys.Up:
if (e.Shift) return;
_tableCellEditor.StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlUp : E_ArrowKeys.Up);
e.Handled = true;
break;
case Keys.Right:
if (e.Shift) return;
if (IsRoTable) Select(Rows.Count - 1, Cols.Count - 1);
_tableCellEditor.StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlRight : E_ArrowKeys.Right);
e.Handled = true;
break;
case Keys.Down:
if (e.Shift) return;
if (IsRoTable) Select(Rows.Count - 1, 0);
_tableCellEditor.StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlDown : E_ArrowKeys.Down);
e.Handled = true;
break;
case Keys.Enter:
if (!e.Control && !e.Shift && !e.Alt)
{
if (MyDVI != null && UserInfo.CanEdit(MyUserInfo,MyDVI))
OnEnterKeyPressed(sender, e);
else
{
// if a Reviewer, then do a <Ctrl><DownArrow>. Don't allow changes to a table
if (IsRoTable) Select(Rows.Count - 1, 0);
_tableCellEditor.StepRTB_ArrowPressed(e.Control ? E_ArrowKeys.CtrlDown : E_ArrowKeys.Down);
e.Handled = true;
}
}
break;
}
}
//void VlnFlexGrid_LeaveEdit(object sender, RowColEventArgs e)
//{
// //Console.WriteLine("LeaveEdit Style = {0}", this.GetCellRange(e.Row, e.Col).Style.Name);
// this.GetCellRange(e.Row, e.Col).Style.ForeColor = Color.Black;
//}
private void Grid_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
using (RTF _rtf = new RTF())
{
// use nearest solid color
// (the RTF control doesn't dither, and doesn't support transparent backgrounds)
Color solid = e.Graphics.GetNearestColor(e.Style.BackColor);
DPI = e.Graphics.DpiX;
if (e.Style.BackColor != solid)
e.Style.BackColor = solid;
// check whether the cell contains RTF
// convert \'99 to \u8482? this is for the trade mark symbol. For some reason RTF is automatically
// converting the unicode \u8482? to \'99, but once this is done, PROMS StepRTB (edit windows) do not show it
// Also convert \~ to a hard spece. Again RTF is automatically converting \u160? to \~ but will then convert
// the \~ to a regular space!
string rtfText = RtfTools.RTFConvertedSymbolsToUnicode(this.GetDataDisplay(e.Row, e.Col));//.Replace(@"\~", @"\u160?").Replace(@"\'99", @"\u8482?");
GridItem gi = Parent as GridItem;
if (gi != null)
{
DisplayText dt = new DisplayText(gi.MyItemInfo, rtfText, true);
rtfText = dt.StartText;
}
// it does, so draw background
e.DrawCell(DrawCellFlags.Background);
if (rtfText.StartsWith(@"{\rtf"))
{
// Please add a comment if this value needs to be changed
_rtf.Rtf = rtfText;
// draw the RTF text
if (e.Bounds.Width > 0 && e.Bounds.Height > 0)
{
_rtf.Width = e.Bounds.Width - 1; // This has also been -3 which matchs the rener command
CellRange cr = GetMergedRange(e.Row, e.Col);
cr.UserData = _rtf.Height;
int hAdjust = 0;
int hDiff = e.Bounds.Height - _rtf.Height;
if (hDiff < 0)
{
Rows[e.Row].Height = _rtf.Height + 4;
AdjustGridControlSize();
hDiff = 0;
}
if (e.Style != null)
{
switch (e.Style.TextAlign)
{
case TextAlignEnum.CenterBottom:
case TextAlignEnum.GeneralBottom:
case TextAlignEnum.LeftBottom:
case TextAlignEnum.RightBottom:
hAdjust = hDiff;
break;
case TextAlignEnum.CenterCenter:
case TextAlignEnum.GeneralCenter:
case TextAlignEnum.LeftCenter:
case TextAlignEnum.RightCenter:
hAdjust = hDiff / 2; //0; // hDiff / 2;
break;
default:
break;
}
}
if (IsRoTable)
{
_rtf.ForeColor = Color.Red;
}
else
{
_rtf.ForeColor = e.Style.ForeColor;
}
_rtf.BackColor = e.Style.BackColor;
_rtf.Render(e.Graphics, new Rectangle(e.Bounds.X + 1, e.Bounds.Y + hAdjust, e.Bounds.Width - 3, e.Bounds.Height));
}
}
else
_rtf.Text = rtfText;
// spell check unless (we're just measuring)
if (!e.Measuring)
{
CharRangeList errors = SpellChecker.CheckText(_rtf.Text);//(text);
// underline errors
if (errors.Count > 0)
{
CharacterRange[] ranges = new CharacterRange[1];
ranges[0] = new CharacterRange(0, 1);
Pen pn = new Pen(Color.Green, 2);
StringFormat sf = new StringFormat(e.Style.StringFormat);
sf.SetMeasurableCharacterRanges(ranges);
Rectangle rc = e.Style.GetTextRectangle(e.Bounds, null);
Region[] rgns = e.Graphics.MeasureCharacterRanges(_rtf.Text, e.Style.Font, rc, sf);//(text, e.Style.Font, rc, sf);
float btm = rgns[0].GetBounds(e.Graphics).Bottom;
float top = rgns[0].GetBounds(e.Graphics).Top;
int adj = (int)(btm - top);
for (int i = 0; i < errors.Count; i++)
{
// The positioning of the the squigle line does not account for mixed font sizes
// should we support having mixed fonts in the table cells, we will need to add
// logic to support it.
Point ptStart = _rtf.GetPositionFromCharIndex(errors[i].Start);
Point ptEnd = _rtf.GetPositionFromCharIndex(errors[i].Start + errors[i].Length);
SquigleLine(e.Graphics, e.Bounds.Left + ptStart.X, e.Bounds.Top + ptStart.Y + adj, e.Bounds.Left + ptEnd.X);
}
}
}
// and draw border last
//e.DrawCell(DrawCellFlags.Border);
// This can be used to draw more specific borders
DrawCellBorder(e);
// we're done with this cell
e.Handled = true;
}
}
private void SquigleLine(Graphics graphics, int x1, int y1, int x2)
{
for (Point pt = new Point(x1, y1); pt.X + 2 < x2; pt.X += 4)
{
//Console.WriteLine("squiggle point {0}", pt);
graphics.DrawLines(Pens.Red, new Point[]
{
new Point(pt.X, pt.Y),
new Point(pt.X + 2, pt.Y - 2),
new Point(pt.X + 4, pt.Y)
});
}
}
private static Color _BorderColor = Color.Black;
public static Color BorderColor
{
get { return VlnFlexGrid._BorderColor; }
set { VlnFlexGrid._BorderColor = value; }
}
private void DrawCellBorder(C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
Graphics grGrid =e.Graphics;
Rectangle bounds = e.Bounds;
int row = e.Row;
int col = e.Col;
MyBorders.CheckAndFixBorderArraySize(this.Rows.Count, this.Cols.Count, GridLinePattern.Single); // C2018-031 check the cell border arrays
CellRange cr = GetMergedRange(row, col);
GridLinePattern topSide = MyBorders.HorizontalLines[cr.r1,cr.c1];
GridLinePattern rightOfTopSide = cr.c2 == Cols.Count - 1 ? GridLinePattern.None : MyBorders.HorizontalLines[cr.r1, cr.c2 + 1];
GridLinePattern leftOfTopSide = cr.c1 == 0? GridLinePattern.None : MyBorders.HorizontalLines[cr.r1, cr.c1 - 1];
GridLinePattern leftSide = MyBorders.VerticalLines[cr.r1, cr.c1];
GridLinePattern aboveLeftSide = cr.r1 == 0 ? GridLinePattern.None : MyBorders.VerticalLines[cr.r1 - 1, cr.c1];
GridLinePattern belowLeftSide = cr.r2 == Rows.Count - 1 ? GridLinePattern.None : MyBorders.VerticalLines[cr.r2 + 1, cr.c1];
GridLinePattern bottomSide = MyBorders.HorizontalLines[cr.r2+1, cr.c2];
GridLinePattern rightOfBottomSide = cr.c2 == Cols.Count - 1 ? GridLinePattern.None : MyBorders.HorizontalLines[cr.r2 + 1, cr.c2 + 1];
GridLinePattern rightSide = MyBorders.VerticalLines[cr.r2, cr.c2+1];
GridLinePattern belowRightSide = cr.r2 == Rows.Count - 1 ? GridLinePattern.None : MyBorders.VerticalLines[cr.r2 + 1, cr.c2 + 1];
GridLinePattern none = GridLinePattern.None;
int x1 = bounds.Left;
int y1 = bounds.Top;
int x2 = bounds.Right - 1;
int y2 = bounds.Bottom - 1;
GridItem myGridItem = Parent as GridItem;
Panel myPanel = Parent as Panel;
if (myGridItem == null && myPanel == null) return;
if (row == 0 || col == 0) // Top or Left Edge - Draw on parent
{
using (Graphics grParent = myGridItem != null ? myGridItem.CreateGraphics() : myPanel.CreateGraphics())
{
if (row == 0)
{
if (col == 0)
{
// Draw the top left intersection
DrawIntersection(grParent, Left - 3, Top-1, none, topSide,leftSide, none);
}
// Draw the top right intersection
DrawIntersection(grParent, Left +x2 - 2, Top-1, none, rightOfTopSide,rightSide,topSide);
// Draw the top side on the parent
DrawLine(grParent, topSide, Left + x1, Top + y1 - 1, Left + x2-3, Top + y1 -1);
}
if (col == 0)
{
// Draw the bottom left intersection
DrawIntersection(grParent, Left -3, Top + y2, leftSide,bottomSide,belowLeftSide,none);
// Draw the left side
DrawLine(grParent, leftSide, Left + x1 - 1, Top + y1, Left + x1 - 1, Top + y2-3);
}
}
}
// Draw the bottom right intersection
DrawIntersection(grGrid, x2 - 2, y2, rightSide, rightOfBottomSide, belowRightSide, bottomSide);
// Draw the bottom side
DrawLine(grGrid, bottomSide, x1, y2, x2-3, y2);
// Draw the right side
DrawLine(grGrid, rightSide, x2, y1, x2, y2-3);
}
private static void DrawLine(Graphics gr, GridLinePattern pattern, int x1, int y1, int x2, int y2)
{
if (pattern == GridLinePattern.None) return;
Pen pn = VlnBorders.LinePen(pattern, BorderColor);
DrawLine(gr, pn, pattern, x1, y1, x2, y2);
}
private static void DrawLine(Graphics gr, Pen pn, int x1, int y1, int x2, int y2)
{
DrawLine(gr, pn, GridLinePattern.Single, x1, y1, x2, y2);
}
private static void DrawLine(Graphics gr, Pen pn, GridLinePattern pattern, int x1, int y1, int x2, int y2)
{
int dx = 0;
int dy = 0;
int dblx = 0;
int dbly = 0;
int xThick = 0;
int yThick = 0;
if (x1 == x2) // Vertical Line
{
dx = (int) (-pn.Width / 2);
dblx = -2;
if (pn.Width > 2)
yThick = 1;
}
else // Horizontal Line
{
dy = (int) (-pn.Width / 2);
dbly = -2;
if (pn.Width > 2)
xThick = 1;
}
gr.DrawLine(pn, x1 + dx, y1 + dy, x2 + dx + xThick, y2 + dy + yThick);
if(pattern == GridLinePattern.Double)
gr.DrawLine(pn, x1 + dx +dblx, y1 + dy + dbly, x2 + dx+dblx, y2 + dy+dbly);
}
private static void DrawIntersection(Graphics gr, int x, int y, GridLinePattern up, GridLinePattern right, GridLinePattern down, GridLinePattern left)
{
if (up == GridLinePattern.Double)
if (right == GridLinePattern.Double)
if (down == GridLinePattern.Double)
if (left == GridLinePattern.Double) DrawIntersectionAllDoubles(gr, x, y);
else DrawDrawIntersection3Doubles_URD(gr, x, y);
else // Down is not double
if (left == GridLinePattern.Double) DrawDrawIntersection3Doubles_URL(gr, x, y);
else DrawDrawIntersection2Doubles_UR(gr, x, y, down, left);
else // right is not double
if (down == GridLinePattern.Double)
if (left == GridLinePattern.Double) DrawDrawIntersection3Doubles_UDL(gr, x, y);
else DrawDrawIntersection2Doubles_UD(gr, x, y, right, left);
else // Down is not double
if (left == GridLinePattern.Double) DrawIntersection2Doubles_UL(gr, x, y, right, down);
else DrawIntersectionOneDoubleOrLess(gr, x, y, up, right, down, left);
else
if (right == GridLinePattern.Double)
if (down == GridLinePattern.Double)
if (left == GridLinePattern.Double) DrawDrawIntersection3Doubles_RDL(gr, x, y);
else DrawDrawIntersection2Doubles_RD(gr, x, y, up, left);
else // Down is not double
if (left == GridLinePattern.Double) DrawDrawIntersection2Doubles_RL(gr, x, y, up, down);
else DrawIntersectionOneDoubleOrLess(gr, x, y, up, right, down, left);
else
if (down == GridLinePattern.Double)
if (left == GridLinePattern.Double) DrawDrawIntersection2Doubles_DL(gr, x, y, up, right);
else DrawIntersectionOneDoubleOrLess(gr, x, y, up, right, down, left);
else // These both use the same function with the same parameters
if (left == GridLinePattern.Double) DrawIntersectionOneDoubleOrLess(gr, x, y, up, right, down, left);
else DrawIntersectionOneDoubleOrLess(gr, x, y, up, right, down, left);
}
private static Pen pnDouble = VlnBorders.LinePen(GridLinePattern.Double, BorderColor);
private static Pen pnThick = VlnBorders.LinePen(GridLinePattern.Thick, BorderColor);
private static void DrawIntersectionAllDoubles(Graphics gr, int x, int y)
{
DrawLine(gr, pnDouble, x-1, y, x, y);
DrawLine(gr, pnDouble, x, y - 2, x, y - 3);
DrawLine(gr, pnDouble, x + 2, y - 2, x + 3, y - 2);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y + 1);
}
private static void DrawDrawIntersection3Doubles_URD(Graphics gr, int x, int y)
{
DrawLine(gr, pnDouble, x , y, x, y - 3);
DrawLine(gr, pnDouble, x + 2, y - 2, x + 3, y - 2);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y + 1);
}
private static void DrawDrawIntersection3Doubles_URL(Graphics gr, int x, int y)
{
DrawLine(gr, pnDouble, x, y, x + 2, y);
DrawLine(gr, pnDouble, x -1, y - 2, x , y - 2);
DrawLine(gr, pnDouble, x + 2, y - 2, x + 3, y - 2);
}
private static void DrawDrawIntersection3Doubles_UDL(Graphics gr, int x, int y)
{
DrawLine(gr, pnDouble, x-1, y, x, y);
DrawLine(gr, pnDouble, x , y - 2, x , y - 3);
DrawLine(gr, pnDouble, x + 2, y-3, x + 2, y);
}
private static void DrawDrawIntersection3Doubles_RDL(Graphics gr, int x, int y)
{
DrawLine(gr, pnDouble, x-1, y, x, y);
DrawLine(gr, pnDouble, x, y - 2, x + 2, y - 2);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y + 1);
}
private static void DrawDrawIntersection2Doubles_UR(Graphics gr, int x, int y, GridLinePattern lp1, GridLinePattern lp2)
{
if (lp1 == GridLinePattern.Thick && lp2 == GridLinePattern.Thick)
DrawLine(gr, pnThick, x, y, x + 3, y);
else
{
DrawLine(gr, pnDouble, x, y, x + 2, y);
DrawLine(gr, pnDouble, x , y, x , y - 2);
DrawLine(gr, pnDouble, x + 2, y - 2, x + 3, y - 2);
}
}
private static void DrawDrawIntersection2Doubles_UD(Graphics gr, int x, int y, GridLinePattern lp1, GridLinePattern lp2)
{
if (lp1 == GridLinePattern.Thick && lp2 == GridLinePattern.Thick)
DrawLine(gr, pnThick, x, y, x + 3, y);
else
{
DrawLine(gr, pnDouble, x, y, x, y - 2);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y - 2);
}
}
private static void DrawIntersection2Doubles_UL(Graphics gr, int x, int y, GridLinePattern lp1, GridLinePattern lp2)
{
if (lp1 == GridLinePattern.Thick && lp2 == GridLinePattern.Thick)
DrawLine(gr, pnThick, x, y, x + 3, y);
else
{
DrawLine(gr, pnDouble, x, y, x + 2, y);
DrawLine(gr, pnDouble, x , y - 2, x, y - 3);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y - 2);
}
}
private static void DrawDrawIntersection2Doubles_RD(Graphics gr, int x, int y, GridLinePattern lp1, GridLinePattern lp2)
{
if (lp1 == GridLinePattern.Thick && lp2 == GridLinePattern.Thick)
DrawLine(gr, pnThick, x, y, x + 3, y);
else
{
DrawLine(gr, pnDouble, x, y, x, y - 2);
DrawLine(gr, pnDouble, x, y - 2, x + 2, y - 2);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y + 1);
}
}
private static void DrawDrawIntersection2Doubles_RL(Graphics gr, int x, int y, GridLinePattern lp1, GridLinePattern lp2)
{
if (lp1 == GridLinePattern.Thick && lp2 == GridLinePattern.Thick)
DrawLine(gr, pnThick, x, y, x + 2, y);
else
{
DrawLine(gr, pnDouble, x, y, x + 2, y);
DrawLine(gr, pnDouble, x, y - 2, x + 2, y - 2);
}
}
private static void DrawDrawIntersection2Doubles_DL(Graphics gr, int x, int y, GridLinePattern lp1, GridLinePattern lp2)
{
if (lp1 == GridLinePattern.Thick && lp2 == GridLinePattern.Thick)
DrawLine(gr, pnThick, x, y, x + 2, y);
else
{
DrawLine(gr, pnDouble, x-1, y, x, y);
DrawLine(gr, pnDouble, x, y - 2, x + 2, y - 2);
DrawLine(gr, pnDouble, x + 2, y, x + 2, y - 2);
}
}
private static void DrawIntersectionOneDoubleOrLess(Graphics gr, int x, int y,
GridLinePattern up, GridLinePattern right, GridLinePattern down, GridLinePattern left)
{
Pen pnUp = VlnBorders.LinePen(up, BorderColor);
Pen pnLeft = VlnBorders.LinePen(left, BorderColor);
int widthUpDown = Math.Max(VlnBorders.LineWidth0(up), VlnBorders.LineWidth0(down));
int heightLeftRight = Math.Max(VlnBorders.LineWidth0(left), VlnBorders.LineWidth0(right));
if (heightLeftRight > 0 && widthUpDown > 0)
{
Pen pn = new Pen(BorderColor, widthUpDown);
if(heightLeftRight > 1)
DrawLine(gr, pn, x + 2, y + 1 - heightLeftRight, x + 2, y);
else if(up == GridLinePattern.None) // Work around to set a pixel (actually set two)
DrawLine(gr, pn, x + 2, y, x + 2, y + 1);
}
if (left != GridLinePattern.None)
{
DrawLine(gr, pnLeft, x, y, x + 2 - widthUpDown, y);
if (left == GridLinePattern.Double)
DrawLine(gr, pnLeft, x, y - 2, x + 2 - widthUpDown, y - 2);
}
if (up != GridLinePattern.None)
{
DrawLine(gr, pnUp, x + 2, y - 3 , x + 2, y +1 - heightLeftRight);
if (up == GridLinePattern.Double)
DrawLine(gr, pnUp, x, y - 3, x, y +1 - heightLeftRight);
}
}
#endregion //Grid Initialize
#region Grid and Cell Styles
public void ChangeBackgroundColor(string bckgndColor)
{
CellRange cr = this.Selection;
if (!bckgndColor.EndsWith(";"))
bckgndColor+=";";
string strBckgndColor = string.Format("BackColor:{0}", bckgndColor);
for (int rw = cr.r1; rw <= cr.r2; rw++)
for (int cl = cr.c1; cl <= cr.c2; cl++)
{
CellRange tmp = this.GetCellRange(rw, cl, rw, cl);
string StyleName = string.Format("R{0}C{1}Style", rw, cl);
CellStyle cs = this.Styles.Add(StyleName, tmp.Style);
cs.ParseString(strBckgndColor);
tmp.Style = cs;
}
}
public void ToggleCellTextAlignment()
{
// only used in test program
CellRange cr = this.Selection;
using (StepRTB srtb = new StepRTB())
{
srtb.Rtf = this.GetCellRTFString(cr.r1, cr.c1);
srtb.SelectAll();
int align = (int)srtb.SelectionAlignment;
align = (align + 1) % 3;
srtb.SelectionAlignment = (HorizontalAlignment)align;
this.PutCellRTFString(cr.r1, cr.c1, srtb.Rtf);
}
}
public void RTFTextAlignment(CellRange cr, HorizontalAlignment ha)
{
using ( StepRTB srtb = new StepRTB())
{
for (int rw = cr.r1; rw <= cr.r2; rw++)
for (int cl = cr.c1; cl <= cr.c2; cl++)
{
srtb.Rtf = this.GetCellRTFString(rw, cl);
srtb.SelectAll();
srtb.SelectionAlignment = ha;
this.PutCellRTFString(rw, cl, srtb.Rtf);
}
}
}
public void SetTableBorder(C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum border)
{
this.BorderStyle = border;
this.AdjustGridControlSize();
}
public void ChangeCellAlign(CellRange cr, TextAlignEnum newAlign)
{
//Console.WriteLine("CellRange = {0}, align={1}", cr, newAlign);
for (int rw = cr.r1; rw <= cr.r2; rw++)
for (int col = cr.c1; col <= cr.c2; col++)
{
CellRange tmp = this.GetCellRange(rw, col, rw, col);
string StyleName = string.Format("R{0}C{1}Style", rw, col);
CellStyle cs = null;
if (Styles.Contains(StyleName))
cs = Styles[StyleName];
else
cs = this.Styles.Add(StyleName, tmp.Style);
cs.TextAlign = newAlign;
tmp.Style = cs;
}
// If one column and one row, then go into edit mode.
if (cr.r1 == cr.r2 && cr.c1 == cr.c2)
SendKeys.Send("{F2}"); // Toggle Edit Mode with F2
}
public void ChangeCellBorder(CellRange cr, BorderStyleEnum newBorder)
{
for (int rw = cr.r1; rw <= cr.r2; rw++)
for (int col = cr.c1; col <= cr.c2; col++)
{
CellRange tmp = this.GetCellRange(rw, col, rw, col);
string StyleName = string.Format("R{0}C{1}Style", rw, col);
CellStyle cs = null;
if (Styles.Contains(StyleName))
cs = Styles[StyleName];
else
cs = this.Styles.Add(StyleName, tmp.Style);
cs.Border.Style = newBorder;
tmp.Style = cs;
}
}
public void ListStyles()
{
for (int r = 0; r < Rows.Count; r++)
for (int c = 0; c < Cols.Count; c++)
{
CellRange cr = GetMergedRange(r, c);
if (cr.r1 == r && cr.c1 == c)
{
if (cr.Style != null) Console.WriteLine("{0}, {1}, {2}, {3}", r, c, cr.Style.Name, cr.Style.BackColor);
}
}
}
//public void VerticalCenterText()
//{
// StepRTB myStepRTB = new StepRTB();
// CellRange selRange = this.Selection;
// for (int r = selRange.r1; r <= selRange.r2; r++)
// for (int c = selRange.c1; c <= selRange.c2; c++)
// {
// CellRange mr = this.GetMergedRange(r, c);
// if (mr.r1 == r)
// {
// int editHeight = (int)mr.UserData;
// int cellHeight = GetCellHeight(mr.r1, mr.c1);
// if (editHeight < cellHeight)
// {
// myStepRTB.Rtf = (string)mr.Data;
// RTBAPI.SetSpaceBefore(myStepRTB, (cellHeight - editHeight) / 2);
// PutCellRTFString(mr.r1, mr.c1, myStepRTB.Rtf);
// }
// }
// }
//}
//public void VerticalTopText()
//{
// StepRTB myStepRTB = new StepRTB();
// CellRange selRange = this.Selection;
// for (int r = selRange.r1; r <= selRange.r2; r++)
// for (int c = selRange.c1; c <= selRange.c2; c++)
// {
// CellRange mr = this.GetMergedRange(r, c);
// if (mr.r1 == r)
// {
// myStepRTB.Rtf = (string)mr.Data;
// RTBAPI.SetSpaceBefore(myStepRTB, 0);
// PutCellRTFString(mr.r1, mr.c1, myStepRTB.Rtf);
// }
// }
//}
//public void VerticalBottomText()
//{
// StepRTB myStepRTB = new StepRTB();
// CellRange selRange = this.Selection;
// for (int r = selRange.r1; r <= selRange.r2; r++)
// for (int c = selRange.c1; c <= selRange.c2; c++)
// {
// CellRange mr = this.GetMergedRange(r, c);
// if (mr.r1 == r)
// {
// int editHeight = (int)mr.UserData;
// int cellHeight = GetCellHeight(mr.r1, mr.c1);
// if (editHeight < cellHeight)
// {
// myStepRTB.Rtf = (string)mr.Data;
// RTBAPI.SetSpaceBefore(myStepRTB, (cellHeight - editHeight));
// PutCellRTFString(mr.r1, mr.c1, myStepRTB.Rtf);
// }
// }
// }
//}
//public void SetupCellStyles()
//{
// //CellStyle cs;
// //cs = this.Styles.Add("Dotted");
// //cs.Border.Style = BorderStyleEnum.Dotted;
// //cs = this.Styles.Add("Double");
// //cs.Border.Style = BorderStyleEnum.Double;
// //cs = this.Styles.Add("Fillet");
// //cs.Border.Style = BorderStyleEnum.Fillet;
// //cs = this.Styles.Add("Flat");
// //cs.Border.Style = BorderStyleEnum.Flat;
// //cs = this.Styles.Add("Groove");
// //cs.Border.Style = BorderStyleEnum.Groove;
// //cs = this.Styles.Add("Inset");
// //cs.Border.Style = BorderStyleEnum.Inset;
// //cs = this.Styles.Add("None");
// //cs.Border.Style = BorderStyleEnum.None;
// //cs = this.Styles.Add("Raised");
// //cs.Border.Style = BorderStyleEnum.Raised;
// //cs = this.Styles.Add("CenterRight");
// //cs.TextAlign = TextAlignEnum.RightCenter; //.LeftCenter; // this is being ignored - probably due to RTF conversion
// //cs = this.Styles.Add("Yellow");
// //cs.BackColor = Color.Yellow;
// //cs = this.Styles.Add("Margins");
// //cs.Margins.Bottom = 5;
// //cs.Margins.Top = 10;
// //cs.Margins.Left = 15;
// //cs.Margins.Right = 20;
//}
#endregion //Grid and Cell Styles
#region Grid Size Adjustments
/// <summary>
/// Adjust the grid control size based on the cell sizes.
/// </summary>
public void AdjustGridControlSize()
{
if (Parent is GridItem ? (Parent as GridItem).Initializing : false ) return;
int difW = this.Width - this.ClientSize.Width;
int difH = this.Height - this.ClientSize.Height;
int wid = 0;
if (this != null)
{
foreach (C1.Win.C1FlexGrid.Column col in this.Cols)
wid += (col.Width >= 0) ? col.Width : this.Cols.DefaultSize;
int height = 0;
foreach (C1.Win.C1FlexGrid.Row row in this.Rows)
//height += (row.Height >= 0) ? row.Height : this.Rows.DefaultSize + 2;
height += (row.Height >= 0) ? row.Height : this.Rows.DefaultSize;
this.Size = new Size(wid + difW, height + difH);
}
}
// B2019-162 Allow grids to not automatically adjust the cell widths
public void ConvertTextCellToRTF(int r, int c, bool adjustWidth)
{
using (StepRTB trtb = new StepRTB())
{
string tstr = null;
bool dummyCharWidth = false;
bool AllowWidthShrink = false;
trtb.SetTableGridCellRTFPrefix(this.Font);
trtb.Clear();
tstr = (string)this[r, c];
trtb.Font = this.Font;
if (tstr != null && tstr.Length > 0)
{
string tsave = tstr;
// regular text has special characters to toggle Bold, Underline, and Italics
// we need to subtract the width of these characters (allow column/row to shrink)
//AllowWidthShrink = RemoveBoldUlineItalicChars(trtb.Rtf);
AllowWidthShrink = tstr.Contains("#Link:");
// this will convert the special characters for Bold, Underline, and Italics
// into RTF commands
//trtb.Rtf = trtb.RtfPrefix + ConvertTableText(trtb.Rtf) + "}";
//string fromRTF = trtb.Rtf;
//string prefix = trtb.RtfPrefix;
//if (tstr.Contains("#Link:")) prefix += @"{\colortbl ;\red255\green0\blue0;}";
//if (tstr.Contains("#Link:"))
// Console.WriteLine("here");
//string jText = trtb.RtfPrefix + ConvertTableText(tstr) + @"\par}";
//trtb.Rtf = jText;
trtb.Rtf = trtb.RtfPrefix + ConvertTableText(tstr) + @"\par}";
//string fromStr = trtb.Rtf;
//if (fromRTF.Contains("SimSun"))
// Console.WriteLine("SimSun");
//else
// Compare(fromRTF, fromStr, tsave);
}
else
{
trtb.Text = "X"; // this is to trick steprtf in giving a char width to fit one character
// note that a space character was too small.
dummyCharWidth = true;
}
// find the needed cell width
trtb.AdjustWidthForContent();
// B2019-162 Allow grids to not automatically adjust the cell widths
if(adjustWidth)trtb.AdjustWidthForContent();
if (dummyCharWidth)
{
trtb.Text = ""; // clear out the dummy character before saving
dummyCharWidth = false;
}
this[r, c] = trtb.Rtf; // save the cleaned up and processed cell text as RTF
this.Select(r, c, false);
CellRange sel = this.Selection;
//sel.UserData = trtb.ContentsRectangle.Height;
// Now adjust the Height and Width in the defined merge ranges
// B2019-162 Allow grids to not automatically adjust the cell widths
AdjustMergeRangeHeightWidth(r, c, trtb, tstr, AllowWidthShrink,adjustWidth);
//// Now see the the selected row,col is in the defined merge ranges
//bool mrgrows = false;
//bool mrgcols = false;
//foreach (CellRange cr in this.MergedRanges)
//{
// if (cr.Contains(r, c))
// {
// if (cr.c1 != cr.c2)
// mrgcols = true; // in a range of merged columns
// if (cr.r1 != cr.r2)
// mrgrows = true; // in a range of merged rows
// continue;
// }
//}
//if (!mrgcols || !mrgrows)
//{
// // IF the row of the selected cell is NOT in merged range
// // then go ahead and adjust the row height (if needed)
// if (!mrgrows)
// {
// // add adjustment for grid and cell borders
// int newheight = trtb.Height + 3;
// //Console.WriteLine("{0} {1} {2} '{3}'", r, c, newheight,trtb.Text);
// if (newheight > this.Rows[r].Height)
// {
// //Console.WriteLine("1 Row {0} Old Height = {1}, New Height = {2}", r, Rows[r].Height, newheight);
// this.Rows[r].Height = newheight;
// }
// }
// // IF the column of the selected cell is NOT in merged range
// // then go ahead and adjust the column width (if needed)
// if (!mrgcols)
// {
// // add adjustment for grid and cell borders
// int newwidth = trtb.Width + 2;
// if (newwidth > this.Cols[c].Width || AllowWidthShrink || r == 0)
// this.Cols[c].Width = newwidth;
// }
//}
//if (mrgrows && tstr != null)
//{
// CellRange cr = GetMergedRange(r, c);
// //Console.WriteLine("grid[{0},{1}] merge = {2}", r, c,cr);
// if (cr.r1 == r && cr.c1 == c)
// {
// // if in merged rows, then make sure the cell's height is large enough
// string[] strary = tstr.Split("\n".ToCharArray());
// // count number of lines of text
// int nlines = strary.Length;
// // count number of rows in merge range
// int nrows = (cr.r2 - cr.r1) + 1;
// //Console.WriteLine("2 Row {0} Height = {1}", cr.r1, Rows[cr.r1].Height);
// while (nlines > nrows)
// {
// // add length to first row in merged range
// int h = this.Rows[cr.r1].Height;
// int defH = Rows.DefaultSize - 3;
// //h = (h == -1) ? _minRowHeight * 2 : h + _minRowHeight;
// h = (h == -1) ? (defH * 2) + 3 : h + defH;
// //h = (h == -1) ? (Rows.DefaultSize + 2) * 2 : h + Rows.DefaultSize + 2;
// //Console.WriteLine("3 Row {0} Old Height = {1}, New Height = {2}", cr.r1, Rows[cr.r1].Height, h);
// this.Rows[cr.r1].Height = h;
// nrows++;
// }
// }
//}
}
}
//private void AdjustCellHeightWidth(int r, int c)
//{
// using (StepRTB trtb = new StepRTB())
// {
// string tstr = null;
// bool dummyCharWidth = false;
// bool AllowWidthShrink = false;
// trtb.SetTableGridCellRTFPrefix(this.Font);
// trtb.Clear();
// trtb.Font = this.Font;
// trtb.Rtf = (string)this[r, c];
// tstr = trtb.Text;
// if (tstr != null && tstr.Length > 0)
// AllowWidthShrink = tstr.Contains("#Link:");
// else
// {
// trtb.Text = "X"; // this is to trick steprtf in giving a char width to fit one character
// // note that a space character was too small.
// dummyCharWidth = true;
// }
// // find the needed cell width
// trtb.AdjustWidthForContent();
// if (dummyCharWidth)
// {
// trtb.Text = ""; // clear out the dummy character before saving
// dummyCharWidth = false;
// }
// // Now adjust the Height and Width in the defined merge ranges
// AdjustMergeRangeHeightWidth(r, c, trtb, tstr, AllowWidthShrink,true);
// }
//}
// B2019-162 Allow grids to not automatically adjust the cell widths
private void AdjustMergeRangeHeightWidth(int r, int c, StepRTB trtb, string tstr, bool AllowWidthShrink, bool adjustWidth)
{
bool mrgrows = false;
bool mrgcols = false;
foreach (CellRange cr in this.MergedRanges)
{
if (cr.Contains(r, c))
{
if (cr.c1 != cr.c2)
mrgcols = true; // in a range of merged columns
if (cr.r1 != cr.r2)
mrgrows = true; // in a range of merged rows
continue;
}
}
if (!mrgcols || !mrgrows)
{
// IF the row of the selected cell is NOT in merged range
// then go ahead and adjust the row height (if needed)
if (!mrgrows)
{
// add adjustment for grid and cell borders
int newheight = trtb.Height + 3;
//Console.WriteLine("{0} {1} {2} '{3}'", r, c, newheight,trtb.Text);
if (newheight > this.Rows[r].Height)
{
//Console.WriteLine("1 Row {0} Old Height = {1}, New Height = {2}", r, Rows[r].Height, newheight);
this.Rows[r].Height = newheight;
}
}
// IF the column of the selected cell is NOT in merged range
// then go ahead and adjust the column width (if needed)
if (!mrgcols)
{
// add adjustment for grid and cell borders
// B2019-162 Allow grids to not automatically adjust the cell widths
if (adjustWidth)
{
int newwidth = trtb.Width + 3; // 2;
if (newwidth > (this.Cols[c].Width == -1 ? this.Cols.DefaultSize : this.Cols[c].Width) || AllowWidthShrink || r == 0)
this.Cols[c].Width = newwidth;
}
}
}
if (mrgrows && tstr != null)
{
CellRange cr = GetMergedRange(r, c);
if (cr.r1 == r && cr.c1 == c)
{
// if in merged rows, then make sure the cell's height is large enough
string[] strary = tstr.Split("\n".ToCharArray());
// count number of lines of text
int nlines = strary.Length;
// count number of rows in merge range
int nrows = (cr.r2 - cr.r1) + 1;
//Console.WriteLine("2 Row {0} Height = {1}", cr.r1, Rows[cr.r1].Height);
while (nlines > nrows)
{
// add length to first row in merged range
int h = this.Rows[cr.r1].Height;
int defH = Rows.DefaultSize - 3;
h = (h == -1) ? (defH * 2) + 3 : h + defH;
this.Rows[cr.r1].Height = h;
nrows++;
}
}
}
}
private int TotalColWidths()
{
int cwid = 0;
foreach (Column c in Cols)
{
cwid += ((c.Width > 0) ? c.Width : Cols.DefaultSize);
}
return cwid;
}
/// <summary>
/// This will adjust the column widths of the current table based upon the page width
/// Note: This is for use in creating a new table - not to process an existing table.
/// </summary>
/// <param name="pgWidthPoints"></param>
public void FitTableToPageWidth(int pgWidthPoints)
{
int grdWidth = TotalColWidths();
int pgwidth = (int)((pgWidthPoints / 72) * this._DPI);
if (grdWidth > pgwidth)
{
int difWid = grdWidth - pgwidth;
int colAdj = (difWid / Cols.Count) +(((difWid % Cols.Count) > 0) ? 1 : 0);
foreach (Column c in Cols)
{
int cwid = (c.Width > 0) ? c.Width : Cols.DefaultSize;
if ((cwid - colAdj) > 0)
c.Width = cwid - colAdj;
}
}
}
//private void AdjustCellHeightWidth(int r, int c)
//{
// StepRTB trtb = new StepRTB();
// string tstr = null;
// bool dummyCharWidth = false;
// bool AllowWidthShrink = false;
// trtb.SetTableGridCellRTFPrefix(this.Font);
// trtb.Clear();
// trtb.Font = this.Font;
// trtb.Rtf = (string)this[r, c];
// tstr = trtb.Text;
// if (tstr != null && tstr.Length > 0)
// AllowWidthShrink = tstr.Contains("#Link:");
// else
// {
// trtb.Text = "X"; // this is to trick steprtf in giving a char width to fit one character
// // note that a space character was too small.
// dummyCharWidth = true;
// }
// // find the needed cell width
// trtb.AdjustWidthForContent();
// if (dummyCharWidth)
// {
// trtb.Text = ""; // clear out the dummy character before saving
// dummyCharWidth = false;
// }
// this.Select(r, c, false);
// CellRange sel = this.Selection;
// // Now see the the selected row,col is in the defined merge ranges
// bool mrgrows = false;
// bool mrgcols = false;
// foreach (CellRange cr in this.MergedRanges)
// {
// if (cr.Contains(r, c))
// {
// if (cr.c1 != cr.c2)
// mrgcols = true; // in a range of merged columns
// if (cr.r1 != cr.r2)
// mrgrows = true; // in a range of merged rows
// continue;
// }
// }
// if (!mrgcols || !mrgrows)
// {
// // IF the row of the selected cell is NOT in merged range
// // then go ahead and adjust the row height (if needed)
// if (!mrgrows)
// {
// // add adjustment for grid and cell borders
// int newheight = trtb.Height + 3;
// //Console.WriteLine("{0} {1} {2} '{3}'", r, c, newheight,trtb.Text);
// if (newheight > this.Rows[r].Height)
// {
// //Console.WriteLine("1 Row {0} Old Height = {1}, New Height = {2}", r, Rows[r].Height, newheight);
// this.Rows[r].Height = newheight;
// }
// }
// // IF the column of the selected cell is NOT in merged range
// // then go ahead and adjust the column width (if needed)
// if (!mrgcols)
// {
// // add adjustment for grid and cell borders
// int newwidth = trtb.Width + 2;
// if (newwidth > this.Cols[c].Width || AllowWidthShrink || r == 0)
// this.Cols[c].Width = newwidth;
// }
// }
// if (mrgrows && tstr != null)
// {
// CellRange cr = GetMergedRange(r, c);
// if (cr.r1 == r && cr.c1 == c)
// {
// // if in merged rows, then make sure the cell's height is large enough
// string[] strary = tstr.Split("\n".ToCharArray());
// // count number of lines of text
// int nlines = strary.Length;
// // count number of rows in merge range
// int nrows = (cr.r2 - cr.r1) + 1;
// //Console.WriteLine("2 Row {0} Height = {1}", cr.r1, Rows[cr.r1].Height);
// while (nlines > nrows)
// {
// // add length to first row in merged range
// int h = this.Rows[cr.r1].Height;
// int defH = Rows.DefaultSize - 3;
// h = (h == -1) ? (defH * 2) + 3 : h + defH;
// this.Rows[cr.r1].Height = h;
// nrows++;
// }
// }
// }
//}
//private void Compare(string fromRTF, string fromStr, string rawstr)
//{
// int istart = fromRTF.IndexOf(" ",fromRTF.IndexOf("viewkind"));
// int jstart = fromStr.IndexOf(" ",fromStr.IndexOf("viewkind"));
// for (int i = istart; i < fromRTF.Length; i++)
// {
// int j = i - istart + jstart;
// //else if (fromRTF[i] != fromStr[j])
// if (fromRTF[i] != fromStr[j])
// {
// if (fromRTF.Substring(i, 1) == @"~" && fromStr.Substring(j, 3) == @"'a0")
// {
// //i++;
// jstart += 2;
// }
// else
// {
// Console.WriteLine("fromStr:\r\n'{0}'\r\nfromRTF:\r\n'{1}'", fromStr, fromRTF);
// ShowRawString(rawstr, "rawstr");
// Console.WriteLine("Str:'{0}' , RTF:'{1}'", fromStr.Substring(j, Math.Min(10,fromStr.Length-j-1)), fromRTF.Substring(i, Math.Min(10,fromRTF.Length-i-1)));
// return;
// }
// }
// }
//}
#region DEBUG
//private void ShowRawString(string str, string title)
//{
// Console.WriteLine("Raw Start --{0}:\n", title);
// foreach (char c in str)
// {
// int ic= (int)c;
// if (c!='\n'&&( ic > 126 || ic < 32))
// Console.Write("<<{0:x4}>>", ic);
// else
// Console.Write(c);
// }
// Console.WriteLine("\n-- Raw End:{0}", title);
//}
#endregion
private void Grid_AfterResize(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
{
this.AdjustGridControlSize();
}
#endregion // Grid Size Adjustments
#region Cell Text
// B2019-162 Allow grids to not automatically adjust the cell widths
public void MakeRTFcells()
{
MakeRTFcells(true);
}
// B2019-162 Allow grids to not automatically adjust the cell widths
public void MakeRTFcells(bool adjustwidth)
{
// This will spin through all the cells in the grid:
// - convert the text to RTF if needed
// - adjust the grid dimensions based on the cell info.
for (int r = 0; r < this.Rows.Count; r++)
{
this.Rows[r].Height = Rows.DefaultSize;//_minRowHeight;//20;//10;
for (int c = 0; c < this.Cols.Count; c++)
{
// B2019-162 Allow grids to not automatically adjust the cell widths
this.ConvertTextCellToRTF(r, c, adjustwidth);
}
}
// B2019-162 Allow grids to not automatically adjust the cell widths
if(adjustwidth) TrimColumnWidths();
RemoveBlankSpaceFromRows();
SetupCellUserData();
this.AdjustGridControlSize();
}
public void FixTableCellsHeightWidth()
{
RemoveBlankSpaceFromColumns();
RemoveBlankSpaceFromRows();
}
private void RemoveBlankSpaceFromRows()
{
for (int r = 0; r < Rows.Count; r++)
{
Select(r, 0);
int blankRowSpace = BlankRowSpace();
if (blankRowSpace > 0)
Rows[r].Height -= blankRowSpace;
}
}
private void RemoveBlankSpaceFromColumns()
{
for (int c = 0; c < Cols.Count; c++)
{
Select(0, c);
int blankColSpace = BlankColSpace();
if (blankColSpace > 0)
Cols[c].Width -= blankColSpace;
}
}
private void TrimColumnWidths()
{
for (int c = 0; c < Cols.Count; c++)
{
Select(0, c);
int newColWidth = MinColWidth();
Cols[c].Width = newColWidth;
}
}
private int MinColWidth()
{
int curColWidth = 0;
for (int r = 0; r < Rows.Count; r++)
{
CellRange cr = GetMergedRange(r, Col);
// find the needed cell width
if (Col == cr.c1)
{
using (StepRTB srtb = new StepRTB())
{
srtb.Rtf = GetCellRTFString(cr.r1, cr.c1);
srtb.AdjustWidthForContent();
curColWidth = Math.Max(curColWidth, srtb.Width + 3);
}
}
}
return curColWidth;
}
//private bool RemoveBoldUlineItalicChars(string str)
//{
// int rtn = 0;
// // Underline next word
// rtn += str.IndexOf(@"\'17");
// // Bold next word
// rtn += str.IndexOf(@"\'13");
// // Italics On
// rtn += str.IndexOf(@"\'1B4");
// // Italics Off
// rtn += str.IndexOf(@"\'1B5");
// // underline On
// rtn += str.IndexOf(@"\'ab");
// // underline Off
// rtn += str.IndexOf(@"\'bb");
// return rtn > 0;
//}
private string ConvertTableText(string str)
{
string rtn = str;
//ShowRawString(str, "ConvertTableText IN");
rtn = rtn.Replace(@"START]\v0", @"START]\cf1\v0");
rtn = rtn.Replace(@"\v #Link:", @"\cf0\v #Link:");
rtn = rtn.Replace("\n", "\\par\r\n");
rtn = rtn.Replace("\xB3", @"\f1\u9474?\f0"); // Vert Bar
rtn = rtn.Replace("\xF2", @"\f1\u8805?\f0 "); // greater than or equal
rtn = rtn.Replace("\x7F", @"\f1\u916?\f0 "); // delta
rtn = rtn.Replace("\xF3", @"\f1\u8804?\f0 "); // less than or equal
rtn = rtn.Replace("\xE4", @"\f1\u931?\f0 "); // sigma
rtn = rtn.Replace("\xE7", @"\f1\u947?\f0 "); // gamma
rtn = rtn.Replace("\xFE", @"\f1\u9604?\f0 "); // accum 2584
rtn = rtn.Replace("\x7", @"\f1\u9679?\f0 "); // bullet 25CF
rtn = rtn.Replace("\xF7", @"\f1\u8776?\f0 "); // approx eq
rtn = rtn.Replace("\xF0", @"\f1\u8773?\f0 "); // similar eq 2245
rtn = rtn.Replace("\xFB", @"\f1\u8730?\f0 "); // square root
rtn = rtn.Replace("\xE2", @"\f1\u961?\f0 "); // rho 3C1
rtn = rtn.Replace("\xE3", @"\f1\u960?\f0 "); // pi
rtn = rtn.Replace("\xE6", @"\f1\u956?\f0 "); // micro
rtn = rtn.Replace("\xEB", @"\f1\u948?\f0 "); // lower case delta
rtn = rtn.Replace("\xE5", @"\f1\u963?\f0 "); // lower case sigma
rtn = rtn.Replace("\x90", @"\f1\u274?\f0 "); // energy, 112
rtn = rtn.Replace("\xEE", @"\f1\u949?\f0 "); // epsilon
rtn = rtn.Replace("\xE9", @"\f1\u952?\f0 "); // theta, 3B8
rtn = rtn.Replace("\xEC", @"\f1\u8857?\f0 "); // dot in oval, 2299
rtn = rtn.Replace("\xA8", @"\f1\u964?\f0 "); // tau, 3C4
rtn = rtn.Replace("\xA9", @"\f1\u9830?\f0 "); // diamond, 2666
rtn = rtn.Replace("\x18", @"\f1\u8593?\f0 "); // Up Arrow
rtn = rtn.Replace("\x19", @"\f1\u8595?\f0 "); // Down Arrow
rtn = rtn.Replace("\xFF", @"\u160?"); // hardspace
//rtn = rtn.Replace(@"\'a0", @"\u160?");
//rtn = rtn.Replace("\xff", @"\u160?");
//rtn = rtn.Replace("\xA0", @"\u160?");
// underline On
rtn = rtn.Replace("\xab", @"\ul");
// underline Off
rtn = rtn.Replace("\xbb", @"\ulnone");
//rtn = rtn.Replace("\xef\xe6", @"\up2 ");
//rtn = rtn.Replace("\xef\xe7", @"\up0 ");
rtn = rtn.Replace("\x9566", @"\up2 ");
rtn = rtn.Replace("\x9567", @"\up0 ");
rtn = rtn.Replace("{", @"\{");
rtn = rtn.Replace("}", @"\}");
rtn = rtn.Replace("\xd5", @"\b");
rtn = rtn.Replace("\xd6", @"\b0");
//ShowRawString(rtn, "ConvertTableText OUT");
return rtn;
}
private static string SomethingNextWord(string str, string nxtwordcmd, string cmdOn, string cmdOff)
{
string rtn = "";
int bidx = 0;
int fidx = str.IndexOf(nxtwordcmd, bidx);
char[] term = " \r\n\x02".ToCharArray();
while (fidx > 0)
{
rtn += str.Substring(bidx, fidx - bidx) + cmdOn;
bidx = fidx + 4;
if (bidx < str.Length)
{
fidx = str.IndexOfAny(term, bidx);
if (fidx > 0)
{
rtn += str.Substring(bidx, fidx - bidx) + cmdOff + str.Substring(fidx, 1);
bidx = fidx + 1;
}
}
if (bidx < str.Length)
fidx = str.IndexOf(nxtwordcmd, bidx);
else
fidx = -1;
}
if (bidx < str.Length)
rtn += str.Substring(bidx);
return rtn;
}
private void _StartEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
{
// start editing the cell with the custom editor
if(!IsRoTable )
_tableCellEditor.StartEditing(e.Row, e.Col, _GettingFontSize); // C2021-005 added _GettingFontSize to prevent showing the editor
e.Cancel = true;
}
// after edit handler (built-in editors)
private void _AfterEdit(object sender, C1.Win.C1FlexGrid.RowColEventArgs e)
{
this.GetCellRange(e.Row, e.Col).Style.ForeColor = Color.Black;
this.AdjustGridControlSize();
GC.Collect(GC.GetGeneration(this)); // there is a memory leak in Regex this fixes it. (called in StepRTB.cs FindLinks)
}
// if the custom editor is visible, make it follow the cell being edited
private void _AfterScroll(object sender, C1.Win.C1FlexGrid.RangeEventArgs e)
{
this._tableCellEditor.UpdatePosition();
}
// save last key pressed for the custom editor
private void _KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
this._tableCellEditor.SetPendingKey(e.KeyChar);
}
public string GetCellRTFString(int row, int col)
{
string rtnstr = "";
foreach (CellRange r in this.MergedRanges)
{
if (r.ContainsRow(row) && r.ContainsCol(col))
{
rtnstr = (string)this[r.r1, r.c1];
return rtnstr;
}
}
rtnstr = (string)this[row, col];
return rtnstr;
}
public void PutCellRTFString(int row, int col, string str)
{
foreach (CellRange r in this.MergedRanges)
{
if (r.ContainsRow(row) && r.ContainsCol(col))
{
this[r.r1, r.c1] = str;
return;
}
}
this[row, col] = str;
return;
}
public void ClearSelectedCellText()
{
CellRange cr = this.Selection;
cr.Clear(ClearFlags.Content);
}
public void SetupCellUserData()
{
for (int r = 0; r < Rows.Count; r++)
for (int c = 0; c < Cols.Count; c++)
{
string rtfText = GetDataDisplay(r, c);
if (rtfText.StartsWith(@"{\rtf"))
{
using (StepRTB _rtf = new StepRTB())
{
_rtf.Width = Cols[c].Width;
_rtf.Rtf = rtfText;
CellRange cr = GetCellRange(r, c);
cr.UserData = _rtf.ContentsRectangle.Height;
}
}
}
}
#endregion //Cell Text
#region Merged / Split Range
public void MergeSelection()
{
this.MergedRanges.Add(this.Selection,true);
this.Invalidate();
this.Select(Selection.r1, Selection.c1);
}
public bool IsInMergeRange()
{
C1.Win.C1FlexGrid.CellRange sel = GetMergedRange(this.Selection.r1, this.Selection.c1);
return MergedRanges.Contains(sel);
}
public void SplitSelection(bool bSplitCols)
{
//Console.WriteLine("SplitSelection this.selection {0}", this.Selection);
//Debug_WritelineMySelection();
//C1.Win.C1FlexGrid.CellRange sel = this.GetMergedRange(this.Selection.r1, this.Selection.c1);
//Console.WriteLine("SplitSelection myselection {0}", MySelection);
//foreach (CellRange sel in MySelection)
//{
// //Console.WriteLine("SplitSelection foreach sel {0}", sel);
// if (sel.IsSingleCell)
// this.MergedRanges.Remove(sel);
// if (!(this.MergedRanges.Contains(sel)) && !didit)
// if (bSplitCols)
// SplitSelectionColumns();
// else
// SplitSelectionRows();
// didit = true;
//}
if (bSplitCols)
SplitSelectionColumns();
else
SplitSelectionRows();
//Debug_WritelineMySelection();
//foreach (CellRange sel in MySelection)
//{
// //Console.WriteLine("SplitSelection foreach sel {0}", sel);
// if (this.MergedRanges.Contains(sel))
// SplitMergedRange(sel, bSplitCols);
//}
//this.Refresh();
//RefreshMergeRangeCollection();
this.AdjustGridControlSize();
}
private void SplitMergedRange(CellRange sel, bool bSplitCols)
{
int sR = sel.r1;
int eR = sel.r2;
int sC = sel.c1;
int eC = sel.c2;
if (bSplitCols && (IsMergedCols(sel) && !IsMergedRows(sel)) ||
(!bSplitCols && (IsMergedRows(sel) && !IsMergedCols(sel))))
MergedRanges.Remove(sel);
else
{
CellRange saveSelection = Selection;
if (bSplitCols && IsMergedRows(sel))
{
MergedRanges.Remove(sel);
for (int c = sC; c <= eC; c++)
{
Select(sR, c, eR, c);
MergeSelection();
}
}
else if (!bSplitCols && IsMergedCols(sel))
{
MergedRanges.Remove(sel);
for (int r = sR; r <= eR; r++)
{
Select(r, sC, r, eC);
MergeSelection();
}
}
Select(saveSelection);
}
}
private bool IsMergedRows(CellRange sel)
{
return (sel.r1 != sel.r2);
}
private bool IsMergedCols(CellRange sel)
{
return (sel.c1 != sel.c2);
}
private void SplitSelectionColumns()
{
bool hasNonMergedColumn = false;
//Console.WriteLine("SplitSelectionColumns this.selection {0}", this.Selection);
//Debug_WritelineMySelection();
CellRange cr = this.Selection;
int numSelCols = (cr.c2 - cr.c1) + 1;
foreach (CellRange sel in MySelection)
{
if (!this.MergedRanges.Contains(sel))
hasNonMergedColumn = true;
else
{
CellRange mr = GetMergedRange(sel.r1, sel.c1);
if (mr.c1 == mr.c2)
hasNonMergedColumn = true;
}
}
// for each column in the selection, add a new column
if (hasNonMergedColumn)
{
for (int c = cr.c2; c >= cr.c1; c--)
{
Select(cr.r1, c, cr.r2, c);
InsertColumnAfter();
}
}
// include new columns in selection
this.Select(cr.r1, cr.c1, cr.r2, cr.c2 + ((hasNonMergedColumn) ? numSelCols : 0));
//if a merged range is part of the selectin, try to split it
foreach (CellRange sel in MySelection)
{
//Console.WriteLine("SplitSelection foreach sel {0}", sel);
if (this.MergedRanges.Contains(sel))
SplitMergedRange(sel, true);
}
cr = this.Selection;
if (hasNonMergedColumn)
{
for (int r = 0; r < this.Rows.Count; r++)
for (int c = cr.c1; c <= cr.c2; c += 2)
{
if (!this.IsCellSelected(r, c))
{
CellRange crTmp = GetMergedRange(r, c);
if (crTmp.IsSingleCell)
{
CellRange tcr = this.GetCellRange(r, c, r, c + 1);
this.MergedRanges.Add(tcr);
this.Invalidate();
}
//CellRange tcr = this.GetCellRange(r, c, r, c + 1);
//this.MergedRanges.Add(tcr);
}
}
// Adjust selected column widths
for (int c = cr.c1; c <= cr.c2; c++)
{
int recWidth = (Cols[c].Width < 0) ? Cols.DefaultSize : Cols[c].Width; // this.GetCellRect(cr.r1, c).Width;
int newWidth = Math.Max(recWidth / 2, _minColSplitWidth);
this.Cols[c].Width = newWidth;
//Console.WriteLine("Cell[{0},{1}].Width = {2}", cr.r1, c, recWidth);
//Console.WriteLine("Cell[{0},{1}].NewWidth = {2}", cr.r1, c, newWidth);
}
}
}
private void SplitSelectionRows()
{
bool hasNonMergedRow = false;
CellRange cr = this.Selection;
int numSelRows = (cr.r2 - cr.r1) + 1;
//Console.WriteLine("numSelRows = {0}", numSelRows);
//Console.WriteLine("Inital Selection [{0},{1}] - [{2},{3}]", cr.r1, cr.c1, cr.r2, cr.c2);
foreach (CellRange sel in MySelection)
{
if (!this.MergedRanges.Contains(sel))
hasNonMergedRow = true;
else
{
CellRange mr = GetMergedRange(sel.r1, sel.c1);
if (mr.r1 == mr.r2)
hasNonMergedRow = true;
}
}
// for each row in the selection, add a new row
if (hasNonMergedRow)
{
for (int r = cr.r2; r >= cr.r1; r--)
{
//Console.WriteLine("Inserted new Row at [{0},{1}]", r, cr.c1);
Select(r, cr.c1, r, cr.c2);
InsertRowAfter();
}
// B2017-197 move the Select inside if (hasNonMergedRow)
// was getting a selection out of range error when spliting rows that contained mergered rows
// only need to do this if we inserted rows
// include new rows in selection
this.Select(cr.r1, cr.c1, cr.r2 + numSelRows, cr.c2);
}
//if a merged range is part of the selectin, try to split it
foreach (CellRange sel in MySelection)
{
//Console.WriteLine("SplitSelection foreach sel {0}", sel);
if (this.MergedRanges.Contains(sel))
SplitMergedRange(sel, false);
}
cr = this.Selection;
//Console.WriteLine(" After Insert [{0},{1}] - [{2},{3}]", cr.r1, cr.c1, cr.r2, cr.c2);
if (hasNonMergedRow)
{
for (int c = 0; c < this.Cols.Count; c++)
for (int r = cr.r1; r <= cr.r2; r += 2)
{
if (!this.IsCellSelected(r, c))
{
CellRange crTmp = GetMergedRange(r, c);
if (crTmp.IsSingleCell)
{
CellRange tcr = this.GetCellRange(r, c, r + 1, c);
this.MergedRanges.Add(tcr);
this.Invalidate();
}
}
}
// Adjust selected Row Heights
for (int r = cr.r1; r <= cr.r2; r++)
{
int recHeight = this.GetCellRect(r, cr.c1).Height;
this.Rows[r].Height = Math.Max(recHeight / 2, Rows.DefaultSize);
//this.Rows[r].Height = Math.Max(recHeight / 2, _minRowSplitHeight);
//Console.WriteLine("Cell[{0},{1}].Height = {2}", r, cr.c1, recHeight);
}
}
//foreach (CellRange crng in this.MergedRanges)
// Console.WriteLine("merge ranges [{0},{1}] - [{2},{3}]", crng.r1, crng.c1, crng.r2, crng.c2);
}
private void AdjustMergedRows(int row, bool above, bool removing)
{
AdjustMergedRows(row, 1, above, removing);
}
private void AdjustMergedRows(int row, int cnt, bool above, bool removing)
{
CellRangeCollection crc = new CellRangeCollection(this);
if (removing)
{
foreach (CellRange r in this.MergedRanges)
{
CellRange cr = r;
if (r.ContainsRow(row))
{
if (r.TopRow != r.BottomRow)
{
cr.r2 -= cnt;
crc.Add(cr);
}
}
else
{
if (row <= r.r1)
{
if (row < r.r1)
cr.r1 -= cnt;
cr.r2 -= cnt;
}
crc.Add(cr);
}
}
}
else // adding
foreach (CellRange r in this.MergedRanges)
{
CellRange cr = r;
int inspos = (above) ? row : row - 1;
if (r.ContainsRow(inspos))
{
bool adjustMergeValues = true;
if (cr.r1 == row && cr.r2 == row + cnt -1)
adjustMergeValues = false; // don't add to existing merge range - we will add a new merge range for this copy
for (int insCnt = 0; insCnt < cnt; insCnt++)
{
if ((above && cr.r1 == inspos) || (!above && cr.r2 == inspos))
{
string tstr = "";
int newrow = 0;
if (above)
{
if (this[cr.r1 + cnt, cr.c1] != null)
tstr = this[cr.r1 + cnt, cr.c1].ToString();
newrow = cr.r1;
}
else
{
if (this[cr.r2, cr.c1] != null)
tstr = this[cr.r2, cr.c1].ToString();
newrow = cr.r2 + cnt;
}
if (tstr != null && tstr.Length > 0)
for (int x = cr.c1; x <= cr.c2; x++)
this[newrow, x] = tstr;
}
if (adjustMergeValues) cr.r2++;
}
}
else
{
if (inspos < cr.r1)
{
cr.r1 += cnt;
cr.r2 += cnt;
}
}
crc.Add(cr);
}
this.MergedRanges.Clear();
foreach (CellRange r in crc)
{
if ((r.r1 != r.r2) || (r.c1 != r.c2))
this.MergedRanges.Add(r);
}
}
private void AdjustMergedColumns(int col, bool left, bool removing)
{
AdjustMergedColumns(col, 1, left, removing); //adjusting for just one column
}
private void AdjustMergedColumns(int col, int cnt, bool left, bool removing)
{
CellRangeCollection crc = new CellRangeCollection(this);
if (removing)
{
foreach (CellRange r in this.MergedRanges)
{
CellRange cr = r;
if (r.ContainsCol(col))
{
if (r.LeftCol != r.RightCol)
{
cr.c2 -= cnt;
crc.Add(cr);
}
}
else
{
if (col < cr.c1)
{
cr.c1-=cnt;
cr.c2-=cnt; }
crc.Add(cr);
}
}
}
else // adding
foreach (CellRange r in this.MergedRanges)
{
CellRange cr = r;
int inspos = (left) ? col : col - 1;
if (r.ContainsCol(inspos))
{
for (int insCnt = 0; insCnt < cnt; insCnt++)
{
string tstr = "";
int newcol = 0;
if (left)
{
if (inspos == cr.c1)
tstr = (this[cr.r1, cr.c1 + 1] == null) ? "" : this[cr.r1, cr.c1 + 1].ToString();
else
tstr = (this[cr.r1, cr.c1] == null) ? "" : this[cr.r1, cr.c1].ToString();
newcol = cr.c1;
}
else
{
if (this[cr.r1, cr.c2] != null)
tstr = this[cr.r1, cr.c2].ToString();
newcol = cr.c2 + 1;
}
for (int x = cr.r1; x <= cr.r2; x++)
this[x, newcol] = tstr;
cr.c2++;
}
}
else if (col <= r.c1)
{
cr.c1+=cnt;
cr.c2+=cnt;
}
crc.Add(cr);
}
this.MergedRanges.Clear();
foreach (CellRange r in crc)
{
if ((r.r1 != r.r2) || (r.c1 != r.c2))
this.MergedRanges.Add(r);
}
}
private bool RowIsInMergeRange(int row)
{
bool rtn = false;
if (row >= 0)
{
CellRange cr = this.Selection;
//rtn = true; // KBR: is this wrong, i.e. should it be like ColIsInMergeRange
int c = cr.c1;
while (!rtn && (c <= cr.c2))
{
int idx = this.MergedRanges.IndexOf(row, c);
rtn = (idx > -1);
c++;
}
}
return rtn;
}
private bool ColIsInMergeRange(int col)
{
bool rtn = false;
if (col >= 0)
{
CellRange cr = this.Selection;
//rtn = true;
int r = cr.r1;
while (!rtn && (r <= cr.r2))
{
int idx = this.MergedRanges.IndexOf(r, col);
rtn = (idx > -1);
r++;
}
}
return rtn;
}
#endregion //Merged / Split Range
#region Grid Add and Remove Row / Column
private int GetRowInsertPosition(Boolean before)
{
int rtnrow;
CellRange selcr = this.Selection;
CellRange cr = selcr;
int idx = this.MergedRanges.IndexOf(cr.r1, cr.c2);
if (idx > -1)
cr = this.MergedRanges[idx]; // we want first or last row in merge range
rtnrow = (before) ? cr.r1 : cr.r2;
// The following is an adjustment needed when we are copying an entire row that includes some merged cells
if (selcr.c1 != selcr.c2)
{
while (!before && rtnrow > selcr.r2) rtnrow--;
while (before && rtnrow < selcr.r2) rtnrow++;
}
return rtnrow;
}
private int GetColInsertPosition(Boolean before)
{
int rtncol;
CellRange selcr = this.Selection;
CellRange cr = selcr;
int idx = this.MergedRanges.IndexOf(cr.r1, cr.c2);
if (idx > -1)
cr = this.MergedRanges[idx]; // we want the first of last col in merge range
rtncol = (before) ? cr.c1 : cr.c2;
// The following is an adjustment needed when we are copying an entire column that includes some merged cells
if (selcr.r1 != selcr.r2)
{
while (!before && rtncol > selcr.c2) rtncol--;
while (before && rtncol < selcr.c2) rtncol++;
}
return rtncol;
}
public void InsertColumnBefore()
{
int newcol = this.GetColInsertPosition(true);
this.Cols.Insert(newcol);
// set new column width to same width as column from where it was inserted
this.Cols[newcol].Width = this.Cols[newcol + 1].Width;
MyBorders.InsertColumn(newcol);
MyShading.InsertColumn(newcol); // C2021-004 table cell shading
this.AdjustMergedColumns(newcol, true, false);
this.AdjustGridControlSize();
}
public void InsertColumnAfter()
{
int colidx = this.GetColInsertPosition(false);
if (colidx == this.Cols.Count - 1) // last column
this.Cols.Add(1);
else
this.Cols.Insert(colidx + 1);
MyBorders.InsertColumn(colidx);
MyShading.InsertColumn(colidx); // C2021-004 table cell shading
// set new column width to same width as column from where it was inserted
this.Cols[colidx + 1].Width = this.Cols[colidx].Width;
this.AdjustMergedColumns(colidx + 1, false, false);
this.AdjustGridControlSize();
}
public void InsertRowBefore()
{
int newrow = this.GetRowInsertPosition(true);
this.Rows.Insert(newrow);
// set new row Height to same heidht as row from where it was inserted
this.Rows[newrow].Height = (Rows[newrow + 1].Height == -1) ? Rows.DefaultSize : Rows[newrow + 1].Height;
//this.Rows[newrow].Height = this.Rows[newrow + 1].Height;
MyBorders.InsertRow(newrow);
MyShading.InsertRow(newrow); // C2021-004 table cell shading
this.AdjustMergedRows(newrow, true, false);
this.AdjustGridControlSize();
}
public void InsertRowAfter()
{
int rowidx = this.GetRowInsertPosition(false);
if (rowidx == this.Rows.Count - 1) // last row
this.Rows.Add(1);
else
this.Rows.Insert(rowidx + 1);
// set new row Height to same heidht as row from where it was inserted
this.Rows[rowidx + 1].Height = (Rows[rowidx].Height == -1) ? Rows.DefaultSize : Rows[rowidx].Height;
//this.Rows[rowidx + 1].Height = this.Rows[rowidx].Height;
MyBorders.InsertRow(rowidx + 1);
MyShading.InsertRow(rowidx + 1); // C2021-004 table cell shading
this.AdjustMergedRows(rowidx + 1, false, false);
this.AdjustGridControlSize();
}
public bool AllRowsSelected()
{
int maxrow = Selection.r2;
foreach (CellRange cr in MySelection)
maxrow = Math.Max(maxrow, cr.r2);
return (Selection.r1 == 0 && maxrow == Rows.Count - 1);
}
public bool AllColumnsSelected()
{
int maxcol = Selection.c2;
foreach (CellRange cr in MySelection)
maxcol = Math.Max(maxcol, cr.c2);
return (Selection.c1 == 0 && maxcol == Cols.Count - 1);
}
public void RemoveSelectedColumn()
{
string msg = "";
string title = "";
CellRange saveCR = Selection;
this.SelectionMode = SelectionModeEnum.ColumnRange;
//this.Select(this.Selection.r1, this.Selection.c1);
this.Select(0, Selection.c1, Rows.Count - 1, Selection.c2);
this.SelectionMode = SelectionModeEnum.Default;
if (Selection.c1 != Selection.c2)
{
msg = "Remove selected columns?";
title = "Delete Columns";
}
else
{
msg = "Remove this column?";
title = "Delete Column";
}
DialogResult dr = FlexibleMessageBox.Show(msg, title, MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
RemoveColumns(this.Selection.r1, this.Selection.c1, 1+this.Selection.c2-this.Selection.c1);
else
Select(saveCR);
}
public void RemoveSelectedRow()
{
string msg = "";
string title = "";
CellRange saveCR = Selection;
this.SelectionMode = SelectionModeEnum.RowRange;
this.Select(Selection.r1, 0, Selection.r2, Cols.Count - 1);
this.SelectionMode = SelectionModeEnum.Default;
if (Selection.r1 != Selection.r2)
{
msg = "Remove selected rows?";
title = "Delete Rows";
}
else
{
msg = "Remove this row?";
title = "Delete Row";
}
DialogResult dr = FlexibleMessageBox.Show(msg, title, MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
this.RemoveRows(this.Selection.r1, this.Selection.c1, 1 + this.Selection.r2 - this.Selection.r1);
else
Select(saveCR);
}
private void RemoveRows(int strow, int stcol, int cnt)
{
bool mergedRow = false;
for (int i = 0; i < cnt; i++)
{
for (int cl = 0; cl < this.Cols.Count && !mergedRow; cl++)
{
int idx = this.MergedRanges.IndexOf(strow, cl);
if (idx > -1)
{
CellRange cr = this.MergedRanges[idx];
if (cr.r1 < cr.r2)
mergedRow = true;
}
cl++;
}
this.Rows.Remove(strow);
this.AdjustMergedRows(strow, false, true);
mergedRow = false;
}
MyBorders.DeleteRows(strow, cnt);
MyShading.DeleteRows(strow, cnt); // C2021-004 table cell shading
this.AdjustGridControlSize();
}
private void RemoveColumns(int strow, int stcol, int cnt)
{
bool mergedCol = false;
for (int i = 0; i < cnt; i++)
{
for (int rw = 0; rw < this.Rows.Count && !mergedCol; rw++)
{
int idx = this.MergedRanges.IndexOf(rw, stcol);
if (idx > -1)
{
CellRange cr = this.MergedRanges[idx];
if (cr.c1 < cr.c2)
mergedCol = true;
}
}
this.Cols.Remove(stcol);
this.AdjustMergedColumns(stcol, false, true);
mergedCol = false;
}
MyBorders.DeleteColumns(stcol, cnt);
MyShading.DeleteColumns(stcol, cnt); // C2021-004 table cell shading
this.AdjustGridControlSize();
}
#endregion //Grid Add and Remove Row / Column
#region Copy/Paste
public void CopyRow()
{
_tableCellEditor.Hide(); // B2017-200 force save of changes from active edit session
DialogResult dr = DialogResult.Yes;
SelectRow();
if (Selection.r1 != Selection.r2)
{
//dr = MessageBox.Show("You selected a row that includes merged cells.\n\nThese additional rows must be included.\n\nCopy these rows?", "Copy Rows", MessageBoxButtons.YesNo);
dr = FlexibleMessageBox.Show("Your selection was expanded due to merged cell regions.\n\nContinue with the copy?", "Copy Rows", MessageBoxButtons.YesNo);
}
if (dr == DialogResult.Yes)
CopyToCopiedFlexGrid(GridCopyOption.Row);
//TestSetBackgroundColor();
}
//public void TestSetBackgroundColor()
//{
// for (int r = Selection.r1; r <= Selection.r2; r++)
// for (int c = Selection.c1; c <= Selection.c2; c++)
// {
// CellRange cr = GetMergedRange(r, c);
// if (cr.Style == null) cr.Style = this.Styles.Add("Shading");
// if (cr.Style != null && cr.Style.BackColor != Color.DarkGreen && cr.Style.Name != "Fixed")
// {
// {
// cr.Style.BackColor = Color.DarkGreen;
// }
// }
// }
//}
public void CopyColumn()
{
_tableCellEditor.Hide(); // B2017-200 force save of changes from active edit session
SelectCol();
DialogResult dr = DialogResult.Yes;
if (Selection.c1 != Selection.c2)
{
//dr = MessageBox.Show("You selected a column that includes merged cells.\n\nThese additional columns must be included.\n\nCopy these columns?", "Copy Columns", MessageBoxButtons.YesNo);
dr = FlexibleMessageBox.Show("Your selection was expanded due to merged cell regions.\n\nContinue with the copy?", "Copy Columns", MessageBoxButtons.YesNo);
}
if (dr == DialogResult.Yes)
CopyToCopiedFlexGrid(GridCopyOption.Column);
}
public void CopyCellSelection()
{
_tableCellEditor.Hide(); // B2017-200 force save of changes from active edit session
DialogResult dr = DialogResult.Yes;
CellRange cr = Selection;
MakeSelectionEven();
if (!cr.Equals(Selection))
{
dr = FlexibleMessageBox.Show("Your selection was expanded due to merged cell regions.\n\nContinue with the copy?", "Copy Selection", MessageBoxButtons.YesNo);
}
if (dr == DialogResult.Yes)
CopyToCopiedFlexGrid(GridCopyOption.Selection);
}
public enum enmPastePos : int
{
Before = 1, Replace = 0, After = -1
}
public void PasteRows(enmPastePos pp)
{
if (MyCopyInfo.MyCopiedFlexGrid == null || MyCopyInfo.MyCopyOption != GridCopyOption.Row) return;
int rowsToAdd = MyCopyInfo.MyCopiedCellRange.r2 - MyCopyInfo.MyCopiedCellRange.r1 + 1;
int colsToAdd = Math.Max((MyCopyInfo.MyCopiedCellRange.c2 - MyCopyInfo.MyCopiedCellRange.c1 + 1) - Cols.Count, 0);
int selR1 = Selection.r1;
int selR2 = Selection.r2;
int rowOffset = selR1 + (pp == enmPastePos.After ?(selR2-selR1)+1 : 0) - MyCopyInfo.MyCopiedCellRange.r1;
// If the rows we are copying has more columns than the current table, then append then needed columns to the grid
if (colsToAdd > 0)
{
Cols.Add(colsToAdd);
AdjustMergedColumns(Cols.Count - 1, colsToAdd, false, false);
MyBorders.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd);
MyShading.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd); // C2021-004 table cell shading
}
switch (pp)
{
case enmPastePos.Before:
this.Rows.InsertRange(selR1, rowsToAdd);
AdjustMergedRows(selR1, rowsToAdd, true, false);
MyBorders.InsertRows(Rows.Count - rowsToAdd - 1, rowsToAdd);
MyShading.InsertRows(Rows.Count - rowsToAdd - 1, rowsToAdd); // C2021-004 table cell shading
break;
case enmPastePos.After:
if (selR2+1 < Rows.Count - 1)
{
this.Rows.InsertRange(selR2 + 1, rowsToAdd);
AdjustMergedRows(selR1+1, rowsToAdd, false, false);
}
else
this.Rows.Add(rowsToAdd);
MyBorders.InsertRows(Rows.Count - rowsToAdd - 1, rowsToAdd);
MyShading.InsertRows(Rows.Count - rowsToAdd - 1, rowsToAdd); // C2021-004 table cell shading
break;
case enmPastePos.Replace:
if (rowsToAdd > Rows.Count - Selection.r1)
{
int numToAdd = rowsToAdd - (Rows.Count = selR1);
this.Rows.Add(numToAdd);
AdjustMergedRows(selR1, numToAdd, false, false);
}
break;
}
RemoveMergedRanges(MyCopyInfo.MyCopiedCellRange.r1 + rowOffset, MyCopyInfo.MyCopiedCellRange.c1, MyCopyInfo.MyCopiedCellRange.r2 + rowOffset, MyCopyInfo.MyCopiedCellRange.c2);
for (int r = MyCopyInfo.MyCopiedCellRange.r1; r <= MyCopyInfo.MyCopiedCellRange.r2; r++)
{
Rows[r + rowOffset].Height = MyCopyInfo.MyCopiedFlexGrid.Rows[r].Height;
for (int c = MyCopyInfo.MyCopiedCellRange.c1; c <= Math.Min(MyCopyInfo.MyCopiedCellRange.c2 + colsToAdd, Cols.Count - 1); c++)
{
CellRange crm = MyCopyInfo.MyCopiedFlexGrid.GetMergedRange(r, c);
if (r == crm.r1 && c == crm.c1)
{
Cols[c].Width = Math.Max(Cols[c].Width, MyCopyInfo.MyCopiedFlexGrid.Cols[c].Width);
CellRange cr = GetCellRange(crm.r1 + rowOffset, crm.c1, crm.r2 + rowOffset, crm.c2);
// if the paste is above - copy merge range for the destination
// if the paste is below - put back the range for the source location
if ((crm.r2 > crm.r1) || (crm.c2 > crm.c1))
MergedRanges.Add(cr);
// B2022-046 if the cell contains an RO or Transition then replace the usage id with <NewID> to force a new usage id in the link
if (MyCopyInfo.MyCopiedFlexGrid[r, c] != null)
this[r + rowOffset, c] = ItemInfo.ReplaceLinkWithNewID(MyCopyInfo.MyCopiedFlexGrid[r, c].ToString().Replace("\r\n", ""));
else
this[r + rowOffset, c] = MyCopyInfo.MyCopiedFlexGrid[r, c];
MatchStyle(crm, cr);
PasteBorders(r + rowOffset, c, r, c);
PasteShading(r + rowOffset, c, r, c); // C2021-004 paste the shading information
// if the paste is above - put back the range for the source location
// if the paste is below - copy merge range for the destination
int r1 = crm.r1 + rowsToAdd - rowOffset;
int r2 = crm.r2 + rowsToAdd - rowOffset;
CellRange ncr = GetCellRange(r1, crm.c1, r2, crm.c2);
if ((crm.r2 > crm.r1) || (crm.c2 > crm.c1))
MergedRanges.Add(ncr);
}
}
}
this.AdjustGridControlSize();
CopyToCopiedFlexGrid(MyCopyInfo.MyCopyOption);
}
private void MatchStyle(CellRange crm, CellRange cr)
{
if (crm.Style != null)
{
ChangeCellAlign(cr, crm.Style.TextAlign);
ChangeCellBorder(cr, crm.Style.Border.Style);
}
//else
//{
// cr.Style = null; // - didn't like the null
//}
}
private void RemoveMergedRanges(int r1, int c1, int r2, int c2)
{
for (int r = r1; r <= r2; r++)
for (int c = c1; c <= c2; c++)
{
CellRange cr = GetMergedRange(r, c);
if (cr.r1 < cr.r2 || cr.c1 < cr.c2)
MergedRanges.Remove(cr);
}
}
public void PasteColumns(enmPastePos pp)
{
if (MyCopyInfo.MyCopiedFlexGrid == null || MyCopyInfo.MyCopyOption != GridCopyOption.Column) return;
int colsToAdd = MyCopyInfo.MyCopiedCellRange.c2 - MyCopyInfo.MyCopiedCellRange.c1 + 1;
int rowsToAdd = Math.Max((MyCopyInfo.MyCopiedCellRange.r2 - MyCopyInfo.MyCopiedCellRange.r1 + 1) - Rows.Count, 0);
int selC1 = Selection.c1;
int selC2 = Selection.c2;
int colOffset = selC1 + (pp == enmPastePos.After ? (selC2-selC1)+1 : 0) - MyCopyInfo.MyCopiedCellRange.c1;
// If the columns we are copying has more rows than the current table, then append the needed rows to the grid
if (rowsToAdd > 0)
{
Rows.Add(rowsToAdd);
AdjustMergedRows(Rows.Count, false, false);
MyBorders.InsertRows(Rows.Count - rowsToAdd - 1,rowsToAdd);
MyShading.InsertRows(Rows.Count - rowsToAdd - 1, rowsToAdd); // C2021-004 table cell shading
}
switch (pp)
{
case enmPastePos.Before:
this.Cols.InsertRange(selC1, colsToAdd);
AdjustMergedColumns(selC1, colsToAdd, true, false);
MyBorders.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd);
MyShading.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd); // C2021-004 table cell shading
break;
case enmPastePos.After:
if (selC2+1 < Cols.Count - 1)
{
this.Cols.InsertRange(selC2+1, colsToAdd);
AdjustMergedColumns(selC1+1, colsToAdd, false, false);
}
else
this.Cols.Add(colsToAdd);
MyBorders.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd);
MyShading.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd); // C2021-004 table cell shading
break;
case enmPastePos.Replace:
if (colsToAdd > Cols.Count - selC1)
{
int numToAdd = colsToAdd - (Cols.Count - selC1);
this.Cols.Add(numToAdd);
AdjustMergedColumns(selC1, numToAdd, true, false);
}
break;
}
RemoveMergedRanges(MyCopyInfo.MyCopiedCellRange.r1, MyCopyInfo.MyCopiedCellRange.c1 + colOffset, MyCopyInfo.MyCopiedCellRange.r2, MyCopyInfo.MyCopiedCellRange.c2 + colOffset);
// Fix the merge ranges
for (int c = MyCopyInfo.MyCopiedCellRange.c1; c <= MyCopyInfo.MyCopiedCellRange.c2; c++)
{
Cols[c + colOffset].Width = MyCopyInfo.MyCopiedFlexGrid.Cols[c].Width;
for (int r = MyCopyInfo.MyCopiedCellRange.r1; r <= Math.Min(MyCopyInfo.MyCopiedCellRange.r2 + rowsToAdd, Rows.Count - 1); r++)
{
CellRange crm = MyCopyInfo.MyCopiedFlexGrid.GetMergedRange(r, c);
if (r == crm.r1 && c == crm.c1)
{
Rows[r].Height = Math.Max(Rows[r].Height, MyCopyInfo.MyCopiedFlexGrid.Rows[r].Height);
CellRange cr = GetCellRange(crm.r1, crm.c1 + colOffset, crm.r2, crm.c2 + colOffset);
// if the paste is to the left - copy merge range for the destination
// if the paste is to the right - put back the range for the source location
if ((crm.r2 > crm.r1) || (crm.c2 > crm.c1))
MergedRanges.Add(cr);
// copy cell text to the destination, copy the style, copy the cell borders
// B2022-046 if the cell contains an RO or Transition then replace the usage id with <NewID> to force a new usage id in the link
if (MyCopyInfo.MyCopiedFlexGrid[r, c] != null)
this[r, c + colOffset] = ItemInfo.ReplaceLinkWithNewID(MyCopyInfo.MyCopiedFlexGrid[r, c].ToString().Replace("\r\n", ""));
else
this[r, c + colOffset] = MyCopyInfo.MyCopiedFlexGrid[r, c];
MatchStyle(crm, cr);
PasteBorders(r, c + colOffset, r, c);
PasteShading(r, c + colOffset, r, c); // C2021-004 paste the shading information
// if the paste is to the left - put back the range for the source location
// if the paste is to the right - copy merge range for the destination
int c1 = crm.c1 + colsToAdd - colOffset;
int c2 = crm.c2 + colsToAdd - colOffset;
CellRange ncr = GetCellRange(crm.r1, c1, crm.r2, c2);
if ((crm.r2 > crm.r1) || (crm.c2 > crm.c1))
MergedRanges.Add(ncr);
}
}
}
this.AdjustGridControlSize();
CopyToCopiedFlexGrid(MyCopyInfo.MyCopyOption);
}
public void PasteCopiedCells()
{
// Warn the user that this type of paste will replace the currently selected (highlighted) table cells and give the option to abort.
DialogResult dr = FlexibleMessageBox.Show("This will replace the cells that are currently selected (highlighted). \n\nContinue with the paste?", "Paste Table Cells", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dr == DialogResult.No) return;
int nSelRows = Selection.r2 - Selection.r1 + 1;
int nSelCols = Selection.c2 - Selection.c1 + 1;
int nCpyRows = MyCopyInfo.MyCopiedCellRange.r2 - MyCopyInfo.MyCopiedCellRange.r1 + 1;
int nCpyCols = MyCopyInfo.MyCopiedCellRange.c2 - MyCopyInfo.MyCopiedCellRange.c1 + 1;
int colsToAdd = Math.Max(nCpyCols - nSelCols, 0);
int rowsToAdd = Math.Max(nCpyRows - nSelRows, 0);
int rowOffset = Selection.r1 - MyCopyInfo.MyCopiedCellRange.r1;
int colOffset = Selection.c1 - MyCopyInfo.MyCopiedCellRange.c1;
int selR2 = Selection.r2;
int selC2 = Selection.c2;
// If there are more cells to copy than what is seleceted in the target table
// Add extra rows and columns as needed
if (rowsToAdd > 0)
{
if (selR2 < Rows.Count - 1)
{
this.Rows.InsertRange(selR2 + 1, rowsToAdd);
AdjustMergedRows(selR2 + 1, false, false);
}
else
this.Rows.Add(rowsToAdd);
MyBorders.InsertRows(selR2,rowsToAdd);
MyShading.InsertRows(selR2, rowsToAdd); // C2021-004 table cell shading
}
if (colsToAdd > 0)
{
if (selC2 < Cols.Count - 1)
{
this.Cols.InsertRange(selC2 + 1, colsToAdd);
AdjustMergedColumns(selC2 + 1, false, false);
}
else
this.Cols.Add(colsToAdd);
MyBorders.InsertColumns(selC2,colsToAdd);
MyShading.InsertColumns(selC2, colsToAdd); // C2021-004 table cell shading
}
RemoveMergedRanges(MyCopyInfo.MyCopiedCellRange.r1 + rowOffset, MyCopyInfo.MyCopiedCellRange.c1 + colOffset, MyCopyInfo.MyCopiedCellRange.r2 + rowOffset, MyCopyInfo.MyCopiedCellRange.c2 + colOffset);
for (int c = MyCopyInfo.MyCopiedCellRange.c1; c <= Math.Min(MyCopyInfo.MyCopiedCellRange.c2, Cols.Count - 1 - colOffset); c++)
Cols[c + colOffset].Width = Math.Max(MyCopyInfo.MyCopiedFlexGrid.Cols[c].Width, Cols[c + colOffset].Width);
for (int r = MyCopyInfo.MyCopiedCellRange.r1; r <= Math.Min(MyCopyInfo.MyCopiedCellRange.r2, Rows.Count - 1 - rowOffset); r++)
{
Rows[r + rowOffset].Height = Math.Max(MyCopyInfo.MyCopiedFlexGrid.Rows[r].Height, Rows[r + rowOffset].Height);
for (int c = MyCopyInfo.MyCopiedCellRange.c1; c <= Math.Min(MyCopyInfo.MyCopiedCellRange.c2, Cols.Count - 1 - colOffset); c++)
{
CellRange crm = MyCopyInfo.MyCopiedFlexGrid.GetMergedRange(r, c);
if (r == crm.r1 && c == crm.c1)
{
CellRange cr = GetCellRange(crm.r1 + rowOffset, crm.c1 + colOffset, crm.r2 + rowOffset, crm.c2 + colOffset);
if ((crm.r2 > crm.r1) || (crm.c2 > crm.c1))
MergedRanges.Add(cr);
// B2022-046 if the cell contains an RO or Transition then replace the usage id with <NewID> to force a new usage id in the link
if (MyCopyInfo.MyCopiedFlexGrid[r, c] != null)
this[r + rowOffset, c + colOffset] = ItemInfo.ReplaceLinkWithNewID(MyCopyInfo.MyCopiedFlexGrid[r, c].ToString().Replace("\r\n", ""));
else
this[r + rowOffset, c + colOffset] = MyCopyInfo.MyCopiedFlexGrid[r, c];
MatchStyle(crm, cr);
PasteBorders(r + rowOffset, c + colOffset, r, c);
PasteShading(r + rowOffset, c + colOffset, r, c); // C2021-004 paste the shading information
}
}
}
this.AdjustGridControlSize();
CopyToCopiedFlexGrid(MyCopyInfo.MyCopyOption);
}
#endregion // Copy/Paste
#region Selection
public bool SelectNextCell()
{
int r = this.Row;
int c = this.Col;
CellRange cr = GetMergedRange(r, c);
do
{
c = cr.c2 + 1;
if (c >= this.Cols.Count)
{
r = r + 1;
c = 0;
if (r >= this.Rows.Count) return false;
}
cr = GetMergedRange(r, c);
} while (r != cr.r1 || c != cr.c1);
Select(r, c);
return true;
}
public bool SelectPrevCell()
{
int r = this.Row;
int c = this.Col;
CellRange cr = GetMergedRange(r, c);
do
{
c = cr.c1 - 1;
if (c < 0)
{
r = r - 1;
c = this.Cols.Count-1;
if (r < 0) return false;
}
cr = GetMergedRange(r, c);
c = cr.c1;
} while (r != cr.r1);
Select(r, c);
return true;
}
#endregion
#region SearchableText
public string GetSearchableText()
{
StringBuilder sb = new StringBuilder();
int r = 0;
int c = 0;
int w = Cols.Count;
int h = Rows.Count;
while (r < h)
{
CellRange cr = GetMergedRange(r, c);
if (cr.r1 == r && cr.c1 == c)
{
if (this[r, c] != null)
{
string strp = DisplayText.StaticStripRtfCommands((string)this[r, c], true); // C2020-001: added 'true', in a table
sb.Append(strp.Replace("\r\n", " "));
}
sb.Append("\r\n");
}
c = c + 1;
if (c == w)
{
c = 0;
r = r + 1;
}
}
return sb.ToString();
}
#endregion
#region Import / Export Grid
/// <summary>
/// Prompts user with Save File dialog.
/// Grid will be saved to an XML file.
/// </summary>
/// <param name="initDir"></param>
public void ExportToXML(string initDir)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = ".xml";
sfd.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.* ";
//sfd.InitialDirectory = @"C:\Development\SampleTableData";
sfd.InitialDirectory = initDir;
sfd.Title = "Save XML File";
sfd.ShowDialog();
this.WriteXml(sfd.FileName);
}
public string GetXMLData()
{
string retstr = null;
using (StringWriter sw = new StringWriter())
{
this.WriteXml(sw);
retstr = sw.GetStringBuilder().ToString();
sw.Close();
}
return retstr;
}
/// <summary>
/// Prompts user with Save File dialog.
/// Grid will be saved to an Excel file.
/// </summary>
/// <param name="initDir"></param>
public void ExportToExcel(string initDir)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = ".xls";
sfd.Filter = "Excel files (*.xls)|*.xls|All files (*.*)|*.* ";
//sfd.InitialDirectory = @"C:\Development\SampleTableData";
sfd.InitialDirectory = initDir;
sfd.Title = "Save Excel File";
sfd.ShowDialog();
this.SaveExcel(sfd.FileName);
}
/// <summary>
/// Prompts user with Open File dialog.
/// XML file will be imported to a table grid.
/// </summary>
/// <param name="initDir"></param>
/// <returns></returns>
public string ImportXML(string initDir)
{
string rtn = "";
OpenFileDialog ofd = new OpenFileDialog();
ofd.DefaultExt = ".xml";
ofd.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.* ";
//ofd.InitialDirectory = @"C:\Development\SampleTableData";
ofd.InitialDirectory = initDir;
ofd.Multiselect = false;
ofd.Title = "Select XML File";
ofd.ShowDialog();
this.Clear();
this.MergedRanges.Clear();
this.ReadXml(ofd.FileName);
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None;
this.KeyActionTab = KeyActionEnum.MoveAcross;
this.AdjustGridControlSize();
rtn = ofd.SafeFileName;
return rtn;
}
/// <summary>
/// Prompts user with Open File dialog.
/// Excel file will be imported to a table grid.
/// </summary>
/// <param name="initDir"></param>
/// <returns></returns>
public string ImportExcel(string initDir)
{
string rtn = "";
//VlnFlexGrid grd = rbtDefaultTable.Checked ? vlnFlexGrid2 : vlnFlexGrid3; //GetActiveGrid();
OpenFileDialog ofd = new OpenFileDialog();
ofd.DefaultExt = ".xls";
ofd.Filter = "Excel files (*.xls)|*.xls|All files (*.*)|*.*";
//ofd.InitialDirectory = @"C:\Development\SampleTableData";
ofd.InitialDirectory = initDir;
ofd.Multiselect = false;
ofd.Title = "Select Excel File";
ofd.ShowDialog();
this.Clear();
this.MergedRanges.Clear();
this.LoadExcel(ofd.FileName);
this.AdjustGridControlSize();
rtn = ofd.SafeFileName;
return rtn;
}
public static List<string> ROTableUpdate(object sender, ROFstInfoROTableUpdateEventArgs args)
{
string xml = null;
string srchtxt = null;
Content content = (Content)sender;
bool isdirty = false;
using (VlnFlexGrid myGrid = new VlnFlexGrid(content.ContentItems[0]))
{
using (StringReader sr = new StringReader(args.OldGridXml))
{
myGrid.ReadXml(sr);
sr.Close();
}
string roid = content.ContentRoUsages[0].ROID; //myGrid.ROID;
int rodbid = content.ContentRoUsages[0].RODbID; //myGrid.RODbId;
myGrid.Visible = false;
myGrid.ConvertTableROToGrid(args.ROText, rodbid, roid);
myGrid.FixTableCellsHeightWidth();
myGrid.AdjustGridControlSize();
myGrid.Visible = true;
using (StringWriter sw = new StringWriter())
{
myGrid.WriteXml(sw);
xml = sw.GetStringBuilder().ToString();
sw.Close();
}
srchtxt = myGrid.GetSearchableText();
isdirty = myGrid.IsGridChanged(args.OldGridXml, xml, false);
}
List<string> retlist = new List<string>();
retlist.Add(srchtxt);
if(isdirty)
retlist.Add(xml);
else
retlist.Add(args.OldGridXml);
return retlist;
}
public void ConvertTableROToGrid(string valtext, int rodbid, string roid)
{
VE_Font vefont = _MyItemInfo.GetItemFont();
this.Font = vefont.WindowsFont;
this.MergedRanges.Clear();
this.Clear();
this.IsRoTable = true;
this.ParseTableFromText(valtext, GridLinePattern.Single);
this.AutoSizeCols();
this.AutoSizeRows();
this.MakeRTFcells();
this.RODbId = rodbid;
this.ROID = roid;
}
private Regex _ReplaceSpaceNewLine = new Regex(@"(?<=\\[^' \\?\r\n\t]*) (?=\r\n)");
private Regex _ReplaceTokenSpaceToken = new Regex(@"(?<=\\[^' \\?\r\n\t]*) (?=\\)");
private Regex _RemoveComments = new Regex(@"\\v .*?\\v0( |$)");
private string PrepROTableText(string stepText)
{
// we need to convert some RTF command to DOS so that we can
// figure out the table size
stepText = stepText.Replace("\r", "");
stepText = stepText.Replace("\xF8", @"\'f8");
stepText = stepText.Replace(@"\par ", "\r\n");
stepText = _ReplaceTokenSpaceToken.Replace(stepText, "");
//Change Token Order to match RTB output
stepText = stepText.Replace(@"\v0\b0", @"\b0\v0");
stepText = stepText.Replace(@"\b0\ulnone", @"\ulnone\b0");
stepText = _ReplaceSpaceNewLine.Replace(stepText, "");
// Now change the Unicode symbols to DOS symbols
stepText = stepText.Replace(@"\u8209?", "-");
stepText = stepText.Replace(@"\u9586?", "\\");
stepText = stepText.Replace(@"\u9474?", "\xB3"); // Vert Line graphic character
stepText = stepText.Replace(@"\'b0", "\xB0");
stepText = stepText.Replace(@"\up2 ", "\x9566");
stepText = stepText.Replace(@"\up0 ", "\x9567");
stepText = stepText.Replace(@"\ulnone", "\xBB");
stepText = stepText.Replace(@"\ul", "\xAB");
stepText = stepText.Replace(@"\{", "{");
stepText = stepText.Replace(@"\}", "}");
stepText = stepText.Replace(@"\b0", "\xD6");
stepText = stepText.Replace(@"\b", "\xD5");
stepText = stepText.Replace(@"\u160?", "\xA0"); //hard space
stepText = stepText.Replace(@"\u916?", "\x7F"); // delta
stepText = stepText.Replace(@"\u8805?", "\xF2"); //greater than or equal
stepText = stepText.Replace(@"\u8804?", "\xF3"); // less than or equal
stepText = stepText.Replace(@"\u931?", "\xE4"); // sigma
stepText = stepText.Replace(@"\u947?", "\xE7"); // gamma
stepText = stepText.Replace(@"\u9604?", "\xFE"); // accum 2584
stepText = stepText.Replace(@"\u9679?", "\x7"); // bullet 25CF
stepText = stepText.Replace(@"\u8776?", "\xF7"); // approx eq
stepText = stepText.Replace(@"\u8773?", "\xF0"); // similar eq 2245
stepText = stepText.Replace(@"\u8730?", "\xFB"); // square root
stepText = stepText.Replace(@"\u961?", "\xE2"); // rho 3C1
stepText = stepText.Replace(@"\u960?", "\xE3"); // pi
stepText = stepText.Replace(@"\u956?", "\xE6"); // micro
stepText = stepText.Replace(@"\u948?", "\xEB"); // lower case delta
stepText = stepText.Replace(@"\u963?", "\xE5"); // lower case sigma
stepText = stepText.Replace(@"\u274?", "\x90"); // energy, 112
stepText = stepText.Replace(@"\u949?", "\xEE"); // epsilon
stepText = stepText.Replace(@"\u952?", "\xE9"); // theta, 3B8
stepText = stepText.Replace(@"\u8857?", "\xEC"); // dot in oval, 2299
stepText = stepText.Replace(@"\u964?", "\xA8"); // tau, 3C4
stepText = stepText.Replace(@"\u9830?", "\xA9"); // diamond, 2666
stepText = stepText.Replace(@"\u8593?", "\x18"); // Up Arrow - changes to \xff
stepText = stepText.Replace(@"\u8595?", "\x19"); // Down Arrow - changes to \xd6
// Fix "|" followed by a newline - this confuses the table converter
stepText = stepText.Replace(@"|\r\n", @"| \r\n");
stepText = stepText.Replace(@"|\n\r", @"| \n\r");
stepText = stepText.Replace(@"|\n", @"| \n");
// if the entire row is underlined, then remove the underline and insert a row of dashes
stepText = ConvertUnderlineToRow(stepText);
return stepText;
}
private bool IsPrintableTableChar(char c)
{
string printablSymbols = "\xB3\xA0\x7F\xF2\xF3\xE4\xE7\xFE\x07\xF7\xF0\xFB\xE2\xE3\xE6\xEB\xE5\x90\xEE\xE9\xEC\xA8\xA9\x18\x19";
return (((c > '\x1F') && (c < '\x80')) || (printablSymbols.IndexOf(c) >= 0));
}
private string ConvertUnderlineToRow(string stepText)
{
string rtnStr = "";
char[] sep = { '\n' };
string[] lines = stepText.Split(sep);
foreach (string line in lines)
{
int idx = 0;
int chrCnt = 0;
int uOnPos = -1;
int uOffPos = -1;
bool ulineOn = false;
//char curChar = line[idx];
string dashRow = "";
while (idx < line.Length && !IsPrintableTableChar(line[idx]))
{
if (line[idx] == '\xAB') //underline ON
{
ulineOn = true;
uOnPos = idx;
}
idx++;
}
while (ulineOn && idx < line.Length)
{
if (IsPrintableTableChar(line[idx]))
{
if (line[idx] == '|' || line[idx] == '\xB3')
{
dashRow += new string('-', chrCnt);
dashRow += "|";
chrCnt = 0;
}
else
chrCnt++;
idx++;
}
else
{
if (line[idx] == '\xBB') //underline OFF
{
uOffPos = idx;
ulineOn = false;
while ((idx < line.Length) && !IsPrintableTableChar(line[idx]))
{
if (line[idx] == '\xAB')
ulineOn = true;
idx++;
}
if (idx == line.Length)
ulineOn = true;
if (!ulineOn)
dashRow = "";
}
else
idx++;
}
}
string curLine = line;
curLine = curLine.Replace('\xB3', '|'); // replace graphic vert bar with DOS vert bar
if (ulineOn && idx == line.Length) // entire line is underlined, remove underline, insert row of dashes
{
curLine = curLine.Replace("\xAB", ""); // remove Underline ON
curLine = curLine.Replace("\xBB", ""); // remove Underline OFF
dashRow += new string('-', chrCnt);
dashRow = "\n" + dashRow;
}
if (rtnStr.Length > 0) rtnStr += "\n";
rtnStr += curLine;
rtnStr += dashRow;
}
return rtnStr;
}
/// <summary>
/// This will parse a string containing the ascii text of the old style VE-PROMS (16-bit) tables.
/// It will find the number of rows and columns base on newlines, vertical bars, and dashes.
/// Then it will parse the the text, place them in cells, and attempt to merge cells were needed.
/// </summary>
/// <param name="txtbuff"></param>
public void ParseTableFromText(string buff,GridLinePattern border)
{
string txtbuff = PrepROTableText(buff);
if (IsRoTable) txtbuff = _RemoveComments.Replace(txtbuff, "");
int curRow = 0;
int curCol = 0;
int maxRow = 0;
int maxCol = 0;
// Get Max Rows and Max Cols
char[] test = "|\n\x02".ToCharArray();
int idx = 0;
int idxst = 0;
int colPos = 0;
int strow = 0;
Dictionary<int, int> dicCols = new Dictionary<int, int>();
do
{
idx = txtbuff.IndexOfAny(test, idxst);
if (idx > -1)
{
switch (txtbuff[idx])
{
case '|': // end of a column
colPos = idxst - strow;
if (!dicCols.ContainsKey(colPos))
dicCols.Add(colPos, curCol);
else if (curCol > dicCols[colPos])
{
dicCols.Remove(colPos);
dicCols.Add(colPos, curCol);
}
curCol++;
break;
case '\x02':
case '\n': // end of a row
colPos = idxst - strow;
if (!dicCols.ContainsKey(colPos))
dicCols.Add(colPos, curCol);
else if (curCol > dicCols[colPos])
{
dicCols.Remove(colPos);
dicCols.Add(colPos, curCol);
}
curRow++;
strow = idx + 1;
if (curCol > maxCol)
maxCol = curCol;
curCol = 0;
break;
}
idxst = idx + 1;
if (idxst >= txtbuff.Length)
idx = -1;
}
} while (idx != -1);
if (idxst < txtbuff.Length)
{
colPos = idxst - strow;
if (!dicCols.ContainsKey(colPos))
dicCols.Add(colPos, curCol);
else if (curCol > dicCols[colPos])
{
dicCols.Remove(colPos);
dicCols.Add(colPos, curCol);
}
}
maxRow = curRow; // +1;
curRow = 0;
curCol = 0;
if (maxCol == 0) maxCol = dicCols.Count;
// The resulting Table Grid size in rows and columns
this.Cols.Count = maxCol + 1;
this.Rows.Count = maxRow + 1;
// make all rows and columns editable
this.Rows.Fixed = 0;
this.Cols.Fixed = 0;
// TableCellInfo is used to assign merge ranges
// Make a two dimensional array of TableCellinfo the same size as the table grid
TableCellInfo[,] tci = new TableCellInfo[maxRow + 1, maxCol + 1];
for (int r = 0; r <= maxRow; r++)
for (int c = 0; c <= maxCol; c++)
tci[r, c] = new TableCellInfo();
// Read in each cell of the grid
idx = 0;
idxst = 0;
colPos = 0;
strow = 0;
int prevCol = 0;
int tstidx = 0;
string tstr = "";
bool incRow = false;
do
{
idx = txtbuff.IndexOfAny(test, idxst);
if (idx > -1)
{
switch (txtbuff[idx])
{
case '|': // end of column
colPos = idxst - strow;
// based on the position of the | char, find what column we are in.
// note that this will tell us if any columns to the left were merged
// the while loop will flag cell that need to be merged
curCol = dicCols[colPos];
while (curCol > prevCol + 1)
{
tci[curRow, prevCol].MergeColRight = true;
prevCol++;
}
prevCol = curCol;
// parse out the text to be placed in the table cell
tstr = txtbuff.Substring(idxst, idx - idxst);
if (tstr.Length == 0)
tstr += " ";
// test for a string of '-' characters
for (tstidx = 0; (tstidx < tstr.Length) && (tstr[tstidx] == '-'); tstidx++) ;
if (tstidx < tstr.Length) // not a full line (row) of '-' chars
{
// take a peek at the start of the next piece of table text to parse
// if it starts with a '-' char, then flag to merge the columns up to
// this point with the same columns in the next row
if (idx < txtbuff.Length - 1 && txtbuff[idx + 1] == '-')
{
for (int c = curCol; c >= 0; c--)
if (!tci[curRow, c].ColEnd)
tci[curRow, c].MergeRowBellow = true;
}
// if this column is in a merged grouping of rows,
// get the cell text in the first cell of the merged grouping of cells
// we will append the newly parsed text to this cell's text.
int rw = curRow;
while (rw - 1 >= 0 && tci[rw - 1, curCol].MergeRowBellow) rw--;
int cl = curCol;
while (cl - 1 >= 0 && tci[rw, cl-1].MergeColRight) cl--;
//string jstr = (string)this[rw, curCol];
string jstr = (string)this[rw, cl];
if (jstr == null)
jstr = tstr;
else
jstr += ((cl==curCol)? "\n" : "") + tstr; // multi line cell
//jstr += "\n" + tstr; // multi line cell
//this[rw, curCol] = jstr;
this[rw, cl] = jstr;
//// take a peek at the start of the next piece of table text to parse
//// if it starts with a '-' char, then flag to merge the columns up to
//// this point with the same columns in the next row
//if (idx < txtbuff.Length - 1 && txtbuff[idx + 1] == '-')
//{
// for (int c = curCol; c >= 0; c--)
// if (!tci[curRow, c].ColEnd)
// tci[curRow, c].MergeRowBellow = true;
//}
//int tcol = dicCols[idx];
//// if were are that the end of the 16-bit text line, but not in the last column,
//// merge the remaining columns to the right
//if (curCol < tcol)
//{
// for (int i = curCol; i <= tcol; i++)
// tci[curRow, i].MergeColRight = true;
//}
}
else // parsed text contains all dashes
{
// take a peek at the start of the next piece of table text to parse
// if it starts with a space, return, newline, or EndOfFile char,
// then flag to merge the columns up to
// this point with the same columns in the next row
if (idx < txtbuff.Length - 1 && " \r\n\x02".IndexOf(txtbuff[idx + 1]) > 0)
{
int nextCol = (curCol + 1 > this.Cols.Count) ? curCol : curCol + 1;
if (!tci[curRow, nextCol].ColEnd)
tci[curRow, nextCol].MergeRowBellow = true;
//for (int c = nextCol; c >= 0; c--)
// if (!tci[curRow, c].ColEnd)
// tci[curRow, c].MergeRowBellow = true;
}
tci[curRow, curCol].ColEnd = true;
incRow = true;
}
break;
case '\x02': // end of file
case '\n': // new line of 16-bit table text
colPos = idxst - strow;
curCol = dicCols[colPos];
// see what column we are in - new line might occure before last grid column
strow = idx + 1;
// parse out the cell text
tstr = txtbuff.Substring(idxst, idx - idxst);
if (tstr.EndsWith("\r")) // strip off carrage return
tstr = tstr.Substring(0, tstr.Length - 1);
//tstr = tstr.TrimEnd(" ".ToCharArray());
if (tstr.Length == 0)
tstr += " ";
// test for a string of '-' characters
for (tstidx = 0; (tstidx < tstr.Length) && (tstr[tstidx] == '-'); tstidx++) ;
if (tstidx < tstr.Length) // not a full line (row) of '-' chars
{
//curCol = dicCols[colPos];
while (curCol > prevCol + 1)
{
tci[curRow, prevCol].MergeColRight = true;
prevCol++;
}
// if this column is in a merged grouping of rows,
// get the cell text in the first cell of the merged grouping of cells
// we will append the newly parsed text to this cell's text.
int rw = curRow;
while (rw - 1 >= 0 && tci[rw - 1, curCol].MergeRowBellow) rw--;
int cl = curCol;
while (cl - 1 >= 0 && tci[rw, cl-1].MergeColRight) cl--;
//string jstr = (string)this[rw, curCol];
string jstr = (string)this[rw, cl];
if (jstr == null)
jstr = tstr;
else
jstr += ((cl == curCol) ? "\n" : "") + tstr; // multi line cell
//jstr += "\n" + tstr; // multi line cell
//this[rw, curCol] = jstr;
this[rw, cl] = jstr;
}
else if (tstr.Length > 0) // parsed text is all dash characters
{
incRow = true;
if (curRow > 0 && curCol > 0) // merge the column in the previous row with this one
tci[curRow - 1, curCol].MergeRowBellow = false;
}
// if were are that the end of the 16-bit text line, but not in the last column,
// merge the remaining columns to the right
if ((curCol < maxCol) && (tstidx < tstr.Length))
{
for (int i = curCol; i < maxCol; i++)
tci[curRow, i].MergeColRight = true;
}
if (incRow)
curRow++;
curCol = 0;
incRow = false;
break;
}
idxst = idx + 1;
if (idxst >= txtbuff.Length)
idx = -1;
}
else if (idxst < txtbuff.Length - 1) // handle any remaining text not yet parsed
{
// find the curent column and merge remaining columns to the right
colPos = idxst - strow;
curCol = dicCols.Count==0?0:dicCols[colPos];
while (curCol > prevCol + 1)
{
tci[curRow, prevCol].MergeColRight = true;
prevCol++;
}
// parse out the remaining text
tstr = txtbuff.Substring(idxst);
//tstr = tstr.TrimEnd(" ".ToCharArray());
if (tstr.Length == 0)
tstr += " ";
// test for a string of '-' characters
for (tstidx = 0; (tstidx < tstr.Length) && (tstr[tstidx] == '-'); tstidx++) ;
if (tstidx < tstr.Length)
{
// if this column is in a merged grouping of rows,
// get the cell text in the first cell of the merged grouping of cells
// we will append the newly parsed text to this cell's text.
int rw = curRow;
while (rw - 1 >= 0 && tci[rw - 1, curCol].MergeRowBellow) rw--;
int cl = curCol;
while (cl - 1 >= 0 && tci[rw, cl-1].MergeColRight) cl--;
//string jstr = (string)this[rw, curCol];
string jstr = (string)this[rw, cl];
if (jstr == null)
jstr = tstr;
else
jstr += ((cl == curCol) ? "\n" : "") + tstr; // multi line cell
//jstr += "\n" + tstr; // multi line cell
//this[rw, curCol] = jstr;
this[rw, cl] = jstr;
}
}
} while (idx != -1);
// we are done parsing the 16-bit text.
// now set the merge ranges in the table grid, based on the
// information saved in that two dimensional array of TableCellinfo
this.Rows.Count = curRow + 1;
this.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.Custom;
maxRow = curRow;
int rR = 0;
int rC = 0;
for (int r = 0; r <= maxRow; r++)
for (int c = 0; c <= maxCol; c++)
{
if (tci[r, c].MergeColRight)
{
rC = c;
while ((rC < maxCol) && (tci[r, rC].MergeColRight)) rC++;
if (rC > c)
{
this.MergedRanges.Add(this.GetCellRange(r, c, r, rC));
string cellstr = (this[r,c]==null)? " ": this[r, c].ToString();
for (int x = c + 1; x <= rC; x++)
this[r, x] = cellstr;
c = rC;
}
}
}
for (int c = 0; c <= maxCol; c++)
for (int r = 0; r <= maxRow; r++)
{
if (tci[r, c].MergeRowBellow)
{
rR = r;
while ((rR < maxRow) && (tci[rR, c].MergeRowBellow)) rR++;
if (rR > r)
{
this.MergedRanges.Add(this.GetCellRange(r, c, rR, c));
string cellstr = this[r, c].ToString();
for (int x = r + 1; x <= rR; x++)
this[x, c] = cellstr;
r = rR;
}
}
}
for (int c = 0; c <= maxCol; c++)
for (int r = 0; r <= maxRow; r++)
{
if (this[r, c] != null)
{
string cellstr = this[r, c].ToString();
this[r, c] = cellstr.TrimEnd("\r\n\t".ToCharArray());
//this[r, c] = cellstr.TrimEnd(" \r\n\t".ToCharArray());
CellRange cr = this.GetMergedRange(r, c);
if (cr.r1 != cr.r2)
TrimMergedRangeCellText(cr);
}
}
MyBorders = new VlnBorders(border, Rows.Count, Cols.Count);
MyShading = new VlnGridCellShading(Color.White, Rows.Count, Cols.Count); // C2021-004 setup shading information
}
private void TrimMergedRangeCellText(CellRange cr)
{
// count number of newlines
string cellstr = this[cr.r1, cr.c1].ToString();
string[] strary = cellstr.Split("\n".ToCharArray());
int nlines = strary.Length;
// count number of rows in merge range
int nrows = (cr.r2 - cr.r1) + 1;
int neededLines = (nlines - (nrows - 1));
bool bNeedToTrim = (nlines > neededLines);
string jstr = "";
int LinesToGo = neededLines;
if (bNeedToTrim)
{
int numBlanksEnd = 0;
// find the number of blank lines at the end of this table cell
for (int i = nlines-1; i >= 0; i--)
{
if (strary[i].Trim().Length == 0)
numBlanksEnd++;
else
break;
}
int preBlanksLines = 0;
//foreach (string tmpstr in strary)
// we ignore the ending blank lines
// this allows us to include any blank lines that are between text lines
for (int i = 0; i < nlines - numBlanksEnd; i++)
{
string tmpstr = strary[i];
int tlen = tmpstr.Trim().Length;
if (tlen > 0 || (LinesToGo < neededLines))
{
if (jstr.Length > 0) jstr += "\n";
jstr += tmpstr;
LinesToGo--;
}
else if (LinesToGo == (nlines - (nrows - 1)))
preBlanksLines++;
}
while (LinesToGo > 0)
{
// need to put this type of hard space (not \xA0) to hold the newline position
if (preBlanksLines > 0)
{
jstr = "\\~\n" + jstr;
LinesToGo--;
}
if (numBlanksEnd > 0)
{
jstr += "\n\\~";
LinesToGo--;
}
}
this[cr.r1, cr.c1] = jstr;
}
}
#endregion //Import / Export Grid
#region Bug Work Around
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
{
// Note: this fixes a bug that happens when the grid has more rows than columns
// notified ComponentOne of the problem 6/25/09 via Email
try
{
base.OnMouseDown(e);
}
catch (Exception ex)
{
while (ex != null)
{
Console.WriteLine("{0} {1} {2}", ex.GetType().Name, ex.Message, ex.StackTrace);
ex = ex.InnerException;
}
}
}
#endregion //Bug Work Around
//public void CenterTheCellText()
//{
// // Cannot use this type of text allignment with RTF text cells
// CellRange cr = this.Selection;
// for (int rw = cr.r1; rw <= cr.r2; rw++)
// for (int col = cr.c1; col <= cr.c2; col++)
// {
// CellRange tmp = this.GetCellRange(rw, col, rw, col);
// string StyleName = string.Format("R{0}C{1}Style", rw, col);
// CellStyle cs = this.Styles.Add(StyleName, tmp.Style);
// cs.TextAlign = TextAlignEnum.CenterCenter;
// tmp.Style = cs;
// }
//}
#region Uneven Selections
/// <summary>
/// True if the top and bottom row of the selection is the same for every column
/// </summary>
public bool EvenSelection
{
get
{
if (Selection.c1 < 0 || Selection.c2 < 0 || Selection.r1 < 0 || Selection.r2 < 0) return true; // Even if there is no selection
if (Selection.IsSingleCell) return true; // One cell by definition is Even
int cMin = MinimumColumn(Selection.r1, Selection.c1); // Get the left column of the top row
int cMax = MaximumColumn(Selection.r1, Selection.c2); // Get the right column of the top row
for (int r = Selection.r1 + 1; r <= Selection.r2; r++)
{
// Uneven if the top row in this column doesn't match the first column
if (MinimumColumn(r, Selection.c1) != cMin)
return false;
// Uneven if the bottom row in this column doesn't match the first column
if (MaximumColumn(r, Selection.c2) != cMax)
return false;
}
int rMin = MinimumRow(Selection.r1, Selection.c1); // Get the top row of the left column
int rMax = MaximumRow(Selection.r2, Selection.c1); // Get the bottom row of the left column
for (int c = Selection.c1 + 1; c <= Selection.c2; c++)
{
// Uneven if the top row in this column doesn't match the first column
if (MinimumRow(Selection.r1, c) != rMin)
return false;
// Uneven if the bottom row in this column doesn't match the first column
if (MaximumRow(Selection.r2, c) != rMax)
return false;
}
return true;
}
}
public void MakeSelectionEven()
{
if (Selection.IsSingleCell) return; // One cell by definition is Even
MakeSelectionEven(Selection.r1, Selection.c1, Selection.r2, Selection.c2);
}
public void SelectRow()
{
MakeSelectionEven(Selection.r1, 0, Selection.r2, Cols.Count - 1);
}
public void SelectCol()
{
MakeSelectionEven(0, Selection.c1, Rows.Count - 1, Selection.c2);
}
public void MakeSelectionEven(int r1,int c1, int r2, int c2)
{
if (c1 < 0 || c2 < 0 || r1 < 0 || r2 < 0) return; // if there is no selection don't bother
CellRange cr = GetEvenSelection(r1, c1, r2, c2);
Select(cr);
}
public CellRange GetEvenSelection()
{
return GetEvenSelection(Selection.r1, Selection.c1, Selection.r2, Selection.c2);
}
public CellRange GetEvenSelection(int r1, int c1, int r2, int c2)
{
int cMinNew = MinimumColumn(r1, c1); // Get the left column of the top row
int cMaxNew = MaximumColumn(r1, c2); // Get the right column of the top row
int rMinNew = MinimumRow(r1, c1); // Get the top row of the left column
int rMaxNew = MaximumRow(r2, c1); // Get the bottom row of the left column
int cMin = cMinNew;
int cMax = cMaxNew;
int rMin = rMinNew;
int rMax = rMaxNew;
do
{
cMin = cMinNew;
cMax = cMaxNew;
rMin = rMinNew;
rMax = rMaxNew;
for (int r = rMin; r <= rMax; r++)
{
// Uneven if the top row in this column doesn't match the first column
int myMin = MinimumColumn(r, cMin);
if (myMin < cMinNew)
cMinNew = myMin;
// Uneven if the bottom row in this column doesn't match the first column
int myMax = MaximumColumn(r, cMax);
if (myMax > cMaxNew)
cMaxNew = myMax;
}
for (int c = cMinNew; c <= cMaxNew; c++)
{
// if the top row in this column is less than the minimum save it
int myMin = MinimumRow(rMin, c);
if (myMin < rMinNew)
rMinNew = myMin;
// Uneven if the bottom row in this column doesn't match the first column
int myMax = MaximumRow(rMax, c);
if (myMax > rMax)
rMaxNew = myMax;
}
}
while (cMinNew < cMin || cMaxNew > cMax || rMinNew < rMin || rMaxNew > rMax);
CellRange cr = GetCellRange(rMinNew, cMinNew, rMaxNew, cMaxNew);
return cr;
}
private int MinimumColumn(int r, int c)
{
return GetMergedRange(r, c).c1;
}
private int MaximumColumn(int r, int c)
{
return GetMergedRange(r, c).c2;
}
private int MinimumRow(int r, int c)
{
return GetMergedRange(r, c).r1;
}
private int MaximumRow(int r, int c)
{
return GetMergedRange(r, c).r2;
}
public Color StyleBackColor
{
get {return Styles.Normal.BackColor;}
set
{
Styles.Normal.BackColor = value;
Styles.Alternate.BackColor = value;
for (int c = 0; c < Cols.Count; c++)
for (int r = 0; r < Rows.Count; r++)
{
CellRange cr = GetMergedRange(r, c);
if (cr.Style != null && cr.Style.BackColor != value && cr.Style.Name != "Fixed")
{
cr.Style.BackColor = value;
}
}
}
}
/// <summary>
/// Returns a list of cells or merged cells within the selection
/// </summary>
public List<CellRange> MySelection
{
get
{
List<CellRange> ranges = new List<CellRange>();
for (int c = Selection.c1; c <= Selection.c2; c++)
for (int r = Selection.r1; r <= Selection.r2; r++)
{
CellRange cr = GetMergedRange(r, c);
if (!ranges.Contains(cr))
ranges.Add(cr);
}
//}
return ranges;
}
}
/// <summary>
/// This is a test to see if MySelection works.
/// </summary>
public void BoldMySelection()
{
foreach (CellRange cr in MySelection)
{
using (StepRTB rtb = new StepRTB())
{
rtb.Rtf = GetCellRTFString(cr.r1, cr.c1);
rtb.SelectAll();
rtb.SelectionFont = new Font(rtb.SelectionFont, FontStyle.Bold);
this[cr.r1, cr.c1] = rtb.Rtf;
}
}
}
public void ShowMySelection()
{
int r1 = MySelection[0].r1;
int r2 = MySelection[0].r2;
int c1 = MySelection[0].c1;
int c2 = MySelection[0].c2;
foreach (CellRange cr in MySelection)
{
r1 = Math.Min(r1, cr.r1);
c1 = Math.Min(c1, cr.c1);
r2 = Math.Max(r2, cr.r2);
c2 = Math.Max(c2, cr.c2);
}
Select(r1,c1,r2,c2);
}
public void Debug_WritelineMySelection()
{
int r1 = MySelection[0].r1;
int r2 = MySelection[0].r2;
int c1 = MySelection[0].c1;
int c2 = MySelection[0].c2;
Console.WriteLine("Initial MySelection[0] {0}", MySelection[0]);
foreach (CellRange cr in MySelection)
{
r1 = Math.Min(r1, cr.r1);
c1 = Math.Min(c1, cr.c1);
r2 = Math.Max(r2, cr.r2);
c2 = Math.Max(c2, cr.c2);
Console.WriteLine("Foreach range ({0},{1}) - ({2},{3})", r1, c1, r2, c2);
}
}
#endregion
}
/// <summary>
/// This is used for storing the grid selection for copy/past Row/Column
/// </summary>
public enum GridCopyOption { Row, Column, Selection };
#region RTF Class for Cell rendering
/// <summary>
/// RTF Should only be used if the contents of the richtextbox are to be converted to an image.
/// </summary>
public class RTF : StepRTB
{
// messages used by RichEd20.dll
internal const int
WM_USER = 0x0400,
EM_FORMATRANGE = WM_USER + 57;
// FORMATRANGE is used by RichEd20.dll to render RTF
internal struct FORMATRANGE
{
internal IntPtr hdc, hdcTarget;
internal Rectangle rc, rcPage;
internal int cpMin, cpMax;
}
// render the control directly into a given Graphics object
// (this does not honor clipping set in the target Graphics object; it that is
// a problem, use the RenderClipped method instead).
public void Render(Graphics g, Rectangle rc)
{
// convert rect from pixels to twips
rc.X = (int)(rc.X * 1440 / g.DpiX);
rc.Y = (int)(rc.Y * 1440 / g.DpiY);
rc.Width = rc.X + (int)((rc.Width) * 1440 / g.DpiX);
rc.Height = rc.Y + (int)((rc.Height) * 1440 / g.DpiY);
// get dc
IntPtr hdc = g.GetHdc();
// set up FORMATRANGE struct
FORMATRANGE fmt = new FORMATRANGE();
fmt.hdc = fmt.hdcTarget = hdc;
fmt.rc = fmt.rcPage = rc;
fmt.cpMin = 0;
fmt.cpMax = -1;
// render RTF
int render = 1;
SendMessageFormatRange(Handle, EM_FORMATRANGE, render, ref fmt);
// clean up
SendMessage(Handle, EM_FORMATRANGE, render, 0);
// done with dc
g.ReleaseHdc(hdc);
}
// render RTF into a Graphics object using a temporary bitmap to ensure
// clipping works correctly.
public void RenderClipped(Graphics g, Rectangle rc)
{
// create temp bitmap
Rectangle rcSrc = new Rectangle(0, 0, rc.Width, rc.Height);
using (Bitmap bmp = new Bitmap(rc.Width, rc.Height))
{
// render RTF into bitmap
using (Graphics gBmp = Graphics.FromImage(bmp))
{
Render(gBmp, rcSrc);
// transfer bitmap to original Graphics object
// (this honors clipping set in the target Graphics object)
g.DrawImage(bmp, rc, rcSrc, GraphicsUnit.Pixel);
}
}
}
// SendMessage
[DllImport("USER32.DLL", CharSet = CharSet.Auto)]
static private extern int SendMessage(
IntPtr hWnd,
uint wMsg,
int wParam,
int lParam);
[DllImport("USER32.DLL", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
static private extern int SendMessageFormatRange(
IntPtr hWnd,
uint wMsg,
int wParam,
ref FORMATRANGE lParam);
}
#endregion //RTF Class for Cell rendering
# region TableCellInfo for text parse
class TableCellInfo
{
private bool _MergeRowBellow;
public bool MergeRowBellow
{
get { return _MergeRowBellow; }
set { _MergeRowBellow = value; }
}
private bool _MergeColRight;
public bool MergeColRight
{
get { return _MergeColRight; }
set { _MergeColRight = value; }
}
private bool _ColEnd;
public bool ColEnd
{
get { return _ColEnd; }
set { _ColEnd = value; }
}
private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; }
}
}
#endregion //TableCellInfo for text parse
#region TableCellEditor
/// <summary>
/// TableCellEditor inherits from a StepRTB and is used as a custom cell editor
/// for the C1FlexGrid control.
/// </summary>
public class TableCellEditor : StepRTB //System.Windows.Forms.RichTextBox //System.Windows.Forms.TextBox // System.Windows.Forms.ComboBox
{
private VlnFlexGrid _owner;
private int _row, _col;
private char _pendingKey;
private bool _cancel;
public bool _initializingEdit;
// constructor: attach to owner grid
public TableCellEditor(VlnFlexGrid owner)
{
Visible = false;
AutoSize = false;
BackColor = Color.SkyBlue;
BorderStyle = BorderStyle.None;
ScrollBars = RichTextBoxScrollBars.None;
_initializingEdit = false;
_pendingKey = (char)0;
_cancel = false;
_owner = owner;
_owner.Controls.Add(this);
this.CursorMovement += new StepRTBCursorMovementEvent(TableCellEditor_CursorMovement);
this.CursorKeyPress += new StepRTBCursorKeysEvent(TableCellEditor_CursorKeyPress);
this.Leave += new EventHandler(_editor_Leave);
this.SelectionChanged += TableCellEditor_SelectionChanged;
//this.HeightChanged += new StepRTBEvent(_HeightChanged);
}
// C2021-005 selecting characters in the cell text editor
private void TableCellEditor_SelectionChanged(object sender, EventArgs e)
{
if (!_initializingEdit)
{
float fnSz = GetRTFFontSize(); // returns the font size in pts from the text's RTF
_owner.SelectedFontSize = fnSz; // will trigger the changing of the font size from VlnFlexGrid class
// B2022-137 Table performance improvements - moved ShowTableCellShading to the onLeave call
//_owner.ShowTableCellShading(); //C2021-004 display any background color change when you move off a cell
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
// start editing: move to cell and activate
// C2021-005 added the showEditor - set to true when we are getting the font size of the text
public void StartEditing(int row, int col, bool showEditor)
{
ItemInfo pinfo = MyItemInfo.MyProcedure as ItemInfo;
DocVersionInfo dvi = (pinfo == null) ? null : pinfo.ActiveParent as DocVersionInfo;
_initializingEdit = true;
ReadOnly = IsRoTable || !UserInfo.CanEdit(MyUserInfo, dvi); // reviewer cannot make changes to a table
// save coordinates of cell being edited
_row = row;
_col = col;
//this.Clear(); //jsj
// assume we'll save the edits
_cancel = false;
// move editor over the current cell
Rectangle rc = _owner.GetCellRect(row, col, true);
rc.Width--;
rc.Height--;
Bounds = rc;
// initialize control content
Text = "";
FindAllLinks(); // jsj 1-5-2011
if (_pendingKey > ' ' && !ReadOnly)
{
if(_pendingKey == '\\')
SendKeys.Send("\\"); // B2016-162 Send a backslash which will be converted to "\u9586?"
else
Text = _pendingKey.ToString();
}
else if (_owner[row, col] != null)
{
string tmp = _owner[row, col].ToString();
// convert \'99 to \u8482? this is for the trade mark symbol. For some reason RTF is automatically
// converting the unicode \u8482? to \'99, but once this is done, PROMS StepRTB (edit windows) do not show it
// Also convert \~ to a hard spece. Again RTF is automatically converting \u160? to \~ but will then convert
// the \~ to a regular space!
if (tmp.StartsWith(@"{\rtf"))
Rtf = RtfTools.RTFConvertedSymbolsToUnicode(tmp);//.Replace(@"\~", @"\u160?").Replace(@"\'99", @"\u8482?");
else
Text = tmp;
}
Select(Text.Length, 0);
Size sz = new Size(rc.Width, rc.Height);
//this.Size = sz;
this.Width = rc.Width;
if (!showEditor) // C2021-005 if we are getting the font size don't show the editor
{
// make editor visible
Visible = true;
}
// and get the focus
//Select();
Focus();
_initializingEdit = false;
}
void TableCellEditor_CursorKeyPress(object sender, KeyEventArgs args)
{
//throw new Exception("The method or operation is not implemented.");
}
void TableCellEditor_CursorMovement(object sender, StepRTBCursorMovementEventArgs args)
{
int row = _owner.Selection.r1;
int col = _owner.Selection.c1;
CellRange cr = _owner.GetMergedRange(row, col);
//Console.WriteLine("keystroke {0} selection {1},{2}", args.Key, row, col);
//vlnStackTrace.ShowStack("keystroke {0} selection {1},{2}", args.Key, row, col);
_owner.Select();
// See if we are in a merged range of cells.
// if so, use the merged range instead of the selected range
// so that we can jump to the top/bottom/left/right of the range
// before attempting the move to the next grid cell.
//int idx = _owner.MergedRanges.IndexOf(row, col);
//if (idx > -1) cr = _owner.MergedRanges[idx];
switch (args.Key)
{
case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlDown:
case VEPROMS.CSLA.Library.E_ArrowKeys.Down:
row = cr.r2;
if (row < _owner.Rows.Count - 1)
_owner.Select(_owner.GetMergedRange(row + 1, col));
else
_owner.OnCursorMovement(this, new VlnFlexGridCursorMovementEventArgs(args.Key));
break;
case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlLeft:
case VEPROMS.CSLA.Library.E_ArrowKeys.Left:
col = cr.c1;
if (col > 0)
_owner.Select(_owner.GetMergedRange(row, col - 1));
else if(row > 0)
_owner.Select(_owner.GetMergedRange(row - 1, _owner.Cols.Count - 1));
else
_owner.OnCursorMovement(this, new VlnFlexGridCursorMovementEventArgs(args.Key));
break;
case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlRight:
case VEPROMS.CSLA.Library.E_ArrowKeys.Right:
col = cr.c2;
if (col < _owner.Cols.Count - 1)
_owner.Select(_owner.GetMergedRange(row, col + 1));
else if (cr.r2 < _owner.Rows.Count - 1)
{
CellRange crDest = _owner.GetMergedRange(cr.r2 + 1, 0);
if (cr.r2 < crDest.r1) // It will move to the correct place
_owner.Select(crDest);
else if (crDest.r2 < _owner.Rows.Count -1) //B2017066 check against count -1 to avoid index out of range error
_owner.Select(_owner.GetMergedRange(crDest.r2 + 1, 0));
else
_owner.OnCursorMovement(this, new VlnFlexGridCursorMovementEventArgs(args.Key));
}
else
_owner.OnCursorMovement(this, new VlnFlexGridCursorMovementEventArgs(args.Key));
break;
case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlUp:
case VEPROMS.CSLA.Library.E_ArrowKeys.Up:
row = cr.r1;
if (row > 0)
_owner.Select(_owner.GetMergedRange(row - 1, col));
else
_owner.OnCursorMovement(this, new VlnFlexGridCursorMovementEventArgs(args.Key));
break;
default:
break;
}
//Console.WriteLine("selection {0}", _owner.Selection);
//_owner.Focus(); // focus was jumping out of the grid this keeps it in.
}
// after edit handler (custom editor)
void _editor_Leave(object sender, EventArgs e)
{
_owner.Invalidate();
_owner.AdjustGridControlSize();
}
//void _HeightChanged(object sender, EventArgs args)
//{
// _owner.Invalidate();
//}
// save key that started the editing mode
public void SetPendingKey(char chr)
{
_pendingKey = chr;
}
// expose internal variables
public bool Cancel { get { return _cancel; } }
public int Row { get { return _row; } }
public int Col { get { return _col; } }
// move editor after the grid has scrolled
public void UpdatePosition()
{
// get cell rect now
Rectangle rcCell = _owner.GetCellRect(_row, _col, false);
// intersect with scrollable part of the grid
Rectangle rcScroll = _owner.ClientRectangle;
rcScroll.X = _owner.Cols[_owner.Cols.Fixed].Left;
rcScroll.Y = _owner.Rows[_owner.Rows.Fixed].Top;
rcScroll.Width -= rcScroll.X;
rcScroll.Height -= rcScroll.Y;
rcCell = Rectangle.Intersect(rcCell, rcScroll);
// and move the control
if (rcCell.Width > 0) rcCell.Width--;
if (rcCell.Height > 0) rcCell.Height--;
Bounds = rcCell;
Size sz = new Size(_owner.GetCellRect(_row, _col).Width, _owner.GetCellRect(_row, _col).Height);
this.Size = sz;
}
// lost focus: hide the editor
override protected void OnLeave(System.EventArgs e)
{
// base processing
base.OnLeave(e);
// copy text to owner grid
if (!_cancel)
{
_owner[_row, _col] = Rtf; //Text;
}
// no more pending keys
_pendingKey = (char)0;
// done for now, hide editor
Visible = false;
_owner.ShowTableCellShading(); // B2022-137 restore shading if table after editing a cell
}
// we will handle the Tab key ourselves
override protected bool IsInputKey(Keys keyData)
{
if (keyData == Keys.Tab) return true;
return base.IsInputKey(keyData);
}
//// some keys end the editing
//override protected void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
//{
// switch (e.KeyCode)
// {
// case Keys.Escape: // cancel edits
// _cancel = true;
// _owner.Select();
// e.Handled = true;
// return;
// case Keys.Enter: // finish editing
// case Keys.Tab:
// case Keys.Up:
// case Keys.Down:
// case Keys.PageUp:
// case Keys.PageDown:
// _owner.Select();
// e.Handled = true;
// MoveCursor(e.KeyCode);
// return;
// default: // default processing
// base.OnKeyDown(e);
// return;
// }
//}
//// move cursor after done editing
//protected void MoveCursor(Keys key)
//{
// int row = _owner.Row;
// int col = _owner.Col;
// switch (key)
// {
// case Keys.Tab: col++; break;
// case Keys.Up: row--; break;
// //case Keys.Return: row++; break;
// case Keys.Down: row++; break;
// //case Keys.PageUp: row -= 10; break;
// //case Keys.PageDown: row += 10; break;
// }
// // validate new selection
// if (row < _owner.Rows.Fixed) row = _owner.Rows.Fixed;
// if (col < _owner.Cols.Fixed) col = _owner.Cols.Fixed;
// if (row > _owner.Rows.Count - 1) row = _owner.Rows.Count - 1;
// if (col > _owner.Cols.Count - 1) col = _owner.Cols.Count - 1;
// // apply new selection
// _owner.Select(row, col);
//}
//// suppress some keys to avoid annoying beep
//override protected void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
//{
// switch (e.KeyChar)
// {
// case (char)27: // Keys.Escape:
// case (char)13: // Keys.Enter:
// case (char)9: // Keys.Tab:
// e.Handled = true;
// return;
// }
// base.OnKeyPress(e);
//}
}
#endregion // TableCellEditor
#region TableClipBoardFuncts Class
class TableClipBoardFuncts
{
DataFormats.Format dfmtTableCellRange = DataFormats.GetFormat("TableCellRange");
private SelectedTableCells mySeldTableCellsObject;
private DataObject myDataObject;
public TableClipBoardFuncts()
{
//mySeldTableCellsObject = new DataObject(dfmtTableCellRange.Name, seldTableCells);
}
public void Put(CellRange cr)
{
// Copies myObject into the clipboard.
// Clip get the value (text) of all the cells in the selected range
// This is saved as one RTF string.
Clipboard.SetDataObject(cr.Clip, true); // the "true" make the copy persistent
//Console.WriteLine("\nClip: '{0}' \n'{1}'", cr.Clip,cr.DataDisplay);
//mySeldTableCellsObject = new SelectedTableCells();
//mySeldTableCellsObject.CpbrdCellRange = cr;
// myDataObject = new DataObject(dfmtTableCellRange.Name, mySeldTableCellsObject);
// try
// {
// Clipboard.SetDataObject(myDataObject); //,true);
// }
// catch (Exception ex)
// {
// Console.WriteLine(ex.Message);
// }
}
public ArrayList Get()
{
// Retrieves the data from the clipboard.
IDataObject myRetrievedObject = Clipboard.GetDataObject();
string jj = (string)myRetrievedObject.GetData(DataFormats.Text);
return GetCellStrings(jj);
}
//public CellRange get_cr_Paste()
//{
// mySeldTableCellsObject = new SelectedTableCells();
// CellRange cr = new CellRange();
// SelectedTableCells sc;
// IDataObject myRetrievedObject = Clipboard.GetDataObject();
// try
// {
// //object obj = myRetrievedObject.GetData(dfmtTableCellRange.Name);
// object obj = myRetrievedObject.GetData("TableCellRange");
// //sc = (SelectedTableCells)myRetrievedObject.GetData(dfmtTableCellRange.Name);
// sc = (SelectedTableCells)obj;
// cr = sc.CpbrdCellRange;
// }
// catch (Exception ex)
// {
// Console.WriteLine(ex.Message);
// }
// return cr;
//}
private ArrayList GetCellStrings(string instr)
{
// The table cells placed on the clipboard is saved as one long RTF string.
// "\r\n\t" defines a cell border
// "\r\n\r" defines beginning of next line (row)
// This function will separate each cell text and place them in an array.
// This allow the clipboard information to be pasted independently from
// how it was selected.
// Bug fix: the CellRange.Clip (see cr.clip in the Put() function above) is replacing
// new lines with spaces. We need to put them back.
instr = instr.Replace(@"}} \", "}}\r\n\\");
string tstr = ""; // this will contain the parsed out cell text
ArrayList arylstCellStrings = new ArrayList();
int sidx = 0; // start index
int tidx = 0;
if (instr != null)
{
int idx = instr.IndexOf(@"{\rtf",sidx+1); // cell boarder
while (idx > 0)
{
tstr = instr.Substring(sidx, idx - sidx);
tstr = tstr.Substring(0, tstr.LastIndexOf('}') + 1);
//Console.WriteLine("\ntstr: '{0}'", tstr);
arylstCellStrings.Add(tstr);
sidx = idx;
idx = instr.IndexOf(@"{\rtf",sidx+1);
}
if (sidx < instr.Length)
{
tstr = instr.Substring(sidx);
arylstCellStrings.Add(tstr);
}
}
return arylstCellStrings;
}
//private ArrayList GetCellStrings(string instr)
//{
// // The table cells placed on the clipboard is saved as one long RTF string.
// // "\r\n\t" defines a cell border
// // "\r\n\r" defines beginning of next line (row)
// // This function will separate each cell text and place them in an array.
// // This allow the clipboard information to be pasted independently from
// // how it was selected.
// string tstr = ""; // this will contain the parsed out cell text
// ArrayList arylstCellStrings = new ArrayList();
// int sidx = 0; // start index
// int tidx = 0;
// if (instr != null)
// {
// int idx = instr.IndexOf("\r\n\t"); // cell boarder
// if (idx < 0) idx = instr.IndexOf("\r\n\r"); // new line (needed for multiple lines in one cell)
// while (idx > 0)
// {
// tstr = instr.Substring(sidx, idx - sidx);
// tidx = tstr.IndexOf("\r\n\r");
// if (tidx > 0)
// {
// idx = instr.IndexOf("\r\n\r", sidx);
// tstr = instr.Substring(sidx, idx - sidx);
// }
// arylstCellStrings.Add(tstr.Substring(tstr.IndexOf("{\\rtf")));
// sidx = idx + 3;
// if (sidx < instr.Length)
// {
// idx = instr.IndexOf("\r\n\t", sidx);
// if (idx < 0) idx = instr.IndexOf("\r\n\r", sidx);
// }
// }
// if (sidx < instr.Length)
// {
// tstr = instr.Substring(sidx);
// arylstCellStrings.Add(tstr.Substring(tstr.IndexOf("{\\rtf")));
// }
// }
// return arylstCellStrings;
//}
}
[Serializable]
public class SelectedTableCells : Object
{
private CellRange _cpbrdCellRange;
public CellRange CpbrdCellRange
{
get { return _cpbrdCellRange; }
set { _cpbrdCellRange = value; }
}
public SelectedTableCells()
{
}
}
#endregion // TableClipBoardFuncts Class
public class VlnFlexGridCursorMovementEventArgs
{
private E_ArrowKeys _Key;
public E_ArrowKeys Key
{
get { return _Key; }
set { _Key = value; }
}
public VlnFlexGridCursorMovementEventArgs(E_ArrowKeys key)
{
_Key = key;
}
}
public class VlnFlexGridPasteEventArgs
{
private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; }
}
public VlnFlexGridPasteEventArgs(string text)
{
_Text = text;
}
}
public class GridCopyInfo
{
private GridCopyOption _MyCopyOption = GridCopyOption.Selection;
public GridCopyOption MyCopyOption
{
get { return _MyCopyOption; }
set
{
//Console.WriteLine("MyCopyOption = {0}", _MyCopyOption);
//if (_MyCopyOption != value)
// Console.WriteLine("Changed Option to {0}", value);
_MyCopyOption = value;
}
}
private VlnFlexGrid _MyCopiedFlexGrid = null;
public VlnFlexGrid MyCopiedFlexGrid
{
get { return _MyCopiedFlexGrid; }
set { _MyCopiedFlexGrid = value; }
}
private CellRange _MyCopiedCellRange;
public CellRange MyCopiedCellRange
{
get { return _MyCopiedCellRange; }
set { _MyCopiedCellRange = value; }
}
}
}