DimTests.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Threading;
  8. using Terminal.Gui;
  9. using Xunit;
  10. using Xunit.Abstractions;
  11. // Alias Console to MockConsole so we don't accidentally use Console
  12. using Console = Terminal.Gui.FakeConsole;
  13. namespace Terminal.Gui.ViewTests {
  14. public class LayoutTests_DimTests {
  15. readonly ITestOutputHelper output;
  16. public LayoutTests_DimTests (ITestOutputHelper output)
  17. {
  18. this.output = output;
  19. Console.OutputEncoding = System.Text.Encoding.Default;
  20. // Change current culture
  21. var culture = CultureInfo.CreateSpecificCulture ("en-US");
  22. Thread.CurrentThread.CurrentCulture = culture;
  23. Thread.CurrentThread.CurrentUICulture = culture;
  24. }
  25. [Fact]
  26. public void New_Works ()
  27. {
  28. var dim = new Dim ();
  29. Assert.Equal ("Terminal.Gui.Dim", dim.ToString ());
  30. }
  31. [Fact]
  32. public void Sized_SetsValue ()
  33. {
  34. var dim = Dim.Sized (0);
  35. Assert.Equal ("Absolute(0)", dim.ToString ());
  36. int testVal = 5;
  37. dim = Dim.Sized (testVal);
  38. Assert.Equal ($"Absolute({testVal})", dim.ToString ());
  39. testVal = -1;
  40. dim = Dim.Sized (testVal);
  41. Assert.Equal ($"Absolute({testVal})", dim.ToString ());
  42. }
  43. [Fact]
  44. public void Sized_Equals ()
  45. {
  46. int n1 = 0;
  47. int n2 = 0;
  48. var dim1 = Dim.Sized (n1);
  49. var dim2 = Dim.Sized (n2);
  50. Assert.Equal (dim1, dim2);
  51. n1 = n2 = 1;
  52. dim1 = Dim.Sized (n1);
  53. dim2 = Dim.Sized (n2);
  54. Assert.Equal (dim1, dim2);
  55. n1 = n2 = -1;
  56. dim1 = Dim.Sized (n1);
  57. dim2 = Dim.Sized (n2);
  58. Assert.Equal (dim1, dim2);
  59. n1 = 0;
  60. n2 = 1;
  61. dim1 = Dim.Sized (n1);
  62. dim2 = Dim.Sized (n2);
  63. Assert.NotEqual (dim1, dim2);
  64. }
  65. [Fact]
  66. public void Width_Set_To_Null_Throws ()
  67. {
  68. var dim = Dim.Width (null);
  69. Assert.Throws<NullReferenceException> (() => dim.ToString ());
  70. }
  71. [Fact, TestRespondersDisposed]
  72. public void SetsValue ()
  73. {
  74. var testVal = Rect.Empty;
  75. var testValView = new View (testVal);
  76. var dim = Dim.Width (testValView);
  77. Assert.Equal ($"View(Width,View()({testVal}))", dim.ToString ());
  78. testValView.Dispose ();
  79. testVal = new Rect (1, 2, 3, 4);
  80. testValView = new View (testVal);
  81. dim = Dim.Width (testValView);
  82. Assert.Equal ($"View(Width,View()({testVal}))", dim.ToString ());
  83. testValView.Dispose ();
  84. }
  85. [Fact, TestRespondersDisposed]
  86. public void Width_Equals ()
  87. {
  88. var testRect1 = Rect.Empty;
  89. var view1 = new View (testRect1);
  90. var testRect2 = Rect.Empty;
  91. var view2 = new View (testRect2);
  92. var dim1 = Dim.Width (view1);
  93. var dim2 = Dim.Width (view1);
  94. // FIXED: Dim.Width should support Equals() and this should change to Equal.
  95. Assert.Equal (dim1, dim2);
  96. dim2 = Dim.Width (view2);
  97. Assert.NotEqual (dim1, dim2);
  98. testRect1 = new Rect (0, 1, 2, 3);
  99. view1 = new View (testRect1);
  100. testRect2 = new Rect (0, 1, 2, 3);
  101. dim1 = Dim.Width (view1);
  102. dim2 = Dim.Width (view1);
  103. // FIXED: Dim.Width should support Equals() and this should change to Equal.
  104. Assert.Equal (dim1, dim2);
  105. testRect1 = new Rect (0, -1, 2, 3);
  106. view1 = new View (testRect1);
  107. testRect2 = new Rect (0, -1, 2, 3);
  108. dim1 = Dim.Width (view1);
  109. dim2 = Dim.Width (view1);
  110. // FIXED: Dim.Width should support Equals() and this should change to Equal.
  111. Assert.Equal (dim1, dim2);
  112. testRect1 = new Rect (0, -1, 2, 3);
  113. view1 = new View (testRect1);
  114. testRect2 = Rect.Empty;
  115. view2 = new View (testRect2);
  116. dim1 = Dim.Width (view1);
  117. dim2 = Dim.Width (view2);
  118. Assert.NotEqual (dim1, dim2);
  119. #if DEBUG_IDISPOSABLE
  120. // HACK: Force clean up of Responders to avoid having to Dispose all the Views created above.
  121. Responder.Instances.Clear ();
  122. Assert.Empty (Responder.Instances);
  123. #endif
  124. }
  125. [Fact]
  126. public void Height_Set_To_Null_Throws ()
  127. {
  128. var dim = Dim.Height (null);
  129. Assert.Throws<NullReferenceException> (() => dim.ToString ());
  130. }
  131. [Fact, TestRespondersDisposed]
  132. public void Height_SetsValue ()
  133. {
  134. var testVal = Rect.Empty;
  135. var testValview = new View (testVal);
  136. var dim = Dim.Height (testValview);
  137. Assert.Equal ($"View(Height,View()({testVal}))", dim.ToString ());
  138. testValview.Dispose ();
  139. testVal = new Rect (1, 2, 3, 4);
  140. testValview = new View (testVal);
  141. dim = Dim.Height (testValview);
  142. Assert.Equal ($"View(Height,View()({testVal}))", dim.ToString ());
  143. testValview.Dispose ();
  144. }
  145. // TODO: Other Dim.Height tests (e.g. Equal?)
  146. [Fact]
  147. public void Fill_SetsValue ()
  148. {
  149. var testMargin = 0;
  150. var dim = Dim.Fill ();
  151. Assert.Equal ($"Fill({testMargin})", dim.ToString ());
  152. testMargin = 0;
  153. dim = Dim.Fill (testMargin);
  154. Assert.Equal ($"Fill({testMargin})", dim.ToString ());
  155. testMargin = 5;
  156. dim = Dim.Fill (testMargin);
  157. Assert.Equal ($"Fill({testMargin})", dim.ToString ());
  158. }
  159. [Fact]
  160. public void Fill_Equal ()
  161. {
  162. var margin1 = 0;
  163. var margin2 = 0;
  164. var dim1 = Dim.Fill (margin1);
  165. var dim2 = Dim.Fill (margin2);
  166. Assert.Equal (dim1, dim2);
  167. }
  168. [Fact]
  169. public void Percent_SetsValue ()
  170. {
  171. float f = 0;
  172. var dim = Dim.Percent (f);
  173. Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
  174. f = 0.5F;
  175. dim = Dim.Percent (f);
  176. Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
  177. f = 100;
  178. dim = Dim.Percent (f);
  179. Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ());
  180. }
  181. [Fact]
  182. public void Percent_Equals ()
  183. {
  184. float n1 = 0;
  185. float n2 = 0;
  186. var dim1 = Dim.Percent (n1);
  187. var dim2 = Dim.Percent (n2);
  188. Assert.Equal (dim1, dim2);
  189. n1 = n2 = 1;
  190. dim1 = Dim.Percent (n1);
  191. dim2 = Dim.Percent (n2);
  192. Assert.Equal (dim1, dim2);
  193. n1 = n2 = 0.5f;
  194. dim1 = Dim.Percent (n1);
  195. dim2 = Dim.Percent (n2);
  196. Assert.Equal (dim1, dim2);
  197. n1 = n2 = 100f;
  198. dim1 = Dim.Percent (n1);
  199. dim2 = Dim.Percent (n2);
  200. Assert.Equal (dim1, dim2);
  201. n1 = n2 = 0.3f;
  202. dim1 = Dim.Percent (n1, true);
  203. dim2 = Dim.Percent (n2, true);
  204. Assert.Equal (dim1, dim2);
  205. n1 = n2 = 0.3f;
  206. dim1 = Dim.Percent (n1);
  207. dim2 = Dim.Percent (n2, true);
  208. Assert.NotEqual (dim1, dim2);
  209. n1 = 0;
  210. n2 = 1;
  211. dim1 = Dim.Percent (n1);
  212. dim2 = Dim.Percent (n2);
  213. Assert.NotEqual (dim1, dim2);
  214. n1 = 0.5f;
  215. n2 = 1.5f;
  216. dim1 = Dim.Percent (n1);
  217. dim2 = Dim.Percent (n2);
  218. Assert.NotEqual (dim1, dim2);
  219. }
  220. [Fact]
  221. public void Percent_Invalid_Throws ()
  222. {
  223. var dim = Dim.Percent (0);
  224. Assert.Throws<ArgumentException> (() => dim = Dim.Percent (-1));
  225. Assert.Throws<ArgumentException> (() => dim = Dim.Percent (101));
  226. Assert.Throws<ArgumentException> (() => dim = Dim.Percent (100.0001F));
  227. Assert.Throws<ArgumentException> (() => dim = Dim.Percent (1000001));
  228. }
  229. [Fact, AutoInitShutdown]
  230. public void ForceValidatePosDim_True_Dim_Validation_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Another_Type_Throws ()
  231. {
  232. var t = Application.Top;
  233. var w = new Window () {
  234. Width = Dim.Fill (0),
  235. Height = Dim.Sized (10)
  236. };
  237. var v = new View ("v") {
  238. Width = Dim.Width (w) - 2,
  239. Height = Dim.Percent (10),
  240. ForceValidatePosDim = true
  241. };
  242. w.Add (v);
  243. t.Add (w);
  244. t.Ready += (s, e) => {
  245. Assert.Equal (2, w.Width = 2);
  246. Assert.Equal (2, w.Height = 2);
  247. Assert.Throws<ArgumentException> (() => v.Width = 2);
  248. Assert.Throws<ArgumentException> (() => v.Height = 2);
  249. v.ForceValidatePosDim = false;
  250. var exception = Record.Exception (() => v.Width = 2);
  251. Assert.Null (exception);
  252. Assert.Equal (2, v.Width);
  253. exception = Record.Exception (() => v.Height = 2);
  254. Assert.Null (exception);
  255. Assert.Equal (2, v.Height);
  256. };
  257. Application.Iteration += () => Application.RequestStop ();
  258. Application.Run ();
  259. }
  260. [Fact, TestRespondersDisposed]
  261. public void Dim_Validation_Do_Not_Throws_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Null ()
  262. {
  263. var t = new View ("top") { Width = 80, Height = 25 };
  264. var w = new Window (new Rect (1, 2, 4, 5)) { Title = "w" };
  265. t.Add (w);
  266. t.LayoutSubviews ();
  267. Assert.Equal (3, w.Width = 3);
  268. Assert.Equal (4, w.Height = 4);
  269. t.Dispose ();
  270. }
  271. [Fact, TestRespondersDisposed]
  272. public void Dim_Validation_Do_Not_Throws_If_NewValue_Is_DimAbsolute_And_OldValue_Is_Another_Type_After_Sets_To_LayoutStyle_Absolute ()
  273. {
  274. var t = new View ("top") { Width = 80, Height = 25 };
  275. var w = new Window () {
  276. Width = Dim.Fill (0),
  277. Height = Dim.Sized (10)
  278. };
  279. var v = new View ("v") {
  280. Width = Dim.Width (w) - 2,
  281. Height = Dim.Percent (10)
  282. };
  283. w.Add (v);
  284. t.Add (w);
  285. t.LayoutSubviews ();
  286. Assert.Equal (2, v.Width = 2);
  287. Assert.Equal (2, v.Height = 2);
  288. v.LayoutStyle = LayoutStyle.Absolute;
  289. t.LayoutSubviews ();
  290. Assert.Equal (2, v.Width = 2);
  291. Assert.Equal (2, v.Height = 2);
  292. t.Dispose ();
  293. }
  294. [Fact, AutoInitShutdown]
  295. public void Only_DimAbsolute_And_DimFactor_As_A_Different_Procedure_For_Assigning_Value_To_Width_Or_Height ()
  296. {
  297. // Testing with the Button because it properly handles the Dim class.
  298. var t = Application.Top;
  299. var w = new Window () {
  300. Width = 100,
  301. Height = 100
  302. };
  303. var f1 = new FrameView ("f1") {
  304. X = 0,
  305. Y = 0,
  306. Width = Dim.Percent (50),
  307. Height = 5
  308. };
  309. var f2 = new FrameView ("f2") {
  310. X = Pos.Right (f1),
  311. Y = 0,
  312. Width = Dim.Fill (),
  313. Height = 5
  314. };
  315. var v1 = new Button ("v1") {
  316. AutoSize = false,
  317. X = Pos.X (f1) + 2,
  318. Y = Pos.Bottom (f1) + 2,
  319. Width = Dim.Width (f1) - 2,
  320. Height = Dim.Fill () - 2,
  321. ForceValidatePosDim = true
  322. };
  323. var v2 = new Button ("v2") {
  324. AutoSize = false,
  325. X = Pos.X (f2) + 2,
  326. Y = Pos.Bottom (f2) + 2,
  327. Width = Dim.Width (f2) - 2,
  328. Height = Dim.Fill () - 2,
  329. ForceValidatePosDim = true
  330. };
  331. var v3 = new Button ("v3") {
  332. AutoSize = false,
  333. Width = Dim.Percent (10),
  334. Height = Dim.Percent (10),
  335. ForceValidatePosDim = true
  336. };
  337. var v4 = new Button ("v4") {
  338. AutoSize = false,
  339. Width = Dim.Sized (50),
  340. Height = Dim.Sized (50),
  341. ForceValidatePosDim = true
  342. };
  343. var v5 = new Button ("v5") {
  344. AutoSize = false,
  345. Width = Dim.Width (v1) - Dim.Width (v3),
  346. Height = Dim.Height (v1) - Dim.Height (v3),
  347. ForceValidatePosDim = true
  348. };
  349. var v6 = new Button ("v6") {
  350. AutoSize = false,
  351. X = Pos.X (f2),
  352. Y = Pos.Bottom (f2) + 2,
  353. Width = Dim.Percent (20, true),
  354. Height = Dim.Percent (20, true),
  355. ForceValidatePosDim = true
  356. };
  357. w.Add (f1, f2, v1, v2, v3, v4, v5, v6);
  358. t.Add (w);
  359. t.Ready += (s, e) => {
  360. Assert.Equal ("Absolute(100)", w.Width.ToString ());
  361. Assert.Equal ("Absolute(100)", w.Height.ToString ());
  362. Assert.Equal (100, w.Frame.Width);
  363. Assert.Equal (100, w.Frame.Height);
  364. Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
  365. Assert.Equal ("Absolute(5)", f1.Height.ToString ());
  366. Assert.Equal (49, f1.Frame.Width); // 50-1=49
  367. Assert.Equal (5, f1.Frame.Height);
  368. Assert.Equal ("Fill(0)", f2.Width.ToString ());
  369. Assert.Equal ("Absolute(5)", f2.Height.ToString ());
  370. Assert.Equal (49, f2.Frame.Width); // 50-1=49
  371. Assert.Equal (5, f2.Frame.Height);
  372. Assert.Equal ("Combine(View(Width,FrameView(f1)((0,0,49,5)))-Absolute(2))", v1.Width.ToString ());
  373. Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ());
  374. Assert.Equal (47, v1.Frame.Width); // 49-2=47
  375. Assert.Equal (89, v1.Frame.Height); // 98-5-2-2=89
  376. Assert.Equal ("Combine(View(Width,FrameView(f2)((49,0,49,5)))-Absolute(2))", v2.Width.ToString ());
  377. Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
  378. Assert.Equal (47, v2.Frame.Width); // 49-2=47
  379. Assert.Equal (89, v2.Frame.Height); // 98-5-2-2=89
  380. Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ());
  381. Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ());
  382. Assert.Equal (9, v3.Frame.Width); // 98*10%=9
  383. Assert.Equal (9, v3.Frame.Height); // 98*10%=9
  384. Assert.Equal ("Absolute(50)", v4.Width.ToString ());
  385. Assert.Equal ("Absolute(50)", v4.Height.ToString ());
  386. Assert.Equal (50, v4.Frame.Width);
  387. Assert.Equal (50, v4.Frame.Height);
  388. Assert.Equal ("Combine(View(Width,Button(v1)((2,7,47,89)))-View(Width,Button(v3)((0,0,9,9))))", v5.Width.ToString ());
  389. Assert.Equal ("Combine(View(Height,Button(v1)((2,7,47,89)))-View(Height,Button(v3)((0,0,9,9))))", v5.Height.ToString ());
  390. Assert.Equal (38, v5.Frame.Width); // 47-9=38
  391. Assert.Equal (80, v5.Frame.Height); // 89-9=80
  392. Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ());
  393. Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ());
  394. Assert.Equal (9, v6.Frame.Width); // 47*20%=9
  395. Assert.Equal (18, v6.Frame.Height); // 89*20%=18
  396. w.Width = 200;
  397. Assert.True (t.LayoutNeeded);
  398. w.Height = 200;
  399. t.LayoutSubviews ();
  400. Assert.Equal ("Absolute(200)", w.Width.ToString ());
  401. Assert.Equal ("Absolute(200)", w.Height.ToString ());
  402. Assert.Equal (200, w.Frame.Width);
  403. Assert.Equal (200, w.Frame.Height);
  404. f1.Text = "Frame1";
  405. Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ());
  406. Assert.Equal ("Absolute(5)", f1.Height.ToString ());
  407. Assert.Equal (99, f1.Frame.Width); // 100-1=99
  408. Assert.Equal (5, f1.Frame.Height);
  409. f2.Text = "Frame2";
  410. Assert.Equal ("Fill(0)", f2.Width.ToString ());
  411. Assert.Equal ("Absolute(5)", f2.Height.ToString ());
  412. Assert.Equal (99, f2.Frame.Width); // 100-1=99
  413. Assert.Equal (5, f2.Frame.Height);
  414. v1.Text = "Button1";
  415. Assert.Equal ("Combine(View(Width,FrameView(f1)((0,0,99,5)))-Absolute(2))", v1.Width.ToString ());
  416. Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ());
  417. Assert.Equal (97, v1.Frame.Width); // 99-2=97
  418. Assert.Equal (189, v1.Frame.Height); // 198-2-7=189
  419. v2.Text = "Button2";
  420. Assert.Equal ("Combine(View(Width,FrameView(f2)((99,0,99,5)))-Absolute(2))", v2.Width.ToString ());
  421. Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ());
  422. Assert.Equal (97, v2.Frame.Width); // 99-2=97
  423. Assert.Equal (189, v2.Frame.Height); // 198-2-7=189
  424. v3.Text = "Button3";
  425. Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ());
  426. Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ());
  427. Assert.Equal (19, v3.Frame.Width); // 198*10%=19 * Percent is related to the super-view if it isn't null otherwise the view width
  428. Assert.Equal (19, v3.Frame.Height); // 199*10%=19
  429. v4.Text = "Button4";
  430. v4.AutoSize = false;
  431. Assert.Equal ("Absolute(50)", v4.Width.ToString ());
  432. Assert.Equal ("Absolute(50)", v4.Height.ToString ());
  433. Assert.Equal (50, v4.Frame.Width);
  434. Assert.Equal (50, v4.Frame.Height);
  435. v4.AutoSize = true;
  436. Assert.Equal ("Absolute(11)", v4.Width.ToString ());
  437. Assert.Equal ("Absolute(1)", v4.Height.ToString ());
  438. Assert.Equal (11, v4.Frame.Width); // 11 is the text length and because is Dim.DimAbsolute
  439. Assert.Equal (1, v4.Frame.Height); // 1 because is Dim.DimAbsolute
  440. v5.Text = "Button5";
  441. Assert.Equal ("Combine(View(Width,Button(v1)((2,7,97,189)))-View(Width,Button(v3)((0,0,19,19))))", v5.Width.ToString ());
  442. Assert.Equal ("Combine(View(Height,Button(v1)((2,7,97,189)))-View(Height,Button(v3)((0,0,19,19))))", v5.Height.ToString ());
  443. Assert.Equal (78, v5.Frame.Width); // 97-9=78
  444. Assert.Equal (170, v5.Frame.Height); // 189-19=170
  445. v6.Text = "Button6";
  446. Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ());
  447. Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ());
  448. Assert.Equal (19, v6.Frame.Width); // 99*20%=19
  449. Assert.Equal (38, v6.Frame.Height); // 198-7*20=18
  450. };
  451. Application.Iteration += () => Application.RequestStop ();
  452. Application.Run ();
  453. }
  454. // See #2461
  455. //[Fact]
  456. //public void Dim_Referencing_SuperView_Throws ()
  457. //{
  458. // var super = new View ("super") {
  459. // Width = 10,
  460. // Height = 10
  461. // };
  462. // var view = new View ("view") {
  463. // Width = Dim.Width (super), // this is not allowed
  464. // Height = Dim.Height (super), // this is not allowed
  465. // };
  466. // super.Add (view);
  467. // super.BeginInit ();
  468. // super.EndInit ();
  469. // Assert.Throws<InvalidOperationException> (() => super.LayoutSubviews ());
  470. //}
  471. /// <summary>
  472. /// This is an intentionally obtuse test. See https://github.com/gui-cs/Terminal.Gui/issues/2461
  473. /// </summary>
  474. [Fact, TestRespondersDisposed]
  475. public void DimCombine_ObtuseScenario_Throw_If_SuperView_Refs_SubView ()
  476. {
  477. var t = new View () { Width = 80, Height = 25 };
  478. var w = new Window () {
  479. Width = Dim.Width (t) - 2, // 78
  480. Height = Dim.Height (t) - 2 // 23
  481. };
  482. var f = new FrameView ();
  483. var v1 = new View () {
  484. Width = Dim.Width (w) - 2, // 76
  485. Height = Dim.Height (w) - 2 // 21
  486. };
  487. var v2 = new View () {
  488. Width = Dim.Width (v1) - 2, // 74
  489. Height = Dim.Height (v1) - 2 // 19
  490. };
  491. f.Add (v1, v2);
  492. w.Add (f);
  493. t.Add (w);
  494. // BUGBUG: v2 - f references t here; t is f's super-superview. This is supported!
  495. // BUGBUG: v2 - f references v2 here; v2 is f's subview. This is not supported!
  496. f.Width = Dim.Width (t) - Dim.Width (v2); // 80 - 74 = 6
  497. f.Height = Dim.Height (t) - Dim.Height (v2); // 25 - 19 = 6
  498. Assert.Throws<InvalidOperationException> (t.LayoutSubviews);
  499. Assert.Equal (80, t.Frame.Width);
  500. Assert.Equal (25, t.Frame.Height);
  501. Assert.Equal (78, w.Frame.Width);
  502. Assert.Equal (23, w.Frame.Height);
  503. // BUGBUG: v2 - this no longer works - see above
  504. //Assert.Equal (6, f.Frame.Width);
  505. //Assert.Equal (6, f.Frame.Height);
  506. //Assert.Equal (76, v1.Frame.Width);
  507. //Assert.Equal (21, v1.Frame.Height);
  508. //Assert.Equal (74, v2.Frame.Width);
  509. //Assert.Equal (19, v2.Frame.Height);
  510. t.Dispose ();
  511. }
  512. [Fact, TestRespondersDisposed]
  513. public void DimCombine_ObtuseScenario_Does_Not_Throw_If_Two_SubViews_Refs_The_Same_SuperView ()
  514. {
  515. var t = new View ("top") { Width = 80, Height = 25 };
  516. var w = new Window () {
  517. Width = Dim.Width (t) - 2, // 78
  518. Height = Dim.Height (t) - 2 // 23
  519. };
  520. var f = new FrameView ();
  521. var v1 = new View () {
  522. Width = Dim.Width (w) - 2, // 76
  523. Height = Dim.Height (w) - 2 // 21
  524. };
  525. var v2 = new View () {
  526. Width = Dim.Width (v1) - 2, // 74
  527. Height = Dim.Height (v1) - 2 // 19
  528. };
  529. f.Add (v1, v2);
  530. w.Add (f);
  531. t.Add (w);
  532. f.Width = Dim.Width (t) - Dim.Width (w) + 4; // 80 - 74 = 6
  533. f.Height = Dim.Height (t) - Dim.Height (w) + 4; // 25 - 19 = 6
  534. // BUGBUG: v2 - f references t and w here; t is f's super-superview and w is f's superview. This is supported!
  535. var exception = Record.Exception (t.LayoutSubviews);
  536. Assert.Null (exception);
  537. Assert.Equal (80, t.Frame.Width);
  538. Assert.Equal (25, t.Frame.Height);
  539. Assert.Equal (78, w.Frame.Width);
  540. Assert.Equal (23, w.Frame.Height);
  541. Assert.Equal (6, f.Frame.Width);
  542. Assert.Equal (6, f.Frame.Height);
  543. Assert.Equal (76, v1.Frame.Width);
  544. Assert.Equal (21, v1.Frame.Height);
  545. Assert.Equal (74, v2.Frame.Width);
  546. Assert.Equal (19, v2.Frame.Height);
  547. t.Dispose ();
  548. }
  549. [Fact, TestRespondersDisposed]
  550. public void PosCombine_View_Not_Added_Throws ()
  551. {
  552. var t = new View () { Width = 80, Height = 50 };
  553. // BUGBUG: v2 - super should not reference it's superview (t)
  554. var super = new View () {
  555. Width = Dim.Width (t) - 2,
  556. Height = Dim.Height (t) - 2
  557. };
  558. t.Add (super);
  559. var sub = new View ();
  560. super.Add (sub);
  561. var v1 = new View () {
  562. Width = Dim.Width (super) - 2,
  563. Height = Dim.Height (super) - 2
  564. };
  565. var v2 = new View () {
  566. Width = Dim.Width (v1) - 2,
  567. Height = Dim.Height (v1) - 2
  568. };
  569. sub.Add (v1);
  570. // v2 not added to sub; should cause exception on Layout since it's referenced by sub.
  571. sub.Width = Dim.Fill () - Dim.Width (v2);
  572. sub.Height = Dim.Fill () - Dim.Height (v2);
  573. Assert.Throws<InvalidOperationException> (() => t.LayoutSubviews ());
  574. t.Dispose ();
  575. v2.Dispose ();
  576. }
  577. [Fact, AutoInitShutdown]
  578. public void Dim_Add_Operator ()
  579. {
  580. var top = Application.Top;
  581. var view = new View () { X = 0, Y = 0, Width = 20, Height = 0 };
  582. var field = new TextField () { X = 0, Y = Pos.Bottom (view), Width = 20 };
  583. var count = 0;
  584. field.KeyDown += (s, k) => {
  585. if (k.KeyEvent.Key == Key.Enter) {
  586. field.Text = $"Label {count}";
  587. var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 20 };
  588. view.Add (label);
  589. Assert.Equal ($"Label {count}", label.Text);
  590. Assert.Equal ($"Absolute({count})", label.Y.ToString ());
  591. Assert.Equal ($"Absolute({count})", view.Height.ToString ());
  592. view.Height += 1;
  593. count++;
  594. Assert.Equal ($"Absolute({count})", view.Height.ToString ());
  595. }
  596. };
  597. Application.Iteration += () => {
  598. while (count < 20) field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  599. Application.RequestStop ();
  600. };
  601. var win = new Window ();
  602. win.Add (view);
  603. win.Add (field);
  604. top.Add (win);
  605. Application.Run (top);
  606. Assert.Equal (20, count);
  607. }
  608. private string [] expecteds = new string [21] {
  609. @"
  610. ┌────────────────────┐
  611. │View with long text │
  612. │ │
  613. └────────────────────┘",
  614. @"
  615. ┌────────────────────┐
  616. │View with long text │
  617. │Label 0 │
  618. │Label 0 │
  619. └────────────────────┘",
  620. @"
  621. ┌────────────────────┐
  622. │View with long text │
  623. │Label 0 │
  624. │Label 1 │
  625. │Label 1 │
  626. └────────────────────┘",
  627. @"
  628. ┌────────────────────┐
  629. │View with long text │
  630. │Label 0 │
  631. │Label 1 │
  632. │Label 2 │
  633. │Label 2 │
  634. └────────────────────┘",
  635. @"
  636. ┌────────────────────┐
  637. │View with long text │
  638. │Label 0 │
  639. │Label 1 │
  640. │Label 2 │
  641. │Label 3 │
  642. │Label 3 │
  643. └────────────────────┘",
  644. @"
  645. ┌────────────────────┐
  646. │View with long text │
  647. │Label 0 │
  648. │Label 1 │
  649. │Label 2 │
  650. │Label 3 │
  651. │Label 4 │
  652. │Label 4 │
  653. └────────────────────┘",
  654. @"
  655. ┌────────────────────┐
  656. │View with long text │
  657. │Label 0 │
  658. │Label 1 │
  659. │Label 2 │
  660. │Label 3 │
  661. │Label 4 │
  662. │Label 5 │
  663. │Label 5 │
  664. └────────────────────┘",
  665. @"
  666. ┌────────────────────┐
  667. │View with long text │
  668. │Label 0 │
  669. │Label 1 │
  670. │Label 2 │
  671. │Label 3 │
  672. │Label 4 │
  673. │Label 5 │
  674. │Label 6 │
  675. │Label 6 │
  676. └────────────────────┘",
  677. @"
  678. ┌────────────────────┐
  679. │View with long text │
  680. │Label 0 │
  681. │Label 1 │
  682. │Label 2 │
  683. │Label 3 │
  684. │Label 4 │
  685. │Label 5 │
  686. │Label 6 │
  687. │Label 7 │
  688. │Label 7 │
  689. └────────────────────┘",
  690. @"
  691. ┌────────────────────┐
  692. │View with long text │
  693. │Label 0 │
  694. │Label 1 │
  695. │Label 2 │
  696. │Label 3 │
  697. │Label 4 │
  698. │Label 5 │
  699. │Label 6 │
  700. │Label 7 │
  701. │Label 8 │
  702. │Label 8 │
  703. └────────────────────┘",
  704. @"
  705. ┌────────────────────┐
  706. │View with long text │
  707. │Label 0 │
  708. │Label 1 │
  709. │Label 2 │
  710. │Label 3 │
  711. │Label 4 │
  712. │Label 5 │
  713. │Label 6 │
  714. │Label 7 │
  715. │Label 8 │
  716. │Label 9 │
  717. │Label 9 │
  718. └────────────────────┘",
  719. @"
  720. ┌────────────────────┐
  721. │View with long text │
  722. │Label 0 │
  723. │Label 1 │
  724. │Label 2 │
  725. │Label 3 │
  726. │Label 4 │
  727. │Label 5 │
  728. │Label 6 │
  729. │Label 7 │
  730. │Label 8 │
  731. │Label 9 │
  732. │Label 10 │
  733. │Label 10 │
  734. └────────────────────┘",
  735. @"
  736. ┌────────────────────┐
  737. │View with long text │
  738. │Label 0 │
  739. │Label 1 │
  740. │Label 2 │
  741. │Label 3 │
  742. │Label 4 │
  743. │Label 5 │
  744. │Label 6 │
  745. │Label 7 │
  746. │Label 8 │
  747. │Label 9 │
  748. │Label 10 │
  749. │Label 11 │
  750. │Label 11 │
  751. └────────────────────┘",
  752. @"
  753. ┌────────────────────┐
  754. │View with long text │
  755. │Label 0 │
  756. │Label 1 │
  757. │Label 2 │
  758. │Label 3 │
  759. │Label 4 │
  760. │Label 5 │
  761. │Label 6 │
  762. │Label 7 │
  763. │Label 8 │
  764. │Label 9 │
  765. │Label 10 │
  766. │Label 11 │
  767. │Label 12 │
  768. │Label 12 │
  769. └────────────────────┘",
  770. @"
  771. ┌────────────────────┐
  772. │View with long text │
  773. │Label 0 │
  774. │Label 1 │
  775. │Label 2 │
  776. │Label 3 │
  777. │Label 4 │
  778. │Label 5 │
  779. │Label 6 │
  780. │Label 7 │
  781. │Label 8 │
  782. │Label 9 │
  783. │Label 10 │
  784. │Label 11 │
  785. │Label 12 │
  786. │Label 13 │
  787. │Label 13 │
  788. └────────────────────┘",
  789. @"
  790. ┌────────────────────┐
  791. │View with long text │
  792. │Label 0 │
  793. │Label 1 │
  794. │Label 2 │
  795. │Label 3 │
  796. │Label 4 │
  797. │Label 5 │
  798. │Label 6 │
  799. │Label 7 │
  800. │Label 8 │
  801. │Label 9 │
  802. │Label 10 │
  803. │Label 11 │
  804. │Label 12 │
  805. │Label 13 │
  806. │Label 14 │
  807. │Label 14 │
  808. └────────────────────┘",
  809. @"
  810. ┌────────────────────┐
  811. │View with long text │
  812. │Label 0 │
  813. │Label 1 │
  814. │Label 2 │
  815. │Label 3 │
  816. │Label 4 │
  817. │Label 5 │
  818. │Label 6 │
  819. │Label 7 │
  820. │Label 8 │
  821. │Label 9 │
  822. │Label 10 │
  823. │Label 11 │
  824. │Label 12 │
  825. │Label 13 │
  826. │Label 14 │
  827. │Label 15 │
  828. │Label 15 │
  829. └────────────────────┘",
  830. @"
  831. ┌────────────────────┐
  832. │View with long text │
  833. │Label 0 │
  834. │Label 1 │
  835. │Label 2 │
  836. │Label 3 │
  837. │Label 4 │
  838. │Label 5 │
  839. │Label 6 │
  840. │Label 7 │
  841. │Label 8 │
  842. │Label 9 │
  843. │Label 10 │
  844. │Label 11 │
  845. │Label 12 │
  846. │Label 13 │
  847. │Label 14 │
  848. │Label 15 │
  849. │Label 16 │
  850. │Label 16 │
  851. └────────────────────┘",
  852. @"
  853. ┌────────────────────┐
  854. │View with long text │
  855. │Label 0 │
  856. │Label 1 │
  857. │Label 2 │
  858. │Label 3 │
  859. │Label 4 │
  860. │Label 5 │
  861. │Label 6 │
  862. │Label 7 │
  863. │Label 8 │
  864. │Label 9 │
  865. │Label 10 │
  866. │Label 11 │
  867. │Label 12 │
  868. │Label 13 │
  869. │Label 14 │
  870. │Label 15 │
  871. │Label 16 │
  872. │Label 17 │
  873. │Label 17 │
  874. └────────────────────┘",
  875. @"
  876. ┌────────────────────┐
  877. │View with long text │
  878. │Label 0 │
  879. │Label 1 │
  880. │Label 2 │
  881. │Label 3 │
  882. │Label 4 │
  883. │Label 5 │
  884. │Label 6 │
  885. │Label 7 │
  886. │Label 8 │
  887. │Label 9 │
  888. │Label 10 │
  889. │Label 11 │
  890. │Label 12 │
  891. │Label 13 │
  892. │Label 14 │
  893. │Label 15 │
  894. │Label 16 │
  895. │Label 17 │
  896. │Label 18 │
  897. │Label 18 │
  898. └────────────────────┘",
  899. @"
  900. ┌────────────────────┐
  901. │View with long text │
  902. │Label 0 │
  903. │Label 1 │
  904. │Label 2 │
  905. │Label 3 │
  906. │Label 4 │
  907. │Label 5 │
  908. │Label 6 │
  909. │Label 7 │
  910. │Label 8 │
  911. │Label 9 │
  912. │Label 10 │
  913. │Label 11 │
  914. │Label 12 │
  915. │Label 13 │
  916. │Label 14 │
  917. │Label 15 │
  918. │Label 16 │
  919. │Label 17 │
  920. │Label 18 │
  921. │Label 19 │
  922. │Label 19 │
  923. └────────────────────┘",
  924. };
  925. [Fact, AutoInitShutdown]
  926. public void Dim_Add_Operator_With_Text ()
  927. {
  928. var top = Application.Top;
  929. // BUGBUG: v2 - If a View's height is zero, it should not be drawn.
  930. //// Although view height is zero the text it's draw due the SetMinWidthHeight method
  931. var view = new View ("View with long text") { X = 0, Y = 0, Width = 20, Height = 1 };
  932. var field = new TextField () { X = 0, Y = Pos.Bottom (view), Width = 20 };
  933. var count = 0;
  934. var listLabels = new List<Label> ();
  935. field.KeyDown += (s, k) => {
  936. if (k.KeyEvent.Key == Key.Enter) {
  937. ((FakeDriver)Application.Driver).SetBufferSize (22, count + 4);
  938. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expecteds [count], output);
  939. Assert.Equal (new Rect (0, 0, 22, count + 4), pos);
  940. if (count < 20) {
  941. field.Text = $"Label {count}";
  942. var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 10 };
  943. view.Add (label);
  944. Assert.Equal ($"Label {count}", label.Text);
  945. Assert.Equal ($"Absolute({count + 1})", label.Y.ToString ());
  946. listLabels.Add (label);
  947. //if (count == 0) {
  948. // Assert.Equal ($"Absolute({count})", view.Height.ToString ());
  949. // view.Height += 2;
  950. //} else {
  951. Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
  952. view.Height += 1;
  953. //}
  954. count++;
  955. }
  956. Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
  957. }
  958. };
  959. Application.Iteration += () => {
  960. while (count < 21) {
  961. field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  962. if (count == 20) {
  963. field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  964. break;
  965. }
  966. }
  967. Application.RequestStop ();
  968. };
  969. var win = new Window ();
  970. win.Add (view);
  971. win.Add (field);
  972. top.Add (win);
  973. Application.Run (top);
  974. Assert.Equal (20, count);
  975. Assert.Equal (count, listLabels.Count);
  976. }
  977. [Fact, AutoInitShutdown]
  978. public void Dim_Subtract_Operator ()
  979. {
  980. var top = Application.Top;
  981. var view = new View () { X = 0, Y = 0, Width = 20, Height = 0 };
  982. var field = new TextField () { X = 0, Y = Pos.Bottom (view), Width = 20 };
  983. var count = 20;
  984. var listLabels = new List<Label> ();
  985. for (int i = 0; i < count; i++) {
  986. field.Text = $"Label {i}";
  987. var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 20 };
  988. view.Add (label);
  989. Assert.Equal ($"Label {i}", label.Text);
  990. // BUGBUG: Bogus test; views have not been initialized yet
  991. //Assert.Equal ($"Absolute({i})", label.Y.ToString ());
  992. listLabels.Add (label);
  993. // BUGBUG: Bogus test; views have not been initialized yet
  994. //Assert.Equal ($"Absolute({i})", view.Height.ToString ());
  995. view.Height += 1;
  996. //Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
  997. }
  998. field.KeyDown += (s, k) => {
  999. if (k.KeyEvent.Key == Key.Enter) {
  1000. Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
  1001. view.Remove (listLabels [count - 1]);
  1002. listLabels [count - 1].Dispose ();
  1003. Assert.Equal ($"Absolute({count})", view.Height.ToString ());
  1004. view.Height -= 1;
  1005. count--;
  1006. Assert.Equal ($"Absolute({count})", view.Height.ToString ());
  1007. }
  1008. };
  1009. Application.Iteration += () => {
  1010. while (count > 0) field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  1011. Application.RequestStop ();
  1012. };
  1013. var win = new Window ();
  1014. win.Add (view);
  1015. win.Add (field);
  1016. top.Add (win);
  1017. Application.Run (top);
  1018. Assert.Equal (0, count);
  1019. }
  1020. [Fact, AutoInitShutdown]
  1021. public void Dim_Subtract_Operator_With_Text ()
  1022. {
  1023. var top = Application.Top;
  1024. // BUGBUG: v2 - If a View's height is zero, it should not be drawn.
  1025. //// Although view height is zero the text it's draw due the SetMinWidthHeight method
  1026. var view = new View ("View with long text") { X = 0, Y = 0, Width = 20, Height = 1 };
  1027. var field = new TextField () { X = 0, Y = Pos.Bottom (view), Width = 20 };
  1028. var count = 20;
  1029. var listLabels = new List<Label> ();
  1030. for (int i = 0; i < count; i++) {
  1031. field.Text = $"Label {i}";
  1032. // BUGBUG: v2 - view has not been initialied yet; view.Bounds is indeterminate
  1033. var label = new Label (field.Text) { X = 0, Y = i + 1, Width = 10 };
  1034. view.Add (label);
  1035. Assert.Equal ($"Label {i}", label.Text);
  1036. // BUGBUG: Bogus test; views have not been initialized yet
  1037. //Assert.Equal ($"Absolute({i + 1})", label.Y.ToString ());
  1038. listLabels.Add (label);
  1039. //if (i == 0) {
  1040. // BUGBUG: Bogus test; views have not been initialized yet
  1041. //Assert.Equal ($"Absolute({i})", view.Height.ToString ());
  1042. //view.Height += 2;
  1043. // BUGBUG: Bogus test; views have not been initialized yet
  1044. //Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ());
  1045. //} else {
  1046. // BUGBUG: Bogus test; views have not been initialized yet
  1047. //Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ());
  1048. view.Height += 1;
  1049. // BUGBUG: Bogus test; views have not been initialized yet
  1050. //Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ());
  1051. //}
  1052. }
  1053. field.KeyDown += (s, k) => {
  1054. if (k.KeyEvent.Key == Key.Enter) {
  1055. ((FakeDriver)Application.Driver).SetBufferSize (22, count + 4);
  1056. var pos = TestHelpers.AssertDriverContentsWithFrameAre (expecteds [count], output);
  1057. Assert.Equal (new Rect (0, 0, 22, count + 4), pos);
  1058. if (count > 0) {
  1059. Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text);
  1060. view.Remove (listLabels [count - 1]);
  1061. listLabels [count - 1].Dispose ();
  1062. listLabels.RemoveAt (count - 1);
  1063. Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
  1064. view.Height -= 1;
  1065. count--;
  1066. if (listLabels.Count > 0)
  1067. field.Text = listLabels [count - 1].Text;
  1068. else
  1069. field.Text = string.Empty;
  1070. }
  1071. Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ());
  1072. }
  1073. };
  1074. Application.Iteration += () => {
  1075. while (count > -1) {
  1076. field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  1077. if (count == 0) {
  1078. field.OnKeyDown (new KeyEvent (Key.Enter, new KeyModifiers ()));
  1079. break;
  1080. }
  1081. }
  1082. Application.RequestStop ();
  1083. };
  1084. var win = new Window ();
  1085. win.Add (view);
  1086. win.Add (field);
  1087. top.Add (win);
  1088. Application.Run (top);
  1089. Assert.Equal (0, count);
  1090. Assert.Equal (count, listLabels.Count);
  1091. }
  1092. [Fact, TestRespondersDisposed]
  1093. public void Internal_Tests ()
  1094. {
  1095. var dimFactor = new Dim.DimFactor (0.10F);
  1096. Assert.Equal (10, dimFactor.Anchor (100));
  1097. var dimAbsolute = new Dim.DimAbsolute (10);
  1098. Assert.Equal (10, dimAbsolute.Anchor (0));
  1099. var dimFill = new Dim.DimFill (1);
  1100. Assert.Equal (99, dimFill.Anchor (100));
  1101. var dimCombine = new Dim.DimCombine (true, dimFactor, dimAbsolute);
  1102. Assert.Equal (dimCombine.left, dimFactor);
  1103. Assert.Equal (dimCombine.right, dimAbsolute);
  1104. Assert.Equal (20, dimCombine.Anchor (100));
  1105. var view = new View (new Rect (20, 10, 20, 1));
  1106. var dimViewHeight = new Dim.DimView (view, 0);
  1107. Assert.Equal (1, dimViewHeight.Anchor (0));
  1108. var dimViewWidth = new Dim.DimView (view, 1);
  1109. Assert.Equal (20, dimViewWidth.Anchor (0));
  1110. view.Dispose ();
  1111. }
  1112. [Fact]
  1113. public void Function_SetsValue ()
  1114. {
  1115. var text = "Test";
  1116. var dim = Dim.Function (() => text.Length);
  1117. Assert.Equal ("DimFunc(4)", dim.ToString ());
  1118. text = "New Test";
  1119. Assert.Equal ("DimFunc(8)", dim.ToString ());
  1120. text = "";
  1121. Assert.Equal ("DimFunc(0)", dim.ToString ());
  1122. }
  1123. [Fact]
  1124. public void Function_Equal ()
  1125. {
  1126. var f1 = () => 0;
  1127. var f2 = () => 0;
  1128. var dim1 = Dim.Function (f1);
  1129. var dim2 = Dim.Function (f2);
  1130. Assert.Equal (dim1, dim2);
  1131. f2 = () => 1;
  1132. dim2 = Dim.Function (f2);
  1133. Assert.NotEqual (dim1, dim2);
  1134. }
  1135. [Theory, AutoInitShutdown]
  1136. [InlineData (0, true)]
  1137. [InlineData (0, false)]
  1138. [InlineData (50, true)]
  1139. [InlineData (50, false)]
  1140. public void DimPercentPlusOne (int startingDistance, bool testHorizontal)
  1141. {
  1142. var container = new View {
  1143. Width = 100,
  1144. Height = 100,
  1145. };
  1146. var label = new Label {
  1147. X = testHorizontal ? startingDistance : 0,
  1148. Y = testHorizontal ? 0 : startingDistance,
  1149. Width = testHorizontal ? Dim.Percent (50) + 1 : 1,
  1150. Height = testHorizontal ? 1 : Dim.Percent (50) + 1,
  1151. };
  1152. container.Add (label);
  1153. Application.Top.Add (container);
  1154. Application.Top.LayoutSubviews ();
  1155. Assert.Equal (100, container.Frame.Width);
  1156. Assert.Equal (100, container.Frame.Height);
  1157. if (testHorizontal) {
  1158. Assert.Equal (51, label.Frame.Width);
  1159. Assert.Equal (1, label.Frame.Height);
  1160. } else {
  1161. Assert.Equal (1, label.Frame.Width);
  1162. Assert.Equal (51, label.Frame.Height);
  1163. }
  1164. }
  1165. [Fact, TestRespondersDisposed]
  1166. public void Dim_Referencing_SuperView_Does_Not_Throw ()
  1167. {
  1168. var super = new View ("super") {
  1169. Width = 10,
  1170. Height = 10
  1171. };
  1172. var view = new View ("view") {
  1173. Width = Dim.Width (super), // this is allowed
  1174. Height = Dim.Height (super), // this is allowed
  1175. };
  1176. super.Add (view);
  1177. super.BeginInit ();
  1178. super.EndInit ();
  1179. var exception = Record.Exception (super.LayoutSubviews);
  1180. Assert.Null (exception);
  1181. super.Dispose ();
  1182. }
  1183. [Fact, TestRespondersDisposed]
  1184. public void Dim_SyperView_Referencing_SubView_Throws ()
  1185. {
  1186. var super = new View ("super") {
  1187. Width = 10,
  1188. Height = 10
  1189. };
  1190. var view2 = new View ("view2") {
  1191. Width = 10,
  1192. Height = 10,
  1193. };
  1194. var view = new View ("view") {
  1195. Width = Dim.Width (view2), // this is not allowed
  1196. Height = Dim.Height (view2), // this is not allowed
  1197. };
  1198. view.Add (view2);
  1199. super.Add (view);
  1200. super.BeginInit ();
  1201. super.EndInit ();
  1202. Assert.Throws<InvalidOperationException> (super.LayoutSubviews);
  1203. super.Dispose ();
  1204. }
  1205. }
  1206. }