DockPanel.AutoHideWindow.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. /*******************************************************************************
  2. * Copyright(c) 2014 DongkeSoft All rights reserved. / Confidential
  3. * 类的信息:
  4. * 1.程序名称:DockPanel.cs
  5. * 2.功能描述:类文件
  6. * 编辑履历:
  7. * 作者 日期 版本 修改内容
  8. * 陈晓野 2014/09/01 1.00 新建
  9. *******************************************************************************/
  10. using System;
  11. using System.Drawing;
  12. using System.Windows.Forms;
  13. namespace Dongke.IBOSS.PRD.Basics.DockPanel
  14. {
  15. /// <summary>
  16. /// 类文件
  17. /// </summary>
  18. partial class DockPanel
  19. {
  20. private class AutoHideWindowControl : Panel, ISplitterDragSource
  21. {
  22. private class SplitterControl : SplitterBase
  23. {
  24. public SplitterControl(AutoHideWindowControl autoHideWindow)
  25. {
  26. m_autoHideWindow = autoHideWindow;
  27. }
  28. private AutoHideWindowControl m_autoHideWindow;
  29. private AutoHideWindowControl AutoHideWindow
  30. {
  31. get
  32. {
  33. return m_autoHideWindow;
  34. }
  35. }
  36. protected override int SplitterSize
  37. {
  38. get
  39. {
  40. return Measures.SplitterSize;
  41. }
  42. }
  43. protected override void StartDrag()
  44. {
  45. AutoHideWindow.DockPanel.BeginDrag(AutoHideWindow, AutoHideWindow.RectangleToScreen(Bounds));
  46. }
  47. }
  48. #region consts
  49. private const int ANIMATE_TIME = 100; // in mini-seconds
  50. #endregion
  51. private Timer m_timerMouseTrack;
  52. private SplitterControl m_splitter;
  53. public AutoHideWindowControl(DockPanel dockPanel)
  54. {
  55. m_dockPanel = dockPanel;
  56. m_timerMouseTrack = new Timer();
  57. m_timerMouseTrack.Tick += new EventHandler(TimerMouseTrack_Tick);
  58. Visible = false;
  59. m_splitter = new SplitterControl(this);
  60. Controls.Add(m_splitter);
  61. }
  62. protected override void Dispose(bool disposing)
  63. {
  64. if (disposing)
  65. {
  66. m_timerMouseTrack.Dispose();
  67. }
  68. base.Dispose(disposing);
  69. }
  70. private DockPanel m_dockPanel = null;
  71. public DockPanel DockPanel
  72. {
  73. get
  74. {
  75. return m_dockPanel;
  76. }
  77. }
  78. private DockPane m_activePane = null;
  79. public DockPane ActivePane
  80. {
  81. get
  82. {
  83. return m_activePane;
  84. }
  85. }
  86. private void SetActivePane()
  87. {
  88. DockPane value = (ActiveContent == null ? null : ActiveContent.DockHandler.Pane);
  89. if (value == m_activePane)
  90. return;
  91. m_activePane = value;
  92. }
  93. private IDockContent m_activeContent = null;
  94. public IDockContent ActiveContent
  95. {
  96. get
  97. {
  98. return m_activeContent;
  99. }
  100. set
  101. {
  102. if (value == m_activeContent)
  103. return;
  104. if (value != null)
  105. {
  106. if (!DockHelper.IsDockStateAutoHide(value.DockHandler.DockState) || value.DockHandler.DockPanel != DockPanel)
  107. throw (new InvalidOperationException(Strings.DockPanel_ActiveAutoHideContent_InvalidValue));
  108. }
  109. DockPanel.SuspendLayout();
  110. if (m_activeContent != null)
  111. {
  112. if (m_activeContent.DockHandler.Form.ContainsFocus)
  113. if (!Win32Helper.IsRunningOnMono)
  114. DockPanel.ContentFocusManager.GiveUpFocus(m_activeContent);
  115. AnimateWindow(false);
  116. }
  117. m_activeContent = value;
  118. SetActivePane();
  119. if (ActivePane != null)
  120. ActivePane.ActiveContent = m_activeContent;
  121. if (m_activeContent != null)
  122. AnimateWindow(true);
  123. DockPanel.ResumeLayout();
  124. DockPanel.RefreshAutoHideStrip();
  125. SetTimerMouseTrack();
  126. }
  127. }
  128. public DockState DockState
  129. {
  130. get
  131. {
  132. return ActiveContent == null ? DockState.Unknown : ActiveContent.DockHandler.DockState;
  133. }
  134. }
  135. private bool m_flagAnimate = true;
  136. private bool FlagAnimate
  137. {
  138. get
  139. {
  140. return m_flagAnimate;
  141. }
  142. set
  143. {
  144. m_flagAnimate = value;
  145. }
  146. }
  147. private bool m_flagDragging = false;
  148. internal bool FlagDragging
  149. {
  150. get
  151. {
  152. return m_flagDragging;
  153. }
  154. set
  155. {
  156. if (m_flagDragging == value)
  157. return;
  158. m_flagDragging = value;
  159. SetTimerMouseTrack();
  160. }
  161. }
  162. private void AnimateWindow(bool show)
  163. {
  164. if (!FlagAnimate && Visible != show)
  165. {
  166. Visible = show;
  167. return;
  168. }
  169. Parent.SuspendLayout();
  170. Rectangle rectSource = GetRectangle(!show);
  171. Rectangle rectTarget = GetRectangle(show);
  172. int dxLoc, dyLoc;
  173. int dWidth, dHeight;
  174. dxLoc = dyLoc = dWidth = dHeight = 0;
  175. if (DockState == DockState.DockTopAutoHide)
  176. dHeight = show ? 1 : -1;
  177. else if (DockState == DockState.DockLeftAutoHide)
  178. dWidth = show ? 1 : -1;
  179. else if (DockState == DockState.DockRightAutoHide)
  180. {
  181. dxLoc = show ? -1 : 1;
  182. dWidth = show ? 1 : -1;
  183. }
  184. else if (DockState == DockState.DockBottomAutoHide)
  185. {
  186. dyLoc = (show ? -1 : 1);
  187. dHeight = (show ? 1 : -1);
  188. }
  189. if (show)
  190. {
  191. Bounds = DockPanel.GetAutoHideWindowBounds(new Rectangle(-rectTarget.Width, -rectTarget.Height, rectTarget.Width, rectTarget.Height));
  192. if (Visible == false)
  193. Visible = true;
  194. PerformLayout();
  195. }
  196. SuspendLayout();
  197. LayoutAnimateWindow(rectSource);
  198. if (Visible == false)
  199. Visible = true;
  200. int speedFactor = 1;
  201. int totalPixels = (rectSource.Width != rectTarget.Width) ?
  202. Math.Abs(rectSource.Width - rectTarget.Width) :
  203. Math.Abs(rectSource.Height - rectTarget.Height);
  204. int remainPixels = totalPixels;
  205. DateTime startingTime = DateTime.Now;
  206. while (rectSource != rectTarget)
  207. {
  208. DateTime startPerMove = DateTime.Now;
  209. rectSource.X += dxLoc * speedFactor;
  210. rectSource.Y += dyLoc * speedFactor;
  211. rectSource.Width += dWidth * speedFactor;
  212. rectSource.Height += dHeight * speedFactor;
  213. if (Math.Sign(rectTarget.X - rectSource.X) != Math.Sign(dxLoc))
  214. rectSource.X = rectTarget.X;
  215. if (Math.Sign(rectTarget.Y - rectSource.Y) != Math.Sign(dyLoc))
  216. rectSource.Y = rectTarget.Y;
  217. if (Math.Sign(rectTarget.Width - rectSource.Width) != Math.Sign(dWidth))
  218. rectSource.Width = rectTarget.Width;
  219. if (Math.Sign(rectTarget.Height - rectSource.Height) != Math.Sign(dHeight))
  220. rectSource.Height = rectTarget.Height;
  221. LayoutAnimateWindow(rectSource);
  222. if (Parent != null)
  223. Parent.Update();
  224. remainPixels -= speedFactor;
  225. while (true)
  226. {
  227. TimeSpan time = new TimeSpan(0, 0, 0, 0, ANIMATE_TIME);
  228. TimeSpan elapsedPerMove = DateTime.Now - startPerMove;
  229. TimeSpan elapsedTime = DateTime.Now - startingTime;
  230. if (((int)((time - elapsedTime).TotalMilliseconds)) <= 0)
  231. {
  232. speedFactor = remainPixels;
  233. break;
  234. }
  235. else
  236. speedFactor = remainPixels * (int)elapsedPerMove.TotalMilliseconds / (int)((time - elapsedTime).TotalMilliseconds);
  237. if (speedFactor >= 1)
  238. break;
  239. }
  240. }
  241. ResumeLayout();
  242. Parent.ResumeLayout();
  243. }
  244. private void LayoutAnimateWindow(Rectangle rect)
  245. {
  246. Bounds = DockPanel.GetAutoHideWindowBounds(rect);
  247. Rectangle rectClient = ClientRectangle;
  248. if (DockState == DockState.DockLeftAutoHide)
  249. ActivePane.Location = new Point(rectClient.Right - 2 - Measures.SplitterSize - ActivePane.Width, ActivePane.Location.Y);
  250. else if (DockState == DockState.DockTopAutoHide)
  251. ActivePane.Location = new Point(ActivePane.Location.X, rectClient.Bottom - 2 - Measures.SplitterSize - ActivePane.Height);
  252. }
  253. private Rectangle GetRectangle(bool show)
  254. {
  255. if (DockState == DockState.Unknown)
  256. return Rectangle.Empty;
  257. Rectangle rect = DockPanel.AutoHideWindowRectangle;
  258. if (show)
  259. return rect;
  260. if (DockState == DockState.DockLeftAutoHide)
  261. rect.Width = 0;
  262. else if (DockState == DockState.DockRightAutoHide)
  263. {
  264. rect.X += rect.Width;
  265. rect.Width = 0;
  266. }
  267. else if (DockState == DockState.DockTopAutoHide)
  268. rect.Height = 0;
  269. else
  270. {
  271. rect.Y += rect.Height;
  272. rect.Height = 0;
  273. }
  274. return rect;
  275. }
  276. private void SetTimerMouseTrack()
  277. {
  278. if (ActivePane == null || ActivePane.IsActivated || FlagDragging)
  279. {
  280. m_timerMouseTrack.Enabled = false;
  281. return;
  282. }
  283. // start the timer
  284. int hovertime = SystemInformation.MouseHoverTime;
  285. // assign a default value 400 in case of setting Timer.Interval invalid value exception
  286. if (hovertime <= 0)
  287. hovertime = 400;
  288. m_timerMouseTrack.Interval = 2 * (int)hovertime;
  289. m_timerMouseTrack.Enabled = true;
  290. }
  291. protected virtual Rectangle DisplayingRectangle
  292. {
  293. get
  294. {
  295. Rectangle rect = ClientRectangle;
  296. // exclude the border and the splitter
  297. if (DockState == DockState.DockBottomAutoHide)
  298. {
  299. rect.Y += 2 + Measures.SplitterSize;
  300. rect.Height -= 2 + Measures.SplitterSize;
  301. }
  302. else if (DockState == DockState.DockRightAutoHide)
  303. {
  304. rect.X += 2 + Measures.SplitterSize;
  305. rect.Width -= 2 + Measures.SplitterSize;
  306. }
  307. else if (DockState == DockState.DockTopAutoHide)
  308. rect.Height -= 2 + Measures.SplitterSize;
  309. else if (DockState == DockState.DockLeftAutoHide)
  310. rect.Width -= 2 + Measures.SplitterSize;
  311. return rect;
  312. }
  313. }
  314. protected override void OnLayout(LayoutEventArgs levent)
  315. {
  316. DockPadding.All = 0;
  317. if (DockState == DockState.DockLeftAutoHide)
  318. {
  319. DockPadding.Right = 2;
  320. m_splitter.Dock = DockStyle.Right;
  321. }
  322. else if (DockState == DockState.DockRightAutoHide)
  323. {
  324. DockPadding.Left = 2;
  325. m_splitter.Dock = DockStyle.Left;
  326. }
  327. else if (DockState == DockState.DockTopAutoHide)
  328. {
  329. DockPadding.Bottom = 2;
  330. m_splitter.Dock = DockStyle.Bottom;
  331. }
  332. else if (DockState == DockState.DockBottomAutoHide)
  333. {
  334. DockPadding.Top = 2;
  335. m_splitter.Dock = DockStyle.Top;
  336. }
  337. Rectangle rectDisplaying = DisplayingRectangle;
  338. Rectangle rectHidden = new Rectangle(-rectDisplaying.Width, rectDisplaying.Y, rectDisplaying.Width, rectDisplaying.Height);
  339. foreach (Control c in Controls)
  340. {
  341. DockPane pane = c as DockPane;
  342. if (pane == null)
  343. continue;
  344. if (pane == ActivePane)
  345. pane.Bounds = rectDisplaying;
  346. else
  347. pane.Bounds = rectHidden;
  348. }
  349. base.OnLayout(levent);
  350. }
  351. protected override void OnPaint(PaintEventArgs e)
  352. {
  353. // Draw the border
  354. Graphics g = e.Graphics;
  355. if (DockState == DockState.DockBottomAutoHide)
  356. g.DrawLine(SystemPens.ControlLightLight, 0, 1, ClientRectangle.Right, 1);
  357. else if (DockState == DockState.DockRightAutoHide)
  358. g.DrawLine(SystemPens.ControlLightLight, 1, 0, 1, ClientRectangle.Bottom);
  359. else if (DockState == DockState.DockTopAutoHide)
  360. {
  361. g.DrawLine(SystemPens.ControlDark, 0, ClientRectangle.Height - 2, ClientRectangle.Right, ClientRectangle.Height - 2);
  362. g.DrawLine(SystemPens.ControlDarkDark, 0, ClientRectangle.Height - 1, ClientRectangle.Right, ClientRectangle.Height - 1);
  363. }
  364. else if (DockState == DockState.DockLeftAutoHide)
  365. {
  366. g.DrawLine(SystemPens.ControlDark, ClientRectangle.Width - 2, 0, ClientRectangle.Width - 2, ClientRectangle.Bottom);
  367. g.DrawLine(SystemPens.ControlDarkDark, ClientRectangle.Width - 1, 0, ClientRectangle.Width - 1, ClientRectangle.Bottom);
  368. }
  369. base.OnPaint(e);
  370. }
  371. public void RefreshActiveContent()
  372. {
  373. if (ActiveContent == null)
  374. return;
  375. if (!DockHelper.IsDockStateAutoHide(ActiveContent.DockHandler.DockState))
  376. {
  377. FlagAnimate = false;
  378. ActiveContent = null;
  379. FlagAnimate = true;
  380. }
  381. }
  382. public void RefreshActivePane()
  383. {
  384. SetTimerMouseTrack();
  385. }
  386. private void TimerMouseTrack_Tick(object sender, EventArgs e)
  387. {
  388. if (IsDisposed)
  389. return;
  390. if (ActivePane == null || ActivePane.IsActivated)
  391. {
  392. m_timerMouseTrack.Enabled = false;
  393. return;
  394. }
  395. DockPane pane = ActivePane;
  396. Point ptMouseInAutoHideWindow = PointToClient(Control.MousePosition);
  397. Point ptMouseInDockPanel = DockPanel.PointToClient(Control.MousePosition);
  398. Rectangle rectTabStrip = DockPanel.GetTabStripRectangle(pane.DockState);
  399. if (!ClientRectangle.Contains(ptMouseInAutoHideWindow) && !rectTabStrip.Contains(ptMouseInDockPanel))
  400. {
  401. ActiveContent = null;
  402. m_timerMouseTrack.Enabled = false;
  403. }
  404. }
  405. #region ISplitterDragSource Members
  406. void ISplitterDragSource.BeginDrag(Rectangle rectSplitter)
  407. {
  408. FlagDragging = true;
  409. }
  410. void ISplitterDragSource.EndDrag()
  411. {
  412. FlagDragging = false;
  413. }
  414. bool ISplitterDragSource.IsVertical
  415. {
  416. get
  417. {
  418. return (DockState == DockState.DockLeftAutoHide || DockState == DockState.DockRightAutoHide);
  419. }
  420. }
  421. Rectangle ISplitterDragSource.DragLimitBounds
  422. {
  423. get
  424. {
  425. Rectangle rectLimit = DockPanel.DockArea;
  426. if ((this as ISplitterDragSource).IsVertical)
  427. {
  428. rectLimit.X += MeasurePane.MinSize;
  429. rectLimit.Width -= 2 * MeasurePane.MinSize;
  430. }
  431. else
  432. {
  433. rectLimit.Y += MeasurePane.MinSize;
  434. rectLimit.Height -= 2 * MeasurePane.MinSize;
  435. }
  436. return DockPanel.RectangleToScreen(rectLimit);
  437. }
  438. }
  439. void ISplitterDragSource.MoveSplitter(int offset)
  440. {
  441. Rectangle rectDockArea = DockPanel.DockArea;
  442. IDockContent content = ActiveContent;
  443. if (DockState == DockState.DockLeftAutoHide && rectDockArea.Width > 0)
  444. {
  445. if (content.DockHandler.AutoHidePortion < 1)
  446. content.DockHandler.AutoHidePortion += ((double)offset) / (double)rectDockArea.Width;
  447. else
  448. content.DockHandler.AutoHidePortion = Width + offset;
  449. }
  450. else if (DockState == DockState.DockRightAutoHide && rectDockArea.Width > 0)
  451. {
  452. if (content.DockHandler.AutoHidePortion < 1)
  453. content.DockHandler.AutoHidePortion -= ((double)offset) / (double)rectDockArea.Width;
  454. else
  455. content.DockHandler.AutoHidePortion = Width - offset;
  456. }
  457. else if (DockState == DockState.DockBottomAutoHide && rectDockArea.Height > 0)
  458. {
  459. if (content.DockHandler.AutoHidePortion < 1)
  460. content.DockHandler.AutoHidePortion -= ((double)offset) / (double)rectDockArea.Height;
  461. else
  462. content.DockHandler.AutoHidePortion = Height - offset;
  463. }
  464. else if (DockState == DockState.DockTopAutoHide && rectDockArea.Height > 0)
  465. {
  466. if (content.DockHandler.AutoHidePortion < 1)
  467. content.DockHandler.AutoHidePortion += ((double)offset) / (double)rectDockArea.Height;
  468. else
  469. content.DockHandler.AutoHidePortion = Height + offset;
  470. }
  471. }
  472. #region IDragSource Members
  473. Control IDragSource.DragControl
  474. {
  475. get
  476. {
  477. return this;
  478. }
  479. }
  480. #endregion
  481. #endregion
  482. }
  483. private AutoHideWindowControl AutoHideWindow
  484. {
  485. get
  486. {
  487. return m_autoHideWindow;
  488. }
  489. }
  490. internal Control AutoHideControl
  491. {
  492. get
  493. {
  494. return m_autoHideWindow;
  495. }
  496. }
  497. internal void RefreshActiveAutoHideContent()
  498. {
  499. AutoHideWindow.RefreshActiveContent();
  500. }
  501. internal Rectangle AutoHideWindowRectangle
  502. {
  503. get
  504. {
  505. DockState state = AutoHideWindow.DockState;
  506. Rectangle rectDockArea = DockArea;
  507. if (ActiveAutoHideContent == null)
  508. return Rectangle.Empty;
  509. if (Parent == null)
  510. return Rectangle.Empty;
  511. Rectangle rect = Rectangle.Empty;
  512. double autoHideSize = ActiveAutoHideContent.DockHandler.AutoHidePortion;
  513. if (state == DockState.DockLeftAutoHide)
  514. {
  515. if (autoHideSize < 1)
  516. autoHideSize = rectDockArea.Width * autoHideSize;
  517. if (autoHideSize > rectDockArea.Width - MeasurePane.MinSize)
  518. autoHideSize = rectDockArea.Width - MeasurePane.MinSize;
  519. rect.X = rectDockArea.X;
  520. rect.Y = rectDockArea.Y;
  521. rect.Width = (int)autoHideSize;
  522. rect.Height = rectDockArea.Height;
  523. }
  524. else if (state == DockState.DockRightAutoHide)
  525. {
  526. if (autoHideSize < 1)
  527. autoHideSize = rectDockArea.Width * autoHideSize;
  528. if (autoHideSize > rectDockArea.Width - MeasurePane.MinSize)
  529. autoHideSize = rectDockArea.Width - MeasurePane.MinSize;
  530. rect.X = rectDockArea.X + rectDockArea.Width - (int)autoHideSize;
  531. rect.Y = rectDockArea.Y;
  532. rect.Width = (int)autoHideSize;
  533. rect.Height = rectDockArea.Height;
  534. }
  535. else if (state == DockState.DockTopAutoHide)
  536. {
  537. if (autoHideSize < 1)
  538. autoHideSize = rectDockArea.Height * autoHideSize;
  539. if (autoHideSize > rectDockArea.Height - MeasurePane.MinSize)
  540. autoHideSize = rectDockArea.Height - MeasurePane.MinSize;
  541. rect.X = rectDockArea.X;
  542. rect.Y = rectDockArea.Y;
  543. rect.Width = rectDockArea.Width;
  544. rect.Height = (int)autoHideSize;
  545. }
  546. else if (state == DockState.DockBottomAutoHide)
  547. {
  548. if (autoHideSize < 1)
  549. autoHideSize = rectDockArea.Height * autoHideSize;
  550. if (autoHideSize > rectDockArea.Height - MeasurePane.MinSize)
  551. autoHideSize = rectDockArea.Height - MeasurePane.MinSize;
  552. rect.X = rectDockArea.X;
  553. rect.Y = rectDockArea.Y + rectDockArea.Height - (int)autoHideSize;
  554. rect.Width = rectDockArea.Width;
  555. rect.Height = (int)autoHideSize;
  556. }
  557. return rect;
  558. }
  559. }
  560. internal Rectangle GetAutoHideWindowBounds(Rectangle rectAutoHideWindow)
  561. {
  562. if (DocumentStyle == DocumentStyle.SystemMdi ||
  563. DocumentStyle == DocumentStyle.DockingMdi)
  564. return (Parent == null) ? Rectangle.Empty : Parent.RectangleToClient(RectangleToScreen(rectAutoHideWindow));
  565. else
  566. return rectAutoHideWindow;
  567. }
  568. internal void RefreshAutoHideStrip()
  569. {
  570. AutoHideStripControl.RefreshChanges();
  571. }
  572. }
  573. }