LayoutItem.cs 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  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 Xceed.Wpf.AvalonDock.Layout;
  16. using System.Windows.Input;
  17. using Xceed.Wpf.AvalonDock.Commands;
  18. using System.ComponentModel;
  19. using System.Windows.Data;
  20. using System.Windows.Media;
  21. using System.Windows.Controls;
  22. namespace Xceed.Wpf.AvalonDock.Controls
  23. {
  24. public abstract class LayoutItem : FrameworkElement
  25. {
  26. static LayoutItem()
  27. {
  28. ToolTipProperty.OverrideMetadata(typeof(LayoutItem), new FrameworkPropertyMetadata(null, (s, e) => OnToolTipChanged(s,e)));
  29. VisibilityProperty.OverrideMetadata(typeof(LayoutItem), new FrameworkPropertyMetadata(Visibility.Visible, (s,e) => OnVisibilityChanged(s, e)));
  30. }
  31. internal LayoutItem()
  32. {
  33. }
  34. internal virtual void Attach(LayoutContent model)
  35. {
  36. LayoutElement = model;
  37. Model = model.Content;
  38. InitDefaultCommands();
  39. LayoutElement.IsSelectedChanged+=new EventHandler(LayoutElement_IsSelectedChanged);
  40. LayoutElement.IsActiveChanged+=new EventHandler(LayoutElement_IsActiveChanged);
  41. DataContext = this;
  42. System.Diagnostics.Trace.WriteLine( string.Format( "Attach({0})", LayoutElement.Title ) );
  43. }
  44. void LayoutElement_IsActiveChanged(object sender, EventArgs e)
  45. {
  46. if (_isActiveReentrantFlag.CanEnter)
  47. {
  48. using (_isActiveReentrantFlag.Enter())
  49. {
  50. var bnd = BindingOperations.GetBinding(this, IsActiveProperty);
  51. IsActive = LayoutElement.IsActive;
  52. var bnd2 = BindingOperations.GetBinding(this, IsActiveProperty);
  53. }
  54. }
  55. }
  56. void LayoutElement_IsSelectedChanged(object sender, EventArgs e)
  57. {
  58. if (_isSelectedReentrantFlag.CanEnter)
  59. {
  60. using (_isSelectedReentrantFlag.Enter())
  61. {
  62. IsSelected = LayoutElement.IsSelected;
  63. }
  64. }
  65. }
  66. internal virtual void Detach()
  67. {
  68. System.Diagnostics.Trace.WriteLine( string.Format( "Detach({0})", LayoutElement.Title ) );
  69. LayoutElement.IsSelectedChanged -= new EventHandler(LayoutElement_IsSelectedChanged);
  70. LayoutElement.IsActiveChanged -= new EventHandler(LayoutElement_IsActiveChanged);
  71. LayoutElement = null;
  72. Model = null;
  73. }
  74. public LayoutContent LayoutElement
  75. {
  76. get;
  77. private set;
  78. }
  79. public object Model
  80. {
  81. get;
  82. private set;
  83. }
  84. ICommand _defaultCloseCommand;
  85. ICommand _defaultFloatCommand;
  86. ICommand _defaultDockAsDocumentCommand;
  87. ICommand _defaultCloseAllButThisCommand;
  88. ICommand _defaultActivateCommand;
  89. ICommand _defaultNewVerticalTabGroupCommand;
  90. ICommand _defaultNewHorizontalTabGroupCommand;
  91. ICommand _defaultMoveToNextTabGroupCommand;
  92. ICommand _defaultMoveToPreviousTabGroupCommand;
  93. protected virtual void InitDefaultCommands()
  94. {
  95. _defaultCloseCommand = new RelayCommand((p) => ExecuteCloseCommand(p), (p) => CanExecuteCloseCommand(p));
  96. _defaultFloatCommand = new RelayCommand((p) => ExecuteFloatCommand(p), (p) => CanExecuteFloatCommand(p));
  97. _defaultDockAsDocumentCommand = new RelayCommand((p) => ExecuteDockAsDocumentCommand(p), (p) => CanExecuteDockAsDocumentCommand(p));
  98. _defaultCloseAllButThisCommand = new RelayCommand((p) => ExecuteCloseAllButThisCommand(p), (p) => CanExecuteCloseAllButThisCommand(p));
  99. _defaultActivateCommand = new RelayCommand((p) => ExecuteActivateCommand(p), (p) => CanExecuteActivateCommand(p));
  100. _defaultNewVerticalTabGroupCommand = new RelayCommand((p) => ExecuteNewVerticalTabGroupCommand(p), (p) => CanExecuteNewVerticalTabGroupCommand(p));
  101. _defaultNewHorizontalTabGroupCommand = new RelayCommand((p) => ExecuteNewHorizontalTabGroupCommand(p), (p) => CanExecuteNewHorizontalTabGroupCommand(p));
  102. _defaultMoveToNextTabGroupCommand = new RelayCommand((p) => ExecuteMoveToNextTabGroupCommand(p), (p) => CanExecuteMoveToNextTabGroupCommand(p));
  103. _defaultMoveToPreviousTabGroupCommand = new RelayCommand((p) => ExecuteMoveToPreviousTabGroupCommand(p), (p) => CanExecuteMoveToPreviousTabGroupCommand(p));
  104. }
  105. protected virtual void ClearDefaultBindings()
  106. {
  107. if (CloseCommand == _defaultCloseCommand)
  108. BindingOperations.ClearBinding(this, CloseCommandProperty);
  109. if (FloatCommand == _defaultFloatCommand)
  110. BindingOperations.ClearBinding(this, FloatCommandProperty);
  111. if (DockAsDocumentCommand == _defaultDockAsDocumentCommand)
  112. BindingOperations.ClearBinding(this, DockAsDocumentCommandProperty);
  113. if (CloseAllButThisCommand == _defaultCloseAllButThisCommand)
  114. BindingOperations.ClearBinding(this, CloseAllButThisCommandProperty);
  115. if (ActivateCommand == _defaultActivateCommand)
  116. BindingOperations.ClearBinding(this, ActivateCommandProperty);
  117. if (NewVerticalTabGroupCommand == _defaultNewVerticalTabGroupCommand)
  118. BindingOperations.ClearBinding(this, NewVerticalTabGroupCommandProperty);
  119. if (NewHorizontalTabGroupCommand == _defaultNewHorizontalTabGroupCommand)
  120. BindingOperations.ClearBinding(this, NewHorizontalTabGroupCommandProperty);
  121. if (MoveToNextTabGroupCommand == _defaultMoveToNextTabGroupCommand)
  122. BindingOperations.ClearBinding(this, MoveToNextTabGroupCommandProperty);
  123. if (MoveToPreviousTabGroupCommand == _defaultMoveToPreviousTabGroupCommand)
  124. BindingOperations.ClearBinding(this, MoveToPreviousTabGroupCommandProperty);
  125. }
  126. protected virtual void SetDefaultBindings()
  127. {
  128. if (CloseCommand == null)
  129. CloseCommand = _defaultCloseCommand;
  130. if (FloatCommand == null)
  131. FloatCommand = _defaultFloatCommand;
  132. if (DockAsDocumentCommand == null)
  133. DockAsDocumentCommand = _defaultDockAsDocumentCommand;
  134. if (CloseAllButThisCommand == null)
  135. CloseAllButThisCommand = _defaultCloseAllButThisCommand;
  136. if (ActivateCommand == null)
  137. ActivateCommand = _defaultActivateCommand;
  138. if (NewVerticalTabGroupCommand == null)
  139. NewVerticalTabGroupCommand = _defaultNewVerticalTabGroupCommand;
  140. if (NewHorizontalTabGroupCommand == null)
  141. NewHorizontalTabGroupCommand = _defaultNewHorizontalTabGroupCommand;
  142. if (MoveToNextTabGroupCommand == null)
  143. MoveToNextTabGroupCommand = _defaultMoveToNextTabGroupCommand;
  144. if (MoveToPreviousTabGroupCommand == null)
  145. MoveToPreviousTabGroupCommand = _defaultMoveToPreviousTabGroupCommand;
  146. IsSelected = LayoutElement.IsSelected;
  147. IsActive = LayoutElement.IsActive;
  148. }
  149. internal void _ClearDefaultBindings()
  150. {
  151. ClearDefaultBindings();
  152. }
  153. internal void _SetDefaultBindings()
  154. {
  155. SetDefaultBindings();
  156. }
  157. ContentPresenter _view = null;
  158. public ContentPresenter View
  159. {
  160. get
  161. {
  162. if (_view == null)
  163. {
  164. _view = new ContentPresenter();
  165. _view.SetBinding(ContentPresenter.ContentProperty, new Binding("Content") { Source = LayoutElement });
  166. _view.SetBinding(ContentPresenter.ContentTemplateProperty, new Binding("LayoutItemTemplate") { Source = LayoutElement.Root.Manager});
  167. _view.SetBinding(ContentPresenter.ContentTemplateSelectorProperty, new Binding("LayoutItemTemplateSelector") { Source = LayoutElement.Root.Manager });
  168. LayoutElement.Root.Manager.InternalAddLogicalChild(_view);
  169. }
  170. return _view;
  171. }
  172. }
  173. #region Title
  174. /// <summary>
  175. /// Title Dependency Property
  176. /// </summary>
  177. public static readonly DependencyProperty TitleProperty =
  178. DependencyProperty.Register("Title", typeof(string), typeof(LayoutItem),
  179. new FrameworkPropertyMetadata((string)null,
  180. new PropertyChangedCallback(OnTitleChanged)));
  181. /// <summary>
  182. /// Gets or sets the Title property. This dependency property
  183. /// indicates the title of the element.
  184. /// </summary>
  185. public string Title
  186. {
  187. get { return (string)GetValue(TitleProperty); }
  188. set { SetValue(TitleProperty, value); }
  189. }
  190. /// <summary>
  191. /// Handles changes to the Title property.
  192. /// </summary>
  193. private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  194. {
  195. ((LayoutItem)d).OnTitleChanged(e);
  196. }
  197. /// <summary>
  198. /// Provides derived classes an opportunity to handle changes to the Title property.
  199. /// </summary>
  200. protected virtual void OnTitleChanged(DependencyPropertyChangedEventArgs e)
  201. {
  202. if (LayoutElement != null)
  203. LayoutElement.Title = (string)e.NewValue;
  204. }
  205. #endregion
  206. #region ToolTip
  207. private static void OnToolTipChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  208. {
  209. ((LayoutItem)s).OnToolTipChanged();
  210. }
  211. private void OnToolTipChanged()
  212. {
  213. if (LayoutElement != null)
  214. LayoutElement.ToolTip = ToolTip;
  215. }
  216. #endregion
  217. #region IconSource
  218. /// <summary>
  219. /// IconSource Dependency Property
  220. /// </summary>
  221. public static readonly DependencyProperty IconSourceProperty =
  222. DependencyProperty.Register("IconSource", typeof(ImageSource), typeof(LayoutItem),
  223. new FrameworkPropertyMetadata((ImageSource)null,
  224. new PropertyChangedCallback(OnIconSourceChanged)));
  225. /// <summary>
  226. /// Gets or sets the IconSource property. This dependency property
  227. /// indicates icon associated with the item.
  228. /// </summary>
  229. public ImageSource IconSource
  230. {
  231. get { return (ImageSource)GetValue(IconSourceProperty); }
  232. set { SetValue(IconSourceProperty, value); }
  233. }
  234. /// <summary>
  235. /// Handles changes to the IconSource property.
  236. /// </summary>
  237. private static void OnIconSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  238. {
  239. ((LayoutItem)d).OnIconSourceChanged(e);
  240. }
  241. /// <summary>
  242. /// Provides derived classes an opportunity to handle changes to the IconSource property.
  243. /// </summary>
  244. protected virtual void OnIconSourceChanged(DependencyPropertyChangedEventArgs e)
  245. {
  246. if (LayoutElement != null)
  247. LayoutElement.IconSource = IconSource;
  248. }
  249. #endregion
  250. #region Visibility
  251. private static void OnVisibilityChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
  252. {
  253. ((LayoutItem)s).OnVisibilityChanged();
  254. }
  255. protected virtual void OnVisibilityChanged()
  256. {
  257. if (LayoutElement != null &&
  258. Visibility == System.Windows.Visibility.Collapsed)
  259. LayoutElement.Close();
  260. }
  261. #endregion
  262. #region ContentId
  263. /// <summary>
  264. /// ContentId Dependency Property
  265. /// </summary>
  266. public static readonly DependencyProperty ContentIdProperty =
  267. DependencyProperty.Register("ContentId", typeof(string), typeof(LayoutItem),
  268. new FrameworkPropertyMetadata((string)null,
  269. new PropertyChangedCallback(OnContentIdChanged)));
  270. /// <summary>
  271. /// Gets or sets the ContentId property. This dependency property
  272. /// indicates the content id used to retrive content when deserializing layouts.
  273. /// </summary>
  274. public string ContentId
  275. {
  276. get { return (string)GetValue(ContentIdProperty); }
  277. set { SetValue(ContentIdProperty, value); }
  278. }
  279. /// <summary>
  280. /// Handles changes to the ContentId property.
  281. /// </summary>
  282. private static void OnContentIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  283. {
  284. ((LayoutItem)d).OnContentIdChanged(e);
  285. }
  286. /// <summary>
  287. /// Provides derived classes an opportunity to handle changes to the ContentId property.
  288. /// </summary>
  289. protected virtual void OnContentIdChanged(DependencyPropertyChangedEventArgs e)
  290. {
  291. if (LayoutElement != null)
  292. LayoutElement.ContentId = (string)e.NewValue;
  293. }
  294. #endregion
  295. #region IsSelected
  296. ReentrantFlag _isSelectedReentrantFlag = new ReentrantFlag();
  297. /// <summary>
  298. /// IsSelected Dependency Property
  299. /// </summary>
  300. public static readonly DependencyProperty IsSelectedProperty =
  301. DependencyProperty.Register("IsSelected", typeof(bool), typeof(LayoutItem),
  302. new FrameworkPropertyMetadata((bool)false,
  303. new PropertyChangedCallback(OnIsSelectedChanged)));
  304. /// <summary>
  305. /// Gets or sets the IsSelected property. This dependency property
  306. /// indicates if the item is selected inside its container.
  307. /// </summary>
  308. public bool IsSelected
  309. {
  310. get { return (bool)GetValue(IsSelectedProperty); }
  311. set { SetValue(IsSelectedProperty, value); }
  312. }
  313. /// <summary>
  314. /// Handles changes to the IsSelected property.
  315. /// </summary>
  316. private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  317. {
  318. ((LayoutItem)d).OnIsSelectedChanged(e);
  319. }
  320. /// <summary>
  321. /// Provides derived classes an opportunity to handle changes to the IsSelected property.
  322. /// </summary>
  323. protected virtual void OnIsSelectedChanged(DependencyPropertyChangedEventArgs e)
  324. {
  325. if (_isSelectedReentrantFlag.CanEnter)
  326. {
  327. using (_isSelectedReentrantFlag.Enter())
  328. {
  329. if (LayoutElement != null)
  330. LayoutElement.IsSelected = (bool)e.NewValue;
  331. }
  332. }
  333. }
  334. #endregion
  335. #region IsActive
  336. ReentrantFlag _isActiveReentrantFlag = new ReentrantFlag();
  337. /// <summary>
  338. /// IsActive Dependency Property
  339. /// </summary>
  340. public static readonly DependencyProperty IsActiveProperty =
  341. DependencyProperty.Register("IsActive", typeof(bool), typeof(LayoutItem),
  342. new FrameworkPropertyMetadata((bool)false,
  343. new PropertyChangedCallback(OnIsActiveChanged)));
  344. /// <summary>
  345. /// Gets or sets the IsActive property. This dependency property
  346. /// indicates if the item is active in the UI.
  347. /// </summary>
  348. public bool IsActive
  349. {
  350. get { return (bool)GetValue(IsActiveProperty); }
  351. set { SetValue(IsActiveProperty, value); }
  352. }
  353. /// <summary>
  354. /// Handles changes to the IsActive property.
  355. /// </summary>
  356. private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  357. {
  358. ((LayoutItem)d).OnIsActiveChanged(e);
  359. }
  360. /// <summary>
  361. /// Provides derived classes an opportunity to handle changes to the IsActive property.
  362. /// </summary>
  363. protected virtual void OnIsActiveChanged(DependencyPropertyChangedEventArgs e)
  364. {
  365. if (_isActiveReentrantFlag.CanEnter)
  366. {
  367. using (_isActiveReentrantFlag.Enter())
  368. {
  369. if (LayoutElement != null)
  370. LayoutElement.IsActive = (bool)e.NewValue;
  371. }
  372. }
  373. }
  374. #endregion
  375. #region CanClose
  376. /// <summary>
  377. /// CanClose Dependency Property
  378. /// </summary>
  379. public static readonly DependencyProperty CanCloseProperty =
  380. DependencyProperty.Register("CanClose", typeof(bool), typeof(LayoutItem),
  381. new FrameworkPropertyMetadata((bool)true,
  382. new PropertyChangedCallback(OnCanCloseChanged)));
  383. /// <summary>
  384. /// Gets or sets the CanClose property. This dependency property
  385. /// indicates if the item can be closed.
  386. /// </summary>
  387. public bool CanClose
  388. {
  389. get { return (bool)GetValue(CanCloseProperty); }
  390. set { SetValue(CanCloseProperty, value); }
  391. }
  392. /// <summary>
  393. /// Handles changes to the CanClose property.
  394. /// </summary>
  395. private static void OnCanCloseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  396. {
  397. ((LayoutItem)d).OnCanCloseChanged(e);
  398. }
  399. /// <summary>
  400. /// Provides derived classes an opportunity to handle changes to the CanClose property.
  401. /// </summary>
  402. protected virtual void OnCanCloseChanged(DependencyPropertyChangedEventArgs e)
  403. {
  404. if (LayoutElement != null)
  405. LayoutElement.CanClose = (bool)e.NewValue;
  406. }
  407. #endregion
  408. #region CanFloat
  409. /// <summary>
  410. /// CanFloat Dependency Property
  411. /// </summary>
  412. public static readonly DependencyProperty CanFloatProperty =
  413. DependencyProperty.Register("CanFloat", typeof(bool), typeof(LayoutItem),
  414. new FrameworkPropertyMetadata((bool)true,
  415. new PropertyChangedCallback(OnCanFloatChanged)));
  416. /// <summary>
  417. /// Gets or sets the CanFloat property. This dependency property
  418. /// indicates if user can move the layout element dragging it to another position.
  419. /// </summary>
  420. public bool CanFloat
  421. {
  422. get { return (bool)GetValue(CanFloatProperty); }
  423. set { SetValue(CanFloatProperty, value); }
  424. }
  425. /// <summary>
  426. /// Handles changes to the CanFloat property.
  427. /// </summary>
  428. private static void OnCanFloatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  429. {
  430. ((LayoutItem)d).OnCanFloatChanged(e);
  431. }
  432. /// <summary>
  433. /// Provides derived classes an opportunity to handle changes to the CanFloat property.
  434. /// </summary>
  435. protected virtual void OnCanFloatChanged(DependencyPropertyChangedEventArgs e)
  436. {
  437. if (LayoutElement != null)
  438. LayoutElement.CanFloat = (bool)e.NewValue;
  439. }
  440. #endregion
  441. #region CloseCommand
  442. /// <summary>
  443. /// CloseCommand Dependency Property
  444. /// </summary>
  445. public static readonly DependencyProperty CloseCommandProperty =
  446. DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(LayoutItem),
  447. new FrameworkPropertyMetadata(null,
  448. new PropertyChangedCallback(OnCloseCommandChanged),
  449. new CoerceValueCallback(CoerceCloseCommandValue)));
  450. /// <summary>
  451. /// Gets or sets the CloseCommand property. This dependency property
  452. /// indicates the command to execute when user click the document close button.
  453. /// </summary>
  454. public ICommand CloseCommand
  455. {
  456. get { return (ICommand)GetValue(CloseCommandProperty); }
  457. set { SetValue(CloseCommandProperty, value); }
  458. }
  459. /// <summary>
  460. /// Handles changes to the CloseCommand property.
  461. /// </summary>
  462. private static void OnCloseCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  463. {
  464. ((LayoutItem)d).OnCloseCommandChanged(e);
  465. }
  466. /// <summary>
  467. /// Provides derived classes an opportunity to handle changes to the CloseCommand property.
  468. /// </summary>
  469. protected virtual void OnCloseCommandChanged(DependencyPropertyChangedEventArgs e)
  470. {
  471. }
  472. /// <summary>
  473. /// Coerces the CloseCommand value.
  474. /// </summary>
  475. private static object CoerceCloseCommandValue(DependencyObject d, object value)
  476. {
  477. return value;
  478. }
  479. private bool CanExecuteCloseCommand(object parameter)
  480. {
  481. #if DEBUG
  482. if( LayoutElement != null )
  483. System.Diagnostics.Trace.WriteLine( string.Format( "CanExecuteCloseCommand({0}) = {1}", LayoutElement.Title, LayoutElement.CanClose ) );
  484. #endif
  485. return LayoutElement != null && LayoutElement.CanClose;
  486. }
  487. private void ExecuteCloseCommand(object parameter)
  488. {
  489. Close();
  490. }
  491. protected abstract void Close();
  492. #endregion
  493. #region FloatCommand
  494. /// <summary>
  495. /// FloatCommand Dependency Property
  496. /// </summary>
  497. public static readonly DependencyProperty FloatCommandProperty =
  498. DependencyProperty.Register("FloatCommand", typeof(ICommand), typeof(LayoutItem),
  499. new FrameworkPropertyMetadata(null,
  500. new PropertyChangedCallback(OnFloatCommandChanged),
  501. new CoerceValueCallback(CoerceFloatCommandValue)));
  502. /// <summary>
  503. /// Gets or sets the FloatCommand property. This dependency property
  504. /// indicates the command to execute when user click the float button.
  505. /// </summary>
  506. /// <remarks>By default this command move the anchorable inside new floating window.</remarks>
  507. public ICommand FloatCommand
  508. {
  509. get { return (ICommand)GetValue(FloatCommandProperty); }
  510. set { SetValue(FloatCommandProperty, value); }
  511. }
  512. /// <summary>
  513. /// Handles changes to the FloatCommand property.
  514. /// </summary>
  515. private static void OnFloatCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  516. {
  517. ((LayoutItem)d).OnFloatCommandChanged(e);
  518. }
  519. /// <summary>
  520. /// Provides derived classes an opportunity to handle changes to the FloatCommand property.
  521. /// </summary>
  522. protected virtual void OnFloatCommandChanged(DependencyPropertyChangedEventArgs e)
  523. {
  524. }
  525. /// <summary>
  526. /// Coerces the FloatCommand value.
  527. /// </summary>
  528. private static object CoerceFloatCommandValue(DependencyObject d, object value)
  529. {
  530. return value;
  531. }
  532. private bool CanExecuteFloatCommand(object anchorable)
  533. {
  534. return LayoutElement != null && LayoutElement.CanFloat && LayoutElement.FindParent<LayoutFloatingWindow>() == null;
  535. }
  536. private void ExecuteFloatCommand(object parameter)
  537. {
  538. LayoutElement.Root.Manager._ExecuteFloatCommand(LayoutElement);
  539. }
  540. protected virtual void Float()
  541. {
  542. }
  543. #endregion
  544. #region DockAsDocumentCommand
  545. /// <summary>
  546. /// DockAsDocumentCommand Dependency Property
  547. /// </summary>
  548. public static readonly DependencyProperty DockAsDocumentCommandProperty =
  549. DependencyProperty.Register("DockAsDocumentCommand", typeof(ICommand), typeof(LayoutItem),
  550. new FrameworkPropertyMetadata(null,
  551. new PropertyChangedCallback(OnDockAsDocumentCommandChanged),
  552. new CoerceValueCallback(CoerceDockAsDocumentCommandValue)));
  553. /// <summary>
  554. /// Gets or sets the DockAsDocumentCommand property. This dependency property
  555. /// indicates the command to execute when user click the DockAsDocument button.
  556. /// </summary>
  557. /// <remarks>By default this command move the anchorable inside the last focused document pane.</remarks>
  558. public ICommand DockAsDocumentCommand
  559. {
  560. get { return (ICommand)GetValue(DockAsDocumentCommandProperty); }
  561. set { SetValue(DockAsDocumentCommandProperty, value); }
  562. }
  563. /// <summary>
  564. /// Handles changes to the DockAsDocumentCommand property.
  565. /// </summary>
  566. private static void OnDockAsDocumentCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  567. {
  568. ((LayoutItem)d).OnDockAsDocumentCommandChanged(e);
  569. }
  570. /// <summary>
  571. /// Provides derived classes an opportunity to handle changes to the DockAsDocumentCommand property.
  572. /// </summary>
  573. protected virtual void OnDockAsDocumentCommandChanged(DependencyPropertyChangedEventArgs e)
  574. {
  575. }
  576. /// <summary>
  577. /// Coerces the DockAsDocumentCommand value.
  578. /// </summary>
  579. private static object CoerceDockAsDocumentCommandValue(DependencyObject d, object value)
  580. {
  581. return value;
  582. }
  583. private bool CanExecuteDockAsDocumentCommand(object parameter)
  584. {
  585. return LayoutElement != null && LayoutElement.FindParent<LayoutDocumentPane>() == null;
  586. }
  587. private void ExecuteDockAsDocumentCommand(object parameter)
  588. {
  589. LayoutElement.Root.Manager._ExecuteDockAsDocumentCommand(LayoutElement);
  590. }
  591. #endregion
  592. #region CloseAllButThisCommand
  593. /// <summary>
  594. /// CloseAllButThisCommand Dependency Property
  595. /// </summary>
  596. public static readonly DependencyProperty CloseAllButThisCommandProperty =
  597. DependencyProperty.Register("CloseAllButThisCommand", typeof(ICommand), typeof(LayoutItem),
  598. new FrameworkPropertyMetadata(null,
  599. new PropertyChangedCallback(OnCloseAllButThisCommandChanged),
  600. new CoerceValueCallback(CoerceCloseAllButThisCommandValue)));
  601. /// <summary>
  602. /// Gets or sets the CloseAllButThisCommand property. This dependency property
  603. /// indicates the 'Close All But This' command.
  604. /// </summary>
  605. public ICommand CloseAllButThisCommand
  606. {
  607. get { return (ICommand)GetValue(CloseAllButThisCommandProperty); }
  608. set { SetValue(CloseAllButThisCommandProperty, value); }
  609. }
  610. /// <summary>
  611. /// Handles changes to the CloseAllButThisCommand property.
  612. /// </summary>
  613. private static void OnCloseAllButThisCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  614. {
  615. ((LayoutItem)d).OnCloseAllButThisCommandChanged(e);
  616. }
  617. /// <summary>
  618. /// Provides derived classes an opportunity to handle changes to the CloseAllButThisCommand property.
  619. /// </summary>
  620. protected virtual void OnCloseAllButThisCommandChanged(DependencyPropertyChangedEventArgs e)
  621. {
  622. }
  623. /// <summary>
  624. /// Coerces the CloseAllButThisCommand value.
  625. /// </summary>
  626. private static object CoerceCloseAllButThisCommandValue(DependencyObject d, object value)
  627. {
  628. return value;
  629. }
  630. private bool CanExecuteCloseAllButThisCommand(object parameter)
  631. {
  632. if (LayoutElement == null)
  633. return false;
  634. var root = LayoutElement.Root;
  635. if (root == null)
  636. return false;
  637. return LayoutElement.Root.Manager.Layout.
  638. Descendents().OfType<LayoutContent>().Where(d => d != LayoutElement && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).Any();
  639. }
  640. private void ExecuteCloseAllButThisCommand(object parameter)
  641. {
  642. LayoutElement.Root.Manager._ExecuteCloseAllButThisCommand(LayoutElement);
  643. }
  644. #endregion
  645. #region ActivateCommand
  646. /// <summary>
  647. /// ActivateCommand Dependency Property
  648. /// </summary>
  649. public static readonly DependencyProperty ActivateCommandProperty =
  650. DependencyProperty.Register("ActivateCommand", typeof(ICommand), typeof(LayoutItem),
  651. new FrameworkPropertyMetadata(null,
  652. new PropertyChangedCallback(OnActivateCommandChanged),
  653. new CoerceValueCallback(CoerceActivateCommandValue)));
  654. /// <summary>
  655. /// Gets or sets the ActivateCommand property. This dependency property
  656. /// indicates the command to execute when user wants to activate a content (either a Document or an Anchorable).
  657. /// </summary>
  658. public ICommand ActivateCommand
  659. {
  660. get { return (ICommand)GetValue(ActivateCommandProperty); }
  661. set { SetValue(ActivateCommandProperty, value); }
  662. }
  663. /// <summary>
  664. /// Handles changes to the ActivateCommand property.
  665. /// </summary>
  666. private static void OnActivateCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  667. {
  668. ((LayoutItem)d).OnActivateCommandChanged(e);
  669. }
  670. /// <summary>
  671. /// Provides derived classes an opportunity to handle changes to the ActivateCommand property.
  672. /// </summary>
  673. protected virtual void OnActivateCommandChanged(DependencyPropertyChangedEventArgs e)
  674. {
  675. }
  676. /// <summary>
  677. /// Coerces the ActivateCommand value.
  678. /// </summary>
  679. private static object CoerceActivateCommandValue(DependencyObject d, object value)
  680. {
  681. return value;
  682. }
  683. private bool CanExecuteActivateCommand(object parameter)
  684. {
  685. return LayoutElement != null;
  686. }
  687. private void ExecuteActivateCommand(object parameter)
  688. {
  689. LayoutElement.Root.Manager._ExecuteContentActivateCommand(LayoutElement);
  690. }
  691. #endregion
  692. #region NewVerticalTabGroupCommand
  693. /// <summary>
  694. /// NewVerticalTabGroupCommand Dependency Property
  695. /// </summary>
  696. public static readonly DependencyProperty NewVerticalTabGroupCommandProperty =
  697. DependencyProperty.Register("NewVerticalTabGroupCommand", typeof(ICommand), typeof(LayoutItem),
  698. new FrameworkPropertyMetadata((ICommand)null,
  699. new PropertyChangedCallback(OnNewVerticalTabGroupCommandChanged)));
  700. /// <summary>
  701. /// Gets or sets the NewVerticalTabGroupCommand property. This dependency property
  702. /// indicates the new vertical tab group command.
  703. /// </summary>
  704. public ICommand NewVerticalTabGroupCommand
  705. {
  706. get { return (ICommand)GetValue(NewVerticalTabGroupCommandProperty); }
  707. set { SetValue(NewVerticalTabGroupCommandProperty, value); }
  708. }
  709. /// <summary>
  710. /// Handles changes to the NewVerticalTabGroupCommand property.
  711. /// </summary>
  712. private static void OnNewVerticalTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  713. {
  714. ((LayoutItem)d).OnNewVerticalTabGroupCommandChanged(e);
  715. }
  716. /// <summary>
  717. /// Provides derived classes an opportunity to handle changes to the NewVerticalTabGroupCommand property.
  718. /// </summary>
  719. protected virtual void OnNewVerticalTabGroupCommandChanged(DependencyPropertyChangedEventArgs e)
  720. {
  721. }
  722. private bool CanExecuteNewVerticalTabGroupCommand(object parameter)
  723. {
  724. if (LayoutElement == null)
  725. return false;
  726. var parentDocumentGroup = LayoutElement.FindParent<LayoutDocumentPaneGroup>();
  727. var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane;
  728. return ((parentDocumentGroup == null ||
  729. parentDocumentGroup.ChildrenCount == 1 ||
  730. parentDocumentGroup.Root.Manager.AllowMixedOrientation ||
  731. parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Horizontal) &&
  732. parentDocumentPane != null &&
  733. parentDocumentPane.ChildrenCount > 1);
  734. }
  735. private void ExecuteNewVerticalTabGroupCommand(object parameter)
  736. {
  737. var layoutElement = LayoutElement;
  738. var parentDocumentGroup = layoutElement.FindParent<LayoutDocumentPaneGroup>();
  739. var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane;
  740. if (parentDocumentGroup == null)
  741. {
  742. var grandParent = parentDocumentPane.Parent as ILayoutContainer;
  743. parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal };
  744. grandParent.ReplaceChild(parentDocumentPane, parentDocumentGroup);
  745. parentDocumentGroup.Children.Add(parentDocumentPane);
  746. }
  747. parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Horizontal;
  748. int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane);
  749. parentDocumentGroup.InsertChildAt(indexOfParentPane + 1, new LayoutDocumentPane(layoutElement));
  750. layoutElement.IsActive = true;
  751. layoutElement.Root.CollectGarbage();
  752. }
  753. #endregion
  754. #region NewHorizontalTabGroupCommand
  755. /// <summary>
  756. /// NewHorizontalTabGroupCommand Dependency Property
  757. /// </summary>
  758. public static readonly DependencyProperty NewHorizontalTabGroupCommandProperty =
  759. DependencyProperty.Register("NewHorizontalTabGroupCommand", typeof(ICommand), typeof(LayoutItem),
  760. new FrameworkPropertyMetadata((ICommand)null,
  761. new PropertyChangedCallback(OnNewHorizontalTabGroupCommandChanged)));
  762. /// <summary>
  763. /// Gets or sets the NewHorizontalTabGroupCommand property. This dependency property
  764. /// indicates the new horizontal tab group command.
  765. /// </summary>
  766. public ICommand NewHorizontalTabGroupCommand
  767. {
  768. get { return (ICommand)GetValue(NewHorizontalTabGroupCommandProperty); }
  769. set { SetValue(NewHorizontalTabGroupCommandProperty, value); }
  770. }
  771. /// <summary>
  772. /// Handles changes to the NewHorizontalTabGroupCommand property.
  773. /// </summary>
  774. private static void OnNewHorizontalTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  775. {
  776. ((LayoutItem)d).OnNewHorizontalTabGroupCommandChanged(e);
  777. }
  778. /// <summary>
  779. /// Provides derived classes an opportunity to handle changes to the NewHorizontalTabGroupCommand property.
  780. /// </summary>
  781. protected virtual void OnNewHorizontalTabGroupCommandChanged(DependencyPropertyChangedEventArgs e)
  782. {
  783. }
  784. private bool CanExecuteNewHorizontalTabGroupCommand(object parameter)
  785. {
  786. if (LayoutElement == null)
  787. return false;
  788. var parentDocumentGroup = LayoutElement.FindParent<LayoutDocumentPaneGroup>();
  789. var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane;
  790. return ((parentDocumentGroup == null ||
  791. parentDocumentGroup.ChildrenCount == 1 ||
  792. parentDocumentGroup.Root.Manager.AllowMixedOrientation ||
  793. parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Vertical) &&
  794. parentDocumentPane != null &&
  795. parentDocumentPane.ChildrenCount > 1);
  796. }
  797. private void ExecuteNewHorizontalTabGroupCommand(object parameter)
  798. {
  799. var layoutElement = LayoutElement;
  800. var parentDocumentGroup = layoutElement.FindParent<LayoutDocumentPaneGroup>();
  801. var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane;
  802. if (parentDocumentGroup == null)
  803. {
  804. var grandParent = parentDocumentPane.Parent as ILayoutContainer;
  805. parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical };
  806. grandParent.ReplaceChild(parentDocumentPane, parentDocumentGroup);
  807. parentDocumentGroup.Children.Add(parentDocumentPane);
  808. }
  809. parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Vertical;
  810. int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane);
  811. parentDocumentGroup.InsertChildAt(indexOfParentPane + 1, new LayoutDocumentPane(layoutElement));
  812. layoutElement.IsActive = true;
  813. layoutElement.Root.CollectGarbage();
  814. }
  815. #endregion
  816. #region MoveToNextTabGroupCommand
  817. /// <summary>
  818. /// MoveToNextTabGroupCommand Dependency Property
  819. /// </summary>
  820. public static readonly DependencyProperty MoveToNextTabGroupCommandProperty =
  821. DependencyProperty.Register("MoveToNextTabGroupCommand", typeof(ICommand), typeof(LayoutItem),
  822. new FrameworkPropertyMetadata((ICommand)null,
  823. new PropertyChangedCallback(OnMoveToNextTabGroupCommandChanged)));
  824. /// <summary>
  825. /// Gets or sets the MoveToNextTabGroupCommand property. This dependency property
  826. /// indicates move to next tab group command.
  827. /// </summary>
  828. public ICommand MoveToNextTabGroupCommand
  829. {
  830. get { return (ICommand)GetValue(MoveToNextTabGroupCommandProperty); }
  831. set { SetValue(MoveToNextTabGroupCommandProperty, value); }
  832. }
  833. /// <summary>
  834. /// Handles changes to the MoveToNextTabGroupCommand property.
  835. /// </summary>
  836. private static void OnMoveToNextTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  837. {
  838. ((LayoutItem)d).OnMoveToNextTabGroupCommandChanged(e);
  839. }
  840. /// <summary>
  841. /// Provides derived classes an opportunity to handle changes to the MoveToNextTabGroupCommand property.
  842. /// </summary>
  843. protected virtual void OnMoveToNextTabGroupCommandChanged(DependencyPropertyChangedEventArgs e)
  844. {
  845. }
  846. private bool CanExecuteMoveToNextTabGroupCommand(object parameter)
  847. {
  848. if (LayoutElement == null)
  849. return false;
  850. var parentDocumentGroup = LayoutElement.FindParent<LayoutDocumentPaneGroup>();
  851. var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane;
  852. return (parentDocumentGroup != null &&
  853. parentDocumentPane != null &&
  854. parentDocumentGroup.ChildrenCount > 1 &&
  855. parentDocumentGroup.IndexOfChild(parentDocumentPane) < parentDocumentGroup.ChildrenCount - 1 &&
  856. parentDocumentGroup.Children[parentDocumentGroup.IndexOfChild(parentDocumentPane) + 1] is LayoutDocumentPane);
  857. }
  858. private void ExecuteMoveToNextTabGroupCommand(object parameter)
  859. {
  860. var layoutElement = LayoutElement;
  861. var parentDocumentGroup = layoutElement.FindParent<LayoutDocumentPaneGroup>();
  862. var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane;
  863. int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane);
  864. var nextDocumentPane = parentDocumentGroup.Children[indexOfParentPane + 1] as LayoutDocumentPane;
  865. nextDocumentPane.InsertChildAt(0, layoutElement);
  866. layoutElement.IsActive = true;
  867. layoutElement.Root.CollectGarbage();
  868. }
  869. #endregion
  870. #region MoveToPreviousTabGroupCommand
  871. /// <summary>
  872. /// MoveToPreviousTabGroupCommand Dependency Property
  873. /// </summary>
  874. public static readonly DependencyProperty MoveToPreviousTabGroupCommandProperty =
  875. DependencyProperty.Register("MoveToPreviousTabGroupCommand", typeof(ICommand), typeof(LayoutItem),
  876. new FrameworkPropertyMetadata((ICommand)null,
  877. new PropertyChangedCallback(OnMoveToPreviousTabGroupCommandChanged)));
  878. /// <summary>
  879. /// Gets or sets the MoveToPreviousTabGroupCommand property. This dependency property
  880. /// indicates move to rpevious tab group command.
  881. /// </summary>
  882. public ICommand MoveToPreviousTabGroupCommand
  883. {
  884. get { return (ICommand)GetValue(MoveToPreviousTabGroupCommandProperty); }
  885. set { SetValue(MoveToPreviousTabGroupCommandProperty, value); }
  886. }
  887. /// <summary>
  888. /// Handles changes to the MoveToPreviousTabGroupCommand property.
  889. /// </summary>
  890. private static void OnMoveToPreviousTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  891. {
  892. ((LayoutItem)d).OnMoveToPreviousTabGroupCommandChanged(e);
  893. }
  894. /// <summary>
  895. /// Provides derived classes an opportunity to handle changes to the MoveToPreviousTabGroupCommand property.
  896. /// </summary>
  897. protected virtual void OnMoveToPreviousTabGroupCommandChanged(DependencyPropertyChangedEventArgs e)
  898. {
  899. }
  900. private bool CanExecuteMoveToPreviousTabGroupCommand(object parameter)
  901. {
  902. if (LayoutElement == null)
  903. return false;
  904. var parentDocumentGroup = LayoutElement.FindParent<LayoutDocumentPaneGroup>();
  905. var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane;
  906. return (parentDocumentGroup != null &&
  907. parentDocumentPane != null &&
  908. parentDocumentGroup.ChildrenCount > 1 &&
  909. parentDocumentGroup.IndexOfChild(parentDocumentPane) > 0 &&
  910. parentDocumentGroup.Children[parentDocumentGroup.IndexOfChild(parentDocumentPane) - 1] is LayoutDocumentPane);
  911. }
  912. private void ExecuteMoveToPreviousTabGroupCommand(object parameter)
  913. {
  914. var layoutElement = LayoutElement;
  915. var parentDocumentGroup = layoutElement.FindParent<LayoutDocumentPaneGroup>();
  916. var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane;
  917. int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane);
  918. var nextDocumentPane = parentDocumentGroup.Children[indexOfParentPane - 1] as LayoutDocumentPane;
  919. nextDocumentPane.InsertChildAt(0, layoutElement);
  920. layoutElement.IsActive = true;
  921. layoutElement.Root.CollectGarbage();
  922. }
  923. #endregion
  924. }
  925. }