From d44e5b7d9cd22e372ce19aa1d4f62904d13ed97e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 6 Mar 2015 15:57:11 -0500 Subject: SL-103 WIP - comment re: possible future work --- indra/llui/llfolderview.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 474b545f00..3ec92cb6e7 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1809,7 +1809,9 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) } // Successively filter out invalid options - + // FIXME this item-by-item approach does not allow options to be enabled/disabled based on the selection as a whole - for example, + // if avatar has room for one more wearable, and the selection includes two wearables, add should be disabled. + // llwearableitemslist.cpp has a more holistic approach here. U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); -- cgit v1.3 From 64511ce28f4c3740fe7f87d680722105f83f82c0 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 6 Mar 2015 16:05:47 -0500 Subject: SL-103 WIP - comment --- indra/llui/llfolderview.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 3ec92cb6e7..26cb90505d 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1808,10 +1808,15 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) (*menu_itor)->setEnabled(TRUE); } + + // FIXME this item-by-item approach does not allow options to be + // enabled/disabled based on the selection as a whole - for + // example, if avatar has room for one more wearable, and the + // selection includes two wearables, add should be disabled. + // canAddWearables() in llwearableitemslist.cpp has a more + // holistic approach to this. + // Successively filter out invalid options - // FIXME this item-by-item approach does not allow options to be enabled/disabled based on the selection as a whole - for example, - // if avatar has room for one more wearable, and the selection includes two wearables, add should be disabled. - // llwearableitemslist.cpp has a more holistic approach here. U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); -- cgit v1.3 From fb072c91485a484e3d0740113ee753b58c439900 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 13 Mar 2015 16:38:23 -0400 Subject: MAINT-4980 WIP - add context menu filtering based on the selection group --- indra/llui/llfolderview.cpp | 16 ++++++- indra/llui/llfolderview.h | 8 +++- indra/llui/llfolderviewitem.h | 7 +++ indra/newview/llinventorybridge.cpp | 86 ++++++++++++++++++++++++++++++++++++- indra/newview/llinventorybridge.h | 8 ++++ indra/newview/llinventorypanel.cpp | 4 +- indra/newview/llinventorypanel.h | 2 + indra/newview/llwearableitemslist.h | 3 +- 8 files changed, 129 insertions(+), 5 deletions(-) mode change 100644 => 100755 indra/llui/llfolderviewitem.h (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 26cb90505d..7f0d486981 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -171,7 +171,8 @@ LLFolderView::LLFolderView(const Params& p) mDraggingOverItem(NULL), mStatusTextBox(NULL), mShowItemLinkOverlays(p.show_item_link_overlays), - mViewModel(p.view_model) + mViewModel(p.view_model), + mGroupedItemModel(p.grouped_item_model) { claimMem(mViewModel); LLPanel* panel = p.parent_panel; @@ -1828,6 +1829,19 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + if (getFolderViewGroupedItemModel()) + { + getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); + } +#if 0 + selected_items_t::iterator item_itor = mSelectedItems.begin(); + if (item_itor != mSelectedItems.end()) + { + LLFolderViewItem* selected_item = (*item_itor); + selected_item->getViewModelItem()->groupFilterContextMenu(mSelectedItems,*menu); + } +#endif + addNoOptions(menu); } diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 08e0a6220a..114dd7bd2f 100755 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -45,6 +45,7 @@ #include "llscrollcontainer.h" class LLFolderViewModelInterface; +class LLFolderViewGroupedItemModel; class LLFolderViewFolder; class LLFolderViewItem; class LLFolderViewFilter; @@ -93,6 +94,7 @@ public: use_ellipses, show_item_link_overlays; Mandatory view_model; + Optional grouped_item_model; Mandatory options_menu; @@ -100,7 +102,7 @@ public: }; friend class LLFolderViewScrollContainer; - typedef std::deque selected_items_t; + typedef folder_view_item_deque selected_items_t; LLFolderView(const Params&); virtual ~LLFolderView( void ); @@ -113,6 +115,9 @@ public: LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } + LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() { return mGroupedItemModel; } + const LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() const { return mGroupedItemModel; } + typedef boost::signals2::signal& items, BOOL user_action)> signal_t; void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } @@ -300,6 +305,7 @@ protected: LLHandle mParentPanel; LLFolderViewModelInterface* mViewModel; + LLFolderViewGroupedItemModel* mGroupedItemModel; /** * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h old mode 100644 new mode 100755 index 0cd20a0f2d..5ad5731cad --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -454,5 +454,12 @@ public: template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } }; +typedef std::deque folder_view_item_deque; + +class LLFolderViewGroupedItemModel: public LLRefCount +{ +public: + virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu) = 0; +}; #endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 958bc7d558..3ec8bb0ab9 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -74,6 +74,7 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" +#include "llwearableitemslist.h" #include "lllandmarkactions.h" #include "llpanellandmarks.h" @@ -557,6 +558,46 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const return TRUE; } +void disable_context_entries_if_present(LLMenuGL& menu, + const menuentry_vec_t &disabled_entries) +{ + const LLView::child_list_t *list = menu.getChildList(); + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + std::string name = menu_item->getName(); + + // descend into split menus: + LLMenuItemBranchGL* branchp = dynamic_cast(menu_item); + if ((name == "More") && branchp) + { + disable_context_entries_if_present(*branchp->getBranch(), disabled_entries); + } + + bool found = false; + menuentry_vec_t::const_iterator itor2; + for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) + { + if (*itor2 == name) + { + found = true; + break; + } + } + + if (found) + { + menu_item->setVisible(TRUE); + // A bit of a hack so we can remember that some UI element explicitly set this to be visible + // so that some other UI element from multi-select doesn't later set this invisible. + menu_item->pushVisible(TRUE); + + menu_item->setEnabled(FALSE); + } + } +} void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, const menuentry_vec_t &disabled_entries) @@ -765,6 +806,31 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +bool get_selection_item_uuids(LLFolderView::selected_items_t& selected_items, uuid_vec_t& ids) +{ + uuid_vec_t results; + S32 non_item = 0; + for(LLFolderView::selected_items_t::iterator it = selected_items.begin(); it != selected_items.end(); ++it) + { + LLItemBridge *view_model = dynamic_cast((*it)->getViewModelItem()); + + if(view_model && view_model->getUUID().notNull()) + { + results.push_back(view_model->getUUID()); + } + else + { + non_item++; + } + } + if (non_item == 0) + { + ids = results; + return true; + } + return false; +} + void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items, menuentry_vec_t &disabled_items) { @@ -3585,7 +3651,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(!model) return; buildContextMenuOptions(flags, items, disabled_items); - hide_context_entries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); // Reposition the menu, in case we're adding items to an existing menu. menu.needsArrange(); @@ -6439,4 +6505,22 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( return new_listener; } +LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge() +{ +} + +void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu) +{ + uuid_vec_t ids; + menuentry_vec_t disabled_items; + if (get_selection_item_uuids(selected_items, ids)) + { + if (!LLWearableItemsList::ContextMenu::canAddWearables(ids)) + { + disabled_items.push_back(std::string("Wearable Add")); + } + } + disable_context_entries_if_present(menu, disabled_items); +} + // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index e8d5db4437..6a8478e64b 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -37,6 +37,7 @@ #include "llviewerwearable.h" #include "lltooldraganddrop.h" #include "lllandmarklist.h" +#include "llfolderviewitem.h" class LLInventoryFilter; class LLInventoryPanel; @@ -687,4 +688,11 @@ void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, const menuentry_vec_t &disabled_entries); +class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel +{ +public: + LLFolderViewGroupedItemBridge(); + virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu); +}; + #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 3546317471..4a230accb6 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -146,7 +146,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mShowEmptyMessage(p.show_empty_message), mViewsInitialized(false), mInvFVBridgeBuilder(NULL), - mInventoryViewModel(p.name) + mInventoryViewModel(p.name), + mGroupedItemBridge(new LLFolderViewGroupedItemBridge) { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; @@ -186,6 +187,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) NULL, root_id); p.view_model = &mInventoryViewModel; + p.grouped_item_model = mGroupedItemBridge; p.use_label_suffix = mParams.use_label_suffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a490dfce5d..bc4c10e441 100755 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -43,6 +43,7 @@ class LLInvFVBridge; class LLInventoryFolderViewModelBuilder; class LLInvPanelComplObserver; class LLFolderViewModelInventory; +class LLFolderViewGroupedItemBridge; namespace LLInitParam { @@ -240,6 +241,7 @@ protected: LLScrollContainer* mScroller; LLFolderViewModelInventory mInventoryViewModel; + LLPointer mGroupedItemBridge; Params mParams; // stored copy of parameter block std::map mItemMap; diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 58a00c5be0..eb975b6301 100755 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -410,6 +410,8 @@ public: ContextMenu(); /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + // FIXME logic should live somewhere more generally useful. + static bool canAddWearables(const uuid_vec_t& item_ids); protected: enum { MASK_CLOTHING = 0x01, @@ -425,7 +427,6 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); - static bool canAddWearables(const uuid_vec_t& item_ids); LLWearableItemsList* mParent; }; -- cgit v1.3 From dd7f0e2954a80e39eba50b7a06e167a50a248632 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 13 Mar 2015 16:55:19 -0400 Subject: MAINT-4980 WIP - moved canAddWearables() to LLAppearanceMgr --- indra/llui/llfolderview.cpp | 21 +++------------ indra/newview/llappearancemgr.cpp | 43 +++++++++++++++++++++++++++++++ indra/newview/llappearancemgr.h | 3 +++ indra/newview/llinventorybridge.cpp | 2 +- indra/newview/llwearableitemslist.cpp | 48 ++--------------------------------- indra/newview/llwearableitemslist.h | 2 -- 6 files changed, 53 insertions(+), 66 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 7f0d486981..0fb163c73a 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1809,14 +1809,6 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) (*menu_itor)->setEnabled(TRUE); } - - // FIXME this item-by-item approach does not allow options to be - // enabled/disabled based on the selection as a whole - for - // example, if avatar has room for one more wearable, and the - // selection includes two wearables, add should be disabled. - // canAddWearables() in llwearableitemslist.cpp has a more - // holistic approach to this. - // Successively filter out invalid options U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; @@ -1829,19 +1821,14 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + // This adds a check for restrictions based on the entire + // selection set - for example, any one wearable may not push you + // over the limit, but all wearables together still might. if (getFolderViewGroupedItemModel()) { getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); } -#if 0 - selected_items_t::iterator item_itor = mSelectedItems.begin(); - if (item_itor != mSelectedItems.end()) - { - LLFolderViewItem* selected_item = (*item_itor); - selected_item->getViewModelItem()->groupFilterContextMenu(mSelectedItems,*menu); - } -#endif - + addNoOptions(menu); } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b5af1af5bc..2c166b6001 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1782,6 +1782,49 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return items.size() > 0; } +// Moved from LLWearableList::ContextMenu for wider utility. +bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) +{ + // TODO: investigate wearables may not be loaded at this point EXT-8231 + + U32 n_objects = 0; + U32 n_clothes = 0; + + // Count given clothes (by wearable type) and objects. + for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if (!item) + { + return false; + } + + if (item->getType() == LLAssetType::AT_OBJECT) + { + ++n_objects; + } + else if (item->getType() == LLAssetType::AT_CLOTHING) + { + ++n_clothes; + } + else + { + LL_WARNS() << "Unexpected wearable type" << LL_ENDL; + return false; + } + } + + // Check whether we can add all the objects. + if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects)) + { + return false; + } + + // Check whether we can add all the clothes. + U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount(); + return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS; +} + void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) { LLInventoryModel::cat_array_t cats; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 399cd6388f..10d97bb8cb 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -100,6 +100,9 @@ public: // Determine whether we can replace current outfit with the given one. bool getCanReplaceCOF(const LLUUID& outfit_cat_id); + // Can we add all referenced items to the avatar? + bool canAddWearables(const uuid_vec_t& item_ids); + // Copy all items in a category. void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, LLPointer cb); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3ec8bb0ab9..cd45d0a4f3 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -6515,7 +6515,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ menuentry_vec_t disabled_items; if (get_selection_item_uuids(selected_items, ids)) { - if (!LLWearableItemsList::ContextMenu::canAddWearables(ids)) + if (!LLAppearanceMgr::instance().canAddWearables(ids)) { disabled_items.push_back(std::string("Wearable Add")); } diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 98559e7782..888ead0613 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -894,13 +894,13 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu setMenuItemVisible(menu, "wear_wear", n_already_worn == 0 && n_worn == 0 && can_be_worn); setMenuItemEnabled(menu, "wear_wear", n_already_worn == 0 && n_worn == 0); setMenuItemVisible(menu, "wear_add", wear_add_visible); - setMenuItemEnabled(menu, "wear_add", canAddWearables(ids)); + setMenuItemEnabled(menu, "wear_add", LLAppearanceMgr::instance().canAddWearables(ids)); setMenuItemVisible(menu, "wear_replace", n_worn == 0 && n_already_worn != 0 && can_be_worn); //visible only when one item selected and this item is worn setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1); setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1); setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); - setMenuItemEnabled(menu, "create_new", canAddWearables(ids)); + setMenuItemEnabled(menu, "create_new", LLAppearanceMgr::instance().canAddWearables(ids)); setMenuItemVisible(menu, "show_original", !standalone); setMenuItemEnabled(menu, "show_original", n_items == 1 && n_links == n_items); setMenuItemVisible(menu, "take_off", mask == MASK_CLOTHING && n_worn == n_items); @@ -1004,48 +1004,4 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id) LLAgentWearables::createWearable(item->getWearableType(), true); } -// Returns true if all the given objects and clothes can be added. -// static -bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_ids) -{ - // TODO: investigate wearables may not be loaded at this point EXT-8231 - - U32 n_objects = 0; - U32 n_clothes = 0; - - // Count given clothes (by wearable type) and objects. - for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if (!item) - { - return false; - } - - if (item->getType() == LLAssetType::AT_OBJECT) - { - ++n_objects; - } - else if (item->getType() == LLAssetType::AT_CLOTHING) - { - ++n_clothes; - } - else - { - LL_WARNS() << "Unexpected wearable type" << LL_ENDL; - return false; - } - } - - // Check whether we can add all the objects. - if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects)) - { - return false; - } - - // Check whether we can add all the clothes. - U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount(); - return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS; -} - // EOF diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index eb975b6301..715c249616 100755 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -410,8 +410,6 @@ public: ContextMenu(); /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); - // FIXME logic should live somewhere more generally useful. - static bool canAddWearables(const uuid_vec_t& item_ids); protected: enum { MASK_CLOTHING = 0x01, -- cgit v1.3