480 lines
14 KiB
C++
480 lines
14 KiB
C++
/**
|
|
* @file llpaneltopinfobar.cpp
|
|
* @brief Coordinates and Parcel Settings information panel definition
|
|
*
|
|
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llpaneltopinfobar.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llagentui.h"
|
|
#include "llclipboard.h"
|
|
#include "llfloatersidepanelcontainer.h"
|
|
#include "lllandmarkactions.h"
|
|
#include "lllocationinputctrl.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "llparcel.h"
|
|
#include "llslurl.h"
|
|
#include "llstatusbar.h"
|
|
#include "lltrans.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llviewerinventory.h"
|
|
#include "llviewermenu.h"
|
|
#include "llviewerparcelmgr.h"
|
|
#include "llviewerregion.h"
|
|
|
|
class LLPanelTopInfoBar::LLParcelChangeObserver : public LLParcelObserver
|
|
{
|
|
public:
|
|
LLParcelChangeObserver(LLPanelTopInfoBar* topInfoBar) : mTopInfoBar(topInfoBar) {}
|
|
|
|
private:
|
|
/*virtual*/ void changed()
|
|
{
|
|
if (mTopInfoBar)
|
|
{
|
|
mTopInfoBar->updateParcelIcons();
|
|
}
|
|
}
|
|
|
|
LLPanelTopInfoBar* mTopInfoBar;
|
|
};
|
|
|
|
LLPanelTopInfoBar::LLPanelTopInfoBar(): mParcelChangedObserver(0)
|
|
{
|
|
buildFromFile( "panel_topinfo_bar.xml");
|
|
}
|
|
|
|
LLPanelTopInfoBar::~LLPanelTopInfoBar()
|
|
{
|
|
if (mParcelChangedObserver)
|
|
{
|
|
LLViewerParcelMgr::getInstance()->removeObserver(mParcelChangedObserver);
|
|
delete mParcelChangedObserver;
|
|
}
|
|
|
|
if (mParcelPropsCtrlConnection.connected())
|
|
{
|
|
mParcelPropsCtrlConnection.disconnect();
|
|
}
|
|
|
|
if (mParcelMgrConnection.connected())
|
|
{
|
|
mParcelMgrConnection.disconnect();
|
|
}
|
|
|
|
if (mShowCoordsCtrlConnection.connected())
|
|
{
|
|
mShowCoordsCtrlConnection.disconnect();
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::initParcelIcons()
|
|
{
|
|
mParcelIcon[VOICE_ICON] = getChild<LLIconCtrl>("voice_icon");
|
|
mParcelIcon[FLY_ICON] = getChild<LLIconCtrl>("fly_icon");
|
|
mParcelIcon[PUSH_ICON] = getChild<LLIconCtrl>("push_icon");
|
|
mParcelIcon[BUILD_ICON] = getChild<LLIconCtrl>("build_icon");
|
|
mParcelIcon[SCRIPTS_ICON] = getChild<LLIconCtrl>("scripts_icon");
|
|
mParcelIcon[DAMAGE_ICON] = getChild<LLIconCtrl>("damage_icon");
|
|
mParcelIcon[SEE_AVATARS_ICON] = getChild<LLIconCtrl>("see_avatars_icon");
|
|
|
|
mParcelIcon[VOICE_ICON]->setToolTip(LLTrans::getString("LocationCtrlVoiceTooltip"));
|
|
mParcelIcon[FLY_ICON]->setToolTip(LLTrans::getString("LocationCtrlFlyTooltip"));
|
|
mParcelIcon[PUSH_ICON]->setToolTip(LLTrans::getString("LocationCtrlPushTooltip"));
|
|
mParcelIcon[BUILD_ICON]->setToolTip(LLTrans::getString("LocationCtrlBuildTooltip"));
|
|
mParcelIcon[SCRIPTS_ICON]->setToolTip(LLTrans::getString("LocationCtrlScriptsTooltip"));
|
|
mParcelIcon[DAMAGE_ICON]->setToolTip(LLTrans::getString("LocationCtrlDamageTooltip"));
|
|
mParcelIcon[SEE_AVATARS_ICON]->setToolTip(LLTrans::getString("LocationCtrlSeeAVsTooltip"));
|
|
|
|
mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, VOICE_ICON));
|
|
mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, FLY_ICON));
|
|
mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, PUSH_ICON));
|
|
mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, BUILD_ICON));
|
|
mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SCRIPTS_ICON));
|
|
mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, DAMAGE_ICON));
|
|
mParcelIcon[SEE_AVATARS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SEE_AVATARS_ICON));
|
|
|
|
mDamageText->setText(LLStringExplicit("100%"));
|
|
}
|
|
|
|
void LLPanelTopInfoBar::handleLoginComplete()
|
|
{
|
|
// An agent parcel update hasn't occurred yet, so
|
|
// we have to manually set location and the icons.
|
|
update();
|
|
}
|
|
|
|
BOOL LLPanelTopInfoBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|
{
|
|
if(!LLUICtrl::CommitCallbackRegistry::getValue("TopInfoBar.Action"))
|
|
{
|
|
LLUICtrl::CommitCallbackRegistry::currentRegistrar()
|
|
.add("TopInfoBar.Action", boost::bind(&LLPanelTopInfoBar::onContextMenuItemClicked, this, _2));
|
|
}
|
|
show_topinfobar_context_menu(this, x, y);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL LLPanelTopInfoBar::postBuild()
|
|
{
|
|
mInfoBtn = getChild<LLButton>("place_info_btn");
|
|
mInfoBtn->setClickedCallback(boost::bind(&LLPanelTopInfoBar::onInfoButtonClicked, this));
|
|
mInfoBtn->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip"));
|
|
|
|
mParcelInfoText = getChild<LLTextBox>("parcel_info_text");
|
|
mDamageText = getChild<LLTextBox>("damage_text");
|
|
|
|
initParcelIcons();
|
|
|
|
mParcelChangedObserver = new LLParcelChangeObserver(this);
|
|
LLViewerParcelMgr::getInstance()->addObserver(mParcelChangedObserver);
|
|
|
|
// Connecting signal for updating parcel icons on "Show Parcel Properties" setting change.
|
|
LLControlVariable* ctrl = gSavedSettings.getControl("NavBarShowParcelProperties").get();
|
|
if (ctrl)
|
|
{
|
|
mParcelPropsCtrlConnection = ctrl->getSignal()->connect(boost::bind(&LLPanelTopInfoBar::updateParcelIcons, this));
|
|
}
|
|
|
|
// Connecting signal for updating parcel text on "Show Coordinates" setting change.
|
|
ctrl = gSavedSettings.getControl("NavBarShowCoordinates").get();
|
|
if (ctrl)
|
|
{
|
|
mShowCoordsCtrlConnection = ctrl->getSignal()->connect(boost::bind(&LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged, this));
|
|
}
|
|
|
|
mParcelMgrConnection = gAgent.addParcelChangedCallback(
|
|
boost::bind(&LLPanelTopInfoBar::onAgentParcelChange, this));
|
|
|
|
setVisibleCallback(boost::bind(&LLPanelTopInfoBar::onVisibilityChanged, this, _2));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged()
|
|
{
|
|
std::string new_text;
|
|
|
|
// don't need to have separate show_coords variable; if user requested the coords to be shown
|
|
// they will be added during the next call to the draw() method.
|
|
buildLocationString(new_text, false);
|
|
setParcelInfoText(new_text);
|
|
}
|
|
|
|
// when panel is shown, all minimized floaters should be shifted downwards to prevent overlapping of
|
|
// PanelTopInfoBar. See EXT-7951.
|
|
void LLPanelTopInfoBar::onVisibilityChanged(const LLSD& show)
|
|
{
|
|
// this height is used as a vertical offset for ALREADY MINIMIZED floaters
|
|
// when PanelTopInfoBar visibility changes
|
|
S32 height = getRect().getHeight();
|
|
|
|
// this vertical offset is used for a start minimize position of floaters that
|
|
// are NOT MIMIMIZED YET
|
|
S32 minimize_pos_offset = 0;
|
|
|
|
if (show.asBoolean())
|
|
{
|
|
height = minimize_pos_offset = -height;
|
|
}
|
|
|
|
gFloaterView->shiftFloaters(0, height);
|
|
gFloaterView->setMinimizePositionVerticalOffset(minimize_pos_offset);
|
|
}
|
|
|
|
boost::signals2::connection LLPanelTopInfoBar::setResizeCallback( const resize_signal_t::slot_type& cb )
|
|
{
|
|
return mResizeSignal.connect(cb);
|
|
}
|
|
|
|
void LLPanelTopInfoBar::draw()
|
|
{
|
|
updateParcelInfoText();
|
|
updateHealth();
|
|
|
|
LLPanel::draw();
|
|
}
|
|
|
|
void LLPanelTopInfoBar::buildLocationString(std::string& loc_str, bool show_coords)
|
|
{
|
|
LLAgentUI::ELocationFormat format =
|
|
(show_coords ? LLAgentUI::LOCATION_FORMAT_FULL : LLAgentUI::LOCATION_FORMAT_NO_COORDS);
|
|
|
|
if (!LLAgentUI::buildLocationString(loc_str, format))
|
|
{
|
|
loc_str = "???";
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::setParcelInfoText(const std::string& new_text)
|
|
{
|
|
LLRect old_rect = getRect();
|
|
const LLFontGL* font = mParcelInfoText->getFont();
|
|
S32 new_text_width = font->getWidth(new_text);
|
|
|
|
mParcelInfoText->setText(new_text);
|
|
|
|
LLRect rect = mParcelInfoText->getRect();
|
|
rect.setOriginAndSize(rect.mLeft, rect.mBottom, new_text_width, rect.getHeight());
|
|
|
|
mParcelInfoText->reshape(rect.getWidth(), rect.getHeight(), TRUE);
|
|
mParcelInfoText->setRect(rect);
|
|
layoutParcelIcons();
|
|
|
|
if (old_rect != getRect())
|
|
{
|
|
mResizeSignal();
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::update()
|
|
{
|
|
std::string new_text;
|
|
|
|
// don't need to have separate show_coords variable; if user requested the coords to be shown
|
|
// they will be added during the next call to the draw() method.
|
|
buildLocationString(new_text, false);
|
|
setParcelInfoText(new_text);
|
|
|
|
updateParcelIcons();
|
|
}
|
|
|
|
void LLPanelTopInfoBar::updateParcelInfoText()
|
|
{
|
|
static LLUICachedControl<bool> show_coords("NavBarShowCoordinates", false);
|
|
|
|
if (show_coords)
|
|
{
|
|
std::string new_text;
|
|
|
|
buildLocationString(new_text, show_coords);
|
|
setParcelInfoText(new_text);
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::updateParcelIcons()
|
|
{
|
|
LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
|
|
|
|
LLViewerRegion* agent_region = gAgent.getRegion();
|
|
LLParcel* agent_parcel = vpm->getAgentParcel();
|
|
if (!agent_region || !agent_parcel)
|
|
return;
|
|
|
|
if (gSavedSettings.getBOOL("NavBarShowParcelProperties"))
|
|
{
|
|
LLParcel* current_parcel;
|
|
LLViewerRegion* selection_region = vpm->getSelectionRegion();
|
|
LLParcel* selected_parcel = vpm->getParcelSelection()->getParcel();
|
|
|
|
// If agent is in selected parcel we use its properties because
|
|
// they are updated more often by LLViewerParcelMgr than agent parcel properties.
|
|
// See LLViewerParcelMgr::processParcelProperties().
|
|
// This is needed to reflect parcel restrictions changes without having to leave
|
|
// the parcel and then enter it again. See EXT-2987
|
|
if (selected_parcel && selected_parcel->getLocalID() == agent_parcel->getLocalID()
|
|
&& selection_region == agent_region)
|
|
{
|
|
current_parcel = selected_parcel;
|
|
}
|
|
else
|
|
{
|
|
current_parcel = agent_parcel;
|
|
}
|
|
|
|
bool allow_voice = vpm->allowAgentVoice(agent_region, current_parcel);
|
|
bool allow_fly = vpm->allowAgentFly(agent_region, current_parcel);
|
|
bool allow_push = vpm->allowAgentPush(agent_region, current_parcel);
|
|
bool allow_build = vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610.
|
|
bool allow_scripts = vpm->allowAgentScripts(agent_region, current_parcel);
|
|
bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel);
|
|
bool see_avs = current_parcel->getSeeAVs();
|
|
|
|
// Most icons are "block this ability"
|
|
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
|
|
mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
|
|
mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
|
|
mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
|
|
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
|
|
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
|
|
mDamageText->setVisible(allow_damage);
|
|
mParcelIcon[SEE_AVATARS_ICON]->setVisible( !see_avs );
|
|
|
|
layoutParcelIcons();
|
|
}
|
|
else
|
|
{
|
|
for (S32 i = 0; i < ICON_COUNT; ++i)
|
|
{
|
|
mParcelIcon[i]->setVisible(false);
|
|
}
|
|
mDamageText->setVisible(false);
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::updateHealth()
|
|
{
|
|
static LLUICachedControl<bool> show_icons("NavBarShowParcelProperties", false);
|
|
|
|
// *FIXME: Status bar owns health information, should be in agent
|
|
if (show_icons && gStatusBar)
|
|
{
|
|
static S32 last_health = -1;
|
|
S32 health = gStatusBar->getHealth();
|
|
if (health != last_health)
|
|
{
|
|
std::string text = llformat("%d%%", health);
|
|
mDamageText->setText(text);
|
|
last_health = health;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::layoutParcelIcons()
|
|
{
|
|
LLRect old_rect = getRect();
|
|
|
|
// TODO: remove hard-coded values and read them as xml parameters
|
|
static const int FIRST_ICON_HPAD = 32;
|
|
static const int LAST_ICON_HPAD = 11;
|
|
|
|
S32 left = mParcelInfoText->getRect().mRight + FIRST_ICON_HPAD;
|
|
|
|
left = layoutWidget(mDamageText, left);
|
|
|
|
for (int i = ICON_COUNT - 1; i >= 0; --i)
|
|
{
|
|
left = layoutWidget(mParcelIcon[i], left);
|
|
}
|
|
|
|
LLRect rect = getRect();
|
|
rect.set(rect.mLeft, rect.mTop, left + LAST_ICON_HPAD, rect.mBottom);
|
|
setRect(rect);
|
|
|
|
if (old_rect != getRect())
|
|
{
|
|
mResizeSignal();
|
|
}
|
|
}
|
|
|
|
S32 LLPanelTopInfoBar::layoutWidget(LLUICtrl* ctrl, S32 left)
|
|
{
|
|
// TODO: remove hard-coded values and read them as xml parameters
|
|
static const int ICON_HPAD = 2;
|
|
|
|
if (ctrl->getVisible())
|
|
{
|
|
LLRect rect = ctrl->getRect();
|
|
rect.mRight = left + rect.getWidth();
|
|
rect.mLeft = left;
|
|
|
|
ctrl->setRect(rect);
|
|
left += rect.getWidth() + ICON_HPAD;
|
|
}
|
|
|
|
return left;
|
|
}
|
|
|
|
void LLPanelTopInfoBar::onParcelIconClick(EParcelIcon icon)
|
|
{
|
|
switch (icon)
|
|
{
|
|
case VOICE_ICON:
|
|
LLNotificationsUtil::add("NoVoice");
|
|
break;
|
|
case FLY_ICON:
|
|
LLNotificationsUtil::add("NoFly");
|
|
break;
|
|
case PUSH_ICON:
|
|
LLNotificationsUtil::add("PushRestricted");
|
|
break;
|
|
case BUILD_ICON:
|
|
LLNotificationsUtil::add("NoBuild");
|
|
break;
|
|
case SCRIPTS_ICON:
|
|
{
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
if(region && region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS))
|
|
{
|
|
LLNotificationsUtil::add("ScriptsStopped");
|
|
}
|
|
else if(region && region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS))
|
|
{
|
|
LLNotificationsUtil::add("ScriptsNotRunning");
|
|
}
|
|
else
|
|
{
|
|
LLNotificationsUtil::add("NoOutsideScripts");
|
|
}
|
|
break;
|
|
}
|
|
case DAMAGE_ICON:
|
|
LLNotificationsUtil::add("NotSafe");
|
|
break;
|
|
case SEE_AVATARS_ICON:
|
|
LLNotificationsUtil::add("SeeAvatars");
|
|
break;
|
|
case ICON_COUNT:
|
|
break;
|
|
// no default to get compiler warning when a new icon gets added
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::onAgentParcelChange()
|
|
{
|
|
update();
|
|
}
|
|
|
|
void LLPanelTopInfoBar::onContextMenuItemClicked(const LLSD::String& item)
|
|
{
|
|
if (item == "landmark")
|
|
{
|
|
LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
|
|
|
|
if(landmark == NULL)
|
|
{
|
|
LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
|
|
}
|
|
else
|
|
{
|
|
LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "landmark").with("id",landmark->getUUID()));
|
|
}
|
|
}
|
|
else if (item == "copy")
|
|
{
|
|
LLSLURL slurl;
|
|
LLAgentUI::buildSLURL(slurl, false);
|
|
LLUIString location_str(slurl.getSLURLString());
|
|
|
|
LLClipboard::instance().copyToClipboard(location_str,0,location_str.length());
|
|
}
|
|
}
|
|
|
|
void LLPanelTopInfoBar::onInfoButtonClicked()
|
|
{
|
|
LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent"));
|
|
}
|