PageRenderTime 83ms CodeModel.GetById 15ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llpaneltopinfobar.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 477 lines | 353 code | 75 blank | 49 comment | 42 complexity | c297e8e0c896fee0a4f606577cce11f1 MD5 | raw file
  1/**
  2 * @file llpaneltopinfobar.cpp
  3 * @brief Coordinates and Parcel Settings information panel definition
  4 *
  5 * $LicenseInfo:firstyear=2010&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 "llpaneltopinfobar.h"
 30
 31#include "llagent.h"
 32#include "llagentui.h"
 33#include "llclipboard.h"
 34#include "llfloatersidepanelcontainer.h"
 35#include "lllandmarkactions.h"
 36#include "lllocationinputctrl.h"
 37#include "llnotificationsutil.h"
 38#include "llparcel.h"
 39#include "llslurl.h"
 40#include "llstatusbar.h"
 41#include "lltrans.h"
 42#include "llviewercontrol.h"
 43#include "llviewerinventory.h"
 44#include "llviewermenu.h"
 45#include "llviewerparcelmgr.h"
 46#include "llviewerregion.h"
 47
 48class LLPanelTopInfoBar::LLParcelChangeObserver : public LLParcelObserver
 49{
 50public:
 51	LLParcelChangeObserver(LLPanelTopInfoBar* topInfoBar) : mTopInfoBar(topInfoBar) {}
 52
 53private:
 54	/*virtual*/ void changed()
 55	{
 56		if (mTopInfoBar)
 57		{
 58			mTopInfoBar->updateParcelIcons();
 59		}
 60	}
 61
 62	LLPanelTopInfoBar* mTopInfoBar;
 63};
 64
 65LLPanelTopInfoBar::LLPanelTopInfoBar(): mParcelChangedObserver(0)
 66{
 67	LLUICtrl::CommitCallbackRegistry::currentRegistrar()
 68			.add("TopInfoBar.Action", boost::bind(&LLPanelTopInfoBar::onContextMenuItemClicked, this, _2));
 69
 70	buildFromFile( "panel_topinfo_bar.xml");
 71}
 72
 73LLPanelTopInfoBar::~LLPanelTopInfoBar()
 74{
 75	if (mParcelChangedObserver)
 76	{
 77		LLViewerParcelMgr::getInstance()->removeObserver(mParcelChangedObserver);
 78		delete mParcelChangedObserver;
 79	}
 80
 81	if (mParcelPropsCtrlConnection.connected())
 82	{
 83		mParcelPropsCtrlConnection.disconnect();
 84	}
 85
 86	if (mParcelMgrConnection.connected())
 87	{
 88		mParcelMgrConnection.disconnect();
 89	}
 90
 91	if (mShowCoordsCtrlConnection.connected())
 92	{
 93		mShowCoordsCtrlConnection.disconnect();
 94	}
 95}
 96
 97void LLPanelTopInfoBar::initParcelIcons()
 98{
 99	mParcelIcon[VOICE_ICON] = getChild<LLIconCtrl>("voice_icon");
100	mParcelIcon[FLY_ICON] = getChild<LLIconCtrl>("fly_icon");
101	mParcelIcon[PUSH_ICON] = getChild<LLIconCtrl>("push_icon");
102	mParcelIcon[BUILD_ICON] = getChild<LLIconCtrl>("build_icon");
103	mParcelIcon[SCRIPTS_ICON] = getChild<LLIconCtrl>("scripts_icon");
104	mParcelIcon[DAMAGE_ICON] = getChild<LLIconCtrl>("damage_icon");
105	mParcelIcon[SEE_AVATARS_ICON] = getChild<LLIconCtrl>("see_avatars_icon");
106
107	mParcelIcon[VOICE_ICON]->setToolTip(LLTrans::getString("LocationCtrlVoiceTooltip"));
108	mParcelIcon[FLY_ICON]->setToolTip(LLTrans::getString("LocationCtrlFlyTooltip"));
109	mParcelIcon[PUSH_ICON]->setToolTip(LLTrans::getString("LocationCtrlPushTooltip"));
110	mParcelIcon[BUILD_ICON]->setToolTip(LLTrans::getString("LocationCtrlBuildTooltip"));
111	mParcelIcon[SCRIPTS_ICON]->setToolTip(LLTrans::getString("LocationCtrlScriptsTooltip"));
112	mParcelIcon[DAMAGE_ICON]->setToolTip(LLTrans::getString("LocationCtrlDamageTooltip"));
113	mParcelIcon[SEE_AVATARS_ICON]->setToolTip(LLTrans::getString("LocationCtrlSeeAVsTooltip"));
114
115	mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, VOICE_ICON));
116	mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, FLY_ICON));
117	mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, PUSH_ICON));
118	mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, BUILD_ICON));
119	mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SCRIPTS_ICON));
120	mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, DAMAGE_ICON));
121	mParcelIcon[SEE_AVATARS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SEE_AVATARS_ICON));
122
123	mDamageText->setText(LLStringExplicit("100%"));
124}
125
126void LLPanelTopInfoBar::handleLoginComplete()
127{
128	// An agent parcel update hasn't occurred yet, so
129	// we have to manually set location and the icons.
130	update();
131}
132
133BOOL LLPanelTopInfoBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
134{
135	show_topinfobar_context_menu(this, x, y);
136	return TRUE;
137}
138
139BOOL LLPanelTopInfoBar::postBuild()
140{
141	mInfoBtn = getChild<LLButton>("place_info_btn");
142	mInfoBtn->setClickedCallback(boost::bind(&LLPanelTopInfoBar::onInfoButtonClicked, this));
143	mInfoBtn->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip"));
144
145	mParcelInfoText = getChild<LLTextBox>("parcel_info_text");
146	mDamageText = getChild<LLTextBox>("damage_text");
147
148	initParcelIcons();
149
150	mParcelChangedObserver = new LLParcelChangeObserver(this);
151	LLViewerParcelMgr::getInstance()->addObserver(mParcelChangedObserver);
152
153	// Connecting signal for updating parcel icons on "Show Parcel Properties" setting change.
154	LLControlVariable* ctrl = gSavedSettings.getControl("NavBarShowParcelProperties").get();
155	if (ctrl)
156	{
157		mParcelPropsCtrlConnection = ctrl->getSignal()->connect(boost::bind(&LLPanelTopInfoBar::updateParcelIcons, this));
158	}
159
160	// Connecting signal for updating parcel text on "Show Coordinates" setting change.
161	ctrl = gSavedSettings.getControl("NavBarShowCoordinates").get();
162	if (ctrl)
163	{
164		mShowCoordsCtrlConnection = ctrl->getSignal()->connect(boost::bind(&LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged, this));
165	}
166
167	mParcelMgrConnection = LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
168			boost::bind(&LLPanelTopInfoBar::onAgentParcelChange, this));
169
170	setVisibleCallback(boost::bind(&LLPanelTopInfoBar::onVisibilityChange, this, _2));
171
172	return TRUE;
173}
174
175void LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged()
176{
177	std::string new_text;
178
179	// don't need to have separate show_coords variable; if user requested the coords to be shown
180	// they will be added during the next call to the draw() method.
181	buildLocationString(new_text, false);
182	setParcelInfoText(new_text);
183}
184
185// when panel is shown, all minimized floaters should be shifted downwards to prevent overlapping of
186// PanelTopInfoBar. See EXT-7951.
187void LLPanelTopInfoBar::onVisibilityChange(const LLSD& show)
188{
189	// this height is used as a vertical offset for ALREADY MINIMIZED floaters
190	// when PanelTopInfoBar visibility changes
191	S32 height = getRect().getHeight();
192
193	// this vertical offset is used for a start minimize position of floaters that
194	// are NOT MIMIMIZED YET
195	S32 minimize_pos_offset = 0;
196
197	if (show.asBoolean())
198	{
199		height = minimize_pos_offset = -height;
200	}
201
202	gFloaterView->shiftFloaters(0, height);
203	gFloaterView->setMinimizePositionVerticalOffset(minimize_pos_offset);
204}
205
206boost::signals2::connection LLPanelTopInfoBar::setResizeCallback( const resize_signal_t::slot_type& cb )
207{
208	return mResizeSignal.connect(cb);
209}
210
211void LLPanelTopInfoBar::draw()
212{
213	updateParcelInfoText();
214	updateHealth();
215
216	LLPanel::draw();
217}
218
219void LLPanelTopInfoBar::buildLocationString(std::string& loc_str, bool show_coords)
220{
221	LLAgentUI::ELocationFormat format =
222		(show_coords ? LLAgentUI::LOCATION_FORMAT_FULL : LLAgentUI::LOCATION_FORMAT_NO_COORDS);
223
224	if (!LLAgentUI::buildLocationString(loc_str, format))
225	{
226		loc_str = "???";
227	}
228}
229
230void LLPanelTopInfoBar::setParcelInfoText(const std::string& new_text)
231{
232	LLRect old_rect = getRect();
233	const LLFontGL* font = mParcelInfoText->getDefaultFont();
234	S32 new_text_width = font->getWidth(new_text);
235
236	mParcelInfoText->setText(new_text);
237
238	LLRect rect = mParcelInfoText->getRect();
239	rect.setOriginAndSize(rect.mLeft, rect.mBottom, new_text_width, rect.getHeight());
240
241	mParcelInfoText->reshape(rect.getWidth(), rect.getHeight(), TRUE);
242	mParcelInfoText->setRect(rect);
243	layoutParcelIcons();
244
245	if (old_rect != getRect())
246	{
247		mResizeSignal();
248	}
249}
250
251void LLPanelTopInfoBar::update()
252{
253	std::string new_text;
254
255	// don't need to have separate show_coords variable; if user requested the coords to be shown
256	// they will be added during the next call to the draw() method.
257	buildLocationString(new_text, false);
258	setParcelInfoText(new_text);
259
260	updateParcelIcons();
261}
262
263void LLPanelTopInfoBar::updateParcelInfoText()
264{
265	static LLUICachedControl<bool> show_coords("NavBarShowCoordinates", false);
266
267	if (show_coords)
268	{
269		std::string new_text;
270
271		buildLocationString(new_text, show_coords);
272		setParcelInfoText(new_text);
273	}
274}
275
276void LLPanelTopInfoBar::updateParcelIcons()
277{
278	LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
279
280	LLViewerRegion* agent_region = gAgent.getRegion();
281	LLParcel* agent_parcel = vpm->getAgentParcel();
282	if (!agent_region || !agent_parcel)
283		return;
284
285	if (gSavedSettings.getBOOL("NavBarShowParcelProperties"))
286	{
287		LLParcel* current_parcel;
288		LLViewerRegion* selection_region = vpm->getSelectionRegion();
289		LLParcel* selected_parcel = vpm->getParcelSelection()->getParcel();
290
291		// If agent is in selected parcel we use its properties because
292		// they are updated more often by LLViewerParcelMgr than agent parcel properties.
293		// See LLViewerParcelMgr::processParcelProperties().
294		// This is needed to reflect parcel restrictions changes without having to leave
295		// the parcel and then enter it again. See EXT-2987
296		if (selected_parcel && selected_parcel->getLocalID() == agent_parcel->getLocalID()
297				&& selection_region == agent_region)
298		{
299			current_parcel = selected_parcel;
300		}
301		else
302		{
303			current_parcel = agent_parcel;
304		}
305
306		bool allow_voice	= vpm->allowAgentVoice(agent_region, current_parcel);
307		bool allow_fly		= vpm->allowAgentFly(agent_region, current_parcel);
308		bool allow_push		= vpm->allowAgentPush(agent_region, current_parcel);
309		bool allow_build	= vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610.
310		bool allow_scripts	= vpm->allowAgentScripts(agent_region, current_parcel);
311		bool allow_damage	= vpm->allowAgentDamage(agent_region, current_parcel);
312		bool see_avs        = current_parcel->getSeeAVs();
313
314		// Most icons are "block this ability"
315		mParcelIcon[VOICE_ICON]->setVisible(   !allow_voice );
316		mParcelIcon[FLY_ICON]->setVisible(     !allow_fly );
317		mParcelIcon[PUSH_ICON]->setVisible(    !allow_push );
318		mParcelIcon[BUILD_ICON]->setVisible(   !allow_build );
319		mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
320		mParcelIcon[DAMAGE_ICON]->setVisible(  allow_damage );
321		mDamageText->setVisible(allow_damage);
322		mParcelIcon[SEE_AVATARS_ICON]->setVisible( !see_avs );
323
324		layoutParcelIcons();
325	}
326	else
327	{
328		for (S32 i = 0; i < ICON_COUNT; ++i)
329		{
330			mParcelIcon[i]->setVisible(false);
331		}
332		mDamageText->setVisible(false);
333	}
334}
335
336void LLPanelTopInfoBar::updateHealth()
337{
338	static LLUICachedControl<bool> show_icons("NavBarShowParcelProperties", false);
339
340	// *FIXME: Status bar owns health information, should be in agent
341	if (show_icons && gStatusBar)
342	{
343		static S32 last_health = -1;
344		S32 health = gStatusBar->getHealth();
345		if (health != last_health)
346		{
347			std::string text = llformat("%d%%", health);
348			mDamageText->setText(text);
349			last_health = health;
350		}
351	}
352}
353
354void LLPanelTopInfoBar::layoutParcelIcons()
355{
356	LLRect old_rect = getRect();
357
358	// TODO: remove hard-coded values and read them as xml parameters
359	static const int FIRST_ICON_HPAD = 32;
360	static const int LAST_ICON_HPAD = 11;
361
362	S32 left = mParcelInfoText->getRect().mRight + FIRST_ICON_HPAD;
363
364	left = layoutWidget(mDamageText, left);
365
366	for (int i = ICON_COUNT - 1; i >= 0; --i)
367	{
368		left = layoutWidget(mParcelIcon[i], left);
369	}
370
371	LLRect rect = getRect();
372	rect.set(rect.mLeft, rect.mTop, left + LAST_ICON_HPAD, rect.mBottom);
373	setRect(rect);
374
375	if (old_rect != getRect())
376	{
377		mResizeSignal();
378	}
379}
380
381S32 LLPanelTopInfoBar::layoutWidget(LLUICtrl* ctrl, S32 left)
382{
383	// TODO: remove hard-coded values and read them as xml parameters
384	static const int ICON_HPAD = 2;
385
386	if (ctrl->getVisible())
387	{
388		LLRect rect = ctrl->getRect();
389		rect.mRight = left + rect.getWidth();
390		rect.mLeft = left;
391
392		ctrl->setRect(rect);
393		left += rect.getWidth() + ICON_HPAD;
394	}
395
396	return left;
397}
398
399void LLPanelTopInfoBar::onParcelIconClick(EParcelIcon icon)
400{
401	switch (icon)
402	{
403	case VOICE_ICON:
404		LLNotificationsUtil::add("NoVoice");
405		break;
406	case FLY_ICON:
407		LLNotificationsUtil::add("NoFly");
408		break;
409	case PUSH_ICON:
410		LLNotificationsUtil::add("PushRestricted");
411		break;
412	case BUILD_ICON:
413		LLNotificationsUtil::add("NoBuild");
414		break;
415	case SCRIPTS_ICON:
416	{
417		LLViewerRegion* region = gAgent.getRegion();
418		if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
419		{
420			LLNotificationsUtil::add("ScriptsStopped");
421		}
422		else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
423		{
424			LLNotificationsUtil::add("ScriptsNotRunning");
425		}
426		else
427		{
428			LLNotificationsUtil::add("NoOutsideScripts");
429		}
430		break;
431	}
432	case DAMAGE_ICON:
433		LLNotificationsUtil::add("NotSafe");
434		break;
435	case SEE_AVATARS_ICON:
436		LLNotificationsUtil::add("SeeAvatars");
437		break;
438	case ICON_COUNT:
439		break;
440	// no default to get compiler warning when a new icon gets added
441	}
442}
443
444void LLPanelTopInfoBar::onAgentParcelChange()
445{
446	update();
447}
448
449void LLPanelTopInfoBar::onContextMenuItemClicked(const LLSD::String& item)
450{
451	if (item == "landmark")
452	{
453		LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
454
455		if(landmark == NULL)
456		{
457			LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
458		}
459		else
460		{
461			LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "landmark").with("id",landmark->getUUID()));
462		}
463	}
464	else if (item == "copy")
465	{
466		LLSLURL slurl;
467		LLAgentUI::buildSLURL(slurl, false);
468		LLUIString location_str(slurl.getSLURLString());
469
470		gClipboard.copyFromString(location_str);
471	}
472}
473
474void LLPanelTopInfoBar::onInfoButtonClicked()
475{
476	LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent"));
477}