View.Drawing.Clipping.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #nullable enable
  2. namespace Terminal.Gui;
  3. public partial class View
  4. {
  5. internal Region? SetClipToFrame ()
  6. {
  7. if (Driver is null)
  8. {
  9. return null;
  10. }
  11. Region previous = Driver.Clip ?? new (Application.Screen);
  12. Region frameRegion = Driver.Clip!.Clone ();
  13. // Translate viewportRegion to screen-relative coords
  14. Rectangle screenRect = FrameToScreen ();
  15. frameRegion.Intersect (screenRect);
  16. if (this is Adornment adornment && adornment.Thickness != Thickness.Empty)
  17. {
  18. // Ensure adornments can't draw outside thier thickness
  19. frameRegion.Exclude (adornment.Thickness.GetInside (Frame));
  20. }
  21. Driver.Clip = frameRegion;
  22. return previous;
  23. }
  24. /// <summary>Sets the <see cref="ConsoleDriver"/>'s clip region to <see cref="Viewport"/>.</summary>
  25. /// <remarks>
  26. /// <para>
  27. /// By default, the clip rectangle is set to the intersection of the current clip region and the
  28. /// <see cref="Viewport"/>. This ensures that drawing is constrained to the viewport, but allows
  29. /// content to be drawn beyond the viewport.
  30. /// </para>
  31. /// <para>
  32. /// If <see cref="ViewportSettings"/> has <see cref="Gui.ViewportSettings.ClipContentOnly"/> set, clipping will be
  33. /// applied to just the visible content area.
  34. /// </para>
  35. /// </remarks>
  36. /// <returns>
  37. /// The current screen-relative clip region, which can be then re-applied by setting
  38. /// <see cref="ConsoleDriver.Clip"/>.
  39. /// </returns>
  40. public Region? SetClipToViewport ()
  41. {
  42. if (Driver is null)
  43. {
  44. return null;
  45. }
  46. Region previous = Driver.Clip ?? new (Application.Screen);
  47. Region viewportRegion = Driver.Clip!.Clone ();
  48. Rectangle viewport = ViewportToScreen (new Rectangle (Point.Empty, Viewport.Size));
  49. viewportRegion?.Intersect (viewport);
  50. if (ViewportSettings.HasFlag (ViewportSettings.ClipContentOnly))
  51. {
  52. // Clamp the Clip to the just content area that is within the viewport
  53. Rectangle visibleContent = ViewportToScreen (new Rectangle (new (-Viewport.X, -Viewport.Y), GetContentSize ()));
  54. viewportRegion?.Intersect (visibleContent);
  55. }
  56. if (this is Adornment adornment && adornment.Thickness != Thickness.Empty)
  57. {
  58. // Ensure adornments can't draw outside their thickness
  59. viewportRegion?.Exclude (adornment.Thickness.GetInside (viewport));
  60. }
  61. Driver.Clip = viewportRegion;
  62. return previous;
  63. }
  64. /// <summary>Gets the view-relative clip region.</summary>
  65. public Region? GetClip ()
  66. {
  67. // get just the portion of the application clip that is within this view's Viewport
  68. if (Driver is null)
  69. {
  70. return null;
  71. }
  72. // Get our Viewport in screen coordinates
  73. Rectangle screen = ViewportToScreen (Viewport with { Location = Point.Empty });
  74. // Get the clip region in screen coordinates
  75. Region? clip = Driver.Clip;
  76. if (clip is null)
  77. {
  78. return null;
  79. }
  80. Region? previous = Driver.Clip;
  81. clip = clip.Clone ();
  82. clip.Intersect (screen);
  83. return clip;
  84. }
  85. }