diff options
author | Maxim Nikolenko <maximnproductengine@lindenlab.com> | 2023-02-17 15:47:03 +0200 |
---|---|---|
committer | Maxim Nikolenko <maximnproductengine@lindenlab.com> | 2023-02-17 16:23:44 +0200 |
commit | 734b1b5d421254c45b3eb0fe0a5bbc8159e489fc (patch) | |
tree | cb02a1bff376f5448e861ba564a86aa1bfbdefe5 /indra/newview | |
parent | 4bc9331dddbacb9c0c36252b32f2514b9080dcf5 (diff) |
SL-19105 WIP Single-folder inventory view
Diffstat (limited to 'indra/newview')
18 files changed, 734 insertions, 168 deletions
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 7c6980a7e6..5999ab3925 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -111,6 +111,7 @@ public: virtual void previewItem( void ); virtual void selectItem(void) { } virtual void showProperties(void); + virtual void navigateToFolder() {} // Methods used in sorting (see LLConversationSort::operator()) EConversationType const getType() const { return mConvType; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 81db0c45c2..31801c0aa0 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -138,6 +138,12 @@ bool isMarketplaceSendAction(const std::string& action) return ("send_to_marketplace" == action); } +bool isPanelActive(const std::string& panel_name) +{ + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + return (active_panel && (active_panel->getName() == panel_name)); +} + // Used by LLFolderBridge as callback for directory fetching recursion class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver { @@ -407,6 +413,25 @@ void LLInvFVBridge::showProperties() } } +void LLInvFVBridge::navigateToFolder() +{ + LLInventorySingleFolderPanel* panel = dynamic_cast<LLInventorySingleFolderPanel*>(mInventoryPanel.get()); + if (!panel) + { + return; + } + LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return; + } + if (mUUID.isNull()) + { + return; + } + panel->changeFolderRoot(mUUID); +} + void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch) { // Deactivate gestures when moving them into Trash @@ -921,8 +946,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, addDeleteContextMenuOptions(items, disabled_items); - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); - if (active_panel && (active_panel->getName() != "All Items")) + if (!isPanelActive("All Items") && !isPanelActive("single_folder_inv")) { items.push_back(std::string("Show in Main Panel")); } @@ -1013,7 +1037,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, items.push_back(std::string("Delete")); - if (!isItemRemovable()) + if (!isItemRemovable() || isPanelActive("Favorite Items")) { disabled_items.push_back(std::string("Delete")); } @@ -4141,14 +4165,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back(std::string("Cut")); disabled_items.push_back(std::string("Delete")); } + + if (isPanelActive("Favorite Items")) + { + disabled_items.push_back(std::string("Delete")); + } if(trash_id == mUUID) { - bool is_recent_panel = false; - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); - if (active_panel && (active_panel->getName() == "Recent Items")) - { - is_recent_panel = true; - } + bool is_recent_panel = isPanelActive("Recent Items"); // This is the trash. items.push_back(std::string("Empty Trash")); @@ -4369,6 +4393,20 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& disabled_items.push_back(std::string("New folder from selected")); } + items.push_back(std::string("open_in_new_window")); + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("open_in_new_window")); + } + if(isPanelActive("single_folder_inv")) + { + items.push_back(std::string("open_in_current_window")); + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("open_in_current_window")); + } + } + #ifndef LL_RELEASE_FOR_DOWNLOAD if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 988e58a661..39dd268115 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -107,6 +107,7 @@ public: virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual void openItem() {} virtual void closeItem() {} + virtual void navigateToFolder(); virtual void showProperties(); virtual BOOL isItemRenameable() const { return TRUE; } virtual BOOL isMultiPreviewAllowed() { return TRUE; } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index ea3525205a..d6110b3cd5 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -81,7 +81,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) mCurrentGeneration(0), mFirstRequiredGeneration(0), mFirstSuccessGeneration(0), - mSearchType(SEARCHTYPE_NAME) + mSearchType(SEARCHTYPE_NAME), + mSingleFolderMode(false) { // copy mFilterOps into mDefaultFilterOps markDefault(); @@ -1626,7 +1627,7 @@ bool LLInventoryFilter::areDateLimitsSet() bool LLInventoryFilter::showAllResults() const { - return hasFilterString(); + return hasFilterString() && !mSingleFolderMode; } diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 72deb7c76b..e127ef03ab 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -239,6 +239,8 @@ public: const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; } bool hasFilterString() const; + void setSingleFolderMode(bool is_single_folder) { mSingleFolderMode = is_single_folder; } + void setFilterPermissions(PermissionMask perms); PermissionMask getFilterPermissions() const; @@ -361,6 +363,8 @@ private: std::vector<std::string> mFilterTokens; std::string mExactToken; + + bool mSingleFolderMode; }; #endif diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index f418b2eed3..91fa856d5e 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -183,6 +183,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryPanel::fileUploadLocation, this, _2)); + mCommitCallbackRegistrar.add("Inventory.OpenNewFolderWindow", boost::bind(&LLInventoryPanel::openSingleViewInventory, this, _2)); } LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) @@ -1643,6 +1644,11 @@ void LLInventoryPanel::fileUploadLocation(const LLSD& userdata) } } +void LLInventoryPanel::openSingleViewInventory(const LLSD& userdata) +{ + LLPanelMainInventory::newFolderWindow(LLFolderBridge::sSelf.get()->getUUID()); +} + void LLInventoryPanel::purgeSelectedItems() { if (!mFolderRoot.get()) return; @@ -2033,6 +2039,138 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; } +static LLDefaultChildRegistry::Register<LLInventorySingleFolderPanel> t_single_folder_inventory_panel("single_folder_inventory_panel"); + +LLInventorySingleFolderPanel::LLInventorySingleFolderPanel(const Params& params) + : LLInventoryPanel(params) +{ + getFilter().setSingleFolderMode(true); + + mCommitCallbackRegistrar.add("Inventory.OpenSelectedFolder", boost::bind(&LLInventorySingleFolderPanel::openInCurrentWindow, this, _2)); +} + +LLInventorySingleFolderPanel::~LLInventorySingleFolderPanel() +{ +} + +void LLInventorySingleFolderPanel::setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb) +{ + if (mFolderRoot.get()) + { + mFolderRoot.get()->setSelectCallback(cb); + mSelectionCallback = cb; + } +} + +void LLInventorySingleFolderPanel::initFromParams(const Params& p) +{ + Params fav_params(p); + fav_params.start_folder.id = gInventory.getRootFolderID(); + LLInventoryPanel::initFromParams(p); + changeFolderRoot(gInventory.getRootFolderID()); +} + +void LLInventorySingleFolderPanel::openInCurrentWindow(const LLSD& userdata) +{ + changeFolderRoot(LLFolderBridge::sSelf.get()->getUUID()); +} + +void LLInventorySingleFolderPanel::changeFolderRoot(const LLUUID& new_id) +{ + if(mFolderID.notNull()) + { + mBackwardFolders.push_back(mFolderID); + } + mFolderID = new_id; + updateSingleFolderRoot(); +} + +void LLInventorySingleFolderPanel::onForwardFolder() +{ + if(!mForwardFolders.empty() && (mFolderID != mForwardFolders.back())) + { + mBackwardFolders.push_back(mFolderID); + mFolderID = mForwardFolders.back(); + mForwardFolders.pop_back(); + updateSingleFolderRoot(); + } +} + +void LLInventorySingleFolderPanel::onBackwardFolder() +{ + if(!mBackwardFolders.empty() && (mFolderID != mBackwardFolders.back())) + { + mForwardFolders.push_back(mFolderID); + mFolderID = mBackwardFolders.back(); + mBackwardFolders.pop_back(); + updateSingleFolderRoot(); + } +} + +void LLInventorySingleFolderPanel::clearNavigationHistory() +{ + mForwardFolders.clear(); + mBackwardFolders.clear(); +} + +boost::signals2::connection LLInventorySingleFolderPanel::setRootChangedCallback(root_changed_callback_t cb) +{ + return mRootChangedSignal.connect(cb); +} + +void LLInventorySingleFolderPanel::updateSingleFolderRoot() +{ + if (mFolderID != getRootFolderID()) + { + mRootChangedSignal(); + + LLUUID root_id = mFolderID; + if (mFolderRoot.get()) + { + removeItemID(getRootFolderID()); + mFolderRoot.get()->destroyView(); + } + + mCommitCallbackRegistrar.pushScope(); + { + LLFolderView* folder_view = createFolderRoot(root_id); + folder_view->setChildrenInited(false); + mFolderRoot = folder_view->getHandle(); + + addItemID(root_id, mFolderRoot.get()); + + LLRect scroller_view_rect = getRect(); + scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); + LLScrollContainer::Params scroller_params(mParams.scroll()); + scroller_params.rect(scroller_view_rect); + + if (mScroller) + { + removeChild(mScroller); + delete mScroller; + mScroller = NULL; + } + mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); + addChild(mScroller); + mScroller->addChild(mFolderRoot.get()); + mFolderRoot.get()->setScrollContainer(mScroller); + mFolderRoot.get()->setFollowsAll(); + mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox); + + if (!mSelectionCallback.empty()) + { + mFolderRoot.get()->setSelectCallback(mSelectionCallback); + } + } + mCommitCallbackRegistrar.popScope(); + mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar); + + buildNewViews(mFolderID); + + mFolderRoot.get()->setShowEmptyMessage(false); + } +} + /************************************************************************/ /* Asset Pre-Filtered Inventory Panel related class */ /************************************************************************/ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 0932482ad7..981bef62a8 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -222,6 +222,7 @@ public: void doCreate(const LLSD& userdata); bool beginIMSession(); void fileUploadLocation(const LLSD& userdata); + void openSingleViewInventory(const LLSD& userdata); void purgeSelectedItems(); bool attachObject(const LLSD& userdata); static void idle(void* user_data); @@ -263,6 +264,8 @@ public: void callbackPurgeSelectedItems(const LLSD& notification, const LLSD& response); + void changeFolderRoot(const LLUUID& new_id) {}; + protected: void openStartFolderOrMyInventory(); // open the first level of inventory void onItemsCompletion(); // called when selected items are complete @@ -382,6 +385,44 @@ private: std::deque<LLUUID> mBuildViewsQueue; }; + +class LLInventorySingleFolderPanel : public LLInventoryPanel +{ +public: + struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params> + {}; + + void initFromParams(const Params& p); + bool isSelectionRemovable() { return false; } + //void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb); + + void openInCurrentWindow(const LLSD& userdata); + void changeFolderRoot(const LLUUID& new_id); + void onForwardFolder(); + void onBackwardFolder(); + void clearNavigationHistory(); + LLUUID getSingleFolderRoot() { return mFolderID; } + + void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb); + + typedef boost::function<void()> root_changed_callback_t; + boost::signals2::connection setRootChangedCallback(root_changed_callback_t cb); + +protected: + LLInventorySingleFolderPanel(const Params& params); + ~LLInventorySingleFolderPanel(); + void updateSingleFolderRoot(); + + boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback; + friend class LLUICtrlFactory; + + LLUUID mFolderID; + std::list<LLUUID> mBackwardFolders; + std::list<LLUUID> mForwardFolders; + + boost::signals2::signal<void()> mRootChangedSignal; +}; + /************************************************************************/ /* Asset Pre-Filtered Inventory Panel related class */ /* Exchanges filter's flexibility for speed of generation and */ diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index a517fae0a5..d13c691abd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -38,7 +38,6 @@ #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" -#include "llinventorypanel.h" #include "llfiltereditor.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterreg.h" @@ -114,7 +113,9 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mMenuVisibility(NULL), mMenuAddHandle(), mNeedUploadCost(true), - mMenuViewDefault(NULL) + mMenuViewDefault(NULL), + mSingleFolderMode(false), + mFolderRootChangedConnection() { // Menu Callbacks (non contex menus) mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2)); @@ -240,6 +241,9 @@ BOOL LLPanelMainInventory::postBuild() mVisibilityMenuButton = getChild<LLMenuButton>("options_visibility_btn"); mViewMenuButton = getChild<LLMenuButton>("view_btn"); + mSingleFolderPanelInventory = getChild<LLInventorySingleFolderPanel>("single_folder_inv"); + mFolderRootChangedConnection = mSingleFolderPanelInventory->setRootChangedCallback(boost::bind(&LLPanelMainInventory::updateTitle, this)); + initListCommandsHandlers(); const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); @@ -316,6 +320,11 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) menu->die(); mMenuAddHandle.markDead(); } + + if (mFolderRootChangedConnection.connected()) + { + mFolderRootChangedConnection.disconnect(); + } } LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel() @@ -383,10 +392,17 @@ void LLPanelMainInventory::closeAllFolders() getPanel()->getRootFolder()->closeAllFolders(); } +S32 get_instance_num() +{ + static S32 instance_num = 0; + instance_num = (instance_num + 1) % S32_MAX; + + return instance_num; +} + void LLPanelMainInventory::newWindow() { - static S32 instance_num = 0; - instance_num = (instance_num + 1) % S32_MAX; + S32 instance_num = get_instance_num(); if (!gAgentCamera.cameraMouselook()) { @@ -394,10 +410,45 @@ void LLPanelMainInventory::newWindow() } } +void LLPanelMainInventory::newFolderWindow(const LLUUID& folder_id) +{ + S32 instance_num = get_instance_num(); + + LLFloaterSidePanelContainer* inventory_container = LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num)); + if(inventory_container) + { + LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(inventory_container->findChild<LLPanel>("main_panel", true)); + if (sidepanel_inventory) + { + LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + if (main_inventory) + { + main_inventory->onViewModeClick(); + if(folder_id.notNull()) + { + main_inventory->setSingleFolderViewRoot(folder_id); + } + } + } + } +} + void LLPanelMainInventory::doCreate(const LLSD& userdata) { reset_inventory_filter(); - menu_create_inventory_item(getPanel(), NULL, userdata); + if(mSingleFolderMode) + { + LLFolderViewItem* current_folder = getActivePanel()->getRootFolder(); + if (current_folder) + { + LLFolderBridge* bridge = (LLFolderBridge*)current_folder->getViewModelItem(); + menu_create_inventory_item(getPanel(), bridge, userdata); + } + } + else + { + menu_create_inventory_item(getPanel(), NULL, userdata); + } } void LLPanelMainInventory::resetFilters() @@ -527,7 +578,7 @@ void LLPanelMainInventory::onClearSearch() } // re-open folders that were initially open in case filter was active - if (mActivePanel && (mFilterSubString.size() || initially_active)) + if (mActivePanel && (mFilterSubString.size() || initially_active) && !mSingleFolderMode) { mSavedFolderState->setApply(TRUE); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -1173,10 +1224,15 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data) void LLPanelMainInventory::initListCommandsHandlers() { childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this)); + childSetAction("view_mode_btn", boost::bind(&LLPanelMainInventory::onViewModeClick, this)); + childSetAction("up_btn", boost::bind(&LLPanelMainInventory::onUpFolderClicked, this)); + childSetAction("back_btn", boost::bind(&LLPanelMainInventory::onBackFolderClicked, this)); + childSetAction("forward_btn", boost::bind(&LLPanelMainInventory::onForwardFolderClicked, this)); mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); + mEnableCallbackRegistrar.add("Inventory.GearDefault.Visible", boost::bind(&LLPanelMainInventory::isActionVisible, this, _2)); mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true); mMenuViewDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_view_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -1211,6 +1267,47 @@ void LLPanelMainInventory::onAddButtonClick() } } +void LLPanelMainInventory::onViewModeClick() +{ + mSingleFolderMode = !mSingleFolderMode; + + getChild<LLPanel>("default_inventory_panel")->setVisible(!mSingleFolderMode); + getChild<LLPanel>("single_folder_inventory")->setVisible(mSingleFolderMode); + getChild<LLLayoutPanel>("nav_buttons")->setVisible(mSingleFolderMode); + getChild<LLButton>("view_mode_btn")->setImageOverlay(mSingleFolderMode ? getString("default_mode_btn") : getString("single_folder_mode_btn")); + + mActivePanel = mSingleFolderMode ? getChild<LLInventoryPanel>("single_folder_inv") : (LLInventoryPanel*)getChild<LLTabContainer>("inventory filter tabs")->getCurrentPanel(); + updateTitle(); +} + +void LLPanelMainInventory::onUpFolderClicked() +{ + const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot()); + if (cat) + { + if (cat->getParentUUID().notNull()) + { + mSingleFolderPanelInventory->changeFolderRoot(cat->getParentUUID()); + } + } +} + +void LLPanelMainInventory::onBackFolderClicked() +{ + mSingleFolderPanelInventory->onBackwardFolder(); +} + +void LLPanelMainInventory::onForwardFolderClicked() +{ + mSingleFolderPanelInventory->onForwardFolder(); +} + +void LLPanelMainInventory::setSingleFolderViewRoot(const LLUUID& folder_id) +{ + mSingleFolderPanelInventory->changeFolderRoot(folder_id); + mSingleFolderPanelInventory->clearNavigationHistory(); +} + void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) { if (menu) @@ -1254,6 +1351,27 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) return; const std::string command_name = userdata.asString(); + if (command_name == "new_single_folder_window") + { + newFolderWindow(LLUUID()); + } + if ((command_name == "open_in_current_window") || (command_name == "open_in_new_window")) + { + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + const LLUUID& folder_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); + if((command_name == "open_in_current_window")) + { + mSingleFolderPanelInventory->changeFolderRoot(folder_id); + } + if((command_name == "open_in_new_window")) + { + newFolderWindow(folder_id); + } + } if (command_name == "new_window") { newWindow(); @@ -1505,10 +1623,34 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); } + if (command_name == "open_folder") + { + LLFolderView* root = getActivePanel()->getRootFolder(); + std::set<LLFolderViewItem*> selection_set = root->getSelectionList(); + if (selection_set.size() != 1) return FALSE; + LLFolderViewItem* current_item = *selection_set.begin(); + if (!current_item) return FALSE; + const LLUUID& folder_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); + return (gInventory.getCategory(folder_id) != NULL); + } return TRUE; } +bool LLPanelMainInventory::isActionVisible(const LLSD& userdata) +{ + const std::string param_str = userdata.asString(); + if (param_str == "single_folder_view") + { + return mSingleFolderMode; + } + if (param_str == "multi_folder_view") + { + return !mSingleFolderMode; + } + return true; +} + BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata) { U32 sort_order_mask = getActivePanel()->getSortOrder(); @@ -1576,5 +1718,24 @@ bool LLPanelMainInventory::hasSettingsInventory() return LLEnvironment::instance().isInventoryEnabled(); } +void LLPanelMainInventory::updateTitle() +{ + LLFloater* inventory_floater = gFloaterView->getParentFloater(this); + if(inventory_floater) + { + if(mSingleFolderMode) + { + const LLViewerInventoryCategory* cat = gInventory.getCategory(mSingleFolderPanelInventory->getSingleFolderRoot()); + if (cat) + { + inventory_floater->setTitle(cat->getName()); + } + } + else + { + inventory_floater->setTitle(getString("inventory_title")); + } + } +} // List Commands // //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 1f07d381ba..923ebba98b 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -30,6 +30,7 @@ #include "llpanel.h" #include "llinventoryobserver.h" +#include "llinventorypanel.h" #include "lldndbutton.h" #include "llfolderview.h" @@ -92,10 +93,16 @@ public: void setFocusFilterEditor(); static void newWindow(); + static void newFolderWindow(const LLUUID& folder_id); void toggleFindOptions(); void resetFilters(); + void onViewModeClick(); + void onUpFolderClicked(); + void onBackFolderClicked(); + void onForwardFolderClicked(); + void setSingleFolderViewRoot(const LLUUID& folder_id); protected: // @@ -149,7 +156,10 @@ private: std::string mCategoryCountString; LLComboBox* mSearchTypeCombo; + bool mSingleFolderMode; + LLInventorySingleFolderPanel* mSingleFolderPanelInventory; + boost::signals2::connection mFolderRootChangedConnection; ////////////////////////////////////////////////////////////////////////////////// // List Commands // @@ -162,7 +172,9 @@ protected: BOOL isActionEnabled(const LLSD& command_name); BOOL isActionChecked(const LLSD& userdata); void onCustomAction(const LLSD& command_name); + bool isActionVisible(const LLSD& userdata); static bool hasSettingsInventory(); + void updateTitle(); /** * Set upload cost in "Upload" sub menu. */ diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 14c9f812f4..c9169fdc8f 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -125,6 +125,7 @@ public: virtual BOOL canOpenItem() const { return FALSE; } virtual void closeItem() {} virtual void selectItem() {} + virtual void navigateToFolder() {} virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); virtual BOOL isItemMovable() const; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 015a887e9f..09fd4b04cb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -9703,6 +9703,7 @@ void initialize_menus() commit.add("PayObject", boost::bind(&handle_give_money_dialog)); commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow)); + commit.add("Inventory.NewFolderWindow", boost::bind(&LLPanelMainInventory::newFolderWindow, LLUUID())); enable.add("EnablePayObject", boost::bind(&enable_pay_object)); enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar)); diff --git a/indra/newview/skins/default/xui/en/floater_my_inventory.xml b/indra/newview/skins/default/xui/en/floater_my_inventory.xml index f182d27da8..1b4f323d04 100644 --- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml @@ -5,14 +5,14 @@ can_resize="true" height="570" help_topic="sidebar_inventory" - min_width="333" + min_width="363" min_height="590" name="floater_my_inventory" save_rect="true" save_visibility="true" reuse_instance="true" title="INVENTORY" - width="333" > + width="363" > <panel class="sidepanel_inventory" name="main_panel" diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index aa3d0ae071..5fe53526c7 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -401,6 +401,20 @@ parameter="model" /> </menu_item_call> </menu> + <menu_item_call + label="Open" + layout="topleft" + name="open_in_current_window"> + <menu_item_call.on_click + function="Inventory.OpenSelectedFolder"/> + </menu_item_call> + <menu_item_call + label="Open in new window" + layout="topleft" + name="open_in_new_window"> + <menu_item_call.on_click + function="Inventory.OpenNewFolderWindow"/> + </menu_item_call> <menu label="Change Type" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml index 3fb2e01e5b..027dd40d08 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -7,14 +7,38 @@ name="menu_gear_default" visible="false"> <menu_item_call + label="Open" + layout="topleft" + name="open_in_current_window"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="open_in_current_window" /> + <on_enable + function="Inventory.GearDefault.Enable" + parameter="open_folder" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="single_folder_view" /> + </menu_item_call> + <menu_item_call + label="Open in new window" + layout="topleft" + name="open_in_new_window"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="open_in_new_window" /> + <on_enable + function="Inventory.GearDefault.Enable" + parameter="open_folder" /> + </menu_item_call> + <menu_item_call label="New Folder Window" layout="topleft" shortcut="control|shift|J" - enabled="false" name="new_single_folder"> <on_click function="Inventory.GearDefault.Custom.Action" - parameter="new_window" /> + parameter="new_single_folder_window" /> </menu_item_call> <menu_item_call label="New Inventory Window" @@ -32,6 +56,9 @@ <on_click function="Inventory.GearDefault.Custom.Action" parameter="close_folders" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -115,6 +142,9 @@ <on_enable function="Inventory.GearDefault.Enable" parameter="empty_lostnfound" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> </menu_item_call> <menu_item_call label="Empty Trash" @@ -126,5 +156,8 @@ <on_enable function="Inventory.GearDefault.Enable" parameter="empty_trash" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> </menu_item_call> </toggleable_menu> 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 6e3cfd9cee..0fcdb1cda0 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 @@ -49,5 +49,8 @@ <on_check function="Inventory.GearDefault.Check" parameter="sort_system_folders_to_top" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 58584345a9..de11a2c0e9 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -37,6 +37,15 @@ parameter="" /> </menu_item_call> <menu_item_call + label="New Folder Window" + name="new_single_folder" + shortcut="control|shift|J" + visible="false"> + <menu_item_call.on_click + function="Inventory.NewFolderWindow" + parameter="" /> + </menu_item_call> + <menu_item_call label="Places..." name="Places" shortcut="control|L"> 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 d437f98e91..606c2175d8 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -23,6 +23,9 @@ name="ItemcountUnknown"> Fetched [ITEM_COUNT] Items and [CATEGORY_COUNT] Folders [FILTER] </panel.string> + <panel.string name="inventory_title">INVENTORY</panel.string> + <panel.string name="default_mode_btn">Command_AboutLand_Icon</panel.string> + <panel.string name="single_folder_mode_btn">Command_Map_Icon</panel.string> <text type="string" length="1" @@ -38,157 +41,262 @@ width="300"> Items: </text> - <combo_box - height="23" - layout="topleft" - left="3" - top="18" - name="search_type" - follows="top|left" - width="67"> - <item - label="Name" - name="Name" - value="search_by_name"/> - <item - label="Creator" - name="Creator" - value="search_by_creator"/> - <item - label="Description" - name="Description" - value="search_by_description"/> - <item - label="UUID" - name="UUID" - value="search_by_UUID"/> - </combo_box> - <menu_button - follows="top|left" - tool_tip="Show search visibility options" - height="23" - image_overlay="Inv_Toolbar_SearchVisibility" - layout="topleft" - left_pad="1" - name="options_visibility_btn" - width="31" /> - <filter_editor - text_pad_left="10" + <layout_stack follows="left|top|right" - height="23" - label="Enter search text" - layout="topleft" - left_pad="1" - max_length_chars="300" - highlight_text_field="true" - name="inventory search editor" - width="99" /> - <menu_button - follows="top|right" - tool_tip="Show additional options" - height="23" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="options_gear_btn" - width="31" /> - <menu_button - follows="top|right" - tool_tip="View/sort options" - height="23" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Conv_toolbar_sort" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="view_btn" - width="31" /> - <button - follows="top|right" - height="23" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="AddItem_Off" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - name="add_btn" - tool_tip="Add new item" - width="31" /> - <button - follows="top|right" - tool_tip="Toggles between traditional and single-folder views" - height="23" - image_hover_unselected="Toolbar_Middle_Over" - image_overlay="Command_Map_Icon" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - layout="topleft" - left_pad="1" - enabled="false" - name="view_mode_btn" - width="31" /> - <tab_container + height="25" + animate="false" + top_pad="10" + left="2" + orientation="horizontal"> + <layout_panel + border="false" + bevel_style="in" + user_resize="false" + auto_resize="false" + height="25" + width="65" + name="nav_buttons" + visible="false"> + <button + follows="top|left" + height="23" + image_selected="Arrow_Left" + image_pressed="Arrow_Left" + image_unselected="Arrow_Left" + scale_image="false" + layout="topleft" + left="3" + top="2" + name="back_btn" + tool_tip="Back" + width="20" /> + <button + follows="top|left" + height="23" + image_selected="Arrow_Right" + image_pressed="Arrow_Right" + image_unselected="Arrow_Right" + scale_image="false" + layout="topleft" + left_pad="1" + name="forward_btn" + tool_tip="Forward" + width="20" /> + <button + follows="top|left" + height="23" + image_selected="Arrow_Up" + image_pressed="Arrow_Up" + image_unselected="Arrow_Up" + scale_image="false" + layout="topleft" + left_pad="1" + name="up_btn" + tool_tip="Go up one level" + width="20" /> + </layout_panel> + <layout_panel + border="false" + bevel_style="in" + user_resize="false" + height="25" + width="375" + visible="true"> + <combo_box + height="23" + layout="topleft" + left="2" + top="0" + name="search_type" + tool_tip="Search by" + follows="top|left" + width="67"> + <item + label="Name" + name="Name" + value="search_by_name"/> + <item + label="Creator" + name="Creator" + value="search_by_creator"/> + <item + label="Description" + name="Description" + value="search_by_description"/> + <item + label="UUID" + name="UUID" + value="search_by_UUID"/> + </combo_box> + <menu_button + follows="top|left" + tool_tip="Search visibility options" + height="23" + image_overlay="Inv_Toolbar_SearchVisibility" + layout="topleft" + left_pad="1" + name="options_visibility_btn" + width="31" /> + <filter_editor + text_pad_left="10" + follows="left|top|right" + height="23" + label="Enter search text" + layout="topleft" + left_pad="1" + max_length_chars="300" + highlight_text_field="true" + name="inventory search editor" + width="150" /> + <menu_button + follows="top|right" + tool_tip="Actions" + height="23" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="options_gear_btn" + width="31" /> + <menu_button + follows="top|right" + tool_tip="View & sort options" + height="23" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="view_btn" + width="31" /> + <button + follows="top|right" + height="23" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="AddItem_Off" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="add_btn" + tool_tip="Create new item" + width="31" /> + <button + follows="top|right" + tool_tip="Switch between views" + height="23" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Command_Map_Icon" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + layout="topleft" + left_pad="1" + name="view_mode_btn" + width="31" /> + </layout_panel> + </layout_stack> + <panel follows="all" halign="center" height="372" layout="topleft" left="7" - name="inventory filter tabs" - tab_height="30" - tab_position="top" - tab_min_width="100" + name="default_inventory_panel" top_pad="10" width="312"> - <inventory_panel - bg_opaque_color="DkGray2" - bg_alpha_color="DkGray2" - background_visible="true" - border="false" - bevel_style="none" + <tab_container + follows="all" + halign="center" + height="372" + layout="topleft" + left="0" + name="inventory filter tabs" + tab_height="30" + tab_position="top" + tab_min_width="100" + top="0" + width="312"> + <inventory_panel + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + follows="all" + height="338" + label="MY INVENTORY" + help_topic="my_inventory_tab" + layout="topleft" + left="0" + name="All Items" + sort_order_setting="InventorySortOrder" + show_item_link_overlays="true" + top="16" + width="288" /> + <recent_inventory_panel + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + follows="all" + height="338" + label="RECENT" + help_topic="recent_inventory_tab" + layout="topleft" + left_delta="0" + name="Recent Items" + show_item_link_overlays="true" + width="290" /> + <inventory_panel + name="Worn Items" + label="WORN" + show_empty_message="false" + follows="all" + layout="topleft" + width="290" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + scroll.reserve_scroll_corner="false"> + </inventory_panel> + </tab_container> + </panel> + <panel follows="all" - height="338" - label="MY INVENTORY" - help_topic="my_inventory_tab" - layout="topleft" - left="0" - name="All Items" - sort_order_setting="InventorySortOrder" - show_item_link_overlays="true" - top="16" - width="288" /> - <recent_inventory_panel - bg_opaque_color="DkGray2" - bg_alpha_color="DkGray2" - background_visible="true" - border="false" - bevel_style="none" - follows="all" - height="338" - label="RECENT" - help_topic="recent_inventory_tab" + halign="center" + height="372" layout="topleft" - left_delta="0" - name="Recent Items" - show_item_link_overlays="true" - width="290" /> - <inventory_panel - name="Worn Items" - label="WORN" - show_empty_message="false" - follows="all" - layout="topleft" - width="290" - bg_opaque_color="DkGray2" - bg_alpha_color="DkGray2" - background_visible="true" - border="false" - bevel_style="none" - scroll.reserve_scroll_corner="false"> - </inventory_panel> - </tab_container> + left="7" + name="single_folder_inventory" + top_delta="0" + visible="false" + width="312"> + <single_folder_inventory_panel + name="single_folder_inv" + show_empty_message="false" + follows="all" + left="0" + top="0" + top_pad="5" + height="372" + width="312" + layout="topleft" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + scroll.reserve_scroll_corner="false"> + <item folder_indentation="0"/> + <folder + single_folder_mode="true" + folder_indentation="0"/> + </single_folder_inventory_panel> + </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index 82eb629670..a4b7f48c5e 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -18,7 +18,7 @@ height="570" visible="true" default_tab_group="1" - width="355"> + width="395"> <layout_stack follows="left|right|top|bottom" layout="topleft" @@ -28,14 +28,14 @@ orientation="vertical" name="inventory_layout_stack" height="565" - width="355"> + width="395"> <layout_panel name="main_inventory_layout_panel" layout="topleft" auto_resize="true" user_resize="true" min_dim="150" - width="355" + width="395" follows="bottom|left|right" height="300"> <panel @@ -48,7 +48,7 @@ top="0" label="" height="300" - width="355" /> + width="395" /> </layout_panel> <layout_panel width="355" |