2
0

guiStackCtrl.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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 "gui/containers/guiStackCtrl.h"
  23. IMPLEMENT_CONOBJECT(GuiStackControl);
  24. static EnumTable::Enums stackTypeEnum[] =
  25. {
  26. { GuiStackControl::stackingTypeVert, "Vertical" },
  27. { GuiStackControl::stackingTypeHoriz,"Horizontal" },
  28. { GuiStackControl::stackingTypeDyn,"Dynamic" }
  29. };
  30. static EnumTable gStackTypeTable(3, &stackTypeEnum[0]);
  31. static EnumTable::Enums stackHorizEnum[] =
  32. {
  33. { GuiStackControl::horizStackLeft, "Left to Right" },
  34. { GuiStackControl::horizStackRight,"Right to Left" }
  35. };
  36. static EnumTable gStackHorizSizingTable(2, &stackHorizEnum[0]);
  37. static EnumTable::Enums stackVertEnum[] =
  38. {
  39. { GuiStackControl::vertStackTop, "Top to Bottom" },
  40. { GuiStackControl::vertStackBottom,"Bottom to Top" }
  41. };
  42. static EnumTable gStackVertSizingTable(2, &stackVertEnum[0]);
  43. GuiStackControl::GuiStackControl()
  44. {
  45. mMinExtent.set(24, 24);
  46. mResizing = false;
  47. mStackingType = stackingTypeVert;
  48. mStackVertSizing = vertStackTop;
  49. mStackHorizSizing = horizStackLeft;
  50. mPadding = 0;
  51. mIsContainer = true;
  52. }
  53. void GuiStackControl::initPersistFields()
  54. {
  55. addGroup( "Stacking" );
  56. addField( "StackingType", TypeEnum, Offset(mStackingType, GuiStackControl), 1, &gStackTypeTable);
  57. addField( "HorizStacking", TypeEnum, Offset(mStackHorizSizing, GuiStackControl), 1, &gStackHorizSizingTable);
  58. addField( "VertStacking", TypeEnum, Offset(mStackVertSizing, GuiStackControl), 1, &gStackVertSizingTable);
  59. addField( "Padding", TypeS32, Offset(mPadding, GuiStackControl));
  60. endGroup( "Stacking" );
  61. Parent::initPersistFields();
  62. }
  63. ConsoleMethod( GuiStackControl, updateStack, void, 2, 2, "%stackCtrl.updateStack() - Restacks controls it owns")
  64. {
  65. object->updatePanes();
  66. }
  67. bool GuiStackControl::onWake()
  68. {
  69. if ( !Parent::onWake() )
  70. return false;
  71. updatePanes();
  72. return true;
  73. }
  74. void GuiStackControl::onSleep()
  75. {
  76. Parent::onSleep();
  77. }
  78. void GuiStackControl::updatePanes()
  79. {
  80. // Prevent recursion
  81. if(mResizing)
  82. return;
  83. // Set Resizing.
  84. mResizing = true;
  85. Point2I extent = getExtent();
  86. // Do we need to stack horizontally?
  87. if( ( extent.x > extent.y && mStackingType == stackingTypeDyn ) || mStackingType == stackingTypeHoriz )
  88. {
  89. switch( mStackHorizSizing )
  90. {
  91. case horizStackLeft:
  92. stackFromLeft();
  93. break;
  94. case horizStackRight:
  95. stackFromRight();
  96. break;
  97. }
  98. }
  99. // Or, vertically?
  100. else if( ( extent.y > extent.x && mStackingType == stackingTypeDyn ) || mStackingType == stackingTypeVert)
  101. {
  102. switch( mStackVertSizing )
  103. {
  104. case vertStackTop:
  105. stackFromTop();
  106. break;
  107. case vertStackBottom:
  108. stackFromBottom();
  109. break;
  110. }
  111. }
  112. // Clear Sizing Flag.
  113. mResizing = false;
  114. }
  115. void GuiStackControl::freeze(bool _shouldfreeze)
  116. {
  117. mResizing = _shouldfreeze;
  118. }
  119. void GuiStackControl::stackFromBottom()
  120. {
  121. // Store the sum of the heights of our controls.
  122. S32 totalHeight=0;
  123. Point2I curPos;
  124. // If we go from the bottom, things are basically the same...
  125. // except we have to assign positions in an arse backwards way
  126. // (literally :P)
  127. // Figure out how high everything is going to be...
  128. // Place each child...
  129. for( S32 i = 0; i < size(); i++ )
  130. {
  131. // Place control
  132. GuiControl * gc = dynamic_cast<GuiControl*>(operator [](i));
  133. if(gc && gc->isVisible() )
  134. {
  135. Point2I childExtent = gc->getExtent();
  136. totalHeight += childExtent.y;
  137. }
  138. }
  139. // Figure out where we're starting...
  140. curPos = getPosition();
  141. curPos.y += totalHeight;
  142. // Offset so the bottom control goes in the right place...
  143. GuiControl * gc = dynamic_cast<GuiControl*>(operator [](size()-1));
  144. if(gc)
  145. curPos.y -= gc->getExtent().y;
  146. // Now work up from there!
  147. for(S32 i=size()-1; i>=0; i--)
  148. {
  149. // Place control
  150. GuiControl * gc = dynamic_cast<GuiControl*>(operator [](i));
  151. if(gc)
  152. {
  153. // We must place the child...
  154. // Make it have our width but keep its height
  155. Point2I childExtent = gc->getExtent();
  156. // Update our state...
  157. curPos.y -= childExtent.y - mPadding;
  158. // And resize...
  159. gc->resize(curPos - getPosition(), Point2I(getExtent().x, childExtent.y));
  160. }
  161. }
  162. }
  163. void GuiStackControl::stackFromTop()
  164. {
  165. // Store the sum of the heights of our controls.
  166. S32 totalHeight=0;
  167. Point2I curPos;
  168. // Position and resize everything...
  169. curPos = getPosition();
  170. // Place each child...
  171. for(S32 i=0; i<size(); i++)
  172. {
  173. // Place control
  174. GuiControl * gc = dynamic_cast<GuiControl*>(operator [](i));
  175. if(gc && gc->isVisible() )
  176. {
  177. // We must place the child...
  178. // Make it have our width but keep its height
  179. Point2I childExtent = gc->getExtent();
  180. gc->resize(curPos - getPosition(), Point2I(getExtent().x, childExtent.y));
  181. // Update our state...
  182. curPos.y += childExtent.y + mPadding;
  183. totalHeight += childExtent.y + mPadding;
  184. }
  185. }
  186. // Conform our size to the sum of the child sizes.
  187. if( totalHeight > getExtent().y )
  188. {
  189. curPos.x = getExtent().x;
  190. curPos.y = totalHeight;
  191. resize(getPosition(), curPos);
  192. }
  193. else if( totalHeight < getExtent().y )
  194. {
  195. curPos.x = getExtent().x;
  196. curPos.y = getMax( totalHeight , mMinExtent.y );
  197. resize(getPosition(), curPos);
  198. }
  199. }
  200. void GuiStackControl::stackFromLeft()
  201. {
  202. // Store the sum of the heights of our controls.
  203. S32 totalWidth=0;
  204. Point2I curPos;
  205. // Position and resize everything...
  206. curPos = getPosition();
  207. // Place each child...
  208. for(S32 i=0; i<size(); i++)
  209. {
  210. // Place control
  211. GuiControl * gc = dynamic_cast<GuiControl*>(operator [](i));
  212. if(gc && gc->isVisible() )
  213. {
  214. // We must place the child...
  215. // Make it have our width but keep its height
  216. Point2I childExtent = gc->getExtent();
  217. gc->resize(curPos - getPosition(), Point2I( childExtent.x,getExtent().y));
  218. // Update our state...
  219. curPos.x += childExtent.x + mPadding;
  220. totalWidth += childExtent.x + mPadding;
  221. }
  222. }
  223. // Conform our size to the sum of the child sizes.
  224. if( totalWidth > getExtent().x )
  225. {
  226. curPos.x = totalWidth;
  227. curPos.y = getExtent().y;
  228. resize(getPosition(), curPos);
  229. }
  230. }
  231. void GuiStackControl::stackFromRight()
  232. {
  233. }
  234. void GuiStackControl::resize(const Point2I &newPosition, const Point2I &newExtent)
  235. {
  236. //call set update both before and after
  237. setUpdate();
  238. Point2I actualNewExtent = Point2I( getMax(mMinExtent.x, newExtent.x),
  239. getMax(mMinExtent.y, newExtent.y));
  240. mBounds.set(newPosition, actualNewExtent);
  241. GuiControl *parent = getParent();
  242. if (parent)
  243. parent->childResized(this);
  244. setUpdate();
  245. updatePanes();
  246. }
  247. void GuiStackControl::addObject(SimObject *obj)
  248. {
  249. Parent::addObject(obj);
  250. updatePanes();
  251. }
  252. void GuiStackControl::removeObject(SimObject *obj)
  253. {
  254. Parent::removeObject(obj);
  255. updatePanes();
  256. }
  257. bool GuiStackControl::reOrder(SimObject* obj, SimObject* target)
  258. {
  259. bool ret = Parent::reOrder(obj, target);
  260. if (ret)
  261. updatePanes();
  262. return ret;
  263. }
  264. void GuiStackControl::childResized(GuiControl *child)
  265. {
  266. updatePanes();
  267. }