2009-07-20 15:48:48 +00:00

1874 lines
52 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 Volian.Controls.Library;
using C1.Win.C1FlexGrid;
namespace Volian.Controls.Library
{
public partial class VlnFlexGrid : C1.Win.C1FlexGrid.C1FlexGrid
{
private TableCellEditor _tableCellEditor;
private TableClipBoardFuncts _clpbrdCpyPste;
#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();
_tableCellEditor = new TableCellEditor(this);
}
private void SetupGrid(int numrows, int numcols) //C1FlexGrid NewGrid()
{
// setup the default size of each cell in the table/grid
this.Cols.DefaultSize = 40;
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.LeftCenter;
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.Always;
this.AllowMerging = C1.Win.C1FlexGrid.AllowMergingEnum.Custom;
this.AllowResizing = C1.Win.C1FlexGrid.AllowResizingEnum.Both;
_tableCellEditor = new TableCellEditor(this);
_clpbrdCpyPste = new TableClipBoardFuncts();
//this.Enter += new System.EventHandler(this.Grid_Enter);
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);
}
private void Grid_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
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);
if (e.Style.BackColor != solid)
e.Style.BackColor = solid;
// check whether the cell contains RTF
string rtfText = this.GetDataDisplay(e.Row, e.Col);
if (rtfText.StartsWith(@"{\rtf"))
{
// it does, so draw background
e.DrawCell(DrawCellFlags.Background);
// draw the RTF text
if (e.Bounds.Width > 0 && e.Bounds.Height > 0)
{
_rtf.Rtf = rtfText;
_rtf.ForeColor = e.Style.ForeColor;
_rtf.BackColor = e.Style.BackColor;
_rtf.Render(e.Graphics, e.Bounds);
}
// and draw border last
e.DrawCell(DrawCellFlags.Border);
// we're done with this cell
e.Handled = true;
}
}
#endregion //Grid Initialize
#region Grid and Cell Styles
public void CellBackgroundYellow()
{
CellRange cr = this.Selection;
cr.Style = this.Styles["Yellow"];
}
public void ToggleCellTextAlignment()
{
CellRange cr = this.Selection;
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 TableBorderNone()
{
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None;
this.AdjustGridControlSize();
}
public void TableBorderFixedSingle()
{
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.FixedSingle;
this.AdjustGridControlSize();
}
public void TableBorderFixed3d()
{
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.Fixed3D;
this.AdjustGridControlSize();
}
public void TableBorderLight3D()
{
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.Light3D;
this.AdjustGridControlSize();
}
public void TableBorderXpThemes()
{
this.BorderStyle = C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.XpThemes;
this.AdjustGridControlSize();
}
private CellRange GetSelectedCellRange()
{
return this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
}
public void SelectedCellsBorderNone()
{
CellRange cr = GetSelectedCellRange();
cr.Style = this.Styles["None"];
}
public void SelectedCellsBorderFlat()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Flat"];
}
public void SelectedCellsBorderDouble()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Double"];
}
public void SelectedCellsBorderRaised()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Raised"];
}
public void SelectedCellsBorderInset()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Inset"];
}
public void SelectedCellsBorderGroove()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Groove"];
}
public void SelectedCellsBorderFillet()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Fillet"];
}
public void SelectedCellsBorderDotted()
{
CellRange cr = this.GetCellRange(this.Selection.TopRow, this.Selection.LeftCol, this.Selection.BottomRow, this.Selection.RightCol);
cr.Style = this.Styles["Dotted"];
}
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()
{
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;
this.Size = new Size(wid + difW, height + difH);
}
this.Refresh();
}
public void AdjustGridHeightWidth(int r, int c)
{
StepRTB trtb = new StepRTB();
string tstr = null;
bool dummyCharWidth = false;
bool AllowWidthShrink = false;
trtb.Clear();
tstr = (string)this[r, c];
trtb.Font = this.Font;
if (tstr != null && tstr.Length > 0)
{
if (tstr.StartsWith(@"{\rtf"))
trtb.Rtf = tstr; // already RTF text
else
trtb.Text = tstr; // this will convert regular text to RTF text
// 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);
// this will convert the special characters for Bold, Underline, and Italics
// into RTF commands
trtb.Rtf = ConvertTableText(trtb.Rtf);
}
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);
// 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 + 2;// (int)numGridLineBorderAdj.Value;
//Console.WriteLine("{0} {1} {2} '{3}'", r, c, newheight,trtb.Text);
if (newheight > this.Rows[r].Height)
this.Rows[r].Height = newheight;
}
// IF the column of the selected sell 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;//(int)numGridLineBorderAdj.Value;
if (newwidth > this.Cols[c].Width || AllowWidthShrink || r == 0)
this.Cols[c].Width = newwidth;
}
}
}
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 = 20;//10;
for (int c = 0; c < this.Cols.Count; c++)
this.AdjustGridHeightWidth(r, c);
}
this.AdjustGridControlSize();
}
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 = "";
// Underline next word
rtn = SomethingNextWord(str, @"\'17", @"\ul ", @"\ulnone ");
// Bold next word
rtn = SomethingNextWord(rtn, @"\'13", @"\b ", @"\b0 ");
// Italics On
rtn = rtn.Replace(@"\'1B4", @"\i ");
// Italics Off
rtn = rtn.Replace(@"\'1B5", @"\i0 ");
// underline On
rtn = rtn.Replace(@"\'ab", @"\ul ");
// underline Off
rtn = rtn.Replace(@"\'bb", @"\ulnone ");
return rtn;
}
// This converts Underline or bold next word character to the corresponding on/off commands
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.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;
}
#endregion //Cell Text
#region Merged / Split Range
public void MergeSelection()
{
//string tstr = "";
//C1.Win.C1FlexGrid.CellRange sel = this.Selection;
//tstr = sel.Clip; // clip hold the data for the selected cells (used for un-merge)
this.MergedRanges.Add(this.Selection);
this.Invalidate();
}
public void SplitSelection()
{
C1.Win.C1FlexGrid.CellRange sel = this.GetMergedRange(this.Selection.r1, this.Selection.c1);
if (this.MergedRanges.Contains(sel))
this.MergedRanges.Remove(sel);
this.Invalidate();
}
private void AdjustMergedRows(int row, 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--;
crc.Add(cr);
}
}
else
{
if (row <= r.r1)
{
if (row < r.r1)
cr.r1--;
cr.r2--;
}
crc.Add(cr);
}
}
}
else // adding
foreach (CellRange r in this.MergedRanges)
{
CellRange cr = r;
int inspos = (above) ? row : row - 1;
if (r.ContainsRow(inspos))
{
if ((above && cr.r1 == inspos) || (!above && cr.r2 == inspos))
{
string tstr = "";
int newrow = 0;
if (above)
{
if (this[cr.r1 + 1, cr.c1] != null)
tstr = this[cr.r1 + 1, cr.c1].ToString();
newrow = cr.r1;
}
else
{
if (this[cr.r2, cr.c1] != null)
tstr = this[cr.r2, cr.c1].ToString();
newrow = cr.r2 + 1;
}
if (tstr != null && tstr.Length > 0)
for (int x = cr.c1; x <= cr.c2; x++)
this[newrow, x] = tstr;
}
cr.r2++;
}
else
{
if (inspos < cr.r1)
{
cr.r1++;
cr.r2++;
}
}
crc.Add(cr);
}
this.MergedRanges.Clear();
foreach (CellRange r in crc)
this.MergedRanges.Add(r);
}
private void AdjustMergedColumns(int col, 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--;
crc.Add(cr);
}
}
else
{
if (col < cr.c1)
{
cr.c1--;
cr.c2--;
}
crc.Add(cr);
}
}
}
else // adding
foreach (CellRange r in this.MergedRanges)
{
CellRange cr = r;
int inspos = (left) ? col : col - 1;
if (r.ContainsCol(inspos))
{
string tstr = "";
int newcol = 0;
if (left)
{
if (inspos == cr.c1)
tstr = this[cr.r1, cr.c1 + 1].ToString();
else
tstr = 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++;
cr.c2++;
}
crc.Add(cr);
}
this.MergedRanges.Clear();
foreach (CellRange r in crc)
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 cr = this.Selection;
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;
return rtnrow;
}
private int GetColInsertPosition(Boolean before)
{
int rtncol;
CellRange cr = this.Selection;
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;
return rtncol;
}
public void InsertColumnBefore()
{
int newcol = this.GetColInsertPosition(true);
this.Cols.Insert(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);
this.AdjustMergedColumns(colidx + 1, false, false);
this.AdjustGridControlSize();
}
public void InsertRowBefore()
{
int newrow = this.GetRowInsertPosition(true);
this.Rows.Insert(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);
this.AdjustMergedRows(rowidx + 1, false, false);
this.AdjustGridControlSize();
}
public void RemoveSelectedColumn()
{
this.SelectionMode = SelectionModeEnum.Column;
this.Select(this.Selection.r1, this.Selection.c1);
DialogResult dr = MessageBox.Show("Remove this column?", "Remove Column", MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
RemoveColumns(this.Selection.r1, this.Selection.c1, 1);
this.SelectionMode = SelectionModeEnum.Default;
}
public void RemoveSelectedRow()
{
this.SelectionMode = SelectionModeEnum.Row;
this.Select(this.Selection.r1, this.Selection.c1);
DialogResult dr = MessageBox.Show("Remove this Row?", "Remove Row", MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
this.RemoveRows(this.Selection.r1, this.Selection.c1, 1);
this.SelectionMode = SelectionModeEnum.Default;
}
private void RemoveRows(int strow, int stcol, int cnt)
{
for (int i = 0; i < cnt; i++)
{
if (this.RowIsInMergeRange(strow))
{
for (int cl = 0; cl < this.Cols.Count; cl++)
{
int idx = this.MergedRanges.IndexOf(strow, cl);
if (idx > -1)
{
CellRange cr = this.MergedRanges[idx];
if (cr.r1 < cr.r2)
this[cr.r1 + 1, cr.c1] = this[cr.r1, cr.c1];
}
cl++;
}
}
this.Rows.Remove(strow);
this.AdjustMergedRows(strow, false, true);
}
this.AdjustGridControlSize();
}
private void RemoveColumns(int strow, int stcol, int cnt)
{
for (int i = 0; i < cnt; i++)
{
if (this.ColIsInMergeRange(stcol))
{
for (int rw = 0; rw < this.Rows.Count; rw++)
{
int idx = this.MergedRanges.IndexOf(rw, stcol);
if (idx > -1)
{
CellRange cr = this.MergedRanges[idx];
if (cr.c1 < cr.c2)
this[cr.r1, cr.c1 + 1] = this[cr.r1, cr.c1];
}
}
}
this.Cols.Remove(stcol);
this.AdjustMergedColumns(stcol, false, true);
}
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.", "Invalid Selection");
return;
}
#endregion //Grid Add and Remove Row / Column
#region Clipboard
public void ClipBoardCopyRow()
{
this.SelectionMode = SelectionModeEnum.Row;
this.Select(this.Selection.r1, 0, this.Selection.r2, this.Cols.Count - 1, true);
DialogResult dr = MessageBox.Show("Copy these Rows?", "Copy Rows", MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
_clpbrdCpyPste.Put(this.Selection);
this.SelectionMode = SelectionModeEnum.Default;
}
public void ClipBoardCopyColumn()
{
this.SelectionMode = SelectionModeEnum.Column;
this.Select(0, this.Selection.c1, this.Rows.Count - 1, this.Selection.c2, true);
DialogResult dr = MessageBox.Show("Copy these columns?", "Copy Columns", MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
_clpbrdCpyPste.Put(this.Selection);
this.SelectionMode = SelectionModeEnum.Default;
}
public void ClipBoardCopySelection()
{
this.Select(this.Selection.r1, this.Selection.c1, this.Selection.r2, this.Selection.c2);
DialogResult dr = MessageBox.Show("Copy Selected Cells?", "Copy Selection", MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
_clpbrdCpyPste.Put(this.Selection);
}
private void CopyTextFromCellRange(ArrayList arylst, int srow, int scol, int erow, int ecol)
{
StepRTB trtb = new StepRTB();
int aryidx = 0;
for (int r = srow; r <= erow; r++)
{
for (int c = scol; c <= ecol; c++)
{
if (aryidx >= arylst.Count)
trtb.Text = "";
else
{
trtb.Rtf = (string)(arylst[aryidx++]);
trtb.AdjustWidthForContent();
}
this[r, c] = trtb.Rtf;
this.AdjustGridHeightWidth(r, c);
}
}
}
public enum enmPastePos : int
{
Before = 1, Replace = 0, After = -1
}
public void ClipBoardPasteRows(enmPastePos pp)
{
// Get a list of strings representing the text (rtf text) in each cell
// that was saved to the clipboard (row/column order)
ArrayList aryCellList = _clpbrdCpyPste.Get();
if (aryCellList != null && aryCellList.Count > 0)
{
// get row/column starting position in which new rows will be added
int startrow = this.Selection.r1 + ((pp == enmPastePos.After) ? 1 : 0);
int startcol = this.Selection.c1;
// get the number of rows needed based on what was save to the clipboard
int numrows = Math.Max(1, (aryCellList.Count / this.Cols.Count));
// insert that number of new rows.
if (pp != enmPastePos.Replace) // insert new rows before or after
for (int r = 0; r < numrows; r++)
if (pp == enmPastePos.After) // create new rows after
this.InsertRowAfter();
else
this.InsertRowBefore();
// copy each grid cell text (aryCellList) into the newly inserted rows
CopyTextFromCellRange(aryCellList, startrow, startcol, startrow + numrows - 1, startcol + this.Cols.Count - 1);
this.AdjustGridControlSize();
}
}
public void ClipBoardPasteColumns(enmPastePos pp)
{
// Get a list of strings representing the text (rtf text) in each cell
// that was saved to the clipboard (row/column order)
ArrayList aryCellList = _clpbrdCpyPste.Get();
if (aryCellList != null && aryCellList.Count > 0)
{
// get row/column starting position in which new rows will be added
int startrow = 0;//grd.Selection.r1+((pp == enmPastePos.After) ? 1 : 0);
int startcol = this.Selection.c1 + ((pp == enmPastePos.After) ? 1 : 0);
// get the number of rows needed based on what was save to the clipboard
int numcols = Math.Max(1, (aryCellList.Count / this.Rows.Count));
// insert that number of new rows.
if (pp != enmPastePos.Replace) // insert new rows before or after
for (int c = 0; c < numcols; c++)
if (pp == enmPastePos.After) // create new rows after
this.InsertColumnAfter();
else
this.InsertColumnBefore();
// copy each grid cell text (aryCellList) into the newly inserted rows
this.CopyTextFromCellRange(aryCellList, startrow, startcol, startrow + this.Rows.Count - 1, startcol + numcols - 1);
this.AdjustGridControlSize();
}
}
public void ClipBoardPasteIntoSelection()
{
// Get a list of strings representing the text (rtf text) in each cell
// that was saved to the clipboard (row/column order)
ArrayList aryCellList = _clpbrdCpyPste.Get();
if (aryCellList != null && aryCellList.Count > 0)
{
// copy each grid cell text (aryCellList) into the selected cells
this.CopyTextFromCellRange(aryCellList, this.Selection.r1, this.Selection.c1, this.Selection.r2, this.Selection.c2);
this.AdjustGridControlSize();
}
}
#endregion //Clipboard
#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);
}
/// <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.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;
}
/// <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 celll, and attempt to merge cells were needed.
/// </summary>
/// <param name="txtbuff"></param>
public void ParseTableFromText(string 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);
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
{
// 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--;
string jstr = (string)this[rw, curCol];
if (jstr == null)
jstr = tstr;
else
jstr += "\n" + tstr; // multi line cell
this[rw, curCol] = 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;
}
}
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;
// see what column we are in - new line might occure before last grid column
curCol = dicCols[colPos];
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);
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
{
// 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--;
string jstr = (string)this[rw, curCol];
if (jstr == null)
jstr = tstr;
else
jstr += "\n" + tstr; // multi line cell
this[rw, curCol] = 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[colPos];
while (curCol > prevCol + 1)
{
tci[curRow, prevCol].MergeColRight = true;
prevCol++;
}
// parse out the remaining text
tstr = txtbuff.Substring(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)
{
// 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--;
string jstr = (string)this[rw, curCol];
if (jstr == null)
jstr = tstr;
else
jstr += "\n" + tstr; // multi line cell
this[rw, curCol] = 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;
}
}
}
}
#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
}
#region RTF Class for Cell rendering
class RTF : StepRTB //RichTextBox
{
// 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;
// constructor: attach to owner grid
public TableCellEditor(VlnFlexGrid owner)
{
Visible = false;
AutoSize = false;
BackColor = Color.Beige;
BorderStyle = BorderStyle.None;
_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);
}
// start editing: move to cell and activate
public void StartEditing(int row, int col)
{
// save coordinates of cell being edited
_row = row;
_col = col;
this.Clear();
// 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 = "";
if (_pendingKey > ' ')
Text = _pendingKey.ToString();
else if (_owner[row, col] != null)
{
string tmp = _owner[row, col].ToString();
if (tmp.StartsWith(@"{\rtf"))
Rtf = tmp;
else
Text = tmp;
}
Select(Text.Length, 0);
Size sz = new Size(rc.Width, rc.Height);
this.Size = sz;
// make editor visible
Visible = true;
// and get the focus
Select();
}
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.Selection;
//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(row + 1, col);
break;
case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlLeft:
case VEPROMS.CSLA.Library.E_ArrowKeys.Left:
col = cr.c1;
if (col > 0)
_owner.Select(row, col - 1);
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(row, col + 1);
break;
case VEPROMS.CSLA.Library.E_ArrowKeys.CtrlUp:
case VEPROMS.CSLA.Library.E_ArrowKeys.Up:
row = cr.r1;
if (row > 0)
_owner.Select(row - 1, col);
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");
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
}
public ArrayList Get()
{
// Retrieves the data from the clipboard.
IDataObject myRetrievedObject = Clipboard.GetDataObject();
string jj = (string)myRetrievedObject.GetData(DataFormats.Text);
return GetCellStrings(jj);
}
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
}