123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542 |
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Text;
- using Terminal.Gui;
- namespace UICatalog.Scenarios;
- [ScenarioMetadata ("TableEditor", "Implements data table editor using the TableView control.")]
- [ScenarioCategory ("TableView")]
- [ScenarioCategory ("Controls")]
- [ScenarioCategory ("Dialogs")]
- [ScenarioCategory ("Text and Formatting")]
- public class TableEditor : Scenario
- {
- private readonly HashSet<FileSystemInfo> _checkedFileSystemInfos = new ();
- private readonly List<IDisposable> _toDispose = new ();
- private readonly List<UnicodeRange> Ranges = new ()
- {
- new (
- 0x0000,
- 0x001F,
- "ASCII Control Characters"
- ),
- new (0x0080, 0x009F, "C0 Control Characters"),
- new (
- 0x1100,
- 0x11ff,
- "Hangul Jamo"
- ), // This is where wide chars tend to start
- new (0x20A0, 0x20CF, "Currency Symbols"),
- new (0x2100, 0x214F, "Letterlike Symbols"),
- new (0x2190, 0x21ff, "Arrows"),
- new (0x2200, 0x22ff, "Mathematical symbols"),
- new (
- 0x2300,
- 0x23ff,
- "Miscellaneous Technical"
- ),
- new (
- 0x2500,
- 0x25ff,
- "Box Drawing & Geometric Shapes"
- ),
- new (0x2600, 0x26ff, "Miscellaneous Symbols"),
- new (0x2700, 0x27ff, "Dingbats"),
- new (0x2800, 0x28ff, "Braille"),
- new (
- 0x2b00,
- 0x2bff,
- "Miscellaneous Symbols and Arrows"
- ),
- new (
- 0xFB00,
- 0xFb4f,
- "Alphabetic Presentation Forms"
- ),
- new (
- 0x12400,
- 0x1240f,
- "Cuneiform Numbers and Punctuation"
- ),
- new (
- (uint)(UICatalog.Scenarios.UnicodeRange.Ranges.Max (r => r.End) - 16),
- (uint)UICatalog.Scenarios.UnicodeRange.Ranges.Max (r => r.End),
- "End"
- ),
- new (0x0020, 0x007F, "Basic Latin"),
- new (0x00A0, 0x00FF, "Latin-1 Supplement"),
- new (0x0100, 0x017F, "Latin Extended-A"),
- new (0x0180, 0x024F, "Latin Extended-B"),
- new (0x0250, 0x02AF, "IPA Extensions"),
- new (
- 0x02B0,
- 0x02FF,
- "Spacing Modifier Letters"
- ),
- new (
- 0x0300,
- 0x036F,
- "Combining Diacritical Marks"
- ),
- new (0x0370, 0x03FF, "Greek and Coptic"),
- new (0x0400, 0x04FF, "Cyrillic"),
- new (0x0500, 0x052F, "Cyrillic Supplementary"),
- new (0x0530, 0x058F, "Armenian"),
- new (0x0590, 0x05FF, "Hebrew"),
- new (0x0600, 0x06FF, "Arabic"),
- new (0x0700, 0x074F, "Syriac"),
- new (0x0780, 0x07BF, "Thaana"),
- new (0x0900, 0x097F, "Devanagari"),
- new (0x0980, 0x09FF, "Bengali"),
- new (0x0A00, 0x0A7F, "Gurmukhi"),
- new (0x0A80, 0x0AFF, "Gujarati"),
- new (0x0B00, 0x0B7F, "Oriya"),
- new (0x0B80, 0x0BFF, "Tamil"),
- new (0x0C00, 0x0C7F, "Telugu"),
- new (0x0C80, 0x0CFF, "Kannada"),
- new (0x0D00, 0x0D7F, "Malayalam"),
- new (0x0D80, 0x0DFF, "Sinhala"),
- new (0x0E00, 0x0E7F, "Thai"),
- new (0x0E80, 0x0EFF, "Lao"),
- new (0x0F00, 0x0FFF, "Tibetan"),
- new (0x1000, 0x109F, "Myanmar"),
- new (0x10A0, 0x10FF, "Georgian"),
- new (0x1100, 0x11FF, "Hangul Jamo"),
- new (0x1200, 0x137F, "Ethiopic"),
- new (0x13A0, 0x13FF, "Cherokee"),
- new (
- 0x1400,
- 0x167F,
- "Unified Canadian Aboriginal Syllabics"
- ),
- new (0x1680, 0x169F, "Ogham"),
- new (0x16A0, 0x16FF, "Runic"),
- new (0x1700, 0x171F, "Tagalog"),
- new (0x1720, 0x173F, "Hanunoo"),
- new (0x1740, 0x175F, "Buhid"),
- new (0x1760, 0x177F, "Tagbanwa"),
- new (0x1780, 0x17FF, "Khmer"),
- new (0x1800, 0x18AF, "Mongolian"),
- new (0x1900, 0x194F, "Limbu"),
- new (0x1950, 0x197F, "Tai Le"),
- new (0x19E0, 0x19FF, "Khmer Symbols"),
- new (0x1D00, 0x1D7F, "Phonetic Extensions"),
- new (
- 0x1E00,
- 0x1EFF,
- "Latin Extended Additional"
- ),
- new (0x1F00, 0x1FFF, "Greek Extended"),
- new (0x2000, 0x206F, "General Punctuation"),
- new (
- 0x2070,
- 0x209F,
- "Superscripts and Subscripts"
- ),
- new (0x20A0, 0x20CF, "Currency Symbols"),
- new (
- 0x20D0,
- 0x20FF,
- "Combining Diacritical Marks for Symbols"
- ),
- new (0x2100, 0x214F, "Letterlike Symbols"),
- new (0x2150, 0x218F, "Number Forms"),
- new (0x2190, 0x21FF, "Arrows"),
- new (0x2200, 0x22FF, "Mathematical Operators"),
- new (
- 0x2300,
- 0x23FF,
- "Miscellaneous Technical"
- ),
- new (0x2400, 0x243F, "Control Pictures"),
- new (
- 0x2440,
- 0x245F,
- "Optical Character Recognition"
- ),
- new (0x2460, 0x24FF, "Enclosed Alphanumerics"),
- new (0x2500, 0x257F, "Box Drawing"),
- new (0x2580, 0x259F, "Block Elements"),
- new (0x25A0, 0x25FF, "Geometric Shapes"),
- new (0x2600, 0x26FF, "Miscellaneous Symbols"),
- new (0x2700, 0x27BF, "Dingbats"),
- new (
- 0x27C0,
- 0x27EF,
- "Miscellaneous Mathematical Symbols-A"
- ),
- new (0x27F0, 0x27FF, "Supplemental Arrows-A"),
- new (0x2800, 0x28FF, "Braille Patterns"),
- new (0x2900, 0x297F, "Supplemental Arrows-B"),
- new (
- 0x2980,
- 0x29FF,
- "Miscellaneous Mathematical Symbols-B"
- ),
- new (
- 0x2A00,
- 0x2AFF,
- "Supplemental Mathematical Operators"
- ),
- new (
- 0x2B00,
- 0x2BFF,
- "Miscellaneous Symbols and Arrows"
- ),
- new (
- 0x2E80,
- 0x2EFF,
- "CJK Radicals Supplement"
- ),
- new (0x2F00, 0x2FDF, "Kangxi Radicals"),
- new (
- 0x2FF0,
- 0x2FFF,
- "Ideographic Description Characters"
- ),
- new (
- 0x3000,
- 0x303F,
- "CJK Symbols and Punctuation"
- ),
- new (0x3040, 0x309F, "Hiragana"),
- new (0x30A0, 0x30FF, "Katakana"),
- new (0x3100, 0x312F, "Bopomofo"),
- new (
- 0x3130,
- 0x318F,
- "Hangul Compatibility Jamo"
- ),
- new (0x3190, 0x319F, "Kanbun"),
- new (0x31A0, 0x31BF, "Bopomofo Extended"),
- new (
- 0x31F0,
- 0x31FF,
- "Katakana Phonetic Extensions"
- ),
- new (
- 0x3200,
- 0x32FF,
- "Enclosed CJK Letters and Months"
- ),
- new (0x3300, 0x33FF, "CJK Compatibility"),
- new (
- 0x3400,
- 0x4DBF,
- "CJK Unified Ideographs Extension A"
- ),
- new (
- 0x4DC0,
- 0x4DFF,
- "Yijing Hexagram Symbols"
- ),
- new (0x4E00, 0x9FFF, "CJK Unified Ideographs"),
- new (0xA000, 0xA48F, "Yi Syllables"),
- new (0xA490, 0xA4CF, "Yi Radicals"),
- new (0xAC00, 0xD7AF, "Hangul Syllables"),
- new (0xD800, 0xDB7F, "High Surrogates"),
- new (
- 0xDB80,
- 0xDBFF,
- "High Private Use Surrogates"
- ),
- new (0xDC00, 0xDFFF, "Low Surrogates"),
- new (0xE000, 0xF8FF, "Private Use Area"),
- new (
- 0xF900,
- 0xFAFF,
- "CJK Compatibility Ideographs"
- ),
- new (
- 0xFB00,
- 0xFB4F,
- "Alphabetic Presentation Forms"
- ),
- new (
- 0xFB50,
- 0xFDFF,
- "Arabic Presentation Forms-A"
- ),
- new (0xFE00, 0xFE0F, "Variation Selectors"),
- new (0xFE20, 0xFE2F, "Combining Half Marks"),
- new (
- 0xFE30,
- 0xFE4F,
- "CJK Compatibility Forms"
- ),
- new (0xFE50, 0xFE6F, "Small Form Variants"),
- new (
- 0xFE70,
- 0xFEFF,
- "Arabic Presentation Forms-B"
- ),
- new (
- 0xFF00,
- 0xFFEF,
- "Halfwidth and Fullwidth Forms"
- ),
- new (0xFFF0, 0xFFFF, "Specials"),
- new (0x10000, 0x1007F, "Linear B Syllabary"),
- new (0x10080, 0x100FF, "Linear B Ideograms"),
- new (0x10100, 0x1013F, "Aegean Numbers"),
- new (0x10300, 0x1032F, "Old Italic"),
- new (0x10330, 0x1034F, "Gothic"),
- new (0x10380, 0x1039F, "Ugaritic"),
- new (0x10400, 0x1044F, "Deseret"),
- new (0x10450, 0x1047F, "Shavian"),
- new (0x10480, 0x104AF, "Osmanya"),
- new (0x10800, 0x1083F, "Cypriot Syllabary"),
- new (
- 0x1D000,
- 0x1D0FF,
- "Byzantine Musical Symbols"
- ),
- new (0x1D100, 0x1D1FF, "Musical Symbols"),
- new (
- 0x1D300,
- 0x1D35F,
- "Tai Xuan Jing Symbols"
- ),
- new (
- 0x1D400,
- 0x1D7FF,
- "Mathematical Alphanumeric Symbols"
- ),
- new (0x1F600, 0x1F532, "Emojis Symbols"),
- new (
- 0x20000,
- 0x2A6DF,
- "CJK Unified Ideographs Extension B"
- ),
- new (
- 0x2F800,
- 0x2FA1F,
- "CJK Compatibility Ideographs Supplement"
- ),
- new (0xE0000, 0xE007F, "Tags")
- };
- private ColorScheme _alternatingColorScheme;
- private DataTable _currentTable;
- private MenuItem _miAlternatingColors;
- private MenuItem _miAlwaysShowHeaders;
- private MenuItem _miAlwaysUseNormalColorForVerticalCellLines;
- private MenuItem _miBottomline;
- private MenuItem _miCellLines;
- private MenuItem _miCheckboxes;
- private MenuItem _miCursor;
- private MenuItem _miExpandLastColumn;
- private MenuItem _miFullRowSelect;
- private MenuItem _miHeaderMidline;
- private MenuItem _miHeaderOverline;
- private MenuItem _miHeaderUnderline;
- private MenuItem _miRadioboxes;
- private MenuItem _miShowHeaders;
- private MenuItem _miShowHorizontalScrollIndicators;
- private MenuItem _miSmoothScrolling;
- private ColorScheme _redColorScheme;
- private ColorScheme _redColorSchemeAlt;
- private TableView _tableView;
- /// <summary>
- /// Builds a simple table in which cell values contents are the index of the cell. This helps testing that
- /// scrolling etc is working correctly and not skipping out any rows/columns when paging
- /// </summary>
- /// <param name="cols"></param>
- /// <param name="rows"></param>
- /// <returns></returns>
- public static DataTable BuildSimpleDataTable (int cols, int rows)
- {
- var dt = new DataTable ();
- for (var c = 0; c < cols; c++)
- {
- dt.Columns.Add ("Col" + c);
- }
- for (var r = 0; r < rows; r++)
- {
- DataRow newRow = dt.NewRow ();
- for (var c = 0; c < cols; c++)
- {
- newRow [c] = $"R{r}C{c}";
- }
- dt.Rows.Add (newRow);
- }
- return dt;
- }
- public override void Main ()
- {
- // Init
- Application.Init ();
- // Setup - Create a top-level application window and configure it.
- Toplevel appWindow = new ();
- _tableView = new () { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
- var menu = new MenuBar
- {
- Menus =
- [
- new (
- "_File",
- new MenuItem []
- {
- new (
- "_OpenBigExample",
- "",
- () => OpenExample (true)
- ),
- new (
- "_OpenSmallExample",
- "",
- () => OpenExample (false)
- ),
- new (
- "OpenCharacter_Map",
- "",
- () => OpenUnicodeMap ()
- ),
- new (
- "OpenTreeExample",
- "",
- () => OpenTreeExample ()
- ),
- new (
- "_CloseExample",
- "",
- () => CloseExample ()
- ),
- new ("_Quit", "", () => Quit ())
- }
- ),
- new (
- "_View",
- new []
- {
- _miShowHeaders =
- new (
- "_ShowHeaders",
- "",
- () => ToggleShowHeaders ()
- )
- {
- Checked = _tableView.Style.ShowHeaders,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miAlwaysShowHeaders =
- new (
- "_AlwaysShowHeaders",
- "",
- () => ToggleAlwaysShowHeaders ()
- )
- {
- Checked = _tableView.Style.AlwaysShowHeaders,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miHeaderOverline =
- new (
- "_HeaderOverLine",
- "",
- () => ToggleOverline ()
- )
- {
- Checked = _tableView.Style
- .ShowHorizontalHeaderOverline,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miHeaderMidline = new (
- "_HeaderMidLine",
- "",
- () => ToggleHeaderMidline ()
- )
- {
- Checked = _tableView.Style
- .ShowVerticalHeaderLines,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miHeaderUnderline = new (
- "_HeaderUnderLine",
- "",
- () => ToggleUnderline ()
- )
- {
- Checked = _tableView.Style
- .ShowHorizontalHeaderUnderline,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miBottomline = new (
- "_BottomLine",
- "",
- () => ToggleBottomline ()
- )
- {
- Checked = _tableView.Style
- .ShowHorizontalBottomline,
- CheckType = MenuItemCheckStyle
- .Checked
- },
- _miShowHorizontalScrollIndicators =
- new (
- "_HorizontalScrollIndicators",
- "",
- () =>
- ToggleHorizontalScrollIndicators ()
- )
- {
- Checked = _tableView.Style
- .ShowHorizontalScrollIndicators,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miFullRowSelect = new (
- "_FullRowSelect",
- "",
- () => ToggleFullRowSelect ()
- )
- {
- Checked = _tableView.FullRowSelect,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miCellLines = new (
- "_CellLines",
- "",
- () => ToggleCellLines ()
- )
- {
- Checked = _tableView.Style
- .ShowVerticalCellLines,
- CheckType = MenuItemCheckStyle
- .Checked
- },
- _miExpandLastColumn =
- new (
- "_ExpandLastColumn",
- "",
- () => ToggleExpandLastColumn ()
- )
- {
- Checked = _tableView.Style.ExpandLastColumn,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miAlwaysUseNormalColorForVerticalCellLines =
- new (
- "_AlwaysUseNormalColorForVerticalCellLines",
- "",
- () =>
- ToggleAlwaysUseNormalColorForVerticalCellLines ()
- )
- {
- Checked = _tableView.Style
- .AlwaysUseNormalColorForVerticalCellLines,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miSmoothScrolling =
- new (
- "_SmoothHorizontalScrolling",
- "",
- () => ToggleSmoothScrolling ()
- )
- {
- Checked = _tableView.Style
- .SmoothHorizontalScrolling,
- CheckType = MenuItemCheckStyle.Checked
- },
- new ("_AllLines", "", () => ToggleAllCellLines ()),
- new ("_NoLines", "", () => ToggleNoCellLines ()),
- _miCheckboxes = new (
- "_Checkboxes",
- "",
- () => ToggleCheckboxes (false)
- )
- {
- Checked = false,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miRadioboxes = new (
- "_Radioboxes",
- "",
- () => ToggleCheckboxes (true)
- )
- {
- Checked = false,
- CheckType = MenuItemCheckStyle.Checked
- },
- _miAlternatingColors =
- new (
- "Alternating Colors",
- "",
- () => ToggleAlternatingColors ()
- ) { CheckType = MenuItemCheckStyle.Checked },
- _miCursor =
- new (
- "Invert Selected Cell First Character",
- "",
- () =>
- ToggleInvertSelectedCellFirstCharacter ()
- )
- {
- Checked = _tableView.Style
- .InvertSelectedCellFirstCharacter,
- CheckType = MenuItemCheckStyle.Checked
- },
- new (
- "_ClearColumnStyles",
- "",
- () => ClearColumnStyles ()
- ),
- new ("Sho_w All Columns", "", () => ShowAllColumns ())
- }
- ),
- new (
- "_Column",
- new MenuItem []
- {
- new ("_Set Max Width", "", SetMaxWidth),
- new ("_Set Min Width", "", SetMinWidth),
- new (
- "_Set MinAcceptableWidth",
- "",
- SetMinAcceptableWidth
- ),
- new (
- "_Set All MinAcceptableWidth=1",
- "",
- SetMinAcceptableWidthToOne
- )
- }
- )
- ]
- };
- appWindow.Add (menu);
- var selectedCellLabel = new Label
- {
- Text = "0,0"
- };
- var statusBar = new StatusBar (
- [
- new (
- Application.QuitKey,
- "Quit",
- Quit
- ),
- new (
- Key.F2,
- "OpenExample",
- () => OpenExample (true)
- ),
- new (
- Key.F3,
- "CloseExample",
- CloseExample
- ),
- new (
- Key.F4,
- "OpenSimple",
- () => OpenSimple (true)
- ),
- new ()
- {
- HelpText = "Cell:",
- CommandView = selectedCellLabel
- }
- ]
- )
- {
- AlignmentModes = AlignmentModes.IgnoreFirstOrLast
- };
- appWindow.Add (statusBar);
- appWindow.Add (_tableView);
- _tableView.SelectedCellChanged += (s, e) => { selectedCellLabel.Text = $"{_tableView.SelectedRow},{_tableView.SelectedColumn}"; };
- _tableView.CellActivated += EditCurrentCell;
- _tableView.KeyDown += TableViewKeyPress;
- //SetupScrollBar ();
- _redColorScheme = new ()
- {
- Disabled = appWindow.ColorScheme.Disabled,
- HotFocus = appWindow.ColorScheme.HotFocus,
- Focus = appWindow.ColorScheme.Focus,
- Normal = new (Color.Red, appWindow.ColorScheme.Normal.Background)
- };
- _alternatingColorScheme = new ()
- {
- Disabled = appWindow.ColorScheme.Disabled,
- HotFocus = appWindow.ColorScheme.HotFocus,
- Focus = appWindow.ColorScheme.Focus,
- Normal = new (Color.White, Color.BrightBlue)
- };
- _redColorSchemeAlt = new ()
- {
- Disabled = appWindow.ColorScheme.Disabled,
- HotFocus = appWindow.ColorScheme.HotFocus,
- Focus = appWindow.ColorScheme.Focus,
- Normal = new (Color.Red, Color.BrightBlue)
- };
- // if user clicks the mouse in TableView
- _tableView.MouseClick += (s, e) =>
- {
- if (_currentTable == null)
- {
- return;
- }
- _tableView.ScreenToCell (e.Position, out int? clickedCol);
- if (clickedCol != null)
- {
- if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
- {
- // left click in a header
- SortColumn (clickedCol.Value);
- }
- else if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
- {
- // right click in a header
- ShowHeaderContextMenu (clickedCol.Value, e);
- }
- }
- };
- _tableView.KeyBindings.ReplaceCommands (Key.Space, Command.Accept);
- // Run - Start the application.
- Application.Run (appWindow);
- appWindow.Dispose ();
- // Shutdown - Calling Application.Shutdown is required.
- Application.Shutdown ();
- }
- protected override void Dispose (bool disposing)
- {
- base.Dispose (disposing);
- foreach (IDisposable d in _toDispose)
- {
- d.Dispose ();
- }
- }
- private DataTable BuildUnicodeMap ()
- {
- var dt = new DataTable ();
- // add cols called 0 to 9
- for (var i = 0; i < 10; i++)
- {
- DataColumn col = dt.Columns.Add (i.ToString (), typeof (uint));
- ColumnStyle style = _tableView.Style.GetOrCreateColumnStyle (col.Ordinal);
- style.RepresentationGetter = o => new Rune ((uint)o).ToString ();
- }
- // add cols called a to z
- for (int i = 'a'; i < 'a' + 26; i++)
- {
- DataColumn col = dt.Columns.Add (((char)i).ToString (), typeof (uint));
- ColumnStyle style = _tableView.Style.GetOrCreateColumnStyle (col.Ordinal);
- style.RepresentationGetter = o => new Rune ((uint)o).ToString ();
- }
- // now add table contents
- List<uint> runes = new ();
- foreach (UnicodeRange range in Ranges)
- {
- for (uint i = range.Start; i <= range.End; i++)
- {
- runes.Add (i);
- }
- }
- DataRow dr = null;
- for (var i = 0; i < runes.Count; i++)
- {
- if (dr == null || i % dt.Columns.Count == 0)
- {
- dr = dt.Rows.Add ();
- }
- dr [i % dt.Columns.Count] = runes [i].ToString ();
- }
- return dt;
- }
- private void CheckOrUncheckFile (FileSystemInfo info, bool check)
- {
- if (check)
- {
- _checkedFileSystemInfos.Add (info);
- }
- else
- {
- _checkedFileSystemInfos.Remove (info);
- }
- }
- private void ClearColumnStyles ()
- {
- _tableView.Style.ColumnStyles.Clear ();
- _tableView.Update ();
- }
- private void CloseExample () { _tableView.Table = null; }
- private void EditCurrentCell (object sender, CellActivatedEventArgs e)
- {
- if (e.Table is not DataTableSource || _currentTable == null)
- {
- return;
- }
- int tableCol = ToTableCol (e.Col);
- if (tableCol < 0)
- {
- return;
- }
- object o = _currentTable.Rows [e.Row] [tableCol];
- string title = o is uint u ? GetUnicodeCategory (u) + $"(0x{o:X4})" : "Enter new value";
- var oldValue = _currentTable.Rows [e.Row] [tableCol].ToString ();
- var okPressed = false;
- var ok = new Button { Text = "Ok", IsDefault = true };
- ok.Accepting += (s, e) =>
- {
- okPressed = true;
- Application.RequestStop ();
- };
- var cancel = new Button { Text = "Cancel" };
- cancel.Accepting += (s, e) => { Application.RequestStop (); };
- var d = new Dialog { Title = title, Buttons = [ok, cancel] };
- var lbl = new Label { X = 0, Y = 1, Text = _tableView.Table.ColumnNames [e.Col] };
- var tf = new TextField { Text = oldValue, X = 0, Y = 2, Width = Dim.Fill () };
- d.Add (lbl, tf);
- tf.SetFocus ();
- Application.Run (d);
- d.Dispose ();
- if (okPressed)
- {
- try
- {
- _currentTable.Rows [e.Row] [tableCol] =
- string.IsNullOrWhiteSpace (tf.Text) ? DBNull.Value : tf.Text;
- }
- catch (Exception ex)
- {
- MessageBox.ErrorQuery (60, 20, "Failed to set text", ex.Message, "Ok");
- }
- _tableView.Update ();
- }
- }
- private IEnumerable<FileSystemInfo> GetChildren (FileSystemInfo arg)
- {
- try
- {
- return arg is DirectoryInfo d ? d.GetFileSystemInfos () : Enumerable.Empty<FileSystemInfo> ();
- }
- catch (Exception)
- {
- // Permission denied etc
- return Enumerable.Empty<FileSystemInfo> ();
- }
- }
- private int? GetColumn ()
- {
- if (_tableView.Table == null)
- {
- return null;
- }
- if (_tableView.SelectedColumn < 0 || _tableView.SelectedColumn > _tableView.Table.Columns)
- {
- return null;
- }
- return _tableView.SelectedColumn;
- }
- private string GetHumanReadableFileSize (FileSystemInfo fsi)
- {
- if (fsi is not FileInfo fi)
- {
- return null;
- }
- long value = fi.Length;
- CultureInfo culture = CultureInfo.CurrentUICulture;
- return GetHumanReadableFileSize (value, culture);
- }
- private string GetHumanReadableFileSize (long value, CultureInfo culture)
- {
- const long ByteConversion = 1024;
- string [] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
- if (value < 0)
- {
- return "-" + GetHumanReadableFileSize (-value, culture);
- }
- if (value == 0)
- {
- return "0.0 bytes";
- }
- var mag = (int)Math.Log (value, ByteConversion);
- double adjustedSize = value / Math.Pow (1000, mag);
- return string.Format (culture.NumberFormat, "{0:n2} {1}", adjustedSize, SizeSuffixes [mag]);
- }
- private string GetProposedNewSortOrder (int clickedCol, out bool isAsc)
- {
- // work out new sort order
- string sort = _currentTable.DefaultView.Sort;
- string colName = _tableView.Table.ColumnNames [clickedCol];
- if (sort?.EndsWith ("ASC") ?? false)
- {
- sort = $"{colName} DESC";
- isAsc = false;
- }
- else
- {
- sort = $"{colName} ASC";
- isAsc = true;
- }
- return sort;
- }
- private string GetUnicodeCategory (uint u) { return Ranges.FirstOrDefault (r => u >= r.Start && u <= r.End)?.Category ?? "Unknown"; }
- private bool HasCheckboxes () { return _tableView.Table is CheckBoxTableSourceWrapperBase; }
- private void HideColumn (int clickedCol)
- {
- ColumnStyle style = _tableView.Style.GetOrCreateColumnStyle (clickedCol);
- style.Visible = false;
- _tableView.Update ();
- }
- private void OpenExample (bool big)
- {
- SetTable (TableView.BuildDemoDataTable (big ? 30 : 5, big ? 1000 : 5));
- SetDemoTableStyles ();
- }
- private void OpenSimple (bool big) { SetTable (BuildSimpleDataTable (big ? 30 : 5, big ? 1000 : 5)); }
- private void OpenTreeExample ()
- {
- _tableView.Style.ColumnStyles.Clear ();
- TreeView<FileSystemInfo> tree = new ()
- {
- AspectGetter = f => f.Name, TreeBuilder = new DelegateTreeBuilder<FileSystemInfo> (GetChildren)
- };
- TreeTableSource<FileSystemInfo> source = new (
- _tableView,
- "Name",
- tree,
- new ()
- {
- { "Extension", f => f.Extension },
- { "CreationTime", f => f.CreationTime },
- { "FileSize", GetHumanReadableFileSize }
- }
- );
- HashSet<string> seen = new ();
- try
- {
- foreach (string path in Environment.GetLogicalDrives ())
- {
- tree.AddObject (new DirectoryInfo (path));
- }
- }
- catch (Exception e)
- {
- MessageBox.ErrorQuery ("Could not find local drives", e.Message, "Ok");
- }
- _tableView.Table = source;
- _toDispose.Add (tree);
- }
- private void OpenUnicodeMap ()
- {
- SetTable (BuildUnicodeMap ());
- _tableView.Update ();
- }
- private void Quit () { Application.RequestStop (); }
- private void RunColumnWidthDialog (
- int? col,
- string prompt,
- Action<ColumnStyle, int> setter,
- Func<ColumnStyle, int> getter
- )
- {
- if (col == null)
- {
- return;
- }
- var accepted = false;
- var ok = new Button { Text = "Ok", IsDefault = true };
- ok.Accepting += (s, e) =>
- {
- accepted = true;
- Application.RequestStop ();
- };
- var cancel = new Button { Text = "Cancel" };
- cancel.Accepting += (s, e) => { Application.RequestStop (); };
- var d = new Dialog
- {
- Title = prompt,
- Buttons = [ok, cancel]
- };
- ColumnStyle style = _tableView.Style.GetOrCreateColumnStyle (col.Value);
- var lbl = new Label { X = 0, Y = 0, Text = $"{_tableView.Table.ColumnNames [col.Value]}: " };
- var tf = new TextField { Text = getter (style).ToString (), X = Pos.Right (lbl), Y = 0, Width = 20 };
- d.Add (lbl, tf);
- tf.SetFocus ();
- Application.Run (d);
- d.Dispose ();
- if (accepted)
- {
- try
- {
- setter (style, int.Parse (tf.Text));
- }
- catch (Exception ex)
- {
- MessageBox.ErrorQuery (60, 20, "Failed to set", ex.Message, "Ok");
- }
- _tableView.Update ();
- }
- }
- private void SetDemoTableStyles ()
- {
- _tableView.Style.ColumnStyles.Clear ();
- var alignMid = new ColumnStyle { Alignment = Alignment.Center };
- var alignRight = new ColumnStyle { Alignment = Alignment.End };
- var dateFormatStyle = new ColumnStyle
- {
- Alignment = Alignment.End,
- RepresentationGetter = v =>
- v is DateTime d ? d.ToString ("yyyy-MM-dd") : v.ToString ()
- };
- var negativeRight = new ColumnStyle
- {
- Format = "0.##",
- MinWidth = 10,
- AlignmentGetter = v => v is double d
- ?
- // align negative values right
- d < 0
- ? Alignment.End
- :
- // align positive values left
- Alignment.Start
- :
- // not a double
- Alignment.Start,
- ColorGetter = a => a.CellValue is double d
- ?
- // color 0 and negative values red
- d <= 0.0000001
- ? a.RowIndex % 2 == 0
- && _miAlternatingColors.Checked == true
- ? _redColorSchemeAlt
- : _redColorScheme
- :
- // use normal scheme for positive values
- null
- :
- // not a double
- null
- };
- _tableView.Style.ColumnStyles.Add (_currentTable.Columns ["DateCol"].Ordinal, dateFormatStyle);
- _tableView.Style.ColumnStyles.Add (_currentTable.Columns ["DoubleCol"].Ordinal, negativeRight);
- _tableView.Style.ColumnStyles.Add (_currentTable.Columns ["NullsCol"].Ordinal, alignMid);
- _tableView.Style.ColumnStyles.Add (_currentTable.Columns ["IntCol"].Ordinal, alignRight);
- _tableView.Update ();
- }
- private void SetMaxWidth ()
- {
- int? col = GetColumn ();
- RunColumnWidthDialog (col, "MaxWidth", (s, v) => s.MaxWidth = v, s => s.MaxWidth);
- }
- private void SetMinAcceptableWidth ()
- {
- int? col = GetColumn ();
- RunColumnWidthDialog (
- col,
- "MinAcceptableWidth",
- (s, v) => s.MinAcceptableWidth = v,
- s => s.MinAcceptableWidth
- );
- }
- private void SetMinAcceptableWidthToOne ()
- {
- for (var i = 0; i < _tableView.Table.Columns; i++)
- {
- ColumnStyle style = _tableView.Style.GetOrCreateColumnStyle (i);
- style.MinAcceptableWidth = 1;
- }
- }
- private void SetMinWidth ()
- {
- int? col = GetColumn ();
- RunColumnWidthDialog (col, "MinWidth", (s, v) => s.MinWidth = v, s => s.MinWidth);
- }
- private void SetTable (DataTable dataTable) { _tableView.Table = new DataTableSource (_currentTable = dataTable); }
- //private void SetupScrollBar ()
- //{
- // var scrollBar = new ScrollBarView (_tableView, true);
- // scrollBar.ChangedPosition += (s, e) =>
- // {
- // _tableView.RowOffset = scrollBar.Position;
- // if (_tableView.RowOffset != scrollBar.Position)
- // {
- // scrollBar.Position = _tableView.RowOffset;
- // }
- // _tableView.SetNeedsDraw ();
- // };
- // /*
- // scrollBar.OtherScrollBarView.ChangedPosition += (s,e) => {
- // tableView.LeftItem = scrollBar.OtherScrollBarView.Position;
- // if (tableView.LeftItem != scrollBar.OtherScrollBarView.Position) {
- // scrollBar.OtherScrollBarView.Position = tableView.LeftItem;
- // }
- // tableView.SetNeedsDraw ();
- // };*/
- // _tableView.DrawingContent += (s, e) =>
- // {
- // scrollBar.Size = _tableView.Table?.Rows ?? 0;
- // scrollBar.Position = _tableView.RowOffset;
- // //scrollBar.OtherScrollBarView.Size = tableView.Maxlength - 1;
- // //scrollBar.OtherScrollBarView.Position = tableView.LeftItem;
- // scrollBar.Refresh ();
- // };
- //}
- private void ShowAllColumns ()
- {
- foreach (KeyValuePair<int, ColumnStyle> colStyle in _tableView.Style.ColumnStyles)
- {
- colStyle.Value.Visible = true;
- }
- _tableView.Update ();
- }
- private void ShowHeaderContextMenu (int clickedCol, MouseEventArgs e)
- {
- if (HasCheckboxes () && clickedCol == 0)
- {
- return;
- }
- string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
- string colName = _tableView.Table.ColumnNames [clickedCol];
- var contextMenu = new ContextMenu
- {
- Position = new (e.Position.X + 1, e.Position.Y + 1)
- };
- MenuBarItem menuItems = new (
- [
- new (
- $"Hide {TrimArrows (colName)}",
- "",
- () => HideColumn (clickedCol)
- ),
- new (
- $"Sort {StripArrows (sort)}",
- "",
- () => SortColumn (
- clickedCol,
- sort,
- isAsc
- )
- )
- ]
- );
- contextMenu.Show (menuItems);
- }
- private void SortColumn (int clickedCol)
- {
- string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
- // don't try to sort on the toggled column
- if (HasCheckboxes () && clickedCol == 0)
- {
- return;
- }
- SortColumn (clickedCol, sort, isAsc);
- }
- private void SortColumn (int clickedCol, string sort, bool isAsc)
- {
- if (_currentTable == null)
- {
- return;
- }
- // set a sort order
- _currentTable.DefaultView.Sort = sort;
- // copy the rows from the view
- DataTable sortedCopy = _currentTable.DefaultView.ToTable ();
- _currentTable.Rows.Clear ();
- foreach (DataRow r in sortedCopy.Rows)
- {
- _currentTable.ImportRow (r);
- }
- foreach (DataColumn col in _currentTable.Columns)
- {
- // remove any lingering sort indicator
- col.ColumnName = TrimArrows (col.ColumnName);
- // add a new one if this the one that is being sorted
- if (col.Ordinal == clickedCol)
- {
- col.ColumnName += isAsc ? CM.Glyphs.UpArrow : CM.Glyphs.DownArrow;
- }
- }
- _tableView.Update ();
- }
- private string StripArrows (string columnName) { return columnName.Replace ($"{CM.Glyphs.DownArrow}", "").Replace ($"{CM.Glyphs.UpArrow}", ""); }
- private void TableViewKeyPress (object sender, Key e)
- {
- if (_currentTable == null)
- {
- return;
- }
- if (e.KeyCode == KeyCode.Delete)
- {
- if (_tableView.FullRowSelect)
- {
- // Delete button deletes all rows when in full row mode
- foreach (int toRemove in _tableView.GetAllSelectedCells ()
- .Select (p => p.Y)
- .Distinct ()
- .OrderByDescending (i => i))
- {
- _currentTable.Rows.RemoveAt (toRemove);
- }
- }
- else
- {
- // otherwise set all selected cells to null
- foreach (Point pt in _tableView.GetAllSelectedCells ())
- {
- _currentTable.Rows [pt.Y] [pt.X] = DBNull.Value;
- }
- }
- _tableView.Update ();
- e.Handled = true;
- }
- }
- private void ToggleAllCellLines ()
- {
- _tableView.Style.ShowHorizontalHeaderOverline = true;
- _tableView.Style.ShowVerticalHeaderLines = true;
- _tableView.Style.ShowHorizontalHeaderUnderline = true;
- _tableView.Style.ShowVerticalCellLines = true;
- _miHeaderOverline.Checked = true;
- _miHeaderMidline.Checked = true;
- _miHeaderUnderline.Checked = true;
- _miCellLines.Checked = true;
- _tableView.Update ();
- }
- private void ToggleAlternatingColors ()
- {
- //toggle menu item
- _miAlternatingColors.Checked = !_miAlternatingColors.Checked;
- if (_miAlternatingColors.Checked == true)
- {
- _tableView.Style.RowColorGetter = a => { return a.RowIndex % 2 == 0 ? _alternatingColorScheme : null; };
- }
- else
- {
- _tableView.Style.RowColorGetter = null;
- }
- _tableView.SetNeedsDraw ();
- }
- private void ToggleAlwaysShowHeaders ()
- {
- _miAlwaysShowHeaders.Checked = !_miAlwaysShowHeaders.Checked;
- _tableView.Style.AlwaysShowHeaders = (bool)_miAlwaysShowHeaders.Checked;
- _tableView.Update ();
- }
- private void ToggleAlwaysUseNormalColorForVerticalCellLines ()
- {
- _miAlwaysUseNormalColorForVerticalCellLines.Checked =
- !_miAlwaysUseNormalColorForVerticalCellLines.Checked;
- _tableView.Style.AlwaysUseNormalColorForVerticalCellLines =
- (bool)_miAlwaysUseNormalColorForVerticalCellLines.Checked;
- _tableView.Update ();
- }
- private void ToggleBottomline ()
- {
- _miBottomline.Checked = !_miBottomline.Checked;
- _tableView.Style.ShowHorizontalBottomline = (bool)_miBottomline.Checked;
- _tableView.Update ();
- }
- private void ToggleCellLines ()
- {
- _miCellLines.Checked = !_miCellLines.Checked;
- _tableView.Style.ShowVerticalCellLines = (bool)_miCellLines.Checked;
- _tableView.Update ();
- }
- private void ToggleCheckboxes (bool radio)
- {
- if (_tableView.Table is CheckBoxTableSourceWrapperBase wrapper)
- {
- // unwrap it to remove check boxes
- _tableView.Table = wrapper.Wrapping;
- _miCheckboxes.Checked = false;
- _miRadioboxes.Checked = false;
- // if toggling off checkboxes/radio
- if (wrapper.UseRadioButtons == radio)
- {
- return;
- }
- }
- ITableSource source;
- // Either toggling on checkboxes/radio or switching from radio to checkboxes (or vice versa)
- if (_tableView.Table is TreeTableSource<FileSystemInfo> treeSource)
- {
- source = new CheckBoxTableSourceWrapperByObject<FileSystemInfo> (
- _tableView,
- treeSource,
- _checkedFileSystemInfos.Contains,
- CheckOrUncheckFile
- )
- { UseRadioButtons = radio };
- }
- else
- {
- source = new CheckBoxTableSourceWrapperByIndex (_tableView, _tableView.Table) { UseRadioButtons = radio };
- }
- _tableView.Table = source;
- if (radio)
- {
- _miRadioboxes.Checked = true;
- _miCheckboxes.Checked = false;
- }
- else
- {
- _miRadioboxes.Checked = false;
- _miCheckboxes.Checked = true;
- }
- }
- private void ToggleExpandLastColumn ()
- {
- _miExpandLastColumn.Checked = !_miExpandLastColumn.Checked;
- _tableView.Style.ExpandLastColumn = (bool)_miExpandLastColumn.Checked;
- _tableView.Update ();
- }
- private void ToggleFullRowSelect ()
- {
- _miFullRowSelect.Checked = !_miFullRowSelect.Checked;
- _tableView.FullRowSelect = (bool)_miFullRowSelect.Checked;
- _tableView.Update ();
- }
- private void ToggleHeaderMidline ()
- {
- _miHeaderMidline.Checked = !_miHeaderMidline.Checked;
- _tableView.Style.ShowVerticalHeaderLines = (bool)_miHeaderMidline.Checked;
- _tableView.Update ();
- }
- private void ToggleHorizontalScrollIndicators ()
- {
- _miShowHorizontalScrollIndicators.Checked = !_miShowHorizontalScrollIndicators.Checked;
- _tableView.Style.ShowHorizontalScrollIndicators = (bool)_miShowHorizontalScrollIndicators.Checked;
- _tableView.Update ();
- }
- private void ToggleInvertSelectedCellFirstCharacter ()
- {
- //toggle menu item
- _miCursor.Checked = !_miCursor.Checked;
- _tableView.Style.InvertSelectedCellFirstCharacter = (bool)_miCursor.Checked;
- _tableView.SetNeedsDraw ();
- }
- private void ToggleNoCellLines ()
- {
- _tableView.Style.ShowHorizontalHeaderOverline = false;
- _tableView.Style.ShowVerticalHeaderLines = false;
- _tableView.Style.ShowHorizontalHeaderUnderline = false;
- _tableView.Style.ShowVerticalCellLines = false;
- _miHeaderOverline.Checked = false;
- _miHeaderMidline.Checked = false;
- _miHeaderUnderline.Checked = false;
- _miCellLines.Checked = false;
- _tableView.Update ();
- }
- private void ToggleOverline ()
- {
- _miHeaderOverline.Checked = !_miHeaderOverline.Checked;
- _tableView.Style.ShowHorizontalHeaderOverline = (bool)_miHeaderOverline.Checked;
- _tableView.Update ();
- }
- private void ToggleShowHeaders ()
- {
- _miShowHeaders.Checked = !_miShowHeaders.Checked;
- _tableView.Style.ShowHeaders = (bool)_miShowHeaders.Checked;
- _tableView.Update ();
- }
- private void ToggleSmoothScrolling ()
- {
- _miSmoothScrolling.Checked = !_miSmoothScrolling.Checked;
- _tableView.Style.SmoothHorizontalScrolling = (bool)_miSmoothScrolling.Checked;
- _tableView.Update ();
- }
- private void ToggleUnderline ()
- {
- _miHeaderUnderline.Checked = !_miHeaderUnderline.Checked;
- _tableView.Style.ShowHorizontalHeaderUnderline = (bool)_miHeaderUnderline.Checked;
- _tableView.Update ();
- }
- private int ToTableCol (int col)
- {
- if (HasCheckboxes ())
- {
- return col - 1;
- }
- return col;
- }
- private string TrimArrows (string columnName)
- {
- return columnName.TrimEnd (
- (char)CM.Glyphs.UpArrow.Value,
- (char)CM.Glyphs.DownArrow.Value
- );
- }
- public class UnicodeRange (uint start, uint end, string category)
- {
- public readonly string Category = category;
- public readonly uint End = end;
- public readonly uint Start = start;
- }
- }
|