StyleTests.cs 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  1. using System;
  2. using System.Collections.Generic;
  3. using Avalonia.Animation;
  4. using Avalonia.Base.UnitTests.Animation;
  5. using Avalonia.Controls;
  6. using Avalonia.Controls.Templates;
  7. using Avalonia.Data;
  8. using Avalonia.Media;
  9. using Avalonia.Styling;
  10. using Avalonia.UnitTests;
  11. using Moq;
  12. using Xunit;
  13. namespace Avalonia.Base.UnitTests.Styling
  14. {
  15. public class StyleTests : ScopedTestBase
  16. {
  17. [Fact]
  18. public void Style_With_Only_Type_Selector_Should_Update_Value()
  19. {
  20. Style style = new Style(x => x.OfType<Class1>())
  21. {
  22. Setters =
  23. {
  24. new Setter(Class1.FooProperty, "Foo"),
  25. },
  26. };
  27. var target = new Class1();
  28. StyleHelpers.TryAttach(style, target);
  29. Assert.Equal("Foo", target.Foo);
  30. }
  31. [Fact]
  32. public void Style_With_Class_Selector_Should_Update_And_Restore_Value()
  33. {
  34. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  35. {
  36. Setters =
  37. {
  38. new Setter(Class1.FooProperty, "Foo"),
  39. },
  40. };
  41. var target = new Class1();
  42. StyleHelpers.TryAttach(style, target);
  43. Assert.Equal("foodefault", target.Foo);
  44. target.Classes.Add("foo");
  45. Assert.Equal("Foo", target.Foo);
  46. target.Classes.Remove("foo");
  47. Assert.Equal("foodefault", target.Foo);
  48. }
  49. [Fact]
  50. public void Style_With_Class_Selector_Should_Update_And_Restore_Value_With_TemplateBinding()
  51. {
  52. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  53. {
  54. Setters =
  55. {
  56. new Setter(Class1.FooProperty, "Foo"),
  57. },
  58. };
  59. var templatedParent = new Class1 { Foo = "unset-foo" };
  60. var target = new Class1 { TemplatedParent = templatedParent };
  61. target.Bind(Class1.FooProperty, new TemplateBinding(Class1.FooProperty), BindingPriority.Template);
  62. StyleHelpers.TryAttach(style, target);
  63. Assert.Equal("unset-foo", target.Foo);
  64. target.Classes.Add("foo");
  65. Assert.Equal("Foo", target.Foo);
  66. target.Classes.Remove("foo");
  67. Assert.Equal("unset-foo", target.Foo);
  68. }
  69. [Fact]
  70. public void Style_With_No_Selector_Should_Apply_To_Containing_Control()
  71. {
  72. Style style = new Style
  73. {
  74. Setters =
  75. {
  76. new Setter(Class1.FooProperty, "Foo"),
  77. },
  78. };
  79. var target = new Class1();
  80. StyleHelpers.TryAttach(style, target);
  81. Assert.Equal("Foo", target.Foo);
  82. }
  83. [Fact]
  84. public void Should_Throw_For_Selector_With_Trailing_Template_Selector()
  85. {
  86. Assert.Throws<InvalidOperationException>(() =>
  87. new Style(x => x.OfType<Button>().Template()));
  88. }
  89. [Fact]
  90. public void Style_With_No_Selector_Should_Not_Apply_To_Other_Control()
  91. {
  92. Style style = new Style
  93. {
  94. Setters =
  95. {
  96. new Setter(Class1.FooProperty, "Foo"),
  97. },
  98. };
  99. var target = new Class1();
  100. var other = new Class1();
  101. StyleHelpers.TryAttach(style, target, host: other);
  102. Assert.Equal("foodefault", target.Foo);
  103. }
  104. [Fact]
  105. public void LocalValue_Should_Override_Style()
  106. {
  107. Style style = new Style(x => x.OfType<Class1>())
  108. {
  109. Setters =
  110. {
  111. new Setter(Class1.FooProperty, "Foo"),
  112. },
  113. };
  114. var target = new Class1
  115. {
  116. Foo = "Original",
  117. };
  118. StyleHelpers.TryAttach(style, target);
  119. Assert.Equal("Original", target.Foo);
  120. }
  121. [Fact]
  122. public void Later_Styles_Should_Override_Earlier()
  123. {
  124. Styles styles = new Styles
  125. {
  126. new Style(x => x.OfType<Class1>().Class("foo"))
  127. {
  128. Setters =
  129. {
  130. new Setter(Class1.FooProperty, "Foo"),
  131. },
  132. },
  133. new Style(x => x.OfType<Class1>().Class("foo"))
  134. {
  135. Setters =
  136. {
  137. new Setter(Class1.FooProperty, "Bar"),
  138. },
  139. }
  140. };
  141. var target = new Class1();
  142. List<string> values = new List<string>();
  143. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  144. styles.TryAttach(target, null);
  145. target.Classes.Add("foo");
  146. target.Classes.Remove("foo");
  147. Assert.Equal(new[] { "foodefault", "Bar", "foodefault" }, values);
  148. }
  149. [Fact]
  150. public void Later_Styles_Should_Override_Earlier_2()
  151. {
  152. Styles styles = new Styles
  153. {
  154. new Style(x => x.OfType<Class1>().Class("foo"))
  155. {
  156. Setters =
  157. {
  158. new Setter(Class1.FooProperty, "Foo"),
  159. },
  160. },
  161. new Style(x => x.OfType<Class1>().Class("bar"))
  162. {
  163. Setters =
  164. {
  165. new Setter(Class1.FooProperty, "Bar"),
  166. },
  167. }
  168. };
  169. var target = new Class1();
  170. List<string> values = new List<string>();
  171. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  172. styles.TryAttach(target, null);
  173. target.Classes.Add("bar");
  174. target.Classes.Add("foo");
  175. target.Classes.Remove("foo");
  176. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  177. }
  178. [Fact]
  179. public void Later_Styles_Should_Override_Earlier_3()
  180. {
  181. Styles styles = new Styles
  182. {
  183. new Style(x => x.OfType<Class1>().Class("foo"))
  184. {
  185. Setters =
  186. {
  187. new Setter(Class1.FooProperty, new Binding("Foo")),
  188. },
  189. },
  190. new Style(x => x.OfType<Class1>().Class("bar"))
  191. {
  192. Setters =
  193. {
  194. new Setter(Class1.FooProperty, new Binding("Bar")),
  195. },
  196. }
  197. };
  198. var target = new Class1
  199. {
  200. DataContext = new
  201. {
  202. Foo = "Foo",
  203. Bar = "Bar",
  204. }
  205. };
  206. List<string> values = new List<string>();
  207. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  208. styles.TryAttach(target, null);
  209. target.Classes.Add("bar");
  210. target.Classes.Add("foo");
  211. target.Classes.Remove("foo");
  212. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  213. }
  214. [Fact]
  215. public void Later_Styles_Should_Override_Earlier_4()
  216. {
  217. Styles styles = new Styles
  218. {
  219. new Style(x => x.OfType<Class1>().Class("foo"))
  220. {
  221. Setters =
  222. {
  223. new Setter(Class1.FooProperty, "foo1"),
  224. },
  225. },
  226. new Style(x => x.OfType<Class1>().Class("foo"))
  227. {
  228. Setters =
  229. {
  230. new Setter(Class1.FooProperty, "foo2"),
  231. new Setter(Class1.DoubleProperty, 123.4),
  232. },
  233. }
  234. };
  235. var target = new Class1();
  236. styles.TryAttach(target, null);
  237. target.Classes.Add("foo");
  238. Assert.Equal("foo2", target.Foo);
  239. Assert.Equal(123.4, target.Double);
  240. }
  241. [Fact]
  242. public void Later_Styles_Should_Override_Earlier_With_Begin_End_Styling()
  243. {
  244. Styles styles = new Styles
  245. {
  246. new Style(x => x.OfType<Class1>().Class("foo"))
  247. {
  248. Setters =
  249. {
  250. new Setter(Class1.FooProperty, "foo1"),
  251. new Setter(Class1.DoubleProperty, 123.4),
  252. },
  253. },
  254. new Style(x => x.OfType<Class1>().Class("foo").Class("bar"))
  255. {
  256. Setters =
  257. {
  258. new Setter(Class1.FooProperty, "foo2"),
  259. },
  260. },
  261. };
  262. var target = new Class1();
  263. target.GetValueStore().BeginStyling();
  264. styles.TryAttach(target, null);
  265. target.GetValueStore().EndStyling();
  266. target.Classes.Add("bar");
  267. target.Classes.Add("foo");
  268. Assert.Equal("foo2", target.Foo);
  269. Assert.Equal(123.4, target.Double);
  270. target.Classes.Remove("foo");
  271. Assert.Equal(0, target.Double);
  272. }
  273. [Fact]
  274. public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Attach()
  275. {
  276. var root = new TestRoot
  277. {
  278. Styles =
  279. {
  280. new Style(x => x.OfType<Class1>())
  281. {
  282. Setters =
  283. {
  284. new Setter(Class1.FooProperty, "Foo"),
  285. },
  286. },
  287. new Style(x => x.OfType<Class1>())
  288. {
  289. Setters =
  290. {
  291. new Setter(Class1.FooProperty, "Bar"),
  292. },
  293. }
  294. }
  295. };
  296. var values = new List<string>();
  297. var target = new Class1();
  298. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  299. root.Child = target;
  300. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  301. }
  302. [Fact]
  303. public void Inactive_Bindings_Should_Not_Be_Made_Active_During_Style_Attach()
  304. {
  305. var root = new TestRoot
  306. {
  307. Styles =
  308. {
  309. new Style(x => x.OfType<Class1>())
  310. {
  311. Setters =
  312. {
  313. new Setter(Class1.FooProperty, new Binding("Foo")),
  314. },
  315. },
  316. new Style(x => x.OfType<Class1>())
  317. {
  318. Setters =
  319. {
  320. new Setter(Class1.FooProperty, new Binding("Bar")),
  321. },
  322. }
  323. }
  324. };
  325. var values = new List<string>();
  326. var target = new Class1
  327. {
  328. DataContext = new
  329. {
  330. Foo = "Foo",
  331. Bar = "Bar",
  332. }
  333. };
  334. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  335. root.Child = target;
  336. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  337. }
  338. [Fact]
  339. public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Detach()
  340. {
  341. var root = new TestRoot
  342. {
  343. Styles =
  344. {
  345. new Style(x => x.OfType<Class1>())
  346. {
  347. Setters =
  348. {
  349. new Setter(Class1.FooProperty, "Foo"),
  350. },
  351. },
  352. new Style(x => x.OfType<Class1>())
  353. {
  354. Setters =
  355. {
  356. new Setter(Class1.FooProperty, "Bar"),
  357. },
  358. }
  359. }
  360. };
  361. var target = new Class1();
  362. root.Child = target;
  363. var values = new List<string>();
  364. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  365. root.Child = null;
  366. Assert.Equal(new[] { "Bar", "foodefault" }, values);
  367. }
  368. [Fact]
  369. public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Detach_2()
  370. {
  371. var root = new TestRoot
  372. {
  373. Styles =
  374. {
  375. new Style(x => x.OfType<Class1>().Class("foo"))
  376. {
  377. Setters =
  378. {
  379. new Setter(Class1.FooProperty, "Foo"),
  380. },
  381. },
  382. new Style(x => x.OfType<Class1>())
  383. {
  384. Setters =
  385. {
  386. new Setter(Class1.FooProperty, "Bar"),
  387. },
  388. }
  389. }
  390. };
  391. var target = new Class1 { Classes = { "foo" } };
  392. root.Child = target;
  393. var values = new List<string>();
  394. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  395. root.Child = null;
  396. Assert.Equal(new[] { "Foo", "foodefault" }, values);
  397. }
  398. [Fact]
  399. public void Inactive_Bindings_Should_Not_Be_Made_Active_During_Style_Detach()
  400. {
  401. var root = new TestRoot
  402. {
  403. Styles =
  404. {
  405. new Style(x => x.OfType<Class1>())
  406. {
  407. Setters =
  408. {
  409. new Setter(Class1.FooProperty, new Binding("Foo")),
  410. },
  411. },
  412. new Style(x => x.OfType<Class1>())
  413. {
  414. Setters =
  415. {
  416. new Setter(Class1.FooProperty, new Binding("Bar")),
  417. },
  418. }
  419. }
  420. };
  421. var target = new Class1
  422. {
  423. DataContext = new
  424. {
  425. Foo = "Foo",
  426. Bar = "Bar",
  427. }
  428. };
  429. root.Child = target;
  430. var values = new List<string>();
  431. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  432. root.Child = null;
  433. Assert.Equal(new[] { "Bar", "foodefault" }, values);
  434. }
  435. [Fact]
  436. public void Template_In_Non_Matching_Style_Is_Not_Built()
  437. {
  438. var instantiationCount = 0;
  439. var template = new FuncTemplate<Class1>(() =>
  440. {
  441. ++instantiationCount;
  442. return new Class1();
  443. });
  444. Styles styles = new Styles
  445. {
  446. new Style(x => x.OfType<Class1>().Class("foo"))
  447. {
  448. Setters =
  449. {
  450. new Setter(Class1.ChildProperty, template),
  451. },
  452. },
  453. new Style(x => x.OfType<Class1>())
  454. {
  455. Setters =
  456. {
  457. new Setter(Class1.ChildProperty, template),
  458. },
  459. }
  460. };
  461. var target = new Class1();
  462. styles.TryAttach(target, null);
  463. Assert.NotNull(target.Child);
  464. Assert.Equal(1, instantiationCount);
  465. }
  466. [Fact]
  467. public void Template_In_Inactive_Style_Is_Not_Built()
  468. {
  469. var instantiationCount = 0;
  470. var template = new FuncTemplate<Class1>(() =>
  471. {
  472. ++instantiationCount;
  473. return new Class1();
  474. });
  475. Styles styles = new Styles
  476. {
  477. new Style(x => x.OfType<Class1>())
  478. {
  479. Setters =
  480. {
  481. new Setter(Class1.ChildProperty, template),
  482. },
  483. },
  484. new Style(x => x.OfType<Class1>())
  485. {
  486. Setters =
  487. {
  488. new Setter(Class1.ChildProperty, template),
  489. },
  490. }
  491. };
  492. var target = new Class1();
  493. target.GetValueStore().BeginStyling();
  494. styles.TryAttach(target, null);
  495. target.GetValueStore().EndStyling();
  496. Assert.NotNull(target.Child);
  497. Assert.Equal(1, instantiationCount);
  498. }
  499. [Fact]
  500. public void Style_Should_Detach_When_Control_Removed_From_Logical_Tree()
  501. {
  502. Border border;
  503. var style = new Style(x => x.OfType<Border>())
  504. {
  505. Setters =
  506. {
  507. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  508. }
  509. };
  510. var root = new TestRoot
  511. {
  512. Child = border = new Border(),
  513. };
  514. StyleHelpers.TryAttach(style, border);
  515. Assert.Equal(new Thickness(4), border.BorderThickness);
  516. root.Child = null;
  517. Assert.Equal(new Thickness(0), border.BorderThickness);
  518. }
  519. [Fact]
  520. public void Removing_Style_Should_Detach_From_Control()
  521. {
  522. var border = new Border();
  523. var root = new TestRoot
  524. {
  525. Styles =
  526. {
  527. new Style(x => x.OfType<Border>())
  528. {
  529. Setters =
  530. {
  531. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  532. }
  533. }
  534. },
  535. Child = border,
  536. };
  537. root.Measure(Size.Infinity);
  538. Assert.Equal(new Thickness(4), border.BorderThickness);
  539. root.Styles.RemoveAt(0);
  540. Assert.Equal(new Thickness(0), border.BorderThickness);
  541. }
  542. [Fact]
  543. public void Adding_Style_Should_Attach_To_Control()
  544. {
  545. var border = new Border();
  546. var root = new TestRoot
  547. {
  548. Styles =
  549. {
  550. new Style(x => x.OfType<Border>())
  551. {
  552. Setters =
  553. {
  554. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  555. }
  556. }
  557. },
  558. Child = border,
  559. };
  560. root.Measure(Size.Infinity);
  561. Assert.Equal(new Thickness(4), border.BorderThickness);
  562. root.Styles.Add(new Style(x => x.OfType<Border>())
  563. {
  564. Setters =
  565. {
  566. new Setter(Border.BorderThicknessProperty, new Thickness(6)),
  567. }
  568. });
  569. root.Measure(Size.Infinity);
  570. Assert.Equal(new Thickness(6), border.BorderThickness);
  571. }
  572. [Fact]
  573. public void Removing_Style_With_Nested_Style_Should_Detach_From_Control()
  574. {
  575. var border = new Border();
  576. var root = new TestRoot
  577. {
  578. Styles =
  579. {
  580. new Styles
  581. {
  582. new Style(x => x.OfType<Border>())
  583. {
  584. Setters =
  585. {
  586. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  587. }
  588. }
  589. }
  590. },
  591. Child = border,
  592. };
  593. root.Measure(Size.Infinity);
  594. Assert.Equal(new Thickness(4), border.BorderThickness);
  595. root.Styles.RemoveAt(0);
  596. Assert.Equal(new Thickness(0), border.BorderThickness);
  597. }
  598. [Fact]
  599. public void Adding_Nested_Style_Should_Attach_To_Control()
  600. {
  601. var border = new Border();
  602. var root = new TestRoot
  603. {
  604. Styles =
  605. {
  606. new Styles
  607. {
  608. new Style(x => x.OfType<Border>())
  609. {
  610. Setters =
  611. {
  612. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  613. }
  614. }
  615. }
  616. },
  617. Child = border,
  618. };
  619. root.Measure(Size.Infinity);
  620. Assert.Equal(new Thickness(4), border.BorderThickness);
  621. ((Styles)root.Styles[0]).Add(new Style(x => x.OfType<Border>())
  622. {
  623. Setters =
  624. {
  625. new Setter(Border.BorderThicknessProperty, new Thickness(6)),
  626. }
  627. });
  628. root.Measure(Size.Infinity);
  629. Assert.Equal(new Thickness(6), border.BorderThickness);
  630. }
  631. [Fact]
  632. public void Removing_Nested_Style_Should_Detach_From_Control()
  633. {
  634. var border = new Border();
  635. var root = new TestRoot
  636. {
  637. Styles =
  638. {
  639. new Styles
  640. {
  641. new Style(x => x.OfType<Border>())
  642. {
  643. Setters =
  644. {
  645. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  646. }
  647. },
  648. new Style(x => x.OfType<Border>())
  649. {
  650. Setters =
  651. {
  652. new Setter(Border.BorderThicknessProperty, new Thickness(6)),
  653. }
  654. },
  655. }
  656. },
  657. Child = border,
  658. };
  659. root.Measure(Size.Infinity);
  660. Assert.Equal(new Thickness(6), border.BorderThickness);
  661. ((Styles)root.Styles[0]).RemoveAt(1);
  662. root.Measure(Size.Infinity);
  663. Assert.Equal(new Thickness(4), border.BorderThickness);
  664. }
  665. [Fact]
  666. public void Adding_Style_With_No_Setters_Or_Animations_Should_Not_Invalidate_Styles()
  667. {
  668. var border = new Border();
  669. var root = new TestRoot
  670. {
  671. Styles =
  672. {
  673. new Style(x => x.OfType<Border>())
  674. {
  675. Setters =
  676. {
  677. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  678. }
  679. }
  680. },
  681. Child = border,
  682. };
  683. root.Measure(Size.Infinity);
  684. Assert.Equal(new Thickness(4), border.BorderThickness);
  685. root.Styles.Add(new Style(x => x.OfType<Border>()));
  686. Assert.Equal(new Thickness(4), border.BorderThickness);
  687. }
  688. [Fact]
  689. public void Invalidating_Styles_Should_Detach_Activator()
  690. {
  691. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  692. {
  693. Setters =
  694. {
  695. new Setter(Class1.FooProperty, "Foo"),
  696. },
  697. };
  698. var target = new Class1();
  699. StyleHelpers.TryAttach(style, target);
  700. Assert.Equal(1, target.Classes.ListenerCount);
  701. target.InvalidateStyles(recurse: false);
  702. Assert.Equal(0, target.Classes.ListenerCount);
  703. }
  704. [Fact]
  705. public void Should_Set_Owner_On_Assigned_Resources()
  706. {
  707. var host = new Mock<IResourceHost>();
  708. var target = new Style();
  709. ((IResourceProvider)target).AddOwner(host.Object);
  710. var resources = new Mock<IResourceDictionary>();
  711. target.Resources = resources.Object;
  712. resources.Verify(x => x.AddOwner(host.Object), Times.Once);
  713. }
  714. [Fact]
  715. public void Should_Set_Owner_On_Assigned_Resources_2()
  716. {
  717. var host = new Mock<IResourceHost>();
  718. var target = new Style();
  719. var resources = new Mock<IResourceDictionary>();
  720. target.Resources = resources.Object;
  721. host.Invocations.Clear();
  722. ((IResourceProvider)target).AddOwner(host.Object);
  723. resources.Verify(x => x.AddOwner(host.Object), Times.Once);
  724. }
  725. [Fact]
  726. public void Nested_Style_Can_Be_Added()
  727. {
  728. var parent = new Style(x => x.OfType<Class1>());
  729. var nested = new Style(x => x.Nesting().Class("foo"));
  730. parent.Children.Add(nested);
  731. Assert.Same(parent, nested.Parent);
  732. }
  733. [Fact]
  734. public void Nested_Or_Style_Can_Be_Added()
  735. {
  736. var parent = new Style(x => x.OfType<Class1>());
  737. var nested = new Style(x => Selectors.Or(
  738. x.Nesting().Class("foo"),
  739. x.Nesting().Class("bar")));
  740. parent.Children.Add(nested);
  741. Assert.Same(parent, nested.Parent);
  742. }
  743. [Fact]
  744. public void Nested_Style_Without_Selector_Throws()
  745. {
  746. var parent = new Style(x => x.OfType<Class1>());
  747. var nested = new Style();
  748. Assert.Throws<InvalidOperationException>(() => parent.Children.Add(nested));
  749. }
  750. [Fact(Skip = "TODO")]
  751. public void Nested_Style_Without_Nesting_Operator_Throws()
  752. {
  753. var parent = new Style(x => x.OfType<Class1>());
  754. var nested = new Style(x => x.Class("foo"));
  755. Assert.Throws<InvalidOperationException>(() => parent.Children.Add(nested));
  756. }
  757. [Fact]
  758. public void Animations_Should_Be_Activated()
  759. {
  760. Style style = new Style(x => x.OfType<Class1>())
  761. {
  762. Animations =
  763. {
  764. new Avalonia.Animation.Animation
  765. {
  766. Duration = TimeSpan.FromSeconds(1),
  767. Children =
  768. {
  769. new KeyFrame
  770. {
  771. Setters =
  772. {
  773. new Setter { Property = Class1.DoubleProperty, Value = 5.0 }
  774. },
  775. },
  776. new KeyFrame
  777. {
  778. Setters =
  779. {
  780. new Setter { Property = Class1.DoubleProperty, Value = 10.0 }
  781. },
  782. Cue = new Cue(1d)
  783. }
  784. },
  785. }
  786. }
  787. };
  788. var clock = new TestClock();
  789. var target = new Class1 { Clock = clock };
  790. StyleHelpers.TryAttach(style, target);
  791. Assert.Equal(0.0, target.Double);
  792. clock.Step(TimeSpan.Zero);
  793. Assert.Equal(5.0, target.Double);
  794. clock.Step(TimeSpan.FromSeconds(0.5));
  795. Assert.Equal(7.5, target.Double);
  796. }
  797. [Fact]
  798. public void Animations_With_Trigger_Should_Be_Activated_And_Deactivated()
  799. {
  800. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  801. {
  802. Animations =
  803. {
  804. new Avalonia.Animation.Animation
  805. {
  806. Duration = TimeSpan.FromSeconds(1),
  807. Children =
  808. {
  809. new KeyFrame
  810. {
  811. Setters =
  812. {
  813. new Setter { Property = Class1.DoubleProperty, Value = 5.0 }
  814. },
  815. },
  816. new KeyFrame
  817. {
  818. Setters =
  819. {
  820. new Setter { Property = Class1.DoubleProperty, Value = 10.0 }
  821. },
  822. Cue = new Cue(1d)
  823. }
  824. },
  825. }
  826. }
  827. };
  828. var clock = new TestClock();
  829. var target = new Class1 { Clock = clock };
  830. StyleHelpers.TryAttach(style, target);
  831. Assert.Equal(0.0, target.Double);
  832. target.Classes.Add("foo");
  833. clock.Step(TimeSpan.Zero);
  834. Assert.Equal(5.0, target.Double);
  835. clock.Step(TimeSpan.FromSeconds(0.5));
  836. Assert.Equal(7.5, target.Double);
  837. target.Classes.Remove("foo");
  838. Assert.Equal(0.0, target.Double);
  839. }
  840. [Fact]
  841. public void Animations_With_Activator_Trigger_Should_Be_Activated_And_Deactivated()
  842. {
  843. var clock = new TestClock();
  844. var border = new Border();
  845. var root = new TestRoot
  846. {
  847. Clock = clock,
  848. Styles =
  849. {
  850. new Style(x => x.OfType<Border>().Not(default(Selector).Class("foo")))
  851. {
  852. Setters =
  853. {
  854. new Setter(Border.BackgroundProperty, Brushes.Yellow),
  855. },
  856. Animations =
  857. {
  858. new Avalonia.Animation.Animation
  859. {
  860. Duration = TimeSpan.FromSeconds(1.0),
  861. Children =
  862. {
  863. new KeyFrame
  864. {
  865. Setters =
  866. {
  867. new Setter(Border.BackgroundProperty, Brushes.Green)
  868. },
  869. Cue = new Cue(0.0)
  870. },
  871. new KeyFrame
  872. {
  873. Setters =
  874. {
  875. new Setter(Border.BackgroundProperty, Brushes.Green)
  876. },
  877. Cue = new Cue(1.0)
  878. }
  879. }
  880. }
  881. }
  882. },
  883. new Style(x => x.OfType<Border>().Class("foo"))
  884. {
  885. Setters =
  886. {
  887. new Setter(Border.BackgroundProperty, Brushes.Blue),
  888. }
  889. }
  890. },
  891. Child = border
  892. };
  893. root.Measure(Size.Infinity);
  894. Assert.Equal(Brushes.Yellow, border.Background);
  895. clock.Step(TimeSpan.FromSeconds(0.5));
  896. Assert.Equal(Brushes.Green, border.Background);
  897. border.Classes.Add("foo");
  898. Assert.Equal(Brushes.Blue, border.Background);
  899. }
  900. [Fact]
  901. public void Should_Not_Share_Instance_When_Or_Selector_Is_Present()
  902. {
  903. // Issue #13910
  904. Style style = new Style(x => Selectors.Or(x.OfType<Class1>(), x.OfType<Class2>().Class("bar")))
  905. {
  906. Setters =
  907. {
  908. new Setter(Class1.FooProperty, "Foo"),
  909. },
  910. };
  911. var target1 = new Class1 { Classes = { "foo" } };
  912. var target2 = new Class2();
  913. StyleHelpers.TryAttach(style, target1);
  914. StyleHelpers.TryAttach(style, target2);
  915. Assert.Equal("Foo", target1.Foo);
  916. Assert.Equal("foodefault", target2.Foo);
  917. }
  918. private class Class1 : Control
  919. {
  920. public static readonly StyledProperty<string> FooProperty =
  921. AvaloniaProperty.Register<Class1, string>(nameof(Foo), "foodefault");
  922. public static readonly StyledProperty<Class1> ChildProperty =
  923. AvaloniaProperty.Register<Class1, Class1>(nameof(Child));
  924. public static readonly StyledProperty<double> DoubleProperty =
  925. AvaloniaProperty.Register<Class1, double>(nameof(Double));
  926. public string Foo
  927. {
  928. get { return GetValue(FooProperty); }
  929. set { SetValue(FooProperty, value); }
  930. }
  931. public Class1 Child
  932. {
  933. get => GetValue(ChildProperty);
  934. set => SetValue(ChildProperty, value);
  935. }
  936. public double Double
  937. {
  938. get => GetValue(DoubleProperty);
  939. set => SetValue(DoubleProperty, value);
  940. }
  941. protected override Size MeasureOverride(Size availableSize)
  942. {
  943. throw new NotImplementedException();
  944. }
  945. }
  946. private class Class2 : Control
  947. {
  948. public static readonly StyledProperty<string> FooProperty =
  949. Class1.FooProperty.AddOwner<Class2>();
  950. public string Foo
  951. {
  952. get { return GetValue(FooProperty); }
  953. set { SetValue(FooProperty, value); }
  954. }
  955. protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
  956. {
  957. base.OnPropertyChanged(change);
  958. }
  959. }
  960. }
  961. }