summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llaccordionctrltab.cpp28
-rw-r--r--indra/llui/llaccordionctrltab.h6
-rw-r--r--indra/newview/llcofwearables.cpp8
-rw-r--r--indra/newview/llinventoryitemslist.cpp55
-rw-r--r--indra/newview/llinventoryitemslist.h17
-rw-r--r--indra/newview/llinventoryobserver.cpp69
-rw-r--r--indra/newview/llinventoryobserver.h13
-rw-r--r--indra/newview/lloutfitslist.cpp119
-rw-r--r--indra/newview/lloutfitslist.h17
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp30
-rw-r--r--indra/newview/llwearableitemslist.cpp84
-rw-r--r--indra/newview/llwearableitemslist.h30
-rw-r--r--indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml62
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_edit.xml24
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml1
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml14
16 files changed, 487 insertions, 90 deletions
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 3c706ce90e..596da782ce 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -436,6 +436,34 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel)
addChild(panel,0);
}
+void LLAccordionCtrlTab::setTitle(const std::string& title)
+{
+ LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+ if (header)
+ {
+ header->setTitle(title);
+ }
+}
+
+boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const focus_signal_t::slot_type& cb)
+{
+ LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+ if (header)
+ {
+ return header->setFocusReceivedCallback(cb);
+ }
+ return boost::signals2::connection();
+}
+
+boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus_signal_t::slot_type& cb)
+{
+ LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+ if (header)
+ {
+ return header->setFocusLostCallback(cb);
+ }
+ return boost::signals2::connection();
+}
LLView* LLAccordionCtrlTab::findContainerView()
{
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index fb19d17e99..de254ed3eb 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -113,6 +113,12 @@ public:
void setAccordionView(LLView* panel);
LLView* getAccordionView() { return mContainerPanel; };
+ // Set text in LLAccordionCtrlTabHeader
+ void setTitle(const std::string& title);
+
+ boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb);
+ boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb);
+
bool getCollapsible() {return mCollapsible;};
void setCollapsible(bool collapsible) {mCollapsible = collapsible;};
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index a2a1dd504a..b8222ebb18 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -204,10 +204,10 @@ void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by
U32 size = clothing_by_type[type].size();
if (size) continue;
- //*TODO create dummy item panel
-
- //*TODO add dummy item panel -> mClothing->addItem(dummy_item_panel, item->getUUID(), ADD_BOTTOM, false);
-
+ EWearableType w_type = static_cast<EWearableType>(type);
+ LLPanelInventoryListItemBase* item_panel = LLPanelDummyClothingListItem::create(w_type);
+ if(!item_panel) continue;
+ mClothing->addItem(item_panel, LLUUID::null, ADD_BOTTOM, false);
addWearableTypeSeparator(mClothing);
}
}
diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp
index 3d8cb6dfe8..8dfdb0788a 100644
--- a/indra/newview/llinventoryitemslist.cpp
+++ b/indra/newview/llinventoryitemslist.cpp
@@ -65,14 +65,8 @@ LLPanelInventoryListItemBase* LLPanelInventoryListItemBase::create(LLViewerInven
void LLPanelInventoryListItemBase::updateItem()
{
- if (mItemIcon.notNull())
- mIcon->setImage(mItemIcon);
-
- LLTextUtil::textboxSetHighlightedVal(
- mTitle,
- LLStyle::Params(),
- mItem->getName(),
- mHighlightedText);
+ setIconImage(mIconImage);
+ setTitle(mItem->getName(), mHighlightedText);
}
void LLPanelInventoryListItemBase::addWidgetToLeftSide(const std::string& name, bool show_widget/* = true*/)
@@ -122,9 +116,10 @@ void LLPanelInventoryListItemBase::setShowWidget(LLUICtrl* ctrl, bool show)
BOOL LLPanelInventoryListItemBase::postBuild()
{
- // Inheritors need to call base implementation
- mIcon = getChild<LLIconCtrl>("item_icon");
- mTitle = getChild<LLTextBox>("item_name");
+ setIconCtrl(getChild<LLIconCtrl>("item_icon"));
+ setTitleCtrl(getChild<LLTextBox>("item_name"));
+
+ mIconImage = get_item_icon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE);
updateItem();
@@ -156,13 +151,12 @@ void LLPanelInventoryListItemBase::onMouseLeave(S32 x, S32 y, MASK mask)
LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem* item)
: LLPanel()
, mItem(item)
-, mIcon(NULL)
-, mTitle(NULL)
+, mIconCtrl(NULL)
+, mTitleCtrl(NULL)
, mWidgetSpacing(WIDGET_SPACING)
, mLeftWidgetsWidth(0)
, mRightWidgetsWidth(0)
{
- mItemIcon = get_item_icon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE);
}
void LLPanelInventoryListItemBase::init()
@@ -197,6 +191,24 @@ void LLPanelInventoryListItemBase::reshapeWidgets()
reshapeMiddleWidgets();
}
+void LLPanelInventoryListItemBase::setIconImage(const LLUIImagePtr& image)
+{
+ if(image)
+ {
+ mIconImage = image;
+ mIconCtrl->setImage(mIconImage);
+ }
+}
+
+void LLPanelInventoryListItemBase::setTitle(const std::string& title, const std::string& highlit_text)
+{
+ LLTextUtil::textboxSetHighlightedVal(
+ mTitleCtrl,
+ LLStyle::Params(),
+ title,
+ highlit_text);
+}
+
void LLPanelInventoryListItemBase::reshapeLeftWidgets()
{
S32 widget_left = 0;
@@ -246,16 +258,16 @@ void LLPanelInventoryListItemBase::reshapeRightWidgets()
void LLPanelInventoryListItemBase::reshapeMiddleWidgets()
{
- LLRect icon_rect(mIcon->getRect());
+ LLRect icon_rect(mIconCtrl->getRect());
icon_rect.setLeftTopAndSize(mLeftWidgetsWidth + getWidgetSpacing(), icon_rect.mTop,
icon_rect.getWidth(), icon_rect.getHeight());
- mIcon->setShape(icon_rect);
+ mIconCtrl->setShape(icon_rect);
S32 name_left = icon_rect.mRight + getWidgetSpacing();
S32 name_right = getLocalRect().getWidth() - mRightWidgetsWidth - getWidgetSpacing();
- LLRect name_rect(mTitle->getRect());
+ LLRect name_rect(mTitleCtrl->getRect());
name_rect.set(name_left, name_rect.mTop, name_right, name_rect.mBottom);
- mTitle->setShape(name_rect);
+ mTitleCtrl->setShape(name_rect);
}
////////////////////////////////////////////////////////////////////////////////
@@ -356,17 +368,18 @@ void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item)
if (!item)
{
llwarns << "No inventory item. Couldn't create flat list item." << llendl;
- llassert(!"No inventory item. Couldn't create flat list item.");
+ llassert(item != NULL);
}
LLPanelInventoryListItemBase *list_item = LLPanelInventoryListItemBase::create(item);
if (!list_item)
return;
- if (!addItem(list_item, item->getUUID()))
+ bool is_item_added = addItem(list_item, item->getUUID());
+ if (!is_item_added)
{
llwarns << "Couldn't add flat list item." << llendl;
- llassert(!"Couldn't add flat list item.");
+ llassert(is_item_added);
}
}
diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h
index 15f04c79a9..152aafbd7e 100644
--- a/indra/newview/llinventoryitemslist.h
+++ b/indra/newview/llinventoryitemslist.h
@@ -125,6 +125,11 @@ protected:
*/
virtual void init();
+ /** setter for mIconCtrl */
+ void setIconCtrl(LLIconCtrl* icon) { mIconCtrl = icon; }
+ /** setter for MTitleCtrl */
+ void setTitleCtrl(LLTextBox* tb) { mTitleCtrl = tb; }
+
void setLeftWidgetsWidth(S32 width) { mLeftWidgetsWidth = width; }
void setRightWidgetsWidth(S32 width) { mRightWidgetsWidth = width; }
@@ -139,6 +144,12 @@ protected:
*/
virtual void reshapeWidgets();
+ /** set wearable type icon image */
+ void setIconImage(const LLUIImagePtr& image);
+
+ /** Set item title - inventory item name usually */
+ void setTitle(const std::string& title, const std::string& highlit_text);
+
private:
/** reshape left side widgets
@@ -155,10 +166,10 @@ private:
LLViewerInventoryItem* mItem;
- LLIconCtrl* mIcon;
- LLTextBox* mTitle;
+ LLIconCtrl* mIconCtrl;
+ LLTextBox* mTitleCtrl;
- LLUIImagePtr mItemIcon;
+ LLUIImagePtr mIconImage;
std::string mHighlightedText;
widget_array_t mLeftSideWidgets;
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index e4a7b17966..86147d65e6 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -669,36 +669,87 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
if (!category)
continue;
- S32 version = category->getVersion();
- if (version != (*iter).second.mVersion)
+ const S32 version = category->getVersion();
+ const S32 expected_num_descendents = category->getDescendentCount();
+ if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) ||
+ (expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN))
{
- // Update category version in map.
- (*iter).second.mVersion = version;
- (*iter).second.mCallback();
+ continue;
+ }
+
+ // Check number of known descendents to find out whether it has changed.
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf((*iter).first, cats, items);
+ if (!cats || !items)
+ {
+ llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl;
+ // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean
+ // that the cat just doesn't have any items or subfolders).
+ // Unrecoverable, so just skip this category.
+
+ llassert(cats != NULL && items != NULL);
+ }
+ const S32 current_num_known_descendents = cats->count() + items->count();
+
+ LLCategoryData cat_data = (*iter).second;
+
+ // If category version or descendents count has changed
+ // update category data in mCategoryMap and fire a callback.
+ if (version != cat_data.mVersion || current_num_known_descendents != cat_data.mDescendentsCount)
+ {
+ cat_data.mVersion = version;
+ cat_data.mDescendentsCount = current_num_known_descendents;
+
+ cat_data.mCallback();
}
}
}
-void LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb)
+bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb)
{
S32 version;
+ S32 current_num_known_descendents;
+ bool can_be_added = true;
+
LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);
if (category)
{
// Inventory category version is used to find out if some changes
// to a category have been made.
version = category->getVersion();
+
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(cat_id, cats, items);
+ if (!cats || !items)
+ {
+ llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl;
+ // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean
+ // that the cat just doesn't have any items or subfolders).
+ // Unrecoverable, so just return "false" meaning that the category can't be observed.
+ can_be_added = false;
+
+ llassert(cats != NULL && items != NULL);
+ }
+ current_num_known_descendents = cats->count() + items->count();
}
else
{
// If category could not be retrieved it might mean that
// inventory is unusable at the moment so the category is
- // stored with VERSION_UNKNOWN and it may be updated later.
+ // stored with VERSION_UNKNOWN and DESCENDENT_COUNT_UNKNOWN,
+ // it may be updated later.
version = LLViewerInventoryCategory::VERSION_UNKNOWN;
+ current_num_known_descendents = LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN;
+ }
+
+ if (can_be_added)
+ {
+ mCategoryMap.insert(category_map_value_t(cat_id, LLCategoryData(cb, version, current_num_known_descendents)));
}
- version = category->getVersion();
- mCategoryMap.insert(category_map_value_t(cat_id, LLCategoryData(cb, version)));
+ return can_be_added;
}
void LLInventoryCategoriesObserver::removeCategory(const LLUUID& cat_id)
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index e63b67d2ad..036e6ca40d 100644
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -276,19 +276,28 @@ public:
LLInventoryCategoriesObserver() {};
virtual void changed(U32 mask);
- void addCategory(const LLUUID& cat_id, callback_t cb);
+ /**
+ * Add cat_id to the list of observed categories with a
+ * callback fired on category being changed.
+ *
+ * @return "true" if category was added, "false" if it could
+ * not be found.
+ */
+ bool addCategory(const LLUUID& cat_id, callback_t cb);
void removeCategory(const LLUUID& cat_id);
protected:
struct LLCategoryData
{
- LLCategoryData(callback_t cb, S32 version)
+ LLCategoryData(callback_t cb, S32 version, S32 num_descendents)
: mCallback(cb)
, mVersion(version)
+ , mDescendentsCount(num_descendents)
{}
callback_t mCallback;
S32 mVersion;
+ S32 mDescendentsCount;
};
typedef std::map<LLUUID, LLCategoryData> category_map_t;
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 1215272685..b103ec45d0 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -41,6 +41,7 @@
#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
+#include "llappearancemgr.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llwearableitemslist.h"
@@ -51,6 +52,7 @@ LLOutfitsList::LLOutfitsList()
: LLPanel()
, mAccordion(NULL)
, mListCommands(NULL)
+ , mSelectedList(NULL)
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
gInventory.addObserver(mCategoriesObserver);
@@ -135,30 +137,37 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
{
const LLUUID cat_id = (*iter);
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
- if (!cat)
- continue;
+ if (!cat) continue;
std::string name = cat->getName();
static LLXMLNodePtr accordionXmlNode = getAccordionTabXMLNode();
-
- accordionXmlNode->setAttributeString("name", name);
- accordionXmlNode->setAttributeString("title", name);
LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder<LLAccordionCtrlTab>(accordionXmlNode, NULL, NULL);
+ tab->setName(name);
+ tab->setTitle(name);
+
// *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
tab->setDisplayChildren(false);
mAccordion->addCollapsibleCtrl(tab);
+ // Start observing the new outfit category.
+ LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
+ if (!mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)))
+ {
+ // Remove accordion tab if category could not be added to observer.
+ mAccordion->removeCollapsibleCtrl(tab);
+ continue;
+ }
+
// Map the new tab with outfit category UUID.
mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
- // Start observing the new outfit category.
- LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
- mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id));
+ // Setting tab focus callback to monitor currently selected outfit.
+ tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id));
- // Setting drop down callback to monitor currently selected outfit.
- tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::onTabExpandedCollapsed, this, list));
+ // Setting list commit callback to monitor currently selected wearable item.
+ list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1));
// Fetch the new outfit contents.
cat->fetch();
@@ -178,10 +187,18 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
// 1. Remove outfit accordion tab from accordion.
mAccordion->removeCollapsibleCtrl(outfits_iter->second);
+ const LLUUID& outfit_id = outfits_iter->first;
+
// 2. Remove outfit category from observer to stop monitoring its changes.
- mCategoriesObserver->removeCategory(outfits_iter->first);
+ mCategoriesObserver->removeCategory(outfit_id);
- // 3. Remove category UUID to accordion tab mapping.
+ // 3. Reset selection if selected outfit is being removed.
+ if (mSelectedOutfitUUID == outfit_id)
+ {
+ changeOutfitSelection(NULL, LLUUID());
+ }
+
+ // 4. Remove category UUID to accordion tab mapping.
mOutfitsMap.erase(outfits_iter);
}
}
@@ -199,40 +216,30 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
mAccordion->arrange();
}
-void LLOutfitsList::updateOutfitTab(const LLUUID& category_id)
+void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
{
- outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id);
- if (outfits_iter != mOutfitsMap.end())
- {
- LLViewerInventoryCategory *cat = gInventory.getCategory(category_id);
- if (!cat)
- return;
+ LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);
+ if (!list) return;
- std::string name = cat->getName();
+ LLViewerInventoryItem *item = gInventory.getItem(list->getSelectedUUID());
+ if (!item) return;
- // Update tab name with the new category name.
- LLAccordionCtrlTab* tab = outfits_iter->second;
- if (tab)
- {
- tab->setName(name);
- }
-
- // Update tab title with the new category name using textbox
- // in accordion tab header.
- LLTextBox* tab_title = tab->findChild<LLTextBox>("dd_textbox");
- if (tab_title)
- {
- tab_title->setText(name);
- }
- }
+ changeOutfitSelection(list, item->getParentUUID());
}
-void LLOutfitsList::onTabExpandedCollapsed(LLWearableItemsList* list)
+void LLOutfitsList::performAction(std::string action)
{
- if (!list)
- return;
+ LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedOutfitUUID);
+ if (!cat) return;
- // TODO: Add outfit selection handling.
+ if ("replaceoutfit" == action)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, FALSE );
+ }
+ else if ("addtooutfit" == action)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, TRUE );
+ }
}
void LLOutfitsList::setFilterSubString(const std::string& string)
@@ -240,7 +247,6 @@ void LLOutfitsList::setFilterSubString(const std::string& string)
mFilterSubString = string;
}
-
//////////////////////////////////////////////////////////////////////////
// Private methods
//////////////////////////////////////////////////////////////////////////
@@ -283,4 +289,37 @@ void LLOutfitsList::computeDifference(
LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved);
}
+void LLOutfitsList::updateOutfitTab(const LLUUID& category_id)
+{
+ outfits_map_t::iterator outfits_iter = mOutfitsMap.find(category_id);
+ if (outfits_iter != mOutfitsMap.end())
+ {
+ LLViewerInventoryCategory *cat = gInventory.getCategory(category_id);
+ if (!cat) return;
+
+ std::string name = cat->getName();
+
+ // Update tab name with the new category name.
+ LLAccordionCtrlTab* tab = outfits_iter->second;
+ if (tab)
+ {
+ tab->setName(name);
+ tab->setTitle(name);
+ }
+ }
+}
+
+void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
+{
+ // Reset selection in previously selected tab
+ // if a new one is selected.
+ if (list && mSelectedList && mSelectedList != list)
+ {
+ mSelectedList->resetSelection();
+ }
+
+ mSelectedList = list;
+ mSelectedOutfitUUID = category_id;
+}
+
// EOF
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index 2d103ea356..d86cf5a703 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -65,10 +65,9 @@ public:
void refreshList(const LLUUID& category_id);
- // Update tab displaying outfit identified by category_id.
- void updateOutfitTab(const LLUUID& category_id);
+ void onSelectionChange(LLUICtrl* ctrl);
- void onTabExpandedCollapsed(LLWearableItemsList* list);
+ void performAction(std::string action);
void setFilterSubString(const std::string& string);
@@ -85,12 +84,24 @@ private:
*/
void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved);
+ /**
+ * Updates tab displaying outfit identified by category_id.
+ */
+ void updateOutfitTab(const LLUUID& category_id);
+
+ /**
+ * Resets previous selection and stores newly selected list and outfit id.
+ */
+ void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id);
LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
LLPanel* mListCommands;
+ LLWearableItemsList* mSelectedList;
+ LLUUID mSelectedOutfitUUID;
+
std::string mFilterSubString;
typedef std::map<LLUUID, LLAccordionCtrlTab*> outfits_map_t;
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 789e85b46f..80964938f5 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -188,19 +188,37 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
void LLPanelOutfitsInventory::onWearButtonClick()
{
- LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
- if (listenerp)
+ // TODO: Remove if/else, add common interface
+ // for "My Outfits" and "Wearing" tabs.
+ if (!isCOFPanelActive())
+ {
+ mMyOutfitsPanel->performAction("replaceoutfit");
+ }
+ else
{
- listenerp->performAction(NULL, "replaceoutfit");
+ LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
+ if (listenerp)
+ {
+ listenerp->performAction(NULL, "replaceoutfit");
+ }
}
}
void LLPanelOutfitsInventory::onAdd()
{
- LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
- if (listenerp)
+ // TODO: Remove if/else, add common interface
+ // for "My Outfits" and "Wearing" tabs.
+ if (!isCOFPanelActive())
+ {
+ mMyOutfitsPanel->performAction("addtooutfit");
+ }
+ else
{
- listenerp->performAction(NULL, "addtooutfit");
+ LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
+ if (listenerp)
+ {
+ listenerp->performAction(NULL, "addtooutfit");
+ }
}
}
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index b8fab63be9..56b2791993 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -33,8 +33,11 @@
#include "llwearableitemslist.h"
+#include "lliconctrl.h"
+
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
+#include "lltransutil.h"
class LLFindOutfitItems : public LLInventoryCollectFunctor
{
@@ -212,6 +215,87 @@ void LLPanelBodyPartsListItem::setShowEditButton(bool show)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLPanelDummyClothingListItem* LLPanelDummyClothingListItem::create(EWearableType w_type)
+{
+ LLPanelDummyClothingListItem* list_item = new LLPanelDummyClothingListItem(w_type);
+ list_item->init();
+ return list_item;
+}
+
+void LLPanelDummyClothingListItem::updateItem()
+{
+ std::string title = wearableTypeToString(mWearableType);
+ setTitle(title, LLStringUtil::null);
+}
+
+BOOL LLPanelDummyClothingListItem::postBuild()
+{
+ LLIconCtrl* icon = getChild<LLIconCtrl>("item_icon");
+ setIconCtrl(icon);
+ setTitleCtrl(getChild<LLTextBox>("item_name"));
+
+ addWidgetToRightSide("btn_add");
+
+ setIconImage(get_item_icon(LLAssetType::AT_CLOTHING, LLInventoryType::IT_NONE, mWearableType, FALSE));
+ updateItem();
+
+ // Make it look loke clothing item - reserve space for 'delete' button
+ setLeftWidgetsWidth(icon->getRect().mLeft);
+
+ setWidgetsVisible(false);
+ reshapeWidgets();
+
+ return TRUE;
+}
+
+LLPanelDummyClothingListItem::LLPanelDummyClothingListItem(EWearableType w_type)
+ : LLPanelWearableListItem(NULL)
+ , mWearableType(w_type)
+{
+}
+
+void LLPanelDummyClothingListItem::init()
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_dummy_clothing_list_item.xml");
+}
+
+typedef std::map<EWearableType, std::string> clothing_to_string_map_t;
+
+clothing_to_string_map_t init_clothing_string_map()
+{
+ clothing_to_string_map_t w_map;
+ w_map.insert(std::make_pair(WT_SHIRT, "shirt_not_worn"));
+ w_map.insert(std::make_pair(WT_PANTS, "pants_not_worn"));
+ w_map.insert(std::make_pair(WT_SHOES, "shoes_not_worn"));
+ w_map.insert(std::make_pair(WT_SOCKS, "socks_not_worn"));
+ w_map.insert(std::make_pair(WT_JACKET, "jacket_not_worn"));
+ w_map.insert(std::make_pair(WT_GLOVES, "gloves_not_worn"));
+ w_map.insert(std::make_pair(WT_UNDERSHIRT, "undershirt_not_worn"));
+ w_map.insert(std::make_pair(WT_UNDERPANTS, "underpants_not_worn"));
+ w_map.insert(std::make_pair(WT_SKIRT, "skirt_not_worn"));
+ w_map.insert(std::make_pair(WT_ALPHA, "alpha_not_worn"));
+ w_map.insert(std::make_pair(WT_TATTOO, "tattoo_not_worn"));
+ return w_map;
+}
+
+std::string LLPanelDummyClothingListItem::wearableTypeToString(EWearableType w_type)
+{
+ static const clothing_to_string_map_t w_map = init_clothing_string_map();
+ static const std::string invalid_str = LLTrans::getString("invalid_not_worn");
+
+ std::string type_str = invalid_str;
+ clothing_to_string_map_t::const_iterator it = w_map.find(w_type);
+ if(w_map.end() != it)
+ {
+ type_str = LLTrans::getString(it->second);
+ }
+ return type_str;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list");
LLWearableItemsList::Params::Params()
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index ae43b3f673..c4a415dfbf 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -81,7 +81,6 @@ public:
virtual ~LLPanelClothingListItem();
- /*virtual*/ void init();
/*virtual*/ BOOL postBuild();
/**
@@ -96,6 +95,8 @@ public:
protected:
LLPanelClothingListItem(LLViewerInventoryItem* item);
+
+ /*virtual*/ void init();
};
class LLPanelBodyPartsListItem : public LLPanelWearableListItem
@@ -107,7 +108,6 @@ public:
virtual ~LLPanelBodyPartsListItem();
- /*virtual*/ void init();
/*virtual*/ BOOL postBuild();
/**
@@ -118,6 +118,32 @@ public:
protected:
LLPanelBodyPartsListItem(LLViewerInventoryItem* item);
+
+ /*virtual*/ void init();
+};
+
+/**
+ * @class LLPanelDummyClothingListItem
+ *
+ * A dummy item panel - displays grayed clothing icon, grayed title '<clothing> not worn' and 'add' button
+ */
+class LLPanelDummyClothingListItem : public LLPanelWearableListItem
+{
+public:
+ static LLPanelDummyClothingListItem* create(EWearableType w_type);
+
+ /*virtual*/ void updateItem();
+ /*virtual*/ BOOL postBuild();
+
+protected:
+ LLPanelDummyClothingListItem(EWearableType w_type);
+
+ /*virtual*/ void init();
+
+ static std::string wearableTypeToString(EWearableType w_type);
+
+private:
+ EWearableType mWearableType;
};
/**
diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml
new file mode 100644
index 0000000000..dbbfa8f2e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="top|right|left"
+ height="20"
+ layout="topleft"
+ left="0"
+ name="dummy_clothing_item"
+ top="0"
+ width="380">
+ <icon
+ follows="top|right|left"
+ height="20"
+ image_name="ListItem_Over"
+ layout="topleft"
+ left="0"
+ name="hovered_icon"
+ top="0"
+ visible="false"
+ width="380" />
+ <icon
+ height="20"
+ follows="top|right|left"
+ image_name="ListItem_Select"
+ layout="topleft"
+ left="0"
+ name="selected_icon"
+ top="0"
+ visible="false"
+ width="380" />
+ <icon
+ height="16"
+ color="0.75 0.75 0.75 1"
+ follows="top|left"
+ image_name="Inv_Object"
+ layout="topleft"
+ left="20"
+ name="item_icon"
+ top="2"
+ width="16" />
+ <text
+ follows="left|right"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ allow_html="false"
+ use_ellipses="true"
+ name="item_name"
+ text_color="LtGray_50"
+ top="4"
+ value="..."
+ width="359" />
+ <button
+ name="btn_add"
+ layout="topleft"
+ follows="top|right"
+ label="+"
+ top="0"
+ left="0"
+ height="20"
+ width="20"
+ tab_stop="false" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index 73181392c9..a9f588698a 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -234,6 +234,14 @@
name="move_further_btn"
top="1"
width="31" />
+ <icon
+ follows="bottom|left"
+ height="25"
+ image_name="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_icon"
+ width="105" />
<button
follows="bottom|right"
height="25"
@@ -440,6 +448,22 @@
name="add_to_outfit_btn"
top="1"
width="31" />
+ <icon
+ follows="bottom|left"
+ height="25"
+ image_name="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_middle_icon"
+ width="140" />
+ <icon
+ follows="bottom|left"
+ height="25"
+ image_name="Toolbar_Right_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_right_icon"
+ width="31" />
</panel>
</layout_panel>
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 066ea3be6e..7e212c9383 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -490,6 +490,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
label="Share"
layout="topleft"
name="share_btn"
+ tool_tip="Share an inventory item"
width="62" />
<button
follows="bottom|left"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 74dc23853d..f544449d02 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -1802,6 +1802,20 @@ Clears (deletes) the media and all params from the given face.
<string name="alpha">Alpha</string>
<string name="tattoo">Tattoo</string>
<string name="invalid">invalid</string>
+
+ <!-- Not Worn Wearable Types -->
+ <string name="shirt_not_worn">Shirt not worn</string>
+ <string name="pants_not_worn">Pants not worn</string>
+ <string name="shoes_not_worn">Shoes not worn</string>
+ <string name="socks_not_worn">Socks not worn</string>
+ <string name="jacket_not_worn">Jacket not worn</string>
+ <string name="gloves_not_worn">Gloves not worn</string>
+ <string name="undershirt_not_worn">Undershirt not worn</string>
+ <string name="underpants_not_worn">Underpants not worn</string>
+ <string name="skirt_not_worn">Skirt not worn</string>
+ <string name="alpha_not_worn">Alpha not worn</string>
+ <string name="tattoo_not_worn">Tattoo not worn</string>
+ <string name="invalid_not_worn">invalid</string>
<!-- Wearable List-->
<string name="NewWearable">New [WEARABLE_ITEM]</string>