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