Container.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. using NStack;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Xml.Linq;
  6. using Terminal.Gui.Graphs;
  7. namespace Terminal.Gui {
  8. public class Frame : View {
  9. /// <summary>
  10. /// Frames are a special form of <see cref="View"/> that act as adornments; they appear outside of the <see cref="View>Bounds"/>
  11. /// eanbling borders, menus, etc...
  12. /// </summary>
  13. public Frame ()
  14. {
  15. IgnoreBorderPropertyOnRedraw = true;
  16. }
  17. /// <summary>
  18. /// The Parent of this Frame (Adornment).
  19. /// </summary>
  20. public View Parent { get; set; }
  21. /// <summary>
  22. /// Frames cannot be used as sub-views, so this method always throws an <see cref="InvalidOperationException"/>.
  23. /// TODO: Are we sure?
  24. /// </summary>
  25. public override View SuperView {
  26. get {
  27. return null;
  28. }
  29. set {
  30. throw new NotImplementedException ();
  31. }
  32. }
  33. /// <inheritdoc/>
  34. public override void ViewToScreen (int col, int row, out int rcol, out int rrow, bool clipped = true)
  35. {
  36. // Frames are children of a View, not SubViews. Thus ViewToScreen will not work.
  37. // To get the screen-relative coordinates of a Frame, we need to know who
  38. // the Parent is
  39. // Computes the real row, col relative to the screen.
  40. var inner = Parent?.Bounds ?? Bounds;
  41. rrow = row - inner.Y;
  42. rcol = col - inner.X;
  43. Parent?.ViewToScreen (rcol, rrow, out rcol, out rrow, clipped);
  44. }
  45. public virtual void OnDrawSubViews (Rect clipRect)
  46. {
  47. // if (Subviews == null) {
  48. // return;
  49. // }
  50. // foreach (var view in Subviews) {
  51. // // BUGBUG: v2 - shouldn't this be !view.LayoutNeeded? Why draw if layout is going to happen and we'll just draw again?
  52. // if (view.LayoutNeeded) {
  53. // view.LayoutSubviews ();
  54. // }
  55. // if ((view.Visible && !view.NeedDisplay.IsEmpty && view.Frame.Width > 0 && view.Frame.Height > 0) || view.ChildNeedsDisplay) {
  56. // view.Redraw (view.Bounds);
  57. // view.NeedDisplay = Rect.Empty;
  58. // // BUGBUG - v2 why does this need to be set to false?
  59. // // Shouldn't it be set when the subviews draw?
  60. // view.ChildNeedsDisplay = false;
  61. // }
  62. // }
  63. }
  64. public override void OnDrawContent (Rect viewport)
  65. {
  66. if (!ustring.IsNullOrEmpty (TextFormatter.Text)) {
  67. Clear (viewport);
  68. SetChildNeedsDisplay ();
  69. // Draw any Text
  70. if (TextFormatter != null) {
  71. TextFormatter.NeedsFormat = true;
  72. Rect containerBounds = GetContainerBounds ();
  73. TextFormatter?.Draw (ViewToScreen (viewport), HasFocus ? ColorScheme.Focus : GetNormalColor (),
  74. HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
  75. containerBounds);
  76. }
  77. }
  78. }
  79. /// <summary>
  80. /// Redraws the Frames that comprise the <see cref="Frame"/>.
  81. /// </summary>
  82. /// <param name="clipRect"></param>
  83. public override void Redraw (Rect clipRect)
  84. {
  85. //OnDrawContent (bounds);
  86. //OnDrawSubViews (bounds);
  87. //OnDrawContentComplete (bounds);
  88. if (ColorScheme != null) {
  89. Driver.SetAttribute (ColorScheme.Normal);
  90. }
  91. var screenBounds = ViewToScreen (Frame);
  92. Thickness.Draw (screenBounds, (string)Data);
  93. //OnDrawContent (bounds);
  94. if (BorderStyle != BorderStyle.None) {
  95. var lc = new LineCanvas ();
  96. lc.AddLine (screenBounds.Location, Frame.Width - 1, Orientation.Horizontal, BorderStyle);
  97. lc.AddLine (screenBounds.Location, Frame.Height - 1, Orientation.Vertical, BorderStyle);
  98. lc.AddLine (new Point (screenBounds.X, screenBounds.Y + screenBounds.Height - 1), screenBounds.Width - 1, Orientation.Horizontal, BorderStyle);
  99. lc.AddLine (new Point (screenBounds.X + screenBounds.Width - 1, screenBounds.Y), screenBounds.Height - 1, Orientation.Vertical, BorderStyle);
  100. foreach (var p in lc.GenerateImage (screenBounds)) {
  101. Driver.Move (p.Key.X, p.Key.Y);
  102. Driver.AddRune (p.Value);
  103. }
  104. if (!ustring.IsNullOrEmpty (Title)) {
  105. Driver.DrawWindowTitle (screenBounds, Title, 0, 0, 0, 0);
  106. }
  107. }
  108. }
  109. //public Label DiagnosticsLabel { get; set; }
  110. // TODO: v2 = This is teporary; need to also enable (or not) simple way of setting
  111. // other border properties
  112. // TOOD: v2 - Missing 3D effect
  113. public BorderStyle BorderStyle { get; set; } = BorderStyle.None;
  114. public Thickness Thickness { get; set; }
  115. // TODO: v2 - This is confusing. It is a read-only property and actually only returns a size, so
  116. // should not be a Rect. However, it may make sense to keep it a Rect and support negative Location
  117. // for scrolling. Still noodling this.
  118. /// <summary>
  119. /// Gets the rectangle that describes the inner area of the frame. The Location is always 0, 0.
  120. /// </summary>
  121. public Rect Bounds {
  122. get {
  123. if (Thickness != null) {
  124. new Rect (Point.Empty, Frame.Size);
  125. }
  126. // Return the frame-relative bounds
  127. return Thickness.GetInnerRect (new Rect (Point.Empty, Frame.Size));
  128. }
  129. set {
  130. throw new InvalidOperationException ("It makes no sense to explicitly set Bounds.");
  131. }
  132. }
  133. //public override void OnDrawContent (Rect viewport)
  134. //{
  135. // // do nothing
  136. //}
  137. //public override void Redraw (Rect bounds)
  138. //{
  139. // if (ColorScheme != null) {
  140. // Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
  141. // }
  142. // //if (Text != null) {
  143. // // Thickness?.Draw (Frame, $"{Text} {DiagnosticsLabel?.Text}");
  144. // //}
  145. // if (BorderStyle != BorderStyle.None) {
  146. // var lc = new LineCanvas ();
  147. // lc.AddLine (Frame.Location, Frame.Width - 1, Orientation.Horizontal, BorderStyle);
  148. // lc.AddLine (Frame.Location, Frame.Height - 1, Orientation.Vertical, BorderStyle);
  149. // lc.AddLine (new Point (Frame.X, Frame.Y + Frame.Height - 1), Frame.Width - 1, Orientation.Horizontal, BorderStyle);
  150. // lc.AddLine (new Point (Frame.X + Frame.Width - 1, Frame.Y), Frame.Height - 1, Orientation.Vertical, BorderStyle);
  151. // foreach (var p in lc.GenerateImage (Frame)) {
  152. // Driver.Move (p.Key.X, p.Key.Y);
  153. // Driver.AddRune (p.Value);
  154. // }
  155. // if (!ustring.IsNullOrEmpty (Title)) {
  156. // Driver.DrawWindowTitle (Frame, Title, 0, 0, 0, 0);
  157. // }
  158. // }
  159. // base.Redraw (bounds);
  160. //}
  161. }
  162. }