From 2ce7556e53544e50a4d4d28705976655cafa6992 Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan Date: Wed, 21 Apr 2010 15:44:24 +0300 Subject: Implemented by SL EXT-6722(normal task) - Create modified inventory view for "my outfits" tab in top-level appearance sidebar (tier 1) llui: - Setting container panel for accordion tab control to dynamically add tabs to accordions. - Added method to dynamically remove accordion tabs. - Added LLIconCtrl image setter. newview: - Class LLOutfitsList - a list of agents's outfits from "My Outfits" inventory category which represents each outfit by an accordion tab with a list of items inside it. - Class LLWearableItemsList - a list of wearable items used in each accordion tab of "My Outfits" tab. - Class LLInventoryItemsList - a base class for LLWearableItemsList that represents inventory items by panels in LLFlatListView. - Class LLPanelInventoryItem - inventory item representation for a flat list. Item icon is set according to item type. - Class LLInventoryCategoriesObserver - an observer used in LLOutfitsList for monitoring changes to "My Outfits" inventory category and updating outfits accordion tabs and list of items for each outfit. Known issues: - Only first outfit tab is displayed in "My Outfits" until this tab is expanded. - Bottom bar buttons and filter field not functioning for "My Outfits" tab since LLOutfitsList still doesn't support selection, filtering and sorting. - "My Outfits" and "Wearing" tabs of "Appearance" side panel might need a common interface to use LLOutfitsList and LLinventoryPanel as tabs in LLPanelOutfitsInventory or "Wearing" tab should be replaces with LLOutfitsList class object i.e. a flat list. On review - https://codereview.productengine.com/secondlife/r/285/ --HG-- branch : product-engine --- indra/newview/lloutfitslist.cpp | 265 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 indra/newview/lloutfitslist.cpp (limited to 'indra/newview/lloutfitslist.cpp') diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp new file mode 100644 index 0000000000..ad42d80467 --- /dev/null +++ b/indra/newview/lloutfitslist.cpp @@ -0,0 +1,265 @@ +/** + * @file lloutfitslist.cpp + * @brief List of agent's outfits for My Appearance side panel. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lloutfitslist.h" + +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llwearableitemslist.h" + +static LLRegisterPanelClassWrapper t_outfits_list("outfits_list"); + +LLOutfitsList::LLOutfitsList() + : LLPanel() + , mAccordion(NULL) + , mListCommands(NULL) +{} + +LLOutfitsList::~LLOutfitsList() +{ + if (gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + delete mCategoriesObserver; + } + + if (gInventory.containsObserver(this)) + { + gInventory.removeObserver(this); + } +} + +BOOL LLOutfitsList::postBuild() +{ + mAccordion = getChild("outfits_accordion"); + + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + + gInventory.addObserver(this); + + return TRUE; +} + +//virtual +void LLOutfitsList::changed(U32 mask) +{ + if (!gInventory.isInventoryUsable()) + return; + + // Start observing changes in "My Outfits" category. + const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + mCategoriesObserver->addCategory(outfits, + boost::bind(&LLOutfitsList::refreshList, this, outfits)); + + LLViewerInventoryCategory* category = gInventory.getCategory(outfits); + if (!category) + return; + + // Fetch "My Outfits" contents and refresh the list to display + // initially fetched items. If not all items are fetched now + // the observer will refresh the list as soon as the new items + // arrive. + category->fetch(); + refreshList(outfits); + + // This observer is used to start the initial outfits fetch + // when inventory becomes usable. It is no longer needed because + // "My Outfits" category is now observed by + // LLInventoryCategoriesObserver. + gInventory.removeObserver(this); +} + +void LLOutfitsList::refreshList(const LLUUID& category_id) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + // Collect all sub-categories of a given category. + LLIsType is_category(LLAssetType::AT_CATEGORY); + gInventory.collectDescendentsIf( + category_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_category); + + uuid_vec_t vnew; + + // Creating a vector of newly collected sub-categories UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); + iter != cat_array.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + + uuid_vec_t vcur; + + // Creating a vector of currently displayed sub-categories UUIDs. + for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); + iter != mOutfitsMap.end(); + iter++) + { + vcur.push_back((*iter).first); + } + + // Sorting both vectors to compare. + std::sort(vcur.begin(), vcur.end()); + std::sort(vnew.begin(), vnew.end()); + + uuid_vec_t vadded; + uuid_vec_t vremoved; + + uuid_vec_t::iterator it; + size_t maxsize = llmax(vcur.size(), vnew.size()); + vadded.resize(maxsize); + vremoved.resize(maxsize); + + // what to remove + it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); + vremoved.erase(it, vremoved.end()); + + // what to add + it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); + vadded.erase(it, vadded.end()); + + // Handle added tabs. + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + iter++) + { + const LLUUID cat_id = (*iter); + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (!cat) + continue; + + std::string name = cat->getName(); + + // *TODO: create accordion tabs and lists from XML. + LLAccordionCtrlTab::Params params; + params.name(name); + params.title(name); + params.rect(LLRect(0, 0, 315, 20)); + params.display_children(false); + LLAccordionCtrlTab* tab = LLUICtrlFactory::create(params); + + mAccordion->addCollapsibleCtrl(tab); + + LLFlatListView::Params list_params; + LLWearableItemsList* list = LLUICtrlFactory::create(list_params); + + tab->addChild(list, 0); + tab->setDisplayChildren(false); + + // Map the new tab with outfit category UUID. + mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab)); + + // Start observing the new outfit category. + mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)); + + // Fetch the new outfit contents. + cat->fetch(); + + // Refresh the list of outfit items after fetch(). + // Further list updates will be triggered by the category observer. + list->updateList(cat_id); + } + + // Handle removed tabs. + for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); iter++) + { + outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter)); + if (outfits_iter != mOutfitsMap.end()) + { + // An outfit is removed from the list. Do the following: + // 1. Remove outfit accordion tab from accordion. + mAccordion->removeCollapsibleCtrl(outfits_iter->second); + + // 2. Remove outfit category from observer to stop monitoring its changes. + mCategoriesObserver->removeCategory(outfits_iter->first); + + // 3. Remove category UUID to accordion tab mapping. + mOutfitsMap.erase(outfits_iter); + } + } + + // Get changed items from inventory model and update outfit tabs + // which might have been renamed. + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); + items_iter != changed_items.end(); + ++items_iter) + { + updateOutfitTab(*items_iter); + } + + mAccordion->arrange(); +} + +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); + } + + // Update tab title with the new category name using textbox + // in accordion tab header. + LLTextBox* tab_title = tab->findChild("dd_textbox"); + if (tab_title) + { + tab_title->setText(name); + } + } +} + +void LLOutfitsList::setFilterSubString(const std::string& string) +{ + mFilterSubString = string; +} + +// EOF -- cgit v1.3 From 5dfc5d020c0497619ae23da61a45f6671903d02c Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Fri, 23 Apr 2010 17:44:33 +0300 Subject: Work on task EXT-6722 (Create modified inventory view for "my outfits" tab in top-level appearance sidebar) Code improvements: * Moved Accordion tab + Flat list into separate xml. * Implemented dynamic creation of the accordion tab via xml Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/312/ --HG-- branch : product-engine --- indra/newview/lloutfitslist.cpp | 38 ++++++++++++++-------- indra/newview/lloutfitslist.h | 8 +++++ .../skins/default/xui/en/outfit_accordion_tab.xml | 18 ++++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/outfit_accordion_tab.xml (limited to 'indra/newview/lloutfitslist.cpp') diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index ad42d80467..cce4f94028 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -168,26 +168,21 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) std::string name = cat->getName(); - // *TODO: create accordion tabs and lists from XML. - LLAccordionCtrlTab::Params params; - params.name(name); - params.title(name); - params.rect(LLRect(0, 0, 315, 20)); - params.display_children(false); - LLAccordionCtrlTab* tab = LLUICtrlFactory::create(params); + static LLXMLNodePtr accordionXmlNode = getAccordionTabXMLNode(); - mAccordion->addCollapsibleCtrl(tab); - - LLFlatListView::Params list_params; - LLWearableItemsList* list = LLUICtrlFactory::create(list_params); + accordionXmlNode->setAttributeString("name", name); + accordionXmlNode->setAttributeString("title", name); + LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder(accordionXmlNode, NULL, NULL); - tab->addChild(list, 0); - tab->setDisplayChildren(false); + // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. + tab->setDisplayChildren(false); + mAccordion->addCollapsibleCtrl(tab); // 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("wearable_items_list"); mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)); // Fetch the new outfit contents. @@ -262,4 +257,21 @@ void LLOutfitsList::setFilterSubString(const std::string& string) mFilterSubString = string; } + +////////////////////////////////////////////////////////////////////////// +// Private methods +////////////////////////////////////////////////////////////////////////// +LLXMLNodePtr LLOutfitsList::getAccordionTabXMLNode() +{ + LLXMLNodePtr xmlNode = NULL; + bool success = LLUICtrlFactory::getLayeredXMLNode("outfit_accordion_tab.xml", xmlNode); + if (!success) + { + llwarns << "Failed to read xml of Outfit's Accordion Tab from outfit_accordion_tab.xml" << llendl; + return NULL; + } + + return xmlNode; +} + // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 892e0a862a..f1756ce873 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -59,6 +59,14 @@ public: void setFilterSubString(const std::string& string); private: + /** + * Reads xml with accordion tab and Flat list from xml file. + * + * @return LLPointer to XMLNode with accordion tab and flat list. + */ + LLXMLNodePtr getAccordionTabXMLNode(); + + LLInventoryCategoriesObserver* mCategoriesObserver; LLAccordionCtrl* mAccordion; diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml new file mode 100644 index 0000000000..d00b1bfb7b --- /dev/null +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -0,0 +1,18 @@ + + + + + + -- cgit v1.3 From fbfc85176670f3f948e6e2f00c8d8e37c96d5299 Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Mon, 26 Apr 2010 18:56:28 +0300 Subject: (EXT-6722) Create modified inventory view for "my outfits" tab in top-level appearance sidebar (tier 1) llui: - Setting container panel for accordion tab control to dynamically add tabs to accordions. - Added method to dynamically remove accordion tabs. - Added LLIconCtrl image setter. newview: - Class LLOutfitsList - a list of agents's outfits from "My Outfits" inventory category which represents each outfit by an accordion tab with a list of items inside it. - Class LLWearableItemsList - a list of wearable items used in each accordion tab of "My Outfits" tab. - Class LLInventoryItemsList - a base class for LLWearableItemsList that represents inventory items by panels in LLFlatListView. - Class LLPanelInventoryItem - inventory item representation for a flat list. Item icon is set according to item type. - Class LLInventoryCategoriesObserver - an observer used in LLOutfitsList for monitoring changes to "My Outfits" inventory category and updating outfits accordion tabs and list of items for each outfit. Reviewed by Mike Antipov https://codereview.productengine.com/secondlife/r/285/ --HG-- branch : product-engine --- indra/llui/llaccordionctrl.cpp | 4 +- indra/llui/llaccordionctrltab.cpp | 3 +- indra/newview/llinventoryitemslist.cpp | 74 +++++++++++++++------- indra/newview/llinventoryitemslist.h | 36 ++++++----- indra/newview/llinventoryobserver.cpp | 30 +++++++-- indra/newview/lloutfitslist.cpp | 60 +++++++++--------- indra/newview/lloutfitslist.h | 13 ++++ indra/newview/llwearableitemslist.cpp | 5 +- indra/newview/llwearableitemslist.h | 19 ++++-- .../skins/default/xui/en/outfit_accordion_tab.xml | 4 +- 10 files changed, 162 insertions(+), 86 deletions(-) (limited to 'indra/newview/lloutfitslist.cpp') diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index dca43c5784..5d1d57cbb2 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -329,7 +329,7 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLView* view) LLAccordionCtrlTab* accordion_tab = dynamic_cast(view); if(!accordion_tab) return; - if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end()) + if(std::find(beginChild(), endChild(), accordion_tab) == endChild()) addChild(accordion_tab); mAccordionTabs.push_back(accordion_tab); @@ -343,7 +343,7 @@ void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) if(!accordion_tab) return; - if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) != getChildList()->end()) + if(std::find(beginChild(), endChild(), accordion_tab) != endChild()) removeChild(accordion_tab); for (std::vector::iterator iter = mAccordionTabs.begin(); diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index d389236642..3c706ce90e 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -554,7 +554,8 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) } //LLAccordionCtrl should rearrange accodion tab if one of accordion change its size - getParent()->notifyParent(info); + if (getParent()) // A parent may not be set if tabs are added dynamically. + getParent()->notifyParent(info); return 1; } else if(str_action == "select_prev") diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 9f54b86607..dca130c672 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -2,6 +2,10 @@ * @file llinventoryitemslist.cpp * @brief A list of inventory items represented by LLFlatListView. * + * Class LLInventoryItemsList implements a flat list of inventory items. + * Class LLPanelInventoryListItem displays inventory item as an element + * of LLInventoryItemsList. + * * $LicenseInfo:firstyear=2010&license=viewergpl$ * * Copyright (c) 2010, Linden Research, Inc. @@ -39,33 +43,31 @@ #include "lliconctrl.h" #include "llinventoryfunctions.h" +#include "llinventorymodel.h" #include "lltextutil.h" //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -LLPanelInventoryItem::LLPanelInventoryItem(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 wearable_type, - const std::string &item_name, - const std::string &hl) -: LLPanel() - ,mItemName(item_name) - ,mHighlightedText(hl) - ,mIcon(NULL) - ,mTitle(NULL) +// static +LLPanelInventoryListItem* LLPanelInventoryListItem::createItemPanel(const LLViewerInventoryItem* item) { - mItemIcon = get_item_icon(asset_type, inventory_type, wearable_type, FALSE); - - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory_item.xml"); + if (item) + { + return new LLPanelInventoryListItem(item); + } + else + { + return NULL; + } } -LLPanelInventoryItem::~LLPanelInventoryItem() +LLPanelInventoryListItem::~LLPanelInventoryListItem() {} //virtual -BOOL LLPanelInventoryItem::postBuild() +BOOL LLPanelInventoryListItem::postBuild() { mIcon = getChild("item_icon"); mTitle = getChild("item_name"); @@ -76,14 +78,14 @@ BOOL LLPanelInventoryItem::postBuild() } //virtual -void LLPanelInventoryItem::setValue(const LLSD& value) +void LLPanelInventoryListItem::setValue(const LLSD& value) { if (!value.isMap()) return; if (!value.has("selected")) return; childSetVisible("selected_icon", value["selected"]); } -void LLPanelInventoryItem::updateItem() +void LLPanelInventoryListItem::updateItem() { if (mItemIcon.notNull()) mIcon->setImage(mItemIcon); @@ -95,28 +97,47 @@ void LLPanelInventoryItem::updateItem() mHighlightedText); } -void LLPanelInventoryItem::onMouseEnter(S32 x, S32 y, MASK mask) +void LLPanelInventoryListItem::onMouseEnter(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", true); LLPanel::onMouseEnter(x, y, mask); } -void LLPanelInventoryItem::onMouseLeave(S32 x, S32 y, MASK mask) +void LLPanelInventoryListItem::onMouseLeave(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", false); LLPanel::onMouseLeave(x, y, mask); } +LLPanelInventoryListItem::LLPanelInventoryListItem(const LLViewerInventoryItem* item) +: LLPanel() + ,mIcon(NULL) + ,mTitle(NULL) +{ + mItemName = item->getName(); + mItemIcon = get_item_icon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE); + + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory_item.xml"); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -LLInventoryItemsList::LLInventoryItemsList(const LLFlatListView::Params& p) +LLInventoryItemsList::Params::Params() +{} + +LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p) : LLFlatListView(p) , mNeedsRefresh(false) -{} +{ + // TODO: mCommitOnSelectionChange is set to "false" in LLFlatListView + // but reset to true in all derived classes. This settings might need to + // be added to LLFlatListView::Params() and/or set to "true" by default. + setCommitOnSelectionChange(true); +} // virtual LLInventoryItemsList::~LLInventoryItemsList() @@ -196,10 +217,15 @@ void LLInventoryItemsList::computeDifference( void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item) { - llassert(item); + if (!item) + { + llwarns << "No inventory item. Couldn't create flat list item." << llendl; + llassert(!"No inventory item. Couldn't create flat list item."); + } - LLPanelInventoryItem *list_item = new LLPanelInventoryItem(item->getType(), - item->getInventoryType(), item->getFlags(), item->getName(), LLStringUtil::null); + LLPanelInventoryListItem *list_item = LLPanelInventoryListItem::createItemPanel(item); + if (!list_item) + return; if (!addItem(list_item, item->getUUID())) { diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 0ca4146867..b496f4b9e9 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -2,6 +2,10 @@ * @file llinventoryitemslist.h * @brief A list of inventory items represented by LLFlatListView. * + * Class LLInventoryItemsList implements a flat list of inventory items. + * Class LLPanelInventoryListItem displays inventory item as an element + * of LLInventoryItemsList. + * * $LicenseInfo:firstyear=2010&license=viewergpl$ * * Copyright (c) 2010, Linden Research, Inc. @@ -32,28 +36,23 @@ #ifndef LL_LLINVENTORYITEMSLIST_H #define LL_LLINVENTORYITEMSLIST_H -#include "llpanel.h" - -#include "llassettype.h" +#include "lldarray.h" -#include "llinventorytype.h" +#include "llpanel.h" // newview #include "llflatlistview.h" -#include "llinventorymodel.h" class LLIconCtrl; class LLTextBox; +class LLViewerInventoryItem; -class LLPanelInventoryItem : public LLPanel +class LLPanelInventoryListItem : public LLPanel { public: - LLPanelInventoryItem(LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - U32 wearable_type, - const std::string &item_name, - const std::string &hl); - virtual ~LLPanelInventoryItem(); + static LLPanelInventoryListItem* createItemPanel(const LLViewerInventoryItem* item); + + virtual ~LLPanelInventoryListItem(); /*virtual*/ BOOL postBuild(); /*virtual*/ void setValue(const LLSD& value); @@ -63,6 +62,9 @@ public: void onMouseEnter(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); +protected: + LLPanelInventoryListItem(const LLViewerInventoryItem* item); + private: LLIconCtrl* mIcon; LLTextBox* mTitle; @@ -72,13 +74,17 @@ private: std::string mHighlightedText; }; - class LLInventoryItemsList : public LLFlatListView { public: + struct Params : public LLInitParam::Block + { + Params(); + }; + virtual ~LLInventoryItemsList(); - void refreshList(const LLInventoryModel::item_array_t item_array); + void refreshList(const LLDynamicArray > item_array); /** * Let list know items need to be refreshed in next draw() @@ -91,7 +97,7 @@ public: protected: friend class LLUICtrlFactory; - LLInventoryItemsList(const LLFlatListView::Params& p); + LLInventoryItemsList(const LLInventoryItemsList::Params& p); uuid_vec_t& getIDs() { return mIDs; } diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 03006243f9..214b5d317a 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -658,11 +658,13 @@ void LLInventoryCategoriesObserver::changed(U32 mask) for (category_map_t::iterator iter = mCategoryMap.begin(); iter != mCategoryMap.end(); - iter++) + ++iter) { - // Inventory category version is used to find out if some changes - // to a category have been made. - S32 version = gInventory.getCategory((*iter).first)->getVersion(); + LLViewerInventoryCategory* category = gInventory.getCategory((*iter).first); + if (!category) + continue; + + S32 version = category->getVersion(); if (version != (*iter).second.mVersion) { // Update category version in map. @@ -674,11 +676,27 @@ void LLInventoryCategoriesObserver::changed(U32 mask) void LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb) { - S32 version = gInventory.getCategory(cat_id)->getVersion(); + S32 version; + 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(); + } + 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. + version = LLViewerInventoryCategory::VERSION_UNKNOWN; + } + + version = category->getVersion(); mCategoryMap.insert(category_map_value_t(cat_id, LLCategoryData(cb, version))); } void LLInventoryCategoriesObserver::removeCategory(const LLUUID& cat_id) { - mCategoryMap.erase(mCategoryMap.find(cat_id)); + mCategoryMap.erase(cat_id); } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index cce4f94028..1c627d452f 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -33,6 +33,9 @@ #include "lloutfitslist.h" +// llcommon +#include "llcommonutils.h" + #include "llaccordionctrl.h" #include "llaccordionctrltab.h" #include "llinventoryfunctions.h" @@ -45,7 +48,12 @@ LLOutfitsList::LLOutfitsList() : LLPanel() , mAccordion(NULL) , mListCommands(NULL) -{} +{ + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + + gInventory.addObserver(this); +} LLOutfitsList::~LLOutfitsList() { @@ -65,11 +73,6 @@ BOOL LLOutfitsList::postBuild() { mAccordion = getChild("outfits_accordion"); - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); - - gInventory.addObserver(this); - return TRUE; } @@ -79,15 +82,15 @@ void LLOutfitsList::changed(U32 mask) if (!gInventory.isInventoryUsable()) return; - // Start observing changes in "My Outfits" category. const LLUUID outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - mCategoriesObserver->addCategory(outfits, - boost::bind(&LLOutfitsList::refreshList, this, outfits)); - LLViewerInventoryCategory* category = gInventory.getCategory(outfits); if (!category) return; + // Start observing changes in "My Outfits" category. + mCategoriesObserver->addCategory(outfits, + boost::bind(&LLOutfitsList::refreshList, this, outfits)); + // Fetch "My Outfits" contents and refresh the list to display // initially fetched items. If not all items are fetched now // the observer will refresh the list as soon as the new items @@ -121,7 +124,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) // Creating a vector of newly collected sub-categories UUIDs. for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); iter != cat_array.end(); - iter++) + ++iter) { vnew.push_back((*iter)->getUUID()); } @@ -131,35 +134,21 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) // Creating a vector of currently displayed sub-categories UUIDs. for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); iter != mOutfitsMap.end(); - iter++) + ++iter) { vcur.push_back((*iter).first); } - // Sorting both vectors to compare. - std::sort(vcur.begin(), vcur.end()); - std::sort(vnew.begin(), vnew.end()); - uuid_vec_t vadded; uuid_vec_t vremoved; - uuid_vec_t::iterator it; - size_t maxsize = llmax(vcur.size(), vnew.size()); - vadded.resize(maxsize); - vremoved.resize(maxsize); - - // what to remove - it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); - vremoved.erase(it, vremoved.end()); - - // what to add - it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); - vadded.erase(it, vadded.end()); + // Create added and removed items vectors. + LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); // Handle added tabs. for (uuid_vec_t::const_iterator iter = vadded.begin(); iter != vadded.end(); - iter++) + ++iter) { const LLUUID cat_id = (*iter); LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); @@ -175,7 +164,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder(accordionXmlNode, NULL, NULL); // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated. - tab->setDisplayChildren(false); + tab->setDisplayChildren(false); mAccordion->addCollapsibleCtrl(tab); // Map the new tab with outfit category UUID. @@ -185,6 +174,9 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) LLWearableItemsList* list = tab->getChild("wearable_items_list"); mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id)); + // Setting drop down callback to monitor currently selected outfit. + tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::onTabExpandedCollapsed, this, list)); + // Fetch the new outfit contents. cat->fetch(); @@ -252,6 +244,14 @@ void LLOutfitsList::updateOutfitTab(const LLUUID& category_id) } } +void LLOutfitsList::onTabExpandedCollapsed(LLWearableItemsList* list) +{ + if (!list) + return; + + // TODO: Add outfit selection handling. +} + void LLOutfitsList::setFilterSubString(const std::string& string) { mFilterSubString = string; diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index f1756ce873..de14c15415 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -41,6 +41,17 @@ class LLAccordionCtrl; class LLAccordionCtrlTab; class LLWearableItemsList; +/** + * @class LLOutfitsList + * + * A list of agents's outfits from "My Outfits" inventory category + * which displays each outfit in an accordion tab with a flat list + * of items inside it. + * Uses LLInventoryCategoriesObserver to monitor changes to "My Outfits" + * inventory category and refresh the outfits listed in it. + * This class is derived from LLInventoryObserver to know when inventory + * becomes usable and it is safe to request data from inventory model. + */ class LLOutfitsList : public LLPanel, public LLInventoryObserver { public: @@ -56,6 +67,8 @@ public: // Update tab displaying outfit identified by category_id. void updateOutfitTab(const LLUUID& category_id); + void onTabExpandedCollapsed(LLWearableItemsList* list); + void setFilterSubString(const std::string& string); private: diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index ff309cbbc3..3d110dcc78 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -62,7 +62,10 @@ bool LLFindOutfitItems::operator()(LLInventoryCategory* cat, static const LLDefaultChildRegistry::Register r("wearable_items_list"); -LLWearableItemsList::LLWearableItemsList(const LLFlatListView::Params& p) +LLWearableItemsList::Params::Params() +{} + +LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) : LLInventoryItemsList(p) {} diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index e3b011912b..e7ccba8e6c 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -34,23 +34,32 @@ #include "llpanel.h" -#include "llassettype.h" - -#include "llinventorytype.h" - // newview #include "llinventoryitemslist.h" +/** + * @class LLWearableItemsList + * + * A flat list of wearable inventory items. + * Collects all items that can be a part of an outfit from + * an inventory category specified by UUID and displays them + * as a flat list. + */ class LLWearableItemsList : public LLInventoryItemsList { public: + struct Params : public LLInitParam::Block + { + Params(); + }; + virtual ~LLWearableItemsList(); void updateList(const LLUUID& category_id); protected: friend class LLUICtrlFactory; - LLWearableItemsList(const LLFlatListView::Params& p); + LLWearableItemsList(const LLWearableItemsList::Params& p); }; #endif //LL_LLWEARABLEITEMSLIST_H diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index d00b1bfb7b..b3150bb98b 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -1,10 +1,10 @@ - + Date: Tue, 27 Apr 2010 10:20:30 +0300 Subject: Making use of LLCommonUtils::computeDifference. Replaced duplicating code with generic function LLCommonUtils::computeDifference() Reviewed by Vadim Savchuk - https://codereview.productengine.com/secondlife/r/313/ --HG-- branch : product-engine --- indra/llcommon/llcommonutils.h | 5 ++++ indra/newview/llavatarlist.cpp | 18 ++------------- indra/newview/lloutfitslist.cpp | 51 ++++++++++++++++++++++++----------------- indra/newview/lloutfitslist.h | 6 +++++ 4 files changed, 43 insertions(+), 37 deletions(-) (limited to 'indra/newview/lloutfitslist.cpp') diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h index f769ab87d3..ad0d884e37 100644 --- a/indra/llcommon/llcommonutils.h +++ b/indra/llcommon/llcommonutils.h @@ -38,6 +38,11 @@ namespace LLCommonUtils * Computes difference between 'vnew' and 'vcur' vectors. * Items present in 'vnew' and missing in 'vcur' are treated as added and are copied into 'vadded' * Items missing in 'vnew' and present in 'vcur' are treated as removed and are copied into 'vremoved' + * + * @param vnew[in] - incoming IDs + * @param vcur[in] - current IDs + * @param vadded[out] - difference between incoming and current IDS - added IDs + * @param vremoved[out] - difference between incoming and current IDS - removed IDs */ LL_COMMON_API void computeDifference( const uuid_vec_t& vnew, diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 8ba47b5198..fd0b20281b 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -34,6 +34,7 @@ // common #include "lltrans.h" +#include "llcommonutils.h" #include "llavatarlist.h" #include "llagentdata.h" // for comparator @@ -404,7 +405,6 @@ void LLAvatarList::computeDifference( uuid_vec_t& vremoved) { uuid_vec_t vcur; - uuid_vec_t vnew = vnew_unsorted; // Convert LLSDs to LLUUIDs. { @@ -415,21 +415,7 @@ void LLAvatarList::computeDifference( vcur.push_back(vcur_values[i].asUUID()); } - std::sort(vcur.begin(), vcur.end()); - std::sort(vnew.begin(), vnew.end()); - - uuid_vec_t::iterator it; - size_t maxsize = llmax(vcur.size(), vnew.size()); - vadded.resize(maxsize); - vremoved.resize(maxsize); - - // what to remove - it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); - vremoved.erase(it, vremoved.end()); - - // what to add - it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); - vadded.erase(it, vadded.end()); + LLCommonUtils::computeDifference(vnew_unsorted, vcur, vadded, vremoved); } // Refresh shown time of our last interaction with all listed avatars. diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 1c627d452f..1215272685 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -36,6 +36,9 @@ // llcommon #include "llcommonutils.h" +// llcommon +#include "llcommonutils.h" + #include "llaccordionctrl.h" #include "llaccordionctrltab.h" #include "llinventoryfunctions.h" @@ -119,31 +122,11 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) LLInventoryModel::EXCLUDE_TRASH, is_category); - uuid_vec_t vnew; - - // Creating a vector of newly collected sub-categories UUIDs. - for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); - iter != cat_array.end(); - ++iter) - { - vnew.push_back((*iter)->getUUID()); - } - - uuid_vec_t vcur; - - // Creating a vector of currently displayed sub-categories UUIDs. - for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); - iter != mOutfitsMap.end(); - ++iter) - { - vcur.push_back((*iter).first); - } - uuid_vec_t vadded; uuid_vec_t vremoved; // Create added and removed items vectors. - LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); + computeDifference(cat_array, vadded, vremoved); // Handle added tabs. for (uuid_vec_t::const_iterator iter = vadded.begin(); @@ -274,4 +257,30 @@ LLXMLNodePtr LLOutfitsList::getAccordionTabXMLNode() return xmlNode; } +void LLOutfitsList::computeDifference( + const LLInventoryModel::cat_array_t& vcats, + uuid_vec_t& vadded, + uuid_vec_t& vremoved) +{ + uuid_vec_t vnew; + // Creating a vector of newly collected sub-categories UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); + iter != vcats.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + + uuid_vec_t vcur; + // Creating a vector of currently displayed sub-categories UUIDs. + for (outfits_map_t::const_iterator iter = mOutfitsMap.begin(); + iter != mOutfitsMap.end(); + iter++) + { + vcur.push_back((*iter).first); + } + + LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); +} + // EOF diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index de14c15415..2d103ea356 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -35,6 +35,7 @@ #include "llpanel.h" // newview +#include "llinventorymodel.h" #include "llinventoryobserver.h" class LLAccordionCtrl; @@ -79,6 +80,11 @@ private: */ LLXMLNodePtr getAccordionTabXMLNode(); + /** + * Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference + */ + void computeDifference(const LLInventoryModel::cat_array_t& vcats, uuid_vec_t& vadded, uuid_vec_t& vremoved); + LLInventoryCategoriesObserver* mCategoriesObserver; -- cgit v1.3