guiPaneCtrl.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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/guiPaneCtrl.h"
  23. IMPLEMENT_CONOBJECT(GuiPaneControl);
  24. GuiPaneControl::GuiPaneControl()
  25. {
  26. mMinExtent.set(10, 10);
  27. mActive = true;
  28. mCollapsable = true;
  29. mCollapsed = false;
  30. mBarBehindText = true;
  31. mMouseOver = false;
  32. mDepressed = false;
  33. mOriginalExtents.set(10,10);
  34. mCaption = StringTable->insert("A Pane");
  35. mCaptionID = StringTable->EmptyString;
  36. mIsContainer = true;
  37. }
  38. void GuiPaneControl::initPersistFields()
  39. {
  40. Parent::initPersistFields();
  41. addField("caption", TypeString, Offset(mCaption, GuiPaneControl));
  42. addField("captionID", TypeString, Offset(mCaptionID, GuiPaneControl));
  43. addField("collapsable", TypeBool, Offset(mCollapsable, GuiPaneControl));
  44. addField("barBehindText", TypeBool, Offset(mBarBehindText, GuiPaneControl));
  45. }
  46. bool GuiPaneControl::onWake()
  47. {
  48. if ( !Parent::onWake() )
  49. return false;
  50. mFont = mProfile->mFont;
  51. AssertFatal(mFont, "GuiPaneControl::onWake: invalid font in profile" );
  52. if(mCaptionID && *mCaptionID != 0)
  53. {
  54. setCaptionID(mCaptionID);
  55. }
  56. mProfile->constructBitmapArray();
  57. if(mProfile->mBitmapArrayRects.size())
  58. {
  59. mThumbSize.set( mProfile->mBitmapArrayRects[0].extent.x, mProfile->mBitmapArrayRects[0].extent.y );
  60. mThumbSize.setMax( mProfile->mBitmapArrayRects[1].extent );
  61. if(mFont->getHeight() > (U32)mThumbSize.y)
  62. mThumbSize.y = mFont->getHeight();
  63. }
  64. else
  65. {
  66. mThumbSize.set(20, 20);
  67. }
  68. return true;
  69. }
  70. void GuiPaneControl::onSleep()
  71. {
  72. Parent::onSleep();
  73. mFont = NULL;
  74. }
  75. void GuiPaneControl::setCaptionID(const char *id)
  76. {
  77. S32 n = Con::getIntVariable(id, -1);
  78. if(n != -1)
  79. {
  80. mCaptionID = StringTable->insert(id);
  81. setCaptionID(n);
  82. }
  83. }
  84. void GuiPaneControl::setCaptionID(S32 id)
  85. {
  86. const UTF8 *str = getGUIString(id);
  87. if(str)
  88. mCaption = StringTable->insert((const char*)str);
  89. }
  90. void GuiPaneControl::resize(const Point2I &newPosition, const Point2I &newExtent)
  91. {
  92. //call set update both before and after
  93. setUpdate();
  94. Point2I actualNewExtent = Point2I(getMax(mMinExtent.x, newExtent.x),
  95. getMax(mMinExtent.y, newExtent.y));
  96. mBounds.set(newPosition, actualNewExtent);
  97. mOriginalExtents.x = actualNewExtent.x;
  98. GuiControl *parent = getParent();
  99. if (parent)
  100. parent->childResized(this);
  101. setUpdate();
  102. // Resize the child control if we're not collapsed
  103. if(size() && !mCollapsed)
  104. {
  105. GuiControl *gc = dynamic_cast<GuiControl*>(operator[](0));
  106. if(gc)
  107. {
  108. Point2I offset(0, mThumbSize.y);
  109. gc->resize(offset, newExtent - offset);
  110. }
  111. }
  112. }
  113. void GuiPaneControl::onRender(Point2I offset, const RectI &updateRect)
  114. {
  115. // Render our awesome little doogong
  116. if(mProfile->mBitmapArrayRects.size() >= 2 && mCollapsable)
  117. {
  118. S32 idx = mCollapsed ? 0 : 1;
  119. dglClearBitmapModulation();
  120. dglDrawBitmapStretchSR(
  121. mProfile->mTextureHandle,
  122. RectI(offset, mProfile->mBitmapArrayRects[idx].extent),
  123. mProfile->mBitmapArrayRects[idx]
  124. );
  125. }
  126. S32 textWidth = 0;
  127. if(!mBarBehindText)
  128. {
  129. dglSetBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor));
  130. textWidth = dglDrawText(
  131. mFont,
  132. Point2I(mThumbSize.x, 0) + offset,
  133. mCaption,
  134. mProfile->mFontColors
  135. );
  136. }
  137. // Draw our little bar, too
  138. if(mProfile->mBitmapArrayRects.size() >= 5)
  139. {
  140. dglClearBitmapModulation();
  141. S32 barStart = mThumbSize.x + offset.x + textWidth;
  142. S32 barTop = mThumbSize.y/2 + offset.y - mProfile->mBitmapArrayRects[3].extent.y /2;
  143. Point2I barOffset(barStart, barTop);
  144. // Draw the start of the bar...
  145. dglDrawBitmapStretchSR(
  146. mProfile->mTextureHandle,
  147. RectI(barOffset, mProfile->mBitmapArrayRects[2].extent),
  148. mProfile->mBitmapArrayRects[2]
  149. );
  150. // Now draw the middle...
  151. barOffset.x += mProfile->mBitmapArrayRects[2].extent.x;
  152. S32 barMiddleSize = (getExtent().x - (barOffset.x - offset.x)) - mProfile->mBitmapArrayRects[4].extent.x;
  153. if(barMiddleSize>0)
  154. {
  155. // We have to do this inset to prevent nasty stretching artifacts
  156. RectI foo = mProfile->mBitmapArrayRects[3];
  157. foo.inset(1,0);
  158. dglDrawBitmapStretchSR(
  159. mProfile->mTextureHandle,
  160. RectI(barOffset, Point2I(barMiddleSize, mProfile->mBitmapArrayRects[3].extent.y)),
  161. foo
  162. );
  163. }
  164. // And the end
  165. barOffset.x += barMiddleSize;
  166. dglDrawBitmapStretchSR(
  167. mProfile->mTextureHandle,
  168. RectI(barOffset, mProfile->mBitmapArrayRects[4].extent),
  169. mProfile->mBitmapArrayRects[4]
  170. );
  171. }
  172. if(mBarBehindText)
  173. {
  174. dglSetBitmapModulation((mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor));
  175. dglDrawText(
  176. mFont,
  177. Point2I(mThumbSize.x, 0) + offset,
  178. mCaption,
  179. mProfile->mFontColors
  180. );
  181. }
  182. // Draw child controls if appropriate
  183. if(!mCollapsed)
  184. renderChildControls(offset, updateRect);
  185. }
  186. ConsoleMethod(GuiPaneControl, setCollapsed, void, 3, 3, "(bool collapsed) Sets the controls \"collapsed\" property\n"
  187. "@param collapsed True if the control is to be collapsed"
  188. "@return No return value.")
  189. {
  190. object->setCollapsed(dAtob(argv[2]));
  191. }
  192. void GuiPaneControl::setCollapsed(bool isCollapsed)
  193. {
  194. // Get the child
  195. if(size() == 0 || !mCollapsable) return;
  196. GuiControl *gc = dynamic_cast<GuiControl*>(operator[](0));
  197. if(mCollapsed && !isCollapsed)
  198. {
  199. mCollapsed = false;
  200. resize(getPosition(), mOriginalExtents);
  201. if(gc)
  202. gc->setVisible(true);
  203. }
  204. else if(!mCollapsed && isCollapsed)
  205. {
  206. mCollapsed = true;
  207. mOriginalExtents = getExtent();
  208. resize(getPosition(), Point2I(getExtent().x, mThumbSize.y));
  209. if(gc)
  210. gc->setVisible(false);
  211. }
  212. }
  213. void GuiPaneControl::onMouseMove(const GuiEvent &event)
  214. {
  215. Point2I localMove = globalToLocalCoord(event.mousePoint);
  216. // If we're clicking in the header then resize
  217. mMouseOver = (localMove.y < mThumbSize.y);
  218. if(isMouseLocked())
  219. mDepressed = mMouseOver;
  220. }
  221. void GuiPaneControl::onMouseEnter(const GuiEvent &event)
  222. {
  223. setUpdate();
  224. if(isMouseLocked())
  225. {
  226. mDepressed = true;
  227. mMouseOver = true;
  228. }
  229. else
  230. {
  231. mMouseOver = true;
  232. }
  233. }
  234. void GuiPaneControl::onMouseLeave(const GuiEvent &event)
  235. {
  236. setUpdate();
  237. if(isMouseLocked())
  238. mDepressed = false;
  239. mMouseOver = false;
  240. }
  241. void GuiPaneControl::onMouseDown(const GuiEvent &event)
  242. {
  243. if(!mCollapsable)
  244. return;
  245. Point2I localClick = globalToLocalCoord(event.mousePoint);
  246. // If we're clicking in the header then resize
  247. if(localClick.y < mThumbSize.y)
  248. {
  249. mouseLock();
  250. mDepressed = true;
  251. //update
  252. setUpdate();
  253. }
  254. }
  255. void GuiPaneControl::onMouseUp(const GuiEvent &event)
  256. {
  257. // Make sure we only get events we ought to be getting...
  258. if (! mActive)
  259. return;
  260. if(!mCollapsable)
  261. return;
  262. mouseUnlock();
  263. setUpdate();
  264. Point2I localClick = globalToLocalCoord(event.mousePoint);
  265. // If we're clicking in the header then resize
  266. if(localClick.y < mThumbSize.y && mDepressed)
  267. setCollapsed(!mCollapsed);
  268. }