lldockcontrol.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:8k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lldockcontrol.cpp
  3.  * @brief Creates a panel of a specific kind for a toast
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "lldockcontrol.h"
  34. #include "lldockablefloater.h"
  35. LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
  36. const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
  37. mDockWidget(dockWidget),
  38. mDockableFloater(dockableFloater),
  39. mDockTongue(dockTongue),
  40. mDockTongueX(0),
  41. mDockTongueY(0)
  42. {
  43. mDockAt = dockAt;
  44. if (dockableFloater->isDocked())
  45. {
  46. on();
  47. }
  48. else
  49. {
  50. off();
  51. }
  52. if (!(get_allowed_rect_callback))
  53. {
  54. mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
  55. }
  56. else
  57. {
  58. mGetAllowedRectCallback = get_allowed_rect_callback;
  59. }
  60. if (dockWidget != NULL) 
  61. {
  62. repositionDockable();
  63. }
  64. if (mDockWidget != NULL)
  65. {
  66. mDockWidgetVisible = isDockVisible();
  67. }
  68. else
  69. {
  70. mDockWidgetVisible = false;
  71. }
  72. }
  73. LLDockControl::~LLDockControl()
  74. {
  75. }
  76. void LLDockControl::setDock(LLView* dockWidget)
  77. {
  78. mDockWidget = dockWidget;
  79. if (mDockWidget != NULL)
  80. {
  81. repositionDockable();
  82. mDockWidgetVisible = isDockVisible();
  83. }
  84. else
  85. {
  86. mDockWidgetVisible = false;
  87. }
  88. }
  89. void LLDockControl::getAllowedRect(LLRect& rect)
  90. {
  91. rect = mDockableFloater->getRootView()->getRect();
  92. }
  93. void LLDockControl::repositionDockable()
  94. {
  95. LLRect dockRect = mDockWidget->calcScreenRect();
  96. LLRect rootRect;
  97. mGetAllowedRectCallback(rootRect);
  98. // recalculate dockable position if dock position changed, dock visibility changed,
  99. // root view rect changed or recalculation is forced
  100. if (mPrevDockRect != dockRect  || mDockWidgetVisible != isDockVisible()
  101. || mRootRect != rootRect || mRecalculateDocablePosition)
  102. {
  103. // undock dockable and off() if dock not visible
  104. if (!isDockVisible())
  105. {
  106. mDockableFloater->setDocked(false);
  107. // force off() since dockable may not have dockControll at this time
  108. off();
  109. LLDockableFloater* dockable_floater =
  110. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  111. if(dockable_floater != NULL)
  112. {
  113. dockable_floater->onDockHidden();
  114. }
  115. }
  116. else
  117. {
  118. if(mEnabled)
  119. {
  120. moveDockable();
  121. }
  122. LLDockableFloater* dockable_floater =
  123. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  124. if(dockable_floater != NULL)
  125. {
  126. dockable_floater->onDockShown();
  127. }
  128. }
  129. mPrevDockRect = dockRect;
  130. mRootRect = rootRect;
  131. mRecalculateDocablePosition = 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. LLRect dockParentRect =
  154. mDockWidget->getParent()->calcScreenRect();
  155. if (dockRect.mRight <= dockParentRect.mLeft
  156. || dockRect.mLeft >= dockParentRect.mRight)
  157. {
  158. res = false;
  159. }
  160. break;
  161. }
  162. default:
  163. break;
  164. }
  165. }
  166. }
  167. return res;
  168. }
  169. void LLDockControl::moveDockable()
  170. {
  171. // calculate new dockable position
  172. LLRect dockRect = mDockWidget->calcScreenRect();
  173. LLRect rootRect;
  174. mGetAllowedRectCallback(rootRect);
  175. bool use_tongue = false;
  176. LLDockableFloater* dockable_floater =
  177. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  178. if (dockable_floater != NULL)
  179. {
  180. use_tongue = dockable_floater->getUseTongue();
  181. }
  182. LLRect dockableRect = mDockableFloater->calcScreenRect();
  183. S32 x = 0;
  184. S32 y = 0;
  185. LLRect dockParentRect;
  186. switch (mDockAt)
  187. {
  188. case LEFT:
  189. x = dockRect.mLeft;
  190. y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
  191. // check is dockable inside root view rect
  192. if (x < rootRect.mLeft)
  193. {
  194. x = rootRect.mLeft;
  195. }
  196. if (x + dockableRect.getWidth() > rootRect.mRight)
  197. {
  198. x = rootRect.mRight - dockableRect.getWidth();
  199. }
  200. mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;
  201. mDockTongueY = dockRect.mTop;
  202. break;
  203. case TOP:
  204. x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
  205. y = dockRect.mTop + dockableRect.getHeight();
  206. // unique docking used with dock tongue, so add tongue height o the Y coordinate
  207. if (use_tongue)
  208. {
  209. y += mDockTongue->getHeight();
  210. }
  211. // check is dockable inside root view rect
  212. if (x < rootRect.mLeft)
  213. {
  214. x = rootRect.mLeft;
  215. }
  216. if (x + dockableRect.getWidth() > rootRect.mRight)
  217. {
  218. x = rootRect.mRight - dockableRect.getWidth();
  219. }
  220. // calculate dock tongue position
  221. dockParentRect = mDockWidget->getParent()->calcScreenRect();
  222. if (dockRect.getCenterX() < dockParentRect.mLeft)
  223. {
  224. mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
  225. }
  226. else if (dockRect.getCenterX() > dockParentRect.mRight)
  227. {
  228. mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
  229. }
  230. else
  231. {
  232. mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
  233. }
  234. mDockTongueY = dockRect.mTop;
  235. break;
  236. case BOTTOM:
  237. x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
  238. y = dockRect.mBottom;
  239. // unique docking used with dock tongue, so add tongue height o the Y coordinate
  240. if (use_tongue)
  241. {
  242. y -= mDockTongue->getHeight();
  243. }
  244. // check is dockable inside root view rect
  245. if (x < rootRect.mLeft)
  246. {
  247. x = rootRect.mLeft;
  248. }
  249. if (x + dockableRect.getWidth() > rootRect.mRight)
  250. {
  251. x = rootRect.mRight - dockableRect.getWidth();
  252. }
  253. // calculate dock tongue position
  254. dockParentRect = mDockWidget->getParent()->calcScreenRect();
  255. if (dockRect.getCenterX() < dockParentRect.mLeft)
  256. {
  257. mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
  258. }
  259. else if (dockRect.getCenterX() > dockParentRect.mRight)
  260. {
  261. mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
  262. }
  263. else
  264. {
  265. mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
  266. }
  267. mDockTongueY = dockRect.mBottom - mDockTongue->getHeight();
  268. break;
  269. }
  270. // move dockable
  271. dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
  272. dockableRect.getHeight());
  273. LLRect localDocableParentRect;
  274. mDockableFloater->getParent()->screenRectToLocal(dockableRect,
  275. &localDocableParentRect);
  276. mDockableFloater->setRect(localDocableParentRect);
  277. mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
  278. &mDockTongueX, &mDockTongueY);
  279. }
  280. void LLDockControl::on()
  281. {
  282.  if (isDockVisible())
  283. {
  284. mEnabled = true;
  285. mRecalculateDocablePosition = true;
  286. }
  287. }
  288. void LLDockControl::off()
  289. {
  290. mEnabled = false;
  291. }
  292. void LLDockControl::forceRecalculatePosition()
  293. {
  294. mRecalculateDocablePosition = true;
  295. }
  296. void LLDockControl::drawToungue()
  297. {
  298. bool use_tongue = false;
  299. LLDockableFloater* dockable_floater =
  300. dynamic_cast<LLDockableFloater*> (mDockableFloater);
  301. if (dockable_floater != NULL)
  302. {
  303. use_tongue = dockable_floater->getUseTongue();
  304. }
  305. if (mEnabled && use_tongue)
  306. {
  307. mDockTongue->draw(mDockTongueX, mDockTongueY);
  308. }
  309. }