guiFrameSetCtrl.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299
  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 "graphics/dgl.h"
  29. #include "gui/containers/guiTabBookCtrl.h"
  30. #include "gui/containers/guiTabPageCtrl.h"
  31. #include "gui/editor/guiEditCtrl.h"
  32. #include "collection/vector.h"
  33. #include "guiFrameSetCtrl_ScriptBinding.h"
  34. void GuiFrameSetCtrl::Frame::deleteChildren()
  35. {
  36. if (child1)
  37. {
  38. child1->deleteChildren();
  39. delete child1;
  40. }
  41. if (child2)
  42. {
  43. child2->deleteChildren();
  44. delete child2;
  45. }
  46. }
  47. void GuiFrameSetCtrl::Frame::resize(const Point2I& newPosition, const Point2I& newExtent)
  48. {
  49. const S32 minSize = owner->minSize;
  50. extent.set(newExtent.x, newExtent.y);
  51. localPosition.set(newPosition.x, newPosition.y);
  52. sizeInsertButtons(newPosition, newExtent);
  53. if (control)
  54. {
  55. if (control->mMinExtent.x > minSize || control->mMinExtent.y > minSize)
  56. {
  57. control->mMinExtent.set(minSize, minSize);
  58. }
  59. control->resize(newPosition, newExtent);
  60. }
  61. if (!child1 && !child2 && owner->isEditMode())
  62. {
  63. if (extent.x > (3 * owner->minSize))
  64. {
  65. spliterRect1.set(localPosition.x + ((extent.x - owner->mDividerThickness) / 2), localPosition.y, owner->mDividerThickness, extent.y);
  66. }
  67. else
  68. {
  69. spliterRect1.set(0, 0, 0, 0);
  70. }
  71. if (extent.y > (3 * owner->minSize))
  72. {
  73. spliterRect2.set(localPosition.x, localPosition.y + ((extent.y - owner->mDividerThickness) / 2), extent.x, owner->mDividerThickness);
  74. }
  75. else
  76. {
  77. spliterRect2.set(0, 0, 0, 0);
  78. }
  79. }
  80. else if (child1 && child2)
  81. {
  82. S32 spaceX = isVertical ? newExtent.x : newExtent.x - owner->mDividerThickness;
  83. S32 spaceY = !isVertical ? newExtent.y : newExtent.y - owner->mDividerThickness;
  84. S32 x1 = newExtent.x;
  85. S32 x2 = newExtent.x;
  86. if(!isVertical)
  87. {
  88. if (child1->isAnchored)
  89. {
  90. x1 = getMin(child1->extent.x, spaceX - minSize);
  91. x2 = spaceX - x1;
  92. }
  93. else
  94. {
  95. x2 = getMin(child2->extent.x, spaceX - minSize);
  96. x1 = spaceX - x2;
  97. }
  98. }
  99. S32 y1 = newExtent.y;
  100. S32 y2 = newExtent.y;
  101. if (isVertical)
  102. {
  103. if (child1->isAnchored)
  104. {
  105. y1 = getMin(child1->extent.y, spaceY - minSize);
  106. y2 = spaceY - y1;
  107. }
  108. else
  109. {
  110. y2 = getMin(child2->extent.y, spaceY - minSize);
  111. y1 = spaceY - y2;
  112. }
  113. }
  114. Point2I ext1 = Point2I(x1, y1);
  115. Point2I ext2 = Point2I(x2, y2);
  116. Point2I pos2 = isVertical ? Point2I(newPosition.x, newPosition.y + y1 + owner->mDividerThickness) : Point2I(newPosition.x + x1 + owner->mDividerThickness, newPosition.y);
  117. if(isVertical)
  118. {
  119. dividerRect.set(newPosition.x, newPosition.y + y1, x1, owner->mDividerThickness);
  120. }
  121. else
  122. {
  123. dividerRect.set(newPosition.x + x1, newPosition.y, owner->mDividerThickness, y1);
  124. }
  125. child1->resize(newPosition, ext1);
  126. child2->resize(pos2, ext2);
  127. }
  128. }
  129. void GuiFrameSetCtrl::Frame::sizeInsertButtons(const Point2I& newPosition, const Point2I& newExtent)
  130. {
  131. const U32 size = 40;
  132. const U32 gutter = 10;
  133. hasLeftRightButtons = false;
  134. hasTopBottomButtons = false;
  135. if (newExtent.x > (4 * (size + gutter)))
  136. {
  137. hasLeftRightButtons = true;
  138. mLeftButtonRect = RectI(newPosition.x + gutter, newPosition.y + ((newExtent.y - size) / 2), size, size);
  139. mRightButtonRect = RectI(newPosition.x + newExtent.x - (gutter + size), newPosition.y + ((newExtent.y - size) / 2), size, size);
  140. }
  141. if (newExtent.y > (4 * (size + gutter)))
  142. {
  143. hasTopBottomButtons = true;
  144. mTopButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + gutter, size, size);
  145. mBottomButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + newExtent.y - (gutter + size), size, size);
  146. }
  147. mCenterButtonRect = RectI(newPosition.x + ((newExtent.x - size) / 2), newPosition.y + ((newExtent.y - size) / 2), size, size);
  148. }
  149. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrame(const S32 frameID)
  150. {
  151. if (id == frameID)
  152. {
  153. return this;
  154. }
  155. if (child1 && child2)
  156. {
  157. Frame* attempt = child1->findFrame(frameID);
  158. return attempt ? attempt : child2->findFrame(frameID);
  159. }
  160. return nullptr;
  161. }
  162. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findEmptyFrame()
  163. {
  164. if (!control && !child1 && !child2)
  165. {
  166. return this;
  167. }
  168. else if (child1 && child2)
  169. {
  170. Frame* attempt = child1->findEmptyFrame();
  171. return attempt ? attempt : child2->findEmptyFrame();
  172. }
  173. return nullptr;
  174. }
  175. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findEmptyFrameAtLocation(const RectI& location)
  176. {
  177. if (!control && !child1 && !child2 && localPosition == location.point && extent == location.extent)
  178. {
  179. return this;
  180. }
  181. else if (child1 && child2)
  182. {
  183. Frame* attempt = child1->findEmptyFrameAtLocation(location);
  184. return attempt ? attempt : child2->findEmptyFrameAtLocation(location);
  185. }
  186. return nullptr;
  187. }
  188. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::twin()
  189. {
  190. if (parent)
  191. {
  192. if (parent->child1 == this)
  193. {
  194. return parent->child2;
  195. }
  196. else
  197. {
  198. return parent->child1;
  199. }
  200. }
  201. return this;
  202. }
  203. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findHitDivider(const Point2I& position)
  204. {
  205. S32 x = position.x;
  206. S32 y = position.y;
  207. if (child1 && child2)
  208. {
  209. if (x >= dividerRect.point.x && x <= (dividerRect.point.x + dividerRect.extent.x) &&
  210. y >= dividerRect.point.y && y <= (dividerRect.point.y + dividerRect.extent.y))
  211. {
  212. return this;
  213. }
  214. Frame* attempt = child1->findHitDivider(position);
  215. return attempt ? attempt : child2->findHitDivider(position);
  216. }
  217. return nullptr;
  218. }
  219. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrameWithCtrl(GuiControl* ctrl)
  220. {
  221. if (ctrl == control)
  222. {
  223. return this;
  224. }
  225. else if(child1 && child2)
  226. {
  227. Frame* attempt = child1->findFrameWithCtrl(ctrl);
  228. return attempt ? attempt : child2->findFrameWithCtrl(ctrl);
  229. }
  230. return nullptr;
  231. }
  232. GuiFrameSetCtrl::Frame* GuiFrameSetCtrl::Frame::findFrameWithPoint(const Point2I& point)
  233. {
  234. //Point is local to the frame.
  235. if (!child1 && !child2)
  236. {
  237. return this;
  238. }
  239. if (child1 && child2)
  240. {
  241. S32 x = point.x;
  242. S32 y = point.y;
  243. Point2I pos2 = isVertical ? Point2I(x, child1->extent.y + owner->mDividerThickness) : Point2I(child1->extent.x + owner->mDividerThickness, y);
  244. if ((isVertical && y < child1->extent.y) || (!isVertical && x < child1->extent.x))
  245. {
  246. return child1->findFrameWithPoint(point);
  247. }
  248. else if ((isVertical && y > pos2.y && y < (pos2.y + child2->extent.y)) || (!isVertical && x > pos2.x && x < (pos2.x + child2->extent.x)))
  249. {
  250. Point2I pt = isVertical ? Point2I(x, y - pos2.y) : Point2I(x - pos2.x, y);
  251. return child2->findFrameWithPoint(pt);
  252. }
  253. }
  254. return nullptr;//This will happen if the mouse is over a divider.
  255. }
  256. void GuiFrameSetCtrl::Frame::editRender(const Point2I& cursorPt, const F32 fade)
  257. {
  258. //cursorPt is local to owner
  259. if (!child1 && !child2)
  260. {
  261. //Show the frame
  262. RectI localRect = RectI(localPosition, extent);
  263. Point2I pos = localPosition;
  264. RectI rect = RectI(owner->localToGlobalCoord(pos), extent);
  265. GuiEditCtrl* edit = GuiControl::smEditorHandle;
  266. ColorI border = edit->getEditorColor();
  267. if (!localRect.pointInRect(cursorPt))
  268. {
  269. border.alpha = (150 * fade);
  270. }
  271. dglDrawRect(rect, border);
  272. ColorI fill = ColorI(border);
  273. fill.alpha = (40 * fade);
  274. dglDrawRectFill(rect, fill);
  275. U8 divThickness = owner->mDividerThickness;
  276. fill.alpha = (10 * fade);
  277. if(spliterRect1.pointInRect(cursorPt))
  278. {
  279. fill.alpha = (200 * fade);
  280. }
  281. RectI globalSpliter1 = RectI(owner->localToGlobalCoord(spliterRect1.point), spliterRect1.extent);
  282. dglDrawRectFill(globalSpliter1, fill);
  283. fill.alpha = (10 * fade);
  284. if (spliterRect2.pointInRect(cursorPt) && !spliterRect1.pointInRect(cursorPt))
  285. {
  286. fill.alpha = (200 * fade);
  287. }
  288. RectI globalSpliter2 = RectI(owner->localToGlobalCoord(spliterRect2.point), spliterRect2.extent);
  289. dglDrawRectFill(globalSpliter2, fill);
  290. }
  291. if (child1)
  292. {
  293. child1->editRender(cursorPt, fade);
  294. }
  295. if (child2)
  296. {
  297. child2->editRender(cursorPt, fade);
  298. }
  299. }
  300. //------------------------------------------------------------------------------
  301. IMPLEMENT_CONOBJECT(GuiFrameSetCtrl);
  302. //------------------------------------------------------------------------------
  303. GuiFrameSetCtrl::GuiFrameSetCtrl()
  304. {
  305. mIsContainer = true;
  306. setField("profile", "GuiDefaultProfile");
  307. mRootFrame = Frame(this, nullptr);
  308. mHitDivider = nullptr;
  309. mDividerThickness = 8;
  310. mNextFrameID = 1;
  311. mResizeGuard = false;
  312. mDepressed = false;
  313. mActive = true;
  314. mFrameDragAnchor = 0;
  315. mEaseFillColorHL = EasingFunction::EaseInOut;
  316. mEaseFillColorSL = EasingFunction::EaseOut;
  317. mEaseTimeFillColorHL = 500;
  318. mEaseTimeFillColorSL = 1000;
  319. mDropButtonProfile = NULL;
  320. setField("dropButtonProfile", "GuiButtonProfile");
  321. mTabBookProfile = NULL;
  322. mTabProfile = NULL;
  323. mTabPageProfile = NULL;
  324. setField("tabBookProfile", "GuiDefaultProfile");
  325. setField("tabProfile", "GuiTabProfile");
  326. setField("tabPageProfile", "GuiDefaultProfile");
  327. mLeftRightCursor = NULL;
  328. mUpDownCursor = NULL;
  329. }
  330. GuiFrameSetCtrl::~GuiFrameSetCtrl()
  331. {
  332. mRootFrame.deleteChildren();
  333. }
  334. //------------------------------------------------------------------------------
  335. void GuiFrameSetCtrl::initPersistFields()
  336. {
  337. Parent::initPersistFields();
  338. addField("DividerThickness", TypeS8, Offset(mDividerThickness, GuiFrameSetCtrl));
  339. addField("dropButtonProfile", TypeGuiProfile, Offset(mDropButtonProfile, GuiFrameSetCtrl));
  340. addField("leftRightCursor", TypeGuiCursor, Offset(mLeftRightCursor, GuiFrameSetCtrl));
  341. addField("upDownCursor", TypeGuiCursor, Offset(mUpDownCursor, GuiFrameSetCtrl));
  342. addProtectedField("TabBookProfile", TypeGuiProfile, Offset(mTabBookProfile, GuiFrameSetCtrl), &setBookProfileFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, "");
  343. addProtectedField("TabProfile", TypeGuiProfile, Offset(mTabProfile, GuiFrameSetCtrl), &setTabProfileFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, "");
  344. addProtectedField("TabPageProfile", TypeGuiProfile, Offset(mTabPageProfile, GuiFrameSetCtrl), &setPageProfileFn, &defaultProtectedGetFn, &defaultProtectedWriteFn, "");
  345. }
  346. //------------------------------------------------------------------------------
  347. bool GuiFrameSetCtrl::onWake()
  348. {
  349. if (!Parent::onWake())
  350. return false;
  351. if (mDropButtonProfile != NULL)
  352. mDropButtonProfile->incRefCount();
  353. if (mTabBookProfile != NULL)
  354. mTabBookProfile->incRefCount();
  355. if (mTabProfile != NULL)
  356. mTabProfile->incRefCount();
  357. if (mTabPageProfile != NULL)
  358. mTabPageProfile->incRefCount();
  359. return true;
  360. }
  361. //------------------------------------------------------------------------------
  362. void GuiFrameSetCtrl::onSleep()
  363. {
  364. Parent::onSleep();
  365. if (mDropButtonProfile != NULL)
  366. mDropButtonProfile->decRefCount();
  367. if (mTabBookProfile != NULL)
  368. mTabBookProfile->decRefCount();
  369. if (mTabProfile != NULL)
  370. mTabProfile->decRefCount();
  371. if (mTabPageProfile != NULL)
  372. mTabPageProfile->decRefCount();
  373. }
  374. //------------------------------------------------------------------------------
  375. void GuiFrameSetCtrl::inspectPostApply()
  376. {
  377. resize(getPosition(), getExtent());
  378. Parent::inspectPostApply();
  379. }
  380. //------------------------------------------------------------------------------
  381. void GuiFrameSetCtrl::resize(const Point2I& newPosition, const Point2I& newExtent)
  382. {
  383. if(!mResizeGuard)//Prevent circular resizing
  384. {
  385. mResizeGuard = true;
  386. Point2I actualNewExtent = Point2I(getMax(mMinExtent.x, newExtent.x),
  387. getMax(mMinExtent.y, newExtent.y));
  388. //call set update both before and after
  389. setUpdate();
  390. Point2I origin = Point2I::Zero;
  391. mRootFrame.resize(origin, actualNewExtent);
  392. mBounds.set(newPosition, actualNewExtent);
  393. GuiControl* parent = getParent();
  394. if (parent)
  395. parent->childResized(this);
  396. setUpdate();
  397. mResizeGuard = false;
  398. }
  399. }
  400. bool GuiFrameSetCtrl::onAdd()
  401. {
  402. // Let Parent Do Work.
  403. if (!Parent::onAdd())
  404. return false;
  405. // Always expand to fill the parent (we just ignore the points passed in).
  406. parentResized(Point2I(), Point2I());
  407. Frame* frame = &mRootFrame;
  408. loadFrame(frame, 1);
  409. clearDynamicFields();
  410. //resize one last time for the frames
  411. resize(getPosition(), getExtent());
  412. // Return Success.
  413. return true;
  414. }
  415. void GuiFrameSetCtrl::parentResized(const Point2I& oldParentExtent, const Point2I& newParentExtent)
  416. {
  417. //In the case of centering, we want to make doubly sure we are using the inner rect.
  418. GuiControl* parent = getParent();
  419. if(parent)
  420. {
  421. Point2I origin = Point2I::Zero;
  422. Point2I parentInnerExt = parent->getInnerRect().extent;
  423. resize(origin, parentInnerExt);
  424. }
  425. }
  426. void GuiFrameSetCtrl::loadFrame(GuiFrameSetCtrl::Frame* frame, const U32 frameID)
  427. {
  428. frame->id = frameID;
  429. U32 child1ID = dAtoi(getDataField("child1ID", frameID));
  430. U32 child2ID = dAtoi(getDataField("child2ID", frameID));
  431. frame->isVertical = dAtob(getDataField("isVertical", frameID));
  432. U32 frameExtentX = dAtoi(getDataField("frameExtentX", frameID));
  433. U32 frameExtentY = dAtoi(getDataField("frameExtentY", frameID));
  434. frame->isAnchored = dAtob(getDataField("isAnchored", frameID));
  435. frame->extent.set(frameExtentX, frameExtentY);
  436. if (child1ID && child2ID)
  437. {
  438. splitFrame(frame, frame->isVertical ? GuiDirection::Up : GuiDirection::Left);
  439. loadFrame(frame->child1, child1ID);
  440. loadFrame(frame->child2, child2ID);
  441. }
  442. }
  443. void GuiFrameSetCtrl::onChildAdded(GuiControl* child)
  444. {
  445. //Ensure the child isn't positioned to the center
  446. if (child->getHorizSizing() == horizResizeCenter)
  447. {
  448. child->setHorizSizing(horizResizeLeft);
  449. }
  450. if (child->getVertSizing() == vertResizeCenter)
  451. {
  452. child->setVertSizing(vertResizeTop);
  453. }
  454. Parent::onChildAdded(child);
  455. Frame* frame = mRootFrame.findFrameWithCtrl(child);
  456. if(!frame)
  457. {
  458. Frame* emptyFrame = mRootFrame.findEmptyFrameAtLocation(child->getBounds());
  459. if(emptyFrame)
  460. {
  461. emptyFrame->control = child;
  462. }
  463. else
  464. {
  465. Frame* emptyFrame = mRootFrame.findEmptyFrame();
  466. if (emptyFrame)
  467. {
  468. emptyFrame->control = child;
  469. }
  470. }
  471. }
  472. //resize(getPosition(), getExtent());
  473. }
  474. void GuiFrameSetCtrl::onChildRemoved(GuiControl* child)
  475. {
  476. Frame* frame = mRootFrame.findFrameWithCtrl(child);
  477. if (frame && frame == &mRootFrame)
  478. {
  479. mRootFrame.control = nullptr;
  480. }
  481. else if(frame)
  482. {
  483. //Remove the frame from the heirarchy
  484. Frame* frameParent = frame->parent;
  485. Frame* frameTwin = frame->twin();
  486. frameParent->control = frameTwin->control;
  487. frameParent->child1 = frameTwin->child1;
  488. frameParent->child2 = frameTwin->child2;
  489. if (frameParent->child1)
  490. {
  491. frameParent->child1->parent = frameParent;
  492. }
  493. if (frameParent->child2)
  494. {
  495. frameParent->child2->parent = frameParent;
  496. }
  497. frameParent->isVertical = frameTwin->isVertical;
  498. delete frame;
  499. delete frameTwin;
  500. }
  501. resize(getPosition(), getExtent());
  502. }
  503. void GuiFrameSetCtrl::childResized(GuiControl* child)
  504. {
  505. Parent::childResized(child);
  506. resize(getPosition(), getExtent());
  507. }
  508. void GuiFrameSetCtrl::childMoved(GuiControl* child)
  509. {
  510. Parent::childMoved(child);
  511. resize(getPosition(), getExtent());
  512. }
  513. void GuiFrameSetCtrl::childrenReordered()
  514. {
  515. resize(getPosition(), getExtent());
  516. Parent::childrenReordered();
  517. }
  518. Point2I GuiFrameSetCtrl::splitFrame(S32 frameID, bool isVertical)
  519. {
  520. Frame* frame = mRootFrame.findFrame(frameID);
  521. if(frame)
  522. {
  523. splitFrame(frame, isVertical ? GuiDirection::Up : GuiDirection::Left);
  524. return Point2I(frame->child1 ? static_cast<S32>(frame->child1->id) : 0, frame->child2 ? static_cast<S32>(frame->child2->id) : 0);
  525. }
  526. return Point2I::Zero;
  527. }
  528. void GuiFrameSetCtrl::splitFrame(GuiFrameSetCtrl::Frame* frame, GuiDirection direction)
  529. {
  530. //The existing control, if any, is moved to the new frame in the direction and anchored. The frame oposite is left empty.
  531. if (!frame->child1 && !frame->child2)
  532. {
  533. GuiControl* ctrl = frame->control;
  534. frame->child1 = new GuiFrameSetCtrl::Frame(this, frame);
  535. frame->child2 = new GuiFrameSetCtrl::Frame(this, frame);
  536. frame->control = nullptr;
  537. frame->child1->control = direction == GuiDirection::Left || direction == GuiDirection::Up ? ctrl : nullptr;
  538. frame->child2->control = direction == GuiDirection::Right || direction == GuiDirection::Down ? ctrl : nullptr;
  539. frame->child1->id = ++mNextFrameID;
  540. frame->child2->id = ++mNextFrameID;
  541. frame->child1->isAnchored = direction == GuiDirection::Left || direction == GuiDirection::Up;
  542. frame->child2->isAnchored = direction == GuiDirection::Right || direction == GuiDirection::Down;
  543. }
  544. frame->isVertical = direction == GuiDirection::Up || direction == GuiDirection::Down;
  545. }
  546. void GuiFrameSetCtrl::anchorFrame(S32 frameID)
  547. {
  548. Frame* frame = mRootFrame.findFrame(frameID);
  549. anchorFrame(frame);
  550. }
  551. void GuiFrameSetCtrl::anchorFrame(GuiFrameSetCtrl::Frame* frame)
  552. {
  553. if (frame && frame != &mRootFrame)//The root frame has no twin and can't be anchored.
  554. {
  555. frame->isAnchored = true;
  556. frame->twin()->isAnchored = false;
  557. }
  558. }
  559. void GuiFrameSetCtrl::setFrameSize(S32 frameID, S32 size)
  560. {
  561. Frame* frame = mRootFrame.findFrame(frameID);
  562. if (frame && frame != &mRootFrame)//The root frame must be the size of the control.
  563. {
  564. if (frame->parent->isVertical)
  565. {
  566. frame->extent.y = size;
  567. frame->twin()->extent.y = getMax(frame->parent->extent.y - (size + mDividerThickness), minSize);
  568. }
  569. else
  570. {
  571. frame->extent.x = size;
  572. frame->twin()->extent.x = getMax(frame->parent->extent.x - (size + mDividerThickness), minSize);
  573. }
  574. //Pass this down to the other frames and then to the child controls
  575. resize(getPosition(), getExtent());
  576. }
  577. }
  578. void GuiFrameSetCtrl::onPreRender()
  579. {
  580. SimSet::iterator i;
  581. for(i = begin(); i < end(); i++)
  582. {
  583. GuiTabBookCtrl* book = dynamic_cast<GuiTabBookCtrl*>(*i);
  584. if (book && book->mIsFrameSetGenerated && book->size() == 0)
  585. {
  586. book->deleteObject();
  587. }
  588. }
  589. if (isEditMode())
  590. {
  591. GuiCanvas* root = getRoot();
  592. GuiEditCtrl* edit = GuiControl::smEditorHandle;
  593. if (root && edit)
  594. {
  595. Point2I cursorPt = globalToLocalCoord(root->getCursorPos());
  596. if (mBounds.pointInRect(cursorPt))
  597. {
  598. mHitDivider = mRootFrame.findHitDivider(cursorPt);
  599. }
  600. }
  601. }
  602. }
  603. void GuiFrameSetCtrl::onRender(Point2I offset, const RectI& updateRect)
  604. {
  605. Parent::onRender(offset, updateRect);
  606. if (mHitDivider)
  607. {
  608. GuiControlState currentState = mDepressed ? SelectedState : HighlightState;
  609. mOldHitDivider = mHitDivider;
  610. RectI contentRect = RectI(localToGlobalCoord(mHitDivider->dividerRect.point), mHitDivider->dividerRect.extent);
  611. renderUniversalRect(contentRect, mProfile, currentState, getFillColor(currentState), true);
  612. }
  613. else if (mOldHitDivider && (mCurrentState == HighlightState || mFluidFillColor.isAnimating()))
  614. {
  615. RectI contentRect = RectI(localToGlobalCoord(mOldHitDivider->dividerRect.point), mOldHitDivider->dividerRect.extent);
  616. renderUniversalRect(contentRect, mProfile, NormalState, getFillColor(NormalState), true);
  617. }
  618. else if (mOldHitDivider)
  619. {
  620. mOldHitDivider = nullptr;
  621. }
  622. if (isEditMode())
  623. {
  624. GuiCanvas* root = getRoot();
  625. GuiEditCtrl* edit = GuiControl::smEditorHandle;
  626. if(root && edit)
  627. {
  628. Point2I cursorPt = globalToLocalCoord(root->getCursorPos());
  629. RectI visBounds = RectI(mBounds);
  630. const S32 fadeDist = 140;
  631. visBounds.inset(-fadeDist, -fadeDist);
  632. if (visBounds.pointInRect(cursorPt) && isEditSelected())
  633. {
  634. visBounds.inset(fadeDist, fadeDist);
  635. F32 fade = getMin(1.0, getMax(0.0, 1.0 - ((F32)visBounds.distanceToRect(cursorPt) / (F32)fadeDist)));
  636. mRootFrame.editRender(cursorPt, fade);
  637. }
  638. }
  639. }
  640. }
  641. void GuiFrameSetCtrl::onTouchMove(const GuiEvent& event)
  642. {
  643. if (!mVisible || !mAwake)
  644. return;
  645. if(!mDepressed)
  646. {
  647. Point2I localPoint = globalToLocalCoord(event.mousePoint);
  648. mHitDivider = mRootFrame.findHitDivider(localPoint);
  649. }
  650. if (!mHitDivider)
  651. {
  652. Parent::onTouchMove(event);
  653. }
  654. }
  655. void GuiFrameSetCtrl::onTouchDragged(const GuiEvent& event)
  656. {
  657. if (mDepressed && mHitDivider && mHitDivider->child1 && mHitDivider->child2)
  658. {
  659. S32 offset = (mHitDivider->isVertical ? event.mousePoint.y : event.mousePoint.x) - mFrameDragAnchor;
  660. if(offset != 0)
  661. {
  662. if (mHitDivider->isVertical)
  663. {
  664. mHitDivider->child1->extent.y = getMax(minSize, mHitDivider->child1->extent.y + offset);
  665. mHitDivider->child2->extent.y = getMax(minSize, mHitDivider->child2->extent.y - offset);
  666. }
  667. else
  668. {
  669. mHitDivider->child1->extent.x = getMax(minSize, mHitDivider->child1->extent.x + offset);
  670. mHitDivider->child2->extent.x = getMax(minSize, mHitDivider->child2->extent.x - offset);
  671. }
  672. resize(getPosition(), getExtent());
  673. mFrameDragAnchor = mHitDivider->isVertical ? event.mousePoint.y : event.mousePoint.x;
  674. }
  675. }
  676. }
  677. void GuiFrameSetCtrl::onTouchDown(const GuiEvent& event)
  678. {
  679. if (!mActive)
  680. return;
  681. if(mHitDivider)
  682. {
  683. mDepressed = true;
  684. mFrameDragAnchor = mHitDivider->isVertical ? event.mousePoint.y : event.mousePoint.x;
  685. //lock the mouse
  686. mouseLock();
  687. //update
  688. setUpdate();
  689. }
  690. }
  691. void GuiFrameSetCtrl::onTouchUp(const GuiEvent& event)
  692. {
  693. if (!mActive)
  694. return;
  695. if(mHitDivider)
  696. {
  697. mouseUnlock();
  698. mDepressed = false;
  699. //update
  700. setUpdate();
  701. }
  702. }
  703. void GuiFrameSetCtrl::getCursor(GuiCursor*& cursor, bool& showCursor, const GuiEvent& lastGuiEvent)
  704. {
  705. GuiControl* parent = getParent();
  706. if (!parent)
  707. {
  708. return;
  709. }
  710. if (mHitDivider && mHitDivider->isVertical)
  711. {
  712. if (mUpDownCursor == NULL)
  713. {
  714. SimObject* obj;
  715. obj = Sim::findObject("UpDownCursor");
  716. mUpDownCursor = dynamic_cast<GuiCursor*>(obj);
  717. }
  718. if (mUpDownCursor != NULL)
  719. {
  720. cursor = mUpDownCursor;
  721. }
  722. }
  723. else if (mHitDivider && !mHitDivider->isVertical)
  724. {
  725. if (mLeftRightCursor == NULL)
  726. {
  727. SimObject* obj;
  728. obj = Sim::findObject("LeftRightCursor");
  729. mLeftRightCursor = dynamic_cast<GuiCursor*>(obj);
  730. }
  731. if (mLeftRightCursor != NULL)
  732. {
  733. cursor = mLeftRightCursor;
  734. }
  735. }
  736. }
  737. bool GuiFrameSetCtrl::onMouseDownEditor(const GuiEvent& event, const Point2I& offset)
  738. {
  739. Point2I cursorPt = globalToLocalCoord(event.mousePoint);
  740. Frame* frame = mRootFrame.findFrameWithPoint(cursorPt);
  741. if(frame && isEditSelected())
  742. {
  743. if (frame->spliterRect1.pointInRect(cursorPt))
  744. {
  745. splitFrame(frame, GuiDirection::Left);
  746. setFrameSize(frame->child1->id, (frame->extent.x - mDividerThickness) / 2);
  747. return true;
  748. }
  749. else if (frame->spliterRect2.pointInRect(cursorPt))
  750. {
  751. splitFrame(frame, GuiDirection::Up);
  752. setFrameSize(frame->child1->id, (frame->extent.y - mDividerThickness) / 2);
  753. return true;
  754. }
  755. }
  756. frame = mRootFrame.findHitDivider(cursorPt);
  757. if (frame)
  758. {
  759. onTouchDown(event);
  760. return true;
  761. }
  762. return Parent::onMouseDownEditor(event, offset);
  763. }
  764. bool GuiFrameSetCtrl::onMouseUpEditor(const GuiEvent& event, const Point2I& offset)
  765. {
  766. if (mDepressed)
  767. {
  768. onTouchUp(event);
  769. return true;
  770. }
  771. return false;
  772. }
  773. bool GuiFrameSetCtrl::onMouseDraggedEditor(const GuiEvent& event, const Point2I& offset)
  774. {
  775. if (mDepressed)
  776. {
  777. onTouchDragged(event);
  778. return true;
  779. }
  780. return false;
  781. }
  782. void GuiFrameSetCtrl::renderDropOptions(GuiWindowCtrl* window)
  783. {
  784. Point2I cursorPt = Point2I(0, 0);
  785. GuiCanvas* root = getRoot();
  786. if (root)
  787. {
  788. cursorPt = globalToLocalCoord(root->getCursorPos());
  789. cursorPt.x = getMin(getMax(0, cursorPt.x), mRootFrame.extent.x);
  790. cursorPt.y = getMin(getMax(0, cursorPt.y), mRootFrame.extent.y);
  791. }
  792. Frame* frame = mRootFrame.findFrameWithPoint(cursorPt);
  793. if (frame)
  794. {
  795. ColorI fillColor = mProfile->getFillColor(SelectedState);
  796. fillColor.alpha = 50;
  797. const U32 width = getMax(minSize, getMin(frame->extent.x / 2, window->mBounds.extent.x));
  798. const U32 height = getMax(minSize, getMin(frame->extent.y / 2, window->mBounds.extent.y));
  799. if (frame->hasLeftRightButtons)
  800. {
  801. Point2I fillExt = Point2I(width, frame->extent.y);
  802. renderDropButton(frame, frame->mLeftButtonRect, cursorPt, frame->localPosition, fillExt, GuiDirection::Left);
  803. renderDropButton(frame, frame->mRightButtonRect, cursorPt, Point2I(frame->localPosition.x + frame->extent.x - width, frame->localPosition.y), fillExt, GuiDirection::Right);
  804. }
  805. if (frame->hasTopBottomButtons)
  806. {
  807. Point2I fillExt = Point2I(frame->extent.x, height);
  808. renderDropButton(frame, frame->mTopButtonRect, cursorPt, frame->localPosition, fillExt, GuiDirection::Up);
  809. renderDropButton(frame, frame->mBottomButtonRect, cursorPt, Point2I(frame->localPosition.x, frame->localPosition.y + frame->extent.y - height), fillExt, GuiDirection::Down);
  810. }
  811. if (hasCenterButton(frame))
  812. {
  813. renderDropButton(frame, frame->mCenterButtonRect, cursorPt, frame->localPosition, frame->extent, GuiDirection::Center);
  814. }
  815. }
  816. }
  817. bool GuiFrameSetCtrl::hasCenterButton(GuiFrameSetCtrl::Frame* frame)
  818. {
  819. return (frame != &mRootFrame && (frame->isAnchored || (!frame->control && !frame->child1 && !frame->child2)));
  820. }
  821. void GuiFrameSetCtrl::renderDropButton(const GuiFrameSetCtrl::Frame* frame, const RectI& buttonRect, const Point2I& cursorPt, const Point2I& fillPos, const Point2I& fillExt, GuiDirection direction)
  822. {
  823. GuiControlState state = NormalState;
  824. if (buttonRect.pointInRect(cursorPt))
  825. {
  826. state = HighlightState;
  827. RectI rect = RectI(fillPos, fillExt);
  828. rect.point = localToGlobalCoord(rect.point);
  829. setUpdateRegion(rect.point, rect.extent);
  830. renderUniversalRect(rect, mDropButtonProfile, SelectedState);
  831. }
  832. RectI globalButtonRect = RectI(localToGlobalCoord(buttonRect.point), buttonRect.extent);
  833. renderUniversalRect(globalButtonRect, mDropButtonProfile, state);
  834. ColorI triColor = getFontColor(mDropButtonProfile, state);
  835. if(direction != GuiDirection::Center)
  836. {
  837. renderTriangleIcon(globalButtonRect, triColor, direction, 10);
  838. }
  839. else
  840. {
  841. RectI iconRect = RectI(buttonRect);
  842. iconRect.inset(15, 15);
  843. RectI lineH = RectI(localToGlobalCoord(Point2I(iconRect.point.x, iconRect.point.y + 4)), Point2I(iconRect.extent.x, 2));
  844. RectI lineV = RectI(localToGlobalCoord(Point2I(iconRect.point.x + 4, iconRect.point.y)), Point2I(2, iconRect.extent.y));
  845. dglDrawRectFill(lineH, triColor);
  846. dglDrawRectFill(lineV, triColor);
  847. }
  848. }
  849. void GuiFrameSetCtrl::handleDropButtons(GuiWindowCtrl* window)
  850. {
  851. Point2I cursorPt = Point2I(0, 0);
  852. GuiCanvas* root = getRoot();
  853. if (root)
  854. {
  855. cursorPt = globalToLocalCoord(root->getCursorPos());
  856. cursorPt.x = getMin(getMax(0, cursorPt.x), mRootFrame.extent.x);
  857. cursorPt.y = getMin(getMax(0, cursorPt.y), mRootFrame.extent.y);
  858. }
  859. Frame* frame = mRootFrame.findFrameWithPoint(cursorPt);
  860. if (frame)
  861. {
  862. const U32 width = getMax(minSize, getMin(frame->extent.x / 2, window->mBounds.extent.x));
  863. const U32 height = getMax(minSize, getMin(frame->extent.y / 2, window->mBounds.extent.y));
  864. bool hitButton = false;
  865. if (frame->hasLeftRightButtons && frame->mLeftButtonRect.pointInRect(cursorPt))
  866. {
  867. splitFrame(frame, GuiDirection::Right);//This existing control goes right, the new window will go left.
  868. anchorFrame(frame->child1);
  869. frame->child1->control = window;
  870. frame->child1->extent = Point2I(width, frame->extent.y);
  871. hitButton = true;
  872. }
  873. else if (frame->hasLeftRightButtons && frame->mRightButtonRect.pointInRect(cursorPt))
  874. {
  875. splitFrame(frame, GuiDirection::Left);
  876. anchorFrame(frame->child2);
  877. frame->child2->control = window;
  878. frame->child2->extent = Point2I(width, frame->extent.y);
  879. hitButton = true;
  880. }
  881. else if (frame->hasTopBottomButtons && frame->mTopButtonRect.pointInRect(cursorPt))
  882. {
  883. splitFrame(frame, GuiDirection::Down);
  884. anchorFrame(frame->child1);
  885. frame->child1->control = window;
  886. frame->child1->extent = Point2I(frame->extent.x, height);
  887. hitButton = true;
  888. }
  889. else if (frame->hasTopBottomButtons && frame->mBottomButtonRect.pointInRect(cursorPt))
  890. {
  891. splitFrame(frame, GuiDirection::Up);
  892. anchorFrame(frame->child2);
  893. frame->child2->control = window;
  894. frame->child2->extent = Point2I(frame->extent.x, height);
  895. hitButton = true;
  896. }
  897. else if (hasCenterButton(frame) && frame->mCenterButtonRect.pointInRect(cursorPt))
  898. {
  899. if (!frame->control)
  900. {
  901. frame->control = window;
  902. hitButton = true;
  903. }
  904. else
  905. {
  906. GuiTabBookCtrl* book = dynamic_cast<GuiTabBookCtrl*>(frame->control);
  907. GuiTabPageCtrl* page = nullptr;
  908. if (!book)
  909. {
  910. book = new GuiTabBookCtrl();
  911. book->setControlProfile(mTabBookProfile);
  912. book->setControlTabProfile(mTabProfile);
  913. book->mBounds.set(frame->localPosition, frame->extent);
  914. book->mIsFrameSetGenerated = true;
  915. book->registerObject();
  916. book->addNewPage();
  917. page = dynamic_cast<GuiTabPageCtrl*>((*book)[0]);
  918. page->setControlProfile(mTabPageProfile);
  919. GuiWindowCtrl* windowChild = dynamic_cast<GuiWindowCtrl*>(frame->control);
  920. GuiControl* child = dynamic_cast<GuiControl*>(frame->control);
  921. if (windowChild)
  922. {
  923. windowChild->dockToPage();
  924. }
  925. page->setText(child->getText());
  926. frame->control = book;
  927. page->addObject(child);
  928. addObject(book);
  929. }
  930. window->dockToPage();
  931. book->addNewPage();
  932. page = dynamic_cast<GuiTabPageCtrl*>((*book)[book->size() - 1]);
  933. page->setControlProfile(mTabPageProfile);
  934. page->setText(window->getText());
  935. page->addObject(window);
  936. book->selectPage(window->getText());
  937. window->resize(window->getPosition(), window->getExtent());
  938. }
  939. }
  940. if (hitButton)
  941. {
  942. addObject(window);
  943. }
  944. }
  945. }
  946. void GuiFrameSetCtrl::undockWindowFromBook(GuiWindowCtrl* window, GuiTabBookCtrl* book, GuiTabPageCtrl* page)
  947. {
  948. GuiControl* parent = getParent();
  949. GuiCanvas* root = getRoot();
  950. if (parent && window && book && page && window->mPageDocked && root)
  951. {
  952. parent->addObject(window);
  953. parent->pushObjectToBack(window);
  954. Point2I cursorPt = globalToLocalCoord(root->getCursorPos());
  955. window->undockFromPage();
  956. window->restore();
  957. Point2I newPosition = Point2I(cursorPt.x - (window->getExtent().x / 2), cursorPt.y - (window->getTitleHeight() / 2));
  958. Point2I pos = parent->localToGlobalCoord(newPosition);
  959. root->addUpdateRegion(pos, window->getExtent());
  960. window->resize(newPosition, window->getExtent());
  961. GuiEvent event = GuiEvent();
  962. event.mousePoint = Point2I(root->getCursorPos());
  963. event.mouseClickCount = 1;
  964. root->rootScreenTouchUp(event);
  965. root->rootScreenTouchDown(event);
  966. book->removeObject(page);
  967. page->deleteObject();
  968. if (book->size() > 0)
  969. {
  970. book->calculatePageTabs();
  971. book->selectPage(0);
  972. }
  973. if (book->mIsFrameSetGenerated && book->size() == 1)
  974. {
  975. GuiTabPageCtrl* lastPage = dynamic_cast<GuiTabPageCtrl*>((*book)[0]);
  976. GuiWindowCtrl* lastWindow = dynamic_cast<GuiWindowCtrl*>((*lastPage)[0]);
  977. GuiFrameSetCtrl::Frame* frame = mRootFrame.findFrameWithCtrl(book);
  978. frame->control = lastWindow;
  979. addObject(lastWindow);
  980. lastPage->deleteObject();
  981. lastWindow->undockFromPage();
  982. }
  983. }
  984. }
  985. void GuiFrameSetCtrl::setDropButtonProfile(GuiControlProfile* prof)
  986. {
  987. AssertFatal(prof, "GuiFrameSetCtrl::setDropButtonProfile: invalid content profile");
  988. if (prof == mDropButtonProfile)
  989. return;
  990. if (mAwake)
  991. mDropButtonProfile->decRefCount();
  992. mDropButtonProfile = prof;
  993. if (mAwake)
  994. mDropButtonProfile->incRefCount();
  995. }
  996. void GuiFrameSetCtrl::setTabBookProfile(GuiControlProfile* prof)
  997. {
  998. AssertFatal(prof, "GuiFrameSetCtrl::setTabBookProfile: invalid content profile");
  999. if (prof == mTabBookProfile)
  1000. return;
  1001. if (mAwake)
  1002. mTabBookProfile->decRefCount();
  1003. mTabBookProfile = prof;
  1004. if (mAwake)
  1005. mTabBookProfile->incRefCount();
  1006. //Cycle through all children and replace the profiles of frameSetGenerated books.
  1007. SimSet::iterator i;
  1008. for (i = begin(); i != end(); i++)
  1009. {
  1010. GuiTabBookCtrl* book = dynamic_cast<GuiTabBookCtrl*>(*i);
  1011. if (book && book->mIsFrameSetGenerated)
  1012. {
  1013. book->setControlProfile(prof);
  1014. }
  1015. }
  1016. }
  1017. void GuiFrameSetCtrl::setTabProfile(GuiControlProfile* prof)
  1018. {
  1019. AssertFatal(prof, "GuiFrameSetCtrl::setTabProfile: invalid content profile");
  1020. if (prof == mTabProfile)
  1021. return;
  1022. if (mAwake)
  1023. mTabProfile->decRefCount();
  1024. mTabProfile = prof;
  1025. if (mAwake)
  1026. mTabProfile->incRefCount();
  1027. SimSet::iterator i;
  1028. for (i = begin(); i != end(); i++)
  1029. {
  1030. GuiTabBookCtrl* book = dynamic_cast<GuiTabBookCtrl*>(*i);
  1031. if (book && book->mIsFrameSetGenerated)
  1032. {
  1033. book->setControlTabProfile(prof);
  1034. }
  1035. }
  1036. }
  1037. void GuiFrameSetCtrl::setTabPageProfile(GuiControlProfile* prof)
  1038. {
  1039. AssertFatal(prof, "GuiFrameSetCtrl::setTabPageProfile: invalid content profile");
  1040. if (prof == mTabPageProfile)
  1041. return;
  1042. if (mAwake)
  1043. mTabPageProfile->decRefCount();
  1044. mTabPageProfile = prof;
  1045. if (mAwake)
  1046. mTabPageProfile->incRefCount();
  1047. SimSet::iterator i;
  1048. for (i = begin(); i != end(); i++)
  1049. {
  1050. GuiTabBookCtrl* book = dynamic_cast<GuiTabBookCtrl*>(*i);
  1051. if (book && book->mIsFrameSetGenerated)
  1052. {
  1053. SimSet::iterator j;
  1054. for (j = begin(); j != end(); j++)
  1055. {
  1056. GuiTabPageCtrl* page = dynamic_cast<GuiTabPageCtrl*>(*i);
  1057. if (page)
  1058. {
  1059. page->setControlProfile(prof);
  1060. }
  1061. }
  1062. }
  1063. }
  1064. }
  1065. void GuiFrameSetCtrl::setControlLeftRightCursor(GuiCursor* cursor)
  1066. {
  1067. AssertFatal(cursor, "GuiFrameSetCtrl::setControlLeftRightCursor: invalid cursor");
  1068. if (cursor == mLeftRightCursor)
  1069. return;
  1070. mLeftRightCursor = cursor;
  1071. }
  1072. void GuiFrameSetCtrl::setControlUpDownCursor(GuiCursor* cursor)
  1073. {
  1074. AssertFatal(cursor, "GuiFrameSetCtrl::setControlUpDownCursor: invalid cursor");
  1075. if (cursor == mUpDownCursor)
  1076. return;
  1077. mUpDownCursor = cursor;
  1078. }
  1079. void GuiFrameSetCtrl::writeFields(Stream& stream, U32 tabStop)
  1080. {
  1081. if (mRootFrame.child1 && mRootFrame.child2)
  1082. {
  1083. setModDynamicFields(true);
  1084. setCanSaveDynamicFields(true);
  1085. Frame* frame = &mRootFrame;
  1086. generateFrameFields(frame);
  1087. Parent::writeFields(stream, tabStop);
  1088. clearDynamicFields();
  1089. setModDynamicFields(false);
  1090. setCanSaveDynamicFields(false);
  1091. }
  1092. else
  1093. {
  1094. Parent::writeFields(stream, tabStop);
  1095. }
  1096. }
  1097. void GuiFrameSetCtrl::generateFrameFields(GuiFrameSetCtrl::Frame* frame)
  1098. {
  1099. //parentID = frame->parent->id
  1100. //child1ID = frame->child1->id
  1101. //child2ID = frame->child2->id
  1102. //isVertical
  1103. //frameExtent = isVertical ? frame->extent.y : frame->extent.x
  1104. //isAnchored
  1105. //and make sure control has the correctID for
  1106. U32 id = frame->id;
  1107. U32 child1ID = frame->child1 ? frame->child1->id : 0;
  1108. U32 child2ID = frame->child2 ? frame->child2->id : 0;
  1109. setDataField("child1ID", id, child1ID);
  1110. setDataField("child2ID", id, child2ID);
  1111. setDataField("isVertical", id, frame->isVertical);
  1112. setDataField("frameExtentX", id, frame->extent.x);
  1113. setDataField("frameExtentY", id, frame->extent.y);
  1114. setDataField("isAnchored", id, frame->isAnchored);
  1115. if (frame->child1)
  1116. {
  1117. generateFrameFields(frame->child1);
  1118. }
  1119. if (frame->child2)
  1120. {
  1121. generateFrameFields(frame->child2);
  1122. }
  1123. }
  1124. void GuiFrameSetCtrl::setDataField(const char* tag, const U32 id, const U32 value)
  1125. {
  1126. char idBuffer[16];
  1127. char valueBuffer[16];
  1128. StringTableEntry tagFieldName = StringTable->insert(tag);
  1129. dSprintf(idBuffer, 16, "%d", id);
  1130. dSprintf(valueBuffer, 16, "%d", value);
  1131. SimObject::setDataField(tagFieldName, idBuffer, valueBuffer);
  1132. }
  1133. const char* GuiFrameSetCtrl::getDataField(const char* tag, const U32 id)
  1134. {
  1135. char idBuffer[16];
  1136. StringTableEntry tagFieldName = StringTable->insert(tag);
  1137. dSprintf(idBuffer, 16, "%d", id);
  1138. return SimObject::getDataField(tagFieldName, idBuffer);
  1139. }