/// <summary> /// Determines required width for the value-fields col. /// </summary> internal void widthValcol() { // for (int r = 0; r != _grid.RowCount; ++r) // for (int c = 0; c != _grid.ColCount; ++c) // { // wT = YataGraphics.MeasureWidth(_grid[r,c].text, Font); // if (wT > _widthVals) // _widthVals = wT; // } // _widthVals += _padHori * 2; _widthVals = 0; int wT, rT = 0, cT = 0; for (int r = 0; r != _grid.RowCount; ++r) { for (int c = 0; c != _grid.ColCount; ++c) { if ((wT = _grid[r, c]._widthtext) > _widthVals) // NOTE: Assume that the widest text in the table-font { // will be widest text in the propanel font. Much faster. _widthVals = wT; rT = r; cT = c; } } } _widthVals = _editRect.Width = YataGraphics.MeasureWidth(_grid[rT, cT].text, Font) + _padHori * 2; _editor.Width = _widthVals - 6; // cf YataGrid.Celledit() telemetric(); }
/// <summary> /// Deters height based on line-height * lines. /// </summary> /// <param name="text"></param> /// <returns></returns> int GetHeight(string text) { string[] lines = text.Split(gs.CRandorLF, StringSplitOptions.None); return(YataGraphics.MeasureHeight(YataGraphics.HEIGHT_TEST, rt_Copyable.Font) * lines.Length); }
/// <summary> /// Creates the cols and caches the 2da's colhead data. /// </summary> /// <param name="rewidthOnly"><c>true</c> to only re-width cols - ie. /// Font changed</param> /// <seealso cref="CreateCol()"><c>CreateCol()</c></seealso> internal void CreateCols(bool rewidthOnly = false) { int c = 0; if (!rewidthOnly) { ColCount = Fields.Length + 1; // 'Fields' does not include rowhead or id-col for (; c != ColCount; ++c) { Cols.Add(new Col()); } Cols[0].text = gs.Id; // NOTE: Is not measured - the cells below it determine col-width. } int widthtext; c = 0; foreach (string head in Fields) // set initial col-widths based on colheads only -> { ++c; // start at col 1 - skip id col if (!rewidthOnly) { Cols[c].text = head; } widthtext = YataGraphics.MeasureWidth(head, _f.FontAccent); Cols[c]._widthtext = widthtext; Cols[c].width(widthtext + _padHori * 2 + _padHoriSort, rewidthOnly); } }
const int _padHoriSort = 12; // additional horizontal text padding to the right in the colheads for the sort-arrow #endregion Fields (static) #region Methods (static) /// <summary> /// Sets standard <c><see cref="HeightColhead"/></c>, /// <c><see cref="HeightRow"/></c>, and minimum cell-width /// <c><see cref="_wId"/></c>. Also caches width of "****" in /// <c><see cref="_wStars"/></c>. /// </summary> /// <param name="f"></param> /// <remarks>These values are the same for all loaded tables.</remarks> internal static void SetStaticMetrics(Yata f) { HeightColhead = YataGraphics.MeasureHeight(YataGraphics.HEIGHT_TEST, f.FontAccent) + _padVert * 2; HeightRow = YataGraphics.MeasureHeight(YataGraphics.HEIGHT_TEST, f.Font) + _padVert * 2; _wId = YataGraphics.MeasureWidth(gs.Id, f.Font) + _padHoriRowhead * 2; _wStars = YataGraphics.MeasureWidth(gs.Stars, f.Font); }
/// <summary> /// cTor. /// </summary> /// <param name="title">a caption on the titlebar</param> /// <param name="label">info to be displayed with a proportional font</param> /// <param name="copyable">info to be displayed with a fixed font in a /// RichTextBox so it can be copied</param> /// <param name="f">parent <c><see cref="Yata"/></c></param> /// <param name="color"></param> /// <param name="goto"></param> /// <param name="reset"></param> internal DifferDialog( string title, string label, string copyable, Yata f, Color color, bool @goto, bool reset) { _f = f; InitializeComponent(); Initialize(YataDialog.METRIC_LOC, true); Text = title; bu_Goto.Visible = @goto; bu_Reset.Visible = reset; la_Info.ForeColor = color; la_Info.Height = YataGraphics.MeasureHeight(label, Font) + 15; // +15 = label's pad top+bot +5 la_Info.Text = label; int w; if (!String.IsNullOrEmpty(copyable)) { copyable += Environment.NewLine; // add a blank line to bot of the copyable text. w = GetWidth(copyable) + 30; // +30 = parent panel's pad left+right +5 pa_Copyable.Height = GetHeight(copyable) + 20; // +20 = parent panel's pad top+bot +5 rt_Copyable.Text = copyable; } else { pa_Copyable.Visible = false; pa_Copyable.Height = w = 0; } if (w < WIDTH_Min) { w = WIDTH_Min; } ClientSize = new Size(w + 20, // +20 = pad real and imagined. la_Info.Height + pa_Copyable.Height + bu_Okay.Height); MinimumSize = new Size(Width, Height); Show(_f); // Yata is owner. }
/// <summary> /// cTor. Instantiates this <c>FileWatcherDialog</c>. /// </summary> /// <param name="grid">the <c><see cref="YataGrid"/></c> being watched</param> /// <param name="fwdType"><c><see cref="FwdType"/></c> /// <list type="bullet"> /// <item><c><see cref="FwdType.FileDeleted">Fwd.FileDeleted</see></c></item> /// <item><c><see cref="FwdType.FileChanged">Fwd.FileChanged</see></c></item> /// </list></param> internal FileWatcherDialog( YataGrid grid, FwdType fwdType) { //logfile.Log("FileWatcherDialog.cTor()"); _f = (_grid = grid)._f; // 'YataDialog._f' is used only to set UI parameters. InitializeComponent(); Initialize(YataDialog.METRIC_NON); string text = String.Empty; switch (_fwdType = fwdType) { case FwdType.FileDeleted: text = FILE_Del; bu_Action.Text = "Resave"; break; case FwdType.FileChanged: text = FILE_Wsc; bu_Action.Text = "Reload"; break; } if (_grid.Readonly) { text += " CANCEL DISABLES THE READONLY FLAG."; } la_Info.Text = text; int wInfo = YataGraphics.MeasureWidth(la_Info.Text, la_Info.Font); tb_Pfe.Text = _grid.Fullpath; int wPfe = YataGraphics.MeasureWidth(tb_Pfe.Text, tb_Pfe.Font); ClientSize = new Size(Math.Max(wInfo, wPfe) + 20, ClientSize.Height); MinimumSize = new Size(Math.Max(WIDTH_Min, Width), Height); MaximumSize = new Size(Int32.MaxValue, Height); _t1.Tick += t1_OnTick; _t1.Interval = 330; // enable button delay. _t1.Start(); _t2.Tick += t2_OnTick; _t2.Interval = 300; // watch file period. _t2.Start(); }
/// <summary> /// Deters width based on longest copyable line. /// </summary> /// <param name="text"></param> /// <returns></returns> int GetWidth(string text) { string[] lines = text.Split(gs.CRandorLF, StringSplitOptions.RemoveEmptyEntries); int width = 0, test; foreach (var line in lines) { if ((test = YataGraphics.MeasureWidth(line, rt_Copyable.Font)) > width) { width = test; } } return(width); }
/// <summary> /// Relabels a col. /// </summary> /// <param name="selc"></param> internal void RelabelCol(int selc) { Fields[selc - 1] = InputDialog._colabel; // the Field-count is 1 less than the col-count Cols[selc]._widthtext = YataGraphics.MeasureWidth((Cols[selc].text = InputDialog._colabel), _f.FontAccent); Colwidth(selc); InitScroll(); EnsureDisplayedCol(selc); Invalidator(INVALID_COLS); if (!Changed) { Changed = true; } }
/// <summary> /// Calculates and maintains rowhead width wrt/ current Font across all /// tabs/tables. /// </summary> /// <param name="f"></param> internal static void metricStaticHeads(Yata f) { YataGrid table; int rows = 0, rowsTest; // row-headers' width stays uniform across all tabpages int tabs = f.Tabs.TabCount; int tab = 0; for (; tab != tabs; ++tab) // find the table w/ most rows -> { table = f.Tabs.TabPages[tab].Tag as YataGrid; if ((rowsTest = table.RowCount - 1) > rows) { rows = rowsTest; } } string texttest = "9"; // determine how many nines need to be measured -> while ((rows /= 10) != 0) { texttest += "9"; } WidthRowhead = YataGraphics.MeasureWidth(texttest, f.FontAccent) + _padHoriRowhead * 2; for (tab = 0; tab != tabs; ++tab) { table = f.Tabs.TabPages[tab].Tag as YataGrid; table.WidthTable = WidthRowhead; foreach (var col in table.Cols) { table.WidthTable += col.width(); } table._panelRows.Width = WidthRowhead; table._panelCols.Height = HeightColhead; metricFrozenLabels(table); } }
/// <summary> /// Clones a specified <c>Font</c> and reduces it in size (if necessary) /// to fit in dialogs. /// </summary> /// <param name="font">a <c>Font</c> to potentially reduce in size</param> /// <returns>a <c>Font</c> that's roughly the size of Yata's default /// <c>Font</c></returns> internal static Font CreateDialogFont(ICloneable font) { var fontdialog = font.Clone() as Font; string label = fontdialog.Name; FontStyle style = Yata.getStyleStandard(fontdialog.FontFamily); // the font as it appears in a dialog is smaller than the same font // with the SAME pointsize as it appears on the table ... float pts = fontdialog.SizeInPoints; while (YataGraphics.MeasureHeight(YataGraphics.HEIGHT_TEST, fontdialog) > YataGraphics.hFontDefault) { fontdialog.Dispose(); fontdialog = new Font(label, pts -= 0.75F, style); } return(fontdialog); }
/// <summary> /// Resets the width of a specified col based on the cells in rows /// <paramref name="r"/> to <paramref name="r"/> + /// <paramref name="range"/>. /// </summary> /// <param name="c">col</param> /// <param name="r">first row to consider as changed (default -1 if /// deleting rows and/or no extant text-widths have changed; ie, no /// text-widths need to be re-measured)</param> /// <param name="range">range of rows to consider as changed (default 0 /// for a single row)</param> internal void Colwidth(int c, int r = -1, int range = 0) { Col col = Cols[c]; int colwidth = col._widthtext + _padHoriSort; int widthtext; if (r != -1) // re-calc '_widthtext' regardless of what happens below -> { string text; int rend = r + range; for (; r <= rend; ++r) { if ((text = this[r, c].text) == gs.Stars) // bingo. { widthtext = _wStars; } else { widthtext = YataGraphics.MeasureWidth(text, Font); } this[r, c]._widthtext = widthtext; if (widthtext > colwidth) { colwidth = widthtext; } } } if (!col.UserSized) // ie. don't resize a col that user has adjusted. If it needs to { // be forced (eg. on reload) unflag UserSized on all cols first. int totalwidth = col.width(); if ((colwidth += _padHori * 2) > totalwidth) { col.width(colwidth); } else if (colwidth < totalwidth) // recalc width on the entire col { if (c == 0 || _wId > colwidth) { colwidth = _wId; } for (r = 0; r != RowCount; ++r) { widthtext = this[r, c]._widthtext + _padHori * 2; if (widthtext > colwidth) { colwidth = widthtext; } } col.width(colwidth, true); } if (range == 0 && totalwidth != colwidth) // if range >0 let Calibrate() handle multiple { // cols or at least the scrollers and do the UI-update InitScroll(); Invalidator(INVALID_GRID | INVALID_COLS); } } if (Propanel != null && Propanel.Visible) { Propanel.widthValcol(); // TODO: Re-calc the 'c' col only. } }
/// <summary> /// Creates a col. /// </summary> /// <param name="selc"></param> /// <seealso cref="CreateCols()"><c>CreateCols()</c></seealso> internal void CreateCol(int selc) { --selc; // the Field-count is 1 less than the col-count int fieldsLength = Fields.Length + 1; // create a new Fields array -> var fields = new string[fieldsLength]; for (int i = 0; i != fieldsLength; ++i) { if (i < selc) { fields[i] = Fields[i]; } else if (i == selc) { fields[i] = InputDialog._colabel; var col = new Col(); col.text = InputDialog._colabel; col._widthtext = YataGraphics.MeasureWidth(col.text, _f.FontAccent); col.width(col._widthtext + _padHori * 2 + _padHoriSort); col.selected = true; Cols.Insert(i + 1, col); ++ColCount; for (int r = 0; r != RowCount; ++r) { var cells = new Cell[ColCount]; // create a new Cells array in each row -> for (int c = 0; c != ColCount; ++c) { if (c < selc + 1) { cells[c] = this[r, c]; } else if (c == selc + 1) { cells[c] = new Cell(r, c, gs.Stars); cells[c].selected = true; cells[c]._widthtext = _wStars; } else // (c > selc + 1) { cells[c] = this[r, c - 1]; cells[c].x += 1; } } Rows[r]._cells = cells; Rows[r].Length += 1; } } else // (i > selc) { fields[i] = Fields[i - 1]; } } Fields = fields; int w = _wStars + _padHori * 2; if (w > Cols[++selc].width()) { Cols[selc].width(w); } InitScroll(); EnsureDisplayedCol(selc); _f.EnableCelleditOperations(); if (!Changed) { Changed = true; } }
/// <summary> /// cTor. /// </summary> /// <remarks>Each tabbed table gets its own Propanel.</remarks> internal Propanel(YataGrid grid) { DrawRegulator.SetDoubleBuffered(this); _grid = grid; if (Settings._gradient) { BackColor = Color.SkyBlue; } else { BackColor = Color.LightBlue; } Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom; TabStop = false; // <- the Propanel is not currently coded to cope w/ keyboard-input. if (Settings._font3 != null) { // Font.Dispose(); // be wary. Be very wary. -> Do NOT Dispose() // debug builds don't throw // but release builds CTD when invoking the SettingsEditor after // the Propanel has been opened ... eg. Font = Settings._font3; } else { Font = new Font("Verdana", 7.25F, FontStyle.Regular, GraphicsUnit.Point, (byte)0); } if (_heightr == -1) { _heightr = YataGraphics.MeasureHeight(YataGraphics.HEIGHT_TEST, Font) + _padVert * 2; } _editRect.Height = _heightr - 1; // cf YataGrid.EditCell() HeightProps = _grid.ColCount * _heightr; int wT; for (int c = 0; c != _grid.ColCount; ++c) { wT = YataGraphics.MeasureWidth(_grid.Cols[c].text, Font); if (wT > _widthVars) { _widthVars = wT; } } _widthVars += _padHori * 2 + 1; _scroll.Dock = DockStyle.Right; _scroll.LargeChange = _heightr; _scroll.ValueChanged += scroll_valuechanged; widthValcol(); Controls.Add(_scroll); _grid.Controls.Add(this); _editor.Leave += editor_leave; Controls.Add(_editor); }
/// <summary> /// Creates the <c><see cref="Row">Rows</see></c> and adds /// <c><see cref="Cell">Cells</see></c> to each <c>Row</c>. Also sets /// <c><see cref="Cell.loadchanged">Cell.loadchanged</see></c> if a /// cell-field's text was altered/corrected while loading the 2da for /// this <c>YataGrid</c>. /// </summary> void CreateRows() { RowCount = _rows.Count; bool changed = false, loadchanged; string text; bool isLoadchanged = false; for (int r = 0; r != RowCount; ++r) { changed = changed || _rows[r].Length > ColCount; // flag Changed if any field(s) get cut off. Rows.Add(new Row(r, ColCount, (r % 2 == 0) ? Brushes.Alice : Brushes.Bob, this)); for (int c = 0; c != ColCount; ++c) { loadchanged = false; if (c < _rows[r].Length) { text = _rows[r][c]; if (VerifyText(ref text, true)) { changed = loadchanged = isLoadchanged = true; } } else { text = gs.Stars; changed = loadchanged = isLoadchanged = true; } (this[r, c] = new Cell(r, c, text)).loadchanged = loadchanged; } } if (isLoadchanged) // inform user regardless of Strict setting -> { using (var ib = new Infobox(Infobox.Title_infor, "Cell-texts changed.")) ib.ShowDialog(_f); } Changed |= changed; _rows.Clear(); // done w/ '_rows' int w, wT; // adjust col-widths based on fields -> for (int c = 0; c != ColCount; ++c) { w = _wId; // start each col at min colwidth for (int r = 0; r != RowCount; ++r) { if ((text = this[r, c].text) == gs.Stars) // bingo. { wT = _wStars; } else { wT = YataGraphics.MeasureWidth(text, Font); } this[r, c]._widthtext = wT; if ((wT += _padHori * 2) > w) { w = wT; } } Cols[c].width(w); } // var threads = new Thread[ColCount]; // for (int c = 0; c != ColCount; ++c) // { // int cT = c; // threads[c] = new Thread(() => doCol(cT)); // //logfile.Log("c= " + c + " IsBackground= " + threads[c].IsBackground); // default false // threads[c].IsBackground = true; // threads[c].Start(); // } // int procs = Environment.ProcessorCount; // logfile.Log("ProcessorCount= " + procs); // var threads = new Thread[procs]; // for (int i = 0; i != procs; ++i) // { // threads[i] = new Thread(()=> doCol(0, RowCount/procs)); // wont work - a lone doCol() method would be totally thread unsafe. // } // int c0 = 0; // int c1 = ColCount / 4; // int c2 = ColCount / 2; // int c3 = ColCount * 3 / 4; // int c4 = ColCount; // // logfile.Log("c0= " + c0); // logfile.Log("c1= " + c1); // logfile.Log("c2= " + c2); // logfile.Log("c3= " + c3); // logfile.Log("c4= " + c4); // // var threads = new Thread[4]; // threads[0] = new Thread(()=> doCol0(c0,c1)); // threads[0].IsBackground = true; // threads[0].Start(); // threads[1] = new Thread(()=> doCol1(c1,c2)); // threads[1].IsBackground = true; // threads[1].Start(); // threads[2] = new Thread(()=> doCol2(c2,c3)); // threads[2].IsBackground = true; // threads[2].Start(); // threads[3] = new Thread(()=> doCol3(c3,c4)); // threads[3].IsBackground = true; // threads[3].Start(); // // foreach (var thread in threads) // thread.Join(); }