PageRenderTime 30ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llstatusbar.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 564 lines | 408 code | 87 blank | 69 comment | 26 complexity | 9f961329783fdc7ccdb78ea10bf1a091 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llstatusbar.cpp
  3. * @brief LLStatusBar class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&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 "llviewerprecompiledheaders.h"
  27. #include "llstatusbar.h"
  28. // viewer includes
  29. #include "llagent.h"
  30. #include "llagentcamera.h"
  31. #include "llbutton.h"
  32. #include "llcommandhandler.h"
  33. #include "llfirstuse.h"
  34. #include "llviewercontrol.h"
  35. #include "llfloaterbuycurrency.h"
  36. #include "llbuycurrencyhtml.h"
  37. #include "llfloaterlagmeter.h"
  38. #include "llpanelnearbymedia.h"
  39. #include "llpanelvolumepulldown.h"
  40. #include "llfloaterregioninfo.h"
  41. #include "llfloaterscriptdebug.h"
  42. #include "llhints.h"
  43. #include "llhudicon.h"
  44. #include "llnavigationbar.h"
  45. #include "llkeyboard.h"
  46. #include "lllineeditor.h"
  47. #include "llmenugl.h"
  48. #include "llrootview.h"
  49. #include "llsd.h"
  50. #include "lltextbox.h"
  51. #include "llui.h"
  52. #include "llviewerparceloverlay.h"
  53. #include "llviewerregion.h"
  54. #include "llviewerstats.h"
  55. #include "llviewerwindow.h"
  56. #include "llframetimer.h"
  57. #include "llvoavatarself.h"
  58. #include "llresmgr.h"
  59. #include "llworld.h"
  60. #include "llstatgraph.h"
  61. #include "llviewermedia.h"
  62. #include "llviewermenu.h" // for gMenuBarView
  63. #include "llviewerparcelmgr.h"
  64. #include "llviewerthrottle.h"
  65. #include "lluictrlfactory.h"
  66. #include "lltoolmgr.h"
  67. #include "llfocusmgr.h"
  68. #include "llappviewer.h"
  69. #include "lltrans.h"
  70. // library includes
  71. #include "imageids.h"
  72. #include "llfloaterreg.h"
  73. #include "llfontgl.h"
  74. #include "llrect.h"
  75. #include "llerror.h"
  76. #include "llnotificationsutil.h"
  77. #include "llparcel.h"
  78. #include "llstring.h"
  79. #include "message.h"
  80. // system includes
  81. #include <iomanip>
  82. //
  83. // Globals
  84. //
  85. LLStatusBar *gStatusBar = NULL;
  86. S32 STATUS_BAR_HEIGHT = 26;
  87. extern S32 MENU_BAR_HEIGHT;
  88. // TODO: these values ought to be in the XML too
  89. const S32 MENU_PARCEL_SPACING = 1; // Distance from right of menu item to parcel information
  90. const S32 SIM_STAT_WIDTH = 8;
  91. const F32 SIM_WARN_FRACTION = 0.75f;
  92. const F32 SIM_FULL_FRACTION = 0.98f;
  93. const LLColor4 SIM_OK_COLOR(0.f, 1.f, 0.f, 1.f);
  94. const LLColor4 SIM_WARN_COLOR(1.f, 1.f, 0.f, 1.f);
  95. const LLColor4 SIM_FULL_COLOR(1.f, 0.f, 0.f, 1.f);
  96. const F32 ICON_TIMER_EXPIRY = 3.f; // How long the balance and health icons should flash after a change.
  97. const F32 ICON_FLASH_FREQUENCY = 2.f;
  98. const S32 TEXT_HEIGHT = 18;
  99. static void onClickVolume(void*);
  100. LLStatusBar::LLStatusBar(const LLRect& rect)
  101. : LLPanel(),
  102. mTextTime(NULL),
  103. mSGBandwidth(NULL),
  104. mSGPacketLoss(NULL),
  105. mBtnStats(NULL),
  106. mBtnVolume(NULL),
  107. mBoxBalance(NULL),
  108. mBalance(0),
  109. mHealth(100),
  110. mSquareMetersCredit(0),
  111. mSquareMetersCommitted(0)
  112. {
  113. setRect(rect);
  114. // status bar can possible overlay menus?
  115. setMouseOpaque(FALSE);
  116. mBalanceTimer = new LLFrameTimer();
  117. mHealthTimer = new LLFrameTimer();
  118. buildFromFile("panel_status_bar.xml");
  119. }
  120. LLStatusBar::~LLStatusBar()
  121. {
  122. delete mBalanceTimer;
  123. mBalanceTimer = NULL;
  124. delete mHealthTimer;
  125. mHealthTimer = NULL;
  126. // LLView destructor cleans up children
  127. }
  128. //-----------------------------------------------------------------------
  129. // Overrides
  130. //-----------------------------------------------------------------------
  131. // virtual
  132. void LLStatusBar::draw()
  133. {
  134. refresh();
  135. LLPanel::draw();
  136. }
  137. BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
  138. {
  139. show_navbar_context_menu(this,x,y);
  140. return TRUE;
  141. }
  142. BOOL LLStatusBar::postBuild()
  143. {
  144. gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3));
  145. mTextTime = getChild<LLTextBox>("TimeText" );
  146. getChild<LLUICtrl>("buyL")->setCommitCallback(
  147. boost::bind(&LLStatusBar::onClickBuyCurrency, this));
  148. getChild<LLUICtrl>("goShop")->setCommitCallback(boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL")));
  149. mBoxBalance = getChild<LLTextBox>("balance");
  150. mBoxBalance->setClickedCallback( &LLStatusBar::onClickBalance, this );
  151. mBtnStats = getChildView("stat_btn");
  152. mBtnVolume = getChild<LLButton>( "volume_btn" );
  153. mBtnVolume->setClickedCallback( onClickVolume, this );
  154. mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this));
  155. mMediaToggle = getChild<LLButton>("media_toggle_btn");
  156. mMediaToggle->setClickedCallback( &LLStatusBar::onClickMediaToggle, this );
  157. mMediaToggle->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterNearbyMedia, this));
  158. LLHints::registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle());
  159. gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2));
  160. // Adding Net Stat Graph
  161. S32 x = getRect().getWidth() - 2;
  162. S32 y = 0;
  163. LLRect r;
  164. r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1);
  165. LLStatGraph::Params sgp;
  166. sgp.name("BandwidthGraph");
  167. sgp.rect(r);
  168. sgp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
  169. sgp.mouse_opaque(false);
  170. mSGBandwidth = LLUICtrlFactory::create<LLStatGraph>(sgp);
  171. mSGBandwidth->setStat(&LLViewerStats::getInstance()->mKBitStat);
  172. mSGBandwidth->setUnits("Kbps");
  173. mSGBandwidth->setPrecision(0);
  174. addChild(mSGBandwidth);
  175. x -= SIM_STAT_WIDTH + 2;
  176. r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1);
  177. //these don't seem to like being reused
  178. LLStatGraph::Params pgp;
  179. pgp.name("PacketLossPercent");
  180. pgp.rect(r);
  181. pgp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
  182. pgp.mouse_opaque(false);
  183. mSGPacketLoss = LLUICtrlFactory::create<LLStatGraph>(pgp);
  184. mSGPacketLoss->setStat(&LLViewerStats::getInstance()->mPacketsLostPercentStat);
  185. mSGPacketLoss->setUnits("%");
  186. mSGPacketLoss->setMin(0.f);
  187. mSGPacketLoss->setMax(5.f);
  188. mSGPacketLoss->setThreshold(0, 0.5f);
  189. mSGPacketLoss->setThreshold(1, 1.f);
  190. mSGPacketLoss->setThreshold(2, 3.f);
  191. mSGPacketLoss->setPrecision(1);
  192. mSGPacketLoss->mPerSec = FALSE;
  193. addChild(mSGPacketLoss);
  194. mPanelVolumePulldown = new LLPanelVolumePulldown();
  195. addChild(mPanelVolumePulldown);
  196. mPanelVolumePulldown->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
  197. mPanelVolumePulldown->setVisible(FALSE);
  198. mPanelNearByMedia = new LLPanelNearByMedia();
  199. addChild(mPanelNearByMedia);
  200. mPanelNearByMedia->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
  201. mPanelNearByMedia->setVisible(FALSE);
  202. mScriptOut = getChildView("scriptout");
  203. return TRUE;
  204. }
  205. // Per-frame updates of visibility
  206. void LLStatusBar::refresh()
  207. {
  208. static LLCachedControl<bool> show_net_stats(gSavedSettings, "ShowNetStats", false);
  209. bool net_stats_visible = show_net_stats;
  210. if (net_stats_visible)
  211. {
  212. // Adding Net Stat Meter back in
  213. F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f;
  214. mSGBandwidth->setMin(0.f);
  215. mSGBandwidth->setMax(bwtotal*1.25f);
  216. mSGBandwidth->setThreshold(0, bwtotal*0.75f);
  217. mSGBandwidth->setThreshold(1, bwtotal);
  218. mSGBandwidth->setThreshold(2, bwtotal);
  219. }
  220. // update clock every 10 seconds
  221. if(mClockUpdateTimer.getElapsedTimeF32() > 10.f)
  222. {
  223. mClockUpdateTimer.reset();
  224. // Get current UTC time, adjusted for the user's clock
  225. // being off.
  226. time_t utc_time;
  227. utc_time = time_corrected();
  228. std::string timeStr = getString("time");
  229. LLSD substitution;
  230. substitution["datetime"] = (S32) utc_time;
  231. LLStringUtil::format (timeStr, substitution);
  232. mTextTime->setText(timeStr);
  233. // set the tooltip to have the date
  234. std::string dtStr = getString("timeTooltip");
  235. LLStringUtil::format (dtStr, substitution);
  236. mTextTime->setToolTip (dtStr);
  237. }
  238. LLRect r;
  239. const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge();
  240. // reshape menu bar to its content's width
  241. if (MENU_RIGHT != gMenuBarView->getRect().getWidth())
  242. {
  243. gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight());
  244. }
  245. mSGBandwidth->setVisible(net_stats_visible);
  246. mSGPacketLoss->setVisible(net_stats_visible);
  247. mBtnStats->setEnabled(net_stats_visible);
  248. // update the master volume button state
  249. bool mute_audio = LLAppViewer::instance()->getMasterSystemAudioMute();
  250. mBtnVolume->setToggleState(mute_audio);
  251. // Disable media toggle if there's no media, parcel media, and no parcel audio
  252. // (or if media is disabled)
  253. bool button_enabled = (gSavedSettings.getBOOL("AudioStreamingMusic")||gSavedSettings.getBOOL("AudioStreamingMedia")) &&
  254. (LLViewerMedia::hasInWorldMedia() || LLViewerMedia::hasParcelMedia() || LLViewerMedia::hasParcelAudio());
  255. mMediaToggle->setEnabled(button_enabled);
  256. // Note the "sense" of the toggle is opposite whether media is playing or not
  257. bool any_media_playing = (LLViewerMedia::isAnyMediaShowing() ||
  258. LLViewerMedia::isParcelMediaPlaying() ||
  259. LLViewerMedia::isParcelAudioPlaying());
  260. mMediaToggle->setValue(!any_media_playing);
  261. }
  262. void LLStatusBar::setVisibleForMouselook(bool visible)
  263. {
  264. mTextTime->setVisible(visible);
  265. getChild<LLUICtrl>("balance_bg")->setVisible(visible);
  266. mBoxBalance->setVisible(visible);
  267. mBtnVolume->setVisible(visible);
  268. mMediaToggle->setVisible(visible);
  269. mSGBandwidth->setVisible(visible);
  270. mSGPacketLoss->setVisible(visible);
  271. setBackgroundVisible(visible);
  272. }
  273. void LLStatusBar::debitBalance(S32 debit)
  274. {
  275. setBalance(getBalance() - debit);
  276. }
  277. void LLStatusBar::creditBalance(S32 credit)
  278. {
  279. setBalance(getBalance() + credit);
  280. }
  281. void LLStatusBar::setBalance(S32 balance)
  282. {
  283. if (balance > getBalance() && getBalance() != 0)
  284. {
  285. LLFirstUse::receiveLindens();
  286. }
  287. std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance );
  288. LLStringUtil::format_map_t string_args;
  289. string_args["[AMT]"] = llformat("%s", money_str.c_str());
  290. std::string label_str = getString("buycurrencylabel", string_args);
  291. mBoxBalance->setValue(label_str);
  292. // Resize the L$ balance background to be wide enough for your balance plus the buy button
  293. {
  294. const S32 HPAD = 24;
  295. LLRect balance_rect = mBoxBalance->getTextBoundingRect();
  296. LLRect buy_rect = getChildView("buyL")->getRect();
  297. LLRect shop_rect = getChildView("goShop")->getRect();
  298. LLView* balance_bg_view = getChildView("balance_bg");
  299. LLRect balance_bg_rect = balance_bg_view->getRect();
  300. balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
  301. balance_bg_view->setShape(balance_bg_rect);
  302. }
  303. if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold")))
  304. {
  305. if (mBalance > balance)
  306. make_ui_sound("UISndMoneyChangeDown");
  307. else
  308. make_ui_sound("UISndMoneyChangeUp");
  309. }
  310. if( balance != mBalance )
  311. {
  312. mBalanceTimer->reset();
  313. mBalanceTimer->setTimerExpirySec( ICON_TIMER_EXPIRY );
  314. mBalance = balance;
  315. }
  316. }
  317. // static
  318. void LLStatusBar::sendMoneyBalanceRequest()
  319. {
  320. LLMessageSystem* msg = gMessageSystem;
  321. msg->newMessageFast(_PREHASH_MoneyBalanceRequest);
  322. msg->nextBlockFast(_PREHASH_AgentData);
  323. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  324. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  325. msg->nextBlockFast(_PREHASH_MoneyData);
  326. msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null );
  327. gAgent.sendReliableMessage();
  328. }
  329. void LLStatusBar::setHealth(S32 health)
  330. {
  331. //llinfos << "Setting health to: " << buffer << llendl;
  332. if( mHealth > health )
  333. {
  334. if (mHealth > (health + gSavedSettings.getF32("UISndHealthReductionThreshold")))
  335. {
  336. if (isAgentAvatarValid())
  337. {
  338. if (gAgentAvatarp->getSex() == SEX_FEMALE)
  339. {
  340. make_ui_sound("UISndHealthReductionF");
  341. }
  342. else
  343. {
  344. make_ui_sound("UISndHealthReductionM");
  345. }
  346. }
  347. }
  348. mHealthTimer->reset();
  349. mHealthTimer->setTimerExpirySec( ICON_TIMER_EXPIRY );
  350. }
  351. mHealth = health;
  352. }
  353. S32 LLStatusBar::getBalance() const
  354. {
  355. return mBalance;
  356. }
  357. S32 LLStatusBar::getHealth() const
  358. {
  359. return mHealth;
  360. }
  361. void LLStatusBar::setLandCredit(S32 credit)
  362. {
  363. mSquareMetersCredit = credit;
  364. }
  365. void LLStatusBar::setLandCommitted(S32 committed)
  366. {
  367. mSquareMetersCommitted = committed;
  368. }
  369. BOOL LLStatusBar::isUserTiered() const
  370. {
  371. return (mSquareMetersCredit > 0);
  372. }
  373. S32 LLStatusBar::getSquareMetersCredit() const
  374. {
  375. return mSquareMetersCredit;
  376. }
  377. S32 LLStatusBar::getSquareMetersCommitted() const
  378. {
  379. return mSquareMetersCommitted;
  380. }
  381. S32 LLStatusBar::getSquareMetersLeft() const
  382. {
  383. return mSquareMetersCredit - mSquareMetersCommitted;
  384. }
  385. void LLStatusBar::onClickBuyCurrency()
  386. {
  387. // open a currency floater - actual one open depends on
  388. // value specified in settings.xml
  389. LLBuyCurrencyHTML::openCurrencyFloater();
  390. LLFirstUse::receiveLindens(false);
  391. }
  392. void LLStatusBar::onMouseEnterVolume()
  393. {
  394. LLButton* volbtn = getChild<LLButton>( "volume_btn" );
  395. LLRect vol_btn_rect = volbtn->getRect();
  396. LLRect volume_pulldown_rect = mPanelVolumePulldown->getRect();
  397. volume_pulldown_rect.setLeftTopAndSize(vol_btn_rect.mLeft -
  398. (volume_pulldown_rect.getWidth() - vol_btn_rect.getWidth())/2,
  399. vol_btn_rect.mBottom,
  400. volume_pulldown_rect.getWidth(),
  401. volume_pulldown_rect.getHeight());
  402. mPanelVolumePulldown->setShape(volume_pulldown_rect);
  403. // show the master volume pull-down
  404. LLUI::clearPopups();
  405. LLUI::addPopup(mPanelVolumePulldown);
  406. mPanelNearByMedia->setVisible(FALSE);
  407. mPanelVolumePulldown->setVisible(TRUE);
  408. }
  409. void LLStatusBar::onMouseEnterNearbyMedia()
  410. {
  411. LLView* popup_holder = gViewerWindow->getRootView()->getChildView("popup_holder");
  412. LLRect nearby_media_rect = mPanelNearByMedia->getRect();
  413. LLButton* nearby_media_btn = getChild<LLButton>( "media_toggle_btn" );
  414. LLRect nearby_media_btn_rect = nearby_media_btn->getRect();
  415. nearby_media_rect.setLeftTopAndSize(nearby_media_btn_rect.mLeft -
  416. (nearby_media_rect.getWidth() - nearby_media_btn_rect.getWidth())/2,
  417. nearby_media_btn_rect.mBottom,
  418. nearby_media_rect.getWidth(),
  419. nearby_media_rect.getHeight());
  420. // force onscreen
  421. nearby_media_rect.translate(popup_holder->getRect().getWidth() - nearby_media_rect.mRight, 0);
  422. // show the master volume pull-down
  423. mPanelNearByMedia->setShape(nearby_media_rect);
  424. LLUI::clearPopups();
  425. LLUI::addPopup(mPanelNearByMedia);
  426. mPanelVolumePulldown->setVisible(FALSE);
  427. mPanelNearByMedia->setVisible(TRUE);
  428. }
  429. static void onClickVolume(void* data)
  430. {
  431. // toggle the master mute setting
  432. bool mute_audio = LLAppViewer::instance()->getMasterSystemAudioMute();
  433. LLAppViewer::instance()->setMasterSystemAudioMute(!mute_audio);
  434. }
  435. //static
  436. void LLStatusBar::onClickBalance(void* )
  437. {
  438. // Force a balance request message:
  439. LLStatusBar::sendMoneyBalanceRequest();
  440. // The refresh of the display (call to setBalance()) will be done by process_money_balance_reply()
  441. }
  442. //static
  443. void LLStatusBar::onClickMediaToggle(void* data)
  444. {
  445. LLStatusBar *status_bar = (LLStatusBar*)data;
  446. // "Selected" means it was showing the "play" icon (so media was playing), and now it shows "pause", so turn off media
  447. bool enable = ! status_bar->mMediaToggle->getValue();
  448. LLViewerMedia::setAllMediaEnabled(enable);
  449. }
  450. BOOL can_afford_transaction(S32 cost)
  451. {
  452. return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost)));
  453. }
  454. void LLStatusBar::onVolumeChanged(const LLSD& newvalue)
  455. {
  456. refresh();
  457. }
  458. // Implements secondlife:///app/balance/request to request a L$ balance
  459. // update via UDP message system. JC
  460. class LLBalanceHandler : public LLCommandHandler
  461. {
  462. public:
  463. // Requires "trusted" browser/URL source
  464. LLBalanceHandler() : LLCommandHandler("balance", UNTRUSTED_BLOCK) { }
  465. bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
  466. {
  467. if (tokens.size() == 1
  468. && tokens[0].asString() == "request")
  469. {
  470. LLStatusBar::sendMoneyBalanceRequest();
  471. return true;
  472. }
  473. return false;
  474. }
  475. };
  476. // register with command dispatch system
  477. LLBalanceHandler gBalanceHandler;