Commits

dessie linden  committed 135b8ca Merge

Merged from viewer-public

  • Participants
  • Parent commits 86a3063, fe0be77

Comments (0)

Files changed (81)

File indra/llcommon/llstring.cpp

 bool LLStringOps::sPacificDaylightTime = 0;
 std::map<std::string, std::string> LLStringOps::datetimeToCodes;
 
+std::vector<std::string> LLStringOps::sWeekDayList;
+std::vector<std::string> LLStringOps::sWeekDayShortList;
+std::vector<std::string> LLStringOps::sMonthList;
+std::vector<std::string> LLStringOps::sMonthShortList;
+
+
+std::string LLStringOps::sDayFormat;
+std::string LLStringOps::sAM;
+std::string LLStringOps::sPM;
+
+
 S32	LLStringOps::collate(const llwchar* a, const llwchar* b)
 { 
 	#if LL_WINDOWS
 	datetimeToCodes["timezone"]	= "%Z";		// PST
 }
 
+void tokenizeStringToArray(const std::string& data, std::vector<std::string>& output)
+{
+	output.clear();
+	size_t length = data.size();
+	
+	// tokenize it and put it in the array
+	std::string cur_word;
+	for(size_t i = 0; i < length; ++i)
+	{
+		if(data[i] == ':')
+		{
+			output.push_back(cur_word);
+			cur_word.clear();
+		}
+		else
+		{
+			cur_word.append(1, data[i]);
+		}
+	}
+	output.push_back(cur_word);
+}
+
+void LLStringOps::setupWeekDaysNames(const std::string& data)
+{
+	tokenizeStringToArray(data,sWeekDayList);
+}
+void LLStringOps::setupWeekDaysShortNames(const std::string& data)
+{
+	tokenizeStringToArray(data,sWeekDayShortList);
+}
+void LLStringOps::setupMonthNames(const std::string& data)
+{
+	tokenizeStringToArray(data,sMonthList);
+}
+void LLStringOps::setupMonthShortNames(const std::string& data)
+{
+	tokenizeStringToArray(data,sMonthShortList);
+}
+void LLStringOps::setupDayFormat(const std::string& data)
+{
+	sDayFormat = data;
+}
+
+
 std::string LLStringOps::getDatetimeCode (std::string key)
 {
 	std::map<std::string, std::string>::iterator iter;
 
 ////////////////////////////////////////////////////////////
 
+// Forward specialization of LLStringUtil::format before use in LLStringUtil::formatDatetime.
+template<>
+S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions);
+
 //static
 template<> 
 void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims)
 		}
 		return true;
 	}
-	replacement = datetime.toHTTPDateString(code);
+
+	//EXT-7013
+	//few codes are not suppotred by strtime function (example - weekdays for Japanise)
+	//so use predefined ones
+	
+	//if sWeekDayList is not empty than current locale doesn't support
+        //weekday name.
+	time_t loc_seconds = (time_t) secFromEpoch;
+	if(LLStringOps::sWeekDayList.size() == 7 && code == "%A")
+	{
+		struct tm * gmt = gmtime (&loc_seconds);
+		replacement = LLStringOps::sWeekDayList[gmt->tm_wday];
+	}
+	else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a")
+	{
+		struct tm * gmt = gmtime (&loc_seconds);
+		replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday];
+	}
+	else if(LLStringOps::sMonthList.size() == 12 && code == "%B")
+	{
+		struct tm * gmt = gmtime (&loc_seconds);
+		replacement = LLStringOps::sWeekDayList[gmt->tm_mon];
+	}
+	else if( !LLStringOps::sDayFormat.empty() && code == "%d" )
+	{
+		struct tm * gmt = gmtime (&loc_seconds);
+		LLStringUtil::format_map_t args;
+		args["[MDAY]"] = llformat ("%d", gmt->tm_mday);
+		replacement = LLStringOps::sDayFormat;
+		LLStringUtil::format(replacement, args);
+	}
+	else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" )
+	{
+		struct tm * gmt = gmtime (&loc_seconds);
+		if(gmt->tm_hour<12)
+		{
+			replacement = LLStringOps::sAM;
+		}
+		else
+		{
+			replacement = LLStringOps::sPM;
+		}
+	}
+	else
+	{
+		replacement = datetime.toHTTPDateString(code);
+	}
 
 	// *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format
 	// to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738).

File indra/llcommon/llstring.h

 	static long sPacificTimeOffset;
 	static long sLocalTimeOffset;
 	static bool sPacificDaylightTime;
+
 	static std::map<std::string, std::string> datetimeToCodes;
 
 public:
+	static std::vector<std::string> sWeekDayList;
+	static std::vector<std::string> sWeekDayShortList;
+	static std::vector<std::string> sMonthList;
+	static std::vector<std::string> sMonthShortList;
+	static std::string sDayFormat;
+
+	static std::string sAM;
+	static std::string sPM;
+
 	static char toUpper(char elem) { return toupper((unsigned char)elem); }
 	static llwchar toUpper(llwchar elem) { return towupper(elem); }
 	
 	static S32	collate(const llwchar* a, const llwchar* b);
 
 	static void setupDatetimeInfo(bool pacific_daylight_time);
+
+	static void setupWeekDaysNames(const std::string& data);
+	static void setupWeekDaysShortNames(const std::string& data);
+	static void setupMonthNames(const std::string& data);
+	static void setupMonthShortNames(const std::string& data);
+	static void setupDayFormat(const std::string& data);
+
+
 	static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
 	static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
 	// Is the Pacific time zone (aka server time zone)

File indra/llui/llaccordionctrl.cpp

  , mFitParent(params.fit_parent)
  , mAutoScrolling( false )
  , mAutoScrollRate( 0.f )
+ , mSelectedTab( NULL )
 {
   mSingleExpansion = params.single_expansion;
 	if(mFitParent && !mSingleExpansion)
 LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
  , mAutoScrolling( false )
  , mAutoScrollRate( 0.f )
+ , mSelectedTab( NULL )
 {
 	mSingleExpansion = false;
 	mFitParent = false;
 			}
 			return 0;
 		}
+		else if(str_action == "select_current")
+		{
+			for(size_t i=0;i<mAccordionTabs.size();++i)
+			{
+				// Set selection to the currently focused tab.
+				if(mAccordionTabs[i]->hasFocus())
+				{
+					if (mAccordionTabs[i] != mSelectedTab)
+					{
+						if (mSelectedTab)
+						{
+							mSelectedTab->setSelected(false);
+						}
+						mSelectedTab = mAccordionTabs[i];
+						mSelectedTab->setSelected(true);
+					}
+
+					return 1;
+				}
+			}
+			return 0;
+		}
 	}
 	else if (info.has("scrollToShowRect"))
 	{

File indra/llui/llaccordionctrl.h

 	bool			mFitParent;
 	bool			mAutoScrolling;
 	F32				mAutoScrollRate;
+	LLAccordionCtrlTab* mSelectedTab;
 };
 
 

File indra/llui/llaccordionctrltab.cpp

 	std::string getTitle();
 	void	setTitle(const std::string& title, const std::string& hl);
 
+	void	setSelected(bool is_selected) { mIsSelected = is_selected; }
+
 	virtual void onMouseEnter(S32 x, S32 y, MASK mask);
 	virtual void onMouseLeave(S32 x, S32 y, MASK mask);
 	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
 	LLUIColor mHeaderBGColor;
 
 	bool mNeedsHighlight;
+	bool mIsSelected;
 
 	LLFrameTimer mAutoOpenTimer;
 };
 	const LLAccordionCtrlTabHeader::Params& p)
 : LLUICtrl(p)
 , mHeaderBGColor(p.header_bg_color())
-,mNeedsHighlight(false),
+, mNeedsHighlight(false)
+, mIsSelected(false),
 	mImageCollapsed(p.header_collapse_img),
 	mImageCollapsedPressed(p.header_collapse_img_pressed),
 	mImageExpanded(p.header_expand_img),
 	// Only show green "focus" background image if the accordion is open,
 	// because the user's mental model of focus is that it goes away after
 	// the accordion is closed.
-	if (getParent()->hasFocus()
+	if (getParent()->hasFocus() || mIsSelected
 		/*&& !(collapsible && !expanded)*/ // WHY??
 		)
 	{
 	,header_image_focused("header_image_focused")
 	,header_text_color("header_text_color")
 	,fit_panel("fit_panel",true)
+	,selection_enabled("selection_enabled", false)
 {
 	mouse_opaque(false);
 }
 	mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
 	addChild(mHeader, 1);
 
+	if (p.selection_enabled)
+	{
+		LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
+	}
+
 	reshape(100, 200,FALSE);
 }
 
 	return boost::signals2::connection();
 }
 
+void LLAccordionCtrlTab::setSelected(bool is_selected)
+{
+	LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+	if (header)
+	{
+		header->setSelected(is_selected);
+	}
+}
+
 LLView*	LLAccordionCtrlTab::findContainerView()
 {
 	for(child_list_const_iter_t it = getChildList()->begin(); 
 	return NULL;
 }
 
+void LLAccordionCtrlTab::selectOnFocusReceived()
+{
+	if (getParent()) // A parent may not be set if tabs are added dynamically.
+		getParent()->notifyParent(LLSD().with("action", "select_current"));
+}
 
 S32 LLAccordionCtrlTab::getHeaderHeight()
 {
 {
 	LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);	
 	header->setFocus(true);
+	header->setSelected(true);
 
 	LLRect screen_rc;
 	LLRect selected_rc = header->getRect();

File indra/llui/llaccordionctrltab.h

 
 		Optional<bool>			fit_panel;
 
+		Optional<bool>			selection_enabled;
+
 		Optional<S32>			padding_left;
 		Optional<S32>			padding_right;
 		Optional<S32>			padding_top;
 	boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb);
 	boost::signals2::connection setFocusLostCallback(const focus_signal_t::slot_type& cb);
 
+	void setSelected(bool is_selected);
+
 	bool getCollapsible() {return mCollapsible;};
 
 	void setCollapsible(bool collapsible) {mCollapsible = collapsible;};
 	void drawChild(const LLRect& root_rect,LLView* child);
 
 	LLView* findContainerView	();
+
+	void selectOnFocusReceived();
+
 private:
 
 	class LLAccordionCtrlTabHeader;

File indra/llui/llbutton.cpp

 	mImageSelected(p.image_selected),
 	mImageDisabled(p.image_disabled),
 	mImageDisabledSelected(p.image_disabled_selected),
+	mImageFlash(p.image_flash),
 	mImagePressed(p.image_pressed),
 	mImagePressedSelected(p.image_pressed_selected),
 	mImageHoverSelected(p.image_hover_selected),
 
 	if (mFlashing)
 	{
-		LLColor4 flash_color = mFlashBgColor.get();
-		use_glow_effect = TRUE;
-		glow_type = LLRender::BT_ALPHA; // blend the glow
-
-		if (mNeedsHighlight) // highlighted AND flashing
-			glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity
+		// if we have icon for flashing, use it as image for button
+		if(flash && mImageFlash->getName() != "FlashIconAbsent")
+		{
+			// setting flash to false to avoid its further influence on glow
+			flash = false;
+			imagep = mImageFlash;
+		}
+		// else use usual flashing via flash_color
 		else
-			glow_color = flash_color;
+		{
+			LLColor4 flash_color = mFlashBgColor.get();
+			use_glow_effect = TRUE;
+			glow_type = LLRender::BT_ALPHA; // blend the glow
+			if (mNeedsHighlight) // highlighted AND flashing
+				glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity
+			else
+				glow_color = flash_color;
+		}
 	}
 
 	if (mNeedsHighlight && !imagep)
 	mImageHoverUnselected = image;
 }
 
+void LLButton::setImageFlash(LLPointer<LLUIImage> image)
+{
+	mImageFlash = image;
+}
+
 void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment, const LLColor4& color)
 {
 	if (image_name.empty())

File indra/llui/llbutton.h

 								image_hover_unselected,
 								image_disabled_selected,
 								image_disabled,
+								image_flash,
 								image_pressed,
 								image_pressed_selected,
 								image_overlay;
 	void			setImageHoverUnselected(LLPointer<LLUIImage> image);
 	void			setImageDisabled(LLPointer<LLUIImage> image);
 	void			setImageDisabledSelected(LLPointer<LLUIImage> image);
+	void			setImageFlash(LLPointer<LLUIImage> image);
 	void			setImagePressed(LLPointer<LLUIImage> image);
 
 	void			setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
 	LLPointer<LLUIImage>		mImagePressed;
 	LLPointer<LLUIImage>		mImagePressedSelected;
 
+	/* There are two ways an image can flash- by making changes in color according to flash_color attribute
+	   or by changing icon from current to the one specified in image_flash. Second way is used only if
+	   the name of flash icon is different from "FlashIconAbsent" which is there by default. First way is used 
+	   otherwise. */
+	LLPointer<LLUIImage>		mImageFlash;
+
 	LLUIColor					mHighlightColor;
 	LLUIColor					mFlashBgColor;
 

File indra/llui/lltabcontainer.cpp

 LLTabContainer::TabParams::TabParams()
 :	tab_top_image_unselected("tab_top_image_unselected"),
 	tab_top_image_selected("tab_top_image_selected"),
+	tab_top_image_flash("tab_top_image_flash"),
 	tab_bottom_image_unselected("tab_bottom_image_unselected"),
 	tab_bottom_image_selected("tab_bottom_image_selected"),
+	tab_bottom_image_flash("tab_bottom_image_flash"),
 	tab_left_image_unselected("tab_left_image_unselected"),
-	tab_left_image_selected("tab_left_image_selected")
+	tab_left_image_selected("tab_left_image_selected"),
+	tab_left_image_flash("tab_left_image_flash")
 {}
 
 LLTabContainer::Params::Params()
 		{
 			tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_top_image_unselected));
 			tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_top_image_selected));
+			tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_top_image_flash));
 		}
 		else if (pos == LLTabContainer::BOTTOM)
 		{
 			tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_bottom_image_unselected));
 			tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_bottom_image_selected));
+			tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_bottom_image_flash));
 		}
 		else if (pos == LLTabContainer::LEFT)
 		{
 			tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_left_image_unselected));
 			tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_left_image_selected));
+			tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_left_image_flash));
 		}
 	}
 }

File indra/llui/lltabcontainer.h

 	{
 		Optional<LLUIImage*>				tab_top_image_unselected,
 											tab_top_image_selected,
+											tab_top_image_flash,
 											tab_bottom_image_unselected,
 											tab_bottom_image_selected,
+											tab_bottom_image_flash,
 											tab_left_image_unselected,
-											tab_left_image_selected;		
+											tab_left_image_selected,
+											tab_left_image_flash;		
 		TabParams();
 	};
 

File indra/newview/CMakeLists.txt

     lllogchat.cpp
     llloginhandler.cpp
     lllogininstance.cpp
+    llmachineid.cpp
     llmanip.cpp
     llmaniprotate.cpp
     llmanipscale.cpp
     llregionposition.cpp
     llremoteparcelrequest.cpp
     llsavedsettingsglue.cpp
+    llsaveoutfitcombobtn.cpp
     llscreenchannel.cpp
     llscriptfloater.cpp
     llscrollingpanelparam.cpp
     lllogchat.h
     llloginhandler.h
     lllogininstance.h
+    llmachineid.h
     llmanip.h
     llmaniprotate.h
     llmanipscale.h
     llresourcedata.h
     llrootview.h
     llsavedsettingsglue.h
+    llsaveoutfitcombobtn.h
     llscreenchannel.h
     llscriptfloater.h
     llscrollingpanelparam.h
   )
 
     LL_ADD_INTEGRATION_TEST(llsechandler_basic
-     llsechandler_basic.cpp
+    llsechandler_basic.cpp
     "${test_libs}"
     )
 

File indra/newview/app_settings/logcontrol.xml

File contents unchanged.

File indra/newview/app_settings/settings.xml

       <key>Value</key>
       <integer>2</integer>
     </map>
-    <key>AvatarUseBakedTextureTimeout</key>
-    <map>
-      <key>Comment</key>
-      <string>Specifes whether to send your baked textures for avatar appearance even before textures are fully ressed in case of timeout</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
+    <key>AvatarBakedTextureTimeout</key>
+    <map>
+      <key>Comment</key>
+      <string>Specifes the maximum time in seconds to wait before sending your baked textures for avatar appearance.  Set to 0 to disable and wait until all baked textures are at highest resolution.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
       <key>Value</key>
       <integer>0</integer>
     </map>

File indra/newview/llagentwearablesfetch.cpp

 #include "llstartup.h"
 #include "llvoavatarself.h"
 
+
+class LLOrderMyOutfitsOnDestroy: public LLInventoryCallback
+{
+public:
+	LLOrderMyOutfitsOnDestroy() {};
+
+	virtual ~LLOrderMyOutfitsOnDestroy()
+	{
+		const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+		if (my_outfits_id.isNull()) return;
+
+		LLInventoryModel::cat_array_t* cats;
+		LLInventoryModel::item_array_t* items;
+		gInventory.getDirectDescendentsOf(my_outfits_id, cats, items);
+		if (!cats) return;
+
+		//My Outfits should at least contain saved initial outfit and one another outfit
+		if (cats->size() < 2)
+		{
+			llwarning("My Outfits category was not populated properly", 0);
+			return;
+		}
+
+		llinfos << "Starting updating My Outfits with wearables ordering information" << llendl;
+
+		for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin();
+			outfit_iter != cats->end(); ++outfit_iter)
+		{
+			const LLUUID& cat_id = (*outfit_iter)->getUUID();
+			if (cat_id.isNull()) continue;
+
+			// saved initial outfit already contains wearables ordering information
+			if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue;
+
+			LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id);
+		}
+
+		llinfos << "Finished updating My Outfits with wearables ordering information" << llendl;
+	}
+
+	/* virtual */ void fire(const LLUUID& inv_item) {};
+};
+
+
 LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :
 	LLInventoryFetchDescendentsObserver(cof_id)
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
 	
+	LLPointer<LLOrderMyOutfitsOnDestroy> order_myoutfits_on_destroy = new LLOrderMyOutfitsOnDestroy;
+
 	for (uuid_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin();
 		 folder_iter != mImportedClothingFolders.end();
 		 ++folder_iter)
 								item->getName(),
 								item->getDescription(),
 								LLAssetType::AT_LINK,
-								NULL);
+								order_myoutfits_on_destroy);
 		}
 	}
 

File indra/newview/llappearancemgr.cpp

 	U32 mControlSize;
 };
 
-void LLAppearanceMgr::updateClothingOrderingInfo()
+void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id)
 {
+	if (cat_id.isNull())
+	{
+		cat_id = getCOF();
+	}
+
+	// COF is processed if cat_id is not specified
 	LLInventoryModel::item_array_t wear_items;
-	getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false);
+	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING, false);
 
 	wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);
 	divvyWearablesByType(wear_items, items_by_type);

File indra/newview/llappearancemgr.h

 	//Divvy items into arrays by wearable type
 	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
 
+	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
+	// COF is processed if cat_id is not specified
+	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null);
+
 protected:
 	LLAppearanceMgr();
 	~LLAppearanceMgr();
 
 private:
 
-	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
-	void updateClothingOrderingInfo();
-
 	void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
 	
 	void getDescendentsOfAssetType(const LLUUID& category, 

File indra/newview/llappviewer.cpp

 
 // Include for security api initialization
 #include "llsecapi.h"
+#include "llmachineid.h"
 
 // *FIX: These extern globals should be cleaned up.
 // The globals either represent state/config/resource-storage of either 
     // *NOTE:Mani - LLCurl::initClass is not thread safe. 
     // Called before threads are created.
     LLCurl::initClass();
+    LLMachineID::init();
 
     initThreads();
     writeSystemInfo();
 	}
 	
 	LLViewerMedia::initClass();
-	
+
+	LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
+	LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
+	LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
+	LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
+	LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
+
+	LLStringOps::sAM = LLTrans::getString("dateTimeAM");
+	LLStringOps::sPM = LLTrans::getString("dateTimePM");
+
 	return true;
 }
 

File indra/newview/llbottomtray.cpp

 		S32 custom_width = mNearbyChatBar->getRect().getWidth();
 		gSavedSettings.setS32("ChatBarCustomWidth", custom_width);
 	}
+
+	// emulate previous floater behavior to be hidden on startup.
+	// override effect of save_visibility=true.
+	// this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly:
+	//		i.g when floater changes its visibility - button changes its toggle state.
+	getChild<LLUICtrl>("search_btn")->setControlValue(false);
 }
 
 // *TODO Vadim: why void* ?

File indra/newview/llcofwearables.cpp

 #include "llmenugl.h"
 #include "llviewermenu.h"
 #include "llwearableitemslist.h"
+#include "llpaneloutfitedit.h"
+#include "llsidetray.h"
 
 static LLRegisterPanelClassWrapper<LLCOFAccordionListAdaptor> t_cof_accodion_list_adaptor("accordion_list_adaptor");
 
 		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
 		LLUUID selected_id = mUUIDs.back();
 
-		registrar.add("BodyPart.Replace", boost::bind(&LLAppearanceMgr::wearItemOnAvatar,
-			LLAppearanceMgr::getInstance(), selected_id, true, true));
+		// *HACK* need to pass pointer to LLPanelOutfitEdit instead of LLSideTray::getInstance()->getPanel().
+		// LLSideTray::getInstance()->getPanel() is rather slow variant
+		LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));
+		registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));
 		registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
 
 		enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2));
 		LLWearableType::EType w_type = static_cast<LLWearableType::EType>(type);
 		LLPanelInventoryListItemBase* item_panel = LLPanelDummyClothingListItem::create(w_type);
 		if(!item_panel) continue;
+		item_panel->childSetAction("btn_add", mCOFCallbacks.mAddWearable);
 		mClothing->addItem(item_panel, LLUUID::null, ADD_BOTTOM, false);
 	}
 }
 	return selected_ids.size() != 0;
 }
 
+LLPanel* LLCOFWearables::getSelectedItem()
+{
+	if (!mLastSelectedList) return NULL;
+
+	return mLastSelectedList->getSelectedItem();
+}
+
 void LLCOFWearables::clear()
 {
 	mAttachments->clear();

File indra/newview/llcofwearables.h

 		
 		typedef boost::function<void (void*)> cof_callback_t;
 
+		cof_callback_t mAddWearable;
 		cof_callback_t mMoveWearableCloser;
 		cof_callback_t mMoveWearableFurther;
 		cof_callback_t mEditWearable;
 	LLUUID getSelectedUUID();
 	bool getSelectedUUIDs(uuid_vec_t& selected_ids);
 
+	LLPanel* getSelectedItem();
+
 	void refresh();
 	void clear();
 

File indra/newview/llfilteredwearablelist.cpp

 #include "llinventoryitemslist.h"
 #include "llinventorymodel.h"
 
-class LLFindNonLinksByMask : public LLInventoryCollectFunctor
-{
-public:
-	LLFindNonLinksByMask(U64 mask)
-		: mFilterMask(mask)
-	{}
 
-	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
-	{
-		if(item && !item->getIsLinkType() && (mFilterMask & (1LL << item->getInventoryType())) )
-		{
-			return true;
-		}
-
-		return false;
-	}
-
-private:
-	U64 mFilterMask;
-};
-
-//////////////////////////////////////////////////////////////////////////
-
-LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask)
+LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector)
 : mWearableList(list)
-, mFilterMask(filter_mask)
+, mCollector(collector)
 {
 	llassert(mWearableList);
 	gInventory.addObserver(this);
 	populateList();
 }
 
-void LLFilteredWearableListManager::setFilterMask(U64 mask)
+void LLFilteredWearableListManager::setFilterCollector(LLInventoryCollectFunctor* collector)
 {
-	mFilterMask = mask;
+	mCollector = collector;
 	populateList();
 }
 
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t item_array;
-	LLFindNonLinksByMask collector(mFilterMask);
 
-	gInventory.collectDescendentsIf(
-		gInventory.getRootFolderID(),
-		cat_array,
-		item_array,
-		LLInventoryModel::EXCLUDE_TRASH,
-		collector);
+	if(mCollector)
+	{
+		gInventory.collectDescendentsIf(
+				gInventory.getRootFolderID(),
+				cat_array,
+				item_array,
+				LLInventoryModel::EXCLUDE_TRASH,
+				*mCollector);
+	}
 
 	// Probably will also need to get items from Library (waiting for reply in EXT-6724).
 

File indra/newview/llfilteredwearablelist.h

 #ifndef LL_LLFILTEREDWEARABLELIST_H
 #define LL_LLFILTEREDWEARABLELIST_H
 
+#include "llinventoryfunctions.h"
 #include "llinventoryobserver.h"
 
 class LLInventoryItemsList;
 	LOG_CLASS(LLFilteredWearableListManager);
 public:
 
-	LLFilteredWearableListManager(LLInventoryItemsList* list, U64 filter_mask);
+	LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector);
 	~LLFilteredWearableListManager();
 
 	/** LLInventoryObserver implementation
 	/*virtual*/ void changed(U32 mask);
 
 	/**
-	 * Sets new filter and applies it immediately
+	 * Sets new collector and applies it immediately
 	 */
-	void setFilterMask(U64 mask);
+	void setFilterCollector(LLInventoryCollectFunctor* collector);
 
 	/**
 	 * Populates wearable list with filtered data.
 
 private:
 	LLInventoryItemsList* mWearableList;
-	U64 mFilterMask;
+	LLInventoryCollectFunctor* mCollector;
 };
 
 #endif //LL_LLFILTEREDWEARABLELIST_H

File indra/newview/llfloatersnapshot.cpp

 	childSetVisible("save", mode == SNAPSHOT_MAIN);
 	childSetVisible("set_profile_pic", mode == SNAPSHOT_MAIN);
 
-	childSetVisible("share_to_web", mode == SNAPSHOT_SHARE);
+//	childSetVisible("share_to_web", mode == SNAPSHOT_SHARE);
 	childSetVisible("share_to_email", mode == SNAPSHOT_SHARE);
 
 	childSetVisible("save_to_inventory", mode == SNAPSHOT_SAVE);

File indra/newview/llinventoryfunctions.cpp

 	return true;
 }
 
+void LLFindWearablesOfType::setType(LLWearableType::EType type)
+{
+	mWearableType = type;
+}
+
 ///----------------------------------------------------------------------------
 /// LLAssetIDMatches 
 ///----------------------------------------------------------------------------

File indra/newview/llinventoryfunctions.h

 };
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFindNonLinksByMask
+//
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFindNonLinksByMask : public LLInventoryCollectFunctor
+{
+public:
+	LLFindNonLinksByMask(U64 mask)
+		: mFilterMask(mask)
+	{}
+
+	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+	{
+		if(item && !item->getIsLinkType() && (mFilterMask & (1LL << item->getInventoryType())) )
+		{
+			return true;
+		}
+
+		return false;
+	}
+
+	void setFilterMask(U64 mask)
+	{
+		mFilterMask = mask;
+	}
+
+private:
+	U64 mFilterMask;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLFindWearables
 //
 // Collects wearables based on item type.
 	LLFindWearablesOfType(LLWearableType::EType type) : mWearableType(type) {}
 	virtual ~LLFindWearablesOfType() {}
 	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+	void setType(LLWearableType::EType type);
 
-	const LLWearableType::EType mWearableType;
+private:
+	LLWearableType::EType mWearableType;
 };
 
 /**                    Inventory Collector Functions

File indra/newview/llinventoryitemslist.h

 	/** Get the description of a corresponding inventory item */
 	const std::string& getDescription() const { return mItem->getDescription(); }
 
+	/** Get the associated inventory item */
+	LLViewerInventoryItem* getItem() const { return mItem; }
+
 	virtual ~LLPanelInventoryListItemBase(){}
 
 protected:

File indra/newview/llmachineid.cpp

+/** 
+ * @file llmachineid.cpp
+ * @brief retrieves unique machine ids
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * 
+ * Copyright (c) 2010, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "lluuid.h"
+#include "llmachineid.h"
+#if	LL_WINDOWS
+#define _WIN32_DCOM
+#include <iostream>
+using namespace std;
+#include <comdef.h>
+#include <Wbemidl.h>
+#endif
+unsigned char static_unique_id[] =  {0,0,0,0,0,0};
+bool static has_static_unique_id = false;
+
+// get an unique machine id.
+// NOT THREAD SAFE - do before setting up threads.
+// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot,  Go figure??
+
+S32 LLMachineID::init()
+{
+    memset(static_unique_id,0,sizeof(static_unique_id));
+    S32 ret_code = 0;
+#if	LL_WINDOWS
+# pragma comment(lib, "wbemuuid.lib")
+        size_t len = sizeof(static_unique_id);
+
+        // algorithm to detect BIOS serial number found at:
+        // http://msdn.microsoft.com/en-us/library/aa394077%28VS.85%29.aspx
+        // we can't use the MAC address since on Windows 7, the first returned MAC address changes with every reboot.
+
+
+        HRESULT hres;
+
+        // Step 1: --------------------------------------------------
+        // Initialize COM. ------------------------------------------
+
+        hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
+        if (FAILED(hres))
+        {
+            LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x"   << hex << hres << LL_ENDL;
+            return 1;                  // Program has failed.
+        }
+
+        // Step 2: --------------------------------------------------
+        // Set general COM security levels --------------------------
+        // Note: If you are using Windows 2000, you need to specify -
+        // the default authentication credentials for a user by using
+        // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
+        // parameter of CoInitializeSecurity ------------------------
+
+        hres =  CoInitializeSecurity(
+            NULL, 
+            -1,                          // COM authentication
+            NULL,                        // Authentication services
+            NULL,                        // Reserved
+            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
+            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
+            NULL,                        // Authentication info
+            EOAC_NONE,                   // Additional capabilities 
+            NULL                         // Reserved
+            );
+
+                          
+        if (FAILED(hres))
+        {
+            LL_DEBUGS("AppInit") << "Failed to initialize security. Error code = 0x"  << hex << hres << LL_ENDL;
+            CoUninitialize();
+            return 1;                    // Program has failed.
+        }
+        
+        // Step 3: ---------------------------------------------------
+        // Obtain the initial locator to WMI -------------------------
+
+        IWbemLocator *pLoc = NULL;
+
+        hres = CoCreateInstance(
+            CLSID_WbemLocator,             
+            0, 
+            CLSCTX_INPROC_SERVER, 
+            IID_IWbemLocator, (LPVOID *) &pLoc);
+     
+        if (FAILED(hres))
+        {
+            LL_DEBUGS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << LL_ENDL;
+            CoUninitialize();
+            return 1;                 // Program has failed.
+        }
+
+        // Step 4: -----------------------------------------------------
+        // Connect to WMI through the IWbemLocator::ConnectServer method
+
+        IWbemServices *pSvc = NULL;
+    	
+        // Connect to the root\cimv2 namespace with
+        // the current user and obtain pointer pSvc
+        // to make IWbemServices calls.
+        hres = pLoc->ConnectServer(
+             _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
+             NULL,                    // User name. NULL = current user
+             NULL,                    // User password. NULL = current
+             0,                       // Locale. NULL indicates current
+             NULL,                    // Security flags.
+             0,                       // Authority (e.g. Kerberos)
+             0,                       // Context object 
+             &pSvc                    // pointer to IWbemServices proxy
+             );
+        
+        if (FAILED(hres))
+        {
+            LL_DEBUGS("AppInit") << "Could not connect. Error code = 0x"  << hex << hres << LL_ENDL;
+            pLoc->Release();     
+            CoUninitialize();
+            return 1;                // Program has failed.
+        }
+
+        LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL;
+
+
+        // Step 5: --------------------------------------------------
+        // Set security levels on the proxy -------------------------
+
+        hres = CoSetProxyBlanket(
+           pSvc,                        // Indicates the proxy to set
+           RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
+           RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
+           NULL,                        // Server principal name 
+           RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
+           RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
+           NULL,                        // client identity
+           EOAC_NONE                    // proxy capabilities 
+        );
+
+        if (FAILED(hres))
+        {
+            LL_DEBUGS("AppInit") << "Could not set proxy blanket. Error code = 0x"   << hex << hres << LL_ENDL;
+            pSvc->Release();
+            pLoc->Release();     
+            CoUninitialize();
+            return 1;               // Program has failed.
+        }
+
+        // Step 6: --------------------------------------------------
+        // Use the IWbemServices pointer to make requests of WMI ----
+
+        // For example, get the name of the operating system
+        IEnumWbemClassObject* pEnumerator = NULL;
+        hres = pSvc->ExecQuery(
+            bstr_t("WQL"), 
+            bstr_t("SELECT * FROM Win32_OperatingSystem"),
+            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
+            NULL,
+            &pEnumerator);
+        
+        if (FAILED(hres))
+        {
+            LL_DEBUGS("AppInit") << "Query for operating system name failed." << " Error code = 0x"  << hex << hres << LL_ENDL;
+            pSvc->Release();
+            pLoc->Release();
+            CoUninitialize();
+            return 1;               // Program has failed.
+        }
+
+        // Step 7: -------------------------------------------------
+        // Get the data from the query in step 6 -------------------
+     
+        IWbemClassObject *pclsObj = NULL;
+        ULONG uReturn = 0;
+       
+        while (pEnumerator)
+        {
+            HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
+                &pclsObj, &uReturn);
+
+            if(0 == uReturn)
+            {
+                break;
+            }
+
+            VARIANT vtProp;
+
+            // Get the value of the Name property
+            hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
+            LL_DEBUGS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL;
+            // use characters in the returned Serial Number to create a byte array of size len
+            BSTR serialNumber ( vtProp.bstrVal);
+            unsigned int j = 0;
+            while( vtProp.bstrVal[j] != 0)
+            {
+                for (unsigned int i = 0; i < len; i++)
+                {
+                    if (vtProp.bstrVal[j] == 0)
+                        break;
+                    
+                    static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]);
+                    j++;
+                }
+            }
+            VariantClear(&vtProp);
+
+            pclsObj->Release();
+            pclsObj = NULL;
+            break;
+        }
+
+        // Cleanup
+        // ========
+        
+        if (pSvc)
+            pSvc->Release();
+        if (pLoc)
+            pLoc->Release();
+        if (pEnumerator)
+            pEnumerator->Release();
+        CoUninitialize();
+        ret_code=0;
+#else
+        unsigned char * staticPtr = (unsigned char *)(&static_unique_id[0]);
+        ret_code = LLUUID::getNodeID(staticPtr);
+#endif
+        has_static_unique_id = true;
+        return ret_code;
+}
+
+
+S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
+{
+    if (has_static_unique_id)
+    {
+        memcpy ( unique_id, &static_unique_id, len);
+        LL_DEBUGS("AppInit") << "UniqueID: " << unique_id[0] << unique_id[1]<< unique_id[2] << unique_id[3] << unique_id[4] << unique_id [5] << LL_ENDL;
+        return 1;
+    }
+    return 0;
+}
+
+
+
+

File indra/newview/llmachineid.h

+/** 
+ * @file llmachineid.h
+ * @brief retrieves unique machine ids
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ * 
+ * Copyright (c) 2010, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMACHINEID_H
+#define LL_LLMACHINEID_H
+
+
+class LLMachineID 
+{
+public:
+	LLMachineID();
+	virtual	~LLMachineID();
+    static S32 getUniqueID(unsigned char *unique_id, size_t len);
+    static S32 init();
+
+protected:
+
+private:
+
+
+};
+
+
+
+
+
+#endif // LL_LLMACHINEID_H

File indra/newview/llnearbychatbar.cpp

 
 #include "message.h"
 
+#include "llappviewer.h"
 #include "llfloaterreg.h"
 #include "lltrans.h"
 
 	mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this));
 	mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this);
 	mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this));
+	mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChatBar::onChatBoxFocusReceived, this));
 
 	mChatBox->setIgnoreArrowKeys( FALSE ); 
 	mChatBox->setCommitOnFocusLost( FALSE );
 	gAgent.stopTyping();
 }
 
+void LLNearbyChatBar::onChatBoxFocusReceived()
+{
+	mChatBox->setEnabled(!gDisconnected);
+}
+
 EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str)
 {
 	U32 length = str.length();

File indra/newview/llnearbychatbar.h

 	static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str);
 	static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata);
 	static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata);
+	void onChatBoxFocusReceived();
 
 	void sendChat( EChatType type );
 	void onChatBoxCommit();

File indra/newview/lloutfitslist.cpp

 	:	LLPanel()
 	,	mAccordion(NULL)
 	,	mListCommands(NULL)
-	,	mSelectedList(NULL)
 {
 	mCategoriesObserver = new LLInventoryCategoriesObserver();
 	gInventory.addObserver(mCategoriesObserver);
 		// Setting list refresh callback to apply filter on list change.
 		list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1));
 
+		list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3));
+
 		// Fetch the new outfit contents.
 		cat->fetch();
 
 		outfits_map_t::iterator outfits_iter = mOutfitsMap.find((*iter));
 		if (outfits_iter != mOutfitsMap.end())
 		{
+			const LLUUID& outfit_id = outfits_iter->first;
+			LLAccordionCtrlTab* tab = outfits_iter->second;
+
 			// An outfit is removed from the list. Do the following:
-			// 1. Remove outfit accordion tab from accordion.
-			mAccordion->removeCollapsibleCtrl(outfits_iter->second);
-
-			const LLUUID& outfit_id = outfits_iter->first;
-
-			// 2. Remove outfit category from observer to stop monitoring its changes.
+			// 1. Remove outfit category from observer to stop monitoring its changes.
 			mCategoriesObserver->removeCategory(outfit_id);
 
-			// 3. Reset selection if selected outfit is being removed.
-			if (mSelectedOutfitUUID == outfit_id)
+			// 2. Remove selected lists map entry.
+			mSelectedListsMap.erase(outfit_id);
+
+			// 3. Reset currently selected outfit id if it is being removed.
+			if (outfit_id == mSelectedOutfitUUID)
 			{
-				changeOutfitSelection(NULL, LLUUID());
+				mSelectedOutfitUUID = LLUUID();
 			}
 
 			// 4. Remove category UUID to accordion tab mapping.
 			mOutfitsMap.erase(outfits_iter);
+
+			// 5. Remove outfit tab from accordion.
+			mAccordion->removeCollapsibleCtrl(tab);
 		}
 	}
 
 
 void LLOutfitsList::performAction(std::string action)
 {
+	if (mSelectedOutfitUUID.isNull()) return;
+
 	LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedOutfitUUID);
 	if (!cat) return;
 
 
 void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id)
 {
-	// Reset selection in previously selected tab
-	// if a new one is selected.
-	if (list && mSelectedList && mSelectedList != list)
+	MASK mask = gKeyboard->currentMask(TRUE);
+
+	// Reset selection in all previously selected tabs except for the current
+	// if new selection is started.
+	if (list && !(mask & MASK_CONTROL))
 	{
-		mSelectedList->resetSelection();
+		for (wearables_lists_map_t::iterator iter = mSelectedListsMap.begin();
+				iter != mSelectedListsMap.end();
+				++iter)
+		{
+			LLWearableItemsList* selected_list = (*iter).second;
+			if (selected_list != list)
+			{
+				selected_list->resetSelection();
+			}
+		}
+
+		// Clear current selection.
+		mSelectedListsMap.clear();
 	}
 
-	mSelectedList = list;
+	mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list));
 	mSelectedOutfitUUID = category_id;
 }
 
 		S32 header_bottom = tab->getLocalRect().getHeight() - tab->getHeaderHeight();
 		if(y >= header_bottom)
 		{
+			// Focus tab header to trigger tab selection change.
+			LLUICtrl* header = tab->findChild<LLUICtrl>("dd_header");
+			if (header)
+			{
+				header->setFocus(TRUE);
+			}
+
 			uuid_vec_t selected_uuids;
 			selected_uuids.push_back(cat_id);
 			mOutfitMenu->show(ctrl, selected_uuids, x, y);
 	}
 }
 
+void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y)
+{
+	LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(ctrl);
+	if (!list) return;
+
+	uuid_vec_t selected_uuids;
+
+	// Collect seleted items from all selected lists.
+	for (wearables_lists_map_t::iterator iter = mSelectedListsMap.begin();
+			iter != mSelectedListsMap.end();
+			++iter)
+	{
+		uuid_vec_t uuids;
+		(*iter).second->getSelectedUUIDs(uuids);
+
+		S32 prev_size = selected_uuids.size();
+		selected_uuids.resize(prev_size + uuids.size());
+		std::copy(uuids.begin(), uuids.end(), selected_uuids.begin() + prev_size);
+	}
+
+	LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y);
+}
 // EOF

File indra/newview/lloutfitslist.h

 
 	void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
 
+	void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
+
 	LLInventoryCategoriesObserver* 	mCategoriesObserver;
 
 	LLAccordionCtrl*				mAccordion;
 	LLPanel*						mListCommands;
 
-	LLWearableItemsList*			mSelectedList;
+	typedef	std::map<LLUUID, LLWearableItemsList*>		wearables_lists_map_t;
+	typedef wearables_lists_map_t::value_type			wearables_lists_map_value_t;
+	wearables_lists_map_t			mSelectedListsMap;
+
 	LLUUID							mSelectedOutfitUUID;
 
 	std::string 					mFilterSubString;

File indra/newview/llpanellogin.cpp

 
 void LLPanelLogin::updateLoginPanelLinks()
 {
-	LLSD grid_data = LLGridManager::getInstance()->getGridInfo();
+	LLSD grid_data;
+	LLGridManager::getInstance()->getGridInfo(grid_data);
 	bool system_grid = grid_data.has(GRID_IS_SYSTEM_GRID_VALUE);
 	
 	// need to call through sInstance, as it's called from onSelectServer, which

File indra/newview/llpaneloutfitedit.cpp

 
 // *TODO: reorder includes to match the coding standard
 #include "llagent.h"
+#include "llagentcamera.h"
 #include "llagentwearables.h"
 #include "llappearancemgr.h"
 #include "llcofwearables.h"
 #include "llinventorymodelbackgroundfetch.h"
 #include "llpaneloutfitsinventory.h"
 #include "lluiconstants.h"
+#include "llsaveoutfitcombobtn.h"
 #include "llscrolllistctrl.h"
 #include "lltextbox.h"
 #include "lluictrlfactory.h"
 #include "llsidepanelappearance.h"
 #include "lltoggleablemenu.h"
 #include "llwearablelist.h"
+#include "llwearableitemslist.h"
 
 static LLRegisterPanelClassWrapper<LLPanelOutfitEdit> t_outfit_edit("panel_outfit_edit");
 
 const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LLInventoryType::IT_OBJECT);
 const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
 
-static const std::string SAVE_BTN("save_btn");
 static const std::string REVERT_BTN("revert_btn");
 
 class LLCOFObserver : public LLInventoryObserver
 	mCOFObserver(NULL),
 	mGearMenu(NULL),
 	mCOFDragAndDropObserver(NULL),
-	mInitialized(false)
+	mInitialized(false),
+	mAddWearablesPanel(NULL),
+	mWearableListMaskCollector(NULL),
+	mWearableListTypeCollector(NULL)
 {
 	mSavedFolderState = new LLSaveFolderState();
 	mSavedFolderState->setApply(FALSE);
 
 	delete mCOFObserver;
 	delete mCOFDragAndDropObserver;
+
+	delete mWearableListMaskCollector;
+	delete mWearableListTypeCollector;
 }
 
 BOOL LLPanelOutfitEdit::postBuild()
 
 	mFolderViewBtn = getChild<LLButton>("folder_view_btn");
 	mListViewBtn = getChild<LLButton>("list_view_btn");
+	mAddToOutfitBtn = getChild<LLButton>("add_to_outfit_btn");
 
 	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL);
 	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredFolderWearablesPanel, this), NULL);
 	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredWearablesPanel, this), NULL);
-	childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
 	childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
 
 	mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list");
 	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onOutfitItemSelectionChange, this));
 
+	mCOFWearables->getCOFCallbacks().mAddWearable = boost::bind(&LLPanelOutfitEdit::onAddWearableClicked, this);
 	mCOFWearables->getCOFCallbacks().mEditWearable = boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this);
 	mCOFWearables->getCOFCallbacks().mDeleteWearable = boost::bind(&LLPanelOutfitEdit::onRemoveFromOutfitClicked, this);
 	mCOFWearables->getCOFCallbacks().mMoveWearableCloser = boost::bind(&LLPanelOutfitEdit::moveWearable, this, true);
 
 	mCOFWearables->childSetAction("add_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this));
 
+	mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel");
 
 	mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items");
 	mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK);
 
 	childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));
 
-	childSetAction(SAVE_BTN, boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));
-	childSetAction("save_flyout_btn", boost::bind(&LLPanelOutfitEdit::showSaveMenu, this));
-
-	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar save_registar;
-	save_registar.add("Outfit.Save.Action", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));
-	save_registar.add("Outfit.SaveAsNew.Action", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true));
-	mSaveMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_save_outfit.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mWearableListMaskCollector = new LLFindNonLinksByMask(ALL_ITEMS_MASK);
+	mWearableListTypeCollector = new LLFindWearablesOfType(LLWearableType::WT_NONE);
 
 	mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel");
 	mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list");
-	mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, ALL_ITEMS_MASK);
+	mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mWearableListMaskCollector);
 
+	mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));
 	return TRUE;
 }
 
 
 void LLPanelOutfitEdit::toggleAddWearablesPanel()
 {
-	childSetVisible("add_wearables_panel", !childIsVisible("add_wearables_panel"));
+	BOOL current_visibility = mAddWearablesPanel->getVisible();
+	mAddWearablesPanel->setVisible(!current_visibility);
+
+	mFolderViewBtn->setVisible(!current_visibility);
+	mListViewBtn->setVisible(!current_visibility);
+	mAddToOutfitBtn->setVisible(!current_visibility);
+
+	// Change right dummy icon to fill the toggled buttons space.
+	childSetVisible("add_wearables_dummy_icon", !current_visibility);
+	childSetVisible("dummy_right_icon", current_visibility);
 }
 
 void LLPanelOutfitEdit::showWearablesFilter()
 	mFolderViewBtn->setToggleState(TRUE);
 }
 
-void LLPanelOutfitEdit::saveOutfit(bool as_new)
-{
-	if (!as_new && LLAppearanceMgr::getInstance()->updateBaseOutfit())
-	{
-		// we don't need to ask for an outfit name, and updateBaseOutfit() successfully saved.
-		// If updateBaseOutfit fails, ask for an outfit name anyways
-		return;
-	}
-
-	LLPanelOutfitsInventory* panel_outfits_inventory = LLPanelOutfitsInventory::findInstance();
-	if (panel_outfits_inventory)
-	{
-		panel_outfits_inventory->onSave();
-	}
-
-	//*TODO how to get to know when base outfit is updated or new outfit is created?
-}
-
-void LLPanelOutfitEdit::showSaveMenu()
-{
-	S32 x, y;
-	LLUI::getMousePositionLocal(this, &x, &y);
-
-	mSaveMenu->updateParent(LLMenuGL::sMenuContainer);
-	LLMenuGL::showPopup(this, mSaveMenu, x, y);
-}
-
 void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl)
 {
 	LLComboBox* type_filter = dynamic_cast<LLComboBox*>(ctrl);
 	{
 		U32 curr_filter_type = type_filter->getCurrentIndex();
 		mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask);
-		mWearableListManager->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask);
+
+		mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask);
+		mWearableListManager->setFilterCollector(mWearableListMaskCollector);
 	}
 	
 	mSavedFolderState->setApply(TRUE);
 	LLAppearanceMgr::getInstance()->wearItemOnAvatar(selected_id);
 }
 
+void LLPanelOutfitEdit::onAddWearableClicked(void)
+{
+	LLPanelDummyClothingListItem* item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem());
+
+	if(item)
+	{
+		showFilteredWearableItemsList(item->getWearableType());
+	}
+}
+
+void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id)
+{
+	LLViewerInventoryItem* item = gInventory.getLinkedItem(selected_item_id);
+
+	if (item && item->getType() == LLAssetType::AT_BODYPART)
+	{
+		showFilteredWearableItemsList(item->getWearableType());
+	}
+}
 
 void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)
 {
 	bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
 	bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull();
 
-	childSetEnabled(SAVE_BTN, outfit_is_dirty);
+	mSaveComboBtn->setSaveBtnEnabled(outfit_is_dirty);
 	childSetEnabled(REVERT_BTN, outfit_is_dirty && has_baseoutfit);
 
-	mSaveMenu->setItemEnabled("save_outfit", outfit_is_dirty);
+	mSaveComboBtn->setMenuItemEnabled("save_outfit", outfit_is_dirty);
 
 	mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing"));
 
 	}
 }
 
+void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type)
+{
+	mWearableListTypeCollector->setType(type);
+	mWearableListManager->setFilterCollector(mWearableListTypeCollector);
+	mAddWearablesPanel->setVisible(TRUE);
+	showFilteredWearablesPanel();
+}
+
 // EOF

File indra/newview/llpaneloutfitedit.h

 class LLFilterEditor;
 class LLFilteredWearableListManager;
 class LLMenuGL;
+class LLFindNonLinksByMask;
+class LLFindWearablesOfType;
+class LLSaveOutfitComboBtn;
 
 class LLPanelOutfitEdit : public LLPanel
 {
 	void showWearablesFilter();
 	void showFilteredWearablesPanel();
 	void showFilteredFolderWearablesPanel();
-	void saveOutfit(bool as_new = false);
-	void showSaveMenu();
 
 	void onTypeFilterChanged(LLUICtrl* ctrl);
 	void onSearchEdit(const std::string& string);
 	void onOutfitItemSelectionChange(void);
 	void onRemoveFromOutfitClicked(void);
 	void onEditWearableClicked(void);
+	void onAddWearableClicked(void);
+	void onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id);
 
 	void displayCurrentOutfit();
 	void updateCurrentOutfitName();
 
 	void onGearButtonClick(LLUICtrl* clicked_button);
 	void onGearMenuItemClick(const LLSD& data);
+	void showFilteredWearableItemsList(LLWearableType::EType type);
 
 
 	LLTextBox*			mCurrentOutfitName;
 	LLButton*			mEditWearableBtn;
 	LLButton*			mFolderViewBtn;
 	LLButton*			mListViewBtn;
-	LLToggleableMenu*	mSaveMenu;
+	LLButton*			mAddToOutfitBtn;
+	LLPanel*			mAddWearablesPanel;
+
+	LLFindNonLinksByMask*  mWearableListMaskCollector;
+	LLFindWearablesOfType* mWearableListTypeCollector;
 
 	LLFilteredWearableListManager* 	mWearableListManager;
 	LLInventoryItemsList* 			mWearableItemsList;
 	LLCOFWearables*		mCOFWearables;
 	LLMenuGL*			mGearMenu;
 	bool				mInitialized;
+	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
+
 };
 
 #endif // LL_LLPANELOUTFITEDIT_H

File indra/newview/llpaneloutfitsinventory.cpp

 #include "llmodaldialog.h"
 #include "llnotificationsutil.h"
 #include "lloutfitslist.h"
+#include "llsaveoutfitcombobtn.h"
 #include "llsidepanelappearance.h"
 #include "llsidetray.h"
 #include "lltabcontainer.h"
 		LLInventoryModelBackgroundFetch::instance().start(outfits_cat);
 	}
 	
+	mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this, true));
+
 	return TRUE;
 }
 
 
 	mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));
 	mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
-	mListCommands->childSetAction("make_outfit_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, this));
 	mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
 
 	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
 	mListCommands->childSetEnabled("trash_btn", trash_enabled);
 	mListCommands->childSetEnabled("wear_btn", wear_enabled);
 	mListCommands->childSetVisible("wear_btn", wear_enabled);
-	mListCommands->childSetEnabled("make_outfit_btn", make_outfit_enabled);
+	mSaveComboBtn->setSaveBtnEnabled(make_outfit_enabled);
 }
 
 void LLPanelOutfitsInventory::onGearButtonClick()
 	showActionMenu(mMenuGearDefault,"options_gear_btn");
 }
 
-void LLPanelOutfitsInventory::onAddButtonClick()
-{
-	onSave();
-}
-
 void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
 {
 	if (menu)

File indra/newview/llpaneloutfitsinventory.h

 class LLMenuGL;
 class LLSidepanelAppearance;
 class LLTabContainer;
+class LLSaveOutfitComboBtn;
 
 class LLPanelOutfitsInventory : public LLPanel