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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltooltip.cpp
  3.  * @brief LLToolTipMgr class implementation and related classes
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-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. // self include
  34. #include "lltooltip.h"
  35. // Library includes
  36. #include "lltextbox.h"
  37. #include "lliconctrl.h"
  38. #include "llbutton.h"
  39. #include "llmenugl.h"       // hideMenus()
  40. #include "llui.h" // positionViewNearMouse()
  41. #include "llwindow.h"
  42. #include "lltrans.h"
  43. //
  44. // Constants
  45. //
  46. //
  47. // Local globals
  48. //
  49. LLToolTipView *gToolTipView = NULL;
  50. //
  51. // Member functions
  52. //
  53. static LLDefaultChildRegistry::Register<LLToolTipView> register_tooltip_view("tooltip_view");
  54. LLToolTipView::Params::Params()
  55. {
  56. mouse_opaque = false;
  57. }
  58. LLToolTipView::LLToolTipView(const LLToolTipView::Params& p)
  59. : LLView(p)
  60. {
  61. }
  62. void LLToolTipView::draw()
  63. {
  64. LLToolTipMgr::instance().updateToolTipVisibility();
  65. // do the usual thing
  66. LLView::draw();
  67. }
  68. BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
  69. {
  70. static S32 last_x = x;
  71. static S32 last_y = y;
  72. LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance();
  73. if (x != last_x && y != last_y)
  74. {
  75. // allow new tooltips because mouse moved
  76. tooltip_mgr.unblockToolTips();
  77. }
  78. last_x = x;
  79. last_y = y;
  80. return LLView::handleHover(x, y, mask);
  81. }
  82. BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
  83. {
  84. LLToolTipMgr::instance().blockToolTips();
  85. if (LLView::handleMouseDown(x, y, mask))
  86. {
  87. // If we are handling the mouse event menu holder 
  88. // won't get a chance to close menus so do this here 
  89. LLMenuGL::sMenuContainer->hideMenus();
  90. return TRUE;
  91. }
  92. return FALSE;
  93. }
  94. BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
  95. {
  96. LLToolTipMgr::instance().blockToolTips();
  97. return LLView::handleMiddleMouseDown(x, y, mask);
  98. }
  99. BOOL LLToolTipView::handleRightMouseDown(S32 x, S32 y, MASK mask)
  100. {
  101. LLToolTipMgr::instance().blockToolTips();
  102. return LLView::handleRightMouseDown(x, y, mask);
  103. }
  104. BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks )
  105. {
  106. LLToolTipMgr::instance().blockToolTips();
  107. return FALSE;
  108. }
  109. void LLToolTipView::drawStickyRect()
  110. {
  111. gl_rect_2d(LLToolTipMgr::instance().getMouseNearRect(), LLColor4::white, false);
  112. }
  113. // defaults for floater param block pulled from widgets/floater.xml
  114. static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(&typeid(LLInspector::Params), "inspector");
  115. //
  116. // LLToolTip
  117. //
  118. static LLDefaultChildRegistry::Register<LLToolTip> register_tooltip("tool_tip");
  119. LLToolTip::Params::Params()
  120. : max_width("max_width", 200),
  121. padding("padding", 4),
  122. wrap("wrap", true),
  123. pos("pos"),
  124. message("message"),
  125. delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
  126. visible_time_over("visible_time_over", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeOver" )),
  127. visible_time_near("visible_time_near", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeNear" )),
  128. visible_time_far("visible_time_far", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeFar" )),
  129. sticky_rect("sticky_rect"),
  130. image("image"),
  131. text_color("text_color"),
  132. time_based_media("time_based_media", false),
  133. web_based_media("web_based_media", false),
  134. media_playing("media_playing", false)
  135. {
  136. chrome = true;
  137. }
  138. LLToolTip::LLToolTip(const LLToolTip::Params& p)
  139. : LLPanel(p),
  140. mHasClickCallback(p.click_callback.isProvided()),
  141. mPadding(p.padding),
  142. mTextBox(NULL),
  143. mInfoButton(NULL),
  144. mPlayMediaButton(NULL),
  145. mHomePageButton(NULL)
  146. {
  147. LLTextBox::Params params;
  148. params.name = params.initial_value().asString();
  149. // bake textbox padding into initial rect
  150. params.rect = LLRect (mPadding, mPadding + 1, mPadding + 1, mPadding);
  151. params.h_pad = 0;
  152. params.v_pad = 0;
  153. params.mouse_opaque = false;
  154. params.text_color = p.text_color;
  155. params.bg_visible = false;
  156. params.font = p.font;
  157. params.use_ellipses = true;
  158. params.wrap = p.wrap;
  159. params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips
  160. mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
  161. addChild(mTextBox);
  162. S32 TOOLTIP_ICON_SIZE = 0;
  163. S32 TOOLTIP_PLAYBUTTON_SIZE = 0;
  164. if (p.image.isProvided())
  165. {
  166. LLButton::Params icon_params;
  167. icon_params.name = "tooltip_info";
  168. icon_params.label(""); // provid label but set to empty so name does not overwrite it -angela
  169. LLRect icon_rect;
  170. LLUIImage* imagep = p.image;
  171. TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
  172. icon_rect.setOriginAndSize(mPadding, mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
  173. icon_params.rect = icon_rect;
  174. icon_params.image_unselected(imagep);
  175. icon_params.image_selected(imagep);
  176. icon_params.scale_image(true);
  177. icon_params.flash_color(icon_params.highlight_color());
  178. mInfoButton  = LLUICtrlFactory::create<LLButton>(icon_params);
  179. if (p.click_callback.isProvided())
  180. {
  181. mInfoButton->setCommitCallback(boost::bind(p.click_callback()));
  182. }
  183. addChild(mInfoButton);
  184. // move text over to fit image in
  185. mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0);
  186. }
  187. if (p.time_based_media)
  188. {
  189. LLButton::Params p_button;
  190. p_button.name(std::string("play_media"));
  191. p_button.label(""); // provide label but set to empty so name does not overwrite it -angela
  192. TOOLTIP_PLAYBUTTON_SIZE = 16;
  193. LLRect button_rect;
  194. button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
  195. p_button.rect = button_rect;
  196. p_button.image_selected.name("button_anim_pause.tga");
  197. p_button.image_unselected.name("button_anim_play.tga");
  198. p_button.scale_image(true);
  199. mPlayMediaButton = LLUICtrlFactory::create<LLButton>(p_button); 
  200. if(p.click_playmedia_callback.isProvided())
  201. {
  202. mPlayMediaButton->setCommitCallback(boost::bind(p.click_playmedia_callback()));
  203. }
  204. mPlayMediaButton->setToggleState(p.media_playing);
  205. addChild(mPlayMediaButton);
  206. // move text over to fit image in
  207. mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0);
  208. }
  209. if (p.web_based_media)
  210. {
  211. LLButton::Params p_w_button;
  212. p_w_button.name(std::string("home_page"));
  213. p_w_button.label(""); // provid label but set to empty so name does not overwrite it -angela
  214. TOOLTIP_PLAYBUTTON_SIZE = 16;
  215. LLRect button_rect;
  216. button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
  217. p_w_button.rect = button_rect;
  218. p_w_button.image_unselected.name("map_home.tga");
  219. p_w_button.scale_image(true);
  220. mHomePageButton = LLUICtrlFactory::create<LLButton>(p_w_button); 
  221. if(p.click_homepage_callback.isProvided())
  222. {
  223. mHomePageButton->setCommitCallback(boost::bind(p.click_homepage_callback()));
  224. }
  225. addChild(mHomePageButton);
  226. // move text over to fit image in
  227. mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0);
  228. }
  229. if (p.click_callback.isProvided())
  230. {
  231. setMouseUpCallback(boost::bind(p.click_callback()));
  232. }
  233. }
  234. void LLToolTip::initFromParams(const LLToolTip::Params& p)
  235. {
  236. LLPanel::initFromParams(p);
  237. // do this *after* we've had our size set in LLPanel::initFromParams();
  238. const S32 REALLY_LARGE_HEIGHT = 10000;
  239. mTextBox->reshape(p.max_width, REALLY_LARGE_HEIGHT);
  240. if (p.styled_message.isProvided())
  241. {
  242. for (LLInitParam::ParamIterator<LLToolTip::StyledText>::const_iterator text_it = p.styled_message().begin();
  243. text_it != p.styled_message().end();
  244. ++text_it)
  245. {
  246. mTextBox->appendText(text_it->text(), false, text_it->style);
  247. }
  248. }
  249. else
  250. {
  251. mTextBox->setText(p.message());
  252. }
  253. S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth());
  254. S32 text_height = mTextBox->getTextPixelHeight();
  255. mTextBox->reshape(text_width, text_height);
  256. // reshape tooltip panel to fit text box
  257. LLRect tooltip_rect = calcBoundingRect();
  258. tooltip_rect.mTop += mPadding;
  259. tooltip_rect.mRight += mPadding;
  260. tooltip_rect.mBottom = 0;
  261. tooltip_rect.mLeft = 0;
  262. setShape(tooltip_rect);
  263. }
  264. void LLToolTip::setVisible(BOOL visible)
  265. {
  266. // fade out tooltip over time
  267. if (visible)
  268. {
  269. mVisibleTimer.start();
  270. mFadeTimer.stop();
  271. LLPanel::setVisible(TRUE);
  272. }
  273. else
  274. {
  275. mVisibleTimer.stop();
  276. // don't actually change mVisible state, start fade out transition instead
  277. if (!mFadeTimer.getStarted())
  278. {
  279. mFadeTimer.start();
  280. }
  281. }
  282. }
  283. BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
  284. {
  285. //mInfoButton->setFlashing(true);
  286. if(mInfoButton)
  287. mInfoButton->setHighlight(true);
  288. LLPanel::handleHover(x, y, mask);
  289. if (mHasClickCallback)
  290. {
  291. getWindow()->setCursor(UI_CURSOR_HAND);
  292. }
  293. return TRUE;
  294. }
  295. void LLToolTip::onMouseLeave(S32 x, S32 y, MASK mask)
  296. {
  297. //mInfoButton->setFlashing(true);
  298. if(mInfoButton)
  299. mInfoButton->setHighlight(false);
  300. LLUICtrl::onMouseLeave(x, y, mask);
  301. }
  302. void LLToolTip::draw()
  303. {
  304. F32 alpha = 1.f;
  305. if (mFadeTimer.getStarted())
  306. {
  307. F32 tool_tip_fade_time = LLUI::sSettingGroups["config"]->getF32("ToolTipFadeTime");
  308. alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f);
  309. if (alpha == 0.f)
  310. {
  311. // finished fading out, so hide ourselves
  312. mFadeTimer.stop();
  313. LLPanel::setVisible(false);
  314. }
  315. }
  316. // draw tooltip contents with appropriate alpha
  317. {
  318. LLViewDrawContext context(alpha);
  319. LLPanel::draw();
  320. }
  321. }
  322. bool LLToolTip::isFading() 
  323. return mFadeTimer.getStarted(); 
  324. }
  325. F32 LLToolTip::getVisibleTime() 
  326. return mVisibleTimer.getStarted() ? mVisibleTimer.getElapsedTimeF32() : 0.f; 
  327. }
  328. bool LLToolTip::hasClickCallback() 
  329. {
  330. return mHasClickCallback; 
  331. }
  332. //
  333. // LLToolTipMgr
  334. //
  335. LLToolTipMgr::LLToolTipMgr()
  336. :       mToolTipsBlocked(false),
  337. mToolTip(NULL),
  338. mNeedsToolTip(false)
  339. {}
  340. void LLToolTipMgr::createToolTip(const LLToolTip::Params& params)
  341. {
  342. // block all other tooltips until tooltips re-enabled (e.g. mouse moved)
  343. blockToolTips(); 
  344. delete mToolTip;
  345. LLToolTip::Params tooltip_params(params);
  346. // block mouse events if there is a click handler registered (specifically, hover)
  347. if (params.click_callback.isProvided())
  348. {
  349. // set mouse_opaque to true if it wasn't already set to something else
  350. // this prevents mouse down from going "through" the tooltip and ultimately
  351. // causing the tooltip to disappear
  352. tooltip_params.mouse_opaque.setIfNotProvided(true);
  353. }
  354. tooltip_params.rect = LLRect (0, 1, 1, 0);
  355. mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
  356. gToolTipView->addChild(mToolTip);
  357. if (params.pos.isProvided())
  358. {
  359. LLCoordGL pos = params.pos;
  360. // try to spawn at requested position
  361. LLUI::positionViewNearMouse(mToolTip, pos.mX, pos.mY);
  362. }
  363. else
  364. {
  365. // just spawn at mouse location
  366. LLUI::positionViewNearMouse(mToolTip);
  367. }
  368. //...update "sticky" rect and tooltip position
  369. if (params.sticky_rect.isProvided())
  370. {
  371. mMouseNearRect = params.sticky_rect;
  372. }
  373. else
  374. {
  375. S32 mouse_x;
  376. S32 mouse_y;
  377. LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y);
  378. // allow mouse a little bit of slop before changing tooltips
  379. mMouseNearRect.setCenterAndSize(mouse_x, mouse_y, 3, 3);
  380. }
  381. // allow mouse to move all the way to the tooltip without changing tooltips
  382. // (tooltip can still time out)
  383. if (mToolTip->hasClickCallback())
  384. {
  385. // keep tooltip up when we mouse over it
  386. mMouseNearRect.unionWith(mToolTip->getRect());
  387. }
  388. }
  389. void LLToolTipMgr::show(const std::string& msg)
  390. {
  391. show(LLToolTip::Params().message(msg));
  392. }
  393. void LLToolTipMgr::show(const LLToolTip::Params& params)
  394. {
  395. // fill in default tooltip params from tool_tip.xml
  396. LLToolTip::Params params_with_defaults(params);
  397. params_with_defaults.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLToolTip>());
  398. if (!params_with_defaults.validateBlock()) 
  399. {
  400. llwarns << "Could not display tooltip!" << llendl;
  401. return;
  402. }
  403. S32 mouse_x;
  404. S32 mouse_y;
  405. LLUI::getMousePositionLocal(gToolTipView, &mouse_x, &mouse_y);
  406. // are we ready to show the tooltip?
  407. if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc.
  408. && LLUI::getMouseIdleTime() > params_with_defaults.delay_time) // the mouse has been still long enough
  409. {
  410. bool tooltip_changed = mLastToolTipParams.message() != params_with_defaults.message()
  411. || mLastToolTipParams.pos() != params_with_defaults.pos()
  412. || mLastToolTipParams.time_based_media() != params_with_defaults.time_based_media()
  413. || mLastToolTipParams.web_based_media() != params_with_defaults.web_based_media();
  414. bool tooltip_shown = mToolTip 
  415.  && mToolTip->getVisible() 
  416.  && !mToolTip->isFading();
  417. mNeedsToolTip = tooltip_changed || !tooltip_shown;
  418. // store description of tooltip for later creation
  419. mNextToolTipParams = params_with_defaults;
  420. }
  421. }
  422. // allow new tooltips to be created, e.g. after mouse has moved
  423. void LLToolTipMgr::unblockToolTips()
  424. {
  425. mToolTipsBlocked = false;
  426. }
  427. // disallow new tooltips until unblockTooltips called
  428. void LLToolTipMgr::blockToolTips()
  429. {
  430. hideToolTips();
  431. mToolTipsBlocked = true;
  432. }
  433. void LLToolTipMgr::hideToolTips() 
  434. if (mToolTip)
  435. {
  436. mToolTip->setVisible(FALSE);
  437. }
  438. }
  439. bool LLToolTipMgr::toolTipVisible()
  440. {
  441. return mToolTip ? mToolTip->isInVisibleChain() : false;
  442. }
  443. LLRect LLToolTipMgr::getToolTipRect()
  444. {
  445. if (mToolTip && mToolTip->getVisible())
  446. {
  447. return mToolTip->getRect();
  448. }
  449. return LLRect();
  450. }
  451. LLRect LLToolTipMgr::getMouseNearRect() 
  452. return toolTipVisible() ? mMouseNearRect : LLRect(); 
  453. }
  454. // every frame, determine if current tooltip should be hidden
  455. void LLToolTipMgr::updateToolTipVisibility()
  456. {
  457. // create new tooltip if we have one ready to go
  458. if (mNeedsToolTip)
  459. {
  460. mNeedsToolTip = false;
  461. createToolTip(mNextToolTipParams);
  462. mLastToolTipParams = mNextToolTipParams;
  463. return;
  464. }
  465. // hide tooltips when mouse cursor is hidden
  466. if (LLUI::getWindow()->isCursorHidden())
  467. {
  468. blockToolTips();
  469. return;
  470. }
  471. // hide existing tooltips if they have timed out
  472. S32 mouse_x, mouse_y;
  473. LLUI::getMousePositionLocal(gToolTipView, &mouse_x, &mouse_y);
  474. F32 tooltip_timeout = 0.f;
  475. if (toolTipVisible())
  476. {
  477. // mouse far away from tooltip
  478. tooltip_timeout = mLastToolTipParams.visible_time_far;
  479. // mouse near rect will only include the tooltip if the 
  480. // tooltip is clickable
  481. if (mMouseNearRect.pointInRect(mouse_x, mouse_y))
  482. {
  483. // mouse "close" to tooltip
  484. tooltip_timeout = mLastToolTipParams.visible_time_near;
  485. // if tooltip is clickable (has large mMouseNearRect)
  486. // than having cursor over tooltip keeps it up indefinitely
  487. if (mToolTip->parentPointInView(mouse_x, mouse_y))
  488. {
  489. // mouse over tooltip itself, don't time out
  490. tooltip_timeout = mLastToolTipParams.visible_time_over;
  491. }
  492. }
  493. if (mToolTip->getVisibleTime() > tooltip_timeout)
  494. {
  495. hideToolTips();
  496. }
  497. }
  498. }
  499. // EOF