diff options
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 2 | ||||
| -rw-r--r-- | indra/llui/llflatlistview.cpp | 12 | ||||
| -rw-r--r-- | indra/llui/llflatlistview.h | 1 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
| -rw-r--r-- | indra/newview/llinventoryitemslist.cpp | 37 | ||||
| -rw-r--r-- | indra/newview/llinventoryitemslist.h | 7 | ||||
| -rw-r--r-- | indra/newview/llinventorylistitem.cpp | 11 | ||||
| -rw-r--r-- | indra/newview/llinventorylistitem.h | 3 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitedit.cpp | 244 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitedit.h | 11 | ||||
| -rw-r--r-- | indra/newview/llwearableitemslist.cpp | 44 | ||||
| -rw-r--r-- | indra/newview/llwearableitemslist.h | 26 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml | 41 | 
13 files changed, 433 insertions, 17 deletions
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index e2fecdffef..ef0bdb21b4 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -83,7 +83,7 @@ public:  	static LLVBOPool sDynamicVBOPool;  	static LLVBOPool sStreamIBOPool;  	static LLVBOPool sDynamicIBOPool; -	 +  	static BOOL	sUseStreamDraw;  	static void initClass(bool use_vbo); diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index b87851490d..a3debdb19a 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -776,6 +776,18 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)  	return true;  } +void LLFlatListView::scrollToShowFirstSelectedItem() +{ +	if (!mSelectedItemPairs.size())	return; + +	LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); + +	if (selected_rc.isValid()) +	{ +		scrollToShowRect(selected_rc); +	} +} +  LLRect LLFlatListView::getLastSelectedItemRect()  {  	if (!mSelectedItemPairs.size()) diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index ded46d8122..bf72289c47 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -293,6 +293,7 @@ public:  	bool updateValue(const LLSD& old_value, const LLSD& new_value); +	void scrollToShowFirstSelectedItem();  	void selectFirstItem	();  	void selectLastItem		(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 510dc815f0..160749e333 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -35,6 +35,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>AddWearableSortOrder</key> +    <map> +      <key>Comment</key> +      <string>Specifies sort order for add wearable panel (0 = name, 1 = date, 2 = by type)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>AgentPause</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index fbb3774917..83725f40ee 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -85,6 +85,37 @@ boost::signals2::connection LLInventoryItemsList::setRefreshCompleteCallback(con  	return mRefreshCompleteSignal.connect(cb);  } +bool LLInventoryItemsList::selectItemByValue(const LLSD& value, bool select) +{ +	if (!LLFlatListView::selectItemByValue(value, select) && !value.isUndefined()) +	{ +		mSelectTheseIDs.push_back(value); +		return false; +	} +	return true; +} + +void LLInventoryItemsList::updateSelection() +{ +	if(mSelectTheseIDs.empty()) return; + +	std::vector<LLSD> cur; +	getValues(cur); + +	for(std::vector<LLSD>::const_iterator cur_id_it = cur.begin(); cur_id_it != cur.end() && !mSelectTheseIDs.empty(); ++cur_id_it) +	{ +		uuid_vec_t::iterator select_ids_it = std::find(mSelectTheseIDs.begin(), mSelectTheseIDs.end(), *cur_id_it); +		if(select_ids_it != mSelectTheseIDs.end()) +		{ +			selectItemByUUID(*select_ids_it); +			mSelectTheseIDs.erase(select_ids_it); +		} +	} + +	scrollToShowFirstSelectedItem(); +	mSelectTheseIDs.clear(); +} +  void LLInventoryItemsList::doIdle()  {  	if (!mNeedsRefresh) return; @@ -149,6 +180,12 @@ void LLInventoryItemsList::refresh()  	bool needs_refresh = add_limit_exceeded;  	setNeedsRefresh(needs_refresh);  	setForceRefresh(needs_refresh); + +	// After list building completed, select items that had been requested to select before list was build +	if(!needs_refresh) +	{ +		updateSelection(); +	}  }  void LLInventoryItemsList::computeDifference( diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 71c7b6a675..5800111f46 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -68,6 +68,10 @@ public:  	 */  	void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; } +	virtual bool selectItemByValue(const LLSD& value, bool select = true); + +	void updateSelection(); +  	/**  	 * Idle routine used to refresh the list regardless of the current list  	 * visibility, unlike draw() which is called only for the visible list. @@ -104,6 +108,9 @@ protected:  private:  	uuid_vec_t mIDs; // IDs of items that were added in refreshList().  					 // Will be used in refresh() to determine added and removed ids + +	uuid_vec_t mSelectTheseIDs; // IDs that will be selected if list is not loaded till now +  	bool mNeedsRefresh;  	bool mForceRefresh; diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index c487aa10a7..7ed4c0dbe5 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -211,6 +211,17 @@ const std::string& LLPanelInventoryListItemBase::getDescription() const  	return inv_item->getDescription();  } +time_t LLPanelInventoryListItemBase::getCreationDate() const +{ +	LLViewerInventoryItem* inv_item = getItem(); +	if (NULL == inv_item) +	{ +		return 0; +	} + +	return inv_item->getCreationDate(); +} +  LLViewerInventoryItem* LLPanelInventoryListItemBase::getItem() const  {  	return gInventory.getItem(mInventoryItemUUID); diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h index f29d92d51c..600bf77230 100644 --- a/indra/newview/llinventorylistitem.h +++ b/indra/newview/llinventorylistitem.h @@ -146,6 +146,9 @@ public:  	/** Get the description of a corresponding inventory item */  	const std::string& getDescription() const; +	/** Get the creation date of a corresponding inventory item */ +	time_t getCreationDate() const; +  	/** Get the associated inventory item */  	LLViewerInventoryItem* getItem() const; diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index ffd879dfd7..a04a040141 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -42,8 +42,8 @@  #include "lloutfitobserver.h"  #include "llcofwearables.h"  #include "llfilteredwearablelist.h" +#include "llfolderviewitem.h"  #include "llinventory.h" -#include "llinventoryitemslist.h"  #include "llviewercontrol.h"  #include "llui.h"  #include "llfloater.h" @@ -84,6 +84,11 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;  static const std::string REVERT_BTN("revert_btn"); + +/////////////////////////////////////////////////////////////////////////////// +// LLShopURLDispatcher +/////////////////////////////////////////////////////////////////////////////// +  class LLShopURLDispatcher  {  public: @@ -143,6 +148,10 @@ std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex  	return gSavedSettings.getString(setting_name);  } +/////////////////////////////////////////////////////////////////////////////// +// LLPanelOutfitEditGearMenu +/////////////////////////////////////////////////////////////////////////////// +  class LLPanelOutfitEditGearMenu  {  public: @@ -158,7 +167,6 @@ public:  		if (menu)  		{  			populateCreateWearableSubmenus(menu); -			menu->buildDrawLabels();  		}  		return menu; @@ -207,6 +215,131 @@ private:  	}  }; +/////////////////////////////////////////////////////////////////////////////// +// LLAddWearablesGearMenu +/////////////////////////////////////////////////////////////////////////////// + +class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu> +{ +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); + +		registrar.add("AddWearable.Gear.Sort", boost::bind(onSort, flat_list, inventory_panel, _2)); +		enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list, inventory_panel, _2)); +		enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel, _2)); + +		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>( +			"menu_add_wearable_gear.xml", +			LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + +		return menu; +	} + +private: +	static void onSort(LLWearableItemsList* flat_list, +					   LLInventoryPanel* inventory_panel, +					   LLSD::String sort_order_str) +	{ +		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; +		} +		else +		{ +			llwarns << "Unrecognized sort order action" << llendl; +			return; +		} + +		if (inventory_panel->getVisible()) +		{ +			inventory_panel->setSortOrder(sort_order); +		} +		else +		{ +			flat_list->setSortOrder(sort_order); +			gSavedSettings.setU32("AddWearableSortOrder", sort_order); +		} +	} + +	static bool onCheck(LLWearableItemsList* flat_list, +						LLInventoryPanel* inventory_panel, +						LLSD::String sort_order_str) +	{ +		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 == sort_order; +			} +			llwarns << "Unrecognized wearable list sort order" << llendl; +		} +		return false; +	} + +	static bool onVisible(LLInventoryPanel* inventory_panel, +						  LLSD::String sort_order_str) +	{ +		// 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: @@ -242,12 +375,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), @@ -325,7 +463,9 @@ BOOL LLPanelOutfitEdit::postBuild()  	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);  	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL); +	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);  	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL); +	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);  	childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);  	childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);  	childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL); @@ -384,10 +524,11 @@ BOOL LLPanelOutfitEdit::postBuild()  	childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));  	mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel"); -	mWearableItemsList = getChild<LLInventoryItemsList>("list_view"); +	mWearableItemsList = getChild<LLWearableItemsList>("list_view");  	mWearableItemsList->setCommitOnSelectionChange(true);  	mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this));  	mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this)); +	mWearableItemsList->setSortOrder((LLWearableItemsList::ESortOrder)gSavedSettings.getU32("AddWearableSortOrder"));  	mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));  	return TRUE; @@ -472,9 +613,7 @@ void LLPanelOutfitEdit::showWearablesListView()  {  	if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel))  	{ -		mFolderViewBtn->setToggleState(FALSE); -		mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); -		mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); +		updateWearablesPanelVerbButtons();  		updateFiltersVisibility();  	}  	mListViewBtn->setToggleState(TRUE); @@ -484,9 +623,7 @@ void LLPanelOutfitEdit::showWearablesFolderView()  {  	if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel))  	{ -		mListViewBtn->setToggleState(FALSE); -		mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); -		mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); +		updateWearablesPanelVerbButtons();  		updateFiltersVisibility();  	}  	mFolderViewBtn->setToggleState(TRUE); @@ -894,13 +1031,33 @@ bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch  void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)  { -	if(!mGearMenu) +	LLMenuGL* menu = NULL; + +	if (mAddWearablesPanel->getVisible()) +	{ +		if (!mAddWearablesGearMenu) +		{ +			mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel); +		} + +		menu = mAddWearablesGearMenu; +	} +	else  	{ -		mGearMenu = LLPanelOutfitEditGearMenu::create(); +		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() @@ -980,5 +1137,66 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)  //	return selected_id;  } +void LLPanelOutfitEdit::updateWearablesPanelVerbButtons() +{ +	if(mWearablesListViewPanel->getVisible()) +	{ +		mFolderViewBtn->setToggleState(FALSE); +		mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); +		mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); +	} +	else if(mInventoryItemsPanel->getVisible()) +	{ +		mListViewBtn->setToggleState(FALSE); +		mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); +		mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); +	} +} + +void LLPanelOutfitEdit::saveListSelection() +{ +	if(mWearablesListViewPanel->getVisible()) +	{ +		std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + +		if(!selected_ids.size()) return; + +		mWearableItemsList->resetSelection(); + +		for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		{ +			mWearableItemsList->selectItemByUUID(*item_id, true); +		} +		mWearableItemsList->scrollToShowFirstSelectedItem(); +	} +	else if(mInventoryItemsPanel->getVisible()) +	{ +		std::vector<LLUUID> selected_ids; +		mWearableItemsList->getSelectedUUIDs(selected_ids); + +		if(!selected_ids.size()) return; + +		mInventoryItemsPanel->clearSelection(); +		LLFolderView* root = mInventoryItemsPanel->getRootFolder(); + +		if(!root) return; + +		for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		{ +			LLFolderViewItem* item = root->getItemByID(*item_id); +			if (!item) continue; + +			LLFolderViewFolder* parent = item->getParentFolder(); +			if(parent) +			{ +				parent->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); +			} +			mInventoryItemsPanel->getRootFolder()->changeSelection(item, TRUE); +		} +		mInventoryItemsPanel->getRootFolder()->scrollToShowSelection(); +	} + +} +  // EOF diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index de1bf87fb3..c19b43c9fd 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; @@ -140,6 +140,12 @@ public:  	void showWearablesListView();  	void showWearablesFolderView(); +	/** +	 * Method preserves selection while switching between folder/list view modes +	*/ +	void saveListSelection(); + +	void updateWearablesPanelVerbButtons();  	void updateFiltersVisibility();  	void onFolderViewFilterCommitted(LLUICtrl* ctrl); @@ -211,7 +217,7 @@ private:  	LLComboBox*			mListViewFilterCmbBox;  	LLFilteredWearableListManager* 	mWearableListManager; -	LLInventoryItemsList* 			mWearableItemsList; +	LLWearableItemsList* 			mWearableItemsList;  	LLPanel*						mWearablesListViewPanel;  	LLCOFDragAndDropObserver* mCOFDragAndDropObserver; @@ -221,6 +227,7 @@ private:  	LLCOFWearables*		mCOFWearables;  	LLMenuGL*			mGearMenu; +	LLMenuGL*			mAddWearablesGearMenu;  	bool				mInitialized;  	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index cf165f8f66..17b871338f 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -437,11 +437,27 @@ LLWearableItemTypeNameComparator::ETypeListOrder LLWearableItemTypeNameComparato  	}  } +/*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 const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR; +static const LLWearableItemCreationDateComparator WEARABLE_CREATION_DATE_COMPARATOR;  static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list"); @@ -453,7 +469,7 @@ LLWearableItemsList::Params::Params()  LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)  :	LLInventoryItemsList(p)  { -	setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); +	setSortOrder(E_SORT_BY_TYPE, false);  	mIsStandalone = p.standalone;  	if (mIsStandalone)  	{ @@ -553,6 +569,32 @@ 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: +		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 d16a2a89c8..b6d210b4fe 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -311,6 +311,19 @@ private:  };  /** + * @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   *   * A flat list of wearable inventory items. @@ -362,6 +375,13 @@ 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			= 2, +	} ESortOrder; +  	virtual ~LLWearableItemsList();  	/*virtual*/ void addNewItem(LLViewerInventoryItem* item, bool rearrange = true); @@ -376,6 +396,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); @@ -384,6 +408,8 @@ protected:  	bool mIsStandalone;  	bool mWornIndicationEnabled; + +	ESortOrder		mSortOrder;  };  #endif //LL_LLWEARABLEITEMSLIST_H diff --git a/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml b/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml new file mode 100644 index 0000000000..1925d3396f --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_add_wearable_gear.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + layout="topleft" + name="Add Wearable Gear Menu"> +    <menu_item_check +     label="Sort by Most Recent" +     layout="topleft" +     name="sort_by_most_recent"> +        <on_check +         function="AddWearable.Gear.Check" +         parameter="by_most_recent" /> +        <on_click +         function="AddWearable.Gear.Sort" +         parameter="by_most_recent" /> +    </menu_item_check> +    <menu_item_check +     label="Sort by Name" +     layout="topleft" +     name="sort_by_name"> +        <on_check +         function="AddWearable.Gear.Check" +         parameter="by_name" /> +        <on_click +         function="AddWearable.Gear.Sort" +         parameter="by_name" /> +    </menu_item_check> +    <menu_item_check +     label="Sort by Type" +     layout="topleft" +     name="sort_by_type"> +        <on_check +         function="AddWearable.Gear.Check" +         parameter="by_type" /> +        <on_click +         function="AddWearable.Gear.Sort" +         parameter="by_type" /> +        <on_visible +         function="AddWearable.Gear.Visible" +         parameter="by_type" /> +    </menu_item_check> +</menu>  | 
