Border.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. using NStack;
  2. using System;
  3. using System.Collections.Generic;
  4. using Terminal.Gui.Graphs;
  5. using System.Text.Json.Serialization;
  6. using System.Data;
  7. using System.Text;
  8. namespace Terminal.Gui {
  9. /// <summary>
  10. /// Specifies the border style for a <see cref="View"/> and to be used by the <see cref="Border"/> class.
  11. /// </summary>
  12. public enum BorderStyle {
  13. /// <summary>
  14. /// No border is drawn.
  15. /// </summary>
  16. None,
  17. /// <summary>
  18. /// The border is drawn using single-width line glyphs.
  19. /// </summary>
  20. Single,
  21. /// <summary>
  22. /// The border is drawn using double-width line glyphs.
  23. /// </summary>
  24. Double,
  25. /// <summary>
  26. /// The border is drawn using single-width line glyphs with rounded corners.
  27. /// </summary>
  28. Rounded,
  29. // TODO: Support Ruler
  30. ///// <summary>
  31. ///// The border is drawn as a diagnostic ruler ("|123456789...").
  32. ///// </summary>
  33. //Ruler
  34. }
  35. /// <summary>
  36. /// Describes the thickness of a frame around a rectangle. Four <see cref="int"/> values describe
  37. /// the <see cref="Left"/>, <see cref="Top"/>, <see cref="Right"/>, and <see cref="Bottom"/> sides
  38. /// of the rectangle, respectively.
  39. /// </summary>
  40. public class Thickness : IEquatable<Thickness> {
  41. private int validate (int width)
  42. {
  43. if (width < 0) {
  44. throw new ArgumentException ("Thickness widths cannot be negative.");
  45. }
  46. return width;
  47. }
  48. /// <summary>
  49. /// Gets or sets the width of the left side of the rectangle.
  50. /// </summary>
  51. [JsonInclude]
  52. public int Left;
  53. /// <summary>
  54. /// Gets or sets the width of the upper side of the rectangle.
  55. /// </summary>
  56. [JsonInclude]
  57. public int Top;
  58. /// <summary>
  59. /// Gets or sets the width of the right side of the rectangle.
  60. /// </summary>
  61. [JsonInclude]
  62. public int Right;
  63. /// <summary>
  64. /// Gets or sets the width of the lower side of the rectangle.
  65. /// </summary>
  66. [JsonInclude]
  67. public int Bottom;
  68. /// <summary>
  69. /// Initializes a new instance of the <see cref="Thickness"/> class with all widths
  70. /// set to 0.
  71. /// </summary>
  72. public Thickness () { }
  73. /// <summary>
  74. /// Initializes a new instance of the <see cref="Thickness"/> class with a uniform width to each side.
  75. /// </summary>
  76. /// <param name="width"></param>
  77. public Thickness (int width) : this (width, width, width, width) { }
  78. /// <summary>
  79. /// Initializes a new instance of the <see cref="Thickness"/> class that has specific
  80. /// widths applied to each side of the rectangle.
  81. /// </summary>
  82. /// <param name="left"></param>
  83. /// <param name="top"></param>
  84. /// <param name="right"></param>
  85. /// <param name="bottom"></param>
  86. public Thickness (int left, int top, int right, int bottom)
  87. {
  88. Left = left;
  89. Top = top;
  90. Right = right;
  91. Bottom = bottom;
  92. }
  93. /// <summary>
  94. /// Returns a rectangle describing the location and size of the inner area of <paramref name="rect"/>
  95. /// with the thickness widths subracted. The height and width of the retunred rect may be zero.
  96. /// </summary>
  97. /// <param name="rect">The source rectangle</param>
  98. /// <returns></returns>
  99. public Rect GetInnerRect (Rect rect)
  100. {
  101. var width = rect.Size.Width - (Left + Right);
  102. var height = rect.Size.Height - (Top + Bottom);
  103. var size = new Size (Math.Max (0, width), Math.Max (0, height));
  104. return new Rect (new Point (rect.X + Left, rect.Y + Top), size);
  105. }
  106. private void FillRect (Rect rect, System.Rune rune = default)
  107. {
  108. for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
  109. for (var c = rect.X; c < rect.X + rect.Width; c++) {
  110. Application.Driver.Move (c, r);
  111. Application.Driver.AddRune (rune == default ? ' ' : rune);
  112. }
  113. }
  114. }
  115. /// <summary>
  116. /// Draws the <see cref="Thickness"/> rectangle with an optional diagnostics label.
  117. /// </summary>
  118. /// <remarks>
  119. /// If <see cref="ConsoleDriver.DiagnosticFlags"/> is set to <see cref="ConsoleDriver.DiagnosticFlags.FramePadding"/> then
  120. /// 'T', 'L', 'R', and 'B' glyphs will be used instead of space. If <see cref="ConsoleDriver.DiagnosticFlags"/>
  121. /// is set to <see cref="ConsoleDriver.DiagnosticFlags.FrameRuler"/> then a ruler will be drawn on the outer edge of the
  122. /// Thickness.
  123. /// </remarks>
  124. /// <param name="rect">The location and size of the rectangle that bounds the thickness rectangle, in
  125. /// screen coordinates.</param>
  126. /// <param name="label">The diagnostics label to draw on the bottom of the <see cref="Bottom"/>.</param>
  127. /// <returns>The inner rectangle remaining to be drawn.</returns>
  128. public Rect Draw (Rect rect, string label = null)
  129. {
  130. System.Rune clearChar = ' ';
  131. System.Rune leftChar = clearChar;
  132. System.Rune rightChar = clearChar;
  133. System.Rune topChar = clearChar;
  134. System.Rune bottomChar = clearChar;
  135. if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding) {
  136. leftChar = 'L';
  137. rightChar = 'R';
  138. topChar = 'T';
  139. bottomChar = 'B';
  140. }
  141. ustring hrule = ustring.Empty;
  142. ustring vrule = ustring.Empty;
  143. if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler) {
  144. string h = "0123456789";
  145. hrule = h.Repeat ((int)Math.Ceiling ((double)(rect.Width) / (double)h.Length)) [0..(rect.Width)];
  146. string v = "0123456789";
  147. vrule = v.Repeat ((int)Math.Ceiling ((double)(rect.Height * 2) / (double)v.Length)) [0..(rect.Height * 2)];
  148. };
  149. // Draw the Top side
  150. FillRect (new Rect (rect.X, rect.Y, rect.Width, Math.Min (rect.Height, Top)), topChar);
  151. // Draw the Left side
  152. FillRect (new Rect (rect.X, rect.Y, Math.Min (rect.Width, Left), rect.Height), leftChar);
  153. // Draw the Right side
  154. FillRect (new Rect (Math.Max (0, rect.X + rect.Width - Right), rect.Y, Math.Min (rect.Width, Right), rect.Height), rightChar);
  155. // Draw the Bottom side
  156. FillRect (new Rect (rect.X, rect.Y + Math.Max (0, rect.Height - Bottom), rect.Width, Bottom), bottomChar);
  157. // TODO: This should be moved to LineCanvas as a new BorderStyle.Ruler
  158. if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler) {
  159. // Top
  160. Application.Driver.Move (rect.X, rect.Y);
  161. Application.Driver.AddStr (hrule);
  162. //Left
  163. for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
  164. Application.Driver.Move (rect.X, r);
  165. Application.Driver.AddRune (vrule [r - rect.Y]);
  166. }
  167. // Bottom
  168. Application.Driver.Move (rect.X, rect.Y + rect.Height - Bottom + 1);
  169. Application.Driver.AddStr (hrule);
  170. // Right
  171. for (var r = rect.Y + 1; r < rect.Y + rect.Height; r++) {
  172. Application.Driver.Move (rect.X + rect.Width - Right + 1, r);
  173. Application.Driver.AddRune (vrule [r - rect.Y]);
  174. }
  175. }
  176. // Draw the diagnostics label on the bottom
  177. var tf = new TextFormatter () {
  178. Text = label == null ? string.Empty : $"{label} {this}",
  179. Alignment = TextAlignment.Centered,
  180. VerticalAlignment = VerticalTextAlignment.Bottom
  181. };
  182. tf.Draw (rect, Application.Driver.CurrentAttribute, Application.Driver.CurrentAttribute, rect, false);
  183. return GetInnerRect (rect);
  184. }
  185. // TODO: add operator overloads
  186. /// <summary>
  187. /// Gets an empty thickness.
  188. /// </summary>
  189. public static Thickness Empty => new Thickness (0);
  190. public override bool Equals (object obj)
  191. {
  192. //Check for null and compare run-time types.
  193. if ((obj == null) || !this.GetType ().Equals (obj.GetType ())) {
  194. return false;
  195. } else {
  196. return Equals ((Thickness)obj);
  197. }
  198. }
  199. /// <summary>Returns the thickness widths of the Thickness formatted as a string.</summary>
  200. /// <returns>The thickness widths as a string.</returns>
  201. public override string ToString ()
  202. {
  203. return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})";
  204. }
  205. // IEquitable
  206. public bool Equals (Thickness other)
  207. {
  208. return other is not null &&
  209. Left == other.Left &&
  210. Right == other.Right &&
  211. Top == other.Top &&
  212. Bottom == other.Bottom;
  213. }
  214. public override int GetHashCode ()
  215. {
  216. int hashCode = 1380952125;
  217. hashCode = hashCode * -1521134295 + Left.GetHashCode ();
  218. hashCode = hashCode * -1521134295 + Right.GetHashCode ();
  219. hashCode = hashCode * -1521134295 + Top.GetHashCode ();
  220. hashCode = hashCode * -1521134295 + Bottom.GetHashCode ();
  221. return hashCode;
  222. }
  223. public static bool operator == (Thickness left, Thickness right)
  224. {
  225. return EqualityComparer<Thickness>.Default.Equals (left, right);
  226. }
  227. public static bool operator != (Thickness left, Thickness right)
  228. {
  229. return !(left == right);
  230. }
  231. }
  232. internal static class StringExtensions {
  233. public static string Repeat (this string instr, int n)
  234. {
  235. if (n <= 0) {
  236. return null;
  237. }
  238. if (string.IsNullOrEmpty (instr) || n == 1) {
  239. return instr;
  240. }
  241. return new StringBuilder (instr.Length * n)
  242. .Insert (0, instr, n)
  243. .ToString ();
  244. }
  245. }
  246. /// <summary>
  247. /// Draws a border, background, or both around another element.
  248. /// </summary>
  249. public class Border {
  250. private int marginFrame => DrawMarginFrame ? 1 : 0;
  251. ///// <summary>
  252. ///// A sealed <see cref="Toplevel"/> derived class to implement <see cref="Border"/> feature.
  253. ///// This is only a wrapper to get borders on a toplevel and is recommended using another
  254. ///// derived, like <see cref="Window"/> where is possible to have borders with or without
  255. ///// border line or spacing around.
  256. ///// </summary>
  257. //public sealed class ToplevelContainer : Toplevel {
  258. // /// <inheritdoc/>
  259. // public override Border Border {
  260. // get => base.Border;
  261. // set {
  262. // if (base.Border != null && base.Border.Child != null && value.Child == null) {
  263. // value.Child = base.Border.Child;
  264. // }
  265. // base.Border = value;
  266. // if (value == null) {
  267. // return;
  268. // }
  269. // Rect frame;
  270. // if (Border.Child != null && (Border.Child.Width is Dim || Border.Child.Height is Dim)) {
  271. // frame = Rect.Empty;
  272. // } else {
  273. // frame = Frame;
  274. // }
  275. // AdjustContentView (frame);
  276. // Border.BorderChanged += Border_BorderChanged;
  277. // }
  278. // }
  279. // void Border_BorderChanged (Border border)
  280. // {
  281. // Rect frame;
  282. // if (Border.Child != null && (Border.Child.Width is Dim || Border.Child.Height is Dim)) {
  283. // frame = Rect.Empty;
  284. // } else {
  285. // frame = Frame;
  286. // }
  287. // AdjustContentView (frame);
  288. // }
  289. // /// <summary>
  290. // /// Initializes with default null values.
  291. // /// </summary>
  292. // public ToplevelContainer () : this (null, string.Empty) { }
  293. // /// <summary>
  294. // /// Initializes a <see cref="ToplevelContainer"/> with a <see cref="LayoutStyle.Computed"/>
  295. // /// </summary>
  296. // /// <param name="border">The border.</param>
  297. // /// <param name="title">The title.</param>
  298. // public ToplevelContainer (Border border, string title = null)
  299. // {
  300. // Initialize (Rect.Empty, border, title ?? string.Empty);
  301. // }
  302. // /// <summary>
  303. // /// Initializes a <see cref="ToplevelContainer"/> with a <see cref="LayoutStyle.Absolute"/>
  304. // /// </summary>
  305. // /// <param name="frame">The frame.</param>
  306. // /// <param name="border">The border.</param>
  307. // /// <param name="title">The title.</param>
  308. // public ToplevelContainer (Rect frame, Border border, string title = null) : base (frame)
  309. // {
  310. // Initialize (frame, border, title ?? string.Empty);
  311. // }
  312. // private void Initialize (Rect frame, Border border, string title)
  313. // {
  314. // ColorScheme = Colors.TopLevel;
  315. // if (border == null) {
  316. // Border = new Border () {
  317. // BorderStyle = BorderStyle.Single,
  318. // BorderBrush = ColorScheme.Normal.Background,
  319. // Title = (ustring)title
  320. // };
  321. // } else {
  322. // Border = border;
  323. // }
  324. // AdjustContentView (frame);
  325. // }
  326. // void AdjustContentView (Rect frame)
  327. // {
  328. // var borderLength = Border.DrawMarginFrame ? 1 : 0;
  329. // var sumPadding = Border.GetSumThickness ();
  330. // var wp = new Point ();
  331. // var wb = new Size ();
  332. // if (frame == Rect.Empty) {
  333. // wp.X = borderLength + sumPadding.Left;
  334. // wp.Y = borderLength + sumPadding.Top;
  335. // wb.Width = borderLength + sumPadding.Right;
  336. // wb.Height = borderLength + sumPadding.Bottom;
  337. // if (Border.Child == null) {
  338. // Border.Child = new ChildContentView (this) {
  339. // X = wp.X,
  340. // Y = wp.Y,
  341. // Width = Dim.Fill (wb.Width),
  342. // Height = Dim.Fill (wb.Height)
  343. // };
  344. // } else {
  345. // Border.Child.X = wp.X;
  346. // Border.Child.Y = wp.Y;
  347. // Border.Child.Width = Dim.Fill (wb.Width);
  348. // Border.Child.Height = Dim.Fill (wb.Height);
  349. // }
  350. // } else {
  351. // wb.Width = (2 * borderLength) + sumPadding.Right + sumPadding.Left;
  352. // wb.Height = (2 * borderLength) + sumPadding.Bottom + sumPadding.Top;
  353. // var cFrame = new Rect (borderLength + sumPadding.Left, borderLength + sumPadding.Top, frame.Width - wb.Width, frame.Height - wb.Height);
  354. // if (Border.Child == null) {
  355. // Border.Child = new ChildContentView (cFrame, this);
  356. // } else {
  357. // Border.Child.Frame = cFrame;
  358. // }
  359. // }
  360. // if (Subviews?.Count == 0)
  361. // base.Add (Border.Child);
  362. // Border.ChildContainer = this;
  363. // }
  364. // /// <inheritdoc/>
  365. // public override void Add (View view)
  366. // {
  367. // Border.Child.Add (view);
  368. // if (view.CanFocus) {
  369. // CanFocus = true;
  370. // }
  371. // AddMenuStatusBar (view);
  372. // }
  373. // /// <inheritdoc/>
  374. // public override void Remove (View view)
  375. // {
  376. // if (view == null) {
  377. // return;
  378. // }
  379. // SetNeedsDisplay ();
  380. // var touched = view.Frame;
  381. // Border.Child.Remove (view);
  382. // if (Border.Child.InternalSubviews.Count < 1) {
  383. // CanFocus = false;
  384. // }
  385. // RemoveMenuStatusBar (view);
  386. // }
  387. // /// <inheritdoc/>
  388. // public override void RemoveAll ()
  389. // {
  390. // Border.Child.RemoveAll ();
  391. // }
  392. // /// <inheritdoc/>
  393. // public override void Redraw (Rect bounds)
  394. // {
  395. // if (!NeedDisplay.IsEmpty) {
  396. // Driver.SetAttribute (GetNormalColor ());
  397. // Clear ();
  398. // }
  399. // var savedClip = Border.Child.ClipToBounds ();
  400. // Border.Child.Redraw (Border.Child.Bounds);
  401. // Driver.Clip = savedClip;
  402. // ClearLayoutNeeded ();
  403. // ClearNeedsDisplay ();
  404. // Driver.SetAttribute (GetNormalColor ());
  405. // Border.DrawContent (this, false);
  406. // if (HasFocus)
  407. // Driver.SetAttribute (ColorScheme.HotNormal);
  408. // if (Border.DrawMarginFrame) {
  409. // if (!ustring.IsNullOrEmpty (Border.Title))
  410. // Border.DrawTitle (this);
  411. // else
  412. // Border.DrawTitle (this, Frame);
  413. // }
  414. // Driver.SetAttribute (GetNormalColor ());
  415. // // Checks if there are any SuperView view which intersect with this window.
  416. // if (SuperView != null) {
  417. // SuperView.SetNeedsLayout ();
  418. // SuperView.SetNeedsDisplay ();
  419. // }
  420. // }
  421. // /// <inheritdoc/>
  422. // public override void OnCanFocusChanged ()
  423. // {
  424. // if (Border.Child != null) {
  425. // Border.Child.CanFocus = CanFocus;
  426. // }
  427. // base.OnCanFocusChanged ();
  428. // }
  429. //}
  430. //private class ChildContentView : View {
  431. // View instance;
  432. // public ChildContentView (Rect frame, View instance) : base (frame)
  433. // {
  434. // this.instance = instance;
  435. // }
  436. // public ChildContentView (View instance)
  437. // {
  438. // this.instance = instance;
  439. // }
  440. // public override bool MouseEvent (MouseEvent mouseEvent)
  441. // {
  442. // return instance.MouseEvent (mouseEvent);
  443. // }
  444. //}
  445. /// <summary>
  446. /// Invoked when any property of Border changes (except <see cref="Child"/>).
  447. /// </summary>
  448. public event Action<Border> BorderChanged;
  449. private BorderStyle borderStyle;
  450. private bool drawMarginFrame;
  451. private Thickness borderThickness = new Thickness (0);
  452. private Color borderBrush;
  453. private Color background;
  454. private Thickness padding = new Thickness (0);
  455. private bool effect3D;
  456. private Point effect3DOffset = new Point (1, 1);
  457. private Attribute? effect3DBrush;
  458. private ustring title = ustring.Empty;
  459. /// <summary>
  460. /// Specifies the <see cref="Gui.BorderStyle"/> for a view.
  461. /// </summary>
  462. [JsonInclude, JsonConverter (typeof (JsonStringEnumConverter))]
  463. public BorderStyle BorderStyle {
  464. get => borderStyle;
  465. set {
  466. if (value != BorderStyle.None && !drawMarginFrame) {
  467. // Ensures drawn the border lines.
  468. drawMarginFrame = true;
  469. }
  470. borderStyle = value;
  471. OnBorderChanged ();
  472. }
  473. }
  474. /// <summary>
  475. /// Gets or sets if a margin frame is drawn around the <see cref="Child"/> regardless the <see cref="BorderStyle"/>
  476. /// </summary>
  477. [JsonInclude]
  478. public bool DrawMarginFrame {
  479. get => drawMarginFrame;
  480. set {
  481. if (borderStyle != BorderStyle.None
  482. && (!value || !drawMarginFrame)) {
  483. // Ensures drawn the border lines.
  484. drawMarginFrame = true;
  485. } else {
  486. drawMarginFrame = value;
  487. }
  488. OnBorderChanged ();
  489. }
  490. }
  491. /// <summary>
  492. /// Gets or sets the relative <see cref="Thickness"/> of a <see cref="Border"/>.
  493. /// </summary>
  494. [JsonInclude]
  495. public Thickness BorderThickness {
  496. get => borderThickness;
  497. set {
  498. borderThickness = value;
  499. OnBorderChanged ();
  500. }
  501. }
  502. /// <summary>
  503. /// Gets or sets the <see cref="Color"/> that draws the outer border color.
  504. /// </summary>
  505. [JsonInclude, JsonConverter (typeof (Configuration.ColorJsonConverter))]
  506. public Color BorderBrush {
  507. get => borderBrush;
  508. set {
  509. borderBrush = value;
  510. OnBorderChanged ();
  511. }
  512. }
  513. /// <summary>
  514. /// Gets or sets the <see cref="Color"/> that fills the area between the bounds of a <see cref="Border"/>.
  515. /// </summary>
  516. [JsonInclude, JsonConverter (typeof (Configuration.ColorJsonConverter))]
  517. public Color Background {
  518. get => background;
  519. set {
  520. background = value;
  521. OnBorderChanged ();
  522. }
  523. }
  524. /// <summary>
  525. /// Gets or sets a <see cref="Thickness"/> value that describes the amount of space between a
  526. /// <see cref="Border"/> and its child element.
  527. /// </summary>
  528. [JsonInclude]
  529. public Thickness Padding {
  530. get => padding;
  531. set {
  532. padding = value;
  533. OnBorderChanged ();
  534. }
  535. }
  536. ///// <summary>
  537. ///// Gets the rendered width of this element.
  538. ///// </summary>
  539. //[JsonIgnore]
  540. //public int ActualWidth {
  541. // get {
  542. // var driver = Application.Driver;
  543. // if (Parent?.Border == null) {
  544. // return Math.Min (Child?.Frame.Width + (2 * marginFrame) + Padding.Right
  545. // + BorderThickness.Right + Padding.Left + BorderThickness.Left ?? 0, driver.Cols);
  546. // }
  547. // return Math.Min (Parent.Frame.Width, driver.Cols);
  548. // }
  549. //}
  550. ///// <summary>
  551. ///// Gets the rendered height of this element.
  552. ///// </summary>
  553. //[JsonIgnore]
  554. //public int ActualHeight {
  555. // get {
  556. // var driver = Application.Driver;
  557. // if (Parent?.Border == null) {
  558. // return Math.Min (Child?.Frame.Height + (2 * marginFrame) + Padding.Bottom
  559. // + BorderThickness.Bottom + Padding.Top + BorderThickness.Top ?? 0, driver.Rows);
  560. // }
  561. // return Math.Min (Parent.Frame.Height, driver.Rows);
  562. // }
  563. //}
  564. ///// <summary>
  565. ///// Gets or sets the single child element of a <see cref="View"/>.
  566. ///// </summary>
  567. //[JsonIgnore]
  568. //public View Child { get; set; }
  569. ///// <summary>
  570. ///// Gets the parent <see cref="Child"/> parent if any.
  571. ///// </summary>
  572. //[JsonIgnore]
  573. //public View Parent { get => Child?.SuperView; }
  574. ///// <summary>
  575. ///// Gets or private sets by the <see cref="ToplevelContainer"/>
  576. ///// </summary>
  577. //[JsonIgnore]
  578. //public ToplevelContainer ChildContainer { get; private set; }
  579. /// <summary>
  580. /// Gets or sets the 3D effect around the <see cref="Border"/>.
  581. /// </summary>
  582. [JsonInclude]
  583. public bool Effect3D {
  584. get => effect3D;
  585. set {
  586. effect3D = value;
  587. OnBorderChanged ();
  588. }
  589. }
  590. /// <summary>
  591. /// Get or sets the offset start position for the <see cref="Effect3D"/>
  592. /// </summary>
  593. [JsonInclude]
  594. public Point Effect3DOffset {
  595. get => effect3DOffset;
  596. set {
  597. effect3DOffset = value;
  598. OnBorderChanged ();
  599. }
  600. }
  601. /// <summary>
  602. /// Gets or sets the color for the <see cref="Border"/>
  603. /// </summary>
  604. [JsonInclude, JsonConverter (typeof (Configuration.AttributeJsonConverter))]
  605. public Attribute? Effect3DBrush {
  606. get {
  607. if (effect3DBrush == null && effect3D) {
  608. return effect3DBrush = new Attribute (Color.Gray, Color.DarkGray);
  609. } else {
  610. return effect3DBrush;
  611. }
  612. }
  613. set {
  614. effect3DBrush = value;
  615. OnBorderChanged ();
  616. }
  617. }
  618. ///// <summary>
  619. ///// The title to be displayed for this view.
  620. ///// </summary>
  621. //[JsonIgnore]
  622. //public ustring Title {
  623. // get => title;
  624. // set {
  625. // title = value;
  626. // OnBorderChanged ();
  627. // }
  628. //}
  629. ///// <summary>
  630. ///// Calculate the sum of the <see cref="Padding"/> and the <see cref="BorderThickness"/>
  631. ///// </summary>
  632. ///// <returns>The total of the <see cref="Border"/> <see cref="Thickness"/></returns>
  633. //public Thickness GetSumThickness ()
  634. //{
  635. // return new Thickness () {
  636. // Left = Padding.Left + BorderThickness.Left,
  637. // Top = Padding.Top + BorderThickness.Top,
  638. // Right = Padding.Right + BorderThickness.Right,
  639. // Bottom = Padding.Bottom + BorderThickness.Bottom
  640. // };
  641. //}
  642. ///// <summary>
  643. ///// Drawn the <see cref="BorderThickness"/> more the <see cref="Padding"/>
  644. ///// more the <see cref="Border.BorderStyle"/> and the <see cref="Effect3D"/>.
  645. ///// </summary>
  646. ///// <param name="view">The view to draw.</param>
  647. ///// <param name="fill">If it will clear or not the content area.</param>
  648. //public void DrawContent (View view = null, bool fill = true)
  649. //{
  650. // if (Child == null) {
  651. // Child = view;
  652. // }
  653. // if (Parent?.Border != null) {
  654. // DrawParentBorder (Parent.ViewToScreen (Parent.Bounds), fill);
  655. // } else {
  656. // DrawChildBorder (Child.ViewToScreen (Child.Bounds), fill);
  657. // }
  658. //}
  659. ///// <summary>
  660. ///// Same as <see cref="DrawContent"/> but drawing full frames for all borders.
  661. ///// </summary>
  662. //public void DrawFullContent ()
  663. //{
  664. // var borderThickness = BorderThickness;
  665. // var padding = Padding;
  666. // var marginFrame = DrawMarginFrame ? 1 : 0;
  667. // var driver = Application.Driver;
  668. // Rect scrRect;
  669. // if (Parent?.Border != null) {
  670. // scrRect = Parent.ViewToScreen (Parent.Bounds);
  671. // } else {
  672. // scrRect = Child.ViewToScreen (Child.Bounds);
  673. // }
  674. // Rect borderRect;
  675. // if (Parent?.Border != null) {
  676. // borderRect = scrRect;
  677. // } else {
  678. // borderRect = new Rect () {
  679. // X = scrRect.X - marginFrame - padding.Left - borderThickness.Left,
  680. // Y = scrRect.Y - marginFrame - padding.Top - borderThickness.Top,
  681. // Width = ActualWidth,
  682. // Height = ActualHeight
  683. // };
  684. // }
  685. // var savedAttribute = driver.GetAttribute ();
  686. // // Draw 3D effects
  687. // if (Effect3D) {
  688. // driver.SetAttribute ((Attribute)Effect3DBrush);
  689. // var effectBorder = new Rect () {
  690. // X = borderRect.X + Effect3DOffset.X,
  691. // Y = borderRect.Y + Effect3DOffset.Y,
  692. // Width = ActualWidth,
  693. // Height = ActualHeight
  694. // };
  695. // //Child.Clear (effectBorder);
  696. // for (int r = effectBorder.Y; r < Math.Min (effectBorder.Bottom, driver.Rows); r++) {
  697. // for (int c = effectBorder.X; c < Math.Min (effectBorder.Right, driver.Cols); c++) {
  698. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  699. // }
  700. // }
  701. // }
  702. // // Draw border thickness
  703. // driver.SetAttribute (new Attribute (BorderBrush));
  704. // Child.Clear (borderRect);
  705. // borderRect = new Rect () {
  706. // X = borderRect.X + borderThickness.Left,
  707. // Y = borderRect.Y + borderThickness.Top,
  708. // Width = Math.Max (borderRect.Width - borderThickness.Right - borderThickness.Left, 0),
  709. // Height = Math.Max (borderRect.Height - borderThickness.Bottom - borderThickness.Top, 0)
  710. // };
  711. // if (borderRect != scrRect) {
  712. // // Draw padding
  713. // driver.SetAttribute (new Attribute (Background));
  714. // Child.Clear (borderRect);
  715. // }
  716. // driver.SetAttribute (savedAttribute);
  717. // // Draw margin frame
  718. // if (DrawMarginFrame) {
  719. // if (Parent?.Border != null) {
  720. // var sumPadding = GetSumThickness ();
  721. // borderRect = new Rect () {
  722. // X = scrRect.X + sumPadding.Left,
  723. // Y = scrRect.Y + sumPadding.Top,
  724. // Width = Math.Max (scrRect.Width - sumPadding.Right - sumPadding.Left, 0),
  725. // Height = Math.Max (scrRect.Height - sumPadding.Bottom - sumPadding.Top, 0)
  726. // };
  727. // } else {
  728. // borderRect = new Rect () {
  729. // X = borderRect.X + padding.Left,
  730. // Y = borderRect.Y + padding.Top,
  731. // Width = Math.Max (borderRect.Width - padding.Right - padding.Left, 0),
  732. // Height = Math.Max (borderRect.Height - padding.Bottom - padding.Top, 0)
  733. // };
  734. // }
  735. // if (borderRect.Width > 0 && borderRect.Height > 0) {
  736. // driver.DrawWindowFrame (borderRect, 1, 1, 1, 1, BorderStyle != BorderStyle.None, fill: true, this);
  737. // }
  738. // }
  739. //}
  740. //private void DrawChildBorder (Rect frame, bool fill = true)
  741. //{
  742. // var drawMarginFrame = DrawMarginFrame ? 1 : 0;
  743. // var sumThickness = GetSumThickness ();
  744. // var padding = Padding;
  745. // var effect3DOffset = Effect3DOffset;
  746. // var driver = Application.Driver;
  747. // var savedAttribute = driver.GetAttribute ();
  748. // driver.SetAttribute (new Attribute (BorderBrush));
  749. // // Draw the upper BorderThickness
  750. // for (int r = frame.Y - drawMarginFrame - sumThickness.Top;
  751. // r < frame.Y - drawMarginFrame - padding.Top; r++) {
  752. // for (int c = frame.X - drawMarginFrame - sumThickness.Left;
  753. // c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
  754. // AddRuneAt (driver, c, r, ' ');
  755. // }
  756. // }
  757. // // Draw the left BorderThickness
  758. // for (int r = frame.Y - drawMarginFrame - padding.Top;
  759. // r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
  760. // for (int c = frame.X - drawMarginFrame - sumThickness.Left;
  761. // c < frame.X - drawMarginFrame - padding.Left; c++) {
  762. // AddRuneAt (driver, c, r, ' ');
  763. // }
  764. // }
  765. // // Draw the right BorderThickness
  766. // for (int r = frame.Y - drawMarginFrame - padding.Top;
  767. // r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
  768. // for (int c = frame.Right + drawMarginFrame + padding.Right;
  769. // c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
  770. // AddRuneAt (driver, c, r, ' ');
  771. // }
  772. // }
  773. // // Draw the lower BorderThickness
  774. // for (int r = frame.Bottom + drawMarginFrame + padding.Bottom;
  775. // r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom, driver.Rows); r++) {
  776. // for (int c = frame.X - drawMarginFrame - sumThickness.Left;
  777. // c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
  778. // AddRuneAt (driver, c, r, ' ');
  779. // }
  780. // }
  781. // driver.SetAttribute (new Attribute (Background));
  782. // // Draw the upper Padding
  783. // for (int r = frame.Y - drawMarginFrame - padding.Top;
  784. // r < frame.Y - drawMarginFrame; r++) {
  785. // for (int c = frame.X - drawMarginFrame - padding.Left;
  786. // c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
  787. // AddRuneAt (driver, c, r, ' ');
  788. // }
  789. // }
  790. // // Draw the left Padding
  791. // for (int r = frame.Y - drawMarginFrame;
  792. // r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
  793. // for (int c = frame.X - drawMarginFrame - padding.Left;
  794. // c < frame.X - drawMarginFrame; c++) {
  795. // AddRuneAt (driver, c, r, ' ');
  796. // }
  797. // }
  798. // // Draw the right Padding
  799. // for (int r = frame.Y - drawMarginFrame;
  800. // r < Math.Min (frame.Bottom + drawMarginFrame, driver.Rows); r++) {
  801. // for (int c = frame.Right + drawMarginFrame;
  802. // c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
  803. // AddRuneAt (driver, c, r, ' ');
  804. // }
  805. // }
  806. // // Draw the lower Padding
  807. // for (int r = frame.Bottom + drawMarginFrame;
  808. // r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
  809. // for (int c = frame.X - drawMarginFrame - padding.Left;
  810. // c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
  811. // AddRuneAt (driver, c, r, ' ');
  812. // }
  813. // }
  814. // driver.SetAttribute (savedAttribute);
  815. // // Draw the MarginFrame
  816. // if (DrawMarginFrame) {
  817. // var rect = new Rect () {
  818. // X = frame.X - drawMarginFrame,
  819. // Y = frame.Y - drawMarginFrame,
  820. // Width = frame.Width + (2 * drawMarginFrame),
  821. // Height = frame.Height + (2 * drawMarginFrame)
  822. // };
  823. // if (rect.Width > 0 && rect.Height > 0) {
  824. // driver.DrawWindowFrame (rect, 1, 1, 1, 1, BorderStyle != BorderStyle.None, fill, this);
  825. // DrawTitle (Child);
  826. // }
  827. // //var rect = Child.ViewToScreen (new Rect (-1, -1, Child.Frame.Width + 2, Child.Frame.Height + 2));
  828. // //if (rect.Width > 0 && rect.Height > 0) {
  829. // // var lc = new LineCanvas ();
  830. // // lc.AddLine (rect.Location, rect.Width-1, Orientation.Horizontal, BorderStyle);
  831. // // lc.AddLine (rect.Location, rect.Height-1, Orientation.Vertical, BorderStyle);
  832. // // lc.AddLine (new Point (rect.X, rect.Y + rect.Height-1), rect.Width, Orientation.Horizontal, BorderStyle);
  833. // // lc.AddLine (new Point (rect.X + rect.Width-1, rect.Y), rect.Height, Orientation.Vertical, BorderStyle);
  834. // // //driver.SetAttribute (new Attribute(Color.Red, Color.BrightYellow));
  835. // // foreach (var p in lc.GenerateImage (rect)) {
  836. // // AddRuneAt (driver, p.Key.X, p.Key.Y, p.Value);
  837. // // }
  838. // // DrawTitle (Child);
  839. // //}
  840. // }
  841. // if (Effect3D) {
  842. // driver.SetAttribute ((Attribute)Effect3DBrush);
  843. // // Draw the upper Effect3D
  844. // for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
  845. // r >= 0 && r < frame.Y - drawMarginFrame - sumThickness.Top; r++) {
  846. // for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
  847. // c >= 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) {
  848. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  849. // }
  850. // }
  851. // // Draw the left Effect3D
  852. // for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
  853. // r >= 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) {
  854. // for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
  855. // c >= 0 && c < frame.X - drawMarginFrame - sumThickness.Left; c++) {
  856. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  857. // }
  858. // }
  859. // // Draw the right Effect3D
  860. // for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
  861. // r >= 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) {
  862. // for (int c = frame.Right + drawMarginFrame + sumThickness.Right;
  863. // c >= 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) {
  864. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  865. // }
  866. // }
  867. // // Draw the lower Effect3D
  868. // for (int r = frame.Bottom + drawMarginFrame + sumThickness.Bottom;
  869. // r >= 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) {
  870. // for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
  871. // c >= 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) {
  872. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  873. // }
  874. // }
  875. // }
  876. // driver.SetAttribute (savedAttribute);
  877. //}
  878. //private void DrawParentBorder (Rect frame, bool fill = true)
  879. //{
  880. // var sumThickness = GetSumThickness ();
  881. // var borderThickness = BorderThickness;
  882. // var effect3DOffset = Effect3DOffset;
  883. // var driver = Application.Driver;
  884. // var savedAttribute = driver.GetAttribute ();
  885. // driver.SetAttribute (new Attribute (BorderBrush));
  886. // // Draw the upper BorderThickness
  887. // for (int r = frame.Y;
  888. // r < Math.Min (frame.Y + borderThickness.Top, frame.Bottom); r++) {
  889. // for (int c = frame.X;
  890. // c < Math.Min (frame.Right, driver.Cols); c++) {
  891. // AddRuneAt (driver, c, r, ' ');
  892. // }
  893. // }
  894. // // Draw the left BorderThickness
  895. // for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
  896. // r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
  897. // for (int c = frame.X;
  898. // c < Math.Min (frame.X + borderThickness.Left, frame.Right); c++) {
  899. // AddRuneAt (driver, c, r, ' ');
  900. // }
  901. // }
  902. // // Draw the right BorderThickness
  903. // for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
  904. // r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
  905. // for (int c = Math.Max (frame.Right - borderThickness.Right, frame.X);
  906. // c < Math.Min (frame.Right, driver.Cols); c++) {
  907. // AddRuneAt (driver, c, r, ' ');
  908. // }
  909. // }
  910. // // Draw the lower BorderThickness
  911. // for (int r = Math.Max (frame.Bottom - borderThickness.Bottom, frame.Y);
  912. // r < Math.Min (frame.Bottom, driver.Rows); r++) {
  913. // for (int c = frame.X;
  914. // c < Math.Min (frame.Right, driver.Cols); c++) {
  915. // AddRuneAt (driver, c, r, ' ');
  916. // }
  917. // }
  918. // driver.SetAttribute (new Attribute (Background));
  919. // // Draw the upper Padding
  920. // for (int r = frame.Y + borderThickness.Top;
  921. // r < Math.Min (frame.Y + sumThickness.Top, frame.Bottom - borderThickness.Bottom); r++) {
  922. // for (int c = frame.X + borderThickness.Left;
  923. // c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
  924. // AddRuneAt (driver, c, r, ' ');
  925. // }
  926. // }
  927. // // Draw the left Padding
  928. // for (int r = frame.Y + sumThickness.Top;
  929. // r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
  930. // for (int c = frame.X + borderThickness.Left;
  931. // c < Math.Min (frame.X + sumThickness.Left, frame.Right - borderThickness.Right); c++) {
  932. // AddRuneAt (driver, c, r, ' ');
  933. // }
  934. // }
  935. // // Draw the right Padding
  936. // for (int r = frame.Y + sumThickness.Top;
  937. // r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
  938. // for (int c = Math.Max (frame.Right - sumThickness.Right, frame.X + sumThickness.Left);
  939. // c < Math.Max (frame.Right - borderThickness.Right, frame.X + sumThickness.Left); c++) {
  940. // AddRuneAt (driver, c, r, ' ');
  941. // }
  942. // }
  943. // // Draw the lower Padding
  944. // for (int r = Math.Max (frame.Bottom - sumThickness.Bottom, frame.Y + borderThickness.Top);
  945. // r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
  946. // for (int c = frame.X + borderThickness.Left;
  947. // c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
  948. // AddRuneAt (driver, c, r, ' ');
  949. // }
  950. // }
  951. // driver.SetAttribute (savedAttribute);
  952. // // Draw the MarginFrame
  953. // if (DrawMarginFrame) {
  954. // var rect = new Rect () {
  955. // X = frame.X + sumThickness.Left,
  956. // Y = frame.Y + sumThickness.Top,
  957. // Width = Math.Max (frame.Width - sumThickness.Right - sumThickness.Left, 0),
  958. // Height = Math.Max (frame.Height - sumThickness.Bottom - sumThickness.Top, 0)
  959. // };
  960. // if (rect.Width > 0 && rect.Height > 0) {
  961. // driver.DrawWindowFrame (rect, 1, 1, 1, 1, BorderStyle != BorderStyle.None, fill, this);
  962. // DrawTitle (Parent);
  963. // }
  964. // }
  965. // if (Effect3D) {
  966. // driver.SetAttribute ((Attribute)Effect3DBrush);
  967. // // Draw the upper Effect3D
  968. // for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
  969. // r < frame.Y; r++) {
  970. // for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
  971. // c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
  972. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  973. // }
  974. // }
  975. // // Draw the left Effect3D
  976. // for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
  977. // r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
  978. // for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
  979. // c < frame.X; c++) {
  980. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  981. // }
  982. // }
  983. // // Draw the right Effect3D
  984. // for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
  985. // r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
  986. // for (int c = frame.Right;
  987. // c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
  988. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  989. // }
  990. // }
  991. // // Draw the lower Effect3D
  992. // for (int r = frame.Bottom;
  993. // r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
  994. // for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
  995. // c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
  996. // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
  997. // }
  998. // }
  999. // }
  1000. // driver.SetAttribute (savedAttribute);
  1001. //}
  1002. //private void AddRuneAt (ConsoleDriver driver, int col, int row, Rune ch)
  1003. //{
  1004. // if (col < driver.Cols && row < driver.Rows && col > 0 && driver.Contents [row, col, 2] == 0
  1005. // && Rune.ColumnWidth ((char)driver.Contents [row, col - 1, 0]) > 1) {
  1006. // driver.Contents [row, col, 1] = driver.GetAttribute ();
  1007. // return;
  1008. // }
  1009. // driver.Move (col, row);
  1010. // driver.AddRune (ch);
  1011. //}
  1012. ///// <summary>
  1013. ///// Draws the view <see cref="Title"/> to the screen.
  1014. ///// </summary>
  1015. ///// <param name="view">The view.</param>
  1016. //public void DrawTitle (View view)
  1017. //{
  1018. // var driver = Application.Driver;
  1019. // if (DrawMarginFrame) {
  1020. // driver.SetAttribute (Child.GetNormalColor ());
  1021. // if (Child.HasFocus)
  1022. // driver.SetAttribute (Child.ColorScheme.HotNormal);
  1023. // var padding = view.Border.GetSumThickness ();
  1024. // Rect scrRect;
  1025. // if (view == Child) {
  1026. // scrRect = view.ViewToScreen (new Rect (0, 0, view.Frame.Width + 2, view.Frame.Height + 2));
  1027. // scrRect = new Rect (scrRect.X - 1, scrRect.Y - 1, scrRect.Width, scrRect.Height);
  1028. // driver.DrawWindowTitle (scrRect, Title, 0, 0, 0, 0);
  1029. // } else {
  1030. // scrRect = view.ViewToScreen (new Rect (0, 0, view.Frame.Width, view.Frame.Height));
  1031. // driver.DrawWindowTitle (scrRect, Title,
  1032. // padding.Left, padding.Top, padding.Right, padding.Bottom);
  1033. // }
  1034. // }
  1035. // driver.SetAttribute (Child.GetNormalColor ());
  1036. //}
  1037. ///// <summary>
  1038. ///// Draws the <see cref="View.Text"/> to the screen.
  1039. ///// </summary>
  1040. ///// <param name="view">The view.</param>
  1041. ///// <param name="rect">The frame.</param>
  1042. //public void DrawTitle (View view, Rect rect)
  1043. //{
  1044. // var driver = Application.Driver;
  1045. // if (DrawMarginFrame) {
  1046. // driver.SetAttribute (view.GetNormalColor ());
  1047. // if (view.HasFocus) {
  1048. // driver.SetAttribute (view.ColorScheme.HotNormal);
  1049. // }
  1050. // var padding = Parent.Border.GetSumThickness ();
  1051. // var scrRect = Parent.ViewToScreen (new Rect (0, 0, rect.Width, rect.Height));
  1052. // driver.DrawWindowTitle (scrRect, view.Text,
  1053. // padding.Left, padding.Top, padding.Right, padding.Bottom);
  1054. // }
  1055. // driver.SetAttribute (view.GetNormalColor ());
  1056. //}
  1057. /// <summary>
  1058. /// Invoke the <see cref="BorderChanged"/> event.
  1059. /// </summary>
  1060. public virtual void OnBorderChanged ()
  1061. {
  1062. BorderChanged?.Invoke (this);
  1063. }
  1064. }
  1065. }