EXT-2705 : Create accordion panel to show COF contents

Also made several infrastructure improvements that help inventory panels defer generating their folders/views until after inventory has been loaded up.  This was pretty haphazard before.

--HG--
branch : avatar-pipeline
meow-7.2.2
Loren Shih 2009-11-23 15:25:31 -05:00
parent 0c3bd94da9
commit fc1860bcc6
6 changed files with 154 additions and 47 deletions

View File

@ -2014,6 +2014,12 @@ static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory");
// Main idle routine
void LLFolderView::doIdle()
{
// Don't do anything until the inventory is loaded up.
if (!gInventory.isInventoryUsable())
{
return;
}
LLFastTimer t2(FTM_INVENTORY);
BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters");

View File

@ -96,6 +96,11 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor"));
setBackgroundVisible(TRUE);
setBackgroundOpaque(TRUE);
if (mStartFolderString != "")
{
mBuildDefaultHierarchy = false;
}
}
BOOL LLInventoryPanel::postBuild()
@ -148,7 +153,7 @@ BOOL LLInventoryPanel::postBuild()
// build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
{
rebuildViews();
generateViews();
mHasInventoryConnection = true;
defaultOpenInventory();
}
@ -253,9 +258,9 @@ void LLInventoryPanel::modelChanged(U32 mask)
bool handled = false;
// inventory just initialized, do complete build
if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
if ((mask & LLInventoryObserver::ADD) && mInventory->isInventoryUsable() && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
{
rebuildViews();
generateViews();
mHasInventoryConnection = true;
defaultOpenInventory();
return;
@ -367,10 +372,14 @@ void LLInventoryPanel::modelChanged(U32 mask)
}
void LLInventoryPanel::rebuildViews()
void LLInventoryPanel::generateViews()
{
// Determine the root folder and rebuild the views starting
// at that folder.
// Blow away the entire previous UI tree.
mFolders->getRoot()->destroyView();
// Determine the root folder in case specified, and
// build the views starting with that folder.
const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
if ("LIBRARY" == mStartFolderString)
@ -381,16 +390,14 @@ void LLInventoryPanel::rebuildViews()
{
mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
}
llinfos << this << " Generating views for start folder " << mStartFolderString << llendl;
rebuildViewsFor(mStartFolderID);
}
void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
{
LLFolderViewItem* old_view = NULL;
// get old LLFolderViewItem
old_view = mFolders->getItemByID(id);
// Destroy the old view for this ID so we can rebuild it
LLFolderViewItem* old_view = mFolders->getItemByID(id);
if (old_view && id.notNull())
{
old_view->destroyView();
@ -409,14 +416,20 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
const LLUUID &parent_id = objectp->getParentUUID();
LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(parent_id);
if (id == mStartFolderID)
parent_folder = mFolders;
if (!parent_folder)
{
// This item exists outside the inventory's hierarchy, so don't add it.
parent_folder = mFolders;
}
else if ((mStartFolderID != LLUUID::null) && (!gInventory.isObjectDescendentOf(id, mStartFolderID)))
{
// This item exists outside the inventory's hierarchy,
// so don't add it.
return;
}
if (objectp->getName() == "My Inventory")
{
llinfos << this << " Adding MyInventory for start folder " << mStartFolderString << llendl;
}
if (objectp->getType() <= LLAssetType::AT_NONE ||
objectp->getType() >= LLAssetType::AT_COUNT)
{
@ -520,19 +533,20 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
// bit of a hack to make sure the inventory is open.
void LLInventoryPanel::defaultOpenInventory()
{
const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
if (preferred_type != LLFolderType::FT_NONE)
if (mStartFolderString != "")
{
const std::string& top_level_folder_name = LLViewerFolderType::lookupNewCategoryName(preferred_type);
mFolders->openFolder(top_level_folder_name);
mFolders->openFolder(mStartFolderString);
}
else
{
// Get the first child (it should be "My Inventory") and
// open it up by name (just to make sure the first child is actually a folder).
LLView* first_child = mFolders->getFirstChild();
const std::string& first_child_name = first_child->getName();
mFolders->openFolder(first_child_name);
if (first_child)
{
const std::string& first_child_name = first_child->getName();
mFolders->openFolder(first_child_name);
}
}
}
@ -640,13 +654,6 @@ void LLInventoryPanel::openAllFolders()
mFolders->arrangeAll();
}
void LLInventoryPanel::openDefaultFolderForType(LLFolderType::EType type)
{
LLUUID category_id = mInventory->findCategoryUUIDForType(type);
LLOpenFolderByID opener(category_id);
mFolders->applyFunctorRecursively(opener);
}
void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
{
// Don't select objects in COF (e.g. to prevent refocus when items are worn).

View File

@ -122,7 +122,6 @@ public:
// Call this method to set the selection.
void openAllFolders();
void openDefaultFolderForType(LLFolderType::EType);
void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); }
void clearSelection();
@ -161,16 +160,17 @@ public:
void openSelected();
void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); }
protected:
private:
// Destroys the old views, and regenerates them based on the
// start folder ID.
void rebuildViews();
void generateViews();
// 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
void defaultOpenInventory(); // open the first level of inventory
protected:
void defaultOpenInventory(); // open the first level of inventory
LLInventoryModel* mInventory;
LLInventoryObserver* mInventoryObserver;
BOOL mAllowMultiSelect;

View File

@ -59,7 +59,7 @@
static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mInventoryPanel(NULL),
mActivePanel(NULL),
mParent(NULL)
{
mSavedFolderState = new LLSaveFolderState();
@ -74,12 +74,8 @@ LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
// 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));
initAccordionPanels();
initListCommandsHandlers();
return TRUE;
}
@ -102,7 +98,7 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
{
if (string == "")
{
mInventoryPanel->setFilterSubString(LLStringUtil::null);
mActivePanel->setFilterSubString(LLStringUtil::null);
// re-open folders that were initially open
mSavedFolderState->setApply(TRUE);
@ -114,7 +110,7 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
gInventory.startBackgroundFetch();
if (mInventoryPanel->getFilterSubString().empty() && string.empty())
if (mActivePanel->getFilterSubString().empty() && string.empty())
{
// current filter and new filter empty, do nothing
return;
@ -128,7 +124,7 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
}
// set new filter string
mInventoryPanel->setFilterSubString(string);
mActivePanel->setFilterSubString(string);
}
void LLPanelOutfitsInventory::onWear()
@ -207,7 +203,7 @@ bool LLPanelOutfitsInventory::getIsCorrectType(const LLFolderViewEventListener *
LLFolderView *LLPanelOutfitsInventory::getRootFolder()
{
return mInventoryPanel->getRootFolder();
return mActivePanel->getRootFolder();
}
//////////////////////////////////////////////////////////////////////////////////
@ -349,3 +345,56 @@ bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropTy
// List Commands //
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Accordion //
void LLPanelOutfitsInventory::initAccordionPanels()
{
mAccordionPanels.resize(2);
LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>("outfitslist_accordionpanel");
myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, TRUE);
myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
mAccordionPanels[0] = myoutfits_panel;
mActivePanel = myoutfits_panel;
LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>("cof_accordionpanel");
cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
mAccordionPanels[1] = cof_panel;
for (accordionpanels_vec_t::iterator iter = mAccordionPanels.begin();
iter != mAccordionPanels.end();
++iter)
{
LLInventoryPanel *panel = (*iter);
panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onAccordionSelectionChange, this, panel, _1, _2));
}
}
void LLPanelOutfitsInventory::onAccordionSelectionChange(LLInventoryPanel* accordion_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
{
if (user_action && items.size() > 0)
{
for (accordionpanels_vec_t::iterator iter = mAccordionPanels.begin();
iter != mAccordionPanels.end();
++iter)
{
LLInventoryPanel *panel = (*iter);
if (panel == accordion_panel)
{
mActivePanel = panel;
}
else
{
panel->getRootFolder()->clearSelection();
}
}
}
onSelectionChange(items, user_action);
}
LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel()
{
return mActivePanel;
}

View File

@ -61,8 +61,6 @@ public:
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();
@ -74,9 +72,25 @@ protected:
private:
LLSidepanelAppearance* mParent;
LLInventoryPanel* mInventoryPanel;
LLSaveFolderState* mSavedFolderState;
public:
//////////////////////////////////////////////////////////////////////////////////
// Accordion //
LLInventoryPanel* getActivePanel();
protected:
void initAccordionPanels();
void onAccordionSelectionChange(LLInventoryPanel* accordion_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
private:
LLInventoryPanel* mActivePanel;
typedef std::vector<LLInventoryPanel *> accordionpanels_vec_t;
accordionpanels_vec_t mAccordionPanels;
// Accordion //
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// List Commands //
@ -95,7 +109,7 @@ private:
LLPanel* mListCommands;
LLMenuGL* mMenuGearDefault;
LLMenuGL* mMenuAdd;
// //
// List Commands //
////////////////////////////////////////////////////////////////////////////////
};

View File

@ -6,6 +6,18 @@
width="310"
border="true"
follows="left|top|right|bottom">
<accordion
follows="left|top|right|bottom"
height="315"
layout="topleft"
left="0"
name="outfits_accordion"
top="2"
width="310">
<accordion_tab
layout="topleft"
name="tab_outfits"
title="Outfits bar">
<inventory_panel
allow_multi_select="true"
border="true"
@ -14,9 +26,28 @@
height="326"
left="0"
mouse_opaque="true"
name="outfits_list"
name="outfitslist_accordionpanel"
width="310"
start_folder="My Outfits"/>
</accordion_tab>
<accordion_tab
layout="topleft"
name="tab_cof"
title="Current Outfit bar">
<inventory_panel
allow_multi_select="true"
border="true"
bottom="0"
follows="left|top|right|bottom"
height="326"
left="0"
mouse_opaque="true"
name="cof_accordionpanel"
width="310"
start_folder="Current Outfit"/>
</accordion_tab>
</accordion>
<button bottom="0"
halign="center"
height="16"