From 74ed51e77d7a44b845dcc12d1d7ad6a426caaa2d Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Mon, 2 Aug 2010 20:52:17 +0300 Subject: EXT-7676 FIXED Restored fix (47df1b3fd94e) reverted in merge 5b5cc4a8642d with slight modifications. - Replaced pointers passed to 'Add More' gear menu with LLHandle. - Removed storing 'Add More' panel sort order from settings because the order is changed each time the panel opens. - Replaced creating items comparator in LLPanelOutfitEdit::postBuild() with a static comparator in llwearableitemslist.cpp. Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/826/. --HG-- branch : product-engine --- indra/newview/app_settings/settings.xml | 11 -- indra/newview/llpaneloutfitedit.cpp | 212 ++++++++++++++++++++++++++++---- indra/newview/llpaneloutfitedit.h | 6 +- indra/newview/llwearableitemslist.cpp | 53 +++++++- indra/newview/llwearableitemslist.h | 27 ++++ 5 files changed, 272 insertions(+), 37 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ce22db97b4..bbf3f4fc75 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -35,17 +35,6 @@ Value 0 - AddWearableSortOrder - - Comment - Specifies sort order for add wearable panel (0 = name, 1 = date, 2 = by type) - Persist - 1 - Type - U32 - Value - 0 - AgentPause Comment diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 17e7965ab7..c7ac4af14c 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -86,6 +86,11 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK; static const std::string REVERT_BTN("revert_btn"); + +/////////////////////////////////////////////////////////////////////////////// +// LLShopURLDispatcher +/////////////////////////////////////////////////////////////////////////////// + class LLShopURLDispatcher { public: @@ -145,6 +150,10 @@ std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex return gSavedSettings.getString(setting_name); } +/////////////////////////////////////////////////////////////////////////////// +// LLPanelOutfitEditGearMenu +/////////////////////////////////////////////////////////////////////////////// + class LLPanelOutfitEditGearMenu { public: @@ -160,7 +169,6 @@ public: if (menu) { populateCreateWearableSubmenus(menu); - menu->buildDrawLabels(); } return menu; @@ -209,6 +217,147 @@ private: } }; +/////////////////////////////////////////////////////////////////////////////// +// LLAddWearablesGearMenu +/////////////////////////////////////////////////////////////////////////////// + +class LLAddWearablesGearMenu : public LLInitClass +{ +public: + static LLMenuGL* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + llassert(flat_list); + llassert(inventory_panel); + + LLHandle flat_list_handle = flat_list->getHandle(); + LLHandle inventory_panel_handle = inventory_panel->getHandle(); + + registrar.add("AddWearable.Gear.Sort", boost::bind(onSort, flat_list_handle, inventory_panel_handle, _2)); + enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2)); + enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2)); + + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile( + "menu_add_wearable_gear.xml", + LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + + return menu; + } + +private: + static void onSort(LLHandle flat_list_handle, + LLHandle inventory_panel_handle, + LLSD::String sort_order_str) + { + if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return; + + LLWearableItemsList* flat_list = dynamic_cast(flat_list_handle.get()); + LLInventoryPanel* inventory_panel = dynamic_cast(inventory_panel_handle.get()); + + if (!flat_list || !inventory_panel) return; + + LLWearableItemsList::ESortOrder sort_order; + + if ("by_most_recent" == sort_order_str) + { + sort_order = LLWearableItemsList::E_SORT_BY_MOST_RECENT; + } + else if ("by_name" == sort_order_str) + { + sort_order = LLWearableItemsList::E_SORT_BY_NAME; + } + else if ("by_type" == sort_order_str) + { + sort_order = LLWearableItemsList::E_SORT_BY_TYPE_NAME; + } + else + { + llwarns << "Unrecognized sort order action" << llendl; + return; + } + + if (inventory_panel->getVisible()) + { + inventory_panel->setSortOrder(sort_order); + } + else + { + flat_list->setSortOrder(sort_order); + } + } + + static bool onCheck(LLHandle flat_list_handle, + LLHandle inventory_panel_handle, + LLSD::String sort_order_str) + { + if (flat_list_handle.isDead() || inventory_panel_handle.isDead()) return false; + + LLWearableItemsList* flat_list = dynamic_cast(flat_list_handle.get()); + LLInventoryPanel* inventory_panel = dynamic_cast(inventory_panel_handle.get()); + + if (!inventory_panel || !flat_list) return false; + + // Inventory panel uses its own sort order independent from + // flat list view so this flag is used to distinguish between + // currently visible "tree" or "flat" representation of inventory. + bool inventory_tree_visible = inventory_panel->getVisible(); + + if (inventory_tree_visible) + { + U32 sort_order = inventory_panel->getSortOrder(); + + if ("by_most_recent" == sort_order_str) + { + return LLWearableItemsList::E_SORT_BY_MOST_RECENT & sort_order; + } + else if ("by_name" == sort_order_str) + { + // If inventory panel is not sorted by date then it is sorted by name. + return LLWearableItemsList::E_SORT_BY_MOST_RECENT & ~sort_order; + } + llwarns << "Unrecognized inventory panel sort order" << llendl; + } + else + { + LLWearableItemsList::ESortOrder sort_order = flat_list->getSortOrder(); + + if ("by_most_recent" == sort_order_str) + { + return LLWearableItemsList::E_SORT_BY_MOST_RECENT == sort_order; + } + else if ("by_name" == sort_order_str) + { + return LLWearableItemsList::E_SORT_BY_NAME == sort_order; + } + else if ("by_type" == sort_order_str) + { + return LLWearableItemsList::E_SORT_BY_TYPE_NAME == sort_order; + } + llwarns << "Unrecognized wearable list sort order" << llendl; + } + return false; + } + + static bool onVisible(LLHandle inventory_panel_handle, + LLSD::String sort_order_str) + { + if (inventory_panel_handle.isDead()) return false; + + LLInventoryPanel* inventory_panel = dynamic_cast(inventory_panel_handle.get()); + + // Enable sorting by type only for the flat list of items + // because inventory panel doesn't support this kind of sorting. + return ( "by_type" == sort_order_str ) + && ( !inventory_panel || !inventory_panel->getVisible() ); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLCOFDragAndDropObserver +/////////////////////////////////////////////////////////////////////////////// + class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver { public: @@ -244,12 +393,17 @@ void LLCOFDragAndDropObserver::done() LLAppearanceMgr::instance().updateAppearanceFromCOF(); } +/////////////////////////////////////////////////////////////////////////////// +// LLPanelOutfitEdit +/////////////////////////////////////////////////////////////////////////////// + LLPanelOutfitEdit::LLPanelOutfitEdit() : LLPanel(), mSearchFilter(NULL), mCOFWearables(NULL), mInventoryItemsPanel(NULL), mGearMenu(NULL), + mAddWearablesGearMenu(NULL), mCOFDragAndDropObserver(NULL), mInitialized(false), mAddWearablesPanel(NULL), @@ -284,8 +438,6 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit() delete mCOFDragAndDropObserver; - delete mWearableListViewItemsComparator; - while (!mListViewItemTypes.empty()) { delete mListViewItemTypes.back(); mListViewItemTypes.pop_back(); @@ -391,24 +543,11 @@ BOOL LLPanelOutfitEdit::postBuild() childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); - /* - * By default AT_CLOTHING are sorted by (in in MY OUTFITS): - * - by type (types order determined in LLWearableType::EType) - * - each LLWearableType::EType by outer layer on top - * - * In Add More panel AT_CLOTHING should be sorted in a such way: - * - by type (types order determined in LLWearableType::EType) - * - each LLWearableType::EType by name (EXT-8205) - */ - mWearableListViewItemsComparator = new LLWearableItemTypeNameComparator(); - mWearableListViewItemsComparator->setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANK_1, false, true); - mWearablesListViewPanel = getChild("filtered_wearables_panel"); - mWearableItemsList = getChild("list_view"); + mWearableItemsList = getChild("list_view"); mWearableItemsList->setCommitOnSelectionChange(true); mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this)); mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this)); - mWearableItemsList->setComparator(mWearableListViewItemsComparator); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); return TRUE; @@ -462,6 +601,17 @@ void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables) showWearablesFilter(); + /* + * By default AT_CLOTHING are sorted by (in in MY OUTFITS): + * - by type (types order determined in LLWearableType::EType) + * - each LLWearableType::EType by outer layer on top + * + * In Add More panel AT_CLOTHING should be sorted in a such way: + * - by type (types order determined in LLWearableType::EType) + * - each LLWearableType::EType by name (EXT-8205) + */ + mWearableItemsList->setSortOrder(LLWearableItemsList::E_SORT_BY_TYPE_NAME); + // Reset mWearableItemsList position to top. See EXT-8180. mWearableItemsList->goToTop(); } @@ -1063,13 +1213,33 @@ void LLPanelOutfitEdit::resetAccordionState() void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button) { - if(!mGearMenu) + LLMenuGL* menu = NULL; + + if (mAddWearablesPanel->getVisible()) { - mGearMenu = LLPanelOutfitEditGearMenu::create(); + if (!mAddWearablesGearMenu) + { + mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel); + } + + menu = mAddWearablesGearMenu; + } + else + { + if (!mGearMenu) + { + mGearMenu = LLPanelOutfitEditGearMenu::create(); + } + + menu = mGearMenu; } - S32 menu_y = mGearMenu->getRect().getHeight() + clicked_button->getRect().getHeight(); - LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y); + if (!menu) return; + + menu->arrangeAndClear(); // update menu height + S32 menu_y = menu->getRect().getHeight() + clicked_button->getRect().getHeight(); + menu->buildDrawLabels(); + LLMenuGL::showPopup(clicked_button, menu, 0, menu_y); } void LLPanelOutfitEdit::onAddMoreButtonClicked() diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index b3394e45a3..0b6926b83e 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -43,8 +43,8 @@ #include "llremoteparcelrequest.h" #include "llinventory.h" #include "llinventoryfunctions.h" -#include "llinventoryitemslist.h" #include "llinventorymodel.h" +#include "llwearableitemslist.h" class LLButton; class LLCOFWearables; @@ -230,9 +230,8 @@ private: LLComboBox* mListViewFilterCmbBox; LLFilteredWearableListManager* mWearableListManager; - LLInventoryItemsList* mWearableItemsList; + LLWearableItemsList* mWearableItemsList; LLPanel* mWearablesListViewPanel; - LLWearableItemTypeNameComparator* mWearableListViewItemsComparator; LLCOFDragAndDropObserver* mCOFDragAndDropObserver; @@ -241,6 +240,7 @@ private: LLCOFWearables* mCOFWearables; LLMenuGL* mGearMenu; + LLMenuGL* mAddWearablesGearMenu; bool mInitialized; std::auto_ptr mSaveComboBtn; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 34f6fbebd6..c9130b56b4 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -583,11 +583,28 @@ bool LLWearableItemTypeNameComparator::sortWearableTypeByName(LLAssetType::EType return const_it->second.mSortWearableTypeByName; } + +/*virtual*/ +bool LLWearableItemCreationDateComparator::doCompare(const LLPanelInventoryListItemBase* item1, const LLPanelInventoryListItemBase* item2) const +{ + time_t date1 = item1->getCreationDate(); + time_t date2 = item2->getCreationDate(); + + if (date1 == date2) + { + return LLWearableItemNameComparator::doCompare(item1, item2); + } + + return date1 > date2; +} ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static const LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR; +static LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR; +static const LLWearableItemTypeNameComparator WEARABLE_TYPE_LAYER_COMPARATOR; +static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR; +static const LLWearableItemCreationDateComparator WEARABLE_CREATION_DATE_COMPARATOR; static const LLDefaultChildRegistry::Register r("wearable_items_list"); @@ -599,7 +616,7 @@ LLWearableItemsList::Params::Params() LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) : LLInventoryItemsList(p) { - setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); + setSortOrder(E_SORT_BY_TYPE_LAYER, false); mIsStandalone = p.standalone; if (mIsStandalone) { @@ -699,6 +716,38 @@ void LLWearableItemsList::onRightClick(S32 x, S32 y) ContextMenu::instance().show(this, selected_uuids, x, y); } +void LLWearableItemsList::setSortOrder(ESortOrder sort_order, bool sort_now) +{ + switch (sort_order) + { + case E_SORT_BY_MOST_RECENT: + setComparator(&WEARABLE_CREATION_DATE_COMPARATOR); + break; + case E_SORT_BY_NAME: + setComparator(&WEARABLE_NAME_COMPARATOR); + break; + case E_SORT_BY_TYPE_LAYER: + setComparator(&WEARABLE_TYPE_LAYER_COMPARATOR); + break; + case E_SORT_BY_TYPE_NAME: + { + WEARABLE_TYPE_NAME_COMPARATOR.setOrder(LLAssetType::AT_CLOTHING, LLWearableItemTypeNameComparator::ORDER_RANK_1, false, true); + setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); + break; + } + + // No "default:" to raise compiler warning + // if we're not handling something + } + + mSortOrder = sort_order; + + if (sort_now) + { + sort(); + } +} + ////////////////////////////////////////////////////////////////////////// /// ContextMenu ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 2e720d13bb..81f1cd1b40 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -379,6 +379,19 @@ private: wearable_type_order_map_t mWearableOrder; }; +/** + * @class LLWearableItemCreationDateComparator + * + * Comparator for sorting wearable list items by creation date (newest go first). + */ +class LLWearableItemCreationDateComparator : public LLWearableItemNameComparator +{ + LOG_CLASS(LLWearableItemCreationDateComparator); + +protected: + /*virtual*/ bool doCompare(const LLPanelInventoryListItemBase* item1, const LLPanelInventoryListItemBase* item2) const; +}; + /** * @class LLWearableItemsList * @@ -431,6 +444,14 @@ public: Params(); }; + typedef enum e_sort_order { + // Values should be compatible with InventorySortOrder setting. + E_SORT_BY_NAME = 0, + E_SORT_BY_MOST_RECENT = 1, + E_SORT_BY_TYPE_LAYER = 2, + E_SORT_BY_TYPE_NAME = 3, + } ESortOrder; + virtual ~LLWearableItemsList(); /*virtual*/ void addNewItem(LLViewerInventoryItem* item, bool rearrange = true); @@ -445,6 +466,10 @@ public: bool isStandalone() const { return mIsStandalone; } + ESortOrder getSortOrder() const { return mSortOrder; } + + void setSortOrder(ESortOrder sort_order, bool sort_now = true); + protected: friend class LLUICtrlFactory; LLWearableItemsList(const LLWearableItemsList::Params& p); @@ -453,6 +478,8 @@ protected: bool mIsStandalone; bool mWornIndicationEnabled; + + ESortOrder mSortOrder; }; #endif //LL_LLWEARABLEITEMSLIST_H -- cgit v1.2.3