Program.cs 26 KB

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