
Shutoff SpellCheck for StepRTB Use using for temporary StepRTB Use using for vlnFlexGrid Added debug output to track StepRTBs and vlnFlexGrids in memory Limit bottom margin to 0 or above Dispose of roImage after it is done being used Dispose of Figure after it is done being used. Use GetJustRODB so that images are not loaded. Added ErrorHandler if annotation is deleted after a search Track create, dispose and finalize Add static variable to control if SpellCheck is used Use using for temporary StepRTB Lazy Load SelectionStack Clean-up on Dispose Track create, dispose and finalize Make MyCopyInfo Lazy Loaded Use using for temporary StepRTB Add Dispose method for TableCellEditor Cleanup on Dispose Only kill MSWord instances that are invisible
4875 lines
154 KiB
C#
4875 lines
154 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;
|
|
|
|
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 VlnFlexGrid : C1.Win.C1FlexGrid.C1FlexGrid
|
|
{
|
|
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();
|
|
//}
|
|
public bool IsDirty
|
|
{
|
|
get
|
|
{
|
|
return IsGridChanged(this._MyItemInfo.MyContent.MyGrid.Data, this.GetXMLData());
|
|
}
|
|
}
|
|
private bool IsGridChanged(string oldXml, string newXml)
|
|
{
|
|
if (this.TableCellEditor.Text.Contains("<NewID>"))
|
|
return false;
|
|
XmlDocument XdOld = new XmlDocument();
|
|
XdOld.LoadXml(oldXml);
|
|
XmlDocument XdNew = new XmlDocument();
|
|
XdNew.LoadXml(newXml);
|
|
//check volian borders 1st
|
|
if (XdNew.SelectSingleNode("C1FlexGrid/Control/MyBorderDetailString").InnerText != XdOld.SelectSingleNode("C1FlexGrid/Control/MyBorderDetailString").InnerText)
|
|
return true;
|
|
//check row/col sizes 2nd
|
|
if (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 (GetCellFormatString(XdNew) != GetCellFormatString(XdOld))
|
|
return true;
|
|
//check for merged cells 5th
|
|
if (GetCellMergeString(XdNew) != GetCellMergeString(XdOld))
|
|
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 = int.Parse(xd.SelectSingleNode("C1FlexGrid/ColumnInfo/Count").InnerText);
|
|
int rows = int.Parse(xd.SelectSingleNode("C1FlexGrid/RowInfo/Count").InnerText);
|
|
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 string GetCellDataString(XmlDocument xd)
|
|
{
|
|
int cols = int.Parse(xd.SelectSingleNode("C1FlexGrid/ColumnInfo/Count").InnerText);
|
|
int rows = int.Parse(xd.SelectSingleNode("C1FlexGrid/RowInfo/Count").InnerText);
|
|
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 = int.Parse(xd.SelectSingleNode("C1FlexGrid/ColumnInfo/Count").InnerText);
|
|
int rows = int.Parse(xd.SelectSingleNode("C1FlexGrid/RowInfo/Count").InnerText);
|
|
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 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 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];
|
|
}
|
|
|
|
[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]+[^ ]* )(VESymbFix)(;})");
|
|
private static Regex _ReplaceArialUnicodeMS = new Regex(@"({\\f[0-9]+[^ ]* )(Arial Unicode MS)(;})");
|
|
private static Regex _ReplaceTextFont = new Regex(@"({\\f[0-9]+[^ ]* )(?((?!VESymbFix)(?!Arial Unicode MS))([^;]*)|(!!!!))(;})");
|
|
public void LoadGrid(ItemInfo itemInfo)
|
|
{
|
|
_MyItemInfo = itemInfo;
|
|
string str = itemInfo.MyContent.MyGrid.Data;
|
|
VE_Font vefont = _MyItemInfo.GetItemFont();
|
|
FontFamily ff = StepRTB.MyFontFamily ?? vefont.WindowsFont.FontFamily; // TODO: Does not change fixed font.
|
|
if (StepRTB.MySymbolFontName != "VESymbFix")
|
|
str = _ReplaceVESymbFix.Replace(str, "$1" + StepRTB.MySymbolFontName + "$3");
|
|
if (StepRTB.MySymbolFontName != "Arial Unicode MS")
|
|
str = _ReplaceArialUnicodeMS.Replace(str, "$1" + StepRTB.MySymbolFontName + "$3");
|
|
str = _ReplaceTextFont.Replace(str, "$1" + ff.Name + "$4");
|
|
// 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.
|
|
System.Drawing.Image img = this.CreateImage();
|
|
Visible = false;
|
|
if (Parent is GridItem)
|
|
{
|
|
using (Graphics gr = (Parent as GridItem).CreateGraphics())
|
|
{
|
|
gr.DrawImage(img, Left, Top);
|
|
}
|
|
}
|
|
Clear();
|
|
MergedRanges.Clear();
|
|
_ReadingXml = true;
|
|
//Console.WriteLine("LoadGrid - Before ReadXML");
|
|
using (StringReader sr = new StringReader(str))
|
|
{
|
|
ReadXml(sr);
|
|
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None;
|
|
sr.Close();
|
|
}
|
|
//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;
|
|
}
|
|
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.LeaveCell += new EventHandler(VlnFlexGrid_LeaveCell);
|
|
|
|
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);
|
|
}
|
|
|
|
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)
|
|
{
|
|
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 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.Shift) return;
|
|
//Select(Rows.Count - 1, 0);
|
|
//_tableCellEditor.StepRTB_ArrowPressed(E_ArrowKeys.Down);
|
|
//e.Handled = true;
|
|
if (!e.Control && !e.Shift && !e.Alt)
|
|
{
|
|
OnEnterKeyPressed(sender, e);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void VlnFlexGrid_LeaveCell(object sender, EventArgs e)
|
|
{
|
|
//CellStyle csd = this.CursorCell.StyleDisplay;
|
|
//CellStyle cs = this.GetCellRange(Row, Col).Style;
|
|
//if (cs != null)
|
|
//{
|
|
// Console.WriteLine("LeaveCell Style = {0}", cs.Name);
|
|
// Console.WriteLine("LeaveCell StyleDisplay = {0}", csd.Name);
|
|
// cs.ForeColor = Color.Black;
|
|
//}
|
|
CellStyle cs = this.Styles["Focus"];
|
|
cs.ForeColor = Color.Black;
|
|
cs = this.Styles["Highlight"];
|
|
cs.ForeColor = Color.Black;
|
|
}
|
|
|
|
//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
|
|
string rtfText = this.GetDataDisplay(e.Row, e.Col).Replace(@"\~", @"\u160?");
|
|
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;
|
|
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;
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
public void ConvertTextCellToRTF(int r, int c)
|
|
{
|
|
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();
|
|
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
|
|
AdjustMergeRangeHeightWidth(r, c, trtb, tstr, AllowWidthShrink);
|
|
|
|
|
|
//// 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;
|
|
}
|
|
|
|
this.Select(r, c, false);
|
|
CellRange sel = this.Selection;
|
|
|
|
// Now adjust the Height and Width in the defined merge ranges
|
|
AdjustMergeRangeHeightWidth(r, c, trtb, tstr, AllowWidthShrink);
|
|
}
|
|
}
|
|
|
|
private void AdjustMergeRangeHeightWidth(int r, int c, StepRTB trtb, string tstr, bool AllowWidthShrink)
|
|
{
|
|
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 + 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
|
|
public void MakeRTFcells()
|
|
{
|
|
// 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++)
|
|
this.ConvertTextCellToRTF(r, c);
|
|
}
|
|
|
|
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
|
|
_tableCellEditor.StartEditing(e.Row, e.Col);
|
|
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();
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
// 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;
|
|
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(col, r);
|
|
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);
|
|
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);
|
|
// 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);
|
|
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);
|
|
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 = MessageBox.Show(msg, title, MessageBoxButtons.YesNo);
|
|
if (dr == DialogResult.Yes)
|
|
RemoveSelectedCells();//RemoveColumns(this.Selection.r1, this.Selection.c1, 1);
|
|
else
|
|
Select(saveCR);
|
|
}
|
|
|
|
public void RemoveSelectedRow()
|
|
{
|
|
string msg = "";
|
|
string title = "";
|
|
CellRange saveCR = Selection;
|
|
this.SelectionMode = SelectionModeEnum.RowRange;
|
|
//this.Select(this.Selection.r1, this.Selection.c1,);
|
|
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 = MessageBox.Show(msg, title, MessageBoxButtons.YesNo);
|
|
if (dr == DialogResult.Yes)
|
|
this.RemoveSelectedCells();//this.RemoveRows(this.Selection.r1, this.Selection.c1, 1);
|
|
else
|
|
Select(saveCR);
|
|
}
|
|
|
|
private void RemoveRows(int strow, int stcol, int cnt)
|
|
{
|
|
bool mergedRow = false;
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
//if (this.RowIsInMergeRange(strow))
|
|
//{
|
|
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;
|
|
//this[cr.r1 + 1, cr.c1] = this[cr.r1, cr.c1];
|
|
}
|
|
cl++;
|
|
}
|
|
//}
|
|
this.Rows.Remove(strow);
|
|
this.AdjustMergedRows(strow, false, true);
|
|
//if (mergedRow)
|
|
//{
|
|
//cnt++;
|
|
mergedRow = false;
|
|
//}
|
|
}
|
|
MyBorders.DeleteRows(strow, cnt);
|
|
this.AdjustGridControlSize();
|
|
}
|
|
|
|
private void RemoveColumns(int strow, int stcol, int cnt)
|
|
{
|
|
bool mergedCol = false;
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
//if (this.ColIsInMergeRange(stcol))
|
|
//{
|
|
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[cr.r1, cr.c1 + 1] = this[cr.r1, cr.c1];
|
|
}
|
|
}
|
|
//}
|
|
this.Cols.Remove(stcol);
|
|
this.AdjustMergedColumns(stcol, false, true);
|
|
//if (mergedCol)
|
|
//{
|
|
// //cnt++;
|
|
mergedCol = false;
|
|
//}
|
|
}
|
|
MyBorders.DeleteColumns(stcol, cnt);
|
|
this.AdjustGridControlSize();
|
|
}
|
|
|
|
public void RemoveSelectedCells()
|
|
{
|
|
bool didremove = false;
|
|
int lastRow = this.Rows.Count - 1;
|
|
int lastCol = this.Cols.Count - 1;
|
|
CellRange cr = this.Selection;
|
|
|
|
// r2 is last row (or in merge range containing last row)
|
|
// r1 is first row or r1-m (m is in merge range) is first row
|
|
// we can remove columns c1 through c2
|
|
|
|
int idx = this.MergedRanges.IndexOf(cr.r2, cr.c2);
|
|
CellRange mr = new CellRange();
|
|
if (idx > -1) mr = this.MergedRanges[idx];
|
|
if (cr.r2 == lastRow || idx > -1 && mr.r2 == lastRow)//RowIsInMergeRange(grd,cr.r2))
|
|
{
|
|
if (cr.r1 == 0 || this.RowIsInMergeRange(cr.r1 - 1))
|
|
{
|
|
this.RemoveColumns(cr.r1, cr.c1, cr.RightCol - cr.LeftCol + 1);// remove selected columns
|
|
didremove = true;
|
|
}
|
|
}
|
|
|
|
|
|
// c2 is last column (or in merge range containing last column)
|
|
// c1 is first column or c1-m (m is merge range) is first column
|
|
// we can remove rows r1 through r2
|
|
|
|
if (cr.c2 == lastCol || idx > -1 && mr.c2 == lastCol)//ColIsInMergeRange(grd,cr.c1-1))
|
|
{
|
|
if (cr.c1 == 0 || this.ColIsInMergeRange(cr.c1 - 1))
|
|
{
|
|
// remove selected rows
|
|
this.RemoveRows(cr.r1, cr.c1, cr.BottomRow - cr.TopRow + 1);
|
|
didremove = true;
|
|
}
|
|
}
|
|
|
|
if (!didremove)
|
|
MessageBox.Show("Cannot Removed Part of a Row or Column.\n\nNote: This function allows you to delete one or more rows/columns at time.", "Invalid Selection",MessageBoxButtons.OK,MessageBoxIcon.Hand);
|
|
|
|
return;
|
|
}
|
|
|
|
#endregion //Grid Add and Remove Row / Column
|
|
|
|
#region Copy/Paste
|
|
|
|
public void CopyRow()
|
|
{
|
|
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 = MessageBox.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);
|
|
}
|
|
|
|
public void CopyColumn()
|
|
{
|
|
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 = MessageBox.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()
|
|
{
|
|
DialogResult dr = DialogResult.Yes;
|
|
CellRange cr = Selection;
|
|
MakeSelectionEven();
|
|
if (!cr.Equals(Selection))
|
|
{
|
|
dr = MessageBox.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);
|
|
}
|
|
|
|
switch (pp)
|
|
{
|
|
case enmPastePos.Before:
|
|
this.Rows.InsertRange(selR1, rowsToAdd);
|
|
AdjustMergedRows(selR1, rowsToAdd, true, false);
|
|
MyBorders.InsertRows(Rows.Count - rowsToAdd - 1, rowsToAdd);
|
|
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);
|
|
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);
|
|
this[r + rowOffset, c] = MyCopyInfo.MyCopiedFlexGrid[r, c];
|
|
MatchStyle(crm, cr);
|
|
PasteBorders(r + rowOffset, c, r, c);
|
|
// 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);
|
|
}
|
|
|
|
switch (pp)
|
|
{
|
|
case enmPastePos.Before:
|
|
this.Cols.InsertRange(selC1, colsToAdd);
|
|
AdjustMergedColumns(selC1, colsToAdd, true, false);
|
|
MyBorders.InsertColumns(Cols.Count - colsToAdd - 1, colsToAdd);
|
|
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);
|
|
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
|
|
this[r, c + colOffset] = MyCopyInfo.MyCopiedFlexGrid[r, c];
|
|
MatchStyle(crm, cr);
|
|
PasteBorders(r, c + colOffset, r, c);
|
|
// 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 = MessageBox.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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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);
|
|
this[r + rowOffset, c + colOffset] = MyCopyInfo.MyCopiedFlexGrid[r, c];
|
|
MatchStyle(crm, cr);
|
|
PasteBorders(r + rowOffset, c + colOffset, r, c);
|
|
}
|
|
}
|
|
}
|
|
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]);
|
|
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 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(@"\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;
|
|
// 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
|
|
{
|
|
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) // 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].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);
|
|
}
|
|
|
|
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;
|
|
//Console.WriteLine("{0}, {1}, {2}, {3}", r, c, cr.Style.Name, cr.Style.BackColor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <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>
|
|
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.HeightChanged += new StepRTBEvent(_HeightChanged);
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
}
|
|
// start editing: move to cell and activate
|
|
public void StartEditing(int row, int col)
|
|
{
|
|
_initializingEdit = true;
|
|
ReadOnly = IsRoTable;
|
|
// 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)
|
|
Text = _pendingKey.ToString();
|
|
else if (_owner[row, col] != null)
|
|
{
|
|
string tmp = _owner[row, col].ToString();
|
|
if (tmp.StartsWith(@"{\rtf"))
|
|
Rtf = tmp.Replace(@"\~",@"\u160?");
|
|
else
|
|
Text = tmp;
|
|
}
|
|
Select(Text.Length, 0);
|
|
|
|
Size sz = new Size(rc.Width, rc.Height);
|
|
|
|
//this.Size = sz;
|
|
this.Width = rc.Width;
|
|
|
|
// 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)
|
|
_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;
|
|
}
|
|
|
|
// 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; }
|
|
}
|
|
|
|
}
|
|
}
|