summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/CMakeLists.txt10
-rw-r--r--indra/newview/llappearancemgr.cpp6
-rw-r--r--indra/newview/llinventoryfilter.cpp17
-rw-r--r--indra/newview/llinventorypanel.cpp35
-rw-r--r--indra/newview/llinventorypanel.h4
-rw-r--r--indra/newview/llpanelmaininventory.cpp48
-rw-r--r--indra/newview/llpanelmaininventory.h29
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp347
-rw-r--r--indra/newview/llpaneloutfitsinventory.h102
-rw-r--r--indra/newview/llsidepanelappearance.cpp372
-rw-r--r--indra/newview/llsidepanelappearance.h102
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml81
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml42
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml6
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_appearance.xml104
16 files changed, 1235 insertions, 72 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4adef84cd3..e7458529be 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -297,8 +297,6 @@ set(viewer_SOURCE_FILES
llnotify.cpp
lloutputmonitorctrl.cpp
lloverlaybar.cpp
- llpanelappearance.cpp
- llpanelappearancetab.cpp
llpanelavatar.cpp
llpanelavatarrow.cpp
llpanelavatartag.cpp
@@ -322,7 +320,6 @@ set(viewer_SOURCE_FILES
llpanellandmedia.cpp
llpanellogin.cpp
llpanellookinfo.cpp
- llpanellooks.cpp
llpanelmaininventory.cpp
llpanelmediasettingsgeneral.cpp
llpanelmediasettingspermissions.cpp
@@ -330,6 +327,7 @@ set(viewer_SOURCE_FILES
llpanelmeprofile.cpp
llpanelobject.cpp
llpanelobjectinventory.cpp
+ llpaneloutfitsinventory.cpp
llpanelpeople.cpp
llpanelpeoplemenus.cpp
llpanelpermissions.cpp
@@ -370,6 +368,7 @@ set(viewer_SOURCE_FILES
llsearchcombobox.cpp
llsearchhistory.cpp
llselectmgr.cpp
+ llsidepanelappearance.cpp
llsidepanelinventory.cpp
llsidepanelinventorysubpanel.cpp
llsidepaneliteminfo.cpp
@@ -792,8 +791,6 @@ set(viewer_HEADER_FILES
llnotify.h
lloutputmonitorctrl.h
lloverlaybar.h
- llpanelappearance.h
- llpanelappearancetab.h
llpanelavatar.h
llpanelavatarrow.h
llpanelavatartag.h
@@ -817,7 +814,6 @@ set(viewer_HEADER_FILES
llpanellandmedia.h
llpanellogin.h
llpanellookinfo.h
- llpanellooks.h
llpanelmaininventory.h
llpanelmediasettingsgeneral.h
llpanelmediasettingspermissions.h
@@ -825,6 +821,7 @@ set(viewer_HEADER_FILES
llpanelmeprofile.h
llpanelobject.h
llpanelobjectinventory.h
+ llpaneloutfitsinventory.h
llpanelpeople.h
llpanelpeoplemenus.h
llpanelpermissions.h
@@ -867,6 +864,7 @@ set(viewer_HEADER_FILES
llsearchcombobox.h
llsearchhistory.h
llselectmgr.h
+ llsidepanelappearance.h
llsidepanelinventory.h
llsidepanelinventorysubpanel.h
llsidepaneliteminfo.h
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 48f11a7cf5..60c6061e96 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -40,7 +40,7 @@
#include "llinventorybridge.h"
#include "llinventoryobserver.h"
#include "llnotifications.h"
-#include "llpanelappearance.h"
+#include "llsidepanelappearance.h"
#include "llsidetray.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
@@ -538,10 +538,10 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)
LLAssetType::AT_LINK_FOLDER, link_waiter);
// Update the current outfit name of the appearance sidepanel.
- LLPanelAppearance* panel_appearance = dynamic_cast<LLPanelAppearance *>(LLSideTray::getInstance()->getPanel("panel_appearance"));
+ LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance *>(LLSideTray::getInstance()->getPanel("sidepanel_appearance"));
if (panel_appearance)
{
- panel_appearance->refreshCurrentLookName(catp->getName());
+ panel_appearance->refreshCurrentOutfitName(catp->getName());
}
}
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 3e4b3327db..085c96c93d 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -100,17 +100,18 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item)
bool passed_type = false;
if (mFilterOps.mFilterForCategories)
{
- if (listener->getInventoryType() == LLInventoryType::IT_CATEGORY)
+ // Pass if this item is a category of the filter type, or
+ // if its parent is a category of the filter type.
+ LLUUID uuid = listener->getUUID();
+ if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)
{
- LLViewerInventoryCategory *cat = gInventory.getCategory(listener->getUUID());
- if (cat)
- {
- passed_type |= ((1LL << cat->getPreferredType() & mFilterOps.mFilterTypes) != U64(0));
- }
+ const LLInventoryObject *obj = gInventory.getObject(uuid);
+ uuid = obj->getParentUUID();
}
- else
+ LLViewerInventoryCategory *cat = gInventory.getCategory(uuid);
+ if (cat)
{
- passed_type = TRUE;
+ passed_type |= ((1LL << cat->getPreferredType() & mFilterOps.mFilterTypes) != U64(0));
}
}
else
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 7b7090d10d..450ce92412 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -145,23 +145,10 @@ BOOL LLInventoryPanel::postBuild()
mInventoryObserver = new LLInventoryPanelObserver(this);
mInventory->addObserver(mInventoryObserver);
- // determine the root folder, if any, so inventory contents show just the children
- // of that folder (i.e. not including the folder itself).
- const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
-
- if ("LIBRARY" == mStartFolderString)
- {
- mStartFolderID = gInventory.getLibraryRootFolderID();
- }
- else
- {
- mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
- }
-
// build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
{
- rebuildViewsFor(mStartFolderID);
+ rebuildViews();
mHasInventoryConnection = true;
defaultOpenInventory();
}
@@ -268,7 +255,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
// inventory just initialized, do complete build
if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
{
- rebuildViewsFor(mStartFolderID);
+ rebuildViews();
mHasInventoryConnection = true;
defaultOpenInventory();
return;
@@ -388,6 +375,24 @@ void LLInventoryPanel::modelChanged(U32 mask)
}
+void LLInventoryPanel::rebuildViews()
+{
+ // Determine the root folder and rebuild the views starting
+ // at that folder.
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+
+ if ("LIBRARY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getLibraryRootFolderID();
+ }
+ else
+ {
+ mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
+ }
+
+ rebuildViewsFor(mStartFolderID);
+}
+
void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
{
LLFolderViewItem* old_view = NULL;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index e398c44105..0ccee337c9 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -162,6 +162,10 @@ public:
void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); }
protected:
+ // Destroys the old views, and regenerates them based on the
+ // start folder ID.
+ void rebuildViews();
+
// Given the id and the parent, build all of the folder views.
void rebuildViewsFor(const LLUUID& id);
virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index e3b2ab77aa..9f723169e1 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -49,7 +49,7 @@
#include "llviewermenu.h"
#include "llviewertexturelist.h"
-static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor?
+static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory");
void on_file_loaded_for_save(BOOL success,
LLViewerFetchedTexture *src_vi,
@@ -197,28 +197,6 @@ BOOL LLPanelMainInventory::postBuild()
return TRUE;
}
-void LLPanelMainInventory::initListCommandsHandlers()
-{
- mListCommands = getChild<LLPanel>("bottom_panel");
-
- mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
- mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
- mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
-
- LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
- trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
- , _4 // BOOL drop
- , _5 // EDragAndDropType cargo_type
- , _7 // EAcceptance* accept
- ));
-
- mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
- mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
- mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-
-}
-
// Destroys the object
LLPanelMainInventory::~LLPanelMainInventory( void )
{
@@ -863,9 +841,30 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
self->childSetValue("check_snapshot", FALSE);
}
+//////////////////////////////////////////////////////////////////////////////////
+// List Commands //
+void LLPanelMainInventory::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
+ LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
+ trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
+ , _4 // BOOL drop
+ , _5 // EDragAndDropType cargo_type
+ , _7 // EAcceptance* accept
+ ));
+
+ mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+}
void LLPanelMainInventory::updateListCommands()
{
@@ -1018,3 +1017,6 @@ bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType
}
return true;
}
+
+// List Commands //
+////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index fbc0f09c50..627be21577 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -111,7 +111,20 @@ protected:
void resetFilters();
void setSortBy(const LLSD& userdata);
- // List Commands Handlers
+private:
+ LLFloaterInventoryFinder* getFinder();
+
+ LLFilterEditor* mFilterEditor;
+ LLTabContainer* mFilterTabs;
+ LLHandle<LLFloater> mFinderHandle;
+ LLInventoryPanel* mActivePanel;
+ LLSaveFolderState* mSavedFolderState;
+ std::string mFilterText;
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // List Commands //
+protected:
void initListCommandsHandlers();
void updateListCommands();
void onGearButtonClick();
@@ -122,22 +135,12 @@ protected:
BOOL isActionEnabled(const LLSD& command_name);
void onCustomAction(const LLSD& command_name);
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
-
-
private:
- LLFloaterInventoryFinder* getFinder();
-
- LLFilterEditor* mFilterEditor;
- LLTabContainer* mFilterTabs;
- LLHandle<LLFloater> mFinderHandle;
- LLInventoryPanel* mActivePanel;
- LLSaveFolderState* mSavedFolderState;
-
LLPanel* mListCommands;
LLMenuGL* mMenuGearDefault;
LLMenuGL* mMenuAdd;
-
- std::string mFilterText;
+ // List Commands //
+ ////////////////////////////////////////////////////////////////////////////////
};
#endif // LL_LLPANELMAININVENTORY_H
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
new file mode 100644
index 0000000000..5ad9bf056e
--- /dev/null
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -0,0 +1,347 @@
+/**
+ * @file llpaneloutfitsinventory.cpp
+ * @brief Outfits inventory panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, 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 "llpaneloutfitsinventory.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "llfloaterinventory.h"
+#include "llfoldervieweventlistener.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "lllandmark.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"
+
+static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
+
+LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
+ mInventoryPanel(NULL),
+ mParent(NULL)
+{
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+}
+
+LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
+{
+ delete mSavedFolderState;
+}
+
+// virtual
+BOOL LLPanelOutfitsInventory::postBuild()
+{
+ mInventoryPanel = getChild<LLInventoryPanel>("outfits_list");
+ mInventoryPanel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, TRUE);
+ mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_MY_OUTFITS);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onSelectionChange, this, _1, _2));
+
+ initListCommandsHandlers();
+ return TRUE;
+}
+
+void LLPanelOutfitsInventory::updateParent()
+{
+ if (mParent)
+ {
+ mParent->updateVerbs();
+ }
+}
+
+void LLPanelOutfitsInventory::setParent(LLSidepanelAppearance* parent)
+{
+ mParent = parent;
+}
+
+// virtual
+void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
+{
+ if (string == "")
+ {
+ mInventoryPanel->setFilterSubString(LLStringUtil::null);
+
+ // re-open folders that were initially open
+ mSavedFolderState->setApply(TRUE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ getRootFolder()->applyFunctorRecursively(opener);
+ getRootFolder()->scrollToShowSelection();
+ }
+
+ gInventory.startBackgroundFetch();
+
+ if (mInventoryPanel->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
+ mInventoryPanel->setFilterSubString(string);
+}
+
+void LLPanelOutfitsInventory::onWear()
+{
+ LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
+ if (listenerp)
+ {
+ listenerp->performAction(NULL, NULL,"replaceoutfit");
+ }
+}
+
+void LLPanelOutfitsInventory::onEdit()
+{
+}
+
+void LLPanelOutfitsInventory::onNew()
+{
+ const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT);
+ LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name);
+ getRootFolder()->setSelectionByID(outfit_folder, TRUE);
+ getRootFolder()->setNeedsAutoRename(TRUE);
+}
+
+void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ updateParent();
+}
+
+void LLPanelOutfitsInventory::onSelectorButtonClicked()
+{
+ /*
+ LLFolderViewItem* cur_item = getRootFolder()->getCurSelectedItem();
+
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+ if (getIsCorrectType(listenerp))
+ {
+ LLSD key;
+ key["type"] = "look";
+ key["id"] = listenerp->getUUID();
+
+ LLSideTray::getInstance()->showPanel("sidepanel_appearance", key);
+ }
+ */
+}
+
+LLFolderViewEventListener *LLPanelOutfitsInventory::getCorrectListenerForAction()
+{
+ 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 mInventoryPanel->getRootFolder();
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// List Commands //
+
+void LLPanelOutfitsInventory::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, 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
+ ));
+
+ mCommitCallbackRegistrar.add("panel_outfits_inventory_gear_default.Custom.Action", boost::bind(&LLPanelOutfitsInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("panel_outfits_inventory_gear_default.Enable", boost::bind(&LLPanelOutfitsInventory::isActionEnabled, this, _2));
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("panel_outfits_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLPanelOutfitsInventory::updateListCommands()
+{
+ bool trash_enabled = isActionEnabled("delete");
+
+ mListCommands->childSetEnabled("trash_btn", trash_enabled);
+}
+
+void LLPanelOutfitsInventory::onGearButtonClick()
+{
+ showActionMenu(mMenuGearDefault,"options_gear_btn");
+}
+
+void LLPanelOutfitsInventory::onAddButtonClick()
+{
+ onNew();
+}
+
+void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+{
+ if (menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+ }
+}
+
+void LLPanelOutfitsInventory::onTrashButtonClick()
+{
+ onClipboardAction("delete");
+}
+
+void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata)
+{
+ std::string command_name = userdata.asString();
+ getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
+}
+
+void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata)
+{
+ if (!isActionEnabled(userdata))
+ return;
+
+ const std::string command_name = userdata.asString();
+ if (command_name == "new")
+ {
+ onNew();
+ }
+ if (command_name == "edit")
+ {
+ onEdit();
+ }
+ if (command_name == "wear")
+ {
+ onWear();
+ }
+ if (command_name == "delete")
+ {
+ onClipboardAction("delete");
+ }
+}
+
+BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+ if (command_name == "delete")
+ {
+ BOOL can_delete = FALSE;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ can_delete = TRUE;
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ for (std::set<LLUUID>::iterator iter = selection_set.begin();
+ iter != selection_set.end();
+ ++iter)
+ {
+ const LLUUID &item_id = (*iter);
+ LLFolderViewItem *item = folder->getItemByID(item_id);
+ can_delete &= item->getListener()->isItemRemovable();
+ }
+ return can_delete;
+ }
+ return FALSE;
+ }
+ if (command_name == "edit" ||
+ command_name == "wear")
+ {
+ return (getCorrectListenerForAction() != NULL);
+ }
+ return TRUE;
+}
+
+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 //
+////////////////////////////////////////////////////////////////////////////////
+
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
new file mode 100644
index 0000000000..4d903a389b
--- /dev/null
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -0,0 +1,102 @@
+/**
+ * @file llpaneloutfitsinventory.h
+ * @brief Outfits inventory panel
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, 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_LLPANELOUTFITSINVENTORY_H
+#define LL_LLPANELOUTFITSINVENTORY_H
+
+#include "llpanel.h"
+#include "llinventoryobserver.h"
+
+class LLFolderView;
+class LLFolderViewItem;
+class LLFolderViewEventListener;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLButton;
+class LLMenuGL;
+class LLSidepanelAppearance;
+
+class LLPanelOutfitsInventory : public LLPanel
+{
+public:
+ LLPanelOutfitsInventory();
+ virtual ~LLPanelOutfitsInventory();
+
+ /*virtual*/ BOOL postBuild();
+
+ void onSearchEdit(const std::string& string);
+ void onWear();
+ void onEdit();
+ void onNew();
+
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onSelectorButtonClicked();
+
+ LLInventoryPanel* getActivePanel() { return mInventoryPanel; }
+
+ // If a compatible listener type is selected, then return a pointer to that.
+ // Otherwise, return NULL.
+ LLFolderViewEventListener* getCorrectListenerForAction();
+ void setParent(LLSidepanelAppearance *parent);
+protected:
+ void updateParent();
+ bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const;
+ LLFolderView* getRootFolder();
+
+private:
+ LLSidepanelAppearance* mParent;
+ LLInventoryPanel* mInventoryPanel;
+ LLSaveFolderState* mSavedFolderState;
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // List Commands //
+protected:
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onGearButtonClick();
+ void onAddButtonClick();
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ 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);
+private:
+ LLPanel* mListCommands;
+ LLMenuGL* mMenuGearDefault;
+ LLMenuGL* mMenuAdd;
+ // //
+ ////////////////////////////////////////////////////////////////////////////////
+};
+
+#endif //LL_LLPANELOUTFITSINVENTORY_H
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
new file mode 100644
index 0000000000..aeab3e2876
--- /dev/null
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -0,0 +1,372 @@
+/**
+ * @file llsidepanelappearance.cpp
+ * @brief Side Bar "Appearance" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, 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 "llsidepanelappearance.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "llpaneleditwearable.h"
+#include "llpaneloutfitsinventory.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "llwearable.h"
+
+static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance");
+
+class LLCurrentlyWornFetchObserver : public LLInventoryFetchObserver
+{
+public:
+ LLCurrentlyWornFetchObserver(LLSidepanelAppearance *panel) :
+ mPanel(panel)
+ {}
+ ~LLCurrentlyWornFetchObserver() {}
+ virtual void done()
+ {
+ mPanel->inventoryFetched();
+ gInventory.removeObserver(this);
+ }
+private:
+ LLSidepanelAppearance *mPanel;
+};
+
+LLSidepanelAppearance::LLSidepanelAppearance() :
+ LLPanel(),
+ mFilterSubString(LLStringUtil::null),
+ mFilterEditor(NULL),
+ mLookInfo(NULL),
+ mCurrLookPanel(NULL)
+{
+ //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_appearance.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+ mFetchWorn = new LLCurrentlyWornFetchObserver(this);
+}
+
+LLSidepanelAppearance::~LLSidepanelAppearance()
+{
+}
+
+// virtual
+BOOL LLSidepanelAppearance::postBuild()
+{
+ mEditAppearanceBtn = getChild<LLButton>("editappearance_btn");
+ mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this));
+
+ mWearBtn = getChild<LLButton>("wear_btn");
+ mWearBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onWearButtonClicked, this));
+
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this));
+
+ mNewLookBtn = getChild<LLButton>("newlook_btn");
+ mNewLookBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this));
+ mNewLookBtn->setEnabled(false);
+
+ mOverflowBtn = getChild<LLButton>("overflow_btn");
+
+ mFilterEditor = getChild<LLFilterEditor>("Filter");
+ if (mFilterEditor)
+ {
+ mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2));
+ }
+
+ mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory"));
+ mPanelOutfitsInventory->setParent(this);
+
+ mLookInfo = dynamic_cast<LLPanelLookInfo*>(getChild<LLPanel>("panel_look_info"));
+ if (mLookInfo)
+ {
+ LLButton* back_btn = mLookInfo->getChild<LLButton>("back_btn");
+ if (back_btn)
+ {
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onBackButtonClicked, this));
+ }
+
+ // *TODO: Assign the action to an appropriate event.
+ // mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::toggleMediaPanel, this));
+ }
+
+ mEditWearable = dynamic_cast<LLPanelEditWearable*>(getChild<LLPanel>("panel_edit_wearable"));
+ if (mEditWearable)
+ {
+ LLButton* edit_wearable_back_btn = mEditWearable->getChild<LLButton>("back_btn");
+ if (edit_wearable_back_btn)
+ {
+ edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditWearBackClicked, this));
+ }
+ }
+
+ mCurrentLookName = getChild<LLTextBox>("currentlook_name");
+
+ mCurrLookPanel = getChild<LLPanel>("panel_currentlook");
+
+ return TRUE;
+}
+
+// virtual
+void LLSidepanelAppearance::onOpen(const LLSD& key)
+{
+ fetchInventory();
+ refreshCurrentOutfitName();
+
+ if(key.size() == 0)
+ return;
+
+ toggleLookInfoPanel(TRUE);
+ updateVerbs();
+
+ mLookInfoType = key["type"].asString();
+
+ if (mLookInfoType == "look")
+ {
+ LLInventoryCategory *pLook = gInventory.getCategory(key["id"].asUUID());
+ if (pLook)
+ mLookInfo->displayLookInfo(pLook);
+ }
+}
+
+void LLSidepanelAppearance::onFilterEdit(const std::string& search_string)
+{
+ if (mFilterSubString != search_string)
+ {
+ mFilterSubString = search_string;
+
+ // Searches are case-insensitive
+ LLStringUtil::toUpper(mFilterSubString);
+ LLStringUtil::trimHead(mFilterSubString);
+
+ mPanelOutfitsInventory->onSearchEdit(mFilterSubString);
+ }
+}
+
+void LLSidepanelAppearance::onWearButtonClicked()
+{
+ if (!mLookInfo->getVisible())
+ {
+ mPanelOutfitsInventory->onWear();
+ }
+}
+
+void LLSidepanelAppearance::onEditAppearanceButtonClicked()
+{
+ if (gAgentWearables.areWearablesLoaded())
+ {
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+}
+
+void LLSidepanelAppearance::onEditButtonClicked()
+{
+ toggleLookInfoPanel(FALSE);
+ toggleWearableEditPanel(TRUE, NULL);
+ /*if (mLookInfo->getVisible())
+ {
+ }
+ else
+ {
+ mPanelOutfitsInventory->onEdit();
+ }*/
+}
+
+void LLSidepanelAppearance::onNewOutfitButtonClicked()
+{
+ if (!mLookInfo->getVisible())
+ {
+ mPanelOutfitsInventory->onNew();
+ }
+}
+
+
+void LLSidepanelAppearance::onBackButtonClicked()
+{
+ toggleLookInfoPanel(FALSE);
+}
+
+void LLSidepanelAppearance::onEditWearBackClicked()
+{
+ mEditWearable->saveChanges();
+ toggleWearableEditPanel(FALSE, NULL);
+ toggleLookInfoPanel(TRUE);
+}
+
+void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible)
+{
+ if (!mLookInfo)
+ return;
+
+ mLookInfo->setVisible(visible);
+ mPanelOutfitsInventory->setVisible(!visible);
+ mFilterEditor->setVisible(!visible);
+ mWearBtn->setVisible(!visible);
+ mEditBtn->setVisible(!visible);
+ mNewLookBtn->setVisible(!visible);
+ mOverflowBtn->setVisible(!visible);
+ mCurrLookPanel->setVisible(!visible);
+}
+
+void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable)
+{
+ if (!wearable)
+ {
+ wearable = gAgentWearables.getWearable(WT_SHAPE, 0);
+ }
+ if (!mEditWearable || !wearable)
+ {
+ return;
+ }
+
+ mEditWearable->setVisible(visible);
+ mFilterEditor->setVisible(!visible);
+ mPanelOutfitsInventory->setVisible(!visible);
+}
+
+void LLSidepanelAppearance::updateVerbs()
+{
+ bool is_look_info_visible = mLookInfo->getVisible();
+ mOverflowBtn->setEnabled(false);
+
+ if (!is_look_info_visible)
+ {
+ const bool is_correct_type = (mPanelOutfitsInventory->getCorrectListenerForAction() != NULL);
+ mEditBtn->setEnabled(is_correct_type);
+ mWearBtn->setEnabled(is_correct_type);
+ }
+ else
+ {
+ mEditBtn->setEnabled(FALSE);
+ mWearBtn->setEnabled(FALSE);
+ }
+}
+
+void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string name)
+{
+ if (name == "")
+ {
+ const LLUUID current_outfit_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ // Can't search on AT_OUTFIT since links to categories return AT_CATEGORY for type since they don't
+ // return preferred type.
+ LLIsType is_category( LLAssetType::AT_CATEGORY );
+ gInventory.collectDescendentsIf(current_outfit_cat,
+ cat_array,
+ item_array,
+ false,
+ is_category,
+ false);
+ for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ const LLViewerInventoryItem *item = (*iter);
+ const LLViewerInventoryCategory *cat = item->getLinkedCategory();
+ if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ mCurrentLookName->setText(cat->getName());
+ return;
+ }
+ }
+ mCurrentLookName->setText(std::string(""));
+ }
+ else
+ {
+ mCurrentLookName->setText(name);
+ }
+}
+
+//static
+void LLSidepanelAppearance::editWearable(LLWearable *wearable, void *data)
+{
+ LLSidepanelAppearance *panel = (LLSidepanelAppearance*) data;
+ panel->toggleLookInfoPanel(FALSE);
+ panel->toggleWearableEditPanel(TRUE, wearable);
+}
+
+// Fetch currently worn items and only enable the New Look button after everything's been
+// fetched. Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks.
+void LLSidepanelAppearance::fetchInventory()
+{
+
+ mNewLookBtn->setEnabled(false);
+ LLInventoryFetchObserver::item_ref_t ids;
+ LLUUID item_id;
+ for(S32 type = (S32)WT_SHAPE; type < (S32)WT_COUNT; ++type)
+ {
+ // MULTI_WEARABLE:
+ item_id = gAgentWearables.getWearableItemID((EWearableType)type,0);
+ if(item_id.notNull())
+ {
+ ids.push_back(item_id);
+ }
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin();
+ iter != avatar->mAttachmentPoints.end(); ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (!attachment) continue;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = (*attachment_iter);
+ if (!attached_object) continue;
+ const LLUUID& item_id = attached_object->getItemID();
+ if (item_id.isNull()) continue;
+ ids.push_back(item_id);
+ }
+ }
+ }
+
+ mFetchWorn->fetchItems(ids);
+ // If no items to be fetched, done will never be triggered.
+ // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition.
+ if (mFetchWorn->isEverythingComplete())
+ {
+ mFetchWorn->done();
+ }
+ else
+ {
+ gInventory.addObserver(mFetchWorn);
+ }
+}
+
+void LLSidepanelAppearance::inventoryFetched()
+{
+ mNewLookBtn->setEnabled(true);
+}
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
new file mode 100644
index 0000000000..496a1fef72
--- /dev/null
+++ b/indra/newview/llsidepanelappearance.h
@@ -0,0 +1,102 @@
+/**
+ * @file llsidepanelappearance.h
+ * @brief Side Bar "Appearance" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, 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_LLSIDEPANELAPPEARANCE_H
+#define LL_LLSIDEPANELAPPEARANCE_H
+
+#include "llpanel.h"
+#include "llinventoryobserver.h"
+
+#include "llinventory.h"
+#include "llpanellookinfo.h"
+
+class LLFilterEditor;
+class LLCurrentlyWornFetchObserver;
+class LLPanelEditWearable;
+class LLWearable;
+class LLPanelOutfitsInventory;
+
+class LLSidepanelAppearance : public LLPanel
+{
+public:
+ LLSidepanelAppearance();
+ virtual ~LLSidepanelAppearance();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ void refreshCurrentOutfitName(const std::string name = "");
+
+ static void editWearable(LLWearable *wearable, void *data);
+
+ void fetchInventory();
+ void inventoryFetched();
+ void updateVerbs();
+
+private:
+ void onFilterEdit(const std::string& search_string);
+
+ void onEditAppearanceButtonClicked();
+ void onWearButtonClicked();
+ void onEditButtonClicked();
+ void onNewOutfitButtonClicked();
+ void onBackButtonClicked();
+ void onEditWearBackClicked();
+ void toggleLookInfoPanel(BOOL visible);
+ void toggleWearableEditPanel(BOOL visible, LLWearable* wearable);
+
+ LLFilterEditor* mFilterEditor;
+ LLPanelOutfitsInventory* mPanelOutfitsInventory;
+ LLPanelLookInfo* mLookInfo;
+ LLPanelEditWearable* mEditWearable;
+
+ LLButton* mEditAppearanceBtn;
+ LLButton* mWearBtn;
+ LLButton* mEditBtn;
+ LLButton* mNewLookBtn;
+ LLButton* mOverflowBtn;
+ LLPanel* mCurrLookPanel;
+
+ LLTextBox* mCurrentLookName;
+
+ // Used to make sure the user's inventory is in memory.
+ LLCurrentlyWornFetchObserver* mFetchWorn;
+
+ // Search string for filtering landmarks and teleport
+ // history locations
+ std::string mFilterSubString;
+
+ // Information type currently shown in Look Information panel
+ std::string mLookInfoType;
+
+};
+
+#endif //LL_LLSIDEPANELAPPEARANCE_H
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index b48c962413..7cfcac8a9a 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -30,7 +30,7 @@
name="Fetched">
Fetched
</floater.string>
-<panel
+ <panel
bottom="560"
class="panel_main_inventory"
filename="panel_main_inventory.xml"
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
new file mode 100644
index 0000000000..f511ec0d6f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="Outfits"
+ bottom="0"
+ height="326"
+ left="0"
+ width="310"
+ border="true"
+ follows="left|top|right|bottom">
+ <inventory_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="326"
+ left="0"
+ mouse_opaque="true"
+ name="outfits_list"
+ width="310"
+ start_folder="My Outfits"/>
+ <button bottom="0"
+ halign="center"
+ height="16"
+ label=">"
+ enabled="false"
+ mouse_opaque="false"
+ name="selector"
+ width="20"
+ left="0"
+ visible="false"
+ follows="right|bottom"
+ tool_tip="View outfit properties"/>
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ bottom="0"
+ follows="left|right|bottom"
+ height="30"
+ layout="bottomleft"
+ left="0"
+ visible="true"
+ name="bottom_panel"
+ width="310">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ picture_style="true"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_btn"
+ picture_style="true"
+ tool_tip="Add new item"
+ width="18" />
+ <dnd_button
+ follows="bottom|right"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ picture_style="true"
+ tool_tip="Remove selected item"
+ top="6"
+ width="18" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml
new file mode 100644
index 0000000000..c8c79f8761
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_gear_default"
+ visible="false">
+ <menu_item_call
+ label="New Outfit"
+ layout="topleft"
+ name="new">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="new" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="new" />
+ </menu_item_call>
+ <menu_item_call
+ label="Wear Outfit"
+ layout="topleft"
+ name="wear">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="wear" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="wear" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete Outfit"
+ layout="topleft"
+ name="delete">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="delete" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="delete" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index a419a02d75..d02354a647 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -120,9 +120,9 @@
background_visible="true"
>
<panel
- class="panel_appearance"
- name="panel_appearance"
- filename="panel_appearance.xml"
+ class="sidepanel_appearance"
+ name="sidepanel_appearance"
+ filename="sidepanel_appearance.xml"
label="Edit Appearance"
font="SansSerifBold"
/>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
new file mode 100644
index 0000000000..d87211d432
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="400"
+ label="Appearance"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="appearance panel"
+ width="333">
+ <string
+ name="looks_tab_title"
+ value="Looks" />
+ <panel
+ left="5" width="320" height="55"
+ background_visible="true"
+ background_opaque="false"
+ bg_alpha_color="0.2 0.2 0.2 1.0"
+ name="panel_currentlook"
+ follows="left|top|right">
+ <text
+ top="-5" width="200" left="5" height="10" follows="left|right|top"
+ font="SansSerif" text_color="LtGray" word_wrap="true"
+ mouse_opaque="false" name="currentlook_title">
+ Current Look
+ </text>
+ <text
+ top="-30" left="8" height="10" follows="left|right|top"
+ font="SansSerifBold" text_color="white" word_wrap="true"
+ mouse_opaque="false" name="currentlook_name" >
+ MyLook
+ </text>
+ <button
+ follows="left|right|top"
+ font="SansSerif"
+ top="28" right="-105" width="60" height="20"
+ layout="topleft"
+ label="Edit"
+ name="editappearance_btn"/>
+ </panel>
+
+ <filter_editor
+ follows="left|top|right"
+ font="SansSerif"
+ label="Filter"
+ layout="topleft"
+ left="15"
+ width="313"
+ height="20"
+ name="Filter" />
+ <panel
+ class="panel_outfits_inventory"
+ filename="panel_outfits_inventory.xml"
+ name="panel_outfits_inventory"
+ follows="all"
+ height="271"
+ halign="center"
+ layout="topleft"
+ left="10"
+ top_pad="19"
+ width="313" />
+ <button
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Wear"
+ layout="topleft"
+ left="10"
+ name="wear_btn"
+ top_pad="0"
+ width="80" />
+ <button
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="New Look"
+ layout="topleft"
+ left_pad="0"
+ name="newlook_btn"
+ top_delta="0"
+ width="90" />
+
+ <panel
+ class="panel_look_info"
+ filename="panel_look_info.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_look_info"
+ top="-200"
+ visible="false" />
+
+ <panel
+ class="panel_edit_wearable"
+ filename="panel_edit_wearable.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_edit_wearable"
+ top="-200"
+ visible="false"
+ width="333" />
+</panel>