ControlTheme_Change.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.CompilerServices;
  4. using Avalonia.Controls;
  5. using Avalonia.Media;
  6. using Avalonia.Styling;
  7. using Avalonia.UnitTests;
  8. using BenchmarkDotNet.Attributes;
  9. namespace Avalonia.Benchmarks.Styling
  10. {
  11. [MemoryDiagnoser]
  12. public class ControlTheme_Change : IDisposable
  13. {
  14. private readonly IDisposable _app;
  15. private readonly TestRoot _root;
  16. private readonly TextBox _control;
  17. private readonly ControlTheme _theme1;
  18. private readonly ControlTheme _theme2;
  19. public ControlTheme_Change()
  20. {
  21. _app = UnitTestApplication.Start(TestServices.StyledWindow);
  22. // Simulate an application with a lot of styles by creating a tree of nested panels,
  23. // each with a bunch of styles applied.
  24. var (rootPanel, leafPanel) = CreateNestedPanels(10);
  25. // We're benchmarking how long it takes to switch control theme on a TextBox in this
  26. // situation.
  27. var baseTheme = (ControlTheme)Application.Current.FindResource(typeof(TextBox)) ??
  28. throw new Exception("Base TextBox theme not found.");
  29. _theme1 = new ControlTheme(typeof(TextBox))
  30. {
  31. BasedOn = baseTheme,
  32. Setters = { new Setter(TextBox.BackgroundProperty, Brushes.Red) },
  33. };
  34. _theme2 = new ControlTheme(typeof(TextBox))
  35. {
  36. BasedOn = baseTheme,
  37. Setters = { new Setter(TextBox.BackgroundProperty, Brushes.Green) },
  38. };
  39. _control = new TextBox { Theme = _theme1 };
  40. leafPanel.Children.Add(_control);
  41. _root = new TestRoot(true, rootPanel)
  42. {
  43. Renderer = new NullRenderer(),
  44. };
  45. _root.LayoutManager.ExecuteInitialLayoutPass();
  46. }
  47. [Benchmark]
  48. [MethodImpl(MethodImplOptions.NoInlining)]
  49. public void Change_ControlTheme()
  50. {
  51. if (_control.Background != Brushes.Red)
  52. throw new Exception("Invalid benchmark state");
  53. _control.Theme = _theme2;
  54. _root.LayoutManager.ExecuteLayoutPass();
  55. if (_control.Background != Brushes.Green)
  56. throw new Exception("Invalid benchmark state");
  57. _control.Theme = _theme1;
  58. _root.LayoutManager.ExecuteLayoutPass();
  59. if (_control.Background != Brushes.Red)
  60. throw new Exception("Invalid benchmark state");
  61. }
  62. public void Dispose()
  63. {
  64. _app.Dispose();
  65. }
  66. private static (Panel, Panel) CreateNestedPanels(int count)
  67. {
  68. var root = new Panel();
  69. var last = root;
  70. for (var i = 0; i < count; ++i)
  71. {
  72. var panel = new Panel();
  73. panel.Styles.AddRange(CreateStyles());
  74. last.Children.Add(panel);
  75. last = panel;
  76. }
  77. return (root, last);
  78. }
  79. private static IEnumerable<IStyle> CreateStyles()
  80. {
  81. var types = new[]
  82. {
  83. typeof(Border),
  84. typeof(Button),
  85. typeof(ButtonSpinner),
  86. typeof(Carousel),
  87. typeof(CheckBox),
  88. typeof(ComboBox),
  89. typeof(ContentControl),
  90. typeof(Expander),
  91. typeof(ItemsControl),
  92. typeof(Label),
  93. typeof(ListBox),
  94. typeof(ProgressBar),
  95. typeof(RadioButton),
  96. typeof(RepeatButton),
  97. typeof(ScrollViewer),
  98. typeof(Slider),
  99. typeof(Spinner),
  100. typeof(SplitView),
  101. typeof(TextBox),
  102. typeof(ToggleSwitch),
  103. typeof(TreeView),
  104. typeof(Viewbox),
  105. typeof(Window),
  106. };
  107. foreach (var type in types)
  108. {
  109. yield return new Style(x => x.OfType(type))
  110. {
  111. Setters = { new Setter(Control.TagProperty, type.Name) }
  112. };
  113. yield return new Style(x => x.OfType(type).Class("foo"))
  114. {
  115. Setters = { new Setter(Control.TagProperty, type.Name + " foo") }
  116. };
  117. yield return new Style(x => x.OfType(type).Class("bar"))
  118. {
  119. Setters = { new Setter(Control.TagProperty, type.Name + " bar") }
  120. };
  121. }
  122. }
  123. }
  124. }