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.cpp740
1 files changed, 693 insertions, 47 deletions
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index aa6909560d..bde8d02885 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -32,39 +32,150 @@
#include "llviewerprecompiledheaders.h"
+#include "llpanelpicks.h"
+
#include "llagent.h"
#include "llagentpicksinfo.h"
#include "llavatarconstants.h"
+#include "llcommandhandler.h"
+#include "lldispatcher.h"
#include "llflatlistview.h"
#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
+#include "llnotificationsutil.h"
#include "lltexturectrl.h"
#include "lltoggleablemenu.h"
+#include "lltrans.h"
#include "llviewergenericmessage.h" // send_generic_message
#include "llmenugl.h"
#include "llviewermenu.h"
#include "llregistry.h"
-#include "llpanelpicks.h"
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
#include "llavatarpropertiesprocessor.h"
#include "llpanelavatar.h"
#include "llpanelprofile.h"
#include "llpanelpick.h"
+#include "llpanelclassified.h"
+#include "llsidetray.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_BTN_OVERFLOW = "overflow_btn";
static const std::string PICK_ID("pick_id");
static const std::string PICK_CREATOR_ID("pick_creator_id");
static const std::string PICK_NAME("pick_name");
+static const std::string CLASSIFIED_ID("classified_id");
+static const std::string CLASSIFIED_NAME("classified_name");
+
static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
+class LLClassifiedHandler :
+ public LLCommandHandler,
+ public LLAvatarPropertiesObserver
+{
+public:
+ // throttle calls from untrusted browsers
+ LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {}
+
+ std::set<LLUUID> mClassifiedIds;
+
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ // handle app/classified/create urls first
+ if (params.size() == 1 && params[0].asString() == "create")
+ {
+ createClassified();
+ return true;
+ }
+
+ // then handle the general app/classified/{UUID}/{CMD} urls
+ if (params.size() < 2)
+ {
+ return false;
+ }
+
+ // get the ID for the classified
+ LLUUID classified_id;
+ if (!classified_id.set(params[0], FALSE))
+ {
+ return false;
+ }
+
+ // show the classified in the side tray.
+ // need to ask the server for more info first though...
+ const std::string verb = params[1].asString();
+ if (verb == "about")
+ {
+ mClassifiedIds.insert(classified_id);
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id);
+ return true;
+ }
+
+ return false;
+ }
+
+ void createClassified()
+ {
+ // open the new classified panel on the Me > Picks sidetray
+ LLSD params;
+ params["id"] = gAgent.getID();
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "create_classified";
+ LLSideTray::getInstance()->showPanel("panel_me", params);
+ }
+
+ void openClassified(LLAvatarClassifiedInfo* c_info)
+ {
+ // open the classified info panel on the Me > Picks sidetray
+ LLSD params;
+ params["id"] = c_info->creator_id;
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "classified_details";
+ params["classified_id"] = c_info->classified_id;
+ params["classified_creator_id"] = c_info->creator_id;
+ params["classified_snapshot_id"] = c_info->snapshot_id;
+ params["classified_name"] = c_info->name;
+ params["classified_desc"] = c_info->description;
+ params["from_search"] = true;
+ LLSideTray::getInstance()->showPanel("panel_profile_view", params);
+ }
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type)
+ {
+ if (APT_CLASSIFIED_INFO != type)
+ {
+ return;
+ }
+
+ // is this the classified that we asked for?
+ LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+ if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end())
+ {
+ return;
+ }
+
+ // open the detail side tray for this classified
+ openClassified(c_info);
+
+ // remove our observer now that we're done
+ mClassifiedIds.erase(c_info->classified_id);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this);
+ }
+
+};
+LLClassifiedHandler gClassifiedHandler;
+
+//////////////////////////////////////////////////////////////////////////
+
+
//-----------------------------------------------------------------------------
// LLPanelPicks
//-----------------------------------------------------------------------------
@@ -73,10 +184,16 @@ LLPanelPicks::LLPanelPicks()
mPopupMenu(NULL),
mProfilePanel(NULL),
mPickPanel(NULL),
- mPicksList(NULL)
- , mPanelPickInfo(NULL)
- , mPanelPickEdit(NULL)
- , mOverflowMenu(NULL)
+ mPicksList(NULL),
+ mClassifiedsList(NULL),
+ mPanelPickInfo(NULL),
+ mPanelPickEdit(NULL),
+ mPlusMenu(NULL),
+ mPicksAccTab(NULL),
+ mClassifiedsAccTab(NULL),
+ mPanelClassifiedInfo(NULL),
+ mNoClassifieds(false),
+ mNoPicks(false)
{
}
@@ -98,8 +215,16 @@ void LLPanelPicks::updateData()
// Send Picks request only when we need to, not on every onOpen(during tab switch).
if(isDirty())
{
+ mNoPicks = false;
+ mNoClassifieds = false;
+
+ childSetValue("picks_panel_text", LLTrans::getString("PicksClassifiedsLoadingText"));
+
mPicksList->clear();
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
+
+ mClassifiedsList->clear();
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId());
}
}
@@ -113,6 +238,9 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
std::string name, second_name;
gCacheName->getName(getAvatarId(),name,second_name);
childSetTextArg("pick_title", "[NAME]",name);
+
+ // Save selection, to be able to edit same item after saving changes. See EXT-3023.
+ LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID];
mPicksList->clear();
@@ -138,15 +266,70 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
mPicksList->addItem(picture, pick_value);
- picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1));
+ // Restore selection by item id.
+ if ( pick_id == selected_id )
+ mPicksList->selectItemByValue(pick_value);
+
+ picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickPickItem, this, _1));
picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4));
picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
}
+ showAccordion("tab_picks", mPicksList->size());
+
+ resetDirty();
+ updateButtons();
+ }
+
+ mNoPicks = !mPicksList->size();
+ }
+ else if(APT_CLASSIFIEDS == type)
+ {
+ LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data);
+ if(c_info && getAvatarId() == c_info->target_id)
+ {
+ // do not clear classified list in case we will receive two or more data packets.
+ // list has been cleared in updateData(). (fix for EXT-6436)
+
+ LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin();
+ for(; c_info->classifieds_list.end() != it; ++it)
+ {
+ LLAvatarClassifieds::classified_data c_data = *it;
+
+ LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), c_data.classified_id);
+ c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this));
+ c_item->setClassifiedName(c_data.name);
+
+ LLSD pick_value = LLSD();
+ pick_value.insert(CLASSIFIED_ID, c_data.classified_id);
+ pick_value.insert(CLASSIFIED_NAME, c_data.name);
+
+ mClassifiedsList->addItem(c_item, pick_value);
+
+ c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1));
+ c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4));
+ c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
+ }
+
+ showAccordion("tab_classifieds", mClassifiedsList->size());
+
resetDirty();
- LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
updateButtons();
}
+
+ mNoClassifieds = !mClassifiedsList->size();
+ }
+
+ if (mNoPicks && mNoClassifieds)
+ {
+ if(getAvatarId() == gAgentID)
+ {
+ childSetValue("picks_panel_text", LLTrans::getString("NoPicksClassifiedsText"));
+ }
+ else
+ {
+ childSetValue("picks_panel_text", LLTrans::getString("NoAvatarPicksClassifiedsText"));
+ }
}
}
@@ -158,16 +341,43 @@ LLPickItem* LLPanelPicks::getSelectedPickItem()
return dynamic_cast<LLPickItem*>(selected_item);
}
+LLClassifiedItem* LLPanelPicks::getSelectedClassifiedItem()
+{
+ LLPanel* selected_item = mClassifiedsList->getSelectedItem();
+ if (!selected_item)
+ {
+ return NULL;
+ }
+ return dynamic_cast<LLClassifiedItem*>(selected_item);
+}
+
BOOL LLPanelPicks::postBuild()
{
mPicksList = getChild<LLFlatListView>("picks_list");
+ mClassifiedsList = getChild<LLFlatListView>("classifieds_list");
+
+ mPicksList->setCommitOnSelectionChange(true);
+ mClassifiedsList->setCommitOnSelectionChange(true);
+
+ mPicksList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mPicksList));
+ mClassifiedsList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mClassifiedsList));
- childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickNew, this));
+ mPicksList->setNoItemsCommentText(getString("no_picks"));
+ mClassifiedsList->setNoItemsCommentText(getString("no_classifieds"));
+
+ childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickPlusBtn, this));
childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this));
childSetAction(XML_BTN_TELEPORT, boost::bind(&LLPanelPicks::onClickTeleport, this));
childSetAction(XML_BTN_SHOW_ON_MAP, boost::bind(&LLPanelPicks::onClickMap, this));
childSetAction(XML_BTN_INFO, boost::bind(&LLPanelPicks::onClickInfo, this));
- childSetAction(XML_BTN_OVERFLOW, boost::bind(&LLPanelPicks::onOverflowButtonClicked, this));
+
+ mPicksAccTab = getChild<LLAccordionCtrlTab>("tab_picks");
+ mPicksAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mPicksAccTab));
+ mPicksAccTab->setDisplayChildren(true);
+
+ mClassifiedsAccTab = getChild<LLAccordionCtrlTab>("tab_classifieds");
+ mClassifiedsAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mClassifiedsAccTab));
+ mClassifiedsAccTab->setDisplayChildren(false);
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
registar.add("Pick.Info", boost::bind(&LLPanelPicks::onClickInfo, this));
@@ -175,41 +385,73 @@ BOOL LLPanelPicks::postBuild()
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));
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registar;
+ enable_registar.add("Pick.Enable", boost::bind(&LLPanelPicks::onEnableMenuItem, this, _2));
+
mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_picks.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar overflow_registar;
- overflow_registar.add("PicksList.Overflow", boost::bind(&LLPanelPicks::onOverflowMenuItemClicked, this, _2));
- mOverflowMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar plus_registar;
+ plus_registar.add("Picks.Plus.Action", boost::bind(&LLPanelPicks::onPlusMenuItemClicked, this, _2));
+ mEnableCallbackRegistrar.add("Picks.Plus.Enable", boost::bind(&LLPanelPicks::isActionEnabled, this, _2));
+ mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
return TRUE;
}
-void LLPanelPicks::onOverflowMenuItemClicked(const LLSD& param)
+void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param)
{
std::string value = param.asString();
- if("info" == value)
+ if("new_pick" == value)
{
- onClickInfo();
+ createNewPick();
}
- else if("teleport" == value)
+ else if("new_classified" == value)
{
- onClickTeleport();
+ createNewClassified();
}
- else if("map" == value)
+}
+
+bool LLPanelPicks::isActionEnabled(const LLSD& userdata) const
+{
+ std::string command_name = userdata.asString();
+
+ if (command_name == "new_pick" && LLAgentPicksInfo::getInstance()->isPickLimitReached())
{
- onClickMap();
+ return false;
}
+
+ return true;
}
-void LLPanelPicks::onOverflowButtonClicked()
+bool LLPanelPicks::isClassifiedPublished(LLClassifiedItem* c_item)
{
- LLRect rect;
- childGetRect(XML_BTN_OVERFLOW, rect);
+ if(c_item)
+ {
+ LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()];
+ if(panel)
+ {
+ return !panel->isNewWithErrors();
+ }
+
+ // we've got this classified from server - it's published
+ return true;
+ }
+ return false;
+}
+
+void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab)
+{
+ if(!mPicksAccTab->getDisplayChildren())
+ {
+ mPicksList->resetSelection(true);
+ }
+ if(!mClassifiedsAccTab->getDisplayChildren())
+ {
+ mClassifiedsList->resetSelection(true);
+ }
- mOverflowMenu->updateParent(LLMenuGL::sMenuContainer);
- mOverflowMenu->setButtonRect(rect, this);
- LLMenuGL::showPopup(this, mOverflowMenu, rect.mRight, rect.mTop);
+ updateButtons();
}
void LLPanelPicks::onOpen(const LLSD& key)
@@ -242,6 +484,9 @@ void LLPanelPicks::onOpen(const LLSD& key)
if(getAvatarId() != id)
{
+ showAccordion("tab_picks", false);
+ showAccordion("tab_classifieds", false);
+
mPicksList->goToTop();
// Set dummy value to make panel dirty and make it reload picks
setValue(LLSD());
@@ -250,21 +495,62 @@ void LLPanelPicks::onOpen(const LLSD& key)
LLPanelProfileTab::onOpen(key);
}
+void LLPanelPicks::onClosePanel()
+{
+ if (mPanelClassifiedInfo)
+ {
+ onPanelClassifiedClose(mPanelClassifiedInfo);
+ }
+ if (mPanelPickInfo)
+ {
+ onPanelPickClose(mPanelPickInfo);
+ }
+}
+
+void LLPanelPicks::onListCommit(const LLFlatListView* f_list)
+{
+ // Make sure only one of the lists has selection.
+ if(f_list == mPicksList)
+ {
+ mClassifiedsList->resetSelection(true);
+ }
+ else if(f_list == mClassifiedsList)
+ {
+ mPicksList->resetSelection(true);
+ }
+ else
+ {
+ llwarns << "Unknown list" << llendl;
+ }
+
+ updateButtons();
+}
+
//static
void LLPanelPicks::onClickDelete()
{
- LLSD pick_value = mPicksList->getSelectedValue();
- if (pick_value.isUndefined()) return;
+ LLSD value = mPicksList->getSelectedValue();
+ if (value.isDefined())
+ {
+ LLSD args;
+ args["PICK"] = value[PICK_NAME];
+ LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeletePick, this, _1, _2));
+ return;
+ }
- LLSD args;
- args["PICK"] = pick_value[PICK_NAME];
- LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDelete, this, _1, _2));
+ value = mClassifiedsList->getSelectedValue();
+ if(value.isDefined())
+ {
+ LLSD args;
+ args["NAME"] = value[CLASSIFIED_NAME];
+ LLNotificationsUtil::add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeleteClassified, this, _1, _2));
+ return;
+ }
}
-bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response)
+bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLSD pick_value = mPicksList->getSelectedValue();
if (0 == option)
@@ -276,9 +562,23 @@ bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response
return false;
}
+bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ LLSD value = mClassifiedsList->getSelectedValue();
+
+ if (0 == option)
+ {
+ LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]);
+ mClassifiedsList->removeItemByValue(value);
+ }
+ updateButtons();
+ return false;
+}
+
bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& response )
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
@@ -291,9 +591,18 @@ bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& respo
void LLPanelPicks::onClickTeleport()
{
LLPickItem* pick_item = getSelectedPickItem();
- if (!pick_item) return;
+ LLClassifiedItem* c_item = getSelectedClassifiedItem();
+
+ LLVector3d pos;
+ if(pick_item)
+ pos = pick_item->getPosGlobal();
+ else if(c_item)
+ {
+ pos = c_item->getPosGlobal();
+ LLPanelClassifiedInfo::sendClickMessage("teleport", false,
+ c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null);
+ }
- LLVector3d pos = pick_item->getPosGlobal();
if (!pos.isExactlyZero())
{
gAgent.teleportViaLocation(pos);
@@ -305,9 +614,19 @@ void LLPanelPicks::onClickTeleport()
void LLPanelPicks::onClickMap()
{
LLPickItem* pick_item = getSelectedPickItem();
- if (!pick_item) return;
+ LLClassifiedItem* c_item = getSelectedClassifiedItem();
- LLFloaterWorldMap::getInstance()->trackLocation(pick_item->getPosGlobal());
+ LLVector3d pos;
+ if (pick_item)
+ pos = pick_item->getPosGlobal();
+ else if(c_item)
+ {
+ LLPanelClassifiedInfo::sendClickMessage("map", false,
+ c_item->getClassifiedId(), LLUUID::null, pos, LLStringUtil::null);
+ pos = c_item->getPosGlobal();
+ }
+
+ LLFloaterWorldMap::getInstance()->trackLocation(pos);
LLFloaterReg::showInstance("world_map", "center");
}
@@ -325,30 +644,44 @@ void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask)
}
}
-void LLPanelPicks::onDoubleClickItem(LLUICtrl* item)
+void LLPanelPicks::onDoubleClickPickItem(LLUICtrl* item)
{
LLSD pick_value = mPicksList->getSelectedValue();
if (pick_value.isUndefined()) return;
LLSD args;
args["PICK"] = pick_value[PICK_NAME];
- LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
+ LLNotificationsUtil::add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
+}
+
+void LLPanelPicks::onDoubleClickClassifiedItem(LLUICtrl* item)
+{
+ LLSD value = mClassifiedsList->getSelectedValue();
+ if (value.isUndefined()) return;
+
+ LLSD args;
+ args["CLASSIFIED"] = value[CLASSIFIED_NAME];
+ LLNotificationsUtil::add("TeleportToClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
}
void LLPanelPicks::updateButtons()
{
- bool has_selected = mPicksList->numSelected();
+ bool has_selected = mPicksList->numSelected() > 0 || mClassifiedsList->numSelected() > 0;
if (getAvatarId() == gAgentID)
{
- childSetEnabled(XML_BTN_NEW, !LLAgentPicksInfo::getInstance()->isPickLimitReached());
childSetEnabled(XML_BTN_DELETE, has_selected);
}
childSetEnabled(XML_BTN_INFO, has_selected);
childSetEnabled(XML_BTN_TELEPORT, has_selected);
childSetEnabled(XML_BTN_SHOW_ON_MAP, has_selected);
- childSetEnabled(XML_BTN_OVERFLOW, has_selected);
+
+ LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem());
+ if(c_item)
+ {
+ childSetEnabled(XML_BTN_INFO, isClassifiedPublished(c_item));
+ }
}
void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
@@ -366,15 +699,45 @@ void LLPanelPicks::buildPickPanel()
// }
}
-void LLPanelPicks::onClickNew()
+void LLPanelPicks::onClickPlusBtn()
+{
+ LLRect rect;
+ childGetRect(XML_BTN_NEW, rect);
+
+ mPlusMenu->updateParent(LLMenuGL::sMenuContainer);
+ mPlusMenu->setButtonRect(rect, this);
+ LLMenuGL::showPopup(this, mPlusMenu, rect.mLeft, rect.mTop);
+}
+
+void LLPanelPicks::createNewPick()
{
createPickEditPanel();
getProfilePanel()->openPanel(mPanelPickEdit, LLSD());
}
+void LLPanelPicks::createNewClassified()
+{
+ LLPanelClassifiedEdit* panel = NULL;
+ createClassifiedEditPanel(&panel);
+
+ getProfilePanel()->openPanel(panel, LLSD());
+}
+
void LLPanelPicks::onClickInfo()
{
+ if(mPicksList->numSelected() > 0)
+ {
+ openPickInfo();
+ }
+ else if(mClassifiedsList->numSelected() > 0)
+ {
+ openClassifiedInfo();
+ }
+}
+
+void LLPanelPicks::openPickInfo()
+{
LLSD selected_value = mPicksList->getSelectedValue();
if (selected_value.isUndefined()) return;
@@ -392,6 +755,37 @@ void LLPanelPicks::onClickInfo()
getProfilePanel()->openPanel(mPanelPickInfo, params);
}
+void LLPanelPicks::openClassifiedInfo()
+{
+ LLSD selected_value = mClassifiedsList->getSelectedValue();
+ if (selected_value.isUndefined()) return;
+
+ LLClassifiedItem* c_item = getSelectedClassifiedItem();
+ LLSD params;
+ params["classified_id"] = c_item->getClassifiedId();
+ params["classified_creator_id"] = c_item->getAvatarId();
+ params["classified_snapshot_id"] = c_item->getSnapshotId();
+ params["classified_name"] = c_item->getClassifiedName();
+ params["classified_desc"] = c_item->getDescription();
+ params["from_search"] = false;
+
+ openClassifiedInfo(params);
+}
+
+void LLPanelPicks::openClassifiedInfo(const LLSD &params)
+{
+ createClassifiedInfoPanel();
+ getProfilePanel()->openPanel(mPanelClassifiedInfo, params);
+}
+
+void LLPanelPicks::showAccordion(const std::string& name, bool show)
+{
+ LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name);
+ tab->setVisible(show);
+ LLAccordionCtrl* acc = getChild<LLAccordionCtrl>("accordion");
+ acc->arrange();
+}
+
void LLPanelPicks::onPanelPickClose(LLPanel* panel)
{
panel->setVisible(FALSE);
@@ -403,6 +797,81 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel)
updateButtons();
}
+void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel)
+{
+ if(!panel->canClose())
+ {
+ return;
+ }
+
+ if(panel->isNew())
+ {
+ mEditClassifiedPanels[panel->getClassifiedId()] = panel;
+
+ LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId());
+ c_item->fillIn(panel);
+
+ LLSD c_value;
+ c_value.insert(CLASSIFIED_ID, c_item->getClassifiedId());
+ c_value.insert(CLASSIFIED_NAME, c_item->getClassifiedName());
+ mClassifiedsList->addItem(c_item, c_value, ADD_TOP);
+
+ c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1));
+ c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4));
+ c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
+ c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this));
+
+ // order does matter, showAccordion will invoke arrange for accordions.
+ mClassifiedsAccTab->changeOpenClose(false);
+ showAccordion("tab_classifieds", true);
+ }
+ else if(panel->isNewWithErrors())
+ {
+ LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem());
+ llassert(c_item);
+ if (c_item)
+ {
+ c_item->fillIn(panel);
+ }
+ }
+ else
+ {
+ onPanelClassifiedClose(panel);
+ return;
+ }
+
+ onPanelPickClose(panel);
+ updateButtons();
+}
+
+void LLPanelPicks::onPanelClassifiedClose(LLPanelClassifiedInfo* panel)
+{
+ if(panel->getInfoLoaded() && !panel->isDirty())
+ {
+ std::vector<LLSD> values;
+ mClassifiedsList->getValues(values);
+ for(size_t n = 0; n < values.size(); ++n)
+ {
+ LLUUID c_id = values[n][CLASSIFIED_ID].asUUID();
+ if(panel->getClassifiedId() == c_id)
+ {
+ LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(
+ mClassifiedsList->getItemByValue(values[n]));
+ llassert(c_item);
+ if (c_item)
+ {
+ c_item->setClassifiedName(panel->getClassifiedName());
+ c_item->setDescription(panel->getDescription());
+ c_item->setSnapshotId(panel->getSnapshotId());
+ }
+ }
+ }
+ }
+
+ onPanelPickClose(panel);
+ updateButtons();
+}
+
void LLPanelPicks::createPickInfoPanel()
{
if(!mPanelPickInfo)
@@ -414,6 +883,30 @@ void LLPanelPicks::createPickInfoPanel()
}
}
+void LLPanelPicks::createClassifiedInfoPanel()
+{
+ if(!mPanelClassifiedInfo)
+ {
+ mPanelClassifiedInfo = LLPanelClassifiedInfo::create();
+ mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo));
+ mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelPicks::onPanelClassifiedEdit, this));
+ mPanelClassifiedInfo->setVisible(FALSE);
+ }
+}
+
+void LLPanelPicks::createClassifiedEditPanel(LLPanelClassifiedEdit** panel)
+{
+ if(panel)
+ {
+ LLPanelClassifiedEdit* new_panel = LLPanelClassifiedEdit::create();
+ new_panel->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel));
+ new_panel->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, new_panel));
+ new_panel->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, new_panel));
+ new_panel->setVisible(FALSE);
+ *panel = new_panel;
+ }
+}
+
void LLPanelPicks::createPickEditPanel()
{
if(!mPanelPickEdit)
@@ -473,9 +966,67 @@ void LLPanelPicks::onPanelPickEdit()
getProfilePanel()->openPanel(mPanelPickEdit, params);
}
+void LLPanelPicks::onPanelClassifiedEdit()
+{
+ LLSD selected_value = mClassifiedsList->getSelectedValue();
+ if (selected_value.isUndefined())
+ {
+ return;
+ }
+
+ LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem());
+ llassert(c_item);
+ if (!c_item)
+ {
+ return;
+ }
+
+ LLSD params;
+ params["classified_id"] = c_item->getClassifiedId();
+ params["classified_creator_id"] = c_item->getAvatarId();
+ params["snapshot_id"] = c_item->getSnapshotId();
+ params["name"] = c_item->getClassifiedName();
+ params["desc"] = c_item->getDescription();
+ params["category"] = (S32)c_item->getCategory();
+ params["content_type"] = (S32)c_item->getContentType();
+ params["auto_renew"] = c_item->getAutoRenew();
+ params["price_for_listing"] = c_item->getPriceForListing();
+ params["location_text"] = c_item->getLocationText();
+
+ LLPanelClassifiedEdit* panel = mEditClassifiedPanels[c_item->getClassifiedId()];
+ if(!panel)
+ {
+ createClassifiedEditPanel(&panel);
+ mEditClassifiedPanels[c_item->getClassifiedId()] = panel;
+ }
+ getProfilePanel()->openPanel(panel, params);
+ panel->setPosGlobal(c_item->getPosGlobal());
+}
+
void LLPanelPicks::onClickMenuEdit()
{
- onPanelPickEdit();
+ if(getSelectedPickItem())
+ {
+ onPanelPickEdit();
+ }
+ else if(getSelectedClassifiedItem())
+ {
+ onPanelClassifiedEdit();
+ }
+}
+
+bool LLPanelPicks::onEnableMenuItem(const LLSD& user_data)
+{
+ std::string param = user_data.asString();
+
+ LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem());
+ if(c_item && "info" == param)
+ {
+ // dont show Info panel if classified was not created
+ return isClassifiedPublished(c_item);
+ }
+
+ return true;
}
inline LLPanelProfile* LLPanelPicks::getProfilePanel()
@@ -610,3 +1161,98 @@ void LLPickItem::setValue(const LLSD& value)
if (!value.has("selected")) return;
childSetVisible("selected_icon", value["selected"]);
}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id)
+ : LLPanel()
+ , mAvatarId(avatar_id)
+ , mClassifiedId(classified_id)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this,"panel_classifieds_list_item.xml");
+
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId());
+}
+
+LLClassifiedItem::~LLClassifiedItem()
+{
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+void LLClassifiedItem::processProperties(void* data, EAvatarProcessorType type)
+{
+ if(APT_CLASSIFIED_INFO != type)
+ {
+ return;
+ }
+
+ LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+ if( !c_info || c_info->classified_id != getClassifiedId() )
+ {
+ return;
+ }
+
+ setClassifiedName(c_info->name);
+ setDescription(c_info->description);
+ setSnapshotId(c_info->snapshot_id);
+ setPosGlobal(c_info->pos_global);
+
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+BOOL LLClassifiedItem::postBuild()
+{
+ setMouseEnterCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", true));
+ setMouseLeaveCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", false));
+ return TRUE;
+}
+
+void LLClassifiedItem::setValue(const LLSD& value)
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
+
+void LLClassifiedItem::fillIn(LLPanelClassifiedEdit* panel)
+{
+ if(!panel)
+ {
+ return;
+ }
+
+ setClassifiedName(panel->getClassifiedName());
+ setDescription(panel->getDescription());
+ setSnapshotId(panel->getSnapshotId());
+ setCategory(panel->getCategory());
+ setContentType(panel->getContentType());
+ setAutoRenew(panel->getAutoRenew());
+ setPriceForListing(panel->getPriceForListing());
+ setPosGlobal(panel->getPosGlobal());
+ setLocationText(panel->getClassifiedLocation());
+}
+
+void LLClassifiedItem::setClassifiedName(const std::string& name)
+{
+ childSetValue("name", name);
+}
+
+void LLClassifiedItem::setDescription(const std::string& desc)
+{
+ childSetValue("description", desc);
+}
+
+void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id)
+{
+ childSetValue("picture", snapshot_id);
+}
+
+LLUUID LLClassifiedItem::getSnapshotId()
+{
+ return childGetValue("picture");
+}
+
+//EOF