LayoutAnchorable.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*************************************************************************************
  2. Extended WPF Toolkit
  3. Copyright (C) 2007-2013 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
  6. For more features, controls, and fast professional support,
  7. pick up the Plus Edition at http://xceed.com/wpf_toolkit
  8. Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
  9. ***********************************************************************************/
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Windows;
  15. using System.Xml.Serialization;
  16. using System.Windows.Controls;
  17. using System.Globalization;
  18. using System.ComponentModel;
  19. namespace Xceed.Wpf.AvalonDock.Layout
  20. {
  21. [Serializable]
  22. public class LayoutAnchorable : LayoutContent
  23. {
  24. #region IsVisible
  25. [XmlIgnore]
  26. public bool IsVisible
  27. {
  28. get
  29. {
  30. return Parent != null && !(Parent is LayoutRoot);
  31. }
  32. set
  33. {
  34. if (value)
  35. {
  36. Show();
  37. }
  38. else
  39. {
  40. Hide();
  41. }
  42. }
  43. }
  44. public event EventHandler IsVisibleChanged;
  45. void NotifyIsVisibleChanged()
  46. {
  47. if (IsVisibleChanged != null)
  48. IsVisibleChanged(this, EventArgs.Empty);
  49. }
  50. [XmlIgnore]
  51. public bool IsHidden
  52. {
  53. get
  54. {
  55. return (Parent is LayoutRoot);
  56. }
  57. }
  58. protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue)
  59. {
  60. UpdateParentVisibility();
  61. RaisePropertyChanged("IsVisible");
  62. NotifyIsVisibleChanged();
  63. RaisePropertyChanged("IsHidden");
  64. RaisePropertyChanged("IsAutoHidden");
  65. base.OnParentChanged(oldValue, newValue);
  66. }
  67. void UpdateParentVisibility()
  68. {
  69. var parentPane = Parent as ILayoutElementWithVisibility;
  70. if (parentPane != null)
  71. parentPane.ComputeVisibility();
  72. }
  73. #endregion
  74. #region AutoHideWidth
  75. private double _autohideWidth = 0.0;
  76. public double AutoHideWidth
  77. {
  78. get { return _autohideWidth; }
  79. set
  80. {
  81. if (_autohideWidth != value)
  82. {
  83. RaisePropertyChanging("AutoHideWidth");
  84. value = Math.Max(value, _autohideMinWidth);
  85. _autohideWidth = value;
  86. RaisePropertyChanged("AutoHideWidth");
  87. }
  88. }
  89. }
  90. #endregion
  91. #region AutoHideMinWidth
  92. private double _autohideMinWidth = 100.0;
  93. public double AutoHideMinWidth
  94. {
  95. get { return _autohideMinWidth; }
  96. set
  97. {
  98. if (_autohideMinWidth != value)
  99. {
  100. RaisePropertyChanging("AutoHideMinWidth");
  101. if (value < 0)
  102. throw new ArgumentException("value");
  103. _autohideMinWidth = value;
  104. RaisePropertyChanged("AutoHideMinWidth");
  105. }
  106. }
  107. }
  108. #endregion
  109. #region AutoHideHeight
  110. private double _autohideHeight = 0.0;
  111. public double AutoHideHeight
  112. {
  113. get { return _autohideHeight; }
  114. set
  115. {
  116. if (_autohideHeight != value)
  117. {
  118. RaisePropertyChanging("AutoHideHeight");
  119. value = Math.Max(value, _autohideMinHeight);
  120. _autohideHeight = value;
  121. RaisePropertyChanged("AutoHideHeight");
  122. }
  123. }
  124. }
  125. #endregion
  126. #region AutoHideMinHeight
  127. private double _autohideMinHeight = 100.0;
  128. public double AutoHideMinHeight
  129. {
  130. get { return _autohideMinHeight; }
  131. set
  132. {
  133. if (_autohideMinHeight != value)
  134. {
  135. RaisePropertyChanging("AutoHideMinHeight");
  136. if (value < 0)
  137. throw new ArgumentException("value");
  138. _autohideMinHeight = value;
  139. RaisePropertyChanged("AutoHideMinHeight");
  140. }
  141. }
  142. }
  143. #endregion
  144. /// <summary>
  145. /// Hide this contents
  146. /// </summary>
  147. /// <remarks>Add this content to <see cref="ILayoutRoot.Hidden"/> collection of parent root.</remarks>
  148. public void Hide(bool cancelable = true)
  149. {
  150. if (!IsVisible)
  151. {
  152. IsSelected = true;
  153. IsActive = true;
  154. return;
  155. }
  156. if (cancelable)
  157. {
  158. CancelEventArgs args = new CancelEventArgs();
  159. OnHiding(args);
  160. if (args.Cancel)
  161. return;
  162. }
  163. RaisePropertyChanging("IsHidden");
  164. RaisePropertyChanging("IsVisible");
  165. //if (Parent is ILayoutPane)
  166. {
  167. var parentAsGroup = Parent as ILayoutGroup;
  168. PreviousContainer = parentAsGroup;
  169. PreviousContainerIndex = parentAsGroup.IndexOfChild(this);
  170. }
  171. Root.Hidden.Add(this);
  172. RaisePropertyChanged("IsVisible");
  173. RaisePropertyChanged("IsHidden");
  174. NotifyIsVisibleChanged();
  175. }
  176. public event EventHandler<CancelEventArgs> Hiding;
  177. protected virtual void OnHiding(CancelEventArgs args)
  178. {
  179. if (Hiding != null)
  180. Hiding(this, args);
  181. }
  182. /// <summary>
  183. /// Show the content
  184. /// </summary>
  185. /// <remarks>Try to show the content where it was previously hidden.</remarks>
  186. public void Show()
  187. {
  188. if (IsVisible)
  189. return;
  190. if (!IsHidden)
  191. throw new InvalidOperationException();
  192. RaisePropertyChanging("IsHidden");
  193. RaisePropertyChanging("IsVisible");
  194. bool added = false;
  195. var root = Root;
  196. if (root != null && root.Manager != null)
  197. {
  198. if (root.Manager.LayoutUpdateStrategy != null)
  199. added = root.Manager.LayoutUpdateStrategy.BeforeInsertAnchorable(root as LayoutRoot, this, PreviousContainer);
  200. }
  201. if (!added && PreviousContainer != null)
  202. {
  203. var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup;
  204. if (PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount)
  205. previousContainerAsLayoutGroup.InsertChildAt(PreviousContainerIndex, this);
  206. else
  207. previousContainerAsLayoutGroup.InsertChildAt(previousContainerAsLayoutGroup.ChildrenCount, this);
  208. IsSelected = true;
  209. IsActive = true;
  210. }
  211. if (root != null && root.Manager != null)
  212. {
  213. if (root.Manager.LayoutUpdateStrategy != null)
  214. {
  215. root.Manager.LayoutUpdateStrategy.AfterInsertAnchorable(root as LayoutRoot, this);
  216. }
  217. }
  218. PreviousContainer = null;
  219. PreviousContainerIndex = -1;
  220. RaisePropertyChanged("IsVisible");
  221. RaisePropertyChanged("IsHidden");
  222. NotifyIsVisibleChanged();
  223. }
  224. protected override void InternalDock()
  225. {
  226. var root = Root as LayoutRoot;
  227. LayoutAnchorablePane anchorablePane = null;
  228. if (root.ActiveContent != null &&
  229. root.ActiveContent != this)
  230. {
  231. //look for active content parent pane
  232. anchorablePane = root.ActiveContent.Parent as LayoutAnchorablePane;
  233. }
  234. if (anchorablePane == null)
  235. {
  236. //look for a pane on the right side
  237. anchorablePane = root.Descendents().OfType<LayoutAnchorablePane>().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault();
  238. }
  239. if (anchorablePane == null)
  240. {
  241. //look for an available pane
  242. anchorablePane = root.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
  243. }
  244. bool added = false;
  245. if (root.Manager.LayoutUpdateStrategy != null)
  246. {
  247. added = root.Manager.LayoutUpdateStrategy.BeforeInsertAnchorable(root, this, anchorablePane);
  248. }
  249. if (!added)
  250. {
  251. if (anchorablePane == null)
  252. {
  253. var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
  254. if (root.RootPanel != null)
  255. {
  256. mainLayoutPanel.Children.Add(root.RootPanel);
  257. }
  258. root.RootPanel = mainLayoutPanel;
  259. anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) };
  260. mainLayoutPanel.Children.Add(anchorablePane);
  261. }
  262. anchorablePane.Children.Add(this);
  263. added = true;
  264. }
  265. if (root.Manager.LayoutUpdateStrategy != null)
  266. {
  267. root.Manager.LayoutUpdateStrategy.AfterInsertAnchorable(root, this);
  268. }
  269. base.InternalDock();
  270. }
  271. /// <summary>
  272. /// Add the anchorable to a DockingManager layout
  273. /// </summary>
  274. /// <param name="manager"></param>
  275. /// <param name="strategy"></param>
  276. public void AddToLayout(DockingManager manager, AnchorableShowStrategy strategy)
  277. {
  278. if (IsVisible ||
  279. IsHidden)
  280. throw new InvalidOperationException();
  281. bool most = (strategy & AnchorableShowStrategy.Most) == AnchorableShowStrategy.Most;
  282. bool left = (strategy & AnchorableShowStrategy.Left) == AnchorableShowStrategy.Left;
  283. bool right = (strategy & AnchorableShowStrategy.Right) == AnchorableShowStrategy.Right;
  284. bool top = (strategy & AnchorableShowStrategy.Top) == AnchorableShowStrategy.Top;
  285. bool bottom = (strategy & AnchorableShowStrategy.Bottom) == AnchorableShowStrategy.Bottom;
  286. if (!most)
  287. {
  288. var side = AnchorSide.Left;
  289. if (left)
  290. side = AnchorSide.Left;
  291. if (right)
  292. side = AnchorSide.Right;
  293. if (top)
  294. side = AnchorSide.Top;
  295. if (bottom)
  296. side = AnchorSide.Bottom;
  297. var anchorablePane = manager.Layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault(p => p.GetSide() == side);
  298. if (anchorablePane != null)
  299. anchorablePane.Children.Add(this);
  300. else
  301. most = true;
  302. }
  303. if (most)
  304. {
  305. if (manager.Layout.RootPanel == null)
  306. manager.Layout.RootPanel = new LayoutPanel() { Orientation = (left || right ? Orientation.Horizontal : Orientation.Vertical) };
  307. if (left || right)
  308. {
  309. if (manager.Layout.RootPanel.Orientation == Orientation.Vertical &&
  310. manager.Layout.RootPanel.ChildrenCount > 1)
  311. {
  312. manager.Layout.RootPanel = new LayoutPanel(manager.Layout.RootPanel);
  313. }
  314. manager.Layout.RootPanel.Orientation = Orientation.Horizontal;
  315. if (left)
  316. manager.Layout.RootPanel.Children.Insert(0, new LayoutAnchorablePane(this));
  317. else
  318. manager.Layout.RootPanel.Children.Add(new LayoutAnchorablePane(this));
  319. }
  320. else
  321. {
  322. if (manager.Layout.RootPanel.Orientation == Orientation.Horizontal &&
  323. manager.Layout.RootPanel.ChildrenCount > 1)
  324. {
  325. manager.Layout.RootPanel = new LayoutPanel(manager.Layout.RootPanel);
  326. }
  327. manager.Layout.RootPanel.Orientation = Orientation.Vertical;
  328. if (top)
  329. manager.Layout.RootPanel.Children.Insert(0, new LayoutAnchorablePane(this));
  330. else
  331. manager.Layout.RootPanel.Children.Add(new LayoutAnchorablePane(this));
  332. }
  333. }
  334. }
  335. /// <summary>
  336. /// Get a value indicating if the anchorable is anchored to a border in an autohide status
  337. /// </summary>
  338. public bool IsAutoHidden
  339. {
  340. get { return Parent != null && Parent is LayoutAnchorGroup; }
  341. }
  342. #region AutoHide
  343. public void ToggleAutoHide()
  344. {
  345. #region Anchorable is already auto hidden
  346. if (IsAutoHidden)
  347. {
  348. var parentGroup = Parent as LayoutAnchorGroup;
  349. var parentSide = parentGroup.Parent as LayoutAnchorSide;
  350. var previousContainer = ((ILayoutPreviousContainer)parentGroup).PreviousContainer as LayoutAnchorablePane;
  351. if (previousContainer == null)
  352. {
  353. AnchorSide side = (parentGroup.Parent as LayoutAnchorSide).Side;
  354. switch (side)
  355. {
  356. case AnchorSide.Right:
  357. if (parentGroup.Root.RootPanel.Orientation == Orientation.Horizontal)
  358. {
  359. previousContainer = new LayoutAnchorablePane();
  360. parentGroup.Root.RootPanel.Children.Add(previousContainer);
  361. }
  362. else
  363. {
  364. previousContainer = new LayoutAnchorablePane();
  365. LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Horizontal };
  366. LayoutRoot root = parentGroup.Root as LayoutRoot;
  367. LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel;
  368. root.RootPanel = panel;
  369. panel.Children.Add(oldRootPanel);
  370. panel.Children.Add(previousContainer);
  371. }
  372. break;
  373. case AnchorSide.Left:
  374. if (parentGroup.Root.RootPanel.Orientation == Orientation.Horizontal)
  375. {
  376. previousContainer = new LayoutAnchorablePane();
  377. parentGroup.Root.RootPanel.Children.Insert(0, previousContainer);
  378. }
  379. else
  380. {
  381. previousContainer = new LayoutAnchorablePane();
  382. LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Horizontal };
  383. LayoutRoot root = parentGroup.Root as LayoutRoot;
  384. LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel;
  385. root.RootPanel = panel;
  386. panel.Children.Add(previousContainer);
  387. panel.Children.Add(oldRootPanel);
  388. }
  389. break;
  390. case AnchorSide.Top:
  391. if (parentGroup.Root.RootPanel.Orientation == Orientation.Vertical)
  392. {
  393. previousContainer = new LayoutAnchorablePane();
  394. parentGroup.Root.RootPanel.Children.Insert(0, previousContainer);
  395. }
  396. else
  397. {
  398. previousContainer = new LayoutAnchorablePane();
  399. LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Vertical };
  400. LayoutRoot root = parentGroup.Root as LayoutRoot;
  401. LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel;
  402. root.RootPanel = panel;
  403. panel.Children.Add(previousContainer);
  404. panel.Children.Add(oldRootPanel);
  405. }
  406. break;
  407. case AnchorSide.Bottom:
  408. if (parentGroup.Root.RootPanel.Orientation == Orientation.Vertical)
  409. {
  410. previousContainer = new LayoutAnchorablePane();
  411. parentGroup.Root.RootPanel.Children.Add(previousContainer);
  412. }
  413. else
  414. {
  415. previousContainer = new LayoutAnchorablePane();
  416. LayoutPanel panel = new LayoutPanel() { Orientation = Orientation.Vertical };
  417. LayoutRoot root = parentGroup.Root as LayoutRoot;
  418. LayoutPanel oldRootPanel = parentGroup.Root.RootPanel as LayoutPanel;
  419. root.RootPanel = panel;
  420. panel.Children.Add(oldRootPanel);
  421. panel.Children.Add(previousContainer);
  422. }
  423. break;
  424. }
  425. }
  426. else
  427. {
  428. //I'm about to remove parentGroup, redirect any content (ie hidden contents) that point to it
  429. //to previousContainer
  430. LayoutRoot root = parentGroup.Root as LayoutRoot;
  431. foreach (var cnt in root.Descendents().OfType<ILayoutPreviousContainer>().Where(c => c.PreviousContainer == parentGroup))
  432. {
  433. cnt.PreviousContainer = previousContainer;
  434. }
  435. }
  436. foreach (var anchorableToToggle in parentGroup.Children.ToArray())
  437. {
  438. previousContainer.Children.Add(anchorableToToggle);
  439. }
  440. parentSide.Children.Remove(parentGroup);
  441. }
  442. #endregion
  443. #region Anchorable is docked
  444. else if (Parent is LayoutAnchorablePane)
  445. {
  446. var root = Root;
  447. var parentPane = Parent as LayoutAnchorablePane;
  448. var newAnchorGroup = new LayoutAnchorGroup();
  449. ((ILayoutPreviousContainer)newAnchorGroup).PreviousContainer = parentPane;
  450. foreach (var anchorableToImport in parentPane.Children.ToArray())
  451. newAnchorGroup.Children.Add(anchorableToImport);
  452. //detect anchor side for the pane
  453. var anchorSide = parentPane.GetSide();
  454. switch (anchorSide)
  455. {
  456. case AnchorSide.Right:
  457. root.RightSide.Children.Add(newAnchorGroup);
  458. break;
  459. case AnchorSide.Left:
  460. root.LeftSide.Children.Add(newAnchorGroup);
  461. break;
  462. case AnchorSide.Top:
  463. root.TopSide.Children.Add(newAnchorGroup);
  464. break;
  465. case AnchorSide.Bottom:
  466. root.BottomSide.Children.Add(newAnchorGroup);
  467. break;
  468. }
  469. }
  470. #endregion
  471. }
  472. #endregion
  473. #region CanHide
  474. private bool _canHide = true;
  475. public bool CanHide
  476. {
  477. get { return _canHide; }
  478. set
  479. {
  480. if (_canHide != value)
  481. {
  482. _canHide = value;
  483. RaisePropertyChanged("CanHide");
  484. }
  485. }
  486. }
  487. #endregion
  488. #region CanAutoHide
  489. private bool _canAutoHide = true;
  490. public bool CanAutoHide
  491. {
  492. get { return _canAutoHide; }
  493. set
  494. {
  495. if (_canAutoHide != value)
  496. {
  497. _canAutoHide = value;
  498. RaisePropertyChanged("CanAutoHide");
  499. }
  500. }
  501. }
  502. #endregion
  503. public override void ReadXml(System.Xml.XmlReader reader)
  504. {
  505. if (reader.MoveToAttribute("CanHide"))
  506. CanHide = bool.Parse(reader.Value);
  507. if (reader.MoveToAttribute("CanAutoHide"))
  508. CanAutoHide = bool.Parse(reader.Value);
  509. if (reader.MoveToAttribute("AutoHideWidth"))
  510. AutoHideWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  511. if (reader.MoveToAttribute("AutoHideHeight"))
  512. AutoHideHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  513. if (reader.MoveToAttribute("AutoHideMinWidth"))
  514. AutoHideMinWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  515. if (reader.MoveToAttribute("AutoHideMinHeight"))
  516. AutoHideMinHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  517. base.ReadXml(reader);
  518. }
  519. public override void WriteXml(System.Xml.XmlWriter writer)
  520. {
  521. if (!CanHide)
  522. writer.WriteAttributeString("CanHide", CanHide.ToString());
  523. if (!CanAutoHide)
  524. writer.WriteAttributeString("CanAutoHide", CanAutoHide.ToString(CultureInfo.InvariantCulture));
  525. if (AutoHideWidth > 0)
  526. writer.WriteAttributeString("AutoHideWidth", AutoHideWidth.ToString(CultureInfo.InvariantCulture));
  527. if (AutoHideHeight > 0)
  528. writer.WriteAttributeString("AutoHideHeight", AutoHideHeight.ToString(CultureInfo.InvariantCulture));
  529. if (AutoHideMinWidth != 25.0)
  530. writer.WriteAttributeString("AutoHideMinWidth", AutoHideMinWidth.ToString(CultureInfo.InvariantCulture));
  531. if (AutoHideMinHeight != 25.0)
  532. writer.WriteAttributeString("AutoHideMinHeight", AutoHideMinHeight.ToString(CultureInfo.InvariantCulture));
  533. base.WriteXml(writer);
  534. }
  535. public override void Close()
  536. {
  537. var dockingManager = this.Root.Manager;
  538. if( ( this.Root != null ) && ( this.Root.Manager != null ) )
  539. dockingManager._ExecuteCloseCommand( this );
  540. }
  541. #if TRACE
  542. public override void ConsoleDump(int tab)
  543. {
  544. System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) );
  545. System.Diagnostics.Trace.WriteLine( "Anchorable()" );
  546. }
  547. #endif
  548. }
  549. }