summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp120
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h52
-rw-r--r--indra/newview/llpanelclassified.cpp526
-rw-r--r--indra/newview/llpanelclassified.h136
-rw-r--r--indra/newview/llpanelpick.cpp3
-rw-r--r--indra/newview/llpanelpicks.cpp486
-rw-r--r--indra/newview/llpanelpicks.h90
-rw-r--r--indra/newview/llpanelprofile.cpp1
-rw-r--r--indra/newview/llstartup.cpp5
-rw-r--r--indra/newview/skins/default/xui/en/menu_picks_plus.xml22
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_classified_info.xml183
-rw-r--r--indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml83
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_classified.xml255
-rw-r--r--indra/newview/skins/default/xui/en/panel_picks.xml43
15 files changed, 1984 insertions, 33 deletions
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index 73e24ca8e7..7cda2d31e6 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -158,6 +158,11 @@ void LLAvatarPropertiesProcessor::sendAvatarTexturesRequest(const LLUUID& avatar
removePendingRequest(avatar_id, APT_TEXTURES);
}
+void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_CLASSIFIEDS, "avatarclassifiedsrequest");
+}
+
void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
{
llinfos << "Sending avatarinfo update" << llendl;
@@ -284,12 +289,60 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m
*/
}
-void LLAvatarPropertiesProcessor::processAvatarClassifiedReply(LLMessageSystem* msg, void**)
+void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**)
{
- // avatarclassifiedsrequest is not sent according to new UI design but
- // keep this method according to resolved issues.
+ LLAvatarClassifieds classifieds;
+
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, classifieds.agent_id);
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, classifieds.target_id);
+
+ S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data);
+
+ for(int n = 0; n < block_count; ++n)
+ {
+ LLAvatarClassifieds::classified_data data;
+
+ msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n);
+ msg->getString(_PREHASH_Data, _PREHASH_Name, data.name, n);
+
+ classifieds.classifieds_list.push_back(data);
+ }
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(classifieds.target_id, APT_CLASSIFIEDS);
+ self->notifyObservers(classifieds.target_id,&classifieds,APT_CLASSIFIEDS);
}
+void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarClassifiedInfo c_info;
+
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, c_info.agent_id);
+
+ msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, c_info.classified_id);
+ msg->getUUID(_PREHASH_Data, _PREHASH_CreatorID, c_info.creator_id);
+ msg->getU32(_PREHASH_Data, _PREHASH_CreationDate, c_info.creation_date);
+ msg->getU32(_PREHASH_Data, _PREHASH_ExpirationDate, c_info.expiration_date);
+ msg->getU32(_PREHASH_Data, _PREHASH_Category, c_info.category);
+ msg->getString(_PREHASH_Data, _PREHASH_Name, c_info.name);
+ msg->getString(_PREHASH_Data, _PREHASH_Desc, c_info.description);
+ msg->getUUID(_PREHASH_Data, _PREHASH_ParcelID, c_info.parcel_id);
+ msg->getU32(_PREHASH_Data, _PREHASH_ParentEstate, c_info.parent_estate);
+ msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, c_info.snapshot_id);
+ msg->getString(_PREHASH_Data, _PREHASH_SimName, c_info.sim_name);
+ msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, c_info.pos_global);
+ msg->getString(_PREHASH_Data, _PREHASH_ParcelName, c_info.parcel_name);
+ msg->getU8(_PREHASH_Data, _PREHASH_ClassifiedFlags, c_info.flags);
+ msg->getS32(_PREHASH_Data, _PREHASH_PriceForListing, c_info.price_for_listing);
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(c_info.creator_id, APT_CLASSIFIED_INFO);
+ self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO);
+}
+
+
void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**)
{
LLAvatarNotes avatar_notes;
@@ -451,6 +504,22 @@ void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id )
LLAgentPicksInfo::getInstance()->decrementNumberOfPicks();
}
+void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_id)
+{
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_ClassifiedDelete);
+
+ msg->nextBlock(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_ClassifiedID, classified_id);
+
+ gAgent.sendReliableMessage();
+}
+
void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
{
if (!new_pick) return;
@@ -485,6 +554,36 @@ void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
}
+void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data)
+{
+ if(!c_data)
+ {
+ return;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_ClassifiedInfoUpdate);
+
+ msg->nextBlock(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_ClassifiedID, c_data->classified_id);
+ msg->addU32(_PREHASH_Category, c_data->category);
+ msg->addString(_PREHASH_Name, c_data->name);
+ msg->addString(_PREHASH_Desc, c_data->description);
+ msg->addUUID(_PREHASH_ParcelID, c_data->parcel_id);
+ msg->addU32(_PREHASH_ParentEstate, 0);
+ msg->addUUID(_PREHASH_SnapshotID, c_data->snapshot_id);
+ msg->addVector3d(_PREHASH_PosGlobal, c_data->pos_global);
+ msg->addU8(_PREHASH_ClassifiedFlags, c_data->flags);
+ msg->addS32(_PREHASH_PriceForListing, c_data->price_for_listing);
+
+ gAgent.sendReliableMessage();
+}
+
void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id)
{
// Must ask for a pick based on the creator id because
@@ -495,6 +594,21 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id,
send_generic_message("pickinforequest", request_params);
}
+void LLAvatarPropertiesProcessor::sendClassifiedInfoRequest(const LLUUID& classified_id)
+{
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_ClassifiedInfoRequest);
+ msg->nextBlock(_PREHASH_AgentData);
+
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_ClassifiedID, classified_id);
+
+ gAgent.sendReliableMessage();
+}
bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
{
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index e6563024b2..716c1b8065 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -53,7 +53,9 @@ enum EAvatarProcessorType
APT_GROUPS,
APT_PICKS,
APT_PICK_INFO,
- APT_TEXTURES
+ APT_TEXTURES,
+ APT_CLASSIFIEDS,
+ APT_CLASSIFIED_INFO
};
struct LLAvatarData
@@ -136,6 +138,43 @@ struct LLAvatarGroups
};
};
+struct LLAvatarClassifieds
+{
+ LLUUID agent_id;
+ LLUUID target_id;
+
+ struct classified_data;
+ typedef std::list<classified_data> classifieds_list_t;
+
+ classifieds_list_t classifieds_list;
+
+ struct classified_data
+ {
+ LLUUID classified_id;
+ std::string name;
+ };
+};
+
+struct LLAvatarClassifiedInfo
+{
+ LLUUID agent_id;
+ LLUUID classified_id;
+ LLUUID creator_id;
+ U32 creation_date;
+ U32 expiration_date;
+ U32 category;
+ std::string name;
+ std::string description;
+ LLUUID parcel_id;
+ U32 parent_estate;
+ LLUUID snapshot_id;
+ std::string sim_name;
+ LLVector3d pos_global;
+ std::string parcel_name;
+ U8 flags;
+ S32 price_for_listing;
+};
+
class LLAvatarPropertiesObserver
{
public:
@@ -162,20 +201,27 @@ public:
void sendAvatarNotesRequest(const LLUUID& avatar_id);
void sendAvatarGroupsRequest(const LLUUID& avatar_id);
void sendAvatarTexturesRequest(const LLUUID& avatar_id);
+ void sendAvatarClassifiedsRequest(const LLUUID& avatar_id);
// Duplicate pick info requests are not suppressed.
void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id);
+ void sendClassifiedInfoRequest(const LLUUID& classified_id);
+
void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props);
void sendPickInfoUpdate(const LLPickData* new_pick);
+ void sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data);
+
void sendFriendRights(const LLUUID& avatar_id, S32 rights);
void sendNotes(const LLUUID& avatar_id, const std::string notes);
void sendPickDelete(const LLUUID& pick_id);
+ void sendClassifiedDelete(const LLUUID& classified_id);
+
// Returns translated, human readable string for account type, such
// as "Resident" or "Linden Employee". Used for profiles, inspectors.
static std::string accountType(const LLAvatarData* avatar_data);
@@ -189,7 +235,9 @@ public:
static void processAvatarInterestsReply(LLMessageSystem* msg, void**);
- static void processAvatarClassifiedReply(LLMessageSystem* msg, void**);
+ static void processAvatarClassifiedsReply(LLMessageSystem* msg, void**);
+
+ static void processClassifiedInfoReply(LLMessageSystem* msg, void**);
static void processAvatarGroupsReply(LLMessageSystem* msg, void**);
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index a29c9752e6..5679233844 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -1142,3 +1142,529 @@ void LLPanelClassified::setDefaultAccessCombo()
break;
}
}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLPanelClassifiedInfo::LLPanelClassifiedInfo()
+ : LLPanel()
+ , mInfoLoaded(false)
+{
+}
+
+LLPanelClassifiedInfo::~LLPanelClassifiedInfo()
+{
+}
+
+// static
+LLPanelClassifiedInfo* LLPanelClassifiedInfo::create()
+{
+ LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_classified_info.xml");
+ return panel;
+}
+
+BOOL LLPanelClassifiedInfo::postBuild()
+{
+ childSetAction("back_btn", boost::bind(&LLPanelClassifiedInfo::onExit, this), NULL);
+
+ return TRUE;
+}
+
+void LLPanelClassifiedInfo::setExitCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("back_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedInfo::onOpen(const LLSD& key)
+{
+ LLUUID avatar_id = key["avatar_id"];
+ if(avatar_id.isNull())
+ {
+ return;
+ }
+
+ if(getAvatarId().notNull())
+ {
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+ }
+
+ setAvatarId(avatar_id);
+
+ resetData();
+ resetControls();
+
+ setClassifiedId(key["classified_id"]);
+ setClassifiedName(key["name"]);
+ setDescription(key["desc"]);
+ setSnapshotId(key["snapshot_id"]);
+
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId());
+ setInfoLoaded(false);
+}
+
+void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType type)
+{
+ if(APT_CLASSIFIED_INFO == type)
+ {
+ LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+ if(c_info && getClassifiedId() == c_info->classified_id)
+ {
+ setClassifiedName(c_info->name);
+ setDescription(c_info->description);
+ setSnapshotId(c_info->snapshot_id);
+ setParcelId(c_info->parcel_id);
+ setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
+ childSetValue("category", LLClassifiedInfo::sCategories[c_info->category]);
+
+ static std::string mature_str = getString("type_mature");
+ static std::string pg_str = getString("type_pg");
+
+ bool mature = is_cf_mature(c_info->flags);
+ childSetValue("content_type", mature ? mature_str : pg_str);
+ childSetValue("auto_renew", is_cf_auto_renew(c_info->flags));
+
+ childSetTextArg("price_for_listing", "[PRICE]", llformat("%d", c_info->price_for_listing));
+
+ setInfoLoaded(true);
+ }
+ }
+}
+
+void LLPanelClassifiedInfo::resetData()
+{
+ setClassifiedName(LLStringUtil::null);
+ setDescription(LLStringUtil::null);
+ setClassifiedLocation(LLStringUtil::null);
+ setClassifiedId(LLUUID::null);
+ setSnapshotId(LLUUID::null);
+ mPosGlobal.clearVec();
+ childSetValue("category", LLStringUtil::null);
+ childSetValue("content_type", LLStringUtil::null);
+}
+
+void LLPanelClassifiedInfo::resetControls()
+{
+ if(getAvatarId() == gAgent.getID())
+ {
+ childSetEnabled("edit_btn", TRUE);
+ childSetVisible("edit_btn", TRUE);
+ }
+ else
+ {
+ childSetEnabled("edit_btn", FALSE);
+ childSetVisible("edit_btn", FALSE);
+ }
+}
+
+void LLPanelClassifiedInfo::setClassifiedName(const std::string& name)
+{
+ childSetValue("classified_name", name);
+}
+
+std::string LLPanelClassifiedInfo::getClassifiedName()
+{
+ return childGetValue("classified_name").asString();
+}
+
+void LLPanelClassifiedInfo::setDescription(const std::string& desc)
+{
+ childSetValue("classified_desc", desc);
+}
+
+std::string LLPanelClassifiedInfo::getDescription()
+{
+ return childGetValue("classified_desc").asString();
+}
+
+void LLPanelClassifiedInfo::setClassifiedLocation(const std::string& location)
+{
+ childSetValue("classified_location", location);
+}
+
+void LLPanelClassifiedInfo::setSnapshotId(const LLUUID& id)
+{
+ childSetValue("classified_snapshot", id);
+}
+
+LLUUID LLPanelClassifiedInfo::getSnapshotId()
+{
+ return childGetValue("classified_snapshot").asUUID();
+}
+
+// static
+std::string LLPanelClassifiedInfo::createLocationText(
+ const std::string& original_name,
+ const std::string& sim_name,
+ const LLVector3d& pos_global)
+{
+ std::string location_text;
+
+ location_text.append(original_name);
+
+ if (!sim_name.empty())
+ {
+ if (!location_text.empty())
+ location_text.append(", ");
+ location_text.append(sim_name);
+ }
+
+ if (!location_text.empty())
+ location_text.append(" ");
+
+ if (!pos_global.isNull())
+ {
+ S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
+ S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
+ S32 region_z = llround((F32)pos_global.mdV[VZ]);
+ location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
+ }
+
+ return location_text;
+}
+
+void LLPanelClassifiedInfo::onExit()
+{
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+static const S32 CB_ITEM_MATURE = 0;
+static const S32 CB_ITEM_PG = 1;
+
+LLPanelClassifiedEdit::LLPanelClassifiedEdit()
+ : LLPanelClassifiedInfo()
+ , mIsNew(false)
+{
+}
+
+LLPanelClassifiedEdit::~LLPanelClassifiedEdit()
+{
+}
+
+//static
+LLPanelClassifiedEdit* LLPanelClassifiedEdit::create()
+{
+ LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_edit_classified.xml");
+ return panel;
+}
+
+BOOL LLPanelClassifiedEdit::postBuild()
+{
+ LLPanelClassifiedInfo::postBuild();
+
+ LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("classified_snapshot");
+ snapshot->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this));
+
+ LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon");
+ snapshot->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon));
+ snapshot->setMouseLeaveCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseLeave, this, edit_icon));
+ edit_icon->setVisible(false);
+
+ LLLineEditor* line_edit = getChild<LLLineEditor>("classified_name");
+ line_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL);
+
+ LLTextEditor* text_edit = getChild<LLTextEditor>("classified_desc");
+ text_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this));
+
+ LLComboBox* combobox = getChild<LLComboBox>( "category");
+ LLClassifiedInfo::cat_map::iterator iter;
+ for (iter = LLClassifiedInfo::sCategories.begin();
+ iter != LLClassifiedInfo::sCategories.end();
+ iter++)
+ {
+ combobox->add(LLTrans::getString(iter->second));
+ }
+
+ combobox->setCommitCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this));
+
+ childSetCommitCallback("content_type", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL);
+ childSetCommitCallback("price_for_listing", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL);
+ childSetCommitCallback("auto_renew", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL);
+
+ childSetAction("save_changes_btn", boost::bind(&LLPanelClassifiedEdit::onSaveClick, this));
+ childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelClassifiedEdit::onSetLocationClick, this));
+
+ return TRUE;
+}
+
+void LLPanelClassifiedEdit::onOpen(const LLSD& key)
+{
+ LLUUID classified_id = key["classified_id"];
+
+ mIsNew = classified_id.isNull();
+
+ if(mIsNew)
+ {
+ setAvatarId(gAgent.getID());
+
+ resetData();
+ resetControls();
+
+ setPosGlobal(gAgent.getPositionGlobal());
+
+ LLUUID snapshot_id = LLUUID::null;
+ std::string desc;
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ if(parcel)
+ {
+ desc = parcel->getDesc();
+ snapshot_id = parcel->getSnapshotID();
+ }
+
+ std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish");
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ region_name = region->getName();
+ }
+
+ childSetValue("classified_name", makeClassifiedName());
+ childSetValue("classified_desc", desc);
+ setSnapshotId(snapshot_id);
+
+ setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal()));
+
+ // server will set valid parcel id
+ setParcelId(LLUUID::null);
+
+ enableVerbs(true);
+ enableEditing(true);
+ }
+ else
+ {
+ LLPanelClassifiedInfo::onOpen(key);
+ enableVerbs(false);
+ enableEditing(false);
+ }
+
+ resetDirty();
+ setInfoLoaded(false);
+}
+
+void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType type)
+{
+ if(APT_CLASSIFIED_INFO == type)
+ {
+ LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+ if(c_info && getClassifiedId() == c_info->classified_id)
+ {
+ enableEditing(true);
+
+ setClassifiedName(c_info->name);
+ setDescription(c_info->description);
+ setSnapshotId(c_info->snapshot_id);
+ setPosGlobal(c_info->pos_global);
+
+ setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
+ getChild<LLComboBox>("category")->setCurrentByIndex(c_info->category + 1);
+ getChild<LLComboBox>("category")->resetDirty();
+
+ bool mature = is_cf_mature(c_info->flags);
+ bool auto_renew = is_cf_auto_renew(c_info->flags);
+
+ getChild<LLComboBox>("content_type")->setCurrentByIndex(mature ? CB_ITEM_MATURE : CB_ITEM_PG);
+ childSetValue("auto_renew", auto_renew);
+ childSetValue("price_for_listing", c_info->price_for_listing);
+
+ resetDirty();
+ setInfoLoaded(true);
+ }
+ }
+}
+
+BOOL LLPanelClassifiedEdit::isDirty() const
+{
+ if(mIsNew)
+ {
+ return TRUE;
+ }
+
+ BOOL dirty = false;
+
+ dirty |= LLPanelClassifiedInfo::isDirty();
+ dirty |= getChild<LLUICtrl>("classified_snapshot")->isDirty();
+ dirty |= getChild<LLUICtrl>("classified_name")->isDirty();
+ dirty |= getChild<LLUICtrl>("classified_desc")->isDirty();
+ dirty |= getChild<LLUICtrl>("category")->isDirty();
+ dirty |= getChild<LLUICtrl>("content_type")->isDirty();
+ dirty |= getChild<LLUICtrl>("auto_renew")->isDirty();
+ dirty |= getChild<LLUICtrl>("price_for_listing")->isDirty();
+
+ return dirty;
+}
+
+void LLPanelClassifiedEdit::resetDirty()
+{
+ LLPanelClassifiedInfo::resetDirty();
+ getChild<LLUICtrl>("classified_snapshot")->resetDirty();
+ getChild<LLUICtrl>("classified_name")->resetDirty();
+ getChild<LLUICtrl>("classified_desc")->resetDirty();
+ getChild<LLUICtrl>("category")->resetDirty();
+ getChild<LLUICtrl>("content_type")->resetDirty();
+ getChild<LLUICtrl>("auto_renew")->resetDirty();
+ getChild<LLUICtrl>("price_for_listing")->resetDirty();
+}
+
+void LLPanelClassifiedEdit::setSaveCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedEdit::setCancelCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedEdit::resetControls()
+{
+ LLPanelClassifiedInfo::resetControls();
+
+ getChild<LLComboBox>("category")->setCurrentByIndex(0);
+ getChild<LLComboBox>("content_type")->setCurrentByIndex(0);
+ childSetValue("auto_renew", false);
+ childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING);
+}
+
+void LLPanelClassifiedEdit::sendUpdate()
+{
+ LLAvatarClassifiedInfo c_data;
+
+ if(getClassifiedId().isNull())
+ {
+ LLUUID id;
+ id.generate();
+ setClassifiedId(id);
+ }
+
+ c_data.agent_id = gAgent.getID();
+ c_data.classified_id = getClassifiedId();
+ c_data.category = getCategory();
+ c_data.name = getClassifiedName();
+ c_data.description = getDescription();
+ c_data.parcel_id = getParcelId();
+ c_data.snapshot_id = getSnapshotId();
+ c_data.pos_global = getPosGlobal();
+ c_data.flags = getFlags();
+ c_data.price_for_listing = getPriceForListing();
+
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data);
+}
+
+U32 LLPanelClassifiedEdit::getCategory()
+{
+ LLComboBox* cat_cb = getChild<LLComboBox>("category");
+ return cat_cb->getCurrentIndex() + 1;
+}
+
+U8 LLPanelClassifiedEdit::getFlags()
+{
+ bool auto_renew = childGetValue("auto_renew").asBoolean();
+
+ LLComboBox* content_cb = getChild<LLComboBox>("content_type");
+ bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE;
+
+ return pack_classified_flags_request(auto_renew, false, mature, false);
+}
+
+void LLPanelClassifiedEdit::enableVerbs(bool enable)
+{
+ childSetEnabled("save_changes_btn", enable);
+}
+
+void LLPanelClassifiedEdit::enableEditing(bool enable)
+{
+ childSetEnabled("classified_snapshot", enable);
+ childSetEnabled("classified_name", enable);
+ childSetEnabled("classified_desc", enable);
+ childSetEnabled("set_to_curr_location_btn", enable);
+ childSetEnabled("category", enable);
+ childSetEnabled("content_type", enable);
+ childSetEnabled("price_for_listing", enable);
+ childSetEnabled("auto_renew", enable);
+}
+
+std::string LLPanelClassifiedEdit::makeClassifiedName()
+{
+ std::string name;
+
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if(parcel)
+ {
+ name = parcel->getName();
+ }
+
+ if(!name.empty())
+ {
+ return name;
+ }
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region)
+ {
+ name = region->getName();
+ }
+
+ return name;
+}
+
+S32 LLPanelClassifiedEdit::getPriceForListing()
+{
+ return childGetValue("price_for_listing").asInteger();
+}
+
+void LLPanelClassifiedEdit::onSetLocationClick()
+{
+ setPosGlobal(gAgent.getPositionGlobal());
+ setParcelId(LLUUID::null);
+
+ std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish");
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ region_name = region->getName();
+ }
+
+ setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal()));
+
+ // mark classified as dirty
+ setValue(LLSD());
+
+ onChange();
+}
+
+void LLPanelClassifiedEdit::onChange()
+{
+ enableVerbs(isDirty());
+}
+
+void LLPanelClassifiedEdit::onSaveClick()
+{
+ sendUpdate();
+ resetDirty();
+}
+
+std::string LLPanelClassifiedEdit::getLocationNotice()
+{
+ static std::string location_notice = getString("location_notice");
+ return location_notice;
+}
+
+void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
+{
+ ctrl->setVisible(TRUE);
+}
+
+void LLPanelClassifiedEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
+{
+ ctrl->setVisible(FALSE);
+}
+
+//EOF
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index 417eddf460..187bdbb37e 100644
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -37,6 +37,7 @@
#ifndef LL_LLPANELCLASSIFIED_H
#define LL_LLPANELCLASSIFIED_H
+#include "llavatarpropertiesprocessor.h"
#include "llpanel.h"
#include "llclassifiedinfo.h"
#include "v3dmath.h"
@@ -55,6 +56,8 @@ class LLTextureCtrl;
class LLUICtrl;
class LLMessageSystem;
+// *TODO deprecated, should be removed.
+// New class implemented in ticket EXT-2095
class LLPanelClassified : public LLPanel
{
public:
@@ -198,5 +201,138 @@ private:
void* mUserData;
};
+class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
+{
+public:
+
+ static LLPanelClassifiedInfo* create();
+
+ virtual ~LLPanelClassifiedInfo();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+
+ LLUUID& getAvatarId() { return mAvatarId; }
+
+ void setSnapshotId(const LLUUID& id);
+
+ LLUUID getSnapshotId();
+
+ void setClassifiedId(const LLUUID& id) { mClassifiedId = id; }
+
+ LLUUID& getClassifiedId() { return mClassifiedId; }
+
+ void setClassifiedName(const std::string& name);
+
+ std::string getClassifiedName();
+
+ void setDescription(const std::string& desc);
+
+ std::string getDescription();
+
+ void setClassifiedLocation(const std::string& location);
+
+ void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+
+ LLVector3d& getPosGlobal() { return mPosGlobal; }
+
+ void setParcelId(const LLUUID& id) { mParcelId = id; }
+
+ LLUUID getParcelId() { return mParcelId; }
+
+ bool getInfoLoaded() { return mInfoLoaded; }
+
+ void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; }
+
+ virtual void setExitCallback(const commit_callback_t& cb);
+
+protected:
+
+ LLPanelClassifiedInfo();
+
+ virtual void resetData();
+
+ virtual void resetControls();
+
+ static std::string createLocationText(
+ const std::string& original_name,
+ const std::string& sim_name,
+ const LLVector3d& pos_global);
+
+ void onClickMap();
+ void onClickTeleport();
+ void onClickBack();
+ void onExit();
+
+private:
+
+ LLUUID mAvatarId;
+ LLUUID mClassifiedId;
+ LLVector3d mPosGlobal;
+ LLUUID mParcelId;
+ bool mInfoLoaded;
+};
+
+class LLPanelClassifiedEdit : public LLPanelClassifiedInfo
+{
+public:
+
+ static LLPanelClassifiedEdit* create();
+
+ virtual ~LLPanelClassifiedEdit();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ /*virtual*/ BOOL isDirty() const;
+
+ /*virtual*/ void resetDirty();
+
+ void setSaveCallback(const commit_callback_t& cb);
+
+ void setCancelCallback(const commit_callback_t& cb);
+
+ /*virtual*/ void resetControls();
+
+ bool isNew() { return mIsNew; }
+
+protected:
+
+ LLPanelClassifiedEdit();
+
+ void sendUpdate();
+
+ U32 getCategory();
+
+ void enableVerbs(bool enable);
+
+ void enableEditing(bool enable);
+
+ std::string makeClassifiedName();
+
+ S32 getPriceForListing();
+
+ U8 getFlags();
+
+ std::string getLocationNotice();
+
+ void onSetLocationClick();
+ void onChange();
+ void onSaveClick();
+
+ void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+ void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+
+private:
+ bool mIsNew;
+};
#endif // LL_LLPANELCLASSIFIED_H
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index f5c4f89702..da0c8d5020 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -440,7 +440,8 @@ void LLPanelPickEdit::resetDirty()
BOOL LLPanelPickEdit::isDirty() const
{
- if( LLPanelPickInfo::isDirty()
+ if( mNewPick
+ || LLPanelPickInfo::isDirty()
|| mLocationChanged
|| mSnapshotCtrl->isDirty()
|| getChild<LLLineEditor>("pick_name")->isDirty()
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index 2bf04f9681..c30658755a 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -45,11 +45,14 @@
#include "llviewermenu.h"
#include "llregistry.h"
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
#include "llpanelpicks.h"
#include "llavatarpropertiesprocessor.h"
#include "llpanelavatar.h"
#include "llpanelprofile.h"
#include "llpanelpick.h"
+#include "llpanelclassified.h"
static const std::string XML_BTN_NEW = "new_btn";
static const std::string XML_BTN_DELETE = "trash_btn";
@@ -62,9 +65,40 @@ 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");
+//////////////////////////////////////////////////////////////////////////
+
+/**
+ * Copy&Pasted from old LLPanelClassified. This class does nothing at the moment.
+ * Subscribing to "classifiedclickthrough" removes a few warnings.
+ */
+class LLClassifiedClickThrough : public LLDispatchHandler
+{
+public:
+
+ // "classifiedclickthrough"
+ // strings[0] = classified_id
+ // strings[1] = teleport_clicks
+ // strings[2] = map_clicks
+ // strings[3] = profile_clicks
+ virtual bool operator()(
+ const LLDispatcher* dispatcher,
+ const std::string& key,
+ const LLUUID& invoice,
+ const sparam_t& strings)
+ {
+ if (strings.size() != 4)
+ return false;
+
+ return true;
+ }
+};
+
//-----------------------------------------------------------------------------
// LLPanelPicks
//-----------------------------------------------------------------------------
@@ -74,10 +108,19 @@ LLPanelPicks::LLPanelPicks()
mProfilePanel(NULL),
mPickPanel(NULL),
mPicksList(NULL),
+ mClassifiedsList(NULL),
mPanelPickInfo(NULL),
mPanelPickEdit(NULL),
- mOverflowMenu(NULL)
+ mOverflowMenu(NULL),
+ mPlusMenu(NULL),
+ mPicksAccTab(NULL),
+ mClassifiedsAccTab(NULL),
+ mPanelClassifiedInfo(NULL),
+ mPanelClassifiedEdit(NULL),
+ mClickThroughDisp(NULL)
{
+ mClickThroughDisp = new LLClassifiedClickThrough();
+ gGenericDispatcher.addHandler("classifiedclickthrough", mClickThroughDisp);
}
LLPanelPicks::~LLPanelPicks()
@@ -86,6 +129,8 @@ LLPanelPicks::~LLPanelPicks()
{
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
}
+
+ delete mClickThroughDisp;
}
void* LLPanelPicks::create(void* data /* = NULL */)
@@ -100,6 +145,9 @@ void LLPanelPicks::updateData()
{
mPicksList->clear();
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
+
+ mClassifiedsList->clear();
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId());
}
}
@@ -138,13 +186,47 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
mPicksList->addItem(picture, pick_value);
- picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1));
+ 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();
+ }
+ }
+ else if(APT_CLASSIFIEDS == type)
+ {
+ LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data);
+ if(c_info && getAvatarId() == c_info->target_id)
+ {
+ mClassifiedsList->clear();
+
+ 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();
}
}
@@ -158,16 +240,44 @@ 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));
+
+ mPicksList->setNoItemsCommentText(getString("no_picks"));
+ mClassifiedsList->setNoItemsCommentText(getString("no_classifieds"));
- childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickNew, this));
+ 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));
@@ -180,6 +290,10 @@ BOOL LLPanelPicks::postBuild()
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));
+ mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
return TRUE;
}
@@ -202,6 +316,34 @@ void LLPanelPicks::onOverflowMenuItemClicked(const LLSD& param)
}
}
+void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param)
+{
+ std::string value = param.asString();
+
+ if("new_pick" == value)
+ {
+ createNewPick();
+ }
+ else if("new_classified" == value)
+ {
+ createNewClassified();
+ }
+}
+
+void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab)
+{
+ if(!mPicksAccTab->getDisplayChildren())
+ {
+ mPicksList->resetSelection(true);
+ }
+ if(!mClassifiedsAccTab->getDisplayChildren())
+ {
+ mClassifiedsList->resetSelection(true);
+ }
+
+ updateButtons();
+}
+
void LLPanelPicks::onOverflowButtonClicked()
{
LLRect rect;
@@ -242,6 +384,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 +395,50 @@ void LLPanelPicks::onOpen(const LLSD& key)
LLPanelProfileTab::onOpen(key);
}
+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];
+ LLNotifications::instance().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];
+ LLNotifications::instance().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);
-
LLSD pick_value = mPicksList->getSelectedValue();
if (0 == option)
@@ -276,6 +450,20 @@ bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response
return false;
}
+bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::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);
@@ -291,9 +479,14 @@ 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();
- LLVector3d pos = pick_item->getPosGlobal();
if (!pos.isExactlyZero())
{
gAgent.teleportViaLocation(pos);
@@ -305,9 +498,15 @@ void LLPanelPicks::onClickTeleport()
void LLPanelPicks::onClickMap()
{
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();
- LLFloaterWorldMap::getInstance()->trackLocation(pick_item->getPosGlobal());
+ LLFloaterWorldMap::getInstance()->trackLocation(pos);
LLFloaterReg::showInstance("world_map", "center");
}
@@ -325,7 +524,7 @@ 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;
@@ -335,9 +534,19 @@ void LLPanelPicks::onDoubleClickItem(LLUICtrl* item)
LLNotifications::instance().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];
+ LLNotifications::instance().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)
{
@@ -366,15 +575,44 @@ 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()
+{
+ createClassifiedEditPanel();
+
+ getProfilePanel()->openPanel(mPanelClassifiedEdit, 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 +630,33 @@ void LLPanelPicks::onClickInfo()
getProfilePanel()->openPanel(mPanelPickInfo, params);
}
+void LLPanelPicks::openClassifiedInfo()
+{
+ LLSD selected_value = mClassifiedsList->getSelectedValue();
+ if (selected_value.isUndefined()) return;
+
+ LLClassifiedItem* c_item = getSelectedClassifiedItem();
+
+ createClassifiedInfoPanel();
+
+ LLSD params;
+ params["classified_id"] = c_item->getClassifiedId();
+ params["avatar_id"] = c_item->getAvatarId();
+ params["snapshot_id"] = c_item->getSnapshotId();
+ params["name"] = c_item->getClassifiedName();
+ params["desc"] = c_item->getDescription();
+
+ 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 +668,61 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel)
updateButtons();
}
+void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel)
+{
+ if(panel->isNew())
+ {
+ LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId());
+
+ c_item->setClassifiedName(panel->getClassifiedName());
+ c_item->setDescription(panel->getDescription());
+ c_item->setSnapshotId(panel->getSnapshotId());
+
+ 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));
+ }
+ 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]));
+
+ 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 +734,28 @@ void LLPanelPicks::createPickInfoPanel()
}
}
+void LLPanelPicks::createClassifiedInfoPanel()
+{
+ if(!mPanelClassifiedInfo)
+ {
+ mPanelClassifiedInfo = LLPanelClassifiedInfo::create();
+ mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo));
+ mPanelClassifiedInfo->setVisible(FALSE);
+ }
+}
+
+void LLPanelPicks::createClassifiedEditPanel()
+{
+ if(!mPanelClassifiedEdit)
+ {
+ mPanelClassifiedEdit = LLPanelClassifiedEdit::create();
+ mPanelClassifiedEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedEdit));
+ mPanelClassifiedEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, mPanelClassifiedEdit));
+ mPanelClassifiedEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedEdit));
+ mPanelClassifiedEdit->setVisible(FALSE);
+ }
+}
+
void LLPanelPicks::createPickEditPanel()
{
if(!mPanelPickEdit)
@@ -473,9 +815,38 @@ 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());
+
+ createClassifiedEditPanel();
+
+ LLSD params;
+ params["classified_id"] = c_item->getClassifiedId();
+ params["avatar_id"] = c_item->getAvatarId();
+ params["snapshot_id"] = c_item->getSnapshotId();
+ params["name"] = c_item->getClassifiedName();
+ params["desc"] = c_item->getDescription();
+
+ getProfilePanel()->openPanel(mPanelClassifiedEdit, params);
+}
+
void LLPanelPicks::onClickMenuEdit()
{
- onPanelPickEdit();
+ if(getSelectedPickItem())
+ {
+ onPanelPickEdit();
+ }
+ else if(getSelectedClassifiedItem())
+ {
+ onPanelClassifiedEdit();
+ }
}
inline LLPanelProfile* LLPanelPicks::getProfilePanel()
@@ -610,3 +981,80 @@ 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::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
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 5a2754ad10..4b90ea5048 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -40,6 +40,7 @@
#include "llpanelavatar.h"
#include "llregistry.h"
+class LLAccordionCtrlTab;
class LLPanelProfile;
class LLMessageSystem;
class LLVector3d;
@@ -47,10 +48,18 @@ class LLPanelProfileTab;
class LLAgent;
class LLMenuGL;
class LLPickItem;
+class LLClassifiedItem;
class LLFlatListView;
class LLPanelPickInfo;
class LLPanelPickEdit;
class LLToggleableMenu;
+class LLPanelClassifiedInfo;
+class LLPanelClassifiedEdit;
+class LLClassifiedClickThrough;
+
+// *TODO
+// Panel Picks has been consolidated with Classifieds (EXT-2095), give LLPanelPicks
+// and corresponding files (cpp, h, xml) a new name. (new name is TBD at the moment)
class LLPanelPicks
: public LLPanelProfileTab
@@ -71,6 +80,7 @@ public:
// returns the selected pick item
LLPickItem* getSelectedPickItem();
+ LLClassifiedItem* getSelectedClassifiedItem();
//*NOTE top down approch when panel toggling is done only by
// parent panels failed to work (picks related code was in me profile panel)
@@ -83,41 +93,67 @@ private:
void onOverflowMenuItemClicked(const LLSD& param);
void onOverflowButtonClicked();
+ void onPlusMenuItemClicked(const LLSD& param);
+
+ void onListCommit(const LLFlatListView* f_list);
+ void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab);
//------------------------------------------------
// Callbacks which require panel toggling
//------------------------------------------------
- void onClickNew();
+ void onClickPlusBtn();
void onClickInfo();
void onPanelPickClose(LLPanel* panel);
void onPanelPickSave(LLPanel* panel);
+ void onPanelClassifiedSave(LLPanelClassifiedEdit* panel);
+ void onPanelClassifiedClose(LLPanelClassifiedInfo* panel);
void onPanelPickEdit();
+ void onPanelClassifiedEdit();
void onClickMenuEdit();
+ void createNewPick();
+ void createNewClassified();
+
+ void openPickInfo();
+ void openClassifiedInfo();
+
+ void showAccordion(const std::string& name, bool show);
+
void buildPickPanel();
- bool callbackDelete(const LLSD& notification, const LLSD& response);
+ bool callbackDeletePick(const LLSD& notification, const LLSD& response);
+ bool callbackDeleteClassified(const LLSD& notification, const LLSD& response);
bool callbackTeleport(const LLSD& notification, const LLSD& response);
void updateButtons();
- virtual void onDoubleClickItem(LLUICtrl* item);
+ virtual void onDoubleClickPickItem(LLUICtrl* item);
+ virtual void onDoubleClickClassifiedItem(LLUICtrl* item);
virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask);
LLPanelProfile* getProfilePanel();
void createPickInfoPanel();
void createPickEditPanel();
-// void openPickEditPanel(LLPickItem* pick);
-// void openPickInfoPanel(LLPickItem* pick);
+ void createClassifiedInfoPanel();
+ void createClassifiedEditPanel();
LLMenuGL* mPopupMenu;
LLPanelProfile* mProfilePanel;
LLPanelPickInfo* mPickPanel;
LLFlatListView* mPicksList;
+ LLFlatListView* mClassifiedsList;
LLPanelPickInfo* mPanelPickInfo;
+ LLPanelClassifiedInfo* mPanelClassifiedInfo;
+ LLPanelClassifiedEdit* mPanelClassifiedEdit;
LLPanelPickEdit* mPanelPickEdit;
LLToggleableMenu* mOverflowMenu;
+ LLToggleableMenu* mPlusMenu;
+
+ LLAccordionCtrlTab* mPicksAccTab;
+ LLAccordionCtrlTab* mClassifiedsAccTab;
+
+ LLClassifiedClickThrough* mClickThroughDisp;
};
class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver
@@ -189,4 +225,48 @@ protected:
std::string mSimName;
};
+class LLClassifiedItem : public LLPanel, public LLAvatarPropertiesObserver
+{
+public:
+
+ LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id);
+
+ virtual ~LLClassifiedItem();
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void setValue(const LLSD& value);
+
+ LLUUID getAvatarId() {return mAvatarId;}
+
+ void setAvatarId(const LLUUID& avatar_id) {mAvatarId = avatar_id;}
+
+ LLUUID getClassifiedId() {return mClassifiedId;}
+
+ void setClassifiedId(const LLUUID& classified_id) {mClassifiedId = classified_id;}
+
+ void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+
+ const LLVector3d& getPosGlobal() { return mPosGlobal; }
+
+ void setClassifiedName (const std::string& name);
+
+ std::string getClassifiedName() { return childGetValue("name").asString(); }
+
+ void setDescription(const std::string& desc);
+
+ std::string getDescription() { return childGetValue("description").asString(); }
+
+ void setSnapshotId(const LLUUID& snapshot_id);
+
+ LLUUID getSnapshotId();
+
+private:
+ LLUUID mAvatarId;
+ LLUUID mClassifiedId;
+ LLVector3d mPosGlobal;
+};
+
#endif // LL_LLPANELPICKS_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 8147ff17f0..02f45c1b48 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -243,5 +243,6 @@ void LLPanelProfile::notifyParent(const LLSD& info)
onOpen(info);
return;
}
+
LLPanel::notifyParent(info);
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 2c1f468f77..0a6eefc41d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2478,7 +2478,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("AvatarPicksReply",
&LLAvatarPropertiesProcessor::processAvatarPicksReply);
msg->setHandlerFunc("AvatarClassifiedReply",
- &LLAvatarPropertiesProcessor::processAvatarClassifiedReply);
+ &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply);
msg->setHandlerFuncFast(_PREHASH_CreateGroupReply,
LLGroupMgr::processCreateGroupReply);
@@ -2543,7 +2543,8 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply);
msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply);
- msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);
+// msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);
+ msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply);
msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply);
msg->setHandlerFunc("ScriptDialog", process_script_dialog);
msg->setHandlerFunc("LoadURL", process_load_url);
diff --git a/indra/newview/skins/default/xui/en/menu_picks_plus.xml b/indra/newview/skins/default/xui/en/menu_picks_plus.xml
new file mode 100644
index 0000000000..3065239615
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_picks_plus.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ height="201"
+ layout="topleft"
+ mouse_opaque="false"
+ name="picks_plus_menu"
+ width="120">
+ <menu_item_call
+ name="create_pick"
+ label="New Pick">
+ <menu_item_call.on_click
+ function="Picks.Plus.Action"
+ userdata="new_pick" />
+ </menu_item_call>
+ <menu_item_call
+ name="create_classified"
+ label="New Classified">
+ <menu_item_call.on_click
+ function="Picks.Plus.Action"
+ userdata="new_classified" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 989dc88851..ccd8bc569e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3051,6 +3051,18 @@ Teleport to [PICK]?
</notification>
<notification
+ icon="alertmodal.tga"
+ name="TeleportToClassified"
+ type="alertmodal">
+ Teleport to [CLASSIFIED]?
+ <usetemplate
+ ignoretext="Confirm that I want to teleport to a location in Classifieds"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Teleport"/>
+ </notification>
+
+ <notification
icon="alert.tga"
label="Message everyone in your Estate"
name="MessageEstate"
diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml
new file mode 100644
index 0000000000..bdca8531dc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="570"
+ layout="topleft"
+ left="0"
+ min_height="350"
+ name="panel_classified_info"
+ top="0"
+ width="333">
+ <panel.string
+ name="type_mature">
+ Mature
+ </panel.string>
+ <panel.string
+ name="type_pg">
+ PG Content
+ </panel.string>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="0"
+ value="Classified Info"
+ use_ellipses="true"
+ width="275" />
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ top_pad="10"
+ name="profile_scroll"
+ reserve_scroll_corner="false"
+ width="313">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top"
+ min_height="300"
+ layout="topleft"
+ top="0"
+ background_visible="false"
+ height="500"
+ left="0"
+ width="295">
+ <texture_picker
+ enabled="false"
+ follows="left|top"
+ height="197"
+ layout="topleft"
+ left="10"
+ name="classified_snapshot"
+ top="20"
+ width="290" />
+ <text
+ follows="left|top|right"
+ height="35"
+ width="290"
+ layout="topleft"
+ font="SansSerifBig"
+ font.style="BOLD"
+ left="10"
+ top_pad="10"
+ name="classified_name"
+ text_color="white"
+ value="[name]"
+ use_ellipses="true" />
+ <text
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left="10"
+ name="classified_location"
+ width="290"
+ word_wrap="true"
+ value="[loading...]" />
+ <text
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="10"
+ name="content_type"
+ width="290"
+ top_pad="5"
+ value="[content type]" />
+ <text
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="10"
+ name="category"
+ width="290"
+ top_pad="5"
+ value="[category]" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Auto renew each week"
+ layout="topleft"
+ left="10"
+ name="auto_renew"
+ top_pad="5"
+ width="290" />
+ <text
+ follows="left|top"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="price_for_listing"
+ top_pad="5"
+ tool_tip="Price for listing."
+ width="105">
+ L$[PRICE]
+ </text>
+ <text
+ follows="left|top|right"
+ height="200"
+ layout="topleft"
+ left="10"
+ name="classified_desc"
+ width="290"
+ value="[description]"
+ word_wrap="true" />
+ </panel>
+ </scroll_container>
+ <panel
+ follows="left|right|bottom"
+ height="20"
+ layout="topleft"
+ top_pad="8"
+ left="10"
+ name="buttons">
+ <button
+ follows="bottom|left"
+ font="SansSerifSmall"
+ height="19"
+ label="Teleport"
+ layout="topleft"
+ left="0"
+ name="teleport_btn"
+ top="0"
+ width="90" />
+ <button
+ follows="bottom|left"
+ font="SansSerifSmall"
+ height="19"
+ label="Map"
+ layout="topleft"
+ left_pad="10"
+ name="show_on_map_btn"
+ top="0"
+ width="90" />
+ <button
+ follows="bottom|left"
+ font="SansSerifSmall"
+ height="19"
+ label="Edit"
+ layout="topleft"
+ right="-1"
+ name="edit_btn"
+ top="0"
+ width="90" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
new file mode 100644
index 0000000000..ee333be0cb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ bevel_style="none"
+ follows="top|left|right"
+ height="85"
+ layout="topleft"
+ left="0"
+ name="classified_item"
+ top="0"
+ width="313">
+ <icon
+ follows="all"
+ height="85"
+ image_name="ListItem_Over"
+ right="-3"
+ mouse_opaque="false"
+ name="hovered_icon"
+ top="1"
+ scale_image="true"
+ visible="false"
+ width="307"/>
+ <icon
+ follows="all"
+ height="85"
+ image_name="ListItem_Select"
+ right="-3"
+ mouse_opaque="false"
+ name="selected_icon"
+ top="1"
+ scale_image="true"
+ visible="false"
+ width="307"/>
+ <texture_picker
+ allow_no_texture="true"
+ border_enabled="true"
+ default_image_name="TabIcon_Places_Large"
+ enabled="false"
+ follows="left|top"
+ height="80"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="picture"
+ tab_stop="false"
+ top="10"
+ top_pad="10"
+ width="90" />
+ <text
+ follows="top|left|right"
+ font="SansSerifSmallBold"
+ height="16"
+ layout="topleft"
+ left="110"
+ name="name"
+ text_color="white"
+ top="9"
+ use_ellipses="false"
+ width="197"
+ word_wrap="false" />
+ <expandable_text
+ follows="top|left|right"
+ font="SansSerifSmall"
+ height="40"
+ layout="topleft"
+ left="110"
+ name="description"
+ top_pad="3"
+ width="178"
+ word_wrap="true" />
+ <button
+ follows="top|right"
+ height="16"
+ image_selected="BuyArrow_Press"
+ image_pressed="BuyArrow_Press"
+ image_unselected="BuyArrow_Press"
+ layout="topleft"
+ name="info_chevron"
+ picture_style="true"
+ right="-7"
+ tab_stop="false"
+ top="27"
+ width="16" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
new file mode 100644
index 0000000000..2f3277804f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ follows="left|top|right|bottom"
+ height="570"
+ label="Edit Classified"
+ layout="topleft"
+ left="0"
+ min_height="350"
+ name="panel_edit_classified"
+ top="0"
+ width="333">
+ <panel.string
+ name="location_notice">
+ (will update after save)
+ </panel.string>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ type="string"
+ length="1"
+ follows="top"
+ font="SansSerifHuge"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="5"
+ width="250">
+ Edit Classified
+ </text>
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="10"
+ top_pad="10"
+ name="profile_scroll"
+ reserve_scroll_corner="false"
+ opaque="true"
+ width="313">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top"
+ min_height="300"
+ layout="topleft"
+ top="0"
+ background_visible="false"
+ height="600"
+ left="0"
+ width="295">
+ <texture_picker
+ follows="left|top|right"
+ height="197"
+ width="290"
+ layout="topleft"
+ top="20"
+ left="10"
+ name="classified_snapshot" />
+ <icon
+ height="18"
+ image_name="AddItem_Off"
+ layout="topleft"
+ right="-5"
+ name="edit_icon"
+ label=""
+ tool_tip="Click to select an image"
+ top="27"
+ width="18" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ font="SansSerifSmall"
+ font.style="BOLD"
+ layout="topleft"
+ left="10"
+ top="215"
+ name="Name:"
+ text_color="white"
+ width="290">
+ Title:
+ </text>
+ <line_editor
+ follows="left|top|right"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ top_pad="2"
+ max_length="63"
+ name="classified_name"
+ text_color="black"
+ width="290" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ font="SansSerifSmall"
+ font.style="BOLD"
+ layout="topleft"
+ left="10"
+ top_pad="20"
+ name="description_label"
+ text_color="white"
+ width="290">
+ Description:
+ </text>
+ <text_editor
+ follows="left|top|right"
+ height="100"
+ width="290"
+ hide_scrollbar="false"
+ layout="topleft"
+ left="10"
+ top_pad="2"
+ max_length="1023"
+ name="classified_desc"
+ text_color="black"
+ word_wrap="true" />
+ <text
+ type="string"
+ length="1"
+ font="SansSerifSmall"
+ font.style="BOLD"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="location_label"
+ text_color="white"
+ top_pad="20"
+ width="290">
+ Location:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="10"
+ name="classified_location"
+ right="-10"
+ top_pad="2"
+ width="290"
+ word_wrap="true">
+ loading...
+ </text>
+ <button
+ follows="left|top"
+ height="20"
+ label="Set to Current Location"
+ layout="topleft"
+ left="8"
+ top_pad="5"
+ name="set_to_curr_location_btn"
+ width="200" />
+ <combo_box
+ follows="left|top"
+ height="18"
+ label=""
+ left="10"
+ name="category"
+ top_pad="5"
+ width="200" />
+ <combo_box
+ allow_text_entry="false"
+ follows="left|top"
+ height="18"
+ left="10"
+ name="content_type"
+ top_pad="5"
+ width="200">
+ <combo_item
+ name="mature_ci"
+ value="Mature">
+ Mature Content
+ </combo_item>
+ <combo_item
+ name="pg_ci"
+ value="PG">
+ PG Content
+ </combo_item>
+ </combo_box>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ halign="left"
+ height="16"
+ increment="1"
+ label_width="20"
+ label="L$"
+ layout="topleft"
+ left="10"
+ value="50"
+ min_val="50"
+ max_val="99999"
+ name="price_for_listing"
+ top_pad="5"
+ tool_tip="Price for listing."
+ width="105" />
+ <check_box
+ height="16"
+ label="Auto renew each week"
+ layout="topleft"
+ left="10"
+ name="auto_renew"
+ top_pad="5"
+ width="250" />
+ </panel>
+ </scroll_container>
+ <panel
+ follows="left|right|bottom"
+ height="20"
+ label="bottom_panel"
+ layout="topleft"
+ left="10"
+ name="bottom_panel"
+ top_pad="5"
+ width="303">
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Save"
+ layout="topleft"
+ name="save_changes_btn"
+ left="0"
+ top="0"
+ width="130" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left_pad="5"
+ right="-1"
+ width="130" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
index ae61852f68..dbe76e553b 100644
--- a/indra/newview/skins/default/xui/en/panel_picks.xml
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -8,16 +8,57 @@
name="panel_picks"
top="0"
width="313">
+ <string
+ name="no_picks"
+ value="No Picks" />
+ <string
+ name="no_classifieds"
+ value="No Classifieds" />
+
+ <accordion
+ follows="all"
+ height="465"
+ layout="topleft"
+ left="0"
+ name="accordion"
+ top="0"
+ width="313">
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ height="235"
+ min_height="150"
+ name="tab_picks"
+ title="Picks"
+ visible="false">
<flat_list_view
color="DkGray2"
follows="all"
- height="465"
layout="topleft"
left="0"
name="picks_list"
opaque="true"
top="0"
width="313" />
+ </accordion_tab>
+ <accordion_tab
+ can_resize="false"
+ layout="topleft"
+ height="235"
+ name="tab_classifieds"
+ title="Classified"
+ visible="false">
+ <flat_list_view
+ color="DkGray2"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="classifieds_list"
+ opaque="true"
+ top="0"
+ width="313" />
+ </accordion_tab>
+ </accordion>
<panel
background_visible="true"
bevel_style="none"