llpanelteleporthistory.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:29k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpanelteleporthistory.cpp
  3.  * @brief Teleport history represented by a scrolling list
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloaterreg.h"
  34. #include "llfloaterworldmap.h"
  35. #include "llpanelteleporthistory.h"
  36. #include "llsidetray.h"
  37. #include "llworldmap.h"
  38. #include "llteleporthistorystorage.h"
  39. #include "lltextutil.h"
  40. #include "llaccordionctrl.h"
  41. #include "llaccordionctrltab.h"
  42. #include "llflatlistview.h"
  43. #include "llnotificationsutil.h"
  44. #include "lltextbox.h"
  45. #include "llviewermenu.h"
  46. #include "lllandmarkactions.h"
  47. #include "llclipboard.h"
  48. // Maximum number of items that can be added to a list in one pass.
  49. // Used to limit time spent for items list update per frame.
  50. static const U32 ADD_LIMIT = 50;
  51. static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
  52. class LLTeleportHistoryFlatItem : public LLPanel
  53. {
  54. public:
  55. LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl);
  56. virtual ~LLTeleportHistoryFlatItem();
  57. virtual BOOL postBuild();
  58. /*virtual*/ S32 notify(const LLSD& info);
  59. S32 getIndex() { return mIndex; }
  60. void setIndex(S32 index) { mIndex = index; }
  61. const std::string& getRegionName() { return mRegionName;}
  62. void setRegionName(const std::string& name);
  63. void setHighlightedText(const std::string& text);
  64. void updateTitle();
  65. /*virtual*/ void setValue(const LLSD& value);
  66. void onMouseEnter(S32 x, S32 y, MASK mask);
  67. void onMouseLeave(S32 x, S32 y, MASK mask);
  68. virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
  69. static void showPlaceInfoPanel(S32 index);
  70. LLHandle<LLTeleportHistoryFlatItem> getItemHandle() { mItemHandle.bind(this); return mItemHandle; }
  71. private:
  72. void onProfileBtnClick();
  73. LLButton* mProfileBtn;
  74. LLTextBox* mTitle;
  75. LLTeleportHistoryPanel::ContextMenu *mContextMenu;
  76. S32 mIndex;
  77. std::string mRegionName;
  78. std::string mHighlight;
  79. LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;
  80. };
  81. ////////////////////////////////////////////////////////////////////////////////
  82. ////////////////////////////////////////////////////////////////////////////////
  83. ////////////////////////////////////////////////////////////////////////////////
  84. class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> {
  85. protected:
  86. typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t;
  87. public:
  88. LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
  89. LLTeleportHistoryPanel::ContextMenu *context_menu,
  90. const LLTeleportHistoryPersistentItem& persistent_item,
  91. const S32 cur_item_index,
  92. const std::string &hl);
  93. void removeItem(LLTeleportHistoryFlatItem* item);
  94. void purge();
  95. private:
  96. flat_item_list_t mItems;
  97. };
  98. ////////////////////////////////////////////////////////////////////////////////
  99. ////////////////////////////////////////////////////////////////////////////////
  100. ////////////////////////////////////////////////////////////////////////////////
  101. LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl)
  102. : LLPanel(),
  103. mIndex(index),
  104. mContextMenu(context_menu),
  105. mRegionName(region_name),
  106. mHighlight(hl)
  107. {
  108. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml");
  109. }
  110. LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
  111. {
  112. }
  113. //virtual
  114. BOOL LLTeleportHistoryFlatItem::postBuild()
  115. {
  116. mTitle = getChild<LLTextBox>("region");
  117. mProfileBtn = getChild<LLButton>("profile_btn");
  118.         
  119. mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
  120. updateTitle();
  121. return true;
  122. }
  123. S32 LLTeleportHistoryFlatItem::notify(const LLSD& info)
  124. {
  125. if(info.has("detach"))
  126. {
  127. delete mMouseDownSignal;
  128. mMouseDownSignal = NULL;
  129. delete mRightMouseDownSignal;
  130. mRightMouseDownSignal = NULL;
  131. return 1;
  132. }
  133. return 0;
  134. }
  135. void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
  136. {
  137. if (!value.isMap()) return;;
  138. if (!value.has("selected")) return;
  139. childSetVisible("selected_icon", value["selected"]);
  140. }
  141. void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text)
  142. {
  143. mHighlight = text;
  144. }
  145. void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
  146. {
  147. mRegionName = name;
  148. }
  149. void LLTeleportHistoryFlatItem::updateTitle()
  150. {
  151. LLTextUtil::textboxSetHighlightedVal(
  152. mTitle,
  153. LLStyle::Params(),
  154. mRegionName,
  155. mHighlight);
  156. }
  157. void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
  158. {
  159. childSetVisible("hovered_icon", true);
  160. mProfileBtn->setVisible(true);
  161. LLPanel::onMouseEnter(x, y, mask);
  162. }
  163. void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
  164. {
  165. childSetVisible("hovered_icon", false);
  166. mProfileBtn->setVisible(false);
  167. LLPanel::onMouseLeave(x, y, mask);
  168. }
  169. // virtual
  170. BOOL LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
  171. {
  172. if (mContextMenu)
  173. mContextMenu->show(this, mIndex, x, y);
  174. return LLPanel::handleRightMouseDown(x, y, mask);
  175. }
  176. void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
  177. {
  178. LLSD params;
  179. params["id"] = index;
  180. params["type"] = "teleport_history";
  181. LLSideTray::getInstance()->showPanel("panel_places", params);
  182. }
  183. void LLTeleportHistoryFlatItem::onProfileBtnClick()
  184. {
  185. LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////
  188. ////////////////////////////////////////////////////////////////////////////////
  189. ////////////////////////////////////////////////////////////////////////////////
  190. LLTeleportHistoryFlatItem*
  191. LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
  192. LLTeleportHistoryPanel::ContextMenu *context_menu,
  193. const LLTeleportHistoryPersistentItem& persistent_item,
  194. const S32 cur_item_index,
  195. const std::string &hl)
  196. {
  197. LLTeleportHistoryFlatItem* item = NULL;
  198. if ( cur_item_index < (S32) mItems.size() )
  199. {
  200. item = mItems[cur_item_index].get();
  201. if (item->getParent() == NULL)
  202. {
  203. item->setIndex(cur_item_index);
  204. item->setRegionName(persistent_item.mTitle);
  205. item->setHighlightedText(hl);
  206. item->setVisible(TRUE);
  207. item->updateTitle();
  208. }
  209. else
  210. {
  211. // Item already added to parent
  212. item = NULL;
  213. }
  214. }
  215. if ( !item )
  216. {
  217. item = new LLTeleportHistoryFlatItem(cur_item_index,
  218.  context_menu,
  219.  persistent_item.mTitle,
  220.  hl);
  221. mItems.push_back(item->getItemHandle());
  222. }
  223. return item;
  224. }
  225. void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item)
  226. {
  227. if (item)
  228. {
  229. flat_item_list_t::iterator item_iter = std::find(mItems.begin(),
  230.  mItems.end(),
  231.  item->getItemHandle());
  232. if (item_iter != mItems.end())
  233. {
  234. mItems.erase(item_iter);
  235. }
  236. }
  237. }
  238. void LLTeleportHistoryFlatItemStorage::purge()
  239. {
  240. for ( flat_item_list_t::iterator
  241.   it = mItems.begin(),
  242.   it_end = mItems.end();
  243.   it != it_end; ++it )
  244. {
  245. LLHandle <LLTeleportHistoryFlatItem> item_handle = *it;
  246. if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL )
  247. {
  248. item_handle.get()->die();
  249. }
  250. }
  251. mItems.clear();
  252. }
  253. ////////////////////////////////////////////////////////////////////////////////
  254. ////////////////////////////////////////////////////////////////////////////////
  255. ////////////////////////////////////////////////////////////////////////////////
  256. LLTeleportHistoryPanel::ContextMenu::ContextMenu() :
  257. mMenu(NULL), mIndex(0)
  258. {
  259. }
  260. void LLTeleportHistoryPanel::ContextMenu::show(LLView* spawning_view, S32 index, S32 x, S32 y)
  261. {
  262. if (mMenu)
  263. {
  264. //preventing parent (menu holder) from deleting already "dead" context menus on exit
  265. LLView* parent = mMenu->getParent();
  266. if (parent)
  267. {
  268. parent->removeChild(mMenu);
  269. }
  270. delete mMenu;
  271. }
  272. mIndex = index;
  273. mMenu = createMenu();
  274. mMenu->show(x, y);
  275. LLMenuGL::showPopup(spawning_view, mMenu, x, y);
  276. }
  277. LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
  278. {
  279. // set up the callbacks for all of the avatar menu items
  280. // (N.B. callbacks don't take const refs as mID is local scope)
  281. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  282. registrar.add("TeleportHistory.Teleport", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this));
  283. registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this));
  284. registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
  285. // create the context menu from the XUI
  286. return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
  287. "menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
  288. }
  289. void LLTeleportHistoryPanel::ContextMenu::onTeleport()
  290. {
  291. LLTeleportHistoryStorage::getInstance()->goToItem(mIndex);
  292. }
  293. void LLTeleportHistoryPanel::ContextMenu::onInfo()
  294. {
  295. LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
  296. }
  297. //static
  298. void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl)
  299. {
  300. gClipboard.copyFromString(utf8str_to_wstring(slurl));
  301. }
  302. void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard()
  303. {
  304. LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
  305. LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
  306. boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
  307. }
  308. // Not yet implemented; need to remove buildPanel() from constructor when we switch
  309. //static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
  310. LLTeleportHistoryPanel::LLTeleportHistoryPanel()
  311. : LLPanelPlacesTab(),
  312. mDirty(true),
  313. mCurrentItem(0),
  314. mTeleportHistory(NULL),
  315. mHistoryAccordion(NULL),
  316. mAccordionTabMenu(NULL),
  317. mLastSelectedFlatlList(NULL),
  318. mLastSelectedItemIndex(-1)
  319. {
  320. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history.xml");
  321. }
  322. LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
  323. {
  324. LLTeleportHistoryFlatItemStorage::instance().purge();
  325. LLView::deleteViewByHandle(mGearMenuHandle);
  326. }
  327. BOOL LLTeleportHistoryPanel::postBuild()
  328. {
  329. mTeleportHistory = LLTeleportHistoryStorage::getInstance();
  330. if (mTeleportHistory)
  331. {
  332. mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1));
  333. }
  334. mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion");
  335. if (mHistoryAccordion)
  336. {
  337. for (child_list_const_iter_t iter = mHistoryAccordion->beginChild(); iter != mHistoryAccordion->endChild(); iter++)
  338. {
  339. if (dynamic_cast<LLAccordionCtrlTab*>(*iter))
  340. {
  341. LLAccordionCtrlTab* tab = (LLAccordionCtrlTab*)*iter;
  342. tab->setRightMouseDownCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionTabRightClick, this, _1, _2, _3, _4));
  343. tab->setDisplayChildren(false);
  344. tab->setDropDownStateChangedCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionExpand, this, _1, _2));
  345. // All accordion tabs are collapsed initially
  346. setAccordionCollapsedByUser(tab, true);
  347. mItemContainers.put(tab);
  348. LLFlatListView* fl = getFlatListViewFromTab(tab);
  349. if (fl)
  350. {
  351. fl->setCommitOnSelectionChange(true);
  352. fl->setDoubleClickCallback(boost::bind(&LLTeleportHistoryPanel::onDoubleClickItem, this));
  353. fl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, fl));
  354. fl->setReturnCallback(boost::bind(&LLTeleportHistoryPanel::onReturnKeyPressed, this));
  355. }
  356. }
  357. }
  358. // Open first 2 accordion tabs
  359. if (mItemContainers.size() > 1)
  360. {
  361. LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1);
  362. tab->setDisplayChildren(true);
  363. setAccordionCollapsedByUser(tab, false);
  364. }
  365. if (mItemContainers.size() > 2)
  366. {
  367. LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 2);
  368. tab->setDisplayChildren(true);
  369. setAccordionCollapsedByUser(tab, false);
  370. }
  371. }
  372. getChild<LLPanel>("bottom_panel")->childSetAction("gear_btn",boost::bind(&LLTeleportHistoryPanel::onGearButtonClicked, this));
  373. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  374. registrar.add("TeleportHistory.ExpandAllFolders",  boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders,  this));
  375. registrar.add("TeleportHistory.CollapseAllFolders",  boost::bind(&LLTeleportHistoryPanel::onCollapseAllFolders,  this));
  376. registrar.add("TeleportHistory.ClearTeleportHistory",  boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory,  this));
  377. mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
  378. LLMenuGL* gear_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_teleport_history_gear.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  379. if(gear_menu)
  380. mGearMenuHandle  = gear_menu->getHandle();
  381. return TRUE;
  382. }
  383. // virtual
  384. void LLTeleportHistoryPanel::draw()
  385. {
  386. if (mDirty)
  387. refresh();
  388. LLPanelPlacesTab::draw();
  389. }
  390. // virtual
  391. void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
  392. {
  393. sFilterSubString = string;
  394. showTeleportHistory();
  395. }
  396. // virtual
  397. void LLTeleportHistoryPanel::onShowOnMap()
  398. {
  399. if (!mLastSelectedFlatlList)
  400. return;
  401. LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
  402. if(!itemp)
  403. return;
  404. LLVector3d global_pos = mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos;
  405. if (!global_pos.isExactlyZero())
  406. {
  407. LLFloaterWorldMap::getInstance()->trackLocation(global_pos);
  408. LLFloaterReg::showInstance("world_map", "center");
  409. }
  410. }
  411. // virtual
  412. void LLTeleportHistoryPanel::onTeleport()
  413. {
  414. if (!mLastSelectedFlatlList)
  415. return;
  416. LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
  417. if(!itemp)
  418. return;
  419. // teleport to existing item in history, so we don't add it again
  420. mTeleportHistory->goToItem(itemp->getIndex());
  421. }
  422. /*
  423. // virtual
  424. void LLTeleportHistoryPanel::onCopySLURL()
  425. {
  426. LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
  427. if(!itemp)
  428. return;
  429. S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
  430. const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
  431. LLVector3d global_pos = hist_items[index].mGlobalPos;
  432. U64 new_region_handle = to_region_handle(global_pos);
  433. LLWorldMapMessage::url_callback_t cb = boost::bind(
  434. &LLPanelPlacesTab::onRegionResponse, this,
  435. global_pos, _1, _2, _3, _4);
  436. LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
  437. }
  438. */
  439. // virtual
  440. void LLTeleportHistoryPanel::updateVerbs()
  441. {
  442. if (!isTabVisible())
  443. return;
  444. if (!mLastSelectedFlatlList)
  445. {
  446. mTeleportBtn->setEnabled(false);
  447. mShowOnMapBtn->setEnabled(false);
  448. return;
  449. }
  450. LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
  451. mTeleportBtn->setEnabled(NULL != itemp);
  452. mShowOnMapBtn->setEnabled(NULL != itemp);
  453. }
  454. void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
  455. {
  456. const U32 seconds_in_day = 24 * 60 * 60;
  457. S32 tabs_cnt = mItemContainers.size();
  458. S32 curr_year = 0, curr_month = 0, curr_day = 0;
  459. tab_date = LLDate::now();
  460. tab_date.split(&curr_year, &curr_month, &curr_day);
  461. tab_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
  462. tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() + seconds_in_day);
  463. tab_idx = -1;
  464. while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
  465. {
  466. tab_idx++;
  467. if (tab_idx <= tabs_cnt - 4)
  468. {
  469. // All tabs, except last three, are tabs for one day, so just push tab_date back by one day
  470. tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
  471. }
  472. else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
  473. {
  474. tab_date =  LLDate::now();
  475. tab_date.split(&curr_year, &curr_month, &curr_day);
  476. curr_month--;
  477. if (0 == curr_month)
  478. {
  479. curr_month = 12;
  480. curr_year--;
  481. }
  482. tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
  483. }
  484. else if (tab_idx == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
  485. {
  486. tab_date =  LLDate::now();
  487. tab_date.split(&curr_year, &curr_month, &curr_day);
  488. if (curr_month > 6)
  489. {
  490. curr_month -= 6;
  491. }
  492. else
  493. {
  494. curr_month += 6;
  495. curr_year--;
  496. }
  497. tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
  498. }
  499. else // 6 months and older
  500. {
  501. tab_date.secondsSinceEpoch(0);
  502. }
  503. }
  504. }
  505. // Called to add items, no more, than ADD_LIMIT at time
  506. void LLTeleportHistoryPanel::refresh()
  507. {
  508. if (!mHistoryAccordion)
  509. {
  510. mDirty = false;
  511. return;
  512. }
  513. const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
  514. // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary.
  515. // That leads to call to getNextTab to get right tab_idx in first pass
  516. LLDate tab_boundary_date =  LLDate::now();
  517. LLFlatListView* curr_flat_view = NULL;
  518. U32 added_items = 0;
  519. while (mCurrentItem >= 0)
  520. {
  521. // Filtering
  522. if (!sFilterSubString.empty())
  523. {
  524. std::string landmark_title(items[mCurrentItem].mTitle);
  525. LLStringUtil::toUpper(landmark_title);
  526. if( std::string::npos == landmark_title.find(sFilterSubString) )
  527. {
  528. mCurrentItem--;
  529. continue;
  530. }
  531. }
  532. // Checking whether date of item is earlier, than tab_boundary_date.
  533. // In that case, item should be added to another tab
  534. const LLDate &date = items[mCurrentItem].mDate;
  535. if (date < tab_boundary_date)
  536. {
  537. // Getting apropriate tab_idx for this and subsequent items,
  538. // tab_boundary_date would be earliest possible date for this tab
  539. S32 tab_idx = 0;
  540. getNextTab(date, tab_idx, tab_boundary_date);
  541. LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1 - tab_idx);
  542. tab->setVisible(true);
  543. // Expand all accordion tabs when filtering
  544. if(!sFilterSubString.empty())
  545. {
  546. //store accordion tab state when filter is not empty
  547. tab->notifyChildren(LLSD().with("action","store_state"));
  548. tab->setDisplayChildren(true);
  549. }
  550. // Restore each tab's expand state when not filtering
  551. else
  552. {
  553. bool collapsed = isAccordionCollapsedByUser(tab);
  554. tab->setDisplayChildren(!collapsed);
  555. //restore accordion state after all those accodrion tabmanipulations
  556. tab->notifyChildren(LLSD().with("action","restore_state"));
  557. }
  558. curr_flat_view = getFlatListViewFromTab(tab);
  559. }
  560. if (curr_flat_view)
  561. {
  562. LLTeleportHistoryFlatItem* item =
  563. LLTeleportHistoryFlatItemStorage::instance()
  564. .getFlatItemForPersistentItem(&mContextMenu,
  565.   items[mCurrentItem],
  566.   mCurrentItem,
  567.   sFilterSubString);
  568. if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) )
  569. llerrs << "Couldn't add flat item to teleport history." << llendl;
  570. if (mLastSelectedItemIndex == mCurrentItem)
  571. curr_flat_view->selectItem(item, true);
  572. }
  573. mCurrentItem--;
  574. if (++added_items >= ADD_LIMIT)
  575. break;
  576. }
  577. for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
  578. {
  579. LLAccordionCtrlTab* tab = mItemContainers.get(n);
  580. LLFlatListView* fv = getFlatListViewFromTab(tab);
  581. if (fv)
  582. {
  583. fv->notify(LLSD().with("rearrange", LLSD()));
  584. }
  585. }
  586. mHistoryAccordion->arrange();
  587. updateVerbs();
  588. if (mCurrentItem < 0)
  589. mDirty = false;
  590. }
  591. void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index)
  592. {
  593. mLastSelectedItemIndex = -1;
  594. if (-1 == removed_index)
  595. showTeleportHistory(); // recreate all items
  596. else
  597. {
  598. replaceItem(removed_index); // replace removed item by most recent
  599. updateVerbs();
  600. }
  601. }
  602. void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
  603. {
  604. // Flat list for 'Today' (mItemContainers keeps accordion tabs in reverse order)
  605. LLFlatListView* fv = getFlatListViewFromTab(mItemContainers[mItemContainers.size() - 1]);
  606. // Empty flat list for 'Today' means that other flat lists are empty as well,
  607. // so all items from teleport history should be added.
  608. if (!fv || fv->size() == 0)
  609. {
  610. showTeleportHistory();
  611. return;
  612. }
  613. const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
  614. LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
  615. .getFlatItemForPersistentItem(&mContextMenu,
  616.   history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
  617.   history_items.size(), // index will be decremented inside loop below
  618.   sFilterSubString);
  619. fv->addItem(item, LLUUID::null, ADD_TOP);
  620. // Index of each item, from last to removed item should be decremented
  621. // to point to the right item in LLTeleportHistoryStorage
  622. for (S32 tab_idx = mItemContainers.size() - 1; tab_idx >= 0; --tab_idx)
  623. {
  624. LLAccordionCtrlTab* tab = mItemContainers.get(tab_idx);
  625. if (!tab->getVisible())
  626. continue;
  627. fv = getFlatListViewFromTab(tab);
  628. if (!fv)
  629. {
  630. showTeleportHistory();
  631. return;
  632. }
  633. std::vector<LLPanel*> items;
  634. fv->getItems(items);
  635. S32 items_cnt = items.size();
  636. for (S32 n = 0; n < items_cnt; ++n)
  637. {
  638. LLTeleportHistoryFlatItem *item = (LLTeleportHistoryFlatItem*) items[n];
  639. if (item->getIndex() == removed_index)
  640. {
  641. LLTeleportHistoryFlatItemStorage::instance().removeItem(item);
  642. fv->removeItem(item);
  643. // If flat list becames empty, then accordion tab should be hidden
  644. if (fv->size() == 0)
  645. tab->setVisible(false);
  646. mHistoryAccordion->arrange();
  647. return; // No need to decrement idexes for the rest of items
  648. }
  649. item->setIndex(item->getIndex() - 1);
  650. }
  651. }
  652. }
  653. void LLTeleportHistoryPanel::showTeleportHistory()
  654. {
  655. mDirty = true;
  656. // Starting to add items from last one, in reverse order,
  657. // since TeleportHistory keeps most recent item at the end
  658. mCurrentItem = mTeleportHistory->getItems().size() - 1;
  659. for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
  660. {
  661. LLAccordionCtrlTab* tab = mItemContainers.get(n);
  662. tab->setVisible(false);
  663. LLFlatListView* fv = getFlatListViewFromTab(tab);
  664. if (fv)
  665. {
  666. // Detached panels are managed by LLTeleportHistoryFlatItemStorage
  667. std::vector<LLPanel*> detached_items;
  668. fv->detachItems(detached_items);
  669. }
  670. }
  671. }
  672. void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
  673. {
  674. mLastSelectedFlatlList = selected;
  675. LLTeleportHistoryFlatItem* item = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
  676. if (item)
  677. mLastSelectedItemIndex = item->getIndex();
  678. S32 tabs_cnt = mItemContainers.size();
  679. for (S32 n = 0; n < tabs_cnt; n++)
  680. {
  681. LLAccordionCtrlTab* tab = mItemContainers.get(n);
  682. if (!tab->getVisible())
  683. continue;
  684. LLFlatListView *flv = getFlatListViewFromTab(tab);
  685. if (!flv)
  686. continue;
  687. if (flv == selected)
  688. continue;
  689. flv->resetSelection(true);
  690. }
  691. updateVerbs();
  692. }
  693. void LLTeleportHistoryPanel::onReturnKeyPressed()
  694. {
  695. // Teleport to selected region as default action on return key pressed
  696. onTeleport();
  697. }
  698. void LLTeleportHistoryPanel::onDoubleClickItem()
  699. {
  700. // If item got doubleclick, then that item is already selected
  701. onTeleport();
  702. }
  703. void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask)
  704. {
  705. LLAccordionCtrlTab *tab = (LLAccordionCtrlTab *) view;
  706. // If click occurred below the header, don't show this menu
  707. if (y < tab->getRect().getHeight() - tab->getHeaderHeight() - tab->getPaddingBottom())
  708. return;
  709. if (mAccordionTabMenu)
  710. {
  711. //preventing parent (menu holder) from deleting already "dead" context menus on exit
  712. LLView* parent = mAccordionTabMenu->getParent();
  713. if (parent)
  714. {
  715. parent->removeChild(mAccordionTabMenu);
  716. }
  717. delete mAccordionTabMenu;
  718. }
  719. // set up the callbacks for all of the avatar menu items
  720. // (N.B. callbacks don't take const refs as mID is local scope)
  721. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  722. registrar.add("TeleportHistory.TabOpen", boost::bind(&LLTeleportHistoryPanel::onAccordionTabOpen, this, tab));
  723. registrar.add("TeleportHistory.TabClose", boost::bind(&LLTeleportHistoryPanel::onAccordionTabClose, this, tab));
  724. // create the context menu from the XUI
  725. mAccordionTabMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
  726. "menu_teleport_history_tab.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
  727. mAccordionTabMenu->setItemVisible("TabOpen", !tab->isExpanded() ? true : false);
  728. mAccordionTabMenu->setItemVisible("TabClose", tab->isExpanded() ? true : false);
  729. mAccordionTabMenu->show(x, y);
  730. LLMenuGL::showPopup(tab, mAccordionTabMenu, x, y);
  731. }
  732. void LLTeleportHistoryPanel::onAccordionTabOpen(LLAccordionCtrlTab *tab)
  733. {
  734. tab->setDisplayChildren(true);
  735. mHistoryAccordion->arrange();
  736. }
  737. void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab)
  738. {
  739. tab->setDisplayChildren(false);
  740. mHistoryAccordion->arrange();
  741. }
  742. void LLTeleportHistoryPanel::onExpandAllFolders()
  743. {
  744. S32 tabs_cnt = mItemContainers.size();
  745. for (S32 n = 0; n < tabs_cnt; n++)
  746. {
  747. mItemContainers.get(n)->setDisplayChildren(true);
  748. }
  749. mHistoryAccordion->arrange();
  750. }
  751. void LLTeleportHistoryPanel::onCollapseAllFolders()
  752. {
  753. S32 tabs_cnt = mItemContainers.size();
  754. for (S32 n = 0; n < tabs_cnt; n++)
  755. {
  756. mItemContainers.get(n)->setDisplayChildren(false);
  757. }
  758. mHistoryAccordion->arrange();
  759. }
  760. void LLTeleportHistoryPanel::onClearTeleportHistory()
  761. {
  762. LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
  763. }
  764. bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response)
  765. {
  766. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  767. if (0 == option)
  768. {
  769. // order does matter, call this first or teleport history will contain one record(current location)
  770. LLTeleportHistory::getInstance()->purgeItems();
  771. LLTeleportHistoryStorage *th = LLTeleportHistoryStorage::getInstance();
  772. th->purgeItems();
  773. th->save();
  774. }
  775. return false;
  776. }
  777. LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTab *tab)
  778. {
  779. for (child_list_const_iter_t iter = tab->beginChild(); iter != tab->endChild(); iter++)
  780. {
  781. if (dynamic_cast<LLFlatListView*>(*iter))
  782. {
  783. return (LLFlatListView*)*iter; // There should be one scroll list per tab.
  784. }
  785. }
  786. return NULL;
  787. }
  788. void LLTeleportHistoryPanel::onGearButtonClicked()
  789. {
  790. LLMenuGL* menu = (LLMenuGL*)mGearMenuHandle.get();
  791. if (!menu)
  792. return;
  793. // Shows the menu at the top of the button bar.
  794. // Calculate its coordinates.
  795. LLPanel* bottom_panel = getChild<LLPanel>("bottom_panel");
  796. menu->arrangeAndClear();
  797. S32 menu_height = menu->getRect().getHeight();
  798. S32 menu_x = -2; // *HACK: compensates HPAD in showPopup()
  799. S32 menu_y = bottom_panel->getRect().mTop + menu_height;
  800. // Actually show the menu.
  801. menu->buildDrawLabels();
  802. menu->updateParent(LLMenuGL::sMenuContainer);
  803. LLMenuGL::showPopup(this, menu, menu_x, menu_y);
  804. }
  805. bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
  806. {
  807. S32 tabs_cnt = mItemContainers.size();
  808. bool has_expanded_tabs = false;
  809. bool has_collapsed_tabs = false;
  810. for (S32 n = 0; n < tabs_cnt; n++)
  811. {
  812. LLAccordionCtrlTab* tab = mItemContainers.get(n);
  813. if (!tab->getVisible())
  814. continue;
  815. if (tab->getDisplayChildren())
  816. {
  817. has_expanded_tabs = true;
  818. }
  819. else
  820. {
  821. has_collapsed_tabs = true;
  822. }
  823. if (has_expanded_tabs && has_collapsed_tabs)
  824. {
  825. break;
  826. }
  827. }
  828. std::string command_name = userdata.asString();
  829. if (has_expanded_tabs && command_name == "collapse_all")
  830. {
  831. return true;
  832. }
  833. if (has_collapsed_tabs && command_name ==  "expand_all")
  834. {
  835. return true;
  836. }
  837. return false;
  838. }
  839. void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed)
  840. {
  841. LLSD param = acc_tab->getValue();
  842. param[COLLAPSED_BY_USER] = collapsed;
  843. acc_tab->setValue(param);
  844. }
  845. bool LLTeleportHistoryPanel::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
  846. {
  847. LLSD param = acc_tab->getValue();
  848. if(!param.has(COLLAPSED_BY_USER))
  849. {
  850. return false;
  851. }
  852. return param[COLLAPSED_BY_USER].asBoolean();
  853. }
  854. void LLTeleportHistoryPanel::onAccordionExpand(LLUICtrl* ctrl, const LLSD& param)
  855. {
  856. bool expanded = param.asBoolean();
  857. // Save accordion tab state to restore it in refresh()
  858. setAccordionCollapsedByUser(ctrl, !expanded);
  859. // Reset selection upon accordion being collapsed
  860. // to disable "Teleport" and "Map" buttons for hidden item.
  861. if (!expanded && mLastSelectedFlatlList)
  862. {
  863. mLastSelectedFlatlList->resetSelection();
  864. }
  865. }