diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llinspecttexture.cpp | 14 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 5 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.h | 9 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.cpp | 924 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.h | 233 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.cpp | 11 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.h | 5 | ||||
-rw-r--r-- | indra/newview/llpanelmaininventory.cpp | 157 | ||||
-rw-r--r-- | indra/newview/llpanelmaininventory.h | 18 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_inventory_view_default.xml | 1 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_inventory_gallery.xml | 37 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml | 63 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_main_inventory.xml | 23 |
14 files changed, 1459 insertions, 43 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7c30d8eba8..d587f8bfc4 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -380,6 +380,7 @@ set(viewer_SOURCE_FILES llinventorybridge.cpp llinventoryfilter.cpp llinventoryfunctions.cpp + llinventorygallery.cpp llinventoryicon.cpp llinventoryitemslist.cpp llinventorylistitem.cpp @@ -1023,6 +1024,7 @@ set(viewer_HEADER_FILES llinventorybridge.h llinventoryfilter.h llinventoryfunctions.h + llinventorygallery.h llinventoryicon.h llinventoryitemslist.h llinventorylistitem.h diff --git a/indra/newview/llinspecttexture.cpp b/indra/newview/llinspecttexture.cpp index 843b4da757..82676bced8 100644 --- a/indra/newview/llinspecttexture.cpp +++ b/indra/newview/llinspecttexture.cpp @@ -38,20 +38,6 @@ // Helper functions // -class LLIsTextureType : public LLInventoryCollectFunctor -{ -public: - LLIsTextureType() {} - virtual ~LLIsTextureType() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item); -}; - -bool LLIsTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) -{ - return item && (item->getType() == LLAssetType::AT_TEXTURE); -} - LLToolTip* LLInspectTextureUtil::createInventoryToolTip(LLToolTip::Params p) { const LLSD& sdTooltip = p.create_params; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index dd116ce2d2..68722e91b3 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2352,6 +2352,11 @@ void LLFindWearablesOfType::setType(LLWearableType::EType type) mWearableType = type; } +bool LLIsTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) +{ + return item && (item->getType() == LLAssetType::AT_TEXTURE); +} + bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if (item) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 1cc778f8a5..918e919e61 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -472,6 +472,15 @@ private: LLWearableType::EType mWearableType; }; +class LLIsTextureType : public LLInventoryCollectFunctor +{ +public: + LLIsTextureType() {} + virtual ~LLIsTextureType() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); +}; + /** Filter out wearables-links */ class LLFindActualWearablesOfType : public LLFindWearablesOfType { diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp new file mode 100644 index 0000000000..b5fd3aaece --- /dev/null +++ b/indra/newview/llinventorygallery.cpp @@ -0,0 +1,924 @@ +/** + * @file llinventorygallery.cpp + * @brief LLInventoryGallery class implementation + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinventorygallery.h" + +#include "llaccordionctrltab.h" +#include "llcommonutils.h" +#include "lliconctrl.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llthumbnailctrl.h" +#include "lltextbox.h" +#include "llviewerfoldertype.h" + +#include "llinventoryicon.h" + +static LLPanelInjector<LLInventoryGallery> t_inventory_gallery("inventory_gallery"); + +const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; + +LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) + : LLPanel(), + mScrollPanel(NULL), + mGalleryPanel(NULL), + mLastRowPanel(NULL), + mGalleryCreated(false), + mRowCount(0), + mItemsAddedCount(0), + mRowPanelHeight(p.row_panel_height), + mVerticalGap(p.vertical_gap), + mHorizontalGap(p.horizontal_gap), + mItemWidth(p.item_width), + mItemHeight(p.item_height), + mItemHorizontalGap(p.item_horizontal_gap), + mItemsInRow(p.items_in_row), + mRowPanWidthFactor(p.row_panel_width_factor), + mGalleryWidthFactor(p.gallery_width_factor), + mIsInitialized(false) +{ + updateGalleryWidth(); +} + +LLInventoryGallery::Params::Params() + : row_panel_height("row_panel_height", 180), + vertical_gap("vertical_gap", 10), + horizontal_gap("horizontal_gap", 10), + item_width("item_width", 150), + item_height("item_height", 175), + item_horizontal_gap("item_horizontal_gap", 16), + items_in_row("items_in_row", GALLERY_ITEMS_PER_ROW_MIN), + row_panel_width_factor("row_panel_width_factor", 166), + gallery_width_factor("gallery_width_factor", 163) +{ + addSynonym(row_panel_height, "row_height"); +} + +const LLInventoryGallery::Params& LLInventoryGallery::getDefaultParams() +{ + return LLUICtrlFactory::getDefaultParams<LLInventoryGallery>(); +} + +BOOL LLInventoryGallery::postBuild() +{ + mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel"); + LLPanel::Params params = LLPanel::getDefaultParams(); + mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params); + mMessageTextBox = getChild<LLTextBox>("empty_txt"); + + return TRUE; +} + +LLInventoryGallery::~LLInventoryGallery() +{ + while (!mUnusedRowPanels.empty()) + { + LLPanel* panelp = mUnusedRowPanels.back(); + mUnusedRowPanels.pop_back(); + panelp->die(); + } + while (!mUnusedItemPanels.empty()) + { + LLPanel* panelp = mUnusedItemPanels.back(); + mUnusedItemPanels.pop_back(); + panelp->die(); + } + + if (gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; +} + +void LLInventoryGallery::setRootFolder(const LLUUID cat_id) +{ + LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); + if(!category || (mFolderID == cat_id)) + { + return; + } + if(mFolderID.notNull()) + { + mBackwardFolders.push_back(mFolderID); + } + mFolderID = cat_id; + updateRootFolder(); +} + +void LLInventoryGallery::updateRootFolder() +{ + if (mIsInitialized) + { + S32 count = mItemsAddedCount; + for (S32 i = count - 1; i >= 0; i--) + { + updateRemovedItem(mItems[i]->getUUID()); + } + + if (gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + } + { + mRootChangedSignal(); + + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + + // Start observing changes in selected category. + mCategoriesObserver->addCategory(mFolderID, + boost::bind(&LLInventoryGallery::refreshList, this, mFolderID)); + + LLViewerInventoryCategory* category = gInventory.getCategory(mFolderID); + //If not all items are fetched now + // the observer will refresh the list as soon as the new items + // arrive. + category->fetch(); + + //refreshList(cat_id); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + + gInventory.getDirectDescendentsOf(mFolderID, cat_array, item_array); + + // Creating a vector of newly collected sub-categories UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array->begin(); + iter != cat_array->end(); + iter++) + { + updateAddedItem((*iter)->getUUID()); + } + + for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin(); + iter != item_array->end(); + iter++) + { + updateAddedItem((*iter)->getUUID()); + } + reArrangeRows(); + mIsInitialized = true; + + if (mScrollPanel) + { + mScrollPanel->goToTop(); + } + } + + if (!mGalleryCreated) + { + initGallery(); + } +} + +void LLInventoryGallery::initGallery() +{ + if (!mGalleryCreated) + { + uuid_vec_t cats; + getCurrentCategories(cats); + int n = cats.size(); + buildGalleryPanel(n); + mScrollPanel->addChild(mGalleryPanel); + for (int i = 0; i < n; i++) + { + addToGallery(mItemMap[cats[i]]); + } + reArrangeRows(); + mGalleryCreated = true; + } +} + +void LLInventoryGallery::draw() +{ + LLPanel::draw(); + if (mGalleryCreated) + { + updateRowsIfNeeded(); + } +} + +void LLInventoryGallery::updateRowsIfNeeded() +{ + if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) + { + reArrangeRows(1); + } + else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > GALLERY_ITEMS_PER_ROW_MIN) + { + reArrangeRows(-1); + } +} + +bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) +{ + if (item1->getSortGroup() != item2->getSortGroup()) + { + return (item1->getSortGroup() < item2->getSortGroup()); + } + if(((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + { + std::string name1 = item1->getItemName(); + std::string name2 = item2->getItemName(); + + return (LLStringUtil::compareDict(name1, name2) < 0); + } + else + { + return item2->isDefaultImage(); + } +} + +void LLInventoryGallery::reArrangeRows(S32 row_diff) +{ + std::vector<LLInventoryGalleryItem*> buf_items = mItems; + for (std::vector<LLInventoryGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) + { + removeFromGalleryLast(*it); + } + for (std::vector<LLInventoryGalleryItem*>::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it) + { + buf_items.push_back(*it); + } + mHiddenItems.clear(); + + mItemsInRow+= row_diff; + updateGalleryWidth(); + std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); + + for (std::vector<LLInventoryGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) + { + (*it)->setHidden(false); + applyFilter(*it, mFilterSubString); + addToGallery(*it); + } + updateMessageVisibility(); +} + +void LLInventoryGallery::updateGalleryWidth() +{ + mRowPanelWidth = mRowPanWidthFactor * mItemsInRow - mItemHorizontalGap; + mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap; +} + +LLPanel* LLInventoryGallery::addLastRow() +{ + mRowCount++; + int row = 0; + int vgap = mVerticalGap * row; + LLPanel* result = buildRowPanel(0, row * mRowPanelHeight + vgap); + mGalleryPanel->addChild(result); + return result; +} + +void LLInventoryGallery::moveRowUp(int row) +{ + moveRow(row, mRowCount - 1 - row + 1); +} + +void LLInventoryGallery::moveRowDown(int row) +{ + moveRow(row, mRowCount - 1 - row - 1); +} + +void LLInventoryGallery::moveRow(int row, int pos) +{ + int vgap = mVerticalGap * pos; + moveRowPanel(mRowPanels[row], 0, pos * mRowPanelHeight + vgap); +} + +void LLInventoryGallery::removeLastRow() +{ + mRowCount--; + mGalleryPanel->removeChild(mLastRowPanel); + mUnusedRowPanels.push_back(mLastRowPanel); + mRowPanels.pop_back(); + if (mRowPanels.size() > 0) + { + // Just removed last row + mLastRowPanel = mRowPanels.back(); + } + else + { + mLastRowPanel = NULL; + } +} + +LLPanel* LLInventoryGallery::addToRow(LLPanel* row_stack, LLInventoryGalleryItem* item, int pos, int hgap) +{ + LLPanel* lpanel = buildItemPanel(pos * mItemWidth + hgap); + lpanel->addChild(item); + row_stack->addChild(lpanel); + mItemPanels.push_back(lpanel); + return lpanel; +} + +void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.push_back(item); + return; + } + mItemsAddedCount++; + mItemIndexMap[item] = mItemsAddedCount - 1; + int n = mItemsAddedCount; + int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; + int n_prev = n - 1; + int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + + bool add_row = row_count != row_count_prev; + int pos = 0; + if (add_row) + { + for (int i = 0; i < row_count_prev; i++) + { + moveRowUp(i); + } + mLastRowPanel = addLastRow(); + mRowPanels.push_back(mLastRowPanel); + } + pos = (n - 1) % mItemsInRow; + mItems.push_back(item); + addToRow(mLastRowPanel, item, pos, mHorizontalGap * pos); + reshapeGalleryPanel(row_count); +} + + +void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.pop_back(); + return; + } + int n_prev = mItemsAddedCount; + int n = mItemsAddedCount - 1; + int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; + int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + mItemsAddedCount--; + + bool remove_row = row_count != row_count_prev; + removeFromLastRow(mItems[mItemsAddedCount]); + mItems.pop_back(); + if (remove_row) + { + for (int i = 0; i < row_count_prev - 1; i++) + { + moveRowDown(i); + } + removeLastRow(); + } + reshapeGalleryPanel(row_count); +} + + +void LLInventoryGallery::removeFromGalleryMiddle(LLInventoryGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end()); + return; + } + int n = mItemIndexMap[item]; + mItemIndexMap.erase(item); + std::vector<LLInventoryGalleryItem*> saved; + for (int i = mItemsAddedCount - 1; i > n; i--) + { + saved.push_back(mItems[i]); + removeFromGalleryLast(mItems[i]); + } + removeFromGalleryLast(mItems[n]); + int saved_count = saved.size(); + for (int i = 0; i < saved_count; i++) + { + addToGallery(saved.back()); + saved.pop_back(); + } +} + +void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) +{ + mItemPanels.back()->removeChild(item); + mLastRowPanel->removeChild(mItemPanels.back()); + mUnusedItemPanels.push_back(mItemPanels.back()); + mItemPanels.pop_back(); +} + +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id) +{ + LLInventoryGalleryItem::Params giparams; + LLInventoryGalleryItem* gitem = LLUICtrlFactory::create<LLInventoryGalleryItem>(giparams); + gitem->reshape(mItemWidth, mItemHeight); + gitem->setVisible(true); + gitem->setFollowsLeft(); + gitem->setFollowsTop(); + gitem->setName(name); + gitem->setUUID(item_id); + gitem->setGallery(this); + gitem->setType(type); + gitem->setThumbnail(thumbnail_id); + return gitem; +} + +void LLInventoryGallery::buildGalleryPanel(int row_count) +{ + LLPanel::Params params; + mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params); + reshapeGalleryPanel(row_count); +} + +void LLInventoryGallery::reshapeGalleryPanel(int row_count) +{ + int bottom = 0; + int left = 0; + int height = row_count * (mRowPanelHeight + mVerticalGap); + LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom); + mGalleryPanel->setRect(rect); + mGalleryPanel->reshape(mGalleryWidth, height); + mGalleryPanel->setVisible(true); + mGalleryPanel->setFollowsLeft(); + mGalleryPanel->setFollowsTop(); +} + +LLPanel* LLInventoryGallery::buildItemPanel(int left) +{ + LLPanel::Params lpparams; + int top = 0; + LLPanel* lpanel = NULL; + if(mUnusedItemPanels.empty()) + { + lpanel = LLUICtrlFactory::create<LLPanel>(lpparams); + } + else + { + lpanel = mUnusedItemPanels.back(); + mUnusedItemPanels.pop_back(); + } + LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); + lpanel->setRect(rect); + lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight); + lpanel->setVisible(true); + lpanel->setFollowsLeft(); + lpanel->setFollowsTop(); + return lpanel; +} + +LLPanel* LLInventoryGallery::buildRowPanel(int left, int bottom) +{ + LLPanel::Params sparams; + LLPanel* stack = NULL; + if(mUnusedRowPanels.empty()) + { + stack = LLUICtrlFactory::create<LLPanel>(sparams); + } + else + { + stack = mUnusedRowPanels.back(); + mUnusedRowPanels.pop_back(); + } + moveRowPanel(stack, left, bottom); + return stack; +} + +void LLInventoryGallery::moveRowPanel(LLPanel* stack, int left, int bottom) +{ + LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom); + stack->setRect(rect); + stack->reshape(mRowPanelWidth, mRowPanelHeight); + stack->setVisible(true); + stack->setFollowsLeft(); + stack->setFollowsTop(); +} + +void LLInventoryGallery::setFilterSubString(const std::string& string) +{ + mFilterSubString = string; + reArrangeRows(); +} + +void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring) +{ + if (!item) return; + + std::string item_name = item->getItemName(); + LLStringUtil::toUpper(item_name); + + std::string cur_filter = filter_substring; + LLStringUtil::toUpper(cur_filter); + + bool hidden = (std::string::npos == item_name.find(cur_filter)); + item->setHidden(hidden); +} + +void LLInventoryGallery::getCurrentCategories(uuid_vec_t& vcur) +{ + for (gallery_item_map_t::const_iterator iter = mItemMap.begin(); + iter != mItemMap.end(); + iter++) + { + if ((*iter).second != NULL) + { + vcur.push_back((*iter).first); + } + } +} + +void LLInventoryGallery::updateAddedItem(LLUUID item_id) +{ + LLInventoryObject* obj = gInventory.getObject(item_id); + if (!obj) + { + LL_WARNS("InventoryGallery") << "Failed to find item: " << item_id << LL_ENDL; + return; + } + + LLUUID thumbnail_id = obj->getThumbnailUUID();; + + if ((LLAssetType::AT_CATEGORY == obj->getType()) && thumbnail_id.isNull()) + { + thumbnail_id = getOutfitImageID(item_id); + } + + LLInventoryGalleryItem* item = buildGalleryItem(obj->getName(), item_id, obj->getType(), thumbnail_id); + mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); + + item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); + if (mGalleryCreated) + { + addToGallery(item); + } +} + +void LLInventoryGallery::updateRemovedItem(LLUUID item_id) +{ + gallery_item_map_t::iterator item_iter = mItemMap.find(item_id); + if (item_iter != mItemMap.end()) + { + LLInventoryGalleryItem* item = item_iter->second; + + deselectItem(item_id); + mItemMap.erase(item_iter); + removeFromGalleryMiddle(item); + + // kill removed item + if (item != NULL) + { + item->die(); + } + } + +} + +void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) +{ + gallery_item_map_t::iterator iter = mItemMap.find(item_id); + if (iter != mItemMap.end()) + { + LLInventoryGalleryItem* item = iter->second; + if (item) + { + item->setName(name); + } + } +} + +void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) +{ + if (mSelectedItemID == category_id) + return; + + if (mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(FALSE); + } + if (mItemMap[category_id]) + { + mItemMap[category_id]->setSelected(TRUE); + } + mSelectedItemID = category_id; + signalSelectionItemID(category_id); +} + +void LLInventoryGallery::updateMessageVisibility() +{ + mMessageTextBox->setVisible(mItems.empty()); + mScrollPanel->setVisible(!mItems.empty()); +} + +void LLInventoryGallery::refreshList(const LLUUID& category_id) +{ + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + + gInventory.getDirectDescendentsOf(category_id, cat_array, item_array); + uuid_vec_t vadded; + uuid_vec_t vremoved; + + // Create added and removed items vectors. + computeDifference(*cat_array, *item_array, vadded, vremoved); + + // Handle added tabs. + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + ++iter) + { + const LLUUID cat_id = (*iter); + updateAddedItem(cat_id); + } + + // Handle removed tabs. + for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + { + const LLUUID cat_id = (*iter); + updateRemovedItem(cat_id); + } + + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); + items_iter != changed_items.end(); + ++items_iter) + { + LLInventoryObject* obj = gInventory.getObject(*items_iter); + if(!obj) + { + return; + } + + updateChangedItemName(*items_iter, obj->getName()); + } + +} + +void LLInventoryGallery::computeDifference( + const LLInventoryModel::cat_array_t vcats, + const LLInventoryModel::item_array_t vitems, + uuid_vec_t& vadded, + uuid_vec_t& vremoved) +{ + uuid_vec_t vnew; + // Creating a vector of newly collected UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); + iter != vcats.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + for (LLInventoryModel::item_array_t::const_iterator iter = vitems.begin(); + iter != vitems.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + + uuid_vec_t vcur; + getCurrentCategories(vcur); + + LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); +} + +void LLInventoryGallery::deselectItem(const LLUUID& category_id) +{ + // Reset selection if the item is selected. + if (category_id == mSelectedItemID) + { + mSelectedItemID = LLUUID::null; + signalSelectionItemID(mSelectedItemID); + } +} + +void LLInventoryGallery::signalSelectionItemID(const LLUUID& category_id) +{ + mSelectionChangeSignal(category_id); +} + +boost::signals2::connection LLInventoryGallery::setSelectionChangeCallback(selection_change_callback_t cb) +{ + return mSelectionChangeSignal.connect(cb); +} + +LLUUID LLInventoryGallery::getOutfitImageID(LLUUID outfit_id) +{ + LLUUID thumbnail_id; + LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_id); + if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + // Not LLIsOfAssetType, because we allow links + LLIsTextureType f; + gInventory.getDirectDescendentsOf(outfit_id, cats, items, f); + + // Exactly one texture found => show the texture as thumbnail + if (1 == items.size()) + { + LLViewerInventoryItem* item = items.front(); + if (item && item->getIsLinkType()) + { + item = item->getLinkedItem(); + } + if (item) + { + thumbnail_id = item->getAssetUUID(); + } + } + } + return thumbnail_id; +} + +boost::signals2::connection LLInventoryGallery::setRootChangedCallback(root_changed_callback_t cb) +{ + return mRootChangedSignal.connect(cb); +} + +void LLInventoryGallery::onForwardFolder() +{ + if(isForwardAvailable()) + { + mBackwardFolders.push_back(mFolderID); + mFolderID = mForwardFolders.back(); + mForwardFolders.pop_back(); + updateRootFolder(); + } +} + +void LLInventoryGallery::onBackwardFolder() +{ + if(isBackwardAvailable()) + { + mForwardFolders.push_back(mFolderID); + mFolderID = mBackwardFolders.back(); + mBackwardFolders.pop_back(); + updateRootFolder(); + } +} + +void LLInventoryGallery::clearNavigationHistory() +{ + mForwardFolders.clear(); + mBackwardFolders.clear(); +} + +bool LLInventoryGallery::isBackwardAvailable() +{ + return (!mBackwardFolders.empty() && (mFolderID != mBackwardFolders.back())); +} + +bool LLInventoryGallery::isForwardAvailable() +{ + return (!mForwardFolders.empty() && (mFolderID != mForwardFolders.back())); +} +//----------------------------- +// LLInventoryGalleryItem +//----------------------------- + +static LLDefaultChildRegistry::Register<LLInventoryGalleryItem> r("inventory_gallery_item"); + +LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) + : LLPanel(p), + mSelected(false), + mDefaultImage(true), + mName(""), + mUUID(LLUUID()), + mIsFolder(true), + mGallery(NULL), + mType(LLAssetType::AT_NONE), + mSortGroup(SG_ITEM) +{ + buildFromFile("panel_inventory_gallery_item.xml"); +} + +LLInventoryGalleryItem::~LLInventoryGalleryItem() +{ +} + +BOOL LLInventoryGalleryItem::postBuild() +{ + mNameText = getChild<LLTextBox>("item_name"); + + mTextBgPanel = getChild<LLPanel>("text_bg_panel"); + mHidden = false; + return TRUE; +} + +void LLInventoryGalleryItem::setType(LLAssetType::EType type) +{ + mType = type; + mIsFolder = (mType == LLAssetType::AT_CATEGORY); + + std::string icon_name = LLInventoryIcon::getIconName(mType); + if(mIsFolder) + { + mSortGroup = SG_NORMAL_FOLDER; + LLViewerInventoryCategory * cat = gInventory.getCategory(mUUID); + if (cat) + { + LLFolderType::EType preferred_type = cat->getPreferredType(); + icon_name = LLViewerFolderType::lookupIconName(preferred_type); + + if (preferred_type == LLFolderType::FT_TRASH) + { + mSortGroup = SG_TRASH_FOLDER; + } + else if(LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + mSortGroup = SG_SYSTEM_FOLDER; + } + } + } + + getChild<LLIconCtrl>("item_type")->setValue(icon_name); +} + +void LLInventoryGalleryItem::setThumbnail(LLUUID id) +{ + mDefaultImage = id.isNull(); + if(mDefaultImage) + { + getChild<LLThumbnailCtrl>("preview_thumbnail")->setValue("Thumbnail_Fallback"); + } + else + { + getChild<LLThumbnailCtrl>("preview_thumbnail")->setValue(id); + } +} + +void LLInventoryGalleryItem::draw() +{ + LLPanel::draw(); + + // Draw border + LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); + LLRect border = getChildView("preview_thumbnail")->getRect(); + border.mRight = border.mRight + 1; + gl_rect_2d(border, border_color.get(), FALSE); +} + +void LLInventoryGalleryItem::setName(std::string name) +{ + mNameText->setText(name); + mNameText->setToolTip(name); + mName = name; +} + +void LLInventoryGalleryItem::setSelected(bool value) +{ + mSelected = value; + mTextBgPanel->setBackgroundVisible(value); +} + +BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + return LLUICtrl::handleMouseDown(x, y, mask); +} + +BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + return LLUICtrl::handleRightMouseDown(x, y, mask); +} + +BOOL LLInventoryGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if (mIsFolder && mGallery) + { + mGallery->setRootFolder(mUUID); + } + else + { + LLInvFVBridgeAction::doAction(mUUID,&gInventory); + //todo: some item types require different handling + } + + return TRUE; +} + diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h new file mode 100644 index 0000000000..ab9d27e260 --- /dev/null +++ b/indra/newview/llinventorygallery.h @@ -0,0 +1,233 @@ +/** + * @file llinventorygallery.h + * @brief LLInventoryGallery class definition + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYGALLERY_H +#define LL_LLINVENTORYGALLERY_H + +#include "llpanel.h" +#include "llinventorymodel.h" + +class LLInventoryCategoriesObserver; +class LLInventoryGalleryItem; +class LLScrollContainer; +class LLTextBox; + +class LLInventoryGallery : public LLPanel +{ +public: + + typedef boost::signals2::signal<void(const LLUUID&)> selection_change_signal_t; + typedef boost::function<void(const LLUUID&)> selection_change_callback_t; + + struct Params + : public LLInitParam::Block<Params, LLPanel::Params> + { + Optional<S32> row_panel_height; + Optional<S32> row_panel_width_factor; + Optional<S32> gallery_width_factor; + Optional<S32> vertical_gap; + Optional<S32> horizontal_gap; + Optional<S32> item_width; + Optional<S32> item_height; + Optional<S32> item_horizontal_gap; + Optional<S32> items_in_row; + + Params(); + }; + + static const LLInventoryGallery::Params& getDefaultParams(); + + LLInventoryGallery(const LLInventoryGallery::Params& params = getDefaultParams()); + ~LLInventoryGallery(); + + BOOL postBuild(); + void initGallery(); + void draw(); + + void setFilterSubString(const std::string& string); + std::string getFilterSubString() { return mFilterSubString; } + + void getCurrentCategories(uuid_vec_t& vcur); + void updateAddedItem(LLUUID item_id); + void updateRemovedItem(LLUUID item_id); + void updateChangedItemName(LLUUID item_id, std::string name); + + void updateMessageVisibility(); + + void setRootFolder(const LLUUID cat_id); + void updateRootFolder(); + LLUUID getRootFolder() { return mFolderID; } + typedef boost::function<void()> root_changed_callback_t; + boost::signals2::connection setRootChangedCallback(root_changed_callback_t cb); + void onForwardFolder(); + void onBackwardFolder(); + void clearNavigationHistory(); + bool isBackwardAvailable(); + bool isForwardAvailable(); + + void setNavBackwardList(std::list<LLUUID> backward_list) { mBackwardFolders = backward_list; } + void setNavForwardList(std::list<LLUUID> forward_list) { mForwardFolders = forward_list; } + std::list<LLUUID> getNavBackwardList() { return mBackwardFolders; } + std::list<LLUUID> getNavForwardList() { return mForwardFolders; } + + LLUUID getOutfitImageID(LLUUID outfit_id); + + void refreshList(const LLUUID& category_id); + void computeDifference(const LLInventoryModel::cat_array_t vcats, const LLInventoryModel::item_array_t vitems, uuid_vec_t& vadded, uuid_vec_t& vremoved); + + void deselectItem(const LLUUID& category_id); + void signalSelectionItemID(const LLUUID& category_id); + boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); + +protected: + + void onChangeItemSelection(const LLUUID& category_id); + + void applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring); + + LLInventoryCategoriesObserver* mCategoriesObserver; + LLUUID mSelectedItemID; + bool mIsInitialized; + + selection_change_signal_t mSelectionChangeSignal; + boost::signals2::signal<void()> mRootChangedSignal; + LLUUID mFolderID; + std::list<LLUUID> mBackwardFolders; + std::list<LLUUID> mForwardFolders; + +private: + void addToGallery(LLInventoryGalleryItem* item); + void removeFromGalleryLast(LLInventoryGalleryItem* item); + void removeFromGalleryMiddle(LLInventoryGalleryItem* item); + LLPanel* addLastRow(); + void removeLastRow(); + void moveRowUp(int row); + void moveRowDown(int row); + void moveRow(int row, int pos); + LLPanel* addToRow(LLPanel* row_stack, LLInventoryGalleryItem* item, int pos, int hgap); + void removeFromLastRow(LLInventoryGalleryItem* item); + void reArrangeRows(S32 row_diff = 0); + void updateRowsIfNeeded(); + void updateGalleryWidth(); + + LLInventoryGalleryItem* buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id); + + void buildGalleryPanel(int row_count); + void reshapeGalleryPanel(int row_count); + LLPanel* buildItemPanel(int left); + LLPanel* buildRowPanel(int left, int bottom); + void moveRowPanel(LLPanel* stack, int left, int bottom); + + std::vector<LLPanel*> mRowPanels; + std::vector<LLPanel*> mItemPanels; + std::vector<LLPanel*> mUnusedRowPanels; + std::vector<LLPanel*> mUnusedItemPanels; + std::vector<LLInventoryGalleryItem*> mItems; + std::vector<LLInventoryGalleryItem*> mHiddenItems; + LLScrollContainer* mScrollPanel; + LLPanel* mGalleryPanel; + LLPanel* mLastRowPanel; + LLTextBox* mMessageTextBox; + int mRowCount; + int mItemsAddedCount; + bool mGalleryCreated; + + /* Params */ + int mRowPanelHeight; + int mVerticalGap; + int mHorizontalGap; + int mItemWidth; + int mItemHeight; + int mItemHorizontalGap; + int mItemsInRow; + int mRowPanelWidth; + int mGalleryWidth; + int mRowPanWidthFactor; + int mGalleryWidthFactor; + + std::string mFilterSubString; + + typedef std::map<LLUUID, LLInventoryGalleryItem*> gallery_item_map_t; + gallery_item_map_t mItemMap; + std::map<LLInventoryGalleryItem*, S32> mItemIndexMap; +}; + +class LLInventoryGalleryItem : public LLPanel +{ +public: + struct Params : public LLInitParam::Block<Params, LLPanel::Params> + {}; + + enum EInventorySortGroup + { + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM + }; + + LLInventoryGalleryItem(const Params& p); + virtual ~LLInventoryGalleryItem(); + + BOOL postBuild(); + void draw(); + BOOL handleMouseDown(S32 x, S32 y, MASK mask); + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + + void setName(std::string name); + void setSelected(bool value); + void setUUID(LLUUID id) {mUUID = id;} + LLUUID getUUID() { return mUUID;} + + std::string getItemName() {return mName;} + bool isDefaultImage() {return mDefaultImage;} + + bool isHidden() {return mHidden;} + void setHidden(bool hidden) {mHidden = hidden;} + + void setType(LLAssetType::EType type); + void setThumbnail(LLUUID id); + void setGallery(LLInventoryGallery* gallery) { mGallery = gallery; } + bool isFolder() { return mIsFolder; } + EInventorySortGroup getSortGroup() { return mSortGroup; } + +private: + LLUUID mUUID; + LLTextBox* mNameText; + LLPanel* mTextBgPanel; + bool mSelected; + bool mDefaultImage; + bool mHidden; + bool mIsFolder; + + EInventorySortGroup mSortGroup; + LLAssetType::EType mType; + std::string mName; + LLInventoryGallery* mGallery; +}; + +#endif diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 7d4abab98f..caaff79c06 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2097,12 +2097,15 @@ void LLInventorySingleFolderPanel::openInCurrentWindow(const LLSD& userdata) void LLInventorySingleFolderPanel::changeFolderRoot(const LLUUID& new_id) { - if(mFolderID.notNull()) + if (mFolderID != new_id) { - mBackwardFolders.push_back(mFolderID); + if(mFolderID.notNull()) + { + mBackwardFolders.push_back(mFolderID); + } + mFolderID = new_id; + updateSingleFolderRoot(); } - mFolderID = new_id; - updateSingleFolderRoot(); } void LLInventorySingleFolderPanel::onForwardFolder() diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 31dd7aec23..b2c27daeec 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -406,6 +406,11 @@ public: bool isBackwardAvailable(); bool isForwardAvailable(); + void setNavBackwardList(std::list<LLUUID> backward_list) { mBackwardFolders = backward_list; } + void setNavForwardList(std::list<LLUUID> forward_list) { mForwardFolders = forward_list; } + std::list<LLUUID> getNavBackwardList() { return mBackwardFolders; } + std::list<LLUUID> getNavForwardList() { return mForwardFolders; } + void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb); typedef boost::function<void()> root_changed_callback_t; diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 9fab6e4d2e..a867077ab0 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -37,6 +37,7 @@ #include "llfilepicker.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" +#include "llinventorygallery.h" #include "llinventorymodelbackgroundfetch.h" #include "llfiltereditor.h" #include "llfloatersidepanelcontainer.h" @@ -115,7 +116,9 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mNeedUploadCost(true), mMenuViewDefault(NULL), mSingleFolderMode(false), - mFolderRootChangedConnection() + mViewMode(VIEW_LIST), + mListViewRootUpdatedConnection(), + mGalleryRootUpdatedConnection() { // Menu Callbacks (non contex menus) mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2)); @@ -242,9 +245,12 @@ BOOL LLPanelMainInventory::postBuild() mViewMenuButton = getChild<LLMenuButton>("view_btn"); mSingleFolderPanelInventory = getChild<LLInventorySingleFolderPanel>("single_folder_inv"); - mFolderRootChangedConnection = mSingleFolderPanelInventory->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this)); + mListViewRootUpdatedConnection = mSingleFolderPanelInventory->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this)); mSingleFolderPanelInventory->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mSingleFolderPanelInventory, _1, _2)); + mInventoryGalleryPanel = getChild<LLInventoryGallery>("gallery_view_inv"); + mGalleryRootUpdatedConnection = mInventoryGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this)); + initListCommandsHandlers(); const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); @@ -322,9 +328,13 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) mMenuAddHandle.markDead(); } - if (mFolderRootChangedConnection.connected()) + if (mListViewRootUpdatedConnection.connected()) + { + mListViewRootUpdatedConnection.disconnect(); + } + if (mGalleryRootUpdatedConnection.connected()) { - mFolderRootChangedConnection.disconnect(); + mGalleryRootUpdatedConnection.disconnect(); } } @@ -635,10 +645,18 @@ void LLPanelMainInventory::onClearSearch() void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) { + if(mSingleFolderMode && isGalleryViewMode()) + { + mFilterSubString = search_string; + mInventoryGalleryPanel->setFilterSubString(mFilterSubString); + return; + } + if (search_string == "") { onClearSearch(); } + if (!mActivePanel) { return; @@ -863,8 +881,9 @@ void LLPanelMainInventory::updateItemcountText() { LLInventoryModel::cat_array_t *cats; LLInventoryModel::item_array_t *items; - gInventory.getDirectDescendentsOf(mSingleFolderPanelInventory->getSingleFolderRoot(), cats, items); - + + gInventory.getDirectDescendentsOf(getCurrentSFVRoot(), cats, items); + string_args["[ITEM_COUNT]"] = llformat("%d", items->size()); string_args["[CATEGORY_COUNT]"] = llformat("%d", cats->size()); text = getString("ItemcountCompleted", string_args); @@ -1334,7 +1353,8 @@ void LLPanelMainInventory::toggleViewMode() mSingleFolderMode = !mSingleFolderMode; getChild<LLPanel>("default_inventory_panel")->setVisible(!mSingleFolderMode); - getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode); + getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode()); + getChild<LLPanel>("gallery_view_inventory")->setVisible(mSingleFolderMode && isGalleryViewMode()); getChild<LLLayoutPanel>("nav_buttons")->setVisible(mSingleFolderMode); getChild<LLButton>("view_mode_btn")->setImageOverlay(mSingleFolderMode ? getString("default_mode_btn") : getString("single_folder_mode_btn")); @@ -1362,7 +1382,10 @@ void LLPanelMainInventory::onViewModeClick() LLUUID new_root_folder; if(mSingleFolderMode) { - selected_folder = mSingleFolderPanelInventory->getSingleFolderRoot(); + if(isListViewMode()) + { + selected_folder = mSingleFolderPanelInventory->getSingleFolderRoot(); + } } else { @@ -1413,33 +1436,57 @@ void LLPanelMainInventory::onViewModeClick() void LLPanelMainInventory::onUpFolderClicked() { - const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot()); + const LLViewerInventoryCategory* cat = gInventory.getCategory(getCurrentSFVRoot()); if (cat) { if (cat->getParentUUID().notNull()) { - mSingleFolderPanelInventory->changeFolderRoot(cat->getParentUUID()); + if(isListViewMode()) + { + mSingleFolderPanelInventory->changeFolderRoot(cat->getParentUUID()); + } + if(isGalleryViewMode()) + { + mInventoryGalleryPanel->setRootFolder(cat->getParentUUID()); + } } } } void LLPanelMainInventory::onBackFolderClicked() { - mSingleFolderPanelInventory->onBackwardFolder(); + if(isListViewMode()) + { + mSingleFolderPanelInventory->onBackwardFolder(); + } + if(isGalleryViewMode()) + { + mInventoryGalleryPanel->onBackwardFolder(); + } } void LLPanelMainInventory::onForwardFolderClicked() { - mSingleFolderPanelInventory->onForwardFolder(); + if(isListViewMode()) + { + mSingleFolderPanelInventory->onForwardFolder(); + } + if(isGalleryViewMode()) + { + mInventoryGalleryPanel->onForwardFolder(); + } } void LLPanelMainInventory::setSingleFolderViewRoot(const LLUUID& folder_id, bool clear_nav_history) { - mSingleFolderPanelInventory->changeFolderRoot(folder_id); - if(clear_nav_history) + if(isListViewMode()) { - mSingleFolderPanelInventory->clearNavigationHistory(); - updateNavButtons(); + mSingleFolderPanelInventory->changeFolderRoot(folder_id); + if(clear_nav_history) + { + mSingleFolderPanelInventory->clearNavigationHistory(); + updateNavButtons(); + } } } @@ -1638,7 +1685,16 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) if (command_name == "include_links") { mActivePanel->getFilter().toggleSearchVisibilityLinks(); - } + } + + if (command_name == "list_view") + { + setViewMode(VIEW_LIST); + } + if (command_name == "gallery_view") + { + setViewMode(VIEW_GALLERY); + } } void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) @@ -1821,11 +1877,11 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata) if (command_name == "list_view") { - return true; + return isListViewMode(); } if (command_name == "gallery_view") { - return false; + return isGalleryViewMode(); } if (command_name == "combination_view") { @@ -1862,7 +1918,7 @@ void LLPanelMainInventory::updateTitle() { if(mSingleFolderMode) { - const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot()); + const LLViewerInventoryCategory* cat = gInventory.getCategory(getCurrentSFVRoot()); if (cat) { inventory_floater->setTitle(cat->getName()); @@ -1883,10 +1939,18 @@ void LLPanelMainInventory::updateTitle() void LLPanelMainInventory::updateNavButtons() { - getChild<LLButton>("back_btn")->setEnabled(mSingleFolderPanelInventory->isBackwardAvailable()); - getChild<LLButton>("forward_btn")->setEnabled(mSingleFolderPanelInventory->isForwardAvailable()); - - const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot()); + if(isListViewMode()) + { + getChild<LLButton>("back_btn")->setEnabled(mSingleFolderPanelInventory->isBackwardAvailable()); + getChild<LLButton>("forward_btn")->setEnabled(mSingleFolderPanelInventory->isForwardAvailable()); + } + if(isGalleryViewMode()) + { + getChild<LLButton>("back_btn")->setEnabled(mInventoryGalleryPanel->isBackwardAvailable()); + getChild<LLButton>("forward_btn")->setEnabled(mInventoryGalleryPanel->isForwardAvailable()); + } + + const LLViewerInventoryCategory* cat = gInventory.getCategory(getCurrentSFVRoot()); bool up_enabled = (cat && cat->getParentUUID().notNull()); getChild<LLButton>("up_btn")->setEnabled(up_enabled); } @@ -1900,5 +1964,50 @@ LLSidepanelInventory* LLPanelMainInventory::getParentSidepanelInventory() } return NULL; } + +void LLPanelMainInventory::setViewMode(EViewModeType mode) +{ + if(mode != mViewMode) + { + LLUUID cur_root = getCurrentSFVRoot(); + mViewMode = mode; + + getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode()); + getChild<LLPanel>("gallery_view_inventory")->setVisible(mSingleFolderMode && isGalleryViewMode()); + + if(isListViewMode()) + { + mSingleFolderPanelInventory->changeFolderRoot(cur_root); + mSingleFolderPanelInventory->setNavForwardList(mInventoryGalleryPanel->getNavForwardList()); + mSingleFolderPanelInventory->setNavBackwardList(mInventoryGalleryPanel->getNavBackwardList()); + } + if(isGalleryViewMode()) + { + mInventoryGalleryPanel->setRootFolder(cur_root); + mInventoryGalleryPanel->setNavForwardList(mSingleFolderPanelInventory->getNavForwardList()); + mInventoryGalleryPanel->setNavBackwardList(mSingleFolderPanelInventory->getNavBackwardList()); + } + updateNavButtons(); + + if((isListViewMode() && (mActivePanel->getFilterSubString() != mFilterSubString)) || + (isGalleryViewMode() && (mInventoryGalleryPanel->getFilterSubString() != mFilterSubString))) + { + onFilterEdit(mFilterSubString); + } + } +} + +LLUUID LLPanelMainInventory::getCurrentSFVRoot() +{ + if(isListViewMode()) + { + return mSingleFolderPanelInventory->getSingleFolderRoot(); + } + if(isGalleryViewMode()) + { + return mInventoryGalleryPanel->getRootFolder(); + } + return LLUUID::null; +} // List Commands // //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 5f488539dd..51c4ace874 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -38,6 +38,7 @@ class LLComboBox; class LLFolderViewItem; class LLInventoryPanel; +class LLInventoryGallery; class LLSaveFolderState; class LLFilterEditor; class LLTabContainer; @@ -65,6 +66,13 @@ public: BOOL postBuild(); + enum EViewModeType + { + VIEW_LIST, + VIEW_GALLERY, + VIEW_COMBINATION + }; + virtual BOOL handleKeyHere(KEY key, MASK mask); // Inherited functionality @@ -108,6 +116,11 @@ public: LLUUID getSingleFolderViewRoot(); bool isSingleFolderMode() { return mSingleFolderMode; } + void setViewMode(EViewModeType mode); + bool isListViewMode() { return (mViewMode == VIEW_LIST); } + bool isGalleryViewMode() { return (mViewMode == VIEW_GALLERY); } + LLUUID getCurrentSFVRoot(); + protected: // // Misc functions @@ -163,9 +176,12 @@ private: LLComboBox* mSearchTypeCombo; bool mSingleFolderMode; + EViewModeType mViewMode; LLInventorySingleFolderPanel* mSingleFolderPanelInventory; + LLInventoryGallery* mInventoryGalleryPanel; - boost::signals2::connection mFolderRootChangedConnection; + boost::signals2::connection mListViewRootUpdatedConnection; + boost::signals2::connection mGalleryRootUpdatedConnection; ////////////////////////////////////////////////////////////////////////////////// // List Commands // diff --git a/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml index c7f9822e41..28ec8f2bf1 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml @@ -89,6 +89,7 @@ <menu_item_check label="Combination view" layout="topleft" + enabled="false" name="combination_view"> <on_click function="Inventory.GearDefault.Custom.Action" diff --git a/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml b/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml new file mode 100644 index 0000000000..68f78a77c8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="true" + bg_alpha_color="DkGray" + border="false" + follows="all" + height="390" + name="Inventory Gallery" + layout="topleft" + left="0" + top="0" + width="404"> + <text + type="string" + clip_partial="false" + follows="left|top" + layout="topleft" + left="13" + name="empty_txt" + top="0" + height="32" + valign="center" + parse_urls="true" + wrap="true"> + Folder is empty. + </text> + <scroll_container + follows="all" + height="400" + layout="topleft" + left="4" + top="0" + name="gallery_scroll_panel" + opaque="false" + top_pad="0"> + </scroll_container> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml b/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml new file mode 100644 index 0000000000..80beb2ec8a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="false" + background_opaque="false" + bg_alpha_color="FrogGreen" + bg_opaque_color="FrogGreen" + border="false" + bevel_style="none" + follows="left|top" + height="149" + width="130" + name="gallery_item_panel" + layout="topleft" + left="0" + top="0"> + <thumbnail + name="preview_thumbnail" + image_name="Thumbnail_Fallback" + layout="topleft" + follows="left|top" + interactable="false" + height="128" + width="128" + top="0" + left="1"/> + <icon + left="5" + top_pad="-25" + layout="topleft" + name="item_type" + height="20" + width="20" + follows="left|top" + visible="true" + image_name="Inv_Eye"/> + <panel + background_visible="false" + background_opaque="true" + bg_opaque_color="MenuItemHighlightBgColor" + border="false" + bevel_style="none" + follows="left|top" + left="0" + top="129" + height="25" + width="148" + name="text_bg_panel"> + <text + read_only="true" + length="1" + follows="left|top" + left="1" + height="10" + layout="topleft" + name="item_name" + parse_urls="false" + top="2" + width="150" + use_ellipses="true"> + Item name, folder name. + </text> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index af4511a92d..3cdb3c5003 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -306,4 +306,27 @@ folder_indentation="-8"/> </single_folder_inventory_panel> </panel> + <panel + follows="all" + halign="center" + height="372" + layout="topleft" + left="7" + name="gallery_view_inventory" + top_delta="0" + visible="false" + width="312"> + <panel + class="inventory_gallery" + filename="panel_inventory_gallery.xml" + left="0" + top="0" + height="372" + width="312" + name="gallery_view_inv" + background_visible="true" + follows="all" + layout="topleft" /> + </panel> + </panel> </panel> |