ToplevelTests.cs 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055
  1. namespace Terminal.Gui.ViewsTests;
  2. public partial class ToplevelTests ()
  3. {
  4. [Fact]
  5. public void Constructor_Default ()
  6. {
  7. var top = new Toplevel ();
  8. Assert.Equal (Colors.ColorSchemes ["TopLevel"], top.ColorScheme);
  9. Assert.Equal ("Fill(Absolute(0))", top.Width.ToString ());
  10. Assert.Equal ("Fill(Absolute(0))", top.Height.ToString ());
  11. Assert.False (top.Running);
  12. Assert.False (top.Modal);
  13. Assert.Null (top.MenuBar);
  14. //Assert.Null (top.StatusBar);
  15. }
  16. [Fact]
  17. public void Arrangement_Default_Is_Overlapped ()
  18. {
  19. var top = new Toplevel ();
  20. Assert.Equal (ViewArrangement.Overlapped, top.Arrangement);
  21. }
  22. [Fact]
  23. [AutoInitShutdown]
  24. public void Internal_Tests ()
  25. {
  26. var top = new Toplevel ();
  27. var eventInvoked = "";
  28. top.Loaded += (s, e) => eventInvoked = "Loaded";
  29. top.OnLoaded ();
  30. Assert.Equal ("Loaded", eventInvoked);
  31. top.Ready += (s, e) => eventInvoked = "Ready";
  32. top.OnReady ();
  33. Assert.Equal ("Ready", eventInvoked);
  34. top.Unloaded += (s, e) => eventInvoked = "Unloaded";
  35. top.OnUnloaded ();
  36. Assert.Equal ("Unloaded", eventInvoked);
  37. top.Add (new MenuBar ());
  38. Assert.NotNull (top.MenuBar);
  39. //top.Add (new StatusBar ());
  40. //Assert.NotNull (top.StatusBar);
  41. var menuBar = top.MenuBar;
  42. top.Remove (top.MenuBar);
  43. Assert.Null (top.MenuBar);
  44. Assert.NotNull (menuBar);
  45. //var statusBar = top.StatusBar;
  46. //top.Remove (top.StatusBar);
  47. //Assert.Null (top.StatusBar);
  48. //Assert.NotNull (statusBar);
  49. #if DEBUG_IDISPOSABLE
  50. Assert.False (menuBar.WasDisposed);
  51. //Assert.False (statusBar.WasDisposed);
  52. menuBar.Dispose ();
  53. //statusBar.Dispose ();
  54. Assert.True (menuBar.WasDisposed);
  55. //Assert.True (statusBar.WasDisposed);
  56. #endif
  57. Application.Begin (top);
  58. Assert.Equal (top, Application.Top);
  59. // Application.Top without menu and status bar.
  60. View supView = View.GetLocationEnsuringFullVisibility (top, 2, 2, out int nx, out int ny/*, out StatusBar sb*/);
  61. Assert.Equal (Application.Top, supView);
  62. Assert.Equal (0, nx);
  63. Assert.Equal (0, ny);
  64. //Assert.Null (sb);
  65. top.Add (new MenuBar ());
  66. Assert.NotNull (top.MenuBar);
  67. // Application.Top with a menu and without status bar.
  68. View.GetLocationEnsuringFullVisibility (top, 2, 2, out nx, out ny/*, out sb*/);
  69. Assert.Equal (0, nx);
  70. Assert.Equal (1, ny);
  71. //Assert.Null (sb);
  72. //top.Add (new StatusBar ());
  73. //Assert.NotNull (top.StatusBar);
  74. // Application.Top with a menu and status bar.
  75. View.GetLocationEnsuringFullVisibility (top, 2, 2, out nx, out ny/*, out sb*/);
  76. Assert.Equal (0, nx);
  77. // The available height is lower than the Application.Top height minus
  78. // the menu bar and status bar, then the top can go beyond the bottom
  79. // Assert.Equal (2, ny);
  80. //Assert.NotNull (sb);
  81. menuBar = top.MenuBar;
  82. top.Remove (top.MenuBar);
  83. Assert.Null (top.MenuBar);
  84. Assert.NotNull (menuBar);
  85. // Application.Top without a menu and with a status bar.
  86. View.GetLocationEnsuringFullVisibility (top, 2, 2, out nx, out ny/*, out sb*/);
  87. Assert.Equal (0, nx);
  88. // The available height is lower than the Application.Top height minus
  89. // the status bar, then the top can go beyond the bottom
  90. // Assert.Equal (2, ny);
  91. //Assert.NotNull (sb);
  92. //statusBar = top.StatusBar;
  93. //top.Remove (top.StatusBar);
  94. //Assert.Null (top.StatusBar);
  95. //Assert.NotNull (statusBar);
  96. Assert.Null (top.MenuBar);
  97. var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
  98. top.Add (win);
  99. top.LayoutSubviews ();
  100. // The SuperView is always the same regardless of the caller.
  101. supView = View.GetLocationEnsuringFullVisibility (win, 0, 0, out nx, out ny/*, out sb*/);
  102. Assert.Equal (Application.Top, supView);
  103. supView = View.GetLocationEnsuringFullVisibility (win, 0, 0, out nx, out ny/*, out sb*/);
  104. Assert.Equal (Application.Top, supView);
  105. // Application.Top without menu and status bar.
  106. View.GetLocationEnsuringFullVisibility (win, 0, 0, out nx, out ny/*, out sb*/);
  107. Assert.Equal (0, nx);
  108. Assert.Equal (0, ny);
  109. //Assert.Null (sb);
  110. top.Add (new MenuBar ());
  111. Assert.NotNull (top.MenuBar);
  112. // Application.Top with a menu and without status bar.
  113. View.GetLocationEnsuringFullVisibility (win, 2, 2, out nx, out ny/*, out sb*/);
  114. Assert.Equal (0, nx);
  115. Assert.Equal (1, ny);
  116. //Assert.Null (sb);
  117. top.Add (new StatusBar ());
  118. //Assert.NotNull (top.StatusBar);
  119. // Application.Top with a menu and status bar.
  120. View.GetLocationEnsuringFullVisibility (win, 30, 20, out nx, out ny/*, out sb*/);
  121. Assert.Equal (0, nx);
  122. // The available height is lower than the Application.Top height minus
  123. // the menu bar and status bar, then the top can go beyond the bottom
  124. //Assert.Equal (20, ny);
  125. //Assert.NotNull (sb);
  126. menuBar = top.MenuBar;
  127. //statusBar = top.StatusBar;
  128. top.Remove (top.MenuBar);
  129. Assert.Null (top.MenuBar);
  130. Assert.NotNull (menuBar);
  131. //top.Remove (top.StatusBar);
  132. //Assert.Null (top.StatusBar);
  133. //Assert.NotNull (statusBar);
  134. top.Remove (win);
  135. win = new () { Width = 60, Height = 15 };
  136. top.Add (win);
  137. // Application.Top without menu and status bar.
  138. View.GetLocationEnsuringFullVisibility (win, 0, 0, out nx, out ny/*, out sb*/);
  139. Assert.Equal (0, nx);
  140. Assert.Equal (0, ny);
  141. //Assert.Null (sb);
  142. top.Add (new MenuBar ());
  143. Assert.NotNull (top.MenuBar);
  144. // Application.Top with a menu and without status bar.
  145. View.GetLocationEnsuringFullVisibility (win, 2, 2, out nx, out ny/*, out sb*/);
  146. Assert.Equal (2, nx);
  147. Assert.Equal (2, ny);
  148. //Assert.Null (sb);
  149. top.Add (new StatusBar ());
  150. //Assert.NotNull (top.StatusBar);
  151. // Application.Top with a menu and status bar.
  152. View.GetLocationEnsuringFullVisibility (win, 30, 20, out nx, out ny/*, out sb*/);
  153. Assert.Equal (20, nx); // 20+60=80
  154. //Assert.Equal (9, ny); // 9+15+1(mb)=25
  155. //Assert.NotNull (sb);
  156. //Assert.Null (Toplevel._dragPosition);
  157. win.NewMouseEvent (new () { Position = new (6, 0), Flags = MouseFlags.Button1Pressed });
  158. // Assert.Equal (new Point (6, 0), Toplevel._dragPosition);
  159. win.NewMouseEvent (new () { Position = new (6, 0), Flags = MouseFlags.Button1Released });
  160. //Assert.Null (Toplevel._dragPosition);
  161. win.CanFocus = false;
  162. win.NewMouseEvent (new () { Position = new (6, 0), Flags = MouseFlags.Button1Pressed });
  163. //Assert.Null (Toplevel._dragPosition);
  164. #if DEBUG_IDISPOSABLE
  165. Assert.False (top.MenuBar.WasDisposed);
  166. //Assert.False (top.StatusBar.WasDisposed);
  167. #endif
  168. menuBar = top.MenuBar;
  169. //statusBar = top.StatusBar;
  170. top.Dispose ();
  171. Assert.Null (top.MenuBar);
  172. //Assert.Null (top.StatusBar);
  173. Assert.NotNull (menuBar);
  174. //Assert.NotNull (statusBar);
  175. #if DEBUG_IDISPOSABLE
  176. Assert.True (menuBar.WasDisposed);
  177. //Assert.True (statusBar.WasDisposed);
  178. #endif
  179. }
  180. [Fact (Skip = "#2491 - Test is broken until #2491 is more mature.")]
  181. [AutoInitShutdown]
  182. public void KeyBindings_Command ()
  183. {
  184. var isRunning = false;
  185. var win1 = new Window { Id = "win1", Width = Dim.Percent (50), Height = Dim.Fill () };
  186. var lblTf1W1 = new Label { Id = "lblTf1W1", Text = "Enter text in TextField on Win1:" };
  187. var tf1W1 = new TextField
  188. {
  189. Id = "tf1W1", X = Pos.Right (lblTf1W1) + 1, Width = Dim.Fill (), Text = "Text1 on Win1"
  190. };
  191. var lblTvW1 = new Label
  192. {
  193. Id = "lblTvW1", Y = Pos.Bottom (lblTf1W1) + 1, Text = "Enter text in TextView on Win1:"
  194. };
  195. var tvW1 = new TextView
  196. {
  197. Id = "tvW1",
  198. X = Pos.Left (tf1W1),
  199. Width = Dim.Fill (),
  200. Height = 2,
  201. Text = "First line Win1\nSecond line Win1"
  202. };
  203. var lblTf2W1 = new Label
  204. {
  205. Id = "lblTf2W1", Y = Pos.Bottom (lblTvW1) + 1, Text = "Enter text in TextField on Win1:"
  206. };
  207. var tf2W1 = new TextField { Id = "tf2W1", X = Pos.Left (tf1W1), Width = Dim.Fill (), Text = "Text2 on Win1" };
  208. win1.Add (lblTf1W1, tf1W1, lblTvW1, tvW1, lblTf2W1, tf2W1);
  209. var win2 = new Window
  210. {
  211. Id = "win2", X = Pos.Right (win1) + 1, Width = Dim.Percent (50), Height = Dim.Fill ()
  212. };
  213. var lblTf1W2 = new Label { Id = "lblTf1W2", Text = "Enter text in TextField on Win2:" };
  214. var tf1W2 = new TextField
  215. {
  216. Id = "tf1W2", X = Pos.Right (lblTf1W2) + 1, Width = Dim.Fill (), Text = "Text1 on Win2"
  217. };
  218. var lblTvW2 = new Label
  219. {
  220. Id = "lblTvW2", Y = Pos.Bottom (lblTf1W2) + 1, Text = "Enter text in TextView on Win2:"
  221. };
  222. var tvW2 = new TextView
  223. {
  224. Id = "tvW2",
  225. X = Pos.Left (tf1W2),
  226. Width = Dim.Fill (),
  227. Height = 2,
  228. Text = "First line Win1\nSecond line Win2"
  229. };
  230. var lblTf2W2 = new Label
  231. {
  232. Id = "lblTf2W2", Y = Pos.Bottom (lblTvW2) + 1, Text = "Enter text in TextField on Win2:"
  233. };
  234. var tf2W2 = new TextField { Id = "tf2W2", X = Pos.Left (tf1W2), Width = Dim.Fill (), Text = "Text2 on Win2" };
  235. win2.Add (lblTf1W2, tf1W2, lblTvW2, tvW2, lblTf2W2, tf2W2);
  236. Toplevel top = new ();
  237. top.Add (win1, win2);
  238. top.Loaded += (s, e) => isRunning = true;
  239. top.Closing += (s, e) => isRunning = false;
  240. Application.Begin (top);
  241. top.Running = true;
  242. Assert.Equal (new (0, 0, 40, 25), win1.Frame);
  243. Assert.Equal (new (41, 0, 40, 25), win2.Frame);
  244. Assert.Equal (win1, top.Focused);
  245. Assert.Equal (tf1W1, top.MostFocused);
  246. Assert.True (isRunning);
  247. Assert.True (Application.RaiseKeyDownEvent (Application.QuitKey));
  248. Assert.False (isRunning);
  249. Assert.True (Application.RaiseKeyDownEvent (Key.Z.WithCtrl));
  250. Assert.True (Application.RaiseKeyDownEvent (Key.F5)); // refresh
  251. Assert.True (Application.RaiseKeyDownEvent (Key.Tab));
  252. Assert.Equal (win1, top.Focused);
  253. Assert.Equal (tvW1, top.MostFocused);
  254. Assert.True (Application.RaiseKeyDownEvent (Key.Tab));
  255. Assert.Equal ($"\tFirst line Win1{Environment.NewLine}Second line Win1", tvW1.Text);
  256. Assert.True (Application.RaiseKeyDownEvent (Key.Tab.WithShift));
  257. Assert.Equal ($"First line Win1{Environment.NewLine}Second line Win1", tvW1.Text);
  258. var prevMostFocusedSubview = top.MostFocused;
  259. Assert.True (Application.RaiseKeyDownEvent (Key.F6)); // move to next TabGroup (win2)
  260. Assert.Equal (win2, top.Focused);
  261. Assert.True (Application.RaiseKeyDownEvent (Key.F6.WithShift)); // move to prev TabGroup (win1)
  262. Assert.Equal (win1, top.Focused);
  263. Assert.Equal (tf2W1, top.MostFocused); // BUGBUG: Should be prevMostFocusedSubview - We need to cache the last focused view in the TabGroup somehow
  264. prevMostFocusedSubview.SetFocus ();
  265. Assert.Equal (tvW1, top.MostFocused);
  266. tf2W1.SetFocus ();
  267. Assert.True (Application.RaiseKeyDownEvent (Key.Tab)); // tf2W1 is last subview in win1 - tabbing should take us to first subview of win1
  268. Assert.Equal (win1, top.Focused);
  269. Assert.Equal (tf1W1, top.MostFocused);
  270. Assert.True (Application.RaiseKeyDownEvent (Key.CursorRight)); // move char to right in tf1W1. We're at last char so nav to next view
  271. Assert.Equal (win1, top.Focused);
  272. Assert.Equal (tvW1, top.MostFocused);
  273. Assert.True (Application.RaiseKeyDownEvent (Key.CursorDown)); // move down to next view (tvW1)
  274. Assert.Equal (win1, top.Focused);
  275. Assert.Equal (tvW1, top.MostFocused);
  276. #if UNIX_KEY_BINDINGS
  277. Assert.True (Application.OnKeyDown (new (Key.I.WithCtrl)));
  278. Assert.Equal (win1, top.GetFocused ());
  279. Assert.Equal (tf2W1, top.MostFocused);
  280. #endif
  281. Assert.True (Application.RaiseKeyDownEvent (Key.Tab.WithShift)); // Ignored. TextView eats shift-tab by default
  282. Assert.Equal (win1, top.Focused);
  283. Assert.Equal (tvW1, top.MostFocused);
  284. tvW1.AllowsTab = false;
  285. Assert.True (Application.RaiseKeyDownEvent (Key.Tab.WithShift));
  286. Assert.Equal (win1, top.Focused);
  287. Assert.Equal (tf1W1, top.MostFocused);
  288. Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
  289. Assert.Equal (win1, top.Focused);
  290. Assert.Equal (tf2W1, top.MostFocused);
  291. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  292. Assert.Equal (win1, top.Focused);
  293. Assert.Equal (tvW1, top.MostFocused);
  294. // nav to win2
  295. Assert.True (Application.RaiseKeyDownEvent (Key.F6));
  296. Assert.Equal (win2, top.Focused);
  297. Assert.Equal (tf1W2, top.MostFocused);
  298. Assert.True (Application.RaiseKeyDownEvent (Key.F6.WithShift));
  299. Assert.Equal (win1, top.Focused);
  300. Assert.Equal (tf2W1, top.MostFocused);
  301. Assert.True (Application.RaiseKeyDownEvent (Application.NextTabGroupKey));
  302. Assert.Equal (win2, top.Focused);
  303. Assert.Equal (tf1W2, top.MostFocused);
  304. Assert.True (Application.RaiseKeyDownEvent (Application.PrevTabGroupKey));
  305. Assert.Equal (win1, top.Focused);
  306. Assert.Equal (tf2W1, top.MostFocused);
  307. Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
  308. Assert.Equal (win1, top.Focused);
  309. Assert.Equal (tvW1, top.MostFocused);
  310. top.Dispose ();
  311. }
  312. [Fact]
  313. public void Added_Event_Should_Not_Be_Used_To_Initialize_Toplevel_Events ()
  314. {
  315. var wasAdded = false;
  316. var view = new View ();
  317. view.Added += View_Added;
  318. void View_Added (object sender, SuperViewChangedEventArgs e)
  319. {
  320. Assert.False (wasAdded);
  321. wasAdded = true;
  322. view.Added -= View_Added;
  323. }
  324. var win = new Window ();
  325. win.Add (view);
  326. Application.Init (new FakeDriver ());
  327. Toplevel top = new ();
  328. top.Add (win);
  329. Assert.True (wasAdded);
  330. Application.Shutdown ();
  331. }
  332. [Fact]
  333. [AutoInitShutdown]
  334. public void Mouse_Drag_On_Top_With_Superview_Null ()
  335. {
  336. var win = new Window ();
  337. Toplevel top = new ();
  338. top.Add (win);
  339. int iterations = -1;
  340. Window testWindow;
  341. Application.Iteration += (s, a) =>
  342. {
  343. iterations++;
  344. if (iterations == 0)
  345. {
  346. ((FakeDriver)Application.Driver!).SetBufferSize (15, 7);
  347. // Don't use MessageBox here; it's too complicated for this unit test; just use Window
  348. testWindow = new ()
  349. {
  350. Text = "Hello",
  351. X = 2,
  352. Y = 2,
  353. Width = 10,
  354. Height = 3,
  355. Arrangement = ViewArrangement.Movable
  356. };
  357. Application.Run (testWindow);
  358. }
  359. else if (iterations == 1)
  360. {
  361. Assert.Equal (new (2, 2), Application.Top!.Frame.Location);
  362. }
  363. else if (iterations == 2)
  364. {
  365. Assert.Null (Application.MouseGrabView);
  366. // Grab the mouse
  367. Application.RaiseMouseEvent (new () { ScreenPosition = new (3, 2), Flags = MouseFlags.Button1Pressed });
  368. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  369. Assert.Equal (new (2, 2, 10, 3), Application.Top.Frame);
  370. }
  371. else if (iterations == 3)
  372. {
  373. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  374. // Drag to left
  375. Application.RaiseMouseEvent (
  376. new ()
  377. {
  378. ScreenPosition = new (2, 2), Flags = MouseFlags.Button1Pressed
  379. | MouseFlags.ReportMousePosition
  380. });
  381. Application.LayoutAndDraw ();
  382. Assert.Equal (Application.Top.Border, Application.MouseGrabView);
  383. Assert.Equal (new (1, 2, 10, 3), Application.Top.Frame);
  384. }
  385. else if (iterations == 4)
  386. {
  387. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  388. Assert.Equal (new (1, 2), Application.Top.Frame.Location);
  389. Assert.Equal (Application.Top.Border, Application.MouseGrabView);
  390. }
  391. else if (iterations == 5)
  392. {
  393. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  394. // Drag up
  395. Application.RaiseMouseEvent (
  396. new ()
  397. {
  398. ScreenPosition = new (2, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  399. });
  400. Application.LayoutAndDraw ();
  401. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  402. Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame);
  403. }
  404. else if (iterations == 6)
  405. {
  406. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  407. Assert.Equal (new (1, 1), Application.Top.Frame.Location);
  408. Assert.Equal (Application.Top.Border, Application.MouseGrabView);
  409. Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame);
  410. }
  411. else if (iterations == 7)
  412. {
  413. Assert.Equal (Application.Top!.Border, Application.MouseGrabView);
  414. // Ungrab the mouse
  415. Application.RaiseMouseEvent (new () { ScreenPosition = new (2, 1), Flags = MouseFlags.Button1Released });
  416. Application.LayoutAndDraw ();
  417. Assert.Null (Application.MouseGrabView);
  418. }
  419. else if (iterations == 8)
  420. {
  421. Application.RequestStop ();
  422. }
  423. else if (iterations == 9)
  424. {
  425. Application.RequestStop ();
  426. }
  427. };
  428. Application.Run (top);
  429. top.Dispose ();
  430. }
  431. [Fact]
  432. [AutoInitShutdown]
  433. public void Mouse_Drag_On_Top_With_Superview_Not_Null ()
  434. {
  435. var win = new Window { X = 3, Y = 2, Width = 10, Height = 5, Arrangement = ViewArrangement.Movable };
  436. Toplevel top = new ();
  437. top.Add (win);
  438. int iterations = -1;
  439. var movex = 0;
  440. var movey = 0;
  441. var location = new Rectangle (win.Frame.X, win.Frame.Y, 7, 3);
  442. Application.Iteration += (s, a) =>
  443. {
  444. iterations++;
  445. if (iterations == 0)
  446. {
  447. ((FakeDriver)Application.Driver!).SetBufferSize (30, 10);
  448. }
  449. else if (iterations == 1)
  450. {
  451. location = win.Frame;
  452. Assert.Null (Application.MouseGrabView);
  453. // Grab the mouse
  454. Application.RaiseMouseEvent (
  455. new ()
  456. {
  457. ScreenPosition = new (win.Frame.X, win.Frame.Y), Flags = MouseFlags.Button1Pressed
  458. });
  459. Assert.Equal (win.Border, Application.MouseGrabView);
  460. }
  461. else if (iterations == 2)
  462. {
  463. Assert.Equal (win.Border, Application.MouseGrabView);
  464. // Drag to left
  465. movex = 1;
  466. movey = 0;
  467. Application.RaiseMouseEvent (
  468. new ()
  469. {
  470. ScreenPosition = new (win.Frame.X + movex, win.Frame.Y + movey), Flags =
  471. MouseFlags.Button1Pressed
  472. | MouseFlags.ReportMousePosition
  473. });
  474. Assert.Equal (win.Border, Application.MouseGrabView);
  475. }
  476. else if (iterations == 3)
  477. {
  478. // we should have moved +1, +0
  479. Assert.Equal (win.Border, Application.MouseGrabView);
  480. Assert.Equal (win.Border, Application.MouseGrabView);
  481. location.Offset (movex, movey);
  482. }
  483. else if (iterations == 4)
  484. {
  485. Assert.Equal (win.Border, Application.MouseGrabView);
  486. // Drag up
  487. movex = 0;
  488. movey = -1;
  489. Application.RaiseMouseEvent (
  490. new ()
  491. {
  492. ScreenPosition = new (win.Frame.X + movex, win.Frame.Y + movey), Flags =
  493. MouseFlags.Button1Pressed
  494. | MouseFlags.ReportMousePosition
  495. });
  496. Assert.Equal (win.Border, Application.MouseGrabView);
  497. }
  498. else if (iterations == 5)
  499. {
  500. // we should have moved +0, -1
  501. Assert.Equal (win.Border, Application.MouseGrabView);
  502. location.Offset (movex, movey);
  503. Assert.Equal (location, win.Frame);
  504. }
  505. else if (iterations == 6)
  506. {
  507. Assert.Equal (win.Border, Application.MouseGrabView);
  508. // Ungrab the mouse
  509. movex = 0;
  510. movey = 0;
  511. Application.RaiseMouseEvent (
  512. new ()
  513. {
  514. ScreenPosition = new (win.Frame.X + movex, win.Frame.Y + movey),
  515. Flags = MouseFlags.Button1Released
  516. });
  517. Assert.Null (Application.MouseGrabView);
  518. }
  519. else if (iterations == 7)
  520. {
  521. Application.RequestStop ();
  522. }
  523. };
  524. Application.Run (top);
  525. top.Dispose ();
  526. }
  527. [Fact]
  528. [SetupFakeDriver]
  529. public void GetLocationThatFits_With_Border_Null_Not_Throws ()
  530. {
  531. var top = new Toplevel ();
  532. top.BeginInit ();
  533. top.EndInit ();
  534. Exception exception = Record.Exception (() => ((FakeDriver)Application.Driver!).SetBufferSize (0, 10));
  535. Assert.Null (exception);
  536. exception = Record.Exception (() => ((FakeDriver)Application.Driver!).SetBufferSize (10, 0));
  537. Assert.Null (exception);
  538. }
  539. [Fact]
  540. [AutoInitShutdown]
  541. public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null ()
  542. {
  543. var tf = new TextField { Width = 5, Text = "test" };
  544. var view = new View { Width = 10, Height = 10, CanFocus = true };
  545. view.Add (tf);
  546. var top = new Toplevel ();
  547. top.Add (view);
  548. Application.Begin (top);
  549. Assert.True (tf.HasFocus);
  550. Application.PositionCursor ();
  551. Application.Driver!.GetCursorVisibility (out CursorVisibility cursor);
  552. Assert.Equal (CursorVisibility.Default, cursor);
  553. view.Enabled = false;
  554. Assert.False (tf.HasFocus);
  555. Application.PositionCursor ();
  556. Application.Driver!.GetCursorVisibility (out cursor);
  557. Assert.Equal (CursorVisibility.Invisible, cursor);
  558. top.Dispose ();
  559. }
  560. [Fact]
  561. [AutoInitShutdown]
  562. public void IsLoaded_Application_Begin ()
  563. {
  564. Toplevel top = new ();
  565. Assert.False (top.IsLoaded);
  566. Application.Begin (top);
  567. Assert.True (top.IsLoaded);
  568. top.Dispose ();
  569. }
  570. [Fact]
  571. [AutoInitShutdown]
  572. public void IsLoaded_With_Sub_Toplevel_Application_Begin_NeedDisplay ()
  573. {
  574. Toplevel top = new ();
  575. var subTop = new Toplevel ();
  576. var view = new View { Frame = new (0, 0, 20, 10) };
  577. subTop.Add (view);
  578. top.Add (subTop);
  579. Assert.False (top.IsLoaded);
  580. Assert.False (subTop.IsLoaded);
  581. Assert.Equal (new (0, 0, 20, 10), view.Frame);
  582. view.SubviewLayout += ViewLayoutStarted;
  583. void ViewLayoutStarted (object sender, LayoutEventArgs e)
  584. {
  585. Assert.Equal (new (0, 0, 20, 10), view._needsDrawRect);
  586. view.SubviewLayout -= ViewLayoutStarted;
  587. }
  588. Application.Begin (top);
  589. Assert.True (top.IsLoaded);
  590. Assert.True (subTop.IsLoaded);
  591. Assert.Equal (new (0, 0, 20, 10), view.Frame);
  592. view.Frame = new (1, 3, 10, 5);
  593. Assert.Equal (new (1, 3, 10, 5), view.Frame);
  594. Assert.Equal (new (0, 0, 10, 5), view._needsDrawRect);
  595. view.Frame = new (1, 3, 10, 5);
  596. top.Layout ();
  597. Assert.Equal (new (1, 3, 10, 5), view.Frame);
  598. Assert.Equal (new (0, 0, 10, 5), view._needsDrawRect);
  599. top.Dispose ();
  600. }
  601. [Fact]
  602. [AutoInitShutdown]
  603. public void Window_Viewport_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Left_Right_And_Bottom ()
  604. {
  605. Toplevel top = new ();
  606. var window = new Window { Width = 20, Height = 3, Arrangement = ViewArrangement.Movable };
  607. RunState rsTop = Application.Begin (top);
  608. ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
  609. RunState rsWindow = Application.Begin (window);
  610. Application.LayoutAndDraw ();
  611. Assert.Equal (new (0, 0, 40, 10), top.Frame);
  612. Assert.Equal (new (0, 0, 20, 3), window.Frame);
  613. Assert.Null (Application.MouseGrabView);
  614. Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
  615. Assert.Equal (window.Border, Application.MouseGrabView);
  616. Application.RaiseMouseEvent (
  617. new ()
  618. {
  619. ScreenPosition = new (-11, -4), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  620. });
  621. Application.LayoutAndDraw ();
  622. Assert.Equal (new (0, 0, 40, 10), top.Frame);
  623. Assert.Equal (new (-11, -4, 20, 3), window.Frame);
  624. // Changes Top size to same size as Dialog more menu and scroll bar
  625. ((FakeDriver)Application.Driver!).SetBufferSize (20, 3);
  626. Application.RaiseMouseEvent (
  627. new ()
  628. {
  629. ScreenPosition = new (-1, -1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  630. });
  631. Application.LayoutAndDraw ();
  632. Assert.Equal (new (0, 0, 20, 3), top.Frame);
  633. Assert.Equal (new (-1, -1, 20, 3), window.Frame);
  634. // Changes Top size smaller than Dialog size
  635. ((FakeDriver)Application.Driver!).SetBufferSize (19, 2);
  636. Application.RaiseMouseEvent (
  637. new ()
  638. {
  639. ScreenPosition = new (-1, -1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  640. });
  641. Application.LayoutAndDraw ();
  642. Assert.Equal (new (0, 0, 19, 2), top.Frame);
  643. Assert.Equal (new (-1, -1, 20, 3), window.Frame);
  644. Application.RaiseMouseEvent (
  645. new ()
  646. {
  647. ScreenPosition = new (18, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  648. });
  649. Application.LayoutAndDraw ();
  650. Assert.Equal (new (0, 0, 19, 2), top.Frame);
  651. Assert.Equal (new (18, 1, 20, 3), window.Frame);
  652. // On a real app we can't go beyond the SuperView bounds
  653. Application.RaiseMouseEvent (
  654. new ()
  655. {
  656. ScreenPosition = new (19, 2), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  657. });
  658. Application.LayoutAndDraw ();
  659. Assert.Equal (new (0, 0, 19, 2), top.Frame);
  660. Assert.Equal (new (19, 2, 20, 3), window.Frame);
  661. //TestHelpers.AssertDriverContentsWithFrameAre (@"", output);
  662. Application.End (rsWindow);
  663. Application.End (rsTop);
  664. top.Dispose ();
  665. }
  666. [Fact]
  667. [AutoInitShutdown]
  668. public void Modal_As_Top_Will_Drag_Cleanly ()
  669. {
  670. // Don't use Dialog as a Top, use a Window instead - dialog has complex layout behavior that is not needed here.
  671. var window = new Window { Width = 10, Height = 3, Arrangement = ViewArrangement.Movable };
  672. window.Add (
  673. new Label
  674. {
  675. X = Pos.Center (),
  676. Y = Pos.Center (),
  677. Width = Dim.Fill (),
  678. Height = Dim.Fill (),
  679. TextAlignment = Alignment.Center,
  680. VerticalTextAlignment = Alignment.Center,
  681. Text = "Test"
  682. }
  683. );
  684. RunState rs = Application.Begin (window);
  685. Assert.Null (Application.MouseGrabView);
  686. Assert.Equal (new (0, 0, 10, 3), window.Frame);
  687. Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
  688. var firstIteration = false;
  689. Application.RunIteration (ref rs, firstIteration);
  690. Assert.Equal (window.Border, Application.MouseGrabView);
  691. Assert.Equal (new (0, 0, 10, 3), window.Frame);
  692. Application.RaiseMouseEvent (
  693. new ()
  694. {
  695. ScreenPosition = new (1, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
  696. });
  697. firstIteration = false;
  698. Application.RunIteration (ref rs, firstIteration);
  699. Assert.Equal (window.Border, Application.MouseGrabView);
  700. Assert.Equal (new (1, 1, 10, 3), window.Frame);
  701. Application.End (rs);
  702. window.Dispose ();
  703. }
  704. [Fact]
  705. [AutoInitShutdown]
  706. public void Begin_With_Window_Sets_Size_Correctly ()
  707. {
  708. Toplevel top = new ();
  709. RunState rsTop = Application.Begin (top);
  710. ((FakeDriver)Application.Driver!).SetBufferSize (20, 20);
  711. var testWindow = new Window { X = 2, Y = 1, Width = 15, Height = 10 };
  712. Assert.Equal (new (2, 1, 15, 10), testWindow.Frame);
  713. RunState rsTestWindow = Application.Begin (testWindow);
  714. Assert.Equal (new (2, 1, 15, 10), testWindow.Frame);
  715. Application.End (rsTestWindow);
  716. Application.End (rsTop);
  717. top.Dispose ();
  718. }
  719. [Fact]
  720. [AutoInitShutdown]
  721. public void Activating_MenuBar_By_Alt_Key_Does_Not_Throw ()
  722. {
  723. var menu = new MenuBar
  724. {
  725. Menus =
  726. [
  727. new ("Child", new MenuItem [] { new ("_Create Child", "", null) })
  728. ]
  729. };
  730. var topChild = new Toplevel ();
  731. topChild.Add (menu);
  732. var top = new Toplevel ();
  733. top.Add (topChild);
  734. Application.Begin (top);
  735. Exception exception = Record.Exception (() => topChild.NewKeyDownEvent (KeyCode.AltMask));
  736. Assert.Null (exception);
  737. top.Dispose ();
  738. }
  739. [Fact]
  740. [TestRespondersDisposed]
  741. public void Multi_Thread_Toplevels ()
  742. {
  743. Application.Init (new FakeDriver ());
  744. Toplevel t = new ();
  745. var w = new Window ();
  746. t.Add (w);
  747. int count = 0, count1 = 0, count2 = 0;
  748. bool log = false, log1 = false, log2 = false;
  749. var fromTopStillKnowFirstIsRunning = false;
  750. var fromTopStillKnowSecondIsRunning = false;
  751. var fromFirstStillKnowSecondIsRunning = false;
  752. Application.AddTimeout (
  753. TimeSpan.FromMilliseconds (100),
  754. () =>
  755. {
  756. count++;
  757. if (count1 == 5)
  758. {
  759. log1 = true;
  760. }
  761. if (count1 == 14 && count2 == 10 && count == 15)
  762. {
  763. // count2 is already stopped
  764. fromTopStillKnowFirstIsRunning = true;
  765. }
  766. if (count1 == 7 && count2 == 7 && count == 8)
  767. {
  768. fromTopStillKnowSecondIsRunning = true;
  769. }
  770. if (count == 30)
  771. {
  772. Assert.Equal (30, count);
  773. Assert.Equal (20, count1);
  774. Assert.Equal (10, count2);
  775. Assert.True (log);
  776. Assert.True (log1);
  777. Assert.True (log2);
  778. Assert.True (fromTopStillKnowFirstIsRunning);
  779. Assert.True (fromTopStillKnowSecondIsRunning);
  780. Assert.True (fromFirstStillKnowSecondIsRunning);
  781. Application.RequestStop ();
  782. return false;
  783. }
  784. return true;
  785. }
  786. );
  787. t.Ready += FirstWindow;
  788. void FirstWindow (object sender, EventArgs args)
  789. {
  790. var firstWindow = new Window ();
  791. firstWindow.Ready += SecondWindow;
  792. Application.AddTimeout (
  793. TimeSpan.FromMilliseconds (100),
  794. () =>
  795. {
  796. count1++;
  797. if (count2 == 5)
  798. {
  799. log2 = true;
  800. }
  801. if (count2 == 4 && count1 == 5 && count == 5)
  802. {
  803. fromFirstStillKnowSecondIsRunning = true;
  804. }
  805. if (count1 == 20)
  806. {
  807. Assert.Equal (20, count1);
  808. Application.RequestStop ();
  809. return false;
  810. }
  811. return true;
  812. }
  813. );
  814. Application.Run (firstWindow);
  815. firstWindow.Dispose ();
  816. }
  817. void SecondWindow (object sender, EventArgs args)
  818. {
  819. var testWindow = new Window ();
  820. Application.AddTimeout (
  821. TimeSpan.FromMilliseconds (100),
  822. () =>
  823. {
  824. count2++;
  825. if (count < 30)
  826. {
  827. log = true;
  828. }
  829. if (count2 == 10)
  830. {
  831. Assert.Equal (10, count2);
  832. Application.RequestStop ();
  833. return false;
  834. }
  835. return true;
  836. }
  837. );
  838. Application.Run (testWindow);
  839. testWindow.Dispose ();
  840. }
  841. Application.Run (t);
  842. t.Dispose ();
  843. Application.Shutdown ();
  844. }
  845. [Fact]
  846. public void Remove_Do_Not_Dispose_MenuBar_Or_StatusBar ()
  847. {
  848. var mb = new MenuBar ();
  849. var sb = new StatusBar ();
  850. var tl = new Toplevel ();
  851. #if DEBUG
  852. Assert.False (mb.WasDisposed);
  853. Assert.False (sb.WasDisposed);
  854. #endif
  855. tl.Add (mb, sb);
  856. Assert.NotNull (tl.MenuBar);
  857. //Assert.NotNull (tl.StatusBar);
  858. #if DEBUG
  859. Assert.False (mb.WasDisposed);
  860. Assert.False (sb.WasDisposed);
  861. #endif
  862. tl.RemoveAll ();
  863. Assert.Null (tl.MenuBar);
  864. //Assert.Null (tl.StatusBar);
  865. #if DEBUG
  866. Assert.False (mb.WasDisposed);
  867. Assert.False (sb.WasDisposed);
  868. #endif
  869. }
  870. }