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