Program.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. // Copyright (c) The Perspex Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Reactive.Linq;
  5. using Perspex;
  6. using Perspex.Animation;
  7. using Perspex.Collections;
  8. using Perspex.Controls;
  9. using Perspex.Controls.Primitives;
  10. using Perspex.Controls.Shapes;
  11. using Perspex.Controls.Templates;
  12. using Perspex.Diagnostics;
  13. using Perspex.Layout;
  14. using Perspex.Media;
  15. using Perspex.Media.Imaging;
  16. #if PERSPEX_GTK
  17. using Perspex.Gtk;
  18. #endif
  19. using ReactiveUI;
  20. namespace TestApplication
  21. {
  22. internal class Item
  23. {
  24. public string Name { get; set; }
  25. public string Value { get; set; }
  26. }
  27. internal class Node
  28. {
  29. public Node()
  30. {
  31. Children = new PerspexList<Node>();
  32. }
  33. public string Name { get; set; }
  34. public PerspexList<Node> Children { get; set; }
  35. }
  36. internal class Program
  37. {
  38. private static readonly PerspexList<Node> s_treeData = new PerspexList<Node>
  39. {
  40. new Node
  41. {
  42. Name = "Root 1",
  43. Children = new PerspexList<Node>
  44. {
  45. new Node
  46. {
  47. Name = "Child 1",
  48. },
  49. new Node
  50. {
  51. Name = "Child 2",
  52. Children = new PerspexList<Node>
  53. {
  54. new Node
  55. {
  56. Name = "Grandchild 1",
  57. },
  58. new Node
  59. {
  60. Name = "Grandmaster Flash",
  61. },
  62. }
  63. },
  64. new Node
  65. {
  66. Name = "Child 3",
  67. },
  68. }
  69. },
  70. new Node
  71. {
  72. Name = "Root 2",
  73. },
  74. };
  75. private static readonly PerspexList<Item> s_listBoxData = new PerspexList<Item>
  76. {
  77. new Item { Name = "Item 1", Value = "Item 1 Value" },
  78. new Item { Name = "Item 2", Value = "Item 2 Value" },
  79. new Item { Name = "Item 3", Value = "Item 3 Value" },
  80. new Item { Name = "Item 4", Value = "Item 4 Value" },
  81. new Item { Name = "Item 5", Value = "Item 5 Value" },
  82. new Item { Name = "Item 6", Value = "Item 6 Value" },
  83. new Item { Name = "Item 7", Value = "Item 7 Value" },
  84. new Item { Name = "Item 8", Value = "Item 8 Value" },
  85. };
  86. private static void Main(string[] args)
  87. {
  88. //Log.Logger = new LoggerConfiguration()
  89. // .Filter.ByIncludingOnly(Matching.WithProperty("Area", "Layout"))
  90. // .MinimumLevel.Verbose()
  91. // .WriteTo.Trace(outputTemplate: "[{Id:X8}] [{SourceContext}] {Message}")
  92. // .CreateLogger();
  93. // The version of ReactiveUI currently included is for WPF and so expects a WPF
  94. // dispatcher. This makes sure it's initialized.
  95. System.Windows.Threading.Dispatcher foo = System.Windows.Threading.Dispatcher.CurrentDispatcher;
  96. App application = new App
  97. {
  98. DataTemplates = new DataTemplates
  99. {
  100. new TreeDataTemplate<Node>(
  101. x => new TextBlock { Text = x.Name },
  102. x => x.Children,
  103. x => true),
  104. },
  105. };
  106. TextBlock fps;
  107. var testCommand = ReactiveCommand.Create();
  108. testCommand.Subscribe(_ => System.Diagnostics.Debug.WriteLine("Test command executed."));
  109. Window window = new Window
  110. {
  111. Title = "Perspex Test Application",
  112. SizeToContent = SizeToContent.WidthAndHeight,
  113. Content = new Grid
  114. {
  115. ColumnDefinitions = new ColumnDefinitions
  116. {
  117. new ColumnDefinition(1, GridUnitType.Star),
  118. new ColumnDefinition(1, GridUnitType.Star),
  119. },
  120. RowDefinitions = new RowDefinitions
  121. {
  122. new RowDefinition(GridLength.Auto),
  123. new RowDefinition(1, GridUnitType.Star),
  124. new RowDefinition(GridLength.Auto),
  125. },
  126. Children = new Controls
  127. {
  128. new Menu
  129. {
  130. Items = new[]
  131. {
  132. new MenuItem
  133. {
  134. Header = "_File",
  135. Items = new[]
  136. {
  137. new MenuItem
  138. {
  139. Header = "_Open...",
  140. Icon = new Image
  141. {
  142. Source = new Bitmap("github_icon.png"),
  143. },
  144. },
  145. new MenuItem
  146. {
  147. Header = "_Save",
  148. Items = new[]
  149. {
  150. new MenuItem
  151. {
  152. Header = "Sub Item _1",
  153. },
  154. new MenuItem
  155. {
  156. Header = "Sub Item _2",
  157. },
  158. }
  159. },
  160. new MenuItem
  161. {
  162. Header = "Save _As",
  163. Items = new[]
  164. {
  165. new MenuItem
  166. {
  167. Header = "Sub Item _1",
  168. },
  169. new MenuItem
  170. {
  171. Header = "Sub Item _2",
  172. },
  173. }
  174. },
  175. new MenuItem
  176. {
  177. Header = "E_xit",
  178. Command = testCommand,
  179. },
  180. }
  181. },
  182. new MenuItem
  183. {
  184. Header = "_Edit",
  185. Items = new[]
  186. {
  187. new MenuItem
  188. {
  189. Header = "Cu_t",
  190. },
  191. new MenuItem
  192. {
  193. Header = "_Copy",
  194. },
  195. new MenuItem
  196. {
  197. Header = "_Paste",
  198. },
  199. }
  200. }
  201. },
  202. [Grid.ColumnSpanProperty] = 2,
  203. },
  204. new TabControl
  205. {
  206. Items = new[]
  207. {
  208. ButtonsTab(),
  209. TextTab(),
  210. ImagesTab(),
  211. ListsTab(),
  212. LayoutTab(),
  213. AnimationsTab(),
  214. },
  215. Transition = new PageSlide(TimeSpan.FromSeconds(0.25)),
  216. [Grid.RowProperty] = 1,
  217. [Grid.ColumnSpanProperty] = 2,
  218. },
  219. (fps = new TextBlock
  220. {
  221. HorizontalAlignment = HorizontalAlignment.Left,
  222. Margin = new Thickness(2),
  223. [Grid.RowProperty] = 2,
  224. }),
  225. new TextBlock
  226. {
  227. Text = "Press F12 for Dev Tools",
  228. HorizontalAlignment = HorizontalAlignment.Right,
  229. Margin = new Thickness(2),
  230. [Grid.ColumnProperty] = 1,
  231. [Grid.RowProperty] = 2,
  232. },
  233. }
  234. },
  235. };
  236. DevTools.Attach(window);
  237. //var renderer = ((IRenderRoot)window).Renderer;
  238. //var last = renderer.RenderCount;
  239. //DispatcherTimer.Run(() =>
  240. //{
  241. // fps.Text = "FPS: " + (renderer.RenderCount - last);
  242. // last = renderer.RenderCount;
  243. // return true;
  244. //}, TimeSpan.FromSeconds(1));
  245. window.Show();
  246. Application.Current.Run(window);
  247. }
  248. private static TabItem ButtonsTab()
  249. {
  250. Button defaultButton;
  251. var showDialog = ReactiveCommand.Create();
  252. Button showDialogButton;
  253. var result = new TabItem
  254. {
  255. Header = "Buttons",
  256. Content = new StackPanel
  257. {
  258. Orientation = Orientation.Vertical,
  259. HorizontalAlignment = HorizontalAlignment.Center,
  260. VerticalAlignment = VerticalAlignment.Center,
  261. Gap = 8,
  262. MinWidth = 120,
  263. Children = new Controls
  264. {
  265. (showDialogButton = new Button
  266. {
  267. Content = "Button",
  268. Command = showDialog,
  269. [ToolTip.TipProperty] = "Hello World!",
  270. }),
  271. new Button
  272. {
  273. Content = "Button",
  274. Background = new SolidColorBrush(0xcc119eda),
  275. [ToolTip.TipProperty] = "Goodbye Cruel World!",
  276. },
  277. (defaultButton = new Button
  278. {
  279. Content = "Default",
  280. IsDefault = true,
  281. }),
  282. new Button
  283. {
  284. Content = "Disabled",
  285. IsEnabled = false,
  286. },
  287. new Button
  288. {
  289. Content = "Disabled",
  290. IsEnabled = false,
  291. Background = new SolidColorBrush(0xcc119eda),
  292. },
  293. new ToggleButton
  294. {
  295. Content = "Toggle",
  296. },
  297. new ToggleButton
  298. {
  299. Content = "Disabled",
  300. IsEnabled = false,
  301. },
  302. new CheckBox
  303. {
  304. Content = "Checkbox",
  305. },
  306. new RadioButton
  307. {
  308. Content = "RadioButton 1",
  309. IsChecked = true,
  310. },
  311. new RadioButton
  312. {
  313. Content = "RadioButton 2",
  314. },
  315. }
  316. },
  317. };
  318. defaultButton.Click += (s, e) =>
  319. {
  320. defaultButton.Content = ((string)defaultButton.Content == "Default") ? "Clicked" : "Default";
  321. };
  322. showDialog.Subscribe(async _ =>
  323. {
  324. var close = ReactiveCommand.Create();
  325. var dialog = new Window
  326. {
  327. Content = new StackPanel
  328. {
  329. Width = 200,
  330. Height = 200,
  331. Children = new Controls
  332. {
  333. new Button { Content = "Yes", Command = close, CommandParameter = "Yes" },
  334. new Button { Content = "No", Command = close, CommandParameter = "No" },
  335. }
  336. }
  337. };
  338. close.Subscribe(x => dialog.Close(x));
  339. showDialogButton.Content = await dialog.ShowDialog<string>();
  340. });
  341. return result;
  342. }
  343. private static TabItem TextTab()
  344. {
  345. return new TabItem
  346. {
  347. Header = "Text",
  348. Content = new StackPanel
  349. {
  350. Orientation = Orientation.Vertical,
  351. HorizontalAlignment = HorizontalAlignment.Center,
  352. VerticalAlignment = VerticalAlignment.Center,
  353. Gap = 8,
  354. Width = 120,
  355. Children = new Controls
  356. {
  357. new TextBlock
  358. {
  359. Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.",
  360. TextWrapping = TextWrapping.Wrap,
  361. TextAlignment = TextAlignment.Center,
  362. },
  363. new TextBlock
  364. {
  365. Text = "Italic text.",
  366. FontStyle = FontStyle.Italic,
  367. TextAlignment = TextAlignment.Left,
  368. },
  369. new TextBlock
  370. {
  371. Text = "Bold text.",
  372. FontWeight = FontWeight.Bold,
  373. TextAlignment = TextAlignment.Right,
  374. },
  375. new TextBox
  376. {
  377. Text = "A non-wrapping text box. Lorem ipsum dolor sit amet.",
  378. TextWrapping = TextWrapping.NoWrap,
  379. },
  380. new TextBox
  381. {
  382. AcceptsReturn = true,
  383. Text = "A wrapping text box. " +
  384. "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt. " +
  385. "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.",
  386. TextWrapping = TextWrapping.Wrap,
  387. MaxHeight = 100,
  388. },
  389. }
  390. },
  391. };
  392. }
  393. private static TabItem ImagesTab()
  394. {
  395. ScrollBar size;
  396. return new TabItem
  397. {
  398. Header = "Images",
  399. Content = new StackPanel
  400. {
  401. Orientation = Orientation.Vertical,
  402. HorizontalAlignment = HorizontalAlignment.Center,
  403. VerticalAlignment = VerticalAlignment.Center,
  404. Gap = 8,
  405. Children = new Controls
  406. {
  407. (size = new ScrollBar
  408. {
  409. Minimum = 100,
  410. Maximum = 400,
  411. Value = 100,
  412. Orientation = Orientation.Horizontal,
  413. }),
  414. new ScrollViewer
  415. {
  416. Width = 200,
  417. Height = 200,
  418. CanScrollHorizontally = true,
  419. Content = new Image
  420. {
  421. Source = new Bitmap("github_icon.png"),
  422. [!Layoutable.WidthProperty] = size[!RangeBase.ValueProperty],
  423. [!Layoutable.HeightProperty] = size[!RangeBase.ValueProperty],
  424. },
  425. },
  426. new ProgressBar
  427. {
  428. [!RangeBase.MinimumProperty] = size[!RangeBase.MinimumProperty],
  429. [!RangeBase.MaximumProperty] = size[!RangeBase.MaximumProperty],
  430. [!RangeBase.ValueProperty] = size[!RangeBase.ValueProperty],
  431. }
  432. }
  433. },
  434. };
  435. }
  436. private static TabItem ListsTab()
  437. {
  438. ListBox listBox;
  439. return new TabItem
  440. {
  441. Header = "Lists",
  442. Content = new StackPanel
  443. {
  444. DataTemplates = new DataTemplates
  445. {
  446. new DataTemplate<Item>(x =>
  447. new StackPanel
  448. {
  449. Children = new Controls
  450. {
  451. new TextBlock { Text = x.Name, FontSize = 24 },
  452. new TextBlock { Text = x.Value },
  453. }
  454. })
  455. },
  456. Orientation = Orientation.Horizontal,
  457. HorizontalAlignment = HorizontalAlignment.Center,
  458. VerticalAlignment = VerticalAlignment.Center,
  459. Gap = 8,
  460. Children = new Controls
  461. {
  462. new TreeView
  463. {
  464. Name = "treeView",
  465. Items = s_treeData,
  466. },
  467. (listBox = new ListBox
  468. {
  469. Items = s_listBoxData,
  470. MaxHeight = 300,
  471. }),
  472. new DropDown
  473. {
  474. Items = s_listBoxData,
  475. SelectedItem = s_listBoxData[0],
  476. VerticalAlignment = VerticalAlignment.Center,
  477. }
  478. }
  479. },
  480. };
  481. }
  482. private static TabItem LayoutTab()
  483. {
  484. return new TabItem
  485. {
  486. Header = "Layout",
  487. Content = new Grid
  488. {
  489. ColumnDefinitions = new ColumnDefinitions
  490. {
  491. new ColumnDefinition(1, GridUnitType.Star),
  492. new ColumnDefinition(1, GridUnitType.Star),
  493. },
  494. Margin = new Thickness(50),
  495. Children = new Controls
  496. {
  497. new StackPanel
  498. {
  499. Orientation = Orientation.Vertical,
  500. Gap = 8,
  501. Children = new Controls
  502. {
  503. new Button { HorizontalAlignment = HorizontalAlignment.Left, Content = "Left Aligned" },
  504. new Button { HorizontalAlignment = HorizontalAlignment.Center, Content = "Center Aligned" },
  505. new Button { HorizontalAlignment = HorizontalAlignment.Right, Content = "Right Aligned" },
  506. new Button { HorizontalAlignment = HorizontalAlignment.Stretch, Content = "Stretch" },
  507. },
  508. [Grid.ColumnProperty] = 0,
  509. },
  510. new StackPanel
  511. {
  512. Orientation = Orientation.Horizontal,
  513. Gap = 8,
  514. Children = new Controls
  515. {
  516. new Button { VerticalAlignment = VerticalAlignment.Top, Content = "Top Aligned" },
  517. new Button { VerticalAlignment = VerticalAlignment.Center, Content = "Center Aligned" },
  518. new Button { VerticalAlignment = VerticalAlignment.Bottom, Content = "Bottom Aligned" },
  519. new Button { VerticalAlignment = VerticalAlignment.Stretch, Content = "Stretch" },
  520. },
  521. [Grid.ColumnProperty] = 1,
  522. },
  523. },
  524. }
  525. };
  526. }
  527. private static TabItem AnimationsTab()
  528. {
  529. Border border1;
  530. Border border2;
  531. RotateTransform rotate;
  532. Button button1;
  533. var result = new TabItem
  534. {
  535. Header = "Animations",
  536. Content = new Grid
  537. {
  538. ColumnDefinitions = new ColumnDefinitions
  539. {
  540. new ColumnDefinition(1, GridUnitType.Star),
  541. new ColumnDefinition(1, GridUnitType.Star),
  542. },
  543. RowDefinitions = new RowDefinitions
  544. {
  545. new RowDefinition(1, GridUnitType.Star),
  546. new RowDefinition(GridLength.Auto),
  547. },
  548. Children = new Controls
  549. {
  550. (border1 = new Border
  551. {
  552. Width = 100,
  553. Height = 100,
  554. HorizontalAlignment = HorizontalAlignment.Center,
  555. VerticalAlignment = VerticalAlignment.Center,
  556. Background = Brushes.Crimson,
  557. RenderTransform = new RotateTransform(),
  558. Child = new TextBox
  559. {
  560. Background = Brushes.White,
  561. Text = "Hello!",
  562. HorizontalAlignment = HorizontalAlignment.Center,
  563. VerticalAlignment = VerticalAlignment.Center,
  564. },
  565. }),
  566. (border2 = new Border
  567. {
  568. Width = 100,
  569. Height = 100,
  570. HorizontalAlignment = HorizontalAlignment.Center,
  571. VerticalAlignment = VerticalAlignment.Center,
  572. Background = Brushes.Coral,
  573. Child = new Image
  574. {
  575. Source = new Bitmap("github_icon.png"),
  576. HorizontalAlignment = HorizontalAlignment.Center,
  577. VerticalAlignment = VerticalAlignment.Center,
  578. },
  579. RenderTransform = (rotate = new RotateTransform
  580. {
  581. PropertyTransitions = new PropertyTransitions
  582. {
  583. RotateTransform.AngleProperty.Transition(500),
  584. }
  585. }),
  586. PropertyTransitions = new PropertyTransitions
  587. {
  588. Layoutable.WidthProperty.Transition(300),
  589. Layoutable.HeightProperty.Transition(1000),
  590. },
  591. [Grid.ColumnProperty] = 1,
  592. }),
  593. (button1 = new Button
  594. {
  595. HorizontalAlignment = HorizontalAlignment.Center,
  596. Content = "Animate",
  597. [Grid.ColumnProperty] = 1,
  598. [Grid.RowProperty] = 1,
  599. }),
  600. },
  601. },
  602. };
  603. button1.Click += (s, e) =>
  604. {
  605. if (border2.Width == 100)
  606. {
  607. border2.Width = border2.Height = 400;
  608. rotate.Angle = 180;
  609. }
  610. else
  611. {
  612. border2.Width = border2.Height = 100;
  613. rotate.Angle = 0;
  614. }
  615. };
  616. var start = Animate.Stopwatch.Elapsed;
  617. var degrees = Animate.Timer
  618. .Select(x =>
  619. {
  620. var elapsed = (x - start).TotalSeconds;
  621. var cycles = elapsed / 4;
  622. var progress = cycles % 1;
  623. return 360.0 * progress;
  624. });
  625. border1.RenderTransform.Bind(
  626. RotateTransform.AngleProperty,
  627. degrees,
  628. BindingPriority.Animation);
  629. return result;
  630. }
  631. }
  632. }