View Draw API docs and code cleanup

This commit is contained in:
Tig
2024-10-26 16:24:41 -07:00
parent 8ea89b8e40
commit ee29ed87ed
2 changed files with 70 additions and 26 deletions

View File

@@ -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 ();
}
/// <summary>
/// Called when the normal attribute for the View is to be set. This is called before the View is drawn.
/// </summary>
/// <returns><see langword="true"/> to stop default behavior.</returns>
protected virtual bool OnSettingAttribute () { return false; }
/// <summary>Raised when the normal attribute for the View is to be set. This is raised before the View is drawn.</summary>
/// <returns>
/// Set <see cref="CancelEventArgs.Cancel"/> to <see langword="true"/> to stop default behavior.
/// </returns>
public event EventHandler<CancelEventArgs>? SettingAttribute;
/// <summary>
/// Sets the attribute for the View. This is called before the View is drawn.
/// </summary>
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
/// <summary>
/// Called when the View is completed drawing.
/// </summary>
/// <param name="viewport"></param>
protected virtual bool OnDrawComplete (Rectangle viewport) { return false; }
protected virtual void OnDrawComplete () { }
/// <summary>Raised when the View is completed drawing.</summary>
/// <remarks>
/// </remarks>
public event EventHandler<DrawEventArgs>? DrawComplete;
public event EventHandler<EventArgs>? DrawComplete;
#endregion DrawComplete

View File

@@ -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.