EXT-4295 FIXED Added gear and context menus for Wearing tab.

- Moved My Outfits gear menu from llpaneloutfitsinventory.cpp to lloutfitslist.cpp

Revieved by Neal Orman and Mike Antipov at https://codereview.productengine.com/secondlife/r/604/.

--HG--
branch : product-engine
meow-7.2.2
Sergei Litovchuk 2010-06-22 16:34:27 +03:00
parent 887b2858d4
commit 2583a4d6ea
10 changed files with 284 additions and 194 deletions

View File

@ -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");
}
@ -170,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))
@ -453,8 +596,11 @@ void LLOutfitsList::setFilterSubString(const std::string& 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")
{
@ -473,7 +619,7 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
}
if (command_name == "wear")
{
return mSelectedOutfitUUID.notNull();
return !gAgentWearables.isCOFChangeInProgress();
}
if (command_name == "take_off")
{
@ -482,6 +628,13 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
return false;
}
// virtual
void LLOutfitsList::showGearMenu(LLView* spawning_view)
{
if (!mGearMenu) return;
mGearMenu->show(spawning_view);
}
boost::signals2::connection LLOutfitsList::setSelectionChangeCallback(selection_change_callback_t cb)
{
return mSelectionChangeSignal.connect(cb);
@ -761,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)

View File

@ -41,6 +41,7 @@
class LLAccordionCtrlTab;
class LLInventoryCategoriesObserver;
class LLOutfitListGearMenu;
class LLWearableItemsList;
class LLListContextMenu;
@ -98,6 +99,8 @@ public:
/*virtual*/ bool isActionEnabled(const LLSD& userdata);
/*virtual*/ void showGearMenu(LLView* spawning_view);
const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
@ -196,6 +199,7 @@ private:
typedef outfits_map_t::value_type outfits_map_value_t;
outfits_map_t mOutfitsMap;
LLOutfitListGearMenu* mGearMenu;
LLListContextMenu* mOutfitMenu;
bool mIsInitialized;

View File

@ -44,6 +44,8 @@ public:
virtual bool isActionEnabled(const LLSD& userdata) = 0;
virtual void showGearMenu(LLView* spawning_view) = 0;
static const std::string& getFilterSubString() { return sFilterSubString; }
protected:

View File

@ -33,7 +33,6 @@
#include "llpaneloutfitsinventory.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
#include "lltabcontainer.h"
@ -48,189 +47,16 @@
#include "llsidepanelappearance.h"
#include "llsidetray.h"
#include "llviewerfoldertype.h"
#include "llviewermenu.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 LLPanelOutfitsInventory;
class LLOutfitListGearMenu
{
public:
LLOutfitListGearMenu(LLOutfitsList* olist, LLPanelOutfitsInventory* parent_panel)
: mOutfitList(olist),
mMyOutfitsPanel(parent_panel),
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);
}
else if ("wear" == param)
{
return mMyOutfitsPanel->isActionEnabled(param);
}
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* mMyOutfitsPanel;
};
LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mMyOutfitsPanel(NULL),
mCurrentOutfitPanel(NULL),
mActivePanel(NULL),
mGearMenu(NULL),
mInitialized(false)
{
gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this));
@ -244,7 +70,6 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
{
delete mGearMenu;
}
// virtual
@ -417,8 +242,6 @@ 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));
mGearMenu = new LLOutfitListGearMenu(mMyOutfitsPanel, this);
}
void LLPanelOutfitsInventory::updateListCommands()
@ -428,9 +251,6 @@ void LLPanelOutfitsInventory::updateListCommands()
bool wear_visible = !isCOFPanelActive();
bool make_outfit_enabled = isActionEnabled("save_outfit");
// *TODO: Enable gear menu for Wearing tab.
childSetEnabled("options_gear_btn", wear_visible);
mListCommands->childSetEnabled("trash_btn", trash_enabled);
mListCommands->childSetEnabled("wear_btn", wear_enabled);
mListCommands->childSetVisible("wear_btn", wear_visible);
@ -439,10 +259,10 @@ 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()
@ -456,8 +276,6 @@ void LLPanelOutfitsInventory::onTrashButtonClick()
bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
{
return mActivePanel && mActivePanel->isActionEnabled(userdata);
if (gAgentWearables.isCOFChangeInProgress()) return FALSE;
}
// List Commands //
//////////////////////////////////////////////////////////////////////////////////

View File

@ -88,9 +88,6 @@ private:
//////////////////////////////////////////////////////////////////////////////////
// List Commands //
public:
BOOL isActionEnabled(const LLSD& command_name);
protected:
void initListCommandsHandlers();
void updateListCommands();
@ -103,7 +100,6 @@ protected:
void onWearablesLoading();
private:
LLPanel* mListCommands;
LLOutfitListGearMenu* mGearMenu;
LLMenuGL* mMenuAdd;
// List Commands //
//////////////////////////////////////////////////////////////////////////////////

View File

@ -36,8 +36,64 @@
#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;
@ -49,10 +105,16 @@ LLPanelWearing::LLPanelWearing()
, mIsInitialized(false)
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
mGearMenu = new LLWearingGearMenu();
mContextMenu = new LLWearingContextMenu();
}
LLPanelWearing::~LLPanelWearing()
{
delete mGearMenu;
delete mContextMenu;
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
@ -63,6 +125,8 @@ LLPanelWearing::~LLPanelWearing()
BOOL LLPanelWearing::postBuild()
{
mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list");
mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3));
return TRUE;
}
@ -106,6 +170,7 @@ void LLPanelWearing::setFilterSubString(const std::string& string)
mCOFItemsList->setFilterSubString(sFilterSubString);
}
// virtual
bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
{
const std::string command_name = userdata.asString();
@ -120,6 +185,13 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
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();
@ -127,4 +199,16 @@ boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_ca
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

View File

@ -38,7 +38,9 @@
#include "llpanelappearancetab.h"
class LLInventoryCategoriesObserver;
class LLListContextMenu;
class LLWearableItemsList;
class LLWearingGearMenu;
/**
* @class LLPanelWearing
@ -61,11 +63,17 @@ public:
/*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;
};

View File

@ -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>

View File

@ -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>

View File

@ -53,6 +53,7 @@
left="1"
multi_select="true"
name="cof_items_list"
standalone="false"
top="0"
translate="false"
width="310"