diff --git a/Terminal.Gui/Views/TabView.cs b/Terminal.Gui/Views/TabView.cs index a0e052f1d..ce9c8f525 100644 --- a/Terminal.Gui/Views/TabView.cs +++ b/Terminal.Gui/Views/TabView.cs @@ -6,72 +6,6 @@ using System.Linq; namespace Terminal.Gui { - /// - /// A single tab in a - /// - public class Tab { - private ustring text; - - /// - /// The text to display in a - /// - /// - public ustring Text { get => text ?? "Unamed"; set => text = value; } - - /// - /// The control to display when the tab is selected - /// - /// - public View View { get; set; } - - /// - /// Creates a new unamed tab with no controls inside - /// - public Tab () - { - - } - - /// - /// Creates a new tab with the given text hosting a view - /// - /// - /// - public Tab (string text, View view) - { - this.Text = text; - this.View = view; - } - } - - /// - /// Describes render stylistic selections of a - /// - public class TabStyle { - - /// - /// True to show the top lip of tabs. False to directly begin with tab text during - /// rendering. When true header line occupies 3 rows, when false only 2. - /// Defaults to true. - /// - /// When is enabled this instead applies to the - /// bottommost line of the control - /// - public bool ShowTopLine { get; set; } = true; - - - /// - /// True to show a solid box around the edge of the control. Defaults to true. - /// - public bool ShowBorder { get; set; } = true; - - /// - /// True to render tabs at the bottom of the view instead of the top - /// - public bool TabsOnBottom { get; set; } = false; - - } - /// /// Control that hosts multiple sub views, presenting a single one at once /// @@ -481,6 +415,8 @@ namespace Terminal.Gui { SetNeedsDisplay (); } + #region Nested Types + private class TabToRender { public int X { get; set; } public Tab Tab { get; set; } @@ -808,32 +744,100 @@ namespace Terminal.Gui { return tabs.LastOrDefault (t => x >= t.X && x < t.X + t.Width)?.Tab; } } - } - /// - /// Describes a change in - /// - public class TabChangedEventArgs : EventArgs { /// - /// The previously selected tab. May be null + /// A single tab in a /// - public Tab OldTab { get; } + public class Tab { + private ustring text; - /// - /// The currently selected tab. May be null - /// - public Tab NewTab { get; } + /// + /// The text to display in a + /// + /// + public ustring Text { get => text ?? "Unamed"; set => text = value; } - /// - /// Documents a tab change - /// - /// - /// - public TabChangedEventArgs (Tab oldTab, Tab newTab) - { - OldTab = oldTab; - NewTab = newTab; + /// + /// The control to display when the tab is selected + /// + /// + public View View { get; set; } + + /// + /// Creates a new unamed tab with no controls inside + /// + public Tab () + { + + } + + /// + /// Creates a new tab with the given text hosting a view + /// + /// + /// + public Tab (string text, View view) + { + this.Text = text; + this.View = view; + } } + + /// + /// Describes render stylistic selections of a + /// + public class TabStyle { + + /// + /// True to show the top lip of tabs. False to directly begin with tab text during + /// rendering. When true header line occupies 3 rows, when false only 2. + /// Defaults to true. + /// + /// When is enabled this instead applies to the + /// bottommost line of the control + /// + public bool ShowTopLine { get; set; } = true; + + + /// + /// True to show a solid box around the edge of the control. Defaults to true. + /// + public bool ShowBorder { get; set; } = true; + + /// + /// True to render tabs at the bottom of the view instead of the top + /// + public bool TabsOnBottom { get; set; } = false; + + } + + /// + /// Describes a change in + /// + public class TabChangedEventArgs : EventArgs { + + /// + /// The previously selected tab. May be null + /// + public Tab OldTab { get; } + + /// + /// The currently selected tab. May be null + /// + public Tab NewTab { get; } + + /// + /// Documents a tab change + /// + /// + /// + public TabChangedEventArgs (Tab oldTab, Tab newTab) + { + OldTab = oldTab; + NewTab = newTab; + } + } + #endregion } } \ No newline at end of file diff --git a/Terminal.Gui/Views/TableView.cs b/Terminal.Gui/Views/TableView.cs index d0ae87ae3..c91a2942a 100644 --- a/Terminal.Gui/Views/TableView.cs +++ b/Terminal.Gui/Views/TableView.cs @@ -6,137 +6,7 @@ using System.Linq; namespace Terminal.Gui { - /// - /// Describes how to render a given column in a including - /// and textual representation of cells (e.g. date formats) - /// - /// See TableView Deep Dive for more information. - /// - public class ColumnStyle { - - /// - /// Defines the default alignment for all values rendered in this column. For custom alignment based on cell contents use . - /// - public TextAlignment Alignment {get;set;} - /// - /// Defines a delegate for returning custom alignment per cell based on cell values. When specified this will override - /// - public Func AlignmentGetter; - - /// - /// Defines a delegate for returning custom representations of cell values. If not set then is used. Return values from your delegate may be truncated e.g. based on - /// - public Func RepresentationGetter; - - /// - /// Defines the format for values e.g. "yyyy-MM-dd" for dates - /// - public string Format{get;set;} - - /// - /// Set the maximum width of the column in characters. This value will be ignored if more than the tables . Defaults to - /// - public int MaxWidth {get;set;} = TableView.DefaultMaxCellWidth; - - /// - /// Set the minimum width of the column in characters. This value will be ignored if more than the tables or the - /// - public int MinWidth {get;set;} - - /// - /// Returns the alignment for the cell based on and / - /// - /// - /// - public TextAlignment GetAlignment(object cellValue) - { - if(AlignmentGetter != null) - return AlignmentGetter(cellValue); - - return Alignment; - } - - /// - /// Returns the full string to render (which may be truncated if too long) that the current style says best represents the given - /// - /// - /// - public string GetRepresentation (object value) - { - if(!string.IsNullOrWhiteSpace(Format)) { - - if(value is IFormattable f) - return f.ToString(Format,null); - } - - - if(RepresentationGetter != null) - return RepresentationGetter(value); - - return value?.ToString(); - } - } - /// - /// Defines rendering options that affect how the table is displayed. - /// - /// See TableView Deep Dive for more information. - /// - public class TableStyle { - - /// - /// When scrolling down always lock the column headers in place as the first row of the table - /// - public bool AlwaysShowHeaders {get;set;} = false; - - /// - /// True to render a solid line above the headers - /// - public bool ShowHorizontalHeaderOverline {get;set;} = true; - - /// - /// True to render a solid line under the headers - /// - public bool ShowHorizontalHeaderUnderline {get;set;} = true; - - /// - /// True to render a solid line vertical line between cells - /// - public bool ShowVerticalCellLines {get;set;} = true; - - /// - /// True to render a solid line vertical line between headers - /// - public bool ShowVerticalHeaderLines {get;set;} = true; - - /// - /// Collection of columns for which you want special rendering (e.g. custom column lengths, text alignment etc) - /// - public Dictionary ColumnStyles {get;set; } = new Dictionary(); - - /// - /// Returns the entry from for the given or null if no custom styling is defined for it - /// - /// - /// - public ColumnStyle GetColumnStyleIfAny (DataColumn col) - { - return ColumnStyles.TryGetValue(col,out ColumnStyle result) ? result : null; - } - - /// - /// Returns an existing for the given or creates a new one with default options - /// - /// - /// - public ColumnStyle GetOrCreateColumnStyle (DataColumn col) - { - if(!ColumnStyles.ContainsKey(col)) - ColumnStyles.Add(col,new ColumnStyle()); - - return ColumnStyles[col]; - } - } /// /// View for tabular data based on a . @@ -1234,114 +1104,247 @@ namespace Terminal.Gui { return colStyle != null ? colStyle.GetRepresentation(value): value.ToString(); } - } - /// - /// Describes a desire to render a column at a given horizontal position in the UI - /// - internal class ColumnToRender { + #region Nested Types /// - /// The column to render + /// Describes how to render a given column in a including + /// and textual representation of cells (e.g. date formats) + /// + /// See TableView Deep Dive for more information. /// - public DataColumn Column {get;set;} + public class ColumnStyle { - /// - /// The horizontal position to begin rendering the column at - /// - public int X{get;set;} + /// + /// Defines the default alignment for all values rendered in this column. For custom alignment based on cell contents use . + /// + public TextAlignment Alignment { get; set; } - public ColumnToRender (DataColumn col, int x) - { - Column = col; - X = x; + /// + /// Defines a delegate for returning custom alignment per cell based on cell values. When specified this will override + /// + public Func AlignmentGetter; + + /// + /// Defines a delegate for returning custom representations of cell values. If not set then is used. Return values from your delegate may be truncated e.g. based on + /// + public Func RepresentationGetter; + + /// + /// Defines the format for values e.g. "yyyy-MM-dd" for dates + /// + public string Format { get; set; } + + /// + /// Set the maximum width of the column in characters. This value will be ignored if more than the tables . Defaults to + /// + public int MaxWidth { get; set; } = TableView.DefaultMaxCellWidth; + + /// + /// Set the minimum width of the column in characters. This value will be ignored if more than the tables or the + /// + public int MinWidth { get; set; } + + /// + /// Returns the alignment for the cell based on and / + /// + /// + /// + public TextAlignment GetAlignment (object cellValue) + { + if (AlignmentGetter != null) + return AlignmentGetter (cellValue); + + return Alignment; + } + + /// + /// Returns the full string to render (which may be truncated if too long) that the current style says best represents the given + /// + /// + /// + public string GetRepresentation (object value) + { + if (!string.IsNullOrWhiteSpace (Format)) { + + if (value is IFormattable f) + return f.ToString (Format, null); + } + + + if (RepresentationGetter != null) + return RepresentationGetter (value); + + return value?.ToString (); + } } - } - - /// - /// Defines the event arguments for - /// - public class SelectedCellChangedEventArgs : EventArgs - { /// - /// The current table to which the new indexes refer. May be null e.g. if selection change is the result of clearing the table from the view + /// Defines rendering options that affect how the table is displayed. + /// + /// See TableView Deep Dive for more information. /// - /// - public DataTable Table {get;} + public class TableStyle { + /// + /// When scrolling down always lock the column headers in place as the first row of the table + /// + public bool AlwaysShowHeaders { get; set; } = false; - /// - /// The previous selected column index. May be invalid e.g. when the selection has been changed as a result of replacing the existing Table with a smaller one - /// - /// - public int OldCol {get;} + /// + /// True to render a solid line above the headers + /// + public bool ShowHorizontalHeaderOverline { get; set; } = true; + /// + /// True to render a solid line under the headers + /// + public bool ShowHorizontalHeaderUnderline { get; set; } = true; - /// - /// The newly selected column index. - /// - /// - public int NewCol {get;} + /// + /// True to render a solid line vertical line between cells + /// + public bool ShowVerticalCellLines { get; set; } = true; + /// + /// True to render a solid line vertical line between headers + /// + public bool ShowVerticalHeaderLines { get; set; } = true; - /// - /// The previous selected row index. May be invalid e.g. when the selection has been changed as a result of deleting rows from the table - /// - /// - public int OldRow {get;} + /// + /// Collection of columns for which you want special rendering (e.g. custom column lengths, text alignment etc) + /// + public Dictionary ColumnStyles { get; set; } = new Dictionary (); + /// + /// Returns the entry from for the given or null if no custom styling is defined for it + /// + /// + /// + public ColumnStyle GetColumnStyleIfAny (DataColumn col) + { + return ColumnStyles.TryGetValue (col, out ColumnStyle result) ? result : null; + } - /// - /// The newly selected row index. - /// - /// - public int NewRow {get;} + /// + /// Returns an existing for the given or creates a new one with default options + /// + /// + /// + public ColumnStyle GetOrCreateColumnStyle (DataColumn col) + { + if (!ColumnStyles.ContainsKey (col)) + ColumnStyles.Add (col, new ColumnStyle ()); - /// - /// Creates a new instance of arguments describing a change in selected cell in a - /// - /// - /// - /// - /// - /// - public SelectedCellChangedEventArgs(DataTable t, int oldCol, int newCol, int oldRow, int newRow) - { - Table = t; - OldCol = oldCol; - NewCol = newCol; - OldRow = oldRow; - NewRow = newRow; + return ColumnStyles [col]; + } } - } - - /// - /// Describes a selected region of the table - /// - public class TableSelection - { /// - /// Corner of the where selection began + /// Describes a desire to render a column at a given horizontal position in the UI /// - /// - public Point Origin{get;set;} + internal class ColumnToRender { - /// - /// Area selected - /// - /// - public Rect Rect { get; set;} + /// + /// The column to render + /// + public DataColumn Column { get; set; } - /// - /// Creates a new selected area starting at the origin corner and covering the provided rectangular area - /// - /// - /// - public TableSelection(Point origin, Rect rect) - { - Origin = origin; - Rect = rect; + /// + /// The horizontal position to begin rendering the column at + /// + public int X { get; set; } + + public ColumnToRender (DataColumn col, int x) + { + Column = col; + X = x; + } } + + /// + /// Defines the event arguments for + /// + public class SelectedCellChangedEventArgs : EventArgs { + /// + /// The current table to which the new indexes refer. May be null e.g. if selection change is the result of clearing the table from the view + /// + /// + public DataTable Table { get; } + + + /// + /// The previous selected column index. May be invalid e.g. when the selection has been changed as a result of replacing the existing Table with a smaller one + /// + /// + public int OldCol { get; } + + + /// + /// The newly selected column index. + /// + /// + public int NewCol { get; } + + + /// + /// The previous selected row index. May be invalid e.g. when the selection has been changed as a result of deleting rows from the table + /// + /// + public int OldRow { get; } + + + /// + /// The newly selected row index. + /// + /// + public int NewRow { get; } + + /// + /// Creates a new instance of arguments describing a change in selected cell in a + /// + /// + /// + /// + /// + /// + public SelectedCellChangedEventArgs (DataTable t, int oldCol, int newCol, int oldRow, int newRow) + { + Table = t; + OldCol = oldCol; + NewCol = newCol; + OldRow = oldRow; + NewRow = newRow; + } + } + + /// + /// Describes a selected region of the table + /// + public class TableSelection { + + /// + /// Corner of the where selection began + /// + /// + public Point Origin { get; set; } + + /// + /// Area selected + /// + /// + public Rect Rect { get; set; } + + /// + /// Creates a new selected area starting at the origin corner and covering the provided rectangular area + /// + /// + /// + public TableSelection (Point origin, Rect rect) + { + Origin = origin; + Rect = rect; + } + } + #endregion } } diff --git a/UICatalog/Scenarios/CsvEditor.cs b/UICatalog/Scenarios/CsvEditor.cs index 895e934c8..70eded9d1 100644 --- a/UICatalog/Scenarios/CsvEditor.cs +++ b/UICatalog/Scenarios/CsvEditor.cs @@ -94,7 +94,7 @@ namespace UICatalog.Scenarios { } - private void OnSelectedCellChanged (SelectedCellChangedEventArgs e) + private void OnSelectedCellChanged (TableView.SelectedCellChangedEventArgs e) { selectedCellLabel.Text = $"{tableView.SelectedRow},{tableView.SelectedColumn}"; diff --git a/UICatalog/Scenarios/Editor.cs b/UICatalog/Scenarios/Editor.cs index f71ab4c59..507d67e98 100644 --- a/UICatalog/Scenarios/Editor.cs +++ b/UICatalog/Scenarios/Editor.cs @@ -436,9 +436,9 @@ namespace UICatalog { Height = Dim.Fill () }; - tabView.AddTab (new Tab ("Find", FindTab ()), isFind); + tabView.AddTab (new TabView.Tab ("Find", FindTab ()), isFind); var replace = ReplaceTab (); - tabView.AddTab (new Tab ("Replace", replace), !isFind); + tabView.AddTab (new TabView.Tab ("Replace", replace), !isFind); tabView.SelectedTabChanged += (s, e) => tabView.SelectedTab.View.FocusFirst (); winDialog.Add (tabView); diff --git a/UICatalog/Scenarios/Notepad.cs b/UICatalog/Scenarios/Notepad.cs index dbf185dcb..ddf5cb78a 100644 --- a/UICatalog/Scenarios/Notepad.cs +++ b/UICatalog/Scenarios/Notepad.cs @@ -73,7 +73,7 @@ namespace UICatalog.Scenarios { New (); } - private void UpdateStatus (Tab newTab) + private void UpdateStatus (TabView.Tab newTab) { lblStatus.Text = $"Len:{(newTab?.View?.Text?.Length ?? 0)}"; } @@ -212,7 +212,7 @@ namespace UICatalog.Scenarios { return true; } - private class OpenedFile : Tab { + private class OpenedFile : TabView.Tab { public FileInfo File { get; set; } diff --git a/UICatalog/Scenarios/TabViewExample.cs b/UICatalog/Scenarios/TabViewExample.cs index a9058224a..0ed553d57 100644 --- a/UICatalog/Scenarios/TabViewExample.cs +++ b/UICatalog/Scenarios/TabViewExample.cs @@ -60,18 +60,18 @@ namespace UICatalog.Scenarios { }; - tabView.AddTab (new Tab ("Tab1", new Label ("hodor!")), false); - tabView.AddTab (new Tab ("Tab2", new Label ("durdur")), false); - tabView.AddTab (new Tab ("Interactive Tab", GetInteractiveTab ()), false); - tabView.AddTab (new Tab ("Big Text", GetBigTextFileTab ()), false); - tabView.AddTab (new Tab ( + tabView.AddTab (new TabView.Tab ("Tab1", new Label ("hodor!")), false); + tabView.AddTab (new TabView.Tab ("Tab2", new Label ("durdur")), false); + tabView.AddTab (new TabView.Tab ("Interactive Tab", GetInteractiveTab ()), false); + tabView.AddTab (new TabView.Tab ("Big Text", GetBigTextFileTab ()), false); + tabView.AddTab (new TabView.Tab ( "Long name Tab, I mean seriously long. Like you would not believe how long this tab's name is its just too much really woooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooowwww thats long", new Label ("This tab has a very long name which should be truncated. See TabView.MaxTabTextWidth")), false); - tabView.AddTab (new Tab ("Les Mise" + Char.ConvertFromUtf32 (Int32.Parse ("0301", NumberStyles.HexNumber)) + "rables", new Label ("This tab name is unicode")), false); + tabView.AddTab (new TabView.Tab ("Les Mise" + Char.ConvertFromUtf32 (Int32.Parse ("0301", NumberStyles.HexNumber)) + "rables", new Label ("This tab name is unicode")), false); for (int i = 0; i < 100; i++) { - tabView.AddTab (new Tab ($"Tab{i}", new Label ($"Welcome to tab {i}")), false); + tabView.AddTab (new TabView.Tab ($"Tab{i}", new Label ($"Welcome to tab {i}")), false); } tabView.SelectedTab = tabView.Tabs.First (); @@ -120,7 +120,7 @@ namespace UICatalog.Scenarios { private void AddBlankTab () { - tabView.AddTab (new Tab (), false); + tabView.AddTab (new TabView.Tab (), false); } private View GetInteractiveTab () diff --git a/UICatalog/Scenarios/TableEditor.cs b/UICatalog/Scenarios/TableEditor.cs index b82a6b9b0..483010a2b 100644 --- a/UICatalog/Scenarios/TableEditor.cs +++ b/UICatalog/Scenarios/TableEditor.cs @@ -235,19 +235,19 @@ namespace UICatalog.Scenarios { private void SetDemoTableStyles () { - var alignMid = new ColumnStyle() { + var alignMid = new TableView.ColumnStyle () { Alignment = TextAlignment.Centered }; - var alignRight = new ColumnStyle() { + var alignRight = new TableView.ColumnStyle () { Alignment = TextAlignment.Right }; - var dateFormatStyle = new ColumnStyle() { + var dateFormatStyle = new TableView.ColumnStyle () { Alignment = TextAlignment.Right, RepresentationGetter = (v)=> v is DateTime d ? d.ToString("yyyy-MM-dd"):v.ToString() }; - var negativeRight = new ColumnStyle() { + var negativeRight = new TableView.ColumnStyle () { Format = "0.##", MinWidth = 10, diff --git a/UnitTests/TabViewTests.cs b/UnitTests/TabViewTests.cs index 7bf03de8c..d892181f0 100644 --- a/UnitTests/TabViewTests.cs +++ b/UnitTests/TabViewTests.cs @@ -14,13 +14,13 @@ namespace Terminal.Gui.Views { return GetTabView (out _, out _); } - private TabView GetTabView (out Tab tab1, out Tab tab2) + private TabView GetTabView (out TabView.Tab tab1, out TabView.Tab tab2) { InitFakeDriver (); var tv = new TabView (); - tv.AddTab (tab1 = new Tab ("Tab1", new TextField ("hi")), false); - tv.AddTab (tab2 = new Tab ("Tab2", new Label ("hi2")), false); + tv.AddTab (tab1 = new TabView.Tab ("Tab1", new TextField ("hi")), false); + tv.AddTab (tab2 = new TabView.Tab ("Tab2", new Label ("hi2")), false); return tv; } @@ -30,10 +30,10 @@ namespace Terminal.Gui.Views { InitFakeDriver (); var tv = new TabView (); - Tab tab1; - Tab tab2; - tv.AddTab (tab1 = new Tab ("Tab1", new TextField ("hi")), false); - tv.AddTab (tab2 = new Tab ("Tab1", new Label ("hi2")), true); + TabView.Tab tab1; + TabView.Tab tab2; + tv.AddTab (tab1 = new TabView.Tab ("Tab1", new TextField ("hi")), false); + tv.AddTab (tab2 = new TabView.Tab ("Tab1", new Label ("hi2")), true); Assert.Equal (2, tv.Tabs.Count); Assert.Equal (tab2, tv.SelectedTab); @@ -82,8 +82,8 @@ namespace Terminal.Gui.Views { tv.SelectedTab = tab1; - Tab oldTab = null; - Tab newTab = null; + TabView.Tab oldTab = null; + TabView.Tab newTab = null; int called = 0; tv.SelectedTabChanged += (s, e) => { @@ -143,13 +143,13 @@ namespace Terminal.Gui.Views { { var tv = GetTabView (out var tab1, out var tab2); - Tab tab3; - Tab tab4; - Tab tab5; + TabView.Tab tab3; + TabView.Tab tab4; + TabView.Tab tab5; - tv.AddTab (tab3 = new Tab (), false); - tv.AddTab (tab4 = new Tab (), false); - tv.AddTab (tab5 = new Tab (), false); + tv.AddTab (tab3 = new TabView.Tab (), false); + tv.AddTab (tab4 = new TabView.Tab (), false); + tv.AddTab (tab5 = new TabView.Tab (), false); tv.SelectedTab = tab1; diff --git a/UnitTests/TableViewTests.cs b/UnitTests/TableViewTests.cs index 1a6e87029..1405c654b 100644 --- a/UnitTests/TableViewTests.cs +++ b/UnitTests/TableViewTests.cs @@ -297,7 +297,7 @@ namespace Terminal.Gui.Views { // select the last row tableView.MultiSelectedRegions.Clear(); - tableView.MultiSelectedRegions.Push(new TableSelection(new Point(0,3), new Rect(0,3,4,1))); + tableView.MultiSelectedRegions.Push(new TableView.TableSelection (new Point(0,3), new Rect(0,3,4,1))); Assert.Equal(4,tableView.GetAllSelectedCells().Count()); @@ -399,8 +399,8 @@ namespace Terminal.Gui.Views { */ tableView.MultiSelectedRegions.Clear(); - tableView.MultiSelectedRegions.Push(new TableSelection(new Point(1,1),new Rect(1,1,2,2))); - tableView.MultiSelectedRegions.Push(new TableSelection(new Point(7,3),new Rect(7,3,2,1))); + tableView.MultiSelectedRegions.Push(new TableView.TableSelection(new Point(1,1),new Rect(1,1,2,2))); + tableView.MultiSelectedRegions.Push(new TableView.TableSelection (new Point(7,3),new Rect(7,3,2,1))); tableView.SelectedColumn = 8; tableView.SelectedRow = 3;