guiArrayCtrl.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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/console.h"
  23. #include "graphics/dgl.h"
  24. #include "platform/event.h"
  25. #include "gui/containers/guiScrollCtrl.h"
  26. #include "gui/guiArrayCtrl.h"
  27. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  28. GuiArrayCtrl::GuiArrayCtrl()
  29. {
  30. mActive = true;
  31. mCellSize.set(80, 30);
  32. mSize = Point2I(5, 30);
  33. mSelectedCell.set(-1, -1);
  34. mMouseOverCell.set(-1, -1);
  35. mIsContainer = true;
  36. }
  37. bool GuiArrayCtrl::onWake()
  38. {
  39. if (! Parent::onWake())
  40. return false;
  41. //get the font
  42. mFont = mProfile->getFont(mFontSizeAdjust);
  43. return true;
  44. }
  45. void GuiArrayCtrl::onSleep()
  46. {
  47. Parent::onSleep();
  48. mFont = NULL;
  49. }
  50. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  51. void GuiArrayCtrl::setSize(Point2I newSize)
  52. {
  53. mSize = newSize;
  54. Point2I newExtent(newSize.x * mCellSize.x, newSize.y * mCellSize.y);
  55. resize(mBounds.point, newExtent);
  56. }
  57. void GuiArrayCtrl::getScrollDimensions(S32 &cell_size, S32 &num_cells)
  58. {
  59. cell_size = mCellSize.y;
  60. num_cells = mSize.y;
  61. }
  62. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  63. bool GuiArrayCtrl::cellSelected(Point2I cell)
  64. {
  65. if (cell.x < 0 || cell.x >= mSize.x || cell.y < 0 || cell.y >= mSize.y)
  66. {
  67. mSelectedCell = Point2I(-1,-1);
  68. return false;
  69. }
  70. mSelectedCell = cell;
  71. scrollSelectionVisible();
  72. onCellSelected(cell);
  73. setUpdate();
  74. return true;
  75. }
  76. void GuiArrayCtrl::onCellSelected(Point2I cell)
  77. {
  78. Con::executef(this, 3, "onSelect", Con::getFloatArg(cell.x), Con::getFloatArg(cell.y));
  79. //call the console function
  80. execConsoleCallback();
  81. }
  82. // Called when a cell is highlighted
  83. void GuiArrayCtrl::onCellHighlighted(Point2I cell)
  84. {
  85. // Do nothing
  86. }
  87. void GuiArrayCtrl::setSelectedCell(Point2I cell)
  88. {
  89. cellSelected(cell);
  90. }
  91. Point2I GuiArrayCtrl::getSelectedCell()
  92. {
  93. return mSelectedCell;
  94. }
  95. void GuiArrayCtrl::scrollSelectionVisible()
  96. {
  97. scrollCellVisible(mSelectedCell);
  98. }
  99. void GuiArrayCtrl::scrollCellVisible(Point2I cell)
  100. {
  101. //make sure we have a parent
  102. //make sure we have a valid cell selected
  103. GuiScrollCtrl *parent = dynamic_cast<GuiScrollCtrl*>(getParent());
  104. if(!parent || cell.x < 0 || cell.y < 0)
  105. return;
  106. RectI cellBounds(cell.x * mCellSize.x, cell.y * mCellSize.y, mCellSize.x, mCellSize.y);
  107. parent->scrollRectVisible(cellBounds);
  108. }
  109. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  110. void GuiArrayCtrl::onRender(Point2I offset, const RectI &updateRect)
  111. {
  112. //make sure we have a parent
  113. GuiControl *parent = getParent();
  114. if (! parent)
  115. return;
  116. S32 i, j;
  117. RectI headerClip;
  118. RectI clipRect = dglGetClipRect();
  119. Point2I parentOffset = parent->localToGlobalCoord(Point2I(0, 0));
  120. //save the original for clipping the row headers
  121. RectI origClipRect = clipRect;
  122. for (j = 0; j < mSize.y; j++)
  123. {
  124. //skip until we get to a visible row
  125. if ((j + 1) * mCellSize.y + offset.y < updateRect.point.y)
  126. continue;
  127. //break once we've reached the last visible row
  128. if(j * mCellSize.y + offset.y >= updateRect.point.y + updateRect.extent.y)
  129. break;
  130. //render the cells for the row
  131. for (i = 0; i < mSize.x; i++)
  132. {
  133. //skip past columns off the left edge
  134. if ((i + 1) * mCellSize.x + offset.x < updateRect.point.x)
  135. continue;
  136. //break once past the last visible column
  137. if (i * mCellSize.x + offset.x >= updateRect.point.x + updateRect.extent.x)
  138. break;
  139. S32 cellx = offset.x + i * mCellSize.x;
  140. S32 celly = offset.y + j * mCellSize.y;
  141. RectI cellClip(cellx, celly, mCellSize.x, mCellSize.y);
  142. //make sure the cell is within the update region
  143. if (cellClip.intersect(clipRect))
  144. {
  145. //set the clip rect
  146. dglSetClipRect(cellClip);
  147. //render the cell
  148. onRenderCell(Point2I(cellx, celly), Point2I(i, j),
  149. i == mSelectedCell.x && j == mSelectedCell.y,
  150. i == mMouseOverCell.x && j == mMouseOverCell.y);
  151. }
  152. }
  153. }
  154. }
  155. void GuiArrayCtrl::onTouchDown(const GuiEvent &event)
  156. {
  157. if ( !mActive || !mAwake || !mVisible )
  158. return;
  159. //let the guiControl method take care of the rest
  160. Parent::onTouchDown(event);
  161. Point2I pt = globalToLocalCoord(event.mousePoint);
  162. Point2I cell(
  163. (pt.x < 0 ? -1 : pt.x / mCellSize.x),
  164. (pt.y < 0 ? -1 : pt.y / mCellSize.y)
  165. );
  166. if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
  167. {
  168. //store the previously selected cell
  169. Point2I prevSelected = mSelectedCell;
  170. //select the new cell
  171. cellSelected(Point2I(cell.x, cell.y));
  172. //if we double clicked on the *same* cell, evaluate the altConsole Command
  173. if ( ( event.mouseClickCount > 1 ) && ( prevSelected == mSelectedCell ) && mAltConsoleCommand[0] )
  174. Con::evaluate( mAltConsoleCommand, false );
  175. }
  176. }
  177. void GuiArrayCtrl::onTouchEnter(const GuiEvent &event)
  178. {
  179. Point2I pt = globalToLocalCoord(event.mousePoint);
  180. //get the cell
  181. Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
  182. if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
  183. {
  184. mMouseOverCell = cell;
  185. setUpdateRegion(Point2I(cell.x * mCellSize.x, cell.y * mCellSize.y), mCellSize );
  186. onCellHighlighted(mMouseOverCell);
  187. }
  188. }
  189. void GuiArrayCtrl::onTouchLeave(const GuiEvent & /*event*/)
  190. {
  191. setUpdateRegion(Point2I(mMouseOverCell.x * mCellSize.x, mMouseOverCell.y * mCellSize.y), mCellSize);
  192. mMouseOverCell.set(-1,-1);
  193. onCellHighlighted(mMouseOverCell);
  194. }
  195. void GuiArrayCtrl::onTouchDragged(const GuiEvent &event)
  196. {
  197. // for the array control, the behaviour of onMouseDragged is the same
  198. // as on mouse moved - basically just recalc the currend mouse over cell
  199. // and set the update regions if necessary
  200. GuiArrayCtrl::onTouchMove(event);
  201. }
  202. void GuiArrayCtrl::onTouchMove(const GuiEvent &event)
  203. {
  204. Point2I pt = globalToLocalCoord(event.mousePoint);
  205. Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
  206. if (cell.x != mMouseOverCell.x || cell.y != mMouseOverCell.y)
  207. {
  208. if (mMouseOverCell.x != -1)
  209. {
  210. setUpdateRegion(Point2I(mMouseOverCell.x * mCellSize.x, mMouseOverCell.y * mCellSize.y), mCellSize);
  211. }
  212. if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
  213. {
  214. setUpdateRegion(Point2I(cell.x * mCellSize.x, cell.y * mCellSize.y), mCellSize);
  215. mMouseOverCell = cell;
  216. }
  217. else
  218. mMouseOverCell.set(-1,-1);
  219. }
  220. onCellHighlighted(mMouseOverCell);
  221. }
  222. bool GuiArrayCtrl::onKeyDown(const GuiEvent &event)
  223. {
  224. //if this control is a dead end, kill the event
  225. if ((! mVisible) || (! mActive) || (! mAwake)) return true;
  226. //get the parent
  227. S32 pageSize = 1;
  228. GuiControl *parent = getParent();
  229. if (parent && mCellSize.y > 0)
  230. {
  231. pageSize = getMax(1, (parent->mBounds.extent.y / mCellSize.y) - 1);
  232. }
  233. Point2I delta(0,0);
  234. switch (event.keyCode)
  235. {
  236. case KEY_LEFT:
  237. delta.set(-1, 0);
  238. break;
  239. case KEY_RIGHT:
  240. delta.set(1, 0);
  241. break;
  242. case KEY_UP:
  243. delta.set(0, -1);
  244. break;
  245. case KEY_DOWN:
  246. delta.set(0, 1);
  247. break;
  248. case KEY_PAGE_UP:
  249. delta.set(0, -pageSize);
  250. break;
  251. case KEY_PAGE_DOWN:
  252. delta.set(0, pageSize);
  253. break;
  254. case KEY_HOME:
  255. cellSelected( Point2I( 0, 0 ) );
  256. return( true );
  257. case KEY_END:
  258. cellSelected( Point2I( 0, mSize.y - 1 ) );
  259. return( true );
  260. default:
  261. return Parent::onKeyDown(event);
  262. }
  263. if (mSize.x < 1 || mSize.y < 1)
  264. return true;
  265. //select the first cell if no previous cell was selected
  266. if (mSelectedCell.x == -1 || mSelectedCell.y == -1)
  267. {
  268. cellSelected(Point2I(0,0));
  269. return true;
  270. }
  271. //select the cell
  272. Point2I cell = mSelectedCell;
  273. cell.x = getMax(0, getMin(mSize.x - 1, cell.x + delta.x));
  274. cell.y = getMax(0, getMin(mSize.y - 1, cell.y + delta.y));
  275. cellSelected(cell);
  276. return true;
  277. }
  278. void GuiArrayCtrl::onRightMouseDown(const GuiEvent &event)
  279. {
  280. if ( !mActive || !mAwake || !mVisible )
  281. return;
  282. Parent::onRightMouseDown( event );
  283. Point2I pt = globalToLocalCoord( event.mousePoint );
  284. Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
  285. if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
  286. {
  287. char buf[32];
  288. dSprintf( buf, sizeof( buf ), "%d %d", event.mousePoint.x, event.mousePoint.y );
  289. // Pass it to the console:
  290. Con::executef(this, 4, "onRightMouseDown", Con::getIntArg(cell.x), Con::getIntArg(cell.y), buf);
  291. }
  292. }