guiFrameSetCtrl.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "console/consoleTypes.h"
  23. #include "console/console.h"
  24. #include "gui/containers/guiFrameSetCtrl.h"
  25. #include "gui/guiDefaultControlRender.h"
  26. #include "gui/guiCanvas.h"
  27. #include "gui/containers/guiWindowCtrl.h"
  28. #include "guiFrameSetCtrl_ScriptBinding.h"
  29. void GuiFrameSetCtrl::Frame::deleteChildren()
  30. {
  31. if (child1)
  32. {
  33. child1->deleteChildren();
  34. delete child1;
  35. }
  36. if (child2)
  37. {
  38. child2->deleteChildren();
  39. delete child2;
  40. }
  41. }
  42. void GuiFrameSetCtrl::Frame::resize(const Point2I& newPosition, const Point2I& newExtent)
  43. {
  44. const S32 minSize = owner->minSize;
  45. extent.set(newExtent.x, newExtent.y);
  46. localPosition.set(newPosition.x, newPosition.y);
  47. sizeInsertButtons(newPosition, newExtent);
  48. if (control)
  49. {
  50. if (control->mMinExtent.x > minSize || control->mMinExtent.y > minSize)
  51. {
  52. control->mMinExtent.set(minSize, minSize);
  53. }
  54. control->resize(newPosition, newExtent);
  55. }
  56. else if (child1 && child2)
  57. {
  58. S32 spaceX = isVertical ? newExtent.x : newExtent.x - owner->mDividerThickness;
  59. S32 spaceY = !isVertical ? newExtent.y : newExtent.y - owner->mDividerThickness;
  60. S32 x1 = newExtent.x;
  61. S32 x2 = newExtent.x;
  62. if(!isVertical)
  63. {
  64. if (child1->isAnchored)
  65. {
  66. x1 = getMin(child1->extent.x, spaceX - minSize);
  67. x2 = spaceX - x1;
  68. }
  69. else
  70. {
  71. x2 = getMin(child2->extent.x, spaceX - minSize);
  72. x1 = spaceX - x2;
  73. }
  74. }
  75. S32 y1 = newExtent.y;
  76. S32 y2 = newExtent.y;
  77. if (isVertical)
  78. {
  79. if (child1->isAnchored)
  80. {
  81. y1 = getMin(child1->extent.y, spaceY - minSize);
  82. y2 = spaceY - y1;
  83. }
  84. else
  85. {
  86. y2 = getMin(child2->extent.y, spaceY - minSize);
  87. y1 = spaceY - y2;
  88. }
  89. }
  90. Point2I ext1 = Point2I(x1, y1);
  91. Point2I ext2 = Point2I(x2, y2);
  92. Point2I pos2 = isVertical ? Point2I(newPosition.x, newPosition.y + y1 + owner->mDividerThickness) : Point2I(newPosition.x + x1 + owner->mDividerThickness, newPosition.y);
  93. if(isVertical)
  94. {
  95. dividerRect.set(newPosition.x, newPosition.y + y1, x1, owner->mDividerThickness);
  96. }
  97. else
  98. {
  99. dividerRect.set(newPosition.x + x1, newPosition.y, owner->mDividerThickness, y1);
  100. }
  101. child1->resize(newPosition, ext1);
  102. child2->resize(pos2, ext2);
  103. }
  104. }
  105. void GuiFrameSetCtrl::Frame::sizeInsertButtons(const Point2I& newPosition, const Point2I& newExtent)
  106. {
  107. const U32 size = 40;
  108. const U32 gutter = 10;
  109. hasLeftRightButtons = false;
  110. hasTopBottomButtons = false;
  111. if (newExtent.x > (4 * (size + gutter)))
  112. {
  113. hasLeftRightButtons = true;
  114. mLeftButtonRect = RectI(newPosition.x + gutter, newPosition.y + ((newExtent.y - size) / 2), size, size);
  115. mRightButtonRect = RectI(newPosition.x + newExtent.x - (gutter + size), newPosition.y + ((newExtent.y - size) / 2), size, size);
  116. }
  117. if (newExtent.y > (4 * (size + gutter)))
  118. {
  119. hasTopBottomButtons = true;
  120. mTopButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + gutter, size, size);
  121. mBottomButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + newExtent.y - (gutter + size), size, size);
  122. }
  123. }
  124. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrame(const S32 frameID)
  125. {
  126. if (id == frameID)
  127. {
  128. return this;
  129. }
  130. if (child1 && child2)
  131. {
  132. Frame* attempt = child1->findFrame(frameID);
  133. return attempt ? attempt : child2->findFrame(frameID);
  134. }
  135. return nullptr;
  136. }
  137. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findEmptyFrame()
  138. {
  139. if (!control && !child1 && !child2)
  140. {
  141. return this;
  142. }
  143. else if (child1 && child2)
  144. {
  145. Frame* attempt = child1->findEmptyFrame();
  146. return attempt ? attempt : child2->findEmptyFrame();
  147. }
  148. return nullptr;
  149. }
  150. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::twin()
  151. {
  152. if (parent)
  153. {
  154. if (parent->child1 == this)
  155. {
  156. return parent->child2;
  157. }
  158. else
  159. {
  160. return parent->child1;
  161. }
  162. }
  163. return this;
  164. }
  165. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findHitDivider(const Point2I& position)
  166. {
  167. S32 x = position.x;
  168. S32 y = position.y;
  169. if (child1 && child2)
  170. {
  171. if (x >= dividerRect.point.x && x <= (dividerRect.point.x + dividerRect.extent.x) &&
  172. y >= dividerRect.point.y && y <= (dividerRect.point.y + dividerRect.extent.y))
  173. {
  174. return this;
  175. }
  176. Frame* attempt = child1->findHitDivider(position);
  177. return attempt ? attempt : child2->findHitDivider(position);
  178. }
  179. return nullptr;
  180. }
  181. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrameWithCtrl(GuiControl* ctrl)
  182. {
  183. if (ctrl == control)
  184. {
  185. return this;
  186. }
  187. else if(child1 && child2)
  188. {
  189. Frame* attempt = child1->findFrameWithCtrl(ctrl);
  190. return attempt ? attempt : child2->findFrameWithCtrl(ctrl);
  191. }
  192. return nullptr;
  193. }
  194. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrameWithPoint(const Point2I& point)
  195. {
  196. //Point is local to the frame.
  197. if (control)
  198. {
  199. return this;
  200. }
  201. if (child1 && child2)
  202. {
  203. S32 x = point.x;
  204. S32 y = point.y;
  205. Point2I pos2 = isVertical ? Point2I(x, child1->extent.y + owner->mDividerThickness) : Point2I(child1->extent.x + owner->mDividerThickness, y);
  206. if ((isVertical && y < child1->extent.y) || (!isVertical && x < child1->extent.x))
  207. {
  208. return child1->findFrameWithPoint(point);
  209. }
  210. else if ((isVertical && y > pos2.y && y < (pos2.y + child2->extent.y)) || (!isVertical && x > pos2.x && x < (pos2.x + child2->extent.x)))
  211. {
  212. Point2I pt = Point2I(x - pos2.x, y - pos2.y);
  213. return child2->findFrameWithPoint(pt);
  214. }
  215. }
  216. return nullptr;//This will happen if the mouse is over a divider.
  217. }
  218. //------------------------------------------------------------------------------
  219. IMPLEMENT_CONOBJECT(GuiFrameSetCtrl);
  220. //------------------------------------------------------------------------------
  221. GuiFrameSetCtrl::GuiFrameSetCtrl()
  222. {
  223. mIsContainer = true;
  224. setField("profile", "GuiDefaultProfile");
  225. mRootFrame = Frame(this, nullptr);
  226. mHitDivider = nullptr;
  227. mDividerThickness = 8;
  228. mNextFrameID = 1;
  229. mResizeGuard = false;
  230. mDepressed = false;
  231. mActive = true;
  232. mFrameDragAnchor = 0;
  233. mEaseFillColorHL = EasingFunction::EaseInOut;
  234. mEaseFillColorSL = EasingFunction::EaseOut;
  235. mEaseTimeFillColorHL = 500;
  236. mEaseTimeFillColorSL = 1000;
  237. mDropButtonProfile = NULL;
  238. setField("dropButtonProfile", "GuiButtonProfile");
  239. mLeftRightCursor = NULL;
  240. mUpDownCursor = NULL;
  241. }
  242. GuiFrameSetCtrl::~GuiFrameSetCtrl()
  243. {
  244. mRootFrame.deleteChildren();
  245. }
  246. //------------------------------------------------------------------------------
  247. void GuiFrameSetCtrl::initPersistFields()
  248. {
  249. Parent::initPersistFields();
  250. addField("DividerThickness", TypeS32, Offset(mDividerThickness, GuiFrameSetCtrl));
  251. addField("dropButtonProfile", TypeGuiProfile, Offset(mDropButtonProfile, GuiFrameSetCtrl));
  252. addField("leftRightCursor", TypeGuiCursor, Offset(mLeftRightCursor, GuiFrameSetCtrl));
  253. addField("upDownCursor", TypeGuiCursor, Offset(mUpDownCursor, GuiFrameSetCtrl));
  254. }
  255. //------------------------------------------------------------------------------
  256. bool GuiFrameSetCtrl::onWake()
  257. {
  258. if (!Parent::onWake())
  259. return false;
  260. if (mDropButtonProfile != NULL)
  261. mDropButtonProfile->incRefCount();
  262. return true;
  263. }
  264. //------------------------------------------------------------------------------
  265. void GuiFrameSetCtrl::onSleep()
  266. {
  267. Parent::onSleep();
  268. if (mDropButtonProfile != NULL)
  269. mDropButtonProfile->decRefCount();
  270. }
  271. //------------------------------------------------------------------------------
  272. void GuiFrameSetCtrl::inspectPostApply()
  273. {
  274. resize(getPosition(), getExtent());
  275. Parent::inspectPostApply();
  276. }
  277. //------------------------------------------------------------------------------
  278. void GuiFrameSetCtrl::resize(const Point2I& newPosition, const Point2I& newExtent)
  279. {
  280. if(!mResizeGuard)//Prevent circular resizing
  281. {
  282. mResizeGuard = true;
  283. Point2I actualNewExtent = Point2I(getMax(mMinExtent.x, newExtent.x),
  284. getMax(mMinExtent.y, newExtent.y));
  285. //call set update both before and after
  286. setUpdate();
  287. Point2I origin = Point2I::Zero;
  288. mRootFrame.resize(origin, actualNewExtent);
  289. mBounds.set(newPosition, actualNewExtent);
  290. GuiControl* parent = getParent();
  291. if (parent)
  292. parent->childResized(this);
  293. setUpdate();
  294. mResizeGuard = false;
  295. }
  296. }
  297. bool GuiFrameSetCtrl::onAdd()
  298. {
  299. // Let Parent Do Work.
  300. if (!Parent::onAdd())
  301. return false;
  302. // Always expand to fill the parent (we just ignore the points passed in).
  303. parentResized(Point2I(), Point2I());
  304. // Return Success.
  305. return true;
  306. }
  307. void GuiFrameSetCtrl::parentResized(const Point2I& oldParentExtent, const Point2I& newParentExtent)
  308. {
  309. //In the case of centering, we want to make doubly sure we are using the inner rect.
  310. GuiControl* parent = getParent();
  311. if(parent)
  312. {
  313. Point2I origin = Point2I(0, 0);
  314. Point2I parentInnerExt = getInnerRect(origin, parent->mBounds.extent, NormalState, parent->mProfile).extent;
  315. resize(origin, parentInnerExt);
  316. }
  317. }
  318. void GuiFrameSetCtrl::onChildAdded(GuiControl* child)
  319. {
  320. //Ensure the child isn't positioned to the center
  321. if (child->getHorizSizing() == horizResizeCenter)
  322. {
  323. child->setHorizSizing(horizResizeLeft);
  324. }
  325. if (child->getVertSizing() == vertResizeCenter)
  326. {
  327. child->setVertSizing(vertResizeTop);
  328. }
  329. resize(getPosition(), getExtent());
  330. Parent::onChildAdded(child);
  331. Frame* frame = mRootFrame.findFrameWithCtrl(child);
  332. if(!frame)
  333. {
  334. Frame* emptyFrame = mRootFrame.findEmptyFrame();
  335. if(emptyFrame)
  336. {
  337. emptyFrame->control = child;
  338. }
  339. }
  340. resize(getPosition(), getExtent());
  341. }
  342. void GuiFrameSetCtrl::onChildRemoved(GuiControl* child)
  343. {
  344. Frame* frame = mRootFrame.findFrameWithCtrl(child);
  345. if (frame && frame == &mRootFrame)
  346. {
  347. mRootFrame.control = nullptr;
  348. }
  349. else if(frame)
  350. {
  351. //Remove the frame from the heirarchy
  352. Frame* frameParent = frame->parent;
  353. Frame* frameTwin = frame->twin();
  354. frameParent->control = frameTwin->control;
  355. frameParent->child1 = frameTwin->child1;
  356. frameParent->child2 = frameTwin->child2;
  357. if (frameParent->child1)
  358. {
  359. frameParent->child1->parent = frameParent;
  360. }
  361. if (frameParent->child2)
  362. {
  363. frameParent->child2->parent = frameParent;
  364. }
  365. frameParent->isVertical = frameTwin->isVertical;
  366. delete frame;
  367. delete frameTwin;
  368. }
  369. resize(getPosition(), getExtent());
  370. }
  371. void GuiFrameSetCtrl::childResized(GuiControl* child)
  372. {
  373. Parent::childResized(child);
  374. resize(getPosition(), getExtent());
  375. }
  376. void GuiFrameSetCtrl::childMoved(GuiControl* child)
  377. {
  378. Parent::childMoved(child);
  379. resize(getPosition(), getExtent());
  380. }
  381. void GuiFrameSetCtrl::childrenReordered()
  382. {
  383. resize(getPosition(), getExtent());
  384. Parent::childrenReordered();
  385. }
  386. Point2I GuiFrameSetCtrl::splitFrame(S32 frameID, bool isVertical)
  387. {
  388. Frame* frame = mRootFrame.findFrame(frameID);
  389. if(frame)
  390. {
  391. splitFrame(frame, isVertical ? GuiDirection::Up : GuiDirection::Left);
  392. return Point2I(frame->child1 ? static_cast<S32>(frame->child1->id) : 0, frame->child2 ? static_cast<S32>(frame->child2->id) : 0);
  393. }
  394. return Point2I::Zero;
  395. }
  396. void GuiFrameSetCtrl::splitFrame(GuiFrameSetCtrl::Frame* frame, GuiDirection direction)
  397. {
  398. //The existing control, if any, is moved to the new frame in the direction and anchored. The frame oposite is left empty.
  399. if (!frame->child1 && !frame->child2)
  400. {
  401. GuiControl* ctrl = frame->control;
  402. frame->child1 = new GuiFrameSetCtrl::Frame(this, frame);
  403. frame->child2 = new GuiFrameSetCtrl::Frame(this, frame);
  404. frame->control = nullptr;
  405. frame->child1->control = direction == GuiDirection::Left || direction == GuiDirection::Up ? ctrl : nullptr;
  406. frame->child2->control = direction == GuiDirection::Right || direction == GuiDirection::Down ? ctrl : nullptr;
  407. frame->child1->id = ++mNextFrameID;
  408. frame->child2->id = ++mNextFrameID;
  409. frame->child1->isAnchored = direction == GuiDirection::Left || direction == GuiDirection::Up;
  410. frame->child2->isAnchored = direction == GuiDirection::Right || direction == GuiDirection::Down;
  411. }
  412. frame->isVertical = direction == GuiDirection::Up || direction == GuiDirection::Down;
  413. }
  414. void GuiFrameSetCtrl::anchorFrame(S32 frameID)
  415. {
  416. Frame* frame = mRootFrame.findFrame(frameID);
  417. anchorFrame(frame);
  418. }
  419. void GuiFrameSetCtrl::anchorFrame(GuiFrameSetCtrl::Frame* frame)
  420. {
  421. if (frame && frame != &mRootFrame)//The root frame has no twin and can't be anchored.
  422. {
  423. frame->isAnchored = true;
  424. frame->twin()->isAnchored = false;
  425. }
  426. }
  427. void GuiFrameSetCtrl::setFrameSize(S32 frameID, S32 size)
  428. {
  429. Frame* frame = mRootFrame.findFrame(frameID);
  430. if (frame && frame != &mRootFrame)//The root frame must be the size of the control.
  431. {
  432. if (frame->parent->isVertical)
  433. {
  434. frame->extent.y = size;
  435. frame->twin()->extent.y = getMax(frame->parent->extent.y - (size + mDividerThickness), minSize);
  436. }
  437. else
  438. {
  439. frame->extent.x = size;
  440. frame->twin()->extent.x = getMax(frame->parent->extent.x - (size + mDividerThickness), minSize);
  441. }
  442. //Pass this down to the other frames and then to the child controls
  443. resize(getPosition(), getExtent());
  444. }
  445. }
  446. void GuiFrameSetCtrl::onRender(Point2I offset, const RectI& updateRect)
  447. {
  448. Parent::onRender(offset, updateRect);
  449. if (mHitDivider)
  450. {
  451. GuiControlState currentState = mDepressed ? SelectedState : HighlightState;
  452. mOldHitDivider = mHitDivider;
  453. RectI contentRect = RectI(localToGlobalCoord(mHitDivider->dividerRect.point), mHitDivider->dividerRect.extent);
  454. renderUniversalRect(contentRect, mProfile, currentState, getFillColor(currentState), true);
  455. }
  456. else if (mOldHitDivider && (mCurrentState == HighlightState || mFluidFillColor.isAnimating()))
  457. {
  458. RectI contentRect = RectI(localToGlobalCoord(mOldHitDivider->dividerRect.point), mOldHitDivider->dividerRect.extent);
  459. renderUniversalRect(contentRect, mProfile, NormalState, getFillColor(NormalState), true);
  460. }
  461. else if (mOldHitDivider)
  462. {
  463. mOldHitDivider = nullptr;
  464. }
  465. }
  466. void GuiFrameSetCtrl::onTouchMove(const GuiEvent& event)
  467. {
  468. if (!mVisible || !mAwake)
  469. return;
  470. if(!mDepressed)
  471. {
  472. Point2I localPoint = globalToLocalCoord(event.mousePoint);
  473. mHitDivider = mRootFrame.findHitDivider(localPoint);
  474. }
  475. if (!mHitDivider)
  476. {
  477. Parent::onTouchMove(event);
  478. }
  479. }
  480. void GuiFrameSetCtrl::onTouchDragged(const GuiEvent& event)
  481. {
  482. if (mDepressed && mHitDivider && mHitDivider->child1 && mHitDivider->child2)
  483. {
  484. S32 offset = (mHitDivider->isVertical ? event.mousePoint.y : event.mousePoint.x) - mFrameDragAnchor;
  485. if(offset != 0)
  486. {
  487. if (mHitDivider->isVertical)
  488. {
  489. mHitDivider->child1->extent.y = getMax(minSize, mHitDivider->child1->extent.y + offset);
  490. mHitDivider->child2->extent.y = getMax(minSize, mHitDivider->child2->extent.y - offset);
  491. }
  492. else
  493. {
  494. mHitDivider->child1->extent.x = getMax(minSize, mHitDivider->child1->extent.x + offset);
  495. mHitDivider->child2->extent.x = getMax(minSize, mHitDivider->child2->extent.x - offset);
  496. }
  497. resize(getPosition(), getExtent());
  498. mFrameDragAnchor = mHitDivider->isVertical ? event.mousePoint.y : event.mousePoint.x;
  499. }
  500. }
  501. }
  502. void GuiFrameSetCtrl::onTouchDown(const GuiEvent& event)
  503. {
  504. if (!mActive)
  505. return;
  506. if(mHitDivider)
  507. {
  508. mDepressed = true;
  509. mFrameDragAnchor = mHitDivider->isVertical ? event.mousePoint.y : event.mousePoint.x;
  510. //lock the mouse
  511. mouseLock();
  512. //update
  513. setUpdate();
  514. }
  515. }
  516. void GuiFrameSetCtrl::onTouchUp(const GuiEvent& event)
  517. {
  518. if (!mActive)
  519. return;
  520. if(mHitDivider)
  521. {
  522. mouseUnlock();
  523. mDepressed = false;
  524. //update
  525. setUpdate();
  526. }
  527. }
  528. void GuiFrameSetCtrl::getCursor(GuiCursor*& cursor, bool& showCursor, const GuiEvent& lastGuiEvent)
  529. {
  530. GuiControl* parent = getParent();
  531. if (!parent)
  532. {
  533. return;
  534. }
  535. if (mHitDivider && mHitDivider->isVertical)
  536. {
  537. if (mUpDownCursor == NULL)
  538. {
  539. SimObject* obj;
  540. obj = Sim::findObject("UpDownCursor");
  541. mUpDownCursor = dynamic_cast<GuiCursor*>(obj);
  542. }
  543. if (mUpDownCursor != NULL)
  544. {
  545. cursor = mUpDownCursor;
  546. }
  547. }
  548. else if (mHitDivider && !mHitDivider->isVertical)
  549. {
  550. if (mLeftRightCursor == NULL)
  551. {
  552. SimObject* obj;
  553. obj = Sim::findObject("LeftRightCursor");
  554. mLeftRightCursor = dynamic_cast<GuiCursor*>(obj);
  555. }
  556. if (mLeftRightCursor != NULL)
  557. {
  558. cursor = mLeftRightCursor;
  559. }
  560. }
  561. }
  562. void GuiFrameSetCtrl::renderDropOptions(GuiWindowCtrl* window)
  563. {
  564. Point2I cursorPt = Point2I(0, 0);
  565. GuiCanvas* root = getRoot();
  566. if (root)
  567. {
  568. cursorPt = globalToLocalCoord(root->getCursorPos());
  569. cursorPt.x = getMin(getMax(0, cursorPt.x), mRootFrame.extent.x);
  570. cursorPt.y = getMin(getMax(0, cursorPt.y), mRootFrame.extent.y);
  571. }
  572. Frame* frame = mRootFrame.findFrameWithPoint(cursorPt);
  573. if (frame)
  574. {
  575. ColorI fillColor = mProfile->getFillColor(SelectedState);
  576. fillColor.alpha = 50;
  577. const U32 width = getMax(minSize, getMin(frame->extent.x / 2, window->mBounds.extent.x));
  578. const U32 height = getMax(minSize, getMin(frame->extent.y / 2, window->mBounds.extent.y));
  579. if (frame->hasLeftRightButtons)
  580. {
  581. Point2I fillExt = Point2I(width, frame->extent.y);
  582. renderDropButton(frame, frame->mLeftButtonRect, cursorPt, frame->localPosition, fillExt, GuiDirection::Left);
  583. renderDropButton(frame, frame->mRightButtonRect, cursorPt, Point2I(frame->localPosition.x + frame->extent.x - width, frame->localPosition.y), fillExt, GuiDirection::Right);
  584. }
  585. if (frame->hasTopBottomButtons)
  586. {
  587. Point2I fillExt = Point2I(frame->extent.x, height);
  588. renderDropButton(frame, frame->mTopButtonRect, cursorPt, frame->localPosition, fillExt, GuiDirection::Up);
  589. renderDropButton(frame, frame->mBottomButtonRect, cursorPt, Point2I(frame->localPosition.x, frame->localPosition.y + frame->extent.y - height), fillExt, GuiDirection::Down);
  590. }
  591. }
  592. }
  593. void GuiFrameSetCtrl::renderDropButton(const GuiFrameSetCtrl::Frame* frame, const RectI& buttonRect, const Point2I& cursorPt, const Point2I& fillPos, const Point2I& fillExt, GuiDirection direction)
  594. {
  595. GuiControlState state = NormalState;
  596. if (buttonRect.pointInRect(cursorPt))
  597. {
  598. state = HighlightState;
  599. RectI rect = RectI(fillPos, fillExt);
  600. rect.point = localToGlobalCoord(rect.point);
  601. setUpdateRegion(rect.point, rect.extent);
  602. renderUniversalRect(rect, mDropButtonProfile, SelectedState);
  603. }
  604. RectI globalButtonRect = RectI(localToGlobalCoord(buttonRect.point), buttonRect.extent);
  605. renderUniversalRect(globalButtonRect, mDropButtonProfile, state);
  606. dglSetBitmapModulation(getFontColor(mDropButtonProfile, state));
  607. ColorI triColor = getFontColor(mDropButtonProfile, state);
  608. renderTriangleIcon(globalButtonRect, triColor, direction, 10);
  609. }
  610. void GuiFrameSetCtrl::handleDropButtons(GuiWindowCtrl* window)
  611. {
  612. Point2I cursorPt = Point2I(0, 0);
  613. GuiCanvas* root = getRoot();
  614. if (root)
  615. {
  616. cursorPt = globalToLocalCoord(root->getCursorPos());
  617. cursorPt.x = getMin(getMax(0, cursorPt.x), mRootFrame.extent.x);
  618. cursorPt.y = getMin(getMax(0, cursorPt.y), mRootFrame.extent.y);
  619. }
  620. Frame* frame = mRootFrame.findFrameWithPoint(cursorPt);
  621. if (frame)
  622. {
  623. const U32 width = getMax(minSize, getMin(frame->extent.x / 2, window->mBounds.extent.x));
  624. const U32 height = getMax(minSize, getMin(frame->extent.y / 2, window->mBounds.extent.y));
  625. bool hitButton = false;
  626. if (frame->mLeftButtonRect.pointInRect(cursorPt))
  627. {
  628. splitFrame(frame, GuiDirection::Right);//This existing control goes right, the new window will go left.
  629. anchorFrame(frame->child1);
  630. frame->child1->control = window;
  631. frame->child1->extent = Point2I(width, frame->extent.y);
  632. hitButton = true;
  633. }
  634. else if (frame->mRightButtonRect.pointInRect(cursorPt))
  635. {
  636. splitFrame(frame, GuiDirection::Left);
  637. anchorFrame(frame->child2);
  638. frame->child2->control = window;
  639. frame->child2->extent = Point2I(width, frame->extent.y);
  640. hitButton = true;
  641. }
  642. else if (frame->mTopButtonRect.pointInRect(cursorPt))
  643. {
  644. splitFrame(frame, GuiDirection::Down);
  645. anchorFrame(frame->child1);
  646. frame->child1->control = window;
  647. frame->child1->extent = Point2I(frame->extent.x, height);
  648. hitButton = true;
  649. }
  650. else if (frame->mBottomButtonRect.pointInRect(cursorPt))
  651. {
  652. splitFrame(frame, GuiDirection::Up);
  653. anchorFrame(frame->child2);
  654. frame->child2->control = window;
  655. frame->child2->extent = Point2I(frame->extent.x, height);
  656. hitButton = true;
  657. }
  658. if (hitButton)
  659. {
  660. addObject(window);
  661. }
  662. }
  663. }
  664. void GuiFrameSetCtrl::setDropButtonProfile(GuiControlProfile* prof)
  665. {
  666. AssertFatal(prof, "GuiFrameSetCtrl::setDropButtonProfile: invalid content profile");
  667. if (prof == mDropButtonProfile)
  668. return;
  669. if (mAwake)
  670. mDropButtonProfile->decRefCount();
  671. mDropButtonProfile = prof;
  672. if (mAwake)
  673. mDropButtonProfile->incRefCount();
  674. }
  675. void GuiFrameSetCtrl::setControlLeftRightCursor(GuiCursor* cursor)
  676. {
  677. AssertFatal(cursor, "GuiFrameSetCtrl::setControlLeftRightCursor: invalid cursor");
  678. if (cursor == mLeftRightCursor)
  679. return;
  680. mLeftRightCursor = cursor;
  681. }
  682. void GuiFrameSetCtrl::setControlUpDownCursor(GuiCursor* cursor)
  683. {
  684. AssertFatal(cursor, "GuiFrameSetCtrl::setControlUpDownCursor: invalid cursor");
  685. if (cursor == mUpDownCursor)
  686. return;
  687. mUpDownCursor = cursor;
  688. }