summaryrefslogtreecommitdiff
path: root/indra/newview/llpanelteleporthistory.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llpanelteleporthistory.cpp
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (diff)
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/cmake/CMakeLists.txt # indra/cmake/GoogleMock.cmake # indra/llaudio/llaudioengine_fmodstudio.cpp # indra/llaudio/llaudioengine_fmodstudio.h # indra/llaudio/lllistener_fmodstudio.cpp # indra/llaudio/lllistener_fmodstudio.h # indra/llaudio/llstreamingaudio_fmodstudio.cpp # indra/llaudio/llstreamingaudio_fmodstudio.h # indra/llcharacter/llmultigesture.cpp # indra/llcharacter/llmultigesture.h # indra/llimage/llimage.cpp # indra/llimage/llimagepng.cpp # indra/llimage/llimageworker.cpp # indra/llimage/tests/llimageworker_test.cpp # indra/llmessage/tests/llmockhttpclient.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llfontfreetype.cpp # indra/llui/llcombobox.cpp # indra/llui/llfolderview.cpp # indra/llui/llfolderviewmodel.h # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltextvalidate.cpp # indra/llui/lltextvalidate.h # indra/llui/lluictrl.h # indra/llui/llview.cpp # indra/llwindow/llwindowmacosx.cpp # indra/newview/app_settings/settings.xml # indra/newview/llappearancemgr.cpp # indra/newview/llappearancemgr.h # indra/newview/llavatarpropertiesprocessor.cpp # indra/newview/llavatarpropertiesprocessor.h # indra/newview/llbreadcrumbview.cpp # indra/newview/llbreadcrumbview.h # indra/newview/llbreastmotion.cpp # indra/newview/llbreastmotion.h # indra/newview/llconversationmodel.h # indra/newview/lldensityctrl.cpp # indra/newview/lldensityctrl.h # indra/newview/llface.inl # indra/newview/llfloatereditsky.cpp # indra/newview/llfloatereditwater.cpp # indra/newview/llfloateremojipicker.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterprofiletexture.cpp # indra/newview/llfloaterprofiletexture.h # indra/newview/llgesturemgr.cpp # indra/newview/llgesturemgr.h # indra/newview/llimpanel.cpp # indra/newview/llimpanel.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryclipboard.cpp # indra/newview/llinventoryclipboard.h # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventoryfunctions.h # indra/newview/llinventorygallery.cpp # indra/newview/lllistbrowser.cpp # indra/newview/lllistbrowser.h # indra/newview/llpanelobjectinventory.cpp # indra/newview/llpanelprofile.cpp # indra/newview/llpanelprofile.h # indra/newview/llpreviewgesture.cpp # indra/newview/llsavedsettingsglue.cpp # indra/newview/llsavedsettingsglue.h # indra/newview/lltooldraganddrop.cpp # indra/newview/llurllineeditorctrl.cpp # indra/newview/llvectorperfoptions.cpp # indra/newview/llvectorperfoptions.h # indra/newview/llviewerparceloverlay.cpp # indra/newview/llviewertexlayer.cpp # indra/newview/llviewertexturelist.cpp # indra/newview/macmain.h # indra/test/test.cpp
Diffstat (limited to 'indra/newview/llpanelteleporthistory.cpp')
-rw-r--r--indra/newview/llpanelteleporthistory.cpp2394
1 files changed, 1197 insertions, 1197 deletions
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 5e6e61b6b3..05a5fffe15 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -1,1197 +1,1197 @@
-/**
- * @file llpanelteleporthistory.cpp
- * @brief Teleport history represented by a scrolling list
- *
- * $LicenseInfo:firstyear=2009&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 "llfloaterreg.h"
-#include "llmenubutton.h"
-
-#include "llfloaterworldmap.h"
-#include "llpanelteleporthistory.h"
-#include "llworldmap.h"
-#include "llteleporthistorystorage.h"
-#include "lltextutil.h"
-
-#include "llaccordionctrl.h"
-#include "llaccordionctrltab.h"
-#include "llflatlistview.h"
-#include "llfloatersidepanelcontainer.h"
-#include "llnotificationsutil.h"
-#include "lltextbox.h"
-#include "lltoggleablemenu.h"
-#include "llviewermenu.h"
-#include "lllandmarkactions.h"
-#include "llclipboard.h"
-#include "lltrans.h"
-
-// Maximum number of items that can be added to a list in one pass.
-// Used to limit time spent for items list update per frame.
-static const U32 ADD_LIMIT = 50;
-
-static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
-
-class LLTeleportHistoryFlatItem : public LLPanel
-{
-public:
- LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
- LLDate date, const std::string &hl);
- virtual ~LLTeleportHistoryFlatItem();
-
- virtual bool postBuild();
-
- /*virtual*/ S32 notify(const LLSD& info);
-
- S32 getIndex() { return mIndex; }
- void setIndex(S32 index) { mIndex = index; }
- const std::string& getRegionName() { return mRegionName;}
- void setRegionName(const std::string& name);
- void setDate(LLDate date);
- void setHighlightedText(const std::string& text);
- void updateTitle();
- void updateTimestamp();
- std::string getTimestamp();
-
- /*virtual*/ void setValue(const LLSD& value);
-
- void onMouseEnter(S32 x, S32 y, MASK mask);
- void onMouseLeave(S32 x, S32 y, MASK mask);
- virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask);
-
- static void showPlaceInfoPanel(S32 index);
-
- LLHandle<LLTeleportHistoryFlatItem> getItemHandle() { mItemHandle.bind(this); return mItemHandle; }
-
-private:
- void onProfileBtnClick();
- void showMenu(S32 x, S32 y);
-
- LLButton* mProfileBtn;
- LLTextBox* mTitle;
- LLTextBox* mTimeTextBox;
-
- LLToggleableMenu *mMenu;
-
- S32 mIndex;
- std::string mRegionName;
- std::string mHighlight;
- LLDate mDate;
- LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage>
-{
- LLSINGLETON_EMPTY_CTOR(LLTeleportHistoryFlatItemStorage);
-protected:
- typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t;
-
-public:
- LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
- LLToggleableMenu *menu,
- const LLTeleportHistoryPersistentItem& persistent_item,
- const S32 cur_item_index,
- const std::string &hl);
-
- void removeItem(LLTeleportHistoryFlatItem* item);
-
- void purge();
-
-private:
-
- flat_item_list_t mItems;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
- LLDate date, const std::string &hl)
-: LLPanel(),
- mIndex(index),
- mMenu(menu),
- mRegionName(region_name),
- mDate(date),
- mHighlight(hl)
-{
- buildFromFile("panel_teleport_history_item.xml");
-}
-
-LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
-{
-}
-
-//virtual
-bool LLTeleportHistoryFlatItem::postBuild()
-{
- mTitle = getChild<LLTextBox>("region");
-
- mTimeTextBox = getChild<LLTextBox>("timestamp");
-
- mProfileBtn = getChild<LLButton>("profile_btn");
-
- mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
-
- updateTitle();
- updateTimestamp();
-
- return true;
-}
-
-S32 LLTeleportHistoryFlatItem::notify(const LLSD& info)
-{
- if(info.has("detach"))
- {
- delete mMouseDownSignal;
- mMouseDownSignal = NULL;
- delete mRightMouseDownSignal;
- mRightMouseDownSignal = NULL;
- return 1;
- }
- return 0;
-}
-
-void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
-{
- if (!value.isMap()) return;;
- if (!value.has("selected")) return;
- getChildView("selected_icon")->setVisible( value["selected"]);
-}
-
-void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text)
-{
- mHighlight = text;
-}
-
-void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
-{
- mRegionName = name;
-}
-
-void LLTeleportHistoryFlatItem::setDate(LLDate date)
-{
- mDate = date;
-}
-
-std::string LLTeleportHistoryFlatItem::getTimestamp()
-{
- const LLDate &date = mDate;
- std::string timestamp = "";
-
- LLDate now = LLDate::now();
- S32 now_year, now_month, now_day, now_hour, now_min, now_sec;
- now.split(&now_year, &now_month, &now_day, &now_hour, &now_min, &now_sec);
-
- const S32 seconds_in_day = 24 * 60 * 60;
- S32 seconds_today = now_hour * 60 * 60 + now_min * 60 + now_sec;
- S32 time_diff = (S32) now.secondsSinceEpoch() - (S32) date.secondsSinceEpoch();
-
- // Only show timestamp for today and yesterday
- if(time_diff < seconds_today + seconds_in_day)
- {
- timestamp = "[" + LLTrans::getString("TimeHour12")+"]:["
- + LLTrans::getString("TimeMin")+"] ["+ LLTrans::getString("TimeAMPM")+"]";
- LLSD substitution;
- substitution["datetime"] = (S32) date.secondsSinceEpoch();
- LLStringUtil::format(timestamp, substitution);
- }
-
- return timestamp;
-
-}
-
-void LLTeleportHistoryFlatItem::updateTitle()
-{
- static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
-
- LLTextUtil::textboxSetHighlightedVal(
- mTitle,
- LLStyle::Params().color(sFgColor),
- mRegionName,
- mHighlight);
-}
-
-void LLTeleportHistoryFlatItem::updateTimestamp()
-{
- static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
-
- LLTextUtil::textboxSetHighlightedVal(
- mTimeTextBox,
- LLStyle::Params().color(sFgColor),
- getTimestamp(),
- mHighlight);
-}
-
-void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
-{
- getChildView("hovered_icon")->setVisible( true);
- mProfileBtn->setVisible(true);
-
- LLPanel::onMouseEnter(x, y, mask);
-}
-
-void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
-{
- getChildView("hovered_icon")->setVisible( false);
- mProfileBtn->setVisible(false);
-
- LLPanel::onMouseLeave(x, y, mask);
-}
-
-// virtual
-bool LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- LLPanel::handleRightMouseDown(x, y, mask);
- showMenu(x, y);
- return true;
-}
-
-void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
-{
- LLSD params;
- params["id"] = index;
- params["type"] = "teleport_history";
-
- LLFloaterSidePanelContainer::showPanel("places", params);
-}
-
-void LLTeleportHistoryFlatItem::onProfileBtnClick()
-{
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
-}
-
-void LLTeleportHistoryFlatItem::showMenu(S32 x, S32 y)
-{
- mMenu->setButtonRect(this);
- mMenu->buildDrawLabels();
- mMenu->arrangeAndClear();
- mMenu->updateParent(LLMenuGL::sMenuContainer);
-
- LLMenuGL::showPopup(this, mMenu, x, y);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-LLTeleportHistoryFlatItem*
-LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
- LLToggleableMenu *menu,
- const LLTeleportHistoryPersistentItem& persistent_item,
- const S32 cur_item_index,
- const std::string &hl)
-{
- LLTeleportHistoryFlatItem* item = NULL;
- if ( cur_item_index < (S32) mItems.size() )
- {
- item = mItems[cur_item_index].get();
- if (item->getParent() == NULL)
- {
- item->setIndex(cur_item_index);
- item->setRegionName(persistent_item.mTitle);
- item->setDate(persistent_item.mDate);
- item->setHighlightedText(hl);
- item->setVisible(true);
- item->updateTitle();
- item->updateTimestamp();
- }
- else
- {
- // Item already added to parent
- item = NULL;
- }
- }
-
- if ( !item )
- {
- item = new LLTeleportHistoryFlatItem(cur_item_index,
- menu,
- persistent_item.mTitle,
- persistent_item.mDate,
- hl);
- mItems.push_back(item->getItemHandle());
- }
-
- return item;
-}
-
-void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item)
-{
- if (item)
- {
- flat_item_list_t::iterator item_iter = std::find(mItems.begin(),
- mItems.end(),
- item->getItemHandle());
- if (item_iter != mItems.end())
- {
- mItems.erase(item_iter);
- }
- }
-}
-
-void LLTeleportHistoryFlatItemStorage::purge()
-{
- for ( flat_item_list_t::iterator
- it = mItems.begin(),
- it_end = mItems.end();
- it != it_end; ++it )
- {
- LLHandle <LLTeleportHistoryFlatItem> item_handle = *it;
- if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL )
- {
- item_handle.get()->die();
- }
- }
- mItems.clear();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-
-// Not yet implemented; need to remove buildPanel() from constructor when we switch
-//static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
-
-LLTeleportHistoryPanel::LLTeleportHistoryPanel()
- : LLPanelPlacesTab(),
- mDirty(true),
- mCurrentItem(0),
- mTeleportHistory(NULL),
- mHistoryAccordion(NULL),
- mAccordionTabMenu(NULL),
- mLastSelectedFlatlList(NULL),
- mLastSelectedItemIndex(-1),
- mGearItemMenu(NULL),
- mSortingMenu(NULL)
-{
- buildFromFile( "panel_teleport_history.xml");
-}
-
-LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
-{
- LLTeleportHistoryFlatItemStorage::instance().purge();
- mTeleportHistoryChangedConnection.disconnect();
-}
-
-bool LLTeleportHistoryPanel::postBuild()
-{
- mCommitCallbackRegistrar.add("TeleportHistory.GearMenu.Action", boost::bind(&LLTeleportHistoryPanel::onGearMenuAction, this, _2));
- mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
-
- // init menus before list, since menus are passed to list
- mGearItemMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_item.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mGearItemMenu->setAlwaysShowMenu(true); // all items can be disabled if nothing is selected, show anyway
- mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-
- mTeleportHistory = LLTeleportHistoryStorage::getInstance();
- if (mTeleportHistory)
- {
- mTeleportHistoryChangedConnection = mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1));
- }
-
- mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion");
-
- if (mHistoryAccordion)
- {
- for (child_list_const_iter_t iter = mHistoryAccordion->beginChild(); iter != mHistoryAccordion->endChild(); iter++)
- {
- if (dynamic_cast<LLAccordionCtrlTab*>(*iter))
- {
- LLAccordionCtrlTab* tab = (LLAccordionCtrlTab*)*iter;
- tab->setRightMouseDownCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionTabRightClick, this, _1, _2, _3, _4));
- tab->setDisplayChildren(false);
- tab->setDropDownStateChangedCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionExpand, this, _1, _2));
-
- // All accordion tabs are collapsed initially
- setAccordionCollapsedByUser(tab, true);
-
- mItemContainers.push_back(tab);
-
- LLFlatListView* fl = getFlatListViewFromTab(tab);
- if (fl)
- {
- fl->setCommitOnSelectionChange(true);
- fl->setDoubleClickCallback(boost::bind(&LLTeleportHistoryPanel::onDoubleClickItem, this));
- fl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, fl));
- fl->setReturnCallback(boost::bind(&LLTeleportHistoryPanel::onReturnKeyPressed, this));
- }
- }
- }
-
- // Open first 2 accordion tabs
- if (mItemContainers.size() > 1)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(mItemContainers.size() - 1);
- tab->setDisplayChildren(true);
- setAccordionCollapsedByUser(tab, false);
- }
-
- if (mItemContainers.size() > 2)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(mItemContainers.size() - 2);
- tab->setDisplayChildren(true);
- setAccordionCollapsedByUser(tab, false);
- }
- }
-
- return true;
-}
-
-// virtual
-void LLTeleportHistoryPanel::draw()
-{
- if (mDirty)
- refresh();
-
- LLPanelPlacesTab::draw();
-}
-
-// virtual
-void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
-{
- sFilterSubString = string;
- showTeleportHistory();
-}
-
-// virtual
-bool LLTeleportHistoryPanel::isSingleItemSelected()
-{
- return mLastSelectedFlatlList && mLastSelectedFlatlList->getSelectedItem();
-}
-
-// virtual
-void LLTeleportHistoryPanel::onShowOnMap()
-{
- if (!mLastSelectedFlatlList)
- return;
-
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
-
- if(!itemp)
- return;
-
- LLVector3d global_pos = mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos;
-
- if (!global_pos.isExactlyZero())
- {
- LLFloaterWorldMap::getInstance()->trackLocation(global_pos);
- LLFloaterReg::showInstance("world_map", "center");
- }
-}
-
-//virtual
-void LLTeleportHistoryPanel::onShowProfile()
-{
- if (!mLastSelectedFlatlList)
- return;
-
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
-
- if(!itemp)
- return;
-
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex());
-}
-
-// virtual
-void LLTeleportHistoryPanel::onTeleport()
-{
- if (!mLastSelectedFlatlList)
- return;
-
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
- if(!itemp)
- return;
-
- // teleport to existing item in history, so we don't add it again
- confirmTeleport(itemp->getIndex());
-}
-
-// virtual
-void LLTeleportHistoryPanel::onRemoveSelected()
-{
- LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
-}
-
-/*
-// virtual
-void LLTeleportHistoryPanel::onCopySLURL()
-{
- LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
- if(!itemp)
- return;
-
- S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
-
- const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
-
- LLVector3d global_pos = hist_items[index].mGlobalPos;
-
- U64 new_region_handle = to_region_handle(global_pos);
-
- LLWorldMapMessage::url_callback_t cb = boost::bind(
- &LLPanelPlacesTab::onRegionResponse, this,
- global_pos, _1, _2, _3, _4);
-
- LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
-}
-*/
-
-// virtual
-void LLTeleportHistoryPanel::updateVerbs()
-{
- if (!isTabVisible())
- return;
-
- if (sRemoveBtn)
- {
- sRemoveBtn->setEnabled(true);
- }
-}
-
-// virtual
-LLToggleableMenu* LLTeleportHistoryPanel::getSelectionMenu()
-{
- return mGearItemMenu;
-}
-
-// virtual
-LLToggleableMenu* LLTeleportHistoryPanel::getSortingMenu()
-{
- return mSortingMenu;
-}
-
-// virtual
-LLToggleableMenu* LLTeleportHistoryPanel::getCreateMenu()
-{
- return NULL;
-}
-
-void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
-{
- const U32 seconds_in_day = 24 * 60 * 60;
-
- S32 tabs_cnt = mItemContainers.size();
- S32 curr_year = 0, curr_month = 0, curr_day = 0;
-
- tab_date = LLDate::now();
- tab_date.split(&curr_year, &curr_month, &curr_day);
- tab_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
- tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() + seconds_in_day);
-
- tab_idx = -1;
-
- while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
- {
- tab_idx++;
-
- if (tab_idx <= tabs_cnt - 4)
- {
- // All tabs, except last three, are tabs for one day, so just push tab_date back by one day
- tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
- }
- else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
- {
- tab_date = LLDate::now();
- tab_date.split(&curr_year, &curr_month, &curr_day);
- curr_month--;
- if (0 == curr_month)
- {
- curr_month = 12;
- curr_year--;
- }
- tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
- }
- else if (tab_idx == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
- {
- tab_date = LLDate::now();
- tab_date.split(&curr_year, &curr_month, &curr_day);
- if (curr_month > 6)
- {
- curr_month -= 6;
- }
- else
- {
- curr_month += 6;
- curr_year--;
- }
- tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
- }
- else // 6 months and older
- {
- tab_date.secondsSinceEpoch(0);
- }
- }
-}
-
-// Called to add items, no more, than ADD_LIMIT at time
-void LLTeleportHistoryPanel::refresh()
-{
- if (!mHistoryAccordion)
- {
- mDirty = false;
- return;
- }
-
- const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
-
- // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary.
- // That leads to call to getNextTab to get right tab_idx in first pass
- LLDate tab_boundary_date = LLDate::now();
-
- LLFlatListView* curr_flat_view = NULL;
- std::string filter_string = sFilterSubString;
- LLStringUtil::toUpper(filter_string);
-
- U32 added_items = 0;
- while (mCurrentItem >= 0)
- {
- // Filtering
- if (!filter_string.empty())
- {
- std::string landmark_title(items[mCurrentItem].mTitle);
- LLStringUtil::toUpper(landmark_title);
- if( std::string::npos == landmark_title.find(filter_string) )
- {
- mCurrentItem--;
- continue;
- }
- }
-
- // Checking whether date of item is earlier, than tab_boundary_date.
- // In that case, item should be added to another tab
- const LLDate &date = items[mCurrentItem].mDate;
-
- if (date < tab_boundary_date)
- {
- // Getting apropriate tab_idx for this and subsequent items,
- // tab_boundary_date would be earliest possible date for this tab
- S32 tab_idx = 0;
- getNextTab(date, tab_idx, tab_boundary_date);
- tab_idx = mItemContainers.size() - 1 - tab_idx;
- if (tab_idx >= 0)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(tab_idx);
- tab->setVisible(true);
-
- // Expand all accordion tabs when filtering
- if(!sFilterSubString.empty())
- {
- //store accordion tab state when filter is not empty
- tab->notifyChildren(LLSD().with("action","store_state"));
-
- tab->setDisplayChildren(true);
- }
- // Restore each tab's expand state when not filtering
- else
- {
- bool collapsed = isAccordionCollapsedByUser(tab);
- tab->setDisplayChildren(!collapsed);
-
- //restore accordion state after all those accodrion tabmanipulations
- tab->notifyChildren(LLSD().with("action","restore_state"));
- }
-
- curr_flat_view = getFlatListViewFromTab(tab);
- }
- }
-
- if (curr_flat_view)
- {
- LLTeleportHistoryFlatItem* item =
- LLTeleportHistoryFlatItemStorage::instance()
- .getFlatItemForPersistentItem(mGearItemMenu,
- items[mCurrentItem],
- mCurrentItem,
- filter_string);
- if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) )
- LL_ERRS() << "Couldn't add flat item to teleport history." << LL_ENDL;
- if (mLastSelectedItemIndex == mCurrentItem)
- curr_flat_view->selectItem(item, true);
- }
-
- mCurrentItem--;
-
- if (++added_items >= ADD_LIMIT)
- break;
- }
-
- for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(n);
- LLFlatListView* fv = getFlatListViewFromTab(tab);
- if (fv)
- {
- fv->notify(LLSD().with("rearrange", LLSD()));
- }
- }
-
- mHistoryAccordion->setFilterSubString(sFilterSubString);
-
- mHistoryAccordion->arrange();
-
- updateVerbs();
-
- if (mCurrentItem < 0)
- mDirty = false;
-}
-
-void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index)
-{
- mLastSelectedItemIndex = -1;
-
- if (-1 == removed_index)
- showTeleportHistory(); // recreate all items
- else
- {
- replaceItem(removed_index); // replace removed item by most recent
- updateVerbs();
- }
-}
-
-void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
-{
- // Flat list for 'Today' (mItemContainers keeps accordion tabs in reverse order)
- LLFlatListView* fv = NULL;
-
- if (mItemContainers.size() > 0)
- {
- fv = getFlatListViewFromTab(mItemContainers[mItemContainers.size() - 1]);
- }
-
- // Empty flat list for 'Today' means that other flat lists are empty as well,
- // so all items from teleport history should be added.
- if (!fv || fv->size() == 0)
- {
- showTeleportHistory();
- return;
- }
-
- const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
- LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
- .getFlatItemForPersistentItem(mGearItemMenu,
- history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
- history_items.size(), // index will be decremented inside loop below
- sFilterSubString);
-
- fv->addItem(item, LLUUID::null, ADD_TOP);
-
- // Index of each item, from last to removed item should be decremented
- // to point to the right item in LLTeleportHistoryStorage
- for (S32 tab_idx = mItemContainers.size() - 1; tab_idx >= 0; --tab_idx)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(tab_idx);
- if (!tab->getVisible())
- continue;
-
- fv = getFlatListViewFromTab(tab);
- if (!fv)
- {
- showTeleportHistory();
- return;
- }
-
- std::vector<LLPanel*> items;
- fv->getItems(items);
-
- S32 items_cnt = items.size();
- for (S32 n = 0; n < items_cnt; ++n)
- {
- LLTeleportHistoryFlatItem *item = (LLTeleportHistoryFlatItem*) items[n];
-
- if (item->getIndex() == removed_index)
- {
- LLTeleportHistoryFlatItemStorage::instance().removeItem(item);
-
- fv->removeItem(item);
-
- // If flat list becames empty, then accordion tab should be hidden
- if (fv->size() == 0)
- tab->setVisible(false);
-
- mHistoryAccordion->arrange();
-
- return; // No need to decrement idexes for the rest of items
- }
-
- item->setIndex(item->getIndex() - 1);
- }
- }
-}
-
-void LLTeleportHistoryPanel::showTeleportHistory()
-{
- mDirty = true;
-
- // Starting to add items from last one, in reverse order,
- // since TeleportHistory keeps most recent item at the end
- if (!mTeleportHistory)
- {
- mTeleportHistory = LLTeleportHistoryStorage::getInstance();
- }
-
- mCurrentItem = mTeleportHistory->getItems().size() - 1;
-
- for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(n);
- if (tab)
- {
- tab->setVisible(false);
-
- LLFlatListView* fv = getFlatListViewFromTab(tab);
- if (fv)
- {
- // Detached panels are managed by LLTeleportHistoryFlatItemStorage
- std::vector<LLPanel*> detached_items;
- fv->detachItems(detached_items);
- }
- }
- }
-}
-
-void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
-{
- mLastSelectedFlatlList = selected;
- LLTeleportHistoryFlatItem* item = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
- if (item)
- mLastSelectedItemIndex = item->getIndex();
-
- S32 tabs_cnt = mItemContainers.size();
-
- for (S32 n = 0; n < tabs_cnt; n++)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(n);
-
- if (!tab->getVisible())
- continue;
-
- LLFlatListView *flv = getFlatListViewFromTab(tab);
- if (!flv)
- continue;
-
- if (flv == selected)
- continue;
-
- flv->resetSelection(true);
- }
-
- updateVerbs();
-}
-
-void LLTeleportHistoryPanel::onReturnKeyPressed()
-{
- // Teleport to selected region as default action on return key pressed
- onTeleport();
-}
-
-void LLTeleportHistoryPanel::onDoubleClickItem()
-{
- // If item got doubleclick, then that item is already selected
- onTeleport();
-}
-
-void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask)
-{
- LLAccordionCtrlTab *tab = (LLAccordionCtrlTab *) view;
-
- // If click occurred below the header, don't show this menu
- if (y < tab->getRect().getHeight() - tab->getHeaderHeight() - tab->getPaddingBottom())
- return;
-
- if (mAccordionTabMenu)
- {
- //preventing parent (menu holder) from deleting already "dead" context menus on exit
- LLView* parent = mAccordionTabMenu->getParent();
- if (parent)
- {
- parent->removeChild(mAccordionTabMenu);
- }
- delete mAccordionTabMenu;
- }
-
- // set up the callbacks for all of the avatar menu items
- // (N.B. callbacks don't take const refs as mID is local scope)
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
- registrar.add("TeleportHistory.TabOpen", boost::bind(&LLTeleportHistoryPanel::onAccordionTabOpen, this, tab));
- registrar.add("TeleportHistory.TabClose", boost::bind(&LLTeleportHistoryPanel::onAccordionTabClose, this, tab));
-
- // create the context menu from the XUI
- llassert(LLMenuGL::sMenuContainer != NULL);
- mAccordionTabMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
- "menu_teleport_history_tab.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
-
- mAccordionTabMenu->setItemVisible("TabOpen", !tab->isExpanded());
- mAccordionTabMenu->setItemVisible("TabClose", tab->isExpanded());
-
- mAccordionTabMenu->show(x, y);
- LLMenuGL::showPopup(tab, mAccordionTabMenu, x, y);
-}
-
-void LLTeleportHistoryPanel::onAccordionTabOpen(LLAccordionCtrlTab *tab)
-{
- tab->setDisplayChildren(true);
- mHistoryAccordion->arrange();
-}
-
-void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab)
-{
- tab->setDisplayChildren(false);
- mHistoryAccordion->arrange();
-}
-
-bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response)
-{
-
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- if (0 == option)
- {
- // order does matter, call this first or teleport history will contain one record(current location)
- LLTeleportHistory::getInstance()->purgeItems();
-
- LLTeleportHistoryStorage *th = LLTeleportHistoryStorage::getInstance();
- th->purgeItems();
- th->save();
- }
-
- return false;
-}
-
-LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTab *tab)
-{
- for (child_list_const_iter_t iter = tab->beginChild(); iter != tab->endChild(); iter++)
- {
- if (dynamic_cast<LLFlatListView*>(*iter))
- {
- return (LLFlatListView*)*iter; // There should be one scroll list per tab.
- }
- }
-
- return NULL;
-}
-
-void LLTeleportHistoryPanel::gotSLURLCallback(const std::string& slurl)
-{
- LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, slurl.size());
-
- LLSD args;
- args["SLURL"] = slurl;
-
- LLNotificationsUtil::add("CopySLURL", args);
-}
-
-void LLTeleportHistoryPanel::onGearMenuAction(const LLSD& userdata)
-{
- std::string command_name = userdata.asString();
-
- if ("expand_all" == command_name)
- {
- S32 tabs_cnt = mItemContainers.size();
-
- for (S32 n = 0; n < tabs_cnt; n++)
- {
- mItemContainers.at(n)->setDisplayChildren(true);
- }
- mHistoryAccordion->arrange();
- }
- else if ("collapse_all" == command_name)
- {
- S32 tabs_cnt = mItemContainers.size();
-
- for (S32 n = 0; n < tabs_cnt; n++)
- {
- mItemContainers.at(n)->setDisplayChildren(false);
- }
- mHistoryAccordion->arrange();
-
- if (mLastSelectedFlatlList)
- {
- mLastSelectedFlatlList->resetSelection();
- }
- }
-
- S32 index = -1;
- if (mLastSelectedFlatlList)
- {
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
- if (itemp)
- {
- index = itemp->getIndex();
- }
- }
-
- if ("teleport" == command_name)
- {
- confirmTeleport(index);
- }
- else if ("view" == command_name)
- {
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(index);
- }
- else if ("show_on_map" == command_name)
- {
- LLTeleportHistoryStorage::getInstance()->showItemOnMap(index);
- }
- else if ("copy_slurl" == command_name)
- {
- LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[index].mGlobalPos;
- LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
- boost::bind(&LLTeleportHistoryPanel::gotSLURLCallback, _1));
- }
- else if ("remove" == command_name)
- {
- LLTeleportHistoryStorage::getInstance()->removeItem(index);
- LLTeleportHistoryStorage::getInstance()->save();
- showTeleportHistory();
- }
-}
-
-bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
-{
- std::string command_name = userdata.asString();
-
- if (command_name == "collapse_all"
- || command_name == "expand_all")
- {
- S32 tabs_cnt = mItemContainers.size();
-
- bool has_expanded_tabs = false;
- bool has_collapsed_tabs = false;
-
- for (S32 n = 0; n < tabs_cnt; n++)
- {
- LLAccordionCtrlTab* tab = mItemContainers.at(n);
- if (!tab->getVisible())
- continue;
-
- if (tab->getDisplayChildren())
- {
- has_expanded_tabs = true;
- }
- else
- {
- has_collapsed_tabs = true;
- }
-
- if (has_expanded_tabs && has_collapsed_tabs)
- {
- break;
- }
- }
-
- if (command_name == "collapse_all")
- {
- return has_expanded_tabs;
- }
-
- if (command_name == "expand_all")
- {
- return has_collapsed_tabs;
- }
- }
-
- if (command_name == "clear_history")
- {
- return mTeleportHistory->getItems().size() > 0;
- }
-
- if ("teleport" == command_name
- || "view" == command_name
- || "show_on_map" == command_name
- || "copy_slurl" == command_name
- || "remove" == command_name)
- {
- if (!mLastSelectedFlatlList)
- {
- return false;
- }
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
- return itemp != NULL;
- }
-
- return false;
-}
-
-void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed)
-{
- LLSD param = acc_tab->getValue();
- param[COLLAPSED_BY_USER] = collapsed;
- acc_tab->setValue(param);
-}
-
-bool LLTeleportHistoryPanel::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
-{
- LLSD param = acc_tab->getValue();
- if(!param.has(COLLAPSED_BY_USER))
- {
- return false;
- }
- return param[COLLAPSED_BY_USER].asBoolean();
-}
-
-void LLTeleportHistoryPanel::onAccordionExpand(LLUICtrl* ctrl, const LLSD& param)
-{
- bool expanded = param.asBoolean();
- // Save accordion tab state to restore it in refresh()
- setAccordionCollapsedByUser(ctrl, !expanded);
-
- // Reset selection upon accordion being collapsed
- // to disable "Teleport" and "Map" buttons for hidden item.
- if (!expanded && mLastSelectedFlatlList)
- {
- mLastSelectedFlatlList->resetSelection();
- }
-}
-
-// static
-void LLTeleportHistoryPanel::confirmTeleport(S32 hist_idx)
-{
- LLSD args;
- args["HISTORY_ENTRY"] = LLTeleportHistoryStorage::getInstance()->getItems()[hist_idx].mTitle;
- LLNotificationsUtil::add("TeleportToHistoryEntry", args, LLSD(),
- boost::bind(&LLTeleportHistoryPanel::onTeleportConfirmation, _1, _2, hist_idx));
-}
-
-// Called when user reacts upon teleport confirmation dialog.
-// static
-bool LLTeleportHistoryPanel::onTeleportConfirmation(const LLSD& notification, const LLSD& response, S32 hist_idx)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- if (0 == option)
- {
- // Teleport to given history item.
- LLTeleportHistoryStorage::getInstance()->goToItem(hist_idx);
- }
-
- return false;
-}
+/**
+ * @file llpanelteleporthistory.cpp
+ * @brief Teleport history represented by a scrolling list
+ *
+ * $LicenseInfo:firstyear=2009&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 "llfloaterreg.h"
+#include "llmenubutton.h"
+
+#include "llfloaterworldmap.h"
+#include "llpanelteleporthistory.h"
+#include "llworldmap.h"
+#include "llteleporthistorystorage.h"
+#include "lltextutil.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+#include "llflatlistview.h"
+#include "llfloatersidepanelcontainer.h"
+#include "llnotificationsutil.h"
+#include "lltextbox.h"
+#include "lltoggleablemenu.h"
+#include "llviewermenu.h"
+#include "lllandmarkactions.h"
+#include "llclipboard.h"
+#include "lltrans.h"
+
+// Maximum number of items that can be added to a list in one pass.
+// Used to limit time spent for items list update per frame.
+static const U32 ADD_LIMIT = 50;
+
+static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
+
+class LLTeleportHistoryFlatItem : public LLPanel
+{
+public:
+ LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
+ LLDate date, const std::string &hl);
+ virtual ~LLTeleportHistoryFlatItem();
+
+ virtual bool postBuild();
+
+ /*virtual*/ S32 notify(const LLSD& info);
+
+ S32 getIndex() { return mIndex; }
+ void setIndex(S32 index) { mIndex = index; }
+ const std::string& getRegionName() { return mRegionName;}
+ void setRegionName(const std::string& name);
+ void setDate(LLDate date);
+ void setHighlightedText(const std::string& text);
+ void updateTitle();
+ void updateTimestamp();
+ std::string getTimestamp();
+
+ /*virtual*/ void setValue(const LLSD& value);
+
+ void onMouseEnter(S32 x, S32 y, MASK mask);
+ void onMouseLeave(S32 x, S32 y, MASK mask);
+ virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ static void showPlaceInfoPanel(S32 index);
+
+ LLHandle<LLTeleportHistoryFlatItem> getItemHandle() { mItemHandle.bind(this); return mItemHandle; }
+
+private:
+ void onProfileBtnClick();
+ void showMenu(S32 x, S32 y);
+
+ LLButton* mProfileBtn;
+ LLTextBox* mTitle;
+ LLTextBox* mTimeTextBox;
+
+ LLToggleableMenu *mMenu;
+
+ S32 mIndex;
+ std::string mRegionName;
+ std::string mHighlight;
+ LLDate mDate;
+ LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage>
+{
+ LLSINGLETON_EMPTY_CTOR(LLTeleportHistoryFlatItemStorage);
+protected:
+ typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t;
+
+public:
+ LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
+ LLToggleableMenu *menu,
+ const LLTeleportHistoryPersistentItem& persistent_item,
+ const S32 cur_item_index,
+ const std::string &hl);
+
+ void removeItem(LLTeleportHistoryFlatItem* item);
+
+ void purge();
+
+private:
+
+ flat_item_list_t mItems;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
+ LLDate date, const std::string &hl)
+: LLPanel(),
+ mIndex(index),
+ mMenu(menu),
+ mRegionName(region_name),
+ mDate(date),
+ mHighlight(hl)
+{
+ buildFromFile("panel_teleport_history_item.xml");
+}
+
+LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
+{
+}
+
+//virtual
+bool LLTeleportHistoryFlatItem::postBuild()
+{
+ mTitle = getChild<LLTextBox>("region");
+
+ mTimeTextBox = getChild<LLTextBox>("timestamp");
+
+ mProfileBtn = getChild<LLButton>("profile_btn");
+
+ mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
+
+ updateTitle();
+ updateTimestamp();
+
+ return true;
+}
+
+S32 LLTeleportHistoryFlatItem::notify(const LLSD& info)
+{
+ if(info.has("detach"))
+ {
+ delete mMouseDownSignal;
+ mMouseDownSignal = NULL;
+ delete mRightMouseDownSignal;
+ mRightMouseDownSignal = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ getChildView("selected_icon")->setVisible( value["selected"]);
+}
+
+void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text)
+{
+ mHighlight = text;
+}
+
+void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
+{
+ mRegionName = name;
+}
+
+void LLTeleportHistoryFlatItem::setDate(LLDate date)
+{
+ mDate = date;
+}
+
+std::string LLTeleportHistoryFlatItem::getTimestamp()
+{
+ const LLDate &date = mDate;
+ std::string timestamp = "";
+
+ LLDate now = LLDate::now();
+ S32 now_year, now_month, now_day, now_hour, now_min, now_sec;
+ now.split(&now_year, &now_month, &now_day, &now_hour, &now_min, &now_sec);
+
+ const S32 seconds_in_day = 24 * 60 * 60;
+ S32 seconds_today = now_hour * 60 * 60 + now_min * 60 + now_sec;
+ S32 time_diff = (S32) now.secondsSinceEpoch() - (S32) date.secondsSinceEpoch();
+
+ // Only show timestamp for today and yesterday
+ if(time_diff < seconds_today + seconds_in_day)
+ {
+ timestamp = "[" + LLTrans::getString("TimeHour12")+"]:["
+ + LLTrans::getString("TimeMin")+"] ["+ LLTrans::getString("TimeAMPM")+"]";
+ LLSD substitution;
+ substitution["datetime"] = (S32) date.secondsSinceEpoch();
+ LLStringUtil::format(timestamp, substitution);
+ }
+
+ return timestamp;
+
+}
+
+void LLTeleportHistoryFlatItem::updateTitle()
+{
+ static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
+
+ LLTextUtil::textboxSetHighlightedVal(
+ mTitle,
+ LLStyle::Params().color(sFgColor),
+ mRegionName,
+ mHighlight);
+}
+
+void LLTeleportHistoryFlatItem::updateTimestamp()
+{
+ static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
+
+ LLTextUtil::textboxSetHighlightedVal(
+ mTimeTextBox,
+ LLStyle::Params().color(sFgColor),
+ getTimestamp(),
+ mHighlight);
+}
+
+void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ getChildView("hovered_icon")->setVisible( true);
+ mProfileBtn->setVisible(true);
+
+ LLPanel::onMouseEnter(x, y, mask);
+}
+
+void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ getChildView("hovered_icon")->setVisible( false);
+ mProfileBtn->setVisible(false);
+
+ LLPanel::onMouseLeave(x, y, mask);
+}
+
+// virtual
+bool LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLPanel::handleRightMouseDown(x, y, mask);
+ showMenu(x, y);
+ return true;
+}
+
+void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
+{
+ LLSD params;
+ params["id"] = index;
+ params["type"] = "teleport_history";
+
+ LLFloaterSidePanelContainer::showPanel("places", params);
+}
+
+void LLTeleportHistoryFlatItem::onProfileBtnClick()
+{
+ LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
+}
+
+void LLTeleportHistoryFlatItem::showMenu(S32 x, S32 y)
+{
+ mMenu->setButtonRect(this);
+ mMenu->buildDrawLabels();
+ mMenu->arrangeAndClear();
+ mMenu->updateParent(LLMenuGL::sMenuContainer);
+
+ LLMenuGL::showPopup(this, mMenu, x, y);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistoryFlatItem*
+LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
+ LLToggleableMenu *menu,
+ const LLTeleportHistoryPersistentItem& persistent_item,
+ const S32 cur_item_index,
+ const std::string &hl)
+{
+ LLTeleportHistoryFlatItem* item = NULL;
+ if ( cur_item_index < (S32) mItems.size() )
+ {
+ item = mItems[cur_item_index].get();
+ if (item->getParent() == NULL)
+ {
+ item->setIndex(cur_item_index);
+ item->setRegionName(persistent_item.mTitle);
+ item->setDate(persistent_item.mDate);
+ item->setHighlightedText(hl);
+ item->setVisible(true);
+ item->updateTitle();
+ item->updateTimestamp();
+ }
+ else
+ {
+ // Item already added to parent
+ item = NULL;
+ }
+ }
+
+ if ( !item )
+ {
+ item = new LLTeleportHistoryFlatItem(cur_item_index,
+ menu,
+ persistent_item.mTitle,
+ persistent_item.mDate,
+ hl);
+ mItems.push_back(item->getItemHandle());
+ }
+
+ return item;
+}
+
+void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item)
+{
+ if (item)
+ {
+ flat_item_list_t::iterator item_iter = std::find(mItems.begin(),
+ mItems.end(),
+ item->getItemHandle());
+ if (item_iter != mItems.end())
+ {
+ mItems.erase(item_iter);
+ }
+ }
+}
+
+void LLTeleportHistoryFlatItemStorage::purge()
+{
+ for ( flat_item_list_t::iterator
+ it = mItems.begin(),
+ it_end = mItems.end();
+ it != it_end; ++it )
+ {
+ LLHandle <LLTeleportHistoryFlatItem> item_handle = *it;
+ if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL )
+ {
+ item_handle.get()->die();
+ }
+ }
+ mItems.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Not yet implemented; need to remove buildPanel() from constructor when we switch
+//static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
+
+LLTeleportHistoryPanel::LLTeleportHistoryPanel()
+ : LLPanelPlacesTab(),
+ mDirty(true),
+ mCurrentItem(0),
+ mTeleportHistory(NULL),
+ mHistoryAccordion(NULL),
+ mAccordionTabMenu(NULL),
+ mLastSelectedFlatlList(NULL),
+ mLastSelectedItemIndex(-1),
+ mGearItemMenu(NULL),
+ mSortingMenu(NULL)
+{
+ buildFromFile( "panel_teleport_history.xml");
+}
+
+LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
+{
+ LLTeleportHistoryFlatItemStorage::instance().purge();
+ mTeleportHistoryChangedConnection.disconnect();
+}
+
+bool LLTeleportHistoryPanel::postBuild()
+{
+ mCommitCallbackRegistrar.add("TeleportHistory.GearMenu.Action", boost::bind(&LLTeleportHistoryPanel::onGearMenuAction, this, _2));
+ mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
+
+ // init menus before list, since menus are passed to list
+ mGearItemMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_item.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearItemMenu->setAlwaysShowMenu(true); // all items can be disabled if nothing is selected, show anyway
+ mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+ mTeleportHistory = LLTeleportHistoryStorage::getInstance();
+ if (mTeleportHistory)
+ {
+ mTeleportHistoryChangedConnection = mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1));
+ }
+
+ mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion");
+
+ if (mHistoryAccordion)
+ {
+ for (child_list_const_iter_t iter = mHistoryAccordion->beginChild(); iter != mHistoryAccordion->endChild(); iter++)
+ {
+ if (dynamic_cast<LLAccordionCtrlTab*>(*iter))
+ {
+ LLAccordionCtrlTab* tab = (LLAccordionCtrlTab*)*iter;
+ tab->setRightMouseDownCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionTabRightClick, this, _1, _2, _3, _4));
+ tab->setDisplayChildren(false);
+ tab->setDropDownStateChangedCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionExpand, this, _1, _2));
+
+ // All accordion tabs are collapsed initially
+ setAccordionCollapsedByUser(tab, true);
+
+ mItemContainers.push_back(tab);
+
+ LLFlatListView* fl = getFlatListViewFromTab(tab);
+ if (fl)
+ {
+ fl->setCommitOnSelectionChange(true);
+ fl->setDoubleClickCallback(boost::bind(&LLTeleportHistoryPanel::onDoubleClickItem, this));
+ fl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, fl));
+ fl->setReturnCallback(boost::bind(&LLTeleportHistoryPanel::onReturnKeyPressed, this));
+ }
+ }
+ }
+
+ // Open first 2 accordion tabs
+ if (mItemContainers.size() > 1)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(mItemContainers.size() - 1);
+ tab->setDisplayChildren(true);
+ setAccordionCollapsedByUser(tab, false);
+ }
+
+ if (mItemContainers.size() > 2)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(mItemContainers.size() - 2);
+ tab->setDisplayChildren(true);
+ setAccordionCollapsedByUser(tab, false);
+ }
+ }
+
+ return true;
+}
+
+// virtual
+void LLTeleportHistoryPanel::draw()
+{
+ if (mDirty)
+ refresh();
+
+ LLPanelPlacesTab::draw();
+}
+
+// virtual
+void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
+{
+ sFilterSubString = string;
+ showTeleportHistory();
+}
+
+// virtual
+bool LLTeleportHistoryPanel::isSingleItemSelected()
+{
+ return mLastSelectedFlatlList && mLastSelectedFlatlList->getSelectedItem();
+}
+
+// virtual
+void LLTeleportHistoryPanel::onShowOnMap()
+{
+ if (!mLastSelectedFlatlList)
+ return;
+
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+
+ if(!itemp)
+ return;
+
+ LLVector3d global_pos = mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos;
+
+ if (!global_pos.isExactlyZero())
+ {
+ LLFloaterWorldMap::getInstance()->trackLocation(global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+}
+
+//virtual
+void LLTeleportHistoryPanel::onShowProfile()
+{
+ if (!mLastSelectedFlatlList)
+ return;
+
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+
+ if(!itemp)
+ return;
+
+ LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex());
+}
+
+// virtual
+void LLTeleportHistoryPanel::onTeleport()
+{
+ if (!mLastSelectedFlatlList)
+ return;
+
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ if(!itemp)
+ return;
+
+ // teleport to existing item in history, so we don't add it again
+ confirmTeleport(itemp->getIndex());
+}
+
+// virtual
+void LLTeleportHistoryPanel::onRemoveSelected()
+{
+ LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
+}
+
+/*
+// virtual
+void LLTeleportHistoryPanel::onCopySLURL()
+{
+ LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
+ if(!itemp)
+ return;
+
+ S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
+
+ const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
+
+ LLVector3d global_pos = hist_items[index].mGlobalPos;
+
+ U64 new_region_handle = to_region_handle(global_pos);
+
+ LLWorldMapMessage::url_callback_t cb = boost::bind(
+ &LLPanelPlacesTab::onRegionResponse, this,
+ global_pos, _1, _2, _3, _4);
+
+ LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
+}
+*/
+
+// virtual
+void LLTeleportHistoryPanel::updateVerbs()
+{
+ if (!isTabVisible())
+ return;
+
+ if (sRemoveBtn)
+ {
+ sRemoveBtn->setEnabled(true);
+ }
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getSelectionMenu()
+{
+ return mGearItemMenu;
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getSortingMenu()
+{
+ return mSortingMenu;
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getCreateMenu()
+{
+ return NULL;
+}
+
+void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
+{
+ const U32 seconds_in_day = 24 * 60 * 60;
+
+ S32 tabs_cnt = mItemContainers.size();
+ S32 curr_year = 0, curr_month = 0, curr_day = 0;
+
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() + seconds_in_day);
+
+ tab_idx = -1;
+
+ while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
+ {
+ tab_idx++;
+
+ if (tab_idx <= tabs_cnt - 4)
+ {
+ // All tabs, except last three, are tabs for one day, so just push tab_date back by one day
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
+ }
+ else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
+ {
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ curr_month--;
+ if (0 == curr_month)
+ {
+ curr_month = 12;
+ curr_year--;
+ }
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
+ }
+ else if (tab_idx == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
+ {
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ if (curr_month > 6)
+ {
+ curr_month -= 6;
+ }
+ else
+ {
+ curr_month += 6;
+ curr_year--;
+ }
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
+ }
+ else // 6 months and older
+ {
+ tab_date.secondsSinceEpoch(0);
+ }
+ }
+}
+
+// Called to add items, no more, than ADD_LIMIT at time
+void LLTeleportHistoryPanel::refresh()
+{
+ if (!mHistoryAccordion)
+ {
+ mDirty = false;
+ return;
+ }
+
+ const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
+
+ // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary.
+ // That leads to call to getNextTab to get right tab_idx in first pass
+ LLDate tab_boundary_date = LLDate::now();
+
+ LLFlatListView* curr_flat_view = NULL;
+ std::string filter_string = sFilterSubString;
+ LLStringUtil::toUpper(filter_string);
+
+ U32 added_items = 0;
+ while (mCurrentItem >= 0)
+ {
+ // Filtering
+ if (!filter_string.empty())
+ {
+ std::string landmark_title(items[mCurrentItem].mTitle);
+ LLStringUtil::toUpper(landmark_title);
+ if( std::string::npos == landmark_title.find(filter_string) )
+ {
+ mCurrentItem--;
+ continue;
+ }
+ }
+
+ // Checking whether date of item is earlier, than tab_boundary_date.
+ // In that case, item should be added to another tab
+ const LLDate &date = items[mCurrentItem].mDate;
+
+ if (date < tab_boundary_date)
+ {
+ // Getting apropriate tab_idx for this and subsequent items,
+ // tab_boundary_date would be earliest possible date for this tab
+ S32 tab_idx = 0;
+ getNextTab(date, tab_idx, tab_boundary_date);
+ tab_idx = mItemContainers.size() - 1 - tab_idx;
+ if (tab_idx >= 0)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(tab_idx);
+ tab->setVisible(true);
+
+ // Expand all accordion tabs when filtering
+ if(!sFilterSubString.empty())
+ {
+ //store accordion tab state when filter is not empty
+ tab->notifyChildren(LLSD().with("action","store_state"));
+
+ tab->setDisplayChildren(true);
+ }
+ // Restore each tab's expand state when not filtering
+ else
+ {
+ bool collapsed = isAccordionCollapsedByUser(tab);
+ tab->setDisplayChildren(!collapsed);
+
+ //restore accordion state after all those accodrion tabmanipulations
+ tab->notifyChildren(LLSD().with("action","restore_state"));
+ }
+
+ curr_flat_view = getFlatListViewFromTab(tab);
+ }
+ }
+
+ if (curr_flat_view)
+ {
+ LLTeleportHistoryFlatItem* item =
+ LLTeleportHistoryFlatItemStorage::instance()
+ .getFlatItemForPersistentItem(mGearItemMenu,
+ items[mCurrentItem],
+ mCurrentItem,
+ filter_string);
+ if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) )
+ LL_ERRS() << "Couldn't add flat item to teleport history." << LL_ENDL;
+ if (mLastSelectedItemIndex == mCurrentItem)
+ curr_flat_view->selectItem(item, true);
+ }
+
+ mCurrentItem--;
+
+ if (++added_items >= ADD_LIMIT)
+ break;
+ }
+
+ for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(n);
+ LLFlatListView* fv = getFlatListViewFromTab(tab);
+ if (fv)
+ {
+ fv->notify(LLSD().with("rearrange", LLSD()));
+ }
+ }
+
+ mHistoryAccordion->setFilterSubString(sFilterSubString);
+
+ mHistoryAccordion->arrange();
+
+ updateVerbs();
+
+ if (mCurrentItem < 0)
+ mDirty = false;
+}
+
+void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index)
+{
+ mLastSelectedItemIndex = -1;
+
+ if (-1 == removed_index)
+ showTeleportHistory(); // recreate all items
+ else
+ {
+ replaceItem(removed_index); // replace removed item by most recent
+ updateVerbs();
+ }
+}
+
+void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
+{
+ // Flat list for 'Today' (mItemContainers keeps accordion tabs in reverse order)
+ LLFlatListView* fv = NULL;
+
+ if (mItemContainers.size() > 0)
+ {
+ fv = getFlatListViewFromTab(mItemContainers[mItemContainers.size() - 1]);
+ }
+
+ // Empty flat list for 'Today' means that other flat lists are empty as well,
+ // so all items from teleport history should be added.
+ if (!fv || fv->size() == 0)
+ {
+ showTeleportHistory();
+ return;
+ }
+
+ const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
+ LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
+ .getFlatItemForPersistentItem(mGearItemMenu,
+ history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
+ history_items.size(), // index will be decremented inside loop below
+ sFilterSubString);
+
+ fv->addItem(item, LLUUID::null, ADD_TOP);
+
+ // Index of each item, from last to removed item should be decremented
+ // to point to the right item in LLTeleportHistoryStorage
+ for (S32 tab_idx = mItemContainers.size() - 1; tab_idx >= 0; --tab_idx)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(tab_idx);
+ if (!tab->getVisible())
+ continue;
+
+ fv = getFlatListViewFromTab(tab);
+ if (!fv)
+ {
+ showTeleportHistory();
+ return;
+ }
+
+ std::vector<LLPanel*> items;
+ fv->getItems(items);
+
+ S32 items_cnt = items.size();
+ for (S32 n = 0; n < items_cnt; ++n)
+ {
+ LLTeleportHistoryFlatItem *item = (LLTeleportHistoryFlatItem*) items[n];
+
+ if (item->getIndex() == removed_index)
+ {
+ LLTeleportHistoryFlatItemStorage::instance().removeItem(item);
+
+ fv->removeItem(item);
+
+ // If flat list becames empty, then accordion tab should be hidden
+ if (fv->size() == 0)
+ tab->setVisible(false);
+
+ mHistoryAccordion->arrange();
+
+ return; // No need to decrement idexes for the rest of items
+ }
+
+ item->setIndex(item->getIndex() - 1);
+ }
+ }
+}
+
+void LLTeleportHistoryPanel::showTeleportHistory()
+{
+ mDirty = true;
+
+ // Starting to add items from last one, in reverse order,
+ // since TeleportHistory keeps most recent item at the end
+ if (!mTeleportHistory)
+ {
+ mTeleportHistory = LLTeleportHistoryStorage::getInstance();
+ }
+
+ mCurrentItem = mTeleportHistory->getItems().size() - 1;
+
+ for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(n);
+ if (tab)
+ {
+ tab->setVisible(false);
+
+ LLFlatListView* fv = getFlatListViewFromTab(tab);
+ if (fv)
+ {
+ // Detached panels are managed by LLTeleportHistoryFlatItemStorage
+ std::vector<LLPanel*> detached_items;
+ fv->detachItems(detached_items);
+ }
+ }
+ }
+}
+
+void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
+{
+ mLastSelectedFlatlList = selected;
+ LLTeleportHistoryFlatItem* item = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ if (item)
+ mLastSelectedItemIndex = item->getIndex();
+
+ S32 tabs_cnt = mItemContainers.size();
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(n);
+
+ if (!tab->getVisible())
+ continue;
+
+ LLFlatListView *flv = getFlatListViewFromTab(tab);
+ if (!flv)
+ continue;
+
+ if (flv == selected)
+ continue;
+
+ flv->resetSelection(true);
+ }
+
+ updateVerbs();
+}
+
+void LLTeleportHistoryPanel::onReturnKeyPressed()
+{
+ // Teleport to selected region as default action on return key pressed
+ onTeleport();
+}
+
+void LLTeleportHistoryPanel::onDoubleClickItem()
+{
+ // If item got doubleclick, then that item is already selected
+ onTeleport();
+}
+
+void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask)
+{
+ LLAccordionCtrlTab *tab = (LLAccordionCtrlTab *) view;
+
+ // If click occurred below the header, don't show this menu
+ if (y < tab->getRect().getHeight() - tab->getHeaderHeight() - tab->getPaddingBottom())
+ return;
+
+ if (mAccordionTabMenu)
+ {
+ //preventing parent (menu holder) from deleting already "dead" context menus on exit
+ LLView* parent = mAccordionTabMenu->getParent();
+ if (parent)
+ {
+ parent->removeChild(mAccordionTabMenu);
+ }
+ delete mAccordionTabMenu;
+ }
+
+ // set up the callbacks for all of the avatar menu items
+ // (N.B. callbacks don't take const refs as mID is local scope)
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("TeleportHistory.TabOpen", boost::bind(&LLTeleportHistoryPanel::onAccordionTabOpen, this, tab));
+ registrar.add("TeleportHistory.TabClose", boost::bind(&LLTeleportHistoryPanel::onAccordionTabClose, this, tab));
+
+ // create the context menu from the XUI
+ llassert(LLMenuGL::sMenuContainer != NULL);
+ mAccordionTabMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ "menu_teleport_history_tab.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+
+ mAccordionTabMenu->setItemVisible("TabOpen", !tab->isExpanded());
+ mAccordionTabMenu->setItemVisible("TabClose", tab->isExpanded());
+
+ mAccordionTabMenu->show(x, y);
+ LLMenuGL::showPopup(tab, mAccordionTabMenu, x, y);
+}
+
+void LLTeleportHistoryPanel::onAccordionTabOpen(LLAccordionCtrlTab *tab)
+{
+ tab->setDisplayChildren(true);
+ mHistoryAccordion->arrange();
+}
+
+void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab)
+{
+ tab->setDisplayChildren(false);
+ mHistoryAccordion->arrange();
+}
+
+bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response)
+{
+
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (0 == option)
+ {
+ // order does matter, call this first or teleport history will contain one record(current location)
+ LLTeleportHistory::getInstance()->purgeItems();
+
+ LLTeleportHistoryStorage *th = LLTeleportHistoryStorage::getInstance();
+ th->purgeItems();
+ th->save();
+ }
+
+ return false;
+}
+
+LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTab *tab)
+{
+ for (child_list_const_iter_t iter = tab->beginChild(); iter != tab->endChild(); iter++)
+ {
+ if (dynamic_cast<LLFlatListView*>(*iter))
+ {
+ return (LLFlatListView*)*iter; // There should be one scroll list per tab.
+ }
+ }
+
+ return NULL;
+}
+
+void LLTeleportHistoryPanel::gotSLURLCallback(const std::string& slurl)
+{
+ LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, slurl.size());
+
+ LLSD args;
+ args["SLURL"] = slurl;
+
+ LLNotificationsUtil::add("CopySLURL", args);
+}
+
+void LLTeleportHistoryPanel::onGearMenuAction(const LLSD& userdata)
+{
+ std::string command_name = userdata.asString();
+
+ if ("expand_all" == command_name)
+ {
+ S32 tabs_cnt = mItemContainers.size();
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ mItemContainers.at(n)->setDisplayChildren(true);
+ }
+ mHistoryAccordion->arrange();
+ }
+ else if ("collapse_all" == command_name)
+ {
+ S32 tabs_cnt = mItemContainers.size();
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ mItemContainers.at(n)->setDisplayChildren(false);
+ }
+ mHistoryAccordion->arrange();
+
+ if (mLastSelectedFlatlList)
+ {
+ mLastSelectedFlatlList->resetSelection();
+ }
+ }
+
+ S32 index = -1;
+ if (mLastSelectedFlatlList)
+ {
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ if (itemp)
+ {
+ index = itemp->getIndex();
+ }
+ }
+
+ if ("teleport" == command_name)
+ {
+ confirmTeleport(index);
+ }
+ else if ("view" == command_name)
+ {
+ LLTeleportHistoryFlatItem::showPlaceInfoPanel(index);
+ }
+ else if ("show_on_map" == command_name)
+ {
+ LLTeleportHistoryStorage::getInstance()->showItemOnMap(index);
+ }
+ else if ("copy_slurl" == command_name)
+ {
+ LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[index].mGlobalPos;
+ LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
+ boost::bind(&LLTeleportHistoryPanel::gotSLURLCallback, _1));
+ }
+ else if ("remove" == command_name)
+ {
+ LLTeleportHistoryStorage::getInstance()->removeItem(index);
+ LLTeleportHistoryStorage::getInstance()->save();
+ showTeleportHistory();
+ }
+}
+
+bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
+{
+ std::string command_name = userdata.asString();
+
+ if (command_name == "collapse_all"
+ || command_name == "expand_all")
+ {
+ S32 tabs_cnt = mItemContainers.size();
+
+ bool has_expanded_tabs = false;
+ bool has_collapsed_tabs = false;
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.at(n);
+ if (!tab->getVisible())
+ continue;
+
+ if (tab->getDisplayChildren())
+ {
+ has_expanded_tabs = true;
+ }
+ else
+ {
+ has_collapsed_tabs = true;
+ }
+
+ if (has_expanded_tabs && has_collapsed_tabs)
+ {
+ break;
+ }
+ }
+
+ if (command_name == "collapse_all")
+ {
+ return has_expanded_tabs;
+ }
+
+ if (command_name == "expand_all")
+ {
+ return has_collapsed_tabs;
+ }
+ }
+
+ if (command_name == "clear_history")
+ {
+ return mTeleportHistory->getItems().size() > 0;
+ }
+
+ if ("teleport" == command_name
+ || "view" == command_name
+ || "show_on_map" == command_name
+ || "copy_slurl" == command_name
+ || "remove" == command_name)
+ {
+ if (!mLastSelectedFlatlList)
+ {
+ return false;
+ }
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ return itemp != NULL;
+ }
+
+ return false;
+}
+
+void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed)
+{
+ LLSD param = acc_tab->getValue();
+ param[COLLAPSED_BY_USER] = collapsed;
+ acc_tab->setValue(param);
+}
+
+bool LLTeleportHistoryPanel::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
+{
+ LLSD param = acc_tab->getValue();
+ if(!param.has(COLLAPSED_BY_USER))
+ {
+ return false;
+ }
+ return param[COLLAPSED_BY_USER].asBoolean();
+}
+
+void LLTeleportHistoryPanel::onAccordionExpand(LLUICtrl* ctrl, const LLSD& param)
+{
+ bool expanded = param.asBoolean();
+ // Save accordion tab state to restore it in refresh()
+ setAccordionCollapsedByUser(ctrl, !expanded);
+
+ // Reset selection upon accordion being collapsed
+ // to disable "Teleport" and "Map" buttons for hidden item.
+ if (!expanded && mLastSelectedFlatlList)
+ {
+ mLastSelectedFlatlList->resetSelection();
+ }
+}
+
+// static
+void LLTeleportHistoryPanel::confirmTeleport(S32 hist_idx)
+{
+ LLSD args;
+ args["HISTORY_ENTRY"] = LLTeleportHistoryStorage::getInstance()->getItems()[hist_idx].mTitle;
+ LLNotificationsUtil::add("TeleportToHistoryEntry", args, LLSD(),
+ boost::bind(&LLTeleportHistoryPanel::onTeleportConfirmation, _1, _2, hist_idx));
+}
+
+// Called when user reacts upon teleport confirmation dialog.
+// static
+bool LLTeleportHistoryPanel::onTeleportConfirmation(const LLSD& notification, const LLSD& response, S32 hist_idx)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (0 == option)
+ {
+ // Teleport to given history item.
+ LLTeleportHistoryStorage::getInstance()->goToItem(hist_idx);
+ }
+
+ return false;
+}