/// <summary> /// Deletes a selected col w/ confirmation. /// </summary> /// <param name="sender"><c><see cref="it_DeleteHead"/></c></param> /// <param name="e"></param> void editcolclick_DeleteHead(object sender, EventArgs e) { int selc = Table.getSelectedCol(); const string head = _warnColhead + " Are you sure you want to delete the selected col ..."; using (var ib = new Infobox(Infobox.Title_infor, head, Table.Fields[selc - 1], InfoboxType.Info, InfoboxButtons.CancelYes)) { if (ib.ShowDialog(this) == DialogResult.OK) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); steadystate(); Table.DeleteCol(selc); it_freeze1.Enabled = Table.ColCount > 1; it_freeze2.Enabled = Table.ColCount > 2; DrawRegulator.ResumeDrawing(Table); Obfuscate(false); } } }
/// <summary> /// Deletes an array of rows in accord with /// <c><see cref="Undo()">Undo()</see></c> or /// <c><see cref="Redo()">Redo()</see></c>. /// </summary> void DeleteArray() { //logfile.Log("UndoRedo.DeleteArray()"); _grid._f.Obfuscate(); DrawRegulator.SuspendDrawing(_grid); for (int a = _it.array.Length - 1; a != -1; --a) // reverse delete. { _grid.Delete(_it.array[a]._id, false); } _grid.Calibrate(); _grid.ClearSelects(); int r = _it.array[0]._id; if (r >= _grid.RowCount) { r = _grid.RowCount - 1; } _grid.EnsureDisplayedRow(r); _grid._f.EnableRoweditOperations(); DrawRegulator.ResumeDrawing(_grid); _grid._f.Obfuscate(false); if (Settings._autorder && Yata.order() != 0) { _grid._f.layout(); } }
/// <summary> /// Inserts a <c><see cref="Row"/></c> into the table. /// </summary> /// <param name="rowid">row-id to insert at</param> /// <param name="fields">an array of fields</param> /// <param name="calibrate"><c>true</c> to re-layout the grid or /// <c>false</c> if <c><see cref="Calibrate()">Calibrate()</see></c> /// will be done by the caller</param> /// <param name="brush">a <c>Brush</c> to use for Undo/Redo</param> internal void Insert(int rowid, string[] fields, bool calibrate = true, Brush brush = null) { if (calibrate) { DrawRegulator.SuspendDrawing(this); } if (fields != null) { if (brush == null) { brush = Brushes.Created; } var row = new Row(rowid, ColCount, brush, this); string field; for (int c = 0; c != ColCount; ++c) { if (c < fields.Length) { field = fields[c]; } else { field = gs.Stars; } row[c] = new Cell(rowid, c, field); } Rows.Insert(rowid, row); ++RowCount; for (int r = rowid + 1; r != RowCount; ++r) // straighten out row._id and cell.y -> { ++(row = Rows[r])._id; for (int c = 0; c != ColCount; ++c) { ++row[c].y; } } } if (calibrate) // is only 1 row (no range) via context single-row edit { Calibrate(rowid); if (rowid < RowCount) { EnsureDisplayedRow(rowid); } DrawRegulator.ResumeDrawing(this); } }
/// <summary> /// Deletes a single or multiple <c><see cref="Row">Rows</see></c>. /// </summary> /// <remarks>Called by /// <c><see cref="Yata"/>.editrowsclick_DeleteRange()</c>.</remarks> internal void DeleteRows() { _f.Obfuscate(); DrawRegulator.SuspendDrawing(this); int selr = getSelectedRow(); int range = Math.Abs(RangeSelect); Restorable rest = UndoRedo.createArray(range + 1, UndoRedo.UrType.rt_ArrayInsert); int rFirst, rLast; if (RangeSelect > 0) { rFirst = selr; rLast = selr + RangeSelect; } else { rFirst = selr + RangeSelect; rLast = selr; } while (rLast >= rFirst) // reverse delete. { rest.array[range--] = Rows[rLast].Clone() as Row; Delete(rLast, false); --rLast; } if (RowCount == 1 && rLast == -1) // ie. if grid was blanked -> ID #0 was auto-inserted. { rLast = 0; } else { rLast = -1; // calibrate all extant rows. } Calibrate(rLast); // delete key if (selr < RowCount) { EnsureDisplayedRow(selr); } if (!Changed) { Changed = true; rest.isSaved = UndoRedo.IsSavedType.is_Undo; } _ur.Push(rest); DrawRegulator.ResumeDrawing(this); _f.Obfuscate(false); }
/// <summary> /// Handles it-click to autosize cols. /// </summary> /// <param name="sender"> /// <list type="bullet"> /// <item><c><see cref="it_AutoCols"/></c></item> /// <item><c>null</c></item> /// </list></param> /// <param name="e"></param> /// <remarks>Fired by /// <list type="bullet"> /// <item>2daOps|Autosize cols <c>[Ctrl+i]</c></item> /// <item><c><see cref="DiffReset()">DiffReset()</see></c></item> /// </list></remarks> internal void opsclick_AutosizeCols(object sender, EventArgs e) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); AutosizeCols(Table); DrawRegulator.ResumeDrawing(Table); Obfuscate(false); }
/// <summary> /// Inserts an array of rows in accord with /// <c><see cref="Undo()">Undo()</see></c> or /// <c><see cref="Redo()">Redo()</see></c>. /// </summary> void InsertArray() { //logfile.Log("UndoRedo.InsertArray()"); _grid._f.Obfuscate(); DrawRegulator.SuspendDrawing(_grid); int cols = _it.array[0].Length; var fields = new string[cols]; Row row; for (int a = 0; a != _it.array.Length; ++a) { row = _it.array[a]; for (int c = 0; c != cols; ++c) { fields[c] = String.Copy(row[c].text); } _grid.Insert(row._id, fields, false, row._brush); for (int c = 0; c != row.Length; ++c) { _grid[row._id, c].loadchanged = row[c].loadchanged; } } _grid.Calibrate(0, _grid.RowCount - 1); _grid.ClearSelects(false, true); int r = _it.array[0]._id; _grid.Rows[r].selected = true; // _grid.RangeSelect = _it.array.Length - 1; // that's problematic ... wrt/ re-Sorted cols // and since only 1 row shall ever be selected you can't just select them all either. _grid.EnsureDisplayedRow(r); // TODO: EnsureDisplayedRows() // NOTE: Does not select the row's cells. DrawRegulator.ResumeDrawing(_grid); _grid._f.Obfuscate(false); if (Settings._autorder && Yata.order() != 0) { _grid._f.layout(); } }
/// <summary> /// Pastes a range of rows. /// </summary> /// <param name="sender"><c><see cref="it_PasteRange"/></c></param> /// <param name="e"></param> /// <remarks>Fired by /// <list type="bullet"> /// <item>Rows|Paste <c>[Ctrl+Shift+v]</c></item> /// </list></remarks> void editrowsclick_PasteRange(object sender, EventArgs e) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); Restorable rest = UndoRedo.createArray(_copyr.Count, UndoRedo.UrType.rt_ArrayDelete); int selr = Table.getSelectedRow(); if (selr == -1) { selr = Table.RowCount; } int r = selr; for (int i = 0; i != _copyr.Count; ++i, ++r) { Table.Insert(r, _copyr[i], false); rest.array[i] = Table.Rows[r].Clone() as Row; } Table.Calibrate(selr, _copyr.Count - 1); // paste range Table.ClearSelects(false, true); Table.Rows[selr].selected = true; Table.RangeSelect = _copyr.Count - 1; Table.EnsureDisplayedRow(selr); if (!Table.Changed) { Table.Changed = true; rest.isSaved = UndoRedo.IsSavedType.is_Undo; } Table._ur.Push(rest); DrawRegulator.ResumeDrawing(Table); Obfuscate(false); if (Settings._autorder && order() != 0) { layout(); } }
/// <summary> /// Pastes <c><see cref="_copyc"/></c> to the cell-fields of a selected /// col. /// </summary> /// <param name="sender"><c><see cref="it_PasteCell"/></c></param> /// <param name="e"></param> void editcolclick_PasteCol(object sender, EventArgs e) { int diff; string head; if (Table.RowCount < _copyc.Count) { diff = _copyc.Count - Table.RowCount; head = "The table has " + diff + " less row" + (diff == 1 ? String.Empty : "s") + " than the copy."; } else if (Table.RowCount > _copyc.Count) { diff = Table.RowCount - _copyc.Count; head = "The copy has " + diff + " less row" + (diff == 1 ? String.Empty : "s") + " than the table."; } else { diff = 0; head = null; } if (diff != 0) { using (var ib = new Infobox(Infobox.Title_warni, head + " Proceed ...", null, InfoboxType.Warn, InfoboxButtons.CancelYes)) { if (ib.ShowDialog(this) == DialogResult.OK) { diff = 0; } } } if (diff == 0) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); Table.PasteCol(_copyc); DrawRegulator.ResumeDrawing(Table); Obfuscate(false); } }
// + " Tip: tidy and save the 2da first."; /// <summary> /// Opens a text-input dialog for creating a col at a selected col-id or /// at the far right if no col is selected. /// </summary> /// <param name="sender"><c><see cref="it_CreateHead"/></c></param> /// <param name="e"></param> void editcolclick_CreateHead(object sender, EventArgs e) { const string head = _warnColhead + " Are you sure you want to create a col ..."; using (var ib = new Infobox(Infobox.Title_infor, head, null, InfoboxType.Info, InfoboxButtons.CancelYes)) { if (ib.ShowDialog(this) == DialogResult.OK) { int selc = Table.getSelectedCol(); using (var idc = new InputDialog(this, selc)) { if (idc.ShowDialog(this) == DialogResult.OK && InputDialog._colabel.Length != 0) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); // create at far right if no col selected if (selc < Table.FrozenCount) // ~safety. { selc = Table.ColCount; } steadystate(); Table.CreateCol(selc); it_freeze1.Enabled = Table.ColCount > 1; it_freeze2.Enabled = Table.ColCount > 2; DrawRegulator.ResumeDrawing(Table); Obfuscate(false); } } } } }
/// <summary> /// Closes all other tables when a tab's context-closeall item is /// clicked. /// </summary> /// <param name="sender"><c><see cref="tabit_CloseAllOthers"/></c></param> /// <param name="e"></param> void tabclick_CloseAllOtherTabs(object sender, EventArgs e) { if (!CancelChangedTables("close", true)) { DrawRegulator.SuspendDrawing(this); // stops tab-flickering on Remove tab for (int tab = Tabs.TabCount - 1; tab != -1; --tab) { if (tab != Tabs.SelectedIndex) { ClosePage(Tabs.TabPages[tab]); } } SetTabSize(); it_SaveAll.Enabled = AllowSaveAll(); DrawRegulator.ResumeDrawing(this); } }
/// <summary> /// Lays out table after rows are ordered. /// </summary> internal void layout() { DrawRegulator.SuspendDrawing(this); if (!Table.Changed) { Table.Changed = true; } Table._ur.ResetSaved(true); if (_diff1 == Table) { _diff1 = null; } else if (_diff2 == Table) { _diff2 = null; } Table.Colwidth(0, 0, Table.RowCount - 1); Table.metricFrozenControls(FROZEN_COL_Id); Table.InitScroll(); int invalid = (YataGrid.INVALID_GRID | YataGrid.INVALID_FROZ); if (Table.Propanel != null && Table.Propanel.Visible) { invalid |= YataGrid.INVALID_PROP; } Table.Invalidator(invalid); DrawRegulator.ResumeDrawing(this); }
/// <summary> /// Handles it-click to create a new 2da-file. /// </summary> /// <param name="sender"><c><see cref="it_Create"/></c></param> /// <param name="e"></param> void fileclick_Create(object sender, EventArgs e) { Table = new YataGrid(this, String.Empty, false); Table.CreateTable(); // <- instead of LoadTable() _isCreate = true; fileclick_SaveAs(it_SaveAs, EventArgs.Empty); // shall set Fullpath (incl. tab-string). _isCreate = false; if (File.Exists(Table.Fullpath)) // instead of CreatePage() -> { DrawRegulator.SuspendDrawing(Table); var tab = new TabPage(); Tabs.TabPages.Add(tab); tab.Tag = Table; tab.Text = Path.GetFileNameWithoutExtension(Table.Fullpath); tab.Controls.Add(Table); Tabs.SelectedTab = tab; Table.Init(); DrawRegulator.ResumeDrawing(Table); } else { YataGrid._init = false; Table.Dispose(); } _bypassVerifyFile = true; tab_SelectedIndexChanged(null, EventArgs.Empty); _bypassVerifyFile = false; }
/// <summary> /// Handles it-click to reload the current table. Requests /// user-confirmation if data has changed etc. /// </summary> /// <param name="sender"> /// <list type="bullet"> /// <item><c><see cref="it_Reload"/></c></item> /// <item><c><see cref="tabit_Reload"/></c></item> /// <item><c>null</c></item> /// </list></param> /// <param name="e"></param> /// <remarks>Called by /// <list type="bullet"> /// <item>File|Reload <c>[Ctrl+r]</c></item> /// <item>tab|Reload</item> /// <item><c><see cref="VerifyCurrentFileState()">VerifyCurrentFileState()</see></c></item> /// </list></remarks> internal void fileclick_Reload(object sender, EventArgs e) { if (File.Exists(Table.Fullpath)) // check 'Table.Fullpath' in case user presses [Ctrl+r] after deleting the 2da-file on the hardrive. { bool reload = !Table.Changed; if (!reload) { using (var ib = new Infobox(Infobox.Title_alert, "Data has changed. Okay to reload ...", null, InfoboxType.Warn, InfoboxButtons.CancelYes)) { reload = ib.ShowDialog(this) == DialogResult.OK; } } if (reload) { Obfuscate(); if (_diff1 == Table) { _diff1 = null; } else if (_diff2 == Table) { _diff2 = null; } _bypassVerifyFile = true; int result = Table.LoadTable(); if (result != YataGrid.LOADRESULT_FALSE) { DrawRegulator.SuspendDrawing(Table); Table._ur.Clear(); it_freeze1.Checked = it_freeze2.Checked = false; Table.Init(result == YataGrid.LOADRESULT_CHANGED, true); if (Table.Propanel != null) { Table.Controls.Remove(Table.Propanel); Table.Propanel = null; } DrawRegulator.ResumeDrawing(Table); } else { Table.Changed = false; // bypass Close warn fileclick_ClosePage(sender, e); } _bypassVerifyFile = false; if (Table != null) { Obfuscate(false); VerifyCurrentFileState(); } } } else { using (var ib = new Infobox(Infobox.Title_error, "File does not exist.", Table.Fullpath, InfoboxType.Error)) { ib.ShowDialog(this); } } }
/// <summary> /// Applies a specified <c>Font</c> to Yata. /// </summary> /// <param name="font"></param> internal void doFont(Font font) { // NOTE: Cf f.AutoScaleMode (None,Font,DPI,Inherit) // Since I'm doing all the necessary scaling due to font-changes // w/ code the AutoScaleMode should not be set to default "Font". // It might better be set to "DPI" for those weirdos and I don't // know what "Inherit" means (other than the obvious). // AutoScaleMode is currently set to "None". // // See also SetProcessDPIAware() // NOTE: Apparently setting GraphicsUnit.Pixel when creating new // Font-objects effectively bypasses the OS's DPI user-setting. Font.Dispose(); Font = font; Settings._fontdialog.Dispose(); Settings._fontdialog = Settings.CreateDialogFont(Font); FontAccent.Dispose(); FontAccent = new Font(Font, getStyleAccented(Font.FontFamily)); YataGrid.SetStaticMetrics(this); if (Table != null) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); SetTabSize(); YataGrid table; for (int tab = 0; tab != Tabs.TabCount; ++tab) { table = Tabs.TabPages[tab].Tag as YataGrid; table.CreateCols(true); table.Calibrate(0, table.RowCount - 1); // font // TODO: This is effed because the Height (at least) of each // table is not well-defined by .NET - OnResize() for the // tables gets called multiples times per table and the // value of Height changes arbitrarily. Since an accurate // Height is required by InitScrollers() a glitch occurs // when the height of Font increases. That is if a cell or // a row is currently selected it will NOT be fully // displayed if it is NOT on the currently displayed page // and it is near the bottom of the tab-control's page-area; // several pixels of the selected cell or row will still be // covered by the horizontal scroller. Given the arbitrary // Height changes that occur throughout this function's // sequence in fact it's surprising/remarkable that things // turn out even almost correct. // NOTE: Height of any table should NOT be changing at all. if (table == Table) { table.Invalidator(table.EnsureDisplayed()); } } DrawRegulator.ResumeDrawing(Table); Obfuscate(false); if (_ffont != null) // layout for big tables will send the Font dialog below the form -> { _ffont.BringToFront(); // (although it should never be behind the form because its owner IS the form) } } }
/// <summary> /// Instantiates <c><see cref="RowCreatorDialog"/></c> for /// inserting/creating multiple rows. /// </summary> /// <param name="sender"><c><see cref="it_CreateRows"/></c></param> /// <param name="e"></param> /// <remarks>Fired by /// <list type="bullet"> /// <item>Rows|Create ... <c>[F2]</c></item> /// </list></remarks> void editrowsclick_CreateRows(object sender, EventArgs e) { int selr = Table.getSelectedRowOrCells(); using (var rcd = new RowCreatorDialog(this, selr, _copyr.Count != 0)) { if (rcd.ShowDialog(this) == DialogResult.OK) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); Restorable rest = UndoRedo.createArray(_lengthCr, UndoRedo.UrType.rt_ArrayDelete); var cells = new string[Table.ColCount]; switch (_fillCr) { case CrFillType.Stars: for (int i = 0; i != Table.ColCount; ++i) { cells[i] = gs.Stars; } break; case CrFillType.Selected: for (int i = 0; i != Table.ColCount; ++i) { cells[i] = Table[selr, i].text; } break; case CrFillType.Copied: for (int i = 0; i != Table.ColCount; ++i) { if (i < _copyr[0].Length) { cells[i] = _copyr[0][i]; } else { cells[i] = gs.Stars; } } break; } int r = _startCr; for (int i = 0; i != _lengthCr; ++i, ++r) { cells[0] = r.ToString(CultureInfo.InvariantCulture); Table.Insert(r, cells, false); rest.array[i] = Table.Rows[r].Clone() as Row; } Table.Calibrate(_startCr, _lengthCr - 1); // insert range Table.ClearSelects(false, true); Table.Rows[_startCr].selected = true; Table.RangeSelect = _lengthCr - 1; Table.EnsureDisplayedRow(_startCr); if (!Table.Changed) { Table.Changed = true; rest.isSaved = UndoRedo.IsSavedType.is_Undo; } Table._ur.Push(rest); DrawRegulator.ResumeDrawing(Table); Obfuscate(false); if (Settings._autorder && order() != 0) { layout(); } } } }
/// <summary> /// Deletes a <c><see cref="Row"/></c> from the table. /// </summary> /// <param name="idr">row-id to delete</param> /// <param name="calibrate"><c>true</c> to re-layout the grid or /// <c>false</c> if <c><see cref="Calibrate()">Calibrate()</see></c> /// will be done by the caller</param> internal void Delete(int idr, bool calibrate = true) { if (calibrate) { DrawRegulator.SuspendDrawing(this); } Row row; Rows.Remove(Rows[idr]); --RowCount; for (int r = idr; r != RowCount; ++r) // straighten out row._id and cell.y -> { --(row = Rows[r])._id; for (int c = 0; c != ColCount; ++c) { --row[c].y; } } if (RowCount == 0) // add a row of stars so grid is not left blank -> { ++RowCount; row = new Row(0, ColCount, Brushes.Created, this); int c = 0; if (Settings._autorder) { row[c++] = new Cell(0, 0, "0"); } for (; c != ColCount; ++c) { row[c] = new Cell(0, c, gs.Stars); } Rows.Add(row); if (calibrate) { Calibrate(0); DrawRegulator.ResumeDrawing(this); return; } } if (calibrate) // is only 1 row (no range) via context single-row edit { Calibrate(); if (idr < RowCount) { EnsureDisplayedRow(idr); } DrawRegulator.ResumeDrawing(this); } }