summaryrefslogtreecommitdiff
path: root/indra/newview/lloutfitslist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lloutfitslist.cpp')
-rw-r--r--indra/newview/lloutfitslist.cpp713
1 files changed, 128 insertions, 585 deletions
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 3eda077b87..77db280487 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -2,25 +2,30 @@
* @file lloutfitslist.cpp
* @brief List of agent's outfits for My Appearance side panel.
*
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * 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$
*/
@@ -39,7 +44,6 @@
#include "llinventorymodel.h"
#include "lllistcontextmenu.h"
#include "llnotificationsutil.h"
-#include "lloutfitobserver.h"
#include "llsidetray.h"
#include "lltransutil.h"
#include "llviewermenu.h"
@@ -49,193 +53,9 @@
static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y);
-static const LLOutfitTabNameComparator OUTFIT_TAB_NAME_COMPARATOR;
-
-/*virtual*/
-bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const
-{
- std::string name1 = tab1->getTitle();
- std::string name2 = tab2->getTitle();
-
- LLStringUtil::toUpper(name1);
- LLStringUtil::toUpper(name2);
-
- return name1 < name2;
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-class LLOutfitListGearMenu
-{
-public:
- LLOutfitListGearMenu(LLOutfitsList* olist)
- : mOutfitList(olist),
- mMenu(NULL)
- {
- llassert_always(mOutfitList);
-
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
-
- registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this));
- registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this));
- registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this));
- registrar.add("Gear.Delete", boost::bind(&LLOutfitListGearMenu::onDelete, this));
- registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2));
-
- registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this));
-
- enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitsList::isActionEnabled, mOutfitList, _2));
- enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2));
-
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
- "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- llassert(mMenu);
- }
-
- void show(LLView* spawning_view)
- {
- if (!mMenu) return;
-
- updateItemsVisibility();
- mMenu->buildDrawLabels();
- mMenu->updateParent(LLMenuGL::sMenuContainer);
- S32 menu_x = 0;
- S32 menu_y = spawning_view->getRect().getHeight() + mMenu->getRect().getHeight();
- LLMenuGL::showPopup(spawning_view, mMenu, menu_x, menu_y);
- }
-
- void updateItemsVisibility()
- {
- if (!mMenu) return;
-
- bool have_selection = getSelectedOutfitID().notNull();
- mMenu->setItemVisible("sepatator1", have_selection);
- mMenu->setItemVisible("sepatator2", have_selection);
- mMenu->arrangeAndClear(); // update menu height
- }
-
-private:
- const LLUUID& getSelectedOutfitID()
- {
- return mOutfitList->getSelectedOutfitUUID();
- }
-
- LLViewerInventoryCategory* getSelectedOutfit()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull())
- {
- return NULL;
- }
-
- LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
- return cat;
- }
-
- void onWear()
- {
- LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
- if (selected_outfit)
- {
- LLAppearanceMgr::instance().wearInventoryCategory(
- selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
- }
- }
-
- void onAdd()
- {
- const LLUUID& selected_id = getSelectedOutfitID();
-
- if (selected_id.notNull())
- {
- LLAppearanceMgr::getInstance()->addCategoryToCurrentOutfit(selected_id);
- }
- }
-
- void onTakeOff()
- {
- // Take off selected items if there are any
- if (mOutfitList->hasItemSelected())
- {
- uuid_vec_t selected_uuids;
- mOutfitList->getSelectedItemsUUIDs(selected_uuids);
-
- for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it)
- {
- if (get_is_item_worn(*it))
- {
- LLAppearanceMgr::instance().removeItemFromAvatar(*it);
- }
- }
- }
- else // or take off the whole selected outfit if no items specified.
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
- }
- }
- }
-
- void onRename()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
- }
- }
-
- void onDelete()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- remove_category(&gInventory, selected_outfit_id);
- }
- }
-
- void onCreate(const LLSD& data)
- {
- LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
- if (type == LLWearableType::WT_NONE)
- {
- llwarns << "Invalid wearable type" << llendl;
- return;
- }
-
- LLAgentWearables::createWearable(type, true);
- }
-
- bool onVisible(LLSD::String param)
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
- {
- return false;
- }
-
- // *TODO This condition leads to menu item behavior inconsistent with
- // "Wear" button behavior and should be modified or removed.
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
-
- if ("wear" == param)
- {
- return !is_worn;
- }
-
- return true;
- }
-
- LLOutfitsList* mOutfitList;
- LLMenuGL* mMenu;
-};
-
//////////////////////////////////////////////////////////////////////////
-class LLOutfitContextMenu : public LLListContextMenu
+class OutfitContextMenu : public LLListContextMenu
{
protected:
/* virtual */ LLContextMenu* createMenu()
@@ -254,48 +74,36 @@ protected:
registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id));
- enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
- enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
+ enable_registrar.add("Outfit.OnEnable", boost::bind(&OutfitContextMenu::onEnable, this, _2));
return createFromFile("menu_outfit_tab.xml");
}
- bool onEnable(LLSD::String param)
+ bool onEnable(const LLSD& data)
{
+ std::string param = data.asString();
LLUUID outfit_cat_id = mUUIDs.back();
+ bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
- if ("rename" == param)
+ if ("wear_replace" == param)
{
- return get_is_category_renameable(&gInventory, outfit_cat_id);
- }
- else if ("wear_replace" == param)
- {
- return LLAppearanceMgr::instance().getCanReplaceCOF(outfit_cat_id);
+ return !is_worn;
}
else if ("wear_add" == param)
{
- return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
+ return !is_worn;
}
else if ("take_off" == param)
{
- return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id);
+ return is_worn;
}
-
- return true;
- }
-
- bool onVisible(LLSD::String param)
- {
- LLUUID outfit_cat_id = mUUIDs.back();
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id;
-
- if ("edit" == param)
+ else if ("edit" == param)
{
return is_worn;
}
- else if ("wear_replace" == param)
+ else if ("rename" == param)
{
- return !is_worn;
+ return get_is_category_renameable(&gInventory, outfit_cat_id);
}
else if ("delete" == param)
{
@@ -326,21 +134,18 @@ protected:
static LLRegisterPanelClassWrapper<LLOutfitsList> t_outfits_list("outfits_list");
LLOutfitsList::LLOutfitsList()
- : LLPanelAppearanceTab()
+ : LLPanel()
, mAccordion(NULL)
, mListCommands(NULL)
, mIsInitialized(false)
- , mItemSelected(false)
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
- mGearMenu = new LLOutfitListGearMenu(this);
- mOutfitMenu = new LLOutfitContextMenu();
+ mOutfitMenu = new OutfitContextMenu();
}
LLOutfitsList::~LLOutfitsList()
{
- delete mGearMenu;
delete mOutfitMenu;
if (gInventory.containsObserver(mCategoriesObserver))
@@ -353,7 +158,6 @@ LLOutfitsList::~LLOutfitsList()
BOOL LLOutfitsList::postBuild()
{
mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");
- mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
return TRUE;
}
@@ -380,21 +184,12 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/)
mCategoriesObserver->addCategory(outfits,
boost::bind(&LLOutfitsList::refreshList, this, outfits));
- const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-
- // Start observing changes in Current Outfit category.
- mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
-
- LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this));
- LLOutfitObserver::instance().addBOFReplacedCallback(boost::bind(&LLOutfitsList::highlightBaseOutfit, this));
-
// 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);
- highlightBaseOutfit();
mIsInitialized = true;
}
@@ -447,12 +242,6 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
{
// Remove accordion tab if category could not be added to observer.
mAccordion->removeCollapsibleCtrl(tab);
-
- // kill removed tab
- if (tab != NULL)
- {
- tab->die();
- }
continue;
}
@@ -462,15 +251,12 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
tab->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onAccordionTabRightClick, this,
_1, _2, _3, cat_id));
+ tab->setDoubleClickCallback(boost::bind(&LLOutfitsList::onAccordionTabDoubleClick, this,
+ _1, _2, _3, cat_id));
+
// Setting tab focus callback to monitor currently selected outfit.
tab->setFocusReceivedCallback(boost::bind(&LLOutfitsList::changeOutfitSelection, this, list, cat_id));
- // Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875)
- tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id));
-
- // force showing list items that don't match current filter(EXT-7158)
- list->setForceShowingUnmatchedItems(true);
-
// Setting list commit callback to monitor currently selected wearable item.
list->setCommitCallback(boost::bind(&LLOutfitsList::onSelectionChange, this, _1));
@@ -488,7 +274,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
// If filter is currently applied we store the initial tab state and
// open it to show matched items if any.
- if (!sFilterSubString.empty())
+ if (!mFilterSubString.empty())
{
tab->notifyChildren(LLSD().with("action","store_state"));
tab->setDisplayChildren(true);
@@ -498,12 +284,12 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
// filter to the newly added list.
list->setForceRefresh(true);
- list->setFilterSubString(sFilterSubString);
+ list->setFilterSubString(mFilterSubString);
}
}
// Handle removed tabs.
- for (uuid_vec_t::const_iterator iter=vremoved.begin(); iter != vremoved.end(); ++iter)
+ 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())
@@ -515,20 +301,20 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
// 1. Remove outfit category from observer to stop monitoring its changes.
mCategoriesObserver->removeCategory(outfit_id);
- // 2. Remove the outfit from selection.
- deselectOutfit(outfit_id);
+ // 2. Remove selected lists map entry.
+ mSelectedListsMap.erase(outfit_id);
+
+ // 3. Reset currently selected outfit id if it is being removed.
+ if (outfit_id == mSelectedOutfitUUID)
+ {
+ mSelectedOutfitUUID = LLUUID();
+ }
- // 3. Remove category UUID to accordion tab mapping.
+ // 4. Remove category UUID to accordion tab mapping.
mOutfitsMap.erase(outfits_iter);
- // 4. Remove outfit tab from accordion.
+ // 5. Remove outfit tab from accordion.
mAccordion->removeCollapsibleCtrl(tab);
-
- // kill removed tab
- if (tab != NULL)
- {
- tab->die();
- }
}
}
@@ -542,28 +328,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
updateOutfitTab(*items_iter);
}
- mAccordion->sort();
-}
-
-void LLOutfitsList::highlightBaseOutfit()
-{
- // id of base outfit
- LLUUID base_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID();
- if (base_id != mHighlightedOutfitUUID)
- {
- if (mOutfitsMap[mHighlightedOutfitUUID])
- {
- mOutfitsMap[mHighlightedOutfitUUID]->setTitleFontStyle("NORMAL");
- mOutfitsMap[mHighlightedOutfitUUID]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
- }
-
- mHighlightedOutfitUUID = base_id;
- }
- if (mOutfitsMap[base_id])
- {
- mOutfitsMap[base_id]->setTitleFontStyle("BOLD");
- mOutfitsMap[base_id]->setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));
- }
+ mAccordion->arrange();
}
void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl)
@@ -598,128 +363,11 @@ void LLOutfitsList::performAction(std::string action)
}
}
-void LLOutfitsList::removeSelected()
-{
- if (mSelectedOutfitUUID.notNull())
- {
- remove_category(&gInventory, mSelectedOutfitUUID);
- }
-}
-
-void LLOutfitsList::setSelectedOutfitByUUID(const LLUUID& outfit_uuid)
-{
- for (outfits_map_t::iterator iter = mOutfitsMap.begin();
- iter != mOutfitsMap.end();
- ++iter)
- {
- if (outfit_uuid == iter->first)
- {
- LLAccordionCtrlTab* tab = iter->second;
- if (!tab) continue;
-
- LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
- if (!list) continue;
-
- tab->setFocus(TRUE);
- changeOutfitSelection(list, outfit_uuid);
-
- tab->setDisplayChildren(true);
- }
- }
-}
-
-// virtual
void LLOutfitsList::setFilterSubString(const std::string& string)
{
applyFilter(string);
- sFilterSubString = string;
-}
-
-// virtual
-bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
-{
- if (mSelectedOutfitUUID.isNull()) return false;
-
- const std::string command_name = userdata.asString();
- if (command_name == "delete")
- {
- return !mItemSelected && LLAppearanceMgr::instance().getCanRemoveOutfit(mSelectedOutfitUUID);
- }
- if (command_name == "rename")
- {
- return get_is_category_renameable(&gInventory, mSelectedOutfitUUID);
- }
- if (command_name == "save_outfit")
- {
- bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked();
- bool outfit_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
- // allow save only if outfit isn't locked and is dirty
- return !outfit_locked && outfit_dirty;
- }
- if (command_name == "wear")
- {
- if (gAgentWearables.isCOFChangeInProgress())
- {
- return false;
- }
-
- if (hasItemSelected())
- {
- return canWearSelected();
- }
-
- // outfit selected
- return LLAppearanceMgr::instance().getCanReplaceCOF(mSelectedOutfitUUID);
- }
- if (command_name == "take_off")
- {
- // Enable "Take Off" if any of selected items can be taken off
- // or the selected outfit contains items that can be taken off.
- return ( hasItemSelected() && canTakeOffSelected() )
- || ( !hasItemSelected() && LLAppearanceMgr::getCanRemoveFromCOF(mSelectedOutfitUUID) );
- }
-
- if (command_name == "wear_add")
- {
- // *TODO: do we ever get here?
- return LLAppearanceMgr::getCanAddToCOF(mSelectedOutfitUUID);
- }
-
- return false;
-}
-
-// virtual
-void LLOutfitsList::showGearMenu(LLView* spawning_view)
-{
- if (!mGearMenu) return;
- mGearMenu->show(spawning_view);
-}
-
-void LLOutfitsList::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
-{
- // Collect selected items from all selected lists.
- for (wearables_lists_map_t::const_iterator iter = mSelectedListsMap.begin();
- iter != mSelectedListsMap.end();
- ++iter)
- {
- uuid_vec_t uuids;
- (*iter).second->getSelectedUUIDs(uuids);
-
- S32 prev_size = selected_uuids.size();
- selected_uuids.resize(prev_size + uuids.size());
- std::copy(uuids.begin(), uuids.end(), selected_uuids.begin() + prev_size);
- }
-}
-
-boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb)
-{
- return mSelectionChangeSignal.connect(cb);
-}
-
-bool LLOutfitsList::hasItemSelected()
-{
- return mItemSelected;
+ mFilterSubString = string;
}
//////////////////////////////////////////////////////////////////////////
@@ -784,13 +432,6 @@ void LLOutfitsList::updateOutfitTab(const LLUUID& category_id)
}
}
-void LLOutfitsList::resetItemSelection(LLWearableItemsList* list, const LLUUID& category_id)
-{
- list->resetSelection();
- mItemSelected = false;
- setSelectedOutfitUUID(category_id);
-}
-
void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
{
MASK mask = gKeyboard->currentMask(TRUE);
@@ -814,41 +455,13 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI
mSelectedListsMap.clear();
}
- mItemSelected = list && (list->getSelectedItem() != NULL);
-
mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list));
- setSelectedOutfitUUID(category_id);
-}
-
-void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id)
-{
- mSelectionChangeSignal(mSelectedOutfitUUID = category_id);
-}
-
-void LLOutfitsList::deselectOutfit(const LLUUID& category_id)
-{
- // Remove selected lists map entry.
- mSelectedListsMap.erase(category_id);
-
- // Reset selection if the outfit is selected.
- if (category_id == mSelectedOutfitUUID)
- {
- setSelectedOutfitUUID(LLUUID::null);
- }
-}
-
-void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID& category_id)
-{
- // Try restoring outfit selection after filtering.
- if (mAccordion->getSelectedTab() == tab)
- {
- setSelectedOutfitUUID(category_id);
- }
+ mSelectedOutfitUUID = category_id;
}
void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
{
- if (!ctrl || sFilterSubString.empty())
+ if (!ctrl || mFilterSubString.empty())
return;
for (outfits_map_t::iterator
@@ -862,14 +475,31 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (list != ctrl) continue;
- applyFilterToTab(iter->first, tab, sFilterSubString);
+ std::string title = tab->getTitle();
+ LLStringUtil::toUpper(title);
+
+ std::string cur_filter = mFilterSubString;
+ LLStringUtil::toUpper(cur_filter);
+
+ if (std::string::npos == title.find(cur_filter))
+ {
+ // hide tab if its title doesn't pass filter
+ // and it has no visible items
+ tab->setVisible(list->size() != 0);
+
+ // remove title highlighting because it might
+ // have been previously highlighted by less restrictive filter
+ tab->setTitle(tab->getTitle());
+ }
+ else
+ {
+ tab->setTitle(tab->getTitle(), cur_filter);
+ }
}
}
void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
{
- mAccordion->setFilterSubString(new_filter_substring);
-
for (outfits_map_t::iterator
iter = mOutfitsMap.begin(),
iter_end = mOutfitsMap.end();
@@ -878,7 +508,7 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
LLAccordionCtrlTab* tab = iter->second;
if (!tab) continue;
- bool more_restrictive = sFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, sFilterSubString.size()).compare(sFilterSubString);
+ bool more_restrictive = mFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, mFilterSubString.size()).compare(mFilterSubString);
// Restore tab visibility in case of less restrictive filter
// to compare it with updated string if it was previously hidden.
@@ -893,7 +523,7 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
list->setFilterSubString(new_filter_substring);
}
- if(sFilterSubString.empty() && !new_filter_substring.empty())
+ if(mFilterSubString.empty() && !new_filter_substring.empty())
{
//store accordion tab state when filter is not empty
tab->notifyChildren(LLSD().with("action","store_state"));
@@ -901,7 +531,38 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
if (!new_filter_substring.empty())
{
- applyFilterToTab(iter->first, tab, new_filter_substring);
+ std::string title = tab->getTitle();
+ LLStringUtil::toUpper(title);
+
+ std::string cur_filter = new_filter_substring;
+ LLStringUtil::toUpper(cur_filter);
+
+ if (std::string::npos == title.find(cur_filter))
+ {
+ // hide tab if its title doesn't pass filter
+ // and it has no visible items
+ tab->setVisible(list->size() != 0);
+
+ // remove title highlighting because it might
+ // have been previously highlighted by less restrictive filter
+ tab->setTitle(tab->getTitle());
+ }
+ else
+ {
+ tab->setTitle(tab->getTitle(), cur_filter);
+ }
+
+ if (tab->getVisible())
+ {
+ // Open tab if it has passed the filter.
+ tab->setDisplayChildren(true);
+ }
+ else
+ {
+ // Set force refresh flag to refresh not visible list
+ // when some changes occur in it.
+ list->setForceRefresh(true);
+ }
}
else
{
@@ -910,99 +571,8 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
//restore accordion state after all those accodrion tab manipulations
tab->notifyChildren(LLSD().with("action","restore_state"));
-
- // Try restoring the tab selection.
- restoreOutfitSelection(tab, iter->first);
- }
- }
-
- mAccordion->arrange();
-}
-
-void LLOutfitsList::applyFilterToTab(
- const LLUUID& category_id,
- LLAccordionCtrlTab* tab,
- const std::string& filter_substring)
-{
- if (!tab) return;
- LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
- if (!list) return;
-
- std::string title = tab->getTitle();
- LLStringUtil::toUpper(title);
-
- std::string cur_filter = filter_substring;
- LLStringUtil::toUpper(cur_filter);
-
- tab->setTitle(tab->getTitle(), cur_filter);
-
- if (std::string::npos == title.find(cur_filter))
- {
- // hide tab if its title doesn't pass filter
- // and it has no visible items
- tab->setVisible(list->hasMatchedItems());
-
- // remove title highlighting because it might
- // have been previously highlighted by less restrictive filter
- tab->setTitle(tab->getTitle());
-
- // Remove the tab from selection.
- deselectOutfit(category_id);
- }
- else
- {
- // Try restoring the tab selection.
- restoreOutfitSelection(tab, category_id);
- }
-
- if (tab->getVisible())
- {
- // Open tab if it has passed the filter.
- tab->setDisplayChildren(true);
- }
- else
- {
- // Set force refresh flag to refresh not visible list
- // when some changes occur in it.
- list->setForceRefresh(true);
- }
-}
-
-bool LLOutfitsList::canTakeOffSelected()
-{
- uuid_vec_t selected_uuids;
- getSelectedItemsUUIDs(selected_uuids);
-
- LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false);
-
- for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if (!item) continue;
-
- if (is_worn(NULL, item)) return true;
- }
- return false;
-}
-
-bool LLOutfitsList::canWearSelected()
-{
- uuid_vec_t selected_items;
- getSelectedItemsUUIDs(selected_items);
-
- for (uuid_vec_t::const_iterator it = selected_items.begin(); it != selected_items.end(); ++it)
- {
- const LLUUID& id = *it;
-
- // Check whether the item is worn.
- if (!get_can_item_be_worn(id))
- {
- return false;
}
}
-
- // All selected items can be worn.
- return true;
}
void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
@@ -1023,17 +593,16 @@ void LLOutfitsList::onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const
}
}
-void LLOutfitsList::wearSelectedItems()
+void LLOutfitsList::onAccordionTabDoubleClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id)
{
- uuid_vec_t selected_uuids;
- getSelectedItemsUUIDs(selected_uuids);
-
- if(selected_uuids.empty())
+ LLAccordionCtrlTab* tab = dynamic_cast<LLAccordionCtrlTab*>(ctrl);
+ if(is_tab_header_clicked(tab, y) && cat_id.notNull())
{
- return;
- }
+ LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+ if (!cat) return;
- wear_multiple(selected_uuids, false);
+ LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, FALSE );
+ }
}
void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
@@ -1043,46 +612,20 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
uuid_vec_t selected_uuids;
- getSelectedItemsUUIDs(selected_uuids);
-
- LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y);
-}
-
-void LLOutfitsList::onCOFChanged()
-{
- LLInventoryModel::changed_items_t changed_linked_items;
-
- const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs();
- for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items.begin();
- iter != changed_items.end();
- ++iter)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*iter);
- if (item)
- {
- // From gInventory we get the UUIDs of new links added to COF
- // or removed from COF. These links UUIDs are not the same UUIDs
- // that we have in each wearable items list. So we collect base items
- // UUIDs to find all items or links that point to same base items in wearable
- // items lists and update their worn state there.
- changed_linked_items.insert(item->getLinkedUUID());
- }
- }
-
- for (outfits_map_t::iterator iter = mOutfitsMap.begin();
- iter != mOutfitsMap.end();
+ // Collect seleted items from all selected lists.
+ for (wearables_lists_map_t::iterator iter = mSelectedListsMap.begin();
+ iter != mSelectedListsMap.end();
++iter)
{
- LLAccordionCtrlTab* tab = iter->second;
- if (!tab) continue;
-
- LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
- if (!list) continue;
+ uuid_vec_t uuids;
+ (*iter).second->getSelectedUUIDs(uuids);
- // Every list updates the labels of changed items or
- // the links that point to these items.
- list->updateChangedItems(changed_linked_items);
+ S32 prev_size = selected_uuids.size();
+ selected_uuids.resize(prev_size + uuids.size());
+ std::copy(uuids.begin(), uuids.end(), selected_uuids.begin() + prev_size);
}
+
+ LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y);
}
bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)