PageRenderTime 35ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llui/lldockcontrol.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 378 lines | 287 code | 49 blank | 42 comment | 55 complexity | f7c272215b63bbe6fd53e3089a7a54d1 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lldockcontrol.cpp
  3. * @brief Creates a panel of a specific kind for a toast
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "lldockcontrol.h"
  28. #include "lldockablefloater.h"
  29. LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
  30. const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
  31. mDockWidget(dockWidget),
  32. mDockableFloater(dockableFloater),
  33. mDockTongue(dockTongue),
  34. mDockTongueX(0),
  35. mDockTongueY(0)
  36. {
  37. mDockAt = dockAt;
  38. if (dockableFloater->isDocked())
  39. {
  40. on();
  41. }
  42. else
  43. {
  44. off();
  45. }
  46. if (!(get_allowed_rect_callback))
  47. {
  48. mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
  49. }
  50. else
  51. {
  52. mGetAllowedRectCallback = get_allowed_rect_callback;
  53. }
  54. if (dockWidget != NULL)
  55. {
  56. repositionDockable();
  57. }
  58. if (mDockWidget != NULL)
  59. {
  60. mDockWidgetVisible = isDockVisible();
  61. }
  62. else
  63. {
  64. mDockWidgetVisible = false;
  65. }
  66. }
  67. LLDockControl::~LLDockControl()
  68. {
  69. }
  70. void LLDockControl::setDock(LLView* dockWidget)
  71. {
  72. mDockWidget = dockWidget;
  73. if (mDockWidget != NULL)
  74. {
  75. repositionDockable();
  76. mDockWidgetVisible = isDockVisible();
  77. }
  78. else
  79. {
  80. mDockWidgetVisible = false;
  81. }
  82. }
  83. void LLDockControl::getAllowedRect(LLRect& rect)
  84. {
  85. rect = mDockableFloater->getRootView()->getChild<LLView>("non_toolbar_panel")->getRect();
  86. }
  87. void LLDockControl::repositionDockable()
  88. {
  89. if (!mDockWidget) return;
  90. LLRect dockRect = mDockWidget->calcScreenRect();
  91. LLRect rootRect;
  92. LLRect floater_rect = mDockableFloater->calcScreenRect();
  93. mGetAllowedRectCallback(rootRect);
  94. // recalculate dockable position if:
  95. if (mPrevDockRect != dockRect //dock position changed
  96. || mDockWidgetVisible != isDockVisible() //dock visibility changed
  97. || mRootRect != rootRect //root view rect changed
  98. || mFloaterRect != floater_rect //floater rect changed
  99. || mRecalculateDockablePosition //recalculation is forced
  100. )
  101. {
  102. // undock dockable and off() if dock not visible
  103. if (!isDockVisible())
  104. {
  105. mDockableFloater->setDocked(false);
  106. // force off() since dockable may not have dockControll at this time
  107. off();
  108. LLDockableFloater* dockable_floater =
  109. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  110. if(dockable_floater != NULL)
  111. {
  112. dockable_floater->onDockHidden();
  113. }
  114. }
  115. else
  116. {
  117. if(mEnabled)
  118. {
  119. moveDockable();
  120. }
  121. LLDockableFloater* dockable_floater =
  122. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  123. if(dockable_floater != NULL)
  124. {
  125. dockable_floater->onDockShown();
  126. }
  127. }
  128. mPrevDockRect = dockRect;
  129. mRootRect = rootRect;
  130. mFloaterRect = floater_rect;
  131. mRecalculateDockablePosition = false;
  132. mDockWidgetVisible = isDockVisible();
  133. }
  134. }
  135. bool LLDockControl::isDockVisible()
  136. {
  137. bool res = true;
  138. if (mDockWidget != NULL)
  139. {
  140. //we should check all hierarchy
  141. res = mDockWidget->isInVisibleChain();
  142. if (res)
  143. {
  144. LLRect dockRect = mDockWidget->calcScreenRect();
  145. switch (mDockAt)
  146. {
  147. case LEFT: // to keep compiler happy
  148. break;
  149. case BOTTOM:
  150. case TOP:
  151. {
  152. // check is dock inside parent rect
  153. // assume that parent for all dockable floaters
  154. // is the root view
  155. LLRect dockParentRect =
  156. mDockWidget->getRootView()->calcScreenRect();
  157. if (dockRect.mRight <= dockParentRect.mLeft
  158. || dockRect.mLeft >= dockParentRect.mRight)
  159. {
  160. res = false;
  161. }
  162. break;
  163. }
  164. default:
  165. break;
  166. }
  167. }
  168. }
  169. return res;
  170. }
  171. void LLDockControl::moveDockable()
  172. {
  173. // calculate new dockable position
  174. LLRect dockRect = mDockWidget->calcScreenRect();
  175. LLRect rootRect;
  176. mGetAllowedRectCallback(rootRect);
  177. bool use_tongue = false;
  178. LLDockableFloater* dockable_floater =
  179. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  180. if (dockable_floater != NULL)
  181. {
  182. use_tongue = dockable_floater->getUseTongue();
  183. }
  184. LLRect dockableRect = mDockableFloater->calcScreenRect();
  185. S32 x = 0;
  186. S32 y = 0;
  187. LLRect dockParentRect;
  188. switch (mDockAt)
  189. {
  190. case LEFT:
  191. x = dockRect.mLeft - dockableRect.getWidth();
  192. y = dockRect.getCenterY() + dockableRect.getHeight() / 2;
  193. if (use_tongue)
  194. {
  195. x -= mDockTongue->getWidth();
  196. }
  197. mDockTongueX = dockableRect.mRight;
  198. mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2;
  199. break;
  200. case RIGHT:
  201. x = dockRect.mRight;
  202. y = dockRect.getCenterY() + dockableRect.getHeight() / 2;
  203. if (use_tongue)
  204. {
  205. x += mDockTongue->getWidth();
  206. }
  207. mDockTongueX = dockRect.mRight;
  208. mDockTongueY = dockableRect.getCenterY() - mDockTongue->getHeight() / 2;
  209. break;
  210. case TOP:
  211. x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
  212. y = dockRect.mTop + dockableRect.getHeight();
  213. // unique docking used with dock tongue, so add tongue height to the Y coordinate
  214. if (use_tongue)
  215. {
  216. y += mDockTongue->getHeight();
  217. if ( y > rootRect.mTop)
  218. {
  219. y = rootRect.mTop;
  220. }
  221. }
  222. // check is dockable inside root view rect
  223. if (x < rootRect.mLeft)
  224. {
  225. x = rootRect.mLeft;
  226. }
  227. if (x + dockableRect.getWidth() > rootRect.mRight)
  228. {
  229. x = rootRect.mRight - dockableRect.getWidth();
  230. }
  231. // calculate dock tongue position
  232. dockParentRect = mDockWidget->getParent()->calcScreenRect();
  233. if (dockRect.getCenterX() < dockParentRect.mLeft)
  234. {
  235. mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
  236. }
  237. else if (dockRect.getCenterX() > dockParentRect.mRight)
  238. {
  239. mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
  240. }
  241. else
  242. {
  243. mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
  244. }
  245. mDockTongueY = dockRect.mTop;
  246. break;
  247. case BOTTOM:
  248. x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
  249. y = dockRect.mBottom;
  250. // unique docking used with dock tongue, so add tongue height to the Y coordinate
  251. if (use_tongue)
  252. {
  253. y -= mDockTongue->getHeight();
  254. }
  255. // check is dockable inside root view rect
  256. if (x < rootRect.mLeft)
  257. {
  258. x = rootRect.mLeft;
  259. }
  260. if (x + dockableRect.getWidth() > rootRect.mRight)
  261. {
  262. x = rootRect.mRight - dockableRect.getWidth();
  263. }
  264. // calculate dock tongue position
  265. dockParentRect = mDockWidget->getParent()->calcScreenRect();
  266. if (dockRect.getCenterX() < dockParentRect.mLeft)
  267. {
  268. mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
  269. }
  270. else if (dockRect.getCenterX() > dockParentRect.mRight)
  271. {
  272. mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
  273. }
  274. else
  275. {
  276. mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
  277. }
  278. mDockTongueY = dockRect.mBottom - mDockTongue->getHeight();
  279. break;
  280. }
  281. S32 max_available_height = rootRect.getHeight() - (rootRect.mBottom - mDockTongueY) - mDockTongue->getHeight();
  282. // A floater should be shrunk so it doesn't cover a part of its docking tongue and
  283. // there is a space between a dockable floater and a control to which it is docked.
  284. if (use_tongue && dockableRect.getHeight() >= max_available_height)
  285. {
  286. dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), max_available_height);
  287. mDockableFloater->reshape(dockableRect.getWidth(), dockableRect.getHeight());
  288. }
  289. else
  290. {
  291. // move dockable
  292. dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
  293. dockableRect.getHeight());
  294. }
  295. LLRect localDocableParentRect;
  296. mDockableFloater->getParent()->screenRectToLocal(dockableRect, &localDocableParentRect);
  297. mDockableFloater->setRect(localDocableParentRect);
  298. mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, &mDockTongueX, &mDockTongueY);
  299. }
  300. void LLDockControl::on()
  301. {
  302. if (isDockVisible())
  303. {
  304. mEnabled = true;
  305. mRecalculateDockablePosition = true;
  306. }
  307. }
  308. void LLDockControl::off()
  309. {
  310. mEnabled = false;
  311. }
  312. void LLDockControl::forceRecalculatePosition()
  313. {
  314. mRecalculateDockablePosition = true;
  315. }
  316. void LLDockControl::drawToungue()
  317. {
  318. bool use_tongue = false;
  319. LLDockableFloater* dockable_floater =
  320. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  321. if (dockable_floater != NULL)
  322. {
  323. use_tongue = dockable_floater->getUseTongue();
  324. }
  325. if (mEnabled && use_tongue)
  326. {
  327. mDockTongue->draw(mDockTongueX, mDockTongueY);
  328. }
  329. }