2
0

guiGridCtrl.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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/guiGridCtrl.h"
  23. //------------------------------------------------------------------------------
  24. IMPLEMENT_CONOBJECT(GuiGridControl);
  25. //------------------------------------------------------------------------------
  26. GuiGridControl::GuiGridControl()
  27. {
  28. mIsContainer = true;
  29. }
  30. //------------------------------------------------------------------------------
  31. void GuiGridControl::initPersistFields()
  32. {
  33. Parent::initPersistFields();
  34. addField("Rows", TypeStringTableEntryVector, Offset(mGridRows, GuiGridControl), "Number of rows in the grid");
  35. addField("Columns", TypeStringTableEntryVector, Offset(mGridCols, GuiGridControl), "Number of columns in the grid");
  36. }
  37. //------------------------------------------------------------------------------
  38. bool GuiGridControl::onWake()
  39. {
  40. if (!Parent::onWake())
  41. return false;
  42. return true;
  43. }
  44. //------------------------------------------------------------------------------
  45. void GuiGridControl::onSleep()
  46. {
  47. Parent::onSleep();
  48. }
  49. //------------------------------------------------------------------------------
  50. void GuiGridControl::inspectPostApply()
  51. {
  52. resize(getPosition(), getExtent());
  53. }
  54. //------------------------------------------------------------------------------
  55. bool GuiGridControl::IsPointInGridControl(GuiControl* ctrl, const Point2I& pt)
  56. {
  57. if (mRowSizes.size() > 0 && mColSizes.size() > 0)
  58. {
  59. RectI gridRect = GetGridRect(ctrl);
  60. RectI ctrlRect = ctrl->getBounds();
  61. Point2I chkPt = gridRect.point + ctrlRect.point;
  62. Point2I chkBound = chkPt + ctrlRect.extent;
  63. if (pt.x >= chkPt.x && pt.x <= chkBound.x && pt.y >= chkPt.y && pt.y <= chkBound.y)
  64. return true;
  65. else
  66. return false;
  67. }
  68. else
  69. {
  70. return false;
  71. }
  72. }
  73. //------------------------------------------------------------------------------
  74. void GuiGridControl::addObject(SimObject *obj)
  75. {
  76. if (mRowSizes.size() <= 0 && mRowSizes.size() <= 0)
  77. AdjustGrid(mBounds.extent);
  78. GuiControl *ctrl = static_cast<GuiControl *>(obj);
  79. if (ctrl)
  80. {
  81. RectI ctrlRect = GetGridRect(ctrl);
  82. if (ctrl->getExtent().isZero())
  83. {
  84. ctrl->setExtent(ctrlRect.extent);
  85. }
  86. else
  87. {
  88. if (ctrl->mBounds.extent.x > ctrlRect.extent.x)
  89. ctrl->mBounds.extent.x = ctrlRect.extent.x;
  90. if (ctrl->mBounds.extent.y > ctrlRect.extent.y)
  91. ctrl->mBounds.extent.y = ctrlRect.extent.y;
  92. }
  93. Point2I pt = ctrl->getPosition();
  94. mOrginalControlPos.push_back(pt);
  95. pt += ctrlRect.point;
  96. ctrl->setPosition(pt);
  97. }
  98. Parent::addObject(obj);
  99. }
  100. //------------------------------------------------------------------------------
  101. void GuiGridControl::removeObject(SimObject *obj)
  102. {
  103. for(int idx =0; idx < objectList.size();idx++)
  104. {
  105. if ( objectList[idx] == obj )
  106. {
  107. mOrginalControlPos.erase(idx);
  108. break;
  109. }
  110. }
  111. Parent::removeObject(obj);
  112. }
  113. //------------------------------------------------------------------------------
  114. void GuiGridControl::resize(const Point2I &newPosition, const Point2I &newExtent)
  115. {
  116. setUpdate();
  117. Point2I actualNewExtent = Point2I( getMax(mMinExtent.x, newExtent.x), getMax(mMinExtent.y, newExtent.y));
  118. mBounds.set(newPosition, actualNewExtent);
  119. bool bFirstResize = false;
  120. iterator i;
  121. Vector<Point2I> oldCtrlExtent;
  122. if (mRowSizes.size() == 0 && mColSizes.size() == 0)
  123. {
  124. bFirstResize = true;
  125. }
  126. else
  127. {
  128. for(i = begin(); i != end(); i++)
  129. {
  130. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  131. if (ctrl)
  132. {
  133. RectI newRect = GetGridRect(ctrl);
  134. oldCtrlExtent.push_back(newRect.extent);
  135. }
  136. }
  137. }
  138. AdjustGrid(mBounds.extent);
  139. //resize and position all child controls.
  140. int idx = 0;
  141. for(i = begin(); i != end(); i++)
  142. {
  143. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  144. if (ctrl)
  145. {
  146. RectI newRect = GetGridRect(ctrl);
  147. if (ctrl->getExtent().x == 0 && ctrl->getExtent().y == 0)
  148. ctrl->setExtent(newRect.extent);
  149. ctrl->setPosition(mOrginalControlPos[idx] + newRect.point);
  150. if (bFirstResize)
  151. {
  152. ctrl->parentResized(newRect.extent, newRect.extent);
  153. }
  154. else
  155. {
  156. ctrl->parentResized(oldCtrlExtent[idx++], newRect.extent);
  157. }
  158. }
  159. }
  160. GuiControl *parent = getParent();
  161. if (parent)
  162. parent->childResized(this);
  163. setUpdate();
  164. }
  165. //------------------------------------------------------------------------------
  166. RectI GuiGridControl::GetGridRect(GuiControl* ctrl)
  167. {
  168. S32 col = dAtoi(ctrl->getDataField( StringTable->insert("Col"), NULL));
  169. S32 row = dAtoi(ctrl->getDataField( StringTable->insert("Row"), NULL));
  170. S32 colSpan = dAtoi(ctrl->getDataField( StringTable->insert("ColSpan"), NULL));
  171. S32 rowSpan = dAtoi(ctrl->getDataField( StringTable->insert("RowSpan"), NULL));
  172. AssertFatal (col < mColSizes.size(), "Col is out of bounds");
  173. AssertFatal (row < mRowSizes.size(), "Row is out of bounds");
  174. if (colSpan < 1)
  175. colSpan = 1;
  176. if (rowSpan < 1)
  177. rowSpan = 1;
  178. RectI newRect(0,0,0,0);
  179. for(int i = 0; i < col; i++)
  180. {
  181. newRect.point.x += mColSizes[i];
  182. }
  183. for(int i =col; i < col+colSpan; i++)
  184. {
  185. newRect.extent.x += mColSizes[i];
  186. }
  187. for(int i = 0; i < row; i++)
  188. {
  189. newRect.point.y += mRowSizes[i];
  190. }
  191. for(int i =row; i < row+rowSpan; i++)
  192. {
  193. newRect.extent.y += mRowSizes[i];
  194. }
  195. return newRect;
  196. }
  197. //------------------------------------------------------------------------------
  198. void GuiGridControl::AdjustGrid(const Point2I& newExtent)
  199. {
  200. mColSizes.clear();
  201. mRowSizes.clear();
  202. AdjustGridItems(newExtent.x, mGridCols, mColSizes);
  203. AdjustGridItems(newExtent.y, mGridRows, mRowSizes);
  204. }
  205. //------------------------------------------------------------------------------
  206. void GuiGridControl::AdjustGridItems(S32 size, Vector<StringTableEntry>& strItems, Vector<S32>& items)
  207. {
  208. Vector<GridItem> GridItems;
  209. S32 bFoundStar;
  210. bFoundStar = false;
  211. S32 IndexRemaining = -1;
  212. S32 totalSize = 0;
  213. S32 idx =0;
  214. //First step : Convert the string based column data into a GridItem vector.
  215. for(Vector<char const*>::iterator col = strItems.begin(); col != strItems.end(); ++col, idx++)
  216. {
  217. StringTableEntry str = *col;
  218. int len = dStrlen(str);
  219. AssertFatal(len >= 1, "Item can not be blank.");
  220. //we support three types of values (absolute size in pixels, percentage based, and remaining size in pixels).
  221. if (str[0] == '*') // use the remaining space left in the columns.
  222. {
  223. AssertFatal(!bFoundStar, "Can only use one * item field");
  224. GridItem gi;
  225. gi.IsAbsolute = false;
  226. gi.IsPercentage = false;
  227. gi.IsRemaining = true;
  228. gi.Size = 0;
  229. GridItems.push_back(gi);
  230. }
  231. else if ( len > 1 && str[len-1] == '%' ) //percentage based
  232. {
  233. char* tmp = new char[len-1];
  234. dStrncpy(tmp, str, len-1);
  235. int perc = dAtoi(tmp);
  236. delete tmp;
  237. GridItem gi;
  238. gi.IsAbsolute = false;
  239. gi.IsPercentage = true;
  240. gi.IsRemaining = false;
  241. gi.Size = perc;
  242. GridItems.push_back(gi);
  243. }
  244. else //standard absolute pixel based
  245. {
  246. int px = dAtoi(str);
  247. GridItem gi;
  248. gi.IsAbsolute = true;
  249. gi.IsPercentage = false;
  250. gi.IsRemaining = false;
  251. gi.Size = px;
  252. GridItems.push_back(gi);
  253. totalSize += px;
  254. }
  255. }
  256. //step two: iterate the grid columns again, and fill in any percentage based sizing, and setup the correct grid array.
  257. int remainingSize = size - totalSize;
  258. int sizeForPerc = remainingSize;
  259. for(int i = 0; i < GridItems.size(); ++i)
  260. {
  261. GridItem gi = GridItems[i];
  262. if (gi.IsAbsolute)
  263. {
  264. items.push_back(gi.Size);
  265. }
  266. else if (gi.IsPercentage)
  267. {
  268. F32 perc = gi.Size / 100.0f;
  269. S32 realSize = sizeForPerc * (S32)perc;
  270. remainingSize -= realSize;
  271. items.push_back(realSize);
  272. }
  273. else if(gi.IsRemaining)
  274. {
  275. //place holder for the moment.
  276. items.push_back(0);
  277. IndexRemaining = i;
  278. }
  279. }
  280. if (IndexRemaining >= 0)
  281. {
  282. items[IndexRemaining] = remainingSize;
  283. remainingSize = 0;
  284. }
  285. }