summaryrefslogtreecommitdiff
path: root/indra/newview/llpanelplaces.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llpanelplaces.cpp')
-rw-r--r--indra/newview/llpanelplaces.cpp1169
1 files changed, 1034 insertions, 135 deletions
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index d18cac9f42..f0e60386b6 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -2,259 +2,1027 @@
* @file llpanelplaces.cpp
* @brief Side Bar "Places" panel
*
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2004-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * 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 "llpanelplaces.h"
+
+#include "llassettype.h"
+#include "lltimer.h"
+
+#include "llinventory.h"
+#include "lllandmark.h"
+#include "llparcel.h"
+
+#include "llcombobox.h"
+#include "llfiltereditor.h"
+#include "llfirstuse.h"
#include "llfloaterreg.h"
-#include "llsearcheditor.h"
+#include "llnotificationsutil.h"
#include "lltabcontainer.h"
+#include "lltexteditor.h"
+#include "lltrans.h"
#include "lluictrlfactory.h"
-#include "lllandmark.h"
+#include "llwindow.h"
#include "llagent.h"
-#include "lllandmarklist.h"
+#include "llagentpicksinfo.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llcommandhandler.h"
#include "llfloaterworldmap.h"
-#include "llpanelplaces.h"
+#include "llinventorybridge.h"
+#include "llinventoryobserver.h"
+#include "llinventorymodel.h"
+#include "lllandmarkactions.h"
+#include "lllandmarklist.h"
+#include "llpanellandmarkinfo.h"
#include "llpanellandmarks.h"
+#include "llpanelpick.h"
+#include "llpanelplaceprofile.h"
#include "llpanelteleporthistory.h"
+#include "llremoteparcelrequest.h"
+#include "llsidetray.h"
+#include "llteleporthistorystorage.h"
+#include "lltoggleablemenu.h"
+#include "llviewerinventory.h"
+#include "llviewermenu.h"
+#include "llviewermessage.h"
+#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
+#include "llviewerwindow.h"
+
+// Constants
+static const S32 LANDMARK_FOLDERS_MENU_WIDTH = 250;
+static const F32 PLACE_INFO_UPDATE_INTERVAL = 3.0;
+static const std::string AGENT_INFO_TYPE = "agent";
+static const std::string CREATE_LANDMARK_INFO_TYPE = "create_landmark";
+static const std::string LANDMARK_INFO_TYPE = "landmark";
+static const std::string REMOTE_PLACE_INFO_TYPE = "remote_place";
+static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history";
+
+// Support for secondlife:///app/parcel/{UUID}/about SLapps
+class LLParcelHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { }
+ bool handle(const LLSD& params, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (params.size() < 2)
+ {
+ return false;
+ }
+ LLUUID parcel_id;
+ if (!parcel_id.set(params[0], FALSE))
+ {
+ return false;
+ }
+ if (params[1].asString() == "about")
+ {
+ if (parcel_id.notNull())
+ {
+ LLSD key;
+ key["type"] = "remote_place";
+ key["id"] = parcel_id;
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+LLParcelHandler gParcelHandler;
+
+// Helper functions
+static bool is_agent_in_selected_parcel(LLParcel* parcel);
+static void onSLURLBuilt(std::string& slurl);
+
+//Observer classes
+class LLPlacesParcelObserver : public LLParcelObserver
+{
+public:
+ LLPlacesParcelObserver(LLPanelPlaces* places_panel) :
+ LLParcelObserver(),
+ mPlaces(places_panel)
+ {}
+
+ /*virtual*/ void changed()
+ {
+ if (mPlaces)
+ mPlaces->changedParcelSelection();
+ }
+
+private:
+ LLPanelPlaces* mPlaces;
+};
+
+class LLPlacesInventoryObserver : public LLInventoryAddedObserver
+{
+public:
+ LLPlacesInventoryObserver(LLPanelPlaces* places_panel) :
+ mPlaces(places_panel),
+ mTabsCreated(false)
+ {}
+
+ /*virtual*/ void changed(U32 mask)
+ {
+ LLInventoryAddedObserver::changed(mask);
+
+ if (!mTabsCreated && mPlaces)
+ {
+ mPlaces->createTabs();
+ mTabsCreated = true;
+ }
+ }
+
+protected:
+ /*virtual*/ void done()
+ {
+ mPlaces->showAddedLandmarkInfo(mAdded);
+ mAdded.clear();
+ }
+
+private:
+ LLPanelPlaces* mPlaces;
+ bool mTabsCreated;
+};
+
+class LLPlacesRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver
+{
+public:
+ LLPlacesRemoteParcelInfoObserver(LLPanelPlaces* places_panel) :
+ LLRemoteParcelInfoObserver(),
+ mPlaces(places_panel)
+ {}
+
+ ~LLPlacesRemoteParcelInfoObserver()
+ {
+ // remove any in-flight observers
+ std::set<LLUUID>::iterator it;
+ for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it)
+ {
+ const LLUUID &id = *it;
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this);
+ }
+ mParcelIDs.clear();
+ }
+
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data)
+ {
+ if (mPlaces)
+ {
+ mPlaces->changedGlobalPos(LLVector3d(parcel_data.global_x,
+ parcel_data.global_y,
+ parcel_data.global_z));
+ }
+
+ mParcelIDs.erase(parcel_data.parcel_id);
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this);
+ }
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id)
+ {
+ if (!parcel_id.isNull())
+ {
+ mParcelIDs.insert(parcel_id);
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+ }
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason)
+ {
+ llerrs << "Can't complete remote parcel request. Http Status: "
+ << status << ". Reason : " << reason << llendl;
+ }
+
+private:
+ std::set<LLUUID> mParcelIDs;
+ LLPanelPlaces* mPlaces;
+};
+
static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places");
LLPanelPlaces::LLPanelPlaces()
: LLPanel(),
- mFilterSubString(LLStringUtil::null),
mActivePanel(NULL),
- mSearchEditor(NULL),
- mPlaceInfo(NULL)
+ mFilterEditor(NULL),
+ mPlaceProfile(NULL),
+ mLandmarkInfo(NULL),
+ mPickPanel(NULL),
+ mItem(NULL),
+ mPlaceMenu(NULL),
+ mLandmarkMenu(NULL),
+ mPosGlobal(),
+ isLandmarkEditModeOn(false)
{
- gInventory.addObserver(this);
+ mParcelObserver = new LLPlacesParcelObserver(this);
+ mInventoryObserver = new LLPlacesInventoryObserver(this);
+ mRemoteParcelObserver = new LLPlacesRemoteParcelInfoObserver(this);
+
+ gInventory.addObserver(mInventoryObserver);
+
+ LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
+ boost::bind(&LLPanelPlaces::updateVerbs, this));
- //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_places.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+ //buildFromFile( "panel_places.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
}
LLPanelPlaces::~LLPanelPlaces()
{
- if (gInventory.containsObserver(this))
- gInventory.removeObserver(this);
+ if (gInventory.containsObserver(mInventoryObserver))
+ gInventory.removeObserver(mInventoryObserver);
+
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ delete mInventoryObserver;
+ delete mParcelObserver;
+ delete mRemoteParcelObserver;
}
BOOL LLPanelPlaces::postBuild()
{
+ mTeleportBtn = getChild<LLButton>("teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this));
+
+ mShowOnMapBtn = getChild<LLButton>("map_btn");
+ mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this));
+
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ mSaveBtn = getChild<LLButton>("save_btn");
+ mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this));
+
+ mCancelBtn = getChild<LLButton>("cancel_btn");
+ mCancelBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCancelButtonClicked, this));
+
+ mCloseBtn = getChild<LLButton>("close_btn");
+ mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+
+ mOverflowBtn = getChild<LLButton>("overflow_btn");
+ mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
+
+ mPlaceInfoBtn = getChild<LLButton>("profile_btn");
+ mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this));
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Places.OverflowMenu.Action", boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2));
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("Places.OverflowMenu.Enable", boost::bind(&LLPanelPlaces::onOverflowMenuItemEnable, this, _2));
+
+ mPlaceMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (!mPlaceMenu)
+ {
+ llwarns << "Error loading Place menu" << llendl;
+ }
+
+ mLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (!mLandmarkMenu)
+ {
+ llwarns << "Error loading Landmark menu" << llendl;
+ }
+
mTabContainer = getChild<LLTabContainer>("Places Tabs");
if (mTabContainer)
{
mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this));
}
- mSearchEditor = getChild<LLSearchEditor>("Filter");
- if (mSearchEditor)
+ mFilterEditor = getChild<LLFilterEditor>("Filter");
+ if (mFilterEditor)
{
- mSearchEditor->setSearchCallback(boost::bind(&LLPanelPlaces::onSearchEdit, this, _1));
- }
+ //when list item is being clicked the filter editor looses focus
+ //committing on focus lost leads to detaching list items
+ //BUT a detached list item cannot be made selected and must not be clicked onto
+ mFilterEditor->setCommitOnFocusLost(false);
- mPlaceInfo = dynamic_cast<LLPanelPlaceInfo*>(getChild<LLPanel>("panel_landmark_info"));
- if (mPlaceInfo)
- {
- LLButton* back_btn = mPlaceInfo->getChild<LLButton>("back_btn");
- if (back_btn)
- {
- back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
- }
+ mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2, false));
}
- //childSetAction("share_btn", boost::bind(&LLPanelPlaces::onShareButtonClicked, this), this);
- childSetAction("teleport_btn", boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this), this);
- childSetAction("map_btn", boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this), this);
+ mPlaceProfile = findChild<LLPanelPlaceProfile>("panel_place_profile");
+ mLandmarkInfo = findChild<LLPanelLandmarkInfo>("panel_landmark_info");
+ if (!mPlaceProfile || !mLandmarkInfo)
+ return FALSE;
- return TRUE;
-}
+ mPlaceProfileBackBtn = mPlaceProfile->getChild<LLButton>("back_btn");
+ mPlaceProfileBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
-void LLPanelPlaces::draw()
-{
- LLPanel::draw();
+ mLandmarkInfoBackBtn = mLandmarkInfo->getChild<LLButton>("back_btn");
+ mLandmarkInfoBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+
+ LLLineEditor* title_editor = mLandmarkInfo->getChild<LLLineEditor>("title_editor");
+ title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL);
+
+ LLTextEditor* notes_editor = mLandmarkInfo->getChild<LLTextEditor>("notes_editor");
+ notes_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ LLComboBox* folder_combo = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
+ folder_combo->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ return TRUE;
}
void LLPanelPlaces::onOpen(const LLSD& key)
{
- if(key.size() == 0)
+ LLFirstUse::notUsingDestinationGuide(false);
+
+ if (!mPlaceProfile || !mLandmarkInfo)
return;
- togglePlaceInfoPanel(TRUE);
-
- mPlaceInfoType = key["type"].asInteger();
+ if (key.size() != 0)
+ {
+ mFilterEditor->clear();
+ onFilterEdit("", false);
+
+ mPlaceInfoType = key["type"].asString();
+ mPosGlobal.setZero();
+ mItem = NULL;
+ isLandmarkEditModeOn = false;
+ togglePlaceInfoPanel(TRUE);
+
+ if (mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
+ }
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ {
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
+
+ if (key.has("x") && key.has("y") && key.has("z"))
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ }
+ else
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
+
+ mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
+
+ // Disabling "Save", "Close" and "Back" buttons to prevent closing "Create Landmark"
+ // panel before created landmark is loaded.
+ // These buttons will be enabled when created landmark is added to inventory.
+ mSaveBtn->setEnabled(FALSE);
+ mCloseBtn->setEnabled(FALSE);
+ mLandmarkInfoBackBtn->setEnabled(FALSE);
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+
+ LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
+ if (!item)
+ return;
+
+ setItem(item);
+ }
+ else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
+ {
+ if (key.has("id"))
+ {
+ LLUUID parcel_id = key["id"].asUUID();
+ mPlaceProfile->setParcelID(parcel_id);
+
+ // query the server to get the global 3D position of this
+ // parcel - we need this for teleport/mapping functions.
+ mRemoteParcelObserver->setParcelID(parcel_id);
+ }
+ else
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ }
+
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
+ }
+ else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ S32 index = key["id"].asInteger();
+
+ const LLTeleportHistoryStorage::slurl_list_t& hist_items =
+ LLTeleportHistoryStorage::getInstance()->getItems();
+
+ mPosGlobal = hist_items[index].mGlobalPos;
+
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ }
+
+ updateVerbs();
+ }
- if (mPlaceInfoType == AGENT)
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ if (!parcel_mgr)
+ return;
+
+ // Start using LLViewerParcelMgr for land selection if
+ // information about nearby land is requested.
+ // Otherwise stop using land selection and deselect land.
+ if (mPlaceInfoType == AGENT_INFO_TYPE)
{
- // We don't need to teleport to the current location so disable the button
- getChild<LLButton>("teleport_btn")->setEnabled(FALSE);
+ // We don't know if we are already added to LLViewerParcelMgr observers list
+ // so try to remove observer not to add an extra one.
+ parcel_mgr->removeObserver(mParcelObserver);
- mPlaceInfo->displayParcelInfo(gAgent.getPositionAgent(),
- gAgent.getRegion()->getRegionID(),
- gAgent.getPositionGlobal());
+ parcel_mgr->addObserver(mParcelObserver);
+ parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());
}
- else if (mPlaceInfoType == LANDMARK)
+ else
{
- LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
- if (!item)
- return;
+ parcel_mgr->removeObserver(mParcelObserver);
- mPlaceInfo->displayItemInfo(item);
+ // Clear the reference to selection to allow its removal in deselectUnused().
+ mParcel.clear();
- LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
- if (!landmark)
- return;
+ if (!parcel_mgr->selectionEmpty())
+ {
+ parcel_mgr->deselectUnused();
+ }
+ }
+}
+
+void LLPanelPlaces::setItem(LLInventoryItem* item)
+{
+ if (!mLandmarkInfo || !item)
+ return;
- LLUUID region_id;
- landmark->getRegionID(region_id);
- LLVector3d pos_global;
- landmark->getGlobalPos(pos_global);
- mPlaceInfo->displayParcelInfo(landmark->getRegionPos(),
- region_id,
- pos_global);
+ mItem = item;
+ LLAssetType::EType item_type = mItem->getActualType();
+ if (item_type == LLAssetType::AT_LANDMARK || item_type == LLAssetType::AT_LINK)
+ {
+ // If the item is a link get a linked item
+ if (item_type == LLAssetType::AT_LINK)
+ {
+ mItem = gInventory.getItem(mItem->getLinkedUUID());
+ if (mItem.isNull())
+ return;
+ }
}
- else if (mPlaceInfoType == TELEPORT_HISTORY)
+ else
{
- S32 index = key["id"].asInteger();
+ return;
+ }
- const LLTeleportHistory::slurl_list_t& hist_items =
- LLTeleportHistory::getInstance()->getItems();
+ // Check if item is in agent's inventory and he has the permission to modify it.
+ BOOL is_landmark_editable = gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) &&
+ mItem->getPermissions().allowModifyBy(gAgent.getID());
- LLVector3d pos_global = hist_items[index].mGlobalPos;
+ mEditBtn->setEnabled(is_landmark_editable);
+ mSaveBtn->setEnabled(is_landmark_editable);
+ mCloseBtn->setEnabled(TRUE);
+ mLandmarkInfoBackBtn->setEnabled(TRUE);
- F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
- F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
+ if (is_landmark_editable)
+ {
+ if(!mLandmarkInfo->setLandmarkFolder(mItem->getParentUUID()) && !mItem->getParentUUID().isNull())
+ {
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(mItem->getParentUUID());
+ if (cat)
+ {
+ std::string cat_fullname = LLPanelLandmarkInfo::getFullFolderName(cat);
+ LLComboBox* folderList = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
+ folderList->add(cat_fullname, cat->getUUID(), ADD_TOP);
+ }
+ }
+ }
- LLVector3 pos_local(region_x, region_y, (F32)pos_global.mdV[VZ]);
+ mLandmarkInfo->displayItemInfo(mItem);
- mPlaceInfo->displayParcelInfo(pos_local,
- hist_items[index].mRegionID,
- pos_global);
+ LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(),
+ boost::bind(&LLPanelPlaces::onLandmarkLoaded, this, _1));
+ if (lm)
+ {
+ onLandmarkLoaded(lm);
}
}
-void LLPanelPlaces::onSearchEdit(const std::string& search_string)
+S32 LLPanelPlaces::notifyParent(const LLSD& info)
{
- if (mFilterSubString != search_string)
+ if(info.has("update_verbs"))
{
- mFilterSubString = search_string;
+ if(mPosGlobal.isExactlyZero())
+ {
+ mPosGlobal.setVec(info["global_x"], info["global_y"], info["global_z"]);
+ }
+
+ updateVerbs();
+
+ return 1;
+ }
+ return LLPanel::notifyParent(info);
+}
+
+void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark)
+{
+ if (!mLandmarkInfo)
+ return;
+
+ LLUUID region_id;
+ landmark->getRegionID(region_id);
+ landmark->getGlobalPos(mPosGlobal);
+ mLandmarkInfo->displayParcelInfo(region_id, mPosGlobal);
+
+ updateVerbs();
+}
- LLStringUtil::toUpper(mFilterSubString);
- LLStringUtil::trimHead(mFilterSubString);
+void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_filter)
+{
+ if (!mActivePanel)
+ return;
- mSearchEditor->setText(mFilterSubString);
+ if (force_filter || mActivePanel->getFilterSubString() != search_string)
+ {
+ std::string string = search_string;
- mActivePanel->onSearchEdit(mFilterSubString);
+ // Searches are case-insensitive
+ // but we don't convert the typed string to upper-case so that it can be fed to the web search as-is.
+
+ mActivePanel->onSearchEdit(string);
}
}
void LLPanelPlaces::onTabSelected()
{
+ mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
if (!mActivePanel)
return;
- mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
+ onFilterEdit(mActivePanel->getFilterSubString(), true);
+ mActivePanel->updateVerbs();
+}
- if (mActivePanel)
+void LLPanelPlaces::onTeleportButtonClicked()
+{
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel && panel->getVisible())
+ {
+ if (mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ LLSD payload;
+ payload["asset_id"] = mItem->getAssetUUID();
+ LLSD args;
+ args["LOCATION"] = mItem->getName();
+ LLNotificationsUtil::add("TeleportFromLandmark", args, payload);
+ }
+ else if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if (!mPosGlobal.isExactlyZero() && worldmap_instance)
+ {
+ gAgent.teleportViaLocation(mPosGlobal);
+ worldmap_instance->trackLocation(mPosGlobal);
+ }
+ }
+ }
+ else
{
- mActivePanel->onSearchEdit(mFilterSubString);
- mActivePanel->onTabSelected();
+ if (mActivePanel)
+ mActivePanel->onTeleport();
}
}
-void LLPanelPlaces::onShareButtonClicked()
+void LLPanelPlaces::onShowOnMapButtonClicked()
{
- // TODO: Launch the "Things" Share wizard
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel && panel->getVisible())
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if(!worldmap_instance)
+ return;
+
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ if (!mPosGlobal.isExactlyZero())
+ {
+ worldmap_instance->trackLocation(mPosGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ LLLandmark* landmark = gLandmarkList.getAsset(mItem->getAssetUUID());
+ if (!landmark)
+ return;
+
+ LLVector3d landmark_global_pos;
+ if (!landmark->getGlobalPos(landmark_global_pos))
+ return;
+
+ if (!landmark_global_pos.isExactlyZero())
+ {
+ worldmap_instance->trackLocation(landmark_global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+ }
+ else
+ {
+ if (mActivePanel && mActivePanel->isSingleItemSelected())
+ {
+ mActivePanel->onShowOnMap();
+ }
+ else
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ LLVector3d global_pos = gAgent.getPositionGlobal();
+
+ if (!global_pos.isExactlyZero() && worldmap_instance)
+ {
+ worldmap_instance->trackLocation(global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+ }
}
-/*
-void LLPanelPlaces::onAddLandmarkButtonClicked()
+void LLPanelPlaces::onEditButtonClicked()
{
- LLFloaterReg::showInstance("add_landmark");
+ if (!mLandmarkInfo || isLandmarkEditModeOn)
+ return;
+
+ isLandmarkEditModeOn = true;
+
+ mLandmarkInfo->toggleLandmarkEditMode(TRUE);
+
+ updateVerbs();
}
-void LLPanelPlaces::onCopySLURLButtonClicked()
+void LLPanelPlaces::onSaveButtonClicked()
{
- mActivePanel->onCopySLURL();
+ if (!mLandmarkInfo || mItem.isNull())
+ return;
+
+ std::string current_title_value = mLandmarkInfo->getLandmarkTitle();
+ std::string item_title_value = mItem->getName();
+ std::string current_notes_value = mLandmarkInfo->getLandmarkNotes();
+ std::string item_notes_value = mItem->getDescription();
+
+ LLStringUtil::trim(current_title_value);
+ LLStringUtil::trim(current_notes_value);
+
+ LLUUID item_id = mItem->getUUID();
+ LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem);
+
+ if (!current_title_value.empty() &&
+ (item_title_value != current_title_value || item_notes_value != current_notes_value))
+ {
+ new_item->rename(current_title_value);
+ new_item->setDescription(current_notes_value);
+ new_item->updateServer(FALSE);
+ }
+
+ if(folder_id != mItem->getParentUUID())
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ new_item->setParent(folder_id);
+ new_item->updateParentOnServer(FALSE);
+ }
+
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+
+ onCancelButtonClicked();
}
-*/
-void LLPanelPlaces::onTeleportButtonClicked()
+void LLPanelPlaces::onCancelButtonClicked()
{
- mActivePanel->onTeleport();
+ if (!mLandmarkInfo)
+ return;
+
+ if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ {
+ onBackButtonClicked();
+ }
+ else
+ {
+ mLandmarkInfo->toggleLandmarkEditMode(FALSE);
+ isLandmarkEditModeOn = false;
+
+ updateVerbs();
+
+ // Reload the landmark properties.
+ mLandmarkInfo->displayItemInfo(mItem);
+ }
}
-void LLPanelPlaces::onShowOnMapButtonClicked()
+void LLPanelPlaces::onOverflowButtonClicked()
{
- if (!mPlaceInfoType)
+ LLToggleableMenu* menu;
+
+ bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
+
+ if ((is_agent_place_info_visible ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE) && mPlaceMenu != NULL)
{
- LLVector3d global_pos = gAgent.getPositionGlobal();
- if (!global_pos.isExactlyZero())
- {
- LLFloaterWorldMap::getInstance()->trackLocation(global_pos);
- LLFloaterReg::showInstance("world_map", "center");
- }
+ menu = mPlaceMenu;
+
+ // Enable adding a landmark only for agent current parcel and if
+ // there is no landmark already pointing to that parcel in agent's inventory.
+ menu->getChild<LLMenuItemCallGL>("landmark")->setEnabled(is_agent_place_info_visible &&
+ !LLLandmarkActions::landmarkAlreadyExists());
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE && mLandmarkMenu != NULL)
+ {
+ menu = mLandmarkMenu;
+
+ BOOL is_landmark_removable = FALSE;
+ if (mItem.notNull())
+ {
+ const LLUUID& item_id = mItem->getUUID();
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ is_landmark_removable = gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) &&
+ !gInventory.isObjectDescendentOf(item_id, trash_id);
+ }
+
+ menu->getChild<LLMenuItemCallGL>("delete")->setEnabled(is_landmark_removable);
}
else
{
- mActivePanel->onShowOnMap();
+ return;
+ }
+
+ if (!menu->toggleVisibility())
+ return;
+
+ if (menu->getButtonRect().isEmpty())
+ {
+ menu->setButtonRect(mOverflowBtn);
+ }
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLRect rect = mOverflowBtn->getRect();
+ LLMenuGL::showPopup(this, menu, rect.mRight, rect.mTop);
+}
+
+void LLPanelPlaces::onProfileButtonClicked()
+{
+ if (!mActivePanel)
+ return;
+
+ mActivePanel->onShowProfile();
+}
+
+bool LLPanelPlaces::onOverflowMenuItemEnable(const LLSD& param)
+{
+ std::string value = param.asString();
+ if("can_create_pick" == value)
+ {
+ return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
+ }
+ return true;
+}
+
+void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
+{
+ std::string item = param.asString();
+ if (item == "landmark")
+ {
+ LLSD key;
+ key["type"] = CREATE_LANDMARK_INFO_TYPE;
+ key["x"] = mPosGlobal.mdV[VX];
+ key["y"] = mPosGlobal.mdV[VY];
+ key["z"] = mPosGlobal.mdV[VZ];
+ onOpen(key);
+ }
+ else if (item == "copy")
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(mPosGlobal, boost::bind(&onSLURLBuilt, _1));
+ }
+ else if (item == "delete")
+ {
+ gInventory.removeItem(mItem->getUUID());
+
+ onBackButtonClicked();
+ }
+ else if (item == "pick")
+ {
+ if (mPickPanel == NULL)
+ {
+ mPickPanel = LLPanelPickEdit::create();
+ addChild(mPickPanel);
+
+ mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
+ mPickPanel->setCancelCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
+ mPickPanel->setSaveCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
+ }
+
+ togglePickPanel(TRUE);
+ mPickPanel->onOpen(LLSD());
+
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel)
+ {
+ panel->createPick(mPosGlobal, mPickPanel);
+ }
+
+ LLRect rect = getRect();
+ mPickPanel->reshape(rect.getWidth(), rect.getHeight());
+ mPickPanel->setRect(rect);
+ }
+ else if (item == "add_to_favbar")
+ {
+ if ( mItem.notNull() )
+ {
+ const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ if ( favorites_id.notNull() )
+ {
+ copy_inventory_item(gAgent.getID(),
+ mItem->getPermissions().getOwner(),
+ mItem->getUUID(),
+ favorites_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
+ }
+ }
}
}
void LLPanelPlaces::onBackButtonClicked()
{
togglePlaceInfoPanel(FALSE);
+
+ // Resetting mPlaceInfoType when Place Info panel is closed.
+ mPlaceInfoType = LLStringUtil::null;
+
+ isLandmarkEditModeOn = false;
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::togglePickPanel(BOOL visible)
+{
+ if (mPickPanel)
+ mPickPanel->setVisible(visible);
}
void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
{
- if (!mPlaceInfo)
+ if (!mPlaceProfile || !mLandmarkInfo)
return;
- mPlaceInfo->setVisible(visible);
- mSearchEditor->setVisible(!visible);
+ mFilterEditor->setVisible(!visible);
mTabContainer->setVisible(!visible);
- if (visible)
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
{
- mPlaceInfo->resetLocation();
+ mPlaceProfile->setVisible(visible);
- LLRect rect = getRect();
- LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
- mPlaceInfo->reshape(new_rect.getWidth(),new_rect.getHeight());
+ if (visible)
+ {
+ mPlaceProfile->resetLocation();
+
+ // Do not reset location info until mResetInfoTimer has expired
+ // to avoid text blinking.
+ mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL);
+
+ LLRect rect = getRect();
+ LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
+ mPlaceProfile->reshape(new_rect.getWidth(), new_rect.getHeight());
+
+ mLandmarkInfo->setVisible(FALSE);
+ }
+ else if (mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ // Clear reference to parcel selection when closing place profile panel.
+ // LLViewerParcelMgr removes the selection if it has 1 reference to it.
+ mParcel.clear();
+ }
+ }
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
+ mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ mLandmarkInfo->setVisible(visible);
+
+ if (visible)
+ {
+ mLandmarkInfo->resetLocation();
+
+ LLRect rect = getRect();
+ LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
+ mLandmarkInfo->reshape(new_rect.getWidth(), new_rect.getHeight());
+
+ mPlaceProfile->setVisible(FALSE);
+ }
+ else
+ {
+ LLLandmarksPanel* landmarks_panel =
+ dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
+ if (landmarks_panel && mItem.notNull())
+ {
+ // If a landmark info is being closed we open the landmarks tab
+ // and set this landmark selected.
+ mTabContainer->selectTabPanel(landmarks_panel);
+
+ landmarks_panel->setItemSelected(mItem->getUUID(), TRUE);
+ }
+ }
+ }
+}
+
+// virtual
+void LLPanelPlaces::handleVisibilityChange(BOOL new_visibility)
+{
+ LLPanel::handleVisibilityChange(new_visibility);
+
+ if (!new_visibility && mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ // Clear reference to parcel selection when closing places panel.
+ mParcel.clear();
+ }
+}
+
+void LLPanelPlaces::changedParcelSelection()
+{
+ if (!mPlaceProfile)
+ return;
+
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ mParcel = parcel_mgr->getFloatingParcelSelection();
+ LLParcel* parcel = mParcel->getParcel();
+ LLViewerRegion* region = parcel_mgr->getSelectionRegion();
+ if (!region || !parcel)
+ return;
+
+ LLVector3d prev_pos_global = mPosGlobal;
+
+ // If agent is inside the selected parcel show agent's region<X, Y, Z>,
+ // otherwise show region<X, Y, Z> of agent's selection point.
+ bool is_current_parcel = is_agent_in_selected_parcel(parcel);
+ if (is_current_parcel)
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
+ else
+ {
+ LLVector3d pos_global = gViewerWindow->getLastPick().mPosGlobal;
+ if (!pos_global.isExactlyZero())
+ {
+ mPosGlobal = pos_global;
+ }
+ }
+
+ // Reset location info only if global position has changed
+ // and update timer has expired to reduce unnecessary text and icons updates.
+ if (prev_pos_global != mPosGlobal && mResetInfoTimer.hasExpired())
+ {
+ mPlaceProfile->resetLocation();
+ mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL);
}
+
+ mPlaceProfile->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel);
+
+ updateVerbs();
}
-//virtual
-void LLPanelPlaces::changed(U32 mask)
+void LLPanelPlaces::createTabs()
{
if (!(gInventory.isInventoryUsable() && LLTeleportHistory::getInstance()))
return;
@@ -267,7 +1035,7 @@ void LLPanelPlaces::changed(U32 mask)
mTabContainer->addTabPanel(
LLTabContainer::TabPanelParams().
panel(landmarks_panel).
- label("Landmarks").
+ label(getString("landmarks_tab_title")).
insert_at(LLTabContainer::END));
}
@@ -279,7 +1047,7 @@ void LLPanelPlaces::changed(U32 mask)
mTabContainer->addTabPanel(
LLTabContainer::TabPanelParams().
panel(teleport_history_panel).
- label("Teleport History").
+ label(getString("teleport_history_tab_title")).
insert_at(LLTabContainer::END));
}
@@ -287,7 +1055,138 @@ void LLPanelPlaces::changed(U32 mask)
mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
- // we don't need to monitor inventory changes anymore,
- // so remove the observer
- gInventory.removeObserver(this);
+ // Filter applied to show all items.
+ if (mActivePanel)
+ mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
+}
+
+void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos)
+{
+ mPosGlobal = global_pos;
+ updateVerbs();
+}
+
+void LLPanelPlaces::showAddedLandmarkInfo(const uuid_vec_t& items)
+{
+ for (uuid_vec_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
+ {
+ const LLUUID& item_id = (*item_iter);
+ if(!highlight_offered_object(item_id))
+ {
+ continue;
+ }
+
+ LLInventoryItem* item = gInventory.getItem(item_id);
+
+ llassert(item);
+ if (item && (LLAssetType::AT_LANDMARK == item->getType()) )
+ {
+ // Created landmark is passed to Places panel to allow its editing.
+ // If the panel is closed we don't reopen it until created landmark is loaded.
+ if("create_landmark" == getPlaceInfoType() && !getItem())
+ {
+ setItem(item);
+ }
+ }
+ }
+}
+
+void LLPanelPlaces::updateVerbs()
+{
+ bool is_place_info_visible;
+
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel)
+ {
+ is_place_info_visible = panel->getVisible();
+ }
+ else
+ {
+ is_place_info_visible = false;
+ }
+
+ bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
+ bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
+ bool have_3d_pos = ! mPosGlobal.isExactlyZero();
+
+ mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
+ mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
+ mSaveBtn->setVisible(isLandmarkEditModeOn);
+ mCancelBtn->setVisible(isLandmarkEditModeOn);
+ mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
+ mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
+
+ mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);
+
+ if (is_place_info_visible)
+ {
+ mShowOnMapBtn->setEnabled(have_3d_pos);
+
+ if (is_agent_place_info_visible)
+ {
+ // We don't need to teleport to the current location
+ // so check if the location is not within the current parcel.
+ mTeleportBtn->setEnabled(have_3d_pos &&
+ !LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal));
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
+ {
+ mTeleportBtn->setEnabled(have_3d_pos);
+ }
+
+ // Do not enable landmark info Back button when we are waiting
+ // for newly created landmark to load.
+ if (!is_create_landmark_visible)
+ {
+ mLandmarkInfoBackBtn->setEnabled(TRUE);
+ }
+ }
+ else
+ {
+ if (mActivePanel)
+ mActivePanel->updateVerbs();
+ }
+}
+
+LLPanelPlaceInfo* LLPanelPlaces::getCurrentInfoPanel()
+{
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ return mPlaceProfile;
+ }
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
+ mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ return mLandmarkInfo;
+ }
+
+ return NULL;
+}
+
+static bool is_agent_in_selected_parcel(LLParcel* parcel)
+{
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+
+ LLViewerRegion* region = parcel_mgr->getSelectionRegion();
+ if (!region || !parcel)
+ return false;
+
+ return region == gAgent.getRegion() &&
+ parcel->getLocalID() == parcel_mgr->getAgentParcel()->getLocalID();
+}
+
+static void onSLURLBuilt(std::string& slurl)
+{
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
+
+ LLSD args;
+ args["SLURL"] = slurl;
+
+ LLNotificationsUtil::add("CopySLURL", args);
}