SceneBuilderTests.cs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. using System.Linq;
  2. using System.Reactive.Subjects;
  3. using Avalonia.Controls;
  4. using Avalonia.Data;
  5. using Avalonia.Layout;
  6. using Avalonia.Media;
  7. using Avalonia.Media.Imaging;
  8. using Avalonia.Platform;
  9. using Avalonia.Rendering.SceneGraph;
  10. using Avalonia.UnitTests;
  11. using Avalonia.Utilities;
  12. using Avalonia.VisualTree;
  13. using Moq;
  14. using Xunit;
  15. namespace Avalonia.Base.UnitTests.Rendering.SceneGraph
  16. {
  17. public partial class SceneBuilderTests
  18. {
  19. [Fact]
  20. public void Should_Build_Initial_Scene()
  21. {
  22. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  23. {
  24. Border border;
  25. TextBlock textBlock;
  26. var tree = new TestRoot
  27. {
  28. Child = border = new Border
  29. {
  30. Width = 100,
  31. Height = 100,
  32. Background = Brushes.Red,
  33. Child = textBlock = new TextBlock
  34. {
  35. TextWrapping = TextWrapping.NoWrap,
  36. Text = "Hello World",
  37. }
  38. }
  39. };
  40. tree.Measure(Size.Infinity);
  41. tree.Arrange(new Rect(tree.DesiredSize));
  42. var result = new Scene(tree);
  43. var sceneBuilder = new SceneBuilder();
  44. sceneBuilder.UpdateAll(result);
  45. Assert.Same(tree, ((VisualNode)result.Root).LayerRoot);
  46. Assert.Equal(1, result.Root.Children.Count);
  47. var borderNode = (VisualNode)result.Root.Children[0];
  48. Assert.Same(borderNode, result.FindNode(border));
  49. Assert.Same(border, borderNode.Visual);
  50. Assert.Equal(1, borderNode.Children.Count);
  51. Assert.Equal(1, borderNode.DrawOperations.Count);
  52. var backgroundNode = (RectangleNode)borderNode.DrawOperations[0].Item;
  53. Assert.Equal(Brushes.Red, backgroundNode.Brush);
  54. var textBlockNode = borderNode.Children[0];
  55. Assert.Same(textBlockNode, result.FindNode(textBlock));
  56. Assert.Same(textBlock, textBlockNode.Visual);
  57. Assert.Equal(1, textBlockNode.DrawOperations.Count);
  58. var textNode = (GlyphRunNode)textBlockNode.DrawOperations[0].Item;
  59. Assert.NotNull(textNode.GlyphRun);
  60. }
  61. }
  62. [Fact]
  63. public void Should_Respect_Margin_For_ClipBounds()
  64. {
  65. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  66. {
  67. Canvas canvas;
  68. var tree = new TestRoot
  69. {
  70. Width = 200,
  71. Height = 300,
  72. Child = new Border
  73. {
  74. Margin = new Thickness(10, 20, 30, 40),
  75. Child = canvas = new Canvas
  76. {
  77. ClipToBounds = true,
  78. Background = Brushes.AliceBlue,
  79. }
  80. }
  81. };
  82. tree.Measure(Size.Infinity);
  83. tree.Arrange(new Rect(tree.DesiredSize));
  84. var result = new Scene(tree);
  85. var sceneBuilder = new SceneBuilder();
  86. sceneBuilder.UpdateAll(result);
  87. var canvasNode = result.FindNode(canvas);
  88. Assert.Equal(new Rect(10, 20, 160, 240), canvasNode.ClipBounds);
  89. // Initial ClipBounds are correct, make sure they're still correct after updating canvas.
  90. result = result.CloneScene();
  91. Assert.True(sceneBuilder.Update(result, canvas));
  92. canvasNode = result.FindNode(canvas);
  93. Assert.Equal(new Rect(10, 20, 160, 240), canvasNode.ClipBounds);
  94. }
  95. }
  96. [Fact]
  97. public void ClipBounds_Should_Be_Intersection_With_Parent_ClipBounds()
  98. {
  99. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  100. {
  101. Border border;
  102. var tree = new TestRoot
  103. {
  104. Width = 200,
  105. Height = 300,
  106. Child = new Canvas
  107. {
  108. ClipToBounds = true,
  109. Width = 100,
  110. Height = 100,
  111. HorizontalAlignment = HorizontalAlignment.Left,
  112. VerticalAlignment = VerticalAlignment.Top,
  113. Children =
  114. {
  115. (border = new Border
  116. {
  117. Background = Brushes.AliceBlue,
  118. ClipToBounds = true,
  119. Width = 100,
  120. Height = 100,
  121. [Canvas.LeftProperty] = 50,
  122. [Canvas.TopProperty] = 50,
  123. })
  124. }
  125. }
  126. };
  127. tree.Measure(Size.Infinity);
  128. tree.Arrange(new Rect(tree.DesiredSize));
  129. var scene = new Scene(tree);
  130. var sceneBuilder = new SceneBuilder();
  131. sceneBuilder.UpdateAll(scene);
  132. var borderNode = scene.FindNode(border);
  133. Assert.Equal(new Rect(50, 50, 50, 50), borderNode.ClipBounds);
  134. }
  135. }
  136. [Fact]
  137. public void Should_Update_Descendent_ClipBounds_When_Margin_Changed()
  138. {
  139. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  140. {
  141. Border border;
  142. Canvas canvas;
  143. var tree = new TestRoot
  144. {
  145. Width = 200,
  146. Height = 300,
  147. Child = canvas = new Canvas
  148. {
  149. ClipToBounds = true,
  150. Width = 100,
  151. Height = 100,
  152. HorizontalAlignment = HorizontalAlignment.Left,
  153. VerticalAlignment = VerticalAlignment.Top,
  154. Children =
  155. {
  156. (border = new Border
  157. {
  158. Background = Brushes.AliceBlue,
  159. ClipToBounds = true,
  160. Width = 100,
  161. Height = 100,
  162. [Canvas.LeftProperty] = 50,
  163. [Canvas.TopProperty] = 50,
  164. })
  165. }
  166. }
  167. };
  168. tree.Measure(Size.Infinity);
  169. tree.Arrange(new Rect(tree.DesiredSize));
  170. var scene = new Scene(tree);
  171. var sceneBuilder = new SceneBuilder();
  172. sceneBuilder.UpdateAll(scene);
  173. var borderNode = scene.FindNode(border);
  174. Assert.Equal(new Rect(50, 50, 50, 50), borderNode.ClipBounds);
  175. canvas.Width = canvas.Height = 125;
  176. canvas.Measure(Size.Infinity);
  177. canvas.Arrange(new Rect(tree.DesiredSize));
  178. // Initial ClipBounds are correct, make sure they're still correct after updating canvas.
  179. scene = scene.CloneScene();
  180. Assert.True(sceneBuilder.Update(scene, canvas));
  181. borderNode = scene.FindNode(border);
  182. Assert.Equal(new Rect(50, 50, 75, 75), borderNode.ClipBounds);
  183. }
  184. }
  185. [Fact]
  186. public void Should_Respect_ZIndex()
  187. {
  188. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  189. {
  190. Border front;
  191. Border back;
  192. var tree = new TestRoot
  193. {
  194. Child = new Panel
  195. {
  196. Children =
  197. {
  198. (front = new Border
  199. {
  200. ZIndex = 1,
  201. }),
  202. (back = new Border
  203. {
  204. ZIndex = 0,
  205. }),
  206. }
  207. }
  208. };
  209. var result = new Scene(tree);
  210. var sceneBuilder = new SceneBuilder();
  211. sceneBuilder.UpdateAll(result);
  212. var panelNode = result.FindNode(tree.Child);
  213. var expected = new IVisual[] { back, front };
  214. var actual = panelNode.Children.OfType<IVisualNode>().Select(x => x.Visual).ToArray();
  215. Assert.Equal(expected, actual);
  216. }
  217. }
  218. [Fact]
  219. public void Should_Respect_Uniform_ZIndex()
  220. {
  221. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  222. {
  223. Panel panel;
  224. var tree = new TestRoot
  225. {
  226. Child = panel = new Panel()
  227. };
  228. for (var i = 0; i < 128; i++)
  229. {
  230. panel.Children.Add(new Border());
  231. }
  232. var result = new Scene(tree);
  233. var sceneBuilder = new SceneBuilder();
  234. sceneBuilder.UpdateAll(result);
  235. var panelNode = result.FindNode(tree.Child);
  236. var expected = panel.Children.ToArray();
  237. var actual = panelNode.Children.OfType<IVisualNode>().Select(x => x.Visual).ToArray();
  238. Assert.Equal(expected, actual);
  239. }
  240. }
  241. [Fact]
  242. public void ClipBounds_Should_Be_In_Global_Coordinates()
  243. {
  244. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  245. {
  246. Border target;
  247. var tree = new TestRoot
  248. {
  249. Child = new Decorator
  250. {
  251. Margin = new Thickness(24, 26),
  252. Child = target = new Border
  253. {
  254. ClipToBounds = true,
  255. Margin = new Thickness(26, 24),
  256. Width = 100,
  257. Height = 100,
  258. }
  259. }
  260. };
  261. tree.Measure(Size.Infinity);
  262. tree.Arrange(new Rect(tree.DesiredSize));
  263. var result = new Scene(tree);
  264. var sceneBuilder = new SceneBuilder();
  265. sceneBuilder.UpdateAll(result);
  266. var targetNode = result.FindNode(target);
  267. Assert.Equal(new Rect(50, 50, 100, 100), targetNode.ClipBounds);
  268. }
  269. }
  270. [Fact]
  271. public void Transform_For_Control_With_RenderTransform_Should_Be_Correct_After_Update()
  272. {
  273. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  274. {
  275. Border border;
  276. var tree = new TestRoot
  277. {
  278. Width = 400,
  279. Height = 200,
  280. Child = new Decorator
  281. {
  282. Width = 200,
  283. Height = 100,
  284. Child = border = new Border
  285. {
  286. Background = Brushes.Red,
  287. HorizontalAlignment = HorizontalAlignment.Right,
  288. Width = 100,
  289. RenderTransform = new ScaleTransform(0.5, 1),
  290. }
  291. }
  292. };
  293. tree.Measure(Size.Infinity);
  294. tree.Arrange(new Rect(tree.DesiredSize));
  295. var scene = new Scene(tree);
  296. var sceneBuilder = new SceneBuilder();
  297. sceneBuilder.UpdateAll(scene);
  298. var expectedTransform = Matrix.CreateScale(0.5, 1) * Matrix.CreateTranslation(225, 50);
  299. var borderNode = scene.FindNode(border);
  300. Assert.Equal(expectedTransform, borderNode.Transform);
  301. scene = scene.CloneScene();
  302. Assert.True(sceneBuilder.Update(scene, border));
  303. borderNode = scene.FindNode(border);
  304. Assert.Equal(expectedTransform, borderNode.Transform);
  305. }
  306. }
  307. [Fact]
  308. public void MirrorTransform_For_Control_With_RenderTransform_Should_Be_Correct()
  309. {
  310. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  311. {
  312. Border border;
  313. var tree = new TestRoot
  314. {
  315. Width = 400,
  316. Height = 200,
  317. Child = border = new Border
  318. {
  319. HorizontalAlignment = HorizontalAlignment.Left,
  320. Background = Brushes.Red,
  321. Width = 100,
  322. RenderTransform = new ScaleTransform(0.5, 1),
  323. FlowDirection = FlowDirection.RightToLeft
  324. }
  325. };
  326. tree.Measure(Size.Infinity);
  327. tree.Arrange(new Rect(tree.DesiredSize));
  328. var scene = new Scene(tree);
  329. var sceneBuilder = new SceneBuilder();
  330. sceneBuilder.UpdateAll(scene);
  331. var expectedTransform = new Matrix(-1, 0, 0, 1, 100, 0) * Matrix.CreateScale(0.5, 1) * Matrix.CreateTranslation(25, 0);
  332. var borderNode = scene.FindNode(border);
  333. Assert.Equal(expectedTransform, borderNode.Transform);
  334. }
  335. }
  336. [Fact]
  337. public void Should_Update_Border_Background_Node()
  338. {
  339. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  340. {
  341. Border border;
  342. TextBlock textBlock;
  343. var tree = new TestRoot
  344. {
  345. Child = border = new Border
  346. {
  347. Width = 100,
  348. Height = 100,
  349. Background = Brushes.Red,
  350. Child = textBlock = new TextBlock
  351. {
  352. Foreground = Brushes.Green,
  353. Text = "Hello World",
  354. }
  355. }
  356. };
  357. tree.Measure(Size.Infinity);
  358. tree.Arrange(new Rect(tree.DesiredSize));
  359. var initial = new Scene(tree);
  360. var sceneBuilder = new SceneBuilder();
  361. sceneBuilder.UpdateAll(initial);
  362. var initialBackgroundNode = initial.FindNode(border).Children[0];
  363. var initialTextNode = initial.FindNode(textBlock).DrawOperations[0];
  364. Assert.NotNull(initialBackgroundNode);
  365. Assert.NotNull(initialTextNode);
  366. border.Background = Brushes.Green;
  367. var result = initial.CloneScene();
  368. sceneBuilder.Update(result, border);
  369. var borderNode = (VisualNode)result.Root.Children[0];
  370. Assert.Same(border, borderNode.Visual);
  371. var backgroundNode = (RectangleNode)borderNode.DrawOperations[0].Item;
  372. Assert.NotSame(initialBackgroundNode, backgroundNode);
  373. Assert.Equal(Brushes.Green, backgroundNode.Brush);
  374. var textBlockNode = (VisualNode)borderNode.Children[0];
  375. Assert.Same(textBlock, textBlockNode.Visual);
  376. var textNode = (GlyphRunNode)textBlockNode.DrawOperations[0].Item;
  377. Assert.Same(initialTextNode.Item, textNode);
  378. }
  379. }
  380. [Fact]
  381. public void Should_Update_When_Control_Added()
  382. {
  383. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  384. {
  385. Border border;
  386. var tree = new TestRoot
  387. {
  388. Width = 100,
  389. Height = 100,
  390. Child = border = new Border
  391. {
  392. Background = Brushes.Red,
  393. }
  394. };
  395. Canvas canvas;
  396. var decorator = new Decorator
  397. {
  398. Child = canvas = new Canvas(),
  399. };
  400. tree.Measure(Size.Infinity);
  401. tree.Arrange(new Rect(tree.DesiredSize));
  402. var initial = new Scene(tree);
  403. var sceneBuilder = new SceneBuilder();
  404. sceneBuilder.UpdateAll(initial);
  405. border.Child = decorator;
  406. var result = initial.CloneScene();
  407. Assert.True(sceneBuilder.Update(result, decorator));
  408. // Updating canvas should result in no-op as it should have been updated along
  409. // with decorator as part of the add opeation.
  410. Assert.False(sceneBuilder.Update(result, canvas));
  411. var borderNode = (VisualNode)result.Root.Children[0];
  412. Assert.Equal(1, borderNode.Children.Count);
  413. Assert.Equal(1, borderNode.DrawOperations.Count);
  414. var decoratorNode = (VisualNode)borderNode.Children[0];
  415. Assert.Same(decorator, decoratorNode.Visual);
  416. Assert.Same(decoratorNode, result.FindNode(decorator));
  417. var canvasNode = (VisualNode)decoratorNode.Children[0];
  418. Assert.Same(canvas, canvasNode.Visual);
  419. Assert.Same(canvasNode, result.FindNode(canvas));
  420. }
  421. }
  422. [Fact]
  423. public void Should_Update_When_Control_Removed()
  424. {
  425. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  426. {
  427. Border border;
  428. Decorator decorator;
  429. Canvas canvas;
  430. var tree = new TestRoot
  431. {
  432. Width = 100,
  433. Height = 100,
  434. Child = border = new Border
  435. {
  436. Background = Brushes.Red,
  437. Child = decorator = new Decorator
  438. {
  439. Child = canvas = new Canvas
  440. {
  441. Background = Brushes.AliceBlue,
  442. }
  443. }
  444. }
  445. };
  446. tree.Measure(Size.Infinity);
  447. tree.Arrange(new Rect(tree.DesiredSize));
  448. var initial = new Scene(tree);
  449. var sceneBuilder = new SceneBuilder();
  450. sceneBuilder.UpdateAll(initial);
  451. border.Child = null;
  452. var result = initial.CloneScene();
  453. Assert.True(sceneBuilder.Update(result, decorator));
  454. Assert.False(sceneBuilder.Update(result, canvas));
  455. var borderNode = (VisualNode)result.Root.Children[0];
  456. Assert.Equal(0, borderNode.Children.Count);
  457. Assert.Equal(1, borderNode.DrawOperations.Count);
  458. Assert.Null(result.FindNode(decorator));
  459. Assert.Equal(new Rect(0, 0, 100, 100), result.Layers.Single().Dirty.Single());
  460. }
  461. }
  462. [Fact]
  463. public void Should_Update_When_Control_Moved()
  464. {
  465. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  466. {
  467. Decorator moveFrom;
  468. Decorator moveTo;
  469. Canvas moveMe;
  470. var tree = new TestRoot
  471. {
  472. Width = 100,
  473. Height = 100,
  474. Child = new StackPanel
  475. {
  476. Children =
  477. {
  478. (moveFrom = new Decorator
  479. {
  480. Child = moveMe = new Canvas(),
  481. }),
  482. (moveTo = new Decorator()),
  483. }
  484. }
  485. };
  486. tree.Measure(Size.Infinity);
  487. tree.Arrange(new Rect(tree.DesiredSize));
  488. var scene = new Scene(tree);
  489. var sceneBuilder = new SceneBuilder();
  490. sceneBuilder.UpdateAll(scene);
  491. var moveFromNode = (VisualNode)scene.FindNode(moveFrom);
  492. var moveToNode = (VisualNode)scene.FindNode(moveTo);
  493. Assert.Equal(1, moveFromNode.Children.Count);
  494. Assert.Same(moveMe, moveFromNode.Children[0].Visual);
  495. Assert.Empty(moveToNode.Children);
  496. moveFrom.Child = null;
  497. moveTo.Child = moveMe;
  498. scene = scene.CloneScene();
  499. moveFromNode = (VisualNode)scene.FindNode(moveFrom);
  500. moveToNode = (VisualNode)scene.FindNode(moveTo);
  501. moveFromNode.SortChildren(scene);
  502. moveToNode.SortChildren(scene);
  503. sceneBuilder.Update(scene, moveFrom);
  504. sceneBuilder.Update(scene, moveTo);
  505. sceneBuilder.Update(scene, moveMe);
  506. Assert.Empty(moveFromNode.Children);
  507. Assert.Equal(1, moveToNode.Children.Count);
  508. Assert.Same(moveMe, moveToNode.Children[0].Visual);
  509. }
  510. }
  511. [Fact]
  512. public void Should_Update_When_Control_Made_Invisible()
  513. {
  514. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  515. {
  516. Decorator decorator;
  517. Border border;
  518. Canvas canvas;
  519. var tree = new TestRoot
  520. {
  521. Width = 100,
  522. Height = 100,
  523. Child = decorator = new Decorator
  524. {
  525. Child = border = new Border
  526. {
  527. Background = Brushes.Red,
  528. Child = canvas = new Canvas(),
  529. }
  530. }
  531. };
  532. tree.Measure(Size.Infinity);
  533. tree.Arrange(new Rect(tree.DesiredSize));
  534. var initial = new Scene(tree);
  535. var sceneBuilder = new SceneBuilder();
  536. sceneBuilder.UpdateAll(initial);
  537. border.IsVisible = false;
  538. var result = initial.CloneScene();
  539. Assert.True(sceneBuilder.Update(result, border));
  540. Assert.False(sceneBuilder.Update(result, canvas));
  541. var decoratorNode = (VisualNode)result.Root.Children[0];
  542. Assert.Equal(0, decoratorNode.Children.Count);
  543. Assert.Null(result.FindNode(border));
  544. Assert.Null(result.FindNode(canvas));
  545. Assert.Equal(new Rect(0, 0, 100, 100), result.Layers.Single().Dirty.Single());
  546. }
  547. }
  548. [Fact]
  549. public void Should_Not_Dispose_Active_VisualNode_When_Control_Reparented_And_Child_Made_Invisible()
  550. {
  551. // Issue #3115
  552. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  553. {
  554. StackPanel panel;
  555. Border border1;
  556. Border border2;
  557. var tree = new TestRoot
  558. {
  559. Width = 100,
  560. Height = 100,
  561. Child = panel = new StackPanel
  562. {
  563. Children =
  564. {
  565. (border1 = new Border
  566. {
  567. Background = Brushes.Red,
  568. }),
  569. (border2 = new Border
  570. {
  571. Background = Brushes.Green,
  572. }),
  573. }
  574. }
  575. };
  576. tree.Measure(Size.Infinity);
  577. tree.Arrange(new Rect(tree.DesiredSize));
  578. var scene = new Scene(tree);
  579. var sceneBuilder = new SceneBuilder();
  580. sceneBuilder.UpdateAll(scene);
  581. var decorator = new Decorator();
  582. tree.Child = null;
  583. decorator.Child = panel;
  584. tree.Child = decorator;
  585. border1.IsVisible = false;
  586. scene = scene.CloneScene();
  587. sceneBuilder.Update(scene, decorator);
  588. var panelNode = (VisualNode)scene.FindNode(panel);
  589. Assert.Equal(2, panelNode.Children.Count);
  590. Assert.False(panelNode.Children[0].Disposed);
  591. Assert.False(panelNode.Children[1].Disposed);
  592. }
  593. }
  594. [Fact]
  595. public void Should_Update_ClipBounds_For_Negative_Margin()
  596. {
  597. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  598. {
  599. Decorator decorator;
  600. Border border;
  601. var tree = new TestRoot
  602. {
  603. Width = 100,
  604. Height = 100,
  605. Child = decorator = new Decorator
  606. {
  607. Margin = new Thickness(0, 10, 0, 0),
  608. Child = border = new Border
  609. {
  610. Background = Brushes.Red,
  611. ClipToBounds = true,
  612. Margin = new Thickness(0, -5, 0, 0),
  613. }
  614. }
  615. };
  616. var layout = tree.LayoutManager;
  617. layout.ExecuteInitialLayoutPass();
  618. var scene = new Scene(tree);
  619. var sceneBuilder = new SceneBuilder();
  620. sceneBuilder.UpdateAll(scene);
  621. var borderNode = scene.FindNode(border);
  622. Assert.Equal(new Rect(0, 5, 100, 95), borderNode.ClipBounds);
  623. border.Margin = new Thickness(0, -8, 0, 0);
  624. layout.ExecuteLayoutPass();
  625. scene = scene.CloneScene();
  626. sceneBuilder.Update(scene, border);
  627. borderNode = scene.FindNode(border);
  628. Assert.Equal(new Rect(0, 2, 100, 98), borderNode.ClipBounds);
  629. }
  630. }
  631. [Fact]
  632. public void Should_Update_Descendent_Tranform_When_Margin_Changed()
  633. {
  634. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  635. {
  636. Decorator decorator;
  637. Border border;
  638. Canvas canvas;
  639. var tree = new TestRoot
  640. {
  641. Width = 100,
  642. Height = 100,
  643. Child = decorator = new Decorator
  644. {
  645. Margin = new Thickness(0, 10, 0, 0),
  646. Child = border = new Border
  647. {
  648. Child = canvas = new Canvas(),
  649. }
  650. }
  651. };
  652. var layout = tree.LayoutManager;
  653. layout.ExecuteInitialLayoutPass();
  654. var scene = new Scene(tree);
  655. var sceneBuilder = new SceneBuilder();
  656. sceneBuilder.UpdateAll(scene);
  657. var borderNode = scene.FindNode(border);
  658. var canvasNode = scene.FindNode(canvas);
  659. Assert.Equal(Matrix.CreateTranslation(0, 10), borderNode.Transform);
  660. Assert.Equal(Matrix.CreateTranslation(0, 10), canvasNode.Transform);
  661. decorator.Margin = new Thickness(0, 20, 0, 0);
  662. layout.ExecuteLayoutPass();
  663. scene = scene.CloneScene();
  664. sceneBuilder.Update(scene, decorator);
  665. borderNode = scene.FindNode(border);
  666. canvasNode = scene.FindNode(canvas);
  667. Assert.Equal(Matrix.CreateTranslation(0, 20), borderNode.Transform);
  668. Assert.Equal(Matrix.CreateTranslation(0, 20), canvasNode.Transform);
  669. }
  670. }
  671. [Fact]
  672. public void DirtyRects_Should_Contain_Old_And_New_Bounds_When_Margin_Changed()
  673. {
  674. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  675. {
  676. Decorator decorator;
  677. Border border;
  678. Canvas canvas;
  679. var tree = new TestRoot
  680. {
  681. Width = 100,
  682. Height = 100,
  683. Child = decorator = new Decorator
  684. {
  685. Margin = new Thickness(0, 10, 0, 0),
  686. Child = border = new Border
  687. {
  688. Background = Brushes.Red,
  689. Child = canvas = new Canvas(),
  690. }
  691. }
  692. };
  693. var layout = tree.LayoutManager;
  694. layout.ExecuteInitialLayoutPass();
  695. var scene = new Scene(tree);
  696. var sceneBuilder = new SceneBuilder();
  697. sceneBuilder.UpdateAll(scene);
  698. var borderNode = scene.FindNode(border);
  699. var canvasNode = scene.FindNode(canvas);
  700. Assert.Equal(Matrix.CreateTranslation(0, 10), borderNode.Transform);
  701. Assert.Equal(Matrix.CreateTranslation(0, 10), canvasNode.Transform);
  702. decorator.Margin = new Thickness(0, 20, 0, 0);
  703. layout.ExecuteLayoutPass();
  704. scene = scene.CloneScene();
  705. sceneBuilder.Update(scene, decorator);
  706. var rects = scene.Layers.Single().Dirty.ToArray();
  707. Assert.Equal(new[] { new Rect(0, 10, 100, 90) }, rects);
  708. }
  709. }
  710. [Fact]
  711. public void Resizing_Scene_Should_Add_DirtyRects()
  712. {
  713. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  714. {
  715. Decorator decorator;
  716. Border border;
  717. Canvas canvas;
  718. var tree = new TestRoot
  719. {
  720. ClientSize = new Size(100, 100),
  721. Child = decorator = new Decorator
  722. {
  723. Margin = new Thickness(0, 10, 0, 0),
  724. Child = border = new Border
  725. {
  726. Background = Brushes.Red,
  727. Child = canvas = new Canvas(),
  728. }
  729. }
  730. };
  731. var animation = new BehaviorSubject<double>(0.5);
  732. border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
  733. var scene = new Scene(tree);
  734. var sceneBuilder = new SceneBuilder();
  735. sceneBuilder.UpdateAll(scene);
  736. Assert.Equal(new Size(100, 100), scene.Size);
  737. tree.ClientSize = new Size(110, 120);
  738. scene = scene.CloneScene();
  739. sceneBuilder.Update(scene, tree);
  740. Assert.Equal(new Size(110, 120), scene.Size);
  741. var expected = new[]
  742. {
  743. new Rect(100, 0, 10, 100),
  744. new Rect(0, 100, 110, 20),
  745. };
  746. Assert.Equal(expected, scene.Layers[tree].Dirty.ToArray());
  747. // Layers are disabled. See #2244
  748. // Assert.Equal(expected, scene.Layers[border].Dirty.ToArray());
  749. }
  750. }
  751. [Fact]
  752. public void Setting_Opacity_Should_Add_Descendent_Bounds_To_DirtyRects()
  753. {
  754. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  755. {
  756. Decorator decorator;
  757. Border border;
  758. var tree = new TestRoot
  759. {
  760. Child = decorator = new Decorator
  761. {
  762. Child = border = new Border
  763. {
  764. Background = Brushes.Red,
  765. Width = 100,
  766. Height = 100,
  767. }
  768. }
  769. };
  770. tree.Measure(Size.Infinity);
  771. tree.Arrange(new Rect(tree.DesiredSize));
  772. var scene = new Scene(tree);
  773. var sceneBuilder = new SceneBuilder();
  774. sceneBuilder.UpdateAll(scene);
  775. decorator.Opacity = 0.5;
  776. scene = scene.CloneScene();
  777. sceneBuilder.Update(scene, decorator);
  778. Assert.NotEmpty(scene.Layers.Single().Dirty);
  779. var dirty = scene.Layers.Single().Dirty.Single();
  780. Assert.Equal(new Rect(0, 0, 100, 100), dirty);
  781. }
  782. }
  783. [Fact]
  784. public void Should_Set_GeometryClip()
  785. {
  786. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  787. {
  788. var clip = StreamGeometry.Parse("M100,0 L0,100 100,100");
  789. Decorator decorator;
  790. var tree = new TestRoot
  791. {
  792. Child = decorator = new Decorator
  793. {
  794. Clip = clip,
  795. }
  796. };
  797. var scene = new Scene(tree);
  798. var sceneBuilder = new SceneBuilder();
  799. sceneBuilder.UpdateAll(scene);
  800. var decoratorNode = scene.FindNode(decorator);
  801. Assert.Same(clip.PlatformImpl, decoratorNode.GeometryClip);
  802. }
  803. }
  804. [Fact]
  805. public void Disposing_Scene_Releases_DrawOperation_References()
  806. {
  807. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  808. {
  809. var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>(
  810. x => x.PixelSize == new PixelSize(100, 100) &&
  811. x.Dpi == new Vector(96, 96)));
  812. Image img;
  813. var tree = new TestRoot
  814. {
  815. Child = img = new Image
  816. {
  817. Source = new Bitmap(bitmap),
  818. Height = 100,
  819. Width = 100
  820. }
  821. };
  822. tree.Measure(Size.Infinity);
  823. tree.Arrange(new Rect(new Size(100, 100)));
  824. Assert.Equal(2, bitmap.RefCount);
  825. IRef<IDrawOperation> operation;
  826. using (var scene = new Scene(tree))
  827. {
  828. var sceneBuilder = new SceneBuilder();
  829. sceneBuilder.UpdateAll(scene);
  830. operation = scene.FindNode(img).DrawOperations[0];
  831. Assert.Equal(1, operation.RefCount);
  832. Assert.Equal(3, bitmap.RefCount);
  833. }
  834. Assert.Equal(0, operation.RefCount);
  835. Assert.Equal(2, bitmap.RefCount);
  836. }
  837. }
  838. [Fact]
  839. public void Replacing_Control_Releases_DrawOperation_Reference()
  840. {
  841. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  842. {
  843. var bitmap = RefCountable.Create(Mock.Of<IBitmapImpl>(
  844. x => x.PixelSize == new PixelSize(100, 100) &&
  845. x.Dpi == new Vector(96, 96)));
  846. Image img;
  847. var tree = new TestRoot
  848. {
  849. Child = img = new Image
  850. {
  851. Source = new Bitmap(bitmap),
  852. Width = 100,
  853. Height = 100
  854. }
  855. };
  856. tree.Measure(Size.Infinity);
  857. tree.Arrange(new Rect(new Size(100, 100)));
  858. var scene = new Scene(tree);
  859. var sceneBuilder = new SceneBuilder();
  860. sceneBuilder.UpdateAll(scene);
  861. var operation = scene.FindNode(img).DrawOperations[0];
  862. tree.Child = new Decorator();
  863. using (var result = scene.CloneScene())
  864. {
  865. sceneBuilder.Update(result, img);
  866. scene.Dispose();
  867. Assert.Equal(0, operation.RefCount);
  868. Assert.Equal(2, bitmap.RefCount);
  869. }
  870. }
  871. }
  872. }
  873. }