summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llflatlistview.cpp8
-rw-r--r--indra/llui/llflatlistview.h5
-rw-r--r--indra/newview/CMakeLists.txt3
-rw-r--r--indra/newview/llagentwearables.cpp40
-rw-r--r--indra/newview/llappearancemgr.cpp20
-rw-r--r--indra/newview/llappearancemgr.h7
-rw-r--r--indra/newview/llinventorybridge.cpp64
-rw-r--r--indra/newview/llinventorybridge.h1
-rw-r--r--indra/newview/lloutfitslist.cpp246
-rw-r--r--indra/newview/lloutfitslist.h26
-rw-r--r--indra/newview/llpanelappearancetab.h24
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp594
-rw-r--r--indra/newview/llpaneloutfitsinventory.h56
-rw-r--r--indra/newview/llpanelwearing.cpp214
-rw-r--r--indra/newview/llpanelwearing.h81
-rw-r--r--indra/newview/llpreviewgesture.cpp1
-rw-r--r--indra/newview/llsidepanelappearance.cpp10
-rw-r--r--indra/newview/llwearableitemslist.cpp17
-rw-r--r--indra/newview/llwearableitemslist.h11
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_gear.xml12
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_tab.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_cof_wearables.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_wearable.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml38
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_appearance.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml3
27 files changed, 728 insertions, 776 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 2433c14315..c7463e581c 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -50,14 +50,21 @@ LLFlatListView::Params::Params()
allow_select("allow_select"),
multi_select("multi_select"),
keep_one_selected("keep_one_selected"),
+ keep_selection_visible_on_reshape("keep_selection_visible_on_reshape",false),
no_items_text("no_items_text")
{};
void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
{
+ S32 delta = height - getRect().getHeight();
LLScrollContainer::reshape(width, height, called_from_parent);
setItemsNoScrollWidth(width);
rearrangeItems();
+
+ if(delta!= 0 && mKeepSelectionVisibleOnReshape)
+ {
+ ensureSelectedVisible();
+ }
}
const LLRect& LLFlatListView::getItemsRect() const
@@ -380,6 +387,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
, mPrevNotifyParentRect(LLRect())
, mNoItemsCommentTextbox(NULL)
, mIsConsecutiveSelection(false)
+ , mKeepSelectionVisibleOnReshape(p.keep_selection_visible_on_reshape)
{
mBorderThickness = getBorderWidth();
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index f4e0426f15..0820a7ab67 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -105,6 +105,9 @@ public:
/** don't allow to deselect all selected items (for mouse events on items only) */
Optional<bool> keep_one_selected;
+ /** try to keep selection visible after reshape */
+ Optional<bool> keep_selection_visible_on_reshape;
+
/** padding between items */
Optional<U32> item_pad;
@@ -412,6 +415,8 @@ private:
bool mIsConsecutiveSelection;
+ bool mKeepSelectionVisibleOnReshape;
+
/** All pairs of the list */
pairs_list_t mItemPairs;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c1b2d680be..ce42cb6038 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -363,6 +363,7 @@ set(viewer_SOURCE_FILES
llpaneltopinfobar.cpp
llpanelvolume.cpp
llpanelvolumepulldown.cpp
+ llpanelwearing.cpp
llparcelselection.cpp
llparticipantlist.cpp
llpatchvertexarray.cpp
@@ -830,6 +831,7 @@ set(viewer_HEADER_FILES
lloutfitslist.h
lloutfitobserver.h
lloutputmonitorctrl.h
+ llpanelappearancetab.h
llpanelavatar.h
llpanelavatartag.h
llpanelblockedlist.h
@@ -883,6 +885,7 @@ set(viewer_HEADER_FILES
llpaneltopinfobar.h
llpanelvolume.h
llpanelvolumepulldown.h
+ llpanelwearing.h
llparcelselection.h
llparticipantlist.h
llpatchvertexarray.h
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 5728256dba..017fcf6e2b 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -48,7 +48,6 @@
#include "llmd5.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
-#include "llpaneloutfitsinventory.h"
#include "llsidepanelappearance.h"
#include "llsidetray.h"
#include "lltexlayer.h"
@@ -1232,45 +1231,6 @@ void LLAgentWearables::createStandardWearablesAllDone()
gAgentAvatarp->onFirstTEMessageReceived();
}
-
-class LLShowCreatedOutfit: public LLInventoryCallback
-{
-public:
- LLShowCreatedOutfit(LLUUID& folder_id):
- mFolderID(folder_id)
- {
- }
-
- virtual ~LLShowCreatedOutfit()
- {
- LLSD key;
- LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key);
- LLPanelOutfitsInventory *outfit_panel =
- dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
- // TODO: add handling "My Outfits" tab.
- if (outfit_panel && outfit_panel->isCOFPanelActive())
- {
- outfit_panel->getRootFolder()->clearSelection();
- outfit_panel->getRootFolder()->setSelectionByID(mFolderID, TRUE);
- }
- LLAccordionCtrlTab* tab_outfits = outfit_panel ? outfit_panel->findChild<LLAccordionCtrlTab>("tab_outfits") : 0;
- if (tab_outfits && !tab_outfits->getDisplayChildren())
- {
- tab_outfits->changeOpenClose(tab_outfits->getDisplayChildren());
- }
-
- LLAppearanceMgr::instance().updateIsDirty();
- LLAppearanceMgr::instance().updatePanelOutfitName("");
- }
-
- virtual void fire(const LLUUID&)
- {
- }
-
-private:
- LLUUID mFolderID;
-};
-
void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
{
LLUUID first_item_id = getWearableItemID((LLWearableType::EType)type, index);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 3947be49bb..597076503d 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -45,7 +45,7 @@
#include "llinventoryobserver.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
-#include "llpaneloutfitsinventory.h"
+#include "lloutfitslist.h"
#include "llselectmgr.h"
#include "llsidepanelappearance.h"
#include "llsidetray.h"
@@ -1697,9 +1697,10 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,
void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
{
- gAgentWearables.notifyLoadingStarted();
if(!category) return;
+ gAgentWearables.notifyLoadingStarted();
+
llinfos << "wearInventoryCategory( " << category->getName()
<< " )" << llendl;
@@ -2305,18 +2306,11 @@ public:
{
LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key);
}
- LLPanelOutfitsInventory *outfit_panel =
- dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
- if (outfit_panel)
- {
- outfit_panel->getRootFolder()->clearSelection();
- outfit_panel->getRootFolder()->setSelectionByID(mFolderID, TRUE);
- }
-
- LLAccordionCtrlTab* tab_outfits = outfit_panel ? outfit_panel->findChild<LLAccordionCtrlTab>("tab_outfits") : 0;
- if (tab_outfits && !tab_outfits->getDisplayChildren())
+ LLOutfitsList *outfits_list =
+ dynamic_cast<LLOutfitsList*>(LLSideTray::getInstance()->getPanel("outfitslist_tab"));
+ if (outfits_list)
{
- tab_outfits->changeOpenClose(tab_outfits->getDisplayChildren());
+ outfits_list->setSelectedOutfitByUUID(mFolderID);
}
LLAppearanceMgr::getInstance()->updateIsDirty();
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index ab4ff1bcfc..61779d5c0e 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -34,10 +34,12 @@
#define LL_LLAPPEARANCEMGR_H
#include "llsingleton.h"
+
+#include "llagentwearables.h"
+#include "llcallbacklist.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llviewerinventory.h"
-#include "llcallbacklist.h"
class LLWearable;
class LLWearableHoldingPattern;
@@ -360,6 +362,9 @@ public:
<< llendl;
//dec_busy_count();
gInventory.removeObserver(this);
+
+ // lets notify observers that loading is finished.
+ gAgentWearables.notifyLoadingFinished();
delete this;
return;
}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index afaeddaaeb..a5f24c55fe 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -72,7 +72,6 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llwearablelist.h"
-#include "llpaneloutfitsinventory.h"
typedef std::pair<LLUUID, LLUUID> two_uuids_t;
typedef std::list<two_uuids_t> two_uuids_list_t;
@@ -511,17 +510,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
const LLInventoryObject *obj = getInventoryObject();
- bool is_sidepanel = isInOutfitsSidePanel();
- if (is_sidepanel)
- {
- // Sidepanel includes restricted menu.
- if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
- {
- items.push_back(std::string("Remove Link"));
- }
- return;
- }
-
if (obj)
{
if (obj->getIsLinkType())
@@ -948,16 +936,6 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
}
}
-BOOL LLInvFVBridge::isInOutfitsSidePanel() const
-{
- LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLPanelOutfitsInventory *outfit_panel =
- dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
- if (!outfit_panel)
- return FALSE;
- return outfit_panel->isTabPanel(my_panel);
-}
-
BOOL LLInvFVBridge::canShare() const
{
const LLInventoryModel* model = getInventoryModel();
@@ -2430,17 +2408,8 @@ void LLFolderBridge::folderOptionsMenu()
const bool is_ensemble = (type == LLFolderType::FT_NONE ||
LLFolderType::lookupIsEnsembleType(type));
- // calling card related functionality for folders.
-
- const bool is_sidepanel = isInOutfitsSidePanel();
- if (is_sidepanel)
- {
- mItems.push_back("Rename");
- addDeleteContextMenuOptions(mItems, disabled_items);
- }
-
// Only enable calling-card related options for non-system folders.
- if (!is_sidepanel && !is_system_folder)
+ if (!is_system_folder)
{
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
@@ -2469,10 +2438,7 @@ void LLFolderBridge::folderOptionsMenu()
checkFolderForContentsOfType(model, is_object) ||
checkFolderForContentsOfType(model, is_gesture) )
{
- if (!is_sidepanel)
- {
- mItems.push_back(std::string("Folder Wearables Separator"));
- }
+ mItems.push_back(std::string("Folder Wearables Separator"));
// Only enable add/replace outfit for non-system folders.
if (!is_system_folder)
@@ -3763,13 +3729,6 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
disabled_items.push_back(std::string("Share"));
}
- bool is_sidepanel = isInOutfitsSidePanel();
-
- if (!is_sidepanel)
- {
- addOpenRightClickMenuOption(items);
- items.push_back(std::string("Properties"));
- }
getClipboardEntries(true, items, disabled_items, flags);
@@ -4071,12 +4030,8 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
disabled_items.push_back(std::string("Share"));
}
- bool is_sidepanel = isInOutfitsSidePanel();
- if (!is_sidepanel)
- {
- items.push_back(std::string("Properties"));
- }
+ items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
@@ -4431,24 +4386,17 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
disabled_items.push_back(std::string("Share"));
}
- bool is_sidepanel = isInOutfitsSidePanel();
- if (can_open && !is_sidepanel)
+ if (can_open)
{
addOpenRightClickMenuOption(items);
}
- if (!is_sidepanel)
- {
- items.push_back(std::string("Properties"));
- }
+ items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
- if (!is_sidepanel)
- {
- items.push_back(std::string("Wearable Separator"));
- }
+ items.push_back(std::string("Wearable Separator"));
items.push_back(std::string("Wearable Edit"));
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 64d0f8d254..97e87c2f3b 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -74,7 +74,6 @@ public:
U32 flags = 0x00);
virtual ~LLInvFVBridge() {}
- BOOL isInOutfitsSidePanel() const; // allow context menus to be customized for side panel
BOOL canShare() const;
//--------------------------------------------------------------------
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 6542afc366..b8489d450b 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -70,7 +70,148 @@ bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LL
//////////////////////////////////////////////////////////////////////////
-class OutfitContextMenu : public LLListContextMenu
+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));
+
+ 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 onTakeOff()
+ {
+ 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
{
protected:
/* virtual */ LLContextMenu* createMenu()
@@ -89,8 +230,8 @@ 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(&OutfitContextMenu::onEnable, this, _2));
- enable_registrar.add("Outfit.OnVisible", boost::bind(&OutfitContextMenu::onVisible, this, _2));
+ enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
+ enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
return createFromFile("menu_outfit_tab.xml");
}
@@ -103,8 +244,13 @@ protected:
{
return get_is_category_renameable(&gInventory, outfit_cat_id);
}
+ else if ("wear_replace" == param)
+ {
+ return !gAgentWearables.isCOFChangeInProgress();
+ }
else if ("wear_add" == param)
{
+ if (gAgentWearables.isCOFChangeInProgress()) return false;
return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
}
else if ("take_off" == param)
@@ -157,7 +303,7 @@ protected:
static LLRegisterPanelClassWrapper<LLOutfitsList> t_outfits_list("outfits_list");
LLOutfitsList::LLOutfitsList()
- : LLPanel()
+ : LLPanelAppearanceTab()
, mAccordion(NULL)
, mListCommands(NULL)
, mIsInitialized(false)
@@ -165,11 +311,13 @@ LLOutfitsList::LLOutfitsList()
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
- mOutfitMenu = new OutfitContextMenu();
+ mGearMenu = new LLOutfitListGearMenu(this);
+ mOutfitMenu = new LLOutfitContextMenu();
}
LLOutfitsList::~LLOutfitsList()
{
+ delete mGearMenu;
delete mOutfitMenu;
if (gInventory.containsObserver(mCategoriesObserver))
@@ -308,7 +456,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 (!mFilterSubString.empty())
+ if (!sFilterSubString.empty())
{
tab->notifyChildren(LLSD().with("action","store_state"));
tab->setDisplayChildren(true);
@@ -318,7 +466,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
// filter to the newly added list.
list->setForceRefresh(true);
- list->setFilterSubString(mFilterSubString);
+ list->setFilterSubString(sFilterSubString);
}
}
@@ -410,14 +558,84 @@ 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);
- mFilterSubString = 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")
+ {
+ return !gAgentWearables.isCOFChangeInProgress();
+ }
+ if (command_name == "take_off")
+ {
+ return LLAppearanceMgr::getInstance()->getBaseOutfitUUID() == mSelectedOutfitUUID;
+ }
+ return false;
+}
+
+// virtual
+void LLOutfitsList::showGearMenu(LLView* spawning_view)
+{
+ if (!mGearMenu) return;
+ mGearMenu->show(spawning_view);
}
-boost::signals2::connection LLOutfitsList::addSelectionChangeCallback(selection_change_callback_t cb)
+boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb)
{
return mSelectionChangeSignal.connect(cb);
}
@@ -553,7 +771,7 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID
void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
{
- if (!ctrl || mFilterSubString.empty())
+ if (!ctrl || sFilterSubString.empty())
return;
for (outfits_map_t::iterator
@@ -567,7 +785,7 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (list != ctrl) continue;
- applyFilterToTab(iter->first, tab, mFilterSubString);
+ applyFilterToTab(iter->first, tab, sFilterSubString);
}
}
@@ -583,7 +801,7 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
LLAccordionCtrlTab* tab = iter->second;
if (!tab) continue;
- bool more_restrictive = mFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, mFilterSubString.size()).compare(mFilterSubString);
+ bool more_restrictive = sFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, sFilterSubString.size()).compare(sFilterSubString);
// Restore tab visibility in case of less restrictive filter
// to compare it with updated string if it was previously hidden.
@@ -598,7 +816,7 @@ void LLOutfitsList::applyFilter(const std::string& new_filter_substring)
list->setFilterSubString(new_filter_substring);
}
- if(mFilterSubString.empty() && !new_filter_substring.empty())
+ if(sFilterSubString.empty() && !new_filter_substring.empty())
{
//store accordion tab state when filter is not empty
tab->notifyChildren(LLSD().with("action","store_state"));
@@ -696,7 +914,7 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
uuid_vec_t selected_uuids;
- // Collect seleted items from all selected lists.
+ // Collect selected items from all selected lists.
for (wearables_lists_map_t::iterator iter = mSelectedListsMap.begin();
iter != mSelectedListsMap.end();
++iter)
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index a6b9a66836..d207624792 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -37,12 +37,15 @@
// newview
#include "llinventorymodel.h"
-#include "llinventoryobserver.h"
+#include "llpanelappearancetab.h"
class LLAccordionCtrlTab;
+class LLInventoryCategoriesObserver;
+class LLOutfitListGearMenu;
class LLWearableItemsList;
class LLListContextMenu;
+
/**
* @class LLOutfitTabNameComparator
*
@@ -66,9 +69,9 @@ public:
* which displays each outfit in an accordion tab with a flat list
* of items inside it.
*
- * Starts fetching nevessary inventory content on first openning.
+ * Starts fetching necessary inventory content on first opening.
*/
-class LLOutfitsList : public LLPanel
+class LLOutfitsList : public LLPanelAppearanceTab
{
public:
typedef boost::function<void (const LLUUID&)> selection_change_callback_t;
@@ -88,11 +91,19 @@ public:
void performAction(std::string action);
- void setFilterSubString(const std::string& string);
+ void removeSelected();
+
+ void setSelectedOutfitByUUID(const LLUUID& outfit_uuid);
+
+ /*virtual*/ void setFilterSubString(const std::string& string);
+
+ /*virtual*/ bool isActionEnabled(const LLSD& userdata);
+
+ /*virtual*/ void showGearMenu(LLView* spawning_view);
const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
- boost::signals2::connection addSelectionChangeCallback(selection_change_callback_t cb);
+ boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
/**
* Returns true if there is a selection inside currently selected outfit
@@ -184,13 +195,12 @@ private:
LLUUID mHighlightedOutfitUUID;
selection_change_signal_t mSelectionChangeSignal;
- std::string mFilterSubString;
-
typedef std::map<LLUUID, LLAccordionCtrlTab*> outfits_map_t;
typedef outfits_map_t::value_type outfits_map_value_t;
outfits_map_t mOutfitsMap;
- LLListContextMenu* mOutfitMenu;
+ LLOutfitListGearMenu* mGearMenu;
+ LLListContextMenu* mOutfitMenu;
bool mIsInitialized;
/**
diff --git a/indra/newview/llpanelappearancetab.h b/indra/newview/llpanelappearancetab.h
index c2f8dbd074..f1901a63a4 100644
--- a/indra/newview/llpanelappearancetab.h
+++ b/indra/newview/llpanelappearancetab.h
@@ -1,6 +1,6 @@
/**
- * @file llpanelplacestab.h
- * @brief Tabs interface for Side Bar "Places" panel
+ * @file llpanelappearancetab.h
+ * @brief Tabs interface for Side Bar "My Appearance" panel
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
@@ -34,28 +34,22 @@
#include "llpanel.h"
-#include "llpanelappearance.h"
-
class LLPanelAppearanceTab : public LLPanel
{
public:
- LLPanelAppearanceTab(LLPanelAppearance *parent) :
- LLPanel(),
- mParent(parent)
- {}
+ LLPanelAppearanceTab() : LLPanel() {}
virtual ~LLPanelAppearanceTab() {}
- virtual void onSearchEdit(const std::string& string) = 0;
- virtual void updateVerbs() = 0; // Updates buttons at the bottom of Appearance panel
- virtual void onWear() = 0;
- virtual void onEdit() = 0;
- virtual void onNew() = 0;
+ virtual void setFilterSubString(const std::string& string) = 0;
+
+ virtual bool isActionEnabled(const LLSD& userdata) = 0;
- bool isTabVisible(); // Check if parent TabContainer is visible.
+ virtual void showGearMenu(LLView* spawning_view) = 0;
+ static const std::string& getFilterSubString() { return sFilterSubString; }
protected:
- LLPanelAppearance* mParent;
+ static std::string sFilterSubString;
};
#endif //LL_LLPANELAPPEARANCETAB_H
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index d382c77430..2f1cad8a75 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -33,216 +33,32 @@
#include "llpaneloutfitsinventory.h"
-#include "llagent.h"
-#include "llagentwearables.h"
-#include "llappearancemgr.h"
+#include "llnotificationsutil.h"
+#include "lltabcontainer.h"
-#include "llbutton.h"
-#include "llfloaterreg.h"
-#include "llfloaterworldmap.h"
-#include "llfloaterinventory.h"
-#include "llfoldervieweventlistener.h"
-#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
-#include "llinventorypanel.h"
-#include "lllandmark.h"
-#include "lllineeditor.h"
-#include "llmodaldialog.h"
-#include "llnotificationsutil.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
#include "lloutfitobserver.h"
#include "lloutfitslist.h"
+#include "llpanelwearing.h"
#include "llsaveoutfitcombobtn.h"
#include "llsidepanelappearance.h"
#include "llsidetray.h"
-#include "lltabcontainer.h"
#include "llviewerfoldertype.h"
-#include "llviewerjointattachment.h"
-#include "llvoavatarself.h"
-
-// List Commands
-#include "lldndbutton.h"
-#include "llmenugl.h"
-#include "llviewermenu.h"
-
-#include "llviewercontrol.h"
static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
static const std::string COF_TAB_NAME = "cof_tab";
static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
-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));
-
- enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _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);
- }
-
- LLMenuGL* getMenu() { return 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 onTakeOff()
- {
- 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 onEnable(LLSD::String param)
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
- {
- return false;
- }
-
- if ("rename" == param)
- {
- return get_is_category_renameable(&gInventory, selected_outfit_id);
- }
- else if ("delete" == param)
- {
- return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id);
- }
- else if ("take_off" == param)
- {
- return LLAppearanceMgr::getCanRemoveFromCOF(selected_outfit_id);
- }
-
- return 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;
- }
-
- bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
-
- if ("wear" == param)
- {
- return !is_worn;
- }
-
- return true;
- }
-
- LLOutfitsList* mOutfitList;
- LLMenuGL* mMenu;
-};
-
LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mMyOutfitsPanel(NULL),
mCurrentOutfitPanel(NULL),
- mGearMenu(NULL),
+ mActivePanel(NULL),
mInitialized(false)
{
- mSavedFolderState = new LLSaveFolderState();
- mSavedFolderState->setApply(FALSE);
gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this));
gAgentWearables.addLoadingStartedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoading, this));
@@ -254,8 +70,6 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
{
- delete mGearMenu;
- delete mSavedFolderState;
}
// virtual
@@ -297,7 +111,8 @@ void LLPanelOutfitsInventory::onOpen(const LLSD& key)
// and update verbs.
onTabChange();
- // Auto open the first outfit newly created so new users can see sample outfit contents
+ // *TODO: Auto open the first outfit newly created so new users can see sample outfit contents
+ /*
static bool should_open_outfit = true;
if (should_open_outfit && gAgent.isFirstLogin())
{
@@ -317,6 +132,7 @@ void LLPanelOutfitsInventory::onOpen(const LLSD& key)
}
}
should_open_outfit = false;
+ */
}
void LLPanelOutfitsInventory::updateVerbs()
@@ -330,93 +146,30 @@ void LLPanelOutfitsInventory::updateVerbs()
// virtual
void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
{
- mFilterSubString = string;
+ if (!mActivePanel) return;
- // TODO: add handling "My Outfits" tab.
- if (!isCOFPanelActive())
- {
- mMyOutfitsPanel->setFilterSubString(string);
- return;
- }
+ mFilterSubString = string;
if (string == "")
{
- getActivePanel()->setFilterSubString(LLStringUtil::null);
-
- // re-open folders that were initially open
- mSavedFolderState->setApply(TRUE);
- getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
- LLOpenFoldersWithSelection opener;
- getRootFolder()->applyFunctorRecursively(opener);
- getRootFolder()->scrollToShowSelection();
+ mActivePanel->setFilterSubString(LLStringUtil::null);
}
LLInventoryModelBackgroundFetch::instance().start();
- if (getActivePanel()->getFilterSubString().empty() && string.empty())
+ if (mActivePanel->getFilterSubString().empty() && string.empty())
{
// current filter and new filter empty, do nothing
return;
}
- // save current folder open state if no filter currently applied
- if (getRootFolder()->getFilterSubString().empty())
- {
- mSavedFolderState->setApply(FALSE);
- getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
- }
-
// set new filter string
- getActivePanel()->setFilterSubString(string);
+ mActivePanel->setFilterSubString(string);
}
void LLPanelOutfitsInventory::onWearButtonClick()
{
- // TODO: Remove if/else, add common interface
- // for "My Outfits" and "Wearing" tabs.
- if (!isCOFPanelActive())
- {
- mMyOutfitsPanel->performAction("replaceoutfit");
- }
- else
- {
- LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
- if (listenerp)
- {
- listenerp->performAction(NULL, "replaceoutfit");
- }
- }
-}
-
-void LLPanelOutfitsInventory::onAdd()
-{
- // TODO: Remove if/else, add common interface
- // for "My Outfits" and "Wearing" tabs.
- if (!isCOFPanelActive())
- {
- mMyOutfitsPanel->performAction("addtooutfit");
- }
- else
- {
- LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
- if (listenerp)
- {
- listenerp->performAction(NULL, "addtooutfit");
- }
- }
-}
-
-void LLPanelOutfitsInventory::onRemove()
-{
- LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
- if (listenerp)
- {
- listenerp->performAction(NULL, "removefromoutfit");
- }
-}
-
-void LLPanelOutfitsInventory::onEdit()
-{
+ mMyOutfitsPanel->performAction("replaceoutfit");
}
bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD& response)
@@ -446,8 +199,6 @@ bool LLPanelOutfitsInventory::onSaveCommit(const LLSD& notification, const LLSD&
return false;
}
-
-
void LLPanelOutfitsInventory::onSave()
{
std::string outfit_name;
@@ -475,57 +226,6 @@ void LLPanelOutfitsInventory::onSave()
}*/
}
-void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
-{
- updateVerbs();
-
- // TODO: add handling "My Outfits" tab.
- if (!isCOFPanelActive())
- return;
-
- if (getRootFolder()->needsAutoRename() && items.size())
- {
- getRootFolder()->startRenamingSelectedItem();
- getRootFolder()->setNeedsAutoRename(FALSE);
- }
-}
-
-LLFolderViewEventListener *LLPanelOutfitsInventory::getCorrectListenerForAction()
-{
- // TODO: add handling "My Outfits" tab.
- if (!isCOFPanelActive())
- return NULL;
-
- LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem();
- if (!current_item)
- return NULL;
-
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (getIsCorrectType(listenerp))
- {
- return listenerp;
- }
- return NULL;
-}
-
-bool LLPanelOutfitsInventory::getIsCorrectType(const LLFolderViewEventListener *listenerp) const
-{
- if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
- {
- LLViewerInventoryCategory *cat = gInventory.getCategory(listenerp->getUUID());
- if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
- {
- return true;
- }
- }
- return false;
-}
-
-LLFolderView *LLPanelOutfitsInventory::getRootFolder()
-{
- return getActivePanel()->getRootFolder();
-}
-
//static
LLPanelOutfitsInventory* LLPanelOutfitsInventory::findInstance()
{
@@ -542,21 +242,12 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::showGearMenu, this));
mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
-
- LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
- trash_btn->setDragAndDropHandler(boost::bind(&LLPanelOutfitsInventory::handleDragAndDropToTrash, this
- , _4 // BOOL drop
- , _5 // EDragAndDropType cargo_type
- , _7 // EAcceptance* accept
- ));
-
- mGearMenu = new LLOutfitListGearMenu(mMyOutfitsPanel);
}
void LLPanelOutfitsInventory::updateListCommands()
{
bool trash_enabled = isActionEnabled("delete");
- bool wear_enabled = !gAgentWearables.isCOFChangeInProgress() && isActionEnabled("wear");
+ bool wear_enabled = isActionEnabled("wear");
bool wear_visible = !isCOFPanelActive();
bool make_outfit_enabled = isActionEnabled("save_outfit");
@@ -568,269 +259,58 @@ void LLPanelOutfitsInventory::updateListCommands()
void LLPanelOutfitsInventory::showGearMenu()
{
- if (!mGearMenu) return;
+ if (!mActivePanel) return;
LLView* spawning_view = getChild<LLView>("options_gear_btn");
- mGearMenu->show(spawning_view);
+ mActivePanel->showGearMenu(spawning_view);
}
void LLPanelOutfitsInventory::onTrashButtonClick()
{
- onClipboardAction("delete");
-}
+ mMyOutfitsPanel->removeSelected();
-void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata)
-{
- std::string command_name = userdata.asString();
- if (isCOFPanelActive())
- {
- getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
- }
- else // "My Outfits" tab active
- {
- if (command_name == "delete")
- {
- const LLUUID& selected_outfit_id = mMyOutfitsPanel->getSelectedOutfitUUID();
- if (selected_outfit_id.notNull())
- {
- remove_category(&gInventory, selected_outfit_id);
- }
- }
- else
- {
- llwarns << "Unrecognized action" << llendl;
- }
- }
- updateListCommands();
- updateVerbs();
+ updateListCommands();
+ updateVerbs();
}
-void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata)
+bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
{
- if (!isActionEnabled(userdata))
- return;
-
- const std::string command_name = userdata.asString();
- if (command_name == "new")
- {
- onSave();
- }
- if (command_name == "edit")
- {
- onEdit();
- }
- if (command_name == "wear")
- {
- onWearButtonClick();
- }
- // Note: This option has been removed from the gear menu.
- if (command_name == "add")
- {
- onAdd();
- }
- if (command_name == "remove")
- {
- onRemove();
- }
- if (command_name == "rename")
- {
- onClipboardAction("rename");
- }
- if (command_name == "remove_link")
- {
- onClipboardAction("delete");
- }
- if (command_name == "delete")
- {
- onClipboardAction("delete");
- }
- updateListCommands();
- updateVerbs();
+ return mActivePanel && mActivePanel->isActionEnabled(userdata);
}
-
-BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
-{
- const std::string command_name = userdata.asString();
- if (command_name == "delete" || command_name == "remove")
- {
- BOOL can_delete = FALSE;
-
- if (isCOFPanelActive())
- {
- LLFolderView* root = getActivePanel()->getRootFolder();
- if (root)
- {
- std::set<LLUUID> selection_set = root->getSelectionList();
- can_delete = (selection_set.size() > 0);
- for (std::set<LLUUID>::iterator iter = selection_set.begin();
- iter != selection_set.end();
- ++iter)
- {
- const LLUUID &item_id = (*iter);
- LLFolderViewItem *item = root->getItemByID(item_id);
- can_delete &= item->getListener()->isItemRemovable();
- }
- }
- }
- else // "My Outfits" tab active
- {
- const LLUUID& selected_outfit = mMyOutfitsPanel->getSelectedOutfitUUID();
- // first condition prevents trash btn from enabling when items are selected inside outfit (EXT-7847)
- can_delete = !mMyOutfitsPanel->hasItemSelected() && LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit);
- }
-
- return can_delete;
- }
- if (command_name == "remove_link")
- {
- BOOL can_delete = FALSE;
- LLFolderView* root = getActivePanel()->getRootFolder();
- if (root)
- {
- std::set<LLUUID> selection_set = root->getSelectionList();
- can_delete = (selection_set.size() > 0);
- for (std::set<LLUUID>::iterator iter = selection_set.begin();
- iter != selection_set.end();
- ++iter)
- {
- const LLUUID &item_id = (*iter);
- LLViewerInventoryItem *item = gInventory.getItem(item_id);
- if (!item || !item->getIsLinkType())
- return FALSE;
- }
- return can_delete;
- }
- return FALSE;
- }
- if (command_name == "rename" ||
- command_name == "delete_outfit")
- {
- return (getCorrectListenerForAction() != NULL) && hasItemsSelected();
- }
-
- if (command_name == "wear")
- {
- if (isCOFPanelActive())
- {
- return FALSE;
- }
- return hasItemsSelected();
- }
- 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 == "edit" ||
- command_name == "add"
- )
- {
- return (getCorrectListenerForAction() != NULL);
- }
- return TRUE;
-}
-
-bool LLPanelOutfitsInventory::hasItemsSelected()
-{
- bool has_items_selected = false;
-
- if (isCOFPanelActive())
- {
- LLFolderView* root = getActivePanel()->getRootFolder();
- if (root)
- {
- std::set<LLUUID> selection_set = root->getSelectionList();
- has_items_selected = (selection_set.size() > 0);
- }
- }
- else // My Outfits Tab is active
- {
- has_items_selected = mMyOutfitsPanel->getSelectedOutfitUUID().notNull();
- }
- return has_items_selected;
-}
-
-bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
-{
- *accept = ACCEPT_NO;
-
- const bool is_enabled = isActionEnabled("delete");
- if (is_enabled) *accept = ACCEPT_YES_MULTI;
-
- if (is_enabled && drop)
- {
- onClipboardAction("delete");
- }
- return true;
-}
-
-// List Commands //
-////////////////////////////////////////////////////////////////////////////////
+// List Commands //
+//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
-// Tab panels //
+// Tab panels //
void LLPanelOutfitsInventory::initTabPanels()
{
- mCurrentOutfitPanel = getChild<LLInventoryPanel>(COF_TAB_NAME);
- mCurrentOutfitPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mCurrentOutfitPanel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, mCurrentOutfitPanel, _1, _2));
+ mCurrentOutfitPanel = getChild<LLPanelWearing>(COF_TAB_NAME);
+ mCurrentOutfitPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
mMyOutfitsPanel = getChild<LLOutfitsList>(OUTFITS_TAB_NAME);
- mMyOutfitsPanel->addSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
+ mMyOutfitsPanel->setSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));
mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs");
mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this));
}
-void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
-{
- if (user_action && items.size() > 0)
- {
- // TODO: add handling "My Outfits" tab.
- if (isCOFPanelActive())
- {
- onSelectionChange(items, user_action);
- }
- else
- {
- mCurrentOutfitPanel->getRootFolder()->clearSelection();
- }
- }
-}
-
void LLPanelOutfitsInventory::onTabChange()
{
- // TODO: add handling "My Outfits" tab.
- if (isCOFPanelActive())
- {
- mCurrentOutfitPanel->setFilterSubString(mFilterSubString);
- }
- else
- {
- mMyOutfitsPanel->setFilterSubString(mFilterSubString);
- mMyOutfitsPanel->onOpen(LLSD());
- }
+ mActivePanel = dynamic_cast<LLPanelAppearanceTab*>(mAppearanceTabs->getCurrentPanel());
+ if (!mActivePanel) return;
+
+ mActivePanel->setFilterSubString(mFilterSubString);
+ mActivePanel->onOpen(LLSD());
updateVerbs();
}
-BOOL LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) const
+bool LLPanelOutfitsInventory::isCOFPanelActive() const
{
- // TODO: add handling "My Outfits" tab.
- if (mCurrentOutfitPanel == panel)
- {
- return TRUE;
- }
- return FALSE;
-}
+ if (!mActivePanel) return false;
-BOOL LLPanelOutfitsInventory::isCOFPanelActive() const
-{
- return (childGetVisibleTab("appearance_tabs")->getName() == COF_TAB_NAME);
+ return mActivePanel->getName() == COF_TAB_NAME;
}
void LLPanelOutfitsInventory::setWearablesLoading(bool val)
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index eabfda7f8c..a50e047140 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -34,20 +34,15 @@
#define LL_LLPANELOUTFITSINVENTORY_H
#include "llpanel.h"
-#include "llinventoryobserver.h"
-class LLFolderView;
-class LLFolderViewItem;
-class LLFolderViewEventListener;
-class LLInventoryPanel;
class LLOutfitsList;
-class LLSaveFolderState;
-class LLButton;
+class LLOutfitListGearMenu;
+class LLPanelAppearanceTab;
+class LLPanelWearing;
class LLMenuGL;
class LLSidepanelAppearance;
class LLTabContainer;
class LLSaveOutfitComboBtn;
-class LLOutfitListGearMenu;
class LLPanelOutfitsInventory : public LLPanel
{
@@ -60,55 +55,36 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
void onSearchEdit(const std::string& string);
- void onAdd();
- void onRemove();
- void onEdit();
void onSave();
bool onSaveCommit(const LLSD& notification, const LLSD& response);
- void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
-
- // If a compatible listener type is selected, then return a pointer to that.
- // Otherwise, return NULL.
- LLFolderViewEventListener* getCorrectListenerForAction();
-
- LLFolderView* getRootFolder();
static LLSidepanelAppearance* getAppearanceSP();
static LLPanelOutfitsInventory* findInstance();
protected:
void updateVerbs();
- bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const;
private:
- LLSaveFolderState* mSavedFolderState;
LLTabContainer* mAppearanceTabs;
std::string mFilterSubString;
std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
-public:
- //////////////////////////////////////////////////////////////////////////////////
- // tab panels
- // TODO: change getActivePanel() to return the active tab instead of returning
- // a pointer to "Wearing" inventory panel.
- LLInventoryPanel* getActivePanel() { return mCurrentOutfitPanel; }
-
- BOOL isTabPanel(LLInventoryPanel *panel) const;
- BOOL isCOFPanelActive() const;
+ //////////////////////////////////////////////////////////////////////////////////
+ // tab panels //
protected:
void initTabPanels();
- void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
void onTabChange();
+ bool isCOFPanelActive() const;
private:
+ LLPanelAppearanceTab* mActivePanel;
LLOutfitsList* mMyOutfitsPanel;
- LLInventoryPanel* mCurrentOutfitPanel;
+ LLPanelWearing* mCurrentOutfitPanel;
- // tab panels //
- ////////////////////////////////////////////////////////////////////////////////
-
+ // tab panels //
+ //////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// List Commands //
@@ -118,21 +94,15 @@ protected:
void onWearButtonClick();
void showGearMenu();
void onTrashButtonClick();
- void onClipboardAction(const LLSD& userdata);
- BOOL isActionEnabled(const LLSD& command_name);
- void onCustomAction(const LLSD& command_name);
- bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
- bool hasItemsSelected();
+ bool isActionEnabled(const LLSD& userdata);
void setWearablesLoading(bool val);
void onWearablesLoaded();
void onWearablesLoading();
private:
LLPanel* mListCommands;
- LLOutfitListGearMenu* mGearMenu;
LLMenuGL* mMenuAdd;
- // List Commands //
- ////////////////////////////////////////////////////////////////////////////////
- ///
+ // List Commands //
+ //////////////////////////////////////////////////////////////////////////////////
bool mInitialized;
};
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
new file mode 100644
index 0000000000..b8852890ad
--- /dev/null
+++ b/indra/newview/llpanelwearing.cpp
@@ -0,0 +1,214 @@
+/**
+ * @file llpanelwearing.cpp
+ * @brief List of agent's worn items.
+ *
+ * $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 "llpanelwearing.h"
+
+#include "llappearancemgr.h"
+#include "llinventorymodel.h"
+#include "llinventoryobserver.h"
+#include "llsidetray.h"
+#include "llviewermenu.h"
+#include "llwearableitemslist.h"
+
+// Context menu and Gear menu helper.
+static void edit_outfit()
+{
+ LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit"));
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+class LLWearingGearMenu
+{
+public:
+ LLWearingGearMenu()
+ : mMenu(NULL)
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("Gear.Edit", boost::bind(&edit_outfit));
+
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ "menu_wearing_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ llassert(mMenu);
+ }
+
+ void show(LLView* spawning_view)
+ {
+ if (!mMenu) return;
+
+ 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);
+ }
+
+private:
+ LLMenuGL* mMenu;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+class LLWearingContextMenu : public LLListContextMenu
+{
+protected:
+ /* virtual */ LLContextMenu* createMenu()
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("Wearing.Edit", boost::bind(&edit_outfit));
+
+ return createFromFile("menu_wearing_tab.xml");
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null;
+
+static LLRegisterPanelClassWrapper<LLPanelWearing> t_panel_wearing("panel_wearing");
+
+LLPanelWearing::LLPanelWearing()
+ : LLPanelAppearanceTab()
+ , mCOFItemsList(NULL)
+ , mIsInitialized(false)
+{
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+
+ mGearMenu = new LLWearingGearMenu();
+ mContextMenu = new LLWearingContextMenu();
+}
+
+LLPanelWearing::~LLPanelWearing()
+{
+ delete mGearMenu;
+ delete mContextMenu;
+
+ if (gInventory.containsObserver(mCategoriesObserver))
+ {
+ gInventory.removeObserver(mCategoriesObserver);
+ delete mCategoriesObserver;
+ }
+}
+
+BOOL LLPanelWearing::postBuild()
+{
+ mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list");
+ mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3));
+
+ return TRUE;
+}
+
+//virtual
+void LLPanelWearing::onOpen(const LLSD& /*info*/)
+{
+ if (!mIsInitialized)
+ {
+ // *TODO: I'm not sure is this check necessary but it never match while developing.
+ if (!gInventory.isInventoryUsable())
+ return;
+
+ const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+
+ // *TODO: I'm not sure is this check necessary but it never match while developing.
+ LLViewerInventoryCategory* category = gInventory.getCategory(cof);
+ if (!category)
+ return;
+
+ gInventory.addObserver(mCategoriesObserver);
+
+ // Start observing changes in Current Outfit category.
+ mCategoriesObserver->addCategory(cof, boost::bind(&LLWearableItemsList::updateList, mCOFItemsList, cof));
+
+ // Fetch Current Outfit 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();
+
+ mCOFItemsList->updateList(cof);
+
+ mIsInitialized = true;
+ }
+}
+
+// virtual
+void LLPanelWearing::setFilterSubString(const std::string& string)
+{
+ sFilterSubString = string;
+ mCOFItemsList->setFilterSubString(sFilterSubString);
+}
+
+// virtual
+bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+
+ 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;
+ }
+ return false;
+}
+
+// virtual
+void LLPanelWearing::showGearMenu(LLView* spawning_view)
+{
+ if (!mGearMenu) return;
+ mGearMenu->show(spawning_view);
+}
+
+boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb)
+{
+ if (!mCOFItemsList) return boost::signals2::connection();
+
+ return mCOFItemsList->setCommitCallback(cb);
+}
+
+void LLPanelWearing::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
+{
+ LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);
+ if (!list) return;
+
+ uuid_vec_t selected_uuids;
+
+ list->getSelectedUUIDs(selected_uuids);
+
+ mContextMenu->show(ctrl, selected_uuids, x, y);
+}
+
+// EOF
diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h
new file mode 100644
index 0000000000..1573990d13
--- /dev/null
+++ b/indra/newview/llpanelwearing.h
@@ -0,0 +1,81 @@
+/**
+ * @file llpanelwearing.h
+ * @brief List of agent's worn items.
+ *
+ * $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$
+ */
+
+#ifndef LL_LLPANELWEARING_H
+#define LL_LLPANELWEARING_H
+
+#include "llpanel.h"
+
+// newview
+#include "llpanelappearancetab.h"
+
+class LLInventoryCategoriesObserver;
+class LLListContextMenu;
+class LLWearableItemsList;
+class LLWearingGearMenu;
+
+/**
+ * @class LLPanelWearing
+ *
+ * A list of agents's currently worn items represented by
+ * a flat list view.
+ * Starts fetching necessary inventory content on first opening.
+ */
+class LLPanelWearing : public LLPanelAppearanceTab
+{
+public:
+ LLPanelWearing();
+ virtual ~LLPanelWearing();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void onOpen(const LLSD& info);
+
+ /*virtual*/ void setFilterSubString(const std::string& string);
+
+ /*virtual*/ bool isActionEnabled(const LLSD& userdata);
+
+ /*virtual*/ void showGearMenu(LLView* spawning_view);
+
+ boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb);
+
+private:
+ void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
+
+ LLInventoryCategoriesObserver* mCategoriesObserver;
+ LLWearableItemsList* mCOFItemsList;
+ LLWearingGearMenu* mGearMenu;
+ LLListContextMenu* mContextMenu;
+
+ bool mIsInitialized;
+};
+
+#endif //LL_LLPANELWEARING_H
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index ff315d3c53..a7b4873fed 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -876,6 +876,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs,
self->mDirty = FALSE;
self->refresh();
+ self->refreshFromItem(); // to update description and title
}
else
{
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 0d1be91125..ea5796d766 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -390,8 +390,8 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
return;
}
- std::string look_name = gAgentWearables.isCOFChangeInProgress() ? "" : getString("No Outfit");
- mCurrentLookName->setText(look_name);
+ std::string string_name = gAgentWearables.isCOFChangeInProgress() ? "Changing outfits" : "No Outfit";
+ mCurrentLookName->setText(getString(string_name));
mOpenOutfitBtn->setEnabled(FALSE);
}
else
@@ -475,6 +475,12 @@ void LLSidepanelAppearance::setWearablesLoading(bool val)
{
childSetVisible("wearables_loading_indicator", val);
childSetVisible("edit_outfit_btn", !val);
+
+ if (!val)
+ {
+ // refresh outfit name when COF is already changed.
+ refreshCurrentOutfitName();
+ }
}
void LLSidepanelAppearance::showDefaultSubpart()
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 832d4a2fe6..da15b93697 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -95,19 +95,22 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item)
//////////////////////////////////////////////////////////////////////////
// static
-LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item)
+LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item,
+ bool worn_indication_enabled)
{
LLPanelWearableOutfitItem* list_item = NULL;
if (item)
{
- list_item = new LLPanelWearableOutfitItem(item);
+ list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled);
list_item->init();
}
return list_item;
}
-LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item)
+LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item,
+ bool worn_indication_enabled)
: LLPanelInventoryListItemBase(item)
+, mWornIndicationEnabled(worn_indication_enabled)
{
}
@@ -117,7 +120,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
{
std::string search_label = name;
- if (get_is_item_worn(mInventoryItemUUID))
+ if (mWornIndicationEnabled && get_is_item_worn(mInventoryItemUUID))
{
search_label += LLTrans::getString("worn");
item_state = IS_WORN;
@@ -444,6 +447,7 @@ static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_i
LLWearableItemsList::Params::Params()
: standalone("standalone", true)
+, worn_indication_enabled("worn_indication_enabled", true)
{}
LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)
@@ -456,6 +460,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)
// Use built-in context menu.
setRightMouseDownCallback(boost::bind(&LLWearableItemsList::onRightClick, this, _2, _3));
}
+ mWornIndicationEnabled = p.worn_indication_enabled;
}
// virtual
@@ -471,7 +476,7 @@ void LLWearableItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange
llassert(item != NULL);
}
- LLPanelWearableOutfitItem *list_item = LLPanelWearableOutfitItem::create(item);
+ LLPanelWearableOutfitItem *list_item = LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
if (!list_item)
return;
@@ -657,7 +662,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
setMenuItemVisible(menu, "wear_add", mask == MASK_CLOTHING && n_worn == 0);
setMenuItemEnabled(menu, "wear_add", n_items == 1 && canAddWearable(ids.front()));
setMenuItemVisible(menu, "wear", n_worn == 0);
- setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART));
+ setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items);
setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1);
setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1);
setMenuItemVisible(menu, "show_original", !standalone);
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 2bfb90e3ec..eb82418454 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -82,7 +82,8 @@ class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase
{
LOG_CLASS(LLPanelWearableOutfitItem);
public:
- static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item);
+ static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item,
+ bool worn_indication_enabled);
/**
* Updates item name and (worn) suffix.
@@ -91,7 +92,11 @@ public:
EItemState item_state = IS_DEFAULT);
protected:
- LLPanelWearableOutfitItem(LLViewerInventoryItem* item);
+ LLPanelWearableOutfitItem(LLViewerInventoryItem* item,
+ bool worn_indication_enabled);
+
+private:
+ bool mWornIndicationEnabled;
};
class LLPanelDeletableWearableListItem : public LLPanelWearableListItem
@@ -352,6 +357,7 @@ public:
struct Params : public LLInitParam::Block<Params, LLInventoryItemsList::Params>
{
Optional<bool> standalone;
+ Optional<bool> worn_indication_enabled;
Params();
};
@@ -377,6 +383,7 @@ protected:
void onRightClick(S32 x, S32 y);
bool mIsStandalone;
+ bool mWornIndicationEnabled;
};
#endif //LL_LLWEARABLEITEMSLIST_H
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml
index 9c3151fe07..8c8bb29baf 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml
@@ -8,6 +8,9 @@
name="wear_replace">
<on_click
function="Outfit.WearReplace" />
+ <on_enable
+ function="Outfit.OnEnable"
+ parameter="wear_replace" />
<on_visible
function="Outfit.OnVisible"
parameter="wear_replace" />
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
new file mode 100644
index 0000000000..84431a2f69
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ name="Gear Wearing">
+ <menu_item_call
+ label="Edit Outfit"
+ layout="topleft"
+ name="edit">
+ <on_click
+ function="Gear.Edit" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
new file mode 100644
index 0000000000..85505f9972
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Wearing">
+ <menu_item_call
+ label="Edit Outfit"
+ layout="topleft"
+ name="edit">
+ <on_click
+ function="Wearing.Edit" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
index f016c27b0a..d2c8ab159f 100644
--- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
+++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
@@ -31,6 +31,7 @@
item_pad="3"
layout="topleft"
left="0"
+ keep_selection_visible_on_reshape="true"
multi_select="true"
name="list_attachments"
top="0"
@@ -45,6 +46,7 @@
follows="all"
height="10"
item_pad="3"
+ keep_selection_visible_on_reshape="true"
layout="topleft"
left="0"
multi_select="true"
@@ -61,6 +63,7 @@
follows="all"
height="10"
item_pad="3"
+ keep_selection_visible_on_reshape="true"
layout="topleft"
left="0"
multi_select="true"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index 1ab9f722d0..06255353a7 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -390,7 +390,7 @@
<button
follows="bottomleft"
height="23"
- label="Revert"
+ label="Undo Changes"
layout="topleft"
left_pad="7"
name="revert_button"
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index a59070496e..b365540d1f 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -34,22 +34,32 @@
follows="all"
label="MY OUTFITS"
layout="topleft"
- width="315" />
- <inventory_panel
- follows="all"
+ width="312" />
+ <panel
background_visible="true"
- background_opaque="true"
- label="WEARING"
+ class="panel_wearing"
+ follows="all"
+ height="490"
help_topic="now_wearing_tab"
- allow_multi_select="true"
- border="false"
- left="0"
- top="0"
- mouse_opaque="true"
+ label="WEARING"
+ layout="topleft"
name="cof_tab"
- start_folder="Current Outfit"
- use_label_suffix="true"
- width="315" />
+ width="312">
+ <wearable_items_list
+ allow_select="true"
+ follows="all"
+ height="490"
+ keep_one_selected="true"
+ left="1"
+ multi_select="true"
+ name="cof_items_list"
+ standalone="false"
+ top="0"
+ translate="false"
+ width="310"
+ worn_indication_enabled="false"
+ />
+ </panel>
</tab_container>
<panel
background_visible="true"
@@ -84,7 +94,7 @@
width="241"
/>
- <dnd_button
+ <button
follows="bottom|right"
height="25"
image_hover_unselected="Toolbar_Right_Over"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index e189d11d35..9a07d3a48a 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -21,6 +21,9 @@ width="333">
<string
name="Now Wearing"
value="Now wearing..." />
+ <string
+ name="Changing outfits"
+ value="Changing outfits" />
<panel
background_opaque="true"
background_visible="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml b/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml
index dbe1ea2874..49c2abe1a5 100644
--- a/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inventory_list_item.xml
@@ -14,5 +14,6 @@
<!-- style for inventory list item WORN on avatar -->
<worn_style
font="SansSerifSmall"
- font.style="BOLD" />
+ font.style="BOLD"
+ color="green" />
</inventory_list_item>