summaryrefslogtreecommitdiff
path: root/indra/newview/llpanelpicks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llpanelpicks.cpp')
-rw-r--r--indra/newview/llpanelpicks.cpp603
1 files changed, 603 insertions, 0 deletions
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
new file mode 100644
index 0000000000..973afae73b
--- /dev/null
+++ b/indra/newview/llpanelpicks.cpp
@@ -0,0 +1,603 @@
+/**
+ * @file llpanelpicks.cpp
+ * @brief LLPanelPicks and related class implementations
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * 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.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llavatarconstants.h"
+#include "lltexturectrl.h"
+#include "llviewergenericmessage.h" // send_generic_message
+#include "llmenugl.h"
+#include "llviewermenu.h"
+#include "llregistry.h"
+
+#include "llpanelpicks.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llpanelavatar.h"
+#include "llpanelprofile.h"
+#include "llpanelpick.h"
+#include "llscrollcontainer.h"
+
+static const std::string XML_BTN_NEW = "new_btn";
+static const std::string XML_BTN_DELETE = "trash_btn";
+static const std::string XML_BTN_INFO = "info_btn";
+static const std::string XML_BTN_TELEPORT = "teleport_btn";
+static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn";
+
+static const std::string XML_PICKS_LIST = "back_panel";
+
+#define PICK_ITEMS_BETWEEN 5
+
+static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
+
+//-----------------------------------------------------------------------------
+// LLPanelPicks
+//-----------------------------------------------------------------------------
+LLPanelPicks::LLPanelPicks()
+: LLPanelProfileTab(),
+ mPopupMenu(NULL),
+ mSelectedPickItem(NULL),
+ mProfilePanel(NULL),
+ mPickPanel(NULL)
+{
+}
+
+LLPanelPicks::~LLPanelPicks()
+{
+ if(getAvatarId().notNull())
+ {
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
+ }
+}
+
+void* LLPanelPicks::create(void* data /* = NULL */)
+{
+ return new LLPanelPicks();
+}
+
+void LLPanelPicks::updateData()
+{
+ LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(getAvatarId(),APT_PICKS);
+}
+
+void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
+{
+ if(APT_PICKS == type)
+ {
+ LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data);
+ if(avatar_picks && getAvatarId() == avatar_picks->target_id)
+ {
+ std::string name, second_name;
+ gCacheName->getName(getAvatarId(),name,second_name);
+ childSetTextArg("pick_title", "[NAME]",name);
+
+ LLView* picks_list = getPicksList();
+
+ // to restore selection of the same item later
+ LLUUID pick_id_selected(LLUUID::null);
+ if (mSelectedPickItem) pick_id_selected = mSelectedPickItem->getPickId();
+
+ clear();
+
+ //*TODO move it somewhere else?
+ picks_list->setEnabled(FALSE);
+ childSetEnabled(XML_BTN_NEW, false);
+ childSetEnabled(XML_BTN_DELETE, false);
+ childSetEnabled(XML_BTN_INFO, false);
+ childSetEnabled(XML_BTN_TELEPORT,!avatar_picks->picks_list.empty());
+ childSetEnabled(XML_BTN_SHOW_ON_MAP,!avatar_picks->picks_list.empty());
+
+ LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin();
+ for(; avatar_picks->picks_list.end() != it; ++it)
+ {
+ LLUUID pick_id = it->first;
+ std::string pick_name = it->second;
+
+ LLPickItem* picture = LLPickItem::create();
+ picture->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this));
+
+ picks_list->addChild(picture);
+
+ picture->setPickName(pick_name);
+ picture->setPickId(pick_id);
+ picture->setCreatorId(getAvatarId());
+
+ LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture);
+ picture->update();
+ mPickItemList.push_back(picture);
+ if (pick_id_selected != LLUUID::null &&
+ pick_id == pick_id_selected) setSelectedPickItem(picture);
+ }
+
+ reshapePicksList();
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
+
+ updateButtons();
+ if (!mSelectedPickItem && mPickItemList.size()) setSelectedPickItem(mPickItemList.back());
+ picks_list->setEnabled(TRUE);
+
+ }
+ }
+}
+
+void LLPanelPicks::clear()
+{
+ LLView* scroll = getPicksList();
+ picture_list_t::const_iterator it = mPickItemList.begin();
+ for(; mPickItemList.end() != it; ++it)
+ {
+ scroll->removeChild(*it);
+ delete *it;
+ }
+ mPickItemList.clear();
+ mSelectedPickItem = NULL;
+}
+
+
+LLPickItem* LLPanelPicks::getSelectedPickItem()
+{
+ return mSelectedPickItem;
+}
+
+
+void LLPanelPicks::removePickItem( LLPickItem* pick_item )
+{
+ LLView* scroll = getPicksList();
+ scroll->removeChild(pick_item);
+ mPickItemList.remove(pick_item);
+ if (mPickItemList.size() == 0)
+ {
+ mSelectedPickItem = NULL;
+ }
+ else
+ {
+ setSelectedPickItem(mPickItemList.back());
+ }
+
+ reshapePicksList();
+}
+
+void LLPanelPicks::reshapePicksList()
+{
+ if (!mPickItemList.size()) return;
+ LLView* pickList = getPicksList();
+
+ //We don't need to update size of the 'pick list' before reshaping pick items. Don't need to reshape the pick list
+ S32 height = mPickItemList.size() * (mPickItemList.front()->getRect().getHeight() + PICK_ITEMS_BETWEEN);
+ LLRect rc = pickList->getRect();
+ rc.setLeftTopAndSize(rc.mLeft, rc.mTop, rc.getWidth(), height);
+ pickList->setRect(rc);
+
+ S32 last_bottom = pickList->getRect().getHeight();
+ std::list<LLPickItem*>::const_iterator pick_it, pick_first_it = mPickItemList.begin();
+ for ( pick_it = pick_first_it; pick_it != mPickItemList.end(); ++pick_it)
+ {
+ LLView* const pick = *pick_it;
+ if(pick_it != pick_first_it)
+ {
+ last_bottom -= pick->getRect().getHeight();
+ last_bottom -= PICK_ITEMS_BETWEEN;
+ }
+ reshapePickItem(pick, last_bottom,pickList->getRect().getWidth());
+ }
+}
+
+void LLPanelPicks::reshapePickItem(LLView* const pick_item, const S32 last_bottom, const S32 newWidth)
+{
+ LLRect rc = pick_item->getRect();
+ rc.mBottom = last_bottom - rc.getHeight();
+ rc.mTop = last_bottom;
+ pick_item->setRect(rc);
+ pick_item->reshape(newWidth, rc.getHeight());
+}
+
+LLView* LLPanelPicks::getPicksList() const
+{
+ return getChild<LLView>(XML_PICKS_LIST);
+}
+
+BOOL LLPanelPicks::postBuild()
+{
+ childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this));
+
+ childSetAction("teleport_btn", boost::bind(&LLPanelPicks::onClickTeleport, this));
+ childSetAction("show_on_map_btn", boost::bind(&LLPanelPicks::onClickMap, this));
+
+ childSetAction("info_btn", boost::bind(&LLPanelPicks::onClickInfo, this));
+ childSetAction("new_btn", boost::bind(&LLPanelPicks::onClickNew, this));
+
+ CommitCallbackRegistry::ScopedRegistrar registar;
+ registar.add("Pick.Info", boost::bind(&LLPanelPicks::onClickInfo, this));
+ registar.add("Pick.Edit", boost::bind(&LLPanelPicks::onClickMenuEdit, this));
+ registar.add("Pick.Teleport", boost::bind(&LLPanelPicks::onClickTeleport, this));
+ registar.add("Pick.Map", boost::bind(&LLPanelPicks::onClickMap, this));
+ registar.add("Pick.Delete", boost::bind(&LLPanelPicks::onClickDelete, this));
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+ return TRUE;
+}
+
+void LLPanelPicks::onOpen(const LLSD& key)
+{
+ const LLUUID id(key.asUUID());
+ BOOL self = (gAgent.getID() == id);
+
+ // only agent can edit her picks
+ childSetEnabled("edit_panel", self);
+ childSetVisible("edit_panel", self);
+
+ // Disable buttons when viewing profile for first time
+ if(getAvatarId() != id)
+ {
+ clear();
+
+ childSetEnabled(XML_BTN_INFO,FALSE);
+ childSetEnabled(XML_BTN_TELEPORT,FALSE);
+ childSetEnabled(XML_BTN_SHOW_ON_MAP,FALSE);
+ }
+
+ // and see a special title - set as invisible by default in xml file
+ if (self)
+ {
+ childSetVisible("pick_title", !self);
+ childSetVisible("pick_title_agent", self);
+ }
+
+ LLPanelProfileTab::onOpen(key);
+}
+
+//static
+void LLPanelPicks::onClickDelete()
+{
+ LLPickItem* pick_item = getSelectedPickItem();
+ if (!pick_item) return;
+
+ LLSD args;
+ args["PICK"] = pick_item->getPickName();
+ LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDelete, this, _1, _2));
+}
+
+bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ LLPickItem* pick_item = getSelectedPickItem();
+
+ if (0 == option)
+ {
+ LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_item->getPickId());
+ removePickItem(pick_item);
+ }
+ updateButtons();
+ return false;
+}
+
+bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& response )
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ if (0 == option)
+ {
+ onClickTeleport();
+ }
+ return false;
+}
+
+//static
+void LLPanelPicks::onClickTeleport()
+{
+ LLPickItem* pick_item = getSelectedPickItem();
+ if (!pick_item) return;
+ LLPanelPick::teleport(pick_item->getPosGlobal());
+}
+
+//static
+void LLPanelPicks::onClickMap()
+{
+ LLPickItem* pick_item = getSelectedPickItem();
+ if (!pick_item) return;
+ LLPanelPick::showOnMap(pick_item->getPosGlobal());
+}
+
+
+BOOL LLPanelPicks::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (isMouseInPick(x, y))
+ {
+ if (mPopupMenu)
+ {
+ mPopupMenu->buildDrawLabels();
+ mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+ ((LLContextMenu*)mPopupMenu)->show(x, y);
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+ return TRUE;
+ }
+ return LLPanel::handleRightMouseDown(x, y, mask);
+}
+
+BOOL LLPanelPicks::handleMouseDown( S32 x, S32 y, MASK mask )
+{
+ isMouseInPick(x, y);
+ return LLPanel::handleMouseDown(x, y, mask);
+}
+
+BOOL LLPanelPicks::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ if (isMouseInPick(x, y))
+ {
+ LLPickItem* pick_item = getSelectedPickItem();
+ if (pick_item)
+ {
+ LLSD args;
+ args["PICK"] = pick_item->getPickName();
+ LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
+ }
+ return TRUE;
+ }
+ return LLPanel::handleDoubleClick(x, y, mask);
+}
+
+void LLPanelPicks::updateButtons()
+{
+ int picks_num = mPickItemList.size();
+ childSetEnabled(XML_BTN_INFO, picks_num > 0);
+
+ if (getAvatarId() == gAgentID)
+ {
+ childSetEnabled(XML_BTN_NEW, picks_num < MAX_AVATAR_PICKS);
+ childSetEnabled(XML_BTN_DELETE, picks_num > 0);
+
+ //*TODO move somewhere this calls
+ // we'd better set them up earlier when a panel was being constructed
+ mPopupMenu->setItemVisible("pick_delete", TRUE);
+ mPopupMenu->setItemVisible("pick_edit", TRUE);
+ mPopupMenu->setItemVisible("pick_separator", TRUE);
+ }
+
+ //*TODO update buttons like Show on Map, Teleport etc.
+
+}
+
+void LLPanelPicks::setSelectedPickItem(LLPickItem* item)
+{
+ if (!item) return;
+ if (mSelectedPickItem == item) return;
+ if (mSelectedPickItem && mSelectedPickItem->isBackgroundVisible())
+ {
+ mSelectedPickItem->setBackgroundVisible(FALSE);
+ }
+ item->setBackgroundVisible(TRUE);
+ mSelectedPickItem = item;
+}
+
+BOOL LLPanelPicks::isMouseInPick( S32 x, S32 y )
+{
+ S32 x_l = x;
+ S32 y_l = y;
+
+ if(!getChild<LLUICtrl>("profile_scroll")->getRect().pointInRect(x, y))
+ {
+ return FALSE;
+ }
+
+ picture_list_t::const_iterator it = mPickItemList.begin();
+ for(; mPickItemList.end() != it; ++it)
+ {
+ localPointToOtherView(x, y, &x_l, &y_l, (*it));
+ if ((*it)->pointInView(x_l, y_l))
+ {
+ setSelectedPickItem(*it);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
+{
+ mProfilePanel = profile_panel;
+}
+
+
+void LLPanelPicks::buildPickPanel()
+{
+ if (mPickPanel == NULL)
+ {
+ mPickPanel = new LLPanelPick();
+ mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onClickBack, this));
+ }
+}
+
+void LLPanelPicks::onClickNew()
+{
+ buildPickPanel();
+ mPickPanel->setEditMode(TRUE);
+ mPickPanel->createNewPick();
+ getProfilePanel()->togglePanel(mPickPanel);
+}
+
+void LLPanelPicks::onClickInfo()
+{
+ LLPickItem* pick = getSelectedPickItem();
+ if (!pick) return;
+
+ buildPickPanel();
+ mPickPanel->reset();
+ mPickPanel->init(pick->getCreatorId(), pick->getPickId());
+ getProfilePanel()->togglePanel(mPickPanel);
+}
+
+void LLPanelPicks::onClickBack()
+{
+ getProfilePanel()->togglePanel(mPickPanel);
+}
+
+void LLPanelPicks::onClickMenuEdit()
+{
+ //*TODO, refactor - most of that is similar to onClickInfo
+ LLPickItem* pick = getSelectedPickItem();
+ if (!pick) return;
+
+ buildPickPanel();
+ mPickPanel->reset();
+ mPickPanel->init(pick->getCreatorId(), pick->getPickId());
+ mPickPanel->setEditMode(TRUE);
+ getProfilePanel()->togglePanel(mPickPanel);
+}
+
+inline LLPanelProfile* LLPanelPicks::getProfilePanel()
+{
+ llassert_always(NULL != mProfilePanel);
+ return mProfilePanel;
+}
+
+//-----------------------------------------------------------------------------
+// LLPanelPicks
+//-----------------------------------------------------------------------------
+LLPickItem::LLPickItem()
+: LLPanel()
+, mPickID(LLUUID::null)
+, mCreatorID(LLUUID::null)
+, mParcelID(LLUUID::null)
+, mSnapshotID(LLUUID::null)
+, mNeedData(true)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this,"panel_pick_list_item.xml");
+}
+
+LLPickItem::~LLPickItem()
+{
+ if (mCreatorID.notNull())
+ {
+ LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
+ }
+
+}
+
+LLPickItem* LLPickItem::create()
+{
+ return new LLPickItem();
+}
+
+void LLPickItem::init(LLPickData* pick_data)
+{
+ setPickDesc(pick_data->desc);
+ setSnapshotId(pick_data->snapshot_id);
+ mPosGlobal = pick_data->pos_global;
+ mLocation = pick_data->location_text;
+
+ LLTextureCtrl* picture = getChild<LLTextureCtrl>("picture");
+ picture->setImageAssetID(pick_data->snapshot_id);
+}
+
+void LLPickItem::setPickName(const std::string& name)
+{
+ mPickName = name;
+ childSetValue("picture_name",name);
+
+}
+
+const std::string& LLPickItem::getPickName()
+{
+ return mPickName;
+}
+
+const LLUUID& LLPickItem::getCreatorId()
+{
+ return mCreatorID;
+}
+
+const LLUUID& LLPickItem::getSnapshotId()
+{
+ return mSnapshotID;
+}
+
+void LLPickItem::setPickDesc(const std::string& descr)
+{
+ childSetValue("picture_descr",descr);
+}
+
+void LLPickItem::setPickId(const LLUUID& id)
+{
+ mPickID = id;
+}
+
+const LLUUID& LLPickItem::getPickId()
+{
+ return mPickID;
+}
+
+const LLVector3d& LLPickItem::getPosGlobal()
+{
+ return mPosGlobal;
+}
+
+const std::string& LLPickItem::getLocation()
+{
+ return mLocation;
+}
+
+const std::string LLPickItem::getDescription()
+{
+ return childGetValue("picture_descr").asString();
+}
+
+void LLPickItem::update()
+{
+ mNeedData = true;
+ LLAvatarPropertiesProcessor::instance().sendDataRequest(mCreatorID, APT_PICK_INFO, &mPickID);
+ mNeedData = false;
+}
+
+void LLPickItem::processProperties(void *data, EAvatarProcessorType type)
+{
+ if (APT_PICK_INFO != type) return;
+ if (!data) return;
+
+ LLPickData* pick_data = static_cast<LLPickData *>(data);
+ if (!pick_data) return;
+ if (mPickID != pick_data->pick_id) return;
+
+ init(pick_data);
+ LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
+}
+
+void LLPanelPicks::onClose()
+{
+ // Toggle off Pick Info panel if it is visible.
+ if(mPickPanel && mPickPanel->getVisible())
+ {
+ getProfilePanel()->togglePanel(mPickPanel);
+ }
+}