DockingFrame.bf 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Beefy.theme;
  5. using Beefy.gfx;
  6. using System.Diagnostics;
  7. using Beefy.geom;
  8. namespace Beefy.widgets
  9. {
  10. public class DockingFrame : DockedWidget
  11. {
  12. public enum WidgetAlign
  13. {
  14. Inside,
  15. Left,
  16. Right,
  17. Top,
  18. Bottom
  19. };
  20. public enum SplitType
  21. {
  22. None,
  23. Horz,
  24. Vert
  25. };
  26. public List<DockedWidget> mDockedWidgets = new List<DockedWidget>() ~ delete _;
  27. public SplitType mSplitType = SplitType.None;
  28. public float mMinWindowSize = 32;
  29. public float mDragMarginSize = 64;
  30. public float mDragWindowMarginSize = 10;
  31. public float mWindowMargin = 0;
  32. public float mSplitterSize = 6.0f;
  33. public float mWindowSpacing = 2.0f;
  34. public int32 mDownSplitterNum = -1;
  35. public IDockable mDraggingDock;
  36. public DockedWidget mDraggingRef;
  37. public WidgetAlign mDraggingAlign;
  38. public ICustomDock mDraggingCustomDock ~ delete (Object)_;
  39. public virtual void AddDockedWidget(DockedWidget widget, DockedWidget refWidget, WidgetAlign align)
  40. {
  41. SplitType wantSplitType = ((align == WidgetAlign.Left) || (align == WidgetAlign.Right)) ?
  42. SplitType.Horz : SplitType.Vert;
  43. if (mDockedWidgets.Count == 0)
  44. wantSplitType = SplitType.None;
  45. if ((wantSplitType != mSplitType) && (mSplitType != SplitType.None))
  46. {
  47. DockingFrame newChildFrame = ThemeFactory.mDefault.CreateDockingFrame(this);
  48. bool hasFillWidget = mHasFillWidget;
  49. if (refWidget != null)
  50. {
  51. newChildFrame.mRequestedWidth = refWidget.mRequestedWidth;
  52. newChildFrame.mRequestedHeight = refWidget.mRequestedHeight;
  53. ReplaceDockedWidget(refWidget, newChildFrame);
  54. // Just split out the one referenced widget
  55. newChildFrame.mParentDockingFrame = this;
  56. refWidget.mParentDockingFrame = newChildFrame;
  57. newChildFrame.mDockedWidgets.Add(refWidget);
  58. newChildFrame.AddWidget(refWidget);
  59. newChildFrame.AddDockedWidget(widget, null, align);
  60. ResizeContent(true);
  61. return;
  62. }
  63. else
  64. {
  65. newChildFrame.mRequestedWidth = 0;
  66. newChildFrame.mRequestedHeight = 0;
  67. for (DockedWidget aDockedWidget in mDockedWidgets)
  68. {
  69. if (mSplitType == SplitType.Horz)
  70. {
  71. newChildFrame.mRequestedWidth += aDockedWidget.mRequestedWidth;
  72. newChildFrame.mRequestedHeight = Math.Max(newChildFrame.mRequestedHeight, aDockedWidget.mRequestedHeight);
  73. }
  74. else
  75. {
  76. newChildFrame.mRequestedWidth = Math.Max(mRequestedWidth, aDockedWidget.mRequestedWidth);
  77. newChildFrame.mRequestedHeight += aDockedWidget.mRequestedHeight;
  78. }
  79. RemoveWidget(aDockedWidget);
  80. newChildFrame.mDockedWidgets.Add(aDockedWidget);
  81. newChildFrame.AddWidget(aDockedWidget);
  82. aDockedWidget.mParentDockingFrame = newChildFrame;
  83. hasFillWidget |= aDockedWidget.mHasFillWidget;
  84. }
  85. mDockedWidgets.Clear();
  86. }
  87. newChildFrame.mParentDockingFrame = this;
  88. newChildFrame.mHasFillWidget = hasFillWidget;
  89. newChildFrame.mSplitType = mSplitType;
  90. newChildFrame.mWidth = newChildFrame.mRequestedWidth;
  91. newChildFrame.mHeight = newChildFrame.mRequestedHeight;
  92. mDockedWidgets.Add(newChildFrame);
  93. AddWidget(newChildFrame);
  94. }
  95. widget.mParentDockingFrame = this;
  96. //TODO:
  97. /*if (fillWidget != null)
  98. {
  99. // Don't take more than half remaining space at a time
  100. widget.mRequestedWidth = Math.Min(fillWidget.mWidth / 2, widget.mRequestedWidth);
  101. widget.mRequestedHeight = Math.Min(fillWidget.mHeight / 2, widget.mRequestedHeight);
  102. }*/
  103. widget.mRequestedWidth = Math.Max(mMinWindowSize, widget.mRequestedWidth);
  104. widget.mRequestedHeight = Math.Max(mMinWindowSize, widget.mRequestedHeight);
  105. if ((align == WidgetAlign.Left) || (align == WidgetAlign.Top))
  106. {
  107. if (refWidget != null)
  108. mDockedWidgets.Insert(mDockedWidgets.IndexOf(refWidget), widget);
  109. else
  110. mDockedWidgets.Insert(0, widget);
  111. }
  112. else
  113. {
  114. if (refWidget != null)
  115. mDockedWidgets.Insert(mDockedWidgets.IndexOf(refWidget) + 1, widget);
  116. else
  117. mDockedWidgets.Add(widget);
  118. }
  119. AddWidget(widget);
  120. mSplitType = wantSplitType;
  121. if ((widget.mHasFillWidget) || (widget.mIsFillWidget))
  122. widget.GetRootDockingFrame().Rehup();
  123. ResizeContent(true);
  124. }
  125. public override void Rehup()
  126. {
  127. bool allHaveSizes = true;
  128. bool didHaveFillWidget = mHasFillWidget;
  129. base.Rehup();
  130. for (var dockedWiget in mDockedWidgets)
  131. {
  132. dockedWiget.mHasFillWidget = dockedWiget.mIsFillWidget;
  133. dockedWiget.Rehup();
  134. if (dockedWiget.mHasFillWidget)
  135. {
  136. mHasFillWidget = true;
  137. }
  138. if ((dockedWiget.mWidth == 0) || (dockedWiget.mHeight == 0))
  139. allHaveSizes = false;
  140. }
  141. // If we turn off mHasFillWidget and go to an all-non-fill situation then we reset the size priority
  142. if (didHaveFillWidget != mHasFillWidget)
  143. {
  144. for (var dockedWiget in mDockedWidgets)
  145. dockedWiget.mSizePriority = 0;
  146. //if (!mHasFillWidget)
  147. if (allHaveSizes)
  148. {
  149. for (var dockedWidget in mDockedWidgets)
  150. {
  151. if (mSplitType == .Horz)
  152. dockedWidget.mRequestedWidth = dockedWidget.mWidth;
  153. else
  154. dockedWidget.mRequestedHeight = dockedWidget.mHeight;
  155. }
  156. }
  157. }
  158. for (var dockedWiget in mDockedWidgets)
  159. {
  160. // Reset the size priority to be whatever the current size is, it should stabilize sizes when
  161. // toggling mIsFillWidget
  162. if (dockedWiget.mHasFillWidget == mHasFillWidget)
  163. {
  164. if (dockedWiget.mSizePriority == 0)
  165. {
  166. if (mSplitType == .Horz)
  167. dockedWiget.mSizePriority = dockedWiget.mWidth;
  168. else
  169. dockedWiget.mSizePriority = dockedWiget.mHeight;
  170. }
  171. }
  172. else
  173. dockedWiget.mSizePriority = 0;
  174. }
  175. }
  176. public override DockingFrame GetRootDockingFrame()
  177. {
  178. var parentFrame = this;
  179. while (parentFrame != null)
  180. {
  181. if (parentFrame.mParentDockingFrame == null)
  182. break;
  183. parentFrame = parentFrame.mParentDockingFrame;
  184. }
  185. return parentFrame;
  186. }
  187. public void WithAllDockedWidgets(Action<DockedWidget> func)
  188. {
  189. for (var dockedWidget in mDockedWidgets)
  190. {
  191. func(dockedWidget);
  192. var dockingFrame = dockedWidget as DockingFrame;
  193. if (dockingFrame != null)
  194. {
  195. dockingFrame.WithAllDockedWidgets(func);
  196. }
  197. }
  198. }
  199. public int GetDockedWindowCount()
  200. {
  201. return mDockedWidgets.Count;
  202. }
  203. public void Simplify()
  204. {
  205. if ((mDockedWidgets.Count == 0) && (mParentDockingFrame != null))
  206. mParentDockingFrame.RemoveWidget(this);
  207. else if ((mDockedWidgets.Count == 1) && (mParentDockingFrame != null))
  208. {
  209. // Just a single object, remove ourselves from the frame
  210. DockedWidget aDockedWidget = mDockedWidgets[0];
  211. mDockedWidgets.Clear();
  212. RemoveWidget(aDockedWidget);
  213. mParentDockingFrame.ReplaceDockedWidget(this, aDockedWidget);
  214. BFApp.sApp.DeferDelete(this);
  215. }
  216. }
  217. public virtual void RemoveDockedWidget(DockedWidget dockedWidget)
  218. {
  219. mDockedWidgets.Remove(dockedWidget);
  220. RemoveWidget(dockedWidget);
  221. if (!mIsFillWidget)
  222. mHasFillWidget = GetHasFillWidget();
  223. ResizeContent(true);
  224. if ((mDockedWidgets.Count == 0) && (mParentDockingFrame == null))
  225. {
  226. // Automatically close when last docked widget is removed
  227. // Should only happen on tool windows
  228. mWidgetWindow.Close();
  229. }
  230. }
  231. // Used when an embedded docking frame gets down to just a single widget
  232. public virtual void ReplaceDockedWidget(DockedWidget dockedWidget, DockedWidget replaceWidget)
  233. {
  234. int index = mDockedWidgets.IndexOf(dockedWidget);
  235. RemoveWidget(dockedWidget);
  236. mDockedWidgets[index] = replaceWidget;
  237. AddWidget(replaceWidget);
  238. replaceWidget.mParentDockingFrame = this;
  239. ResizeContent(true);
  240. }
  241. protected virtual bool GetHasFillWidget()
  242. {
  243. for (DockedWidget aDockedWidget in mDockedWidgets)
  244. if (aDockedWidget.mHasFillWidget)
  245. return true;
  246. return false;
  247. }
  248. public virtual void StartContentInterpolate()
  249. {
  250. for (DockedWidget aDockedWidget in mDockedWidgets)
  251. {
  252. aDockedWidget.StartInterpolate();
  253. }
  254. }
  255. public virtual void ResizeContent(bool interpolate = false)
  256. {
  257. float sizeLeft = (mSplitType == SplitType.Horz) ? (mWidth - mWindowMargin*2) : (mHeight - mWindowMargin*2);
  258. sizeLeft -= (mDockedWidgets.Count - 1) * mWindowSpacing;
  259. if (sizeLeft <= 0)
  260. return;
  261. List<DockedWidget> widgetsLeft = scope List<DockedWidget>();
  262. for (DockedWidget aDockedWidget in mDockedWidgets)
  263. {
  264. widgetsLeft.Add(aDockedWidget);
  265. if (interpolate)
  266. aDockedWidget.StartInterpolate();
  267. }
  268. //DockedWidget fillWidget = GetFillWidget();
  269. //if (fillWidget != null)
  270. {
  271. bool hasFillWidget = false;
  272. for (int32 widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
  273. {
  274. DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
  275. if (aDockedWidget.mHasFillWidget)
  276. {
  277. hasFillWidget = true;
  278. break;
  279. }
  280. }
  281. if (hasFillWidget)
  282. {
  283. for (int32 widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
  284. {
  285. DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
  286. if (aDockedWidget.mHasFillWidget)
  287. continue;
  288. float requestedSize = (mSplitType == SplitType.Horz) ? (aDockedWidget.mRequestedWidth) : aDockedWidget.mRequestedHeight;
  289. float size = Math.Round(Math.Max(mMinWindowSize, Math.Min(requestedSize, sizeLeft - (widgetsLeft.Count * mMinWindowSize))));
  290. if (mSplitType == SplitType.Horz)
  291. aDockedWidget.mWidth = size;
  292. else
  293. aDockedWidget.mHeight = size;
  294. sizeLeft -= size;
  295. widgetsLeft.RemoveAt(widgetIdx);
  296. widgetIdx--;
  297. }
  298. }
  299. //widgetsLeft.Add(fillWidget);
  300. /*if (mSplitType == SplitType.Horz)
  301. fillWidget.mWidth = sizeLeft;
  302. else
  303. fillWidget.mHeight = sizeLeft;*/
  304. }
  305. //if (fillWidget == null)
  306. {
  307. int32 totalPriCount = 0;
  308. int32 newPriCounts = 0;
  309. float totalPriAcc = 0.0f;
  310. float avgPri = 0;
  311. for (DockedWidget aDockedWidget in widgetsLeft)
  312. {
  313. totalPriAcc += aDockedWidget.mSizePriority;
  314. if (aDockedWidget.mSizePriority == 0)
  315. newPriCounts++;
  316. else
  317. totalPriCount++;
  318. }
  319. if (totalPriCount == 0)
  320. {
  321. // Totally uninitialized, possibly from having a document frame and then removing it
  322. for (DockedWidget aDockedWidget in widgetsLeft)
  323. if ((aDockedWidget.mSizePriority == 0) && (aDockedWidget.mWidth > 0) && (aDockedWidget.mHeight > 0))
  324. {
  325. aDockedWidget.mSizePriority = (mSplitType == .Horz) ? aDockedWidget.mWidth : aDockedWidget.mHeight;
  326. totalPriCount++;
  327. totalPriAcc += aDockedWidget.mSizePriority;
  328. newPriCounts--;
  329. }
  330. }
  331. if (newPriCounts > 0)
  332. {
  333. if (totalPriAcc > 0)
  334. avgPri = totalPriAcc / totalPriCount;
  335. else
  336. avgPri = 1.0f / newPriCounts;
  337. for (DockedWidget aDockedWidget in widgetsLeft)
  338. if (aDockedWidget.mSizePriority == 0)
  339. {
  340. aDockedWidget.mSizePriority = avgPri;
  341. totalPriCount++;
  342. totalPriAcc += aDockedWidget.mSizePriority;
  343. }
  344. }
  345. float sharedWidth = sizeLeft;
  346. for (int32 widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
  347. {
  348. DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
  349. float size = (aDockedWidget.mSizePriority / totalPriAcc) * sharedWidth;
  350. size = (float) Math.Round(size);
  351. if (widgetIdx == widgetsLeft.Count - 1)
  352. size = sizeLeft;
  353. if (mSplitType == SplitType.Horz)
  354. {
  355. aDockedWidget.mWidth = size;
  356. }
  357. else
  358. {
  359. aDockedWidget.mHeight = size;
  360. }
  361. sizeLeft -= size;
  362. widgetsLeft.RemoveAt(widgetIdx);
  363. widgetIdx--;
  364. }
  365. }
  366. /*DockedWidget fillWidget = GetFillWidget();
  367. if (fillWidget == null)
  368. {
  369. int totalPriCount = 0;
  370. int newPriCounts = 0;
  371. float totalPriAcc = 0.0f;
  372. float avgPri = 0;
  373. foreach (DockedWidget aDockedWidget in widgetsLeft)
  374. {
  375. totalPriAcc += aDockedWidget.mSizePriority;
  376. if (aDockedWidget.mSizePriority == 0)
  377. newPriCounts++;
  378. else
  379. totalPriCount++;
  380. }
  381. if (newPriCounts > 0)
  382. {
  383. if (totalPriAcc > 0)
  384. avgPri = totalPriAcc / totalPriCount;
  385. else
  386. avgPri = 1.0f / newPriCounts;
  387. foreach (DockedWidget aDockedWidget in widgetsLeft)
  388. if (aDockedWidget.mSizePriority == 0)
  389. {
  390. aDockedWidget.mSizePriority = avgPri;
  391. totalPriCount++;
  392. totalPriAcc += aDockedWidget.mSizePriority;
  393. }
  394. }
  395. float sharedWidth = sizeLeft;
  396. for (int widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
  397. {
  398. DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
  399. float size = (aDockedWidget.mSizePriority / totalPriAcc) * sharedWidth;
  400. size = (float) Math.Round(size);
  401. if (widgetIdx == widgetsLeft.Count - 1)
  402. size = sizeLeft;
  403. if (mSplitType == SplitType.Horz)
  404. {
  405. aDockedWidget.mWidth = size;
  406. }
  407. else
  408. {
  409. aDockedWidget.mHeight = size;
  410. }
  411. sizeLeft -= size;
  412. widgetsLeft.RemoveAt(widgetIdx);
  413. widgetIdx--;
  414. }
  415. }
  416. else
  417. {
  418. widgetsLeft.Remove(fillWidget);
  419. for (int widgetIdx = 0; widgetIdx < widgetsLeft.Count; widgetIdx++)
  420. {
  421. DockedWidget aDockedWidget = widgetsLeft[widgetIdx];
  422. float requestedSize = (mSplitType == SplitType.Horz) ? (aDockedWidget.mRequestedWidth) : aDockedWidget.mRequestedHeight;
  423. float size = Math.Max(mMinWindowSize, Math.Min(requestedSize, sizeLeft - (widgetsLeft.Count * mMinWindowSize)));
  424. if (mSplitType == SplitType.Horz)
  425. aDockedWidget.mWidth = size;
  426. else
  427. aDockedWidget.mHeight = size;
  428. sizeLeft -= size;
  429. widgetsLeft.RemoveAt(widgetIdx);
  430. widgetIdx--;
  431. }
  432. if (mSplitType == SplitType.Horz)
  433. fillWidget.mWidth = sizeLeft;
  434. else
  435. fillWidget.mHeight = sizeLeft;
  436. }*/
  437. float curPos = mWindowMargin;
  438. for (DockedWidget aDockedWidget in mDockedWidgets)
  439. {
  440. float size = (mSplitType == SplitType.Horz) ? aDockedWidget.mWidth : aDockedWidget.mHeight;
  441. if (mSplitType == SplitType.Horz)
  442. {
  443. aDockedWidget.ResizeDocked(curPos, mWindowMargin, size, mHeight - mWindowMargin*2);
  444. }
  445. else
  446. {
  447. aDockedWidget.ResizeDocked(mWindowMargin, curPos, mWidth - mWindowMargin*2, size);
  448. }
  449. curPos += size;
  450. curPos += mWindowSpacing;
  451. }
  452. }
  453. public override void Resize(float x, float y, float width, float height)
  454. {
  455. base.Resize(x, y, width, height);
  456. ResizeContent();
  457. }
  458. public int32 FindSplitterAt(float x, float y)
  459. {
  460. if (!Contains(x, y))
  461. return -1;
  462. float curPos = 0;
  463. float findPos = (mSplitType == SplitType.Horz) ? (x - mWindowMargin) : (y - mWindowMargin);
  464. for (int32 widgetIdx = 0; widgetIdx < mDockedWidgets.Count; widgetIdx++)
  465. {
  466. DockedWidget aDockedWidget = mDockedWidgets[widgetIdx];
  467. float size = (mSplitType == SplitType.Horz) ? aDockedWidget.mWidth : aDockedWidget.mHeight;
  468. float diff = (findPos - curPos) + mWindowSpacing + (mSplitterSize - mWindowSpacing) / 2.0f;
  469. if ((diff >= 0) && (diff < mSplitterSize))
  470. return widgetIdx - 1;
  471. curPos += size;
  472. curPos += mWindowSpacing;
  473. }
  474. return -1;
  475. }
  476. DockingFrame GetDockingFrame(WidgetWindow widgetWindow)
  477. {
  478. if (widgetWindow == null)
  479. return null;
  480. DockingFrame dockingFrame = widgetWindow.mRootWidget as DockingFrame;
  481. if (dockingFrame != null)
  482. return dockingFrame;
  483. for (var child in widgetWindow.mRootWidget.mChildWidgets)
  484. {
  485. dockingFrame = child as DockingFrame;
  486. if (dockingFrame != null)
  487. return dockingFrame;
  488. }
  489. return null;
  490. }
  491. public virtual void ShowDragTarget(IDockable draggingItem)
  492. {
  493. Debug.Assert(mParentDockingFrame == null);
  494. for (BFWindow window in BFApp.sApp.mWindows)
  495. {
  496. if (window.mAlpha != 1.0f)
  497. continue;
  498. WidgetWindow widgetWindow = window as WidgetWindow;
  499. var dockingFrame = GetDockingFrame(widgetWindow);
  500. if (dockingFrame != null)
  501. {
  502. if ((widgetWindow.mHasMouseInside) || (widgetWindow.mHasProxyMouseInside))
  503. dockingFrame.ShowDragTarget(draggingItem, widgetWindow.mMouseX, widgetWindow.mMouseY);
  504. else
  505. dockingFrame.HideDragTargets();
  506. }
  507. }
  508. }
  509. public virtual void HideDragTarget(IDockable draggingItem, bool executeDrag = false)
  510. {
  511. Debug.Assert(mParentDockingFrame == null);
  512. for (int32 windowIdx = 0; windowIdx < BFApp.sApp.mWindows.Count; windowIdx++)
  513. {
  514. BFWindow window = BFApp.sApp.mWindows[windowIdx];
  515. WidgetWindow widgetWindow = window as WidgetWindow;
  516. if (widgetWindow != null)
  517. {
  518. DockingFrame dockingFrame = GetDockingFrame(widgetWindow);
  519. if (dockingFrame != null)
  520. dockingFrame.HideDragTargets(executeDrag);
  521. }
  522. }
  523. }
  524. void HideDragTargets(bool executeDrag = false)
  525. {
  526. if ((executeDrag) && (mDraggingDock != null))
  527. {
  528. if (mDraggingCustomDock != null)
  529. mDraggingCustomDock.Dock(mDraggingDock);
  530. else
  531. mDraggingDock.Dock(this, mDraggingRef, mDraggingAlign);
  532. }
  533. mDraggingDock = null;
  534. mDraggingRef = null;
  535. delete (Object)mDraggingCustomDock;
  536. mDraggingCustomDock = null;
  537. for (int32 dockedWidgetIdx = 0; dockedWidgetIdx < mDockedWidgets.Count; dockedWidgetIdx++)
  538. {
  539. DockedWidget aDockedWidget = mDockedWidgets[dockedWidgetIdx];
  540. DockingFrame childFrame = aDockedWidget as DockingFrame;
  541. if (childFrame != null)
  542. childFrame.HideDragTargets(executeDrag);
  543. }
  544. }
  545. bool FindDragTarget(IDockable draggingItem, float x, float y, ref DockingFrame containingFrame, ref DockedWidget refWidget, ref WidgetAlign align, ref ICustomDock customDock, int32 minDist = -2)
  546. {
  547. //int foundMinDist = -1;
  548. bool foundInSelf = false;
  549. for (DockedWidget aDockedWidget in mDockedWidgets)
  550. {
  551. float childX;
  552. float childY;
  553. aDockedWidget.ParentToSelfTranslate(x, y, out childX, out childY);
  554. var rect = Rect(-2, -2, aDockedWidget.mWidth + 4, aDockedWidget.mHeight + 4);
  555. //if (aDockedWidget.Contains(childX, childY))
  556. if (rect.Contains(childX, childY))
  557. {
  558. float leftDist = childX;
  559. float topDist = childY;
  560. float rightDist = aDockedWidget.mWidth - childX;
  561. float botDist = aDockedWidget.mHeight - childY;
  562. if (Math.Min(Math.Min(Math.Min(leftDist, topDist), rightDist), botDist) < minDist)
  563. continue;
  564. float marginX = Math.Min(mDragMarginSize, aDockedWidget.mWidth / 4);
  565. float marginY = Math.Min(mDragMarginSize, aDockedWidget.mHeight / 4);
  566. if ((marginX < Math.Min(leftDist, rightDist)) && (marginY < Math.Min(topDist, botDist)))
  567. align = WidgetAlign.Inside;
  568. else if (leftDist < Math.Min(topDist, Math.Min(rightDist, botDist)))
  569. align = WidgetAlign.Left;
  570. else if (topDist < Math.Min(rightDist, botDist))
  571. align = WidgetAlign.Top;
  572. else if (rightDist < botDist)
  573. align = WidgetAlign.Right;
  574. else
  575. align = WidgetAlign.Bottom;
  576. if (draggingItem.CanDock(this, aDockedWidget, align))
  577. {
  578. customDock = aDockedWidget.GetCustomDock(draggingItem, childX, childY);
  579. containingFrame = this;
  580. refWidget = aDockedWidget;
  581. foundInSelf = true;
  582. break;
  583. }
  584. }
  585. }
  586. int32 newMinDist = minDist;
  587. if (foundInSelf)
  588. newMinDist = Math.Max(minDist, 0) + 2;
  589. for (DockedWidget aDockedWidget in mDockedWidgets)
  590. {
  591. float childX;
  592. float childY;
  593. aDockedWidget.ParentToSelfTranslate(x, y, out childX, out childY);
  594. if (aDockedWidget.Contains(childX, childY))
  595. {
  596. DockingFrame childFrame = aDockedWidget as DockingFrame;
  597. if (childFrame != null)
  598. {
  599. childFrame.FindDragTarget(draggingItem, childX, childY, ref containingFrame, ref refWidget, ref align, ref customDock, newMinDist);
  600. break;
  601. }
  602. }
  603. }
  604. if ((mParentDockingFrame == null) && (customDock == null))
  605. {
  606. if (Contains(x, y))
  607. {
  608. float leftDist = x;
  609. float topDist = y;
  610. float rightDist = mWidth - x;
  611. float botDist = mHeight - y;
  612. float marginX = Math.Min(mDragWindowMarginSize, mWidth / 4);
  613. float marginY = Math.Min(mDragWindowMarginSize, mHeight / 4);
  614. WidgetAlign anAlign;
  615. if ((marginX < Math.Min(leftDist, rightDist)) && (marginY < Math.Min(topDist, botDist)))
  616. anAlign = WidgetAlign.Inside;
  617. else if (leftDist < Math.Min(topDist, Math.Min(rightDist, botDist)))
  618. anAlign = WidgetAlign.Left;
  619. else if (topDist < Math.Min(rightDist, botDist))
  620. anAlign = WidgetAlign.Top;
  621. else if (rightDist < botDist)
  622. anAlign = WidgetAlign.Right;
  623. else
  624. anAlign = WidgetAlign.Bottom;
  625. if ((anAlign != WidgetAlign.Inside) && (draggingItem.CanDock(this, null, align)))
  626. {
  627. containingFrame = this;
  628. refWidget = null;
  629. customDock = null;
  630. align = anAlign;
  631. }
  632. }
  633. }
  634. return containingFrame != null;
  635. }
  636. void ShowDragTarget(IDockable draggingItem, float x, float y)
  637. {
  638. DockingFrame containingFrame = null;
  639. DockedWidget refWidget = null;
  640. WidgetAlign align = .Inside;
  641. ICustomDock customDock = null;
  642. /*containingFrame = null;
  643. refWidget = null;
  644. align = WidgetAlign.Inside;
  645. customDock = null;*/
  646. MarkDirty();
  647. HideDragTargets();
  648. if ((y < 0) && (y >= -6) && (x >= 0) && (x < mWidgetWindow.mWindowWidth))
  649. {
  650. containingFrame = this;
  651. containingFrame.mDraggingDock = draggingItem;
  652. containingFrame.mDraggingRef = null;
  653. containingFrame.mDraggingAlign = .Top;
  654. delete (Object)containingFrame.mDraggingCustomDock;
  655. containingFrame.mDraggingCustomDock = null;
  656. return;
  657. }
  658. if (FindDragTarget(draggingItem, x, y, ref containingFrame, ref refWidget, ref align, ref customDock))
  659. {
  660. containingFrame.mDraggingDock = draggingItem;
  661. containingFrame.mDraggingRef = refWidget;
  662. containingFrame.mDraggingAlign = align;
  663. delete (Object)containingFrame.mDraggingCustomDock;
  664. containingFrame.mDraggingCustomDock = customDock;
  665. }
  666. }
  667. public override Widget FindWidgetByCoords(float x, float y)
  668. {
  669. if (FindSplitterAt(x, y) != -1)
  670. return this;
  671. return base.FindWidgetByCoords(x, y);
  672. }
  673. public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
  674. {
  675. base.MouseDown(x, y, btn, btnCount);
  676. mDownSplitterNum = FindSplitterAt(x, y);
  677. }
  678. public override void MouseMove(float x, float y)
  679. {
  680. base.MouseMove(x, y);
  681. if (mDownSplitterNum != -1)
  682. {
  683. float wantPos = (mSplitType == SplitType.Horz) ? x : y;
  684. DockedWidget resizedWidget = null;
  685. DockedWidget widget1 = mDockedWidgets[mDownSplitterNum];
  686. DockedWidget widget2 = mDockedWidgets[mDownSplitterNum + 1];
  687. List<DockedWidget> widgetsLeft = scope List<DockedWidget>();
  688. float sizeLeft = (mSplitType == SplitType.Horz) ? (mWidth - mWindowMargin*2) : (mHeight - mWindowMargin*2);
  689. if ((widget1.mHasFillWidget) && (widget2.mHasFillWidget))
  690. {
  691. bool foundWidget = false;
  692. for (var dockedWidget in mDockedWidgets)
  693. {
  694. if (dockedWidget == widget1)
  695. foundWidget = true;
  696. if (dockedWidget.mHasFillWidget)
  697. widgetsLeft.Add(dockedWidget);
  698. else
  699. {
  700. float curSize = (mSplitType == SplitType.Horz) ? dockedWidget.mWidth : dockedWidget.mHeight;
  701. if (!foundWidget)
  702. wantPos -= curSize;
  703. sizeLeft -= curSize;
  704. }
  705. }
  706. }
  707. else if (widget1.mHasFillWidget != widget2.mHasFillWidget)
  708. {
  709. if (widget2.mHasFillWidget)
  710. {
  711. if (mSplitType == .Horz)
  712. widget1.mRequestedWidth = wantPos - widget1.mX;
  713. else
  714. widget1.mRequestedHeight = wantPos - widget1.mY;
  715. }
  716. else
  717. {
  718. if (mSplitType == .Horz)
  719. {
  720. float totalSize = widget1.mWidth + widget2.mWidth;
  721. widget2.mRequestedWidth = Math.Max(0, widget2.mRequestedWidth + (widget2.mX - wantPos));
  722. widget2.mRequestedWidth = Math.Min(widget2.mRequestedWidth, totalSize - mMinWindowSize * 2);
  723. }
  724. else
  725. {
  726. float totalSize = widget1.mHeight + widget2.mHeight;
  727. widget2.mRequestedHeight = Math.Max(0, widget2.mRequestedHeight + (widget2.mY - wantPos));
  728. widget2.mRequestedHeight = Math.Min(widget2.mRequestedHeight, totalSize - mMinWindowSize * 2);
  729. }
  730. resizedWidget = widget2;
  731. //Debug.WriteLine("RW:{0} WH:{1}", widget2.mRequestedWidth, widget2.mRequestedHeight);
  732. }
  733. }
  734. else
  735. {
  736. bool hasFillWidget = false;
  737. for (var dockedWidget in mDockedWidgets)
  738. {
  739. if (dockedWidget.mHasFillWidget)
  740. hasFillWidget = true;
  741. }
  742. if (hasFillWidget)
  743. {
  744. for (var dockedWidget in mDockedWidgets)
  745. {
  746. // Size prioritizes will get initialized later if we remove the fill widget
  747. if (!dockedWidget.mHasFillWidget)
  748. dockedWidget.mSizePriority = 0;
  749. }
  750. if (mSplitType == .Horz)
  751. {
  752. float totalSize = widget1.mWidth + widget2.mWidth;
  753. widget2.mRequestedWidth = Math.Clamp(widget2.mRequestedWidth + (widget2.mX - wantPos), mMinWindowSize, totalSize - mMinWindowSize);
  754. widget1.mRequestedWidth = totalSize - widget2.mRequestedWidth;
  755. }
  756. else
  757. {
  758. float totalSize = widget1.mHeight + widget2.mHeight;
  759. widget2.mRequestedHeight = Math.Clamp(widget2.mRequestedHeight + (widget2.mY - wantPos), mMinWindowSize, totalSize - mMinWindowSize);
  760. widget1.mRequestedHeight = totalSize - widget2.mRequestedHeight;
  761. }
  762. }
  763. else
  764. {
  765. for (var dockedWidget in mDockedWidgets)
  766. widgetsLeft.Add(dockedWidget);
  767. }
  768. }
  769. if (widgetsLeft.Count > 0)
  770. {
  771. // First we normalize to 1.0
  772. float sizePriTotal = 0.0f;
  773. for (DockedWidget aDockedWidget in widgetsLeft)
  774. sizePriTotal += aDockedWidget.mSizePriority;
  775. for (DockedWidget aDockedWidget in widgetsLeft)
  776. aDockedWidget.mSizePriority = aDockedWidget.mSizePriority / sizePriTotal;
  777. float totalPrevSize = widget1.mSizePriority + widget2.mSizePriority;
  778. float startCurPos = 0;
  779. for (DockedWidget aDockedWidget in widgetsLeft)
  780. {
  781. if (aDockedWidget == widget1)
  782. break;
  783. startCurPos += aDockedWidget.mSizePriority * sizeLeft + mWindowSpacing;
  784. }
  785. float wantSize = Math.Max(mMinWindowSize, wantPos - startCurPos);
  786. wantSize = Math.Min(wantSize, totalPrevSize * sizeLeft - mMinWindowSize);
  787. wantSize /= sizeLeft;
  788. widget1.mSizePriority = wantSize;
  789. widget2.mSizePriority = totalPrevSize - wantSize;
  790. }
  791. ResizeContent();
  792. // Set to actual used value
  793. if (resizedWidget != null)
  794. {
  795. if (mSplitType == .Horz)
  796. resizedWidget.mRequestedWidth = resizedWidget.mWidth;
  797. else
  798. resizedWidget.mRequestedHeight = resizedWidget.mHeight;
  799. }
  800. }
  801. else
  802. {
  803. if (FindSplitterAt(x, y) != -1)
  804. {
  805. if (mSplitType == SplitType.Horz)
  806. BFApp.sApp.SetCursor(Cursor.SizeWE);
  807. else
  808. BFApp.sApp.SetCursor(Cursor.SizeNS);
  809. }
  810. else
  811. {
  812. BFApp.sApp.SetCursor(Cursor.Pointer);
  813. }
  814. }
  815. }
  816. public override void MouseUp(float x, float y, int32 btn)
  817. {
  818. base.MouseUp(x, y, btn);
  819. mDownSplitterNum = -1;
  820. MouseMove(x, y);
  821. }
  822. public override void MouseLeave()
  823. {
  824. base.MouseLeave();
  825. if (!mMouseDown)
  826. BFApp.sApp.SetCursor(Cursor.Pointer);
  827. }
  828. public virtual void DrawDraggingDock(Graphics g)
  829. {
  830. }
  831. public override void DrawAll(Graphics g)
  832. {
  833. base.DrawAll(g);
  834. if (mDraggingDock != null)
  835. DrawDraggingDock(g);
  836. }
  837. public override void Update()
  838. {
  839. base.Update();
  840. Simplify();
  841. }
  842. }
  843. }