diff --git a/Terminal.Gui/View/View.Drawing.cs b/Terminal.Gui/View/View.Drawing.cs
index d7404cb87..fbd75542e 100644
--- a/Terminal.Gui/View/View.Drawing.cs
+++ b/Terminal.Gui/View/View.Drawing.cs
@@ -1,4 +1,5 @@
#nullable enable
+using System.ComponentModel;
using System.Diagnostics;
namespace Terminal.Gui;
@@ -26,12 +27,7 @@ public partial class View // Drawing APIs
}
DoDrawAdornments ();
-
- // Set the color scheme for the view after adornments have been drawn
- if (ColorScheme is { })
- {
- Driver?.SetAttribute (GetNormalColor ());
- }
+ DoSetAttribute ();
// By default, we clip to the viewport preventing drawing outside the viewport
// We also clip to the content, but if a developer wants to draw outside the viewport, they can do
@@ -130,6 +126,52 @@ public partial class View // Drawing APIs
#endregion DrawAdornments
+ #region SetAttribute
+
+ private void DoSetAttribute ()
+ {
+ if (OnSettingAttribute ())
+ {
+ return;
+ }
+
+ var args = new CancelEventArgs ();
+ SettingAttribute?.Invoke (this, args);
+
+ if (args.Cancel)
+ {
+ return;
+ }
+
+ SetNormalAttribute ();
+ }
+
+
+ ///
+ /// Called when the normal attribute for the View is to be set. This is called before the View is drawn.
+ ///
+ /// to stop default behavior.
+ protected virtual bool OnSettingAttribute () { return false; }
+
+ /// Raised when the normal attribute for the View is to be set. This is raised before the View is drawn.
+ ///
+ /// Set to to stop default behavior.
+ ///
+ public event EventHandler? SettingAttribute;
+
+ ///
+ /// Sets the attribute for the View. This is called before the View is drawn.
+ ///
+ public void SetNormalAttribute ()
+ {
+ if (ColorScheme is { })
+ {
+ Driver?.SetAttribute (GetNormalColor ());
+ }
+ }
+
+
+ #endregion
#region ClearViewport
private void DoClearViewport (Rectangle viewport)
@@ -465,20 +507,11 @@ public partial class View // Drawing APIs
#region DrawComplete
- private void DoDrawComplete (Rectangle viewport)
+ private void DoDrawComplete ()
{
- Debug.Assert (viewport == Viewport);
+ OnDrawComplete ();
- if (OnDrawComplete (Viewport))
- {
- return;
- }
-
- var dev = new DrawEventArgs (Viewport, Rectangle.Empty);
- DrawComplete?.Invoke (this, dev);
-
- if (dev.Cancel)
- { }
+ DrawComplete?.Invoke (this, EventArgs.Empty);
// Default implementation does nothing.
}
@@ -486,13 +519,12 @@ public partial class View // Drawing APIs
///
/// Called when the View is completed drawing.
///
- ///
- protected virtual bool OnDrawComplete (Rectangle viewport) { return false; }
+ protected virtual void OnDrawComplete () { }
/// Raised when the View is completed drawing.
///
///
- public event EventHandler? DrawComplete;
+ public event EventHandler? DrawComplete;
#endregion DrawComplete
diff --git a/docfx/docs/drawing.md b/docfx/docs/drawing.md
index 577be2b51..02095e3a8 100644
--- a/docfx/docs/drawing.md
+++ b/docfx/docs/drawing.md
@@ -6,13 +6,13 @@ Color is supported on all platforms, including Windows, Mac, and Linux. The defa
## View Drawing API
-A @Terminal.Gui.View will typically draw text when the @Terminal.Gui.Border.OnDrawContent(System.Drawing.Rectangle) is called (or the `DrawContent` event is received).
+Terminal.Gui apps draw using the @Terminal.Gui.View.Move and @Terminal.Gui.View.AddRune APIs. @Terminal.Gui.View.Move selects the column and row of the @Terminal.Gui.Cell and @Terminal.Gui.AddRune places the specified glyph in that cell using the @Terminal.Gui.Attribute that was most recently set via @Terminal.Gui.SetAttribute. The @Terminal.Gui.ConsoleDriver caches all changed Cells and efficiently outputs them to the terminal each iteration of the Application. In other words, Terminal.Gui uses deferred rendering.
Outputting unformatted text involves:
-a) Moving the draw cursor using the `Move` API.
-b) Setting the attributes using `SetAttribute`.
-c) Outputting glyphs by calling `AddRune` or `AddStr`.
+a) Moving the draw cursor using @Terminal.Gui.ViewMove.
+b) Setting the attributes using @Terminal.Gui.ViewSetAttribute`
+c) Outputting glyphs by calling @Terminal.Gui.View.AddRune or @Terminal.Gui.View.AddStr
Outputting formatted text involves:
@@ -25,9 +25,21 @@ Line drawing is accomplished using the @Terminal.Gui.LineCanvas API:
a) Add the lines via @Terminal.Gui.LineCanvas.Add.
b) Either render the line canvas via @Terminal.Gui.LineCanvas.GetMap() or let the @Terminal.Gui.View do so automatically (which enables automatic line joining across Views).
+The @Terminal.Gui.Application MainLoop will iterate over all Views in an application looking for views have their @Terminal.Gui.View.NeedsDisplay property set. The @Terminal.Gui.View.Draw method will be called which, in turn.
+
+1) Draws the Adornments (e.g. @Terminal.Gui.View.Border).
+2) Sets the Normal color scheme.
+3) Clears the @Terminal.Gui.View.Viewport.
+4) Draws @Terminal.Gui.View.Text.
+5) Draws any non-text or Subview content.
+6) Draws @Terminal.Gui.View.Subviews.
+7) Draws @Terminal.Gui.View.LineCanvas (which may have been added to by any of the steps above).
+
+Each of these steps can be overridden by developers using the standard [Terminal.Gui cancellable event pattern](events.md). For example, the base @Terminal.Gui.View always clears the viewport. To override this, a subclass can override @Terminal.Gui.View.OnClearingViewport to simply return `true`. Or, a user of `View` can subscribe to the @Terminal.Gui.View.ClearingViewport event and set the `Cancel` argument to `true`.
+
## Coordinate System for Drawing
-The @Terminal.Gui.View draw APIs, including the `OnDrawContent` method, the `DrawContent` event, and the @Terminal.Gui.View.Move method, all take coordinates specified in *Viewport-Relative* coordinates. That is, `0, 0` is the top-left cell visible to the user.
+The @Terminal.Gui.View draw APIs all take coordinates specified in *Viewport-Relative* coordinates. That is, `0, 0` is the top-left cell visible to the user.
See [Layout](layout.md) for more details of the Terminal.Gui coordinate system.