EXT-7639 FIXED added shop button which reacts according to the ticket description

- Added method LLAccordionCtrl::getExpandedTab() which search for the first expanded accordion tab. This method is a bit of hacking, but I discussed it with Vadim Savchuk.
- LLAccordionCtrlTab::isExpanded() is made 'const'. This is necessary to call it from getExpandedTab() which is also 'const'.
- Added all provided Marketplace URLs (taken from EXT-7257) to the settings.xml. So URLs can be configured without recompilation.
- Added method LLCOFWearables::getSelectedItems() which can be used to get ALL selected items (not only one).
- Class LLShopURLDispatcher is implemented in the llpaneloutfitedit.cpp.
- Added callback LLPanelOutfitEdit::onShopButtonClicked() which calls LLShopURLDispatcher to send user to the correct URL.
- Added shop button (shop_btn) widget in panel_outfit_edit.xml. It has invalid icon for now. After review I'm going to reassign the ticket to someone who will provide correct icons.

Reviewed by Vadim Savchuk and Mike Antipov at https://codereview.productengine.com/secondlife/r/569/

--HG--
branch : product-engine
master
Andrew Polunin 2010-06-15 21:52:15 +03:00
parent 33c3064639
commit e460985ddf
9 changed files with 553 additions and 3 deletions

View File

@ -826,6 +826,24 @@ void LLAccordionCtrl::setFilterSubString(const std::string& filter_string)
mNoVisibleTabsHelpText->setValue(text);
}
const LLAccordionCtrlTab* LLAccordionCtrl::getExpandedTab() const
{
typedef std::vector<LLAccordionCtrlTab*>::const_iterator tabs_const_iterator;
const LLAccordionCtrlTab* result = 0;
for (tabs_const_iterator i = mAccordionTabs.begin(); i != mAccordionTabs.end(); ++i)
{
if ((*i)->isExpanded())
{
result = *i;
break;
}
}
return result;
}
S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
{
if(tab_index < 0)

View File

@ -129,6 +129,13 @@ public:
*/
void setFilterSubString(const std::string& filter_string);
/**
* This method returns the first expanded accordion tab.
* It is expected to be called for accordion which doesn't allow multiple
* tabs to be expanded. Use with care.
*/
const LLAccordionCtrlTab* getExpandedTab() const;
private:
void initNoTabsWidget(const LLTextBox::Params& tb_params);
void updateNoTabsHelpTextVisibility();

View File

@ -171,7 +171,7 @@ public:
virtual bool addChild(LLView* child, S32 tab_group);
bool isExpanded() { return mDisplayChildren; }
bool isExpanded() const { return mDisplayChildren; }
S32 getHeaderHeight();

View File

@ -4667,7 +4667,381 @@
<string>String</string>
<key>Value</key>
<string>https://www.xstreetsl.com/modules.php?name=Marketplace</string>
</map>
</map>
<key>MarketplaceURL_objectFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Attachments Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/attachments</string>
</map>
<key>MarketplaceURL_objectMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Attachments Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/attachments</string>
</map>
<key>MarketplaceURL_clothingFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Clothing Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/clothing_female_avatar</string>
</map>
<key>MarketplaceURL_clothingMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Clothing Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/clothing_male_avatar</string>
</map>
<key>MarketplaceURL_bodypartFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Bodyparts Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>https://www.xstreetsl.com/modules.php?name=Marketplace</string>
</map>
<key>MarketplaceURL_bodypartMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Bodyparts Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>https://www.xstreetsl.com/modules.php?name=Marketplace</string>
</map>
<key>MarketplaceURL_glovesMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Gloves Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/gloves_both_women_and_men</string>
</map>
<key>MarketplaceURL_glovesFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Gloves Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/gloves_both_women_and_men</string>
</map>
<key>MarketplaceURL_jacketFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Jacket Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/jacket_womens</string>
</map>
<key>MarketplaceURL_jacketMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Jacket Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/jacket_mens</string>
</map>
<key>MarketplaceURL_shirtFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Shirt Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/shirt_womens</string>
</map>
<key>MarketplaceURL_shirtMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Shirt Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/shirt_mens</string>
</map>
<key>MarketplaceURL_undershirtFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Undershirt Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/undershirt_womens</string>
</map>
<key>MarketplaceURL_undershirtMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Undershirt Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/undershirt_mens</string>
</map>
<key>MarketplaceURL_skirtFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Skirt Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/skirts_women</string>
</map>
<key>MarketplaceURL_skirtMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Skirt Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/skirts_women</string>
</map>
<key>MarketplaceURL_pantsFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Pants Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/pants_women</string>
</map>
<key>MarketplaceURL_pantsMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Pants Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/pants_men</string>
</map>
<key>MarketplaceURL_underpantsFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Underwear Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/underwear_women</string>
</map>
<key>MarketplaceURL_underpantsMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Underwear Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/underwear_men</string>
</map>
<key>MarketplaceURL_shoesFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Shoes Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/shoes_women</string>
</map>
<key>MarketplaceURL_shoesMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Shoes Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/shoes_men</string>
</map>
<key>MarketplaceURL_socksFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Socks Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/socks_women</string>
</map>
<key>MarketplaceURL_socksMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Socks Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/socks_women</string>
</map>
<key>MarketplaceURL_tattooMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Tattoo Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/tattoo_both_women_and_men</string>
</map>
<key>MarketplaceURL_tattooFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Tattoo Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/tattoo_both_women_and_men</string>
</map>
<key>MarketplaceURL_hairFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Hair Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/womens_hair</string>
</map>
<key>MarketplaceURL_hairMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Hair Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/mens_hair</string>
</map>
<key>MarketplaceURL_eyesFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Eyes Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/womens_eyes</string>
</map>
<key>MarketplaceURL_eyesMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Eyes Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/mens_eyes</string>
</map>
<key>MarketplaceURL_shapeFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Shape Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/womens_shape</string>
</map>
<key>MarketplaceURL_shapeMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Shape Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/mens_shape</string>
</map>
<key>MarketplaceURL_skinFemale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Skin Female</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/womens_skin</string>
</map>
<key>MarketplaceURL_skinMale</key>
<map>
<key>Comment</key>
<string>URL to the Marketplace Skins Male</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://marketplace.secondlife.com/trampoline/viewer21/mens_skin</string>
</map>
<key>MaxDragDistance</key>
<map>
<key>Comment</key>

View File

@ -34,6 +34,8 @@
#include "llcofwearables.h"
#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagentdata.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
@ -557,6 +559,14 @@ LLPanel* LLCOFWearables::getSelectedItem()
return mLastSelectedList->getSelectedItem();
}
void LLCOFWearables::getSelectedItems(std::vector<LLPanel*>& selected_items) const
{
if (mLastSelectedList)
{
mLastSelectedList->getSelectedItems(selected_items);
}
}
void LLCOFWearables::clear()
{
mAttachments->clear();
@ -564,6 +574,29 @@ void LLCOFWearables::clear()
mBodyParts->clear();
}
LLAssetType::EType LLCOFWearables::getExpandedAccordionAssetType()
{
static std::map<std::string, LLAssetType::EType> type_map;
static LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("cof_wearables_accordion");
if (type_map.empty())
{
type_map["tab_clothing"] = LLAssetType::AT_CLOTHING;
type_map["tab_attachments"] = LLAssetType::AT_OBJECT;
type_map["tab_body_parts"] = LLAssetType::AT_BODYPART;
}
const LLAccordionCtrlTab* tab = accordion_ctrl->getExpandedTab();
if (!tab)
{
llwarns << "No accordion is expanded" << llendl;
return LLAssetType::AT_NONE;
}
return type_map[tab->getName()];
}
void LLCOFWearables::onListRightClick(LLUICtrl* ctrl, S32 x, S32 y, LLListContextMenu* menu)
{
if(menu)

View File

@ -78,10 +78,13 @@ public:
bool getSelectedUUIDs(uuid_vec_t& selected_ids);
LLPanel* getSelectedItem();
void getSelectedItems(std::vector<LLPanel*>& selected_items) const;
void refresh();
void clear();
LLAssetType::EType getExpandedAccordionAssetType();
LLCOFCallbacks& getCOFCallbacks() { return mCOFCallbacks; }
protected:

View File

@ -72,6 +72,8 @@
#include "lltoggleablemenu.h"
#include "llwearablelist.h"
#include "llwearableitemslist.h"
#include "llwearabletype.h"
#include "llweb.h"
static LLRegisterPanelClassWrapper<LLPanelOutfitEdit> t_outfit_edit("panel_outfit_edit");
@ -81,6 +83,65 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
static const std::string REVERT_BTN("revert_btn");
class LLShopURLDispatcher
{
public:
std::string resolveURL(LLWearableType::EType wearable_type, ESex sex);
std::string resolveURL(LLAssetType::EType asset_type, ESex sex);
};
std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type, ESex sex)
{
const std::string prefix = "MarketplaceURL";
const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female";
const std::string type_str = LLWearableType::getTypeName(wearable_type);
std::string setting_name = prefix;
switch (wearable_type)
{
case LLWearableType::WT_ALPHA:
case LLWearableType::WT_NONE:
case LLWearableType::WT_INVALID: // just in case, this shouldn't happen
case LLWearableType::WT_COUNT: // just in case, this shouldn't happen
break;
default:
setting_name += '_';
setting_name += type_str;
setting_name += sex_str;
break;
}
return gSavedSettings.getString(setting_name);
}
std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex sex)
{
const std::string prefix = "MarketplaceURL";
const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female";
const std::string type_str = LLAssetType::lookup(asset_type);
std::string setting_name = prefix;
switch (asset_type)
{
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_OBJECT:
case LLAssetType::AT_BODYPART:
setting_name += '_';
setting_name += type_str;
setting_name += sex_str;
break;
// to suppress warnings
default:
break;
}
return gSavedSettings.getString(setting_name);
}
class LLPanelOutfitEditGearMenu
{
public:
@ -262,6 +323,7 @@ BOOL LLPanelOutfitEdit::postBuild()
childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);
childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
childSetCommitCallback("shop_btn", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);
mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list");
mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, this));
@ -530,6 +592,46 @@ void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id
}
}
void LLPanelOutfitEdit::onShopButtonClicked()
{
static LLShopURLDispatcher url_resolver;
std::string url;
std::vector<LLPanel*> selected_items;
mCOFWearables->getSelectedItems(selected_items);
ESex sex = gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE;
if (selected_items.size() == 1)
{
LLWearableType::EType type = LLWearableType::WT_NONE;
LLPanel* item = selected_items.front();
// LLPanelDummyClothingListItem is lower then LLPanelInventoryListItemBase in hierarchy tree
if (LLPanelDummyClothingListItem* dummy_item = dynamic_cast<LLPanelDummyClothingListItem*>(item))
{
type = dummy_item->getWearableType();
}
else if (LLPanelInventoryListItemBase* real_item = dynamic_cast<LLPanelInventoryListItemBase*>(item))
{
type = real_item->getWearableType();
}
// WT_INVALID comes for attachments
if (type != LLWearableType::WT_INVALID)
{
url = url_resolver.resolveURL(type, sex);
}
}
if (url.empty())
{
url = url_resolver.resolveURL(mCOFWearables->getExpandedAccordionAssetType(), sex);
}
LLWeb::loadURLExternal(url);
}
void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)
{
LLUUID id_to_remove = mCOFWearables->getSelectedUUID();

View File

@ -163,6 +163,7 @@ public:
void onEditWearableClicked(void);
void onAddWearableClicked(void);
void onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id);
void onShopButtonClicked();
void displayCurrentOutfit();
void updateCurrentOutfitName();

View File

@ -375,7 +375,19 @@ It is calculated as border_size + 2*UIResizeBarOverlap
layout="topleft"
left_pad="1"
name="dummy_right_icon"
width="281" />
width="246" />
<button
follows="bottom|right"
height="25"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="AddItem_Off"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
left_pad="0"
name="shop_btn"
top="1"
width="31" />
</panel>