Program.cs 27 KB

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