diff --git a/Examples/UICatalog/Scenarios/Transparent.cs b/Examples/UICatalog/Scenarios/Transparent.cs
index 801372d2c..833bcc558 100644
--- a/Examples/UICatalog/Scenarios/Transparent.cs
+++ b/Examples/UICatalog/Scenarios/Transparent.cs
@@ -1,8 +1,9 @@
+// ReSharper disable AccessToDisposedClosure
#nullable enable
namespace UICatalog.Scenarios;
-[ScenarioMetadata ("Transparent", "Testing Transparency")]
+[ScenarioMetadata ("Transparent", "Demonstrates View Transparency")]
public sealed class Transparent : Scenario
{
public override void Main ()
@@ -53,11 +54,19 @@ public sealed class Transparent : Scenario
var tv = new TransparentView ()
{
- X = 3,
- Y = 3,
- Width = 50,
- Height = 15
+ X = 2,
+ Y = 2,
+ Width = Dim.Fill (10),
+ Height = Dim.Fill (10)
};
+
+ appWindow.ViewportChanged += (sender, args) =>
+ {
+ // Little hack to convert the Dim.Fill to actual size
+ // So resizing works
+ tv.Width = appWindow!.Frame.Width - 10;
+ tv.Height = appWindow!.Frame.Height - 10;
+ };
appWindow.Add (tv);
// Run - Start the application.
@@ -72,34 +81,31 @@ public sealed class Transparent : Scenario
{
public TransparentView ()
{
- Title = "Transparent View";
- //base.Text = "View.Text.\nThis should be opaque.\nNote how clipping works?";
- TextFormatter.Alignment = Alignment.Center;
- TextFormatter.VerticalAlignment = Alignment.Center;
+ Title = "Transparent View - Move and Resize To See Transparency In Action";
+ base.Text = "View.Text.\nThis should be opaque. Note how clipping works?";
Arrangement = ViewArrangement.Overlapped | ViewArrangement.Resizable | ViewArrangement.Movable;
- ViewportSettings |= Terminal.Gui.ViewBase.ViewportSettingsFlags.Transparent | Terminal.Gui.ViewBase.ViewportSettingsFlags.TransparentMouse;
+ ViewportSettings |= ViewportSettingsFlags.Transparent | ViewportSettingsFlags.TransparentMouse;
BorderStyle = LineStyle.RoundedDotted;
- //SchemeName = "Base";
+ SchemeName = "Base";
var transparentSubView = new View ()
{
- Text = "Sizable/Movable View with border. Should be opaque. No Shadow.",
+ Text = "Sizable/Movable SunView with border and shadow.",
Id = "transparentSubView",
- X = 4,
- Y = 8,
+ X = Pos.Center (),
+ Y = Pos.Center (),
Width = 20,
Height = 8,
BorderStyle = LineStyle.Dashed,
Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable,
- // ShadowStyle = ShadowStyle.Transparent,
+ ShadowStyle = ShadowStyle.Transparent,
};
transparentSubView.Border!.Thickness = new (1, 1, 1, 1);
transparentSubView.SchemeName = "Dialog";
- //transparentSubView.Visible = false;
Button button = new Button ()
{
- Title = "_Opaque Shadows No Worky",
+ Title = "_Opaque Shadow",
X = Pos.Center (),
Y = 2,
SchemeName = "Dialog",
@@ -109,8 +115,6 @@ public sealed class Transparent : Scenario
MessageBox.Query (App, "Clicked!", "Button in Transparent View", "_Ok");
args.Handled = true;
};
- //button.Visible = false;
-
var shortcut = new Shortcut ()
{
@@ -121,7 +125,6 @@ public sealed class Transparent : Scenario
HelpText = "Help!",
Key = Key.F11,
SchemeName = "Base"
-
};
button.ClearingViewport += (sender, args) =>
@@ -129,16 +132,91 @@ public sealed class Transparent : Scenario
args.Cancel = true;
};
+ // Subscribe to DrawingContent event to draw "TUI"
+ DrawingContent += TransparentView_DrawingContent;
base.Add (button);
base.Add (shortcut);
base.Add (transparentSubView);
- //Padding.Thickness = new (1);
- //Padding.SchemeName = "Error";
+ Padding!.Thickness = new (1);
+ Padding.Text = "This is the Padding";
+ }
- Margin!.Thickness = new (1);
- // Margin.ViewportSettings |= Terminal.Gui.ViewportSettingsFlags.Transparent;
+ private void TransparentView_DrawingContent (object? sender, DrawEventArgs e)
+ {
+ // Draw "TUI" text using rectangular regions, positioned after "Hi"
+ // Letter "T"
+ Rectangle tTop = new (20, 5, 7, 2); // Top horizontal bar
+ Rectangle tStem = new (23, 7, 2, 8); // Vertical stem
+
+ // Letter "U"
+ Rectangle uLeft = new (30, 5, 2, 8); // Left vertical bar
+ Rectangle uBottom = new (32, 13, 3, 2); // Bottom horizontal bar
+ Rectangle uRight = new (35, 5, 2, 8); // Right vertical bar
+
+ // Letter "I"
+ Rectangle iTop = new (39, 5, 4, 2); // Bar on top
+ Rectangle iStem = new (40, 7, 2, 6); // Vertical stem
+ Rectangle iBottom = new (39, 13, 4, 2); // Bar on Bottom
+
+ // Draw "TUI" using the HotActive attribute
+ SetAttributeForRole (VisualRole.HotActive);
+ FillRect (tTop, Glyphs.BlackCircle);
+ FillRect (tStem, Glyphs.BlackCircle);
+ FillRect (uLeft, Glyphs.BlackCircle);
+ FillRect (uBottom, Glyphs.BlackCircle);
+ FillRect (uRight, Glyphs.BlackCircle);
+ FillRect (iTop, Glyphs.BlackCircle);
+ FillRect (iStem, Glyphs.BlackCircle);
+ FillRect (iBottom, Glyphs.BlackCircle);
+
+ Region tuiRegion = new Region (ViewportToScreen (tTop));
+ tuiRegion.Union (ViewportToScreen (tStem));
+ tuiRegion.Union (ViewportToScreen (uLeft));
+ tuiRegion.Union (ViewportToScreen (uBottom));
+ tuiRegion.Union (ViewportToScreen (uRight));
+ tuiRegion.Union (ViewportToScreen (iTop));
+ tuiRegion.Union (ViewportToScreen (iStem));
+ tuiRegion.Union (ViewportToScreen (iBottom));
+
+ // Register the drawn region for "TUI" to enable transparency effects
+ e.DrawContext?.AddDrawnRegion (tuiRegion);
+ }
+
+ ///
+ protected override bool OnDrawingContent (DrawContext? context)
+ {
+ base.OnDrawingContent (context);
+
+ // Draw "Hi" text using rectangular regions
+ // Letter "H"
+ Rectangle hLeft = new (5, 5, 2, 10); // Left vertical bar
+ Rectangle hMiddle = new (7, 9, 3, 2); // Middle horizontal bar
+ Rectangle hRight = new (10, 5, 2, 10); // Right vertical bar
+
+ // Letter "i" (with some space between H and i)
+ Rectangle iDot = new (15, 5, 2, 2); // Dot on top
+ Rectangle iStem = new (15, 9, 2, 6); // Vertical stem
+
+ // Draw "Hi" using the Highlight attribute
+ SetAttributeForRole (VisualRole.Highlight);
+ FillRect (hLeft, Glyphs.BlackCircle);
+ FillRect (hMiddle, Glyphs.BlackCircle);
+ FillRect (hRight, Glyphs.BlackCircle);
+ FillRect (iDot, Glyphs.BlackCircle);
+ FillRect (iStem, Glyphs.BlackCircle);
+
+ // Register the drawn region for "Hi" to enable transparency effects
+ Region hiRegion = new Region (ViewportToScreen (hLeft));
+ hiRegion.Union (ViewportToScreen (hMiddle));
+ hiRegion.Union (ViewportToScreen (hRight));
+ hiRegion.Union (ViewportToScreen (iDot));
+ hiRegion.Union (ViewportToScreen (iStem));
+ context?.AddDrawnRegion (hiRegion);
+
+ // Return false to allow DrawingContent event to fire
+ return false;
}
///
diff --git a/Terminal.Gui/ViewBase/DrawContext.cs b/Terminal.Gui/ViewBase/DrawContext.cs
index e6df3033b..0a683a636 100644
--- a/Terminal.Gui/ViewBase/DrawContext.cs
+++ b/Terminal.Gui/ViewBase/DrawContext.cs
@@ -1,10 +1,43 @@
-
-namespace Terminal.Gui.ViewBase;
+namespace Terminal.Gui.ViewBase;
///
/// Tracks the region that has been drawn during . This is primarily
/// in support of .
///
+///
+///
+/// When a has set, the
+/// is used to track exactly which areas of the screen have been drawn to. After drawing is complete, these drawn
+/// regions are excluded from the clip region, allowing views beneath the transparent view to show through in
+/// the areas that were not drawn.
+///
+///
+/// All coordinates tracked by are in screen-relative coordinates. When reporting
+/// drawn areas from within , use
+/// or to convert viewport-relative or content-relative coordinates to
+/// screen-relative coordinates before calling or .
+///
+///
+/// Example of reporting a non-rectangular drawn region for transparency:
+///
+///
+/// protected override bool OnDrawingContent (DrawContext? context)
+/// {
+/// // Draw some content in viewport-relative coordinates
+/// Rectangle rect1 = new Rectangle (5, 5, 10, 3);
+/// Rectangle rect2 = new Rectangle (8, 8, 4, 7);
+/// FillRect (rect1, Glyphs.BlackCircle);
+/// FillRect (rect2, Glyphs.BlackCircle);
+///
+/// // Report the drawn region in screen-relative coordinates
+/// Region drawnRegion = new Region (ViewportToScreen (rect1));
+/// drawnRegion.Union (ViewportToScreen (rect2));
+/// context?.AddDrawnRegion (drawnRegion);
+///
+/// return true;
+/// }
+///
+///
public class DrawContext
{
private readonly Region _drawnRegion = new Region ();
@@ -12,12 +45,20 @@ public class DrawContext
///
/// Gets a copy of the region drawn so far in this context.
///
+ ///
+ /// The returned region contains all areas that have been reported as drawn via
+ /// or , in screen-relative coordinates.
+ ///
public Region GetDrawnRegion () => _drawnRegion.Clone ();
///
/// Reports that a rectangle has been drawn.
///
- /// The rectangle that was drawn.
+ /// The rectangle that was drawn, in screen-relative coordinates.
+ ///
+ /// When called from within , ensure the rectangle is in
+ /// screen-relative coordinates by using or similar methods.
+ ///
public void AddDrawnRectangle (Rectangle rect)
{
_drawnRegion.Combine (rect, RegionOp.Union);
@@ -26,7 +67,18 @@ public class DrawContext
///
/// Reports that a region has been drawn.
///
- /// The region that was drawn.
+ /// The region that was drawn, in screen-relative coordinates.
+ ///
+ ///
+ /// This method is useful for reporting non-rectangular drawn areas, which is important for
+ /// proper transparency support with .
+ ///
+ ///
+ /// When called from within , ensure the region is in
+ /// screen-relative coordinates by using to convert each
+ /// rectangle in the region.
+ ///
+ ///
public void AddDrawnRegion (Region region)
{
_drawnRegion.Combine (region, RegionOp.Union);
@@ -36,7 +88,7 @@ public class DrawContext
/// Clips (intersects) the drawn region with the specified rectangle.
/// This modifies the internal drawn region directly.
///
- /// The clipping rectangle.
+ /// The clipping rectangle, in screen-relative coordinates.
public void ClipDrawnRegion (Rectangle clipRect)
{
_drawnRegion.Intersect (clipRect);
@@ -46,7 +98,7 @@ public class DrawContext
/// Clips (intersects) the drawn region with the specified region.
/// This modifies the internal drawn region directly.
///
- /// The clipping region.
+ /// The clipping region, in screen-relative coordinates.
public void ClipDrawnRegion (Region clipRegion)
{
_drawnRegion.Intersect (clipRegion);
diff --git a/Terminal.Gui/ViewBase/View.Drawing.cs b/Terminal.Gui/ViewBase/View.Drawing.cs
index 3a523de7d..5c213f55e 100644
--- a/Terminal.Gui/ViewBase/View.Drawing.cs
+++ b/Terminal.Gui/ViewBase/View.Drawing.cs
@@ -520,14 +520,66 @@ public partial class View // Drawing APIs
///
/// The draw context to report drawn areas to.
/// to stop further drawing content.
+ ///
+ ///
+ /// Override this method to draw custom content for your View.
+ ///
+ ///
+ /// Transparency Support: If your View has with
+ /// set, you should report the exact regions you draw to via the parameter. This allows
+ /// the transparency system to exclude only the drawn areas from the clip region, letting views beneath show through
+ /// in the areas you didn't draw.
+ ///
+ ///
+ /// Use for simple rectangular areas, or
+ /// for complex, non-rectangular shapes. All coordinates passed to these methods must be in screen-relative coordinates.
+ /// Use or to convert from
+ /// viewport-relative or content-relative coordinates.
+ ///
+ ///
+ /// Example of drawing custom content with transparency support:
+ ///
+ ///
+ /// protected override bool OnDrawingContent (DrawContext? context)
+ /// {
+ /// base.OnDrawingContent (context);
+ ///
+ /// // Draw content in viewport-relative coordinates
+ /// Rectangle rect1 = new Rectangle (5, 5, 10, 3);
+ /// Rectangle rect2 = new Rectangle (8, 8, 4, 7);
+ /// FillRect (rect1, Glyphs.BlackCircle);
+ /// FillRect (rect2, Glyphs.BlackCircle);
+ ///
+ /// // Report drawn region in screen-relative coordinates for transparency
+ /// if (ViewportSettings.HasFlag (ViewportSettingsFlags.Transparent))
+ /// {
+ /// Region drawnRegion = new Region (ViewportToScreen (rect1));
+ /// drawnRegion.Union (ViewportToScreen (rect2));
+ /// context?.AddDrawnRegion (drawnRegion);
+ /// }
+ ///
+ /// return true;
+ /// }
+ ///
+ ///
protected virtual bool OnDrawingContent (DrawContext? context) { return false; }
/// Raised when the View's content is to be drawn.
///
- /// Will be invoked before any subviews added with have been drawn.
///
- /// Rect provides the view-relative rectangle describing the currently visible viewport into the
- /// .
+ /// Subscribe to this event to draw custom content for the View. Use the drawing methods available on
+ /// such as , , and .
+ ///
+ ///
+ /// The event is invoked after and after any and have been drawn.
+ ///
+ ///
+ /// Transparency Support: If the View has with
+ /// set, use the to report which areas were actually drawn. This enables proper transparency
+ /// by excluding only the drawn areas from the clip region. See for details on reporting drawn regions.
+ ///
+ ///
+ /// The property provides the view-relative rectangle describing the currently visible viewport into the View.
///
///
public event EventHandler? DrawingContent;