/indra/newview/llpanelpick.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 617 lines · 448 code · 114 blank · 55 comment · 40 complexity · d051236df69d45791c06360ff17ad9e8 MD5 · raw file

  1. /**
  2. * @file llpanelpick.cpp
  3. * @brief LLPanelPick class implementation
  4. *
  5. * $LicenseInfo:firstyear=2004&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. // Display of a "Top Pick" used both for the global top picks in the
  27. // Find directory, and also for each individual user's picks in their
  28. // profile.
  29. #include "llviewerprecompiledheaders.h"
  30. #include "llpanelpick.h"
  31. #include "message.h"
  32. #include "llparcel.h"
  33. #include "llbutton.h"
  34. #include "llfloaterreg.h"
  35. #include "lliconctrl.h"
  36. #include "lllineeditor.h"
  37. #include "llpanel.h"
  38. #include "llscrollcontainer.h"
  39. #include "lltexteditor.h"
  40. #include "llagent.h"
  41. #include "llagentpicksinfo.h"
  42. #include "llavatarpropertiesprocessor.h"
  43. #include "llfloaterworldmap.h"
  44. #include "lltexturectrl.h"
  45. #include "lluiconstants.h"
  46. #include "llviewerparcelmgr.h"
  47. #include "llviewerregion.h"
  48. #include "llworldmap.h"
  49. #define XML_PANEL_EDIT_PICK "panel_edit_pick.xml"
  50. #define XML_PANEL_PICK_INFO "panel_pick_info.xml"
  51. #define XML_NAME "pick_name"
  52. #define XML_DESC "pick_desc"
  53. #define XML_SNAPSHOT "pick_snapshot"
  54. #define XML_LOCATION "pick_location"
  55. #define XML_BTN_ON_TXTR "edit_icon"
  56. #define XML_BTN_SAVE "save_changes_btn"
  57. //////////////////////////////////////////////////////////////////////////
  58. //////////////////////////////////////////////////////////////////////////
  59. //////////////////////////////////////////////////////////////////////////
  60. //static
  61. LLPanelPickInfo* LLPanelPickInfo::create()
  62. {
  63. LLPanelPickInfo* panel = new LLPanelPickInfo();
  64. panel->buildFromFile(XML_PANEL_PICK_INFO);
  65. return panel;
  66. }
  67. LLPanelPickInfo::LLPanelPickInfo()
  68. : LLPanel()
  69. , LLAvatarPropertiesObserver()
  70. , LLRemoteParcelInfoObserver()
  71. , mAvatarId(LLUUID::null)
  72. , mSnapshotCtrl(NULL)
  73. , mPickId(LLUUID::null)
  74. , mParcelId(LLUUID::null)
  75. , mRequestedId(LLUUID::null)
  76. , mScrollingPanelMinHeight(0)
  77. , mScrollingPanelWidth(0)
  78. , mScrollingPanel(NULL)
  79. , mScrollContainer(NULL)
  80. {
  81. }
  82. LLPanelPickInfo::~LLPanelPickInfo()
  83. {
  84. LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
  85. if (mParcelId.notNull())
  86. {
  87. LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
  88. }
  89. }
  90. void LLPanelPickInfo::onOpen(const LLSD& key)
  91. {
  92. LLUUID avatar_id = key["avatar_id"];
  93. if(avatar_id.isNull())
  94. {
  95. return;
  96. }
  97. if(getAvatarId().notNull())
  98. {
  99. LLAvatarPropertiesProcessor::getInstance()->removeObserver(
  100. getAvatarId(), this);
  101. }
  102. setAvatarId(avatar_id);
  103. resetData();
  104. resetControls();
  105. setPickId(key["pick_id"]);
  106. setPickName(key["pick_name"]);
  107. setPickDesc(key["pick_desc"]);
  108. setSnapshotId(key["snapshot_id"]);
  109. LLAvatarPropertiesProcessor::getInstance()->addObserver(
  110. getAvatarId(), this);
  111. LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(
  112. getAvatarId(), getPickId());
  113. }
  114. BOOL LLPanelPickInfo::postBuild()
  115. {
  116. mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
  117. childSetAction("teleport_btn", boost::bind(&LLPanelPickInfo::onClickTeleport, this));
  118. childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this));
  119. childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this));
  120. mScrollingPanel = getChild<LLPanel>("scroll_content_panel");
  121. mScrollContainer = getChild<LLScrollContainer>("profile_scroll");
  122. mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight();
  123. mScrollingPanelWidth = mScrollingPanel->getRect().getWidth();
  124. return TRUE;
  125. }
  126. void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
  127. {
  128. LLPanel::reshape(width, height, called_from_parent);
  129. if (!mScrollContainer || !mScrollingPanel)
  130. return;
  131. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  132. S32 scroll_height = mScrollContainer->getRect().getHeight();
  133. if (mScrollingPanelMinHeight >= scroll_height)
  134. {
  135. mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight);
  136. }
  137. else
  138. {
  139. mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height);
  140. }
  141. }
  142. void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)
  143. {
  144. if(APT_PICK_INFO != type)
  145. {
  146. return;
  147. }
  148. LLPickData* pick_info = static_cast<LLPickData*>(data);
  149. if(!pick_info
  150. || pick_info->creator_id != getAvatarId()
  151. || pick_info->pick_id != getPickId())
  152. {
  153. return;
  154. }
  155. mParcelId = pick_info->parcel_id;
  156. setSnapshotId(pick_info->snapshot_id);
  157. setPickName(pick_info->name);
  158. setPickDesc(pick_info->desc);
  159. setPosGlobal(pick_info->pos_global);
  160. // Send remote parcel info request to get parcel name and sim (region) name.
  161. sendParcelInfoRequest();
  162. // *NOTE dzaporozhan
  163. // We want to keep listening to APT_PICK_INFO because user may
  164. // edit the Pick and we have to update Pick info panel.
  165. // revomeObserver is called from onClickBack
  166. }
  167. void LLPanelPickInfo::sendParcelInfoRequest()
  168. {
  169. if (mParcelId != mRequestedId)
  170. {
  171. LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this);
  172. LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId);
  173. mRequestedId = mParcelId;
  174. }
  175. }
  176. void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)
  177. {
  178. getChild<LLButton>("back_btn")->setClickedCallback(cb);
  179. }
  180. void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)
  181. {
  182. setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name,
  183. parcel_data.sim_name, getPosGlobal()));
  184. // We have received parcel info for the requested ID so clear it now.
  185. mRequestedId.setNull();
  186. if (mParcelId.notNull())
  187. {
  188. LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
  189. }
  190. }
  191. void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb)
  192. {
  193. getChild<LLButton>("edit_btn")->setClickedCallback(cb);
  194. }
  195. // PROTECTED AREA
  196. void LLPanelPickInfo::resetControls()
  197. {
  198. if(getAvatarId() == gAgent.getID())
  199. {
  200. getChildView("edit_btn")->setEnabled(TRUE);
  201. getChildView("edit_btn")->setVisible( TRUE);
  202. }
  203. else
  204. {
  205. getChildView("edit_btn")->setEnabled(FALSE);
  206. getChildView("edit_btn")->setVisible( FALSE);
  207. }
  208. }
  209. void LLPanelPickInfo::resetData()
  210. {
  211. setPickName(LLStringUtil::null);
  212. setPickDesc(LLStringUtil::null);
  213. setPickLocation(LLStringUtil::null);
  214. setPickId(LLUUID::null);
  215. setSnapshotId(LLUUID::null);
  216. mPosGlobal.clearVec();
  217. mParcelId.setNull();
  218. mRequestedId.setNull();
  219. }
  220. // static
  221. std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global)
  222. {
  223. std::string location_text;
  224. location_text.append(owner_name);
  225. if (!original_name.empty())
  226. {
  227. if (!location_text.empty()) location_text.append(", ");
  228. location_text.append(original_name);
  229. }
  230. if (!sim_name.empty())
  231. {
  232. if (!location_text.empty()) location_text.append(", ");
  233. location_text.append(sim_name);
  234. }
  235. if (!location_text.empty()) location_text.append(" ");
  236. if (!pos_global.isNull())
  237. {
  238. S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
  239. S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
  240. S32 region_z = llround((F32)pos_global.mdV[VZ]);
  241. location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
  242. }
  243. return location_text;
  244. }
  245. void LLPanelPickInfo::setSnapshotId(const LLUUID& id)
  246. {
  247. mSnapshotCtrl->setImageAssetID(id);
  248. mSnapshotCtrl->setValid(TRUE);
  249. }
  250. void LLPanelPickInfo::setPickName(const std::string& name)
  251. {
  252. getChild<LLUICtrl>(XML_NAME)->setValue(name);
  253. }
  254. void LLPanelPickInfo::setPickDesc(const std::string& desc)
  255. {
  256. getChild<LLUICtrl>(XML_DESC)->setValue(desc);
  257. }
  258. void LLPanelPickInfo::setPickLocation(const std::string& location)
  259. {
  260. getChild<LLUICtrl>(XML_LOCATION)->setValue(location);
  261. }
  262. void LLPanelPickInfo::onClickMap()
  263. {
  264. LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
  265. LLFloaterReg::showInstance("world_map", "center");
  266. }
  267. void LLPanelPickInfo::onClickTeleport()
  268. {
  269. if (!getPosGlobal().isExactlyZero())
  270. {
  271. gAgent.teleportViaLocation(getPosGlobal());
  272. LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
  273. }
  274. }
  275. void LLPanelPickInfo::onClickBack()
  276. {
  277. LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
  278. }
  279. //////////////////////////////////////////////////////////////////////////
  280. //////////////////////////////////////////////////////////////////////////
  281. //////////////////////////////////////////////////////////////////////////
  282. //static
  283. LLPanelPickEdit* LLPanelPickEdit::create()
  284. {
  285. LLPanelPickEdit* panel = new LLPanelPickEdit();
  286. panel->buildFromFile(XML_PANEL_EDIT_PICK);
  287. return panel;
  288. }
  289. LLPanelPickEdit::LLPanelPickEdit()
  290. : LLPanelPickInfo()
  291. , mLocationChanged(false)
  292. , mNeedData(true)
  293. , mNewPick(false)
  294. {
  295. }
  296. LLPanelPickEdit::~LLPanelPickEdit()
  297. {
  298. }
  299. void LLPanelPickEdit::onOpen(const LLSD& key)
  300. {
  301. LLUUID pick_id = key["pick_id"];
  302. mNeedData = true;
  303. // creating new Pick
  304. if(pick_id.isNull())
  305. {
  306. mNewPick = true;
  307. setAvatarId(gAgent.getID());
  308. resetData();
  309. resetControls();
  310. setPosGlobal(gAgent.getPositionGlobal());
  311. LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null;
  312. std::string pick_name, pick_desc, region_name;
  313. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  314. if(parcel)
  315. {
  316. parcel_id = parcel->getID();
  317. pick_name = parcel->getName();
  318. pick_desc = parcel->getDesc();
  319. snapshot_id = parcel->getSnapshotID();
  320. }
  321. LLViewerRegion* region = gAgent.getRegion();
  322. if(region)
  323. {
  324. region_name = region->getName();
  325. }
  326. setParcelID(parcel_id);
  327. getChild<LLUICtrl>("pick_name")->setValue(pick_name.empty() ? region_name : pick_name);
  328. getChild<LLUICtrl>("pick_desc")->setValue(pick_desc);
  329. setSnapshotId(snapshot_id);
  330. setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal()));
  331. enableSaveButton(true);
  332. }
  333. // editing existing pick
  334. else
  335. {
  336. mNewPick = false;
  337. LLPanelPickInfo::onOpen(key);
  338. enableSaveButton(false);
  339. }
  340. resetDirty();
  341. }
  342. void LLPanelPickEdit::setPickData(const LLPickData* pick_data)
  343. {
  344. if(!pick_data)
  345. {
  346. return;
  347. }
  348. mNeedData = false;
  349. setParcelID(pick_data->parcel_id);
  350. getChild<LLUICtrl>("pick_name")->setValue(pick_data->name);
  351. getChild<LLUICtrl>("pick_desc")->setValue(pick_data->desc);
  352. setSnapshotId(pick_data->snapshot_id);
  353. setPosGlobal(pick_data->pos_global);
  354. setPickLocation(createLocationText(LLStringUtil::null, pick_data->name,
  355. pick_data->sim_name, pick_data->pos_global));
  356. }
  357. BOOL LLPanelPickEdit::postBuild()
  358. {
  359. LLPanelPickInfo::postBuild();
  360. mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this));
  361. LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
  362. line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL);
  363. LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
  364. text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
  365. childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this));
  366. childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this));
  367. initTexturePickerMouseEvents();
  368. return TRUE;
  369. }
  370. void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb)
  371. {
  372. getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
  373. }
  374. void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb)
  375. {
  376. getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
  377. }
  378. void LLPanelPickEdit::resetDirty()
  379. {
  380. LLPanelPickInfo::resetDirty();
  381. getChild<LLLineEditor>("pick_name")->resetDirty();
  382. getChild<LLTextEditor>("pick_desc")->resetDirty();
  383. mSnapshotCtrl->resetDirty();
  384. mLocationChanged = false;
  385. }
  386. BOOL LLPanelPickEdit::isDirty() const
  387. {
  388. if( mNewPick
  389. || LLPanelPickInfo::isDirty()
  390. || mLocationChanged
  391. || mSnapshotCtrl->isDirty()
  392. || getChild<LLLineEditor>("pick_name")->isDirty()
  393. || getChild<LLTextEditor>("pick_desc")->isDirty())
  394. {
  395. return TRUE;
  396. }
  397. return FALSE;
  398. }
  399. // PROTECTED AREA
  400. void LLPanelPickEdit::sendUpdate()
  401. {
  402. LLPickData pick_data;
  403. // If we don't have a pick id yet, we'll need to generate one,
  404. // otherwise we'll keep overwriting pick_id 00000 in the database.
  405. if (getPickId().isNull())
  406. {
  407. getPickId().generate();
  408. }
  409. pick_data.agent_id = gAgent.getID();
  410. pick_data.session_id = gAgent.getSessionID();
  411. pick_data.pick_id = getPickId();
  412. pick_data.creator_id = gAgent.getID();;
  413. //legacy var need to be deleted
  414. pick_data.top_pick = FALSE;
  415. pick_data.parcel_id = mParcelId;
  416. pick_data.name = getChild<LLUICtrl>(XML_NAME)->getValue().asString();
  417. pick_data.desc = getChild<LLUICtrl>(XML_DESC)->getValue().asString();
  418. pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
  419. pick_data.pos_global = getPosGlobal();
  420. pick_data.sort_order = 0;
  421. pick_data.enabled = TRUE;
  422. LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
  423. if(mNewPick)
  424. {
  425. // Assume a successful create pick operation, make new number of picks
  426. // available immediately. Actual number of picks will be requested in
  427. // LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond.
  428. LLAgentPicksInfo::getInstance()->incrementNumberOfPicks();
  429. }
  430. }
  431. void LLPanelPickEdit::onSnapshotChanged()
  432. {
  433. enableSaveButton(true);
  434. }
  435. void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl)
  436. {
  437. enableSaveButton(isDirty());
  438. }
  439. void LLPanelPickEdit::resetData()
  440. {
  441. LLPanelPickInfo::resetData();
  442. mLocationChanged = false;
  443. }
  444. void LLPanelPickEdit::enableSaveButton(bool enable)
  445. {
  446. getChildView(XML_BTN_SAVE)->setEnabled(enable);
  447. }
  448. void LLPanelPickEdit::onClickSetLocation()
  449. {
  450. // Save location for later use.
  451. setPosGlobal(gAgent.getPositionGlobal());
  452. std::string parcel_name, region_name;
  453. LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
  454. if (parcel)
  455. {
  456. mParcelId = parcel->getID();
  457. parcel_name = parcel->getName();
  458. }
  459. LLViewerRegion* region = gAgent.getRegion();
  460. if(region)
  461. {
  462. region_name = region->getName();
  463. }
  464. setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal()));
  465. mLocationChanged = true;
  466. enableSaveButton(TRUE);
  467. }
  468. void LLPanelPickEdit::onClickSave()
  469. {
  470. sendUpdate();
  471. mLocationChanged = false;
  472. LLSD params;
  473. params["action"] = "save_new_pick";
  474. notifyParent(params);
  475. }
  476. std::string LLPanelPickEdit::getLocationNotice()
  477. {
  478. static std::string notice = getString("location_notice");
  479. return notice;
  480. }
  481. void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type)
  482. {
  483. if(mNeedData)
  484. {
  485. LLPanelPickInfo::processProperties(data, type);
  486. }
  487. }
  488. // PRIVATE AREA
  489. void LLPanelPickEdit::initTexturePickerMouseEvents()
  490. {
  491. text_icon = getChild<LLIconCtrl>(XML_BTN_ON_TXTR);
  492. mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseEnter, this, _1));
  493. mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseLeave, this, _1));
  494. text_icon->setVisible(FALSE);
  495. }
  496. void LLPanelPickEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
  497. {
  498. text_icon->setVisible(TRUE);
  499. }
  500. void LLPanelPickEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
  501. {
  502. text_icon->setVisible(FALSE);
  503. }