diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1684f416c..d6686b758 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -241,6 +241,11 @@ dotnet run --project Examples/UICatalog/UICatalog.csproj
- **Tests**: Add tests for new functionality (see [Testing Requirements](#testing-requirements))
- **Coverage**: Maintain or increase code coverage
- **Scenarios**: Update UICatalog scenarios when adding features
+- **Warnings**: **CRITICAL - PRs must not introduce any new warnings**
+ - Any file modified in a PR that currently generates warnings **MUST** be fixed to remove those warnings
+ - Exception: Warnings caused by `[Obsolete]` attributes can remain
+ - Expected baseline: ~326 warnings (mostly nullable reference warnings, unused variables, xUnit suggestions)
+ - Action: Before submitting a PR, verify your changes don't add new warnings and fix any warnings in files you modify
---
@@ -396,6 +401,7 @@ Key documentation:
- ❌ Don't decrease code coverage
- ❌ **Don't use `var` for anything but built-in simple types** (use explicit types)
- ❌ **Don't use redundant type names with `new`** (**ALWAYS PREFER** target-typed `new ()`)
+- ❌ **Don't introduce new warnings** (fix warnings in files you modify; exception: `[Obsolete]` warnings)
---
diff --git a/Terminal.Gui/ViewBase/Adornment/ShadowView.cs b/Terminal.Gui/ViewBase/Adornment/ShadowView.cs
index a2d2eb577..e2dbb7d46 100644
--- a/Terminal.Gui/ViewBase/Adornment/ShadowView.cs
+++ b/Terminal.Gui/ViewBase/Adornment/ShadowView.cs
@@ -95,12 +95,12 @@ internal class ShadowView : View
{
for (int c = Math.Max (0, screen.X + 1); c < screen.X + screen.Width; c++)
{
- Driver?.Move (c, r);
+ Driver.Move (c, r);
SetAttribute (GetAttributeUnderLocation (new (c, r)));
- if (c < Driver?.Contents!.GetLength (1) && r < Driver?.Contents?.GetLength (0))
+ if (c < ScreenContents?.GetLength (1) && r < ScreenContents?.GetLength (0))
{
- Driver.AddRune (Driver.Contents [r, c].Rune);
+ AddRune (ScreenContents [r, c].Rune);
}
}
}
@@ -129,12 +129,12 @@ internal class ShadowView : View
{
for (int r = Math.Max (0, screen.Y); r < screen.Y + viewport.Height; r++)
{
- Driver?.Move (c, r);
+ Driver.Move (c, r);
SetAttribute (GetAttributeUnderLocation (new (c, r)));
- if (Driver?.Contents is { } && screen.X < Driver.Contents.GetLength (1) && r < Driver.Contents.GetLength (0))
+ if (ScreenContents is { } && screen.X < ScreenContents.GetLength (1) && r < ScreenContents.GetLength (0))
{
- Driver.AddRune (Driver.Contents [r, c].Rune);
+ AddRune (ScreenContents [r, c].Rune);
}
}
}
@@ -151,14 +151,14 @@ internal class ShadowView : View
return Attribute.Default;
}
- if (Driver?.Contents == null ||
- location.Y < 0 || location.Y >= Driver.Contents.GetLength (0) ||
- location.X < 0 || location.X >= Driver.Contents.GetLength (1))
+ if (ScreenContents == null ||
+ location.Y < 0 || location.Y >= ScreenContents.GetLength (0) ||
+ location.X < 0 || location.X >= ScreenContents.GetLength (1))
{
return Attribute.Default;
}
- Attribute attr = Driver!.Contents! [location.Y, location.X].Attribute!.Value;
+ Attribute attr = ScreenContents [location.Y, location.X].Attribute!.Value;
var newAttribute =
new Attribute (
diff --git a/Terminal.Gui/ViewBase/View.Drawing.cs b/Terminal.Gui/ViewBase/View.Drawing.cs
index 6919b8e34..1f2756123 100644
--- a/Terminal.Gui/ViewBase/View.Drawing.cs
+++ b/Terminal.Gui/ViewBase/View.Drawing.cs
@@ -658,7 +658,7 @@ public partial class View // Drawing APIs
Driver.Move (p.Key.X, p.Key.Y);
// TODO: #2616 - Support combining sequences that don't normalize
- Driver.AddRune (p.Value.Value.Rune);
+ AddRune (p.Value.Value.Rune);
}
}
diff --git a/Terminal.Gui/ViewBase/View.cs b/Terminal.Gui/ViewBase/View.cs
index a86589750..0a26aa37b 100644
--- a/Terminal.Gui/ViewBase/View.cs
+++ b/Terminal.Gui/ViewBase/View.cs
@@ -130,6 +130,9 @@ public partial class View : IDisposable, ISupportInitializeNotification
set => _driver = value;
}
+ /// Gets the screen buffer contents. This is a convenience property for Views that need direct access to the screen buffer.
+ protected Cell [,]? ScreenContents => Driver?.Contents;
+
/// Initializes a new instance of .
///
///
diff --git a/Terminal.Gui/Views/Color/ColorBar.cs b/Terminal.Gui/Views/Color/ColorBar.cs
index 262abc99e..ad15e231f 100644
--- a/Terminal.Gui/Views/Color/ColorBar.cs
+++ b/Terminal.Gui/Views/Color/ColorBar.cs
@@ -92,7 +92,7 @@ internal abstract class ColorBar : View, IColorBar
{
Move (0, 0);
SetAttribute (HasFocus ? GetAttributeForRole (VisualRole.Focus) : GetAttributeForRole (VisualRole.Normal));
- Driver?.AddStr (Text);
+ AddStr (Text);
// TODO: is there a better method than this? this is what it is in TableView
xOffset = Text.EnumerateRunes ().Sum (c => c.GetColumns ());
diff --git a/Terminal.Gui/Views/FileDialogs/FileDialog.cs b/Terminal.Gui/Views/FileDialogs/FileDialog.cs
index 2d326cc5f..7fd813fb8 100644
--- a/Terminal.Gui/Views/FileDialogs/FileDialog.cs
+++ b/Terminal.Gui/Views/FileDialogs/FileDialog.cs
@@ -427,9 +427,9 @@ public class FileDialog : Dialog, IDesignable
Move (0, Viewport.Height / 2);
SetAttribute (new (Color.Red, GetAttributeForRole (VisualRole.Normal).Background));
- Driver!.AddStr (new (' ', feedbackPadLeft));
- Driver.AddStr (_feedback);
- Driver.AddStr (new (' ', feedbackPadRight));
+ AddStr (new (' ', feedbackPadLeft));
+ AddStr (_feedback);
+ AddStr (new (' ', feedbackPadRight));
}
return true;
@@ -507,7 +507,7 @@ public class FileDialog : Dialog, IDesignable
_allowedTypeMenuBar.DrawingContent += (s, e) =>
{
_allowedTypeMenuBar.Move (e.NewViewport.Width - 1, 0);
- Driver!.AddRune (Glyphs.DownArrow);
+ AddRune (Glyphs.DownArrow);
};
Add (_allowedTypeMenuBar);
diff --git a/Terminal.Gui/Views/GraphView/GraphView.cs b/Terminal.Gui/Views/GraphView/GraphView.cs
index dfd6bab9b..92b31a60f 100644
--- a/Terminal.Gui/Views/GraphView/GraphView.cs
+++ b/Terminal.Gui/Views/GraphView/GraphView.cs
@@ -213,7 +213,7 @@ public class GraphView : View, IDesignable
for (var i = 0; i < Viewport.Height; i++)
{
Move (0, i);
- Driver?.AddStr (new (' ', Viewport.Width));
+ AddStr (new (' ', Viewport.Width));
}
// If there is no data do not display a graph
diff --git a/Terminal.Gui/Views/GraphView/IAnnotation.cs b/Terminal.Gui/Views/GraphView/IAnnotation.cs
index 9ebfe4904..004339875 100644
--- a/Terminal.Gui/Views/GraphView/IAnnotation.cs
+++ b/Terminal.Gui/Views/GraphView/IAnnotation.cs
@@ -18,7 +18,7 @@ public interface IAnnotation
///
/// Called once after series have been rendered (or before if is true). Use
- /// to draw and to avoid drawing outside of graph
+ /// methods like and to draw. Use to avoid drawing outside of graph.
///
///
void Render (GraphView graph);
diff --git a/Terminal.Gui/Views/GraphView/TextAnnotation.cs b/Terminal.Gui/Views/GraphView/TextAnnotation.cs
index 91ae17c98..98f1fec3e 100644
--- a/Terminal.Gui/Views/GraphView/TextAnnotation.cs
+++ b/Terminal.Gui/Views/GraphView/TextAnnotation.cs
@@ -68,11 +68,11 @@ public class TextAnnotation : IAnnotation
if (Text.Length < availableWidth)
{
- graph.Driver?.AddStr (Text);
+ graph.AddStr (Text);
}
else
{
- graph.Driver?.AddStr (Text.Substring (0, availableWidth));
+ graph.AddStr (Text.Substring (0, availableWidth));
}
}
}
diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs
index 5bfd9a5eb..b933af9e0 100644
--- a/Terminal.Gui/Views/ListView.cs
+++ b/Terminal.Gui/Views/ListView.cs
@@ -750,7 +750,7 @@ public class ListView : View, IDesignable
{
for (var c = 0; c < f.Width; c++)
{
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
}
else
@@ -766,11 +766,11 @@ public class ListView : View, IDesignable
if (_allowsMarking)
{
- Driver?.AddRune (
+ AddRune (
_source.IsMarked (item) ? AllowsMultipleSelection ? Glyphs.CheckStateChecked : Glyphs.Selected :
AllowsMultipleSelection ? Glyphs.CheckStateUnChecked : Glyphs.UnSelected
);
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
Source.Render (this, isSelected, item, col, row, f.Width - col, start);
diff --git a/Terminal.Gui/Views/Menuv1/Menu.cs b/Terminal.Gui/Views/Menuv1/Menu.cs
index a079418f1..ceb63d412 100644
--- a/Terminal.Gui/Views/Menuv1/Menu.cs
+++ b/Terminal.Gui/Views/Menuv1/Menu.cs
@@ -847,7 +847,7 @@ internal sealed class Menu : View
continue;
}
- if (ViewportToScreen (Viewport).Y + i >= Driver.Rows)
+ if (ViewportToScreen (Viewport).Y + i >= Application.Screen.Height)
{
break;
}
@@ -863,11 +863,10 @@ internal sealed class Menu : View
if (item is null && BorderStyle != LineStyle.None)
{
- Point s = ViewportToScreen (new Point (-1, i));
- Driver.Move (s.X, s.Y);
- Driver.AddRune (Glyphs.LeftTee);
+ Move (-1, i);
+ AddRune (Glyphs.LeftTee);
}
- else if (Frame.X < Driver.Cols)
+ else if (Frame.X < Application.Screen.Width)
{
Move (0, i);
}
@@ -882,28 +881,28 @@ internal sealed class Menu : View
continue;
}
- if (ViewportToScreen (Viewport).X + p >= Driver.Cols)
+ if (ViewportToScreen (Viewport).X + p >= Application.Screen.Width)
{
break;
}
if (item is null)
{
- Driver.AddRune (Glyphs.HLine);
+ AddRune (Glyphs.HLine);
}
else if (i == 0 && p == 0 && _host.UseSubMenusSingleFrame && item.Parent!.Parent is { })
{
- Driver.AddRune (Glyphs.LeftArrow);
+ AddRune (Glyphs.LeftArrow);
}
// This `- 3` is left border + right border + one row in from right
else if (p == Frame.Width - 3 && _barItems?.SubMenu (_barItems.Children [i]!) is { })
{
- Driver.AddRune (Glyphs.RightArrow);
+ AddRune (Glyphs.RightArrow);
}
else
{
- Driver.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
}
@@ -911,9 +910,8 @@ internal sealed class Menu : View
{
if (BorderStyle != LineStyle.None && SuperView?.Frame.Right - Frame.X > Frame.Width)
{
- Point s = ViewportToScreen (new Point (Frame.Width - 2, i));
- Driver.Move (s.X, s.Y);
- Driver.AddRune (Glyphs.RightTee);
+ Move (Frame.Width - 2, i);
+ AddRune (Glyphs.RightTee);
}
continue;
@@ -950,9 +948,9 @@ internal sealed class Menu : View
Point screen = ViewportToScreen (new Point (0, i));
- if (screen.X < Driver.Cols)
+ if (screen.X < Application.Screen.Width)
{
- Driver.Move (screen.X + 1, screen.Y);
+ Move (1, i);
if (!item.IsEnabled ())
{
@@ -991,16 +989,16 @@ internal sealed class Menu : View
int col = Frame.Width - l - 3;
screen = ViewportToScreen (new Point (col, i));
- if (screen.X < Driver.Cols)
+ if (screen.X < Application.Screen.Width)
{
- Driver.Move (screen.X, screen.Y);
- Driver.AddStr (item.Help);
+ Move (col, i);
+ AddStr (item.Help);
// The shortcut tag string
if (!string.IsNullOrEmpty (item.ShortcutTag))
{
- Driver.Move (screen.X + l - item.ShortcutTag.GetColumns (), screen.Y);
- Driver.AddStr (item.ShortcutTag);
+ Move (col + l - item.ShortcutTag.GetColumns (), i);
+ AddStr (item.ShortcutTag);
}
}
}
diff --git a/Terminal.Gui/Views/Menuv1/MenuBar.cs b/Terminal.Gui/Views/Menuv1/MenuBar.cs
index b08e61911..8b66a63dc 100644
--- a/Terminal.Gui/Views/Menuv1/MenuBar.cs
+++ b/Terminal.Gui/Views/Menuv1/MenuBar.cs
@@ -697,7 +697,7 @@ public class MenuBar : View, IDesignable
internal Point GetScreenOffset ()
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
- if (Driver is null)
+ if (Application.Screen.Height == 0)
{
return Point.Empty;
}
diff --git a/Terminal.Gui/Views/ProgressBar.cs b/Terminal.Gui/Views/ProgressBar.cs
index 0d78b2c93..3e27bd556 100644
--- a/Terminal.Gui/Views/ProgressBar.cs
+++ b/Terminal.Gui/Views/ProgressBar.cs
@@ -144,11 +144,11 @@ public class ProgressBar : View, IDesignable
{
if (Array.IndexOf (_activityPos!, i) != -1)
{
- Driver?.AddRune (SegmentCharacter);
+ AddRune (SegmentCharacter);
}
else
{
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
}
}
@@ -159,12 +159,12 @@ public class ProgressBar : View, IDesignable
for (i = 0; (i < mid) & (i < Viewport.Width); i++)
{
- Driver?.AddRune (SegmentCharacter);
+ AddRune (SegmentCharacter);
}
for (; i < Viewport.Width; i++)
{
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
}
diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs
index b3c522b25..1040c6e83 100644
--- a/Terminal.Gui/Views/RadioGroup.cs
+++ b/Terminal.Gui/Views/RadioGroup.cs
@@ -375,7 +375,7 @@ public class RadioGroup : View, IDesignable, IOrientation
string rl = _radioLabels [i];
SetAttribute (GetAttributeForRole (VisualRole.Normal));
- Driver?.AddStr ($"{(i == _selected ? Glyphs.Selected : Glyphs.UnSelected)} ");
+ AddStr ($"{(i == _selected ? Glyphs.Selected : Glyphs.UnSelected)} ");
TextFormatter.FindHotKey (rl, HotKeySpecifier, out int hotPos, out Key hotKey);
if (hotPos != -1 && hotKey != Key.Empty)
diff --git a/Terminal.Gui/Views/Slider/Slider.cs b/Terminal.Gui/Views/Slider/Slider.cs
index b8642686f..ff0308a56 100644
--- a/Terminal.Gui/Views/Slider/Slider.cs
+++ b/Terminal.Gui/Views/Slider/Slider.cs
@@ -441,13 +441,13 @@ public class Slider : View, IOrientation
private void MoveAndAdd (int x, int y, Rune rune)
{
Move (x, y);
- Driver?.AddRune (rune);
+ AddRune (rune);
}
private void MoveAndAdd (int x, int y, string str)
{
Move (x, y);
- Driver?.AddStr (str);
+ AddStr (str);
}
/// Sets the dimensions of the Slider to the ideal values.
diff --git a/Terminal.Gui/Views/SpinnerView/SpinnerView.cs b/Terminal.Gui/Views/SpinnerView/SpinnerView.cs
index 5ee1db270..00f723fe6 100644
--- a/Terminal.Gui/Views/SpinnerView/SpinnerView.cs
+++ b/Terminal.Gui/Views/SpinnerView/SpinnerView.cs
@@ -187,7 +187,7 @@ public class SpinnerView : View, IDesignable
if (Sequence is { Length: > 0 } && _currentIdx < Sequence.Length)
{
Move (Viewport.X, Viewport.Y);
- Driver?.AddStr (Sequence [_currentIdx]);
+ AddStr (Sequence [_currentIdx]);
}
}
diff --git a/Terminal.Gui/Views/TableView/TableView.cs b/Terminal.Gui/Views/TableView/TableView.cs
index a269d69d0..272e7495d 100644
--- a/Terminal.Gui/Views/TableView/TableView.cs
+++ b/Terminal.Gui/Views/TableView/TableView.cs
@@ -943,7 +943,7 @@ public class TableView : View, IDesignable
SetAttribute (GetAttributeForRole (VisualRole.Normal));
//invalidate current row (prevents scrolling around leaving old characters in the frame
- Driver?.AddStr (new (' ', Viewport.Width));
+ AddStr (new (' ', Viewport.Width));
var line = 0;
@@ -1289,12 +1289,11 @@ public class TableView : View, IDesignable
protected virtual void OnSelectedCellChanged (SelectedCellChangedEventArgs args) { SelectedCellChanged?.Invoke (this, args); }
///
- /// Override to provide custom multi colouring to cells. Use to with
- /// . The driver will already be in the correct place when rendering and
- /// you
- /// must render the full or the view will not look right. For simpler provision of color use
- /// For changing the content that is rendered use
- ///
+ /// Override to provide custom multi-coloring to cells. Use methods like .
+ /// The cursor will already be in the correct position when rendering. You must render the full
+ /// or the view will not look right. For simpler color provision use
+ /// . For changing the content that is rendered use
+ /// .
///
///
///
@@ -1310,19 +1309,19 @@ public class TableView : View, IDesignable
{
// invert the color of the current cell for the first character
SetAttribute (new (cellAttribute.Foreground, cellAttribute.Background, TextStyle.Reverse));
- Driver?.AddRune ((Rune)render [0]);
+ AddRune ((Rune)render [0]);
if (render.Length > 1)
{
SetAttribute (cellAttribute);
- Driver?.AddStr (render.Substring (1));
+ AddStr (render.Substring (1));
}
}
}
else
{
SetAttribute (cellAttribute);
- Driver?.AddStr (render);
+ AddStr (render);
}
}
@@ -1349,10 +1348,10 @@ public class TableView : View, IDesignable
///
internal int GetHeaderHeightIfAny () { return ShouldRenderHeaders () ? GetHeaderHeight () : 0; }
- private void AddRuneAt (IConsoleDriver d, int col, int row, Rune ch)
+ private void AddRuneAt (int col, int row, Rune ch)
{
Move (col, row);
- d?.AddRune (ch);
+ AddRune (ch);
}
///
@@ -1534,14 +1533,14 @@ public class TableView : View, IDesignable
///
private void ClearLine (int row, int width)
{
- if (Driver is null)
+ if (Application.Screen.Height == 0)
{
return;
}
Move (0, row);
SetAttribute (GetAttributeForRole (VisualRole.Normal));
- Driver.AddStr (new (' ', width));
+ AddStr (new (' ', width));
}
private void ClearMultiSelectedRegions (bool keepToggledSelections)
@@ -1734,7 +1733,7 @@ public class TableView : View, IDesignable
}
}
- AddRuneAt (Driver, c, row, rune);
+ AddRuneAt (c, row, rune);
}
}
@@ -1762,7 +1761,7 @@ public class TableView : View, IDesignable
Move (current.X, row);
- Driver?.AddStr (TruncateOrPad (colName, colName, current.Width, colStyle));
+ AddStr (TruncateOrPad (colName, colName, current.Width, colStyle));
if (Style.ExpandLastColumn == false && current.IsVeryLast)
{
@@ -1810,9 +1809,9 @@ public class TableView : View, IDesignable
}
}
- if (Driver is { })
+ if (Application.Screen.Height > 0)
{
- AddRuneAt (Driver, c, row, rune);
+ AddRuneAt (c, row, rune);
}
}
}
@@ -1906,7 +1905,7 @@ public class TableView : View, IDesignable
}
}
- AddRuneAt (Driver, c, row, rune);
+ AddRuneAt (c, row, rune);
}
}
@@ -1934,7 +1933,7 @@ public class TableView : View, IDesignable
}
SetAttribute (attribute.Value);
- Driver?.AddStr (new (' ', Viewport.Width));
+ AddStr (new (' ', Viewport.Width));
// Render cells for each visible header for the current row
for (var i = 0; i < columnsToRender.Length; i++)
diff --git a/Terminal.Gui/Views/TableView/TreeTableSource.cs b/Terminal.Gui/Views/TableView/TreeTableSource.cs
index c8c4a01fe..6cbb5b0a7 100644
--- a/Terminal.Gui/Views/TableView/TreeTableSource.cs
+++ b/Terminal.Gui/Views/TableView/TreeTableSource.cs
@@ -178,7 +178,7 @@ public class TreeTableSource : IEnumerableTableSource, IDisposable where T
Branch branch = RowToBranch (hit.Value.Y);
- if (branch.IsHitOnExpandableSymbol (Application.Driver, offsetX.Value))
+ if (branch.IsHitOnExpandableSymbol (offsetX.Value))
{
T m = branch.Model;
diff --git a/Terminal.Gui/Views/TextInput/TextField.cs b/Terminal.Gui/Views/TextInput/TextField.cs
index 73c449d81..70d7e007e 100644
--- a/Terminal.Gui/Views/TextInput/TextField.cs
+++ b/Terminal.Gui/Views/TextInput/TextField.cs
@@ -973,7 +973,7 @@ public class TextField : View, IDesignable
if (col + cols <= width)
{
- Driver?.AddRune (Secret ? Glyphs.Dot : rune);
+ AddRune (Secret ? Glyphs.Dot : rune);
}
if (!TextModel.SetCol (ref col, width, cols))
@@ -992,7 +992,7 @@ public class TextField : View, IDesignable
// Fill rest of line with spaces
for (int i = col; i < width; i++)
{
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
PositionCursor ();
@@ -1717,7 +1717,7 @@ public class TextField : View, IDesignable
render = render [..Viewport.Width];
}
- Driver?.AddStr (render);
+ AddStr (render);
}
private void SetClipboard (IEnumerable text)
diff --git a/Terminal.Gui/Views/TextInput/TextValidateField.cs b/Terminal.Gui/Views/TextInput/TextValidateField.cs
index 1b32d5cf0..f7e897feb 100644
--- a/Terminal.Gui/Views/TextInput/TextValidateField.cs
+++ b/Terminal.Gui/Views/TextInput/TextValidateField.cs
@@ -177,7 +177,7 @@ public class TextValidateField : View, IDesignable
if (_provider is null)
{
Move (0, 0);
- Driver?.AddStr ("Error: ITextValidateProvider not set!");
+ AddStr ("Error: ITextValidateProvider not set!");
return true;
}
@@ -194,7 +194,7 @@ public class TextValidateField : View, IDesignable
for (var i = 0; i < marginLeft; i++)
{
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
// Content
@@ -203,7 +203,7 @@ public class TextValidateField : View, IDesignable
// Content
for (var i = 0; i < _provider.DisplayText.Length; i++)
{
- Driver?.AddRune ((Rune)_provider.DisplayText [i]);
+ AddRune ((Rune)_provider.DisplayText [i]);
}
// Right Margin
@@ -211,7 +211,7 @@ public class TextValidateField : View, IDesignable
for (var i = 0; i < marginRight; i++)
{
- Driver?.AddRune ((Rune)' ');
+ AddRune ((Rune)' ');
}
return true;
diff --git a/Terminal.Gui/Views/TreeView/Branch.cs b/Terminal.Gui/Views/TreeView/Branch.cs
index 5b628ef12..59b0475a6 100644
--- a/Terminal.Gui/Views/TreeView/Branch.cs
+++ b/Terminal.Gui/Views/TreeView/Branch.cs
@@ -454,7 +454,7 @@ internal class Branch where T : class
///
///
///
- internal bool IsHitOnExpandableSymbol (IConsoleDriver driver, int x)
+ internal bool IsHitOnExpandableSymbol (int x)
{
// if leaf node then we cannot expand
if (!CanExpand ())
diff --git a/Terminal.Gui/Views/TreeView/TreeView.cs b/Terminal.Gui/Views/TreeView/TreeView.cs
index 858bc465d..c640b4e25 100644
--- a/Terminal.Gui/Views/TreeView/TreeView.cs
+++ b/Terminal.Gui/Views/TreeView/TreeView.cs
@@ -1065,7 +1065,7 @@ public class TreeView : View, ITreeView where T : class
return false;
}
- bool isExpandToggleAttempt = clickedBranch.IsHitOnExpandableSymbol (Driver, me.Position.X);
+ bool isExpandToggleAttempt = clickedBranch.IsHitOnExpandableSymbol (me.Position.X);
// If we are already selected (double click)
if (Equals (SelectedObject, clickedBranch.Model))
@@ -1157,7 +1157,7 @@ public class TreeView : View, ITreeView where T : class
if (TreeBuilder is null)
{
Move (0, 0);
- Driver?.AddStr (NoBuilderError);
+ AddStr (NoBuilderError);
return true;
}
@@ -1179,7 +1179,7 @@ public class TreeView : View, ITreeView where T : class
// Else clear the line to prevent stale symbols due to scrolling etc
Move (0, line);
SetAttribute (GetAttributeForRole (VisualRole.Normal));
- Driver?.AddStr (new (' ', Viewport.Width));
+ AddStr (new (' ', Viewport.Width));
}
}
diff --git a/docfx/docs/View.md b/docfx/docs/View.md
index af69a5713..623650ca2 100644
--- a/docfx/docs/View.md
+++ b/docfx/docs/View.md
@@ -36,6 +36,8 @@ See the [Layout Deep Dive](layout.md) and the [Arrangement Deep Dive](arrangemen
See the [Drawing Deep Dive](drawing.md).
+Views should use viewport-relative coordinates for all drawing operations. The `View.Move(col, row)` method positions the cursor using viewport-relative coordinates. For screen dimensions, use @Terminal.Gui.App.Application.Screen instead of accessing the driver directly.
+
### Navigation
See the [Navigation Deep Dive](navigation.md).
diff --git a/docfx/docs/drivers.md b/docfx/docs/drivers.md
index 17b753984..3a78d597a 100644
--- a/docfx/docs/drivers.md
+++ b/docfx/docs/drivers.md
@@ -151,7 +151,7 @@ When `Application.Shutdown()` is called:
### IConsoleDriver
-The main driver interface that applications interact with. Provides:
+The main driver interface that the framework uses internally. Provides:
- **Screen Management**: `Screen`, `Cols`, `Rows`, `Contents`
- **Drawing Operations**: `AddRune()`, `AddStr()`, `Move()`, `FillRect()`
@@ -161,6 +161,12 @@ The main driver interface that applications interact with. Provides:
- **Events**: `KeyDown`, `KeyUp`, `MouseEvent`, `SizeChanged`
- **Platform Features**: `SupportsTrueColor`, `Force16Colors`, `Clipboard`
+**Note:** The driver is internal to Terminal.Gui. View classes should not access `Driver` directly. Instead:
+- Use @Terminal.Gui.App.Application.Screen to get screen dimensions
+- Use @Terminal.Gui.ViewBase.View.Move for positioning (with viewport-relative coordinates)
+- Use @Terminal.Gui.ViewBase.View.AddRune and @Terminal.Gui.ViewBase.View.AddStr for drawing
+- ViewBase infrastructure classes (in `Terminal.Gui/ViewBase/`) can access Driver when needed for framework implementation
+
### IConsoleDriverFacade
Extended interface for v2 drivers that exposes the internal components:
@@ -215,18 +221,23 @@ This ensures Terminal.Gui applications can be debugged directly in Visual Studio
- Captures output for verification
- Always used when `Application._forceFakeConsole` is true
-## Example: Accessing Driver Components
+## Example: Checking Driver Capabilities
```csharp
Application.Init();
-// Access the driver
-IConsoleDriver driver = Application.Driver;
+// The driver is internal - access through Application properties
+// Check screen dimensions
+var screenWidth = Application.Screen.Width;
+var screenHeight = Application.Screen.Height;
-// Check if it's a v2 driver with facade
-if (driver is IConsoleDriverFacade facade)
+// Check if 24-bit color is supported
+bool supportsTrueColor = Application.Driver?.SupportsTrueColor ?? false;
+
+// Access advanced components (for framework/infrastructure code only)
+if (Application.Driver is IConsoleDriverFacade facade)
{
- // Access individual components
+ // Access individual components for advanced scenarios
IInputProcessor inputProcessor = facade.InputProcessor;
IOutputBuffer outputBuffer = facade.OutputBuffer;
IWindowSizeMonitor sizeMonitor = facade.WindowSizeMonitor;
@@ -239,6 +250,11 @@ if (driver is IConsoleDriverFacade facade)
}
```
+**Important:** View subclasses should not access `Application.Driver`. Use the View APIs instead:
+- `View.Move(col, row)` for positioning
+- `View.AddRune()` and `View.AddStr()` for drawing
+- `Application.Screen` for screen dimensions
+
## Custom Drivers
To create a custom driver, implement `IComponentFactory`:
diff --git a/docfx/docs/migratingfromv1.md b/docfx/docs/migratingfromv1.md
index 8bdbb903b..6677b0987 100644
--- a/docfx/docs/migratingfromv1.md
+++ b/docfx/docs/migratingfromv1.md
@@ -225,7 +225,7 @@ The cursor and focus system has been redesigned in v2 to be more consistent and
### Cursor
-In v1, whether the cursor (the flashing caret) was visible or not was controlled by `View.CursorVisibility` which was an enum extracted from Ncruses/Terminfo. It only works in some cases on Linux, and only partially with `WindowsDriver`. The position of the cursor was the same as `ConsoleDriver.Row`/`Col` and determined by the last call to `ConsoleDriver.Move`. `View.PositionCursor()` could be overridden by views to cause `Application` to call `ConsoleDriver.Move` on behalf of the app and to manage setting `CursorVisibility`. This API was confusing and bug-prone.
+In v1, whether the cursor (the flashing caret) was visible or not was controlled by `View.CursorVisibility` which was an enum extracted from Ncruses/Terminfo. It only works in some cases on Linux, and only partially with `WindowsDriver`. The position of the cursor was determined by the last call to the driver's Move method. `View.PositionCursor()` could be overridden by views to cause `Application` to call the driver's positioning method on behalf of the app and to manage setting `CursorVisibility`. This API was confusing and bug-prone.
In v2, the API is (NOT YET IMPLEMENTED) simplified. A view simply reports the style of cursor it wants and the Viewport-relative location:
@@ -237,7 +237,7 @@ In v2, the API is (NOT YET IMPLEMENTED) simplified. A view simply reports the st
- If `null` the default cursor style is used.
- If `{}` specifies the style of cursor. See [cursor.md](cursor.md) for more.
* `Application` now has APIs for querying available cursor styles.
-* The details in `ConsoleDriver` are no longer available to applications.
+* The driver details are no longer directly accessible to View subclasses.
#### How to Fix (Cursor API)
@@ -245,6 +245,26 @@ In v2, the API is (NOT YET IMPLEMENTED) simplified. A view simply reports the st
* Set @Terminal.Gui.ViewBase.View.CursorVisibility to the cursor style you want to use.
* Remove any overrides of `OnEnter` and `OnLeave` that explicitly change the cursor.
+### Driver Access
+
+In v1, Views could access `Driver` directly (e.g., `Driver.Move()`, `Driver.Rows`, `Driver.Cols`). In v2, `Driver` is internal and View subclasses should not access it directly. ViewBase provides all necessary abstractions for Views to function without needing direct driver access.
+
+#### How to Fix (Driver Access)
+
+* Replace `Driver.Rows` and `Driver.Cols` with @Terminal.Gui.App.Application.Screen.Height and @Terminal.Gui.App.Application.Screen.Width
+* Replace direct `Driver.Move(screenX, screenY)` calls with @Terminal.Gui.ViewBase.View.Move using viewport-relative coordinates
+* Use @Terminal.Gui.ViewBase.View.AddRune and @Terminal.Gui.ViewBase.View.AddStr for drawing
+* ViewBase infrastructure classes (in `Terminal.Gui/ViewBase/`) can still access Driver for framework implementation needs
+
+```diff
+- if (x >= Driver.Cols) return;
++ if (x >= Application.Screen.Width) return;
+
+- Point screenPos = ViewportToScreen(new Point(col, row));
+- Driver.Move(screenPos.X, screenPos.Y);
++ Move(col, row); // Move handles viewport-to-screen conversion
+```
+
### Focus
See [navigation.md](navigation.md) for more details.