diff options
Diffstat (limited to 'indra/newview')
231 files changed, 12637 insertions, 16594 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 753dbd7438..70493b1214 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -107,6 +107,8 @@ set(viewer_SOURCE_FILES      llavatarlist.cpp      llavatarlistitem.cpp      llavatarpropertiesprocessor.cpp +    llblockedlistitem.cpp +    llblocklist.cpp      llbox.cpp      llbreadcrumbview.cpp      llbrowsernotification.cpp @@ -132,6 +134,10 @@ set(viewer_SOURCE_FILES      llcommandlineparser.cpp      llcompilequeue.cpp      llconfirmationmanager.cpp +    llconversationlog.cpp +    llconversationloglist.cpp +    llconversationloglistitem.cpp +    llconversationmodel.cpp      llcurrencyuimanager.cpp      llcylinder.cpp      lldateutil.cpp @@ -188,6 +194,8 @@ set(viewer_SOURCE_FILES      llfloaterbuyland.cpp      llfloatercamera.cpp      llfloatercolorpicker.cpp +    llfloaterconversationlog.cpp +    llfloaterconversationpreview.cpp      llfloaterdeleteenvpreset.cpp      llfloaterdestinations.cpp      llfloaterdisplayname.cpp @@ -255,13 +263,13 @@ set(viewer_SOURCE_FILES      llfloateruipreview.cpp      llfloaterurlentry.cpp      llfloatervoiceeffect.cpp +    llfloatervoicevolume.cpp      llfloaterwebcontent.cpp      llfloaterwebprofile.cpp      llfloaterwhitelistentry.cpp      llfloaterwindowsize.cpp      llfloaterworldmap.cpp -    llfolderview.cpp -    llfolderviewitem.cpp +    llfolderviewmodelinventory.cpp      llfollowcam.cpp      llfriendcard.cpp      llgesturelistener.cpp @@ -287,6 +295,7 @@ set(viewer_SOURCE_FILES      llhudrender.cpp      llhudtext.cpp      llhudview.cpp +    llimconversation.cpp      llimfloater.cpp      llimfloatercontainer.cpp      llimhandler.cpp @@ -341,7 +350,6 @@ set(viewer_SOURCE_FILES      llnamelistctrl.cpp      llnavigationbar.cpp      llnearbychat.cpp -    llnearbychatbar.cpp      llnearbychathandler.cpp      llnearbychatbarlistener.cpp      llnetmap.cpp @@ -373,7 +381,6 @@ set(viewer_SOURCE_FILES      llpanelgroupnotices.cpp      llpanelgrouproles.cpp      llpanelhome.cpp -    llpanelimcontrolpanel.cpp      llpanelland.cpp      llpanellandaudio.cpp      llpanellandmarkinfo.cpp @@ -384,7 +391,6 @@ set(viewer_SOURCE_FILES      llpanelmaininventory.cpp      llpanelmarketplaceinbox.cpp      llpanelmarketplaceinboxinventory.cpp -    llpanelmarketplaceoutboxinventory.cpp      llpanelmediasettingsgeneral.cpp      llpanelmediasettingspermissions.cpp      llpanelmediasettingssecurity.cpp @@ -683,6 +689,8 @@ set(viewer_HEADER_FILES      llavatarlist.h      llavatarlistitem.h      llavatarpropertiesprocessor.h +    llblockedlistitem.h +    llblocklist.h      llbox.h      llbreadcrumbview.h      llbuycurrencyhtml.h @@ -708,6 +716,10 @@ set(viewer_HEADER_FILES      llcommandlineparser.h      llcompilequeue.h      llconfirmationmanager.h +    llconversationlog.h +    llconversationloglist.h +    llconversationloglistitem.h +    llconversationmodel.h      llcurrencyuimanager.h      llcylinder.h      lldateutil.h @@ -764,6 +776,8 @@ set(viewer_HEADER_FILES      llfloaterbuyland.h      llfloatercamera.h      llfloatercolorpicker.h +    llfloaterconversationlog.h +    llfloaterconversationpreview.h      llfloaterdeleteenvpreset.h      llfloaterdestinations.h      llfloaterdisplayname.h @@ -831,14 +845,13 @@ set(viewer_HEADER_FILES      llfloateruipreview.h      llfloaterurlentry.h      llfloatervoiceeffect.h +    llfloatervoicevolume.h      llfloaterwebcontent.h      llfloaterwebprofile.h      llfloaterwhitelistentry.h      llfloaterwindowsize.h      llfloaterworldmap.h -    llfolderview.h -    llfoldervieweventlistener.h -    llfolderviewitem.h +    llfolderviewmodelinventory.h      llfollowcam.h      llfriendcard.h      llgesturelistener.h @@ -863,6 +876,7 @@ set(viewer_HEADER_FILES      llhudrender.h      llhudtext.h      llhudview.h +    llimconversation.h      llimfloater.h      llimfloatercontainer.h      llimview.h @@ -917,7 +931,6 @@ set(viewer_HEADER_FILES      llnamelistctrl.h      llnavigationbar.h      llnearbychat.h -    llnearbychatbar.h      llnearbychathandler.h      llnearbychatbarlistener.h      llnetmap.h @@ -943,7 +956,6 @@ set(viewer_HEADER_FILES      llpanelgroupnotices.h      llpanelgrouproles.h      llpanelhome.h -    llpanelimcontrolpanel.h      llpanelland.h      llpanellandaudio.h      llpanellandmarkinfo.h @@ -954,7 +966,6 @@ set(viewer_HEADER_FILES      llpanelmaininventory.h      llpanelmarketplaceinbox.h      llpanelmarketplaceinboxinventory.h -    llpanelmarketplaceoutboxinventory.h      llpanelmediasettingsgeneral.h      llpanelmediasettingspermissions.h      llpanelmediasettingssecurity.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 73df064ab2..51211a8ce5 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -46,11 +46,11 @@             available_in_toybox="true"             icon="Command_Chat_Icon"             label_ref="Command_Chat_Label" -           tooltip_ref="Command_Chat_Tooltip" +           tooltip_ref="Command_Conversations_Tooltip"             execute_function="Floater.ToggleOrBringToFront" -           execute_parameters="chat_bar" +           execute_parameters="im_container"             is_running_function="Floater.IsOpen" -           is_running_parameters="chat_bar" +           is_running_parameters="im_container"             />    <command name="compass"             available_in_toybox="false" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2af71d98b8..e4337cf8b6 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,28 @@  <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="llsd.xsd">  <map> +    <key>IMShowTime</key> +    <map> +      <key>Comment</key> +      <string>Enable(disable) timestamp showing in the chat.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map> +    <key>IMShowNamesForP2PConv</key> +    <map> +      <key>Comment</key> +      <string>Enable(disable) showing of a names in the chat.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>  	<key>CrashHostUrl</key>      <map>        <key>Comment</key> @@ -1595,17 +1617,6 @@        <key>Value</key>        <integer>1</integer>      </map> -    <key>ChatWindow</key> -    <map> -      <key>Comment</key> -      <string>Show chat in multiple windows(by default) or in one multi-tabbed window(requires restart)</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>S32</string> -      <key>Value</key> -      <integer>0</integer> -    </map>      <key>CheesyBeacon</key>      <map>        <key>Comment</key> @@ -1628,6 +1639,17 @@        <key>Value</key>        <string />      </map> +    <key>NearbyChatIsNotTornOff</key> +    <map> +      <key>Comment</key> +      <string>saving torn-off state of the nearby chat between sessions</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>CloseChatOnReturn</key>      <map>        <key>Comment</key> @@ -9835,7 +9857,7 @@  	<key>ShowScriptErrorsLocation</key>      <map>        <key>Comment</key> -      <string>Show script error in chat or window</string> +      <string>Show script error in chat (0) or window (1).</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> @@ -10019,6 +10041,39 @@        <key>Value</key>        <integer>2</integer>      </map> +    <key>BlockPeopleSortOrder</key> +    <map> +      <key>Comment</key> +      <string>Specifies sort order for recent people (0 = by name, 1 = by type)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>2</integer> +    </map> +    <key>CallLogSortOrder</key> +    <map> +      <key>Comment</key> +      <string>Specifies sort order for Call Log (0 = by name, 1 = by date)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>2</integer> +    </map> +    <key>SortFriendsFirst</key> +    <map> +      <key>Comment</key> +      <string>Specifies whether friends will be sorted first in Call Log</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>ShowPGSearchAll</key>          <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 143126b334..1f637ef3ff 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -22,6 +22,61 @@          <key>Value</key>              <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed.  Your message will still be shown in their IM panel for later viewing.</string>          </map> +    <key>ConversationsExpandMessagePaneFirst</key> +    <map> +        <key>Comment</key> +            <string>Expand either messages or conversations list pane from Conversations compact mode.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +    </map> +    <key>ConversationsListPaneCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of the conversations list pane in Conversations floater.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +    </map> +    <key>ConversationsListPaneWidth</key> +    <map> +        <key>Comment</key> +            <string>Conversations floater list pane width.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>268</integer> +    </map> +    <key>ConversationsMessagePaneCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of Conversations floater message pane.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +    </map> +    <key>ConversationsMessagePaneWidth</key> +    <map> +        <key>Comment</key> +            <string>Conversations floater message pane width.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>412</integer> +    </map>      <key>InstantMessageLogPath</key>          <map>          <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 447836910d..f187318c0f 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -54,7 +54,7 @@  #include "llmorphview.h"  #include "llmoveview.h"  #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llnotificationsutil.h"  #include "llpanelpathfindingrebakenavmesh.h"  #include "llpaneltopinfobar.h" @@ -1911,7 +1911,7 @@ void LLAgent::startTyping()  	{  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);  	} -	LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); +	LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);  }  //----------------------------------------------------------------------------- @@ -1923,7 +1923,7 @@ void LLAgent::stopTyping()  	{  		clearRenderState(AGENT_STATE_TYPING);  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); -		LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); +		LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);  	}  } diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index e2417cdddb..e31e39dca2 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -342,7 +342,7 @@ void LLLibraryOutfitsFetch::folderDone()  	}  	mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); -	mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); +	mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false);  	// If Library->Clothing->Initial Outfits exists, use that.  	LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6d67e098a6..510abf198a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2330,7 +2330,7 @@ void LLAppearanceMgr::copyLibraryGestures()  	// Copy gestures  	LLUUID lib_gesture_cat_id = -		gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE,false,true); +		gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE,false);  	if (lib_gesture_cat_id.isNull())  	{  		llwarns << "Unable to copy gestures, source category not found" << llendl; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 63737c78d0..1c81459912 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -59,6 +59,7 @@  #include "llares.h"   #include "llcurl.h"  #include "llcalc.h" +#include "llconversationlog.h"  #include "lltexturestats.h"  #include "lltexturestats.h"  #include "llviewerwindow.h" @@ -1832,6 +1833,9 @@ bool LLAppViewer::cleanup()  	// save mute list. gMuteList used to also be deleted here too.  	LLMuteList::getInstance()->cache(gAgent.getID()); +	//save call log list +	LLConversationLog::instance().cache(); +  	if (mPurgeOnExit)  	{  		llinfos << "Purging all cache files on exit" << llendflush; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index fdd4565e50..93e8b9ca40 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -235,7 +235,7 @@ void LLAvatarActions::startCall(const LLUUID& id)  }  // static -void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids) +void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id)  {  	if (ids.size() == 0)  	{ @@ -252,7 +252,7 @@ void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids)  	// create the new ad hoc voice session  	const std::string title = LLTrans::getString("conference-title");  	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, -										   ids[0], id_array, true); +										   ids[0], id_array, true, floater_id);  	if (session_id == LLUUID::null)  	{  		return; @@ -285,7 +285,7 @@ bool LLAvatarActions::canCall()  }  // static -void LLAvatarActions::startConference(const uuid_vec_t& ids) +void LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUID& floater_id)  {  	// *HACK: Copy into dynamic array  	LLDynamicArray<LLUUID> id_array; @@ -294,7 +294,7 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids)  		id_array.push_back(*it);  	}  	const std::string title = LLTrans::getString("conference-title"); -	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array); +	LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, false, floater_id);  	if (session_id != LLUUID::null)  	{  		LLIMFloater::show(session_id); @@ -529,23 +529,6 @@ namespace action_give_inventory  		return acceptable;  	} -	static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) -	{ -		llassert(avatar_names.size() > 0); - -		const std::string& separator = LLTrans::getString("words_separator"); -		for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) -		{ -			LLAvatarName av_name = *it; -			residents_string.append(av_name.mDisplayName); -			if	(++it == avatar_names.end()) -			{ -				break; -			} -			residents_string.append(separator); -		} -	} -  	static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)  	{  		llassert(inventory_selected_uuids.size() > 0); @@ -681,7 +664,7 @@ namespace action_give_inventory  		}  		std::string residents; -		build_residents_string(avatar_names, residents); +		LLAvatarActions::buildResidentsString(avatar_names, residents);  		std::string items;  		build_items_string(inventory_selected_uuids, items); @@ -712,28 +695,51 @@ namespace action_give_inventory  	}  } +// static +void LLAvatarActions::buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string) +{ +	llassert(avatar_names.size() > 0); +	const std::string& separator = LLTrans::getString("words_separator"); +	for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; ) +	{ +		LLAvatarName av_name = *it; +		residents_string.append(av_name.mDisplayName); +		if	(++it == avatar_names.end()) +		{ +			break; +		} +		residents_string.append(separator); +	} +}  //static  std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()  { -	std::set<LLUUID> inventory_selected_uuids; +	std::set<LLFolderViewItem*> inventory_selected;  	LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();  	if (active_panel)  	{ -		inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList(); +		inventory_selected= active_panel->getRootFolder()->getSelectionList();  	} -	if (inventory_selected_uuids.empty()) +	if (inventory_selected.empty())  	{  		LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");  		if (sidepanel_inventory)  		{ -			inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); +			inventory_selected= sidepanel_inventory->getInboxSelectionList();  		}  	} +	std::set<LLUUID> inventory_selected_uuids; +	for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); +		it != end_it; +		++it) +	{ +		inventory_selected_uuids.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +	}  	return inventory_selected_uuids;  } @@ -769,15 +775,15 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  	// check selection in the panel  	LLFolderView* root_folder = inv_panel->getRootFolder(); -	const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList(); -	if (inventory_selected_uuids.empty()) return false; // nothing selected +	const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); +	if (inventory_selected.empty()) return false; // nothing selected  	bool can_share = true; -	std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); -	const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); +	std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(); +	const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end();  	for (; it != it_end; ++it)  	{ -		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); +		LLViewerInventoryCategory* inv_cat = gInventory.getCategory(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());  		// any category can be offered.  		if (inv_cat)  		{ @@ -785,9 +791,9 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL  		}  		// check if inventory item can be given -		LLFolderViewItem* item = root_folder->getItemByID(*it); +		LLFolderViewItem* item = *it;  		if (!item) return false; -		LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener()); +		LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem());  		if (bridge && bridge->canShare())  		{  			continue; @@ -820,6 +826,26 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)  }  // static +void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +{ +	std::string name; +	gCacheName->getFullName(id, name); // needed for mute + +	LLMuteList* mute_list = LLMuteList::getInstance(); +	bool is_muted = mute_list->isMuted(id, LLMute::flagVoiceChat); + +	LLMute mute(id, name, LLMute::AGENT); +	if (!is_muted) +	{ +		mute_list->add(mute, LLMute::flagVoiceChat); +	} +	else +	{ +		mute_list->remove(mute, LLMute::flagVoiceChat); +	} +} + +// static  bool LLAvatarActions::canOfferTeleport(const LLUUID& id)  {  	// First use LLAvatarTracker::isBuddy() @@ -1015,7 +1041,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri  	LLSD payload;  	payload["from_id"] = target_id; -	payload["SUPPRESS_TOAST"] = true;  	LLNotificationsUtil::add("FriendshipOffered", args, payload);  } @@ -1034,6 +1059,12 @@ bool LLAvatarActions::isBlocked(const LLUUID& id)  }  // static +bool LLAvatarActions::isVoiceMuted(const LLUUID& id) +{ +	return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); +} + +// static  bool LLAvatarActions::canBlock(const LLUUID& id)  {  	std::string full_name; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 748b7cb3d1..259e87c336 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -34,6 +34,7 @@  #include <string>  #include <vector> +class LLAvatarName;  class LLInventoryPanel;  class LLFloater; @@ -81,14 +82,14 @@ public:  	static void startCall(const LLUUID& id);  	/** -	 * Start an ad-hoc conference voice call with multiple users +	 * Start an ad-hoc conference voice call with multiple users in a specific IM floater.  	 */ -	static void startAdhocCall(const uuid_vec_t& ids); +	static void startAdhocCall(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null);  	/** -	 * Start conference chat with the given avatars. +	 * Start conference chat with the given avatars in a specific IM floater.  	 */ -	static void startConference(const uuid_vec_t& ids); +	static void startConference(const uuid_vec_t& ids, const LLUUID& floater_id = LLUUID::null);  	/**  	 * Show avatar profile. @@ -124,6 +125,11 @@ public:  	static void toggleBlock(const LLUUID& id);  	/** +	 * Block/unblock the avatar voice. +	 */ +	static void toggleMuteVoice(const LLUUID& id); + +	/**  	 * Return true if avatar with "id" is a friend  	 */  	static bool isFriend(const LLUUID& id); @@ -134,6 +140,11 @@ public:  	static bool isBlocked(const LLUUID& id);  	/** +	 * @return true if the avatar voice is blocked +	 */ +	static bool isVoiceMuted(const LLUUID& id); + +	/**  	 * @return true if you can block the avatar  	 */  	static bool canBlock(const LLUUID& id); @@ -198,6 +209,14 @@ public:  	 */  	static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL); +	/** +	 * Builds a string of residents' display names separated by "words_separator" string. +	 * +	 * @param avatar_names - a vector of given avatar names from which resulting string is built +	 * @param residents_string - the resulting string +	 */ +	static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); +  	static std::set<LLUUID> getInventorySelectedUUIDs();  private: diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 30eecfe323..7b5229b5e6 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -38,6 +38,7 @@  #include "llavatarnamecache.h"  #include "llavatariconctrl.h"  #include "lloutputmonitorctrl.h" +#include "lltooldraganddrop.h"  bool LLAvatarListItem::sStaticInitialized = false;  S32 LLAvatarListItem::sLeftPadding = 0; @@ -334,6 +335,61 @@ BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask)  	return LLPanel::handleDoubleClick(x, y, mask);  } +BOOL LLAvatarListItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ +	if (LLUICtrl::handleMouseDown(x, y, mask)) +	{ +		return TRUE; +	} + +	gFocusMgr.setMouseCapture(this); + +	S32 screen_x; +	S32 screen_y; +	localPointToScreen(x, y, &screen_x, &screen_y); +	LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); + +	return TRUE; +} + +BOOL LLAvatarListItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ +	if (LLUICtrl::childrenHandleMouseUp(x, y, mask)) +	{ +		return TRUE; +	} + +	if(hasMouseCapture()) +	{ +		gFocusMgr.setMouseCapture(NULL); +	} +	return TRUE; +} + +BOOL LLAvatarListItem::handleHover(S32 x, S32 y, MASK mask) +{ +	bool handled = hasMouseCapture(); +	if(handled) +	{ +		S32 screen_x; +		S32 screen_y; +		localPointToScreen(x, y, &screen_x, &screen_y); + +		if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) +		{ +			// First, create the global drag and drop object +			std::vector<EDragAndDropType> types; +			uuid_vec_t cargo_ids; +			types.push_back(DAD_PERSON); +			cargo_ids.push_back(mAvatarId); +			LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_PEOPLE; +			LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src); +		} +	} + +	return handled; +} +  void LLAvatarListItem::setValue( const LLSD& value )  {  	if (!value.isMap()) return;; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index c95ac39696..28a50870d4 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -112,6 +112,9 @@ public:  	void onProfileBtnClick();  	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); +	/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);  protected:  	/** diff --git a/indra/newview/llblockedlistitem.cpp b/indra/newview/llblockedlistitem.cpp new file mode 100644 index 0000000000..d9afd2b629 --- /dev/null +++ b/indra/newview/llblockedlistitem.cpp @@ -0,0 +1,114 @@ +/** + * @file llviewerobjectlistitem.cpp + * @brief viewer object list item implementation + * + * Class LLPanelInventoryListItemBase displays inventory item as an element + * of LLInventoryItemsList. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llblockedlistitem.h" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavatariconctrl.h" +#include "llgroupiconctrl.h" +#include "llinventoryicon.h" +#include "llviewerobject.h" + +LLBlockedListItem::LLBlockedListItem(const LLMute* item) +:	LLPanel(), +	mItemID(item->mID), +	mItemName(item->mName), +	mMuteType(item->mType) +{ +	buildFromFile("panel_blocked_list_item.xml"); +} + +BOOL LLBlockedListItem::postBuild() +{ +	mTitleCtrl = getChild<LLTextBox>("item_name"); +	mTitleCtrl->setValue(mItemName); + +	switch (mMuteType) +	{ +	case LLMute::AGENT: +	case LLMute::EXTERNAL: +		{ +			LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); +			avatar_icon->setVisible(TRUE); +			avatar_icon->setValue(mItemID); +		} +		break; +	case LLMute::GROUP: +		{ +			LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); +			group_icon->setVisible(TRUE); +			group_icon->setValue(mItemID); +		} +		break; +	case LLMute::OBJECT: +	case LLMute::BY_NAME: +		getChild<LLUICtrl>("object_icon")->setVisible(TRUE); +		break; + +	default: +		break; +	} + +	return TRUE; +} + +void LLBlockedListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(true); +	LLPanel::onMouseEnter(x, y, mask); +} + +void LLBlockedListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(false); +	LLPanel::onMouseLeave(x, y, mask); +} + +void LLBlockedListItem::setValue(const LLSD& value) +{ +	if (!value.isMap() || !value.has("selected")) +	{ +		return; +	} + +	getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLBlockedListItem::highlightName(const std::string& highlited_text) +{ +	LLStyle::Params params; +	LLTextUtil::textboxSetHighlightedVal(mTitleCtrl, params, mItemName, highlited_text); +} diff --git a/indra/newview/llblockedlistitem.h b/indra/newview/llblockedlistitem.h new file mode 100644 index 0000000000..05409e8a3b --- /dev/null +++ b/indra/newview/llblockedlistitem.h @@ -0,0 +1,73 @@ +/** + * @file llviewerobjectlistitem.h + * @brief viewer object list item header file + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#ifndef LLVIEWEROBJECTLISTITEM_H_ +#define LLVIEWEROBJECTLISTITEM_H_ + +#include "llmutelist.h" +#include "llpanel.h" +#include "llstyle.h" +#include "lltextbox.h" +#include "lliconctrl.h" + +/** + * This class represents items of LLBlockList, which represents + * contents of LLMuteList. LLMuteList "consists" of LLMute items. + * Each LLMute represents either blocked avatar or object and + * stores info about mute type (avatar or object) + * + * Each item consists if object/avatar icon and object/avatar name + * + * To create a blocked list item just need to pass LLMute pointer + * and appropriate block list item will be created depending on + * LLMute type (LLMute::EType) and other LLMute's info + */ +class LLBlockedListItem : public LLPanel +{ +public: + +	LLBlockedListItem(const LLMute* item); +	virtual BOOL postBuild(); + +	void onMouseEnter(S32 x, S32 y, MASK mask); +	void onMouseLeave(S32 x, S32 y, MASK mask); + +	virtual void setValue(const LLSD& value); + +	void 					highlightName(const std::string& highlited_text); +	const std::string&		getName() const { return mItemName; } +	const LLMute::EType&	getType() const { return mMuteType; } +	const LLUUID&			getUUID() const { return mItemID;	} + +private: + +	LLTextBox*		mTitleCtrl; +	const LLUUID	mItemID; +	std::string		mItemName; +	LLMute::EType	mMuteType; + +}; + +#endif /* LLVIEWEROBJECTLISTITEM_H_ */ diff --git a/indra/newview/llblocklist.cpp b/indra/newview/llblocklist.cpp new file mode 100644 index 0000000000..066cb71677 --- /dev/null +++ b/indra/newview/llblocklist.cpp @@ -0,0 +1,284 @@ +/** + * @file llblocklist.cpp + * @brief List of the blocked avatars and objects. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llblocklist.h" + +#include "llavataractions.h" +#include "llblockedlistitem.h" +#include "llfloatersidepanelcontainer.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register<LLBlockList> r("block_list"); + +static const LLBlockListNameComparator 		NAME_COMPARATOR; +static const LLBlockListNameTypeComparator	NAME_TYPE_COMPARATOR; + +LLBlockList::LLBlockList(const Params& p) +:	LLFlatListViewEx(p), + 	mSelectedItem(NULL), + 	mDirty(true) +{ + +	LLMuteList::getInstance()->addObserver(this); + +	// Set up context menu. +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	registrar.add		("Block.Action",	boost::bind(&LLBlockList::onCustomAction,	this, _2)); +	enable_registrar.add("Block.Enable",	boost::bind(&LLBlockList::isActionEnabled,	this, _2)); + +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( +									"menu_people_blocked_gear.xml", +									gMenuHolder, +									LLViewerMenuHolderGL::child_registry_t::instance()); +	if(context_menu) +	{ +		mContextMenu = context_menu->getHandle(); +	} +} + +LLBlockList::~LLBlockList() +{ +	if (mContextMenu.get()) +	{ +		mContextMenu.get()->die(); +	} + +	LLMuteList::getInstance()->removeObserver(this); +} + +BOOL LLBlockList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + +	LLToggleableMenu* context_menu = mContextMenu.get(); +	if (context_menu && size()) +	{ +		context_menu->buildDrawLabels(); +		context_menu->updateParent(LLMenuGL::sMenuContainer); +		LLMenuGL::showPopup(this, context_menu, x, y); +	} + +	return handled; +} + +void LLBlockList::setNameFilter(const std::string& filter) +{ +	std::string filter_upper = filter; +	LLStringUtil::toUpper(filter_upper); +	if (mNameFilter != filter_upper) +	{ +		mNameFilter = filter_upper; +		setDirty(); +	} +} + +void LLBlockList::sortByName() +{ +	setComparator(&NAME_COMPARATOR); +	sort(); +} + +void LLBlockList::sortByType() +{ +	setComparator(&NAME_TYPE_COMPARATOR); +	sort(); +} + +void LLBlockList::draw() +{ +	if (mDirty) +	{ +		refresh(); +	} + +	LLFlatListView::draw(); +} + +void LLBlockList::addNewItem(const LLMute* mute) +{ +	LLBlockedListItem* item = new LLBlockedListItem(mute); +	if (!mNameFilter.empty()) +	{ +		item->highlightName(mNameFilter); +	} +	addItem(item, item->getUUID(), ADD_BOTTOM); +} + +void LLBlockList::refresh() +{ +	bool have_filter = !mNameFilter.empty(); + +	// save selection to restore it after list rebuilt +	LLUUID selected = getSelectedUUID(); + +	// calling refresh may be initiated by removing currently selected item +	// so select next item and save the selection to restore it after list rebuilt +	if (!selectNextItemPair(false, true)) +	{ +		selectNextItemPair(true, true); +	} +	LLUUID next_selected = getSelectedUUID(); + +	clear(); + +	std::vector<LLMute> mutes = LLMuteList::instance().getMutes(); +	std::vector<LLMute>::const_iterator mute_it = mutes.begin(); + +	for (; mute_it != mutes.end(); ++mute_it) +	{ +		if (have_filter && !findInsensitive(mute_it->mName, mNameFilter)) +			continue; + +		addNewItem(&*mute_it); +	} + +	if (getItemPair(selected)) +	{ +		// restore previously selected item +		selectItemPair(getItemPair(selected), true); +	} +	else if (getItemPair(next_selected)) +	{ +		// previously selected item was removed, so select next item +		selectItemPair(getItemPair(next_selected), true); +	} + +	// Sort the list. +	sort(); + +	setDirty(false); +} + +bool LLBlockList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ +    LLStringUtil::toUpper(haystack); +    return haystack.find(needle_upper) != std::string::npos; +} + +LLBlockedListItem* LLBlockList::getBlockedItem() const +{ +	LLPanel* panel = LLFlatListView::getSelectedItem(); +	LLBlockedListItem* item = dynamic_cast<LLBlockedListItem*>(panel); +	return item; +} + +bool LLBlockList::isActionEnabled(const LLSD& userdata) +{ +	bool action_enabled = true; + +	const std::string command_name = userdata.asString(); + +	if ("profile_item" == command_name) +	{ +		LLBlockedListItem* item = getBlockedItem(); +		action_enabled = item && (LLMute::AGENT == item->getType()); +	} + +	if ("unblock_item" == command_name) +	{ +		action_enabled = getSelectedItem() != NULL; +	} + +	return action_enabled; +} + +void LLBlockList::onCustomAction(const LLSD& userdata) +{ +	if (!isActionEnabled(userdata)) +	{ +		return; +	} + +	LLBlockedListItem* item = getBlockedItem(); +	const std::string command_name = userdata.asString(); + +	if ("unblock_item" == command_name) +	{ +		LLMute mute(item->getUUID(), item->getName()); +		LLMuteList::getInstance()->remove(mute); +	} +	else if ("profile_item" == command_name) +	{ +		switch(item->getType()) +		{ + +		case LLMute::AGENT: +			LLAvatarActions::showProfile(item->getUUID()); +			break; + +		default: +			break; +		} +	} +} + +bool LLBlockListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ +	const LLBlockedListItem* blocked_item1 = dynamic_cast<const LLBlockedListItem*>(item1); +	const LLBlockedListItem* blocked_item2 = dynamic_cast<const LLBlockedListItem*>(item2); + +	if (!blocked_item1 || !blocked_item2) +	{ +		llerror("blocked_item1 and blocked_item2 cannot be null", 0); +		return true; +	} + +	return doCompare(blocked_item1, blocked_item2); +} + +bool LLBlockListNameComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const +{ +	std::string name1 = blocked_item1->getName(); +	std::string name2 = blocked_item2->getName(); + +	LLStringUtil::toUpper(name1); +	LLStringUtil::toUpper(name2); + +	return name1 < name2; +} + +bool LLBlockListNameTypeComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const +{ +	LLMute::EType type1 = blocked_item1->getType(); +	LLMute::EType type2 = blocked_item2->getType(); + +	// if mute type is LLMute::BY_NAME or LLMute::OBJECT it means that this mute is an object +	bool both_mutes_are_objects = (LLMute::OBJECT == type1 || LLMute::BY_NAME == type1) && (LLMute::OBJECT == type2 || LLMute::BY_NAME == type2); + +	// mute types may be different, but since both LLMute::BY_NAME and LLMute::OBJECT types represent objects +	// it's needed to perform additional checking of both_mutes_are_objects variable +	if (type1 != type2 && !both_mutes_are_objects) +	{ +		// objects in block list go first, so return true if mute type is not an avatar +		return LLMute::AGENT != type1; +	} + +	return NAME_COMPARATOR.compare(blocked_item1, blocked_item2); +} diff --git a/indra/newview/llblocklist.h b/indra/newview/llblocklist.h new file mode 100644 index 0000000000..1a215710f4 --- /dev/null +++ b/indra/newview/llblocklist.h @@ -0,0 +1,138 @@ +/** + * @file llblocklist.h + * @brief List of the blocked avatars and objects. + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#ifndef LLBLOCKLIST_H_ +#define LLBLOCKLIST_H_ + +#include "llflatlistview.h" +#include "lllistcontextmenu.h" +#include "llmutelist.h" +#include "lltoggleablemenu.h" + +class LLBlockedListItem; +class LLMute; + +/** + * List of blocked avatars and objects. + * This list represents contents of the LLMuteList. + * Each change in LLMuteList leads to rebuilding this list, so + * it's always in actual state. + */ +class LLBlockList: public LLFlatListViewEx, public LLMuteListObserver +{ +	LOG_CLASS(LLBlockList); +public: +	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> +	{ +		Params(){}; +	}; + +	LLBlockList(const Params& p); +	virtual ~LLBlockList(); + +	virtual BOOL 		handleRightMouseDown(S32 x, S32 y, MASK mask); +	LLToggleableMenu*	getContextMenu() const { return mContextMenu.get(); } +	LLBlockedListItem*	getBlockedItem() const; + +	virtual void onChange() { refresh(); } +	virtual void draw(); + +	void setNameFilter(const std::string& filter); +	void sortByName(); +	void sortByType(); +	void refresh(); + +private: + +	void addNewItem(const LLMute* mute); +	void setDirty(bool dirty = true) { mDirty = dirty; } +	bool findInsensitive(std::string haystack, const std::string& needle_upper); + +	bool isActionEnabled(const LLSD& userdata); +	void onCustomAction (const LLSD& userdata); + + +	LLHandle<LLToggleableMenu>	mContextMenu; + +	LLBlockedListItem*			mSelectedItem; +	std::string 				mNameFilter; +	bool 						mDirty; + +}; + + +/* + * Abstract comparator for blocked items + */ +class LLBlockListItemComparator : public LLFlatListView::ItemComparator +{ +	LOG_CLASS(LLBlockListItemComparator); + +public: +	LLBlockListItemComparator() {}; +	virtual ~LLBlockListItemComparator() {}; + +	virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + +	virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const = 0; +}; + + +/* + * Compares items by name + */ +class LLBlockListNameComparator : public LLBlockListItemComparator +{ +	LOG_CLASS(LLBlockListNameComparator); + +public: +	LLBlockListNameComparator() {}; +	virtual ~LLBlockListNameComparator() {}; + +protected: + +	virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const; +}; + +/* + * Compares items by type and then by name within type + * Objects come first then avatars + */ +class LLBlockListNameTypeComparator : public LLBlockListItemComparator +{ +	LOG_CLASS(LLBlockListNameTypeComparator); + +public: +	LLBlockListNameTypeComparator() {}; +	virtual ~LLBlockListNameTypeComparator() {}; + +protected: + +	virtual bool doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const; +}; + +#endif /* LLBLOCKLIST_H_ */ diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 6e77d1e336..9e608d2c8b 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,11 +35,8 @@  using namespace LLNotificationsUI; -bool LLBrowserNotification::processNotification(const LLSD& notify) +bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification)  { -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	if (!notification) return false; -  	LLUUID media_id = notification->getPayload()["media_id"].asUUID();  	LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id);  	if (media_instance) diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0d55c4429a..60d60abd45 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -54,6 +54,7 @@  #include "llresmgr.h"  #include "llslurl.h"  #include "llimview.h" +#include "lltrans.h"  #include "llviewercontrol.h"  #include "llviewernetwork.h"  #include "llviewerobjectlist.h" @@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	// Use display name only because this user is your friend  	LLSD args;  	args["NAME"] = av_name.mDisplayName; +	args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus");  	LLNotificationPtr notification;  	if (online)  	{  		notification = -			LLNotificationsUtil::add("FriendOnline", +			LLNotificationsUtil::add("FriendOnlineOffline",  									 args,  									 payload.with("respond_on_mousedown", TRUE),  									 boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	else  	{  		notification = -			LLNotificationsUtil::add("FriendOffline", args, payload); +			LLNotificationsUtil::add("FriendOnlineOffline", args, payload);  	}  	// If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 84e73e96fa..e3d57ab7ae 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -143,7 +143,8 @@ public:  		{  			LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); -			LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with("blocked_to_select", getAvatarId())); +			LLFloaterSidePanelContainer::showPanel("people", "panel_people", +				LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));  		}  	} @@ -695,6 +696,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  {  	LLFastTimer _(FTM_APPEND_MESSAGE);  	bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); +	bool square_brackets = false; // square brackets necessary for a system messages  	llassert(mEditor);  	if (!mEditor) @@ -702,9 +704,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		return;  	} +	bool from_me = chat.mFromID == gAgent.getID();  	mEditor->setPlainText(use_plain_text_chat_history); -	if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) +	if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty())  	{  		mUnreadChatSources.insert(chat.mFromName);  		mMoreChatPanel->setVisible(TRUE); @@ -734,16 +737,23 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	}  	LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); +	LLColor4 name_color(txt_color); +  	LLViewerChat::getChatColor(chat,txt_color);  	LLFontGL* fontp = LLViewerChat::getChatFont();	  	std::string font_name = LLFontGL::nameFromFont(fontp);  	std::string font_size = LLFontGL::sizeFromFont(fontp);	 -	LLStyle::Params style_params; -	style_params.color(txt_color); -	style_params.readonly_color(txt_color); -	style_params.font.name(font_name); -	style_params.font.size(font_size);	 -	style_params.font.style(input_append_params.font.style); + +	LLStyle::Params body_message_params; +	body_message_params.color(txt_color); +	body_message_params.readonly_color(txt_color); +	body_message_params.font.name(font_name); +	body_message_params.font.size(font_size); +	body_message_params.font.style(input_append_params.font.style); + +	LLStyle::Params name_params(body_message_params); +	name_params.color(name_color); +	name_params.readonly_color(name_color);  	std::string prefix = chat.mText.substr(0, 4); @@ -766,29 +776,51 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  	if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC)  	{  		delimiter = LLStringUtil::null; -		style_params.font.style = "ITALIC"; +		name_params.font.style = "ITALIC";  	}  	bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY;  	// We graying out chat history by graying out messages that contains full date in a time string  	if (message_from_log)  	{ -		style_params.color(LLColor4::grey); -		style_params.readonly_color(LLColor4::grey); +		txt_color = LLColor4::grey; +		body_message_params.color(txt_color); +		body_message_params.readonly_color(txt_color); +		name_params.color(txt_color); +		name_params.readonly_color(txt_color);  	} +	bool prependNewLineState = mEditor->getText().size() != 0; + +	// compact mode: show a timestamp and name  	if (use_plain_text_chat_history)  	{ -		LLStyle::Params timestamp_style(style_params); +		square_brackets = chat.mFromName == SYSTEM_FROM; + +		LLStyle::Params timestamp_style(body_message_params); + +		// out of the timestamp +		if (args["show_time"].asBoolean()) +		{  		if (!message_from_log)  		{  			LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor");  			timestamp_style.color(timestamp_color);  			timestamp_style.readonly_color(timestamp_color);  		} -		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getLength() != 0, timestamp_style); +			mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style); +			prependNewLineState = false; +		} + +        // out the opening square bracket (if need) +		if (square_brackets) +		{ +			mEditor->appendText("[", prependNewLineState, body_message_params); +			prependNewLineState = false; +		} -		if (utf8str_trim(chat.mFromName).size() != 0) +		// names showing +		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0)  		{  			// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.  			if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) @@ -798,32 +830,47 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  				// set the link for the object name to be the objectim SLapp  				// (don't let object names with hyperlinks override our objectim Url) -				LLStyle::Params link_params(style_params); +				LLStyle::Params link_params(body_message_params);  				LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor");  				link_params.color = link_color;  				link_params.readonly_color = link_color;  				link_params.is_link = true;  				link_params.link_href = url; -				mEditor->appendText(chat.mFromName + delimiter, -									false, link_params); +				mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params); +				prependNewLineState = false;  			}  			else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)  			{ -				LLStyle::Params link_params(style_params); +				LLStyle::Params link_params(body_message_params);  				link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); +				if (from_me) +				{	std::string localized_name; +					bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); +					mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, +							prependNewLineState, link_params); +					prependNewLineState = false; +				} +				else +				{  				// Add link to avatar's inspector and delimiter to message. -				mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); +					mEditor->appendText(std::string(link_params.link_href) + delimiter, +							prependNewLineState, link_params); +					prependNewLineState = false; +				}  			}  			else  			{ -				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params); +				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, +						prependNewLineState, body_message_params); +				prependNewLineState = false;  			}  		}  	} -	else +	else // showing timestamp and name in the expanded mode  	{ +		prependNewLineState = false;  		LLView* view = NULL;  		LLInlineViewSegment::Params p;  		p.force_newline = true; @@ -844,7 +891,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		}  		else  		{ -			view = getHeader(chat, style_params, args); +			view = getHeader(chat, name_params, args);  			if (mEditor->getLength() == 0)  				p.top_pad = 0;  			else @@ -873,41 +920,16 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		mIsLastMessageFromLog = message_from_log;  	} +	// body of the message processing + +	// notify processing  	if (chat.mNotifId.notNull())  	{  		LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId);  		if (notification != NULL)  		{  			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( -					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); -			//we can't set follows in xml since it broke toasts behavior -			notify_box->setFollowsLeft(); -			notify_box->setFollowsRight(); -			notify_box->setFollowsTop(); - -			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); -			S32 offset = 0; -			// Children were added by addChild() which uses push_front to insert them into list, -			// so to get buttons in correct order reverse iterator is used (EXT-5906)  -			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) -			{ -				LLButton * button = dynamic_cast<LLButton*> (*it); -				if (button != NULL) -				{ -					button->setOrigin( offset, -							button->getRect().mBottom); -					button->setLeftHPad(2 * HPAD); -					button->setRightHPad(2 * HPAD); -					// set zero width before perform autoResize() -					button->setRect(LLRect(button->getRect().mLeft, -							button->getRect().mTop, button->getRect().mLeft, -							button->getRect().mBottom)); -					button->setAutoResize(true); -					button->autoResize(); -					offset += HPAD + button->getRect().getWidth(); -					button->setFollowsNone(); -				} -			} +					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor);  			//Prepare the rect for the view  			LLRect target_rect = mEditor->getDocumentView()->getRect(); @@ -924,6 +946,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			mEditor->appendWidget(params, "\n", false);  		}  	} + +	// usual messages showing  	else  	{  		std::string message = irc_me ? chat.mText.substr(3) : chat.mText; @@ -931,7 +955,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		//MESSAGE TEXT PROCESSING  		//*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010) -		if (use_plain_text_chat_history && gAgentID != chat.mFromID && chat.mFromID.notNull()) +		if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull())  		{  			std::string slurl_about = SLURL_APP_AGENT + chat.mFromID.asString() + SLURL_ABOUT;  			if (message.length() > slurl_about.length() &&  @@ -946,13 +970,19 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			message = chat.mFromName + message;  		} -		mEditor->appendText(message, FALSE, style_params); +		if (square_brackets) +		{ +			message += "]"; +	} + +		mEditor->appendText(message, prependNewLineState, body_message_params); +		prependNewLineState = false;  	}  	mEditor->blockUndo();  	// automatically scroll to end when receiving chat from myself -	if (chat.mFromID == gAgentID) +	if (from_me)  	{  		mEditor->setCursorAndScrollToEnd();  	} diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9a84280f25..61772b4bb7 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -35,7 +35,7 @@  #include "llfloaterreg.h"  #include "lllocalcliprect.h"  #include "lltrans.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llviewercontrol.h"  #include "llagentdata.h" @@ -96,8 +96,15 @@ void	LLNearbyChatToastPanel::reshape		(S32 width, S32 height, BOOL called_from_p  {  	LLPanel::reshape(width, height,called_from_parent); -	LLUICtrl* msg_text = getChild<LLUICtrl>("msg_text", false); -	LLUICtrl* icon = getChild<LLUICtrl>("avatar_icon", false); +	// reshape() may be called from LLView::initFromParams() before the children are created. +	// We call findChild() instead of getChild() here to avoid creating dummy controls. +	LLUICtrl* msg_text = findChild<LLUICtrl>("msg_text", false); +	LLUICtrl* icon = findChild<LLUICtrl>("avatar_icon", false); + +	if (!msg_text || !icon) +	{ +		return; +	}  	LLRect msg_text_rect = msg_text->getRect();  	LLRect avatar_rect = icon->getRect(); @@ -316,12 +323,12 @@ BOOL	LLNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)  			return TRUE;  		else  		{ -			LLNearbyChatBar::getInstance()->showHistory(); +			LLNearbyChat::getInstance()->showHistory();  			return FALSE;  		}  	} -	LLNearbyChatBar::getInstance()->showHistory(); +	LLNearbyChat::getInstance()->showHistory();  	return LLPanel::handleMouseUp(x,y,mask);  } @@ -355,6 +362,8 @@ BOOL	LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)  }  void LLNearbyChatToastPanel::draw()  { +	LLPanel::draw(); +  	if(mIsDirty)  	{  		LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon", false); @@ -372,7 +381,6 @@ void LLNearbyChatToastPanel::draw()  		}  		mIsDirty = false;  	} -	LLToastPanelBase::draw();  } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 1d700dcede..89b0c4f37a 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,7 +40,7 @@ typedef enum e_show_item_header  	CHATITEMHEADER_SHOW_BOTH  } EShowItemHeader; -class LLNearbyChatToastPanel: public LLToastPanelBase +class LLNearbyChatToastPanel : public LLPanel  {  protected:          LLNearbyChatToastPanel() diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a661808d1f..17181edffc 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -335,30 +335,15 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)  /*               LLNotificationChiclet implementation                   */  /************************************************************************/  LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p) -, mUreadSystemNotifications(0) +:	LLSysWellChiclet(p), +	mUreadSystemNotifications(0)  { -	// connect counter handlers to the signals -	connectCounterUpdatersToSignal("notify"); -	connectCounterUpdatersToSignal("groupnotify"); -	connectCounterUpdatersToSignal("offer"); - +	mNotificationChannel.reset(new ChicletNotificationChannel(this));  	// ensure that notification well window exists, to synchronously  	// handle toast add/delete events.  	LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);  } -void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); -		n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); -	} -} -  void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)  {  	std::string action = user_data.asString(); @@ -407,6 +392,18 @@ void LLNotificationChiclet::setCounter(S32 counter)  	updateWidget(getCounter() == 0);  } + +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) +{ +	if( !(notification->canLogToIM() && notification->hasFormElements()) +		&& (!notification->getPayload().has("give_inventory_notification") +			|| notification->getPayload()["give_inventory_notification"])) +	{ +		return true; +	} +	return false; +} +  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 19683492c2..f51d7b622c 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@  #include "lloutputmonitorctrl.h"  #include "llgroupmgr.h"  #include "llimview.h" +#include "llnotifications.h"  class LLMenuGL;  class LLIMFloater; @@ -872,9 +873,10 @@ class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver  {  	friend class LLUICtrlFactory;  public: -	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} -	virtual void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } -	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; +	/*virtual*/ void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}  	~LLIMWellChiclet();  protected: @@ -911,11 +913,35 @@ protected:  class LLNotificationChiclet : public LLSysWellChiclet  { +	LOG_CLASS(LLNotificationChiclet); +	  	friend class LLUICtrlFactory;  public:  	struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{};  protected: +	struct ChicletNotificationChannel : public LLNotificationChannel +	{ +		ChicletNotificationChannel(LLNotificationChiclet* chiclet)  +		:	LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), +			mChiclet(chiclet) +		{ +			// connect counter handlers to the signals +			connectToChannel("Group Notifications"); +			connectToChannel("Offer"); +			connectToChannel("Notifications"); +		} + +		static bool filterNotification(LLNotificationPtr notify); +		// connect counter updaters to the corresponding signals +		/*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } +		/*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } + +		LLNotificationChiclet* const mChiclet; +	}; + +	boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel; +  	LLNotificationChiclet(const Params& p);  	/** @@ -933,12 +959,6 @@ protected:  	 */  	/*virtual*/ void createMenu(); -	// connect counter updaters to the corresponding signals -	void connectCounterUpdatersToSignal(const std::string& notification_type); - -	// methods for updating a number of unread System notifications -	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } -	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }  	/*virtual*/ void setCounter(S32 counter);  	S32 mUreadSystemNotifications;  }; diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index f1bc51fbe7..39f5d0b8f6 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -57,19 +57,11 @@ LLChicletBar::LLChicletBar(const LLSD&)  :	mChicletPanel(NULL),  	mToolbarStack(NULL)  { -	// Firstly add our self to IMSession observers, so we catch session events -	// before chiclets do that. -	LLIMMgr::getInstance()->addSessionObserver(this); -  	buildFromFile("panel_chiclet_bar.xml");  }  LLChicletBar::~LLChicletBar()  { -	if (!LLSingleton<LLIMMgr>::destroyed()) -	{ -		LLIMMgr::getInstance()->removeSessionObserver(this); -	}  }  LLIMChiclet* LLChicletBar::createIMChiclet(const LLUUID& session_id) @@ -102,6 +94,13 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam  	// no need to spawn chiclets for participants in P2P calls called through Avaline  	if (session->isP2P() && session->isOtherParticipantAvaline()) return; +	// Do not spawn chiclet when using the new multitab conversation UI +	if (LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloater::addToHost(session_id); +		return; +	} +	  	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;  	LLIMChiclet* chiclet = createIMChiclet(session_id); @@ -109,7 +108,7 @@ void LLChicletBar::sessionAdded(const LLUUID& session_id, const std::string& nam  	{  		chiclet->setIMSessionName(name);  		chiclet->setOtherParticipantId(other_participant_id); -		 +  		LLIMFloater::onIMChicletCreated(session_id);  	} @@ -125,10 +124,12 @@ void LLChicletBar::sessionRemoved(const LLUUID& session_id)  	if(getChicletPanel())  	{  		// IM floater should be closed when session removed and associated chiclet closed -		LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (iMfloater != NULL) +		LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); +		if (im_floater != NULL && !im_floater->getStartConferenceInSameFloater())  		{ -			iMfloater->closeFloater(); +			// Close the IM floater only if we are not planning to close the P2P chat +			// and start a new conference in the same floater. +			im_floater->closeFloater();  		}  		getChicletPanel()->removeChiclet(session_id); diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 1427bf95e0..7d0d904810 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -50,9 +50,10 @@ public:  	LLChicletPanel*	getChicletPanel() { return mChicletPanel; }  	// LLIMSessionObserver observe triggers -	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); -	virtual void sessionRemoved(const LLUUID& session_id); -	void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {}; +	/*virtual*/ void sessionRemoved(const LLUUID& session_id); +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);  	S32 getTotalUnreadIMCount(); diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp new file mode 100644 index 0000000000..137b97326c --- /dev/null +++ b/indra/newview/llconversationlog.cpp @@ -0,0 +1,354 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llconversationlog.h" +#include "lltrans.h" + +struct Conversation_params +{ +	Conversation_params(time_t time) +	:	mTime(time), +		mTimestamp(LLConversation::createTimestamp(time)) +	{} + +	time_t		mTime; +	std::string	mTimestamp; +	SessionType	mConversationType; +	std::string	mConversationName; +	std::string	mHistoryFileName; +	LLUUID		mSessionID; +	LLUUID		mParticipantID; +	bool		mIsVoice; +	bool		mHasOfflineIMs; +}; + +/************************************************************************/ +/*             LLConversation implementation                            */ +/************************************************************************/ + +LLConversation::LLConversation(const Conversation_params& params) +:	mTime(params.mTime), +	mTimestamp(params.mTimestamp), +	mConversationType(params.mConversationType), +	mConversationName(params.mConversationName), +	mHistoryFileName(params.mHistoryFileName), +	mSessionID(params.mSessionID), +	mParticipantID(params.mParticipantID), +	mIsVoice(params.mIsVoice), +	mHasOfflineIMs(params.mHasOfflineIMs) +{ +	setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLIMModel::LLIMSession& session) +:	mTime(time_corrected()), +	mTimestamp(createTimestamp(mTime)), +	mConversationType(session.mSessionType), +	mConversationName(session.mName), +	mHistoryFileName(session.mHistoryFileName), +	mSessionID(session.mSessionID), +	mParticipantID(session.mOtherParticipantID), +	mIsVoice(session.mStartedAsIMCall), +	mHasOfflineIMs(session.mHasOfflineMessage) +{ +	setListenIMFloaterOpened(); +} + +LLConversation::LLConversation(const LLConversation& conversation) +{ +	mTime				= conversation.getTime(); +	mTimestamp			= conversation.getTimestamp(); +	mConversationType	= conversation.getConversationType(); +	mConversationName	= conversation.getConversationName(); +	mHistoryFileName	= conversation.getHistoryFileName(); +	mSessionID			= conversation.getSessionID(); +	mParticipantID		= conversation.getParticipantID(); +	mIsVoice			= conversation.isVoice(); +	mHasOfflineIMs		= conversation.hasOfflineMessages(); + +	setListenIMFloaterOpened(); +} + +LLConversation::~LLConversation() +{ +	mIMFloaterShowedConnection.disconnect(); +} + +void LLConversation::onIMFloaterShown(const LLUUID& session_id) +{ +	if (mSessionID == session_id) +	{ +		mHasOfflineIMs = false; +	} +} + +// static +const std::string LLConversation::createTimestamp(const time_t& utc_time) +{ +	std::string timeStr; +	LLSD substitution; +	substitution["datetime"] = (S32) utc_time; + +	timeStr = "["+LLTrans::getString ("TimeMonth")+"]/[" +				 +LLTrans::getString ("TimeDay")+"]/[" +				 +LLTrans::getString ("TimeYear")+"] [" +				 +LLTrans::getString ("TimeHour")+"]:[" +				 +LLTrans::getString ("TimeMin")+"]"; + + +	LLStringUtil::format (timeStr, substitution); +	return timeStr; +} + +void LLConversation::setListenIMFloaterOpened() +{ +	LLIMFloater* floater = LLIMFloater::findInstance(mSessionID); + +	bool has_offline_ims = !mIsVoice && mHasOfflineIMs; +	bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + +	// we don't need to listen for im floater with this conversation is opened +	// if floater is already opened or this conversation doesn't have unread offline messages +	if (has_offline_ims && !ims_are_read) +	{ +		mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversation::onIMFloaterShown, this, _1)); +	} +} +/************************************************************************/ +/*             LLConversationLogFriendObserver implementation           */ +/************************************************************************/ + +// Note : An LLSingleton like LLConversationLog cannot be an LLFriendObserver  +// at the same time. +// This is because avatar observers are deleted by the observed object which  +// conflicts with the way LLSingleton are deleted. + +class LLConversationLogFriendObserver : public LLFriendObserver +{ +public: +	LLConversationLogFriendObserver() {} +	virtual ~LLConversationLogFriendObserver() {} +	virtual void changed(U32 mask); +}; + +void LLConversationLogFriendObserver::changed(U32 mask) +{ +	if (mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE)) +	{ +		LLConversationLog::instance().notifyObservers(); +	} +} + +/************************************************************************/ +/*             LLConversationLog implementation                         */ +/************************************************************************/ + +LLConversationLog::LLConversationLog() +{ +	loadFromFile(getFileName()); + +	LLIMMgr::instance().addSessionObserver(this); +	 +	mFriendObserver = new LLConversationLogFriendObserver; +	LLAvatarTracker::instance().addObserver(mFriendObserver); +} +void LLConversationLog::logConversation(const LLConversation& conversation) +{ +	mConversations.push_back(conversation); +	notifyObservers(); +} + +void LLConversationLog::removeConversation(const LLConversation& conversation) +{ +	conversations_vec_t::iterator conv_it = mConversations.begin(); +	for(; conv_it != mConversations.end(); ++conv_it) +	{ +		if (conv_it->getSessionID() == conversation.getSessionID() && conv_it->getTime() == conversation.getTime()) +		{ +			mConversations.erase(conv_it); +			notifyObservers(); +			return; +		} +	} +} + +const LLConversation* LLConversationLog::getConversation(const LLUUID& session_id) +{ +	conversations_vec_t::const_iterator conv_it = mConversations.begin(); +	for(; conv_it != mConversations.end(); ++conv_it) +	{ +		if (conv_it->getSessionID() == session_id) +		{ +			return &*conv_it; +		} +	} + +	return NULL; +} + +void LLConversationLog::addObserver(LLConversationLogObserver* observer) +{ +	mObservers.insert(observer); +} + +void LLConversationLog::removeObserver(LLConversationLogObserver* observer) +{ +	mObservers.erase(observer); +} + +void LLConversationLog::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); +	if (session) +	{ +		LLConversation conversation(*session); +		LLConversationLog::instance().logConversation(conversation); +	} +} + +void LLConversationLog::cache() +{ +	saveToFile(getFileName()); +} + +std::string LLConversationLog::getFileName() +{ +	std::string agent_id_string; +	gAgent.getID().toString(agent_id_string); + +	return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_string) + ".call_log"; +} + +bool LLConversationLog::saveToFile(const std::string& filename) +{ +	if(!filename.size()) +	{ +		llwarns << "Call log list filename is empty!" << llendl; +		return false; +	} + +	LLFILE* fp = LLFile::fopen(filename, "wb"); +	if (!fp) +	{ +		llwarns << "Couldn't open call log list" << filename << llendl; +		return false; +	} + +	std::string participant_id; +	std::string conversation_id; + +	conversations_vec_t::const_iterator conv_it = mConversations.begin(); +	for (; conv_it != mConversations.end(); ++conv_it) +	{ +		conv_it->getSessionID().toString(conversation_id); +		conv_it->getParticipantID().toString(participant_id); + +		// examples of two file entries +		// [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe| +		// [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a| + +		fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n", +				(S32)conv_it->getTime(), +				(S32)conv_it->getConversationType(), +				(S32)conv_it->isVoice(), +				(S32)conv_it->hasOfflineMessages(), +				     conv_it->getConversationName().c_str(), +				participant_id.c_str(), +				conversation_id.c_str(), +				conv_it->getHistoryFileName().c_str()); +	} +	fclose(fp); +	return true; +} +bool LLConversationLog::loadFromFile(const std::string& filename) +{ +	if(!filename.size()) +	{ +		llwarns << "Call log list filename is empty!" << llendl; +		return false; +	} + +	LLFILE* fp = LLFile::fopen(filename, "rb"); +	if (!fp) +	{ +		llwarns << "Couldn't open call log list" << filename << llendl; +		return false; +	} + +	char buffer[MAX_STRING]; +	char conv_name_buffer[MAX_STRING]; +	char part_id_buffer[MAX_STRING]; +	char conv_id_buffer[MAX_STRING]; +	char history_file_name[MAX_STRING]; +	int is_voice; +	int has_offline_ims; +	int stype; +	S32 time; + +	while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) +	{ +		conv_name_buffer[0] = '\0'; +		part_id_buffer[0]	= '\0'; +		conv_id_buffer[0]	= '\0'; + +		sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|", +				&time, +				&stype, +				&is_voice, +				&has_offline_ims, +				conv_name_buffer, +				part_id_buffer, +				conv_id_buffer, +				history_file_name); + +		Conversation_params params(time); +		params.mConversationType = (SessionType)stype; +		params.mIsVoice = is_voice; +		params.mHasOfflineIMs = has_offline_ims; +		params.mConversationName = std::string(conv_name_buffer); +		params.mParticipantID = LLUUID(part_id_buffer); +		params.mSessionID = LLUUID(conv_id_buffer); +		params.mHistoryFileName = std::string(history_file_name); + +		LLConversation conversation(params); +		mConversations.push_back(conversation); +	} +	fclose(fp); + +	notifyObservers(); +	return true; +} + +void LLConversationLog::notifyObservers() +{ +	std::set<LLConversationLogObserver*>::const_iterator iter = mObservers.begin(); +	for (; iter != mObservers.end(); ++iter) +	{ +		(*iter)->changed(); +	} +} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h new file mode 100644 index 0000000000..a7457d55e3 --- /dev/null +++ b/indra/newview/llconversationlog.h @@ -0,0 +1,165 @@ +/** + * @file llconversationlog.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOG_H_ +#define LLCONVERSATIONLOG_H_ + +#include "llcallingcard.h" +#include "llimfloater.h" +#include "llimview.h" + +class LLConversationLogObserver; +struct Conversation_params; + +typedef LLIMModel::LLIMSession::SType SessionType; + +/* + * This class represents a particular session(conversation) of any type(im/voice/p2p/group/...) by storing some of session's data. + * Each LLConversation object has a corresponding visual representation in a form of LLConversationLogListItem. + */ +class LLConversation +{ +public: + +	LLConversation(const Conversation_params& params); +	LLConversation(const LLIMModel::LLIMSession& session); +	LLConversation(const LLConversation& conversation); + +	~LLConversation(); + +	const SessionType&	getConversationType()	const	{ return mConversationType; } +	const std::string&	getConversationName()	const	{ return mConversationName; } +	const std::string&	getHistoryFileName()	const	{ return mHistoryFileName; } +	const LLUUID&		getSessionID()			const	{ return mSessionID; } +	const LLUUID&		getParticipantID()		const	{ return mParticipantID; } +	const std::string&	getTimestamp()			const	{ return mTimestamp; } +	const time_t&		getTime()				const	{ return mTime; } +	bool				isVoice()				const	{ return mIsVoice; } +	bool				hasOfflineMessages()	const	{ return mHasOfflineIMs; } + +	/* +	 * Resets flag of unread offline message to false when im floater with this conversation is opened. +	 */ +	void onIMFloaterShown(const LLUUID& session_id); + +	/* +	 * returns string representation(in form of: mm/dd/yyyy hh:mm) of time when conversation was started +	 */ +	static const std::string createTimestamp(const time_t& utc_time); + +private: + +	/* +	 * If conversation has unread offline messages sets callback for opening LLIMFloater +	 * with this conversation. +	 */ +	void setListenIMFloaterOpened(); + +	boost::signals2::connection mIMFloaterShowedConnection; + +	time_t			mTime; // start time of conversation +	SessionType		mConversationType; +	std::string		mConversationName; +	std::string		mHistoryFileName; +	LLUUID			mSessionID; +	LLUUID			mParticipantID; +	bool			mIsVoice; +	bool			mHasOfflineIMs; +	std::string		mTimestamp; // conversation start time in form of: mm/dd/yyyy hh:mm +}; + +/** + * LLConversationLog stores all agent's conversations. + * This class is responsible for creating and storing LLConversation objects when im or voice session starts. + * Also this class saves/retrieves conversations to/from file. + * + * Also please note that it may be several conversations with the same sessionID stored in the conversation log. + * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. + */ + +class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver +{ +	friend class LLSingleton<LLConversationLog>; +public: + +	/** +	 * adds conversation to the conversation list and notifies observers +	 */ +	void logConversation(const LLConversation& conversation); +	void removeConversation(const LLConversation& conversation); + +	/** +	 * Returns first conversation with matched session_id +	 */ +	const LLConversation* getConversation(const LLUUID& session_id); + +	void addObserver(LLConversationLogObserver* observer); +	void removeObserver(LLConversationLogObserver* observer); + +	const std::vector<LLConversation>& getConversations() { return mConversations; } + +	// LLIMSessionObserver triggers +	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id){}							// Stub +	virtual void sessionRemoved(const LLUUID& session_id){}										// Stub +	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id){}	// Stub + +	// Triggered by LLFriendObserver change +	void notifyObservers(); + +	/** +	 * public method which is called on viewer exit to save conversation log +	 */ +	void cache(); + +private: + +	LLConversationLog(); + +	/** +	 * constructs file name in which conversations log will be saved +	 * file name template: agentID.call_log. +	 * For example: a086icaa-782d-88d0-ae29-987a55c99sss.call_log +	 */ +	std::string getFileName(); + +	bool saveToFile(const std::string& filename); +	bool loadFromFile(const std::string& filename); + +	typedef std::vector<LLConversation> conversations_vec_t; +	std::vector<LLConversation>				mConversations; +	std::set<LLConversationLogObserver*>	mObservers; + +	LLFriendObserver* mFriendObserver;		// Observer of the LLAvatarTracker instance +}; + +class LLConversationLogObserver +{ +public: +	virtual ~LLConversationLogObserver(){} +	virtual void changed() = 0; +}; + +#endif /* LLCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llconversationloglist.cpp b/indra/newview/llconversationloglist.cpp new file mode 100644 index 0000000000..0433719a89 --- /dev/null +++ b/indra/newview/llconversationloglist.cpp @@ -0,0 +1,422 @@ +/** + * @file llconversationloglist.cpp + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llavataractions.h" +#include "llagent.h" +#include "llfloaterreg.h" +#include "llfloaterconversationpreview.h" +#include "llgroupactions.h" +#include "llconversationloglist.h" +#include "llconversationloglistitem.h" +#include "llviewermenu.h" + +static LLDefaultChildRegistry::Register<LLConversationLogList> r("conversation_log_list"); + +static LLConversationLogListNameComparator NAME_COMPARATOR; +static LLConversationLogListDateComparator DATE_COMPARATOR; + +LLConversationLogList::LLConversationLogList(const Params& p) +:	LLFlatListViewEx(p), +	mIsDirty(true) +{ +	LLConversationLog::instance().addObserver(this); + +	// Set up context menu. +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar check_registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	registrar.add		("Calllog.Action",	boost::bind(&LLConversationLogList::onCustomAction,	this, _2)); +	check_registrar.add ("Calllog.Check",	boost::bind(&LLConversationLogList::isActionChecked,this, _2)); +	enable_registrar.add("Calllog.Enable",	boost::bind(&LLConversationLogList::isActionEnabled,this, _2)); + +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( +									"menu_conversation_log_gear.xml", +									gMenuHolder, +									LLViewerMenuHolderGL::child_registry_t::instance()); +	if(context_menu) +	{ +		mContextMenu = context_menu->getHandle(); +	} + +	mIsFriendsOnTop = gSavedSettings.getBOOL("SortFriendsFirst"); +} + +LLConversationLogList::~LLConversationLogList() +{ +	if (mContextMenu.get()) +	{ +		mContextMenu.get()->die(); +	} + +	LLConversationLog::instance().removeObserver(this); +} + +void LLConversationLogList::draw() +{ +	if (mIsDirty) +	{ +		refresh(); +	} +	LLFlatListViewEx::draw(); +} + +BOOL LLConversationLogList::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); + +	LLToggleableMenu* context_menu = mContextMenu.get(); +	{ +		context_menu->buildDrawLabels(); +	if (context_menu && size()) +		context_menu->updateParent(LLMenuGL::sMenuContainer); +		LLMenuGL::showPopup(this, context_menu, x, y); +	} + +	return handled; +} + +void LLConversationLogList::setNameFilter(const std::string& filter) +{ +	std::string filter_upper = filter; +	LLStringUtil::toUpper(filter_upper); +	if (mNameFilter != filter_upper) +	{ +		mNameFilter = filter_upper; +		setDirty(); +	} +} + +bool LLConversationLogList::findInsensitive(std::string haystack, const std::string& needle_upper) +{ +    LLStringUtil::toUpper(haystack); +    return haystack.find(needle_upper) != std::string::npos; +} + +void LLConversationLogList::sortByName() +{ +	setComparator(&NAME_COMPARATOR); +	sort(); +} + +void LLConversationLogList::sortByDate() +{ +	setComparator(&DATE_COMPARATOR); +	sort(); +} + +void LLConversationLogList::toggleSortFriendsOnTop() +{ +	mIsFriendsOnTop = !mIsFriendsOnTop; +	gSavedSettings.setBOOL("SortFriendsFirst", mIsFriendsOnTop); +	sort(); +} + +void LLConversationLogList::changed() +{ +	refresh(); +} + +void LLConversationLogList::addNewItem(const LLConversation* conversation) +{ +	LLConversationLogListItem* item = new LLConversationLogListItem(&*conversation); +	if (!mNameFilter.empty()) +	{ +		item->highlightNameDate(mNameFilter); +	} +	addItem(item, conversation->getSessionID(), ADD_TOP); +} + +void LLConversationLogList::refresh() +{ +	rebuildList(); +	sort(); + +	mIsDirty = false; +} + +void LLConversationLogList::rebuildList() +{ +	clear(); + +	bool have_filter = !mNameFilter.empty(); + +	const std::vector<LLConversation>& conversations = LLConversationLog::instance().getConversations(); +	std::vector<LLConversation>::const_iterator iter = conversations.begin(); + +	for (; iter != conversations.end(); ++iter) +	{ +		bool not_found = have_filter && !findInsensitive(iter->getConversationName(), mNameFilter) && !findInsensitive(iter->getTimestamp(), mNameFilter); +		if (not_found) +			continue; + +		addNewItem(&*iter); +	} +} + +void LLConversationLogList::onCustomAction(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); +	const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); +	LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); + +	if ("im" == command_name) +	{ +		switch (stype) +		{ +		case LLIMModel::LLIMSession::P2P_SESSION: +			LLAvatarActions::startIM(selected_id); +			break; + +		case LLIMModel::LLIMSession::GROUP_SESSION: +			LLGroupActions::startIM(selected_id); +			break; + +		default: +			break; +		} +	} +	else if ("call" == command_name) +	{ +		switch (stype) +		{ +		case LLIMModel::LLIMSession::P2P_SESSION: +			LLAvatarActions::startCall(selected_id); +			break; + +		case LLIMModel::LLIMSession::GROUP_SESSION: +			LLGroupActions::startCall(selected_id); +			break; + +		default: +			break; +		} +	} +	else if ("view_profile" == command_name) +	{ +		switch (stype) +		{ +		case LLIMModel::LLIMSession::P2P_SESSION: +			LLAvatarActions::showProfile(selected_id); +			break; + +		case LLIMModel::LLIMSession::GROUP_SESSION: +			LLGroupActions::show(selected_id); +			break; + +		default: +			break; +		} +	} +	else if ("chat_history" == command_name) +	{ +		const LLUUID& session_id = getSelectedConversation()->getSessionID(); +		LLFloaterReg::showInstance("preview_conversation", session_id, true); +	} +	else if ("offer_teleport" == command_name) +	{ +		LLAvatarActions::offerTeleport(selected_id); +	} +	else if("add_rem_friend" == command_name) +	{ +		if (LLAvatarActions::isFriend(selected_id)) +		{ +			LLAvatarActions::removeFriendDialog(selected_id); +		} +		else +		{ +			LLAvatarActions::requestFriendshipDialog(selected_id); +		} +	} +	else if ("invite_to_group" == command_name) +	{ +		LLAvatarActions::inviteToGroup(selected_id); +	} +	else if ("show_on_map" == command_name) +	{ +		LLAvatarActions::showOnMap(selected_id); +	} +	else if ("share" == command_name) +	{ +		LLAvatarActions::share(selected_id); +	} +	else if ("pay" == command_name) +	{ +		LLAvatarActions::pay(selected_id); +	} +	else if ("block" == command_name) +	{ +		LLAvatarActions::toggleBlock(selected_id); +	} +} + +bool LLConversationLogList::isActionEnabled(const LLSD& userdata) +{ +	if (numSelected() != 1) +	{ +		return false; +	} + +	const std::string command_name = userdata.asString(); + +	LLIMModel::LLIMSession::SType stype = getSelectedSessionType(); +	const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); + +	bool is_p2p   = LLIMModel::LLIMSession::P2P_SESSION == stype; +	bool is_group = LLIMModel::LLIMSession::GROUP_SESSION == stype; + +	if ("can_im" == command_name || "can_view_profile" == command_name) +	{ +		return is_p2p || is_group; +	} +	else if ("can_view_chat_history" == command_name) +	{ +		return true; +	} +	else if ("can_call"	== command_name) +	{ +		return (is_p2p || is_group) && LLAvatarActions::canCall(); +	} +	else if ("add_rem_friend"		== command_name || +			 "can_invite_to_group"	== command_name || +			 "can_share"			== command_name || +			 "can_block"			== command_name || +			 "can_pay"				== command_name) +	{ +		return is_p2p; +	} +	else if("can_offer_teleport" == command_name) +	{ +		return is_p2p && LLAvatarActions::canOfferTeleport(selected_id); +	} +	else if ("can_show_on_map") +	{ +		return is_p2p && ((LLAvatarTracker::instance().isBuddyOnline(selected_id) && is_agent_mappable(selected_id)) || gAgent.isGodlike()); +	} + +	return false; +} + +bool LLConversationLogList::isActionChecked(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); + +	const LLUUID& selected_id = getSelectedConversation()->getParticipantID(); +	bool is_p2p = LLIMModel::LLIMSession::P2P_SESSION == getSelectedSessionType(); + +	if ("is_blocked" == command_name) +	{ +		return is_p2p && LLAvatarActions::isBlocked(selected_id); +	} +	else if ("is_friend" == command_name) +	{ +		return is_p2p && LLAvatarActions::isFriend(selected_id); +	} + +	return false; +} + +LLIMModel::LLIMSession::SType LLConversationLogList::getSelectedSessionType() +{ +	const LLConversationLogListItem* item = getSelectedConversationPanel(); + +	if (item) +	{ +		return item->getConversation()->getConversationType(); +	} + +	return LLIMModel::LLIMSession::NONE_SESSION; +} + +const LLConversationLogListItem* LLConversationLogList::getSelectedConversationPanel() +{ +	LLPanel* panel = LLFlatListViewEx::getSelectedItem(); +	LLConversationLogListItem* conv_panel = dynamic_cast<LLConversationLogListItem*>(panel); + +	return conv_panel; +} + +const LLConversation* LLConversationLogList::getSelectedConversation() +{ +	const LLConversationLogListItem* panel = getSelectedConversationPanel(); + +	if (panel) +	{ +		return panel->getConversation(); +	} + +	return NULL; +} + +bool LLConversationLogListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ +	const LLConversationLogListItem* conversation_item1 = dynamic_cast<const LLConversationLogListItem*>(item1); +	const LLConversationLogListItem* conversation_item2 = dynamic_cast<const LLConversationLogListItem*>(item2); + +	if (!conversation_item1 || !conversation_item2) +	{ +		llerror("conversation_item1 and conversation_item2 cannot be null", 0); +		return true; +	} + +	return doCompare(conversation_item1, conversation_item2); +} + +bool LLConversationLogListNameComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ +	std::string name1 = conversation1->getConversation()->getConversationName(); +	std::string name2 = conversation2->getConversation()->getConversationName(); +	const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); +	const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + +	LLStringUtil::toUpper(name1); +	LLStringUtil::toUpper(name2); + +	bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); +	if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) +	{ +		return LLAvatarActions::isFriend(id1); +	} + +	return name1 < name2; +} + +bool LLConversationLogListDateComparator::doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const +{ +	time_t date1 = conversation1->getConversation()->getTime(); +	time_t date2 = conversation2->getConversation()->getTime(); +	const LLUUID& id1 = conversation1->getConversation()->getParticipantID(); +	const LLUUID& id2 = conversation2->getConversation()->getParticipantID(); + +	bool friends_first = gSavedSettings.getBOOL("SortFriendsFirst"); +	if (friends_first && (LLAvatarActions::isFriend(id1) ^ LLAvatarActions::isFriend(id2))) +	{ +		return LLAvatarActions::isFriend(id1); +	} + +	return date1 > date2; +} diff --git a/indra/newview/llconversationloglist.h b/indra/newview/llconversationloglist.h new file mode 100644 index 0000000000..dff34a74c6 --- /dev/null +++ b/indra/newview/llconversationloglist.h @@ -0,0 +1,143 @@ +/** + * @file llconversationloglist.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOGLIST_H_ +#define LLCONVERSATIONLOGLIST_H_ + +#include "llconversationlog.h" +#include "llflatlistview.h" +#include "lltoggleablemenu.h" + +class LLConversationLogListItem; + +/** + * List of all agent's conversations. I.e. history of conversations. + * This list represents contents of the LLConversationLog. + * Each change in LLConversationLog leads to rebuilding this list, so + * it's always in actual state. + */ + +class LLConversationLogList: public LLFlatListViewEx, public LLConversationLogObserver +{ +	LOG_CLASS(LLConversationLogList); +public: +	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> +	{ +		Params(){}; +	}; + +	LLConversationLogList(const Params& p); +	virtual ~LLConversationLogList(); + +	virtual void draw(); + +	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + +	LLToggleableMenu*	getContextMenu() const { return mContextMenu.get(); } + +	void addNewItem(const LLConversation* conversation); +	void setNameFilter(const std::string& filter); +	void sortByName(); +	void sortByDate(); +	void toggleSortFriendsOnTop(); +	bool getSortFriendsOnTop() const { return mIsFriendsOnTop; } + +	/** +	 * Changes from LLConversationLogObserver +	 */ +	virtual void changed(); + +private: + +	void setDirty(bool dirty = true) { mIsDirty = dirty; } +	void refresh(); + +	/** +	 * Clears list and re-adds items from LLConverstationLog +	 * If filter is not empty re-adds items which match the filter +	 */ +	void rebuildList(); + +	bool findInsensitive(std::string haystack, const std::string& needle_upper); + +	void onCustomAction (const LLSD& userdata); +	bool isActionEnabled(const LLSD& userdata); +	bool isActionChecked(const LLSD& userdata); + +	LLIMModel::LLIMSession::SType getSelectedSessionType(); +	const LLConversationLogListItem* getSelectedConversationPanel(); +	const LLConversation* getSelectedConversation(); + +	LLHandle<LLToggleableMenu>	mContextMenu; +	bool mIsDirty; +	bool mIsFriendsOnTop; +	std::string mNameFilter; +}; + +/** + * Abstract comparator for ConversationLogList items + */ +class LLConversationLogListItemComparator : public LLFlatListView::ItemComparator +{ +	LOG_CLASS(LLConversationLogListItemComparator); + +public: +	LLConversationLogListItemComparator() {}; +	virtual ~LLConversationLogListItemComparator() {}; + +	virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; + +protected: + +	virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const = 0; +}; + +class LLConversationLogListNameComparator : public LLConversationLogListItemComparator +{ +	LOG_CLASS(LLConversationLogListNameComparator); + +public: +	LLConversationLogListNameComparator() {}; +	virtual ~LLConversationLogListNameComparator() {}; + +protected: + +	virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +class LLConversationLogListDateComparator : public LLConversationLogListItemComparator +{ +	LOG_CLASS(LLConversationLogListDateComparator); + +public: +	LLConversationLogListDateComparator() {}; +	virtual ~LLConversationLogListDateComparator() {}; + +protected: + +	virtual bool doCompare(const LLConversationLogListItem* conversation1, const LLConversationLogListItem* conversation2) const; +}; + +#endif /* LLCONVERSATIONLOGLIST_H_ */ diff --git a/indra/newview/llconversationloglistitem.cpp b/indra/newview/llconversationloglistitem.cpp new file mode 100644 index 0000000000..fc2e757864 --- /dev/null +++ b/indra/newview/llconversationloglistitem.cpp @@ -0,0 +1,157 @@ +/** + * @file llconversationloglistitem.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// llui +#include "lliconctrl.h" +#include "lltextbox.h" +#include "lltextutil.h" + +// newview +#include "llavatariconctrl.h" +#include "llconversationlog.h" +#include "llconversationloglistitem.h" +#include "llgroupiconctrl.h" +#include "llinventoryicon.h" + +LLConversationLogListItem::LLConversationLogListItem(const LLConversation* conversation) +:	LLPanel(), +	mConversation(conversation), +	mConversationName(NULL), +	mConversationDate(NULL) +{ +	buildFromFile("panel_conversation_log_list_item.xml"); + +	LLIMFloater* floater = LLIMFloater::findInstance(mConversation->getSessionID()); + +	bool has_offline_ims = !mConversation->isVoice() && mConversation->hasOfflineMessages(); +	bool ims_are_read = LLIMFloater::isVisible(floater) && floater->hasFocus(); + +	if (has_offline_ims && !ims_are_read) +	{ +		mIMFloaterShowedConnection = LLIMFloater::setIMFloaterShowedCallback(boost::bind(&LLConversationLogListItem::onIMFloaterShown, this, _1)); +	} +} + +LLConversationLogListItem::~LLConversationLogListItem() +{ +	mIMFloaterShowedConnection.disconnect(); +} + +BOOL LLConversationLogListItem::postBuild() +{ +	initIcons(); + +	// set conversation name +	mConversationName = getChild<LLTextBox>("conversation_name"); +	mConversationName->setValue(mConversation->getConversationName()); + +	// set conversation date and time +	mConversationDate = getChild<LLTextBox>("date_time"); +	mConversationDate->setValue(mConversation->getTimestamp()); + +	getChild<LLButton>("delete_btn")->setClickedCallback(boost::bind(&LLConversationLogListItem::onRemoveBtnClicked, this)); + +	return TRUE; +} + +void LLConversationLogListItem::initIcons() +{ +	switch (mConversation->getConversationType()) +	{ +		case LLIMModel::LLIMSession::P2P_SESSION: +		case LLIMModel::LLIMSession::ADHOC_SESSION: +		{ +			LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); +			avatar_icon->setVisible(TRUE); +			avatar_icon->setValue(mConversation->getParticipantID()); +			break; +		} +		case LLIMModel::LLIMSession::GROUP_SESSION: +		{ +			LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon"); +			group_icon->setVisible(TRUE); +			group_icon->setValue(mConversation->getSessionID()); +			break; +		} +		default: +			break; +	} + +	if (mConversation->isVoice()) +	{ +		getChild<LLIconCtrl>("voice_session_icon")->setVisible(TRUE); +	} +	else +	{ +		if (mConversation->hasOfflineMessages()) +		{ +			getChild<LLIconCtrl>("unread_ims_icon")->setVisible(TRUE); +		} +	} +} + +void LLConversationLogListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(true); +	LLPanel::onMouseEnter(x, y, mask); +} + +void LLConversationLogListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	getChildView("hovered_icon")->setVisible(false); +	LLPanel::onMouseLeave(x, y, mask); +} + +void LLConversationLogListItem::setValue(const LLSD& value) +{ +	if (!value.isMap() || !value.has("selected")) +	{ +		return; +	} + +	getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLConversationLogListItem::onIMFloaterShown(const LLUUID& session_id) +{ +	if (mConversation->getSessionID() == session_id) +	{ +		getChild<LLIconCtrl>("unread_ims_icon")->setVisible(FALSE); +	} +} + +void LLConversationLogListItem::onRemoveBtnClicked() +{ +	LLConversationLog::instance().removeConversation(*mConversation); +} + +void LLConversationLogListItem::highlightNameDate(const std::string& highlited_text) +{ +	LLStyle::Params params; +	LLTextUtil::textboxSetHighlightedVal(mConversationName, params, mConversation->getConversationName(), highlited_text); +	LLTextUtil::textboxSetHighlightedVal(mConversationDate, params, mConversation->getTimestamp(), highlited_text); +} diff --git a/indra/newview/llconversationloglistitem.h b/indra/newview/llconversationloglistitem.h new file mode 100644 index 0000000000..deba7d4563 --- /dev/null +++ b/indra/newview/llconversationloglistitem.h @@ -0,0 +1,77 @@ +/** + * @file llconversationloglistitem.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLCONVERSATIONLOGLISTITEM_H_ +#define LLCONVERSATIONLOGLISTITEM_H_ + +#include "llimfloater.h" +#include "llpanel.h" + +class LLTextBox; +class LLConversation; + +/** + * This class is a visual representation of LLConversation, each of which is LLConversationLog entry. + * LLConversationLogList consists of these LLConversationLogListItems. + * LLConversationLogListItem consists of: + *		conversaion_type_icon + *		conversaion_name + *		conversaion_date + * Also LLConversationLogListItem holds pointer to its LLConversationLog. + */ + +class LLConversationLogListItem : public LLPanel +{ +public: +	LLConversationLogListItem(const LLConversation* conversation); +	virtual ~LLConversationLogListItem(); + +	void onMouseEnter(S32 x, S32 y, MASK mask); +	void onMouseLeave(S32 x, S32 y, MASK mask); + +	virtual void setValue(const LLSD& value); + +	virtual BOOL postBuild(); + +	void onIMFloaterShown(const LLUUID& session_id); +	void onRemoveBtnClicked(); + +	const LLConversation* getConversation() const { return mConversation; } + +	void highlightNameDate(const std::string& highlited_text); + +private: + +	void initIcons(); + +	const LLConversation* mConversation; + +	LLTextBox*		mConversationName; +	LLTextBox*		mConversationDate; + +	boost::signals2::connection mIMFloaterShowedConnection; +}; + +#endif /* LLCONVERSATIONLOGITEM_H_ */ diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp new file mode 100644 index 0000000000..bd314588a0 --- /dev/null +++ b/indra/newview/llconversationmodel.cpp @@ -0,0 +1,106 @@ +/**  + * @file llconversationmodel.cpp + * @brief Implementation of conversations list + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llconversationmodel.h" +#include "llimfloatercontainer.h" + +// Conversation items +LLConversationItem::LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp) : +	LLFolderViewModelItemCommon(containerp->getRootViewModel()), +	mName(name), +	mUUID(uuid), +    mFloater(floaterp), +    mContainer(containerp) +{ +} + +LLConversationItem::LLConversationItem(LLIMFloaterContainer* containerp) : +	LLFolderViewModelItemCommon(containerp->getRootViewModel()), +	mName(""), +	mUUID(), +	mFloater(NULL), +	mContainer(NULL) +{ +} + + +// Virtual action callbacks +void LLConversationItem::selectItem(void) +{ +	LLMultiFloater* host_floater = mFloater->getHost(); +	if (host_floater == mContainer) +	{ +		// Always expand the message pane if the panel is hosted by the container +		mContainer->collapseMessagesPane(false); +		// Switch to the conversation floater that is being selected +		mContainer->selectFloater(mFloater); +	} +	// Set the focus on the selected floater +	mFloater->setFocus(TRUE);     +} + +void LLConversationItem::setVisibleIfDetached(BOOL visible) +{ +	// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized +	// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here +	if (!mFloater->getHost() && !mFloater->isMinimized()) +	{ +		mFloater->setVisible(visible);     +	} +} + +void LLConversationItem::performAction(LLInventoryModel* model, std::string action) +{ +} + +void LLConversationItem::openItem( void ) +{ +} + +void LLConversationItem::closeItem( void ) +{ +} + +void LLConversationItem::previewItem( void ) +{ +} + +void LLConversationItem::showProperties(void) +{ +} + +bool LLConversationSort::operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const +{ +	// We compare only by name for the moment +	// *TODO : Implement the sorting by date +	S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); +	return (compare < 0); +} + +// EOF diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h new file mode 100644 index 0000000000..85760eb1a8 --- /dev/null +++ b/indra/newview/llconversationmodel.h @@ -0,0 +1,202 @@ +/**  + * @file llconversationmodel.h + * @brief Implementation of conversations list + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONVERSATIONMODEL_H +#define LL_LLCONVERSATIONMODEL_H + +//#include <map> +//#include <vector> + +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h" + +class LLButton; +class LLFloater; +class LLLayoutPanel; +class LLLayoutStack; +class LLTabContainer; +class LLIMFloaterContainer; + +// Implementation of conversations list + +class LLConversationItem; + +typedef std::map<LLFloater*, LLConversationItem*> conversations_items_map; +typedef std::map<LLFloater*, LLFolderViewItem*> conversations_widgets_map; + +// Conversation items: we hold a list of those and create an LLFolderViewItem widget for each   +// that we tuck into the mConversationsListPanel.  +class LLConversationItem : public LLFolderViewModelItemCommon +{ +public: +	LLConversationItem(std::string name, const LLUUID& uuid, LLFloater* floaterp, LLIMFloaterContainer* containerp); +	LLConversationItem(LLIMFloaterContainer* containerp); +	virtual ~LLConversationItem() {} + +	// Stub those things we won't really be using in this conversation context +	virtual const std::string& getName() const { return mName; } +	virtual const std::string& getDisplayName() const { return mName; } +	virtual const std::string& getSearchableName() const { return mName; } +	virtual const LLUUID& getUUID() const { return mUUID; } +	virtual time_t getCreationDate() const { return 0; } +	virtual LLPointer<LLUIImage> getIcon() const { return NULL; } +	virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } +	virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } +	virtual std::string getLabelSuffix() const { return LLStringUtil::null; } +	virtual BOOL isItemRenameable() const { return FALSE; } +	virtual BOOL renameItem(const std::string& new_name) { return FALSE; } +	virtual BOOL isItemMovable( void ) const { return FALSE; } +	virtual BOOL isItemRemovable( void ) const { return FALSE; } +	virtual BOOL isItemInTrash( void) const { return FALSE; } +	virtual BOOL removeItem() { return FALSE; } +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } +	virtual void move( LLFolderViewModelItem* parent_listener ) { } +	virtual BOOL isItemCopyable() const { return FALSE; } +	virtual BOOL copyToClipboard() const { return FALSE; } +	virtual BOOL cutToClipboard() const { return FALSE; } +	virtual BOOL isClipboardPasteable() const { return FALSE; } +	virtual void pasteFromClipboard() { } +	virtual void pasteLinkFromClipboard() { } +	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } +	virtual BOOL isUpToDate() const { return TRUE; } +	virtual bool hasChildren() const { return FALSE; } + +	virtual bool potentiallyVisible() { return true; } +	virtual bool filter( LLFolderViewFilter& filter) { return false; } +	virtual bool descendantsPassedFilter(S32 filter_generation = -1) { return true; } +	virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) { } +	virtual bool passedFilter(S32 filter_generation = -1) { return true; } + +	// The action callbacks +	virtual void performAction(LLInventoryModel* model, std::string action); +	virtual void openItem( void ); +	virtual void closeItem( void ); +	virtual void previewItem( void ); +	virtual void selectItem(void); +	virtual void showProperties(void); + +	void setVisibleIfDetached(BOOL visible); +	 +	// This method will be called to determine if a drop can be +	// performed, and will set drop to TRUE if a drop is +	// requested.  +	// Returns TRUE if a drop is possible/happened, FALSE otherwise. +	virtual BOOL dragOrDrop(MASK mask, BOOL drop, +							EDragAndDropType cargo_type, +							void* cargo_data, +							std::string& tooltip_msg) { return FALSE; } +	 +	bool hasSameValues(std::string name, const LLUUID& uuid) { return ((name == mName) && (uuid == mUUID)); } +	bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); } +private: +	std::string mName; +	const LLUUID mUUID; +    LLFloater* mFloater; +    LLIMFloaterContainer* mContainer; +}; + +// We don't want to ever filter conversations but we need to declare that class to create a conversation view model. +// We just stubb everything for the moment. +class LLConversationFilter : public LLFolderViewFilter +{ +public: +		 +	enum ESortOrderType +	{ +		SO_NAME = 0,						// Sort inventory by name +		SO_DATE = 0x1,						// Sort inventory by date +	}; + +	LLConversationFilter() { mEmpty = ""; } +	~LLConversationFilter() {} +		 +	bool 				check(const LLFolderViewModelItem* item) { return true; } +	bool				checkFolder(const LLFolderViewModelItem* folder) const { return true; } +	void 				setEmptyLookupMessage(const std::string& message) { } +	std::string			getEmptyLookupMessage() const { return mEmpty; } +	bool				showAllResults() const { return true; } +	std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; } +	std::string::size_type getFilterStringSize() const { return 0; } +		 +	bool 				isActive() const { return false; } +	bool 				isModified() const { return false; } +	void 				clearModified() { } +	const std::string& 	getName() const { return mEmpty; } +	const std::string& 	getFilterText() { return mEmpty; } +	void 				setModified(EFilterModified behavior = FILTER_RESTART) { } +		 +	void 				setFilterCount(S32 count) { } +	S32 				getFilterCount() const { return 0; } +	void 				decrementFilterCount() { } +		 +	bool 				isDefault() const { return true; } +	bool 				isNotDefault() const { return false; } +	void 				markDefault() { } +	void 				resetDefault() { } +		 +	S32 				getCurrentGeneration() const { return 0; } +	S32 				getFirstSuccessGeneration() const { return 0; } +	S32 				getFirstRequiredGeneration() const { return 0; } +private: +	std::string mEmpty; +}; + +class LLConversationSort +{ +public: +	LLConversationSort(U32 order = 0) +	:	mSortOrder(order), +	mByDate(false), +	mByName(false) +	{ +		mByDate = (order & LLConversationFilter::SO_DATE); +		mByName = (order & LLConversationFilter::SO_NAME); +	} +	 +	bool isByDate() const { return mByDate; } +	U32 getSortOrder() const { return mSortOrder; } +	 +	bool operator()(const LLConversationItem* const& a, const LLConversationItem* const& b) const; +private: +	U32  mSortOrder; +	bool mByDate; +	bool mByName; +}; + +class LLConversationViewModel +:	public LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> +{ +public: +	typedef LLFolderViewModel<LLConversationSort, LLConversationItem, LLConversationItem, LLConversationFilter> base_t; +	 +	void sort(LLFolderViewFolder* folder) { } // *TODO : implement conversation sort +	bool contentsReady() { return true; }	// *TODO : we need to check that participants names are available somewhat +	bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; } // We do not allow drag of conversation items +	 +private: +}; + +#endif // LL_LLCONVERSATIONMODEL_H diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 935dcb74b0..a50184460b 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -150,7 +150,7 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText()  		std::pair<S32, S32> visible_lines = getVisibleLines(true);  		S32 last_line = visible_lines.second - 1; -		LLStyle::Params expander_style(getDefaultStyleParams()); +		LLStyle::Params expander_style(getStyleParams());  		expander_style.font.style = "UNDERLINE";  		expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor");  		LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, mExpanderLabel, *this); @@ -166,7 +166,7 @@ void LLExpandableTextBox::LLTextBoxEx::hideExpandText()  	if (mExpanderVisible)  	{  		// this will overwrite the expander segment and all text styling with a single style -		LLStyleConstSP sp(new LLStyle(getDefaultStyleParams())); +		LLStyleConstSP sp(new LLStyle(getStyleParams()));  		LLNormalTextSegment* segmentp = new LLNormalTextSegment(sp, 0, getLength() + 1, *this);  		insertSegment(segmentp); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 4cbc9cab4a..c68577db75 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -38,6 +38,7 @@  #include "lltooltip.h"  #include "llagent.h" +#include "llavatarnamecache.h"  #include "llclipboard.h"  #include "llclipboard.h"  #include "llinventorybridge.h" @@ -45,12 +46,14 @@  #include "llfloatersidepanelcontainer.h"  #include "llfloaterworldmap.h"  #include "lllandmarkactions.h" +#include "lllogininstance.h"  #include "llnotificationsutil.h"  #include "lltoggleablemenu.h"  #include "llviewerinventory.h"  #include "llviewermenu.h"  #include "llviewermenu.h"  #include "lltooldraganddrop.h" +#include "llsdserialize.h"  static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); @@ -317,7 +320,8 @@ public:  		if (item)  		{ -			item->setSortField(mSortField); +			LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); +  			item->setComplete(TRUE);  			item->updateServer(FALSE); @@ -339,8 +343,8 @@ struct LLFavoritesSort  	// TODO - made it customizible using gSavedSettings  	bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b)  	{ -		S32 sortField1 = a->getSortField(); -		S32 sortField2 = b->getSortField(); +		S32 sortField1 = LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID()); +		S32 sortField2 = LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID());  		if (!(sortField1 < 0 && sortField2 < 0))  		{ @@ -528,7 +532,7 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)  		mItems.push_back(gInventory.getItem(mDragItemId));  	} -	gInventory.saveItemsOrder(mItems); +	LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);  	LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get(); @@ -587,7 +591,8 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con  		}  		else  		{ -			currItem->setSortField(++sortField); +			LLFavoritesOrderStorage::instance().setSortIndex(currItem, ++sortField); +  			currItem->setComplete(TRUE);  			currItem->updateServer(FALSE); @@ -640,7 +645,7 @@ void LLFavoritesBarCtrl::changed(U32 mask)  		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)  		{ -			(*i)->getSLURL(); +			LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());  		}  		updateButtons();  	} @@ -909,7 +914,7 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it  		S32 sortField = 0;  		for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)  		{ -			(*i)->setSortField(++sortField); +			LLFavoritesOrderStorage::instance().setSortIndex((*i), ++sortField);  		}  	} @@ -1355,7 +1360,7 @@ BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array  	// if there is an item without sort order field set, we need to save items order  	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)  	{ -		if ((*i)->getSortField() < 0) +		if (LLFavoritesOrderStorage::instance().getSortIndex((*i)->getUUID()) < 0)  		{  			result = TRUE;  			break; @@ -1390,4 +1395,291 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const  	}  } +const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; +const S32 LLFavoritesOrderStorage::NO_INDEX = -1; + +void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index) +{ +	mSortIndexes[inv_item->getUUID()] = sort_index; +	mIsDirty = true; +	getSLURL(inv_item->getAssetUUID()); +} + +S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) +{ +	sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); +	if (it != mSortIndexes.end()) +	{ +		return it->second; +	} +	return NO_INDEX; +} + +void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) +{ +	mSortIndexes.erase(inv_item_id); +	mIsDirty = true; +} + +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ +	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); +	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + +	LLLandmark* lm = gLandmarkList.getAsset(asset_id, +		boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); +	if (lm) +	{ +		onLandmarkLoaded(asset_id, lm); +	} +} + +// static +void LLFavoritesOrderStorage::destroyClass() +{ +	LLFavoritesOrderStorage::instance().cleanup(); +	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) +	{ +		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); +	} +	else +	{ +		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); +	} +} + +void LLFavoritesOrderStorage::load() +{ +	// load per-resident sorting information +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); + +	LLSD settings_llsd; +	llifstream file; +	file.open(filename); +	if (file.is_open()) +	{ +		LLSDSerialize::fromXML(settings_llsd, file); +	} + +	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); +		iter != settings_llsd.endMap(); ++iter) +	{ +		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); +	} +} + +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ +	// Do not change the file if we are not logged in yet. +	if (!LLLoginInstance::getInstance()->authSuccess()) +	{ +		llwarns << "Cannot save favorites: not logged in" << llendl; +		return; +	} + +	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); +	if (user_dir.empty()) +	{ +		llwarns << "Cannot save favorites: empty user dir name" << llendl; +		return; +	} + +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	llifstream in_file; +	in_file.open(filename); +	LLSD fav_llsd; +	if (in_file.is_open()) +	{ +		LLSDSerialize::fromXML(fav_llsd, in_file); +	} + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	LLSD user_llsd; +	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) +	{ +		LLSD value; +		value["name"] = (*it)->getName(); +		value["asset_id"] = (*it)->getAssetUUID(); + +		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); +		if (slurl_iter != mSLURLs.end()) +		{ +			lldebugs << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl; +			value["slurl"] = slurl_iter->second; +			user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; +		} +		else +		{ +			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; +		} +	} + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; +	fav_llsd[av_name.getLegacyName()] = user_llsd; + +	llofstream file; +	file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, file); +} + +void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() +{ +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); +	LLSD fav_llsd; +	llifstream file; +	file.open(filename); +	if (!file.is_open()) return; +	LLSDSerialize::fromXML(fav_llsd, file); + +	LLAvatarName av_name; +	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; +	if (fav_llsd.has(av_name.getLegacyName())) +	{ +		fav_llsd.erase(av_name.getLegacyName()); +	} + +	llofstream out_file; +	out_file.open(filename); +	LLSDSerialize::toPrettyXML(fav_llsd, out_file); + +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ +	if (!landmark) return; + +	LLVector3d pos_global; +	if (!landmark->getGlobalPos(pos_global)) +	{ +		// If global position was unknown on first getGlobalPos() call +		// it should be set for the subsequent calls. +		landmark->getGlobalPos(pos_global); +	} + +	if (!pos_global.isExactlyZero()) +	{ +		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, +			boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); +	} +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ +	lldebugs << "Saving landmark SLURL: " << slurl << llendl; +	mSLURLs[asset_id] = slurl; +} + +void LLFavoritesOrderStorage::save() +{ +	// nothing to save if clean +	if (!mIsDirty) return; + +	// If we quit from the login screen we will not have an SL account +	// name.  Don't try to save, otherwise we'll dump a file in +	// C:\Program Files\SecondLife\ or similar. JC +	std::string user_dir = gDirUtilp->getLindenUserDir(); +	if (!user_dir.empty()) +	{ +		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); +		LLSD settings_llsd; + +		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) +		{ +			settings_llsd[iter->first.asString()] = iter->second; +		} + +		llofstream file; +		file.open(filename); +		LLSDSerialize::toPrettyXML(settings_llsd, file); +	} +} + +void LLFavoritesOrderStorage::cleanup() +{ +	// nothing to clean +	if (!mIsDirty) return; + +	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + +	IsNotInFavorites is_not_in_fav(items); + +	sort_index_map_t  aTempMap; +	//copy unremoved values from mSortIndexes to aTempMap +	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  +		inserter(aTempMap, aTempMap.begin()), +		is_not_in_fav); + +	//Swap the contents of mSortIndexes and aTempMap +	mSortIndexes.swap(aTempMap); +} + +void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items ) +{ +	int sortField = 0; + +	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field +	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) +	{ +		LLViewerInventoryItem* item = *i; + +		setSortIndex(item, ++sortField); + +		item->setComplete(TRUE); +		item->updateServer(FALSE); + +		gInventory.updateItem(item); + +		// Tell the parent folder to refresh its sort order. +		gInventory.addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); +	} + +	gInventory.notifyObservers(); +} + +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: +	bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) +	{ +		return LLFavoritesOrderStorage::instance().getSortIndex(a->getUUID())  +			< LLFavoritesOrderStorage::instance().getSortIndex(b->getUUID()); +	} +}; + +// * @param source_item_id - LLUUID of the source item to be moved into new position +// * @param target_item_id - LLUUID of the target item before which source item should be placed. +void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLIsType is_type(LLAssetType::AT_LANDMARK); +	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + +	// ensure items are sorted properly before changing order. EXT-3498 +	std::sort(items.begin(), items.end(), LLViewerInventoryItemSort()); + +	// update order +	gInventory.updateItemsOrder(items, source_item_id, target_item_id); + +	saveItemsOrder(items); +} + +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ +	if (mTargetLandmarkId.isNull()) return; + +	LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +}  // EOF diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 447d30f1f4..e000adc4aa 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -33,6 +33,7 @@  #include "llinventoryobserver.h"  #include "llinventorymodel.h" +#include "llviewerinventory.h"  class LLMenuItemCallGL;  class LLToggleableMenu; @@ -161,5 +162,115 @@ private:  	boost::signals2::connection mEndDragConnection;  }; +class AddFavoriteLandmarkCallback : public LLInventoryCallback +{ +public: +	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} +	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } + +private: +	void fire(const LLUUID& inv_item); + +	LLUUID mTargetLandmarkId; +}; + +/** + * Class to store sorting order of favorites landmarks in a local file. EXT-3985. + * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. + * Data are stored in user home directory. + */ +class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> +	, public LLDestroyClass<LLFavoritesOrderStorage> +{ +	LOG_CLASS(LLFavoritesOrderStorage); +public: +	/** +	 * Sets sort index for specified with LLUUID favorite landmark +	 */ +	void setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index); + +	/** +	 * Gets sort index for specified with LLUUID favorite landmark +	 */ +	S32 getSortIndex(const LLUUID& inv_item_id); +	void removeSortIndex(const LLUUID& inv_item_id); + +	void getSLURL(const LLUUID& asset_id); + +	// Saves current order of the passed items using inventory item sort field. +	// Resets 'items' sort fields and saves them on server. +	// Is used to save order for Favorites folder. +	void saveItemsOrder(const LLInventoryModel::item_array_t& items); + +	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + +	/** +	 * Implementation of LLDestroyClass. Calls cleanup() instance method. +	 * +	 * It is important this callback is called before gInventory is cleaned. +	 * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), +	 * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. +	 * @see cleanup() +	 */ +	static void destroyClass(); + +	const static S32 NO_INDEX; +private: +	friend class LLSingleton<LLFavoritesOrderStorage>; +	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } +	~LLFavoritesOrderStorage() { save(); } + +	/** +	 * Removes sort indexes for items which are not in Favorites bar for now. +	 */ +	void cleanup(); + +	const static std::string SORTING_DATA_FILE_NAME; + +	void load(); +	void save(); + +	void saveFavoritesSLURLs(); + +	// Remove record of current user's favorites from file on disk. +	void removeFavoritesRecordOfUser(); + +	void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark); +	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); + +	typedef std::map<LLUUID, S32> sort_index_map_t; +	sort_index_map_t mSortIndexes; + +	typedef std::map<LLUUID, std::string> slurls_map_t; +	slurls_map_t mSLURLs; + +	bool mIsDirty; + +	struct IsNotInFavorites +	{ +		IsNotInFavorites(const LLInventoryModel::item_array_t& items) +			: mFavoriteItems(items) +		{ + +		} + +		/** +		 * Returns true if specified item is not found among inventory items +		 */ +		bool operator()(const sort_index_map_t::value_type& id_index_pair) const +		{ +			LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); +			if (item.isNull()) return true; + +			LLInventoryModel::item_array_t::const_iterator found_it = +				std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); + +			return found_it == mFavoriteItems.end(); +		} +	private: +		LLInventoryModel::item_array_t mFavoriteItems; +	}; + +};  #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfloaterconversationlog.cpp b/indra/newview/llfloaterconversationlog.cpp new file mode 100644 index 0000000000..c77a9e74bb --- /dev/null +++ b/indra/newview/llfloaterconversationlog.cpp @@ -0,0 +1,127 @@ +/** + * @file llfloaterconversationlog.cpp + * @brief Functionality of the "conversation log" floater + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llconversationloglist.h" +#include "llfiltereditor.h" +#include "llfloaterconversationlog.h" +#include "llmenubutton.h" + +LLFloaterConversationLog::LLFloaterConversationLog(const LLSD& key) +:	LLFloater(key), +	mConversationLogList(NULL) +{ +	mCommitCallbackRegistrar.add("CallLog.Action",	boost::bind(&LLFloaterConversationLog::onCustomAction,  this, _2)); +	mEnableCallbackRegistrar.add("CallLog.Check",	boost::bind(&LLFloaterConversationLog::isActionChecked, this, _2)); +} + +BOOL LLFloaterConversationLog::postBuild() +{ +	mConversationLogList = getChild<LLConversationLogList>("conversation_log_list"); + +	switch (gSavedSettings.getU32("CallLogSortOrder")) +	{ +	case E_SORT_BY_NAME: +		mConversationLogList->sortByName(); +		break; + +	case E_SORT_BY_DATE: +		mConversationLogList->sortByDate(); +		break; +	} + +	// Use the context menu of the Conversation list for the Conversation tab gear menu. +	LLToggleableMenu* conversations_gear_menu = mConversationLogList->getContextMenu(); +	if (conversations_gear_menu) +	{ +		getChild<LLMenuButton>("conversations_gear_btn")->setMenu(conversations_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} + +	getChild<LLFilterEditor>("people_filter_input")->setCommitCallback(boost::bind(&LLFloaterConversationLog::onFilterEdit, this, _2)); + +	return LLFloater::postBuild(); +} + +void LLFloaterConversationLog::draw() +{ +	LLFloater::draw(); +} + +void LLFloaterConversationLog::onFilterEdit(const std::string& search_string) +{ +	std::string filter = search_string; +	LLStringUtil::trimHead(filter); + +	mConversationLogList->setNameFilter(filter); +} + + +void LLFloaterConversationLog::onCustomAction (const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); + +	if ("sort_by_name" == command_name) +	{ +		mConversationLogList->sortByName(); +		gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_NAME); +	} +	else if ("sort_by_date" == command_name) +	{ +		mConversationLogList->sortByDate(); +		gSavedSettings.setU32("CallLogSortOrder", E_SORT_BY_DATE); +	} +	else if ("sort_friends_on_top" == command_name) +	{ +		mConversationLogList->toggleSortFriendsOnTop(); +	} +} + +bool LLFloaterConversationLog::isActionEnabled(const LLSD& userdata) +{ +	return true; +} + +bool LLFloaterConversationLog::isActionChecked(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); + +	U32 sort_order = gSavedSettings.getU32("CallLogSortOrder"); + +	if ("sort_by_name" == command_name) +	{ +		return sort_order == E_SORT_BY_NAME; +	} +	else if ("sort_by_date" == command_name) +	{ +		return sort_order == E_SORT_BY_DATE; +	} +	else if ("sort_friends_on_top" == command_name) +	{ +		return gSavedSettings.getBOOL("SortFriendsFirst"); +	} + +	return false; +} diff --git a/indra/newview/llfloaterconversationlog.h b/indra/newview/llfloaterconversationlog.h new file mode 100644 index 0000000000..7d788c0290 --- /dev/null +++ b/indra/newview/llfloaterconversationlog.h @@ -0,0 +1,61 @@ +/** + * @file llfloaterconversationlog.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERCONVERSATIONLOG_H_ +#define LL_LLFLOATERCONVERSATIONLOG_H_ + +#include "llfloater.h" + +class LLConversationLogList; + +class LLFloaterConversationLog : public LLFloater +{ +public: + +	typedef enum e_sort_oder{ +		E_SORT_BY_NAME = 0, +		E_SORT_BY_DATE = 1, +	} ESortOrder; + +	LLFloaterConversationLog(const LLSD& key); +	virtual ~LLFloaterConversationLog(){}; + +	virtual BOOL postBuild(); + +	virtual void draw(); + +	void onFilterEdit(const std::string& search_string); + +private: + +	void onCustomAction (const LLSD& userdata); +	bool isActionEnabled(const LLSD& userdata); +	bool isActionChecked(const LLSD& userdata); + +	LLConversationLogList* mConversationLogList; +}; + + +#endif /* LLFLOATERCONVERSATIONLOG_H_ */ diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp new file mode 100644 index 0000000000..e8554bb066 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -0,0 +1,112 @@ +/** + * @file llfloaterconversationpreview.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llconversationlog.h" +#include "llfloaterconversationpreview.h" +#include "llimview.h" +#include "lllineeditor.h" + +LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) +:	LLFloater(session_id), +	mChatHistory(NULL), +	mSessionID(session_id.asUUID()) +{} + +BOOL LLFloaterConversationPreview::postBuild() +{ +	mChatHistory = getChild<LLChatHistory>("chat_history"); + +	const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); +	if (conv) +	{ +		std::string name = conv->getConversationName(); +		LLStringUtil::format_map_t args; +		args["[NAME]"] = name; +		std::string title = getString("Title", args); +		setTitle(title); + +		getChild<LLLineEditor>("description")->setValue(name); +	} + +	return LLFloater::postBuild(); +} + +void LLFloaterConversationPreview::draw() +{ +	LLFloater::draw(); +} + +void LLFloaterConversationPreview::onOpen(const LLSD& session_id) +{ +	const LLConversation* conv = LLConversationLog::instance().getConversation(session_id); +	if (!conv) +	{ +		return; +	} +	std::list<LLSD> messages; +	std::string file = conv->getHistoryFileName(); +	LLLogChat::loadAllHistory(file, messages); + +	if (messages.size()) +	{ +		std::ostringstream message; +		std::list<LLSD>::const_iterator iter = messages.begin(); +		for (; iter != messages.end(); ++iter) +		{ +			LLSD msg = *iter; + +			std::string time	= msg["time"].asString(); +			LLUUID from_id		= msg["from_id"].asUUID(); +			std::string from	= msg["from"].asString(); +			std::string message	= msg["message"].asString(); +			bool is_history	= msg["is_history"].asBoolean(); + +			LLChat chat; +			chat.mFromID = from_id; +			chat.mSessionID = session_id; +			chat.mFromName = from; +			chat.mTimeStr = time; +			chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; +			chat.mText = message; + +			appendMessage(chat); +		} +	} +} + +void LLFloaterConversationPreview::appendMessage(const LLChat& chat) +{ +	if (!chat.mMuted) +	{ +		LLSD args; +		args["use_plain_text_chat_history"] = true; +		args["show_time"] = true; +		args["show_names_for_p2p_conv"] = true; + +		mChatHistory->appendMessage(chat); +	} +} diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h new file mode 100644 index 0000000000..cfc7c34485 --- /dev/null +++ b/indra/newview/llfloaterconversationpreview.h @@ -0,0 +1,51 @@ +/** + * @file llfloaterconversationpreview.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERCONVERSATIONPREVIEW_H_ +#define LLFLOATERCONVERSATIONPREVIEW_H_ + +#include "llchathistory.h" +#include "llfloater.h" + +class LLFloaterConversationPreview : public LLFloater +{ +public: + +	LLFloaterConversationPreview(const LLSD& session_id); +	virtual ~LLFloaterConversationPreview(){}; + +	virtual BOOL postBuild(); + +	virtual void draw(); +	virtual void onOpen(const LLSD& session_id); + +private: +	void appendMessage(const LLChat& chat); + +	LLChatHistory*	mChatHistory; +	LLUUID			mSessionID; +}; + +#endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 2681d4b34d..4f35c325a8 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -44,21 +44,16 @@ public:  	BOOL postBuild();  private: -	bool update(const LLSD& payload, bool passed_filter); +	bool update(const LLSD& payload);  	static void toggleClick(void* user_data);  	static void onClickNotification(void* user_data); -	static void onClickNotificationReject(void* user_data);  	LLNotificationChannelPtr mChannelPtr; -	LLNotificationChannelPtr mChannelRejectsPtr;  };  LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChannelPanel::Params& p)   :	LLLayoutPanel(p)  {  	mChannelPtr = LLNotifications::instance().getChannel(p.name); -	mChannelRejectsPtr = LLNotificationChannelPtr( -		LLNotificationChannel::buildChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), -											!boost::bind(mChannelPtr->getFilter(), _1)));  	buildFromFile( "panel_notifications_channel.xml");  } @@ -68,15 +63,11 @@ BOOL LLNotificationChannelPanel::postBuild()  	header_button->setLabel(mChannelPtr->getName());  	header_button->setClickedCallback(toggleClick, this); -	mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, true)); -	mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false)); +	mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1));  	LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("notifications_list");  	scroll->setDoubleClickCallback(onClickNotification, this);  	scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); -	scroll = getChild<LLScrollListCtrl>("notification_rejects_list"); -	scroll->setDoubleClickCallback(onClickNotificationReject, this); -	scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0));  	return TRUE;  } @@ -97,8 +88,6 @@ void LLNotificationChannelPanel::toggleClick(void *user_data)  	// turn off tab stop for collapsed panel  	self->getChild<LLScrollListCtrl>("notifications_list")->setTabStop(!header_button->getToggleState());  	self->getChild<LLScrollListCtrl>("notifications_list")->setVisible(!header_button->getToggleState()); -	self->getChild<LLScrollListCtrl>("notification_rejects_list")->setTabStop(!header_button->getToggleState()); -	self->getChild<LLScrollListCtrl>("notification_rejects_list")->setVisible(!header_button->getToggleState());  }  /*static*/ @@ -118,24 +107,7 @@ void LLNotificationChannelPanel::onClickNotification(void* user_data)  	}  } -/*static*/ -void LLNotificationChannelPanel::onClickNotificationReject(void* user_data) -{ -	LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data; -	if (!self) return; -	LLScrollListItem* firstselected = self->getChild<LLScrollListCtrl>("notification_rejects_list")->getFirstSelected(); -	llassert(firstselected); -	if (firstselected) -	{ -		void* data = firstselected->getUserdata(); -		if (data) -		{ -			gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE); -		} -	} -} - -bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) +bool LLNotificationChannelPanel::update(const LLSD& payload)  {  	LLNotificationPtr notification = LLNotifications::instance().find(payload["id"].asUUID());  	if (notification) @@ -151,9 +123,7 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter)  		row["columns"][2]["column"] = "date";  		row["columns"][2]["type"] = "date"; -		LLScrollListItem* sli = passed_filter ?  -			getChild<LLScrollListCtrl>("notifications_list")->addElement(row) : -			getChild<LLScrollListCtrl>("notification_rejects_list")->addElement(row); +		LLScrollListItem* sli = getChild<LLScrollListCtrl>("notifications_list")->addElement(row);  		sli->setUserdata(&(*notification));  	} diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 540f977305..18ed36d0f3 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -44,14 +44,12 @@  #include "llviewernetwork.h"  #include "llwindowshade.h" -#define USE_WINDOWSHADE_DIALOGS	0 -  ///----------------------------------------------------------------------------  /// LLOutboxNotification class  ///---------------------------------------------------------------------------- -bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify)  {  	LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); @@ -60,6 +58,14 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& no  	return false;  } +void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p) +{ +	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); +	if (sys_handler) +	{ +		sys_handler->onDelete(p); +	} +}  ///----------------------------------------------------------------------------  /// LLOutboxAddedObserver helper class @@ -168,9 +174,8 @@ void LLFloaterOutbox::onOpen(const LLSD& key)  	if (mOutboxId.isNull())  	{  		const bool do_not_create_folder = false; -		const bool do_not_find_in_library = false; -		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); +		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder);  		if (outbox_id.isNull())  		{ @@ -244,8 +249,9 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)  	mOutboxInventoryPanel->setShape(inventory_placeholder_rect);  	// Set the sort order newest to oldest -	mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME);	 -	mOutboxInventoryPanel->getFilter()->markDefault(); + +	mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME);	 +	mOutboxInventoryPanel->getFilter().markDefault();  	fetchOutboxContents(); @@ -380,7 +386,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	// Determine if the mouse is inside the inventory panel itself or just within the floater  	bool pointInInventoryPanel = false;  	bool pointInInventoryPanelChild = false; -	LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); +	LLFolderView* root_folder = mOutboxInventoryPanel->getRootFolder();  	if (mOutboxInventoryPanel->getVisible())  	{  		S32 inv_x, inv_y; @@ -437,10 +443,10 @@ void LLFloaterOutbox::onOutboxChanged()  {  	llassert(!mOutboxId.isNull()); -	if (mOutboxInventoryPanel) -	{ -		mOutboxInventoryPanel->requestSort(); -	} +	//if (mOutboxInventoryPanel) +	//{ +	//	mOutboxInventoryPanel->requestSort(); +	//}  	fetchOutboxContents(); @@ -516,52 +522,11 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)  	updateView();  } -void LLFloaterOutbox::showNotification(const LLSD& notify) +void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification)  { -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	 -	if (!notification) -	{ -		llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; -		 -		return; -	} - -#if USE_WINDOWSHADE_DIALOGS - -	if (mWindowShade) -	{ -		delete mWindowShade; -	} -	 -	LLRect floater_rect = getLocalRect(); -	floater_rect.mTop -= getHeaderHeight(); -	floater_rect.stretch(-5, 0); -	 -	LLWindowShade::Params params; -	params.name = "notification_shade"; -	params.rect = floater_rect; -	params.follows.flags = FOLLOWS_ALL; -	params.modal = true; -	params.can_close = false; -	params.shade_color = LLColor4::white % 0.25f; -	params.text_color = LLColor4::white; -	 -	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); -	 -	addChild(mWindowShade); -	mWindowShade->show(notification); -	 -#else -	 -	LLNotificationsUI::LLEventHandler * handler = -		LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); -	 -	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler); +	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get());  	llassert(sys_handler); -	sys_handler->processNotification(notify); -	 -#endif +	sys_handler->processNotification(notification);  } diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 18baccf1c9..a91d8c1139 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -64,7 +64,7 @@ public:  						   EAcceptance* accept,  						   std::string& tooltip_msg); -	void showNotification(const LLSD& notify); +	void showNotification(const LLNotificationPtr& notification);  	BOOL handleHover(S32 x, S32 y, MASK mask);  	void onMouseLeave(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5752f839ce..c78a803bf3 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -425,13 +425,7 @@ void LLFloaterPreference::saveAvatarProperties( void )  BOOL LLFloaterPreference::postBuild()  { -	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); +	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate));  	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -461,14 +455,11 @@ BOOL LLFloaterPreference::postBuild()  void LLFloaterPreference::onBusyResponseChanged()  {  	// set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise -	if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) -	{ -		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); -	} -	else -	{ -		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE ); -	} +	bool busy_flag = +			LLTrans::getString("BusyModeResponseDefault") +					!= getChild<LLUICtrl>("busy_response")->getValue().asString(); + +	gSavedPerAccountSettings.setBOOL("BusyResponseChanged", busy_flag );  }  LLFloaterPreference::~LLFloaterPreference() @@ -553,8 +544,6 @@ void LLFloaterPreference::apply()  //	LLWString busy_response = utf8str_to_wstring(getChild<LLUICtrl>("busy_response")->getValue().asString());  //	LLWStringUtil::replaceTabsWithSpaces(busy_response, 4); - -	gSavedSettings.setBOOL("PlainTextChatHistory", getChild<LLUICtrl>("plain_text_chat_history")->getValue().asBoolean());  	if (mGotPersonalInfo)  	{  @@ -1440,8 +1429,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  	getChild<LLUICtrl>("online_visibility")->setLabelArg("[DIR_VIS]", mDirectoryVisibility);  	getChildView("send_im_to_email")->setEnabled(TRUE);  	getChild<LLUICtrl>("send_im_to_email")->setValue(im_via_email); -	getChildView("plain_text_chat_history")->setEnabled(TRUE); -	getChild<LLUICtrl>("plain_text_chat_history")->setValue(gSavedSettings.getBOOL("PlainTextChatHistory"));  	getChildView("log_instant_messages")->setEnabled(TRUE);  //	getChildView("log_chat")->setEnabled(TRUE);  //	getChildView("busy_response")->setEnabled(TRUE); @@ -1523,7 +1510,8 @@ void LLFloaterPreference::onChangeMaturity()  // but the UI for this will still be enabled  void LLFloaterPreference::onClickBlockList()  { -	LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); +	LLFloaterSidePanelContainer::showPanel("people", "panel_people", +		LLSD().with("people_panel_tab_name", "blocked_panel"));  }  void LLFloaterPreference::onClickProxySettings() diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 5385977d95..96b5c6b09b 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -61,7 +61,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	if (!getVisible())  	{ -		openFloater(); +	openFloater();  	}  	LLPanel* panel = NULL; @@ -69,10 +69,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());  	if (container)  	{ -		LLSD new_params = params; -		new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; -		container->onOpen(new_params); - +		container->openPanel(panel_name, params);  		panel = container->getCurrentPanel();  	}  	else if ((panel = dynamic_cast<LLPanel*>(view)) != NULL) diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 99ebb0eb34..4d38f5834e 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -658,8 +658,8 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  	mBtnEdit	->setToggleState( edit_visible );  	mRadioGroupEdit->setVisible( edit_visible ); -	bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); -	getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost); +	//bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts"); +	//getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost);  	mBtnLink->setVisible(edit_visible);  	mBtnUnlink->setVisible(edit_visible); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 1a17183efd..bb01ce5a7e 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,7 +29,7 @@  #include "llfloatertranslationsettings.h"  // Viewer includes -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "lltranslate.h"  #include "llviewercontrol.h" // for gSavedSettings @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()  	gSavedSettings.setString("TranslationService", getSelectedService());  	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());  	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); -	LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +	LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());  	closeFloater(false);  } diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp new file mode 100644 index 0000000000..87b388b30a --- /dev/null +++ b/indra/newview/llfloatervoicevolume.cpp @@ -0,0 +1,209 @@ +/**  + * @file llfloatervoicevolume.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatervoicevolume.h" + +// Linden libraries +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lltextbox.h" + +// viewer files +#include "llagent.h" +#include "llavataractions.h" +#include "llinspect.h" +#include "lltransientfloatermgr.h" +#include "llvoiceclient.h" + +class LLAvatarName; + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolume +////////////////////////////////////////////////////////////////////////////// + +// Avatar Inspector, a small information window used when clicking +// on avatar names in the 2D UI and in the ambient inspector widget for +// the 3D world. +class LLFloaterVoiceVolume : public LLInspect, LLTransientFloater +{ +	friend class LLFloaterReg; +	 +public: +	// avatar_id - Avatar ID for which to show information +	// Inspector will be positioned relative to current mouse position +	LLFloaterVoiceVolume(const LLSD& avatar_id); +	virtual ~LLFloaterVoiceVolume(); +	 +	/*virtual*/ BOOL postBuild(void); +	 +	// Because floater is single instance, need to re-parse data on each spawn +	// (for example, inspector about same avatar but in different position) +	/*virtual*/ void onOpen(const LLSD& avatar_id); + +	/*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } + +private: +	// Set the volume slider to this user's current client-side volume setting, +	// hiding/disabling if the user is not nearby. +	void updateVolumeControls(); + +	void onClickMuteVolume(); +	void onVolumeChange(const LLSD& data); +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); +	 +private: +	LLUUID				mAvatarID; +	// Need avatar name information to spawn friend add request +	LLAvatarName		mAvatarName; +}; + +LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) +:	LLInspect(LLSD())		// single_instance, doesn't really need key +,	mAvatarID()				// set in onOpen()  *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* +,	mAvatarName() +{ +	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); +	LLTransientFloater::init(this); +} + +LLFloaterVoiceVolume::~LLFloaterVoiceVolume() +{ +	LLTransientFloaterMgr::getInstance()->removeControlView(this); +} + +/*virtual*/ +BOOL LLFloaterVoiceVolume::postBuild(void) +{ +	getChild<LLUICtrl>("mute_btn")->setCommitCallback( +		boost::bind(&LLFloaterVoiceVolume::onClickMuteVolume, this) ); + +	getChild<LLUICtrl>("volume_slider")->setCommitCallback( +		boost::bind(&LLFloaterVoiceVolume::onVolumeChange, this, _2)); + +	return TRUE; +} + + +// Multiple calls to showInstance("floater_voice_volume", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLFloaterVoiceVolume::onOpen(const LLSD& data) +{ +	// Start open animation +	LLInspect::onOpen(data); + +	// Extract appropriate avatar id +	mAvatarID = data["avatar_id"]; + +	LLUI::positionViewNearMouse(this); + +	getChild<LLUICtrl>("avatar_name")->setValue(""); +	updateVolumeControls(); + +	LLAvatarNameCache::get(mAvatarID, +		boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterVoiceVolume::updateVolumeControls() +{ +	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); + +	LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); +	LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); + +	// Do not display volume slider and mute button if it  +	// is ourself or we are not in a voice channel together +	if (!voice_enabled || (mAvatarID == gAgent.getID())) +	{ +		mute_btn->setVisible(false); +		volume_slider->setVisible(false); +	} +	else  +	{ +		mute_btn->setVisible(true); +		volume_slider->setVisible(true); + +		// By convention, we only display and toggle voice mutes, not all mutes +		bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); +		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + +		mute_btn->setEnabled(!is_linden); +		mute_btn->setValue(is_muted); + +		volume_slider->setEnabled(!is_muted); + +		F32 volume; +		if (is_muted) +		{ +			// it's clearer to display their volume as zero +			volume = 0.f; +		} +		else +		{ +			// actual volume +			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); +		} +		volume_slider->setValue((F64)volume); +	} + +} + +void LLFloaterVoiceVolume::onClickMuteVolume() +{ +	LLAvatarActions::toggleMuteVoice(mAvatarID); +	updateVolumeControls(); +} + +void LLFloaterVoiceVolume::onVolumeChange(const LLSD& data) +{ +	F32 volume = (F32)data.asReal(); +	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); +} + +void LLFloaterVoiceVolume::onAvatarNameCache( +		const LLUUID& agent_id, +		const LLAvatarName& av_name) +{ +	if (agent_id != mAvatarID) +	{ +		return; +	} + +	getChild<LLUICtrl>("avatar_name")->setValue(av_name.getCompleteName()); +	mAvatarName = av_name; +} + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolumeUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterVoiceVolumeUtil::registerFloater() +{ +	LLFloaterReg::add("floater_voice_volume", "floater_voice_volume.xml", +					  &LLFloaterReg::build<LLFloaterVoiceVolume>); +} diff --git a/indra/newview/llfloatervoicevolume.h b/indra/newview/llfloatervoicevolume.h new file mode 100644 index 0000000000..8fcf7f250b --- /dev/null +++ b/indra/newview/llfloatervoicevolume.h @@ -0,0 +1,35 @@ +/**  + * @file llfloatervoicevolume.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERVOICEVOLUME_H +#define LL_LLFLOATERVOICEVOLUME_H + +namespace LLFloaterVoiceVolumeUtil +{ +	// Register with LLFloaterReg +	void registerFloater(); +} + +#endif // LL_LLFLOATERVOICEVOLUME_H diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp deleted file mode 100644 index 7d047ec67e..0000000000 --- a/indra/newview/llfolderview.cpp +++ /dev/null @@ -1,2627 +0,0 @@ -/**  - * @file llfolderview.cpp - * @brief Implementation of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfolderview.h" - -#include "llcallbacklist.h" -#include "llinventorybridge.h" -#include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llinventorypanel.h" -#include "llfoldertype.h" -#include "llfloaterinventory.h"// hacked in for the bonus context menu items. -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpanel.h" -#include "llpreview.h" -#include "llscrollcontainer.h" // hack to allow scrolling -#include "lltooldraganddrop.h" -#include "lltrans.h" -#include "llui.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llviewerjointattachment.h" -#include "llviewermenu.h" -#include "lluictrlfactory.h" -#include "llviewercontrol.h" -#include "llviewerfoldertype.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llfloaterproperties.h" -#include "llnotificationsutil.h" - -// Linden library includes -#include "lldbstrings.h" -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llgl.h"  -#include "llrender.h" -#include "llinventory.h" - -// Third-party library includes -#include <algorithm> - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -const S32 RENAME_WIDTH_PAD = 4; -const S32 RENAME_HEIGHT_PAD = 1; -const S32 AUTO_OPEN_STACK_DEPTH = 16; -const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH -			+ LLFolderViewItem::ICON_PAD  -			+ LLFolderViewItem::ARROW_SIZE  -			+ LLFolderViewItem::TEXT_PAD  -			+ /*first few characters*/ 40; -const S32 MINIMUM_RENAMER_WIDTH = 80; - -// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. -const S32 STATUS_TEXT_HPAD = 6; -const S32 STATUS_TEXT_VPAD = 8; - -enum { -	SIGNAL_NO_KEYBOARD_FOCUS = 1, -	SIGNAL_KEYBOARD_FOCUS = 2 -}; - -F32 LLFolderView::sAutoOpenTime = 1.f; - -void delete_selected_item(void* user_data); -void copy_selected_item(void* user_data); -void open_selected_items(void* user_data); -void properties_selected_items(void* user_data); -void paste_items(void* user_data); - - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to sort their items -// (and only their items, not folders) by a certain function. -class LLSetItemSortFunction : public LLFolderViewFunctor -{ -public: -	LLSetItemSortFunction(U32 ordering) -		: mSortOrder(ordering) {} -	virtual ~LLSetItemSortFunction() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); - -	U32 mSortOrder; -}; - - -// Set the sort order. -void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) -{ -	folder->setItemSortOrder(mSortOrder); -} - -// Do nothing. -void LLSetItemSortFunction::doItem(LLFolderViewItem* item) -{ -	return; -} - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to close themselves -// For efficiency, calls setOpenArrangeRecursively(). -// The calling function must then call: -//	LLFolderView* root = getRoot(); -//	if( root ) -//	{ -//		root->arrange( NULL, NULL ); -//		root->scrollToShowSelection(); -//	} -// to patch things up. -class LLCloseAllFoldersFunctor : public LLFolderViewFunctor -{ -public: -	LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } -	virtual ~LLCloseAllFoldersFunctor() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); - -	BOOL mOpen; -}; - - -// Set the sort order. -void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) -{ -	folder->setOpenArrangeRecursively(mOpen); -} - -// Do nothing. -void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) -{ } - -///---------------------------------------------------------------------------- -/// Class LLFolderViewScrollContainer -///---------------------------------------------------------------------------- - -// virtual -const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const -{ -	LLRect rect = LLRect::null; -	if (mScrolledView) -	{ -		LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView); -		if (folder_view) -		{ -			S32 height = folder_view->mRunningHeight; - -			rect = mScrolledView->getRect(); -			rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); -		} -	} - -	return rect; -} - -LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) -:	LLScrollContainer(p) -{} - -///---------------------------------------------------------------------------- -/// Class LLFolderView -///---------------------------------------------------------------------------- -LLFolderView::Params::Params() -:	task_id("task_id"), -	title("title"), -	use_label_suffix("use_label_suffix"), -	allow_multiselect("allow_multiselect", true), -	show_empty_message("show_empty_message", true), -	show_load_status("show_load_status", true), -	use_ellipses("use_ellipses", false) -{ -} - - -// Default constructor -LLFolderView::LLFolderView(const Params& p) -:	LLFolderViewFolder(p), -	mRunningHeight(0), -	mScrollContainer( NULL ), -	mPopupMenuHandle(), -	mAllowMultiSelect(p.allow_multiselect), -	mShowEmptyMessage(p.show_empty_message), -	mShowFolderHierarchy(FALSE), -	mSourceID(p.task_id), -	mRenameItem( NULL ), -	mNeedsScroll( FALSE ), -	mUseLabelSuffix(p.use_label_suffix), -	mPinningSelectedItem(FALSE), -	mNeedsAutoSelect( FALSE ), -	mAutoSelectOverride(FALSE), -	mNeedsAutoRename(FALSE), -	mDebugFilters(FALSE), -	mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME),	// This gets overridden by a pref immediately -	mFilter( new LLInventoryFilter(p.title) ), -	mShowSelectionContext(FALSE), -	mShowSingleSelection(FALSE), -	mArrangeGeneration(0), -	mSignalSelectCallback(0), -	mMinWidth(0), -	mDragAndDropThisFrame(FALSE), -	mCallbackRegistrar(NULL), -	mParentPanel(p.parent_panel), -	mUseEllipses(p.use_ellipses), -	mDraggingOverItem(NULL), -	mStatusTextBox(NULL) -{ -	mRoot = this; - -	mShowLoadStatus = p.show_load_status(); - -	LLRect rect = p.rect; -	LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); -	setRect( rect ); -	reshape(rect.getWidth(), rect.getHeight()); -	mIsOpen = TRUE; // this view is always open. -	mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); -	mAutoOpenCandidate = NULL; -	mAutoOpenTimer.stop(); -	mKeyboardSelection = FALSE; -	const LLFolderViewItem::Params& item_params = -		LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); -	S32 indentation = item_params.folder_indentation(); -	mIndentation = -indentation; // children start at indentation 0 -	gIdleCallbacks.addFunction(idle, this); - -	//clear label -	// go ahead and render root folder as usual -	// just make sure the label ("Inventory Folder") never shows up -	mLabel = LLStringUtil::null; - -	//mRenamer->setWriteableBgColor(LLColor4::white); -	// Escape is handled by reverting the rename, not commiting it (default behavior) -	LLLineEditor::Params params; -	params.name("ren"); -	params.rect(rect); -	params.font(getLabelFontForStyle(LLFontGL::NORMAL)); -	params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); -	params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); -	params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); -	params.commit_on_focus_lost(true); -	params.visible(false); -	mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); -	addChild(mRenamer); - -	// Textbox -	LLTextBox::Params text_p; -	LLFontGL* font = getLabelFontForStyle(mLabelStyle); -	LLRect new_r = LLRect(rect.mLeft + ICON_PAD, -			      rect.mTop - TEXT_PAD, -			      rect.mRight, -			      rect.mTop - TEXT_PAD - font->getLineHeight()); -	text_p.rect(new_r); -	text_p.name(std::string(p.name)); -	text_p.font(font); -	text_p.visible(false); -	text_p.parse_urls(true); -	text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 -	// set text padding the same as in People panel. EXT-7047, EXT-4837 -	text_p.h_pad(STATUS_TEXT_HPAD); -	text_p.v_pad(STATUS_TEXT_VPAD); -	mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p); -	mStatusTextBox->setFollowsLeft(); -	mStatusTextBox->setFollowsTop(); -	//addChild(mStatusTextBox); - - -	// make the popup menu available -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if (!menu) -	{ -		menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); -	} -	menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); -	mPopupMenuHandle = menu->getHandle(); - -	mListener->openItem(); -} - -// Destroys the object -LLFolderView::~LLFolderView( void ) -{ -	closeRenamer(); - -	// The release focus call can potentially call the -	// scrollcontainer, which can potentially be called with a partly -	// destroyed scollcontainer. Just null it out here, and no worries -	// about calling into the invalid scroll container. -	// Same with the renamer. -	mScrollContainer = NULL; -	mRenameItem = NULL; -	mRenamer = NULL; -	mStatusTextBox = NULL; - -	mAutoOpenItems.removeAllNodes(); -	gIdleCallbacks.deleteFunction(idle, this); - -	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - -	mAutoOpenItems.removeAllNodes(); -	clearSelection(); -	mItems.clear(); -	mFolders.clear(); - -	mItemMap.clear(); - -	delete mFilter; -	mFilter = NULL; -} - -BOOL LLFolderView::canFocusChildren() const -{ -	return FALSE; -} - -static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); - -void LLFolderView::setSortOrder(U32 order) -{ -	if (order != mSortOrder) -	{ -		LLFastTimer t(FTM_SORT); -		 -		mSortOrder = order; - -		sortBy(order); -		arrangeAll(); -	} -} - - -U32 LLFolderView::getSortOrder() const -{ -	return mSortOrder; -} - -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) -{ -	// enforce sort order of My Inventory followed by Library -	if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID()) -	{ -		mFolders.push_back(folder); -	} -	else -	{ -		mFolders.insert(mFolders.begin(), folder); -	} -	folder->setShowLoadStatus(mShowLoadStatus); -	folder->setOrigin(0, 0); -	folder->reshape(getRect().getWidth(), 0); -	folder->setVisible(FALSE); -	addChild( folder ); -	folder->dirtyFilter(); -	folder->requestArrange(); -	return TRUE; -} - -void LLFolderView::closeAllFolders() -{ -	// Close all the folders -	setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); -	arrangeAll(); -} - -void LLFolderView::openTopLevelFolders() -{ -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->setOpen(TRUE); -	} -} - -void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ -	// call base class to do proper recursion -	LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); -	// make sure root folder is always open -	mIsOpen = TRUE; -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); - -// This view grows and shrinks to enclose all of its children items and folders. -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) -{ -	if (getListener()->getUUID().notNull()) -	{ -		if (mNeedsSort) -		{ -			mFolders.sort(mSortFunction); -			mItems.sort(mSortFunction); -			mNeedsSort = false; -		} -	} - -	LLFastTimer t2(FTM_ARRANGE); - -	filter_generation = mFilter->getMinRequiredGeneration(); -	mMinWidth = 0; - -	mHasVisibleChildren = hasFilteredDescendants(filter_generation); -	// arrange always finishes, so optimistically set the arrange generation to the most current -	mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - -	LLInventoryFilter::EFolderShow show_folder_state = -		getRoot()->getFilter()->getShowFolderState(); - -	S32 total_width = LEFT_PAD; -	S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; -	S32 target_height = running_height; -	S32 parent_item_height = getRect().getHeight(); - -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		LLFolderViewFolder* folderp = (*fit); -		if (getDebugFilters()) -		{ -			folderp->setVisible(TRUE); -		} -		else -		{ -			folderp->setVisible((show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? -								 (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)))); -		} - -		if (folderp->getVisible()) -		{ -			S32 child_height = 0; -			S32 child_width = 0; -			S32 child_top = parent_item_height - running_height; -			 -			target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - -			mMinWidth = llmax(mMinWidth, child_width); -			total_width = llmax( total_width, child_width ); -			running_height += child_height; -			folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); -		} -	} - -	for (items_t::iterator iter = mItems.begin(); -		 iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		LLFolderViewItem* itemp = (*iit); -		itemp->setVisible(itemp->getFiltered(filter_generation)); - -		if (itemp->getVisible()) -		{ -			S32 child_width = 0; -			S32 child_height = 0; -			S32 child_top = parent_item_height - running_height; -			 -			target_height += itemp->arrange( &child_width, &child_height, filter_generation ); -			itemp->reshape(itemp->getRect().getWidth(), child_height); - -			mMinWidth = llmax(mMinWidth, child_width); -			total_width = llmax( total_width, child_width ); -			running_height += child_height; -			itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); -		} -	} - -	if(!mHasVisibleChildren)// is there any filtered items ? -	{ -		//Nope. We need to display status textbox, let's reserve some place for it -		running_height = mStatusTextBox->getTextPixelHeight(); -		target_height = running_height; -	} - -	mRunningHeight = running_height; -	LLRect scroll_rect = mScrollContainer->getContentWindowRect(); -	reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); - -	LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); -	if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) -	{ -		reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); -	} - -	// move item renamer text field to item's new position -	updateRenamerPosition(); - -	mTargetHeight = (F32)target_height; -	return llround(mTargetHeight); -} - -const std::string LLFolderView::getFilterSubString(BOOL trim) -{ -	return mFilter->getFilterSubString(trim); -} - -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); - -void LLFolderView::filter( LLInventoryFilter& filter ) -{ -	LLFastTimer t2(FTM_FILTER); -	filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); - -	if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) -	{ -		mPassedFilter = FALSE; -		mMinWidth = 0; -		LLFolderViewFolder::filter(filter); -	} -	else -	{ -		mPassedFilter = TRUE; -	} -} - -void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) -{ -	LLRect scroll_rect; -	if (mScrollContainer) -	{ -		LLView::reshape(width, height, called_from_parent); -		scroll_rect = mScrollContainer->getContentWindowRect(); -	} -	width  = llmax(mMinWidth, scroll_rect.getWidth()); -	height = llmax(mRunningHeight, scroll_rect.getHeight()); - -	// Restrict width within scroll container's width -	if (mUseEllipses && mScrollContainer) -	{ -		width = scroll_rect.getWidth(); -	} -	LLView::reshape(width, height, called_from_parent); -	mReshapeSignal(mSelectedItems, FALSE); -} - -void LLFolderView::addToSelectionList(LLFolderViewItem* item) -{ -	if (item->isSelected()) -	{ -		removeFromSelectionList(item); -	} -	if (mSelectedItems.size()) -	{ -		mSelectedItems.back()->setIsCurSelection(FALSE); -	} -	item->setIsCurSelection(TRUE); -	mSelectedItems.push_back(item); -} - -void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) -{ -	if (mSelectedItems.size()) -	{ -		mSelectedItems.back()->setIsCurSelection(FALSE); -	} - -	selected_items_t::iterator item_iter; -	for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) -	{ -		if (*item_iter == item) -		{ -			item_iter = mSelectedItems.erase(item_iter); -		} -		else -		{ -			++item_iter; -		} -	} -	if (mSelectedItems.size()) -	{ -		mSelectedItems.back()->setIsCurSelection(TRUE); -	} -} - -LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) -{ -	if(mSelectedItems.size()) -	{ -		LLFolderViewItem* itemp = mSelectedItems.back(); -		llassert(itemp->getIsCurSelection()); -		return itemp; -	} -	return NULL; -} - - -// Record the selected item and pass it down the hierachy. -BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, -								BOOL take_keyboard_focus) -{ -	mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - -	if( selection == this ) -	{ -		return FALSE; -	} - -	if( selection && take_keyboard_focus) -	{ -		mParentPanel->setFocus(TRUE); -	} - -	// clear selection down here because change of keyboard focus can potentially -	// affect selection -	clearSelection(); - -	if(selection) -	{ -		addToSelectionList(selection); -	} - -	BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); -	if(openitem && selection) -	{ -		selection->getParentFolder()->requestArrange(); -	} - -	llassert(mSelectedItems.size() <= 1); - -	return rv; -} - -void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ -	LLFolderViewItem* itemp = getItemByID(obj_id); -	if(itemp && itemp->getListener()) -	{ -		itemp->arrangeAndSet(TRUE, take_keyboard_focus); -		mSelectThisID.setNull(); -		return; -	} -	else -	{ -		// save the desired item to be selected later (if/when ready) -		mSelectThisID = obj_id; -	} -} - -void LLFolderView::updateSelection() -{ -	if (mSelectThisID.notNull()) -	{ -		setSelectionByID(mSelectThisID, false); -	} -} - -BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ -	BOOL rv = FALSE; - -	// can't select root folder -	if(!selection || selection == this) -	{ -		return FALSE; -	} - -	if (!mAllowMultiSelect) -	{ -		clearSelection(); -	} - -	selected_items_t::iterator item_iter; -	for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) -	{ -		if (*item_iter == selection) -		{ -			break; -		} -	} - -	BOOL on_list = (item_iter != mSelectedItems.end()); - -	if(selected && !on_list) -	{ -		addToSelectionList(selection); -	} -	if(!selected && on_list) -	{ -		removeFromSelectionList(selection); -	} - -	rv = LLFolderViewFolder::changeSelection(selection, selected); - -	mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; -	 -	return rv; -} - -static LLFastTimer::DeclareTimer FTM_SANITIZE_SELECTION("Sanitize Selection"); -void LLFolderView::sanitizeSelection() -{ -	LLFastTimer _(FTM_SANITIZE_SELECTION); -	// store off current item in case it is automatically deselected -	// and we want to preserve context -	LLFolderViewItem* original_selected_item = getCurSelectedItem(); - -	// Cache "Show all folders" filter setting -	BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); - -	std::vector<LLFolderViewItem*> items_to_remove; -	selected_items_t::iterator item_iter; -	for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) -	{ -		LLFolderViewItem* item = *item_iter; - -		// ensure that each ancestor is open and potentially passes filtering -		BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item -		// modify with parent open and filters states -		LLFolderViewFolder* parent_folder = item->getParentFolder(); -		if ( parent_folder ) -		{ -			if ( show_all_folders ) -			{	// "Show all folders" is on, so this folder is visible -				visible = TRUE; -			} -			else -			{	// Move up through parent folders and see what's visible -				while(parent_folder) -				{ -					visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); -					parent_folder = parent_folder->getParentFolder(); -				} -			} -		} - -		//  deselect item if any ancestor is closed or didn't pass filter requirements. -		if (!visible) -		{ -			items_to_remove.push_back(item); -		} - -		// disallow nested selections (i.e. folder items plus one or more ancestors) -		// could check cached mum selections count and only iterate if there are any -		// but that may be a premature optimization. -		selected_items_t::iterator other_item_iter; -		for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) -		{ -			LLFolderViewItem* other_item = *other_item_iter; -			for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) -			{ -				if (parent_folder == item) -				{ -					// this is a descendent of the current folder, remove from list -					items_to_remove.push_back(other_item); -					break; -				} -			} -		} - -		// Don't allow invisible items (such as root folders) to be selected. -		if (item == getRoot()) -		{ -			items_to_remove.push_back(item); -		} -	} - -	std::vector<LLFolderViewItem*>::iterator item_it; -	for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) -	{ -		changeSelection(*item_it, FALSE); // toggle selection (also removes from list) -	} - -	// if nothing selected after prior constraints... -	if (mSelectedItems.empty()) -	{ -		// ...select first available parent of original selection -		LLFolderViewItem* new_selection = NULL; -		if (original_selected_item) -		{ -			for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); -				parent_folder; -				parent_folder = parent_folder->getParentFolder()) -			{ -				if (parent_folder->potentiallyVisible()) -				{ -					// give initial selection to first ancestor folder that potentially passes the filter -					if (!new_selection) -					{ -						new_selection = parent_folder; -					} - -					// if any ancestor folder of original item is closed, move the selection up  -					// to the highest closed -					if (!parent_folder->isOpen()) -					{	 -						new_selection = parent_folder; -					} -				} -			} -		} -		else -		{ -			new_selection = NULL; -		} - -		if (new_selection) -		{ -			setSelection(new_selection, FALSE, FALSE); -		} -	} -} - -void LLFolderView::clearSelection() -{ -	for (selected_items_t::const_iterator item_it = mSelectedItems.begin();  -		 item_it != mSelectedItems.end();  -		 ++item_it) -	{ -		(*item_it)->setUnselected(); -	} - -	mSelectedItems.clear(); -	mSelectThisID.setNull(); -} - -std::set<LLUUID> LLFolderView::getSelectionList() const -{ -	std::set<LLUUID> selection; -	for (selected_items_t::const_iterator item_it = mSelectedItems.begin();  -		 item_it != mSelectedItems.end();  -		 ++item_it) -	{ -		selection.insert((*item_it)->getListener()->getUUID()); -	} -	return selection; -} - -BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) -{ -	std::vector<EDragAndDropType> types; -	uuid_vec_t cargo_ids; -	selected_items_t::iterator item_it; -	BOOL can_drag = TRUE; -	if (!mSelectedItems.empty()) -	{ -		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -		{ -			EDragAndDropType type = DAD_NONE; -			LLUUID id = LLUUID::null; -			can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); - -			types.push_back(type); -			cargo_ids.push_back(id); -		} - -		LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, source, mSourceID);  -	} -	return can_drag; -} - -void LLFolderView::commitRename( const LLSD& data ) -{ -	finishRenamingItem(); -} - -void LLFolderView::draw() -{ -	static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white); -	if (mDebugFilters) -	{ -		std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", -										mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); -		LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2,  -			getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f),  -			LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); -	} - -	//LLFontGL* font = getLabelFontForStyle(mLabelStyle); - -	// if cursor has moved off of me during drag and drop -	// close all auto opened folders -	if (!mDragAndDropThisFrame) -	{ -		closeAutoOpenedFolders(); -	} - -	// while dragging, update selection rendering to reflect single/multi drag status -	if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) -	{ -		EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); -		if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) -		{ -			setShowSingleSelection(TRUE); -		} -		else -		{ -			setShowSingleSelection(FALSE); -		} -	} -	else -	{ -		setShowSingleSelection(FALSE); -	} - - -	if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size()) -	{ -		mSearchString.clear(); -	} - -	if (hasVisibleChildren() -		|| mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) -	{ -		mStatusText.clear(); -		mStatusTextBox->setVisible( FALSE ); -	} -	else if (mShowEmptyMessage) -	{ -		if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) -		{ -			mStatusText = LLTrans::getString("Searching"); -		} -		else -		{ -			if (getFilter()) -			{ -				LLStringUtil::format_map_t args; -				args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); -				mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args); -			} -		} -		mStatusTextBox->setValue(mStatusText); -		mStatusTextBox->setVisible( TRUE ); -		 -		// firstly reshape message textbox with current size. This is necessary to -		// LLTextBox::getTextPixelHeight works properly -		const LLRect local_rect = getLocalRect(); -		mStatusTextBox->setShape(local_rect); - -		// get preferable text height... -		S32 pixel_height = mStatusTextBox->getTextPixelHeight(); -		bool height_changed = local_rect.getHeight() != pixel_height; -		if (height_changed) -		{ -			// ... if it does not match current height, lets rearrange current view. -			// This will indirectly call ::arrange and reshape of the status textbox. -			// We should call this method to also notify parent about required rect. -			// See EXT-7564, EXT-7047. -			arrangeFromRoot(); -			LLUI::popMatrix(); -			LLUI::pushMatrix(); -			LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); -		} -	} - -	// skip over LLFolderViewFolder::draw since we don't want the folder icon, label,  -	// and arrow for the root folder -	LLView::draw(); - -	mDragAndDropThisFrame = FALSE; -} - -void LLFolderView::finishRenamingItem( void ) -{ -	if(!mRenamer) -	{ -		return; -	} -	if( mRenameItem ) -	{ -		mRenameItem->rename( mRenamer->getText() ); -	} - -	closeRenamer(); - -	// List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. -	scrollToShowSelection(); -} - -void LLFolderView::closeRenamer( void ) -{ -	if (mRenamer && mRenamer->getVisible()) -	{ -		// Triggers onRenamerLost() that actually closes the renamer. -		gViewerWindow->removePopup(mRenamer); -	} -} - -void LLFolderView::removeSelectedItems( void ) -{ -	if (mSelectedItems.empty()) return; -	LLSD args; -	args["QUESTION"] = LLTrans::getString(mSelectedItems.size() > 1 ? "DeleteItems" :  "DeleteItem"); -	LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLFolderView::onItemsRemovalConfirmation, this, _1, _2)); -} - -bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems) -{ -	LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent()); - -	if (item_parent) -	{ -		for(std::vector<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) -		{ -			const LLFolderViewItem* const selected_item = (*it); - -			LLFolderViewItem* parent = item_parent; - -			while (parent) -			{ -				if (selected_item == parent) -				{ -					return true; -				} - -				parent = dynamic_cast<LLFolderViewItem*>(parent->getParent()); -			} -		} -	} - -	return false; -} - -// static -void LLFolderView::removeCutItems() -{ -	// There's no item in "cut" mode on the clipboard -> exit -	if (!LLClipboard::instance().isCutMode()) -		return; - -	// Get the list of clipboard item uuids and iterate through them -	LLDynamicArray<LLUUID> objects; -	LLClipboard::instance().pasteFromClipboard(objects); -	for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); -		 iter != objects.end(); -		 ++iter) -	{ -		gInventory.removeObject(*iter); -	} -} - -void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	if (option != 0) return; // canceled - -	if(getVisible() && getEnabled()) -	{ -		// just in case we're removing the renaming item. -		mRenameItem = NULL; - -		// create a temporary structure which we will use to remove -		// items, since the removal will futz with internal data -		// structures. -		std::vector<LLFolderViewItem*> items; -		S32 count = mSelectedItems.size(); -		if(count == 0) return; -		LLFolderViewItem* item = NULL; -		selected_items_t::iterator item_it; -		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -		{ -			item = *item_it; -			if (item && item->isRemovable()) -			{ -				items.push_back(item); -			} -			else -			{ -				llinfos << "Cannot delete " << item->getName() << llendl; -				return; -			} -		} - -		// iterate through the new container. -		count = items.size(); -		LLUUID new_selection_id; -		if(count == 1) -		{ -			LLFolderViewItem* item_to_delete = items[0]; -			LLFolderViewFolder* parent = item_to_delete->getParentFolder(); -			LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); -			if (!new_selection) -			{ -				new_selection = item_to_delete->getPreviousOpenNode(FALSE); -			} -			if(parent) -			{ -				if (parent->removeItem(item_to_delete)) -				{ -					// change selection on successful delete -					if (new_selection) -					{ -						setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); -					} -					else -					{ -						setSelectionFromRoot(NULL, mParentPanel->hasFocus()); -					} -				} -			} -			arrangeAll(); -		} -		else if (count > 1) -		{ -			LLDynamicArray<LLFolderViewEventListener*> listeners; -			LLFolderViewEventListener* listener; -			LLFolderViewItem* last_item = items[count - 1]; -			LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); -			while(new_selection && new_selection->isSelected()) -			{ -				new_selection = new_selection->getNextOpenNode(FALSE); -			} -			if (!new_selection) -			{ -				new_selection = last_item->getPreviousOpenNode(FALSE); -				while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items))) -				{ -					new_selection = new_selection->getPreviousOpenNode(FALSE); -				} -			} -			if (new_selection) -			{ -				setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus()); -			} -			else -			{ -				setSelectionFromRoot(NULL, mParentPanel->hasFocus()); -			} - -			for(S32 i = 0; i < count; ++i) -			{ -				listener = items[i]->getListener(); -				if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) -				{ -					listeners.put(listener); -				} -			} -			listener = listeners.get(0); -			if(listener) -			{ -				listener->removeBatch(listeners); -			} -		} -		arrangeAll(); -		scrollToShowSelection(); -	} -} - -// open the selected item. -void LLFolderView::openSelectedItems( void ) -{ -	if(getVisible() && getEnabled()) -	{ -		if (mSelectedItems.size() == 1) -		{ -			mSelectedItems.front()->openItem(); -		} -		else -		{ -			LLMultiPreview* multi_previewp = new LLMultiPreview(); -			LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - -			selected_items_t::iterator item_it; -			for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -			{ -				// IT_{OBJECT,ATTACHMENT} creates LLProperties -				// floaters; others create LLPreviews.  Put -				// each one in the right type of container. -				LLFolderViewEventListener* listener = (*item_it)->getListener(); -				bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); -				if (is_prop) -					LLFloater::setFloaterHost(multi_propertiesp); -				else -					LLFloater::setFloaterHost(multi_previewp); -				(*item_it)->openItem(); -			} - -			LLFloater::setFloaterHost(NULL); -			// *NOTE: LLMulti* will safely auto-delete when open'd -			// without any children. -			multi_previewp->openFloater(LLSD()); -			multi_propertiesp->openFloater(LLSD()); -		} -	} -} - -void LLFolderView::propertiesSelectedItems( void ) -{ -	if(getVisible() && getEnabled()) -	{ -		if (mSelectedItems.size() == 1) -		{ -			LLFolderViewItem* folder_item = mSelectedItems.front(); -			if(!folder_item) return; -			folder_item->getListener()->showProperties(); -		} -		else -		{ -			LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - -			LLFloater::setFloaterHost(multi_propertiesp); - -			selected_items_t::iterator item_it; -			for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -			{ -				(*item_it)->getListener()->showProperties(); -			} - -			LLFloater::setFloaterHost(NULL); -			multi_propertiesp->openFloater(LLSD()); -		} -	} -} - -void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) -{ -	LLFolderBridge *folder_bridge = LLFolderBridge::sSelf.get(); - -	if (!folder_bridge) return; -	LLViewerInventoryCategory *cat = folder_bridge->getCategory(); -	if (!cat) return; -	cat->changeType(new_folder_type); -} - -void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) -{ -	if ((mAutoOpenItems.check() == item) ||  -		(mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || -		item->isOpen()) -	{ -		return; -	} - -	// close auto-opened folders -	LLFolderViewFolder* close_item = mAutoOpenItems.check(); -	while (close_item && close_item != item->getParentFolder()) -	{ -		mAutoOpenItems.pop(); -		close_item->setOpenArrangeRecursively(FALSE); -		close_item = mAutoOpenItems.check(); -	} - -	item->requestArrange(); - -	mAutoOpenItems.push(item); -	 -	item->setOpen(TRUE); -	LLRect content_rect = mScrollContainer->getContentWindowRect(); -	LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); -	scrollToShowItem(item, constraint_rect); -} - -void LLFolderView::closeAutoOpenedFolders() -{ -	while (mAutoOpenItems.check()) -	{ -		LLFolderViewFolder* close_item = mAutoOpenItems.pop(); -		close_item->setOpen(FALSE); -	} - -	if (mAutoOpenCandidate) -	{ -		mAutoOpenCandidate->setAutoOpenCountdown(0.f); -	} -	mAutoOpenCandidate = NULL; -	mAutoOpenTimer.stop(); -} - -BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) -{ -	if (folder && mAutoOpenCandidate == folder) -	{ -		if (mAutoOpenTimer.getStarted()) -		{ -			if (!mAutoOpenCandidate->isOpen()) -			{ -				mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); -			} -			if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) -			{ -				autoOpenItem(folder); -				mAutoOpenTimer.stop(); -				return TRUE; -			} -		} -		return FALSE; -	} - -	// otherwise new candidate, restart timer -	if (mAutoOpenCandidate) -	{ -		mAutoOpenCandidate->setAutoOpenCountdown(0.f); -	} -	mAutoOpenCandidate = folder; -	mAutoOpenTimer.start(); -	return FALSE; -} - -BOOL LLFolderView::canCopy() const -{ -	if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) -	{ -		return FALSE; -	} -	 -	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) -	{ -		const LLFolderViewItem* item = *selected_it; -		if (!item->getListener()->isItemCopyable()) -		{ -			return FALSE; -		} -	} -	return TRUE; -} - -// copy selected item -void LLFolderView::copy() -{ -	// *NOTE: total hack to clear the inventory clipboard -	LLClipboard::instance().reset(); -	S32 count = mSelectedItems.size(); -	if(getVisible() && getEnabled() && (count > 0)) -	{ -		LLFolderViewEventListener* listener = NULL; -		selected_items_t::iterator item_it; -		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -		{ -			listener = (*item_it)->getListener(); -			if(listener) -			{ -				listener->copyToClipboard(); -			} -		} -	} -	mSearchString.clear(); -} - -BOOL LLFolderView::canCut() const -{ -	if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) -	{ -		return FALSE; -	} -	 -	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) -	{ -		const LLFolderViewItem* item = *selected_it; -		const LLFolderViewEventListener* listener = item->getListener(); - -		if (!listener || !listener->isItemRemovable()) -		{ -			return FALSE; -		} -	} -	return TRUE; -} - -void LLFolderView::cut() -{ -	// clear the inventory clipboard -	LLClipboard::instance().reset(); -	S32 count = mSelectedItems.size(); -	if(getVisible() && getEnabled() && (count > 0)) -	{ -		LLFolderViewEventListener* listener = NULL; -		selected_items_t::iterator item_it; -		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -		{ -			listener = (*item_it)->getListener(); -			if(listener) -			{ -				listener->cutToClipboard(); -			} -		} -		LLFolderView::removeCutItems(); -	} -	mSearchString.clear(); -} - -BOOL LLFolderView::canPaste() const -{ -	if (mSelectedItems.empty()) -	{ -		return FALSE; -	} - -	if(getVisible() && getEnabled()) -	{ -		for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); -			 item_it != mSelectedItems.end(); ++item_it) -		{ -			// *TODO: only check folders and parent folders of items -			const LLFolderViewItem* item = (*item_it); -			const LLFolderViewEventListener* listener = item->getListener(); -			if(!listener || !listener->isClipboardPasteable()) -			{ -				const LLFolderViewFolder* folderp = item->getParentFolder(); -				listener = folderp->getListener(); -				if (!listener || !listener->isClipboardPasteable()) -				{ -					return FALSE; -				} -			} -		} -		return TRUE; -	} -	return FALSE; -} - -// paste selected item -void LLFolderView::paste() -{ -	if(getVisible() && getEnabled()) -	{ -		// find set of unique folders to paste into -		std::set<LLFolderViewItem*> folder_set; - -		selected_items_t::iterator selected_it; -		for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) -		{ -			LLFolderViewItem* item = *selected_it; -			LLFolderViewEventListener* listener = item->getListener(); -			if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) -			{ -				item = item->getParentFolder(); -			} -			folder_set.insert(item); -		} - -		std::set<LLFolderViewItem*>::iterator set_iter; -		for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) -		{ -			LLFolderViewEventListener* listener = (*set_iter)->getListener(); -			if(listener && listener->isClipboardPasteable()) -			{ -				listener->pasteFromClipboard(); -			} -		} -	} -	mSearchString.clear(); -} - -// public rename functionality - can only start the process -void LLFolderView::startRenamingSelectedItem( void ) -{ -	// make sure selection is visible -	scrollToShowSelection(); - -	S32 count = mSelectedItems.size(); -	LLFolderViewItem* item = NULL; -	if(count > 0) -	{ -		item = mSelectedItems.front(); -	} -	if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && -	   item->getListener()->isItemRenameable()) -	{ -		mRenameItem = item; - -		updateRenamerPosition(); - - -		mRenamer->setText(item->getName()); -		mRenamer->selectAll(); -		mRenamer->setVisible( TRUE ); -		// set focus will fail unless item is visible -		mRenamer->setFocus( TRUE ); -		mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); -		gViewerWindow->addPopup(mRenamer); -	} -} - -BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) -{ -	BOOL handled = FALSE; - -	// SL-51858: Key presses are not being passed to the Popup menu. -	// A proper fix is non-trivial so instead just close the menu. -	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); -	if (menu && menu->isOpen()) -	{ -		LLMenuGL::sMenuContainer->hideMenus(); -	} - -	LLView *item = NULL; -	if (getChildCount() > 0) -	{ -		item = *(getChildList()->begin()); -	} - -	switch( key ) -	{ -	case KEY_F2: -		mSearchString.clear(); -		startRenamingSelectedItem(); -		handled = TRUE; -		break; - -	case KEY_RETURN: -		if (mask == MASK_NONE) -		{ -			if( mRenameItem && mRenamer->getVisible() ) -			{ -				finishRenamingItem(); -				mSearchString.clear(); -				handled = TRUE; -			} -			else -			{ -				LLFolderView::openSelectedItems(); -				handled = TRUE; -			} -		} -		break; - -	case KEY_ESCAPE: -		if( mRenameItem && mRenamer->getVisible() ) -		{ -			closeRenamer(); -			handled = TRUE; -		} -		mSearchString.clear(); -		break; - -	case KEY_PAGE_UP: -		mSearchString.clear(); -		mScrollContainer->pageUp(30); -		handled = TRUE; -		break; - -	case KEY_PAGE_DOWN: -		mSearchString.clear(); -		mScrollContainer->pageDown(30); -		handled = TRUE; -		break; - -	case KEY_HOME: -		mSearchString.clear(); -		mScrollContainer->goToTop(); -		handled = TRUE; -		break; - -	case KEY_END: -		mSearchString.clear(); -		mScrollContainer->goToBottom(); -		break; - -	case KEY_DOWN: -		if((mSelectedItems.size() > 0) && mScrollContainer) -		{ -			LLFolderViewItem* last_selected = getCurSelectedItem(); - -			if (!mKeyboardSelection) -			{ -				setSelection(last_selected, FALSE, TRUE); -				mKeyboardSelection = TRUE; -			} - -			LLFolderViewItem* next = NULL; -			if (mask & MASK_SHIFT) -			{ -				// don't shift select down to children of folders (they are implicitly selected through parent) -				next = last_selected->getNextOpenNode(FALSE); -				if (next) -				{ -					if (next->isSelected()) -					{ -						// shrink selection -						changeSelectionFromRoot(last_selected, FALSE); -					} -					else if (last_selected->getParentFolder() == next->getParentFolder()) -					{ -						// grow selection -						changeSelectionFromRoot(next, TRUE); -					} -				} -			} -			else -			{ -				next = last_selected->getNextOpenNode(); -				if( next ) -				{ -					if (next == last_selected) -					{ -						//special case for LLAccordionCtrl -						if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed -						{ -							clearSelection(); -							return TRUE; -						} -						return FALSE; -					} -					setSelection( next, FALSE, TRUE ); -				} -				else -				{ -					//special case for LLAccordionCtrl -					if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed -					{ -						clearSelection(); -						return TRUE; -					} -					return FALSE; -				} -			} -			scrollToShowSelection(); -			mSearchString.clear(); -			handled = TRUE; -		} -		break; - -	case KEY_UP: -		if((mSelectedItems.size() > 0) && mScrollContainer) -		{ -			LLFolderViewItem* last_selected = mSelectedItems.back(); - -			if (!mKeyboardSelection) -			{ -				setSelection(last_selected, FALSE, TRUE); -				mKeyboardSelection = TRUE; -			} - -			LLFolderViewItem* prev = NULL; -			if (mask & MASK_SHIFT) -			{ -				// don't shift select down to children of folders (they are implicitly selected through parent) -				prev = last_selected->getPreviousOpenNode(FALSE); -				if (prev) -				{ -					if (prev->isSelected()) -					{ -						// shrink selection -						changeSelectionFromRoot(last_selected, FALSE); -					} -					else if (last_selected->getParentFolder() == prev->getParentFolder()) -					{ -						// grow selection -						changeSelectionFromRoot(prev, TRUE); -					} -				} -			} -			else -			{ -				prev = last_selected->getPreviousOpenNode(); -				if( prev ) -				{ -					if (prev == this) -					{ -						// If case we are in accordion tab notify parent to go to the previous accordion -						if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed -						{ -							clearSelection(); -							return TRUE; -						} - -						return FALSE; -					} -					setSelection( prev, FALSE, TRUE ); -				} -			} -			scrollToShowSelection(); -			mSearchString.clear(); - -			handled = TRUE; -		} -		break; - -	case KEY_RIGHT: -		if(mSelectedItems.size()) -		{ -			LLFolderViewItem* last_selected = getCurSelectedItem(); -			last_selected->setOpen( TRUE ); -			mSearchString.clear(); -			handled = TRUE; -		} -		break; - -	case KEY_LEFT: -		if(mSelectedItems.size()) -		{ -			LLFolderViewItem* last_selected = getCurSelectedItem(); -			LLFolderViewItem* parent_folder = last_selected->getParentFolder(); -			if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) -			{ -				setSelection(parent_folder, FALSE, TRUE); -			} -			else -			{ -				last_selected->setOpen( FALSE ); -			} -			mSearchString.clear(); -			scrollToShowSelection(); -			handled = TRUE; -		} -		break; -	} - -	if (!handled && mParentPanel->hasFocus()) -	{ -		if (key == KEY_BACKSPACE) -		{ -			mSearchTimer.reset(); -			if (mSearchString.size()) -			{ -				mSearchString.erase(mSearchString.size() - 1, 1); -			} -			search(getCurSelectedItem(), mSearchString, FALSE); -			handled = TRUE; -		} -	} - -	return handled; -} - - -BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) -{ -	if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL -	{ -		return FALSE; -	} - -	if (uni_char > 0x7f) -	{ -		llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl; -		return FALSE; -	} - -	BOOL handled = FALSE; -	if (mParentPanel->hasFocus()) -	{ -		// SL-51858: Key presses are not being passed to the Popup menu. -		// A proper fix is non-trivial so instead just close the menu. -		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); -		if (menu && menu->isOpen()) -		{ -			LLMenuGL::sMenuContainer->hideMenus(); -		} - -		//do text search -		if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout")) -		{ -			mSearchString.clear(); -		} -		mSearchTimer.reset(); -		if (mSearchString.size() < 128) -		{ -			mSearchString += uni_char; -		} -		search(getCurSelectedItem(), mSearchString, FALSE); - -		handled = TRUE; -	} - -	return handled; -} - - -BOOL LLFolderView::canDoDelete() const -{ -	if (mSelectedItems.size() == 0) return FALSE; - -	for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -	{ -		if (!(*item_it)->getListener()->isItemRemovable()) -		{ -			return FALSE; -		} -	} -	return TRUE; -} - -void LLFolderView::doDelete() -{ -	if(mSelectedItems.size() > 0) -	{				 -		removeSelectedItems(); -	} -} - - -BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) -{ -	mKeyboardSelection = FALSE; -	mSearchString.clear(); - -	mParentPanel->setFocus(TRUE); - -	LLEditMenuHandler::gEditMenuHandler = this; - -	return LLView::handleMouseDown( x, y, mask ); -} - -BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) -{ -	// get first selected item -	LLFolderViewItem* search_item = first_item; - -	// make sure search string is upper case -	std::string upper_case_string = search_string; -	LLStringUtil::toUpper(upper_case_string); - -	// if nothing selected, select first item in folder -	if (!search_item) -	{ -		// start from first item -		search_item = getNextFromChild(NULL); -	} - -	// search over all open nodes for first substring match (with wrapping) -	BOOL found = FALSE; -	LLFolderViewItem* original_search_item = search_item; -	do -	{ -		// wrap at end -		if (!search_item) -		{ -			if (backward) -			{ -				search_item = getPreviousFromChild(NULL); -			} -			else -			{ -				search_item = getNextFromChild(NULL); -			} -			if (!search_item || search_item == original_search_item) -			{ -				break; -			} -		} - -		const std::string current_item_label(search_item->getSearchableLabel()); -		S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); -		if (!current_item_label.compare(0, search_string_length, upper_case_string)) -		{ -			found = TRUE; -			break; -		} -		if (backward) -		{ -			search_item = search_item->getPreviousOpenNode(); -		} -		else -		{ -			search_item = search_item->getNextOpenNode(); -		} - -	} while(search_item != original_search_item); -	 - -	if (found) -	{ -		setSelection(search_item, FALSE, TRUE); -		scrollToShowSelection(); -	} - -	return found; -} - -BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ -	// skip LLFolderViewFolder::handleDoubleClick() -	return LLView::handleDoubleClick( x, y, mask ); -} - -BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ -	// all user operations move keyboard focus to inventory -	// this way, we know when to stop auto-updating a search -	mParentPanel->setFocus(TRUE); - -	BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; -	S32 count = mSelectedItems.size(); -	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); -	if (   handled -		&& ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible -		&& menu ) -	{ -		if (mCallbackRegistrar) -			mCallbackRegistrar->pushScope(); - -		updateMenuOptions(menu); -	    -		menu->updateParent(LLMenuGL::sMenuContainer); -		LLMenuGL::showPopup(this, menu, x, y); -		if (mCallbackRegistrar) -			mCallbackRegistrar->popScope(); -	} -	else -	{ -		if (menu && menu->getVisible()) -		{ -			menu->setVisible(FALSE); -		} -		setSelection(NULL, FALSE, TRUE); -	} -	return handled; -} - -// Add "--no options--" if the menu is completely blank. -BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const -{ -	const std::string nooptions_str = "--no options--"; -	LLView *nooptions_item = NULL; -	 -	const LLView::child_list_t *list = menu->getChildList(); -	for (LLView::child_list_t::const_iterator itor = list->begin();  -		 itor != list->end();  -		 ++itor) -	{ -		LLView *menu_item = (*itor); -		if (menu_item->getVisible()) -		{ -			return FALSE; -		} -		std::string name = menu_item->getName(); -		if (menu_item->getName() == nooptions_str) -		{ -			nooptions_item = menu_item; -		} -	} -	if (nooptions_item) -	{ -		nooptions_item->setVisible(TRUE); -		nooptions_item->setEnabled(FALSE); -		return TRUE; -	} -	return FALSE; -} - -BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) -{ -	return LLView::handleHover( x, y, mask ); -} - -BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -									 EDragAndDropType cargo_type, -									 void* cargo_data,  -									 EAcceptance* accept, -									 std::string& tooltip_msg) -{ -	mDragAndDropThisFrame = TRUE; -	// have children handle it first -	BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, -											 accept, tooltip_msg); - -	// when drop is not handled by child, it should be handled -	// by the folder which is the hierarchy root. -	if (!handled) -	{ -		if (getListener()->getUUID().notNull()) -		{ -			handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); -		} -		else -		{ -			if (!mFolders.empty()) -			{ -				// dispatch to last folder as a hack to support "Contents" folder in object inventory -				handled = mFolders.back()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); -			} -		} -	} - -	if (handled) -	{ -		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; -	} - -	return handled; -} - -void LLFolderView::deleteAllChildren() -{ -	closeRenamer(); -	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); -	mPopupMenuHandle = LLHandle<LLView>(); -	mScrollContainer = NULL; -	mRenameItem = NULL; -	mRenamer = NULL; -	mStatusTextBox = NULL; -	 -	clearSelection(); -	LLView::deleteAllChildren(); -} - -void LLFolderView::scrollToShowSelection() -{ -	if ( mSelectedItems.size() ) -	{ -		mNeedsScroll = TRUE; -	} -} - -// If the parent is scroll container, scroll it to make the selection -// is maximally visible. -void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) -{ -	if (!mScrollContainer) return; - -	// don't scroll to items when mouse is being used to scroll/drag and drop -	if (gFocusMgr.childHasMouseCapture(mScrollContainer)) -	{ -		mNeedsScroll = FALSE; -		return; -	} - -	// if item exists and is in visible portion of parent folder... -	if(item) -	{ -		LLRect local_rect = item->getLocalRect(); -		LLRect item_scrolled_rect; // item position relative to display area of scroller -		LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect(); -		 -		S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();  -		S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight();  -		// when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder -		S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight();  -		 -		// get portion of item that we want to see... -		LLRect item_local_rect = LLRect(item->getIndentation(),  -										local_rect.getHeight(),  -										llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()),  -										llmax(0, local_rect.getHeight() - max_height_to_show)); - -		LLRect item_doc_rect; - -		item->localRectToOtherView(item_local_rect, &item_doc_rect, this);  - -		mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); - -	} -} - -LLRect LLFolderView::getVisibleRect() -{ -	S32 visible_height = mScrollContainer->getRect().getHeight(); -	S32 visible_width = mScrollContainer->getRect().getWidth(); -	LLRect visible_rect; -	visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); -	return visible_rect; -} - -BOOL LLFolderView::getShowSelectionContext() -{ -	if (mShowSelectionContext) -	{ -		return TRUE; -	} -	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); -	if (menu && menu->getVisible()) -	{ -		return TRUE; -	} -	return FALSE; -} - -void LLFolderView::setShowSingleSelection(BOOL show) -{ -	if (show != mShowSingleSelection) -	{ -		mMultiSelectionFadeTimer.reset(); -		mShowSingleSelection = show; -	} -} - -void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) -{ -	mItemMap[id] = itemp; -} - -void LLFolderView::removeItemID(const LLUUID& id) -{ -	mItemMap.erase(id); -} - -LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); -LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) -{ -	LLFastTimer _(FTM_GET_ITEM_BY_ID); -	if (id == getListener()->getUUID()) -	{ -		return this; -	} - -	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; -	map_it = mItemMap.find(id); -	if (map_it != mItemMap.end()) -	{ -		return map_it->second; -	} - -	return NULL; -} - -LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) -{ -	if (id == getListener()->getUUID()) -	{ -		return this; -	} - -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end(); -		 ++iter) -	{ -		LLFolderViewFolder *folder = (*iter); -		if (folder->getListener()->getUUID() == id) -		{ -			return folder; -		} -	} -	return NULL; -} - -bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) -{ -	std::string action = userdata.asString(); -	 -	if ("rename" == action) -	{ -		startRenamingSelectedItem(); -		return true; -	} -	if ("delete" == action) -	{ -		removeSelectedItems(); -		return true; -	} -	if (("copy" == action) || ("cut" == action)) -	{ -		// Clear the clipboard before we start adding things on it -		LLClipboard::instance().reset(); -	} - -	static const std::string change_folder_string = "change_folder_type_"; -	if (action.length() > change_folder_string.length() &&  -		(action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) -	{ -		LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); -		changeType(model, new_folder_type); -		return true; -	} - - -	std::set<LLUUID> selected_items = getSelectionList(); - -	LLMultiPreview* multi_previewp = NULL; -	LLMultiProperties* multi_propertiesp = NULL; - -	if (("task_open" == action  || "open" == action) && selected_items.size() > 1) -	{ -		multi_previewp = new LLMultiPreview(); -		gFloaterView->addChild(multi_previewp); - -		LLFloater::setFloaterHost(multi_previewp); -	 -	} -	else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) -	{ -		multi_propertiesp = new LLMultiProperties(); -		gFloaterView->addChild(multi_propertiesp); - -		LLFloater::setFloaterHost(multi_propertiesp); -	} - -	std::set<LLUUID>::iterator set_iter; - -	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) -	{ -		LLFolderViewItem* folder_item = getItemByID(*set_iter); -		if(!folder_item) continue; -		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); -		if(!bridge) continue; -		bridge->performAction(model, action); -	} - -	LLFloater::setFloaterHost(NULL); -	if (multi_previewp) -	{ -		multi_previewp->openFloater(LLSD()); -	} -	else if (multi_propertiesp) -	{ -		multi_propertiesp->openFloater(LLSD()); -	} - -	return true; -} - -static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select"); -static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); - -// Main idle routine -void LLFolderView::doIdle() -{ -	// If this is associated with the user's inventory, don't do anything -	// until that inventory is loaded up. -	const LLInventoryPanel *inventory_panel = dynamic_cast<LLInventoryPanel*>(mParentPanel); -	if (inventory_panel && !inventory_panel->getIsViewsInitialized()) -	{ -		return; -	} -	 -	LLFastTimer t2(FTM_INVENTORY); - -	BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); -	if (debug_filters != getDebugFilters()) -	{ -		mDebugFilters = debug_filters; -		arrangeAll(); -	} - -	mNeedsAutoSelect = mFilter->hasFilterString() && -							!(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture()); - -		 -	if (mFilter->isModified() && mFilter->isNotDefault()) -	{ -		mNeedsAutoSelect = TRUE; -	} -	mFilter->clearModified(); -			 -	// filter to determine visibility before arranging -	filterFromRoot(); - -	// automatically show matching items, and select first one if we had a selection -	if (mNeedsAutoSelect) -	{ -		LLFastTimer t3(FTM_AUTO_SELECT); -		// select new item only if a filtered item not currently selected -		LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); -		if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->potentiallyFiltered())) -		{ -			// these are named variables to get around gcc not binding non-const references to rvalues -			// and functor application is inherently non-const to allow for stateful functors -			LLSelectFirstFilteredItem functor; -			applyFunctorRecursively(functor); -		} - -		// Open filtered folders for folder views with mAutoSelectOverride=TRUE. -		// Used by LLPlacesFolderView. -		if (mAutoSelectOverride && !mFilter->getFilterSubString().empty()) -		{ -			// these are named variables to get around gcc not binding non-const references to rvalues -			// and functor application is inherently non-const to allow for stateful functors -			LLOpenFilteredFolders functor; -			applyFunctorRecursively(functor); -		} - -		scrollToShowSelection(); -	} - -	BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration()  -						&& !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); -	if (filter_finished  -		|| gFocusMgr.childHasKeyboardFocus(inventory_panel)  -		|| gFocusMgr.childHasMouseCapture(inventory_panel)) -	{ -		// finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process -		mNeedsAutoSelect = FALSE; -	} - - -	// during filtering process, try to pin selected item's location on screen -	// this will happen when searching your inventory and when new items arrive -	if (!filter_finished) -	{ -		// calculate rectangle to pin item to at start of animated rearrange -		if (!mPinningSelectedItem && !mSelectedItems.empty()) -		{ -			// lets pin it! -			mPinningSelectedItem = TRUE; - -			LLRect visible_content_rect = mScrollContainer->getVisibleContentRect(); -			LLFolderViewItem* selected_item = mSelectedItems.back(); - -			LLRect item_rect; -			selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); -			// if item is visible in scrolled region -			if (visible_content_rect.overlaps(item_rect)) -			{ -				// then attempt to keep it in same place on screen -				mScrollConstraintRect = item_rect; -				mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); -			} -			else -			{ -				// otherwise we just want it onscreen somewhere -				LLRect content_rect = mScrollContainer->getContentWindowRect(); -				mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); -			} -		} -	} -	else -	{ -		// stop pinning selected item after folders stop rearranging -		if (!needsArrange()) -		{ -			mPinningSelectedItem = FALSE; -		} -	} - -	LLRect constraint_rect; -	if (mPinningSelectedItem) -	{ -		// use last known constraint rect for pinned item -		constraint_rect = mScrollConstraintRect; -	} -	else -	{ -		// during normal use (page up/page down, etc), just try to fit item on screen -		LLRect content_rect = mScrollContainer->getContentWindowRect(); -		constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); -	} - - -	BOOL is_visible = isInVisibleChain(); - -	if ( is_visible ) -	{ -		sanitizeSelection(); -		if( needsArrange() ) -		{ -			arrangeFromRoot(); -		} -	} - -	if (mSelectedItems.size() && mNeedsScroll) -	{ -		scrollToShowItem(mSelectedItems.back(), constraint_rect); -		// continue scrolling until animated layout change is done -		if (filter_finished -			&& (!needsArrange() || !is_visible)) -		{ -			mNeedsScroll = FALSE; -		} -	} - -	if (mSignalSelectCallback) -	{ -		//RN: we use keyboard focus as a proxy for user-explicit actions -		BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); -		mSelectSignal(mSelectedItems, take_keyboard_focus); -	} -	mSignalSelectCallback = FALSE; -} - - -//static -void LLFolderView::idle(void* user_data) -{ -	LLFolderView* self = (LLFolderView*)user_data; -	if ( self ) -	{	// Do the real idle  -		self->doIdle(); -	} -} - -void LLFolderView::dumpSelectionInformation() -{ -	llinfos << "LLFolderView::dumpSelectionInformation()" << llendl; -	llinfos << "****************************************" << llendl; -	selected_items_t::iterator item_it; -	for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) -	{ -		llinfos << "  " << (*item_it)->getName() << llendl; -	} -	llinfos << "****************************************" << llendl; -} - -void LLFolderView::updateRenamerPosition() -{ -	if(mRenameItem) -	{ -		// See also LLFolderViewItem::draw() -		S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); -		S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; -		mRenameItem->localPointToScreen( x, y, &x, &y ); -		screenPointToLocal( x, y, &x, &y ); -		mRenamer->setOrigin( x, y ); - -		LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0); -		if (mScrollContainer) -		{ -			scroller_rect = mScrollContainer->getContentWindowRect(); -		} - -		S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); -		S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; -		mRenamer->reshape( width, height, TRUE ); -	} -} - -// Update visibility and availability (i.e. enabled/disabled) of context menu items. -void LLFolderView::updateMenuOptions(LLMenuGL* menu) -{ -	const LLView::child_list_t *list = menu->getChildList(); - -	LLView::child_list_t::const_iterator menu_itor; -	for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) -	{ -		(*menu_itor)->setVisible(FALSE); -		(*menu_itor)->pushVisible(TRUE); -		(*menu_itor)->setEnabled(TRUE); -	} - -	// Successively filter out invalid options - -	U32 flags = FIRST_SELECTED_ITEM; -	for (selected_items_t::iterator item_itor = mSelectedItems.begin(); -			item_itor != mSelectedItems.end(); -			++item_itor) -	{ -		LLFolderViewItem* selected_item = (*item_itor); -		selected_item->buildContextMenu(*menu, flags); -		flags = 0x0; -	} - -	addNoOptions(menu); -} - -// Refresh the context menu (that is already shown). -void LLFolderView::updateMenu() -{ -	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); -	if (menu && menu->getVisible()) -	{ -		updateMenuOptions(menu); -		menu->needsArrange(); // update menu height if needed -	} -} - -bool LLFolderView::selectFirstItem() -{ -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end();++iter) -	{ -		LLFolderViewFolder* folder = (*iter ); -		if (folder->getVisible()) -		{ -			LLFolderViewItem* itemp = folder->getNextFromChild(0,true); -			if(itemp) -				setSelection(itemp,FALSE,TRUE); -			return true;	 -		} -		 -	} -	for(items_t::iterator iit = mItems.begin(); -		iit != mItems.end(); ++iit) -	{ -		LLFolderViewItem* itemp = (*iit); -		if (itemp->getVisible()) -		{ -			setSelection(itemp,FALSE,TRUE); -			return true;	 -		} -	} -	return false; -} -bool LLFolderView::selectLastItem() -{ -	for(items_t::reverse_iterator iit = mItems.rbegin(); -		iit != mItems.rend(); ++iit) -	{ -		LLFolderViewItem* itemp = (*iit); -		if (itemp->getVisible()) -		{ -			setSelection(itemp,FALSE,TRUE); -			return true;	 -		} -	} -	for (folders_t::reverse_iterator iter = mFolders.rbegin(); -		 iter != mFolders.rend();++iter) -	{ -		LLFolderViewFolder* folder = (*iter); -		if (folder->getVisible()) -		{ -			LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); -			if(itemp) -				setSelection(itemp,FALSE,TRUE); -			return true;	 -		} -	} -	return false; -} - - -S32	LLFolderView::notify(const LLSD& info)  -{ -	if(info.has("action")) -	{ -		std::string str_action = info["action"]; -		if(str_action == "select_first") -		{ -			setFocus(true); -			selectFirstItem(); -			scrollToShowSelection(); -			return 1; - -		} -		else if(str_action == "select_last") -		{ -			setFocus(true); -			selectLastItem(); -			scrollToShowSelection(); -			return 1; -		} -	} -	return 0; -} - - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- - -void LLFolderView::onRenamerLost() -{ -	if (mRenamer && mRenamer->getVisible()) -	{ -		mRenamer->setVisible(FALSE); - -		// will commit current name (which could be same as original name) -		mRenamer->setFocus(FALSE); -	} - -	if( mRenameItem ) -	{ -		setSelectionFromRoot( mRenameItem, TRUE ); -		mRenameItem = NULL; -	} -} - -LLInventoryFilter* LLFolderView::getFilter() -{ -	return mFilter; -} - -void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) -{ -	mFilter->setFilterPermissions(filter_perm_mask); -} - -U32 LLFolderView::getFilterObjectTypes() const -{ -	return mFilter->getFilterObjectTypes(); -} - -PermissionMask LLFolderView::getFilterPermissions() const -{ -	return mFilter->getFilterPermissions(); -} - -BOOL LLFolderView::isFilterModified() -{ -	return mFilter->isNotDefault(); -} - -void delete_selected_item(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->removeSelectedItems(); -	} -} - -void copy_selected_item(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->copy(); -	} -} - -void paste_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->paste(); -	} -} - -void open_selected_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->openSelectedItems(); -	} -} - -void properties_selected_items(void* user_data) -{ -	if(user_data) -	{ -		LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); -		fv->propertiesSelectedItems(); -	} -} diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h deleted file mode 100644 index da8bb15f8e..0000000000 --- a/indra/newview/llfolderview.h +++ /dev/null @@ -1,375 +0,0 @@ -/**  - * @file llfolderview.h - * @brief Definition of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -/** - * - * The folder view collection of classes provides an interface for - * making a 'folder view' similar to the way the a single pane file - * folder interface works. - * - */ - -#ifndef LL_LLFOLDERVIEW_H -#define LL_LLFOLDERVIEW_H - -#include "llfolderviewitem.h"	// because LLFolderView is-a LLFolderViewFolder - -#include "lluictrl.h" -#include "v4color.h" -#include "lldarray.h" -#include "stdenums.h" -#include "lldepthstack.h" -#include "lleditmenuhandler.h" -#include "llfontgl.h" -#include "llscrollcontainer.h" -#include "lltooldraganddrop.h" -#include "llviewertexture.h" - -class LLFolderViewEventListener; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLInventoryModel; -class LLPanel; -class LLLineEditor; -class LLMenuGL; -class LLUICtrl; -class LLTextBox; - -/** - * Class LLFolderViewScrollContainer - * - * A scroll container which provides the information about the height - * of currently displayed folder view contents. - * Used for updating vertical scroll bar visibility in inventory panel. - * See LLScrollContainer::calcVisibleSize(). - */ -class LLFolderViewScrollContainer : public LLScrollContainer -{ -public: -	/*virtual*/ ~LLFolderViewScrollContainer() {}; -	/*virtual*/ const LLRect getScrolledViewRect() const; - -protected: -	LLFolderViewScrollContainer(const LLScrollContainer::Params& p); -	friend class LLUICtrlFactory; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderView -// -// The LLFolderView represents the root level folder view object.  -// It manages the screen region of the folder view. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler -{ -public: -	struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> -	{ -		Mandatory<LLPanel*>	    parent_panel; -		Optional<LLUUID>        task_id; -		Optional<std::string>   title; -		Optional<bool>			use_label_suffix, -								allow_multiselect, -								show_empty_message, -								show_load_status, -								use_ellipses; - -		Params(); -	}; - -	friend class LLFolderViewScrollContainer; - -	LLFolderView(const Params&); -	virtual ~LLFolderView( void ); - -	virtual BOOL canFocusChildren() const; - -	virtual LLFolderView*	getRoot() { return this; } - -	// FolderViews default to sort by name. This will change that, -	// and resort the items if necessary. -	void setSortOrder(U32 order); -	void setFilterPermMask(PermissionMask filter_perm_mask); -	 -	typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t; -	void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } -	void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } -	 -	// filter is never null -	LLInventoryFilter* getFilter(); -	const std::string getFilterSubString(BOOL trim = FALSE); -	U32 getFilterObjectTypes() const; -	PermissionMask getFilterPermissions() const; -	// *NOTE: use getFilter()->getShowFolderState(); -	//LLInventoryFilter::EFolderShow getShowFolderState(); -	U32 getSortOrder() const; -	BOOL isFilterModified(); - -	bool getAllowMultiSelect() { return mAllowMultiSelect; } - -	// Close all folders in the view -	void closeAllFolders(); -	void openTopLevelFolders(); - -	virtual void toggleOpen() {}; -	virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse); -	virtual BOOL addFolder( LLFolderViewFolder* folder); - -	// Find width and height of this object and its children. Also -	// makes sure that this view and its children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); - -	void arrangeAll() { mArrangeGeneration++; } -	S32 getArrangeGeneration() { return mArrangeGeneration; } - -	// Apply filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); - -	// Get the last selected item -	virtual LLFolderViewItem* getCurSelectedItem( void ); - -	// Record the selected item and pass it down the hierarchy. -	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, -		BOOL take_keyboard_focus); - -	// Used by menu callbacks -	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); - -	// Called once a frame to update the selection if mSelectThisID has been set -	void updateSelection(); - -	// This method is used to toggle the selection of an item.  -	// Walks children and keeps track of selected objects. -	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - -	virtual std::set<LLUUID> getSelectionList() const; - -	// Make sure if ancestor is selected, descendents are not -	void sanitizeSelection(); -	void clearSelection(); -	void addToSelectionList(LLFolderViewItem* item); -	void removeFromSelectionList(LLFolderViewItem* item); - -	BOOL startDrag(LLToolDragAndDrop::ESource source); -	void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } -	void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } -	LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - -	// Deletion functionality - 	void removeSelectedItems(); - 	static void removeCutItems(); - -	// Open the selected item -	void openSelectedItems( void ); -	void propertiesSelectedItems( void ); - -	// Change the folder type -	void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); - -	void autoOpenItem(LLFolderViewFolder* item); -	void closeAutoOpenedFolders(); -	BOOL autoOpenTest(LLFolderViewFolder* item); - -	// Copy & paste -	virtual void	copy(); -	virtual BOOL	canCopy() const; - -	virtual void	cut(); -	virtual BOOL	canCut() const; - -	virtual void	paste(); -	virtual BOOL	canPaste() const; - -	virtual void	doDelete(); -	virtual BOOL	canDoDelete() const; - -	// Public rename functionality - can only start the process -	void startRenamingSelectedItem( void ); - -	// These functions were used when there was only one folderview, -	// and relied on that concept. This functionality is now handled -	// by the listeners and the lldraganddroptool. -	//LLFolderViewItem*	getMovingItem() { return mMovingItem; } -	//void setMovingItem( LLFolderViewItem* item ) { mMovingItem = item; } -	//void				dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); -	//void				dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); - -	// LLView functionality -	///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); -	/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); -	/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char); -	/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); -	/*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); -	/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); -	/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask ); -	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -								   EDragAndDropType cargo_type, -								   void* cargo_data, -								   EAcceptance* accept, -								   std::string& tooltip_msg); -	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); -	/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } -	virtual void draw(); -	virtual void deleteAllChildren(); - -	void scrollToShowSelection(); -	void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); -	void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } -	LLRect getVisibleRect(); - -	BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward); -	void setShowSelectionContext(BOOL show) { mShowSelectionContext = show; } -	BOOL getShowSelectionContext(); -	void setShowSingleSelection(BOOL show); -	BOOL getShowSingleSelection() { return mShowSingleSelection; } -	F32  getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } -	bool getUseEllipses() { return mUseEllipses; } - -	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); -	void removeItemID(const LLUUID& id); -	LLFolderViewItem* getItemByID(const LLUUID& id); -	LLFolderViewFolder* getFolderByID(const LLUUID& id); -	 -	bool doToSelected(LLInventoryModel* model, const LLSD& userdata); -	 -	void	doIdle();						// Real idle routine -	static void idle(void* user_data);		// static glue to doIdle() - -	BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } -	BOOL needsAutoRename() { return mNeedsAutoRename; } -	void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } -	void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } -	void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } - -	void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } - -	BOOL getDebugFilters() { return mDebugFilters; } - -	LLPanel* getParentPanel() { return mParentPanel; } -	// DEBUG only -	void dumpSelectionInformation(); - -	virtual S32	notify(const LLSD& info) ; -	 -	bool useLabelSuffix() { return mUseLabelSuffix; } -	void updateMenu(); - -private: -	void updateMenuOptions(LLMenuGL* menu); -	void updateRenamerPosition(); - -protected: -	LLScrollContainer* mScrollContainer;  // NULL if this is not a child of a scroll container. - -	void commitRename( const LLSD& data ); -	void onRenamerLost(); - -	void finishRenamingItem( void ); -	void closeRenamer( void ); - -	bool selectFirstItem(); -	bool selectLastItem(); -	 -	BOOL addNoOptions(LLMenuGL* menu) const; - -	void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response); - -protected: -	LLHandle<LLView>					mPopupMenuHandle; -	 -	typedef std::deque<LLFolderViewItem*> selected_items_t; -	selected_items_t				mSelectedItems; -	BOOL							mKeyboardSelection; -	BOOL							mAllowMultiSelect; -	BOOL							mShowEmptyMessage; -	BOOL							mShowFolderHierarchy; -	LLUUID							mSourceID; - -	// Renaming variables and methods -	LLFolderViewItem*				mRenameItem;  // The item currently being renamed -	LLLineEditor*					mRenamer; - -	BOOL							mNeedsScroll; -	BOOL							mPinningSelectedItem; -	LLRect							mScrollConstraintRect; -	BOOL							mNeedsAutoSelect; -	BOOL							mAutoSelectOverride; -	BOOL							mNeedsAutoRename; -	bool							mUseLabelSuffix; -	 -	BOOL							mDebugFilters; -	U32								mSortOrder; -	LLDepthStack<LLFolderViewFolder>	mAutoOpenItems; -	LLFolderViewFolder*				mAutoOpenCandidate; -	LLFrameTimer					mAutoOpenTimer; -	LLFrameTimer					mSearchTimer; -	std::string						mSearchString; -	LLInventoryFilter*				mFilter; -	BOOL							mShowSelectionContext; -	BOOL							mShowSingleSelection; -	LLFrameTimer					mMultiSelectionFadeTimer; -	S32								mArrangeGeneration; - -	signal_t						mSelectSignal; -	signal_t						mReshapeSignal; -	S32								mSignalSelectCallback; -	S32								mMinWidth; -	S32								mRunningHeight; -	std::map<LLUUID, LLFolderViewItem*> mItemMap; -	BOOL							mDragAndDropThisFrame; -	 -	LLUUID							mSelectThisID; // if non null, select this item -	 -	LLPanel*						mParentPanel; - -	/** -	 * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. -	 * NOTE: For now it's used only to cut LLFolderViewItem::mLabel text for Landmarks in Places Panel. -	 */ -	bool							mUseEllipses; // See EXT-719 - -	/** -	 * Contains item under mouse pointer while dragging -	 */ -	LLFolderViewItem*				mDraggingOverItem; // See EXT-719 - -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; -	 -public: -	static F32 sAutoOpenTime; -	LLTextBox*						mStatusTextBox; - -}; - -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b); -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b); - -// Flags for buildContextMenu() -const U32 SUPPRESS_OPEN_ITEM = 0x1; -const U32 FIRST_SELECTED_ITEM = 0x2; - -#endif // LL_LLFOLDERVIEW_H diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h deleted file mode 100644 index 06682dcbf1..0000000000 --- a/indra/newview/llfoldervieweventlistener.h +++ /dev/null @@ -1,103 +0,0 @@ -/**  - * @file llfoldervieweventlistener.h - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H - -#include "lldarray.h"	// *TODO: convert to std::vector -#include "llfoldertype.h" -#include "llfontgl.h"	// just for StyleFlags enum -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" - - -class LLFolderViewItem; -class LLFolderView; -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLScrollContainer; -class LLUIImage; -class LLUUID; - -// This is an abstract base class that users of the folderview classes -// would use to catch the useful events emitted from the folder -// views. -class LLFolderViewEventListener -{ -public: -	virtual ~LLFolderViewEventListener( void ) {} -	virtual const std::string& getName() const = 0; -	virtual const std::string& getDisplayName() const = 0; -	virtual const LLUUID& getUUID() const = 0; -	virtual time_t getCreationDate() const = 0;	// UTC seconds -	virtual PermissionMask getPermissionMask() const = 0; -	virtual LLFolderType::EType getPreferredType() const = 0; -	virtual LLPointer<LLUIImage> getIcon() const = 0; -	virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } -	virtual LLFontGL::StyleFlags getLabelStyle() const = 0; -	virtual std::string getLabelSuffix() const = 0; -	virtual void openItem( void ) = 0; -	virtual void closeItem( void ) = 0; -	virtual void previewItem( void ) = 0; -	virtual void selectItem(void) = 0; -	virtual void showProperties(void) = 0; -	virtual BOOL isItemRenameable() const = 0; -	virtual BOOL renameItem(const std::string& new_name) = 0; -	virtual BOOL isItemMovable( void ) const = 0;		// Can be moved to another folder -	virtual BOOL isItemRemovable( void ) const = 0;		// Can be destroyed -	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. -	virtual BOOL removeItem() = 0; -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; -	virtual void move( LLFolderViewEventListener* parent_listener ) = 0; -	virtual BOOL isItemCopyable() const = 0; -	virtual BOOL copyToClipboard() const = 0; -	virtual BOOL cutToClipboard() const = 0; -	virtual BOOL isClipboardPasteable() const = 0; -	virtual void pasteFromClipboard() = 0; -	virtual void pasteLinkFromClipboard() = 0; -	virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; -	virtual BOOL isUpToDate() const = 0; -	virtual BOOL hasChildren() const = 0; -	virtual LLInventoryType::EType getInventoryType() const = 0; -	virtual void performAction(LLInventoryModel* model, std::string action) = 0; -	virtual LLWearableType::EType getWearableType() const = 0; -	 -	// This method should be called when a drag begins. returns TRUE -	// if the drag can begin, otherwise FALSE. -	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; -	 -	// This method will be called to determine if a drop can be -	// performed, and will set drop to TRUE if a drop is -	// requested. Returns TRUE if a drop is possible/happened, -	// otherwise FALSE. -	virtual BOOL dragOrDrop(MASK mask, BOOL drop, -							EDragAndDropType cargo_type, -							void* cargo_data, -							std::string& tooltip_msg) = 0; -}; - -#endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp deleted file mode 100644 index 515e544452..0000000000 --- a/indra/newview/llfolderviewitem.cpp +++ /dev/null @@ -1,2897 +0,0 @@ -/**  -* @file llfolderviewitem.cpp -* @brief Items and folders that can appear in a hierarchical folder view -* -* $LicenseInfo:firstyear=2001&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -*  -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -*  -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -* Lesser General Public License for more details. -*  -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA -*  -* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA -* $/LicenseInfo$ -*/ -#include "llviewerprecompiledheaders.h" - -#include "llfolderviewitem.h" - -// viewer includes -#include "llfolderview.h"		// Items depend extensively on LLFolderViews -#include "llfoldervieweventlistener.h" -#include "llviewerfoldertype.h" -#include "llinventorybridge.h"	// for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llpanel.h" -#include "llviewercontrol.h"	// gSavedSettings -#include "llviewerwindow.h"		// Argh, only for setCursor() - -// linden library includes -#include "llclipboard.h" -#include "llfocusmgr.h"		// gFocusMgr -#include "lltrans.h" - -///---------------------------------------------------------------------------- -/// Class LLFolderViewItem -///---------------------------------------------------------------------------- - -static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item"); - -// statics  -std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts - -// only integers can be initialized in header -const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; -const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; - -const LLColor4U DEFAULT_WHITE(255, 255, 255); - - -//static -LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) -{ -	LLFontGL* rtn = sFonts[style]; -	if (!rtn) // grab label font with this style, lazily -	{ -		LLFontDescriptor labelfontdesc("SansSerif", "Small", style); -		rtn = LLFontGL::getFont(labelfontdesc); -		if (!rtn) -		{ -			rtn = LLFontGL::getFontDefault(); -		} -		sFonts[style] = rtn; -	} -	return rtn; -} - -//static -void LLFolderViewItem::initClass() -{ -} - -//static -void LLFolderViewItem::cleanupClass() -{ -	sFonts.clear(); -} - - -// NOTE: Optimize this, we call it a *lot* when opening a large inventory -LLFolderViewItem::Params::Params() -:	icon(), -	icon_open(), -	icon_overlay(), -	root(), -	listener(), -	folder_arrow_image("folder_arrow_image"), -	folder_indentation("folder_indentation"), -	selection_image("selection_image"), -	item_height("item_height"), -	item_top_pad("item_top_pad"), -	creation_date() -{} - -// Default constructor -LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) -:	LLView(p), -	mLabelWidth(0), -	mLabelWidthDirty(false), -	mParentFolder( NULL ), -	mIsSelected( FALSE ), -	mIsCurSelection( FALSE ), -	mSelectPending(FALSE), -	mLabelStyle( LLFontGL::NORMAL ), -	mHasVisibleChildren(FALSE), -	mIndentation(0), -	mItemHeight(p.item_height), -	mPassedFilter(FALSE), -	mLastFilterGeneration(-1), -	mStringMatchOffset(std::string::npos), -	mControlLabelRotation(0.f), -	mDragAndDropTarget(FALSE), -	mIsLoading(FALSE), -	mLabel(p.name), -	mRoot(p.root), -	mCreationDate(p.creation_date), -	mIcon(p.icon), -	mIconOpen(p.icon_open), -	mIconOverlay(p.icon_overlay), -	mListener(p.listener), -	mShowLoadStatus(false), -	mIsMouseOverTitle(false) -{ -} - -BOOL LLFolderViewItem::postBuild() -{ -	refresh(); -	return TRUE; -} - -// Destroys the object -LLFolderViewItem::~LLFolderViewItem( void ) -{ -	delete mListener; -	mListener = NULL; -} - -LLFolderView* LLFolderViewItem::getRoot() -{ -	return mRoot; -} - -// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. -BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) -{ -	LLFolderViewItem* root = this; -	while( root->mParentFolder ) -	{ -		if( root->mParentFolder == potential_ancestor ) -		{ -			return TRUE; -		} -		root = root->mParentFolder; -	} -	return FALSE; -} - -LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) -{ -	if (!mParentFolder) -	{ -		return NULL; -	} - -	LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); -	while(itemp && !itemp->getVisible()) -	{ -		LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); -		if (itemp == next_itemp)  -		{ -			// hit last item -			return itemp->getVisible() ? itemp : this; -		} -		itemp = next_itemp; -	} - -	return itemp; -} - -LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) -{ -	if (!mParentFolder) -	{ -		return NULL; -	} - -	LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); - -	// Skip over items that are invisible or are hidden from the UI. -	while(itemp && !itemp->getVisible()) -	{ -		LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); -		if (itemp == next_itemp)  -		{ -			// hit first item -			return itemp->getVisible() ? itemp : this; -		} -		itemp = next_itemp; -	} - -	return itemp; -} - -// is this item something we think we should be showing? -// for example, if we haven't gotten around to filtering it yet, then the answer is yes -// until we find out otherwise -BOOL LLFolderViewItem::potentiallyVisible() -{ -	// we haven't been checked against min required filter -	// or we have and we passed -	return potentiallyFiltered(); -} - -BOOL LLFolderViewItem::potentiallyFiltered() -{ -	return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); -} - -BOOL LLFolderViewItem::getFiltered()  -{  -	return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();  -} - -BOOL LLFolderViewItem::getFiltered(S32 filter_generation)  -{ -	return mPassedFilter && mLastFilterGeneration >= filter_generation; -} - -void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation) -{ -	mPassedFilter = filtered; -	mLastFilterGeneration = filter_generation; -} - -void LLFolderViewItem::setIcon(LLUIImagePtr icon) -{ -	mIcon = icon; -} - -// refresh information from the listener -void LLFolderViewItem::refreshFromListener() -{ -	if(mListener) -	{ -		mLabel = mListener->getDisplayName(); -		LLFolderType::EType preferred_type = mListener->getPreferredType(); - -		// *TODO: to be removed when database supports multi language. This is a -		// temporary attempt to display the inventory folder in the user locale. -		// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID -		//		it uses the same way to find localized string - -		// HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) -		// Translation of Accessories folder in Library inventory folder -		bool accessories = false; -		if(mLabel == std::string("Accessories")) -		{ -			//To ensure that Accessories folder is in Library we have to check its parent folder. -			//Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model -			LLInventoryCategory* cat = gInventory.getCategory(mListener->getUUID()); -			if(cat) -			{ -				const LLUUID& parent_folder_id = cat->getParentUUID(); -				accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); -			} -		} - -		//"Accessories" inventory category has folder type FT_NONE. So, this folder -		//can not be detected as protected with LLFolderType::lookupIsProtectedType -		if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) -		{ -			LLTrans::findString(mLabel, "InvFolder " + mLabel); -		}; - -		setToolTip(mLabel); -		setIcon(mListener->getIcon()); -		time_t creation_date = mListener->getCreationDate(); -		if ((creation_date > 0) && (mCreationDate != creation_date)) -		{ -			setCreationDate(creation_date); -			dirtyFilter(); -		} -		if (mRoot->useLabelSuffix()) -		{ -			mLabelStyle = mListener->getLabelStyle(); -			mLabelSuffix = mListener->getLabelSuffix(); -		} -	} -} - -void LLFolderViewItem::refresh() -{ -	refreshFromListener(); - -	std::string searchable_label(mLabel); -	searchable_label.append(mLabelSuffix); -	LLStringUtil::toUpper(searchable_label); - -	if (mSearchableLabel.compare(searchable_label)) -	{ -		mSearchableLabel.assign(searchable_label); -		dirtyFilter(); -		// some part of label has changed, so overall width has potentially changed, and sort order too -		if (mParentFolder) -		{ -			mParentFolder->requestSort(); -			mParentFolder->requestArrange(); -		} -	} - -	mLabelWidthDirty = true; -} - -void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ -	functor(mListener); -} - -// This function is called when items are added or view filters change. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::filterFromRoot( void ) -{ -	LLFolderViewItem* root = getRoot(); - -	root->filter(*((LLFolderView*)root)->getFilter()); -} - -// This function is called when the folder view is dirty. It's -// implemented here but called by derived classes when folding the -// views. -void LLFolderViewItem::arrangeFromRoot() -{ -	LLFolderViewItem* root = getRoot(); - -	S32 height = 0; -	S32 width = 0; -	S32 total_height = root->arrange( &width, &height, 0 ); - -	LLSD params; -	params["action"] = "size_changes"; -	params["height"] = total_height; -	getParent()->notifyParent(params); -} - -// Utility function for LLFolderView -void LLFolderViewItem::arrangeAndSet(BOOL set_selection, -									 BOOL take_keyboard_focus) -{ -	LLFolderView* root = getRoot(); -	if (getParentFolder()) -	{ -	getParentFolder()->requestArrange(); -	} -	if(set_selection) -	{ -		setSelectionFromRoot(this, TRUE, take_keyboard_focus); -		if(root) -		{ -			root->scrollToShowSelection(); -		} -	}		 -} - -// This function clears the currently selected item, and records the -// specified selected item appropriately for display and use in the -// UI. If open is TRUE, then folders are opened up along the way to -// the selection. -void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, -											BOOL openitem, -											BOOL take_keyboard_focus) -{ -	getRoot()->setSelection(selection, openitem, take_keyboard_focus); -} - -// helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) -{ -	getRoot()->changeSelection(selection, selected); -} - -std::set<LLUUID> LLFolderViewItem::getSelectionList() const -{ -	std::set<LLUUID> selection; -	return selection; -} - -EInventorySortGroup LLFolderViewItem::getSortGroup()  const -{  -	return SG_ITEM;  -} - -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) -{ -	if (!folder) -	{ -		return FALSE; -	} -	mParentFolder = folder; -	root->addItemID(getListener()->getUUID(), this); -	return folder->addItem(this); -} - - -// Finds width and height of this object and its children.  Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation) -{ -	const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); -	S32 indentation = p.folder_indentation(); -	// Only indent deeper items in hierarchy -	mIndentation = (getParentFolder()  -					&& getParentFolder()->getParentFolder() ) -		? mParentFolder->getIndentation() + indentation -		: 0; -	if (mLabelWidthDirty) -	{ -		mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT;  -		mLabelWidthDirty = false; -	} - -	*width = llmax(*width, mLabelWidth + mIndentation);  - -	// determine if we need to use ellipses to avoid horizontal scroll. EXT-719 -	bool use_ellipses = getRoot()->getUseEllipses(); -	if (use_ellipses) -	{ -		// limit to set rect to avoid horizontal scrollbar -		*width = llmin(*width, getRoot()->getRect().getWidth()); -	} -	*height = getItemHeight(); -	return *height; -} - -S32 LLFolderViewItem::getItemHeight() -{ -	return mItemHeight; -} - -void LLFolderViewItem::filter( LLInventoryFilter& filter) -{ -	const BOOL previous_passed_filter = mPassedFilter; -	const BOOL passed_filter = filter.check(this); - -	// If our visibility will change as a result of this filter, then -	// we need to be rearranged in our parent folder -	if (mParentFolder) -	{ -		if (getVisible() != passed_filter -			||	previous_passed_filter != passed_filter ) -			mParentFolder->requestArrange(); -	} - -	setFiltered(passed_filter, filter.getCurrentGeneration()); -	mStringMatchOffset = filter.getStringMatchOffset(); -	filter.decrementFilterCount(); - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -	} -} - -void LLFolderViewItem::dirtyFilter() -{ -	mLastFilterGeneration = -1; -	// bubble up dirty flag all the way to root -	if (getParentFolder()) -	{ -		getParentFolder()->setCompletedFilterGeneration(-1, TRUE); -	} -} - -// *TODO: This can be optimized a lot by simply recording that it is -// selected in the appropriate places, and assuming that set selection -// means 'deselect' for a leaf item. Do this optimization after -// multiple selection is implemented to make sure it all plays nice -// together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) -{ -	if (selection == this && !mIsSelected) -	{ -		selectItem(); -	} -	else if (mIsSelected)	// Deselect everything else. -	{ -		deselectItem(); -	} -	return mIsSelected; -} - -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ -	if (selection == this) -	{ -		if (mIsSelected) -		{ -			deselectItem(); -		} -		else -		{ -			selectItem(); -		} -		return TRUE; -	} -	return FALSE; -} - -void LLFolderViewItem::deselectItem(void) -{ -	mIsSelected = FALSE; -} - -void LLFolderViewItem::selectItem(void) -{ -	if (mIsSelected == FALSE) -	{ -		if (mListener) -		{ -			mListener->selectItem(); -		} -		mIsSelected = TRUE; -	} -} - -BOOL LLFolderViewItem::isMovable() -{ -	if( mListener ) -	{ -		return mListener->isItemMovable(); -	} -	else -	{ -		return TRUE; -	} -} - -BOOL LLFolderViewItem::isRemovable() -{ -	if( mListener ) -	{ -		return mListener->isItemRemovable(); -	} -	else -	{ -		return TRUE; -	} -} - -void LLFolderViewItem::destroyView() -{ -	if (mParentFolder) -	{ -		// removeView deletes me -		mParentFolder->removeView(this); -	} -} - -// Call through to the viewed object and return true if it can be -// removed. -//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) -BOOL LLFolderViewItem::remove() -{ -	if(!isRemovable()) -	{ -		return FALSE; -	} -	if(mListener) -	{ -		return mListener->removeItem(); -	} -	return TRUE; -} - -// Build an appropriate context menu for the item. -void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) -{ -	if(mListener) -	{ -		mListener->buildContextMenu(menu, flags); -	} -} - -void LLFolderViewItem::openItem( void ) -{ -	if( mListener ) -	{ -		mListener->openItem(); -	} -} - -void LLFolderViewItem::preview( void ) -{ -	if (mListener) -	{ -		mListener->previewItem(); -	} -} - -void LLFolderViewItem::rename(const std::string& new_name) -{ -	if( !new_name.empty() ) -	{ -		if( mListener ) -		{ -			mListener->renameItem(new_name); - -			if(mParentFolder) -			{ -				mParentFolder->requestSort(); -			} -		} -	} -} - -const std::string& LLFolderViewItem::getSearchableLabel() const -{ -	return mSearchableLabel; -} - -LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) -{ -	if (!getListener()) return NULL; -	return gInventory.getItem(getListener()->getUUID()); -} - -const std::string& LLFolderViewItem::getName( void ) const -{ -	if(mListener) -	{ -		return mListener->getName(); -	} -	return mLabel; -} - -// LLView functionality -BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ -	if(!mIsSelected) -	{ -		setSelectionFromRoot(this, FALSE); -	} -	make_ui_sound("UISndClick"); -	return TRUE; -} - -BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) -{ -	if (LLView::childrenHandleMouseDown(x, y, mask)) -	{ -		return TRUE; -	} -	 -	// No handler needed for focus lost since this class has no -	// state that depends on it. -	gFocusMgr.setMouseCapture( this ); - -	if (!mIsSelected) -	{ -		if(mask & MASK_CONTROL) -		{ -			changeSelectionFromRoot(this, !mIsSelected); -		} -		else if (mask & MASK_SHIFT) -		{ -			getParentFolder()->extendSelectionTo(this); -		} -		else -		{ -			setSelectionFromRoot(this, FALSE); -		} -		make_ui_sound("UISndClick"); -	} -	else -	{ -		mSelectPending = TRUE; -	} - -	if( isMovable() ) -	{ -		S32 screen_x; -		S32 screen_y; -		localPointToScreen(x, y, &screen_x, &screen_y ); -		LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y ); -	} -	return TRUE; -} - -BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) -{ -	mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - -	if( hasMouseCapture() && isMovable() ) -	{ -		S32 screen_x; -		S32 screen_y; -		localPointToScreen(x, y, &screen_x, &screen_y ); -		BOOL can_drag = TRUE; -		if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) ) -		{ -			LLFolderView* root = getRoot(); - -			if(root->getCurSelectedItem()) -			{ -				LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD; - -				// *TODO: push this into listener and remove -				// dependency on llagent -				if (mListener -					&& gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID())) -				{ -					src = LLToolDragAndDrop::SOURCE_AGENT; -				} -				else if (mListener -					&& gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID())) -				{ -					src = LLToolDragAndDrop::SOURCE_LIBRARY; -				} - -				can_drag = root->startDrag(src); -				if (can_drag) -				{ -					// if (mListener) mListener->startDrag(); -					// RN: when starting drag and drop, clear out last auto-open -					root->autoOpenTest(NULL); -					root->setShowSelectionContext(TRUE); - -					// Release keyboard focus, so that if stuff is dropped into the -					// world, pressing the delete key won't blow away the inventory -					// item. -					gFocusMgr.setKeyboardFocus(NULL); - -					return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask ); -				} -			} -		} - -		if (can_drag) -		{ -			gViewerWindow->setCursor(UI_CURSOR_ARROW); -		} -		else -		{ -			gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); -		} -		return TRUE; -	} -	else -	{ -		getRoot()->setShowSelectionContext(FALSE); -		gViewerWindow->setCursor(UI_CURSOR_ARROW); -		// let parent handle this then... -		return FALSE; -	} -} - - -BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ -	preview(); -	return TRUE; -} - -BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) -{ -	if (LLView::childrenHandleMouseUp(x, y, mask)) -	{ -		return TRUE; -	} -	 -	// if mouse hasn't moved since mouse down... -	if ( pointInView(x, y) && mSelectPending ) -	{ -		//...then select -		if(mask & MASK_CONTROL) -		{ -			changeSelectionFromRoot(this, !mIsSelected); -		} -		else if (mask & MASK_SHIFT) -		{ -			getParentFolder()->extendSelectionTo(this); -		} -		else -		{ -			setSelectionFromRoot(this, FALSE); -		} -	} - -	mSelectPending = FALSE; - -	if( hasMouseCapture() ) -	{ -		getRoot()->setShowSelectionContext(FALSE); -		gFocusMgr.setMouseCapture( NULL ); -	} -	return TRUE; -} - -void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) -{ -	mIsMouseOverTitle = false; -} - -BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -										 EDragAndDropType cargo_type, -										 void* cargo_data, -										 EAcceptance* accept, -										 std::string& tooltip_msg) -{ -	BOOL accepted = FALSE; -	BOOL handled = FALSE; -	if(mListener) -	{ -		accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); -		handled = accepted; -		if (accepted) -		{ -			mDragAndDropTarget = TRUE; -			*accept = ACCEPT_YES_MULTI; -		} -		else -		{ -			*accept = ACCEPT_NO; -		} -	} -	if(mParentFolder && !handled) -	{ -		// store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. -		mRoot->setDraggingOverItem(this); -		handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); -		mRoot->setDraggingOverItem(NULL); -	} -	if (handled) -	{ -		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl; -	} - -	return handled; -} - -void LLFolderViewItem::draw() -{ -	static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); -	static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); -	static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE); -	static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); -	static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); -	static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); -	static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemColor", DEFAULT_WHITE); -	static LLUIColor sLibraryColor = LLUIColorTable::instance().getColor("InventoryItemLibraryColor", DEFAULT_WHITE); -	static LLUIColor sLinkColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); -	static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); -	static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - -	const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); -	const S32 TOP_PAD = default_params.item_top_pad; -	const S32 FOCUS_LEFT = 1; -	const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - -	const BOOL in_inventory = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); -	const BOOL in_library = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); - -	//--------------------------------------------------------------------------------// -	// Draw open folder arrow -	// -	const bool up_to_date = mListener && mListener->isUpToDate(); -	const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter... -										|| (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) -	if (possibly_has_children) -	{ -		LLUIImage* arrow_image = default_params.folder_arrow_image; -		gl_draw_scaled_rotated_image( -			mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD, -			ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor); -	} - - -	//--------------------------------------------------------------------------------// -	// Draw highlight for selected items -	// -	const BOOL show_context = getRoot()->getShowSelectionContext(); -	const BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus()); // If we have keyboard focus, draw selection filled -	const S32 focus_top = getRect().getHeight(); -	const S32 focus_bottom = getRect().getHeight() - mItemHeight; -	const bool folder_open = (getRect().getHeight() > mItemHeight + 4); -	if (mIsSelected) // always render "current" item.  Only render other selected items if mShowSingleSelection is FALSE -	{ -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		LLColor4 bg_color = sHighlightBgColor; -		if (!mIsCurSelection) -		{ -			// do time-based fade of extra objects -			F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); -			if (getRoot()->getShowSingleSelection()) -			{ -				// fading out -				bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); -			} -			else -			{ -				// fading in -				bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); -			} -		} -		gl_rect_2d(FOCUS_LEFT, -				   focus_top,  -				   getRect().getWidth() - 2, -				   focus_bottom, -				   bg_color, filled); -		if (mIsCurSelection) -		{ -			gl_rect_2d(FOCUS_LEFT,  -					   focus_top,  -					   getRect().getWidth() - 2, -					   focus_bottom, -					   sFocusOutlineColor, FALSE); -		} -		if (folder_open) -		{ -			gl_rect_2d(FOCUS_LEFT, -					   focus_bottom + 1, // overlap with bottom edge of above rect -					   getRect().getWidth() - 2, -					   0, -					   sFocusOutlineColor, FALSE); -			if (show_context) -			{ -				gl_rect_2d(FOCUS_LEFT, -						   focus_bottom + 1, -						   getRect().getWidth() - 2, -						   0, -						   sHighlightBgColor, TRUE); -			} -		} -	} -	else if (mIsMouseOverTitle) -	{ -		gl_rect_2d(FOCUS_LEFT, -			focus_top,  -			getRect().getWidth() - 2, -			focus_bottom, -			sMouseOverColor, FALSE); -	} - -	//--------------------------------------------------------------------------------// -	// Draw DragNDrop highlight -	// -	if (mDragAndDropTarget) -	{ -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		gl_rect_2d(FOCUS_LEFT,  -				   focus_top,  -				   getRect().getWidth() - 2, -				   focus_bottom, -				   sHighlightBgColor, FALSE); -		if (folder_open) -		{ -			gl_rect_2d(FOCUS_LEFT, -					   focus_bottom + 1, // overlap with bottom edge of above rect -					   getRect().getWidth() - 2, -					   0, -					   sHighlightBgColor, FALSE); -		} -		mDragAndDropTarget = FALSE; -	} - -	const LLViewerInventoryItem *item = getInventoryItem(); -	const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); -	//--------------------------------------------------------------------------------// -	// Draw open icon -	// -	const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; -	if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - 	{ -		mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); -	} -	else if (mIcon) -	{ - 		mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - 	} - -	if (highlight_link) -	{ -		mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); -	} - -	//--------------------------------------------------------------------------------// -	// Exit if no label to draw -	// -	if (mLabel.empty()) -	{ -		return; -	} - -	LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; -	if (highlight_link) color = sLinkColor; -	if (in_library) color = sLibraryColor; -	 -	F32 right_x  = 0; -	F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; -	F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - -	//--------------------------------------------------------------------------------// -	// Highlight filtered text -	// -	if (getRoot()->getDebugFilters()) -	{ -		if (!getFiltered() && !possibly_has_children) -		{ -			color.mV[VALPHA] *= 0.5f; -		} -		LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ?  -			LLColor4(0.5f, 0.8f, 0.5f, 1.f) :  -			LLColor4(0.8f, 0.5f, 0.5f, 1.f); -		LLFontGL::getFontMonospace()->renderUTF8(mStatusText, 0, text_left, y, filter_color, -												 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -												 S32_MAX, S32_MAX, &right_x, FALSE ); -		text_left = right_x; -	} -	//--------------------------------------------------------------------------------// -	// Draw the actual label text -	// -	font->renderUTF8(mLabel, 0, text_left, y, color, -					 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -					 S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); - -	//--------------------------------------------------------------------------------// -	// Draw "Loading..." text -	// -	bool root_is_loading = false; -	if (in_inventory) -	{ -		root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress();  -	} -	if (in_library) -	{ -		root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); -	} -	if ((mIsLoading -		&&	mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) -			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive() -				&&	root_is_loading -				&&	mShowLoadStatus)) -	{ -		std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; -		font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, -						 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,  -						 S32_MAX, S32_MAX, &right_x, FALSE); -	} - -	//--------------------------------------------------------------------------------// -	// Draw label suffix -	// -	if (!mLabelSuffix.empty()) -	{ -		font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, -						  LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -						  S32_MAX, S32_MAX, &right_x, FALSE ); -	} - -	//--------------------------------------------------------------------------------// -	// Highlight string match -	// -	if (mStringMatchOffset != std::string::npos) -	{ -		// don't draw backgrounds for zero-length strings -		S32 filter_string_length = getRoot()->getFilterSubString().size(); -		if (filter_string_length > 0) -		{ -			std::string combined_string = mLabel + mLabelSuffix; -			S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; -			S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; -			S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); -			S32 top = getRect().getHeight() - TOP_PAD; -		 -			LLUIImage* box_image = default_params.selection_image; -			LLRect box_rect(left, top, right, bottom); -			box_image->draw(box_rect, sFilterBGColor); -			F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); -			F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; -			font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, -							  sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -							  filter_string_length, S32_MAX, &right_x, FALSE ); -		} -	} -} - - -///---------------------------------------------------------------------------- -/// Class LLFolderViewFolder -///---------------------------------------------------------------------------- - -LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):  -	LLFolderViewItem( p ),	// 0 = no create time -	mIsOpen(FALSE), -	mExpanderHighlighted(FALSE), -	mCurHeight(0.f), -	mTargetHeight(0.f), -	mAutoOpenCountdown(0.f), -	mSubtreeCreationDate(0), -	mAmTrash(LLFolderViewFolder::UNKNOWN), -	mLastArrangeGeneration( -1 ), -	mLastCalculatedWidth(0), -	mCompletedFilterGeneration(-1), -	mMostFilteredDescendantGeneration(-1), -	mNeedsSort(false), -	mPassedFolderFilter(FALSE) -{ -} - -// Destroys the object -LLFolderViewFolder::~LLFolderViewFolder( void ) -{ -	// The LLView base class takes care of object destruction. make sure that we -	// don't have mouse or keyboard focus -	gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() -} - -void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) -{ -	mPassedFolderFilter = filtered; -	mLastFilterGeneration = filter_generation; -} - -bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) -{ -	return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); -} - -// addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) -{ -	if (!folder) -	{ -		return FALSE; -	} -	mParentFolder = folder; -	root->addItemID(getListener()->getUUID(), this); -	return folder->addFolder(this); -} - -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) -{ -	// sort before laying out contents -	if (mNeedsSort) -	{ -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -		mNeedsSort = false; -	} - -	// evaluate mHasVisibleChildren -	mHasVisibleChildren = false; -	if (hasFilteredDescendants(filter_generation)) -	{ -		// We have to verify that there's at least one child that's not filtered out -		bool found = false; -		// Try the items first -		for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) -		{ -			LLFolderViewItem* itemp = (*iit); -			found = (itemp->getFiltered(filter_generation)); -			if (found) -				break; -		} -		if (!found) -		{ -			// If no item found, try the folders -			for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) -			{ -				LLFolderViewFolder* folderp = (*fit); -				found = ( folderp->getListener() -								&&	(folderp->getFiltered(filter_generation) -									 ||	(folderp->getFilteredFolder(filter_generation)  -										 && folderp->hasFilteredDescendants(filter_generation)))); -				if (found) -					break; -			} -		} - -		mHasVisibleChildren = found; -	} - -	// calculate height as a single item (without any children), and reshapes rectangle to match -	LLFolderViewItem::arrange( width, height, filter_generation ); - -	// clamp existing animated height so as to never get smaller than a single item -	mCurHeight = llmax((F32)*height, mCurHeight); - -	// initialize running height value as height of single item in case we have no children -	*height = getItemHeight(); -	F32 running_height = (F32)*height; -	F32 target_height = (F32)*height; - -	// are my children visible? -	if (needsArrange()) -	{ -		// set last arrange generation first, in case children are animating -		// and need to be arranged again -		mLastArrangeGeneration = getRoot()->getArrangeGeneration(); -		if (mIsOpen) -		{ -			// Add sizes of children -			S32 parent_item_height = getRect().getHeight(); - -			for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) -			{ -				LLFolderViewFolder* folderp = (*fit); -				if (getRoot()->getDebugFilters()) -				{ -					folderp->setVisible(TRUE); -				} -				else -				{ -					folderp->setVisible( folderp->getListener() -										&&	(folderp->getFiltered(filter_generation) -											||	(folderp->getFilteredFolder(filter_generation)  -												&& folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter -				} - -				if (folderp->getVisible()) -				{ -					S32 child_width = *width; -					S32 child_height = 0; -					S32 child_top = parent_item_height - llround(running_height); - -					target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - -					running_height += (F32)child_height; -					*width = llmax(*width, child_width); -					folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); -				} -			} -			for(items_t::iterator iit = mItems.begin(); -				iit != mItems.end(); ++iit) -			{ -				LLFolderViewItem* itemp = (*iit); -				if (getRoot()->getDebugFilters()) -				{ -					itemp->setVisible(TRUE); -				} -				else -				{ -					itemp->setVisible(itemp->getFiltered(filter_generation)); -				} - -				if (itemp->getVisible()) -				{ -					S32 child_width = *width; -					S32 child_height = 0; -					S32 child_top = parent_item_height - llround(running_height); - -					target_height += itemp->arrange( &child_width, &child_height, filter_generation ); -					// don't change width, as this item is as wide as its parent folder by construction -					itemp->reshape( itemp->getRect().getWidth(), child_height); - -					running_height += (F32)child_height; -					*width = llmax(*width, child_width); -					itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); -				} -			} -		} - -		mTargetHeight = target_height; -		// cache this width so next time we can just return it -		mLastCalculatedWidth = *width; -	} -	else -	{ -		// just use existing width -		*width = mLastCalculatedWidth; -	} - -	// animate current height towards target height -	if (llabs(mCurHeight - mTargetHeight) > 1.f) -	{ -		mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); - -		requestArrange(); - -		// hide child elements that fall out of current animated height -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			// number of pixels that bottom of folder label is from top of parent folder -			if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight()  -				> llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) -			{ -				// hide if beyond current folder height -				(*fit)->setVisible(FALSE); -			} -		} - -		for (items_t::iterator iter = mItems.begin(); -			iter != mItems.end();) -		{ -			items_t::iterator iit = iter++; -			// number of pixels that bottom of item label is from top of parent folder -			if (getRect().getHeight() - (*iit)->getRect().mBottom -				> llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP) -			{ -				(*iit)->setVisible(FALSE); -			} -		} -	} -	else -	{ -		mCurHeight = mTargetHeight; -	} - -	// don't change width as this item is already as wide as its parent folder -	reshape(getRect().getWidth(),llround(mCurHeight)); - -	// pass current height value back to parent -	*height = llround(mCurHeight); - -	return llround(mTargetHeight); -} - -BOOL LLFolderViewFolder::needsArrange() -{ -	return mLastArrangeGeneration < getRoot()->getArrangeGeneration();  -} - -void LLFolderViewFolder::requestSort() -{ -	mNeedsSort = true; -	// whenever item order changes, we need to lay things out again -	requestArrange(); -} - -void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) -{ -	//mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation); -	mCompletedFilterGeneration = generation; -	// only aggregate up if we are a lower (older) value -	if (recurse_up -		&& mParentFolder -		&& generation < mParentFolder->getCompletedFilterGeneration()) -	{ -		mParentFolder->setCompletedFilterGeneration(generation, TRUE); -	} -} - -void LLFolderViewFolder::filter( LLInventoryFilter& filter) -{ -	S32 filter_generation = filter.getCurrentGeneration(); -	// if failed to pass filter newer than must_pass_generation -	// you will automatically fail this time, so we only -	// check against items that have passed the filter -	S32 must_pass_generation = filter.getMustPassGeneration(); -	 -	bool autoopen_folders = (filter.hasFilterString()); - -	// if we have already been filtered against this generation, skip out -	if (getCompletedFilterGeneration() >= filter_generation) -	{ -		return; -	} - -	// filter folder itself -	if (getLastFilterGeneration() < filter_generation) -	{ -		if (getLastFilterGeneration() >= must_pass_generation	// folder has been compared to a valid precursor filter -			&& !mPassedFilter)									// and did not pass the filter -		{ -			// go ahead and flag this folder as done -			mLastFilterGeneration = filter_generation; -			mStringMatchOffset = std::string::npos; -		} -		else // filter self only on first pass through -		{ -			// filter against folder rules -			filterFolder(filter); -			// and then item rules -			LLFolderViewItem::filter( filter ); -		} -	} - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -		mStatusText += llformat("(%d)", mCompletedFilterGeneration); -		mStatusText += llformat("+%d", mMostFilteredDescendantGeneration); -	} - -	// all descendants have been filtered later than must pass generation -	// but none passed -	if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation)) -	{ -		// don't traverse children if we've already filtered them since must_pass_generation -		// and came back with nothing -		return; -	} - -	// we entered here with at least one filter iteration left -	// check to see if we have any more before continuing on to children -	if (filter.getFilterCount() < 0) -	{ -		return; -	} - -	// when applying a filter, matching folders get their contents downloaded first -	if (filter.isNotDefault() -		&& getFiltered(filter.getMinRequiredGeneration()) -		&&	(mListener -			&& !gInventory.isCategoryComplete(mListener->getUUID()))) -	{ -		LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID()); -	} - -	// now query children -	for (folders_t::iterator iter = mFolders.begin(); -		 iter != mFolders.end(); -		 ++iter) -	{ -		LLFolderViewFolder* folder = (*iter); -		// have we run out of iterations this frame? -		if (filter.getFilterCount() < 0) -		{ -			break; -		} - -		// mMostFilteredDescendantGeneration might have been reset -		// in which case we need to update it even for folders that -		// don't need to be filtered anymore -		if (folder->getCompletedFilterGeneration() >= filter_generation) -		{ -			// track latest generation to pass any child items -			if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) -			{ -				mMostFilteredDescendantGeneration = filter_generation; -				requestArrange(); -			} -			// just skip it, it has already been filtered -			continue; -		} - -		// update this folders filter status (and children) -		folder->filter( filter ); - -		// track latest generation to pass any child items -		if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation)) -		{ -			mMostFilteredDescendantGeneration = filter_generation; -			requestArrange(); -			if (getRoot()->needsAutoSelect() && autoopen_folders) -			{ -				folder->setOpenArrangeRecursively(TRUE); -			} -		} -	} - -	for (items_t::iterator iter = mItems.begin(); -		 iter != mItems.end(); -		 ++iter) -	{ -		LLFolderViewItem* item = (*iter); -		if (filter.getFilterCount() < 0) -		{ -			break; -		} -		if (item->getLastFilterGeneration() >= filter_generation) -		{ -			if (item->getFiltered()) -			{ -				mMostFilteredDescendantGeneration = filter_generation; -				requestArrange(); -			} -			continue; -		} - -		if (item->getLastFilterGeneration() >= must_pass_generation &&  -			!item->getFiltered(must_pass_generation)) -		{ -			// failed to pass an earlier filter that was a subset of the current one -			// go ahead and flag this item as done -			item->setFiltered(FALSE, filter_generation); -			continue; -		} - -		item->filter( filter ); - -		if (item->getFiltered(filter.getMinRequiredGeneration())) -		{ -			mMostFilteredDescendantGeneration = filter_generation; -			requestArrange(); -		} -	} - -	// if we didn't use all filter iterations -	// that means we filtered all of our descendants -	// instead of exhausting the filter count for this frame -	if (filter.getFilterCount() > 0) -	{ -		// flag this folder as having completed filter pass for all descendants -		setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/); -	} -} - -void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter) -{ -	const BOOL previous_passed_filter = mPassedFolderFilter; -	const BOOL passed_filter = filter.checkFolder(this); - -	// If our visibility will change as a result of this filter, then -	// we need to be rearranged in our parent folder -	if (mParentFolder) -	{ -		if (getVisible() != passed_filter -			|| previous_passed_filter != passed_filter ) -		{ -			mParentFolder->requestArrange(); -		} -	} - -	setFilteredFolder(passed_filter, filter.getCurrentGeneration()); -	filter.decrementFilterCount(); - -	if (getRoot()->getDebugFilters()) -	{ -		mStatusText = llformat("%d", mLastFilterGeneration); -	} -} - -void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation) -{ -	// if this folder is now filtered, but wasn't before -	// (it just passed) -	if (filtered && !mPassedFilter) -	{ -		// reset current height, because last time we drew it -		// it might have had more visible items than now -		mCurHeight = 0.f; -	} - -	LLFolderViewItem::setFiltered(filtered, filter_generation); -} - -void LLFolderViewFolder::dirtyFilter() -{ -	// we're a folder, so invalidate our completed generation -	setCompletedFilterGeneration(-1, FALSE); -	LLFolderViewItem::dirtyFilter(); -} - -BOOL LLFolderViewFolder::getFiltered()  -{  -	return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration())  -		&& LLFolderViewItem::getFiltered();  -} - -BOOL LLFolderViewFolder::getFiltered(S32 filter_generation)  -{ -	return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation); -} - -BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) -{  -	return mMostFilteredDescendantGeneration >= filter_generation;  -} - - -BOOL LLFolderViewFolder::hasFilteredDescendants() -{ -	return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); -} - -// Passes selection information on to children and record selection -// information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, -                                      BOOL take_keyboard_focus) -{ -	BOOL rv = FALSE; -	if (selection == this) -	{ -		if (!isSelected()) -		{ -			selectItem(); -		} -		rv = TRUE; -	} -	else -	{ -		if (isSelected()) -		{ -			deselectItem(); -		} -		rv = FALSE; -	} -	BOOL child_selected = FALSE; - -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) -		{ -			rv = TRUE; -			child_selected = TRUE; -		} -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) -		{ -			rv = TRUE; -			child_selected = TRUE; -		} -	} -	if(openitem && child_selected) -	{ -		setOpenArrangeRecursively(TRUE); -	} -	return rv; -} - -// This method is used to change the selection of an item. -// Recursively traverse all children; if 'selection' is 'this' then change -// the select status if necessary. -// Returns TRUE if the selection state of this folder, or of a child, was changed. -BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) -{ -	BOOL rv = FALSE; -	if(selection == this) -	{ -		if (isSelected() != selected) -		{ -			rv = TRUE; -			if (selected) -			{ -				selectItem(); -			} -			else -			{ -				deselectItem(); -			} -		} -	} - -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		if((*fit)->changeSelection(selection, selected)) -		{ -			rv = TRUE; -		} -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		if((*iit)->changeSelection(selection, selected)) -		{ -			rv = TRUE; -		} -	} -	return rv; -} - -LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) -{ -	if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; - -	std::deque<LLFolderViewFolder*> item_a_ancestors; - -	LLFolderViewFolder* parent = item_a->getParentFolder(); -	while(parent) -	{ -		item_a_ancestors.push_back(parent); -		parent = parent->getParentFolder(); -	} - -	std::deque<LLFolderViewFolder*> item_b_ancestors; -	 -	parent = item_b->getParentFolder(); -	while(parent) -	{ -		item_b_ancestors.push_back(parent); -		parent = parent->getParentFolder(); -	} - -	LLFolderViewFolder* common_ancestor = item_a->getRoot(); - -	while(item_a_ancestors.size() > item_b_ancestors.size()) -	{ -		item_a = item_a_ancestors.front(); -		item_a_ancestors.pop_front(); -	} - -	while(item_b_ancestors.size() > item_a_ancestors.size()) -	{ -		item_b = item_b_ancestors.front(); -		item_b_ancestors.pop_front(); -	} - -	while(item_a_ancestors.size()) -	{ -		common_ancestor = item_a_ancestors.front(); - -		if (item_a_ancestors.front() == item_b_ancestors.front()) -		{ -			// which came first, sibling a or sibling b? -			for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); -				it != end_it; -				++it) -			{ -				LLFolderViewItem* item = *it; - -				if (item == item_a) -				{ -					reverse = false; -					return common_ancestor; -				} -				if (item == item_b) -				{ -					reverse = true; -					return common_ancestor; -				} -			} - -			for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); -				it != end_it; -				++it) -			{ -				LLFolderViewItem* item = *it; - -				if (item == item_a) -				{ -					reverse = false; -					return common_ancestor; -				} -				if (item == item_b) -				{ -					reverse = true; -					return common_ancestor; -				} -			} -			break; -		} - -		item_a = item_a_ancestors.front(); -		item_a_ancestors.pop_front(); -		item_b = item_b_ancestors.front(); -		item_b_ancestors.pop_front(); -	} - -	return NULL; -} - -void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items) -{ -	bool selecting = start == NULL; -	if (reverse) -	{ -		for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); -			it != end_it; -			++it) -		{ -			if (*it == end) -			{ -				return; -			} -			if (selecting) -			{ -				items.push_back(*it); -			} - -			if (*it == start) -			{ -				selecting = true; -			} -		} -		for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); -			it != end_it; -			++it) -		{ -			if (*it == end) -			{ -				return; -			} - -			if (selecting) -			{ -				items.push_back(*it); -			} - -			if (*it == start) -			{ -				selecting = true; -			} -		} -	} -	else -	{ -		for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); -			it != end_it; -			++it) -		{ -			if (*it == end) -			{ -				return; -			} - -			if (selecting) -			{ -				items.push_back(*it); -			} - -			if (*it == start) -			{ -				selecting = true; -			} -		} -		for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); -			it != end_it; -			++it) -		{ -			if (*it == end) -			{ -				return; -			} - -			if (selecting) -			{ -				items.push_back(*it); -			} - -			if (*it == start) -			{ -				selecting = true; -			} -		} -	} -} - -void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) -{ -	if (getRoot()->getAllowMultiSelect() == FALSE) return; - -	LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); -	if (cur_selected_item == NULL) -	{ -		cur_selected_item = new_selection; -	} - - -	bool reverse = false; -	LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); -	if (!common_ancestor) return; - -	LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; -	LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); - -	std::vector<LLFolderViewItem*> items_to_select_forward; - -	while(cur_folder != common_ancestor) -	{ -		cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); -			 -		last_selected_item_from_cur = cur_folder; -		cur_folder = cur_folder->getParentFolder(); -	} - -	std::vector<LLFolderViewItem*> items_to_select_reverse; - -	LLFolderViewItem* last_selected_item_from_new = new_selection; -	cur_folder = new_selection->getParentFolder(); -	while(cur_folder != common_ancestor) -	{ -		cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); - -		last_selected_item_from_new = cur_folder; -		cur_folder = cur_folder->getParentFolder(); -	} - -	common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); - -	for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); -		it != end_it; -		++it) -	{ -		items_to_select_forward.push_back(*it); -	} - -	LLFolderView* root = getRoot(); - -	for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); -		it != end_it; -		++it) -	{ -		LLFolderViewItem* item = *it; -		if (item->isSelected()) -		{ -			root->removeFromSelectionList(item); -		} -		else -		{ -			item->selectItem(); -		} -		root->addToSelectionList(item); -	} - -	if (new_selection->isSelected()) -	{ -		root->removeFromSelectionList(new_selection); -	} -	else -	{ -		new_selection->selectItem(); -	} -	root->addToSelectionList(new_selection); -} - - -void LLFolderViewFolder::destroyView() -{ -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		LLFolderViewItem* item = (*iit); -		getRoot()->removeItemID(item->getListener()->getUUID()); -	} - -	std::for_each(mItems.begin(), mItems.end(), DeletePointer()); -	mItems.clear(); - -	while (!mFolders.empty()) -	{ -		LLFolderViewFolder *folderp = mFolders.back(); -		folderp->destroyView(); // removes entry from mFolders -	} - -	//deleteAllChildren(); - -	if (mParentFolder) -	{ -		mParentFolder->removeView(this); -	} -} - -// remove the specified item (and any children) if possible. Return -// TRUE if the item was deleted. -BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) -{ -	if(item->remove()) -	{ -		return TRUE; -	} -	return FALSE; -} - -// simply remove the view (and any children) Don't bother telling the -// listeners. -void LLFolderViewFolder::removeView(LLFolderViewItem* item) -{ -	if (!item || item->getParentFolder() != this) -	{ -		return; -	} -	// deselect without traversing hierarchy -	if (item->isSelected()) -	{ -		item->deselectItem(); -	} -	getRoot()->removeFromSelectionList(item); -	extractItem(item); -	delete item; -} - -// extractItem() removes the specified item from the folder, but -// doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) -{ -	items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); -	if(it == mItems.end()) -	{ -		// This is an evil downcast. However, it's only doing -		// pointer comparison to find if (which it should be ) the -		// item is in the container, so it's pretty safe. -		LLFolderViewFolder* f = static_cast<LLFolderViewFolder*>(item); -		folders_t::iterator ft; -		ft = std::find(mFolders.begin(), mFolders.end(), f); -		if (ft != mFolders.end()) -		{ -			mFolders.erase(ft); -		} -	} -	else -	{ -		mItems.erase(it); -	} -	//item has been removed, need to update filter -	dirtyFilter(); -	//because an item is going away regardless of filter status, force rearrange -	requestArrange(); -	getRoot()->removeItemID(item->getListener()->getUUID()); -	removeChild(item); -} - -bool LLFolderViewFolder::isTrash() const -{ -	if (mAmTrash == LLFolderViewFolder::UNKNOWN) -	{ -		mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; -	} -	return mAmTrash == LLFolderViewFolder::TRASH; -} - -void LLFolderViewFolder::sortBy(U32 order) -{ -	if (!mSortFunction.updateSort(order)) -	{ -		// No changes. -		return; -	} - -	// Propagate this change to sub folders -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->sortBy(order); -	} - -	// Don't sort the topmost folders (My Inventory and Library) -	if (mListener->getUUID().notNull()) -	{ -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -	} - -	if (order & LLInventoryFilter::SO_DATE) -	{ -		time_t latest = 0; - -		if (!mItems.empty()) -		{ -			LLFolderViewItem* item = *(mItems.begin()); -			latest = item->getCreationDate(); -		} - -		if (!mFolders.empty()) -		{ -			LLFolderViewFolder* folder = *(mFolders.begin()); -			if (folder->getCreationDate() > latest) -			{ -				latest = folder->getCreationDate(); -			} -		} -		mSubtreeCreationDate = latest; -	} -} - -void LLFolderViewFolder::setItemSortOrder(U32 ordering) -{ -	if (mSortFunction.updateSort(ordering)) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			(*fit)->setItemSortOrder(ordering); -		} - -		mFolders.sort(mSortFunction); -		mItems.sort(mSortFunction); -	} -} - -EInventorySortGroup LLFolderViewFolder::getSortGroup() const -{ -	if (isTrash()) -	{ -		return SG_TRASH_FOLDER; -	} - -	if( mListener ) -	{ -		if(LLFolderType::lookupIsProtectedType(mListener->getPreferredType())) -		{ -			return SG_SYSTEM_FOLDER; -		} -	} - -	return SG_NORMAL_FOLDER; -} - -BOOL LLFolderViewFolder::isMovable() -{ -	if( mListener ) -	{ -		if( !(mListener->isItemMovable()) ) -		{ -			return FALSE; -		} - -		for (items_t::iterator iter = mItems.begin(); -			iter != mItems.end();) -		{ -			items_t::iterator iit = iter++; -			if(!(*iit)->isMovable()) -			{ -				return FALSE; -			} -		} - -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			if(!(*fit)->isMovable()) -			{ -				return FALSE; -			} -		} -	} -	return TRUE; -} - - -BOOL LLFolderViewFolder::isRemovable() -{ -	if( mListener ) -	{ -		if( !(mListener->isItemRemovable()) ) -		{ -			return FALSE; -		} - -		for (items_t::iterator iter = mItems.begin(); -			iter != mItems.end();) -		{ -			items_t::iterator iit = iter++; -			if(!(*iit)->isRemovable()) -			{ -				return FALSE; -			} -		} - -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			if(!(*fit)->isRemovable()) -			{ -				return FALSE; -			} -		} -	} -	return TRUE; -} - -// this is an internal method used for adding items to folders.  -BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) -{ -	mItems.push_back(item); -	 -	item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); -	item->setVisible(FALSE); -	 -	addChild(item); -	 -	item->dirtyFilter(); - -	// Update the folder creation date if the child is newer than our current date -	setCreationDate(llmax<time_t>(mCreationDate, item->getCreationDate())); - -	// Handle sorting -	requestArrange(); -	requestSort(); - -	// Traverse parent folders and update creation date and resort, if necessary -	LLFolderViewFolder* parentp = getParentFolder(); -	while (parentp) -	{ -		// Update the folder creation date if the child is newer than our current date -		parentp->setCreationDate(llmax<time_t>(parentp->mCreationDate, item->getCreationDate())); - -		if (parentp->mSortFunction.isByDate()) -		{ -			// parent folder doesn't have a time stamp yet, so get it from us -			parentp->requestSort(); -		} - -		parentp = parentp->getParentFolder(); -	} - -	return TRUE; -} - -// this is an internal method used for adding items to folders.  -BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -{ -	mFolders.push_back(folder); -	folder->setOrigin(0, 0); -	folder->reshape(getRect().getWidth(), 0); -	folder->setVisible(FALSE); -	addChild( folder ); -	folder->dirtyFilter(); -	// rearrange all descendants too, as our indentation level might have changed -	folder->requestArrange(TRUE); -	requestSort(); -	LLFolderViewFolder* parentp = getParentFolder(); -	while (parentp && !parentp->mSortFunction.isByDate()) -	{ -		// parent folder doesn't have a time stamp yet, so get it from us -		parentp->requestSort(); -		parentp = parentp->getParentFolder(); -	} -	return TRUE; -} - -void LLFolderViewFolder::requestArrange(BOOL include_descendants)	 -{  -	mLastArrangeGeneration = -1;  -	// flag all items up to root -	if (mParentFolder) -	{ -		mParentFolder->requestArrange(); -	} - -	if (include_descendants) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end(); -			++iter) -		{ -			(*iter)->requestArrange(TRUE); -		} -	} -} - -void LLFolderViewFolder::toggleOpen() -{ -	setOpen(!mIsOpen); -} - -// Force a folder open or closed -void LLFolderViewFolder::setOpen(BOOL openitem) -{ -	setOpenArrangeRecursively(openitem); -} - -void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ -	BOOL was_open = mIsOpen; -	mIsOpen = openitem; -	if (mListener) -	{ -		if(!was_open && openitem) -		{ -			mListener->openItem(); -		} -		else if(was_open && !openitem) -		{ -			mListener->closeItem(); -		} -	} - -	if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) -	{ -		for (folders_t::iterator iter = mFolders.begin(); -			iter != mFolders.end();) -		{ -			folders_t::iterator fit = iter++; -			(*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN);		/* Flawfinder: ignore */ -		} -	} -	if (mParentFolder -		&&	(recurse == RECURSE_UP -			|| recurse == RECURSE_UP_DOWN)) -	{ -		mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); -	} - -	if (was_open != mIsOpen) -	{ -		requestArrange(); -	} -} - -BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, -													BOOL drop, -													EDragAndDropType c_type, -													void* cargo_data, -													EAcceptance* accept, -													std::string& tooltip_msg) -{ -	BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); -	if (accepted)  -	{ -		mDragAndDropTarget = TRUE; -		*accept = ACCEPT_YES_MULTI; -	} -	else  -	{ -		*accept = ACCEPT_NO; -	} - -	// drag and drop to child item, so clear pending auto-opens -	getRoot()->autoOpenTest(NULL); - -	return TRUE; -} - -void LLFolderViewFolder::openItem( void ) -{ -	toggleOpen(); -} - -void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) -{ -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		functor.doItem((*fit)); -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		functor.doItem((*iit)); -	} -} - -void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) -{ -	functor.doFolder(this); - -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->applyFunctorRecursively(functor); -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		functor.doItem((*iit)); -	} -} - -void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ -	functor(mListener); -	for (folders_t::iterator iter = mFolders.begin(); -		iter != mFolders.end();) -	{ -		folders_t::iterator fit = iter++; -		(*fit)->applyListenerFunctorRecursively(functor); -	} -	for (items_t::iterator iter = mItems.begin(); -		iter != mItems.end();) -	{ -		items_t::iterator iit = iter++; -		(*iit)->applyListenerFunctorRecursively(functor); -	} -} - -// LLView functionality -BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, -										   BOOL drop, -										   EDragAndDropType cargo_type, -										   void* cargo_data, -										   EAcceptance* accept, -										   std::string& tooltip_msg) -{ -	BOOL handled = FALSE; - -	if (mIsOpen) -	{ -		handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); -	} - -	if (!handled) -	{ -		handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - -		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; -	} - -	return TRUE; -} - -BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, -													   BOOL drop, -													   EDragAndDropType cargo_type, -													   void* cargo_data, -													   EAcceptance* accept, -													   std::string& tooltip_msg) -{ -	BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); -	 -	if (accepted)  -	{ -		mDragAndDropTarget = TRUE; -		*accept = ACCEPT_YES_MULTI; -	} -	else  -	{ -		*accept = ACCEPT_NO; -	} -	 -	if (!drop && accepted) -	{ -		getRoot()->autoOpenTest(this); -	} -	 -	return TRUE; -} - - -BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ -	BOOL handled = FALSE; -	// fetch contents of this folder, as context menu can depend on contents -	// still, user would have to open context menu again to see the changes -	gInventory.fetchDescendentsOf(mListener->getUUID()); - -	if( mIsOpen ) -	{ -		handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; -	} -	if (!handled) -	{ -		handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); -	} -	return handled; -} - - -BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) -{ -	mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - -	BOOL handled = LLView::handleHover(x, y, mask); - -	if (!handled) -	{ -		// this doesn't do child processing -		handled = LLFolderViewItem::handleHover(x, y, mask); -	} - -	return handled; -} - -BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) -{ -	BOOL handled = FALSE; -	if( mIsOpen ) -	{ -		handled = childrenHandleMouseDown(x,y,mask) != NULL; -	} -	if( !handled ) -	{ -		if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) -		{ -			toggleOpen(); -			handled = TRUE; -		} -		else -		{ -			// do normal selection logic -			handled = LLFolderViewItem::handleMouseDown(x, y, mask); -		} -	} - -	return handled; -} - -BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ -	/* Disable outfit double click to wear -	const LLUUID &cat_uuid = getListener()->getUUID(); -	const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); -	if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) -	{ -		getListener()->performAction(NULL, NULL,"replaceoutfit"); -		return TRUE; -	} -	*/ - -	BOOL handled = FALSE; -	if( mIsOpen ) -	{ -		handled = childrenHandleDoubleClick( x, y, mask ) != NULL; -	} -	if( !handled ) -	{ -		if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD) -		{ -			// don't select when user double-clicks plus sign -			// so as not to contradict single-click behavior -			toggleOpen(); -		} -		else -		{ -			setSelectionFromRoot(this, FALSE); -			toggleOpen(); -		} -		handled = TRUE; -	} -	return handled; -} - -void LLFolderViewFolder::draw() -{ -	if (mAutoOpenCountdown != 0.f) -	{ -		mControlLabelRotation = mAutoOpenCountdown * -90.f; -	} -	else if (mIsOpen) -	{ -		mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); -	} -	else -	{ -		mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); -	} - -	bool possibly_has_children = false; -	bool up_to_date = mListener && mListener->isUpToDate(); -	if(!up_to_date -		&& mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) -	{ -		possibly_has_children = true; -	} - - -	BOOL loading = (mIsOpen -					&& possibly_has_children -					&& !up_to_date ); - -	if ( loading && !mIsLoading ) -	{ -		// Measure how long we've been in the loading state -		mTimeSinceRequestStart.reset(); -	} - -	mIsLoading = loading; - -	LLFolderViewItem::draw(); - -	// draw children if root folder, or any other folder that is open or animating to closed state -	if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) -	{ -		LLView::draw(); -	} - -	mExpanderHighlighted = FALSE; -} - -time_t LLFolderViewFolder::getCreationDate() const -{ -	return llmax<time_t>(mCreationDate, mSubtreeCreationDate); -} - - -BOOL	LLFolderViewFolder::potentiallyVisible() -{ -	// folder should be visible by it's own filter status -	return LLFolderViewItem::potentiallyVisible() 	 -		// or one or more of its descendants have passed the minimum filter requirement -		|| hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) -		// or not all of its descendants have been checked against minimum filter requirement -		|| getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration();  -} - -// this does prefix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) -{ -	BOOL found_item = FALSE; - -	LLFolderViewItem* result = NULL; -	// when not starting from a given item, start at beginning -	if(item == NULL) -	{ -		found_item = TRUE; -	} - -	// find current item among children -	folders_t::iterator fit = mFolders.begin(); -	folders_t::iterator fend = mFolders.end(); - -	items_t::iterator iit = mItems.begin(); -	items_t::iterator iend = mItems.end(); - -	// if not trivially starting at the beginning, we have to find the current item -	if (!found_item) -	{ -		// first, look among folders, since they are always above items -		for(; fit != fend; ++fit) -		{ -			if(item == (*fit)) -			{ -				found_item = TRUE; -				// if we are on downwards traversal -				if (include_children && (*fit)->isOpen()) -				{ -					// look for first descendant -					return (*fit)->getNextFromChild(NULL, TRUE); -				} -				// otherwise advance to next folder -				++fit; -				include_children = TRUE; -				break; -			} -		} - -		// didn't find in folders?  Check items... -		if (!found_item) -		{ -			for(; iit != iend; ++iit) -			{ -				if(item == (*iit)) -				{ -					found_item = TRUE; -					// point to next item -					++iit; -					break; -				} -			} -		} -	} - -	if (!found_item) -	{ -		// you should never call this method with an item that isn't a child -		// so we should always find something -		llassert(FALSE); -		return NULL; -	} - -	// at this point, either iit or fit point to a candidate "next" item -	// if both are out of range, we need to punt up to our parent - -	// now, starting from found folder, continue through folders -	// searching for next visible folder -	while(fit != fend && !(*fit)->getVisible()) -	{ -		// turn on downwards traversal for next folder -		++fit; -	}  - -	if (fit != fend) -	{ -		result = (*fit); -	} -	else -	{ -		// otherwise, scan for next visible item -		while(iit != iend && !(*iit)->getVisible()) -		{ -			++iit; -		}  - -		// check to see if we have a valid item -		if (iit != iend) -		{ -			result = (*iit); -		} -	} - -	if( !result && mParentFolder ) -	{ -		// If there are no siblings or children to go to, recurse up one level in the tree -		// and skip children for this folder, as we've already discounted them -		result = mParentFolder->getNextFromChild(this, FALSE); -	} - -	return result; -} - -// this does postfix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) -{ -	BOOL found_item = FALSE; - -	LLFolderViewItem* result = NULL; -	// when not starting from a given item, start at end -	if(item == NULL) -	{ -		found_item = TRUE; -	} - -	// find current item among children -	folders_t::reverse_iterator fit = mFolders.rbegin(); -	folders_t::reverse_iterator fend = mFolders.rend(); - -	items_t::reverse_iterator iit = mItems.rbegin(); -	items_t::reverse_iterator iend = mItems.rend(); - -	// if not trivially starting at the end, we have to find the current item -	if (!found_item) -	{ -		// first, look among items, since they are always below the folders -		for(; iit != iend; ++iit) -		{ -			if(item == (*iit)) -			{ -				found_item = TRUE; -				// point to next item -				++iit; -				break; -			} -		} - -		// didn't find in items?  Check folders... -		if (!found_item) -		{ -			for(; fit != fend; ++fit) -			{ -				if(item == (*fit)) -				{ -					found_item = TRUE; -					// point to next folder -					++fit; -					break; -				} -			} -		} -	} - -	if (!found_item) -	{ -		// you should never call this method with an item that isn't a child -		// so we should always find something -		llassert(FALSE); -		return NULL; -	} - -	// at this point, either iit or fit point to a candidate "next" item -	// if both are out of range, we need to punt up to our parent - -	// now, starting from found item, continue through items -	// searching for next visible item -	while(iit != iend && !(*iit)->getVisible()) -	{ -		++iit; -	}  - -	if (iit != iend) -	{ -		// we found an appropriate item -		result = (*iit); -	} -	else -	{ -		// otherwise, scan for next visible folder -		while(fit != fend && !(*fit)->getVisible()) -		{ -			++fit; -		}  - -		// check to see if we have a valid folder -		if (fit != fend) -		{ -			// try selecting child element of this folder -			if ((*fit)->isOpen()) -			{ -				result = (*fit)->getPreviousFromChild(NULL); -			} -			else -			{ -				result = (*fit); -			} -		} -	} - -	if( !result ) -	{ -		// If there are no siblings or children to go to, recurse up one level in the tree -		// which gets back to this folder, which will only be visited if it is a valid, visible item -		result = this; -	} - -	return result; -} - - -bool LLInventorySort::updateSort(U32 order) -{ -	if (order != mSortOrder) -	{ -		mSortOrder = order; -		mByDate = (order & LLInventoryFilter::SO_DATE); -		mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); -		mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); -		return true; -	} -	return false; -} - -bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) -{ -	// ignore sort order for landmarks in the Favorites folder. -	// they should be always sorted as in Favorites bar. See EXT-719 -	if (a->getSortGroup() == SG_ITEM -		&& b->getSortGroup() == SG_ITEM -		&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK -		&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) -	{ - -		static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - -		LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); -		LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); - -		if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) -		{ -			// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem -			// or to LLInvFVBridge -			LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a->getListener()))->getItem(); -			LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b->getListener()))->getItem(); -			if (!aitem || !bitem) -				return false; -			S32 a_sort = aitem->getSortField(); -			S32 b_sort = bitem->getSortField(); -			return a_sort < b_sort; -		} -	} - -	// We sort by name if we aren't sorting by date -	// OR if these are folders and we are sorting folders by name. -	bool by_name = (!mByDate  -		|| (mFoldersByName  -		&& (a->getSortGroup() != SG_ITEM))); - -	if (a->getSortGroup() != b->getSortGroup()) -	{ -		if (mSystemToTop) -		{ -			// Group order is System Folders, Trash, Normal Folders, Items -			return (a->getSortGroup() < b->getSortGroup()); -		} -		else if (mByDate) -		{ -			// Trash needs to go to the bottom if we are sorting by date -			if ( (a->getSortGroup() == SG_TRASH_FOLDER) -				|| (b->getSortGroup() == SG_TRASH_FOLDER)) -			{ -				return (b->getSortGroup() == SG_TRASH_FOLDER); -			} -		} -	} - -	if (by_name) -	{ -		S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); -		if (0 == compare) -		{ -			return (a->getCreationDate() > b->getCreationDate()); -		} -		else -		{ -			return (compare < 0); -		} -	} -	else -	{ -		// BUG: This is very very slow.  The getCreationDate() is log n in number -		// of inventory items. -		time_t first_create = a->getCreationDate(); -		time_t second_create = b->getCreationDate(); -		if (first_create == second_create) -		{ -			return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); -		} -		else -		{ -			return (first_create > second_create); -		} -	} -} diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h deleted file mode 100644 index 3c7592046a..0000000000 --- a/indra/newview/llfolderviewitem.h +++ /dev/null @@ -1,576 +0,0 @@ -/**  -* @file llfolderviewitem.h -* @brief Items and folders that can appear in a hierarchical folder view -* -* $LicenseInfo:firstyear=2001&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2010, Linden Research, Inc. -*  -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -*  -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -* Lesser General Public License for more details. -*  -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA -*  -* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA -* $/LicenseInfo$ -*/ -#ifndef LLFOLDERVIEWITEM_H -#define LLFOLDERVIEWITEM_H - -#include "llview.h" -#include "lldarray.h"  // *TODO: Eliminate, forward declare -#include "lluiimage.h" - -class LLFontGL; -class LLFolderView; -class LLFolderViewEventListener; -class LLFolderViewFolder; -class LLFolderViewFunctor; -class LLFolderViewItem; -class LLFolderViewListenerFunctor; -class LLInventoryFilter; -class LLMenuGL; -class LLUIImage; -class LLViewerInventoryItem; - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{  -	SG_SYSTEM_FOLDER,  -	SG_TRASH_FOLDER,  -	SG_NORMAL_FOLDER,  -	SG_ITEM  -}; - -// *TODO: do we really need one sort object per folder? -// can we just have one of these per LLFolderView ? -class LLInventorySort -{ -public: -	LLInventorySort()  -		: mSortOrder(0), -		mByDate(false), -		mSystemToTop(false), -		mFoldersByName(false) { } - -	// Returns true if order has changed -	bool updateSort(U32 order); -	U32 getSort() { return mSortOrder; } -	bool isByDate() { return mByDate; } - -	bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); -private: -	U32  mSortOrder; -	bool mByDate; -	bool mSystemToTop; -	bool mFoldersByName; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewItem -// -// An instance of this class represents a single item in a folder view -// such as an inventory item or a file. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewItem : public LLView -{ -public: -	static void initClass(); -	static void cleanupClass(); - -	struct Params : public LLInitParam::Block<Params, LLView::Params> -	{ -		Optional<LLUIImage*>					icon; -		Optional<LLUIImage*>					icon_open;  // used for folders -		Optional<LLUIImage*>					icon_overlay;  // for links -		Optional<LLFolderView*>					root; -		Mandatory<LLFolderViewEventListener*>	listener; - -		Optional<LLUIImage*>					folder_arrow_image; -		Optional<S32>							folder_indentation; // pixels -		Optional<LLUIImage*>					selection_image; -		Optional<S32>							item_height; // pixels -		Optional<S32>							item_top_pad; // pixels - -		Optional<S32>							creation_date; //UTC seconds - -		Params(); -	}; - -	// layout constants -	static const S32 LEFT_PAD = 5; -	// LEFT_INDENTATION is set via folder_indentation above -	static const S32 ICON_PAD = 2; -	static const S32 ICON_WIDTH = 16; -	static const S32 TEXT_PAD = 1; -	static const S32 TEXT_PAD_RIGHT = 4; -	static const S32 ARROW_SIZE = 12; -	static const S32 MAX_FOLDER_ITEM_OVERLAP = 2; -	// animation parameters -	static const F32 FOLDER_CLOSE_TIME_CONSTANT; -	static const F32 FOLDER_OPEN_TIME_CONSTANT; - -	// Mostly for debugging printout purposes. -	const std::string& getSearchableLabel() { return mSearchableLabel; } -	 -	BOOL isLoading() const { return mIsLoading; } - -private: -	BOOL						mIsSelected; - -protected: -	friend class LLUICtrlFactory; -	friend class LLFolderViewEventListener; - -	LLFolderViewItem(const Params& p); - -	std::string					mLabel; -	std::string					mSearchableLabel; -	S32							mLabelWidth; -	bool						mLabelWidthDirty; -	time_t						mCreationDate; -	LLFolderViewFolder*			mParentFolder; -	LLFolderViewEventListener*	mListener; -	BOOL						mIsCurSelection; -	BOOL						mSelectPending; -	LLFontGL::StyleFlags		mLabelStyle; -	std::string					mLabelSuffix; -	LLUIImagePtr				mIcon; -	std::string					mStatusText; -	LLUIImagePtr				mIconOpen; -	LLUIImagePtr				mIconOverlay; -	BOOL						mHasVisibleChildren; -	S32							mIndentation; -	S32							mItemHeight; -	BOOL						mPassedFilter; -	S32							mLastFilterGeneration; -	std::string::size_type		mStringMatchOffset; -	F32							mControlLabelRotation; -	LLFolderView*				mRoot; -	BOOL						mDragAndDropTarget; -	BOOL                        mIsLoading; -	LLTimer                     mTimeSinceRequestStart; -	bool						mShowLoadStatus; -	bool						mIsMouseOverTitle; - -	// helper function to change the selection from the root. -	void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); - -	// this is an internal method used for adding items to folders. A -	// no-op at this level, but reimplemented in derived classes. -	virtual BOOL addItem(LLFolderViewItem*) { return FALSE; } -	virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; } - -	static LLFontGL* getLabelFontForStyle(U8 style); - -	virtual void setCreationDate(time_t creation_date_utc)	{ mCreationDate = creation_date_utc; } - -public: -	BOOL postBuild(); - -	// This function clears the currently selected item, and records -	// the specified selected item appropriately for display and use -	// in the UI. If open is TRUE, then folders are opened up along -	// the way to the selection. -	void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem, -		BOOL take_keyboard_focus = TRUE); - -	// This function is called when the folder view is dirty. It's -	// implemented here but called by derived classes when folding the -	// views. -	void arrangeFromRoot(); -	void filterFromRoot( void ); -	 -	void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus); - -	virtual ~LLFolderViewItem( void ); - -	// addToFolder() returns TRUE if it succeeds. FALSE otherwise -	enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; -	virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - -	virtual EInventorySortGroup getSortGroup() const; - -	// Finds width and height of this object and it's children.  Also -	// makes sure that this view and it's children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); -	virtual S32 getItemHeight(); - -	// applies filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); - -	// updates filter serial number and optionally propagated value up to root -	S32		getLastFilterGeneration() { return mLastFilterGeneration; } - -	virtual void	dirtyFilter(); - -	// If 'selection' is 'this' then note that otherwise ignore. -	// Returns TRUE if this item ends up being selected. -	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - -	// This method is used to set the selection state of an item. -	// If 'selection' is 'this' then note selection. -	// Returns TRUE if the selection state of this item was changed. -	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - -	// this method is used to deselect this element -	void deselectItem(); - -	// this method is used to select this element -	virtual void selectItem(); - -	// gets multiple-element selection -	virtual std::set<LLUUID> getSelectionList() const; - -	// Returns true is this object and all of its children can be removed (deleted by user) -	virtual BOOL isRemovable(); - -	// Returns true is this object and all of its children can be moved -	virtual BOOL isMovable(); - -	// destroys this item recursively -	virtual void destroyView(); - -	BOOL isSelected() const { return mIsSelected; } - -	void setUnselected() { mIsSelected = FALSE; } - -	void setIsCurSelection(BOOL select) { mIsCurSelection = select; } - -	BOOL getIsCurSelection() { return mIsCurSelection; } - -	BOOL hasVisibleChildren() { return mHasVisibleChildren; } - -	void setShowLoadStatus(bool status) { mShowLoadStatus = status; } - -	// Call through to the viewed object and return true if it can be -	// removed. Returns true if it's removed. -	//virtual BOOL removeRecursively(BOOL single_item); -	BOOL remove(); - -	// Build an appropriate context menu for the item.	Flags unused. -	void buildContextMenu(LLMenuGL& menu, U32 flags); - -	// This method returns the actual name of the thing being -	// viewed. This method will ask the viewed object itself. -	const std::string& getName( void ) const; - -	const std::string& getSearchableLabel( void ) const; - -	// This method returns the label displayed on the view. This -	// method was primarily added to allow sorting on the folder -	// contents possible before the entire view has been constructed. -	const std::string& getLabel() const { return mLabel; } - -	// Used for sorting, like getLabel() above. -	virtual time_t getCreationDate() const { return mCreationDate; } - -	LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } -	const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } - -	LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); -	LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - -	const LLFolderViewEventListener* getListener( void ) const { return mListener; } -	LLFolderViewEventListener* getListener( void ) { return mListener; } -	 -	// Gets the inventory item if it exists (null otherwise) -	LLViewerInventoryItem * getInventoryItem(void); - -	// just rename the object. -	void rename(const std::string& new_name); - -	// open -	virtual void openItem( void ); -	virtual void preview(void); - -	// Show children (unfortunate that this is called "open") -	virtual void setOpen(BOOL open = TRUE) {}; - -	virtual BOOL isOpen() const { return FALSE; } - -	virtual LLFolderView*	getRoot(); -	BOOL			isDescendantOf( const LLFolderViewFolder* potential_ancestor ); -	S32				getIndentation() { return mIndentation; } - -	virtual BOOL	potentiallyVisible(); // do we know for a fact that this item won't be displayed? -	virtual BOOL	potentiallyFiltered(); // do we know for a fact that this item has been filtered out? - -	virtual BOOL	getFiltered(); -	virtual BOOL	getFiltered(S32 filter_generation); -	virtual void	setFiltered(BOOL filtered, S32 filter_generation); - -	// change the icon -	void setIcon(LLUIImagePtr icon); - -	// refresh information from the object being viewed. -	void refreshFromListener(); -	virtual void refresh(); - -	virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - -	// LLView functionality -	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); -	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); -	virtual BOOL handleHover( S32 x, S32 y, MASK mask ); -	virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); -	virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - -	virtual void onMouseLeave(S32 x, S32 y, MASK mask); - -	virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; } - -	//	virtual void handleDropped(); -	virtual void draw(); -	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -		EDragAndDropType cargo_type, -		void* cargo_data, -		EAcceptance* accept, -		std::string& tooltip_msg); - -private: -	static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts -}; - - -// function used for sorting. -typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFolder -// -// An instance of an LLFolderViewFolder represents a collection of -// more folders and items. This is used to build the hierarchy of -// items found in the folder view. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewFolder : public LLFolderViewItem -{ -protected: -	LLFolderViewFolder( const LLFolderViewItem::Params& ); -	friend class LLUICtrlFactory; - -public: -	typedef enum e_trash -	{ -		UNKNOWN, TRASH, NOT_TRASH -	} ETrash; - -	typedef std::list<LLFolderViewItem*> items_t; -	typedef std::list<LLFolderViewFolder*> folders_t; - -protected: -	items_t mItems; -	folders_t mFolders; -	LLInventorySort	mSortFunction; - -	BOOL		mIsOpen; -	BOOL		mExpanderHighlighted; -	F32			mCurHeight; -	F32			mTargetHeight; -	F32			mAutoOpenCountdown; -	time_t		mSubtreeCreationDate; -	mutable ETrash mAmTrash; -	S32			mLastArrangeGeneration; -	S32			mLastCalculatedWidth; -	S32			mCompletedFilterGeneration; -	S32			mMostFilteredDescendantGeneration; -	bool		mNeedsSort; -	bool		mPassedFolderFilter; - -public: -	typedef enum e_recurse_type -	{ -		RECURSE_NO, -		RECURSE_UP, -		RECURSE_DOWN, -		RECURSE_UP_DOWN -	} ERecurseType; - - -	virtual ~LLFolderViewFolder( void ); - -	virtual BOOL	potentiallyVisible(); - -	LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); -	LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE  ); - -	// addToFolder() returns TRUE if it succeeds. FALSE otherwise -	virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - -	// Finds width and height of this object and it's children.  Also -	// makes sure that this view and it's children are the right size. -	virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); - -	BOOL needsArrange(); -	void requestSort(); - -	// Returns the sort group (system, trash, folder) for this folder. -	virtual EInventorySortGroup getSortGroup() const; - -	virtual void	setCompletedFilterGeneration(S32 generation, BOOL recurse_up); -	virtual S32		getCompletedFilterGeneration() { return mCompletedFilterGeneration; } - -	BOOL hasFilteredDescendants(S32 filter_generation); -	BOOL hasFilteredDescendants(); - -	// applies filters to control visibility of inventory items -	virtual void filter( LLInventoryFilter& filter); -	virtual void setFiltered(BOOL filtered, S32 filter_generation); -	virtual BOOL getFiltered(); -	virtual BOOL getFiltered(S32 filter_generation); - -	virtual void dirtyFilter(); -	 -	// folder-specific filtering (filter status propagates top down instead of bottom up) -	void filterFolder(LLInventoryFilter& filter); -	void setFilteredFolder(bool filtered, S32 filter_generation); -	bool getFilteredFolder(S32 filter_generation); - -	// Passes selection information on to children and record -	// selection information if necessary. -	// Returns TRUE if this object (or a child) ends up being selected. -	// If 'openitem' is TRUE then folders are opened up along the way to the selection. -	virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - -	// This method is used to change the selection of an item. -	// Recursively traverse all children; if 'selection' is 'this' then change -	// the select status if necessary. -	// Returns TRUE if the selection state of this folder, or of a child, was changed. -	virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - -	// this method is used to group select items -	void extendSelectionTo(LLFolderViewItem* selection); - -	// Returns true is this object and all of its children can be removed. -	virtual BOOL isRemovable(); - -	// Returns true is this object and all of its children can be moved -	virtual BOOL isMovable(); - -	// destroys this folder, and all children -	virtual void destroyView(); - -	// If this folder can be removed, remove all children that can be -	// removed, return TRUE if this is empty after the operation and -	// it's viewed folder object can be removed. -	//virtual BOOL removeRecursively(BOOL single_item); -	//virtual BOOL remove(); - -	// remove the specified item (and any children) if -	// possible. Return TRUE if the item was deleted. -	BOOL removeItem(LLFolderViewItem* item); - -	// simply remove the view (and any children) Don't bother telling -	// the listeners. -	void removeView(LLFolderViewItem* item); - -	// extractItem() removes the specified item from the folder, but -	// doesn't delete it. -	void extractItem( LLFolderViewItem* item ); - -	// This function is called by a child that needs to be resorted. -	void resort(LLFolderViewItem* item); - -	void setItemSortOrder(U32 ordering); -	void sortBy(U32); -	//BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); - -	void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } - -	// folders can be opened. This will usually be called by internal -	// methods. -	virtual void toggleOpen(); - -	// Force a folder open or closed -	virtual void setOpen(BOOL openitem = TRUE); - -	// Called when a child is refreshed. -	// don't rearrange child folder contents unless explicitly requested -	virtual void requestArrange(BOOL include_descendants = FALSE); - -	// internal method which doesn't update the entire view. This -	// method was written because the list iterators destroy the state -	// of other iterations, thus, we can't arrange while iterating -	// through the children (such as when setting which is selected. -	virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO); - -	// Get the current state of the folder. -	virtual BOOL isOpen() const { return mIsOpen; } - -	// special case if an object is dropped on the child. -	BOOL handleDragAndDropFromChild(MASK mask, -		BOOL drop, -		EDragAndDropType cargo_type, -		void* cargo_data, -		EAcceptance* accept, -		std::string& tooltip_msg); - -	void applyFunctorRecursively(LLFolderViewFunctor& functor); -	virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - -	// Just apply this functor to the folder's immediate children. -	void applyFunctorToChildren(LLFolderViewFunctor& functor); - -	virtual void openItem( void ); -	virtual BOOL addItem(LLFolderViewItem* item); -	virtual BOOL addFolder( LLFolderViewFolder* folder); - -	// LLView functionality -	virtual BOOL handleHover(S32 x, S32 y, MASK mask); -	virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); -	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); -	virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); -	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, -		EDragAndDropType cargo_type, -		void* cargo_data, -		EAcceptance* accept, -		std::string& tooltip_msg); -	BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, -									   EDragAndDropType cargo_type, -									   void* cargo_data, -									   EAcceptance* accept, -									   std::string& tooltip_msg); -	virtual void draw(); - -	time_t getCreationDate() const; -	bool isTrash() const; - -	folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); } -	folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); } -	folders_t::size_type getFoldersCount() const { return mFolders.size(); } - -	items_t::const_iterator getItemsBegin() const { return mItems.begin(); } -	items_t::const_iterator getItemsEnd() const { return mItems.end(); } -	items_t::size_type getItemsCount() const { return mItems.size(); } -	LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); -	void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse,  std::vector<LLFolderViewItem*>& items); -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewListenerFunctor -// -// This simple abstract base class can be used to applied to all -// listeners in a hierarchy. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewListenerFunctor -{ -public: -	virtual ~LLFolderViewListenerFunctor() {} -	virtual void operator()(LLFolderViewEventListener* listener) = 0; -}; - -#endif  // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp new file mode 100644 index 0000000000..8a4b4bae84 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -0,0 +1,322 @@ +/*  + * @file llfolderviewmodelinventory.cpp + * @brief Implementation of the inventory-specific view model + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfolderviewmodelinventory.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" +#include "lltooldraganddrop.h" + +// +// class LLFolderViewModelInventory +// +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +bool LLFolderViewModelInventory::startDrag(std::vector<LLFolderViewModelItem*>& items) +{ +	std::vector<EDragAndDropType> types; +	uuid_vec_t cargo_ids; +	std::vector<LLFolderViewModelItem*>::iterator item_it; +	bool can_drag = true; +	if (!items.empty()) +	{ +		for (item_it = items.begin(); item_it != items.end(); ++item_it) +		{ +			EDragAndDropType type = DAD_NONE; +			LLUUID id = LLUUID::null; +			can_drag = can_drag && static_cast<LLFolderViewModelItemInventory*>(*item_it)->startDrag(&type, &id); + +			types.push_back(type); +			cargo_ids.push_back(id); +		} + +		LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids,  +			static_cast<LLFolderViewModelItemInventory*>(items.front())->getDragSource(), mTaskID);  +	} +	return can_drag; +} + + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ +	LLFastTimer _(FTM_INVENTORY_SORT); + +	if (!needsSort(folder->getViewModelItem())) return; + +	LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); +	if (modelp->getUUID().isNull()) return; + +	for (std::list<LLFolderViewFolder*>::iterator it =   folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); +		it != end_it; +		++it) +	{ +		LLFolderViewFolder* child_folderp = *it; +		sort(child_folderp); + +		if (child_folderp->getFoldersCount() > 0) +		{ +			time_t most_recent_folder_time = +				static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); +			LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); +			if (most_recent_folder_time > modelp->getCreationDate()) +			{ +				modelp->setCreationDate(most_recent_folder_time); +			} +		} +		if (child_folderp->getItemsCount() > 0)			 +		{ +			time_t most_recent_item_time = +				static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); + +			LLFolderViewModelItemInventory* modelp =   static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); +			if (most_recent_item_time > modelp->getCreationDate()) +			{ +				modelp->setCreationDate(most_recent_item_time); +			} +		} +	} +	base_t::sort(folder); +} + +bool LLFolderViewModelInventory::contentsReady() +{ +	return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + +void LLFolderViewModelItemInventory::requestSort() +{ +	LLFolderViewModelItemCommon::requestSort(); +	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(mFolderViewItem); +	if (folderp) +	{ +		folderp->requestArrange(); +	} +	if (static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter().isByDate()) +	{ +		// sort by date potentially affects parent folders which use a date +		// derived from newest item in them +		if (mParent) +		{ +			mParent->requestSort(); +		} +	} +} + +void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size) +{ +	LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size); + +	bool passed_filter_before = mPrevPassedAllFilters; +	mPrevPassedAllFilters = passedFilter(filter_generation); + +	if (passed_filter_before != mPrevPassedAllFilters) +	{ +		//TODO RN: ensure this still happens, but without dependency on folderview +		LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder(); +		if (parent_folder) +		{ +			parent_folder->requestArrange(); +		} +	} +} + +bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter ) +{ +	S32 filter_generation = filter.getCurrentGeneration(); + +	bool continue_filtering = true; +	if (item->getLastFilterGeneration() < filter_generation) +	{ +		// recursive application of the filter for child items +		continue_filtering = item->filter( filter ); +	} + +	// track latest generation to pass any child items, for each folder up to root +	if (item->passedFilter()) +	{ +		LLFolderViewModelItemInventory* view_model = this; +		 +		while(view_model && view_model->mMostFilteredDescendantGeneration < filter_generation) +		{ +			view_model->mMostFilteredDescendantGeneration = filter_generation; +			view_model = static_cast<LLFolderViewModelItemInventory*>(view_model->mParent); +		} +	} + +	return continue_filtering; +} + +bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter) +{ +	const S32 filter_generation = filter.getCurrentGeneration(); +	const S32 must_pass_generation = filter.getFirstRequiredGeneration(); + +	if (getLastFilterGeneration() >= must_pass_generation  +		&& getLastFolderFilterGeneration() >= must_pass_generation +		&& !passedFilter(must_pass_generation)) +	{ +		// failed to pass an earlier filter that was a subset of the current one +		// go ahead and flag this item as done +		setPassedFilter(false, filter_generation); +		setPassedFolderFilter(false, filter_generation); +		return true; +	} + +	const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)  +		? filter.checkFolder(this) +		: true; +	setPassedFolderFilter(passed_filter_folder, filter_generation); + +	if(!mChildren.empty() +		&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass +			|| descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement +	{ +		// now query children +		for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); +			iter != end_iter && filter.getFilterCount() > 0; +			++iter) +		{ +			if (!filterChildItem((*iter), filter)) +			{ +				break; +			} +		} +	} + +	// if we didn't use all filter iterations +	// that means we filtered all of our descendants +	// so filter ourselves now +	if (filter.getFilterCount() > 0) +	{ +		filter.decrementFilterCount(); + +		const bool passed_filter = filter.check(this); +		setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize()); +		return true; +	} +	else +	{ +		return false; +	} +} + +LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() +{ +	return &mInventoryViewModel; +} + + +const LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel() const +{ +	return &mInventoryViewModel; +} + +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const +{ +	// ignore sort order for landmarks in the Favorites folder. +	// they should be always sorted as in Favorites bar. See EXT-719 +	//TODO RN: fix sorting in favorites folder +	//if (a->getSortGroup() == SG_ITEM +	//	&& b->getSortGroup() == SG_ITEM +	//	&& a->getInventoryType() == LLInventoryType::IT_LANDMARK +	//	&& b->getInventoryType() == LLInventoryType::IT_LANDMARK) +	//{ + +	//	static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + +	//	LLUUID a_uuid = a->getParentFolder()->getUUID(); +	//	LLUUID b_uuid = b->getParentFolder()->getUUID(); + +	//	if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) +	//	{ +	//		// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem +	//		// or to LLInvFVBridge +	//		LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); +	//		LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); +	//		if (!aitem || !bitem) +	//			return false; +	//		S32 a_sort = aitem->getSortField(); +	//		S32 b_sort = bitem->getSortField(); +	//		return a_sort < b_sort; +	//	} +	//} + +	// We sort by name if we aren't sorting by date +	// OR if these are folders and we are sorting folders by name. +	bool by_name = (!mByDate  +		|| (mFoldersByName  +		&& (a->getSortGroup() != SG_ITEM))); + +	if (a->getSortGroup() != b->getSortGroup()) +	{ +		if (mSystemToTop) +		{ +			// Group order is System Folders, Trash, Normal Folders, Items +			return (a->getSortGroup() < b->getSortGroup()); +		} +		else if (mByDate) +		{ +			// Trash needs to go to the bottom if we are sorting by date +			if ( (a->getSortGroup() == SG_TRASH_FOLDER) +				|| (b->getSortGroup() == SG_TRASH_FOLDER)) +			{ +				return (b->getSortGroup() == SG_TRASH_FOLDER); +			} +		} +	} + +	if (by_name) +	{ +		S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); +		if (0 == compare) +		{ +			return (a->getCreationDate() > b->getCreationDate()); +		} +		else +		{ +			return (compare < 0); +		} +	} +	else +	{ +		time_t first_create = a->getCreationDate(); +		time_t second_create = b->getCreationDate(); +		if (first_create == second_create) +		{ +			return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); +		} +		else +		{ +			return (first_create > second_create); +		} +	} +} + +LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )  +	:	LLFolderViewModelItemCommon(root_view_model), +	mPrevPassedAllFilters(false) +{ +} diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h new file mode 100644 index 0000000000..890d03d1c9 --- /dev/null +++ b/indra/newview/llfolderviewmodelinventory.h @@ -0,0 +1,118 @@ +/**  + * @file llfolderviewmodelinventory.h + * @brief view model implementation specific to inventory + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFOLDERVIEWMODELINVENTORY_H +#define LL_LLFOLDERVIEWMODELINVENTORY_H + +#include "llinventoryfilter.h" +#include "llinventory.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" + +class LLFolderViewModelItemInventory +	:	public LLFolderViewModelItemCommon +{ +public: +	LLFolderViewModelItemInventory(class LLFolderViewModelInventory& root_view_model); +	virtual const LLUUID& getUUID() const = 0; +	virtual time_t getCreationDate() const = 0;	// UTC seconds +	virtual void setCreationDate(time_t creation_date_utc) = 0; +	virtual PermissionMask getPermissionMask() const = 0; +	virtual LLFolderType::EType getPreferredType() const = 0; +	virtual void showProperties(void) = 0; +	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual. +	virtual BOOL isUpToDate() const = 0; +	virtual bool hasChildren() const = 0; +	virtual LLInventoryType::EType getInventoryType() const = 0; +	virtual void performAction(LLInventoryModel* model, std::string action)   = 0; +	virtual LLWearableType::EType getWearableType() const = 0; +	virtual EInventorySortGroup getSortGroup() const = 0; +	virtual LLInventoryObject* getInventoryObject() const = 0; +	virtual void requestSort(); +	virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); +	virtual bool filter( LLFolderViewFilter& filter); +	virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); + +	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; +	virtual LLToolDragAndDrop::ESource getDragSource() const = 0; + +protected: +	bool								mPrevPassedAllFilters; +}; + +class LLInventorySort +{ +public: +	struct Params : public LLInitParam::Block<Params> +	{ +		Optional<S32> order; + +		Params() +		:	order("order", 0) +		{} +	}; + +	LLInventorySort(S32 order = 0) +	{ +		fromParams(Params().order(order)); +	} + +	bool isByDate() const { return mByDate; } +	U32 getSortOrder() const { return mSortOrder; } +	void toParams(Params& p) { p.order(mSortOrder);} +	void fromParams(Params& p)  +	{  +		mSortOrder = p.order;  +		mByDate = (mSortOrder & LLInventoryFilter::SO_DATE); +		mSystemToTop = (mSortOrder & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); +		mFoldersByName = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); +	} + +	bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; +private: +	U32  mSortOrder; +	bool mByDate; +	bool mSystemToTop; +	bool mFoldersByName; +}; + +class LLFolderViewModelInventory +	:	public LLFolderViewModel<LLInventorySort,   LLFolderViewModelItemInventory, LLFolderViewModelItemInventory,   LLInventoryFilter> +{ +public: +	typedef LLFolderViewModel<LLInventorySort,   LLFolderViewModelItemInventory, LLFolderViewModelItemInventory,   LLInventoryFilter> base_t; + +	void setTaskID(const LLUUID& id) {mTaskID = id;} + +	void sort(LLFolderViewFolder* folder); +	bool contentsReady(); +	bool startDrag(std::vector<LLFolderViewModelItem*>& items); + +private: +	LLUUID mTaskID; +}; +#endif // LL_LLFOLDERVIEWMODELINVENTORY_H diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index b670af1782..47612fe25c 100644 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -38,7 +38,6 @@ std::vector<LLFollowCamParams*> LLFollowCamMgr::sParamStack;  //-------------------------------------------------------  // constants  //------------------------------------------------------- -const F32 ONE_HALF							= 0.5;   const F32 FOLLOW_CAM_ZOOM_FACTOR			= 0.1f;  const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT		= 0.1f;  const F32 DISTANCE_EPSILON					= 0.0001f; diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 11401d6c68..a64ddd185d 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -47,13 +47,13 @@ static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All";  // helper functions  // NOTE: For now Friends & All folders are created as protected folders of the LLFolderType::FT_CALLINGCARD type. -// So, their names will be processed in the LLFolderViewItem::refreshFromListener() to be localized +// So, their names will be processed in the LLFolderViewItem::refresh() to be localized  // using "InvFolder LABEL_NAME" as LLTrans::findString argument.  // We must use in this file their hard-coded names to ensure found them on different locales. EXT-5829.  // These hard-coded names will be stored in InventoryItems but shown localized in FolderViewItems -// If hack in the LLFolderViewItem::refreshFromListener() to localize protected folder is removed +// If hack in the LLFolderViewItem::refresh() to localize protected folder is removed  // or these folders are not protected these names should be localized in another place/way.  inline const std::string get_friend_folder_name()  { diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 66ca76bfb0..26b63bdacb 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -51,7 +51,7 @@  #include "llviewermessage.h"  #include "llvoavatarself.h"  #include "llviewerstats.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llappearancemgr.h"  #include "llgesturelistener.h" @@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)  			const BOOL animate = FALSE; -			LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); +			LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);  			gesture->mCurrentStep++;  			break; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 129cddda45..aba3d74d87 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -86,7 +86,7 @@ LLGroupList::LLGroupList(const Params& p)  	registrar.add("People.Groups.Action",			boost::bind(&LLGroupList::onContextMenuItemClick,	this, _2));  	enable_registrar.add("People.Groups.Enable",	boost::bind(&LLGroupList::onContextMenuItemEnable,	this, _2)); -	LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml", +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",  			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	if(context_menu)  		mContextMenuHandle = context_menu->getHandle(); @@ -112,7 +112,7 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); -	LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get(); +	LLToggleableMenu* context_menu = mContextMenuHandle.get();  	if (context_menu && size() > 0)  	{  		context_menu->buildDrawLabels(); @@ -406,7 +406,7 @@ void LLGroupListItem::setActive(bool active)  	// *BUG: setName() overrides the style params.  	// Active group should be bold. -	LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc()); +	LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc());  	// *NOTE dzaporozhan  	// On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font  diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 8abf14b3d0..e96a720886 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -28,10 +28,13 @@  #define LL_LLGROUPLIST_H  #include "llevent.h" +#include "llpointer.h" +  #include "llflatlistview.h"  #include "llpanel.h" -#include "llpointer.h"  #include "llstyle.h" +#include "lltoggleablemenu.h" +  #include "llgroupmgr.h"  /** @@ -45,6 +48,10 @@ class LLGroupList: public LLFlatListViewEx, public LLOldEvents::LLSimpleListener  {  	LOG_CLASS(LLGroupList);  public: +	struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> +	{ +		Params(){}; +	};  	LLGroupList(const Params& p);  	virtual ~LLGroupList(); @@ -57,6 +64,8 @@ public:  	void toggleIcons();  	bool getIconsVisible() const { return mShowIcons; } +	LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); } +  private:  	void setDirty(bool val = true)		{ mDirty = val; }  	void refresh(); @@ -66,7 +75,7 @@ private:  	bool onContextMenuItemClick(const LLSD& userdata);  	bool onContextMenuItemEnable(const LLSD& userdata); -	LLHandle<LLView>	mContextMenuHandle; +	LLHandle<LLToggleableMenu>	mContextMenuHandle;  	bool mShowIcons;  	bool mDirty; diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 482294c8a6..3336097955 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -166,7 +166,6 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3&  	}  	// scale screen size of borders down -	//RN: for now, text on hud objects is never occluded  	LLVector3 x_pixel_vec;  	LLVector3 y_pixel_vec; @@ -187,45 +186,29 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3&  			+ (y_pixel_vec * screen_offset.mV[VY]); -	//if (mUseBubble) +	LLVector3 bg_pos = render_position +		+ (F32)mOffsetY * y_pixel_vec +		- (width_vec / 2.f) +		- (height_vec); + +	LLVector3 v[] =   	{ -		LLVector3 bg_pos = render_position -			+ (F32)mOffsetY * y_pixel_vec -			- (width_vec / 2.f) -			- (height_vec); -		//LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); +		bg_pos, +		bg_pos + width_vec, +		bg_pos + width_vec + height_vec, +		bg_pos + height_vec, +	}; -		LLVector3 v[] =  -		{ -			bg_pos, -			bg_pos + width_vec, -			bg_pos + width_vec + height_vec, -			bg_pos + height_vec, -		}; +	LLVector3 dir = end-start; +	F32 a, b, t; -		if (debug_render) +	if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || +		LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) +	{ +		if (t <= 1.f)  		{ -			gGL.begin(LLRender::LINE_STRIP); -			gGL.vertex3fv(v[0].mV); -			gGL.vertex3fv(v[1].mV); -			gGL.vertex3fv(v[2].mV); -			gGL.vertex3fv(v[3].mV); -			gGL.vertex3fv(v[0].mV); -			gGL.vertex3fv(v[2].mV); -			gGL.end(); -		} - -		LLVector3 dir = end-start; -		F32 a, b, t; - -		if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || -			LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) -		{ -			if (t <= 1.f) -			{ -				intersection = start + dir*t; -				return TRUE; -			} +			intersection = start + dir*t; +			return TRUE;  		}  	} @@ -241,12 +224,6 @@ void LLHUDNameTag::render()  	}  } -void LLHUDNameTag::renderForSelect() -{ -	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -	renderText(TRUE); -} -  void LLHUDNameTag::renderText(BOOL for_select)  {  	if (!mVisible || mHidden) @@ -299,24 +276,6 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");  	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); -	// maybe a no-op? -	//const S32 border_height = 16; -	//const S32 border_width = 16; -	const S32 border_height = 8; -	const S32 border_width = 8; - -	// *TODO move this into helper function -	F32 border_scale = 1.f; - -	if (border_height * 2 > mHeight) -	{ -		border_scale = (F32)mHeight / ((F32)border_height * 2.f); -	} -	if (border_width * 2 > mWidth) -	{ -		border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); -	} -  	// scale screen size of borders down  	//RN: for now, text on hud objects is never occluded @@ -325,152 +284,34 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); -	LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());  	LLVector3 width_vec = mWidth * x_pixel_vec;  	LLVector3 height_vec = mHeight * y_pixel_vec; -	LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; -	LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;  	mRadius = (width_vec + height_vec).magVec() * 0.5f;  	LLCoordGL screen_pos;  	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); -	LLVector2 screen_offset; -//	if (!mUseBubble) -//	{ -//		screen_offset = mPositionOffset; -//	} -//	else -//	{ -		screen_offset = updateScreenPos(mPositionOffset); -//	} +	LLVector2 screen_offset = updateScreenPos(mPositionOffset);  	LLVector3 render_position = mPositionAgent    			+ (x_pixel_vec * screen_offset.mV[VX])  			+ (y_pixel_vec * screen_offset.mV[VY]); -//	if (mUseBubble) +	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); +	LLRect screen_rect; +	screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); +	imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); +	if (mLabelSegments.size())  	{ -		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -		LLUI::pushMatrix(); -		{ -			LLVector3 bg_pos = render_position -				+ (F32)mOffsetY * y_pixel_vec -				- (width_vec / 2.f) -				- (height_vec); -			LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - -			if (for_select) -			{ -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				S32 name = mSourceObject->mGLName; -				LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); -				gGL.color4ubv(coloru.mV); -				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); -				LLUI::popMatrix(); -				return; -			} -			else -			{ -				gGL.getTexUnit(0)->bind(imagep->getImage()); -				 -				gGL.color4fv(bg_color.mV); -				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); -		 -				if ( mLabelSegments.size()) -				{ -					LLUI::pushMatrix(); -					{ -						gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); -						LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; -						LLVector3 label_offset = height_vec - label_height; -						LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); -						gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); -					} -					LLUI::popMatrix(); -				} -			} - -			BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; -			BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); +		LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); +		LLRect label_top_rect = screen_rect; +		const S32 label_height = llround((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); +		label_top_rect.mBottom = label_top_rect.mTop - label_height; +		LLColor4 label_top_color = text_color; +		label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; -			// draw line segments pointing to parent object -			if (!mOffscreen && (outside_width || outside_height)) -			{ -				LLUI::pushMatrix(); -				{ -					gGL.color4fv(bg_color.mV); -					LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); -					target_pos += (width_vec / 2.f); -					target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero; -					target_pos -= 3.f * x_pixel_vec; -					target_pos -= 6.f * y_pixel_vec; -					LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); -					gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);	 -				} -				LLUI::popMatrix(); - -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); -				 -				LLVector3 box_center_offset; -				box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); -				LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); -				gGL.color4fv(bg_color.mV); -				LLUI::setLineWidth(2.0); -				gGL.begin(LLRender::LINES); -				{ -					if (outside_width) -					{ -						LLVector3 vert; -						// draw line in x then y -						if (mPositionOffset.mV[VX] < 0.f) -						{ -							// start at right edge -							vert = width_vec * 0.5f; -							gGL.vertex3fv(vert.mV); -						} -						else -						{ -							// start at left edge -							vert = width_vec * -0.5f; -							gGL.vertex3fv(vert.mV); -						} -						vert = -mPositionOffset.mV[VX] * x_pixel_vec; -						gGL.vertex3fv(vert.mV); -						gGL.vertex3fv(vert.mV); -						vert -= mPositionOffset.mV[VY] * y_pixel_vec; -						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); -						gGL.vertex3fv(vert.mV); -					} -					else -					{ -						LLVector3 vert; -						// draw line in y then x -						if (mPositionOffset.mV[VY] < 0.f) -						{ -							// start at top edge -							vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); -							gGL.vertex3fv(vert.mV); -						} -						else -						{ -							// start at bottom edge -							vert = (height_vec * -0.5f)  - (mPositionOffset.mV[VX] * x_pixel_vec); -							gGL.vertex3fv(vert.mV); -						} -						vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; -						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); -						gGL.vertex3fv(vert.mV); -					} -				} -				gGL.end(); -				LLUI::setLineWidth(1.0); - -			} -		} -		LLUI::popMatrix(); +		rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);  	}  	F32 y_offset = (F32)mOffsetY; @@ -874,29 +715,26 @@ void LLHUDNameTag::updateAll()  	for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)  	{  		LLHUDNameTag* textp = (*r_it); -//		if (textp->mUseBubble) -//		{ -			if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) -			{ -				textp->setLOD(3); -			} -			else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) -			{ -				textp->setLOD(2); -			} -			else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) -			{ -				textp->setLOD(1); -			} -			else -			{ -				textp->setLOD(0); -			} -			textp->updateSize(); -			// find on-screen position and initialize collision rectangle -			textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); -			current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); -//		} +		if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) +		{ +			textp->setLOD(3); +		} +		else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) +		{ +			textp->setLOD(2); +		} +		else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) +		{ +			textp->setLOD(1); +		} +		else +		{ +			textp->setLOD(0); +		} +		textp->updateSize(); +		// find on-screen position and initialize collision rectangle +		textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); +		current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());  	}  	LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); @@ -914,20 +752,12 @@ void LLHUDNameTag::updateAll()  		{  			LLHUDNameTag* src_textp = (*src_it); -//			if (!src_textp->mUseBubble) -//			{ -//				continue; -//			}  			VisibleTextObjectIterator dst_it = src_it;  			++dst_it;  			for (; dst_it != sVisibleTextObjects.end(); ++dst_it)  			{  				LLHUDNameTag* dst_textp = (*dst_it); -//				if (!dst_textp->mUseBubble) -//				{ -//					continue; -//				}  				if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))  				{  					LLRectf intersect_rect = src_textp->mSoftScreenRect; @@ -976,10 +806,6 @@ void LLHUDNameTag::updateAll()  	VisibleTextObjectIterator this_object_it;  	for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)  	{ -//		if (!(*this_object_it)->mUseBubble) -//		{ -//			continue; -//		}  		(*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));  	}  } @@ -1037,10 +863,6 @@ void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)  	VisibleTextObjectIterator text_it;  	for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)  	{ -//		if (!(*text_it)->mUseBubble) -//		{ -//			continue; -//		}  		pick_list.insert((*text_it)->mSourceObject);  	}  } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 3325c22def..72647d5b26 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -118,7 +118,6 @@ public:  	/*virtual*/ void markDead();  	friend class LLHUDObject;  	/*virtual*/ F32 getDistance() const { return mLastDistance; } -	//void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }  	S32  getLOD() { return mLOD; }  	BOOL getVisible() { return mVisible; }  	BOOL getHidden() const { return mHidden; } @@ -136,7 +135,6 @@ protected:  	LLHUDNameTag(const U8 type);  	/*virtual*/ void render(); -	/*virtual*/ void renderForSelect();  	void renderText(BOOL for_select);  	static void updateAll();  	void setLOD(S32 lod); diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 95d57d08d8..0960846510 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -232,9 +232,11 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)  	case LL_HUD_EFFECT_LOOKAT:  		hud_objectp = new LLHUDEffectLookAt(type);  		break; +#ifdef XXX_STINSON_CHUI_REWORK  	case LL_HUD_EFFECT_VOICE_VISUALIZER:  		hud_objectp = new LLVoiceVisualizer(type);  		break; +#endif // XXX_STINSON_CHUI_REWORK  	case LL_HUD_EFFECT_POINTAT:  		hud_objectp = new LLHUDEffectPointAt(type);  		break; diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 2f7a98c86c..32cffe6839 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -39,6 +39,8 @@  #include "lldrawpool.h"		// TODO: eliminate, unused below  #include <list> +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot +  class LLViewerCamera;  class LLFontGL;  class LLFace; @@ -94,7 +96,9 @@ public:  		LL_HUD_EFFECT_EDIT,  		LL_HUD_EFFECT_LOOKAT,  		LL_HUD_EFFECT_POINTAT, +#ifdef XXX_STINSON_CHUI_REWORK  		LL_HUD_EFFECT_VOICE_VISUALIZER,	// Ventrella +#endif // XXX_STINSON_CHUI_REWORK  		LL_HUD_NAME_TAG,  		LL_HUD_EFFECT_BLOB  	}; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp new file mode 100644 index 0000000000..b56f30312a --- /dev/null +++ b/indra/newview/llimconversation.cpp @@ -0,0 +1,406 @@ +/** + * @file llimconversation.cpp + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llimconversation.h" + +#include "llchatentry.h" +#include "llchathistory.h" +#include "lldraghandle.h" +#include "llfloaterreg.h" +#include "llimfloater.h" +#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h" +#include "llnearbychat.h" + +const F32 REFRESH_INTERVAL = 0.2f; + +LLIMConversation::LLIMConversation(const LLUUID& session_id) +  : LLTransientDockableFloater(NULL, true, session_id) +  ,  mIsP2PChat(false) +  ,  mExpandCollapseBtn(NULL) +  ,  mTearOffBtn(NULL) +  ,  mCloseBtn(NULL) +  ,  mSessionID(session_id) +  , mParticipantList(NULL) +  , mChatHistory(NULL) +  , mInputEditor(NULL) +  , mInputEditorTopPad(0) +  , mRefreshTimer(new LLTimer()) +{ +	mCommitCallbackRegistrar.add("IMSession.Menu.Action", +			boost::bind(&LLIMConversation::onIMSessionMenuItemClicked,  this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", +			boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", +			boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck,   this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", +			boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable,  this, _2)); + +	// Zero expiry time is set only once to allow initial update. +	mRefreshTimer->setTimerExpirySec(0); +	mRefreshTimer->start(); +} + +LLIMConversation::~LLIMConversation() +{ +	if (mParticipantList) +	{ +		delete mParticipantList; +		mParticipantList = NULL; +	} + +	delete mRefreshTimer; +} + +BOOL LLIMConversation::postBuild() +{ +	BOOL result; + +	mCloseBtn = getChild<LLButton>("close_btn"); +	mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + +	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); +	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); + +	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); + +	mTearOffBtn = getChild<LLButton>("tear_off_btn"); +	mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + +	mChatHistory = getChild<LLChatHistory>("chat_history"); + +	mInputEditor = getChild<LLChatEntry>("chat_editor"); +	mInputEditor->setTextExpandedCallback(boost::bind(&LLIMConversation::reshapeChatHistory, this)); +	mInputEditor->setCommitOnFocusLost( FALSE ); +	mInputEditor->setPassDelete(TRUE); +	mInputEditor->setFont(LLViewerChat::getChatFont()); + +	mInputEditorTopPad = mChatHistory->getRect().mBottom - mInputEditor->getRect().mTop; + +	setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); + +	buildParticipantList(); + +	updateHeaderAndToolbar(); + +	mSaveRect = isTornOff(); +	initRectControl(); + +	if (isChatMultiTab()) +	{ +		if (mIsNearbyChat) +		{ +			setCanClose(FALSE); +		} +		result = LLFloater::postBuild(); +	} +	else +	{ +		result = LLDockableFloater::postBuild(); +	} + +	return result; +} + +void LLIMConversation::draw() +{ +	LLTransientDockableFloater::draw(); + +	if (mRefreshTimer->hasExpired()) +	{ +		if (mParticipantList) +		{ +			mParticipantList->update(); +		} + +		refresh(); + +		// Restart the refresh timer +		mRefreshTimer->setTimerExpirySec(REFRESH_INTERVAL); +	} +} + +void LLIMConversation::buildParticipantList() +{ +	if (mIsNearbyChat) +	{ +		LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); +		mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); +	} +	else +	{ +		LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +		// for group and ad-hoc chat we need to include agent into list +		if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) +		{ +			delete mParticipantList; // remove the old list and create a new one if the session id has changed +			mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); +		} +	} +} + +void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +{ +	// TODO: Check this code when sort order menu will be added. (EM) +	if (!mParticipantList) +	{ +		return; +	} + +	std::string chosen_item = userdata.asString(); + +	if (chosen_item == "sort_name") +	{ +		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); +	} + +} + +void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) +{ +	std::string item = userdata.asString(); + +	if (item == "compact_view" || item == "expanded_view") +	{ +		gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); +	} +	else +	{ +		bool prev_value = gSavedSettings.getBOOL(item); +		gSavedSettings.setBOOL(item, !prev_value); +	} + +	LLIMConversation::processChatHistoryStyleUpdate(); +} + + +bool LLIMConversation::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) +{ +	std::string item = userdata.asString(); +	bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); + +	return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; +} + + +bool LLIMConversation::onIMShowModesMenuItemCheck(const LLSD& userdata) +{ +	return gSavedSettings.getBOOL(userdata.asString()); +} + +// enable/disable states for the "show time" and "show names" items of the show-modes menu +bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) +{ +	std::string item = userdata.asString(); +	bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); +	bool is_not_names = (item != "IMShowNamesForP2PConv"); +	return (plain_text && (is_not_names || mIsP2PChat)); +} + +void LLIMConversation::hideOrShowTitle() +{ +	const LLFloater::Params& default_params = LLFloater::getDefaultParams(); +	S32 floater_header_size = default_params.header_height; +	LLView* floater_contents = getChild<LLView>("contents_view"); + +	LLRect floater_rect = getLocalRect(); +	S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); +	LLRect handle_rect (0, floater_rect.mTop, floater_rect.mRight, top_border_of_contents); +	LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); +	mDragHandle->setShape(handle_rect); +	mDragHandle->setVisible(isTornOff()); +	floater_contents->setShape(contents_rect); +} + +void LLIMConversation::hideAllStandardButtons() +{ +	for (S32 i = 0; i < BUTTON_COUNT; i++) +	{ +		if (mButtons[i]) +		{ +			// Hide the standard header buttons in a docked IM floater. +			mButtons[i]->setVisible(false); +		} +	} +} + +void LLIMConversation::updateHeaderAndToolbar() +{ +	bool is_torn_off = isTornOff(); +	if (!is_torn_off) +	{ +		hideAllStandardButtons(); +	} + +	hideOrShowTitle(); + +	// Participant list should be visible only in torn off floaters. +	bool is_participant_list_visible = +			is_torn_off +			&& gSavedSettings.getBOOL("IMShowControlPanel") +			&& !mIsP2PChat; + +	mParticipantListPanel->setVisible(is_participant_list_visible); + +	// Display collapse image (<<) if the floater is hosted +	// or if it is torn off but has an open control panel. +	bool is_expanded = !is_torn_off || is_participant_list_visible; +	mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + +	// toggle floater's drag handle and title visibility +	if (mDragHandle) +	{ +		mDragHandle->setTitleVisible(is_torn_off); +	} + +	// The button (>>) should be disabled for torn off P2P conversations. +	mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat); + +	mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon")); + +	mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat); + +	enableDisableCallBtn(); + +	showTranslationCheckbox(); +} + +void LLIMConversation::reshapeChatHistory() +{ +	LLRect chat_rect  = mChatHistory->getRect(); +	LLRect input_rect = mInputEditor->getRect(); + +	int delta_height = chat_rect.mBottom - (input_rect.mTop + mInputEditorTopPad); + +	chat_rect.setLeftTopAndSize(chat_rect.mLeft, chat_rect.mTop, chat_rect.getWidth(), chat_rect.getHeight() + delta_height); +	mChatHistory->setShape(chat_rect); +} + +void LLIMConversation::showTranslationCheckbox(BOOL show) +{ +	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE); +} + +// static +void LLIMConversation::processChatHistoryStyleUpdate() +{ +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); +			iter != inst_list.end(); ++iter) +	{ +		LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); +		if (floater) +		{ +			floater->reloadMessages(); +		} +	} + +	LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); +	if (nearby_chat) +	{ +		nearby_chat->reloadMessages(); +	} +} + +void LLIMConversation::updateCallBtnState(bool callIsActive) +{ +	getChild<LLButton>("voice_call_btn")->setImageOverlay( +			callIsActive? getString("call_btn_stop") : getString("call_btn_start")); +    enableDisableCallBtn(); + +} + +void LLIMConversation::onSlide(LLIMConversation* self) +{ +	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(self->getHost()); +	if (host_floater) +	{ +		// Hide the messages pane if a floater is hosted in the Conversations +		host_floater->collapseMessagesPane(true); +	} +	else ///< floater is torn off +	{ +		if (!self->mIsP2PChat) +		{ +			bool expand = !self->mParticipantListPanel->getVisible(); + +			// Expand/collapse the IM control panel +			self->mParticipantListPanel->setVisible(expand); + +			gSavedSettings.setBOOL("IMShowControlPanel", expand); + +			self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); +		} +	} +} + +/*virtual*/ +void LLIMConversation::onOpen(const LLSD& key) +{ +	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); +    bool is_hosted = !!host_floater; +	if (is_hosted) +	{ +		// Show the messages pane when opening a floater hosted in the Conversations +		host_floater->collapseMessagesPane(false); +	} + +	setTornOff(!is_hosted); +	updateHeaderAndToolbar(); +} + +// virtual +void LLIMConversation::onClose(bool app_quitting) +{ +	// Always suppress the IM from the conversations list on close if present for any reason +	if (LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); +		if (im_box) +		{ +            im_box->removeConversationListItem(this); +        } +    } +} + +void LLIMConversation::onTearOffClicked() +{ +    setFollows(isTornOff()? FOLLOWS_ALL : FOLLOWS_NONE); +    mSaveRect = isTornOff(); +    initRectControl(); +	LLFloater::onClickTearOff(this); +	updateHeaderAndToolbar(); +} + +// static +bool LLIMConversation::isChatMultiTab() +{ +	// Restart is required in order to change chat window type. +	return true; +} diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h new file mode 100644 index 0000000000..649c200899 --- /dev/null +++ b/indra/newview/llimconversation.h @@ -0,0 +1,128 @@ +/** + * @file llimconversation.h + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_IMCONVERSATION_H +#define LL_IMCONVERSATION_H + +#include "lllayoutstack.h" +#include "llparticipantlist.h" +#include "lltransientdockablefloater.h" +#include "llviewercontrol.h" +#include "lleventtimer.h" + +class LLPanelChatControlPanel; +class LLChatEntry; +class LLChatHistory; + +class LLIMConversation +	: public LLTransientDockableFloater +{ + +public: +	LOG_CLASS(LLIMConversation); + +	LLIMConversation(const LLUUID& session_id); +	~LLIMConversation(); + +	// reload all message with new settings of visual modes +	static void processChatHistoryStyleUpdate(); + +	/** +	 * Returns true if chat is displayed in multi tabbed floater +	 *         false if chat is displayed in multiple windows +	 */ +	static bool isChatMultiTab(); + +	// show/hide the translation check box +	void showTranslationCheckbox(const BOOL visible = FALSE); + +	// LLFloater overrides +	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void onClose(bool app_quitting); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void draw(); + +protected: + +	// callback for click on any items of the visual states menu +	void onIMSessionMenuItemClicked(const LLSD& userdata); + +	// callback for check/uncheck of the expanded/collapse mode's switcher +	bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); + +	// +	bool onIMShowModesMenuItemCheck(const LLSD& userdata); +	bool onIMShowModesMenuItemEnable(const LLSD& userdata); +	static void onSlide(LLIMConversation *self); +	virtual void onTearOffClicked(); + +	// refresh a visual state of the Call button +	void updateCallBtnState(bool callIsActive); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn() = 0; + +	void buildParticipantList(); +	void onSortMenuItemClicked(const LLSD& userdata); + +	void hideOrShowTitle(); // toggle the floater's drag handle +	void hideAllStandardButtons(); + +	bool mIsNearbyChat; +	bool mIsP2PChat; + +	LLLayoutPanel* mParticipantListPanel; +	LLParticipantList* mParticipantList; +	LLUUID mSessionID; + +	LLChatHistory* mChatHistory; +	LLChatEntry* mInputEditor; +	int mInputEditorTopPad; // padding between input field and chat history + +	LLButton* mExpandCollapseBtn; +	LLButton* mTearOffBtn; +	LLButton* mCloseBtn; + +private: +	/// Refreshes the floater at a constant rate. +	virtual void refresh() = 0; + +	/// Update floater header and toolbar buttons when hosted/torn off state is toggled. +	void updateHeaderAndToolbar(); + +	/** +	 * Adjusts chat history height to fit vertically with input chat field +	 * and avoid overlapping, since input chat field can be vertically expanded. +	 * Implementation: chat history bottom "follows" top+top_pad of input chat field +	 */ +	void reshapeChatHistory(); + +	LLTimer* mRefreshTimer; ///< Defines the rate at which refresh() is called. +}; + + +#endif // LL_IMCONVERSATION_H diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 63eedcdfea..3399a88c9e 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -28,44 +28,44 @@  #include "llimfloater.h" +#include "lldraghandle.h"  #include "llnotificationsutil.h"  #include "llagent.h"  #include "llappviewer.h" +#include "llavataractions.h"  #include "llavatarnamecache.h"  #include "llbutton.h"  #include "llchannelmanager.h"  #include "llchiclet.h"  #include "llchicletbar.h"  #include "llfloaterreg.h" +#include "llfloateravatarpicker.h"  #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container  #include "llinventoryfunctions.h" -#include "lllayoutstack.h" -#include "lllineeditor.h" +//#include "lllayoutstack.h" +#include "llchatentry.h"  #include "lllogchat.h" -#include "llpanelimcontrolpanel.h"  #include "llscreenchannel.h"  #include "llsyswellwindow.h"  #include "lltrans.h"  #include "llchathistory.h"  #include "llnotifications.h"  #include "llviewerwindow.h" -#include "llvoicechannel.h"  #include "lltransientfloatermgr.h"  #include "llinventorymodel.h"  #include "llrootview.h"  #include "llspeakers.h"  #include "llviewerchat.h" +#include "llnotificationmanager.h"  #include "llautoreplace.h" +floater_showed_signal_t LLIMFloater::sIMFloaterShowedSignal; +  LLIMFloater::LLIMFloater(const LLUUID& session_id) -  : LLTransientDockableFloater(NULL, true, session_id), -	mControlPanel(NULL), -	mSessionID(session_id), +  : LLIMConversation(session_id),  	mLastMessageIndex(-1),  	mDialog(IM_NOTHING_SPECIAL), -	mChatHistory(NULL), -	mInputEditor(NULL),  	mSavedTitle(),  	mTypingStart(),  	mShouldSendTypingState(false), @@ -74,38 +74,13 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  	mTypingTimer(),  	mTypingTimeoutTimer(),  	mPositioned(false), -	mSessionInitialized(false) +	mSessionInitialized(false), +	mStartConferenceInSameFloater(false)  { -	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID); -	if (im_session) -	{ -		mSessionInitialized = im_session->mSessionInitialized; +	mIsNearbyChat = false; + +	initIMSession(session_id); -		mDialog = im_session->mType; -		switch(mDialog){ -		case IM_NOTHING_SPECIAL: -		case IM_SESSION_P2P_INVITE: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); -			break; -		case IM_SESSION_CONFERENCE_START: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); -			break; -		case IM_SESSION_GROUP_START: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); -			break; -		case IM_SESSION_INVITE:		 -			if (gAgent.isInGroup(mSessionID)) -			{ -				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); -			} -			else -			{ -				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); -			} -			break; -		default: break; -		} -	}  	setOverlapsScreenChannel(true);  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -133,30 +108,58 @@ void LLIMFloater::onFocusReceived()  }  // virtual -void LLIMFloater::onClose(bool app_quitting) +void LLIMFloater::refresh() +{ +	if (mMeTyping)  { +		// Time out if user hasn't typed for a while. +		if (mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS) +		{  	setTyping(false); +		} +	} +} -	// The source of much argument and design thrashing -	// Should the window hide or the session close when the X is clicked? -	// -	// Last change: -	// EXT-3516 X Button should end IM session, _ button should hide -	gIMMgr->leaveSession(mSessionID); +// virtual +void LLIMFloater::onClickCloseBtn() +{ +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( +				mSessionID); + +	if (session == NULL) +	{ +		llwarns << "Empty session." << llendl; +		return; +} + +	bool is_call_with_chat = session->isGroupSessionType() +			|| session->isAdHocSessionType() || session->isP2PSessionType(); + +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + +	if (is_call_with_chat && voice_channel != NULL +			&& voice_channel->isActive()) +	{ +		LLSD payload; +		payload["session_id"] = mSessionID; +		LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); +		return; +	} + +	LLIMConversation::onClickCloseBtn();  }  /* static */ -void LLIMFloater::newIMCallback(const LLSD& data){ -	 +void LLIMFloater::newIMCallback(const LLSD& data) +{  	if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())  	{  		LLUUID session_id = data["session_id"].asUUID();  		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (floater == NULL) return;          // update if visible, otherwise will be updated when opened -		if (floater->getVisible()) +		if (floater && floater->getVisible())  		{  			floater->updateMessages();  		} @@ -189,17 +192,15 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )  void LLIMFloater::sendMsg()  { -	if (!gAgent.isGodlike()  -		&& (mDialog == IM_NOTHING_SPECIAL) -		&& mOtherParticipantUUID.isNull()) +	if (gAgent.isGodlike() +		|| (mDialog != IM_NOTHING_SPECIAL) +		|| !mOtherParticipantUUID.isNull())  	{ -		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; -		return; -	} -  	if (mInputEditor)  	{ -		LLWString text = mInputEditor->getConvertedText(); +			LLWString text = mInputEditor->getWText(); +			LLWStringUtil::trim(text); +			LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines.  		if(!text.empty())  		{  			// Truncate and convert to UTF8 for transport @@ -208,8 +209,7 @@ void LLIMFloater::sendMsg()  			if (mSessionInitialized)  			{ -				LLIMModel::sendMessage(utf8_text, mSessionID, -					mOtherParticipantUUID,mDialog); +					LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog);  			}  			else  			{ @@ -223,95 +223,307 @@ void LLIMFloater::sendMsg()  		}  	}  } - - +	else +	{ +		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; +	} +}  LLIMFloater::~LLIMFloater()  { +	mParticipantsListRefreshConnection.disconnect(); +	mVoiceChannelStateChangeConnection.disconnect(); +	if(LLVoiceClient::instanceExists()) +	{ +		LLVoiceClient::getInstance()->removeObserver(this); +	} +  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);  } -//virtual -BOOL LLIMFloater::postBuild() +void LLIMFloater::initIMSession(const LLUUID& session_id) +{ +	// Change the floater key to bind it to a new session. +	setKey(session_id); + +	mSessionID = session_id; +	mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + +	if (mSession)  { -	const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); +		mIsP2PChat = mSession->isP2PSessionType(); +		mSessionInitialized = mSession->mSessionInitialized; + +		mDialog = mSession->mType; +	} +} + +void LLIMFloater::initIMFloater() +{ +	const LLUUID& other_party_id = +			LLIMModel::getInstance()->getOtherParticipantID(mSessionID);  	if (other_party_id.notNull())  	{  		mOtherParticipantUUID = other_party_id;  	} -	mControlPanel->setSessionId(mSessionID); -	mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); +	boundVoiceChannel(); + +	mTypingStart = LLTrans::getString("IM_typing_start_string"); + +	// Show control panel in torn off floaters only. +	mParticipantListPanel->setVisible(!getHost() && gSavedSettings.getBOOL("IMShowControlPanel")); + +	// Disable input editor if session cannot accept text +	if ( mSession && !mSession->mTextIMPossible ) +	{ +		mInputEditor->setEnabled(FALSE); +		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); +	} -	LLButton* slide_left = getChild<LLButton>("slide_left_btn"); -	slide_left->setVisible(mControlPanel->getParent()->getVisible()); -	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); +	if (mIsP2PChat) +	{ +		// look up display name for window title +		LLAvatarNameCache::get(mSession->mOtherParticipantID, +							   boost::bind(&LLIMFloater::onAvatarNameCache, +										   this, _1, _2)); +	} +	else +	{ +		std::string session_name(LLIMModel::instance().getName(mSessionID)); +		updateSessionName(session_name, session_name); -	LLButton* slide_right = getChild<LLButton>("slide_right_btn"); -	slide_right->setVisible(!mControlPanel->getParent()->getVisible()); -	slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); +		// For ad hoc conferences we should update the title with participants names. +		if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) +						|| mDialog == IM_SESSION_CONFERENCE_START) +		{ +			if (mParticipantsListRefreshConnection.connected()) +			{ +				mParticipantsListRefreshConnection.disconnect(); +			} + +			LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list"); +			mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback( +					boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); +		} +	} +} + +//virtual +BOOL LLIMFloater::postBuild() +{ +	BOOL result = LLIMConversation::postBuild(); -	mInputEditor = getChild<LLLineEditor>("chat_editor");  	mInputEditor->setMaxTextLength(1023);  	// enable line history support for instant message bar -	mInputEditor->setEnableLineHistory(TRUE); +	// XXX stinson TODO : resolve merge by adding autoreplace to text editors +#if 0  	// *TODO Establish LineEditor with autoreplace callback  	mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); - -	LLFontGL* font = LLViewerChat::getChatFont(); -	mInputEditor->setFont(font);	 +#endif  	mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );  	mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) ); -	mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); -	mInputEditor->setCommitOnFocusLost( FALSE ); -	mInputEditor->setRevertOnEsc( FALSE ); -	mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); -	mInputEditor->setPassDelete( TRUE ); +	mInputEditor->setKeystrokeCallback( boost::bind(onInputEditorKeystroke, _1, this) ); +	mInputEditor->setCommitCallback(boost::bind(onSendMsg, _1, this)); + +	setDocked(true); + +	LLButton* add_btn = getChild<LLButton>("add_btn"); + +	// Allow to add chat participants depending on the session type +	add_btn->setEnabled(isInviteAllowed()); +	add_btn->setClickedCallback(boost::bind(&LLIMFloater::onAddButtonClicked, this)); + +	childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); -	childSetCommitCallback("chat_editor", onSendMsg, this); +	LLVoiceClient::getInstance()->addObserver(this); -	mChatHistory = getChild<LLChatHistory>("chat_history"); +	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" +	//see LLFloaterIMPanel for how it is done (IB) -	setDocked(true); +	initIMFloater(); -	mTypingStart = LLTrans::getString("IM_typing_start_string"); +	// Add a conversation list item in the left pane +	LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); +	im_box->addConversationListItem(getTitle(), getKey(), this); -	// Disable input editor if session cannot accept text -	LLIMModel::LLIMSession* im_session = -		LLIMModel::instance().findIMSession(mSessionID); -	if( im_session && !im_session->mTextIMPossible ) +	return result; +} + +void LLIMFloater::onAddButtonClicked()  	{ -		mInputEditor->setEnabled(FALSE); -		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label")); +       LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloater::addSessionParticipants, this, _1), TRUE, TRUE); +       if (!picker) +       { +               return;  	} -	if ( im_session && im_session->isP2PSessionType()) +       // Need to disable 'ok' button when selected users are already in conversation. +       picker->setOkBtnEnableCb(boost::bind(&LLIMFloater::canAddSelectedToChat, this, _1)); +       LLFloater* root_floater = gFloaterView->getParentFloater(this); +       if (root_floater)  	{ -		// look up display name for window title -		LLAvatarNameCache::get(im_session->mOtherParticipantID, -							   boost::bind(&LLIMFloater::onAvatarNameCache, -										   this, _1, _2)); +               root_floater->addDependentFloater(picker); +	} +} + +bool LLIMFloater::canAddSelectedToChat(const uuid_vec_t& uuids) +{ +	if (!mSession +		|| mDialog == IM_SESSION_GROUP_START +		|| mDialog == IM_SESSION_INVITE && gAgent.isInGroup(mSessionID)) +	{ +		return false; +	} + +	if (mIsP2PChat) +	{ +		// For a P2P session just check if we are not adding the other participant. + +		for (uuid_vec_t::const_iterator id = uuids.begin(); +				id != uuids.end(); ++id) +		{ +			if (*id == mOtherParticipantUUID) +			{ +				return false; +			} +		}  	}  	else  	{ -		std::string session_name(LLIMModel::instance().getName(mSessionID)); -		updateSessionName(session_name, session_name); +		// For a conference session we need to check against the list from LLSpeakerMgr, +		// because this list may change when participants join or leave the session. + +		LLSpeakerMgr::speaker_list_t speaker_list; +		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +		if (speaker_mgr) +		{ +			speaker_mgr->getSpeakerList(&speaker_list, true);  	} -	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla" -	//see LLFloaterIMPanel for how it is done (IB) +		for (uuid_vec_t::const_iterator id = uuids.begin(); +				id != uuids.end(); ++id) +		{ +			for (LLSpeakerMgr::speaker_list_t::const_iterator it = speaker_list.begin(); +					it != speaker_list.end(); ++it) +			{ +				const LLPointer<LLSpeaker>& speaker = *it; +				if (*id == speaker->mID) +				{ +					return false; +				} +			} +		} +	} -	if(isChatMultiTab()) +	return true; +} + +void LLIMFloater::addSessionParticipants(const uuid_vec_t& uuids) +	{ +	if (mIsP2PChat)  	{ -		return LLFloater::postBuild(); +		mStartConferenceInSameFloater = true; + +		uuid_vec_t temp_ids; + +		// Add the initial participant of a P2P session +		temp_ids.push_back(mOtherParticipantUUID); +		temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end()); + +		LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); + +		// first check whether this is a voice session +		bool is_voice_call = voice_channel != NULL && voice_channel->isActive(); + +		// then we can close the current session +		onClose(false); + +		// Start a new ad hoc voice call if we invite new participants to a P2P call, +		// or start a text chat otherwise. +		if (is_voice_call) +		{ +			LLAvatarActions::startAdhocCall(temp_ids, mSessionID); +	} +	else +	{ +			LLAvatarActions::startConference(temp_ids, mSessionID);  	} +}  	else  	{ -		return LLDockableFloater::postBuild(); +		inviteToSession(uuids); +	} +} + +void LLIMFloater::boundVoiceChannel() +{ +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); +	if(voice_channel) +	{ +		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback( +				boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2)); + +		//call (either p2p, group or ad-hoc) can be already in started state +		bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; +		updateCallBtnState(callIsActive); +	} +} + +void LLIMFloater::enableDisableCallBtn() +{ +	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() +			&& LLVoiceClient::getInstance()->isVoiceWorking(); + +	if (mSession) +	{ +		bool session_initialized = mSession->mSessionInitialized; +		bool callback_enabled = mSession->mCallBackEnabled; + +		BOOL enable_connect = +				session_initialized && voice_enabled && callback_enabled; +		getChildView("voice_call_btn")->setEnabled(enable_connect); +	} +	else +	{ +		getChildView("voice_call_btn")->setEnabled(false); +	} +} + + +void LLIMFloater::onCallButtonClicked() +{ +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); +	if (voice_channel) +	{ +		bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; +	    if (is_call_active) +	    { +		    gIMMgr->endCall(mSessionID); +	    } +	    else +	    { +		    gIMMgr->startCall(mSessionID); +	    } +	} +} + +void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) +	{ +		enableDisableCallBtn();  	}  } +void LLIMFloater::onVoiceChannelStateChanged( +		const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +{ +	bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED; +	updateCallBtnState(callIsActive); +} +  void LLIMFloater::updateSessionName(const std::string& ui_title,  									const std::string& ui_label)  { @@ -329,58 +541,59 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,  	mTypingStart.setArg("[NAME]", ui_title);  } -// virtual -void LLIMFloater::draw() +void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)  { -	if ( mMeTyping ) +	LLAvatarList* avatar_list = dynamic_cast<LLAvatarList*>(ctrl); +	if (!avatar_list)  	{ -		// Time out if user hasn't typed for a while. -		if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS ) -		{ -			setTyping(false); +		return;  		} -	} -	LLTransientDockableFloater::draw(); -} +	bool all_names_resolved = true; +	std::vector<LLSD> participants_uuids; +	avatar_list->getValues(participants_uuids); -// static -void* LLIMFloater::createPanelIMControl(void* userdata) +	// Check whether we have all participants names in LLAvatarNameCache +	for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it)  { -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelIMControlPanel(); -	self->mControlPanel->setXMLFilename("panel_im_control_panel.xml"); -	return self->mControlPanel; -} - +		const LLUUID& id = it->asUUID(); +		LLAvatarName av_name; +		if (!LLAvatarNameCache::get(id, &av_name)) +		{ +			all_names_resolved = false; -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) -{ -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); -	self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); -	return self->mControlPanel; +			// If a name is not found in cache, request it and continue the process recursively +			// until all ids are resolved into names. +			LLAvatarNameCache::get(id, +					boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); +			break; +		}  } -// static -void* LLIMFloater::createPanelAdHocControl(void* userdata) +	if (all_names_resolved) +	{ +		std::vector<LLAvatarName> avatar_names; +		std::vector<LLSD>::const_iterator it = participants_uuids.begin(); +		for (; it != participants_uuids.end(); ++it) +		{ +			const LLUUID& id = it->asUUID(); +			LLAvatarName av_name; +			if (LLAvatarNameCache::get(id, &av_name))  { -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); -	self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); -	return self->mControlPanel; +				avatar_names.push_back(av_name); +			}  } -void LLIMFloater::onSlide() +		// We should check whether the vector is not empty to pass the assertion +		// that avatar_names.size() > 0 in LLAvatarActions::buildResidentsString. +		if (!avatar_names.empty())  { -	mControlPanel->getParent()->setVisible(!mControlPanel->getParent()->getVisible()); - -	gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getParent()->getVisible()); - -	getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible()); -	getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible()); +			std::string ui_title; +			LLAvatarActions::buildResidentsString(avatar_names, ui_title); +			updateSessionName(ui_title, ui_title); +		} +}  }  //static @@ -388,7 +601,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  {  	closeHiddenIMToasts(); -	if (!gIMMgr->hasSession(session_id)) return NULL; +	if (!gIMMgr->hasSession(session_id)) +		return NULL;  	if(!isChatMultiTab())  	{ @@ -405,22 +619,24 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  		}  	} +	// Test the existence of the floater before we try to create it  	bool exist = findInstance(session_id); +	// Get the floater: this will create the instance if it didn't exist  	LLIMFloater* floater = getInstance(session_id); -	if (!floater) return NULL; +	if (!floater) +		return NULL;  	if(isChatMultiTab())  	{  		LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance(); -		// do not add existed floaters to avoid adding torn off instances +		// Do not add again existing floaters  		if (!exist)  		{  			//		LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;  			// TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists  			LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END; -			  			if (floater_container)  			{  				floater_container->addFloater(floater, TRUE, i_pt); @@ -458,6 +674,37 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  	return floater;  } +//static +LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) +{ +    LLIMFloater* conversation = +    		LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + +	return conversation; +} + +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) +{ +	LLIMFloater* conversation = +				LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); + +	return conversation; +} + +void LLIMFloater::onClose(bool app_quitting) +{ +	setTyping(false); + +	// The source of much argument and design thrashing +	// Should the window hide or the session close when the X is clicked? +	// +	// Last change: +	// EXT-3516 X Button should end IM session, _ button should hide +	gIMMgr->leaveSession(mSessionID); + +	// Clean up the conversation *after* the session has been ended +	LLIMConversation::onClose(app_quitting); +}  void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  { @@ -516,13 +763,21 @@ void LLIMFloater::setVisible(BOOL visible)  			chiclet->setToggleState(false);  		}  	} + +	if (visible) +	{ +		sIMFloaterShowedSignal(mSessionID); +	}  }  BOOL LLIMFloater::getVisible()  { +	bool visible; +  	if(isChatMultiTab())  	{ -		LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance(); +		LLIMFloaterContainer* im_container = +				LLIMFloaterContainer::getInstance();  		// Treat inactive floater as invisible.  		bool is_active = im_container->getActiveFloater() == this; @@ -530,16 +785,21 @@ BOOL LLIMFloater::getVisible()  		//torn off floater is always inactive  		if (!is_active && getHost() != im_container)  		{ -			return LLTransientDockableFloater::getVisible(); +			visible = LLTransientDockableFloater::getVisible();  		} - +		else +		{  		// getVisible() returns TRUE when Tabbed IM window is minimized. -		return is_active && !im_container->isMinimized() && im_container->getVisible(); +			visible = is_active && !im_container->isMinimized() +						&& im_container->getVisible(); +	}  	}  	else  	{ -		return LLTransientDockableFloater::getVisible(); +		visible = LLTransientDockableFloater::getVisible();  	} + +	return visible;  }  //static @@ -547,7 +807,8 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  {  	if(!isChatMultiTab())  	{ -		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); +		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>( +				"impanel", session_id);  		if (floater && floater->getVisible() && floater->hasFocus())  		{  			// clicking on chiclet to close floater just hides it to maintain existing @@ -568,17 +829,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  	return true;  } -//static -LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) -{ -	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) -{ -	return LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); -} -  void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  {  	mSessionInitialized = true; @@ -586,53 +836,57 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  	//will be different only for an ad-hoc im session  	if (mSessionID != im_session_id)  	{ -		mSessionID = im_session_id; -		setKey(im_session_id); -		mControlPanel->setSessionId(im_session_id); -	} +		initIMSession(im_session_id); -	// updating "Call" button from group control panel here to enable it without placing into draw() (EXT-4796) -	if(gAgent.isInGroup(im_session_id)) -	{ -		mControlPanel->updateCallButton(); +		buildParticipantList();  	} + +	initIMFloater();  	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) -  	//need to send delayed messaged collected while waiting for session initialization -	if (!mQueuedMsgsForInit.size()) return; +	if (mQueuedMsgsForInit.size()) +	{  	LLSD::array_iterator iter;  	for ( iter = mQueuedMsgsForInit.beginArray(); -		iter != mQueuedMsgsForInit.endArray(); -		++iter) +				iter != mQueuedMsgsForInit.endArray(); ++iter)  	{  		LLIMModel::sendMessage(iter->asString(), mSessionID,  			mOtherParticipantUUID, mDialog);  	}  } +} -void LLIMFloater::updateMessages() +void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args)  { -	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); +	LLChat& tmp_chat = const_cast<LLChat&>(chat); +	if (!chat.mMuted) +	{ +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = !mIsP2PChat +				|| gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + +		mChatHistory->appendMessage(chat, chat_args); +	} +} + +void LLIMFloater::updateMessages() +{  	std::list<LLSD> messages;  	// we shouldn't reset unread message counters if IM floater doesn't have focus -	if (hasFocus()) -	{ -		LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); -	} -	else -	{ -		LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1); -	} +    LLIMModel::instance().getMessages( +    		mSessionID, messages, mLastMessageIndex + 1, hasFocus());  	if (messages.size())  	{ -		LLSD chat_args; -		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; -  		std::ostringstream message;  		std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();  		std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); @@ -682,7 +936,7 @@ void LLIMFloater::updateMessages()  				chat.mText = message;  			} -			mChatHistory->appendMessage(chat, chat_args); +			appendMessage(chat);  			mLastMessageIndex = msg["index"].asInteger();  			// if it is a notification - next message is a notification history log, so skip it @@ -706,6 +960,7 @@ void LLIMFloater::reloadMessages()  	mChatHistory->clear();  	mLastMessageIndex = -1;  	updateMessages(); +	mInputEditor->setFont(LLViewerChat::getChatFont());  }  // static @@ -732,19 +987,13 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd  }  // static -void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) +void LLIMFloater::onInputEditorKeystroke(LLTextEditor* caller, void* userdata)  {  	LLIMFloater* self = (LLIMFloater*)userdata;  	std::string text = self->mInputEditor->getText(); -	if (!text.empty()) -	{ -		self->setTyping(true); -	} -	else -	{ +  		// Deleting all text counts as stopping typing. -		self->setTyping(false); -	} +	self->setTyping(!text.empty());  }  void LLIMFloater::setTyping(bool typing) @@ -769,27 +1018,25 @@ void LLIMFloater::setTyping(bool typing)  	// much network traffic. Only send in person-to-person IMs.  	if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )  	{ -		if ( mMeTyping ) +		// Still typing, send 'start typing' notification or +		// send 'stop typing' notification immediately +		if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f)  		{ -			if ( mTypingTimer.getElapsedTimeF32() > 1.f ) -			{ -				// Still typing, send 'start typing' notification -				LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE); +			LLIMModel::instance().sendTypingState(mSessionID, +					mOtherParticipantUUID, mMeTyping);  				mShouldSendTypingState = false; +  			}  		} -		else -		{ -			// Send 'stop typing' notification immediately -			LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE); -			mShouldSendTypingState = false; -		} -	} +	if (!mIsNearbyChat) +		{  	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);  	if (speaker_mgr) +		{  		speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); - +		} +}  }  void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) @@ -808,9 +1055,7 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)  void LLIMFloater::processAgentListUpdates(const LLSD& body)  { -	if ( !body.isMap() ) return; - -	if ( body.has("agent_updates") && body["agent_updates"].isMap() ) +	if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap())  	{  		LLSD agent_data = body["agent_updates"].get(gAgentID.asString());  		if (agent_data.isMap() && agent_data.has("info")) @@ -835,30 +1080,6 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body)  	}  } -void LLIMFloater::updateChatHistoryStyle() -{ -	mChatHistory->clear(); -	mLastMessageIndex = -1; -	updateMessages(); -} - -void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) -{ -	LLFontGL* font = LLViewerChat::getChatFont(); -	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); -	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); -		 iter != inst_list.end(); ++iter) -	{ -		LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); -		if (floater) -		{ -			floater->updateChatHistoryStyle(); -			floater->mInputEditor->setFont(font); -		} -	} - -} -  void LLIMFloater::processSessionUpdate(const LLSD& session_update)  {  	// *TODO : verify following code when moderated mode will be implemented @@ -870,7 +1091,8 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)  		if (voice_moderated)  		{ -			setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label")); +			setTitle(session_label + std::string(" ") +							+ LLTrans::getString("IM_moderated_chat_label"));  		}  		else  		{ @@ -883,98 +1105,56 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)  	}  } -BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, -						   BOOL drop, EDragAndDropType cargo_type, -						   void *cargo_data, EAcceptance *accept, +// virtual +BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +									EDragAndDropType cargo_type, +									void* cargo_data, +									EAcceptance* accept,  						   std::string& tooltip_msg)  { - -	if (mDialog == IM_NOTHING_SPECIAL) +	if (cargo_type == DAD_PERSON)  	{ -		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, -												 cargo_type, cargo_data, accept); +		if (dropPerson(static_cast<LLUUID*>(cargo_data), drop)) +	{ +			*accept = ACCEPT_YES_MULTI;  	} - -	// handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites -	else if (isInviteAllowed()) +		else  	{  		*accept = ACCEPT_NO; - -		if (cargo_type == DAD_CALLINGCARD) -		{ -			if (dropCallingCard((LLInventoryItem*)cargo_data, drop)) -			{ -				*accept = ACCEPT_YES_MULTI;  			}  		} -		else if (cargo_type == DAD_CATEGORY) +	else if (mDialog == IM_NOTHING_SPECIAL)  		{ -			if (dropCategory((LLInventoryCategory*)cargo_data, drop)) -			{ -				*accept = ACCEPT_YES_MULTI; +		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, +				cargo_type, cargo_data, accept);  			} -		} -	} +  	return TRUE;  } -BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop) +bool LLIMFloater::dropPerson(LLUUID* person_id, bool drop)  { -	BOOL rv = isInviteAllowed(); -	if(rv && item && item->getCreatorUUID().notNull()) +	bool res = person_id && person_id->notNull(); +	if(res)  	{ -		if(drop) -		{  			uuid_vec_t ids; -			ids.push_back(item->getCreatorUUID()); -			inviteToSession(ids); -		} -	} -	else +		ids.push_back(*person_id); + +		res = canAddSelectedToChat(ids); +		if(res && drop)  	{ -		// set to false if creator uuid is null. -		rv = FALSE; +			addSessionParticipants(ids);  	} -	return rv;  } -BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop) -{ -	BOOL rv = isInviteAllowed(); -	if(rv && category) -	{ -		LLInventoryModel::cat_array_t cats; -		LLInventoryModel::item_array_t items; -		LLUniqueBuddyCollector buddies; -		gInventory.collectDescendentsIf(category->getUUID(), -										cats, -										items, -										LLInventoryModel::EXCLUDE_TRASH, -										buddies); -		S32 count = items.count(); -		if(count == 0) -		{ -			rv = FALSE; +	return res;  		} -		else if(drop) -		{ -			uuid_vec_t ids; -			ids.reserve(count); -			for(S32 i = 0; i < count; ++i) -			{ -				ids.push_back(items.get(i)->getCreatorUUID()); -			} -			inviteToSession(ids); -		} -	} -	return rv; -}  BOOL LLIMFloater::isInviteAllowed() const  { -  	return ( (IM_SESSION_CONFERENCE_START == mDialog) -			 || (IM_SESSION_INVITE == mDialog) ); +			 || (IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) +			 || mIsP2PChat);  }  class LLSessionInviteResponder : public LLHTTPClient::Responder @@ -998,11 +1178,10 @@ private:  BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)  {  	LLViewerRegion* region = gAgent.getRegion(); -	if (!region) -	{ -		return FALSE; -	} +	bool is_region_exist = region != NULL; +	if (is_region_exist) +	{  	S32 count = ids.size();  	if( isInviteAllowed() && (count > 0) ) @@ -1024,8 +1203,7 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)  		LLHTTPClient::post(  			url,  			data, -			new LLSessionInviteResponder( -					mSessionID)); +					new LLSessionInviteResponder(mSessionID));  	}  	else  	{ @@ -1035,8 +1213,9 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)  		// successful add, because everyone that needed to get added  		// was added.  	} +	} -	return TRUE; +	return is_region_exist;  }  void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info) @@ -1077,7 +1256,6 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)  				speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);  			}  		} -  	}  } @@ -1094,7 +1272,8 @@ void LLIMFloater::closeHiddenIMToasts()  		}  	}; -	LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); +	LLNotificationsUI::LLScreenChannel* channel = +			LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();  	if (channel != NULL)  	{  		channel->closeHiddenToasts(IMToastMatcher()); @@ -1107,7 +1286,7 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&  	const LLSD& payload = notification["payload"];  	LLUUID session_id = payload["session_id"]; -	LLFloater* im_floater = LLFloaterReg::findInstance("impanel", session_id); +	LLFloater* im_floater = findInstance(session_id);  	if (option == 0 && im_floater != NULL)  	{  		im_floater->closeFloater(); @@ -1117,79 +1296,49 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&  }  // static -bool LLIMFloater::isChatMultiTab() -{ -	// Restart is required in order to change chat window type. -	static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; -	return is_single_window; -} - -// static -void LLIMFloater::initIMFloater() -{ -	// This is called on viewer start up -	// init chat window type before user changed it in preferences -	isChatMultiTab(); -} - -//static  void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)  {  	LLUUID session_id = data["session_id"]; -	if (session_id.isNull()) return; +	if (session_id.isNull()) +		return;  	LLUUID from_id = data["from_id"]; -	if (gAgentID == from_id || LLUUID::null == from_id) return; +	if (gAgentID == from_id || LLUUID::null == from_id) +		return;  	LLIMFloater* floater = LLIMFloater::findInstance(session_id); -	if (!floater) return; +	if (!floater) +		return; -	if (IM_NOTHING_SPECIAL != floater->mDialog) return; +	if (IM_NOTHING_SPECIAL != floater->mDialog) +		return;  	floater->removeTypingIndicator();  }  void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )  { - -	if (isChatMultiTab()) -	{ -		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); -		if (!im_box) return; - -		if (LLIMFloater::findInstance(session_id)) return; - -		LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); - -		im_box->addFloater(new_tab, FALSE, LLTabContainer::END); -	} - +	LLIMFloater::addToHost(session_id);  } - -void	LLIMFloater::onClickCloseBtn() +void LLIMFloater::addToHost(const LLUUID& session_id) +	{ +	if (LLIMConversation::isChatMultiTab())  { - -	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( -				mSessionID); - -	if (session == NULL) +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); +		if (!im_box)  	{ -		llwarns << "Empty session." << llendl; -		return; +			im_box = LLIMFloaterContainer::getInstance();  	} -	bool is_call_with_chat = session->isGroupSessionType() -			|| session->isAdHocSessionType() || session->isP2PSessionType(); - -	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); - -	if (is_call_with_chat && voice_channel != NULL && voice_channel->isActive()) +		if (im_box && !LLIMFloater::findInstance(session_id))  	{ -		LLSD payload; -		payload["session_id"] = mSessionID; -		LLNotificationsUtil::add("ConfirmLeaveCall", LLSD(), payload, confirmLeaveCallCallback); -		return; +			LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); +			im_box->addFloater(new_tab, FALSE, LLTabContainer::END);  	} +	} +} -	LLFloater::onClickCloseBtn(); +boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) +{ +	return LLIMFloater::sIMFloaterShowedSignal.connect(cb);  } diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f7cd35b5eb..434613ff43 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -27,41 +27,55 @@  #ifndef LL_IMFLOATER_H  #define LL_IMFLOATER_H +#include "llimview.h" +#include "llimconversation.h"  #include "llinstantmessage.h"  #include "lllogchat.h"  #include "lltooldraganddrop.h" -#include "lltransientdockablefloater.h" +#include "llvoicechannel.h" +#include "llvoiceclient.h"  class LLAvatarName; -class LLLineEditor; +class LLButton; +class LLChatEntry; +class LLTextEditor;  class LLPanelChatControlPanel;  class LLChatHistory;  class LLInventoryItem;  class LLInventoryCategory; +typedef boost::signals2::signal<void(const LLUUID& session_id)> floater_showed_signal_t; +  /**   * Individual IM window that appears at the bottom of the screen,   * optionally "docked" to the bottom tray.   */ -class LLIMFloater : public LLTransientDockableFloater +class LLIMFloater +    : public LLVoiceClientStatusObserver +    , public LLIMConversation  {  	LOG_CLASS(LLIMFloater);  public:  	LLIMFloater(const LLUUID& session_id);  	virtual ~LLIMFloater(); -	 + +	void initIMSession(const LLUUID& session_id); +	void initIMFloater(); +  	// LLView overrides  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible);  	/*virtual*/ BOOL getVisible();  	// Check typing timeout timer. -	/*virtual*/ void draw(); + +	static LLIMFloater* findInstance(const LLUUID& session_id); +	static LLIMFloater* getInstance(const LLUUID& session_id); +	static void addToHost(const LLUUID& session_id);  	// LLFloater overrides  	/*virtual*/ void onClose(bool app_quitting);  	/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); -  	// Make IM conversion visible and update the message history  	static LLIMFloater* show(const LLUUID& session_id); @@ -69,16 +83,12 @@ public:  	// Returns true iff panel became visible  	static bool toggle(const LLUUID& session_id); -	static LLIMFloater* findInstance(const LLUUID& session_id); - -	static LLIMFloater* getInstance(const LLUUID& session_id); -  	void sessionInitReplyReceived(const LLUUID& im_session_id);  	// get new messages from LLIMModel  	void updateMessages();  	void reloadMessages(); -	static void onSendMsg( LLUICtrl*, void*); +	static void onSendMsg(LLUICtrl*, void*);  	void sendMsg();  	// callback for LLIMModel on new messages @@ -89,62 +99,76 @@ public:  	void setPositioned(bool b) { mPositioned = b; };  	void onVisibilityChange(const LLSD& new_visibility); + +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	void onChange(EStatusType status, const std::string &channelURI, +			bool proximal); + +	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } +	virtual void onVoiceChannelStateChanged( +			const LLVoiceChannel::EState& old_state, +			const LLVoiceChannel::EState& new_state); +  	void processIMTyping(const LLIMInfo* im_info, BOOL typing);  	void processAgentListUpdates(const LLSD& body);  	void processSessionUpdate(const LLSD& session_update); -	void updateChatHistoryStyle(); -	static void processChatHistoryStyleUpdate(const LLSD& newvalue); - -	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, -							   BOOL drop, EDragAndDropType cargo_type, -							   void *cargo_data, EAcceptance *accept, -							   std::string& tooltip_msg); - -	/** -	 * Returns true if chat is displayed in multi tabbed floater -	 *         false if chat is displayed in multiple windows -	 */ -	static bool isChatMultiTab(); +	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +									   EDragAndDropType cargo_type, +									   void* cargo_data, +									   EAcceptance* accept, +									   std::string& tooltip_msg); -	static void initIMFloater();  	//used as a callback on receiving new IM message  	static void sRemoveTypingIndicator(const LLSD& data); -  	static void onIMChicletCreated(const LLUUID& session_id); -	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } +	bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } -protected: -	/* virtual */ -	void	onClickCloseBtn(); +	static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); +	static floater_showed_signal_t sIMFloaterShowedSignal;  private: +  	// process focus events to set a currently active session  	/* virtual */ void onFocusLost();  	/* virtual */ void onFocusReceived(); +	/*virtual*/ void refresh(); + +	/*virtual*/ void onClickCloseBtn(); +  	// Update the window title, input field help text, etc.  	void updateSessionName(const std::string& ui_title, const std::string& ui_label); -	 +  	// For display name lookups for IM window titles  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); -	 -	BOOL dropCallingCard(LLInventoryItem* item, BOOL drop); -	BOOL dropCategory(LLInventoryCategory* category, BOOL drop); + +	/// Updates the list of ad hoc conference participants +	/// in an IM floater title. +	void onParticipantsListChanged(LLUICtrl* ctrl); + +	bool dropPerson(LLUUID* person_id, bool drop);  	BOOL isInviteAllowed() const;  	BOOL inviteToSession(const uuid_vec_t& agent_ids); -	 -	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); -	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); -	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata); -	void			setTyping(bool typing); -	void			onSlide(); -	static void*	createPanelIMControl(void* userdata); -	static void*	createPanelGroupControl(void* userdata); -	static void* 	createPanelAdHocControl(void* userdata); +	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); +	static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); +	static void onInputEditorKeystroke(LLTextEditor* caller, void* userdata); +	void setTyping(bool typing); +	void onAddButtonClicked(); +	void addSessionParticipants(const uuid_vec_t& uuids); +	bool canAddSelectedToChat(const uuid_vec_t& uuids); + +	void onCallButtonClicked(); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	void boundVoiceChannel();  	// Add the "User is typing..." indicator.  	void addTypingIndicator(const LLIMInfo* im_info); @@ -156,14 +180,12 @@ private:  	static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); -	LLPanelChatControlPanel* mControlPanel; -	LLUUID mSessionID; + +	LLIMModel::LLIMSession* mSession;  	S32 mLastMessageIndex;  	EInstantMessage mDialog;  	LLUUID mOtherParticipantUUID; -	LLChatHistory* mChatHistory; -	LLLineEditor* mInputEditor;  	bool mPositioned;  	std::string mSavedTitle; @@ -176,7 +198,13 @@ private:  	bool mSessionInitialized;  	LLSD mQueuedMsgsForInit; -}; +	bool mStartConferenceInSameFloater; + +	// connection to voice channel state change signal +	boost::signals2::connection mVoiceChannelStateChangeConnection; + +	boost::signals2::connection mParticipantsListRefreshConnection; +};  #endif  // LL_IMFLOATER_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 0f0ae896a2..c2c0ddddea 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -27,20 +27,34 @@  #include "llviewerprecompiledheaders.h" +#include "llimfloater.h"  #include "llimfloatercontainer.h" +  #include "llfloaterreg.h" -#include "llimview.h" +#include "lllayoutstack.h" +#include "llnearbychat.h" + +#include "llagent.h" +#include "llavataractions.h"  #include "llavatariconctrl.h" +#include "llavatarnamecache.h"  #include "llgroupiconctrl.h" -#include "llagent.h" +#include "llfloateravatarpicker.h" +#include "llimview.h"  #include "lltransientfloatermgr.h" +#include "llviewercontrol.h"  //  // LLIMFloaterContainer  //  LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -:	LLMultiFloater(seed) +:	LLMultiFloater(seed), +	mExpandCollapseBtn(NULL), +	mConversationsRoot(NULL)  { +	// Firstly add our self to IMSession observers, so we catch session events +    LLIMMgr::getInstance()->addSessionObserver(this); +  	mAutoResize = FALSE;  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);  } @@ -49,6 +63,26 @@ LLIMFloaterContainer::~LLIMFloaterContainer()  {  	mNewMessageConnection.disconnect();  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); + +	gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); +	gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); + +	if (!LLSingleton<LLIMMgr>::destroyed()) +	{ +		LLIMMgr::getInstance()->removeSessionObserver(this); +	} +} + +void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) +{ +	LLIMFloater::show(session_id); +} + +void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) +{ +	LLIMFloater* floaterp = LLIMFloater::findInstance(session_id); +	LLFloater::onClickClose(floaterp); +	removeConversationListItem(floaterp);  }  BOOL LLIMFloaterContainer::postBuild() @@ -56,24 +90,47 @@ BOOL LLIMFloaterContainer::postBuild()  	mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1));  	// Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button  	// mTabContainer will be initialized in LLMultiFloater::addChild() +	 +	setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + +	mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); +	mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); +	mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); +	 +	mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + +	// CHUI-98 : View Model for conversations +	LLConversationItem* base_item = new LLConversationItem(this); +	LLFolderView::Params p; +	p.view_model = &mConversationViewModel; +	p.parent_panel = mConversationsListPanel; +	p.rect = mConversationsListPanel->getLocalRect(); +	p.follows.flags = FOLLOWS_ALL; +	p.listener = base_item; +	p.root = NULL; + +	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); +	mConversationsListPanel->addChild(mConversationsRoot); + +	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); +	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); + +	childSetAction("add_btn", boost::bind(&LLIMFloaterContainer::onAddButtonClicked, this)); + +	collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); +	collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); +	LLAvatarNameCache::addUseDisplayNamesCallback( +			boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); +  	return TRUE;  }  void LLIMFloaterContainer::onOpen(const LLSD& key)  {  	LLMultiFloater::onOpen(key); -/* -	if (key.isDefined()) -	{ -		LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); -		if (im_floater) -		{ -			im_floater->openFloater(); -		} -	} -*/  } +// virtual  void LLIMFloaterContainer::addFloater(LLFloater* floaterp,   									BOOL select_added_floater,   									LLTabContainer::eInsertionPoint insertion_point) @@ -86,11 +143,15 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  		openFloater(floaterp->getKey());  		return;  	} +	 +	// Make sure the message panel is open when adding a floater or it stays mysteriously hidden +	collapseMessagesPane(false); +	// Add the floater  	LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);  	LLUUID session_id = floaterp->getKey(); - +	  	LLIconCtrl* icon = 0;  	if(gAgent.isInGroup(session_id, TRUE)) @@ -113,15 +174,52 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  		mSessions[session_id] = floaterp;  		floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id));  	} + +	// forced resize of the floater +	LLRect wrapper_rect = this->mTabContainer->getLocalRect(); +	floaterp->setRect(wrapper_rect); +  	mTabContainer->setTabImage(floaterp, icon);  } +  void LLIMFloaterContainer::onCloseFloater(LLUUID& id)  {  	mSessions.erase(id);  	setFocus(TRUE);  } +// virtual +void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ +	bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); +	bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + +	S32 conversations_pane_min_dim = mConversationsPane->getMinDim(); + +	if (is_right_pane_expanded) +	{ +		S32 conversations_pane_width = +				(is_left_pane_expanded ? gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") : conversations_pane_min_dim); + +		// possibly increase minimum size constraint due to children's minimums. +		for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +		{ +			LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); +			if (floaterp) +			{ +				new_min_width = llmax(new_min_width, +						floaterp->getMinWidth() + conversations_pane_width + LLPANEL_BORDER_WIDTH * 2); +				new_min_height = llmax(new_min_height, floaterp->getMinHeight()); +			} +		} +	} +	else +	{ +		new_min_width = conversations_pane_min_dim; +	} +} +  void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)  {  	LLUUID session_id = data["session_id"].asUUID(); @@ -136,6 +234,21 @@ void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)  	}  } +void LLIMFloaterContainer::onExpandCollapseButtonClicked() +{ +	if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() +			&& gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst")) +	{ +		// Expand the messages pane from ultra minimized state +		// if it was collapsed last in order. +		collapseMessagesPane(false); +	} +	else +	{ +		collapseConversationsPane(!mConversationsPane->isCollapsed()); +	} +} +  LLIMFloaterContainer* LLIMFloaterContainer::findInstance()  {  	return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container"); @@ -151,8 +264,6 @@ void LLIMFloaterContainer::setMinimized(BOOL b)  	if (isMinimized() == b) return;  	LLMultiFloater::setMinimized(b); -	// Hide minimized floater (see EXT-5315) -	setVisible(!b);  	if (isMinimized()) return; @@ -162,4 +273,267 @@ void LLIMFloaterContainer::setMinimized(BOOL b)  	}  } +void LLIMFloaterContainer::draw() +{ +	if (mTabContainer->getTabCount() == 0) +	{ +		// Do not close the container when every conversation is torn off because the user +		// still needs the conversation list. Simply collapse the message pane in that case. +		collapseMessagesPane(true); +	} +	LLFloater::draw(); + +	repositioningWidgets(); +} + +void LLIMFloaterContainer::tabClose() +{ +	if (mTabContainer->getTabCount() == 0) +	{ +		// Do not close the container when every conversation is torn off because the user +		// still needs the conversation list. Simply collapse the message pane in that case. +		collapseMessagesPane(true); +	} +} + +void LLIMFloaterContainer::setVisible(BOOL visible) +{ +	if (visible) +	{ +		// Make sure we have the Nearby Chat present when showing the conversation container +		LLFloater* nearby_chat = LLFloaterReg::findInstance("chat_bar"); +		if (nearby_chat == NULL) +		{ +			// If not found, force the creation of the nearby chat conversation panel +			// *TODO: find a way to move this to XML as a default panel or something like that +			LLSD name("chat_bar"); +			LLFloaterReg::toggleInstanceOrBringToFront(name); +		} +	} + +	// We need to show/hide all the associated conversations that have been torn off +	// (and therefore, are not longer managed by the multifloater), +	// so that they show/hide with the conversations manager. +	conversations_items_map::iterator item_it = mConversationsItems.begin(); +	for (;item_it != mConversationsItems.end(); ++item_it) +	{ +		LLConversationItem* item = item_it->second; +		item->setVisibleIfDetached(visible); +	} +	 +	// Now, do the normal multifloater show/hide +	LLMultiFloater::setVisible(visible); +	 +} + +void LLIMFloaterContainer::collapseMessagesPane(bool collapse) +{ +	if (mMessagesPane->isCollapsed() == collapse) +	{ +		return; +	} + +	if (collapse) +	{ +		// Save the messages pane width before collapsing it. +		gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + +		// Save the order in which the panels are closed to reverse user's last action. +		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); +	} + +	// Show/hide the messages pane. +	mConversationsStack->collapsePanel(mMessagesPane, collapse); + +	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); +} + +void LLIMFloaterContainer::collapseConversationsPane(bool collapse) +{ +	if (mConversationsPane->isCollapsed() == collapse) +	{ +		return; +	} + +	LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded"); +	button_panel->setVisible(!collapse); +	mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + +	if (collapse) +	{ +		// Save the conversations pane width before collapsing it. +		gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + +		// Save the order in which the panels are closed to reverse user's last action. +		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); +	} + +	mConversationsStack->collapsePanel(mConversationsPane, collapse); + +	S32 collapsed_width = mConversationsPane->getMinDim(); +	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); +} + +void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) +{ +	LLRect floater_rect = getRect(); +	floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); + +	// Set by_user = true so that reshaped rect is saved in user_settings. +	setShape(floater_rect, true); + +	updateResizeLimits(); + +	bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); +	bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + +	setCanResize(is_left_pane_expanded || is_right_pane_expanded); +	setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); +} + +void LLIMFloaterContainer::onAddButtonClicked() +{ +    LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE); +    LLFloater* root_floater = gFloaterView->getParentFloater(this); +    if (picker && root_floater) +    { +        root_floater->addDependentFloater(picker); +    } +} + +void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids) +{ +    if (ids.size() == 1) +    { +        LLAvatarActions::startIM(ids.back()); +    } +    else +    { +        LLAvatarActions::startConference(ids); +    } +} + +void LLIMFloaterContainer::repositioningWidgets() +{ +	LLRect panel_rect = mConversationsListPanel->getRect(); +	S32 item_height = 16; +	int index = 0; +	for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); +		 widget_it != mConversationsWidgets.end(); +		 widget_it++, ++index) +	{ +		LLFolderViewItem* widget = widget_it->second; +		widget->setVisible(TRUE); +		widget->setRect(LLRect(0, +							   panel_rect.getHeight() - item_height*index, +							   panel_rect.getWidth(), +							   panel_rect.getHeight() - item_height*(index+1))); +	} +} + +// CHUI-137 : Temporary implementation of conversations list +void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp) +{ +	// Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) +	// Note: this happens often, when reattaching a torn off conversation for instance +	conversations_items_map::iterator item_it = mConversationsItems.find(floaterp); +	if (item_it != mConversationsItems.end()) +	{ +		LLConversationItem* item = item_it->second; +		// Check if the item has changed +		if (item->hasSameValues(name,uuid)) +		{ +			// If it hasn't changed, nothing to do -> exit +			return; +		} +	} +	 +	// Remove the conversation item that might exist already: it'll be recreated anew further down anyway +	// and nothing wrong will happen removing it if it doesn't exist +	removeConversationListItem(floaterp,false); + +	// Create a conversation item +	LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this); +	mConversationsItems[floaterp] = item; + +	// Create a widget from it +	LLFolderViewItem* widget = createConversationItemWidget(item); +	mConversationsWidgets[floaterp] = widget; + +	// Add a new conversation widget to the root folder of a folder view. +	widget->addToFolder(mConversationsRoot); + +	// Add it to the UI +	widget->setVisible(TRUE); + +	repositioningWidgets(); +	 +	mConversationsListPanel->addChild(widget); + +	return; +} + +void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, bool change_focus) +{ +	// Delete the widget and the associated conversation item +	// Note : since the mConversationsItems is also the listener to the widget, deleting  +	// the widget will also delete its listener +	conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(floaterp); +	if (widget_it != mConversationsWidgets.end()) +	{ +		LLFolderViewItem* widget = widget_it->second; +		widget->destroyView(); +	} +	 +	// Suppress the conversation items and widgets from their respective maps +	mConversationsItems.erase(floaterp); +	mConversationsWidgets.erase(floaterp); + +	repositioningWidgets(); +	 +	// Don't let the focus fall IW, select and refocus on the first conversation in the list +	if (change_focus) +	{ +		setFocus(TRUE); +		conversations_items_map::iterator item_it = mConversationsItems.begin(); +		if (item_it != mConversationsItems.end()) +		{ +			LLConversationItem* item = item_it->second; +			item->selectItem(); +		} +	} +	return; +} + +LLFloater* LLIMFloaterContainer::findConversationItem(LLUUID& uuid) +{ +	LLFloater* floaterp = NULL; +	for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it) +	{ +		LLConversationItem* item = item_it->second; +		if (item->hasSameValue(uuid)) +		{ +			floaterp = item_it->first; +			break; +		} +	} +	return floaterp; +} + +LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) +{ +	LLFolderViewItem::Params params; +	 +	params.name = item->getDisplayName(); +	//params.icon = bridge->getIcon(); +	//params.icon_open = bridge->getOpenIcon(); +	//params.creation_date = bridge->getCreationDate(); +	params.root = mConversationsRoot; +	params.listener = item; +	params.rect = LLRect (0, 0, 0, 0); +	params.tool_tip = params.name; +	 +	return LLUICtrlFactory::create<LLFolderViewItem>(params); +} +  // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 892ecef48d..161c6d9806 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -30,14 +30,22 @@  #include <map>  #include <vector> +#include "llimview.h"  #include "llfloater.h"  #include "llmultifloater.h"  #include "llavatarpropertiesprocessor.h"  #include "llgroupmgr.h" +#include "llconversationmodel.h" +class LLButton; +class LLLayoutPanel; +class LLLayoutStack;  class LLTabContainer; +class LLIMFloaterContainer; -class LLIMFloaterContainer : public LLMultiFloater +class LLIMFloaterContainer +	: public LLMultiFloater +	, public LLIMSessionObserver  {  public:  	LLIMFloaterContainer(const LLSD& seed); @@ -45,12 +53,16 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void draw(); +	/*virtual*/ void setVisible(BOOL visible);  	void onCloseFloater(LLUUID& id);  	/*virtual*/ void addFloater(LLFloater* floaterp,   								BOOL select_added_floater,   								LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); +	/*virtual*/ void tabClose(); +  	static LLFloater* getCurrentVoiceFloater();  	static LLIMFloaterContainer* findInstance(); @@ -59,12 +71,54 @@ public:  	virtual void setMinimized(BOOL b); +	void collapseMessagesPane(bool collapse); +	 + +	// LLIMSessionObserver observe triggers +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}; +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id); +	/*virtual*/ void sessionRemoved(const LLUUID& session_id); +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}; +	LLConversationViewModel& getRootViewModel() { return mConversationViewModel; } +  private:  	typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;  	avatarID_panel_map_t mSessions;  	boost::signals2::connection mNewMessageConnection; +	/*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); +  	void onNewMessageReceived(const LLSD& data); + +	void onExpandCollapseButtonClicked(); + +	void collapseConversationsPane(bool collapse); + +	void updateState(bool collapse, S32 delta_width); +	void repositioningWidgets(); + +	void onAddButtonClicked(); +	void onAvatarPicked(const uuid_vec_t& ids); + +	LLButton* mExpandCollapseBtn; +	LLLayoutPanel* mMessagesPane; +	LLLayoutPanel* mConversationsPane; +	LLLayoutStack* mConversationsStack; +	 +	// Conversation list implementation +public: +	void removeConversationListItem(LLFloater* floaterp, bool change_focus = true); +	void addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp); +	LLFloater* findConversationItem(LLUUID& uuid); +private: +	LLFolderViewItem* createConversationItemWidget(LLConversationItem* item); + +	// Conversation list data +	LLPanel* mConversationsListPanel;	// This is the main widget we add conversation widget to +	conversations_items_map mConversationsItems; +	conversations_widgets_map mConversationsWidgets; +	LLConversationViewModel mConversationViewModel; +	LLFolderView* mConversationsRoot;  };  #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 07d73c8c66..047472a282 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -37,10 +37,9 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) +LLIMHandler::LLIMHandler() +:	LLSysHandler("IM Notifications", "notifytoast")  { -	mType = type; -  	// Getting a Channel for our notifications  	mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle();  } @@ -59,72 +58,49 @@ void LLIMHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLIMHandler::processNotification(const LLSD& notify) +bool LLIMHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ -		LLSD substitutions = notification->getSubstitutions(); - -		// According to comments in LLIMMgr::addMessage(), if we get message -		// from ourselves, the sender id is set to null. This fixes EXT-875. -		LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); -		if (avatar_id.isNull()) -			avatar_id = gAgentID; - -		LLToastIMPanel::Params im_p; -		im_p.notification = notification; -		im_p.avatar_id = avatar_id; -		im_p.from = substitutions["FROM"].asString(); -		im_p.time = substitutions["TIME"].asString(); -		im_p.message = substitutions["MESSAGE"].asString(); -		im_p.session_id = substitutions["SESSION_ID"].asUUID(); - -		LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.session_id = im_p.session_id; -		p.notification = notification; -		p.panel = im_box; -		p.can_be_stored = false; -		p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); - -		// send a signal to the counter manager; -		mNewNotificationSignal(); -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); -	} -	return false; -} +	LLSD substitutions = notification->getSubstitutions(); + +	// According to comments in LLIMMgr::addMessage(), if we get message +	// from ourselves, the sender id is set to null. This fixes EXT-875. +	LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); +	if (avatar_id.isNull()) +		avatar_id = gAgentID; + +	LLToastIMPanel::Params im_p; +	im_p.notification = notification; +	im_p.avatar_id = avatar_id; +	im_p.from = substitutions["FROM"].asString(); +	im_p.time = substitutions["TIME"].asString(); +	im_p.message = substitutions["MESSAGE"].asString(); +	im_p.session_id = substitutions["SESSION_ID"].asUUID(); + +	LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.session_id = im_p.session_id; +	p.notification = notification; +	p.panel = im_box; +	p.can_be_stored = false; +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); -//-------------------------------------------------------------------------- -void LLIMHandler::onDeleteToast(LLToast* toast) -{ -	// send a signal to the counter manager -	mDelNotificationSignal(); +	return false;  } -//-------------------------------------------------------------------------- diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4000570872..d88a558125 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -41,7 +41,7 @@  #include "lltextutil.h"  #include "lltrans.h"  #include "lluictrlfactory.h" - +#include "llimconversation.h"  #include "llagent.h"  #include "llagentui.h"  #include "llappviewer.h" @@ -175,10 +175,11 @@ LLIMModel::LLIMModel()  	addNewMsgCallback(boost::bind(&toast_callback, _1));  } -LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) +LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)  :	mSessionID(session_id),  	mName(name),  	mType(type), +	mHasOfflineMessage(has_offline_msg),  	mParticipantUnreadMessageCount(0),  	mNumUnread(0),  	mOtherParticipantID(other_participant_id), @@ -375,6 +376,8 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  				break;  			}  		} +	default: +		break;  	}  	// Update speakers list when connected  	if (LLVoiceChannel::STATE_CONNECTED == new_state) @@ -676,7 +679,7 @@ void LLIMModel::testMessages()  //session name should not be empty  bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,  -						   const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice) +						   const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)  {  	if (name.empty())  	{ @@ -690,7 +693,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co  		return false;  	} -	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice); +	LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg);  	mId2SessionMap[session_id] = session;  	// When notifying observer, name of session is used instead of "name", because they may not be the @@ -702,10 +705,10 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co  } -bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice) +bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice, bool has_offline_msg)  {  	uuid_vec_t no_ids; -	return newSession(session_id, name, type, other_participant_id, no_ids, voice); +	return newSession(session_id, name, type, other_participant_id, no_ids, voice, has_offline_msg);  }  bool LLIMModel::clearSession(const LLUUID& session_id) @@ -716,6 +719,16 @@ bool LLIMModel::clearSession(const LLUUID& session_id)  	return true;  } +void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index, const bool sendNoUnreadMsgs) +{ +	getMessagesSilently(session_id, messages, start_index); + +	if (sendNoUnreadMsgs) +	{ +		sendNoUnreadMessages(session_id); +	} +} +  void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)  {  	LLIMSession* session = findIMSession(session_id); @@ -757,13 +770,6 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id)  	mNoUnreadMsgsSignal(arg);  } -void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) -{ -	getMessagesSilently(session_id, messages, start_index); - -	sendNoUnreadMessages(session_id); -} -  bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {  	LLIMSession* session = findIMSession(session_id); @@ -904,7 +910,7 @@ const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const  	LLIMSession* session = findIMSession(session_id);  	if (!session)  	{ -		llwarns << "session " << session_id << "does not exist " << llendl; +		llwarns << "session " << session_id << " does not exist " << llendl;  		return LLUUID::null;  	} @@ -2395,6 +2401,7 @@ void LLIMMgr::addMessage(  	const LLUUID& target_id,  	const std::string& from,  	const std::string& msg, +	bool  is_offline_msg,  	const std::string& session_name,  	EInstantMessage dialog,  	U32 parent_estate_id, @@ -2420,7 +2427,7 @@ void LLIMMgr::addMessage(  	bool new_session = !hasSession(new_session_id);  	if (new_session)  	{ -		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id); +		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg);  		// When we get a new IM, and if you are a god, display a bit  		// of information about the source. This is to help liaisons @@ -2480,8 +2487,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  		LLChat chat(message);  		chat.mSourceType = CHAT_SOURCE_SYSTEM; -		LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -		LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); +		LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();  		if(nearby_chat)  		{ @@ -2497,6 +2503,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  			gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());  		}  		// log message to file +  		else  		{  			std::string session_name; @@ -2579,7 +2586,8 @@ LLUUID LLIMMgr::addSession(  {  	LLDynamicArray<LLUUID> ids;  	ids.put(other_participant_id); -	return addSession(name, dialog, other_participant_id, ids, voice); +	LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voice); +	return session_id;  }  // Adds a session using the given session_id.  If the session already exists  @@ -2588,7 +2596,8 @@ LLUUID LLIMMgr::addSession(  	const std::string& name,  	EInstantMessage dialog,  	const LLUUID& other_participant_id, -	const LLDynamicArray<LLUUID>& ids, bool voice) +	const LLDynamicArray<LLUUID>& ids, bool voice, +	const LLUUID& floater_id)  {  	if (0 == ids.getLength())  	{ @@ -2603,6 +2612,19 @@ LLUUID LLIMMgr::addSession(  	LLUUID session_id = computeSessionID(dialog,other_participant_id); +	if (floater_id.notNull()) +	{ +		LLIMFloater* im_floater = LLIMFloater::findInstance(floater_id); + +		if (im_floater && im_floater->getStartConferenceInSameFloater()) +		{ +			// The IM floater should be initialized with a new session_id +			// so that it is found by that id when creating a chiclet in LLIMFloater::onIMChicletCreated, +			// and a new floater is not created. +			im_floater->initIMSession(session_id); +		} +	} +  	bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);  	//works only for outgoing ad-hoc sessions @@ -2634,6 +2656,8 @@ LLUUID LLIMMgr::addSession(  		noteMutedUsers(session_id, ids);  	} +	notifyObserverSessionVoiceOrIMStarted(session_id); +  	return session_id;  } @@ -2920,6 +2944,14 @@ void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::st  	}  } +void LLIMMgr::notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id) +{ +	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) +	{ +		(*it)->sessionVoiceOrIMStarted(session_id); +	} +} +  void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)  {  	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++) @@ -3279,6 +3311,7 @@ public:  				from_id,  				name,  				buffer, +				IM_OFFLINE == offline,  				std::string((char*)&bin_bucket[0]),  				IM_SESSION_INVITE,  				message_params["parent_estate_id"].asInteger(), diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 7c2cd03d97..fa9d20ca53 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -70,10 +70,11 @@ public:  			GROUP_SESSION,  			ADHOC_SESSION,  			AVALINE_SESSION, +			NONE_SESSION,  		} SType;  		LLIMSession(const LLUUID& session_id, const std::string& name,  -			const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice); +			const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg);  		virtual ~LLIMSession();  		void sessionInitReplyReceived(const LLUUID& new_session_id); @@ -133,6 +134,8 @@ public:  		//if IM session is created for a voice call  		bool mStartedAsIMCall; +		bool mHasOfflineMessage; +  	private:  		void onAdHocNameCache(const LLAvatarName& av_name); @@ -181,10 +184,10 @@ public:  	 * @param name session name should not be empty, will return false if empty  	 */  	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,  -		const uuid_vec_t& ids, bool voice = false); +		const uuid_vec_t& ids, bool voice = false, bool has_offline_msg = false);  	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, -		const LLUUID& other_participant_id, bool voice = false); +		const LLUUID& other_participant_id, bool voice = false, bool has_offline_msg = false);  	/**  	 * Remove all session data associated with a session specified by session_id @@ -192,12 +195,6 @@ public:  	bool clearSession(const LLUUID& session_id);  	/** -	 * Populate supplied std::list with messages starting from index specified by start_index without -	 * emitting no unread messages signal. -	 */ -	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); - -	/**  	 * Sends no unread messages signal.  	 */  	void sendNoUnreadMessages(const LLUUID& session_id); @@ -205,7 +202,7 @@ public:  	/**  	 * Populate supplied std::list with messages starting from index specified by start_index  	 */ -	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); +	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0, const bool sendNoUnreadMsgs = true);  	/**  	 * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id @@ -288,6 +285,12 @@ public:  private:  	/** +	 * Populate supplied std::list with messages starting from index specified by start_index without +	 * emitting no unread messages signal. +	 */ +	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); + +	/**  	 * Add message to a list of message associated with session specified by session_id  	 */  	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); @@ -298,6 +301,7 @@ class LLIMSessionObserver  public:  	virtual ~LLIMSessionObserver() {}  	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0; +	virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) = 0;  	virtual void sessionRemoved(const LLUUID& session_id) = 0;  	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0;  }; @@ -324,6 +328,7 @@ public:  					const LLUUID& target_id,  					const std::string& from,  					const std::string& msg, +					bool  is_offline_msg = false,  					const std::string& session_name = LLStringUtil::null,  					EInstantMessage dialog = IM_NOTHING_SPECIAL,  					U32 parent_estate_id = 0, @@ -347,10 +352,12 @@ public:  	// Adds a session using a specific group of starting agents  	// the dialog type is assumed correct. Returns the uuid of the session. +	// A session can be added to a floater specified by floater_id.  	LLUUID addSession(const std::string& name,  					  EInstantMessage dialog,  					  const LLUUID& other_participant_id, -					  const LLDynamicArray<LLUUID>& ids, bool voice = false); +					  const LLDynamicArray<LLUUID>& ids, bool voice = false, +					  const LLUUID& floater_id = LLUUID::null);  	/**  	 * Creates a P2P session with the requisite handle for responding to voice calls. @@ -460,6 +467,7 @@ private:  	static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group);  	void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	void notifyObserverSessionVoiceOrIMStarted(const LLUUID& session_id);  	void notifyObserverSessionRemoved(const LLUUID& session_id);  	void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 17d0b0ffbb..8a15cd279f 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -28,38 +28,21 @@  #include "llinspectavatar.h"  // viewer files -#include "llagent.h" -#include "llagentdata.h" -#include "llavataractions.h" +#include "llavatariconctrl.h"  #include "llavatarnamecache.h"  #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h"  #include "lldateutil.h" -#include "llfloaterreporter.h" -#include "llfloaterworldmap.h" -#include "llimview.h"  #include "llinspect.h" -#include "llmutelist.h" -#include "llpanelblockedlist.h" +#include "llslurl.h"  #include "llstartup.h" -#include "llspeakers.h" -#include "llviewermenu.h" -#include "llvoiceclient.h" -#include "llviewerobjectlist.h"  #include "lltransientfloatermgr.h" -#include "llnotificationsutil.h"  // Linden libraries  #include "llfloater.h"  #include "llfloaterreg.h" -#include "llmenubutton.h"  #include "lltextbox.h" -#include "lltoggleablemenu.h"  #include "lltooltip.h"	// positionViewNearMouse()  #include "lltrans.h" -#include "lluictrl.h" - -#include "llavatariconctrl.h"  class LLFetchAvatarData; @@ -81,22 +64,13 @@ public:  	LLInspectAvatar(const LLSD& avatar_id);  	virtual ~LLInspectAvatar(); -	/*virtual*/ BOOL postBuild(void); -	  	// Because floater is single instance, need to re-parse data on each spawn  	// (for example, inspector about same avatar but in different position)  	/*virtual*/ void onOpen(const LLSD& avatar_id); -	// When closing they should close their gear menu  -	/*virtual*/ void onClose(bool app_quitting); -	  	// Update view based on information from avatar properties processor  	void processAvatarData(LLAvatarData* data); -	// override the inspector mouse leave so timer is only paused if  -	// gear menu is not open -	/* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask); -	  	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }  private: @@ -104,47 +78,6 @@ private:  	// Used on construction and if avatar id changes.  	void requestUpdate(); -	// Set the volume slider to this user's current client-side volume setting, -	// hiding/disabling if the user is not nearby. -	void updateVolumeSlider(); - -	// Shows/hides moderator panel depending on voice state  -	void updateModeratorPanel(); - -	// Moderator ability to enable/disable voice chat for avatar -	void toggleSelectedVoice(bool enabled); -	 -	// Button callbacks -	void onClickAddFriend(); -	void onClickViewProfile(); -	void onClickIM(); -	void onClickCall(); -	void onClickTeleport(); -	void onClickInviteToGroup(); -	void onClickPay(); -	void onClickShare(); -	void onToggleMute(); -	void onClickReport(); -	void onClickFreeze(); -	void onClickEject(); -	void onClickKick(); -	void onClickCSR(); -	void onClickZoomIn();   -	void onClickFindOnMap(); -	bool onVisibleFindOnMap(); -	bool onVisibleEject(); -	bool onVisibleFreeze(); -	bool onVisibleZoomIn(); -	void onClickMuteVolume(); -	void onVolumeChange(const LLSD& data); -	bool enableMute(); -	bool enableUnmute(); -	bool enableTeleportOffer(); -	bool godModeEnabled(); - -	// Is used to determine if "Add friend" option should be enabled in gear menu -	bool isNotFriend(); -	  	void onAvatarNameCache(const LLUUID& agent_id,  						   const LLAvatarName& av_name); @@ -209,39 +142,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd)  	mAvatarName(),  	mPropertiesRequest(NULL)  { -	mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile",	boost::bind(&LLInspectAvatar::onClickViewProfile, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.AddFriend",	boost::bind(&LLInspectAvatar::onClickAddFriend, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.IM", -		boost::bind(&LLInspectAvatar::onClickIM, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Call",		boost::bind(&LLInspectAvatar::onClickCall, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Teleport",	boost::bind(&LLInspectAvatar::onClickTeleport, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup",	boost::bind(&LLInspectAvatar::onClickInviteToGroup, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Pay",	boost::bind(&LLInspectAvatar::onClickPay, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Share",	boost::bind(&LLInspectAvatar::onClickShare, this)); -	mCommitCallbackRegistrar.add("InspectAvatar.ToggleMute",	boost::bind(&LLInspectAvatar::onToggleMute, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Freeze", boost::bind(&LLInspectAvatar::onClickFreeze, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Eject", boost::bind(&LLInspectAvatar::onClickEject, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Kick", boost::bind(&LLInspectAvatar::onClickKick, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.CSR", boost::bind(&LLInspectAvatar::onClickCSR, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Report",	boost::bind(&LLInspectAvatar::onClickReport, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap",	boost::bind(&LLInspectAvatar::onClickFindOnMap, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.ZoomIn", boost::bind(&LLInspectAvatar::onClickZoomIn, this)); -	mCommitCallbackRegistrar.add("InspectAvatar.DisableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, false)); -	mCommitCallbackRegistrar.add("InspectAvatar.EnableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, true)); - -	mEnableCallbackRegistrar.add("InspectAvatar.EnableGod",	boost::bind(&LLInspectAvatar::godModeEnabled, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap",	boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleEject",	boost::bind(&LLInspectAvatar::onVisibleEject, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreeze",	boost::bind(&LLInspectAvatar::onVisibleFreeze, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableTeleportOffer", boost::bind(&LLInspectAvatar::enableTeleportOffer, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this)); -  	// can't make the properties request until the widgets are constructed -	// as it might return immediately, so do it in postBuild. +	// as it might return immediately, so do it in onOpen.  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this);  	LLTransientFloater::init(this); @@ -257,25 +159,6 @@ LLInspectAvatar::~LLInspectAvatar()  	LLTransientFloaterMgr::getInstance()->removeControlView(this);  } -/*virtual*/ -BOOL LLInspectAvatar::postBuild(void) -{ -	getChild<LLUICtrl>("add_friend_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickAddFriend, this) ); - -	getChild<LLUICtrl>("view_profile_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickViewProfile, this) ); - -	getChild<LLUICtrl>("mute_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickMuteVolume, this) ); - -	getChild<LLUICtrl>("volume_slider")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onVolumeChange, this, _2)); - -	return TRUE; -} - -  // Multiple calls to showInstance("inspect_avatar", foo) will provide different  // LLSD for foo, which we will catch here.  //virtual @@ -287,11 +170,6 @@ void LLInspectAvatar::onOpen(const LLSD& data)  	// Extract appropriate avatar id  	mAvatarID = data["avatar_id"]; -	BOOL self = mAvatarID == gAgent.getID(); -	 -	getChild<LLUICtrl>("gear_self_btn")->setVisible(self); -	getChild<LLUICtrl>("gear_btn")->setVisible(!self); -  	// Position the inspector relative to the mouse cursor  	// Similar to how tooltips are positioned  	// See LLToolTipMgr::createToolTip @@ -304,20 +182,13 @@ void LLInspectAvatar::onOpen(const LLSD& data)  		LLUI::positionViewNearMouse(this);  	} +	// Generate link to avatar profile. +	getChild<LLUICtrl>("avatar_profile_link")->setTextArg("[LINK]", LLSLURL("agent", mAvatarID, "about").getSLURLString()); +  	// can't call from constructor as widgets are not built yet  	requestUpdate(); - -	updateVolumeSlider(); - -	updateModeratorPanel();  } -// virtual -void LLInspectAvatar::onClose(bool app_quitting) -{   -  getChild<LLMenuButton>("gear_btn")->hideMenu(); -}	 -  void LLInspectAvatar::requestUpdate()  {  	// Don't make network requests when spawning from the debug menu at the @@ -344,25 +215,6 @@ void LLInspectAvatar::requestUpdate()  	delete mPropertiesRequest;  	mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this); -	// You can't re-add someone as a friend if they are already your friend -	bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; -	bool is_self = (mAvatarID == gAgentID); -	if (is_self) -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(false); -		getChild<LLUICtrl>("im_btn")->setVisible(false); -	} -	else if (is_friend) -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(false); -		getChild<LLUICtrl>("im_btn")->setVisible(true); -	} -	else -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(true); -		getChild<LLUICtrl>("im_btn")->setVisible(false); -	} -  	// Use an avatar_icon even though the image id will come down with the  	// avatar properties because the avatar_icon code maintains a cache of icons  	// and this may result in the image being visible sooner. @@ -405,214 +257,6 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)  	mPropertiesRequest = NULL;  } -// For the avatar inspector, we only want to unpause the fade timer  -// if neither the gear menu or self gear menu are open -void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask) -{ -	LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu(); -	LLToggleableMenu* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu(); -	if ( gear_menu && gear_menu->getVisible() && -		 gear_menu_self && gear_menu_self->getVisible() ) -	{ -		return; -	} - -	if(childHasVisiblePopupMenu()) -	{ -		return; -	} - -	mOpenTimer.unpause(); -} - -void LLInspectAvatar::updateModeratorPanel() -{ -	bool enable_moderator_panel = false; - -    if (LLVoiceChannel::getCurrentVoiceChannel() && -		mAvatarID != gAgent.getID()) -    { -		LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); - -		if (session_id != LLUUID::null) -		{ -			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - -			if (speaker_mgr) -			{ -				LLPointer<LLSpeaker> self_speakerp = speaker_mgr->findSpeaker(gAgent.getID()); -				LLPointer<LLSpeaker> selected_speakerp = speaker_mgr->findSpeaker(mAvatarID); -				 -				if(speaker_mgr->isVoiceActive() && selected_speakerp &&  -					selected_speakerp->isInVoiceChannel() && -					((self_speakerp && self_speakerp->mIsModerator) || gAgent.isGodlike())) -				{ -					getChild<LLUICtrl>("enable_voice")->setVisible(selected_speakerp->mModeratorMutedVoice); -					getChild<LLUICtrl>("disable_voice")->setVisible(!selected_speakerp->mModeratorMutedVoice); - -					enable_moderator_panel = true; -				} -			} -		} -	} - -	if (enable_moderator_panel) -	{ -		if (!getChild<LLUICtrl>("moderator_panel")->getVisible()) -		{ -			getChild<LLUICtrl>("moderator_panel")->setVisible(true); -			// stretch the floater so it can accommodate the moderator panel -			reshape(getRect().getWidth(), getRect().getHeight() + getChild<LLUICtrl>("moderator_panel")->getRect().getHeight()); -		} -	} -	else if (getChild<LLUICtrl>("moderator_panel")->getVisible()) -	{ -		getChild<LLUICtrl>("moderator_panel")->setVisible(false); -		// shrink the inspector floater back to original size -		reshape(getRect().getWidth(), getRect().getHeight() - getChild<LLUICtrl>("moderator_panel")->getRect().getHeight());					 -	} -} - -void LLInspectAvatar::toggleSelectedVoice(bool enabled) -{ -	LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); -	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - -	if (speaker_mgr) -	{ -		if (!gAgent.getRegion()) -			return; - -		std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); -		LLSD data; -		data["method"] = "mute update"; -		data["session-id"] = session_id; -		data["params"] = LLSD::emptyMap(); -		data["params"]["agent_id"] = mAvatarID; -		data["params"]["mute_info"] = LLSD::emptyMap(); -		// ctrl value represents ability to type, so invert -		data["params"]["mute_info"]["voice"] = !enabled; - -		class MuteVoiceResponder : public LLHTTPClient::Responder -		{ -		public: -			MuteVoiceResponder(const LLUUID& session_id) -			{ -				mSessionID = session_id; -			} - -			virtual void error(U32 status, const std::string& reason) -			{ -				llwarns << status << ": " << reason << llendl; - -				if ( gIMMgr ) -				{ -					//403 == you're not a mod -					//should be disabled if you're not a moderator -					if ( 403 == status ) -					{ -						gIMMgr->showSessionEventError( -							"mute", -							"not_a_moderator", -							mSessionID); -					} -					else -					{ -						gIMMgr->showSessionEventError( -							"mute", -							"generic", -							mSessionID); -					} -				} -			} - -		private: -			LLUUID mSessionID; -		}; - -		LLHTTPClient::post( -			url, -			data, -			new MuteVoiceResponder(speaker_mgr->getSessionID())); -	} - -	closeFloater(); - -} - -void LLInspectAvatar::updateVolumeSlider() -{ -	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); - -	// Do not display volume slider and mute button if it  -	// is ourself or we are not in a voice channel together -	if (!voice_enabled || (mAvatarID == gAgent.getID())) -	{ -		getChild<LLUICtrl>("mute_btn")->setVisible(false); -		getChild<LLUICtrl>("volume_slider")->setVisible(false); -	} - -	else  -	{ -		getChild<LLUICtrl>("mute_btn")->setVisible(true); -		getChild<LLUICtrl>("volume_slider")->setVisible(true); - -		// By convention, we only display and toggle voice mutes, not all mutes -		bool is_muted = LLMuteList::getInstance()-> -							isMuted(mAvatarID, LLMute::flagVoiceChat); - -		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); - -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); - -		mute_btn->setEnabled( !is_linden); -		mute_btn->setValue( is_muted ); - -		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); -		volume_slider->setEnabled( !is_muted ); - -		F32 volume; -		 -		if (is_muted) -		{ -			// it's clearer to display their volume as zero -			volume = 0.f; -		} -		else -		{ -			// actual volume -			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); -		} -		volume_slider->setValue( (F64)volume ); -	} - -} - -void LLInspectAvatar::onClickMuteVolume() -{ -	// By convention, we only display and toggle voice mutes, not all mutes -	LLMuteList* mute_list = LLMuteList::getInstance(); -	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - -	LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT); -	if (!is_muted) -	{ -		mute_list->add(mute, LLMute::flagVoiceChat); -	} -	else -	{ -		mute_list->remove(mute, LLMute::flagVoiceChat); -	} - -	updateVolumeSlider(); -} - -void LLInspectAvatar::onVolumeChange(const LLSD& data) -{ -	F32 volume = (F32)data.asReal(); -	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} -  void LLInspectAvatar::onAvatarNameCache(  		const LLUUID& agent_id,  		const LLAvatarName& av_name) @@ -640,215 +284,6 @@ void LLInspectAvatar::onAvatarNameCache(  	}  } -void LLInspectAvatar::onClickAddFriend() -{ -	LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName()); -	closeFloater(); -} - -void LLInspectAvatar::onClickViewProfile() -{ -	LLAvatarActions::showProfile(mAvatarID); -	closeFloater(); -} - -bool LLInspectAvatar::isNotFriend() -{ -	return !LLAvatarActions::isFriend(mAvatarID); -} - -bool LLInspectAvatar::onVisibleFindOnMap() -{ -	return gAgent.isGodlike() || is_agent_mappable(mAvatarID); -} - -bool LLInspectAvatar::onVisibleEject() -{ -	return enable_freeze_eject( LLSD(mAvatarID) ); -} - -bool LLInspectAvatar::onVisibleFreeze() -{ -	// either user is a god and can do long distance freeze -	// or check for target proximity and permissions -	return gAgent.isGodlike() || enable_freeze_eject(LLSD(mAvatarID)); -} - -bool LLInspectAvatar::onVisibleZoomIn() -{ -	return gObjectList.findObject(mAvatarID); -} - -void LLInspectAvatar::onClickIM() -{  -	LLAvatarActions::startIM(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickCall() -{  -	LLAvatarActions::startCall(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickTeleport() -{ -	LLAvatarActions::offerTeleport(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickInviteToGroup() -{ -	LLAvatarActions::inviteToGroup(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickPay() -{ -	LLAvatarActions::pay(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickShare() -{ -	LLAvatarActions::share(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onToggleMute() -{ -	LLMute mute(mAvatarID, mAvatarName.mDisplayName, LLMute::AGENT); - -	if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName)) -	{ -		LLMuteList::getInstance()->remove(mute); -	} -	else -	{ -		LLMuteList::getInstance()->add(mute); -	} - -	LLPanelBlockedList::showPanelAndSelect(mute.mID); -	closeFloater(); -} - -void LLInspectAvatar::onClickReport() -{ -	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName()); -	closeFloater(); -} - -bool godlike_freeze(const LLSD& notification, const LLSD& response) -{ -	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - -	switch (option) -	{ -	case 0: -		LLAvatarActions::freeze(avatar_id); -		break; -	case 1: -		LLAvatarActions::unfreeze(avatar_id); -		break; -	default: -		break; -	} - -	return false; -} - -void LLInspectAvatar::onClickFreeze() -{ -	if (gAgent.isGodlike()) -	{ -		// use godlike freeze-at-a-distance, with confirmation -		LLNotificationsUtil::add("FreezeAvatar", -			LLSD(), -			LLSD().with("avatar_id", mAvatarID), -			godlike_freeze); -	} -	else -	{ -		// use default "local" version of freezing that requires avatar to be in range -		handle_avatar_freeze( LLSD(mAvatarID) ); -	} -	closeFloater(); -} - -void LLInspectAvatar::onClickEject() -{ -	handle_avatar_eject( LLSD(mAvatarID) ); -	closeFloater(); -} - -void LLInspectAvatar::onClickKick() -{ -	LLAvatarActions::kick(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickCSR() -{ -	std::string name; -	gCacheName->getFullName(mAvatarID, name); -	LLAvatarActions::csr(mAvatarID, name); -	closeFloater(); -} - -void LLInspectAvatar::onClickZoomIn()  -{ -	handle_zoom_to_object(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickFindOnMap() -{ -	gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName.mDisplayName); -	LLFloaterReg::showInstance("world_map"); -} - - -bool LLInspectAvatar::enableMute() -{ -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); -		bool is_self = mAvatarID == gAgent.getID(); - -		if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) -		{ -			return true; -		} -		else -		{ -			return false; -		} -} - -bool LLInspectAvatar::enableUnmute() -{ -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); -		bool is_self = mAvatarID == gAgent.getID(); - -		if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) -		{ -			return true; -		} -		else -		{ -			return false; -		} -} - -bool LLInspectAvatar::enableTeleportOffer() -{ -	return LLAvatarActions::canOfferTeleport(mAvatarID); -} - -bool LLInspectAvatar::godModeEnabled() -{ -	return gAgent.isGodlike(); -} -  //////////////////////////////////////////////////////////////////////////////  // LLInspectAvatarUtil  ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b86c453d61..43c4ce1278 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -37,6 +37,7 @@  #include "llappearancemgr.h"  #include "llattachmentsmgr.h"  #include "llavataractions.h"  +#include "llfavoritesbar.h" // management of favorites folder  #include "llfloateropenobject.h"  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h" @@ -115,10 +116,10 @@ void teleport_via_landmark(const LLUUID& asset_id);  static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);  static bool check_category(LLInventoryModel* model,  						   const LLUUID& cat_id, -						   LLFolderView* active_folder_view, +						   LLInventoryPanel* active_panel,  						   LLInventoryFilter* filter);  static bool check_item(const LLUUID& item_id, -					   LLFolderView* active_folder_view, +					   LLInventoryPanel* active_panel,  					   LLInventoryFilter* filter);  // Helper functions @@ -189,7 +190,8 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,  	mUUID(uuid),   	mRoot(root),  	mInvType(LLInventoryType::IT_NONE), -	mIsLink(FALSE) +	mIsLink(FALSE), +	LLFolderViewModelItemInventory(inventory->getRootViewModel())  {  	mInventoryPanel = inventory->getInventoryPanelHandle();  	const LLInventoryObject* obj = getInventoryObject(); @@ -208,7 +210,11 @@ const std::string& LLInvFVBridge::getName() const  const std::string& LLInvFVBridge::getDisplayName() const  { -	return getName(); +	if(mDisplayName.empty()) +	{ +		buildDisplayName(); +	} +	return mDisplayName;  }  // Folders have full perms @@ -227,9 +233,24 @@ LLFolderType::EType LLInvFVBridge::getPreferredType() const  // Folders don't have creation dates.  time_t LLInvFVBridge::getCreationDate() const  { -	return 0; +	LLInventoryObject* objectp = getInventoryObject(); +	if (objectp) +	{ +		return objectp->getCreationDate(); +	} +	return (time_t)0; +} + +void LLInvFVBridge::setCreationDate(time_t creation_date_utc) +{ +	LLInventoryObject* objectp = getInventoryObject(); +	if (objectp) +	{ +		objectp->setCreationDate(creation_date_utc); +	}  } +  // Can be destroyed (or moved to trash)  BOOL LLInvFVBridge::isItemRemovable() const  { @@ -283,7 +304,7 @@ void LLInvFVBridge::showProperties()  	*/  } -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)  {  	// Deactivate gestures when moving them into Trash  	LLInvFVBridge* bridge; @@ -292,11 +313,11 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	LLViewerInventoryCategory* cat = NULL;  	LLInventoryModel::cat_array_t	descendent_categories;  	LLInventoryModel::item_array_t	descendent_items; -	S32 count = batch.count(); +	S32 count = batch.size();  	S32 i,j;  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if (item) @@ -309,7 +330,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	}  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());  		if (cat) @@ -327,7 +348,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc  	removeBatchNoCheck(batch);  } -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) +void  LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>&  batch)  {  	// this method moves a bunch of items and folders to the trash. As  	// per design guidelines for the inventory model, the message is @@ -343,14 +364,14 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	uuid_vec_t move_ids;  	LLInventoryModel::update_map_t update;  	bool start_new_message = true; -	S32 count = batch.count(); +	S32 count = batch.size();  	S32 i;  	// first, hide any 'preview' floaters that correspond to the items  	// being deleted.  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if(item) @@ -363,7 +384,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());  		if(item) @@ -404,7 +425,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*  	for(i = 0; i < count; ++i)  	{ -		bridge = (LLInvFVBridge*)(batch.get(i)); +		bridge = (LLInvFVBridge*)(batch[i]);  		if(!bridge || !bridge->isItemRemovable()) continue;  		LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());  		if(cat) @@ -876,6 +897,12 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const  	return panel ? panel->getModel() : NULL;  } +LLInventoryFilter* LLInvFVBridge::getInventoryFilter() const +{ +	LLInventoryPanel* panel = mInventoryPanel.get(); +	return panel ? &(panel->getFilter()) : NULL; +} +  BOOL LLInvFVBridge::isItemInTrash() const  {  	LLInventoryModel* model = getInventoryModel(); @@ -928,7 +955,7 @@ BOOL LLInvFVBridge::isCOFFolder() const  BOOL LLInvFVBridge::isInboxFolder() const  { -	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); +	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false);  	if (inbox_id.isNull())  	{ @@ -968,7 +995,7 @@ BOOL LLInvFVBridge::isOutboxFolderDirectParent() const  const LLUUID LLInvFVBridge::getOutboxFolder() const  { -	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  	return outbox_id;  } @@ -1000,6 +1027,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  										   LLAssetType::EType actual_asset_type,  										   LLInventoryType::EType inv_type,  										   LLInventoryPanel* inventory, +										   LLFolderViewModelInventory* view_model,  										   LLFolderView* root,  										   const LLUUID& uuid,  										   U32 flags) @@ -1125,7 +1153,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  		default:  			llinfos << "Unhandled asset type (llassetstorage.h): "  					<< (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << llendl; -			break; +			break;	  	}  	if (new_listener) @@ -1250,10 +1278,10 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  		if (can_list)  		{ -			LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id); +			LLFolderViewFolder * object_folderp =   mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL;  			if (object_folderp)  			{ -				can_list = !object_folderp->isLoading(); +				can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading();  			}  		} @@ -1261,7 +1289,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  		{  			// Get outbox id  			const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); -			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); +			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL;  			if (outbox_itemp)  			{ @@ -1271,7 +1299,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  				void * cargo_data = (void *) obj;  				std::string tooltip_msg; -				can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +				can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);  			}  		}  	} @@ -1283,14 +1311,30 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const  #endif  } +LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const +{ +	if (gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID())) +	{ +		return LLToolDragAndDrop::SOURCE_AGENT; +	} +	else if (gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID())) +	{ +		return LLToolDragAndDrop::SOURCE_LIBRARY; +	} + +	return LLToolDragAndDrop::SOURCE_VIEWER; +} + +  // +=================================================+  // |        InventoryFVBridgeBuilder                 |  // +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, +LLInvFVBridge* LLInventoryFolderViewModelBuilder::createBridge(LLAssetType::EType asset_type,  														LLAssetType::EType actual_asset_type,  														LLInventoryType::EType inv_type,  														LLInventoryPanel* inventory, +														LLFolderViewModelInventory* view_model,  														LLFolderView* root,  														const LLUUID& uuid,  														U32 flags /* = 0x00 */) const @@ -1299,6 +1343,7 @@ LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset  									   actual_asset_type,  									   inv_type,  									   inventory, +									   view_model,  									   root,  									   uuid,  									   flags); @@ -1355,7 +1400,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  	else if ("cut" == action)  	{  		cutToClipboard(); -		LLFolderView::removeCutItems(); +		gInventory.removeObject(mUUID);  		return;  	}  	else if ("copy" == action) @@ -1368,10 +1413,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); +		LLFolderViewItem* folder_view_itemp =   mInventoryPanel.get()->getItemByID(itemp->getParentUUID());  		if (!folder_view_itemp) return; -		folder_view_itemp->getListener()->pasteFromClipboard(); +		folder_view_itemp->getViewModelItem()->pasteFromClipboard();  		return;  	}  	else if ("paste_link" == action) @@ -1380,10 +1425,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); +		LLFolderViewItem* folder_view_itemp =   mInventoryPanel.get()->getItemByID(itemp->getParentUUID());  		if (!folder_view_itemp) return; -		folder_view_itemp->getListener()->pasteLinkFromClipboard(); +		folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();  		return;  	}  	else if (isMarketplaceCopyAction(action)) @@ -1393,7 +1438,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryItem* itemp = model->getItem(mUUID);  		if (!itemp) return; -		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  		copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());  	}  } @@ -1494,25 +1539,20 @@ PermissionMask LLItemBridge::getPermissionMask() const  	return perm_mask;  } -const std::string& LLItemBridge::getDisplayName() const -{ -	if(mDisplayName.empty()) -	{ -		buildDisplayName(getItem(), mDisplayName); -	} -	return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +void LLItemBridge::buildDisplayName() const  { -	if(item) +	if(getItem())  	{ -		name.assign(item->getName()); +		mDisplayName.assign(getItem()->getName());  	}  	else  	{ -		name.assign(LLStringUtil::null); +		mDisplayName.assign(LLStringUtil::null);  	} + +	mSearchableName.assign(mDisplayName); +	mSearchableName.append(getLabelSuffix()); +	LLStringUtil::toUpper(mSearchableName);  }  LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const @@ -1629,25 +1669,23 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)  	{  		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);  		new_item->rename(new_name); -		buildDisplayName(new_item, mDisplayName);  		new_item->updateServer(FALSE);  		model->updateItem(new_item);  		model->notifyObservers(); +		buildDisplayName();  	}  	// return FALSE because we either notified observers (& therefore  	// rebuilt) or we didn't update.  	return FALSE;  } -  BOOL LLItemBridge::removeItem()  {  	if(!isItemRemovable())  	{  		return FALSE;  	} -  	// move it to the trash  	LLPreview::hide(mUUID, TRUE); @@ -1786,6 +1824,93 @@ void LLFolderBridge::selectItem()  	LLInventoryModelBackgroundFetch::instance().start(getUUID(), true);  } +void LLFolderBridge::buildDisplayName() const +{ +	LLFolderType::EType preferred_type = getPreferredType(); + +	// *TODO: to be removed when database supports multi language. This is a +	// temporary attempt to display the inventory folder in the user locale. +	// mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID +	//		it uses the same way to find localized string + +	// HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) +	// Translation of Accessories folder in Library inventory folder +	bool accessories = false; +	if(getName() == "Accessories") +	{ +		//To ensure that Accessories folder is in Library we have to check its parent folder. +		//Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model +		LLInventoryCategory* cat = gInventory.getCategory(getUUID()); +		if(cat) +		{ +			const LLUUID& parent_folder_id = cat->getParentUUID(); +			accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); +		} +	} + +	//"Accessories" inventory category has folder type FT_NONE. So, this folder +	//can not be detected as protected with LLFolderType::lookupIsProtectedType +	mDisplayName.assign(getName()); +	if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) +	{ +		LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); +	} + +	mSearchableName.assign(mDisplayName); +	mSearchableName.append(getLabelSuffix()); +	LLStringUtil::toUpper(mSearchableName); +} + + +void LLFolderBridge::update() +{ +	bool possibly_has_children = false; +	bool up_to_date = isUpToDate(); +	if(!up_to_date && hasChildren()) // we know we have children but  haven't  fetched them (doesn't obey filter) +	{ +		possibly_has_children = true; +	} + +	bool loading = (possibly_has_children +		&& !up_to_date ); + +	if (loading != mIsLoading) +	{ +		if ( loading && !mIsLoading ) +		{ +			// Measure how long we've been in the loading state +			mTimeSinceRequestStart.reset(); +		} + +		const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getRootFolderID()); +		const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(),   gInventory.getLibraryRootFolderID()); + +		bool root_is_loading = false; +		if (in_inventory) +		{ +			root_is_loading =   LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); +		} +		if (in_library) +		{ +			root_is_loading =   LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); +		} +		if ((mIsLoading +				&&	mTimeSinceRequestStart.getElapsedTimeF32() >=   gSavedSettings.getF32("FolderLoadingMessageWaitTime")) +			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive() +				&&	root_is_loading)) +		{ +			mDisplayName = LLInvFVBridge::getDisplayName() + " ( " +   LLTrans::getString("LoadingData") + " ) "; +			mIsLoading = true; +		} +		else +		{ +			mDisplayName = LLInvFVBridge::getDisplayName(); +			mIsLoading = false; +		} +	} +} + +  // Iterate through a folder's children to determine if  // all the children are removable.  class LLIsItemRemovable : public LLFolderViewFunctor @@ -1794,11 +1919,11 @@ public:  	LLIsItemRemovable() : mPassed(TRUE) {}  	virtual void doFolder(LLFolderViewFolder* folder)  	{ -		mPassed &= folder->getListener()->isItemRemovable(); +		mPassed &= folder->getViewModelItem()->isItemRemovable();  	}  	virtual void doItem(LLFolderViewItem* item)  	{ -		mPassed &= item->getListener()->isItemRemovable(); +		mPassed &= item->getViewModelItem()->isItemRemovable();  	}  	BOOL mPassed;  }; @@ -1812,7 +1937,7 @@ BOOL LLFolderBridge::isItemRemovable() const  	}  	LLInventoryPanel* panel = mInventoryPanel.get(); -	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); +	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ?   panel->getItemByID(mUUID) : NULL);  	if (folderp)  	{  		LLIsItemRemovable folder_test; @@ -2051,7 +2176,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  	LLInventoryPanel* destination_panel = mInventoryPanel.get();  	if (!destination_panel) return false; -	LLInventoryFilter* filter = destination_panel->getFilter(); +	LLInventoryFilter* filter = getInventoryFilter();  	if (!filter) return false;  	const LLUUID &cat_id = inv_cat->getUUID(); @@ -2270,7 +2395,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  				{  					// Check whether the folder being dragged from active inventory panel  					// passes the filter of the destination panel. -					is_movable = check_category(model, cat_id, active_folder_view, filter); +					is_movable = check_category(model, cat_id, active_panel, filter);  				}  			}  		} @@ -2344,7 +2469,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  			}  			else  			{ -				if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) +				if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))  				{  					set_dad_inbox_object(cat_id);  				} @@ -2696,7 +2821,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  {  	if ("open" == action)  	{ -		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mRoot->getItemByID(mUUID)); +		LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder   *>(mInventoryPanel.get()->getItemByID(mUUID));  		if (f)  		{  			f->setOpen(TRUE); @@ -2743,7 +2868,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  	else if ("cut" == action)  	{  		cutToClipboard(); -		LLFolderView::removeCutItems(); +		gInventory.removeObject(mUUID);  		return;  	}  	else if ("copy" == action) @@ -2784,7 +2909,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  		LLInventoryCategory * cat = gInventory.getCategory(mUUID);  		if (!cat) return; -		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  		copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());  	}  #if ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU @@ -2880,17 +3005,24 @@ LLUIImagePtr LLFolderBridge::getIcon() const  LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)  {  	return LLUI::getUIImage(LLViewerFolderType::lookupIconName(preferred_type, FALSE)); -		/*case LLAssetType::AT_MESH: -			control = "inv_folder_mesh.tga"; -			break;*/  } -LLUIImagePtr LLFolderBridge::getOpenIcon() const +LLUIImagePtr LLFolderBridge::getIconOpen() const  {  	return LLUI::getUIImage(LLViewerFolderType::lookupIconName(getPreferredType(), TRUE));  } +LLUIImagePtr LLFolderBridge::getIconOverlay() const +{ +	if (getInventoryObject() && getInventoryObject()->getIsLinkType()) +	{ +		return LLUI::getUIImage("Inv_Link"); +	} +	return NULL; +} + +  BOOL LLFolderBridge::renameItem(const std::string& new_name)  {  	rename_category(getInventoryModel(), mUUID, new_name); @@ -2971,7 +3103,7 @@ void LLFolderBridge::pasteFromClipboard()  		if (move_is_into_outbox)  		{ -			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); +			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get()->getItemByID(mUUID);  			if (outbox_itemp)  			{ @@ -2994,7 +3126,7 @@ void LLFolderBridge::pasteFromClipboard()  						void * cargo_data = (void *) item;  						std::string tooltip_msg; -						can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +						can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);  					}  				} @@ -3166,7 +3298,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv  	return ((item_array.count() > 0) ? TRUE : FALSE );  } -void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) +void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items, menuentry_vec_t& disabled_items)  {  	LLInventoryModel* model = getInventoryModel();  	llassert(model != NULL); @@ -3177,30 +3309,30 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  	if (lost_and_found_id == mUUID)  	{  		// This is the lost+found folder. -		mItems.push_back(std::string("Empty Lost And Found")); +		items.push_back(std::string("Empty Lost And Found")); -		mDisabledItems.push_back(std::string("New Folder")); -		mDisabledItems.push_back(std::string("New Script")); -		mDisabledItems.push_back(std::string("New Note")); -		mDisabledItems.push_back(std::string("New Gesture")); -		mDisabledItems.push_back(std::string("New Clothes")); -		mDisabledItems.push_back(std::string("New Body Parts")); +		disabled_items.push_back(std::string("New Folder")); +		disabled_items.push_back(std::string("New Script")); +		disabled_items.push_back(std::string("New Note")); +		disabled_items.push_back(std::string("New Gesture")); +		disabled_items.push_back(std::string("New Clothes")); +		disabled_items.push_back(std::string("New Body Parts"));  	}  	if(trash_id == mUUID)  	{  		// This is the trash. -		mItems.push_back(std::string("Empty Trash")); +		items.push_back(std::string("Empty Trash"));  	}  	else if(isItemInTrash())  	{  		// This is a folder in the trash. -		mItems.clear(); // clear any items that used to exist -		addTrashContextMenuOptions(mItems, mDisabledItems); +		items.clear(); // clear any items that used to exist +		addTrashContextMenuOptions(items, disabled_items);  	}  	else if(isOutboxFolder())  	{ -		addOutboxContextMenuOptions(flags, mItems, mDisabledItems); +		addOutboxContextMenuOptions(flags, items, disabled_items);  	}  	else if(isAgentInventory()) // do not allow creating in library  	{ @@ -3214,40 +3346,40 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.  				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))  				{ -					mItems.push_back(std::string("New Folder")); +					items.push_back(std::string("New Folder"));  				} -				mItems.push_back(std::string("New Script")); -				mItems.push_back(std::string("New Note")); -				mItems.push_back(std::string("New Gesture")); -				mItems.push_back(std::string("New Clothes")); -				mItems.push_back(std::string("New Body Parts")); +				items.push_back(std::string("New Script")); +				items.push_back(std::string("New Note")); +				items.push_back(std::string("New Gesture")); +				items.push_back(std::string("New Clothes")); +				items.push_back(std::string("New Body Parts"));  			}  #if SUPPORT_ENSEMBLES  			// Changing folder types is an unfinished unsupported feature  			// and can lead to unexpected behavior if enabled. -			mItems.push_back(std::string("Change Type")); +			items.push_back(std::string("Change Type"));  			const LLViewerInventoryCategory *cat = getCategory();  			if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))  			{ -				mDisabledItems.push_back(std::string("Change Type")); +				disabled_items.push_back(std::string("Change Type"));  			}  #endif -			getClipboardEntries(false, mItems, mDisabledItems, flags); +			getClipboardEntries(false, items, disabled_items, flags);  		}  		else  		{  			// Want some but not all of the items from getClipboardEntries for outfits.  			if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))  			{ -				mItems.push_back(std::string("Rename")); +				items.push_back(std::string("Rename")); -				addDeleteContextMenuOptions(mItems, mDisabledItems); +				addDeleteContextMenuOptions(items, disabled_items);  				// EXT-4030: disallow deletion of currently worn outfit  				const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();  				if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))  				{ -					mDisabledItems.push_back(std::string("Delete")); +					disabled_items.push_back(std::string("Delete"));  				}  			}  		} @@ -3276,20 +3408,44 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)  	// Preemptively disable system folder removal if more than one item selected.  	if ((flags & FIRST_SELECTED_ITEM) == 0)  	{ -		mDisabledItems.push_back(std::string("Delete System Folder")); +		disabled_items.push_back(std::string("Delete System Folder"));  	}  	if (!isOutboxFolder())  	{ -		mItems.push_back(std::string("Share")); +		items.push_back(std::string("Share"));  		if (!canShare())  		{ -			mDisabledItems.push_back(std::string("Share")); +			disabled_items.push_back(std::string("Share")); +		} +	} +	// Add menu items that are dependent on the contents of the folder. +	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); +	if (category) +	{ +		uuid_vec_t folders; +		folders.push_back(category->getUUID()); + +		sSelf = getHandle(); +		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); +		fetch->startFetch(); +		if (fetch->isFinished()) +		{ +			// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down  +			// This saves lots of time as buildContextMenu() is called a lot +			delete fetch; +			buildContextMenuFolderOptions(flags, items, disabled_items); +		} +		else +		{ +			// it's all on its way - add an observer, and the inventory will call done for us when everything is here. +			inc_busy_count(); +			gInventory.addObserver(fetch);  		}  	}  } -void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) +void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t& items, menuentry_vec_t& disabled_items)  {  	// Build folder specific options back up  	LLInventoryModel* model = getInventoryModel(); @@ -3316,21 +3472,21 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  		LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);  		if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))  		{ -			mItems.push_back(std::string("Calling Card Separator")); -			mItems.push_back(std::string("Conference Chat Folder")); -			mItems.push_back(std::string("IM All Contacts In Folder")); +			items.push_back(std::string("Calling Card Separator")); +			items.push_back(std::string("Conference Chat Folder")); +			items.push_back(std::string("IM All Contacts In Folder"));  		}  	}  	if (!isItemRemovable())  	{ -		mDisabledItems.push_back(std::string("Delete")); +		disabled_items.push_back(std::string("Delete"));  	}  #ifndef LL_RELEASE_FOR_DOWNLOAD  	if (LLFolderType::lookupIsProtectedType(type))  	{ -		mItems.push_back(std::string("Delete System Folder")); +		items.push_back(std::string("Delete System Folder"));  	}  #endif @@ -3345,7 +3501,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  		checkFolderForContentsOfType(model, is_object) ||  		checkFolderForContentsOfType(model, is_gesture) )  	{ -		mItems.push_back(std::string("Folder Wearables Separator")); +		items.push_back(std::string("Folder Wearables Separator"));  		// Only enable add/replace outfit for non-system folders.  		if (!is_system_folder) @@ -3353,25 +3509,25 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)  			// Adding an outfit onto another (versus replacing) doesn't make sense.  			if (type != LLFolderType::FT_OUTFIT)  			{ -				mItems.push_back(std::string("Add To Outfit")); +				items.push_back(std::string("Add To Outfit"));  			} -			mItems.push_back(std::string("Replace Outfit")); +			items.push_back(std::string("Replace Outfit"));  		}  		if (is_ensemble)  		{ -			mItems.push_back(std::string("Wear As Ensemble")); +			items.push_back(std::string("Wear As Ensemble"));  		} -		mItems.push_back(std::string("Remove From Outfit")); +		items.push_back(std::string("Remove From Outfit"));  		if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))  		{ -			mDisabledItems.push_back(std::string("Remove From Outfit")); +			disabled_items.push_back(std::string("Remove From Outfit"));  		}  		if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))  		{ -			mDisabledItems.push_back(std::string("Replace Outfit")); +			disabled_items.push_back(std::string("Replace Outfit"));  		} -		mItems.push_back(std::string("Outfit Separator")); +		items.push_back(std::string("Outfit Separator"));  	}  } @@ -3380,49 +3536,28 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  {  	sSelf.markDead(); -	mItems.clear(); -	mDisabledItems.clear(); +	// fetch contents of this folder, as context menu can depend on contents +	// still, user would have to open context menu again to see the changes +	gInventory.fetchDescendentsOf(getUUID()); + + +	menuentry_vec_t items; +	menuentry_vec_t disabled_items;  	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;  	LLInventoryModel* model = getInventoryModel();  	if(!model) return; -	buildContextMenuBaseOptions(flags); - -	// Add menu items that are dependent on the contents of the folder. -	LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); -	if (category) -	{ -		uuid_vec_t folders; -		folders.push_back(category->getUUID()); - -		sSelf = getHandle(); -		LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); -		fetch->startFetch(); -		if (fetch->isFinished()) -		{ -			// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down  -			// This saves lots of time as buildContextMenu() is called a lot -			delete fetch; -			buildContextMenuFolderOptions(flags); -		} -		else -		{ -			// it's all on its way - add an observer, and the inventory will call done for us when everything is here. -			inc_busy_count(); -			gInventory.addObserver(fetch); -		} -	} - -	hide_context_entries(menu, mItems, mDisabledItems); +	buildContextMenuOptions(flags, items, disabled_items); +        hide_context_entries(menu, items, disabled_items);  	// Reposition the menu, in case we're adding items to an existing menu.  	menu.needsArrange();  	menu.arrangeAndClear();  } -BOOL LLFolderBridge::hasChildren() const +bool LLFolderBridge::hasChildren() const  {  	LLInventoryModel* model = getInventoryModel();  	if(!model) return FALSE; @@ -3512,25 +3647,6 @@ void LLFolderBridge::pasteClipboard(void* user_data)  	if(self) self->pasteFromClipboard();  } -void LLFolderBridge::createNewCategory(void* user_data) -{ -	LLFolderBridge* bridge = (LLFolderBridge*)user_data; -	if(!bridge) return; -	LLInventoryPanel* panel = bridge->mInventoryPanel.get(); -	if (!panel) return; -	LLInventoryModel* model = panel->getModel(); -	if(!model) return; -	LLUUID id; -	id = model->createNewCategory(bridge->getUUID(), -								  LLFolderType::FT_NONE, -								  LLStringUtil::null); -	model->notifyObservers(); - -	// At this point, the bridge has probably been deleted, but the -	// view is still there. -	panel->setSelection(id, TAKE_FOCUS_YES); -} -  void LLFolderBridge::createNewShirt(void* user_data)  {  	LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_SHIRT); @@ -3596,6 +3712,24 @@ void LLFolderBridge::createNewEyes(void* user_data)  	LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES);  } +EInventorySortGroup LLFolderBridge::getSortGroup() const +{ +	LLFolderType::EType preferred_type = getPreferredType(); + +	if (preferred_type == LLFolderType::FT_TRASH) +	{ +		return SG_TRASH_FOLDER; +	} + +	if(LLFolderType::lookupIsProtectedType(preferred_type)) +	{ +		return SG_SYSTEM_FOLDER; +	} + +	return SG_NORMAL_FOLDER; +} + +  // static  void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type)  { @@ -3698,9 +3832,10 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)  	LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();  	LLInventoryPanel* panel = mInventoryPanel.get();  	LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; -	if (drag_over_item && drag_over_item->getListener()) +	LLFolderViewModelItemInventory* view_model = drag_over_item ? static_cast<LLFolderViewModelItemInventory*>(drag_over_item->getViewModelItem()) : NULL; +	if (view_model)  	{ -		cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); +		cb.get()->setTargetLandmarkId(view_model->getUUID());  	}  	copy_inventory_item( @@ -3749,7 +3884,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  	LLInventoryPanel* destination_panel = mInventoryPanel.get();  	if (!destination_panel) return false; -	LLInventoryFilter* filter = destination_panel->getFilter(); +	LLInventoryFilter* filter = getInventoryFilter();  	if (!filter) return false;  	const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3866,13 +4001,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  		// passes the filter of the destination panel.  		if (accept && active_panel)  		{ -			LLFolderView* active_folder_view = active_panel->getRootFolder(); -			if (!active_folder_view) return false; - -			LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +			LLFolderViewItem* fv_item =   active_panel->getItemByID(inv_item->getUUID());  			if (!fv_item) return false; -			accept = filter->check(fv_item); +			accept = filter->check(fv_item->getViewModelItem());  		}  		if (accept && drop) @@ -3884,6 +4016,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			}  			// If an item is being dragged between windows, unselect everything in the active window   			// so that we don't follow the selection to its new location (which is very annoying). +                        // RN: a better solution would be to deselect automatically when an   item is moved +			// and then select any item that is dropped only in the panel that it   is dropped in  			if (active_panel && (destination_panel != active_panel))  				{  					active_panel->unSelectAll(); @@ -3901,8 +4035,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  				if (itemp)  				{  					LLUUID srcItemId = inv_item->getUUID(); -					LLUUID destItemId = itemp->getListener()->getUUID(); -					gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); +					LLUUID destItemId = static_cast<LLFolderViewModelItemInventory*>(itemp->getViewModelItem())->getUUID(); +					LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId);  				}  			} @@ -3934,7 +4068,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			else  			{  				// set up observer to select item once drag and drop from inbox is complete  -				if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) +				if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false)))  				{  					set_dad_inbox_object(inv_item->getUUID());  				} @@ -4089,13 +4223,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			// passes the filter of the destination panel.  			if (accept && active_panel)  			{ -				LLFolderView* active_folder_view = active_panel->getRootFolder(); -				if (!active_folder_view) return false; - -				LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +				LLFolderViewItem* fv_item =   active_panel->getItemByID(inv_item->getUUID());  				if (!fv_item) return false; -				accept = filter->check(fv_item); +				accept = filter->check(fv_item->getViewModelItem());  			}  			if (accept && drop) @@ -4135,10 +4266,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  // static  bool check_category(LLInventoryModel* model,  					const LLUUID& cat_id, -					LLFolderView* active_folder_view, +					LLInventoryPanel* active_panel,  					LLInventoryFilter* filter)  { -	if (!model || !active_folder_view || !filter) +	if (!model || !active_panel || !filter)  		return false;  	if (!filter->checkFolder(cat_id)) @@ -4158,13 +4289,13 @@ bool check_category(LLInventoryModel* model,  		// Empty folder should be checked as any other folder view item.  		// If we are filtering by date the folder should not pass because  		// it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). -		return check_item(cat_id, active_folder_view, filter); +		return check_item(cat_id, active_panel, filter);  	}  	for (S32 i = 0; i < num_descendent_categories; ++i)  	{  		LLInventoryCategory* category = descendent_categories[i]; -		if(!check_category(model, category->getUUID(), active_folder_view, filter)) +		if(!check_category(model, category->getUUID(), active_panel, filter))  		{  			return false;  		} @@ -4173,7 +4304,7 @@ bool check_category(LLInventoryModel* model,  	for (S32 i = 0; i < num_descendent_items; ++i)  	{  		LLViewerInventoryItem* item = descendent_items[i]; -		if(!check_item(item->getUUID(), active_folder_view, filter)) +		if(!check_item(item->getUUID(), active_panel, filter))  		{  			return false;  		} @@ -4184,15 +4315,15 @@ bool check_category(LLInventoryModel* model,  // static  bool check_item(const LLUUID& item_id, -				LLFolderView* active_folder_view, +				LLInventoryPanel* active_panel,  				LLInventoryFilter* filter)  { -	if (!active_folder_view || !filter) return false; +	if (!active_panel || !filter) return false; -	LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); +	LLFolderViewItem* fv_item = active_panel->getItemByID(item_id);  	if (!fv_item) return false; -	return filter->check(fv_item); +	return filter->check(fv_item->getViewModelItem());  }  // +=================================================+ @@ -4294,15 +4425,6 @@ void LLSoundBridge::openItem()  	}  } -void LLSoundBridge::previewItem() -{ -	LLViewerInventoryItem* item = getItem(); -	if(item) -	{ -		send_sound_trigger(item->getAssetUUID(), 1.0); -	} -} -  void LLSoundBridge::openSoundPreview(void* which)  {  	LLSoundBridge *me = (LLSoundBridge *)which; @@ -4518,7 +4640,7 @@ LLCallingCardBridge::~LLCallingCardBridge()  void LLCallingCardBridge::refreshFolderViewItem()  {  	LLInventoryPanel* panel = mInventoryPanel.get(); -	LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; +	LLFolderViewItem* itemp = panel ? panel->getItemByID(mUUID) : NULL;  	if (itemp)  	{  		itemp->refresh(); @@ -5309,11 +5431,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)  	{  		LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);  		new_item->rename(new_name); -		buildDisplayName(new_item, mDisplayName);  		new_item->updateServer(FALSE);  		model->updateItem(new_item); -  		model->notifyObservers(); +		buildDisplayName();  		if (isAgentAvatarValid())  		{ @@ -5913,16 +6034,6 @@ void LLMeshBridge::openItem()  	}  } -void LLMeshBridge::previewItem() -{ -	LLViewerInventoryItem* item = getItem(); -	if(item) -	{ -		// preview mesh -	} -} - -  void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  {  	lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; @@ -6011,14 +6122,15 @@ void LLLinkFolderBridge::gotoItem()  	const LLUUID &cat_uuid = getFolderID();  	if (!cat_uuid.isNull())  	{ -		if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) +		LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid); +		if (base_folder)  		{  			if (LLInventoryModel* model = getInventoryModel())  			{  				model->fetchDescendentsOf(cat_uuid);  			}  			base_folder->setOpen(TRUE); -			mRoot->setSelectionFromRoot(base_folder,TRUE); +			mRoot->setSelection(base_folder,TRUE);  			mRoot->scrollToShowSelection();  		}  	} @@ -6349,9 +6461,8 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_  /************************************************************************/  void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  { -	LLFolderBridge::buildContextMenu(menu, flags); - -	menuentry_vec_t disabled_items, items = getMenuItems(); +	menuentry_vec_t disabled_items, items; +        buildContextMenuOptions(flags, items, disabled_items);  	items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); @@ -6363,42 +6474,29 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(  	LLAssetType::EType actual_asset_type,  	LLInventoryType::EType inv_type,  	LLInventoryPanel* inventory, +	LLFolderViewModelInventory* view_model,  	LLFolderView* root,  	const LLUUID& uuid,  	U32 flags /*= 0x00*/ ) const  {  	LLInvFVBridge* new_listener = NULL; -	switch(asset_type) +	if (asset_type == LLAssetType::AT_CATEGORY  +		&& actual_asset_type != LLAssetType::AT_LINK_FOLDER)  	{ -	case LLAssetType::AT_CATEGORY: -		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) -		{ -			// *TODO: Create a link folder handler instead if it is necessary -			new_listener = LLInventoryFVBridgeBuilder::createBridge( -				asset_type, -				actual_asset_type, -				inv_type, -				inventory, -				root, -				uuid, -				flags); -			break; -		}  		new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); -		break; -	default: -		new_listener = LLInventoryFVBridgeBuilder::createBridge( -			asset_type, -			actual_asset_type, -			inv_type, -			inventory, -			root, -			uuid, -			flags); +	} +	else +	{ +		new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type, +																actual_asset_type, +																inv_type, +																inventory, +																view_model, +																root, +																uuid, +																flags);  	}  	return new_listener; -  } -  // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index dc9e88d54d..fc0b15acad 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -29,11 +29,13 @@  #include "llcallingcard.h"  #include "llfloaterproperties.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llinventorymodel.h"  #include "llinventoryobserver.h" +#include "llinventorypanel.h"  #include "llviewercontrol.h"  #include "llwearable.h" +#include "lltooldraganddrop.h"  class LLInventoryFilter;  class LLInventoryPanel; @@ -41,7 +43,7 @@ class LLInventoryModel;  class LLMenuGL;  class LLCallingCardObserver;  class LLViewerJointAttachment; - +class LLFolderView;  typedef std::vector<std::string> menuentry_vec_t; @@ -56,7 +58,7 @@ typedef std::vector<std::string> menuentry_vec_t;  // functionality a bit. (except for folders, you can create those  // manually...)  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInvFVBridge : public LLFolderViewEventListener +class LLInvFVBridge : public LLFolderViewModelItemInventory  {  public:  	// This method is a convenience function which creates the correct @@ -65,6 +67,7 @@ public:  									   LLAssetType::EType actual_asset_type,  									   LLInventoryType::EType inv_type,  									   LLInventoryPanel* inventory, +									   LLFolderViewModelInventory* view_model,  									   LLFolderView* root,  									   const LLUUID& uuid,  									   U32 flags = 0x00); @@ -78,23 +81,25 @@ public:  	// LLInvFVBridge functionality  	//--------------------------------------------------------------------  	virtual const LLUUID& getUUID() const { return mUUID; } -	virtual void clearDisplayName() {} +	virtual void clearDisplayName() { mDisplayName.clear(); }  	virtual void restoreItem() {}  	virtual void restoreToWorld() {}  	//-------------------------------------------------------------------- -	// Inherited LLFolderViewEventListener functions +	// Inherited LLFolderViewModelItemInventory functions  	//--------------------------------------------------------------------  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const; +	const std::string& getSearchableName() const { return mSearchableName; } +  	virtual PermissionMask getPermissionMask() const;  	virtual LLFolderType::EType getPreferredType() const;  	virtual time_t getCreationDate() const; +        virtual void setCreationDate(time_t creation_date_utc);  	virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }  	virtual std::string getLabelSuffix() const { return LLStringUtil::null; }  	virtual void openItem() {}  	virtual void closeItem() {} -	virtual void previewItem() {openItem();}  	virtual void showProperties();  	virtual BOOL isItemRenameable() const { return TRUE; }  	//virtual BOOL renameItem(const std::string& new_name) {} @@ -103,8 +108,8 @@ public:  	virtual BOOL isItemInTrash() const;  	virtual BOOL isLink() const;  	//virtual BOOL removeItem() = 0; -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); -	virtual void move(LLFolderViewEventListener* new_parent_bridge) {} +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); +	virtual void move(LLFolderViewModelItem* new_parent_bridge) {}  	virtual BOOL isItemCopyable() const { return FALSE; }  	virtual BOOL copyToClipboard() const;  	virtual BOOL cutToClipboard() const; @@ -115,6 +120,7 @@ public:  	void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items,   							 menuentry_vec_t &disabled_items, U32 flags);  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); +    virtual LLToolDragAndDrop::ESource getDragSource() const;  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -122,6 +128,9 @@ public:  							std::string& tooltip_msg) { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return mInvType; }  	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +        EInventorySortGroup getSortGroup()  const { return SG_ITEM; } +	virtual LLInventoryObject* getInventoryObject() const; +  	//--------------------------------------------------------------------  	// Convenience functions for adding various common menu options. @@ -138,16 +147,16 @@ protected:  protected:  	LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); -	LLInventoryObject* getInventoryObject() const;  	LLInventoryModel* getInventoryModel() const; +	LLInventoryFilter* getInventoryFilter() const;  	BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?  	BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?  	BOOL isAgentInventory() const; // false if lost or in the inventory library -	BOOL isCOFFolder() const; // true if COF or descendent of -	BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox -	BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox +	BOOL isCOFFolder() const;       // true if COF or descendant of +	BOOL isInboxFolder() const;     // true if COF or descendant of   marketplace inbox +	BOOL isOutboxFolder() const;    // true if COF or descendant of   marketplace outbox  	BOOL isOutboxFolderDirectParent() const;  	const LLUUID getOutboxFolder() const; @@ -160,30 +169,36 @@ protected:  									 LLViewerInventoryCategory* item,  									 const LLUUID& new_parent,  									 BOOL restamp); -	void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch); +	void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch);  protected: -	LLHandle<LLInventoryPanel> mInventoryPanel; -	LLFolderView* mRoot; -	const LLUUID mUUID;	// item id -	LLInventoryType::EType mInvType; -	BOOL mIsLink; +	LLHandle<LLInventoryPanel>	mInventoryPanel; +	LLFolderView*				mRoot; +	const LLUUID				mUUID;	// item id +	LLInventoryType::EType		mInvType; +	bool						mIsLink; +	LLTimer						mTimeSinceRequestStart; +	mutable std::string			mDisplayName; +	mutable std::string			mSearchableName; +  	void purgeItem(LLInventoryModel *model, const LLUUID &uuid); +	virtual void buildDisplayName() const {}  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInvFVBridgeBuilder +// Class LLInventoryFolderViewModelBuilder  // -// This class intended to build Folder View Bridge via LLInvFVBridge::createBridge. -// It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge. +// This class intended to build Folder View Model via LLInvFVBridge::createBridge. +// It can be overridden with another way of creation necessary Inventory Folder View Models.  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFVBridgeBuilder +class LLInventoryFolderViewModelBuilder  {  public: - 	virtual ~LLInventoryFVBridgeBuilder() {} + 	virtual ~LLInventoryFolderViewModelBuilder() {}  	virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,  										LLAssetType::EType actual_asset_type,  										LLInventoryType::EType inv_type,  										LLInventoryPanel* inventory, +										LLFolderViewModelInventory* view_model,  										LLFolderView* root,  										const LLUUID& uuid,  										U32 flags = 0x00) const; @@ -203,7 +218,6 @@ public:  	virtual void restoreToWorld();  	virtual void gotoItem();  	virtual LLUIImagePtr getIcon() const; -	virtual const std::string& getDisplayName() const;  	virtual std::string getLabelSuffix() const;  	virtual LLFontGL::StyleFlags getLabelStyle() const;  	virtual PermissionMask getPermissionMask() const; @@ -212,19 +226,16 @@ public:  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL removeItem();  	virtual BOOL isItemCopyable() const; -	virtual BOOL hasChildren() const { return FALSE; } +	virtual bool hasChildren() const { return FALSE; }  	virtual BOOL isUpToDate() const { return TRUE; } -	/*virtual*/ void clearDisplayName() { mDisplayName.clear(); } -  	LLViewerInventoryItem* getItem() const;  protected:  	BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response);  	virtual BOOL isItemPermissive() const; -	static void buildDisplayName(LLInventoryItem* item, std::string& name); +	virtual void buildDisplayName() const; -	mutable std::string mDisplayName;  };  class LLFolderBridge : public LLInvFVBridge @@ -232,15 +243,18 @@ class LLFolderBridge : public LLInvFVBridge  public:  	LLFolderBridge(LLInventoryPanel* inventory,   				   LLFolderView* root, -				   const LLUUID& uuid) : -		LLInvFVBridge(inventory, root, uuid), +				   const LLUUID& uuid)  +        :       LLInvFVBridge(inventory, root, uuid),  		mCallingCards(FALSE), -		mWearables(FALSE) +		mWearables(FALSE), +		mIsLoading(false)  	{}  	BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg);  	BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); +    virtual void buildDisplayName() const; +  	virtual void performAction(LLInventoryModel* model, std::string action);  	virtual void openItem();  	virtual void closeItem(); @@ -250,7 +264,9 @@ public:  	virtual LLFolderType::EType getPreferredType() const;  	virtual LLUIImagePtr getIcon() const; -	virtual LLUIImagePtr getOpenIcon() const; +	virtual LLUIImagePtr getIconOpen() const; +	virtual LLUIImagePtr getIconOverlay() const; +  	static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);  	virtual BOOL renameItem(const std::string& new_name); @@ -262,7 +278,7 @@ public:  	virtual void pasteFromClipboard();  	virtual void pasteLinkFromClipboard();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); -	virtual BOOL hasChildren() const; +	virtual bool hasChildren() const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type,  							void* cargo_data, @@ -275,20 +291,24 @@ public:  	virtual BOOL isClipboardPasteable() const;  	virtual BOOL isClipboardPasteableAsLink() const; +	EInventorySortGroup getSortGroup()  const; +	virtual void update(); +  	static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);  	LLViewerInventoryCategory* getCategory() const;  	LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } +	bool isLoading() { return mIsLoading; } +  protected: -	void buildContextMenuBaseOptions(U32 flags); -	void buildContextMenuFolderOptions(U32 flags); +	void buildContextMenuOptions(U32 flags, menuentry_vec_t& items,   menuentry_vec_t& disabled_items); +	void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items,   menuentry_vec_t& disabled_items);  	//--------------------------------------------------------------------  	// Menu callbacks  	//--------------------------------------------------------------------  	static void pasteClipboard(void* user_data); -	static void createNewCategory(void* user_data);  	static void createNewShirt(void* user_data);  	static void createNewPants(void* user_data);  	static void createNewShoes(void* user_data); @@ -308,8 +328,6 @@ protected:  	void modifyOutfit(BOOL append);  	void determineFolderType(); -	menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items -  	void dropToFavorites(LLInventoryItem* inv_item);  	void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); @@ -321,11 +339,12 @@ public:  	static void staticFolderOptionsMenu();  private: -	BOOL				mCallingCards; -	BOOL				mWearables; -	menuentry_vec_t		mItems; -	menuentry_vec_t		mDisabledItems; -	LLRootHandle<LLFolderBridge> mHandle; + +	bool							mCallingCards; +	bool							mWearables; +	bool							mIsLoading; +	LLTimer							mTimeSinceRequestStart; +	LLRootHandle<LLFolderBridge>	mHandle;  };  class LLTextureBridge : public LLItemBridge @@ -354,7 +373,6 @@ public:  				  const LLUUID& uuid) :  		LLItemBridge(inventory, root, uuid) {}  	virtual void openItem(); -	virtual void previewItem();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	static void openSoundPreview(void*);  }; @@ -544,7 +562,6 @@ class LLMeshBridge : public LLItemBridge  public:  	virtual LLUIImagePtr getIcon() const;  	virtual void openItem(); -	virtual void previewItem();  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  protected: @@ -620,7 +637,7 @@ public:  };  // Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel -class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLRecentInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder  {  public:  	// Overrides FolderBridge for Recent Inventory Panel. @@ -629,6 +646,7 @@ public:  		LLAssetType::EType actual_asset_type,  		LLInventoryType::EType inv_type,  		LLInventoryPanel* inventory, +		LLFolderViewModelInventory* view_model,  		LLFolderView* root,  		const LLUUID& uuid,  		U32 flags = 0x00) const; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 4573074c73..c913269aad 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -29,7 +29,7 @@  #include "llinventoryfilter.h"  // viewer includes -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llfolderviewitem.h"  #include "llinventorymodel.h"  #include "llinventorymodelbackgroundfetch.h" @@ -42,109 +42,90 @@  #include "llclipboard.h"  #include "lltrans.h" +//TODO RN: fix use of static cast as much as possible +  LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); -LLInventoryFilter::FilterOps::FilterOps() : -	mFilterObjectTypes(0xffffffffffffffffULL), -	mFilterCategoryTypes(0xffffffffffffffffULL), -	mFilterWearableTypes(0xffffffffffffffffULL), -	mMinDate(time_min()), -	mMaxDate(time_max()), -	mHoursAgo(0), -	mShowFolderState(SHOW_NON_EMPTY_FOLDERS), -	mPermissions(PERM_NONE), -	mFilterTypes(FILTERTYPE_OBJECT), -	mFilterUUID(LLUUID::null), -	mFilterLinks(FILTERLINK_INCLUDE_LINKS) +LLInventoryFilter::FilterOps::FilterOps(const Params& p) +:	mFilterObjectTypes(p.object_types), +	mFilterCategoryTypes(p.category_types), +	mFilterWearableTypes(p.wearable_types), +	mMinDate(p.date_range.min_date), +	mMaxDate(p.date_range.max_date), +	mHoursAgo(p.hours_ago), +	mShowFolderState(p.show_folder_state), +	mPermissions(p.permissions), +	mFilterTypes(p.types), +	mFilterUUID(p.uuid), +	mFilterLinks(p.links)  {  }  ///----------------------------------------------------------------------------  /// Class LLInventoryFilter  ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) -:	mName(name), -	mModified(FALSE), -	mNeedTextRebuild(TRUE), -	mEmptyLookupMessage("InventoryNoMatchingItems") +LLInventoryFilter::LLInventoryFilter(const Params& p) +:	mName(p.name), +	mFilterModified(FILTER_NONE), +	mEmptyLookupMessage("InventoryNoMatchingItems"), +    mFilterOps(p.filter_ops), +	mFilterSubString(p.substring), +	mCurrentGeneration(0), +	mFirstRequiredGeneration(0), +	mFirstSuccessGeneration(0), +	mFilterCount(0)  { -	mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately - -	mSubStringMatchOffset = 0; -	mFilterSubString.clear(); -	mFilterGeneration = 0; -	mMustPassGeneration = S32_MAX; -	mMinRequiredGeneration = 0; -	mFilterCount = 0; -	mNextFilterGeneration = mFilterGeneration + 1; - -	mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); -	mFilterBehavior = FILTER_NONE; +	mNextFilterGeneration = mCurrentGeneration + 1;  	// copy mFilterOps into mDefaultFilterOps  	markDefault();  } -LLInventoryFilter::~LLInventoryFilter() -{ -} - -BOOL LLInventoryFilter::check(const LLFolderViewItem* item)  +bool LLInventoryFilter::check(const LLFolderViewModelItem* item)   { +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item);  	// Clipboard cut items are *always* filtered so we need this value upfront -	const LLFolderViewEventListener* listener = item->getListener();  	const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE);  	// If it's a folder and we're showing all folders, return automatically. -	const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL); +	const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;  	if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))  	{  		return passed_clipboard;  	} -	mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; +	std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos; -	const BOOL passed_filtertype = checkAgainstFilterType(item); -	const BOOL passed_permissions = checkAgainstPermissions(item); -	const BOOL passed_filterlink = checkAgainstFilterLinks(item); -	const BOOL passed = (passed_filtertype && -						 passed_permissions && -						 passed_filterlink && -						 passed_clipboard && -						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); +	BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos); +	passed = passed && checkAgainstFilterType(listener); +	passed = passed && checkAgainstPermissions(listener); +	passed = passed && checkAgainstFilterLinks(listener); +	passed = passed && passed_clipboard;  	return passed;  }  bool LLInventoryFilter::check(const LLInventoryItem* item)  { -	mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; +	std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos;  	const bool passed_filtertype = checkAgainstFilterType(item);  	const bool passed_permissions = checkAgainstPermissions(item);  	const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); -	const bool passed = (passed_filtertype && -						 passed_permissions && -						 passed_clipboard && -						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); +	const bool passed = (passed_filtertype  +		&& passed_permissions +		&& passed_clipboard  +		&&	(mFilterSubString.size() == 0 || string_offset != std::string::npos));  	return passed;  } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const  { -	if (!folder) -	{ -		llwarns << "The filter can not be checked on an invalid folder." << llendl; -		llassert(false); // crash in development builds -		return false; -	} - -	const LLFolderViewEventListener* listener = folder->getListener(); +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item);  	if (!listener)  	{ -		llwarns << "Folder view event listener not found." << llendl; -		llassert(false); // crash in development builds +		llerrs << "Folder view event listener not found." << llendl;  		return false;  	} @@ -155,6 +136,13 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const  bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  { +	// when applying a filter, matching folders get their contents downloaded first +	if (isNotDefault() +		&& !gInventory.isCategoryComplete(folder_id)) +	{ +		LLInventoryModelBackgroundFetch::instance().start(folder_id); +	} +  	// Always check against the clipboard  	const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -163,14 +151,14 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  	{  		return passed_clipboard;  	} - +	  	if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)  	{  		// Can only filter categories for items in your inventory  		// (e.g. versus in-world object contents).  		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);  		if (!cat) -			return false; +			return folder_id.isNull();  		LLFolderType::EType cat_type = cat->getPreferredType();  		if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))  			return false; @@ -179,9 +167,8 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const  	return passed_clipboard;  } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return FALSE;  	LLInventoryType::EType object_type = listener->getInventoryType(); @@ -268,7 +255,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  			}  		}  	} - +	  	return TRUE;  } @@ -347,13 +334,12 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const  	return true;  } -BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return FALSE;  	PermissionMask perm = listener->getPermissionMask(); -	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener()); +	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(listener);  	if (bridge && bridge->isLink())  	{  		const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -375,9 +361,8 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con  	return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;  } -BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const  { -	const LLFolderViewEventListener* listener = item->getListener();  	if (!listener) return TRUE;  	const LLUUID object_id = listener->getUUID(); @@ -397,20 +382,21 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const  	return mFilterSubString;  } -std::string::size_type LLInventoryFilter::getStringMatchOffset() const +std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const  { -	return mSubStringMatchOffset; +	const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item); +	return mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos;  } -BOOL LLInventoryFilter::isDefault() const +bool LLInventoryFilter::isDefault() const  {  	return !isNotDefault();  }  // has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() const +bool LLInventoryFilter::isNotDefault() const  { -	BOOL not_default = FALSE; +	S32 not_default = 0;  	not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes);  	not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); @@ -422,11 +408,11 @@ BOOL LLInventoryFilter::isNotDefault() const  	not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate);  	not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate);  	not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); -	 -	return not_default; + +	return not_default != 0;  } -BOOL LLInventoryFilter::isActive() const +bool LLInventoryFilter::isActive() const  {  	return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL  		|| mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL @@ -440,16 +426,9 @@ BOOL LLInventoryFilter::isActive() const  		|| mFilterOps.mHoursAgo != 0;  } -BOOL LLInventoryFilter::isModified() const +bool LLInventoryFilter::isModified() const  { -	return mModified; -} - -BOOL LLInventoryFilter::isModifiedAndClear() -{ -	BOOL ret = mModified; -	mModified = FALSE; -	return ret; +	return mFilterModified != FILTER_NONE;  }  void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) @@ -613,9 +592,10 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)  void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  { +	static LLCachedControl<U32> s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0);  	if (sl && !isSinceLogoff())  	{ -		setDateRange(mLastLogoff, time_max()); +		setDateRange(s_last_logoff(), time_max());  		setModified();  	}  	if (!sl && isSinceLogoff()) @@ -634,17 +614,18 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  	}  } -BOOL LLInventoryFilter::isSinceLogoff() const +bool LLInventoryFilter::isSinceLogoff() const  { -	return (mFilterOps.mMinDate == (time_t)mLastLogoff) && +	static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); + +	return (mFilterOps.mMinDate == (time_t)s_last_logoff()) &&  		(mFilterOps.mMaxDate == time_max()) &&  		(mFilterOps.mFilterTypes & FILTERTYPE_DATE);  }  void LLInventoryFilter::clearModified()  { -	mModified = FALSE;  -	mFilterBehavior = FILTER_NONE; +	mFilterModified = FILTER_NONE;  }  void LLInventoryFilter::setHoursAgo(U32 hours) @@ -722,15 +703,6 @@ void LLInventoryFilter::setShowFolderState(EFolderShow state)  	}  } -void LLInventoryFilter::setSortOrder(U32 order) -{ -	if (mOrder != order) -	{ -		mOrder = order; -		setModified(); -	} -} -  void LLInventoryFilter::markDefault()  {  	mDefaultFilterOps = mFilterOps; @@ -742,83 +714,68 @@ void LLInventoryFilter::resetDefault()  	setModified();  } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +void LLInventoryFilter::setModified(EFilterModified behavior)  { -	mModified = TRUE; -	mNeedTextRebuild = TRUE; -	mFilterGeneration = mNextFilterGeneration++; +	mFilterText.clear(); +	mCurrentGeneration = mNextFilterGeneration++; -	if (mFilterBehavior == FILTER_NONE) +	if (mFilterModified == FILTER_NONE)  	{ -		mFilterBehavior = behavior; +		mFilterModified = behavior;  	} -	else if (mFilterBehavior != behavior) +	else if (mFilterModified != behavior)  	{  		// trying to do both less restrictive and more restrictive filter  		// basically means restart from scratch -		mFilterBehavior = FILTER_RESTART; +		mFilterModified = FILTER_RESTART;  	} -	if (isNotDefault()) +	// if not keeping current filter results, update last valid as well +	switch(mFilterModified)  	{ -		// if not keeping current filter results, update last valid as well -		switch(mFilterBehavior) -		{ -			case FILTER_RESTART: -				mMustPassGeneration = mFilterGeneration; -				mMinRequiredGeneration = mFilterGeneration; -				break; -			case FILTER_LESS_RESTRICTIVE: -				mMustPassGeneration = mFilterGeneration; -				break; -			case FILTER_MORE_RESTRICTIVE: -				mMinRequiredGeneration = mFilterGeneration; -				// must have passed either current filter generation (meaningless, as it hasn't been run yet) -				// or some older generation, so keep the value -				mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); -				break; -			default: -				llerrs << "Bad filter behavior specified" << llendl; -		} -	} -	else -	{ -		// shortcut disabled filters to show everything immediately -		mMinRequiredGeneration = 0; -		mMustPassGeneration = S32_MAX; +		case FILTER_RESTART: +			mFirstRequiredGeneration = mCurrentGeneration; +			mFirstSuccessGeneration = mCurrentGeneration; +			break; +		case FILTER_LESS_RESTRICTIVE: +			mFirstRequiredGeneration = mCurrentGeneration; +			break; +		case FILTER_MORE_RESTRICTIVE: +			mFirstSuccessGeneration = mCurrentGeneration; +			break; +		default: +			llerrs << "Bad filter behavior specified" << llendl;  	}  } -BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const +bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const  {  	return mFilterOps.mFilterObjectTypes & (1LL << t);  }  const std::string& LLInventoryFilter::getFilterText()  { -	if (!mNeedTextRebuild) +	if (!mFilterText.empty())  	{  		return mFilterText;  	} -	mNeedTextRebuild = FALSE;  	std::string filtered_types;  	std::string not_filtered_types;  	BOOL filtered_by_type = FALSE;  	BOOL filtered_by_all_types = TRUE;  	S32 num_filter_types = 0; +  	mFilterText.clear();  	if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION))  	{ -		//filtered_types += " Animations,";  		filtered_types += LLTrans::getString("Animations");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Animations,";  		not_filtered_types += LLTrans::getString("Animations");  		filtered_by_all_types = FALSE; @@ -826,140 +783,120 @@ const std::string& LLInventoryFilter::getFilterText()  	if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD))  	{ -		//filtered_types += " Calling Cards,";  		filtered_types += LLTrans::getString("Calling Cards");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Calling Cards,";  		not_filtered_types += LLTrans::getString("Calling Cards");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE))  	{ -		//filtered_types += " Clothing,";  		filtered_types +=  LLTrans::getString("Clothing");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Clothing,";  		not_filtered_types +=  LLTrans::getString("Clothing");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE))  	{ -		//filtered_types += " Gestures,";  		filtered_types +=  LLTrans::getString("Gestures");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Gestures,";  		not_filtered_types +=  LLTrans::getString("Gestures");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK))  	{ -		//filtered_types += " Landmarks,";  		filtered_types +=  LLTrans::getString("Landmarks");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Landmarks,";  		not_filtered_types +=  LLTrans::getString("Landmarks");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))  	{ -		//filtered_types += " Notecards,";  		filtered_types +=  LLTrans::getString("Notecards");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Notecards,";  		not_filtered_types +=  LLTrans::getString("Notecards");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT))  	{ -		//filtered_types += " Objects,";  		filtered_types +=  LLTrans::getString("Objects");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Objects,";  		not_filtered_types +=  LLTrans::getString("Objects");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_LSL))  	{ -		//filtered_types += " Scripts,";  		filtered_types +=  LLTrans::getString("Scripts");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Scripts,";  		not_filtered_types +=  LLTrans::getString("Scripts");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND))  	{ -		//filtered_types += " Sounds,";  		filtered_types +=  LLTrans::getString("Sounds");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Sounds,";  		not_filtered_types +=  LLTrans::getString("Sounds");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE))  	{ -		//filtered_types += " Textures,";  		filtered_types +=  LLTrans::getString("Textures");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Textures,";  		not_filtered_types +=  LLTrans::getString("Textures");  		filtered_by_all_types = FALSE;  	}  	if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT))  	{ -		//filtered_types += " Snapshots,";  		filtered_types +=  LLTrans::getString("Snapshots");  		filtered_by_type = TRUE;  		num_filter_types++;  	}  	else  	{ -		//not_filtered_types += " Snapshots,";  		not_filtered_types +=  LLTrans::getString("Snapshots");  		filtered_by_all_types = FALSE;  	} @@ -975,7 +912,6 @@ const std::string& LLInventoryFilter::getFilterText()  		}  		else  		{ -			//mFilterText += "No ";  			mFilterText += LLTrans::getString("No Filters");  			mFilterText += not_filtered_types;  		} @@ -985,66 +921,55 @@ const std::string& LLInventoryFilter::getFilterText()  	if (isSinceLogoff())  	{ -		//mFilterText += " - Since Logoff";  		mFilterText += LLTrans::getString("Since Logoff");  	}  	return mFilterText;  } -void LLInventoryFilter::toLLSD(LLSD& data) const -{ -	data["filter_types"] = (LLSD::Integer)getFilterObjectTypes(); -	data["min_date"] = (LLSD::Integer)getMinDate(); -	data["max_date"] = (LLSD::Integer)getMaxDate(); -	data["hours_ago"] = (LLSD::Integer)getHoursAgo(); -	data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); -	data["permissions"] = (LLSD::Integer)getFilterPermissions(); -	data["substring"] = (LLSD::String)getFilterSubString(); -	data["sort_order"] = (LLSD::Integer)getSortOrder(); -	data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); -} -void LLInventoryFilter::fromLLSD(LLSD& data) +LLInventoryFilter& LLInventoryFilter::operator=( const  LLInventoryFilter&  other )  { -	if(data.has("filter_types")) -	{ -		setFilterObjectTypes((U64)data["filter_types"].asInteger()); -	} - -	if(data.has("min_date") && data.has("max_date")) -	{ -		setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); -	} - -	if(data.has("hours_ago")) -	{ -		setHoursAgo((U32)data["hours_ago"].asInteger()); -	} - -	if(data.has("show_folder_state")) -	{ -		setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); -	} +	setFilterObjectTypes(other.getFilterObjectTypes()); +	setDateRange(other.getMinDate(), other.getMaxDate()); +	setHoursAgo(other.getHoursAgo()); +	setShowFolderState(other.getShowFolderState()); +	setFilterPermissions(other.getFilterPermissions()); +	setFilterSubString(other.getFilterSubString()); +	setDateRangeLastLogoff(other.isSinceLogoff()); +	return *this; +} -	if(data.has("permissions")) -	{ -		setFilterPermissions((PermissionMask)data["permissions"].asInteger()); -	} -	if(data.has("substring")) -	{ -		setFilterSubString(std::string(data["substring"].asString())); -	} +void LLInventoryFilter::toParams(Params& params) const +{ +	params.filter_ops.types = getFilterObjectTypes(); +	params.filter_ops.category_types = getFilterCategoryTypes(); +	params.filter_ops.wearable_types = getFilterWearableTypes(); +	params.filter_ops.date_range.min_date = getMinDate(); +	params.filter_ops.date_range.max_date = getMaxDate(); +	params.filter_ops.hours_ago = getHoursAgo(); +	params.filter_ops.show_folder_state = getShowFolderState(); +	params.filter_ops.permissions = getFilterPermissions(); +	params.substring = getFilterSubString(); +	params.since_logoff = isSinceLogoff(); +} -	if(data.has("sort_order")) +void LLInventoryFilter::fromParams(const Params& params) +{ +	if (!params.validateBlock())  	{ -		setSortOrder((U32)data["sort_order"].asInteger()); +		return;  	} -	if(data.has("since_logoff")) -	{ -		setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); -	} +	setFilterObjectTypes(params.filter_ops.types); +	setFilterCategoryTypes(params.filter_ops.category_types); +	setFilterWearableTypes(params.filter_ops.wearable_types); +	setDateRange(params.filter_ops.date_range.min_date,   params.filter_ops.date_range.max_date); +	setHoursAgo(params.filter_ops.hours_ago); +	setShowFolderState(params.filter_ops.show_folder_state); +	setFilterPermissions(params.filter_ops.permissions); +	setFilterSubString(params.substring); +	setDateRangeLastLogoff(params.since_logoff);  }  U64 LLInventoryFilter::getFilterObjectTypes() const @@ -1057,11 +982,21 @@ U64 LLInventoryFilter::getFilterCategoryTypes() const  	return mFilterOps.mFilterCategoryTypes;  } -BOOL LLInventoryFilter::hasFilterString() const +U64 LLInventoryFilter::getFilterWearableTypes() const +{ +	return mFilterOps.mFilterWearableTypes; +} + +bool LLInventoryFilter::hasFilterString() const  {  	return mFilterSubString.size() > 0;  } +std::string::size_type LLInventoryFilter::getFilterStringSize() const +{ +	return mFilterSubString.size(); +} +  PermissionMask LLInventoryFilter::getFilterPermissions() const  {  	return mFilterOps.mPermissions; @@ -1088,14 +1023,6 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const  {   	return mFilterOps.mShowFolderState;   } -U32 LLInventoryFilter::getSortOrder() const  -{  -	return mOrder;  -} -const std::string& LLInventoryFilter::getName() const  -{  -	return mName;  -}  void LLInventoryFilter::setFilterCount(S32 count)   {  @@ -1113,15 +1040,15 @@ void LLInventoryFilter::decrementFilterCount()  S32 LLInventoryFilter::getCurrentGeneration() const   {  -	return mFilterGeneration;  +	return mCurrentGeneration;  } -S32 LLInventoryFilter::getMinRequiredGeneration() const  +S32 LLInventoryFilter::getFirstSuccessGeneration() const  {  -	return mMinRequiredGeneration;  +	return mFirstSuccessGeneration;   } -S32 LLInventoryFilter::getMustPassGeneration() const  +S32 LLInventoryFilter::getFirstRequiredGeneration() const  {  -	return mMustPassGeneration;  +	return mFirstRequiredGeneration;   }  void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) @@ -1129,9 +1056,12 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)  	mEmptyLookupMessage = message;  } -const std::string& LLInventoryFilter::getEmptyLookupMessage() const +std::string LLInventoryFilter::getEmptyLookupMessage() const  { -	return mEmptyLookupMessage; +	LLStringUtil::format_map_t args; +	args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); + +	return LLTrans::getString(mEmptyLookupMessage, args);  } @@ -1141,3 +1071,27 @@ bool LLInventoryFilter::areDateLimitsSet()  			|| mFilterOps.mMaxDate != time_max()  			|| mFilterOps.mHoursAgo != 0;  } + +bool LLInventoryFilter::showAllResults() const +{ +	return hasFilterString(); +} + + + +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool   emit_errors /*= true*/ ) const +{ +	bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); +	if (valid) +	{ +		if (max_date() < min_date()) +		{ +			if (emit_errors) +			{ +				llwarns << "max_date should be greater or equal to min_date" <<   llendl; +			} +			valid = false; +		} +	} +	return valid; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 9e600c036f..4912b5ca91 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -29,12 +29,13 @@  #include "llinventorytype.h"  #include "llpermissionsflags.h" +#include "llfolderviewmodel.h"  class LLFolderViewItem;  class LLFolderViewFolder;  class LLInventoryItem; -class LLInventoryFilter +class LLInventoryFilter : public LLFolderViewFilter  {  public:  	enum EFolderShow @@ -44,14 +45,6 @@ public:  		SHOW_NO_FOLDERS  	}; -	enum EFilterBehavior -	{ -		FILTER_NONE,				// nothing to do, already filtered -		FILTER_RESTART,				// restart filtering from scratch -		FILTER_LESS_RESTRICTIVE,	// existing filtered items will certainly pass this filter -		FILTER_MORE_RESTRICTIVE		// if you didn't pass the previous filter, you definitely won't pass this one -	}; -  	enum EFilterType	{  		FILTERTYPE_NONE = 0,  		FILTERTYPE_OBJECT = 0x1 << 0,	// normal default search-by-object-type @@ -59,7 +52,7 @@ public:  		FILTERTYPE_UUID	= 0x1 << 2,		// find the object with UUID and any links to it  		FILTERTYPE_DATE = 0x1 << 3,		// search by date range  		FILTERTYPE_WEARABLE = 0x1 << 4,	// search by wearable type -		FILTERTYPE_EMPTYFOLDERS = 0x1 << 5	// pass if folder is not a system folder to be hidden if empty +		FILTERTYPE_EMPTYFOLDERS = 0x1 << 5		// pass if folder is not a system   folder to be hidden if  	};  	enum EFilterLink @@ -77,16 +70,92 @@ public:  		SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2	// Force system folders to be on top  	}; -	LLInventoryFilter(const std::string& name); -	virtual ~LLInventoryFilter(); +	struct FilterOps +	{ +		struct DateRange : public LLInitParam::Block<DateRange> +		{ +			Optional<time_t>	min_date, +								max_date; + +			DateRange() +			:	min_date("min_date", time_min()), +				max_date("max_date", time_max()) +			{} + +			bool validateBlock(bool emit_errors = true) const; +		}; + +		struct Params : public LLInitParam::Block<Params> +		{ +			Optional<U32>				types; +			Optional<U64>				object_types, +										wearable_types, +										category_types; +			Optional<EFilterLink>		links; +			Optional<LLUUID>			uuid; +			Optional<DateRange>			date_range; +			Optional<S32>				hours_ago; +			Optional<EFolderShow>		show_folder_state; +			Optional<PermissionMask>	permissions; + +			Params() +			:	types("filter_types", FILTERTYPE_OBJECT), +				object_types("object_types", 0xffffFFFFffffFFFFULL), +				wearable_types("wearable_types", 0xffffFFFFffffFFFFULL), +				category_types("category_types", 0xffffFFFFffffFFFFULL), +				links("links", FILTERLINK_INCLUDE_LINKS), +				uuid("uuid"), +				date_range("date_range"), +				hours_ago("hours_ago", 0), +				show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS), +				permissions("permissions", PERM_NONE) +			{} +		}; + +		FilterOps(const Params& = Params()); + +		U32 			mFilterTypes; +		U64				mFilterObjectTypes,   // For _OBJECT +						mFilterWearableTypes, +						mFilterLinks, +						mFilterCategoryTypes; // For _CATEGORY +		LLUUID      	mFilterUUID; 		  // for UUID + +		time_t			mMinDate, +						mMaxDate; +		U32				mHoursAgo; + +		EFolderShow		mShowFolderState; +		PermissionMask	mPermissions; +	}; +							 +	struct Params : public LLInitParam::Block<Params> +	{ +		Optional<std::string>		name; +		Optional<FilterOps::Params>	filter_ops; +		Optional<std::string>		substring; +		Optional<bool>				since_logoff; + +		Params() +		:	name("name"), +			filter_ops(""), +			substring("substring"), +			since_logoff("since_logoff") +		{} +	}; +									 +	LLInventoryFilter(const Params& p = Params()); +	LLInventoryFilter(const LLInventoryFilter& other) { *this = other; } +	virtual ~LLInventoryFilter() {}  	// +-------------------------------------------------------------------+  	// + Parameters  	// +-------------------------------------------------------------------+ -	void 				setFilterObjectTypes(U64 types);  	U64 				getFilterObjectTypes() const;  	U64					getFilterCategoryTypes() const; -	BOOL 				isFilterObjectTypesWith(LLInventoryType::EType t) const; +	U64					getFilterWearableTypes() const; +	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const; +	void 				setFilterObjectTypes(U64 types);  	void 				setFilterCategoryTypes(U64 types);  	void 				setFilterUUID(const LLUUID &object_id);  	void				setFilterWearableTypes(U64 types); @@ -96,7 +165,7 @@ public:  	void 				setFilterSubString(const std::string& string);  	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;  	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; }  -	BOOL 				hasFilterString() const; +	bool 				hasFilterString() const;  	void 				setFilterPermissions(PermissionMask perms);  	PermissionMask 		getFilterPermissions() const; @@ -115,43 +184,35 @@ public:  	// +-------------------------------------------------------------------+  	// + Execution And Results  	// +-------------------------------------------------------------------+ -	BOOL 				check(const LLFolderViewItem* item); +	bool				check(const LLFolderViewModelItem* listener);  	bool				check(const LLInventoryItem* item); -	bool				checkFolder(const LLFolderViewFolder* folder) const; +	bool				checkFolder(const LLFolderViewModelItem* listener) const;  	bool				checkFolder(const LLUUID& folder_id) const; -	BOOL 				checkAgainstFilterType(const LLFolderViewItem* item) const; -	bool 				checkAgainstFilterType(const LLInventoryItem* item) const; -	BOOL 				checkAgainstPermissions(const LLFolderViewItem* item) const; -	bool 				checkAgainstPermissions(const LLInventoryItem* item) const; -	BOOL 				checkAgainstFilterLinks(const LLFolderViewItem* item) const; -	bool				checkAgainstClipboard(const LLUUID& object_id) const; -	std::string::size_type getStringMatchOffset() const; +	bool				showAllResults() const; +	std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const; +	std::string::size_type getFilterStringSize() const;  	// +-------------------------------------------------------------------+  	// + Presentation  	// +-------------------------------------------------------------------+  	void 				setShowFolderState( EFolderShow state);  	EFolderShow 		getShowFolderState() const; -	void 				setSortOrder(U32 order); -	U32 				getSortOrder() const; -  	void 				setEmptyLookupMessage(const std::string& message); -	const std::string&	getEmptyLookupMessage() const; +	std::string			getEmptyLookupMessage() const;  	// +-------------------------------------------------------------------+  	// + Status  	// +-------------------------------------------------------------------+ -	BOOL 				isActive() const; -	BOOL 				isModified() const; -	BOOL 				isModifiedAndClear(); -	BOOL 				isSinceLogoff() const; +	bool 				isActive() const; +	bool 				isModified() const; +	bool 				isSinceLogoff() const;  	void 				clearModified(); -	const std::string& 	getName() const; +	const std::string& 	getName() const { return mName; }  	const std::string& 	getFilterText();  	//RN: this is public to allow system to externally force a global refilter -	void 				setModified(EFilterBehavior behavior = FILTER_RESTART); +	void 				setModified(EFilterModified behavior = FILTER_RESTART);  	// +-------------------------------------------------------------------+  	// + Count @@ -163,8 +224,8 @@ public:  	// +-------------------------------------------------------------------+  	// + Default  	// +-------------------------------------------------------------------+ -	BOOL 				isDefault() const; -	BOOL 				isNotDefault() const; +	bool 				isDefault() const; +	bool 				isNotDefault() const;  	void 				markDefault();  	void 				resetDefault(); @@ -172,57 +233,42 @@ public:  	// + Generation  	// +-------------------------------------------------------------------+  	S32 				getCurrentGeneration() const; -	S32 				getMinRequiredGeneration() const; -	S32 				getMustPassGeneration() const; +	S32 				getFirstSuccessGeneration() const; +	S32 				getFirstRequiredGeneration() const; +  	// +-------------------------------------------------------------------+  	// + Conversion  	// +-------------------------------------------------------------------+ -	void 				toLLSD(LLSD& data) const; -	void 				fromLLSD(LLSD& data); +	void 				toParams(Params& params) const; +	void 				fromParams(const Params& p); + +	LLInventoryFilter& operator =(const LLInventoryFilter& other);  private:  	bool				areDateLimitsSet(); - -	struct FilterOps -	{ -		FilterOps(); -		U32 			mFilterTypes; - -		U64				mFilterObjectTypes; // For _OBJECT -		U64				mFilterWearableTypes; -		U64				mFilterCategoryTypes; // For _CATEGORY -		LLUUID      	mFilterUUID; // for UUID - -		time_t			mMinDate; -		time_t			mMaxDate; -		U32				mHoursAgo; -		EFolderShow		mShowFolderState; -		PermissionMask	mPermissions; -		U64				mFilterLinks; -	}; - -	U32						mOrder; -	U32 					mLastLogoff; +	bool 				checkAgainstFilterType(const class LLFolderViewModelItemInventory* listener) const; +	bool 				checkAgainstFilterType(const LLInventoryItem* item) const; +	bool 				checkAgainstPermissions(const class LLFolderViewModelItemInventory* listener) const; +	bool 				checkAgainstPermissions(const LLInventoryItem* item) const; +	bool 				checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; +	bool				checkAgainstClipboard(const LLUUID& object_id) const;  	FilterOps				mFilterOps;  	FilterOps				mDefaultFilterOps; -	std::string::size_type	mSubStringMatchOffset;  	std::string				mFilterSubString;  	std::string				mFilterSubStringOrig;  	const std::string		mName; -	S32						mFilterGeneration; -	S32						mMustPassGeneration; -	S32						mMinRequiredGeneration; +	S32						mCurrentGeneration; +	S32						mFirstRequiredGeneration; +	S32						mFirstSuccessGeneration;  	S32						mNextFilterGeneration;  	S32						mFilterCount; -	EFilterBehavior 		mFilterBehavior; +	EFilterModified 		mFilterModified; -	BOOL 					mModified; -	BOOL 					mNeedTextRebuild;  	std::string 			mFilterText;  	std::string 			mEmptyLookupMessage;  }; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ab5b082915..07f3dd8ffb 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -45,7 +45,7 @@  // newview includes  #include "llappearancemgr.h"  #include "llappviewer.h" -//#include "llfirstuse.h" +#include "llclipboard.h"  #include "llfloaterinventory.h"  #include "llfloatersidepanelcontainer.h"  #include "llfocusmgr.h" @@ -74,8 +74,10 @@  #include "llsidepanelinventory.h"  #include "lltabcontainer.h"  #include "lltooldraganddrop.h" +#include "lltrans.h"  #include "lluictrlfactory.h"  #include "llviewermessage.h" +#include "llviewerfoldertype.h"  #include "llviewerobjectlist.h"  #include "llviewerregion.h"  #include "llviewerwindow.h" @@ -948,7 +950,7 @@ void LLSaveFolderState::setApply(BOOL apply)  void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)  {  	LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); -	LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); +	LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem();  	if(!bridge) return;  	if(mApply) @@ -983,7 +985,7 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)  void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)  { -	if (item->getFiltered()) +	if (item->passedFilter())  	{  		item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);  	} @@ -991,12 +993,12 @@ void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)  void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getFiltered() && folder->getParentFolder()) +	if (folder->LLFolderViewItem::passedFilter() && folder->getParentFolder())  	{  		folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);  	}  	// if this folder didn't pass the filter, and none of its descendants did -	else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) +	else if (!folder->getViewModelItem()->passedFilter() && !folder->getViewModelItem()->descendantsPassedFilter())  	{  		folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);  	} @@ -1004,7 +1006,7 @@ void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)  void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)  { -	if (item->getFiltered() && !mItemSelected) +	if (item->passedFilter() && !mItemSelected)  	{  		item->getRoot()->setSelection(item, FALSE, FALSE);  		if (item->getParentFolder()) @@ -1017,7 +1019,7 @@ void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)  void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getFiltered() && !mItemSelected) +	if (folder->LLFolderViewItem::passedFilter() && !mItemSelected)  	{  		folder->getRoot()->setSelection(folder, FALSE, FALSE);  		if (folder->getParentFolder()) @@ -1044,3 +1046,87 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)  	}  } +void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action) +{ +	if ("rename" == action) +	{ +		root->startRenamingSelectedItem(); +		return; +	} +	if ("delete" == action) +	{ +		LLSD args; +		args["QUESTION"] = LLTrans::getString(root->getNumSelectedItems() > 1 ? "DeleteItems" :  "DeleteItem"); +		LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); +		return; +	} +	if (("copy" == action) || ("cut" == action)) +	{	 +		// Clear the clipboard before we start adding things on it +		LLClipboard::instance().reset(); +	} + +	static const std::string change_folder_string = "change_folder_type_"; +	if (action.length() > change_folder_string.length() &&  +		(action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) +	{ +		LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); +		LLFolderViewModelItemInventory* inventory_item = static_cast<LLFolderViewModelItemInventory*>(root->getViewModelItem()); +		LLViewerInventoryCategory *cat = model->getCategory(inventory_item->getUUID()); +		if (!cat) return; +		cat->changeType(new_folder_type); +		return; +	} + + +	std::set<LLFolderViewItem*> selected_items = root->getSelectionList(); + +	LLMultiPreview* multi_previewp = NULL; +	LLMultiProperties* multi_propertiesp = NULL; + +	if (("task_open" == action  || "open" == action) && selected_items.size() > 1) +	{ +		multi_previewp = new LLMultiPreview(); +		gFloaterView->addChild(multi_previewp); + +		LLFloater::setFloaterHost(multi_previewp); + +	} +	else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) +	{ +		multi_propertiesp = new LLMultiProperties(); +		gFloaterView->addChild(multi_propertiesp); + +		LLFloater::setFloaterHost(multi_propertiesp); +	} + +	std::set<LLFolderViewItem*>::iterator set_iter; + +	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) +	{ +		LLFolderViewItem* folder_item = *set_iter; +		if(!folder_item) continue; +		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); +		if(!bridge) continue; +		bridge->performAction(model, action); +	} + +	LLFloater::setFloaterHost(NULL); +	if (multi_previewp) +	{ +		multi_previewp->openFloater(LLSD()); +	} +	else if (multi_propertiesp) +	{ +		multi_propertiesp->openFloater(LLSD()); +	} +} + +void LLInventoryAction::onItemsRemovalConfirmation( const LLSD& notification, const LLSD& response, LLFolderView* root ) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (option == 0) +	{ +		root->removeSelectedItems(); +	} +} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 5cf9c528b0..d8d3d9bbbb 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -418,21 +418,6 @@ public:  class LLFolderViewItem;  class LLFolderViewFolder; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: -	virtual ~LLFolderViewFunctor() {} -	virtual void doFolder(LLFolderViewFolder* folder) = 0; -	virtual void doItem(LLFolderViewItem* item) = 0; -};  class LLInventoryState  { @@ -442,49 +427,13 @@ public:  	static LLUUID sWearNewClothingTransactionID;	// wear all clothing in this transaction	  }; -class LLSelectFirstFilteredItem : public LLFolderViewFunctor +struct LLInventoryAction  { -public: -	LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} -	virtual ~LLSelectFirstFilteredItem() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -	BOOL wasItemSelected() { return mItemSelected; } -protected: -	BOOL mItemSelected; -}; +	static void doToSelected(class LLInventoryModel* model, class LLFolderView* root, const std::string& action); -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: -	LLOpenFilteredFolders()  {} -	virtual ~LLOpenFilteredFolders() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); +	static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLFolderView* root);  }; -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: -	LLSaveFolderState() : mApply(FALSE) {} -	virtual ~LLSaveFolderState() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item) {} -	void setApply(BOOL apply); -	void clearOpenFolders() { mOpenFolders.clear(); } -protected: -	std::set<LLUUID> mOpenFolders; -	BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: -	LLOpenFoldersWithSelection() {} -	virtual ~LLOpenFoldersWithSelection() {} -	virtual void doFolder(LLFolderViewFolder* folder); -	virtual void doItem(LLFolderViewItem* item); -};  #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6e23d7c701..0673970d89 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -373,13 +373,12 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)  // specifies 'type' as what it defaults to containing. The category is  // not necessarily only for that type. *NOTE: This will create a new  // inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type,  -													   bool create_folder,  -													   bool find_in_library) +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder/*,  +					  bool find_in_library*/)  {  	LLUUID rv = LLUUID::null; -	const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); +	const LLUUID &root_id = /*(find_in_library) ? gInventory.getLibraryRootFolderID() :*/ gInventory.getRootFolderID();  	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)  	{  		rv = root_id; @@ -402,7 +401,44 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType prefe  		}  	} -	if(rv.isNull() && isInventoryUsable() && (create_folder && !find_in_library)) +	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/)) +	{ +		if(root_id.notNull()) +		{ +			return createNewCategory(root_id, preferred_type, LLStringUtil::null); +		} +	} +	return rv; +} + +const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +{ +	LLUUID rv = LLUUID::null; + +	const LLUUID &root_id = gInventory.getLibraryRootFolderID(); +	if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) +	{ +		rv = root_id; +	} +	else if (root_id.notNull()) +	{ +		cat_array_t* cats = NULL; +		cats = get_ptr_in_map(mParentChildCategoryTree, root_id); +		if(cats) +		{ +			S32 count = cats->count(); +			for(S32 i = 0; i < count; ++i) +			{ +				if(cats->get(i)->getPreferredType() == preferred_type) +				{ +					rv = cats->get(i)->getUUID(); +					break; +				} +			} +		} +	} + +	if(rv.isNull() && isInventoryUsable() && (create_folder && true/*!find_in_library*/))  	{  		if(root_id.notNull())  		{ @@ -1245,14 +1281,33 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id)  							   items,  							   INCLUDE_TRASH);  			S32 count = items.count(); + +			item_map_t::iterator item_map_end = mItemMap.end(); +			cat_map_t::iterator cat_map_end = mCategoryMap.end(); +			LLUUID uu_id; +  			for(S32 i = 0; i < count; ++i)  			{ -				deleteObject(items.get(i)->getUUID()); +				uu_id = items.get(i)->getUUID(); + +				// This check prevents the deletion of a previously deleted item. +				// This is necessary because deletion is not done in a hierarchical +				// order. The current item may have been already deleted as a child +				// of its deleted parent. +				if (mItemMap.find(uu_id) != item_map_end) +				{ +					deleteObject(uu_id); +				}  			} +  			count = categories.count();  			for(S32 i = 0; i < count; ++i)  			{ -				deleteObject(categories.get(i)->getUUID()); +				uu_id = categories.get(i)->getUUID(); +				if (mCategoryMap.find(uu_id) != cat_map_end) +				{ +					deleteObject(uu_id); +				}  			}  		}  	} @@ -3239,68 +3294,7 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c  	}  } -//* @param[in] items vector of items in order to be saved. -void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) -{ -	int sortField = 0; - -	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field -	for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) -	{ -		LLViewerInventoryItem* item = *i; - -		item->setSortField(++sortField); -		item->setComplete(TRUE); -		item->updateServer(FALSE); - -		updateItem(item); - -		// Tell the parent folder to refresh its sort order. -		addChangedMask(LLInventoryObserver::SORT, item->getParentUUID()); -	} - -	notifyObservers(); -} - -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: -	bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) -	{ -		return a->getSortField() < b->getSortField(); -	} -}; -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ -	static LLViewerInventoryItemSort sort_functor; -	std::sort(items.begin(), items.end(), sort_functor); -} - -// * @param source_item_id - LLUUID of the source item to be moved into new position -// * @param target_item_id - LLUUID of the target item before which source item should be placed. -void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) -{ -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	LLIsType is_type(LLAssetType::AT_LANDMARK); -	LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - -	// ensure items are sorted properly before changing order. EXT-3498 -	rearrange_item_order_by_sort_field(items); - -	// update order -	updateItemsOrder(items, source_item_id, target_item_id); - -	saveItemsOrder(items); -}  //---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 8382e875b4..503de627a0 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -231,11 +231,12 @@ public:  	// Returns the uuid of the category that specifies 'type' as what it   	// defaults to containing. The category is not necessarily only for that type.   	//    NOTE: If create_folder is true, this will create a new inventory category  -	//    on the fly if one does not exist. *NOTE: if find_in_library is true it  -	//    will search in the user's library folder instead of "My Inventory" +	//    on the fly if one does not exist.   	const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type,  -										 bool create_folder = true,  -										 bool find_in_library = false); +										 bool create_folder = true); +	//    will search in the user's library folder instead of "My Inventory" +	const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type,  +												bool create_folder = true);  	// Get whatever special folder this object is a child of, if any.  	const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; @@ -362,15 +363,6 @@ public:  	// Returns end() of the vector if not found.  	static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); -	// Saves current order of the passed items using inventory item sort field. -	// Resets 'items' sort fields and saves them on server. -	// Is used to save order for Favorites folder. -	void saveItemsOrder(const LLInventoryModel::item_array_t& items); - -	// Rearranges Landmarks inside Favorites folder. -	// Moves source landmark before target one. -	void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); -  	//--------------------------------------------------------------------  	// Creation  	//-------------------------------------------------------------------- diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 71dd963f28..7fba52d47f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -38,11 +38,13 @@  #include "llfloaterreg.h"  #include "llfloatersidepanelcontainer.h"  #include "llfolderview.h" +#include "llfolderviewitem.h"  #include "llimfloater.h"  #include "llimview.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llinventorymodelbackgroundfetch.h" +#include "llpreview.h"  #include "llsidepanelinventory.h"  #include "llviewerattachmenu.h"  #include "llviewerfoldertype.h" @@ -53,8 +55,7 @@ static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");  const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");  const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");  const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); -static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; - +static const LLInventoryFolderViewModelBuilder INVENTORY_BRIDGE_BUILDER;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLInventoryPanelObserver @@ -134,13 +135,12 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :  	mAllowMultiSelect(p.allow_multi_select),  	mShowItemLinkOverlays(p.show_item_link_overlays),  	mShowEmptyMessage(p.show_empty_message), -	mShowLoadStatus(p.show_load_status),  	mViewsInitialized(false),  	mInvFVBridgeBuilder(NULL)  {  	mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; -	// contex menu callbacks +	// context menu callbacks  	mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));  	mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));  	mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); @@ -151,69 +151,67 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :  } -void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	 -	std::string start_folder_name(params.start_folder()); -	 -	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(start_folder_name); - -	LLUUID root_id; -	if ("LIBRARY" == params.start_folder()) -	{ -		root_id = gInventory.getLibraryRootFolderID(); -	} -	else -	{ -		root_id = (preferred_type != LLFolderType::FT_NONE) -				? gInventory.findCategoryUUIDForType(preferred_type, false, false)  -				: LLUUID::null; -	} -	 -	if ((root_id == LLUUID::null) && !start_folder_name.empty()) +void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) +{ +	// save off copy of params +	mParams = params; +	// Clear up the root view +	// Note: This needs to be done *before* we build the new folder view  +	LLUUID root_id = getRootFolderID(); +	if (mFolderRoot)  	{ -		llwarns << "No category found that matches start_folder: " << start_folder_name << llendl; -		root_id = LLUUID::generateNewID(); +		removeItemID(root_id); +		mFolderRoot->destroyView(); +		mFolderRoot = NULL;  	} -	 -	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -																	LLAssetType::AT_CATEGORY, -																	LLInventoryType::IT_CATEGORY, -																	this, -																	NULL, -																	root_id); -	 -	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} -void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) -{  	LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); - -	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves -	buildFolderView(params); - +	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves +	{ +		// Determine the root folder in case specified, and +		// build the views starting with that folder. + + +		LLFolderView::Params p(mParams.folder_view); +		p.name = getName(); +		p.title = getLabel(); +		p.rect = LLRect(0, 0, getRect().getWidth(), 0); +		p.parent_panel = this; +		p.tool_tip = p.name; +		p.listener = mInvFVBridgeBuilder->createBridge(	LLAssetType::AT_CATEGORY, +														LLAssetType::AT_CATEGORY, +														LLInventoryType::IT_CATEGORY, +														this, +														&mInventoryViewModel, +														NULL, +														root_id); +		p.view_model = &mInventoryViewModel; +		p.use_label_suffix = mParams.use_label_suffix; +		p.allow_multiselect = mAllowMultiSelect; +		p.show_empty_message = mShowEmptyMessage; +		p.show_item_link_overlays = mShowItemLinkOverlays; +		p.root = NULL; + +		mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p); +		 +		addItemID(root_id, mFolderRoot); +	} 	  	mCommitCallbackRegistrar.popScope(); -	  	mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);  	// Scroller -	{ -		LLRect scroller_view_rect = getRect(); -		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); -		LLScrollContainer::Params scroller_params(params.scroll()); -		scroller_params.rect(scroller_view_rect); -		mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); -		addChild(mScroller); -		mScroller->addChild(mFolderRoot); -		mFolderRoot->setScrollContainer(mScroller); -		mFolderRoot->setFollowsAll(); -		mFolderRoot->addChild(mFolderRoot->mStatusTextBox); -	} +	LLRect scroller_view_rect = getRect(); +	scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +	LLScrollContainer::Params scroller_params(mParams.scroll()); +	scroller_params.rect(scroller_view_rect); +	mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); +	addChild(mScroller); +	mScroller->addChild(mFolderRoot); +	mFolderRoot->setScrollContainer(mScroller); +	mFolderRoot->setFollowsAll(); +	mFolderRoot->addChild(mFolderRoot->mStatusTextBox);  	// Set up the callbacks from the inventory we're viewing, and then build everything.  	mInventoryObserver = new LLInventoryPanelObserver(this); @@ -228,6 +226,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	{  		initializeViews();  	} +	  	gIdleCallbacks.addFunction(onIdle, (void*)this);  	if (mSortOrderSetting != INHERIT_SORT_ORDER) @@ -240,31 +239,30 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	}  	// hide inbox -	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); -	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); +	getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); +	getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX));  	// set the filter for the empty folder if the debug setting is on  	if (gSavedSettings.getBOOL("DebugHideEmptySystemFolders"))  	{ -		getFilter()->setFilterEmptySystemFolders(); +		getFilter().setFilterEmptySystemFolders();  	}  	// keep track of the clipboard state so that we avoid filtering too much  	mClipboardState = LLClipboard::instance().getGeneration();  	// Initialize base class params. -	LLPanel::initFromParams(params); +	LLPanel::initFromParams(mParams);  }  LLInventoryPanel::~LLInventoryPanel()  { -	if (mFolderRoot) +	gIdleCallbacks.deleteFunction(idle, this); + +	U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); +	if (mSortOrderSetting != INHERIT_SORT_ORDER)  	{ -		U32 sort_order = mFolderRoot->getSortOrder(); -		if (mSortOrderSetting != INHERIT_SORT_ORDER) -		{ -			gSavedSettings.setU32(mSortOrderSetting, sort_order); -		} +		gSavedSettings.setU32(mSortOrderSetting, sort_order);  	}  	gIdleCallbacks.deleteFunction(onIdle, this); @@ -281,82 +279,68 @@ LLInventoryPanel::~LLInventoryPanel()  void LLInventoryPanel::draw()  {  	// Select the desired item (in case it wasn't loaded when the selection was requested) -	mFolderRoot->updateSelection(); -	 -	// Nudge the filter if the clipboard state changed -	if (mClipboardState != LLClipboard::instance().getGeneration()) -	{ -		mClipboardState = LLClipboard::instance().getGeneration(); -		getFilter()->setModified(LLClipboard::instance().isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE); -	} +	updateSelection();  	LLPanel::draw();  } -LLInventoryFilter* LLInventoryPanel::getFilter() +const LLInventoryFilter& LLInventoryPanel::getFilter() const  { -	if (mFolderRoot)  -	{ -		return mFolderRoot->getFilter(); -	} -	return NULL; +	return getFolderViewModel()->getFilter();  } -const LLInventoryFilter* LLInventoryPanel::getFilter() const +LLInventoryFilter& LLInventoryPanel::getFilter()  { -	if (mFolderRoot) -	{ -		return mFolderRoot->getFilter(); -	} -	return NULL; +	return getFolderViewModel()->getFilter();  }  void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)  {  	if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT) -		getFilter()->setFilterObjectTypes(types); +		getFilter().setFilterObjectTypes(types);  	if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY) -		getFilter()->setFilterCategoryTypes(types); +		getFilter().setFilterCategoryTypes(types);  }  U32 LLInventoryPanel::getFilterObjectTypes() const   {  -	return mFolderRoot->getFilterObjectTypes();  +	return getFilter().getFilterObjectTypes();  }  U32 LLInventoryPanel::getFilterPermMask() const   {  -	return mFolderRoot->getFilterPermissions();  +	return getFilter().getFilterPermissions();  }  void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)  { -	getFilter()->setFilterPermissions(filter_perm_mask); +	getFilter().setFilterPermissions(filter_perm_mask);  }  void LLInventoryPanel::setFilterWearableTypes(U64 types)  { -	getFilter()->setFilterWearableTypes(types); +	getFilter().setFilterWearableTypes(types);  }  void LLInventoryPanel::setFilterSubString(const std::string& string)  { -	getFilter()->setFilterSubString(string); +	getFilter().setFilterSubString(string);  }  const std::string LLInventoryPanel::getFilterSubString()   {  -	return mFolderRoot->getFilterSubString();  +	return getFilter().getFilterSubString();  }  void LLInventoryPanel::setSortOrder(U32 order)  { -	getFilter()->setSortOrder(order); -	if (getFilter()->isModified()) +    LLInventorySort sorter(order); +	if (order != getFolderViewModel()->getSorter().getSortOrder())  	{ -		mFolderRoot->setSortOrder(order); +		getFolderViewModel()->setSorter(sorter); +		mFolderRoot->arrangeAll();  		// try to keep selection onscreen, even if it wasn't to start with  		mFolderRoot->scrollToShowSelection();  	} @@ -364,37 +348,32 @@ void LLInventoryPanel::setSortOrder(U32 order)  U32 LLInventoryPanel::getSortOrder() const   {  -	return mFolderRoot->getSortOrder();  -} - -void LLInventoryPanel::requestSort() -{ -	mFolderRoot->requestSort(); +	return getFolderViewModel()->getSorter().getSortOrder();  }  void LLInventoryPanel::setSinceLogoff(BOOL sl)  { -	getFilter()->setDateRangeLastLogoff(sl); +	getFilter().setDateRangeLastLogoff(sl);  }  void LLInventoryPanel::setHoursAgo(U32 hours)  { -	getFilter()->setHoursAgo(hours); +	getFilter().setHoursAgo(hours);  }  void LLInventoryPanel::setFilterLinks(U64 filter_links)  { -	getFilter()->setFilterLinks(filter_links); +	getFilter().setFilterLinks(filter_links);  }  void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)  { -	getFilter()->setShowFolderState(show); +	getFilter().setShowFolderState(show);  }  LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()  { -	return getFilter()->getShowFolderState(); +	return getFilter().getShowFolderState();  }  void LLInventoryPanel::modelChanged(U32 mask) @@ -418,11 +397,20 @@ void LLInventoryPanel::modelChanged(U32 mask)  	{  		const LLUUID& item_id = (*items_iter);  		const LLInventoryObject* model_item = model->getObject(item_id); -		LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id); +		LLFolderViewItem* view_item = getItemByID(item_id); +		LLFolderViewModelItemInventory* viewmodel_item =  +			static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);  		// LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item  		// to folder is the fast way to get a folder without searching through folders tree. -		LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); +		LLFolderViewFolder* view_folder = NULL; + +		// Check requires as this item might have already been deleted +		// as a child of its deleted parent. +		if (model_item && view_item) +		{ +			view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); +		}  		//////////////////////////////  		// LABEL Operation @@ -433,7 +421,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  			if (view_item)  			{  				// Request refresh on this item (also flags for filtering) -				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener(); +				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem();  				if(bridge)  				{	// Clear the display name first, so it gets properly re-built during refresh()  					bridge->clearDisplayName(); @@ -449,11 +437,14 @@ void LLInventoryPanel::modelChanged(U32 mask)  		if (mask & LLInventoryObserver::REBUILD)  		{  			handled = true; -			if (model_item && view_item) +			if (model_item && view_item && viewmodel_item)  			{  				view_item->destroyView(); +				removeItemID(viewmodel_item->getUUID());  			}  			view_item = buildNewViews(item_id); +			viewmodel_item =  +				static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);  			view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);  		} @@ -475,7 +466,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  		{  			if (view_folder)  			{ -				view_folder->requestSort(); +				view_folder->getViewModelItem()->requestSort();  			}  		}	 @@ -510,20 +501,24 @@ void LLInventoryPanel::modelChanged(U32 mask)  			else if (model_item && view_item)  			{  				// Don't process the item if it is the root -				if (view_item->getRoot() != view_item) +				if (view_item->getParentFolder())  				{ -					LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID()); +					LLFolderViewFolder* new_parent =   (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());  					// Item has been moved.  					if (view_item->getParentFolder() != new_parent)  					{  						if (new_parent != NULL)  						{  							// Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. -							view_item->getParentFolder()->extractItem(view_item); -							view_item->addToFolder(new_parent, mFolderRoot); +							view_item->addToFolder(new_parent); +							addItemID(viewmodel_item->getUUID(), view_item);  						}  						else   						{ +							// Remove the item ID before destroying the view because the view-model-item gets +							// destroyed when the view is destroyed +                            removeItemID(viewmodel_item->getUUID()); +  							// Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that   							// doesn't include trash).  Just remove the item's UI.  							view_item->destroyView(); @@ -535,9 +530,10 @@ void LLInventoryPanel::modelChanged(U32 mask)  			//////////////////////////////  			// REMOVE Operation  			// This item has been removed from memory, but its associated UI element still exists. -			else if (!model_item && view_item) +			else if (!model_item && view_item && viewmodel_item)  			{  				// Remove the item's UI. +                removeItemID(viewmodel_item->getUUID());  				view_item->destroyView();  			}  		} @@ -549,6 +545,43 @@ LLFolderView* LLInventoryPanel::getRootFolder()  	return mFolderRoot;   } +LLUUID LLInventoryPanel::getRootFolderID() +{ +	if (mFolderRoot && mFolderRoot->getViewModelItem()) +	{ +		return static_cast<LLFolderViewModelItemInventory*>(mFolderRoot->getViewModelItem())->getUUID(); + +	} +	else +	{ +		LLUUID root_id; +		if (mParams.start_folder.id.isChosen()) +		{ +			root_id = mParams.start_folder.id; +		} +		else +		{ +			const LLFolderType::EType preferred_type = mParams.start_folder.type.isChosen()  +				? mParams.start_folder.type +				: LLViewerFolderType::lookupTypeFromNewCategoryName(mParams.start_folder.name); + +			if ("LIBRARY" == mParams.start_folder.name()) +			{ +				root_id = gInventory.getLibraryRootFolderID(); +			} +			else if (preferred_type != LLFolderType::FT_NONE) +			{ +				root_id = gInventory.findCategoryUUIDForType(preferred_type, false); +				if (root_id.isNull()) +				{ +					llwarns << "Could not find folder of type " << preferred_type << llendl; +					root_id.generateNewID(); +				} +			} +		} +		return root_id; +	} +}  // static  void LLInventoryPanel::onIdle(void *userdata) @@ -568,16 +601,72 @@ void LLInventoryPanel::onIdle(void *userdata)  	}  } -const LLUUID& LLInventoryPanel::getRootFolderID() const +struct DirtyFilterFunctor : public LLFolderViewFunctor +{ +	/*virtual*/ void doFolder(LLFolderViewFolder* folder) +	{ +		folder->getViewModelItem()->dirtyFilter(); +	} +	/*virtual*/ void doItem(LLFolderViewItem* item) +	{ +		item->getViewModelItem()->dirtyFilter(); +	} +}; + +void LLInventoryPanel::idle(void* user_data)  { -	return mFolderRoot->getListener()->getUUID(); +	LLInventoryPanel* panel = (LLInventoryPanel*)user_data; +	// Nudge the filter if the clipboard state changed +	if (panel->mClipboardState != LLClipboard::instance().getGeneration()) +	{ +		panel->mClipboardState = LLClipboard::instance().getGeneration(); +		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); +		LLFolderViewFolder* trash_folder = panel->getFolderByID(trash_id); +		if (trash_folder) +		{ +            DirtyFilterFunctor dirtyFilterFunctor; +			trash_folder->applyFunctorToChildren(dirtyFilterFunctor); +		} + +	} + +	panel->mFolderRoot->update(); +	// while dragging, update selection rendering to reflect single/multi drag status +	if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) +	{ +		EAcceptance last_accept = LLToolDragAndDrop::getInstance()->getLastAccept(); +		if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE) +		{ +			panel->mFolderRoot->setShowSingleSelection(TRUE); +		} +		else +		{ +			panel->mFolderRoot->setShowSingleSelection(FALSE); +		} +	} +	else +	{ +		panel->mFolderRoot->setShowSingleSelection(FALSE); +	}  } +  void LLInventoryPanel::initializeViews()  {  	if (!gInventory.isInventoryUsable()) return; -	rebuildViewsFor(getRootFolderID()); +	LLUUID root_id = getRootFolderID(); +	if (root_id.notNull()) +	{ +		buildNewViews(getRootFolderID()); +	} +	else +	{ +		buildNewViews(gInventory.getRootFolderID()); +		buildNewViews(gInventory.getLibraryRootFolderID()); +	} + +	gIdleCallbacks.addFunction(idle, this);  	mViewsInitialized = true; @@ -587,14 +676,14 @@ void LLInventoryPanel::initializeViews()  	if (gAgent.isFirstLogin())  	{  		// Auto open the user's library -		LLFolderViewFolder* lib_folder = mFolderRoot->getFolderByID(gInventory.getLibraryRootFolderID()); +		LLFolderViewFolder* lib_folder =   getFolderByID(gInventory.getLibraryRootFolderID());  		if (lib_folder)  		{  			lib_folder->setOpen(TRUE);  		}  		// Auto close the user's my inventory folder -		LLFolderViewFolder* my_inv_folder = mFolderRoot->getFolderByID(gInventory.getRootFolderID()); +		LLFolderViewFolder* my_inv_folder =   getFolderByID(gInventory.getRootFolderID());  		if (my_inv_folder)  		{  			my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); @@ -602,54 +691,12 @@ void LLInventoryPanel::initializeViews()  	}  } -LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) -{ -	// Destroy the old view for this ID so we can rebuild it. -	LLFolderViewItem* old_view = mFolderRoot->getItemByID(id); -	if (old_view) -	{ -		old_view->destroyView(); -	} - -	return buildNewViews(id); -} - -LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix) -{ -	LLRect folder_rect(0, -					   0, -					   getRect().getWidth(), -					   0); - -	LLFolderView::Params p; -	 -	p.name = getName(); -	p.title = getLabel(); -	p.rect = folder_rect; -	p.parent_panel = this; -	p.tool_tip = p.name; -	p.listener =  bridge; -	p.use_label_suffix = useLabelSuffix; -	p.allow_multiselect = mAllowMultiSelect; -	p.show_empty_message = mShowEmptyMessage; -	p.show_load_status = mShowLoadStatus; - -	return LLUICtrlFactory::create<LLFolderView>(p); -}  LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)  { -	LLFolderViewFolder::Params params; +	LLFolderViewFolder::Params params(mParams.folder);  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -659,17 +706,9 @@ LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * br  LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge)  { -	LLFolderViewItem::Params params; +	LLFolderViewItem::Params params(mParams.item);  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; @@ -682,79 +721,69 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge  LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  {   	LLInventoryObject const* objectp = gInventory.getObject(id); - 	LLUUID root_id = mFolderRoot->getListener()->getUUID(); - 	LLFolderViewFolder* parent_folder = NULL; -	LLFolderViewItem* itemp = NULL; - 	if (id == root_id) - 	{ - 		parent_folder = mFolderRoot; - 	} - 	else if (objectp) - 	{ - 		const LLUUID &parent_id = objectp->getParentUUID(); - 		parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id); -  		 -  		if (parent_folder) +	if (!objectp) return NULL; + +	LLFolderViewItem* folder_view_item = getItemByID(id); + +	const LLUUID &parent_id = objectp->getParentUUID(); +	LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); +	  + 	if (!folder_view_item && parent_folder) +  	{ +  		if (objectp->getType() <= LLAssetType::AT_NONE || +  			objectp->getType() >= LLAssetType::AT_COUNT)    		{ -  			if (objectp->getType() <= LLAssetType::AT_NONE || -  				objectp->getType() >= LLAssetType::AT_COUNT) -  			{ -  				llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " -  						<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() -  						<< llendl; -  				return NULL; -  			} +  			llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " +  					<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() +  					<< llendl; +  			return NULL; +  		} -  			if ((objectp->getType() == LLAssetType::AT_CATEGORY) && -  				(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) +  		if ((objectp->getType() == LLAssetType::AT_CATEGORY) && +  			(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) +  		{ +  			LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), +  																			objectp->getType(), +  																			LLInventoryType::IT_CATEGORY, +  																			this, +																			&mInventoryViewModel, +  																			mFolderRoot, +  																			objectp->getUUID()); +  			if (new_listener)    			{ -  				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), -  																				objectp->getType(), -  																				LLInventoryType::IT_CATEGORY, -  																				this, -  																				mFolderRoot, -  																				objectp->getUUID()); -  				if (new_listener) -  				{ -					LLFolderViewFolder* folderp = createFolderViewFolder(new_listener); -					if (folderp) -					{ -						folderp->setItemSortOrder(mFolderRoot->getSortOrder()); -					} -  					itemp = folderp; -  				} +				folder_view_item = createFolderViewFolder(new_listener);    			} -  			else -  			{ -  				// Build new view for item. -  				LLInventoryItem* item = (LLInventoryItem*)objectp; -  				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), -  																				item->getActualType(), -  																				item->getInventoryType(), -  																				this, -  																				mFolderRoot, -  																				item->getUUID(), -  																				item->getFlags()); +  		} +  		else +  		{ +  			// Build new view for item. +  			LLInventoryItem* item = (LLInventoryItem*)objectp; +  			LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), +  																			item->getActualType(), +  																			item->getInventoryType(), +  																			this, +																			&mInventoryViewModel, +  																			mFolderRoot, +  																			item->getUUID(), +  																			item->getFlags()); -  				if (new_listener) -  				{ -					itemp = createFolderViewItem(new_listener); -  				} +  			if (new_listener) +  			{ +				folder_view_item = createFolderViewItem(new_listener);    			} +  		} -  			if (itemp) -  			{ -  				itemp->addToFolder(parent_folder, mFolderRoot); -   			} -		} +  		if (folder_view_item) +  		{ +  			folder_view_item->addToFolder(parent_folder); +			addItemID(id, folder_view_item); +   		}  	}  	// If this is a folder, add the children of the folder and recursively add any   	// child folders. -	if (id.isNull() -		||	(objectp -			&& objectp->getType() == LLAssetType::AT_CATEGORY)) +	if (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY)  	{  		LLViewerInventoryCategory::cat_array_t* categories;  		LLViewerInventoryItem::item_array_t* items; @@ -771,7 +800,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  			}  		} -		if(items && parent_folder) +		if(items)  		{  			for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();  				 item_iter != items->end(); @@ -784,7 +813,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)  		mInventory->unlockDirectDescendentArrays(id);  	} -	return itemp; +	return folder_view_item;  }  // bit of a hack to make sure the inventory is open. @@ -795,8 +824,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory()  	{  		LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);  		if (fchild -			&& fchild->getListener() -				&& fchild->getListener()->getUUID() == gInventory.getRootFolderID()) +			&& fchild->getViewModelItem() +			&& fchild->getViewModelItem()->getName() == "My Inventory")  		{  			fchild->setOpen(TRUE);  			break; @@ -813,7 +842,7 @@ void LLInventoryPanel::openSelected()  {  	LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem();  	if(!folder_item) return; -	LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); +	LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();  	if(!bridge) return;  	bridge->openItem();  } @@ -917,7 +946,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc  	{  		return;  	} -	mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus); +	setSelectionByID(obj_id, take_keyboard_focus);  }  void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)  @@ -930,7 +959,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::  void LLInventoryPanel::clearSelection()  { -	mFolderRoot->clearSelection(); +	mSelectThisID.setNull();  }  void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) @@ -939,7 +968,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it  	mCompletionObserver->reset();  	for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it)  	{ -		LLUUID id = (*it)->getListener()->getUUID(); +		LLUUID id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID();  		LLViewerInventoryItem* inv_item = mInventory->getItem(id);  		if (inv_item && !inv_item->isFinished()) @@ -959,19 +988,14 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it  	}  } -void LLInventoryPanel::doToSelected(const LLSD& userdata) -{ -	mFolderRoot->doToSelected(&gInventory, userdata); -} -  void LLInventoryPanel::doCreate(const LLSD& userdata)  { -	menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf.get(), userdata); +	menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata);  }  bool LLInventoryPanel::beginIMSession()  { -	std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); +	std::set<LLFolderViewItem*> selected_items =   mFolderRoot->getSelectionList();  	std::string name;  	static int session_num = 1; @@ -979,20 +1003,19 @@ bool LLInventoryPanel::beginIMSession()  	LLDynamicArray<LLUUID> members;  	EInstantMessage type = IM_SESSION_CONFERENCE_START; -	std::set<LLUUID>::const_iterator iter; +	std::set<LLFolderViewItem*>::const_iterator iter;  	for (iter = selected_items.begin(); iter != selected_items.end(); iter++)  	{ -		LLUUID item = *iter; -		LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); +		LLFolderViewItem* folder_item = (*iter);  		if(folder_item)   		{ -			LLFolderViewEventListener* fve_listener = folder_item->getListener(); +			LLFolderViewModelItemInventory* fve_listener = static_cast<LLFolderViewModelItemInventory*>(folder_item->getViewModelItem());  			if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))  			{ -				LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); +				LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem();  				if(!bridge) return true;  				LLViewerInventoryCategory* cat = bridge->getCategory();  				if(!cat) return true; @@ -1026,9 +1049,7 @@ bool LLInventoryPanel::beginIMSession()  			}  			else  			{ -				LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); -				if(!folder_item) return true; -				LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); +				LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getViewModelItem();  				if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)  				{ @@ -1069,13 +1090,13 @@ bool LLInventoryPanel::beginIMSession()  bool LLInventoryPanel::attachObject(const LLSD& userdata)  {  	// Copy selected item UUIDs to a vector. -	std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); +	std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList();  	uuid_vec_t items; -	for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();  +	for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin();  		 set_iter != selected_items.end();   		 ++set_iter)  	{ -		items.push_back(*set_iter); +		items.push_back(static_cast<LLFolderViewModelItemInventory*>((*set_iter)->getViewModelItem())->getUUID());  	}  	// Attach selected items. @@ -1088,7 +1109,7 @@ bool LLInventoryPanel::attachObject(const LLSD& userdata)  BOOL LLInventoryPanel::getSinceLogoff()  { -	return getFilter()->isSinceLogoff(); +	return getFilter().isSinceLogoff();  }  // DEBUG ONLY @@ -1214,12 +1235,93 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L  void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type)  { -	getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type)); +	getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << folder_type));  }  BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const  { -	return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type)); +	return !(getFilter().getFilterCategoryTypes() & (1ULL << folder_type)); +} + +void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem*   itemp ) +{ +	mItemMap[id] = itemp; +} + +void LLInventoryPanel::removeItemID(const LLUUID& id) +{ +	LLInventoryModel::cat_array_t categories; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(id, categories, items, TRUE); + +	mItemMap.erase(id); + +	for (LLInventoryModel::cat_array_t::iterator it = categories.begin(),    end_it = categories.end(); +		it != end_it; +		++it) +	{ +		mItemMap.erase((*it)->getUUID()); +	} + +	for (LLInventoryModel::item_array_t::iterator it = items.begin(),   end_it  = items.end(); +		it != end_it; +		++it) +	{ +		mItemMap.erase((*it)->getUUID()); +	} +} + +LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) +{ +	LLFastTimer _(FTM_GET_ITEM_BY_ID); + +	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; +	map_it = mItemMap.find(id); +	if (map_it != mItemMap.end()) +	{ +		return map_it->second; +	} + +	return NULL; +} + +LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) +{ +	LLFolderViewItem* item = getItemByID(id); +	return dynamic_cast<LLFolderViewFolder*>(item); +} + + +void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL    take_keyboard_focus ) +{ +	LLFolderViewItem* itemp = getItemByID(obj_id); +	if(itemp && itemp->getViewModelItem()) +	{ +		itemp->arrangeAndSet(TRUE, take_keyboard_focus); +		mSelectThisID.setNull(); +		return; +	} +	else +	{ +		// save the desired item to be selected later (if/when ready) +		mSelectThisID = obj_id; +	} +} + +void LLInventoryPanel::updateSelection() +{ +	if (mSelectThisID.notNull()) +	{ +		setSelectionByID(mSelectThisID, false); +	} +} + +void LLInventoryPanel::doToSelected(const LLSD& userdata) +{ +	LLInventoryAction::doToSelected(mInventory, mFolderRoot, userdata.asString()); + +	return;  } @@ -1240,7 +1342,7 @@ public:  	{  		LLInventoryPanel::initFromParams(p);  		// turn on inbox for recent items -		getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); +		getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX));  	}  protected: @@ -1255,3 +1357,34 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)  	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;  } +namespace LLInitParam +{ +	void TypeValues<LLFolderType::EType>::declareValues() +	{ +		declare(LLFolderType::lookup(LLFolderType::FT_TEXTURE)          , LLFolderType::FT_TEXTURE); +		declare(LLFolderType::lookup(LLFolderType::FT_SOUND)            , LLFolderType::FT_SOUND); +		declare(LLFolderType::lookup(LLFolderType::FT_CALLINGCARD)      , LLFolderType::FT_CALLINGCARD); +		declare(LLFolderType::lookup(LLFolderType::FT_LANDMARK)         , LLFolderType::FT_LANDMARK); +		declare(LLFolderType::lookup(LLFolderType::FT_CLOTHING)         , LLFolderType::FT_CLOTHING); +		declare(LLFolderType::lookup(LLFolderType::FT_OBJECT)           , LLFolderType::FT_OBJECT); +		declare(LLFolderType::lookup(LLFolderType::FT_NOTECARD)         , LLFolderType::FT_NOTECARD); +		declare(LLFolderType::lookup(LLFolderType::FT_ROOT_INVENTORY)   , LLFolderType::FT_ROOT_INVENTORY); +		declare(LLFolderType::lookup(LLFolderType::FT_LSL_TEXT)         , LLFolderType::FT_LSL_TEXT); +		declare(LLFolderType::lookup(LLFolderType::FT_BODYPART)         , LLFolderType::FT_BODYPART); +		declare(LLFolderType::lookup(LLFolderType::FT_TRASH)            , LLFolderType::FT_TRASH); +		declare(LLFolderType::lookup(LLFolderType::FT_SNAPSHOT_CATEGORY), LLFolderType::FT_SNAPSHOT_CATEGORY); +		declare(LLFolderType::lookup(LLFolderType::FT_LOST_AND_FOUND)   , LLFolderType::FT_LOST_AND_FOUND); +		declare(LLFolderType::lookup(LLFolderType::FT_ANIMATION)        , LLFolderType::FT_ANIMATION); +		declare(LLFolderType::lookup(LLFolderType::FT_GESTURE)          , LLFolderType::FT_GESTURE); +		declare(LLFolderType::lookup(LLFolderType::FT_FAVORITE)         , LLFolderType::FT_FAVORITE); +		declare(LLFolderType::lookup(LLFolderType::FT_ENSEMBLE_START)   , LLFolderType::FT_ENSEMBLE_START); +		declare(LLFolderType::lookup(LLFolderType::FT_ENSEMBLE_END)     , LLFolderType::FT_ENSEMBLE_END); +		declare(LLFolderType::lookup(LLFolderType::FT_CURRENT_OUTFIT)   , LLFolderType::FT_CURRENT_OUTFIT); +		declare(LLFolderType::lookup(LLFolderType::FT_OUTFIT)           , LLFolderType::FT_OUTFIT); +		declare(LLFolderType::lookup(LLFolderType::FT_MY_OUTFITS)       , LLFolderType::FT_MY_OUTFITS); +		declare(LLFolderType::lookup(LLFolderType::FT_MESH )            , LLFolderType::FT_MESH ); +		declare(LLFolderType::lookup(LLFolderType::FT_INBOX)            , LLFolderType::FT_INBOX); +		declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX)           , LLFolderType::FT_OUTBOX); +		declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT)       , LLFolderType::FT_BASIC_ROOT); +	} +} diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 6db59afb9b..e9bfcb0ccf 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -30,6 +30,8 @@  #include "llassetstorage.h"  #include "lldarray.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodelinventory.h"  #include "llfloater.h"  #include "llinventory.h"  #include "llinventoryfilter.h" @@ -38,22 +40,19 @@  #include "lluictrlfactory.h"  #include <set> -class LLFolderView; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel;  class LLInvFVBridge; -class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; +class LLInventoryFolderViewModelBuilder;  class LLInvPanelComplObserver; +class LLFolderViewModelInventory; + +namespace LLInitParam +{ +	template<> +	struct TypeValues<LLFolderType::EType> : public TypeValuesHelper<LLFolderType::EType> +	{ +		static void declareValues(); +	}; +}  class LLInventoryPanel : public LLPanel  { @@ -74,6 +73,19 @@ public:  		{}  	}; +	struct StartFolder : public LLInitParam::ChoiceBlock<StartFolder> +	{ +		Alternative<std::string>			name; +		Alternative<LLUUID>					id; +		Alternative<LLFolderType::EType>	type; + +		StartFolder() +		:	name("name"),  +			id("id"), +			type("type") +		{} +	}; +  	struct Params   	:	public LLInitParam::Block<Params, LLPanel::Params>  	{ @@ -82,12 +94,14 @@ public:  		Optional<bool>						allow_multi_select;  		Optional<bool>						show_item_link_overlays;  		Optional<Filter>					filter; -		Optional<std::string>               start_folder; +		Optional<StartFolder>               start_folder;  		Optional<bool>						use_label_suffix;  		Optional<bool>						show_empty_message; -		Optional<bool>						show_load_status;  		Optional<LLScrollContainer::Params>	scroll;  		Optional<bool>						accepts_drag_and_drop; +		Optional<LLFolderView::Params>		folder_view; +		Optional<LLFolderViewFolder::Params> folder; +		Optional<LLFolderViewItem::Params>	 item;  		Params()  		:	sort_order_setting("sort_order_setting"), @@ -98,24 +112,34 @@ public:  			start_folder("start_folder"),  			use_label_suffix("use_label_suffix", true),  			show_empty_message("show_empty_message", true), -			show_load_status("show_load_status"),  			scroll("scroll"), -			accepts_drag_and_drop("accepts_drag_and_drop") +			accepts_drag_and_drop("accepts_drag_and_drop"), +			folder_view("folder_view"), +			folder("folder"), +			item("item")  		{}  	}; +	struct InventoryState : public LLInitParam::Block<InventoryState> +	{ +		Mandatory<LLInventoryFilter::Params> filter; +		Mandatory<LLInventorySort::Params> sort; +	}; +  	//--------------------------------------------------------------------  	// Initialization  	//--------------------------------------------------------------------  protected:  	LLInventoryPanel(const Params&);  	void initFromParams(const Params&); +  	friend class LLUICtrlFactory;  public:  	virtual ~LLInventoryPanel();  public:  	LLInventoryModel* getModel() { return mInventory; } +	LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; }  	// LLView methods  	void draw(); @@ -137,8 +161,8 @@ public:  	void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);  	void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);  	void clearSelection(); -	LLInventoryFilter* getFilter(); -	const LLInventoryFilter* getFilter() const; +	LLInventoryFilter& getFilter(); +	const LLInventoryFilter& getFilter() const;  	void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);  	U32 getFilterObjectTypes() const;  	void setFilterPermMask(PermissionMask filter_perm_mask); @@ -156,6 +180,7 @@ public:  	// This method is called when something has changed about the inventory.  	void modelChanged(U32 mask);  	LLFolderView* getRootFolder(); +	LLUUID getRootFolderID();  	LLScrollContainer* getScrollableContainer() { return mScroller; }  	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); @@ -167,7 +192,8 @@ public:  	void doCreate(const LLSD& userdata);  	bool beginIMSession();  	bool attachObject(const LLSD& userdata); -	 +	static void idle(void* user_data); +  	// DEBUG ONLY:  	static void dumpSelectionInformation(void* user_data); @@ -182,30 +208,44 @@ public:  	static void openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id); +	void addItemID(const LLUUID& id, LLFolderViewItem* itemp); +	void removeItemID(const LLUUID& id); +	LLFolderViewItem* getItemByID(const LLUUID& id); +	LLFolderViewFolder* getFolderByID(const LLUUID& id); +	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); +	void updateSelection(); + +	LLFolderViewModelInventory* getFolderViewModel(); +	const LLFolderViewModelInventory* getFolderViewModel() const; +  protected:  	void openStartFolderOrMyInventory(); // open the first level of inventory  	void onItemsCompletion();			// called when selected items are complete +    LLUUID						mSelectThisID;	  	LLInventoryModel*			mInventory;  	LLInventoryObserver*		mInventoryObserver;  	LLInvPanelComplObserver*	mCompletionObserver; -	BOOL						mAcceptsDragAndDrop; -	BOOL 						mAllowMultiSelect; -	BOOL 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons -	BOOL						mShowEmptyMessage; -	BOOL						mShowLoadStatus; +	bool						mAcceptsDragAndDrop; +	bool 						mAllowMultiSelect; +	bool 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons +	bool						mShowEmptyMessage;  	LLFolderView*				mFolderRoot;  	LLScrollContainer*			mScroller; +	LLFolderViewModelInventory	mInventoryViewModel; +	Params						mParams;	// stored copy of parameter block + +	std::map<LLUUID, LLFolderViewItem*> mItemMap;  	/** -	 * Pointer to LLInventoryFVBridgeBuilder. +	 * Pointer to LLInventoryFolderViewModelBuilder.  	 *  	 * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with   	 * another implementation.  	 * Take into account it will not be deleted by LLInventoryPanel itself.  	 */ -	const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder; +	const LLInventoryFolderViewModelBuilder* mInvFVBridgeBuilder;  	//-------------------------------------------------------------------- @@ -218,7 +258,6 @@ public:  	void setSortOrder(U32 order);  	U32 getSortOrder() const; -	void requestSort();  private:  	std::string					mSortOrderSetting; @@ -231,26 +270,19 @@ public:  	void addHideFolderType(LLFolderType::EType folder_type);  public: -	BOOL 				getIsViewsInitialized() const { return mViewsInitialized; } -	const LLUUID&		getRootFolderID() const; +	BOOL getIsViewsInitialized() const { return mViewsInitialized; }  protected:  	// Builds the UI.  Call this once the inventory is usable.  	void 				initializeViews(); -	LLFolderViewItem*	rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views. -	virtual void		buildFolderView(const LLInventoryPanel::Params& params);  	LLFolderViewItem*	buildNewViews(const LLUUID& id);  	BOOL				getIsHiddenFolderType(LLFolderType::EType folder_type) const; -	virtual LLFolderView*		createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix);  	virtual LLFolderViewFolder*	createFolderViewFolder(LLInvFVBridge * bridge);  	virtual LLFolderViewItem*	createFolderViewItem(LLInvFVBridge * bridge);  private: -	BOOL				mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() -	BOOL				mViewsInitialized; // Views have been generated -	// UUID of category from which hierarchy should be built.  Set with the  -	// "start_folder" xml property.  Default is LLUUID::null that means total Inventory hierarchy.  -	LLUUID				mStartFolderID; +	bool				mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() +	bool				mViewsInitialized; // Views have been generated  };  #endif // LL_LLINVENTORYPANEL_H diff --git a/indra/newview/lllistcontextmenu.h b/indra/newview/lllistcontextmenu.h index fabd68ee20..04d3314829 100644 --- a/indra/newview/lllistcontextmenu.h +++ b/indra/newview/lllistcontextmenu.h @@ -37,7 +37,7 @@ class LLContextMenu;  /**   * Context menu for single or multiple list items.   *  - * Derived classes must implement contextMenu(). + * Derived classes must implement createMenu().   *    * Typical usage:   * <code> diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a7303ad035..8f0e6b4c83 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -1,8 +1,8 @@  /**    * @file LLNearbyChat.cpp - * @brief Nearby chat history scrolling panel implementation + * @brief LLNearbyChat class implementation   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -26,68 +26,67 @@  #include "llviewerprecompiledheaders.h" -#include "llnearbychat.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llrootview.h" -//#include "llchatitemscontainerctrl.h" +#include "message.h" +  #include "lliconctrl.h" +#include "llappviewer.h" +#include "llchatentry.h" +#include "llfloaterreg.h" +#include "lltrans.h" +#include "llimfloatercontainer.h"  #include "llfloatersidepanelcontainer.h"  #include "llfocusmgr.h"  #include "lllogchat.h"  #include "llresizebar.h"  #include "llresizehandle.h" +#include "lldraghandle.h"  #include "llmenugl.h" -#include "llviewermenu.h"//for gMenuHolder - +#include "llviewermenu.h" // for gMenuHolder  #include "llnearbychathandler.h"  #include "llchannelmanager.h" - -#include "llagent.h" 			// gAgent  #include "llchathistory.h"  #include "llstylemap.h" -  #include "llavatarnamecache.h" - -#include "lldraghandle.h" - -#include "llnearbychatbar.h"  #include "llfloaterreg.h"  #include "lltrans.h" -static const S32 RESIZE_BAR_THICKNESS = 3; - - -static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat"); +#include "llfirstuse.h" +#include "llnearbychat.h" +#include "llagent.h" // gAgent +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" +#include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" +#include "llviewerchat.h" +#include "lltranslate.h" -LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p)  -:	LLPanel(p), -	mChatHistory(NULL) -{ -} +S32 LLNearbyChat::sLastSpecialChatChannel = 0; -BOOL LLNearbyChat::postBuild() +// --- 2 functions in the global namespace :( --- +bool isWordsName(const std::string& name)  { -	//menu -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - -	enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); -	registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - -	 -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(menu) -		mPopupMenuHandle = menu->getHandle(); - -	gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); - -	mChatHistory = getChild<LLChatHistory>("chat_history"); +	// checking to see if it's display name plus username in parentheses +	S32 open_paren = name.find(" (", 0); +	S32 close_paren = name.find(')', 0); -	if(!LLPanel::postBuild()) -		return false; -	 -	return true; +	if (open_paren != std::string::npos && +		close_paren == name.length()-1) +	{ +		return true; +	} +	else +	{ +		//checking for a single space +		S32 pos = name.find(' ', 0); +		return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; +	}  }  std::string appendTime() @@ -106,52 +105,97 @@ std::string appendTime()  } -void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +const S32 EXPANDED_HEIGHT = 266; +const S32 COLLAPSED_HEIGHT = 60; +const S32 EXPANDED_MIN_HEIGHT = 150; + +// legacy callback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); + +struct LLChatTypeTrigger { +	std::string name; +	EChatType type; +}; + +static LLChatTypeTrigger sChatTypeTriggers[] = { +	{ "/whisper"	, CHAT_TYPE_WHISPER}, +	{ "/shout"	, CHAT_TYPE_SHOUT} +}; + + +LLNearbyChat::LLNearbyChat(const LLSD& key) +:	LLIMConversation(key), +	//mOutputMonitor(NULL), +	mSpeakerMgr(NULL), +	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)  { -	LLChat& tmp_chat = const_cast<LLChat&>(chat); +	mIsNearbyChat = true; +	setIsChrome(TRUE); +	mKey = LLSD(); +	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); +} -	if(tmp_chat.mTimeStr.empty()) -		tmp_chat.mTimeStr = appendTime(); +//virtual +BOOL LLNearbyChat::postBuild() +{ +    BOOL result = LLIMConversation::postBuild(); +	mInputEditor->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); +	mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); +	mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); +	mInputEditor->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); -	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); -	 -	if (!chat.mMuted) -	{ -		tmp_chat.mFromName = chat.mFromName; -		LLSD chat_args = args; -		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; -		mChatHistory->appendMessage(chat, chat_args); -	} +//	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); +//	mOutputMonitor->setVisible(FALSE); -	if(archive) +	// Register for font change notifications +	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); + +	// title must be defined BEFORE call addConversationListItem() because +	// it is used for show the item's name in the conversations list +	setTitle(getString("NearbyChatTitle")); + +	addToHost(); + +	//for menu +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + +	enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); +	registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); + +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if(menu)  	{ -		mMessageArchive.push_back(chat); -		if(mMessageArchive.size()>200) -			mMessageArchive.erase(mMessageArchive.begin()); +		mPopupMenuHandle = menu->getHandle();  	} -	if (args["do_not_log"].asBoolean())  +	// obsolete, but may be needed for backward compatibility? +	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); + +	if (gSavedPerAccountSettings.getBOOL("LogShowHistory"))  	{ -		return; +		loadHistory();  	} -	if (gSavedPerAccountSettings.getBOOL("LogNearbyChat")) -	{ -		std::string from_name = chat.mFromName; +	// added row in the conversations list when nearby chat is tear-off +	LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); +	im_box->addConversationListItem(getTitle(), LLSD(), this); -		if (chat.mSourceType == CHAT_SOURCE_AGENT) -		{ -			// if the chat is coming from an agent, log the complete name -			LLAvatarName av_name; -			LLAvatarNameCache::get(chat.mFromID, &av_name); +	return result; +} -			if (!av_name.mIsDisplayNameDefault) -			{ -				from_name = av_name.getCompleteName(); -			} -		} +// virtual +void LLNearbyChat::refresh() +{ +	displaySpeakingIndicator(); +	updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); -		LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); +	// *HACK: Update transparency type depending on whether our children have focus. +	// This is needed because this floater is chrome and thus cannot accept focus, so +	// the transparency type setting code from LLFloater::setFocus() isn't reached. +	if (getTransparencyType() != TT_DEFAULT) +	{ +		setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);  	}  } @@ -162,44 +206,47 @@ void LLNearbyChat::onNearbySpeakers()  	LLFloaterSidePanelContainer::showPanel("people", "panel_people", param);  } -  void	LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)  {  } +  bool	LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)  {  	std::string str = userdata.asString();  	if(str == "nearby_people") -		onNearbySpeakers();	 +		onNearbySpeakers();  	return false;  } -void LLNearbyChat::removeScreenChat() +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusReceived()  { -	LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); -	if(chat_channel) -	{ -		chat_channel->removeToastsFromChannel(); -	} +	setBackgroundOpaque(true); +	LLIMConversation::onFocusReceived();  } -void	LLNearbyChat::setVisible(BOOL visible) +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusLost()  { -	if(visible) -	{ -		removeScreenChat(); -	} - -	LLPanel::setVisible(visible); +	setBackgroundOpaque(false); +	LLIMConversation::onFocusLost();  } - -void LLNearbyChat::getAllowedRect(LLRect& rect) +BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)  { -	rect = gViewerWindow->getWorldViewRectScaled(); +	//fix for EXT-6625 +	//highlight NearbyChat history whenever mouseclick happen in NearbyChat +	//setting focus to eidtor will force onFocusLost() call that in its turn will change +	//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + +	if(mChatHistory) +		mChatHistory->setFocus(TRUE); +	return LLPanel::handleMouseDown(x, y, mask);  } -void LLNearbyChat::updateChatHistoryStyle() +void LLNearbyChat::reloadMessages()  {  	mChatHistory->clear(); @@ -212,34 +259,6 @@ void LLNearbyChat::updateChatHistoryStyle()  	}  } -//static  -void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue) -{ -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); -	if(nearby_chat) -		nearby_chat->updateChatHistoryStyle(); -} - -bool isWordsName(const std::string& name) -{ -	// checking to see if it's display name plus username in parentheses  -	S32 open_paren = name.find(" (", 0); -	S32 close_paren = name.find(')', 0); - -	if (open_paren != std::string::npos && -		close_paren == name.length()-1) -	{ -		return true; -	} -	else -	{ -		//checking for a single space -		S32 pos = name.find(' ', 0); -		return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; -	} -} -  void LLNearbyChat::loadHistory()  {  	LLSD do_not_log; @@ -274,9 +293,9 @@ void LLNearbyChat::loadHistory()  		chat.mSourceType = CHAT_SOURCE_AGENT;  		if (from_id.isNull() && SYSTEM_FROM == from) -		{	 +		{  			chat.mSourceType = CHAT_SOURCE_SYSTEM; -			 +  		}  		else if (from_id.isNull())  		{ @@ -289,50 +308,620 @@ void LLNearbyChat::loadHistory()  	}  } +void LLNearbyChat::removeScreenChat() +{ +	LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); +	if(chat_channel) +	{ +		chat_channel->removeToastsFromChannel(); +	} +} + +void	LLNearbyChat::setVisible(BOOL visible) +{ +	if(visible) +	{ +		removeScreenChat(); +	} + +	LLIMConversation::setVisible(visible); +} + + +void LLNearbyChat::enableDisableCallBtn() +{ +	// bool btn_enabled = LLAgent::isActionAllowed("speak"); + +	getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/); +} + +void LLNearbyChat::onTearOffClicked() +{ +	LLIMConversation::onTearOffClicked(); + +	// see CHUI-170: Save torn-off state of the nearby chat between sessions +	BOOL in_the_multifloater = !isTornOff(); +	gSavedSettings.setBOOL("NearbyChatIsNotTornOff", in_the_multifloater); +} + +void LLNearbyChat::addToHost() +{ +	if ( LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); +		if (im_box) +		{ +			if (gSavedSettings.getBOOL("NearbyChatIsNotTornOff")) +			{ +				im_box->addFloater(this, TRUE, LLTabContainer::END); +			} +			else +			{ +				// setting of the "potential" host: this sequence sets +				// LLFloater::mHostHandle = NULL (a current host), but +				// LLFloater::mLastHostHandle = im_box (a "future" host) +				setHost(im_box); +				setHost(NULL); +			} +		} +	} +} + +// virtual +void LLNearbyChat::onOpen(const LLSD& key) +{ +	LLIMConversation::onOpen(key); +	showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + +void LLNearbyChat::onChatFontChange(LLFontGL* fontp) +{ +	// Update things with the new font whohoo +	if (mInputEditor) +	{ +		mInputEditor->setFont(fontp); +	} +} +  //static  LLNearbyChat* LLNearbyChat::getInstance()  { -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -	return chat_bar->findChild<LLNearbyChat>("nearby_chat"); +	return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar");  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() +void LLNearbyChat::show()  { -	setBackgroundOpaque(true); -	LLPanel::onFocusReceived(); +	if (isChatMultiTab()) +	{ +		openFloater(getKey()); +	}  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() +bool LLNearbyChat::isChatVisible() const  { -	setBackgroundOpaque(false); -	LLPanel::onFocusLost(); +	bool isVisible = false; +	LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); +	// Is the IM floater container ever null? +	llassert(im_box != NULL); +	if (im_box != NULL) +	{ +		isVisible = +				isChatMultiTab() && gSavedSettings.getBOOL("NearbyChatIsNotTornOff")? +						im_box->getVisible() && !im_box->isMinimized() : +						getVisible() && !isMinimized(); +	} + +	return isVisible;  } -BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) +void LLNearbyChat::showHistory()  { -	//fix for EXT-6625 -	//highlight NearbyChat history whenever mouseclick happen in NearbyChat -	//setting focus to eidtor will force onFocusLost() call that in its turn will change  -	//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. +	openFloater(); +	setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +} + +std::string LLNearbyChat::getCurrentChat() +{ +	return mInputEditor ? mInputEditor->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask ) +{ +	BOOL handled = FALSE; + +	if( KEY_RETURN == key && mask == MASK_CONTROL) +	{ +		// shout +		sendChat(CHAT_TYPE_SHOUT); +		handled = TRUE; +	} + +	return handled; +} + +BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ +	U32 in_len = in_str.length(); +	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	if(mChatHistory) -		mChatHistory->setFocus(TRUE); -	return LLPanel::handleMouseDown(x, y, mask); +	bool string_was_found = false; + +	for (S32 n = 0; n < cnt && !string_was_found; n++) +	{ +		if (in_len <= sChatTypeTriggers[n].name.length()) +		{ +			std::string trigger_trunc = sChatTypeTriggers[n].name; +			LLStringUtil::truncate(trigger_trunc, in_len); + +			if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) +			{ +				*out_str = sChatTypeTriggers[n].name; +				string_was_found = true; +			} +		} +	} + +	return string_was_found;  } -void LLNearbyChat::draw() +void LLNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata)  { -	// *HACK: Update transparency type depending on whether our children have focus. -	// This is needed because this floater is chrome and thus cannot accept focus, so -	// the transparency type setting code from LLFloater::setFocus() isn't reached. -	if (getTransparencyType() != TT_DEFAULT) +	LLFirstUse::otherAvatarChatFirst(false); + +	LLNearbyChat* self = (LLNearbyChat *)userdata; + +	LLWString raw_text = self->mInputEditor->getWText(); + +	// Can't trim the end, because that will cause autocompletion +	// to eat trailing spaces that might be part of a gesture. +	LLWStringUtil::trimHead(raw_text); + +	S32 length = raw_text.length(); + +	if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences  	{ -		setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE); +		gAgent.startTyping(); +	} +	else +	{ +		gAgent.stopTyping(); +	} + +	/* Doesn't work -- can't tell the difference between a backspace +	   that killed the selection vs. backspace at the end of line. +	if (length > 1  +		&& text[0] == '/' +		&& key == KEY_BACKSPACE) +	{ +		// the selection will already be deleted, but we need to trim +		// off the character before +		std::string new_text = raw_text.substr(0, length-1); +		self->mInputEditor->setText( new_text ); +		self->mInputEditor->setCursorToEnd(); +		length = length - 1; +	} +	*/ + +	KEY key = gKeyboard->currentKey(); + +	// Ignore "special" keys, like backspace, arrows, etc. +	if (length > 1  +		&& raw_text[0] == '/' +		&& key < KEY_SPECIAL) +	{ +		// we're starting a gesture, attempt to autocomplete + +		std::string utf8_trigger = wstring_to_utf8str(raw_text); +		std::string utf8_out_str(utf8_trigger); + +		if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) +		{ +			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); +			self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + +			// Select to end of line, starting from the character +			// after the last one the user typed. +			self->mInputEditor->selectNext(rest_of_match, false); +		} +		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) +		{ +			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); +			self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part +			self->mInputEditor->endOfDoc(); +		} + +		//llinfos << "GESTUREDEBUG " << trigger  +		//	<< " len " << length +		//	<< " outlen " << out_str.getLength() +		//	<< llendl; +	} +} + +// static +void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ +	// stop typing animation +	gAgent.stopTyping(); +} + +void LLNearbyChat::onChatBoxFocusReceived() +{ +	mInputEditor->setEnabled(!gDisconnected); +} + +EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) +{ +	U32 length = str.length(); +	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); +	 +	for (S32 n = 0; n < cnt; n++) +	{ +		if (length >= sChatTypeTriggers[n].name.length()) +		{ +			std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + +			if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) +			{ +				U32 trigger_length = sChatTypeTriggers[n].name.length(); + +				// It's to remove space after trigger name +				if (length > trigger_length && str[trigger_length] == ' ') +					trigger_length++; + +				str = str.substr(trigger_length, length); + +				if (CHAT_TYPE_NORMAL == type) +					return sChatTypeTriggers[n].type; +				else +					break; +			} +		} +	} + +	return type; +} + +void LLNearbyChat::sendChat( EChatType type ) +{ +	if (mInputEditor) +	{ +		LLWString text = mInputEditor->getWText(); +		LLWStringUtil::trim(text); +		LLWStringUtil::replaceChar(text,182,'\n'); // Convert paragraph symbols back into newlines. +		if (!text.empty()) +		{ +			// Check if this is destined for another channel +			S32 channel = 0; +			stripChannelNumber(text, &channel); +			 +			std::string utf8text = wstring_to_utf8str(text); +			// Try to trigger a gesture, if not chat to a script. +			std::string utf8_revised_text; +			if (0 == channel) +			{ +				// discard returned "found" boolean +				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); +			} +			else +			{ +				utf8_revised_text = utf8text; +			} + +			utf8_revised_text = utf8str_trim(utf8_revised_text); + +			type = processChatTypeTriggers(type, utf8_revised_text); + +			if (!utf8_revised_text.empty()) +			{ +				// Chat with animation +				sendChatFromViewer(utf8_revised_text, type, TRUE); +			} +		} + +		mInputEditor->setText(LLStringExplicit("")); +	} + +	gAgent.stopTyping(); + +	// If the user wants to stop chatting on hitting return, lose focus +	// and go out of chat mode. +	if (gSavedSettings.getBOOL("CloseChatOnReturn")) +	{ +		stopChat(); +	} +} + + +void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) +{ +	LLChat& tmp_chat = const_cast<LLChat&>(chat); + +	if(tmp_chat.mTimeStr.empty()) +		tmp_chat.mTimeStr = appendTime(); + +	if (!chat.mMuted) +	{ +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = true; + +		mChatHistory->appendMessage(chat, chat_args); +	} +} + +void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ +	appendMessage(chat, args); + +	if(archive) +	{ +		mMessageArchive.push_back(chat); +		if(mMessageArchive.size()>200) +			mMessageArchive.erase(mMessageArchive.begin());  	} -	LLPanel::draw(); +	// logging +	if (!args["do_not_log"].asBoolean() +			&& gSavedPerAccountSettings.getBOOL("LogNearbyChat")) +	{ +		std::string from_name = chat.mFromName; + +		if (chat.mSourceType == CHAT_SOURCE_AGENT) +		{ +			// if the chat is coming from an agent, log the complete name +			LLAvatarName av_name; +			LLAvatarNameCache::get(chat.mFromID, &av_name); + +			if (!av_name.mIsDisplayNameDefault) +			{ +				from_name = av_name.getCompleteName(); +			} +		} + +		LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); +	} +} + + +void LLNearbyChat::onChatBoxCommit() +{ +	if (mInputEditor->getText().length() > 0) +	{ +		sendChat(CHAT_TYPE_NORMAL); +	} + +	gAgent.stopTyping(); +} + +void LLNearbyChat::displaySpeakingIndicator() +{ +	LLSpeakerMgr::speaker_list_t speaker_list; +	LLUUID id; + +	id.setNull(); +	mSpeakerMgr->update(TRUE); +	mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); + +	for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) +	{ +		LLPointer<LLSpeaker> s = *i; +		if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) +		{ +			id = s->mID; +			break; +		} +	} + +	if (!id.isNull()) +	{ +		//mOutputMonitor->setVisible(TRUE); +		//mOutputMonitor->setSpeakerId(id); +	} +	else +	{ +		//mOutputMonitor->setVisible(FALSE); +	}  } + +void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ +	sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) +{ +	// Look for "/20 foo" channel chats. +	S32 channel = 0; +	LLWString out_text = stripChannelNumber(wtext, &channel); +	std::string utf8_out_text = wstring_to_utf8str(out_text); +	std::string utf8_text = wstring_to_utf8str(wtext); + +	utf8_text = utf8str_trim(utf8_text); +	if (!utf8_text.empty()) +	{ +		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); +	} + +	// Don't animate for chats people can't hear (chat to scripts) +	if (animate && (channel == 0)) +	{ +		if (type == CHAT_TYPE_WHISPER) +		{ +			lldebugs << "You whisper " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); +		} +		else if (type == CHAT_TYPE_NORMAL) +		{ +			lldebugs << "You say " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); +		} +		else if (type == CHAT_TYPE_SHOUT) +		{ +			lldebugs << "You shout " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); +		} +		else +		{ +			llinfos << "send_chat_from_viewer() - invalid volume" << llendl; +			return; +		} +	} +	else +	{ +		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) +		{ +			lldebugs << "Channel chat: " << utf8_text << llendl; +		} +	} + +	send_chat_from_viewer(utf8_out_text, type, channel); +} + +// static  +void LLNearbyChat::startChat(const char* line) +{ +	LLNearbyChat* cb = LLNearbyChat::getInstance(); + +	if (cb ) +	{ +		cb->show(); +		cb->setVisible(TRUE); +		cb->setFocus(TRUE); +		cb->mInputEditor->setFocus(TRUE); + +		if (line) +		{ +			std::string line_string(line); +			cb->mInputEditor->setText(line_string); +		} + +		cb->mInputEditor->endOfDoc(); +	} +} + +// Exit "chat mode" and do the appropriate focus changes +// static +void LLNearbyChat::stopChat() +{ +	LLNearbyChat* cb = LLNearbyChat::getInstance(); + +	if (cb) +	{ +		cb->mInputEditor->setFocus(FALSE); + +		// stop typing animation +		gAgent.stopTyping(); +	} +} + +// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. +// Otherwise returns input and channel 0. +LLWString LLNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel) +{ +	if (mesg[0] == '/' +		&& mesg[1] == '/') +	{ +		// This is a "repeat channel send" +		*channel = sLastSpecialChatChannel; +		return mesg.substr(2, mesg.length() - 2); +	} +	else if (mesg[0] == '/' +			 && mesg[1] +			 && LLStringOps::isDigit(mesg[1])) +	{ +		// This a special "/20" speak on a channel +		S32 pos = 0; + +		// Copy the channel number into a string +		LLWString channel_string; +		llwchar c; +		do +		{ +			c = mesg[pos+1]; +			channel_string.push_back(c); +			pos++; +		} +		while(c && pos < 64 && LLStringOps::isDigit(c)); +		 +		// Move the pointer forward to the first non-whitespace char +		// Check isspace before looping, so we can handle "/33foo" +		// as well as "/33 foo" +		while(c && iswspace(c)) +		{ +			c = mesg[pos+1]; +			pos++; +		} +		 +		sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); +		*channel = sLastSpecialChatChannel; +		return mesg.substr(pos, mesg.length() - pos); +	} +	else +	{ +		// This is normal chat. +		*channel = 0; +		return mesg; +	} +} + +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) +{ +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_ChatFromViewer); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +	msg->nextBlockFast(_PREHASH_ChatData); +	msg->addStringFast(_PREHASH_Message, utf8_out_text); +	msg->addU8Fast(_PREHASH_Type, type); +	msg->addS32("Channel", channel); + +	gAgent.sendReliableMessage(); + +	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); +} + +class LLChatCommandHandler : public LLCommandHandler +{ +public: +	// not allowed from outside the app +	LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + +    // Your code here +	bool handle(const LLSD& tokens, const LLSD& query_map, +				LLMediaCtrl* web) +	{ +		bool retval = false; +		// Need at least 2 tokens to have a valid message. +		if (tokens.size() < 2) +		{ +			retval = false; +		} +		else +		{ +		S32 channel = tokens[0].asInteger(); +			// VWR-19499 Restrict function to chat channels greater than 0. +			if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) +			{ +				retval = true; +		// Send unescaped message, see EXT-6353. +		std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); +		send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); +			} +			else +			{ +				retval = false; +				// Tell us this is an unsupported SLurl. +			} +		} +		return retval; +	} +}; + +// Creating the object registers with the dispatcher. +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7c5975cbc5..7c58e3037e 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -1,8 +1,8 @@ - /**  +/**    * @file llnearbychat.h - * @brief nearby chat history scrolling panel implementation + * @brief LLNearbyChat class definition   * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -24,60 +24,108 @@   * $/LicenseInfo$   */ -#ifndef LL_LLNEARBYCHAT_H_ -#define LL_LLNEARBYCHAT_H_ +#ifndef LL_LLNEARBYCHAT_H +#define LL_LLNEARBYCHAT_H +#include "llimconversation.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" +#include "llspeakers.h"  #include "llscrollbar.h"  #include "llviewerchat.h" -#include "llfloater.h" +#include "llpanel.h"  class LLResizeBar; -class LLChatHistory; -class LLNearbyChat: public LLPanel +class LLNearbyChat +	:	public LLIMConversation  {  public: -	LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); +	// constructor for inline chat-bars (e.g. hosted in chat history window) +	LLNearbyChat(const LLSD& key); +	~LLNearbyChat() {} -	BOOL	postBuild			(); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +	// focus overrides +	/*virtual*/ void	onFocusLost(); +	/*virtual*/ void	onFocusReceived(); + +	/*virtual*/ void	setVisible(BOOL visible); + +	void loadHistory(); +    void reloadMessages(); +	void removeScreenChat(); + +	static LLNearbyChat* getInstance(); + +	void addToHost(); +	void show(); +	bool isChatVisible() const;  	/** @param archive true - to save a message to the chat history log */ -	void	addMessage			(const LLChat& message,bool archive = true, const LLSD &args = LLSD());	 +	void	addMessage			(const LLChat& message,bool archive = true, const LLSD &args = LLSD());  	void	onNearbyChatContextMenuItemClicked(const LLSD& userdata);  	bool	onNearbyChatCheckContextMenuItem(const LLSD& userdata); +	LLChatEntry* getChatBox() { return mInputEditor; } + +	std::string getCurrentChat(); + +	virtual BOOL handleKeyHere( KEY key, MASK mask );  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); -	virtual void	draw(); -	// focus overrides -	/*virtual*/ void	onFocusLost(); -	/*virtual*/ void	onFocusReceived(); -	 -	/*virtual*/ void	setVisible(BOOL visible); -	 -	virtual void updateChatHistoryStyle(); +	static void startChat(const char* line); +	static void stopChat(); -	static void processChatHistoryStyleUpdate(const LLSD& newvalue); +	static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); +	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); -	void loadHistory(); +	void showHistory(); -	static LLNearbyChat* getInstance(); -	void removeScreenChat(); +protected: +	static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); +	static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata); +	static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); +	void onChatBoxFocusReceived(); -private: +	void sendChat( EChatType type ); +	void onChatBoxCommit(); +	void onChatFontChange(LLFontGL* fontp); -	void	getAllowedRect		(LLRect& rect); +	/*virtual*/ void onTearOffClicked(); -	void	onNearbySpeakers	(); +	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); +	EChatType processChatTypeTriggers(EChatType type, std::string &str); + +	void displaySpeakingIndicator(); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	// Which non-zero channel did we last chat on? +	static S32 sLastSpecialChatChannel; + +	LLOutputMonitorCtrl*	mOutputMonitor; +	LLLocalSpeakerMgr*		mSpeakerMgr; +	S32 mExpandedHeight;  private: -	LLHandle<LLView>	mPopupMenuHandle; -	LLChatHistory*		mChatHistory; +	// prepare chat's params and out one message to chatHistory +	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	void	onNearbySpeakers	(); + +	/*virtual*/ void refresh(); + +	LLHandle<LLView>	mPopupMenuHandle;  	std::vector<LLChat> mMessageArchive; +  };  #endif - - diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp deleted file mode 100644 index f8f0f7d243..0000000000 --- a/indra/newview/llnearbychatbar.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/**  - * @file llnearbychatbar.cpp - * @brief LLNearbyChatBar class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "message.h" - -#include "llappviewer.h" -#include "llfloaterreg.h" -#include "lltrans.h" - -#include "llfirstuse.h" -#include "llnearbychatbar.h" -#include "llnearbychatbarlistener.h" -#include "llagent.h" -#include "llgesturemgr.h" -#include "llmultigesture.h" -#include "llkeyboard.h" -#include "llanimationstates.h" -#include "llviewerstats.h" -#include "llcommandhandler.h" -#include "llviewercontrol.h" -#include "llnavigationbar.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llrootview.h" -#include "llviewerchat.h" -#include "llnearbychat.h" -#include "lltranslate.h" - -#include "llresizehandle.h" -#include "llautoreplace.h" - -S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; - -const S32 EXPANDED_HEIGHT = 300; -const S32 COLLAPSED_HEIGHT = 60; -const S32 EXPANDED_MIN_HEIGHT = 150; - -// legacy callback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -struct LLChatTypeTrigger { -	std::string name; -	EChatType type; -}; - -static LLChatTypeTrigger sChatTypeTriggers[] = { -	{ "/whisper"	, CHAT_TYPE_WHISPER}, -	{ "/shout"	, CHAT_TYPE_SHOUT} -}; - -LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) -:	LLFloater(key), -	mChatBox(NULL), -	mNearbyChat(NULL), -	mOutputMonitor(NULL), -	mSpeakerMgr(NULL), -	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) -{ -	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); -	mListener.reset(new LLNearbyChatBarListener(*this)); -} - -//virtual -BOOL LLNearbyChatBar::postBuild() -{ -	mChatBox = getChild<LLLineEditor>("chat_box"); - -	mChatBox->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2)); -	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 ); -	mChatBox->setRevertOnEsc( FALSE ); -	mChatBox->setIgnoreTab(TRUE); -	mChatBox->setPassDelete(TRUE); -	mChatBox->setReplaceNewlinesWithSpaces(FALSE); -	mChatBox->setEnableLineHistory(TRUE); -	mChatBox->setFont(LLViewerChat::getChatFont()); - -	mNearbyChat = getChildView("nearby_chat"); - -	gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); -	BOOL show_nearby_chat = gSavedSettings.getBOOL("nearbychat_history_visibility"); - -	LLButton* show_btn = getChild<LLButton>("show_nearby_chat"); -	show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this)); -	show_btn->setToggleState(show_nearby_chat); - -	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); -	mOutputMonitor->setVisible(FALSE); - -	showNearbyChatPanel(show_nearby_chat); - -	// Register for font change notifications -	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - -	enableResizeCtrls(true, true, false); - -	return TRUE; -} - -// virtual -void LLNearbyChatBar::onOpen(const LLSD& key) -{ -	showTranslationCheckbox(LLTranslate::isTranslationConfigured()); -} - -bool LLNearbyChatBar::applyRectControl() -{ -	bool rect_controlled = LLFloater::applyRectControl(); - -	if (!mNearbyChat->getVisible()) -	{ -		reshape(getRect().getWidth(), getMinHeight()); -		enableResizeCtrls(true, true, false); -	} -	else -	{ -		enableResizeCtrls(true); -		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -	} -	 -	return rect_controlled; -} - -void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp) -{ -	// Update things with the new font whohoo -	if (mChatBox) -	{ -		mChatBox->setFont(fontp); -	} -} - -//static -LLNearbyChatBar* LLNearbyChatBar::getInstance() -{ -	return LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar"); -} - -void LLNearbyChatBar::showHistory() -{ -	openFloater(); - -	if (!getChildView("nearby_chat")->getVisible()) -	{ -		onToggleNearbyChatPanel(); -	} -} - -void LLNearbyChatBar::showTranslationCheckbox(BOOL show) -{ -	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); -} - -void LLNearbyChatBar::draw() -{ -	displaySpeakingIndicator(); -	LLFloater::draw(); -} - -std::string LLNearbyChatBar::getCurrentChat() -{ -	return mChatBox ? mChatBox->getText() : LLStringUtil::null; -} - -// virtual -BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) -{ -	BOOL handled = FALSE; - -	if( KEY_RETURN == key && mask == MASK_CONTROL) -	{ -		// shout -		sendChat(CHAT_TYPE_SHOUT); -		handled = TRUE; -	} - -	return handled; -} - -BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) -{ -	U32 in_len = in_str.length(); -	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	 -	for (S32 n = 0; n < cnt; n++) -	{ -		if (in_len > sChatTypeTriggers[n].name.length()) -			continue; - -		std::string trigger_trunc = sChatTypeTriggers[n].name; -		LLStringUtil::truncate(trigger_trunc, in_len); - -		if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) -		{ -			*out_str = sChatTypeTriggers[n].name; -			return TRUE; -		} -	} - -	return FALSE; -} - -void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) -{ -	LLFirstUse::otherAvatarChatFirst(false); - -	LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - -	LLWString raw_text = self->mChatBox->getWText(); - -	// Can't trim the end, because that will cause autocompletion -	// to eat trailing spaces that might be part of a gesture. -	LLWStringUtil::trimHead(raw_text); - -	S32 length = raw_text.length(); - -	if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences -	{ -		gAgent.startTyping(); -	} -	else -	{ -		gAgent.stopTyping(); -	} - -	/* Doesn't work -- can't tell the difference between a backspace -	   that killed the selection vs. backspace at the end of line. -	if (length > 1  -		&& text[0] == '/' -		&& key == KEY_BACKSPACE) -	{ -		// the selection will already be deleted, but we need to trim -		// off the character before -		std::string new_text = raw_text.substr(0, length-1); -		self->mInputEditor->setText( new_text ); -		self->mInputEditor->setCursorToEnd(); -		length = length - 1; -	} -	*/ - -	KEY key = gKeyboard->currentKey(); - -	// Ignore "special" keys, like backspace, arrows, etc. -	if (length > 1  -		&& raw_text[0] == '/' -		&& key < KEY_SPECIAL) -	{ -		// we're starting a gesture, attempt to autocomplete - -		std::string utf8_trigger = wstring_to_utf8str(raw_text); -		std::string utf8_out_str(utf8_trigger); - -		if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) -		{ -			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); -			self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part -			S32 outlength = self->mChatBox->getLength(); // in characters - -			// Select to end of line, starting from the character -			// after the last one the user typed. -			self->mChatBox->setSelection(length, outlength); -		} -		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) -		{ -			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); -			self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part -			self->mChatBox->setCursorToEnd(); -		} - -		//llinfos << "GESTUREDEBUG " << trigger  -		//	<< " len " << length -		//	<< " outlen " << out_str.getLength() -		//	<< llendl; -	} -} - -// static -void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) -{ -	// stop typing animation -	gAgent.stopTyping(); -} - -void LLNearbyChatBar::onChatBoxFocusReceived() -{ -	mChatBox->setEnabled(!gDisconnected); -} - -EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str) -{ -	U32 length = str.length(); -	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	 -	for (S32 n = 0; n < cnt; n++) -	{ -		if (length >= sChatTypeTriggers[n].name.length()) -		{ -			std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); - -			if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) -			{ -				U32 trigger_length = sChatTypeTriggers[n].name.length(); - -				// It's to remove space after trigger name -				if (length > trigger_length && str[trigger_length] == ' ') -					trigger_length++; - -				str = str.substr(trigger_length, length); - -				if (CHAT_TYPE_NORMAL == type) -					return sChatTypeTriggers[n].type; -				else -					break; -			} -		} -	} - -	return type; -} - -void LLNearbyChatBar::sendChat( EChatType type ) -{ -	if (mChatBox) -	{ -		LLWString text = mChatBox->getConvertedText(); -		if (!text.empty()) -		{ -			// store sent line in history, duplicates will get filtered -			mChatBox->updateHistory(); -			// Check if this is destined for another channel -			S32 channel = 0; -			stripChannelNumber(text, &channel); -			 -			std::string utf8text = wstring_to_utf8str(text); -			// Try to trigger a gesture, if not chat to a script. -			std::string utf8_revised_text; -			if (0 == channel) -			{ -				// discard returned "found" boolean -				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); -			} -			else -			{ -				utf8_revised_text = utf8text; -			} - -			utf8_revised_text = utf8str_trim(utf8_revised_text); - -			type = processChatTypeTriggers(type, utf8_revised_text); - -			if (!utf8_revised_text.empty()) -			{ -				// Chat with animation -				sendChatFromViewer(utf8_revised_text, type, TRUE); -			} -		} - -		mChatBox->setText(LLStringExplicit("")); -	} - -	gAgent.stopTyping(); - -	// If the user wants to stop chatting on hitting return, lose focus -	// and go out of chat mode. -	if (gSavedSettings.getBOOL("CloseChatOnReturn")) -	{ -		stopChat(); -	} -} - -void LLNearbyChatBar::showNearbyChatPanel(bool show) -{ -	if (!show) -	{ -		if (mNearbyChat->getVisible() && !isMinimized()) -		{ -			mExpandedHeight = getRect().getHeight(); -		} -		setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT); -		mNearbyChat->setVisible(FALSE); -		reshape(getRect().getWidth(), COLLAPSED_HEIGHT); -		enableResizeCtrls(true, true, false); -		storeRectControl(); -	} -	else -	{ -		mNearbyChat->setVisible(TRUE); -		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -		reshape(getRect().getWidth(), mExpandedHeight); -		enableResizeCtrls(true); -		storeRectControl(); -	} - -	gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::onToggleNearbyChatPanel() -{ -	showNearbyChatPanel(!mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::setMinimized(BOOL b) -{ -	LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat"); -	// when unminimizing with nearby chat visible, go ahead and kill off screen chats -	if (!b && nearby_chat->getVisible()) -	{ -		nearby_chat->removeScreenChat(); -	} -		LLFloater::setMinimized(b); -} - -void LLNearbyChatBar::onChatBoxCommit() -{ -	if (mChatBox->getText().length() > 0) -	{ -		sendChat(CHAT_TYPE_NORMAL); -	} - -	gAgent.stopTyping(); -} - -void LLNearbyChatBar::displaySpeakingIndicator() -{ -	LLSpeakerMgr::speaker_list_t speaker_list; -	LLUUID id; - -	id.setNull(); -	mSpeakerMgr->update(TRUE); -	mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); - -	for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) -	{ -		LLPointer<LLSpeaker> s = *i; -		if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) -		{ -			id = s->mID; -			break; -		} -	} - -	if (!id.isNull()) -	{ -		mOutputMonitor->setVisible(TRUE); -		mOutputMonitor->setSpeakerId(id); -	} -	else -	{ -		mOutputMonitor->setVisible(FALSE); -	} -} - -void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) -{ -	sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); -} - -void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) -{ -	// Look for "/20 foo" channel chats. -	S32 channel = 0; -	LLWString out_text = stripChannelNumber(wtext, &channel); -	std::string utf8_out_text = wstring_to_utf8str(out_text); -	std::string utf8_text = wstring_to_utf8str(wtext); - -	utf8_text = utf8str_trim(utf8_text); -	if (!utf8_text.empty()) -	{ -		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); -	} - -	// Don't animate for chats people can't hear (chat to scripts) -	if (animate && (channel == 0)) -	{ -		if (type == CHAT_TYPE_WHISPER) -		{ -			lldebugs << "You whisper " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); -		} -		else if (type == CHAT_TYPE_NORMAL) -		{ -			lldebugs << "You say " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); -		} -		else if (type == CHAT_TYPE_SHOUT) -		{ -			lldebugs << "You shout " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); -		} -		else -		{ -			llinfos << "send_chat_from_viewer() - invalid volume" << llendl; -			return; -		} -	} -	else -	{ -		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) -		{ -			lldebugs << "Channel chat: " << utf8_text << llendl; -		} -	} - -	send_chat_from_viewer(utf8_out_text, type, channel); -} - -// static  -void LLNearbyChatBar::startChat(const char* line) -{ -	LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - -	if (!cb ) -		return; - -	cb->setVisible(TRUE); -	cb->setFocus(TRUE); -	cb->mChatBox->setFocus(TRUE); - -	if (line) -	{ -		std::string line_string(line); -		cb->mChatBox->setText(line_string); -	} - -	cb->mChatBox->setCursorToEnd(); -} - -// Exit "chat mode" and do the appropriate focus changes -// static -void LLNearbyChatBar::stopChat() -{ -	LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - -	if (!cb) -		return; - -	cb->mChatBox->setFocus(FALSE); - - 	// stop typing animation - 	gAgent.stopTyping(); -} - -// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. -// Otherwise returns input and channel 0. -LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) -{ -	if (mesg[0] == '/' -		&& mesg[1] == '/') -	{ -		// This is a "repeat channel send" -		*channel = sLastSpecialChatChannel; -		return mesg.substr(2, mesg.length() - 2); -	} -	else if (mesg[0] == '/' -			 && mesg[1] -			 && LLStringOps::isDigit(mesg[1])) -	{ -		// This a special "/20" speak on a channel -		S32 pos = 0; - -		// Copy the channel number into a string -		LLWString channel_string; -		llwchar c; -		do -		{ -			c = mesg[pos+1]; -			channel_string.push_back(c); -			pos++; -		} -		while(c && pos < 64 && LLStringOps::isDigit(c)); -		 -		// Move the pointer forward to the first non-whitespace char -		// Check isspace before looping, so we can handle "/33foo" -		// as well as "/33 foo" -		while(c && iswspace(c)) -		{ -			c = mesg[pos+1]; -			pos++; -		} -		 -		sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); -		*channel = sLastSpecialChatChannel; -		return mesg.substr(pos, mesg.length() - pos); -	} -	else -	{ -		// This is normal chat. -		*channel = 0; -		return mesg; -	} -} - -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) -{ -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessageFast(_PREHASH_ChatFromViewer); -	msg->nextBlockFast(_PREHASH_AgentData); -	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->nextBlockFast(_PREHASH_ChatData); -	msg->addStringFast(_PREHASH_Message, utf8_out_text); -	msg->addU8Fast(_PREHASH_Type, type); -	msg->addS32("Channel", channel); - -	gAgent.sendReliableMessage(); - -	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); -} - -class LLChatCommandHandler : public LLCommandHandler -{ -public: -	// not allowed from outside the app -	LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - -    // Your code here -	bool handle(const LLSD& tokens, const LLSD& query_map, -				LLMediaCtrl* web) -	{ -		bool retval = false; -		// Need at least 2 tokens to have a valid message. -		if (tokens.size() < 2) -		{ -			retval = false; -		} -		else -		{ -		S32 channel = tokens[0].asInteger(); -			// VWR-19499 Restrict function to chat channels greater than 0. -			if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) -			{ -				retval = true; -		// Send unescaped message, see EXT-6353. -		std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); -		send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); -			} -			else -			{ -				retval = false; -				// Tell us this is an unsupported SLurl. -			} -		} -		return retval; -	} -}; - -// Creating the object registers with the dispatcher. -LLChatCommandHandler gChatHandler; - - diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h deleted file mode 100644 index 662496d338..0000000000 --- a/indra/newview/llnearbychatbar.h +++ /dev/null @@ -1,104 +0,0 @@ -/**  - * @file llnearbychatbar.h - * @brief LLNearbyChatBar class definition - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLNEARBYCHATBAR_H -#define LL_LLNEARBYCHATBAR_H - -#include "llfloater.h" -#include "llcombobox.h" -#include "llgesturemgr.h" -#include "llchat.h" -#include "llvoiceclient.h" -#include "lloutputmonitorctrl.h" -#include "llspeakers.h" - -class LLNearbyChatBarListener; - -class LLNearbyChatBar :	public LLFloater -{ -	LOG_CLASS(LLNearbyChatBar); - -public: -	// constructor for inline chat-bars (e.g. hosted in chat history window) -	LLNearbyChatBar(const LLSD& key); -	~LLNearbyChatBar() {} - -	virtual BOOL postBuild(); -	/*virtual*/ void onOpen(const LLSD& key); - -	static LLNearbyChatBar* getInstance(); - -	LLLineEditor* getChatBox() { return mChatBox; } - -	virtual void draw(); - -	std::string getCurrentChat(); -	virtual BOOL handleKeyHere( KEY key, MASK mask ); - -	static void startChat(const char* line); -	static void stopChat(); - -	static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); -	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); - -	void showHistory(); -	void showTranslationCheckbox(BOOL show); -	/*virtual*/void setMinimized(BOOL b); - -protected: -	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(); -	void onChatFontChange(LLFontGL* fontp); - -	/* virtual */ bool applyRectControl(); - -	void showNearbyChatPanel(bool show); -	void onToggleNearbyChatPanel(); - -	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); -	EChatType processChatTypeTriggers(EChatType type, std::string &str); - -	void displaySpeakingIndicator(); - -	// Which non-zero channel did we last chat on? -	static S32 sLastSpecialChatChannel; - -	LLLineEditor*			mChatBox; -	LLView*					mNearbyChat; -	LLOutputMonitorCtrl*	mOutputMonitor; -	LLLocalSpeakerMgr*		mSpeakerMgr; - -	S32 mExpandedHeight; - -	boost::shared_ptr<LLNearbyChatBarListener> mListener; -}; - -#endif diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp index a63e1fb76e..61815d1864 100644 --- a/indra/newview/llnearbychatbarlistener.cpp +++ b/indra/newview/llnearbychatbarlistener.cpp @@ -29,14 +29,14 @@  #include "llviewerprecompiledheaders.h"  #include "llnearbychatbarlistener.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llagent.h"  #include "llchat.h" -LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar) +LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar)    : LLEventAPI("LLChatBar",                 "LLChatBar listener to (e.g.) sendChat, etc."),  	mChatbar(chatbar) diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h index 9af9bc1f7b..0537275424 100644 --- a/indra/newview/llnearbychatbarlistener.h +++ b/indra/newview/llnearbychatbarlistener.h @@ -33,17 +33,17 @@  #include "lleventapi.h"  class LLSD; -class LLNearbyChatBar; +class LLNearbyChat;  class LLNearbyChatBarListener : public LLEventAPI  {  public: -	LLNearbyChatBarListener(LLNearbyChatBar & chatbar); +	LLNearbyChatBarListener(LLNearbyChat & chatbar);  private:      void sendChat(LLSD const & chat_data) const; -	LLNearbyChatBar & mChatbar; +	LLNearbyChat & mChatbar;  };  #endif // LL_LLNEARBYCHATBARLISTENER_H diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 600fd395fb..c97e3585e1 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -1,6 +1,6 @@  /**    * @file LLNearbyChatHandler.cpp - * @brief Nearby chat notification managment + * @brief Nearby chat chat managment   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code @@ -40,22 +40,24 @@  #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance  #include "llviewerwindow.h"//for screen channel position -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llrootview.h"  #include "lllayoutstack.h"  //add LLNearbyChatHandler to LLNotificationsUI namespace  using namespace LLNotificationsUI; -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//-----------------------------------------------------------------------------------------------	 -LLToastPanelBase* createToastPanel() +static LLNearbyChatToastPanel* createToastPanel()  {  	LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();  	return item;  } + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//-----------------------------------------------------------------------------------------------	 +  class LLNearbyChatScreenChannel: public LLScreenChannelBase  {  	LOG_CLASS(LLNearbyChatScreenChannel); @@ -81,10 +83,10 @@ public:  		}  	} -	void addNotification	(LLSD& notification); +	void addChat	(LLSD& chat);  	void arrangeToasts		(); -	typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; +	typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t;  	void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}  	void onToastDestroyed	(LLToast* toast, bool app_quitting); @@ -152,6 +154,8 @@ protected:  	bool	mChannelRect;  }; + +  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast  //----------------------------------------------------------------------------------------------- @@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime()  bool	LLNearbyChatScreenChannel::createPoolToast()  { -	LLToastPanelBase* panel= m_create_toast_panel_callback_t(); +	LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t();  	if(!panel)  		return false; @@ -277,7 +281,7 @@ bool	LLNearbyChatScreenChannel::createPoolToast()  	return true;  } -void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +void LLNearbyChatScreenChannel::addChat(LLSD& chat)  {  	//look in pool. if there is any message  	if(mStopProcessing) @@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	if(m_active_toasts.size())  	{ -		LLUUID fromID = notification["from_id"].asUUID();		// agent id or object id -		std::string from = notification["from"].asString(); +		LLUUID fromID = chat["from_id"].asUUID();		// agent id or object id +		std::string from = chat["from"].asString();  		LLToast* toast = m_active_toasts[0].get();  		if (toast)  		{ @@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  			if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())  			{ -				panel->addMessage(notification); +				panel->addMessage(chat);  				toast->reshapeToPanel();  				toast->startTimer(); @@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  		LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;  		if(!createPoolToast())//created toast will go to pool. so next call will find it  			return; -		addNotification(notification); +		addChat(chat);  		return;  	} -	int chat_type = notification["chat_type"].asInteger(); +	int chat_type = chat["chat_type"].asInteger();  	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))  	{ @@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	m_toast_pool.pop_back(); -	LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); +	LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());  	if(!panel)  		return; -	panel->init(notification); +	panel->init(chat);  	toast->reshapeToPanel();  	toast->startTimer(); @@ -445,10 +449,8 @@ void LLNearbyChatScreenChannel::arrangeToasts()  //-----------------------------------------------------------------------------------------------  boost::scoped_ptr<LLEventPump> LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); -LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) +LLNearbyChatHandler::LLNearbyChatHandler()  { -	mType = type; -  	// Getting a Channel for our notifications  	LLNearbyChatScreenChannel::Params p;  	p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); @@ -485,28 +487,26 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	if(chat_msg.mText.empty())  		return;//don't process empty messages -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - -	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); +	LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();  	// Build notification data  -	LLSD notification; -	notification["message"] = chat_msg.mText; -	notification["from"] = chat_msg.mFromName; -	notification["from_id"] = chat_msg.mFromID; -	notification["time"] = chat_msg.mTime; -	notification["source"] = (S32)chat_msg.mSourceType; -	notification["chat_type"] = (S32)chat_msg.mChatType; -	notification["chat_style"] = (S32)chat_msg.mChatStyle; +	LLSD chat; +	chat["message"] = chat_msg.mText; +	chat["from"] = chat_msg.mFromName; +	chat["from_id"] = chat_msg.mFromID; +	chat["time"] = chat_msg.mTime; +	chat["source"] = (S32)chat_msg.mSourceType; +	chat["chat_type"] = (S32)chat_msg.mChatType; +	chat["chat_style"] = (S32)chat_msg.mChatStyle;  	// Pass sender info so that it can be rendered properly (STORM-1021). -	notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); +	chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);  	if (chat_msg.mChatType == CHAT_TYPE_DIRECT &&  		chat_msg.mText.length() > 0 &&  		chat_msg.mText[0] == '@')  	{  		// Send event on to LLEventStream and exit -		sChatWatcher->post(notification); +		sChatWatcher->post(chat);  		return;  	} @@ -553,11 +553,9 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	}  	// Send event on to LLEventStream -	sChatWatcher->post(notification); +	sChatWatcher->post(chat); - -	if( !chat_bar->isMinimized() -		&& nearby_chat->isInVisibleChain()  +	if( nearby_chat->isInVisibleChain()  		|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT  			&& gSavedSettings.getBOOL("UseChatBubbles") )  		|| mChannel.isDead() @@ -604,23 +602,19 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  		// Add a nearby chat toast.  		LLUUID id;  		id.generate(); -		notification["id"] = id; +		chat["id"] = id;  		std::string r_color_name = "White";  		F32 r_color_alpha = 1.0f;   		LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); -		notification["text_color"] = r_color_name; -		notification["color_alpha"] = r_color_alpha; -		notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ; -		notification["message"] = toast_msg; -		channel->addNotification(notification);	 +		chat["text_color"] = r_color_name; +		chat["color_alpha"] = r_color_alpha; +		chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; +		chat["message"] = toast_msg; +		channel->addChat(chat);	  	}  } -void LLNearbyChatHandler::onDeleteToast(LLToast* toast) -{ -} -  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h index b0e4f62d51..a5034ac1cb 100644 --- a/indra/newview/llnearbychathandler.h +++ b/indra/newview/llnearbychathandler.h @@ -37,14 +37,13 @@ namespace LLNotificationsUI{  class LLNearbyChatHandler : public LLChatHandler  {  public: -	LLNearbyChatHandler(e_notification_type type,const LLSD& id); +	LLNearbyChatHandler();  	virtual ~LLNearbyChatHandler();  	virtual void processChat(const LLChat& chat_msg, const LLSD &args);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel();  	static boost::scoped_ptr<LLEventPump> sChatWatcher; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 89fe7bb3c2..2bc9cdd3c1 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -40,10 +40,10 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false) +LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal)  +:	LLSysHandler(name, notification_type), +	mIsModal(is_modal)  { -	mType = type; -  	LLScreenChannelBase::Params p;  	p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID"));  	p.display_toasts_always = true; @@ -68,79 +68,58 @@ void LLAlertHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLAlertHandler::processNotification(const LLSD& notify) +bool LLAlertHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") +	if (notification->canLogToIM() && notification->hasFormElements())  	{ -		if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) -		{ -			const std::string name = LLHandlerUtil::getSubstitutionName(notification); - -			LLUUID from_id = notification->getPayload()["from_id"]; - -			// firstly create session... -			LLHandlerUtil::spawnIMSession(name, from_id); - -			// ...then log message to have IM Well notified about new message -			LLHandlerUtil::logToIMP2P(notification); -		} - -		LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); -		p.enable_hide_btn = false; -		p.can_fade = false; -		p.is_modal = mIsModal; -		p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - -		// Show alert in middle of progress view (during teleport) (EXT-1093) -		LLProgressView* progress = gViewerWindow->getProgressView(); -		LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); -		mChannel.get()->updatePositionAndSize(rc); - -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); -	} -	else if (notify["sigtype"].asString() == "change") -	{ -		LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); -	} -	else -	{ -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->killToastByNotificationID(notification->getID()); +		const std::string name = LLHandlerUtil::getSubstitutionName(notification); + +		LLUUID from_id = notification->getPayload()["from_id"]; + +		// firstly create session... +		LLHandlerUtil::spawnIMSession(name, from_id); + +		// ...then log message to have IM Well notified about new message +		LLHandlerUtil::logToIMP2P(notification);  	} + +	LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); +	p.enable_hide_btn = false; +	p.can_fade = false; +	p.is_modal = mIsModal; +	p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); + +	// Show alert in middle of progress view (during teleport) (EXT-1093) +	LLProgressView* progress = gViewerWindow->getProgressView(); +	LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); +	mChannel.get()->updatePositionAndSize(rc); + +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); +	  	return false;  } -//-------------------------------------------------------------------------- - -void LLAlertHandler::onDeleteToast(LLToast* toast) +void LLAlertHandler::onChange( LLNotificationPtr notification )  { +	LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);  } - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index ad51389241..18cd94e685 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -37,15 +37,13 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) +LLGroupHandler::LLGroupHandler() +:	LLSysHandler("Group Notifications", "groupnotify")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -64,72 +62,37 @@ void LLGroupHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLGroupHandler::processNotification(const LLSD& notify) +bool LLGroupHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ -		LLHandlerUtil::logGroupNoticeToIMGroup(notification); +	LLHandlerUtil::logGroupNoticeToIMGroup(notification); -		LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.panel = notify_box; -		p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); +	LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.panel = notify_box; +	p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); -		// send a signal to the counter manager -		mNewNotificationSignal(); +	LLGroupActions::refresh_notices(); -		LLGroupActions::refresh_notices(); -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); -	}  	return false;  } -//-------------------------------------------------------------------------- -void LLGroupHandler::onDeleteToast(LLToast* toast) -{ -	// send a signal to the counter manager -	mDelNotificationSignal(); - -	// send a signal to a listener to let him perform some action -	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID()); -} - -//-------------------------------------------------------------------------- -void LLGroupHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification && LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) -	{ -		LLNotifications::instance().cancel(notification); -	} -}  //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 3569ad6447..0899625242 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -30,7 +30,7 @@  #include "llwindow.h" -//#include "llnotificationsutil.h" +#include "llnotifications.h"  #include "llchannelmanager.h"  #include "llchat.h"  #include "llinstantmessage.h" @@ -40,20 +40,6 @@ class LLIMFloater;  namespace LLNotificationsUI  { -// ENotificationType enumerates all possible types of notifications that could be met -//  -typedef enum e_notification_type -{ -	NT_NOTIFY,  -	NT_NOTIFYTIP, -	NT_GROUPNOTIFY, -	NT_IMCHAT,  -	NT_GROUPCHAT,  -	NT_NEARBYCHAT,  -	NT_ALERT, -	NT_ALERTMODAL, -	NT_OFFER -} ENotificationType;  /**   * Handler of notification events. @@ -81,21 +67,8 @@ class LLEventHandler  public:  	virtual ~LLEventHandler() {}; -	// callbacks for counters -	typedef boost::function<void (void)> notification_callback_t; -	typedef boost::signals2::signal<void (void)> notification_signal_t; -	notification_signal_t mNewNotificationSignal; -	notification_signal_t mDelNotificationSignal; -	boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); } -	boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); } -	// callback for notification/toast -	typedef boost::function<void (const LLUUID id)> notification_id_callback_t; -	typedef boost::signals2::signal<void (const LLUUID id)> notification_id_signal_t; -	notification_id_signal_t mNotificationIDSignal; -	boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } -  protected: -	virtual void onDeleteToast(LLToast* toast)=0; +	virtual void onDeleteToast(LLToast* toast) {}  	// arrange handler's channel on a screen  	// is necessary to unbind a moment of creation of a channel and a moment of positioning of it @@ -104,8 +77,6 @@ protected:  	virtual void initChannel()=0;  	LLHandle<LLScreenChannelBase>	mChannel; -	e_notification_type				mType; -  };  // LLSysHandler and LLChatHandler are more specific base classes @@ -115,20 +86,18 @@ protected:  /**   * Handler for system notifications.   */ -class LLSysHandler : public LLEventHandler +class LLSysHandler : public LLEventHandler, public LLNotificationChannel  {  public: -	LLSysHandler(); +	LLSysHandler(const std::string& name, const std::string& notification_type);  	virtual ~LLSysHandler() {}; -	virtual bool processNotification(const LLSD& notify)=0; - -protected : -	static void init(); -	void removeExclusiveNotifications(const LLNotificationPtr& notif); +	// base interface functions +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} -	typedef std::list< std::set<std::string> > exclusive_notif_sets; -	static exclusive_notif_sets sExclusiveNotificationGroups; +	virtual bool processNotification(const LLNotificationPtr& notify)=0;  };  /** @@ -149,15 +118,12 @@ public:  class LLIMHandler : public LLSysHandler  {  public: -	LLIMHandler(e_notification_type type, const LLSD& id); +	LLIMHandler();  	virtual ~LLIMHandler(); -	// base interface functions -	virtual bool processNotification(const LLSD& notify); -  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); +	bool processNotification(const LLNotificationPtr& p); +	/*virtual*/ void initChannel();  };  /** @@ -167,16 +133,15 @@ protected:  class LLTipHandler : public LLSysHandler  {  public: -	LLTipHandler(e_notification_type type, const LLSD& id); +	LLTipHandler();  	virtual ~LLTipHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void onRejectToast(const LLUUID& id); -	virtual void initChannel(); +	/*virtual*/ void initChannel();  };  /** @@ -186,18 +151,16 @@ protected:  class LLScriptHandler : public LLSysHandler  {  public: -	LLScriptHandler(e_notification_type type, const LLSD& id); +	LLScriptHandler();  	virtual ~LLScriptHandler(); +	/*virtual*/ void onDelete(LLNotificationPtr p);  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id); +	/*virtual*/ void onDeleteToast(LLToast* toast); +	/*virtual*/ void initChannel();  }; @@ -207,18 +170,15 @@ protected:  class LLGroupHandler : public LLSysHandler  {  public: -	LLGroupHandler(e_notification_type type, const LLSD& id); +	LLGroupHandler();  	virtual ~LLGroupHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id);  };  /** @@ -227,16 +187,14 @@ protected:  class LLAlertHandler : public LLSysHandler  {  public: -	LLAlertHandler(e_notification_type type, const LLSD& id); +	LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal);  	virtual ~LLAlertHandler(); -	void setAlertMode(bool is_modal) { mIsModal = is_modal; } - -	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p); +	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel();  	bool	mIsModal; @@ -249,102 +207,71 @@ protected:  class LLOfferHandler : public LLSysHandler  {  public: -	LLOfferHandler(e_notification_type type, const LLSD& id); +	LLOfferHandler();  	virtual ~LLOfferHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p); +	/*virtual*/ void onDelete(LLNotificationPtr notification); +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id); +	/*virtual*/ void initChannel();  };  /**   * Handler for UI hints.   */ -class LLHintHandler : public LLSingleton<LLHintHandler> +class LLHintHandler : public LLNotificationChannel  {  public: -	LLHintHandler(); -	virtual ~LLHintHandler(); +	LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")) +	{} +	virtual ~LLHintHandler() {} -	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onAdd(LLNotificationPtr p); +	/*virtual*/ void onLoad(LLNotificationPtr p); +	/*virtual*/ void onDelete(LLNotificationPtr p);  };  /**   * Handler for browser notifications   */ -class LLBrowserNotification : public LLSingleton<LLBrowserNotification> +class LLBrowserNotification : public LLNotificationChannel  {  public: -	virtual bool processNotification(const LLSD& notify); +	LLBrowserNotification() +	: LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")) +	{} +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	bool processNotification(const LLNotificationPtr& p);  };  /**   * Handler for outbox notifications   */ -class LLOutboxNotification : public LLSingleton<LLOutboxNotification> +class LLOutboxNotification : public LLNotificationChannel  {  public: -	virtual bool processNotification(const LLSD& notify); +	LLOutboxNotification() +	:	LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")) +	{} +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p) { } +	/*virtual*/ void onDelete(LLNotificationPtr p); +	bool processNotification(const LLNotificationPtr& p);  };  class LLHandlerUtil  {  public:  	/** -	 * Checks sufficient conditions to log notification message to IM session. -	 */ -	static bool canLogToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to log notification message to nearby chat session. -	 */ -	static bool canLogToNearbyChat(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to spawn IM session. -	 */ -	static bool canSpawnIMSession(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to add notification toast panel IM floater. -	 */ -	static bool canAddNotifPanelToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks whether notification can be used multiple times or not. -	 */ -	static bool isNotificationReusable(const LLNotificationPtr& notification); - -	/** -	 * Checks if passed notification can create IM session and be written into it. -	 * -	 * This method uses canLogToIM() & canSpawnIMSession(). -	 */ -	static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks if passed notification can create toast. -	 */ -	static bool canSpawnToast(const LLNotificationPtr& notification); - -	/**  	 * Determines whether IM floater is opened.  	 */  	static bool isIMFloaterOpened(const LLNotificationPtr& notification);  	/** -	* Determines whether IM floater is focused. -	*/ -	static bool isIMFloaterFocused(const LLNotificationPtr& notification); - -	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -355,12 +282,7 @@ public:  	/**  	 * Writes notification message to IM  p2p session.  	 */ -	static void logToIMP2P(const LLNotificationPtr& notification); - -	/** -	 * Writes notification message to IM  p2p session. -	 */ -	static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only); +	static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only = false);  	/**  	 * Writes group notice notification message to IM  group session. @@ -406,13 +328,6 @@ public:  	 */  	static void decIMMesageCounter(const LLNotificationPtr& notification); -private: - -	/** -	 * Find IM floater based on "from_id" -	 */ -	static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); -  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 16c51138a9..cba22b233b 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,212 +41,19 @@  using namespace LLNotificationsUI; -// static -std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups; - -// static -void LLSysHandler::init() -{ -	std::set<std::string> online_offline_group; -	online_offline_group.insert("FriendOnline"); -	online_offline_group.insert("FriendOffline"); - -	sExclusiveNotificationGroups.push_back(online_offline_group); -} - -LLSysHandler::LLSysHandler() -{ -	if(sExclusiveNotificationGroups.empty()) -	{ -		init(); -	} -} - -void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) -{ -	LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); -	if (channel == NULL) -	{ -		return; -	} - -	class ExclusiveMatcher: public LLScreenChannel::Matcher -	{ -	public: -		ExclusiveMatcher(const std::set<std::string>& excl_group, -				const std::string& from_name) : -			mExclGroup(excl_group), mFromName(from_name) -		{ -		} -		bool matches(const LLNotificationPtr notification) const -		{ -			for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it -					!= mExclGroup.end(); it++) -			{ -				std::string from_name = LLHandlerUtil::getSubstitutionName(notification); -				if (notification->getName() == *it && from_name == mFromName) -				{ -					return true; -				} -			} -			return false; -		} -	private: -		const std::set<std::string>& mExclGroup; -		const std::string& mFromName; -	}; - - -	for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it -			!= sExclusiveNotificationGroups.end(); it++) -	{ -		std::set<std::string> group = *it; -		std::set<std::string>::iterator g_it = group.find(notif->getName()); -		if (g_it != group.end()) -		{ -			channel->killMatchedToasts(ExclusiveMatcher(group, -					LLHandlerUtil::getSubstitutionName(notif))); -		} -	} -} - -const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), -		REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), -		OBJECT_GIVE_ITEM("ObjectGiveItem"), -		OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"), -						PAYMENT_RECEIVED("PaymentReceived"), -						PAYMENT_SENT("PaymentSent"), -						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), -						USER_GIVE_ITEM("UserGiveItem"), -						INVENTORY_ACCEPTED("InventoryAccepted"), -						INVENTORY_DECLINED("InventoryDeclined"), -						OFFER_FRIENDSHIP("OfferFriendship"), -						FRIENDSHIP_ACCEPTED("FriendshipAccepted"), -						FRIENDSHIP_OFFERED("FriendshipOffered"), -						FRIENDSHIP_ACCEPTED_BYME("FriendshipAcceptedByMe"), -						FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"), -						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), -						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), -						TELEPORT_OFFERED("TeleportOffered"), -						TELEPORT_OFFERED_MATURITY_EXCEEDED("TeleportOffered_MaturityExceeded"), -						TELEPORT_OFFERED_MATURITY_BLOCKED("TeleportOffered_MaturityBlocked"), -						TELEPORT_OFFER_SENT("TeleportOfferSent"), -						IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); - +LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) +:	LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) +{}  // static -bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) -{ -	return GRANTED_MODIFY_RIGHTS == notification->getName() -			|| REVOKED_MODIFY_RIGHTS == notification->getName() -			|| PAYMENT_RECEIVED == notification->getName() -			|| PAYMENT_SENT == notification->getName() -			|| OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_OFFERED == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName() -			|| FRIENDSHIP_ACCEPTED_BYME == notification->getName() -			|| FRIENDSHIP_DECLINED_BYME == notification->getName() -			|| SERVER_OBJECT_MESSAGE == notification->getName() -			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName() -			|| USER_GIVE_ITEM == notification->getName() -			|| TELEPORT_OFFERED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName() -			|| TELEPORT_OFFER_SENT == notification->getName() -			|| IM_SYSTEM_MESSAGE_TIP == notification->getName(); -} - -// static -bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) -{ -	return notification->getType() == "notifytip" -			&&  FRIEND_ONLINE != notification->getName() -			&& FRIEND_OFFLINE != notification->getName() -			&& INVENTORY_ACCEPTED != notification->getName() -			&& INVENTORY_DECLINED != notification->getName() -			&& IM_SYSTEM_MESSAGE_TIP != notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -			|| USER_GIVE_ITEM == notification->getName() -			|| TELEPORT_OFFERED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -			|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); -} - -// static -bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -					|| USER_GIVE_ITEM == notification->getName() -					|| TELEPORT_OFFERED == notification->getName() -					|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -					|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); -} - -// static -bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -		|| USER_GIVE_ITEM == notification->getName() -		|| TELEPORT_OFFERED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) -{ -	return canLogToIM(notification) && canSpawnIMSession(notification); -} - -// static -bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) +bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)  { -	if(INVENTORY_DECLINED == notification->getName()  -		|| INVENTORY_ACCEPTED == notification->getName()) -	{ -		// return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909) -		return ! isIMFloaterOpened(notification); -	} - -	if(FRIENDSHIP_ACCEPTED == notification->getName()) -	{ -		// don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441 -		return ! isIMFloaterFocused(notification); -	} - -	if(OFFER_FRIENDSHIP == notification->getName() -		|| USER_GIVE_ITEM == notification->getName() -		|| TELEPORT_OFFERED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_EXCEEDED == notification->getName() -		|| TELEPORT_OFFERED_MATURITY_BLOCKED == notification->getName()) -	{ -		// When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 -		return ! isIMFloaterOpened(notification); -	} - -	return true; -} +	bool res = false; -// static -LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification) -{  	LLUUID from_id = notification->getPayload()["from_id"];  	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); -	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -// static -bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) -{ -	bool res = false; +	LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -	LLIMFloater* im_floater = findIMFloater(notification);  	if (im_floater != NULL)  	{  		res = im_floater->getVisible() == TRUE; @@ -255,19 +62,6 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)  	return res;  } -bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification) -{ -	bool res = false; - -	LLIMFloater* im_floater = findIMFloater(notification); -	if (im_floater != NULL) -	{ -		res = im_floater->hasFocus() == TRUE; -	} - -	return res; -} -  // static  void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		const std::string& session_name, const std::string& from_name, @@ -329,12 +123,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  	}  } -// static -void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) -{ -	logToIMP2P(notification, false); -} -  void log_name_callback(const std::string& full_name, const std::string& from_name,   					   const std::string& message, const LLUUID& from_id) @@ -346,9 +134,6 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam  // static  void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)  { -	// don't create IM p2p session with objects, it's necessary condition to log -	if (notification->getName() != OBJECT_GIVE_ITEM) -	{  		LLUUID from_id = notification->getPayload()["from_id"];  		if (from_id.isNull()) @@ -366,7 +151,6 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi  			gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));  		}  	} -}  // static  void LLHandlerUtil::logGroupNoticeToIMGroup( @@ -501,14 +285,10 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)  	LLUUID from_id = notification->getPayload()["from_id"];  	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); -	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( -			session_id); +	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(session_id); -	if (session == NULL) +	if (session)  	{ -		return; -	} -  	LLSD arg;  	arg["session_id"] = session_id;  	session->mNumUnread--; @@ -517,3 +297,5 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)  	arg["participant_unread"] = session->mParticipantUnreadMessageCount;  	LLIMModel::getInstance()->mNewMsgSignal(arg);  } +} + diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index f7163cb04f..271f418507 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,26 +33,6 @@  using namespace LLNotificationsUI; -LLHintHandler::LLHintHandler() -{ -} - -LLHintHandler::~LLHintHandler() -{ -} - -bool LLHintHandler::processNotification(const LLSD& notify) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	std::string sigtype = notify["sigtype"].asString(); -	if (sigtype == "add" || sigtype == "load") -	{ -		LLHints::show(notification); -	} -	else if (sigtype == "delete") -	{ -		LLHints::hide(notification); -	} -	return false; -} +void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index f792f53ac5..2862ad6962 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -42,107 +42,35 @@ using namespace LLNotificationsUI;  //--------------------------------------------------------------------------  LLNotificationManager::LLNotificationManager()  { -	mNotifyHandlers.clear();  	init();  }  //--------------------------------------------------------------------------  LLNotificationManager::~LLNotificationManager()  { -	BOOST_FOREACH(listener_pair_t& pair, mChannelListeners) -	{ -		pair.second.disconnect(); -	}  }  //--------------------------------------------------------------------------  void LLNotificationManager::init()  { -	LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify")); -	LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip")); -	LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify")); -	LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); -	LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); -	LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast")); -	LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); -	LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")); -	LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); -	LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); +	mChannels.push_back(new LLScriptHandler()); +	mChannels.push_back(new LLTipHandler()); +	mChannels.push_back(new LLGroupHandler()); +	mChannels.push_back(new LLAlertHandler("Alerts", "alert", false)); +	mChannels.push_back(new LLAlertHandler("AlertModal", "alertmodal", true)); +	mChannels.push_back(new LLOfferHandler()); +	mChannels.push_back(new LLHintHandler()); +	mChannels.push_back(new LLBrowserNotification()); +	mChannels.push_back(new LLOutboxNotification()); +	mChannels.push_back(new LLIMHandler()); -	mChannelListeners["Notifications"] = LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["NotificationTips"] = LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Group Notifications"] = LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Alerts"] = LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["AlertModal"] = LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["IM Notifications"] = LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Offer"] = LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Hints"] = LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); -	mChannelListeners["Browser"] = LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); -	mChannelListeners["Outbox"] = LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); - -	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); -	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); -	mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD())); -	mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); -	mNotifyHandlers["alertmodal"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); -	static_cast<LLAlertHandler*>(mNotifyHandlers["alertmodal"].get())->setAlertMode(true); -	mNotifyHandlers["notifytoast"] = boost::shared_ptr<LLEventHandler>(new LLIMHandler(NT_IMCHAT, LLSD())); -	 -	mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); -	mNotifyHandlers["offer"] = boost::shared_ptr<LLEventHandler>(new LLOfferHandler(NT_OFFER, LLSD())); -} - -//-------------------------------------------------------------------------- -bool LLNotificationManager::onNotification(const LLSD& notify) -{ -	LLSysHandler* handle = NULL; - -	if (LLNotifications::destroyed()) -		return false; - -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	 -	if (!notification)  -		return false; - -	std::string notification_type = notification->getType(); -	handle = static_cast<LLSysHandler*>(mNotifyHandlers[notification_type].get()); - -	if(!handle) -		return false; -	 -	return handle->processNotification(notify); +	mChatHandler = boost::shared_ptr<LLNearbyChatHandler>(new LLNearbyChatHandler());  }  //--------------------------------------------------------------------------  void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args)  { -	// check ENotificationType argument -	switch(args["type"].asInteger()) -	{ -	case NT_NEARBYCHAT: -		{ -			LLNearbyChatHandler* handle = dynamic_cast<LLNearbyChatHandler*>(mNotifyHandlers["nearbychat"].get()); - -			if(handle) -				handle->processChat(msg, args); -		} -		break; -	default: 	//no need to handle all enum types -		break; -	} -} - -//-------------------------------------------------------------------------- -LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type)  -{  -	std::map<std::string, boost::shared_ptr<LLEventHandler> >::iterator it = mNotifyHandlers.find(notification_type); - -	if(it != mNotifyHandlers.end()) -		return (*it).second.get(); - -	return NULL; +	if(mChatHandler) +		mChatHandler->processChat(msg, args);  } -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 27b6ba1c71..c8afdf9e46 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -28,8 +28,6 @@  #ifndef LL_LLNOTIFICATIONMANAGER_H  #define LL_LLNOTIFICATIONMANAGER_H -#include "llevents.h" -  #include "lluictrl.h"  #include "llnotificationhandler.h" @@ -49,7 +47,6 @@ class LLToast;  class LLNotificationManager : public LLSingleton<LLNotificationManager>  {  	typedef std::pair<std::string, LLEventHandler*> eventhandlers; -	typedef std::pair<const std::string, LLBoundListener> listener_pair_t;  public:	  	LLNotificationManager();	  	virtual ~LLNotificationManager(); @@ -59,22 +56,12 @@ public:  	void init(void);  	//TODO: combine processing and storage (*) -	// this method reacts on system notifications and calls an appropriate handler -	bool onNotification(const LLSD& notification); -  	// this method reacts on chat notifications and calls an appropriate handler  	void onChat(const LLChat& msg, const LLSD &args); -	// get a handler for a certain type of notification -	LLEventHandler* getHandlerForNotification(std::string notification_type); - -  private: -	//TODO (*) -	std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers; -	// cruft std::map<std::string, LLChatHandler*> mChatHandlers; - -	std::map<std::string, LLBoundListener> mChannelListeners; +	boost::shared_ptr<class LLNearbyChatHandler> mChatHandler; +	std::vector<LLNotificationChannelPtr> mChannels;  };  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 1552ed3346..6e641575fa 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -40,16 +40,14 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) +LLOfferHandler::LLOfferHandler() +:	LLSysHandler("Offer", "offer")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{  		channel->setControlHovering(true); -		channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -68,147 +66,109 @@ void LLOfferHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLOfferHandler::processNotification(const LLSD& notify) +bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ +	if( notification->getPayload().has("give_inventory_notification") +		&& notification->getPayload()["give_inventory_notification"].asBoolean() == false) +	{ +		// This is an original inventory offer, so add a script floater +		LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +	} +	else +	{ +		bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		if (add_notif_to_im)  		{ -			// This is an original inventory offer, so add a script floater -			LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +			const std::string name = LLHandlerUtil::getSubstitutionName(notification); + +			LLUUID from_id = notification->getPayload()["from_id"]; + +			LLHandlerUtil::spawnIMSession(name, from_id); +			LLHandlerUtil::addNotifPanelToIM(notification);  		} -		else + +		if (!notification->canShowToast())  		{ -			notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); - -			LLUUID session_id; -			if (LLHandlerUtil::canSpawnIMSession(notification)) -			{ -				const std::string name = LLHandlerUtil::getSubstitutionName(notification); - -				LLUUID from_id = notification->getPayload()["from_id"]; - -				session_id = LLHandlerUtil::spawnIMSession(name, from_id); -			} - -			bool show_toast = LLHandlerUtil::canSpawnToast(notification); -			bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); -			if (add_notid_to_im) -			{ -				LLHandlerUtil::addNotifPanelToIM(notification); -			} - -			if (notification->getPayload().has("SUPPRESS_TOAST") -						&& notification->getPayload()["SUPPRESS_TOAST"]) -			{ -				LLNotificationsUtil::cancel(notification); -			} -			else if(show_toast) -			{ -				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); -				// don't close notification on panel destroy since it will be used by IM floater -				notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); -				LLToast::Params p; -				p.notif_id = notification->getID(); -				p.notification = notification; -				p.panel = notify_box; -				p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); -				// we not save offer notifications to the syswell floater that should be added to the IM floater -				p.can_be_stored = !add_notid_to_im; - -				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -				if(channel) -					channel->addToast(p); - -				// if we not add notification to IM - add it to notification well -				if (!add_notid_to_im) -				{ -					// send a signal to the counter manager -					mNewNotificationSignal(); -				} -			} - -			if (LLHandlerUtil::canLogToIM(notification)) -			{ -				// log only to file if notif panel can be embedded to IM and IM is opened -				if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) -				{ -					LLHandlerUtil::logToIMP2P(notification, true); -				} -				else -				{ -					LLHandlerUtil::logToIMP2P(notification); -				} -			} +			LLNotificationsUtil::cancel(notification);  		} -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification))  		{ -			// Remove original inventory offer script floater -			LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); +			LLToast::Params p; +			p.notif_id = notification->getID(); +			p.notification = notification; +			p.panel = notify_box; +			// we not save offer notifications to the syswell floater that should be added to the IM floater +			p.can_be_stored = !add_notif_to_im; + +			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +			if(channel) +				channel->addToast(p);  		} -		else + +		if (notification->canLogToIM())  		{ -			if (LLHandlerUtil::canAddNotifPanelToIM(notification) -					&& !LLHandlerUtil::isIMFloaterOpened(notification)) -			{ -				LLHandlerUtil::decIMMesageCounter(notification); -			} -			mChannel.get()->killToastByNotificationID(notification->getID()); +			// log only to file if notif panel can be embedded to IM and IM is opened +			bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); +			LLHandlerUtil::logToIMP2P(notification, file_only);  		}  	}  	return false;  } -//-------------------------------------------------------------------------- - -void LLOfferHandler::onDeleteToast(LLToast* toast) +/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p)  { -	if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) +	LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); +	if (panelp)  	{ -		// send a signal to the counter manager -		mDelNotificationSignal(); +		// +		// HACK: if we're dealing with a notification embedded in IM, update it +		// otherwise remove its toast +		// +		if (dynamic_cast<LLIMToastNotifyPanel*>(panelp)) +		{ +			panelp->updateNotification(); +		} +		else +		{ +			// if notification has changed, hide it +			mChannel.get()->removeToastByNotificationID(p->getID()); +		}  	} - -	// send a signal to a listener to let him perform some action -	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID());  } -//-------------------------------------------------------------------------- -void LLOfferHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this -					// don't delete notification since it may be used by IM floater -					&& !LLHandlerUtil::canAddNotifPanelToIM(notification)) +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ +	if( notification->getPayload().has("give_inventory_notification") +		&& !notification->getPayload()["give_inventory_notification"] ) +	{ +		// Remove original inventory offer script floater +		LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +	} +	else  	{ -		LLNotifications::instance().cancel(notification); +		if (notification->canLogToIM()  +			&& notification->hasFormElements() +			&& !LLHandlerUtil::isIMFloaterOpened(notification)) +		{ +			LLHandlerUtil::decIMMesageCounter(notification); +		} +		mChannel.get()->removeToastByNotificationID(notification->getID());  	}  } + diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 398f54c6f7..7e9c0d4f4b 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -37,21 +37,15 @@  using namespace LLNotificationsUI; -static const std::string SCRIPT_DIALOG				("ScriptDialog"); -static const std::string SCRIPT_DIALOG_GROUP		("ScriptDialogGroup"); -static const std::string SCRIPT_LOAD_URL			("LoadWebPage"); -  //-------------------------------------------------------------------------- -LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) +LLScriptHandler::LLScriptHandler() +:	LLSysHandler("Notifications", "notify")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{  		channel->setControlHovering(true); -		channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -70,32 +64,25 @@ void LLScriptHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLScriptHandler::processNotification(const LLSD& notify) +bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add") -	{ -		if (LLHandlerUtil::canLogToIM(notification)) +	if (notification->canLogToIM())  		{  			LLHandlerUtil::logToIMP2P(notification);  		} -		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) +	if(notification->hasFormElements())  		{  			LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());  		} @@ -114,60 +101,39 @@ bool LLScriptHandler::processNotification(const LLSD& notify)  			{  				channel->addToast(p);  			} +	} -			// send a signal to the counter manager -			mNewNotificationSignal(); +	return false;  		} -	} -	else if (notify["sigtype"].asString() == "delete") + + +void LLScriptHandler::onDelete( LLNotificationPtr notification )  	{ -		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) +	if(notification->hasFormElements())  		{  			LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());  		}  		else  		{ -			mChannel.get()->killToastByNotificationID(notification->getID()); +			mChannel.get()->removeToastByNotificationID(notification->getID());  		}  	} -	return false; -} +  //--------------------------------------------------------------------------  void LLScriptHandler::onDeleteToast(LLToast* toast)  { -	// send a signal to the counter manager -	mDelNotificationSignal(); -  	// send a signal to a listener to let him perform some action  	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID()); -  	LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); -	if( notification &&  -		(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) ) +	if( notification && notification->hasFormElements())  	{  		LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());  	}  } -//-------------------------------------------------------------------------- -void LLScriptHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) -	{ -		LLNotifications::instance().cancel(notification); -	} -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index fb1adc7ddf..a31b95811e 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -84,9 +84,11 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay  	return false;  } +static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); +  void LLPersistentNotificationStorage::saveNotifications()  { -	// TODO - think about save optimization. +	LLFastTimer _(FTM_SAVE_NOTIFICATIONS);  	llofstream notify_file(mFileName.c_str());  	if (!notify_file.is_open()) @@ -98,10 +100,15 @@ void LLPersistentNotificationStorage::saveNotifications()  	LLSD output;  	LLSD& data = output["data"]; -	LLNotificationChannelPtr history_channel = LLNotifications::instance().getChannel("Persistent"); -	LLNotificationSet::iterator it = history_channel->begin(); +	boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); +	if (!history_channel) +	{ +		return; +	} -	for ( ; history_channel->end() != it; ++it) +	for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); +		it != end_it; +		++it)  	{  		LLNotificationPtr notification = *it; @@ -120,8 +127,11 @@ void LLPersistentNotificationStorage::saveNotifications()  	formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);  } +static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); +  void LLPersistentNotificationStorage::loadNotifications()  { +	LLFastTimer _(FTM_LOAD_NOTIFICATIONS);  	LLResponderRegistry::registerResponders();  	LLNotifications::instance().getChannel("Persistent")-> diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index e397cfa046..a420c0d2ed 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -29,7 +29,7 @@  #include "llfloaterreg.h"  #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llnotificationhandler.h"  #include "llnotifications.h"  #include "lltoastnotifypanel.h" @@ -41,15 +41,13 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) +LLTipHandler::LLTipHandler() +:	LLSysHandler("NotificationTips", "notifytip")  { -	mType = type;	 -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->setOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -68,102 +66,67 @@ void LLTipHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLTipHandler::processNotification(const LLSD& notify) +bool LLTipHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false;	 -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{  		// archive message in nearby chat -		if (LLHandlerUtil::canLogToNearbyChat(notification)) -		{ -			LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - -			// don't show toast if Nearby Chat is opened -			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); -			if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) -			{ -				return false; -			} -		} - -		std::string session_name = notification->getPayload()["SESSION_NAME"]; -		const std::string name = notification->getSubstitutions()["NAME"]; -		if (session_name.empty()) -		{ -			session_name = name; -		} -		LLUUID from_id = notification->getPayload()["from_id"]; -		if (LLHandlerUtil::canLogToIM(notification)) -		{ -			LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, -					notification->getMessage(), from_id, from_id); -		} - -		if (LLHandlerUtil::canSpawnIMSession(notification)) -		{ -			LLHandlerUtil::spawnIMSession(name, from_id); -		} +	if (notification->canLogToChat()) +	{ +		LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); -		// don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) -		if (!LLHandlerUtil::canSpawnToast(notification)) +		// don't show toast if Nearby Chat is opened +		LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); +		if (nearby_chat->isChatVisible())  		{  			return false;  		} +	} -		LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); -		p.panel = notify_box; -		p.is_tip = true; -		p.can_be_stored = false; -		 -		removeExclusiveNotifications(notification); - -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); +	std::string session_name = notification->getPayload()["SESSION_NAME"]; +	const std::string name = notification->getSubstitutions()["NAME"]; +	if (session_name.empty()) +	{ +		session_name = name;  	} -	else if (notify["sigtype"].asString() == "delete") +	LLUUID from_id = notification->getPayload()["from_id"]; +	if (notification->canLogToIM())  	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); +		LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, +				notification->getMessage(), from_id, from_id);  	} -	return false; -} - -//-------------------------------------------------------------------------- -void LLTipHandler::onDeleteToast(LLToast* toast) -{ -} - -//-------------------------------------------------------------------------- -void LLTipHandler::onRejectToast(const LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (notification->canLogToIM() && notification->hasFormElements()) +	{ +		LLHandlerUtil::spawnIMSession(name, from_id); +	} -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) +	if (notification->canLogToIM() && LLHandlerUtil::isIMFloaterOpened(notification))  	{ -		LLNotifications::instance().cancel(notification); +		return false;  	} + +	LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); +	p.panel = notify_box; +	p.is_tip = true; +	p.can_be_stored = false; +		 +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); +	return false;  } diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 85626d8783..096e714981 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -28,6 +28,7 @@  #include "lloutputmonitorctrl.h"  // library includes  +#include "llfloaterreg.h"  #include "llui.h"  // viewer includes @@ -241,6 +242,17 @@ void LLOutputMonitorCtrl::draw()  		gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE);  } +// virtual +BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ +	if (mSpeakerId != gAgentID) +	{ +		LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); +	} + +	return TRUE; +} +  void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/)  {  	if (speaker_id.isNull() && mSpeakerId.notNull()) diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 2d23753d46..7b02e84744 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -68,6 +68,7 @@ public:  	// llview overrides  	virtual void	draw(); +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	void			setPower(F32 val);  	F32				getPower(F32 val) const { return mPower; } diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 5c85ec438c..35cda14f8d 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -30,15 +30,23 @@  // library include  #include "llavatarname.h" +#include "llfiltereditor.h"  #include "llfloater.h"  #include "llfloaterreg.h"  #include "llnotificationsutil.h"  #include "llscrolllistctrl.h" +#include "llmenubutton.h"  // project include +#include "llavatarlistitem.h" +#include "llblocklist.h" +#include "llblockedlistitem.h"  #include "llfloateravatarpicker.h"  #include "llfloatersidepanelcontainer.h" +#include "llinventorylistitem.h" +#include "llinventorymodel.h"  #include "llsidetraypanelcontainer.h" +#include "llviewercontrol.h"  static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray"); @@ -54,26 +62,35 @@ const std::string BLOCKED_PARAM_NAME = "blocked_to_select";  LLPanelBlockedList::LLPanelBlockedList()  :	LLPanel()  { -	mCommitCallbackRegistrar.add("Block.ClickPick",			boost::bind(&LLPanelBlockedList::onPickBtnClick, this)); -	mCommitCallbackRegistrar.add("Block.ClickBlockByName",	boost::bind(&LLPanelBlockedList::onBlockByNameClick, this)); -	mCommitCallbackRegistrar.add("Block.ClickRemove",		boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this)); -} - -LLPanelBlockedList::~LLPanelBlockedList() -{ -	LLMuteList::getInstance()->removeObserver(this); +	mCommitCallbackRegistrar.add("Block.Action",	boost::bind(&LLPanelBlockedList::onCustomAction,  this, _2)); +	mEnableCallbackRegistrar.add("Block.Check",		boost::bind(&LLPanelBlockedList::isActionChecked, this, _2));  }  BOOL LLPanelBlockedList::postBuild()  { -	mBlockedList = getChild<LLScrollListCtrl>("blocked"); +	mBlockedList = getChild<LLBlockList>("blocked");  	mBlockedList->setCommitOnSelectionChange(TRUE); -	childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL); +	switch (gSavedSettings.getU32("BlockPeopleSortOrder")) +	{ +	case E_SORT_BY_NAME: +		mBlockedList->sortByName(); +		break; + +	case E_SORT_BY_TYPE: +		mBlockedList->sortByType(); +		break; +	} + +	// Use the context menu of the Block list for the Block tab gear menu. +	LLToggleableMenu* blocked_gear_menu = mBlockedList->getContextMenu(); +	if (blocked_gear_menu) +	{ +		getChild<LLMenuButton>("blocked_gear_btn")->setMenu(blocked_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} -	LLMuteList::getInstance()->addObserver(this); -	 -	refreshBlockedList(); +	getChild<LLButton>("unblock_btn")->setCommitCallback(boost::bind(&LLPanelBlockedList::unblockItem, this)); +	getChild<LLFilterEditor>("blocked_filter_input")->setCommitCallback(boost::bind(&LLPanelBlockedList::onFilterEdit, this, _2));  	return LLPanel::postBuild();  } @@ -94,78 +111,77 @@ void LLPanelBlockedList::onOpen(const LLSD& key)  void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id)  { -	mBlockedList->selectByID(mute_id); +	mBlockedList->selectItemByUUID(mute_id);  }  void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect)  { -	LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with(BLOCKED_PARAM_NAME, idToSelect)); +	LLFloaterSidePanelContainer::showPanel("people", "panel_people", +		LLSD().with("people_panel_tab_name", "blocked_panel").with(BLOCKED_PARAM_NAME, idToSelect));  }  //////////////////////////////////////////////////////////////////////////  // Private Section  ////////////////////////////////////////////////////////////////////////// -void LLPanelBlockedList::refreshBlockedList() +void LLPanelBlockedList::updateButtons()  { -	mBlockedList->deleteAllItems(); +	bool hasSelected = NULL != mBlockedList->getSelectedItem(); +	getChildView("unblock_btn")->setEnabled(hasSelected); +} -	std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes(); -	std::vector<LLMute>::iterator it; -	for (it = mutes.begin(); it != mutes.end(); ++it) +void LLPanelBlockedList::unblockItem() +{ +	LLBlockedListItem* item = mBlockedList->getBlockedItem(); +	if (item)  	{ -		LLScrollListItem::Params item_p; -		item_p.enabled(TRUE); -		item_p.value(it->mID); // link UUID of blocked item with ScrollListItem -		item_p.columns.add().column("item_name").value(it->mName);//.type("text"); -		item_p.columns.add().column("item_type").value(it->getDisplayType());//.type("text").width(111); - -		mBlockedList->addRow(item_p, ADD_BOTTOM); +		LLMute mute(item->getUUID(), item->getName()); +		LLMuteList::instance().remove(mute);  	}  } -void LLPanelBlockedList::updateButtons() +void LLPanelBlockedList::onCustomAction(const LLSD& userdata)  { -	bool hasSelected = NULL != mBlockedList->getFirstSelected(); -	getChildView("Unblock")->setEnabled(hasSelected); -} - +	const std::string command_name = userdata.asString(); - -void LLPanelBlockedList::onBackBtnClick() -{ -	LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); -	if(parent) +	if ("block_obj_by_name" == command_name) +	{ +		blockObjectByName(); +	} +	else if ("block_res_by_name" == command_name) +	{ +		blockResidentByName(); +	} +	else if ("sort_by_name" == command_name) +	{ +		mBlockedList->sortByName(); +		gSavedSettings.setU32("BlockPeopleSortOrder", E_SORT_BY_NAME); +	} +	else if ("sort_by_type" == command_name)  	{ -		parent->openPreviousPanel(); +		mBlockedList->sortByType(); +		gSavedSettings.setU32("BlockPeopleSortOrder", E_SORT_BY_TYPE);  	}  } -void LLPanelBlockedList::onRemoveBtnClick() +BOOL LLPanelBlockedList::isActionChecked(const LLSD& userdata)  { -	std::string name = mBlockedList->getSelectedItemLabel(); -	LLUUID id = mBlockedList->getStringUUIDSelectedItem(); -	LLMute mute(id, name); -	 -	S32 last_selected = mBlockedList->getFirstSelectedIndex(); -	if (LLMuteList::getInstance()->remove(mute)) +	std::string item = userdata.asString(); +	U32 sort_order = gSavedSettings.getU32("BlockPeopleSortOrder"); + +	if ("sort_by_name" == item) +	{ +		return E_SORT_BY_NAME == sort_order; +	} +	else if ("sort_by_type" == item)  	{ -		// Above removals may rebuild this dialog. -		 -		if (last_selected == mBlockedList->getItemCount()) -		{ -			// we were on the last item, so select the last item again -			mBlockedList->selectNthItem(last_selected - 1); -		} -		else -		{ -			// else select the item after the last item previously selected -			mBlockedList->selectNthItem(last_selected); -		} +		return E_SORT_BY_TYPE == sort_order;  	} + +	return false;  } -void LLPanelBlockedList::onPickBtnClick() +void LLPanelBlockedList::blockResidentByName()  {  	const BOOL allow_multiple = FALSE;  	const BOOL close_on_select = TRUE; @@ -176,11 +192,19 @@ void LLPanelBlockedList::onPickBtnClick()  	// addDependentFloater(picker);  } -void LLPanelBlockedList::onBlockByNameClick() +void LLPanelBlockedList::blockObjectByName()  {  	LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);  } +void LLPanelBlockedList::onFilterEdit(const std::string& search_string) +{ +	std::string filter = search_string; +	LLStringUtil::trimHead(filter); + +	mBlockedList->setNameFilter(filter); +} +  void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)  {  	if (names.empty() || ids.empty()) return; diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 74ad82e32d..332349dfc0 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -30,21 +30,15 @@  #include "llpanel.h"  #include "llmutelist.h"  #include "llfloater.h" -// #include <vector> -// class LLButton; -// class LLLineEditor; -// class LLMessageSystem; -// class LLUUID;  class LLAvatarName; -class LLScrollListCtrl; +class LLBlockList; -class LLPanelBlockedList -	:	public LLPanel, public LLMuteListObserver +class LLPanelBlockedList : public LLPanel  {  public:  	LLPanelBlockedList(); -	~LLPanelBlockedList(); +	~LLPanelBlockedList(){};  	virtual BOOL postBuild();  	virtual void draw(); @@ -59,25 +53,31 @@ public:  	 *			If it is LLUUID::null, nothing will be selected.  	 */  	static void showPanelAndSelect(const LLUUID& idToSelect); - -	// LLMuteListObserver callback interface implementation. -	/* virtual */ void onChange() {	refreshBlockedList();}  private: -	void refreshBlockedList(); + +	typedef enum e_sort_oder{ +		E_SORT_BY_NAME = 0, +		E_SORT_BY_TYPE = 1, +	} ESortOrder; +  	void updateButtons();  	// UI callbacks -	void onBackBtnClick(); -	void onRemoveBtnClick(); -	void onPickBtnClick(); -	void onBlockByNameClick(); +	void unblockItem(); +	void blockResidentByName(); +	void blockObjectByName(); +	void onFilterEdit(const std::string& search_string); + +	// List commnads +	void onCustomAction(const LLSD& userdata); +	BOOL isActionChecked(const LLSD& userdata);  	void callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);  	static void callbackBlockByName(const std::string& text);  private: -	LLScrollListCtrl* mBlockedList; +	LLBlockList* mBlockedList;  };  //----------------------------------------------------------------------------- diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index eda0749cdb..389baa86cd 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,31 +1,30 @@ -/**  +/**   * @file llpanelavatar.cpp   * @brief LLPanelAvatar and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc. - *  + *   * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public   * License as published by the Free Software Foundation;   * version 2.1 of the License only. - *  + *   * This library is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   * Lesser General Public License for more details. - *  + *   * You should have received a copy of the GNU Lesser General Public   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  + *   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */  #include "llviewerprecompiledheaders.h" -  #include "llfloaterreg.h"  #include "llpanelimcontrolpanel.h" @@ -39,393 +38,7 @@  #include "llavatarlist.h"  #include "llparticipantlist.h"  #include "llimview.h" -#include "llvoicechannel.h"  #include "llspeakers.h"  #include "lltrans.h" -void LLPanelChatControlPanel::onCallButtonClicked() -{ -	gIMMgr->startCall(mSessionId); -} - -void LLPanelChatControlPanel::onEndCallButtonClicked() -{ -	gIMMgr->endCall(mSessionId); -} - -void LLPanelChatControlPanel::onOpenVoiceControlsClicked() -{ -	LLFloaterReg::showInstance("voice_controls"); -} - -void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ -	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) -	{ -		return; -	} - -	updateCallButton(); -} - -void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ -	updateButtons(new_state); -} - -void LLPanelChatControlPanel::updateCallButton() -{ -	// hide/show call button -	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - -	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); -	 -	if (!session)  -	{ -		getChildView("call_btn")->setEnabled(false); -		return; -	} - -	bool session_initialized = session->mSessionInitialized; -	bool callback_enabled = session->mCallBackEnabled; - -	BOOL enable_connect = session_initialized -		&& voice_enabled -		&& callback_enabled; -	getChildView("call_btn")->setEnabled(enable_connect); -} - -void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state) -{ -	bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED; -	getChildView("end_call_btn_panel")->setVisible( is_call_started); -	getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel")); -	getChildView("call_btn_panel")->setVisible( ! is_call_started); -	 -	getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED); -	 -	updateCallButton(); -	 -} - -LLPanelChatControlPanel::~LLPanelChatControlPanel() -{ -	mVoiceChannelStateChangeConnection.disconnect(); -	if(LLVoiceClient::instanceExists()) -	{ -		LLVoiceClient::getInstance()->removeObserver(this); -	} -} - -BOOL LLPanelChatControlPanel::postBuild() -{ -	childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this)); -	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this)); -	childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this)); - -	LLVoiceClient::getInstance()->addObserver(this); - -	return TRUE; -} - -void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) -{ -	//Method is called twice for AdHoc and Group chat. Second time when server init reply received -	mSessionId = session_id; -	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId); -	if(voice_channel) -	{ -		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2)); -		 -		//call (either p2p, group or ad-hoc) can be already in started state -		updateButtons(voice_channel->getState()); -	} -} - -LLPanelIMControlPanel::LLPanelIMControlPanel() -{ -} - -LLPanelIMControlPanel::~LLPanelIMControlPanel() -{ -	LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -} - -BOOL LLPanelIMControlPanel::postBuild() -{ -	childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); -	childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); - -	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); -	childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this)); -	childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this)); - -	childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this)); -	childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this)); -	childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this)); -	 -	getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2)); - -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId())); - -	setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this)); -	 -	return LLPanelChatControlPanel::postBuild(); -} - -void LLPanelIMControlPanel::draw() -{ -	bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID); - -	getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted); -	getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted); - -	if (getChildView("volume_ctrl_panel")->getVisible()) -	{ - -		bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat); - -		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); -		mute_btn->setValue( is_muted_voice ); - -		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); -		volume_slider->setEnabled( !is_muted_voice ); - -		F32 volume; - -		if (is_muted_voice) -		{ -			// it's clearer to display their volume as zero -			volume = 0.f; -		} -		else -		{ -			// actual volume -			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); -		} -		volume_slider->setValue( (F64)volume ); -	} - -	LLPanelChatControlPanel::draw(); -} - -void LLPanelIMControlPanel::onClickMuteVolume() -{ -	// By convention, we only display and toggle voice mutes, not all mutes -	LLMuteList* mute_list = LLMuteList::getInstance(); -	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); -	if (!is_muted) -	{ -		mute_list->add(mute, LLMute::flagVoiceChat); -	} -	else -	{ -		mute_list->remove(mute, LLMute::flagVoiceChat); -	} -} - -void LLPanelIMControlPanel::onClickBlock() -{ -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); -	 -	LLMuteList::getInstance()->add(mute); -} - -void LLPanelIMControlPanel::onClickUnblock() -{ -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - -	LLMuteList::getInstance()->remove(mute); -} - -void LLPanelIMControlPanel::onVolumeChange(const LLSD& data) -{ -	F32 volume = (F32)data.asReal(); -	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} - -void LLPanelIMControlPanel::onTeleportButtonClicked() -{ -	LLAvatarActions::offerTeleport(mAvatarID); -} -void LLPanelIMControlPanel::onPayButtonClicked() -{ -	LLAvatarActions::pay(mAvatarID); -} - -void LLPanelIMControlPanel::onViewProfileButtonClicked() -{ -	LLAvatarActions::showProfile(mAvatarID); -} - -void LLPanelIMControlPanel::onAddFriendButtonClicked() -{ -	LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); -	std::string full_name = avatar_icon->getFullName(); -	LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name); -} - -void LLPanelIMControlPanel::onShareButtonClicked() -{ -	LLAvatarActions::share(mAvatarID); -} - -void LLPanelIMControlPanel::onFocusReceived() -{ -	// Disable all the buttons (Call, Teleport, etc) if disconnected. -	if (gDisconnected) -	{ -		setAllChildrenEnabled(FALSE); -	} -} - -void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) -{ -	LLPanelChatControlPanel::setSessionId(session_id); - -	LLIMModel& im_model = LLIMModel::instance(); - -	LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -	mAvatarID = im_model.getOtherParticipantID(session_id); -	LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); - -	// Disable "Add friend" button for friends. -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); -	 -	// Disable "Teleport" button if friend is offline -	if(LLAvatarActions::isFriend(mAvatarID)) -	{ -		getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); -	} - -	getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID); - -	// Disable most profile buttons if the participant is -	// not really an SL avatar (e.g., an Avaline caller). -	LLIMModel::LLIMSession* im_session = -		im_model.findIMSession(session_id); -	if( im_session && !im_session->mOtherParticipantIsAvatar ) -	{ -		getChildView("view_profile_btn")->setEnabled(FALSE); -		getChildView("add_friend_btn")->setEnabled(FALSE); - -		getChildView("share_btn")->setEnabled(FALSE); -		getChildView("teleport_btn")->setEnabled(FALSE); -		getChildView("pay_btn")->setEnabled(FALSE); - -        getChild<LLTextBox>("avatar_name")->setValue(im_session->mName); -        getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName); -	} -	else -	{ -		// If the participant is an avatar, fetch the currect name -		gCacheName->get(mAvatarID, false, -			boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3)); -	} -} - -//virtual -void LLPanelIMControlPanel::changed(U32 mask) -{ -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); -	 -	// Disable "Teleport" button if friend is offline -	if(LLAvatarActions::isFriend(mAvatarID)) -	{ -		getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); -	} -} - -void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group) -{ -	if ( id == mAvatarID ) -	{ -		std::string avatar_name = full_name; -		getChild<LLTextBox>("avatar_name")->setValue(avatar_name); -		getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name); - -		bool is_linden = LLStringUtil::endsWith(full_name, " Linden"); -		getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden); -	} -} - -LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): -mParticipantList(NULL) -{ -} - -BOOL LLPanelGroupControlPanel::postBuild() -{ -	childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this)); - -	return LLPanelChatControlPanel::postBuild(); -} - -LLPanelGroupControlPanel::~LLPanelGroupControlPanel() -{ -	delete mParticipantList; -	mParticipantList = NULL; -} - -// virtual -void LLPanelGroupControlPanel::draw() -{ -	// Need to resort the participant list if it's in sort by recent speaker order. -	if (mParticipantList) -		mParticipantList->update(); -	LLPanelChatControlPanel::draw(); -} - -void LLPanelGroupControlPanel::onGroupInfoButtonClicked() -{ -	LLGroupActions::show(mGroupID); -} - -void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) -{ -	// TODO: Check this code when when sort order menu will be added. (EM) -	if (false && !mParticipantList) -		return; - -	std::string chosen_item = userdata.asString(); - -	if (chosen_item == "sort_name") -	{ -		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); -	} - -} - -void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ -	LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state); -	mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED); -} - -void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) -{ -	LLPanelChatControlPanel::setSessionId(session_id); - -	mGroupID = session_id; - -	// for group and Ad-hoc chat we need to include agent into list  -	if(!mParticipantList) -	{ -		LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); -		mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false); -	} -} - - -LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id) -{ -} - -BOOL LLPanelAdHocControlPanel::postBuild() -{ -	//We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat -	return LLPanelChatControlPanel::postBuild(); -} diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index bba847b5d4..02915ec4bb 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -28,14 +28,12 @@  #define LL_LLPANELIMCONTROLPANEL_H  #include "llpanel.h" -#include "llvoicechannel.h"  #include "llcallingcard.h"  class LLParticipantList; -class LLPanelChatControlPanel  +class LLPanelChatControlPanel  	: public LLPanel -	, public LLVoiceClientStatusObserver  {  public:  	LLPanelChatControlPanel() : @@ -44,21 +42,6 @@ public:  	virtual BOOL postBuild(); -	void onCallButtonClicked(); -	void onEndCallButtonClicked(); -	void onOpenVoiceControlsClicked(); - -	// Implements LLVoiceClientStatusObserver::onChange() to enable the call -	// button when voice is available -	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - -	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); - -	void updateButtons(LLVoiceChannel::EState state); -	 -	// Enables/disables call button depending on voice availability -	void updateCallButton(); -  	virtual void setSessionId(const LLUUID& session_id);  	const LLUUID& getSessionId() { return mSessionId; } @@ -69,41 +52,6 @@ private:  	boost::signals2::connection mVoiceChannelStateChangeConnection;  }; - -class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver -{ -public: -	LLPanelIMControlPanel(); -	~LLPanelIMControlPanel(); - -	BOOL postBuild(); - -	void setSessionId(const LLUUID& session_id); - -	// LLFriendObserver trigger -	virtual void changed(U32 mask); - -protected: -	void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group); - -private: -	void onViewProfileButtonClicked(); -	void onAddFriendButtonClicked(); -	void onShareButtonClicked(); -	void onTeleportButtonClicked(); -	void onPayButtonClicked(); -	void onFocusReceived(); - -	void onClickMuteVolume(); -	void onClickBlock(); -	void onClickUnblock(); -	/*virtual*/ void draw(); -	void onVolumeChange(const LLSD& data); - -	LLUUID mAvatarID; -}; - -  class LLPanelGroupControlPanel : public LLPanelChatControlPanel  {  public: @@ -121,9 +69,7 @@ protected:  	LLParticipantList* mParticipantList;  private: -	void onGroupInfoButtonClicked();  	void onSortMenuItemClicked(const LLSD& userdata); -	/*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);  };  class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 68a3b6d1cd..9225ea3d53 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -102,7 +102,7 @@ void LLCheckFolderState::doFolder(LLFolderViewFolder* folder)  	// Counting only folders that pass the filter.  	// The listener check allow us to avoid counting the folder view  	// object itself because it has no listener assigned. -	if (folder->hasFilteredDescendants() && folder->getListener()) +	if (folder->getViewModelItem()->descendantsPassedFilter())  	{  		if (folder->isOpen())  		{ @@ -138,7 +138,7 @@ private:  // virtual  void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder)  { -	if (folder->getListener() && folder->getListener()->getUUID() == mFolderID) +	if (folder->getViewModelItem() && static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem())->getUUID() == mFolderID)  	{  		if (!folder->isOpen())  		{ @@ -177,7 +177,7 @@ void LLLandmarksPanelObserver::changed(U32 mask)  	if (!mIsLibraryLandmarksOpen && library)  	{  		// Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827. -		const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true); +		const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);  		if (landmarks_cat.notNull())  		{  			LLOpenFolderByID opener(landmarks_cat); @@ -247,10 +247,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  		LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());  		if (NULL == inventory_list) continue; -		if (inventory_list->getFilter()) -		{ -			filter_list(inventory_list, string); -		} +		filter_list(inventory_list, string);  	}  	if (sFilterSubString != string) @@ -281,28 +278,21 @@ void LLLandmarksPanel::onShowOnMap()  //virtual  void LLLandmarksPanel::onShowProfile()  { -	LLFolderViewItem* cur_item = getCurSelectedItem(); +	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  	if(!cur_item)  		return; -	cur_item->getListener()->performAction(mCurrentSelectedList->getModel(),"about"); +	cur_item->performAction(mCurrentSelectedList->getModel(),"about");  }  // virtual  void LLLandmarksPanel::onTeleport()  { -	LLFolderViewItem* current_item = getCurSelectedItem(); -	if (!current_item) -	{ -		llwarns << "There are no selected list. No actions are performed." << llendl; -		return; -	} - -	LLFolderViewEventListener* listenerp = current_item->getListener(); -	if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* view_model_item = getCurSelectedViewModelItem(); +	if (view_model_item && view_model_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{ -		listenerp->openItem(); +		view_model_item->openItem();  	}  } @@ -313,8 +303,7 @@ bool LLLandmarksPanel::isSingleItemSelected()  	if (mCurrentSelectedList != NULL)  	{ -		LLPlacesFolderView* root_view = -				static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()); +		LLFolderView* root_view = mCurrentSelectedList->getRootFolder();  		if (root_view->getSelectedCount() == 1)  		{ @@ -360,7 +349,7 @@ void LLLandmarksPanel::onSelectorButtonClicked()  	LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();  	if (!cur_item) return; -	LLFolderViewEventListener* listenerp = cur_item->getListener(); +	LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem());  	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		LLSD key; @@ -373,10 +362,7 @@ void LLLandmarksPanel::onSelectorButtonClicked()  void LLLandmarksPanel::updateShowFolderState()  { -	if (!mLandmarksInventoryPanel->getFilter()) -		return; - -	bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); +	bool show_all_folders =   mLandmarksInventoryPanel->getFilterSubString().empty();  	if (show_all_folders)  	{  		show_all_folders = category_has_descendents(mLandmarksInventoryPanel); @@ -417,8 +403,9 @@ void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_  bool LLLandmarksPanel::isLandmarkSelected() const   { -	LLFolderViewItem* current_item = getCurSelectedItem(); -	if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* current_item = getCurSelectedViewModelItem(); + +	if(current_item && current_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		return true;  	} @@ -440,10 +427,10 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const  void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)  { -	LLFolderViewItem* cur_item = getCurSelectedItem(); -	if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); +	if(cur_item && cur_item->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  -		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb); +		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getUUID(), cb);  		if (landmark)  		{  			cb(landmark); @@ -456,6 +443,17 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const  	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;  } +LLFolderViewModelItemInventory* LLLandmarksPanel::getCurSelectedViewModelItem() const +{ +	LLFolderViewItem* cur_item = getCurSelectedItem(); +	if (cur_item) +	{ +		return 	static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem()); +	} +	return NULL; +} + +  LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,  															 const std::string& tab_name,  															 const LLUUID& obj_id, @@ -466,7 +464,7 @@ LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPa  	LLFolderView* root = inventory_list->getRootFolder(); -	LLFolderViewItem* item = root->getItemByID(obj_id); +	LLFolderViewItem* item = inventory_list->getItemByID(obj_id);  	if (!item)  		return NULL; @@ -508,12 +506,12 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)  	// We have to make request to sever to get parcel_id and snaption_id.   	if(isLandmarkSelected())  	{ -		LLFolderViewItem* cur_item = getCurSelectedItem(); +		LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  		if (!cur_item) return; -		LLUUID id = cur_item->getListener()->getUUID(); +		LLUUID id = cur_item->getUUID();  		LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);  		doActionOnCurSelectedLandmark(boost::bind( -				&LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data)); +				&LLLandmarksPanel::doProcessParcelInfo, this, _1, getCurSelectedItem(), inv_item, parcel_data));  	}  } @@ -543,7 +541,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel()  	mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");  	initLandmarksPanel(mFavoritesInventoryPanel); -	mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); +	mFavoritesInventoryPanel->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems");  	initAccordion("tab_favorites", mFavoritesInventoryPanel, true);  } @@ -554,12 +552,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel()  	initLandmarksPanel(mLandmarksInventoryPanel); -	// Check if mLandmarksInventoryPanel is properly initialized and has a Filter created. -	// In case of a dummy widget getFilter() will return NULL. -	if (mLandmarksInventoryPanel->getFilter()) -	{ -		mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); -	} +	mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);  	// subscribe to have auto-rename functionality while creating New Folder  	mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2)); @@ -583,7 +576,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel()  	initLandmarksPanel(mLibraryInventoryPanel);  	// We want to fetch only "Landmarks" category from the library. -	const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true); +	const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);  	if (landmarks_cat.notNull())  	{  		LLInventoryModelBackgroundFetch::instance().start(landmarks_cat); @@ -595,12 +588,7 @@ void LLLandmarksPanel::initLibraryInventoryPanel()  void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list)  { -	// In case of a dummy widget further we have no Folder View widget and no Filter, -	// so further initialization leads to crash. -	if (!inventory_list->getFilter()) -		return; - -	inventory_list->getFilter()->setEmptyLookupMessage("PlacesNoMatchingItems"); +	inventory_list->getFilter().setEmptyLookupMessage("PlacesNoMatchingItems");  	inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);  	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); @@ -665,20 +653,20 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory  {  	if (inventory_list != mFavoritesInventoryPanel)  	{ -		mFavoritesInventoryPanel->getRootFolder()->clearSelection(); +		mFavoritesInventoryPanel->clearSelection();  	}  	if (inventory_list != mLandmarksInventoryPanel)  	{ -		mLandmarksInventoryPanel->getRootFolder()->clearSelection(); +		mLandmarksInventoryPanel->clearSelection();  	}  	if (inventory_list != mMyInventoryPanel)  	{ -		mMyInventoryPanel->getRootFolder()->clearSelection(); +		mMyInventoryPanel->clearSelection();  	}  	if (inventory_list != mLibraryInventoryPanel)  	{ -		mLibraryInventoryPanel->getRootFolder()->clearSelection(); +		mLibraryInventoryPanel->clearSelection();  	}  } @@ -731,14 +719,9 @@ void LLLandmarksPanel::onActionsButtonClick()  {  	LLToggleableMenu* menu = mGearFolderMenu; -	LLFolderViewItem* cur_item = NULL;  	if(mCurrentSelectedList)  	{ -		cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem(); -		if(!cur_item) -			return; - -		LLFolderViewEventListener* listenerp = cur_item->getListener(); +		LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();  		if(!listenerp)  			return; @@ -776,6 +759,9 @@ void LLLandmarksPanel::onTrashButtonClick() const  void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  { +	LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem(); +	LLFolderViewItem* item = getCurSelectedItem(); +  	std::string command_name = userdata.asString();  	if("add_landmark" == command_name)  	{ @@ -791,24 +777,24 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  	}   	else if ("category" == command_name)  	{ -		LLFolderViewItem* item = getCurSelectedItem();  		if (item && mCurrentSelectedList == mLandmarksInventoryPanel)  		{ -			LLFolderViewEventListener* folder_bridge = NULL; -			if (item-> getListener()->getInventoryType() +			LLFolderViewModelItem* folder_bridge = NULL; + +			if (view_model->getInventoryType()  					== LLInventoryType::IT_LANDMARK)  			{  				// for a landmark get parent folder bridge -				folder_bridge = item->getParentFolder()->getListener(); +				folder_bridge = item->getParentFolder()->getViewModelItem();  			} -			else if (item-> getListener()->getInventoryType() +			else if (view_model->getInventoryType()  					== LLInventoryType::IT_CATEGORY)  			{  				// for a folder get its own bridge -				folder_bridge = item->getListener(); +				folder_bridge = view_model;  			} -			menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), +			menu_create_inventory_item(mCurrentSelectedList,  					dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(  							"category"), gInventory.findCategoryUUIDForType(  							LLFolderType::FT_LANDMARK)); @@ -816,7 +802,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const  		else  		{  			//in case My Landmarks tab is completely empty (thus cannot be determined as being selected) -			menu_create_inventory_item(mLandmarksInventoryPanel->getRootFolder(), NULL, LLSD("category"),  +			menu_create_inventory_item(mLandmarksInventoryPanel, NULL,  LLSD("category"),   				gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));  			if (mMyLandmarksAccordionTab) @@ -834,9 +820,9 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const  	std::string command_name = userdata.asString();      if("copy_slurl" == command_name)  	{ -    	LLFolderViewItem* cur_item = getCurSelectedItem(); +    	LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  		if(cur_item) -			LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); +			LLLandmarkActions::copySLURLtoClipboard(cur_item->getUUID());  	}  	else if ( "paste" == command_name)  	{ @@ -848,7 +834,7 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const  	}  	else  	{ -		mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name); +		mCurrentSelectedList->doToSelected(command_name);  	}  } @@ -893,7 +879,7 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)  	{  		if(mCurrentSelectedList)  		{ -			mCurrentSelectedList->getRootFolder()->doToSelected(&gInventory, userdata); +			mCurrentSelectedList->doToSelected(userdata);  		}  	}  } @@ -915,8 +901,9 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  {  	std::string command_name = userdata.asString(); -	LLPlacesFolderView* root_folder_view = mCurrentSelectedList ? -		static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL; +	LLFolderView* root_folder_view = mCurrentSelectedList  +		? mCurrentSelectedList->getRootFolder()  +		: NULL;  	if ("collapse_all" == command_name)  	{ @@ -977,18 +964,13 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  	{  		if (!root_folder_view) return false; -		std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); +		std::set<LLFolderViewItem*> selected_uuids =    root_folder_view->getSelectionList();  		// Allow to execute the command only if it can be applied to all selected items. -		for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) +		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_uuids.begin(); iter != selected_uuids.end(); ++iter)  		{ -			LLFolderViewItem* item = root_folder_view->getItemByID(*iter); +			LLFolderViewItem* item = *iter; -			// If no item is found it might be a folder id. -			if (!item) -			{ -				item = root_folder_view->getFolderByID(*iter); -			}  			if (!item) return false;  			if (!canItemBeModified(command_name, item)) return false; @@ -1012,10 +994,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  		if ("show_on_map" == command_name)  		{ -			LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem(); +			LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem();  			if (!cur_item) return false; -			LLViewerInventoryItem* inv_item = cur_item->getInventoryItem(); +			LLViewerInventoryItem* inv_item = dynamic_cast<LLViewerInventoryItem*>(cur_item->getInventoryObject());  			if (!inv_item) return false;  			LLUUID asset_uuid = inv_item->getAssetUUID(); @@ -1049,7 +1031,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  	{  		if (mCurrentSelectedList)  		{ -			std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selection =    mCurrentSelectedList->getRootFolder()->getSelectionList();  			if (!selection.empty())  			{  				return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); @@ -1105,27 +1087,23 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param)  	{  		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); -		std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); +		std::set<LLFolderViewItem*> selected_items =    root_folder_view->getSelectionList();  		// Iterate through selected items to find out if any of these items are in Trash  		// or all the items are in Trash category. -		for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) +		for (std::set<LLFolderViewItem*>::const_iterator iter =    selected_items.begin(); iter != selected_items.end(); ++iter)  		{ -			LLFolderViewItem* item = root_folder_view->getItemByID(*iter); +			LLFolderViewItem* item = *iter;  			// If no item is found it might be a folder id. -			if (!item) -			{ -				item = root_folder_view->getFolderByID(*iter); -			}  			if (!item) continue; -			LLFolderViewEventListener* listenerp = item->getListener(); +			LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());  			if(!listenerp) continue;  			// Trash category itself should not be included because it can't be  			// actually restored from trash. -			are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id; +			are_all_items_in_trash &= listenerp->isItemInTrash() &&    listenerp->getUUID() != trash_id;  			// If there are any selected items in Trash including the Trash category itself  			// we show "Restore Item" in context menu and hide other irrelevant items. @@ -1164,7 +1142,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	bool can_be_modified = false;  	// landmarks can be modified in any other accordion... -	if (item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	if (static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem())->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  		can_be_modified = true; @@ -1202,7 +1180,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold  	if (can_be_modified)  	{ -		LLFolderViewEventListener* listenerp = item->getListener(); +		LLFolderViewModelItemInventory* listenerp = static_cast<LLFolderViewModelItemInventory*>(item->getViewModelItem());  		if ("cut" == command_name)  		{ @@ -1262,8 +1240,9 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg  				LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data);  				if (item)  				{ -					LLFolderViewItem* fv_item = (mCurrentSelectedList && mCurrentSelectedList->getRootFolder()) ? -						mCurrentSelectedList->getRootFolder()->getItemByID(item->getUUID()) : NULL; +					LLFolderViewItem* fv_item = mCurrentSelectedList +						? mCurrentSelectedList->getItemByID(item->getUUID()) +						: NULL;  					if (fv_item)  					{ @@ -1391,7 +1370,7 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)  static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)  {  	// When search is cleared, restore the old folder state. -	if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "") +	if (!inventory_list->getFilterSubString().empty() && string == "")  	{  		inventory_list->setFilterSubString(LLStringUtil::null);  		// Re-open folders that were open before @@ -1405,7 +1384,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin  	}  	// save current folder open state if no filter currently applied -	if (inventory_list->getRootFolder()->getFilterSubString().empty()) +	if (inventory_list->getFilterSubString().empty())  	{  		inventory_list->saveFolderState();  	} diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b2f4e92473..aa5f69739d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -44,6 +44,7 @@ class LLMenuGL;  class LLToggleableMenu;  class LLInventoryPanel;  class LLPlacesInventoryPanel; +class LLFolderViewModelItemInventory;  class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver  { @@ -87,6 +88,7 @@ protected:  	bool isReceivedFolderSelected() const;  	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);  	LLFolderViewItem* getCurSelectedItem() const; +	LLFolderViewModelItemInventory* getCurSelectedViewModelItem() const;  	/**  	 * Selects item with "obj_id" in "inventory_list" and scrolls accordion diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c11597f532..e1aa70cc4a 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -47,12 +47,14 @@  #include "llresmgr.h"  #include "llscrollcontainer.h"  #include "llsdserialize.h" +#include "llsdparam.h"  #include "llspinctrl.h"  #include "lltoggleablemenu.h"  #include "lltooldraganddrop.h"  #include "llviewermenu.h"  #include "llviewertexturelist.h"  #include "llsidepanelinventory.h" +#include "llfolderview.h"  const std::string FILTERS_FILENAME("filters.xml"); @@ -87,9 +89,9 @@ public:  	static void selectNoTypes(void* user_data);  private:  	LLPanelMainInventory*	mPanelMainInventory; -	LLSpinCtrl*			mSpinSinceDays; -	LLSpinCtrl*			mSpinSinceHours; -	LLInventoryFilter*	mFilter; +	LLSpinCtrl*				mSpinSinceDays; +	LLSpinCtrl*				mSpinSinceHours; +	LLInventoryFilter*		mFilter;  };  ///---------------------------------------------------------------------------- @@ -129,7 +131,7 @@ BOOL LLPanelMainInventory::postBuild()  	mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");  	mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); -	//panel->getFilter()->markDefault(); +	//panel->getFilter().markDefault();  	// Set up the default inv. panel/filter settings.  	mActivePanel = getChild<LLInventoryPanel>("All Items"); @@ -137,7 +139,7 @@ BOOL LLPanelMainInventory::postBuild()  	{  		// "All Items" is the previous only view, so it gets the InventorySortOrder  		mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); -		mActivePanel->getFilter()->markDefault(); +		mActivePanel->getFilter().markDefault();  		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);  		mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));  		mResortActivePanel = true; @@ -148,7 +150,7 @@ BOOL LLPanelMainInventory::postBuild()  		recent_items_panel->setSinceLogoff(TRUE);  		recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);  		recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -		recent_items_panel->getFilter()->markDefault(); +		recent_items_panel->getFilter().markDefault();  		recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));  	} @@ -167,11 +169,14 @@ BOOL LLPanelMainInventory::postBuild()  		// Note that the "All Items" settings do not persist.  		if(recent_items_panel)  		{ -			if(savedFilterState.has(recent_items_panel->getFilter()->getName())) +			if(savedFilterState.has(recent_items_panel->getFilter().getName()))  			{  				LLSD recent_items = savedFilterState.get( -					recent_items_panel->getFilter()->getName()); -				recent_items_panel->getFilter()->fromLLSD(recent_items); +					recent_items_panel->getFilter().getName()); +				LLInventoryFilter::Params p; +				LLParamSDParser parser; +				parser.readSD(recent_items, p); +				recent_items_panel->getFilter().fromParams(p);  			}  		} @@ -208,24 +213,28 @@ LLPanelMainInventory::~LLPanelMainInventory( void )  	LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");  	if (all_items_panel)  	{ -		LLInventoryFilter* filter = all_items_panel->getFilter(); -		if (filter) +		LLSD filterState; +		LLInventoryPanel::InventoryState p; +		all_items_panel->getFilter().toParams(p.filter); +		all_items_panel->getRootViewModel().getSorter().toParams(p.sort); +		if (p.validateBlock(false))  		{ -			LLSD filterState; -			filter->toLLSD(filterState); -			filterRoot[filter->getName()] = filterState; +			LLParamSDParser().writeSD(filterState, p); +			filterRoot[all_items_panel->getName()] = filterState;  		}  	} -	LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); -	if (recent_items_panel) +	LLInventoryPanel* panel = findChild<LLInventoryPanel>("Recent Items"); +	if (panel)  	{ -		LLInventoryFilter* filter = recent_items_panel->getFilter(); -		if (filter) +		LLSD filterState; +		LLInventoryPanel::InventoryState p; +		panel->getFilter().toParams(p.filter); +		panel->getRootViewModel().getSorter().toParams(p.sort); +		if (p.validateBlock(false))  		{ -			LLSD filterState; -			filter->toLLSD(filterState); -			filterRoot[filter->getName()] = filterState; +			LLParamSDParser().writeSD(filterState, p); +			filterRoot[panel->getName()] = filterState;  		}  	} @@ -285,7 +294,7 @@ BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask)  void LLPanelMainInventory::doToSelected(const LLSD& userdata)  { -	getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); +	getPanel()->doToSelected(userdata);  }  void LLPanelMainInventory::closeAllFolders() @@ -306,13 +315,13 @@ void LLPanelMainInventory::newWindow()  void LLPanelMainInventory::doCreate(const LLSD& userdata)  { -	menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); +	menu_create_inventory_item(getPanel(), NULL, userdata);  }  void LLPanelMainInventory::resetFilters()  {  	LLFloaterInventoryFinder *finder = getFinder(); -	getActivePanel()->getFilter()->resetDefault(); +	getActivePanel()->getFilter().resetDefault();  	if (finder)  	{  		finder->updateElementsFromFilter(); @@ -417,7 +426,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string )  	}  	// save current folder open state if no filter currently applied -	if (!mActivePanel->getRootFolder()->isFilterModified()) +	if (!mActivePanel->getFilter().isNotDefault())  	{  		mSavedFolderState->setApply(FALSE);  		mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -479,13 +488,13 @@ void LLPanelMainInventory::onFilterSelected()  	}  	setFilterSubString(mFilterSubString); -	LLInventoryFilter* filter = mActivePanel->getFilter(); +	LLInventoryFilter& filter = mActivePanel->getFilter();  	LLFloaterInventoryFinder *finder = getFinder();  	if (finder)  	{ -		finder->changeFilter(filter); +		finder->changeFilter(&filter);  	} -	if (filter->isActive()) +	if (filter.isActive())  	{  		// If our filter is active we may be the first thing requiring a fetch so we better start it here.  		LLInventoryModelBackgroundFetch::instance().start(); @@ -598,7 +607,7 @@ void LLPanelMainInventory::onFocusReceived()  void LLPanelMainInventory::setFilterTextFromFilter()   {  -	mFilterText = mActivePanel->getFilter()->getFilterText();  +	mFilterText = mActivePanel->getFilter().getFilterText();   }  void LLPanelMainInventory::toggleFindOptions() @@ -648,7 +657,7 @@ LLFloaterInventoryFinder* LLPanelMainInventory::getFinder()  LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :	  	LLFloater(LLSD()),  	mPanelMainInventory(inventory_view), -	mFilter(inventory_view->getPanel()->getFilter()) +	mFilter(&inventory_view->getPanel()->getFilter())  {  	buildFromFile("floater_inventory_view_finder.xml");  	updateElementsFromFilter(); @@ -961,7 +970,7 @@ void LLPanelMainInventory::onTrashButtonClick()  void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)  {  	std::string command_name = userdata.asString(); -	getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); +	getActivePanel()->doToSelected(command_name);  }  void LLPanelMainInventory::saveTexture(const LLSD& userdata) @@ -972,7 +981,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata)  		return;  	} -	const LLUUID& item_id = current_item->getListener()->getUUID(); +	const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  	LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);  	if (preview_texture)  	{ @@ -1045,7 +1054,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		const LLUUID item_id = current_item->getListener()->getUUID(); +		const LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item)  		{ @@ -1060,7 +1069,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		current_item->getListener()->performAction(getActivePanel()->getModel(), "goto"); +		static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto");  	}  	if (command_name == "find_links") @@ -1070,17 +1079,17 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)  		{  			return;  		} -		const LLUUID& item_id = current_item->getListener()->getUUID(); -		const std::string &item_name = current_item->getListener()->getName(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID(); +		const std::string &item_name = current_item->getViewModelItem()->getName();  		mFilterSubString = item_name; -		LLInventoryFilter *filter = mActivePanel->getFilter(); -		filter->setFilterSubString(item_name); +		LLInventoryFilter &filter = mActivePanel->getFilter(); +		filter.setFilterSubString(item_name);  		mFilterEditor->setText(item_name);  		mFilterEditor->setFocus(TRUE); -		filter->setFilterUUID(item_id); -		filter->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -		filter->setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS); +		filter.setFilterUUID(item_id); +		filter.setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); +		filter.setFilterLinks(LLInventoryFilter::FILTERLINK_ONLY_LINKS);  	}  } @@ -1089,11 +1098,11 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)  	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  	if (current_item)   	{ -		LLViewerInventoryItem *inv_item = current_item->getInventoryItem(); +		LLViewerInventoryItem *inv_item = dynamic_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryObject());  		if(inv_item)  		{  			bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); -			LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType(); +			LLInventoryType::EType curr_type = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryType();  			return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT);  		}  	} @@ -1110,15 +1119,14 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  		if (root)  		{  			can_delete = TRUE; -			std::set<LLUUID> selection_set = root->getSelectionList(); +			std::set<LLFolderViewItem*> selection_set = root->getSelectionList();  			if (selection_set.empty()) return FALSE; -			for (std::set<LLUUID>::iterator iter = selection_set.begin(); +			for (std::set<LLFolderViewItem*>::iterator iter =    selection_set.begin();  				 iter != selection_set.end();  				 ++iter)  			{ -				const LLUUID &item_id = (*iter); -				LLFolderViewItem *item = root->getItemByID(item_id); -				const LLFolderViewEventListener *listener = item->getListener(); +				LLFolderViewItem *item = *iter; +				const LLFolderViewModelItemInventory *listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem());  				llassert(listener);  				if (!listener) return FALSE;  				can_delete &= listener->isItemRemovable(); @@ -1136,7 +1144,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	{  		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item && item->getIsLinkType() && !item->getIsBrokenLink())  		{ @@ -1148,11 +1156,11 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	if (command_name == "find_links")  	{  		LLFolderView* root = getActivePanel()->getRootFolder(); -		std::set<LLUUID> selection_set = root->getSelectionList(); +		std::set<LLFolderViewItem*> selection_set = root->getSelectionList();  		if (selection_set.size() != 1) return FALSE;  		LLFolderViewItem* current_item = root->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLInventoryObject *obj = gInventory.getObject(item_id);  		if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType()))  		{ @@ -1165,7 +1173,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)  	{  		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();  		if (!current_item) return FALSE; -		const LLUUID& item_id = current_item->getListener()->getUUID(); +		const LLUUID& item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  		const LLViewerInventoryItem *item = gInventory.getItem(item_id);  		if (item && item->getIsBrokenLink())  		{ diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 66c9c323cb..ea0521e3a7 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -94,14 +94,14 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel()  	mInventoryPanel->setShape(inventory_placeholder_rect);  	// Set the sort order newest to oldest -	mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);	 -	mInventoryPanel->getFilter()->markDefault(); +	mInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_DATE); +	mInventoryPanel->getFilter().markDefault();  	// Set selection callback for proper update of inventory status buttons  	mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));  	// Set up the note to display when the inbox is empty -	mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems"); +	mInventoryPanel->getFilter().setEmptyLookupMessage("InventoryInboxNoItems");  	// Hide the placeholder text  	inbox_inventory_placeholder->setVisible(FALSE); @@ -139,7 +139,7 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const  	if (mInventoryPanel)  	{ -		const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); +		LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();  		if (inbox_folder)  		{ diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 678e4f2843..0d3fbe66d7 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -29,7 +29,8 @@  #include "llpanelmarketplaceinboxinventory.h"  #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -53,82 +54,17 @@ static LLDefaultChildRegistry::Register<LLInboxFolderViewItem> r3("inbox_folder_  //  LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p) -	: LLInventoryPanel(p) -{ -} +:	LLInventoryPanel(p) +{}  LLInboxInventoryPanel::~LLInboxInventoryPanel() -{ -} - -// virtual -void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	 -	LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); -	 -	// leslie -- temporary HACK to work around sim not creating inbox with proper system folder type -	if (root_id.isNull()) -	{ -		std::string start_folder_name(params.start_folder()); -		 -		LLInventoryModel::cat_array_t* cats; -		LLInventoryModel::item_array_t* items; -		 -		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); -		 -		if (cats) -		{ -			for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) -			{ -				LLInventoryCategory* cat = *cat_it; -				 -				if (cat->getName() == start_folder_name) -				{ -					root_id = cat->getUUID(); -					break; -				} -			} -		} -		 -		if (root_id == LLUUID::null) -		{ -			llwarns << "No category found that matches inbox inventory panel start_folder: " << start_folder_name << llendl; -		} -	} -	// leslie -- end temporary HACK -	 -	if (root_id == LLUUID::null) -	{ -		llwarns << "Inbox inventory panel has no root folder!" << llendl; -		root_id = LLUUID::generateNewID(); -	} -	 -	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -																	LLAssetType::AT_CATEGORY, -																	LLInventoryType::IT_CATEGORY, -																	this, -																	NULL, -																	root_id); -	 -	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} +{}  LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)  {  	LLInboxFolderViewFolder::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); -	 -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	  	params.root = mFolderRoot;  	params.listener = bridge;  	params.tool_tip = params.name; @@ -141,14 +77,6 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b  	LLInboxFolderViewItem::Params params;  	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -  	params.creation_date = bridge->getCreationDate();  	params.root = mFolderRoot;  	params.listener = bridge; @@ -163,9 +91,9 @@ LLFolderViewItem * LLInboxInventoryPanel::createFolderViewItem(LLInvFVBridge * b  //  LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p) -	: LLFolderViewFolder(p) -	, LLBadgeOwner(getHandle()) -	, mFresh(false) +:	LLFolderViewFolder(p), +	LLBadgeOwner(getHandle()), +	mFresh(false)  {  #if SUPPORTING_FRESH_ITEM_COUNT  	initBadgeParams(p.new_badge()); @@ -207,7 +135,7 @@ void LLInboxFolderViewFolder::computeFreshness()  	if (last_expansion_utc > 0)  	{ -		mFresh = (mCreationDate > last_expansion_utc); +		mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);  #if DEBUGGING_FRESHNESS  		if (mFresh) @@ -229,15 +157,16 @@ void LLInboxFolderViewFolder::deFreshify()  	gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());  } -void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) -{  -	mCreationDate = creation_date_utc;  - -	if (mParentFolder == mRoot) -	{ -		computeFreshness(); -	} -} +// TODO RN: move this behavior to modelview? +//void LLInboxFolderViewFolder::setCreationDate(time_t creation_date_utc) +//{  +//	mCreationDate = creation_date_utc;  +// +//	if (LLFolderViewItem::mParentFolder == mRoot) +//	{ +//		computeFreshness(); +//	} +//}  //  // LLInboxFolderViewItem Implementation @@ -253,9 +182,9 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p)  #endif  } -BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +void LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder)  { -	BOOL retval = LLFolderViewItem::addToFolder(folder, root); +	LLFolderViewItem::addToFolder(folder);  #if SUPPORTING_FRESH_ITEM_COUNT  	// Compute freshness if our parent is the root folder for the inbox @@ -264,8 +193,6 @@ BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView  		computeFreshness();  	}  #endif -	 -	return retval;  }  BOOL LLInboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -303,7 +230,7 @@ void LLInboxFolderViewItem::computeFreshness()  	if (last_expansion_utc > 0)  	{ -		mFresh = (mCreationDate > last_expansion_utc); +		mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);  #if DEBUGGING_FRESHNESS  		if (mFresh) diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d6b827ee3e..098969aca6 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -47,9 +47,6 @@ public:  	~LLInboxInventoryPanel();  	// virtual -	void buildFolderView(const LLInventoryPanel::Params& params); - -	// virtual  	LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge);  	LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge);  }; @@ -63,9 +60,8 @@ public:  		Optional<LLBadge::Params>	new_badge;  		Params() -		: new_badge("new_badge") -		{ -		} +		:	new_badge("new_badge") +		{}  	};  	LLInboxFolderViewFolder(const Params& p); @@ -81,8 +77,6 @@ public:  	bool isFresh() const { return mFresh; }  protected: -	void setCreationDate(time_t creation_date_utc); -  	bool mFresh;  }; @@ -95,14 +89,13 @@ public:  		Optional<LLBadge::Params>	new_badge;  		Params() -			: new_badge("new_badge") -		{ -		} +		:	new_badge("new_badge") +		{}  	};  	LLInboxFolderViewItem(const Params& p); -	BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); +	void addToFolder(LLFolderViewFolder* folder);  	BOOL handleDoubleClick(S32 x, S32 y, MASK mask);  	void draw(); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp deleted file mode 100644 index ff62cb23db..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**  - * @file llpanelmarketplaceoutboxinventory.cpp - * @brief LLOutboxInventoryPanel  class definition - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmarketplaceoutboxinventory.h" - -#include "llfolderview.h" -#include "llfoldervieweventlistener.h" -#include "llinventorybridge.h" -#include "llinventoryfunctions.h" -#include "llpanellandmarks.h" -#include "llplacesinventorybridge.h" -#include "lltrans.h" -#include "llviewerfoldertype.h" - - -// -// statics -// - -static LLDefaultChildRegistry::Register<LLOutboxInventoryPanel> r1("outbox_inventory_panel"); -static LLDefaultChildRegistry::Register<LLOutboxFolderViewFolder> r2("outbox_folder_view_folder"); - - -// -// LLOutboxInventoryPanel Implementation -// - -LLOutboxInventoryPanel::LLOutboxInventoryPanel(const LLOutboxInventoryPanel::Params& p) -	: LLInventoryPanel(p) -{ -} - -LLOutboxInventoryPanel::~LLOutboxInventoryPanel() -{ -} - -// virtual -void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	 -	LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); -	 -	if (root_id == LLUUID::null) -	{ -		llwarns << "Outbox inventory panel has no root folder!" << llendl; -		root_id = LLUUID::generateNewID(); -	} -	 -	LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -																	LLAssetType::AT_CATEGORY, -																	LLInventoryType::IT_CATEGORY, -																	this, -																	NULL, -																	root_id); -	 -	mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); -} - -LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) -{ -	LLOutboxFolderViewFolder::Params params; -	 -	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); -	 -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} -	 -	params.root = mFolderRoot; -	params.listener = bridge; -	params.tool_tip = params.name; -	 -	return LLUICtrlFactory::create<LLOutboxFolderViewFolder>(params); -} - -LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge) -{ -	LLFolderViewItem::Params params; - -	params.name = bridge->getDisplayName(); -	params.icon = bridge->getIcon(); -	params.icon_open = bridge->getOpenIcon(); - -	if (mShowItemLinkOverlays) // if false, then links show up just like normal items -	{ -		params.icon_overlay = LLUI::getUIImage("Inv_Link"); -	} - -	params.creation_date = bridge->getCreationDate(); -	params.root = mFolderRoot; -	params.listener = bridge; -	params.rect = LLRect (0, 0, 0, 0); -	params.tool_tip = params.name; - -	return LLUICtrlFactory::create<LLOutboxFolderViewItem>(params); -} - -// -// LLOutboxFolderViewFolder Implementation -// - -LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p) -	: LLFolderViewFolder(p) -{ -} - -// -// LLOutboxFolderViewItem Implementation -// - -LLOutboxFolderViewItem::LLOutboxFolderViewItem(const Params& p) -	: LLFolderViewItem(p) -{ -} - -BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask) -{ -	return TRUE; -} - -void LLOutboxFolderViewItem::openItem() -{ -	// Intentionally do nothing to block attaching items from the outbox -} - -// eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h deleted file mode 100644 index a6c522b7c2..0000000000 --- a/indra/newview/llpanelmarketplaceoutboxinventory.h +++ /dev/null @@ -1,78 +0,0 @@ -/**  - * @file llpanelmarketplaceoutboxinventory.h - * @brief LLOutboxInventoryPanel class declaration - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_OUTBOXINVENTORYPANEL_H -#define LL_OUTBOXINVENTORYPANEL_H - - -#include "llinventorypanel.h" -#include "llfolderviewitem.h" - - -class LLOutboxInventoryPanel : public LLInventoryPanel -{ -public: -	struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params> -	{ -		Params() {} -	}; -	 -	LLOutboxInventoryPanel(const Params& p); -	~LLOutboxInventoryPanel(); - -	// virtual -	void buildFolderView(const LLInventoryPanel::Params& params); - -	// virtual -	LLFolderViewFolder *	createFolderViewFolder(LLInvFVBridge * bridge); -	LLFolderViewItem *		createFolderViewItem(LLInvFVBridge * bridge); -}; - - -class LLOutboxFolderViewFolder : public LLFolderViewFolder -{ -public: -	struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> -	{ -		Params() {} -	}; -	 -	LLOutboxFolderViewFolder(const Params& p); -}; - - -class LLOutboxFolderViewItem : public LLFolderViewItem -{ -public: -	LLOutboxFolderViewItem(const Params& p); - -	// virtual -	BOOL handleDoubleClick(S32 x, S32 y, MASK mask); -	void openItem(); -}; - - -#endif //LL_OUTBOXINVENTORYPANEL_H diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1ca24f3031..82956beb3d 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -71,12 +71,13 @@  /// Class LLTaskInvFVBridge  ///---------------------------------------------------------------------------- -class LLTaskInvFVBridge : public LLFolderViewEventListener +class LLTaskInvFVBridge : public LLFolderViewModelItemInventory  {  protected:  	LLUUID mUUID;  	std::string mName;  	mutable std::string mDisplayName; +	mutable std::string mSearchableName;  	LLPanelObjectInventory* mPanel;  	U32 mFlags;  	LLAssetType::EType mAssetType;	 @@ -102,26 +103,29 @@ public:  	S32 getPrice();  	static bool commitBuyItem(const LLSD& notification, const LLSD& response); -	// LLFolderViewEventListener functionality +	// LLFolderViewModelItemInventory functionality  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const; +	virtual const std::string& getSearchableName() const; +  	virtual PermissionMask getPermissionMask() const { return PERM_NONE; }  	/*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; }  	virtual const LLUUID& getUUID() const { return mUUID; }  	virtual time_t getCreationDate() const; +	virtual void setCreationDate(time_t creation_date_utc); +  	virtual LLUIImagePtr getIcon() const;  	virtual void openItem();  	virtual BOOL canOpenItem() const { return FALSE; }  	virtual void closeItem() {} -	virtual void previewItem();  	virtual void selectItem() {}  	virtual BOOL isItemRenameable() const;  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL isItemMovable() const;  	virtual BOOL isItemRemovable() const;  	virtual BOOL removeItem(); -	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); -	virtual void move(LLFolderViewEventListener* parent_listener); +	virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); +	virtual void move(LLFolderViewModelItem* parent_listener);	  	virtual BOOL isItemCopyable() const;  	virtual BOOL copyToClipboard() const;  	virtual BOOL cutToClipboard() const; @@ -131,11 +135,15 @@ public:  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags);  	virtual void performAction(LLInventoryModel* model, std::string action);  	virtual BOOL isUpToDate() const { return TRUE; } -	virtual BOOL hasChildren() const { return FALSE; } +	virtual bool hasChildren() const { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }  	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +	virtual EInventorySortGroup getSortGroup() const { return SG_ITEM; } +	virtual LLInventoryObject* getInventoryObject() const { return findInvObject(); } +  	// LLDragAndDropBridge functionality +	virtual LLToolDragAndDrop::ESource getDragSource() const { return LLToolDragAndDrop::SOURCE_WORLD; }  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -147,7 +155,8 @@ LLTaskInvFVBridge::LLTaskInvFVBridge(  	LLPanelObjectInventory* panel,  	const LLUUID& uuid,  	const std::string& name, -	U32 flags): +	U32 flags) +:	LLFolderViewModelItemInventory(panel->getRootViewModel()),  	mUUID(uuid),  	mName(name),  	mPanel(panel), @@ -330,15 +339,27 @@ const std::string& LLTaskInvFVBridge::getDisplayName() const  		}  	} +	mSearchableName.assign(mDisplayName + getLabelSuffix()); +  	return mDisplayName;  } +const std::string& LLTaskInvFVBridge::getSearchableName() const +{ +	return mSearchableName; +} + +  // BUG: No creation dates for task inventory  time_t LLTaskInvFVBridge::getCreationDate() const  {  	return 0;  } +void LLTaskInvFVBridge::setCreationDate(time_t creation_date_utc) +{} + +  LLUIImagePtr LLTaskInvFVBridge::getIcon() const  {  	const BOOL item_is_multi = (mFlags & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS); @@ -352,11 +373,6 @@ void LLTaskInvFVBridge::openItem()  	lldebugs << "LLTaskInvFVBridge::openItem()" << llendl;  } -void LLTaskInvFVBridge::previewItem() -{ -	openItem(); -} -  BOOL LLTaskInvFVBridge::isItemRenameable() const  {  	if(gAgent.isGodlike()) return TRUE; @@ -467,7 +483,7 @@ BOOL LLTaskInvFVBridge::removeItem()  	return FALSE;  } -void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void   LLTaskInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch)  {  	if (!mPanel)  	{ @@ -507,7 +523,7 @@ void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>&  	}  } -void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener) +void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener)  {  } @@ -709,7 +725,7 @@ public:  	virtual BOOL renameItem(const std::string& new_name);  	virtual BOOL isItemRemovable() const;  	virtual void buildContextMenu(LLMenuGL& menu, U32 flags); -	virtual BOOL hasChildren() const; +	virtual bool hasChildren() const;  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop,  							EDragAndDropType cargo_type, @@ -717,6 +733,7 @@ public:  							std::string& tooltip_msg);  	virtual BOOL canOpenItem() const { return TRUE; }  	virtual void openItem(); +	virtual EInventorySortGroup getSortGroup() const { return SG_NORMAL_FOLDER; }  };  LLTaskCategoryBridge::LLTaskCategoryBridge( @@ -739,15 +756,7 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const  	if (cat)  	{ -		// Localize "Contents" folder. -		if (cat->getParentUUID().isNull() && cat->getName() == "Contents") -		{ -			mDisplayName.assign(LLTrans::getString("ViewerObjectContents")); -		} -		else -		{ -			mDisplayName.assign(cat->getName()); -		} +		mDisplayName.assign(cat->getName());  	}  	return mDisplayName; @@ -775,7 +784,7 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	hide_context_entries(menu, items, disabled_items);  } -BOOL LLTaskCategoryBridge::hasChildren() const +bool LLTaskCategoryBridge::hasChildren() const  {  	// return TRUE if we have or do know know if we have children.  	// *FIX: For now, return FALSE - we will know for sure soon enough. @@ -1514,7 +1523,7 @@ BOOL LLPanelObjectInventory::postBuild()  void LLPanelObjectInventory::doToSelected(const LLSD& userdata)  { -	mFolders->doToSelected(&gInventory, userdata); +	LLInventoryAction::doToSelected(&gInventory, mFolders, userdata.asString());  }  void LLPanelObjectInventory::clearContents() @@ -1526,6 +1535,8 @@ void LLPanelObjectInventory::clearContents()  		LLToolDragAndDrop::getInstance()->endDrag();  	} +	clearItemIDs(); +  	if( mScroller )  	{  		// removes mFolders @@ -1541,21 +1552,24 @@ void LLPanelObjectInventory::reset()  {  	clearContents(); -	//setBorderVisible(FALSE); -	  	mCommitCallbackRegistrar.pushScope(); // push local callbacks  	LLRect dummy_rect(0, 1, 1, 0);  	LLFolderView::Params p;  	p.name = "task inventory";  	p.title = "task inventory"; -	p.task_id = getTaskUUID();  	p.parent_panel = this;  	p.tool_tip= LLTrans::getString("PanelContentsTooltip");  	p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); +	p.folder_indentation = -14; // subtract space normally reserved for folder expanders +	p.view_model = &mInventoryViewModel; +	p.root = NULL;  	mFolders = LLUICtrlFactory::create<LLFolderView>(p);  	// this ensures that we never say "searching..." or "no items found" -	mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); +	//TODO RN: make this happen by manipulating filter object directly +  	LLInventoryFilter& inventoryFilter = dynamic_cast<LLInventoryFilter&>(mFolders->getFolderViewModel()->getFilter()); +   	inventoryFilter.setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); +    	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);  	if (hasFocus()) @@ -1600,7 +1614,7 @@ void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object,  			 iter != inventory->end(); )  		{  			LLInventoryObject* item = *iter++; -			LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properites", item->getUUID()); +			LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properties", item->getUUID());  			if(floater)  			{  				floater->refresh(); @@ -1615,15 +1629,20 @@ void LLPanelObjectInventory::updateInventory()  	//		<< " panel UUID: " << panel->mTaskUUID << "\n"  	//		<< " task  UUID: " << object->mID << llendl;  	// We're still interested in this task's inventory. -	std::set<LLUUID> selected_items; +	std::vector<LLUUID> selected_item_ids; +	std::set<LLFolderViewItem*> selected_items;  	BOOL inventory_has_focus = FALSE; -	if (mHaveInventory) +	if (mHaveInventory && mFolders)  	{  		selected_items = mFolders->getSelectionList();  		inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders);  	} - -	reset(); +	for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(), end_it = selected_items.end(); +		it != end_it; +		++it) +	{ +		selected_item_ids.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +	}  	LLViewerObject* objectp = gObjectList.findObject(mTaskUUID);  	if (objectp) @@ -1631,19 +1650,21 @@ void LLPanelObjectInventory::updateInventory()  		LLInventoryObject* inventory_root = objectp->getInventoryRoot();  		LLInventoryObject::object_list_t contents;  		objectp->getInventoryContents(contents); +  		if (inventory_root)  		{ -			createFolderViews(inventory_root, contents); -			mHaveInventory = TRUE; +			reset();  			mIsInventoryEmpty = FALSE; +			createFolderViews(inventory_root, contents);  			mFolders->setEnabled(TRUE);  		}  		else  		{  			// TODO: create an empty inventory  			mIsInventoryEmpty = TRUE; -			mHaveInventory = TRUE;  		} + +		mHaveInventory = TRUE;  	}  	else  	{ @@ -1653,11 +1674,12 @@ void LLPanelObjectInventory::updateInventory()  	}  	// restore previous selection -	std::set<LLUUID>::iterator selection_it; -	BOOL first_item = TRUE; -	for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) +	std::vector<LLUUID>::iterator selection_it; +	bool first_item = true; +	for (selection_it = selected_item_ids.begin(); selection_it != selected_item_ids.end(); ++selection_it)  	{ -		LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); +		LLFolderViewItem* selected_item = getItemByID(*selection_it); +		  		if (selected_item)  		{  			//HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1673,7 +1695,10 @@ void LLPanelObjectInventory::updateInventory()  		}  	} -	mFolders->requestArrange(); +	if (mFolders) +	{ +		mFolders->requestArrange(); +	}  	mInventoryNeedsUpdate = FALSE;  	// Edit menu handler is set in onFocusReceived  } @@ -1694,19 +1719,20 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root  	bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);  	if(bridge)  	{ -		LLFolderViewFolder* new_folder = NULL;  		LLFolderViewFolder::Params p;  		p.name = inventory_root->getName(); -		p.icon = LLUI::getUIImage("Inv_FolderClosed"); -		p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); +		p.tool_tip = p.name;  		p.root = mFolders;  		p.listener = bridge; -		p.tool_tip = p.name; -		new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); -		new_folder->addToFolder(mFolders, mFolders); + +		LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); +		new_folder->addToFolder(mFolders);  		new_folder->toggleOpen(); -		createViewsForCategory(&contents, inventory_root, new_folder); +		if (!contents.empty()) +		{ +			createViewsForCategory(&contents, inventory_root, new_folder); +		}  	}  } @@ -1738,8 +1764,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  			{  				LLFolderViewFolder::Params p;  				p.name = obj->getName(); -				p.icon = LLUI::getUIImage("Inv_FolderClosed"); -				p.icon_open = LLUI::getUIImage("Inv_FolderOpen");  				p.root = mFolders;  				p.listener = bridge;  				p.tool_tip = p.name; @@ -1751,7 +1775,6 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  			{  				LLFolderViewItem::Params params;  				params.name(obj->getName()); -				params.icon(bridge->getIcon());  				params.creation_date(bridge->getCreationDate());  				params.root(mFolders);  				params.listener(bridge); @@ -1759,7 +1782,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li  				params.tool_tip = params.name;  				view = LLUICtrlFactory::create<LLFolderViewItem> (params);  			} -			view->addToFolder(folder, mFolders); +			view->addToFolder(folder); +			addItemID(obj->getUUID(), view);  		}  	} @@ -1827,6 +1851,7 @@ void LLPanelObjectInventory::refresh()  		removeVOInventoryListener();  		clearContents();  	} +	mInventoryViewModel.setTaskID(mTaskUUID);  	//llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl;  } @@ -1914,7 +1939,10 @@ void LLPanelObjectInventory::idle(void* user_data)  {  	LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data; - +	if (self->mFolders) +	{ +		self->mFolders->update(); +	}  	if (self->mInventoryNeedsUpdate)  	{  		self->updateInventory(); @@ -1939,3 +1967,32 @@ void LLPanelObjectInventory::onFocusReceived()  	LLPanel::onFocusReceived();  } + + +LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id ) +{ +	std::map<LLUUID, LLFolderViewItem*>::iterator map_it; +	map_it = mItemMap.find(id); +	if (map_it != mItemMap.end()) +	{ +		return map_it->second; +	} + +	return NULL; +} + +void LLPanelObjectInventory::removeItemID( const LLUUID& id ) +{ +	mItemMap.erase(id); +} + +void LLPanelObjectInventory::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ +	mItemMap[id] = itemp; +} + +void LLPanelObjectInventory::clearItemIDs() +{ +	mItemMap.clear(); +} + diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 607b705f7f..f497c695b3 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -29,6 +29,7 @@  #include "llvoinventorylistener.h"  #include "llpanel.h" +#include "llinventorypanel.h" // for LLFolderViewModelInventory  #include "llinventory.h" @@ -55,6 +56,8 @@ public:  	virtual BOOL postBuild(); +	LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; } +  	void doToSelected(const LLSD& userdata);  	void refresh(); @@ -85,8 +88,15 @@ protected:  								LLInventoryObject* parent,  								LLFolderViewFolder* folder);  	void clearContents(); +	LLFolderViewItem* getItemByID(const LLUUID& id); + +	void addItemID( const LLUUID& id, LLFolderViewItem*   itemp ); +	void removeItemID(const LLUUID& id); +	void clearItemIDs();  private: +	std::map<LLUUID, LLFolderViewItem*> mItemMap; +  	LLScrollContainer* mScroller;  	LLFolderView* mFolders; @@ -94,6 +104,7 @@ private:  	BOOL mHaveInventory;  	BOOL mIsInventoryEmpty;  	BOOL mInventoryNeedsUpdate; +	LLFolderViewModelInventory	mInventoryViewModel;	  };  #endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..d690a18477 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -270,7 +270,7 @@ private:  		if (inventory_panel->getVisible())  		{ -			inventory_panel->setSortOrder(sort_order); +			inventory_panel->getFolderViewModel()->setSorter(sort_order);  		}  		else  		{ @@ -738,7 +738,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string)  	}  	// save current folder open state if no filter currently applied -	if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty()) +	if (mInventoryItemsPanel->getFilterSubString().empty())  	{  		mSavedFolderState->setApply(FALSE);  		mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -885,13 +885,13 @@ LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionT  	{  		if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible())  		{ -			std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selected_items =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); -			result.second = selected_uuids.size(); +			result.second = selected_items.size();  			if (result.second == 1)  			{ -				result.first = getWearableTypeByItemUUID(*(selected_uuids.begin())); +				result.first = getWearableTypeByItemUUID(static_cast<LLFolderViewModelItemInventory*>((*selected_items.begin())->getViewModelItem())->getUUID());  			}  		}  		else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id)  		LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem();  		if (!curr_item) return; -		LLFolderViewEventListener* listenerp  = curr_item->getListener(); +		LLFolderViewModelItemInventory* listenerp  = static_cast<LLFolderViewModelItemInventory*>(curr_item->getViewModelItem());  		if (!listenerp) return;  		selected_id = listenerp->getUUID(); @@ -1327,9 +1327,13 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)  	void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back;  	if (mInventoryItemsPanel->getVisible())  	{ -		std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - -		std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1)); +		std::set<LLFolderViewItem*> item_set =    mInventoryItemsPanel->getRootFolder()->getSelectionList(); +		for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(),    end_it = item_set.end(); +			it != end_it; +			++it) +		{ +			uuid_list.push_back(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +		}  	}  	else if (mWearablesListViewPanel->getVisible())  	{ @@ -1374,13 +1378,13 @@ void LLPanelOutfitEdit::saveListSelection()  {  	if(mWearablesListViewPanel->getVisible())  	{ -		std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); +		std::set<LLFolderViewItem*> selected_ids =    mInventoryItemsPanel->getRootFolder()->getSelectionList();  		if(!selected_ids.size()) return; -		for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) +		for (std::set<LLFolderViewItem*>::const_iterator item_id =    selected_ids.begin(); item_id != selected_ids.end(); ++item_id)  		{ -			mWearableItemsList->selectItemByUUID(*item_id, true); +			mWearableItemsList->selectItemByUUID(static_cast<LLFolderViewModelItemInventory*>((*item_id)->getViewModelItem())->getUUID(),    true);  		}  		mWearableItemsList->scrollToShowFirstSelectedItem();  	} @@ -1398,7 +1402,7 @@ void LLPanelOutfitEdit::saveListSelection()  		for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id)  		{ -			LLFolderViewItem* item = root->getItemByID(*item_id); +			LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id);  			if (!item) continue;  			LLFolderViewFolder* parent = item->getParentFolder(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f1380e7a36..260de40eef 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -72,6 +72,7 @@ static const std::string NEARBY_TAB_NAME	= "nearby_panel";  static const std::string FRIENDS_TAB_NAME	= "friends_panel";  static const std::string GROUP_TAB_NAME		= "groups_panel";  static const std::string RECENT_TAB_NAME	= "recent_panel"; +static const std::string BLOCKED_TAB_NAME	= "blocked_panel"; // blocked avatars  static const std::string COLLAPSED_BY_USER  = "collapsed_by_user"; @@ -492,26 +493,37 @@ public:  LLPanelPeople::LLPanelPeople()  	:	LLPanel(), -		mFilterSubString(LLStringUtil::null), -		mFilterSubStringOrig(LLStringUtil::null), -		mFilterEditor(NULL),  		mTabContainer(NULL),  		mOnlineFriendList(NULL),  		mAllFriendList(NULL),  		mNearbyList(NULL),  		mRecentList(NULL),  		mGroupList(NULL), -		mNearbyGearButton(NULL), -		mFriendsGearButton(NULL), -		mGroupsGearButton(NULL), -		mRecentGearButton(NULL),  		mMiniMap(NULL)  {  	mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList,	this));  	mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList,	this));  	mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList,	this));  	mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this)); -	mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + +	mCommitCallbackRegistrar.add("People.AddFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); +	mCommitCallbackRegistrar.add("People.AddFriendWizard",	boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked,	this)); +	mCommitCallbackRegistrar.add("People.DelFriend",		boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this)); +	mCommitCallbackRegistrar.add("People.Group.Minus",		boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this)); +	mCommitCallbackRegistrar.add("People.Chat",			boost::bind(&LLPanelPeople::onChatButtonClicked,		this)); +	mCommitCallbackRegistrar.add("People.Gear",			boost::bind(&LLPanelPeople::onGearButtonClicked,		this, _1)); + +	mCommitCallbackRegistrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); + +	mEnableCallbackRegistrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2)); +	mEnableCallbackRegistrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2)); +	mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); + +	mEnableCallbackRegistrar.add("People.Group.Plus.Validate",	boost::bind(&LLPanelPeople::onGroupPlusButtonValidate,	this));  }  LLPanelPeople::~LLPanelPeople() @@ -525,13 +537,6 @@ LLPanelPeople::~LLPanelPeople()  	{  		LLVoiceClient::getInstance()->removeObserver(this);  	} - -	if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); -	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); -	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); -	if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); -	if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); -  }  void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list) @@ -553,11 +558,15 @@ void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LL  BOOL LLPanelPeople::postBuild()  { -	mFilterEditor = getChild<LLFilterEditor>("filter_input"); -	mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	mTabContainer = getChild<LLTabContainer>("tabs");  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); +	mSavedFilters.resize(mTabContainer->getTabCount()); +	mSavedOriginalFilters.resize(mTabContainer->getTabCount());  	LLPanel* friends_tab = getChild<LLPanel>(FRIENDS_TAB_NAME);  	// updater is active only if panel is visible to user. @@ -601,14 +610,6 @@ BOOL LLPanelPeople::postBuild()  	setSortOrder(mAllFriendList,	(ESortOrder)gSavedSettings.getU32("FriendsSortOrder"),		false);  	setSortOrder(mNearbyList,		(ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"),	false); -	LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME); -	groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked,	this)); -	groups_panel->childSetAction("plus_btn",	boost::bind(&LLPanelPeople::onGroupPlusButtonClicked,	this)); - -	LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME); -	friends_panel->childSetAction("add_btn",	boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked,	this)); -	friends_panel->childSetAction("del_btn",	boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this)); -  	mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));  	mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));  	mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); @@ -629,6 +630,19 @@ BOOL LLPanelPeople::postBuild()  	mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));  	mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this)); +	LLMenuButton* groups_gear_btn = getChild<LLMenuButton>("groups_gear_btn"); + +	// Use the context menu of the Groups list for the Groups tab gear menu. +	LLToggleableMenu* groups_gear_menu = mGroupList->getContextMenu(); +	if (groups_gear_menu) +	{ +		groups_gear_btn->setMenu(groups_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} +	else +	{ +		llwarns << "People->Groups list menu not found" << llendl; +	} +  	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");  	accordion_tab->setDropDownStateChangedCallback(  		boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mAllFriendList)); @@ -637,70 +651,9 @@ BOOL LLPanelPeople::postBuild()  	accordion_tab->setDropDownStateChangedCallback(  		boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList)); -	buttonSetAction("view_profile_btn",	boost::bind(&LLPanelPeople::onViewProfileButtonClicked,	this)); -	buttonSetAction("group_info_btn",	boost::bind(&LLPanelPeople::onGroupInfoButtonClicked,	this)); -	buttonSetAction("chat_btn",			boost::bind(&LLPanelPeople::onChatButtonClicked,		this)); -	buttonSetAction("im_btn",			boost::bind(&LLPanelPeople::onImButtonClicked,			this)); -	buttonSetAction("call_btn",			boost::bind(&LLPanelPeople::onCallButtonClicked,		this)); -	buttonSetAction("group_call_btn",	boost::bind(&LLPanelPeople::onGroupCallButtonClicked,	this)); -	buttonSetAction("teleport_btn",		boost::bind(&LLPanelPeople::onTeleportButtonClicked,	this)); -	buttonSetAction("share_btn",		boost::bind(&LLPanelPeople::onShareButtonClicked,		this)); -  	// Must go after setting commit callback and initializing all pointers to children.  	mTabContainer->selectTabByName(NEARBY_TAB_NAME); -	// Create menus. -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -	 -	registrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2)); -	registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this)); -	registrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); - -	enable_registrar.add("People.Group.Minus.Enable",	boost::bind(&LLPanelPeople::isRealGroup,	this)); -	enable_registrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2)); -	enable_registrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2)); -	enable_registrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); - -	mNearbyGearButton = getChild<LLMenuButton>("nearby_view_sort_btn"); -	mFriendsGearButton = getChild<LLMenuButton>("friends_viewsort_btn"); -	mGroupsGearButton = getChild<LLMenuButton>("groups_viewsort_btn"); -	mRecentGearButton = getChild<LLMenuButton>("recent_viewsort_btn"); - -	LLMenuGL* plus_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mGroupPlusMenuHandle  = plus_menu->getHandle(); - -	LLToggleableMenu* nearby_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_nearby_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(nearby_view_sort) -	{ -		mNearbyViewSortMenuHandle  = nearby_view_sort->getHandle(); -		mNearbyGearButton->setMenu(nearby_view_sort); -	} - -	LLToggleableMenu* friend_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_friends_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(friend_view_sort) -	{ -		mFriendsViewSortMenuHandle  = friend_view_sort->getHandle(); -		mFriendsGearButton->setMenu(friend_view_sort); -	} - -	LLToggleableMenu* group_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(group_view_sort) -	{ -		mGroupsViewSortMenuHandle  = group_view_sort->getHandle(); -		mGroupsGearButton->setMenu(group_view_sort); -	} - -	LLToggleableMenu* recent_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_recent_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(recent_view_sort) -	{ -		mRecentViewSortMenuHandle  = recent_view_sort->getHandle(); -		mRecentGearButton->setMenu(recent_view_sort); -	} -  	LLVoiceClient::getInstance()->addObserver(this);  	// call this method in case some list is empty and buttons can be in inconsistent state @@ -735,9 +688,11 @@ void LLPanelPeople::updateFriendListHelpText()  	if (no_friends_text->getVisible())  	{  		//update help text for empty lists -		std::string message_name = mFilterSubString.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; +		const std::string& filter = mSavedOriginalFilters[mTabContainer->getCurrentPanelIndex()]; + +		std::string message_name = filter.empty() ? "no_friends_msg" : "no_filtered_friends_msg";  		LLStringUtil::format_map_t args; -		args["[SEARCH_TERM]"] = LLURI::escape(mFilterSubStringOrig); +		args["[SEARCH_TERM]"] = LLURI::escape(filter);  		no_friends_text->setText(getString(message_name, args));  	}  } @@ -821,31 +776,9 @@ void LLPanelPeople::updateRecentList()  	mRecentList->setDirty();  } -void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setVisible(visible); -} - -void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setEnabled(enabled); -} - -void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setClickedCallback(cb); -} -  void LLPanelPeople::updateButtons()  {  	std::string cur_tab		= getActiveTabName(); -	bool nearby_tab_active	= (cur_tab == NEARBY_TAB_NAME);  	bool friends_tab_active = (cur_tab == FRIENDS_TAB_NAME);  	bool group_tab_active	= (cur_tab == GROUP_TAB_NAME);  	//bool recent_tab_active	= (cur_tab == RECENT_TAB_NAME); @@ -856,28 +789,15 @@ void LLPanelPeople::updateButtons()  	bool item_selected = (selected_uuids.size() == 1);  	bool multiple_selected = (selected_uuids.size() >= 1); -	buttonSetVisible("group_info_btn",		group_tab_active); -	buttonSetVisible("chat_btn",			group_tab_active); -	buttonSetVisible("view_profile_btn",	!group_tab_active); -	buttonSetVisible("im_btn",				!group_tab_active); -	buttonSetVisible("call_btn",			!group_tab_active); -	buttonSetVisible("group_call_btn",		group_tab_active); -	buttonSetVisible("teleport_btn",		friends_tab_active); -	buttonSetVisible("share_btn",			nearby_tab_active || friends_tab_active); -  	if (group_tab_active)  	{ -		bool cur_group_active = true; -  		if (item_selected)  		{  			selected_id = mGroupList->getSelectedUUID(); -			cur_group_active = (gAgent.getGroupID() == selected_id);  		}  		LLPanel* groups_panel = mTabContainer->getCurrentPanel(); -		groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected -		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); +		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected  	}  	else  	{ @@ -893,26 +813,20 @@ void LLPanelPeople::updateButtons()  		LLPanel* cur_panel = mTabContainer->getCurrentPanel();  		if (cur_panel)  		{ -			cur_panel->getChildView("add_friend_btn")->setEnabled(!is_friend); +			if (cur_panel->hasChild("add_friend_btn", TRUE)) +				cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend); +  			if (friends_tab_active)  			{ -				cur_panel->getChildView("del_btn")->setEnabled(multiple_selected); +				cur_panel->getChildView("friends_del_btn")->setEnabled(multiple_selected); +			} + +			if (!group_tab_active) +			{ +				cur_panel->getChildView("gear_btn")->setEnabled(multiple_selected);  			}  		}  	} - -	bool enable_calls = LLVoiceClient::getInstance()->isVoiceWorking() && LLVoiceClient::getInstance()->voiceEnabled(); - -	buttonSetEnabled("view_profile_btn",item_selected); -	buttonSetEnabled("share_btn",		item_selected); -	buttonSetEnabled("im_btn",			multiple_selected); // allow starting the friends conference for multiple selection -	buttonSetEnabled("call_btn",		multiple_selected && enable_calls); -	buttonSetEnabled("teleport_btn",	multiple_selected && LLAvatarActions::canOfferTeleport(selected_uuids)); - -	bool none_group_selected = item_selected && selected_id.isNull(); -	buttonSetEnabled("group_info_btn", !none_group_selected); -	buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls); -	buttonSetEnabled("chat_btn", !none_group_selected);  }  std::string LLPanelPeople::getActiveTabName() const @@ -943,6 +857,9 @@ LLUUID LLPanelPeople::getCurrentItemID() const  	if (cur_tab == GROUP_TAB_NAME)  		return mGroupList->getSelectedUUID(); +	if (cur_tab == BLOCKED_TAB_NAME) +		return LLUUID::null; // FIXME? +  	llassert(0 && "unknown tab selected");  	return LLUUID::null;  } @@ -963,6 +880,8 @@ void LLPanelPeople::getCurrentItemIDs(uuid_vec_t& selected_uuids) const  		mRecentList->getSelectedUUIDs(selected_uuids);  	else if (cur_tab == GROUP_TAB_NAME)  		mGroupList->getSelectedUUIDs(selected_uuids); +	else if (cur_tab == BLOCKED_TAB_NAME) +		selected_uuids.clear(); // FIXME?  	else  		llassert(0 && "unknown tab selected"); @@ -1031,49 +950,60 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save  	}  } -bool LLPanelPeople::isRealGroup() -{ -	return getCurrentItemID() != LLUUID::null; -} -  void LLPanelPeople::onFilterEdit(const std::string& search_string)  { -	mFilterSubStringOrig = search_string; -	LLStringUtil::trimHead(mFilterSubStringOrig); +	const S32 cur_tab_idx = mTabContainer->getCurrentPanelIndex(); +	std::string& filter = mSavedOriginalFilters[cur_tab_idx]; +	std::string& saved_filter = mSavedFilters[cur_tab_idx]; + +	filter = search_string; +	LLStringUtil::trimHead(filter); +  	// Searches are case-insensitive -	std::string search_upper = mFilterSubStringOrig; +	std::string search_upper = filter;  	LLStringUtil::toUpper(search_upper); -	if (mFilterSubString == search_upper) +	if (saved_filter == search_upper)  		return; -	mFilterSubString = search_upper; +	saved_filter = search_upper; -	//store accordion tabs state before any manipulation with accordion tabs -	if(!mFilterSubString.empty()) +	// Apply new filter to the current tab. +	const std::string cur_tab = getActiveTabName(); +	if (cur_tab == NEARBY_TAB_NAME) +	{ +		mNearbyList->setNameFilter(filter); +	} +	else if (cur_tab == FRIENDS_TAB_NAME) +	{ +		// store accordion tabs opened/closed state before any manipulation with accordion tabs +		if (!saved_filter.empty())  	{  		notifyChildren(LLSD().with("action","store_state"));  	} - -	// Apply new filter. -	mNearbyList->setNameFilter(mFilterSubStringOrig); -	mOnlineFriendList->setNameFilter(mFilterSubStringOrig); -	mAllFriendList->setNameFilter(mFilterSubStringOrig); -	mRecentList->setNameFilter(mFilterSubStringOrig); -	mGroupList->setNameFilter(mFilterSubStringOrig); +		mOnlineFriendList->setNameFilter(filter); +		mAllFriendList->setNameFilter(filter);  	setAccordionCollapsedByUser("tab_online", false);  	setAccordionCollapsedByUser("tab_all", false); -  	showFriendsAccordionsIfNeeded(); -	//restore accordion tabs state _after_ all manipulations... -	if(mFilterSubString.empty()) +		// restore accordion tabs state _after_ all manipulations +		if(saved_filter.empty())  	{  		notifyChildren(LLSD().with("action","restore_state"));  	}  } +	else if (cur_tab == GROUP_TAB_NAME) +	{ +		mGroupList->setNameFilter(filter); +	} +	else if (cur_tab == RECENT_TAB_NAME) +	{ +		mRecentList->setNameFilter(filter); +	} +}  void LLPanelPeople::onTabSelected(const LLSD& param)  { @@ -1081,11 +1011,6 @@ void LLPanelPeople::onTabSelected(const LLSD& param)  	updateButtons();  	showFriendsAccordionsIfNeeded(); - -	if (GROUP_TAB_NAME == tab_name) -		mFilterEditor->setLabel(getString("groups_filter_label")); -	else -		mFilterEditor->setLabel(getString("people_filter_label"));  }  void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl) @@ -1127,12 +1052,6 @@ void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)  	updateButtons();  } -void LLPanelPeople::onViewProfileButtonClicked() -{ -	LLUUID id = getCurrentItemID(); -	LLAvatarActions::showProfile(id); -} -  void LLPanelPeople::onAddFriendButtonClicked()  {  	LLUUID id = getCurrentItemID(); @@ -1191,11 +1110,6 @@ void LLPanelPeople::onDeleteFriendButtonClicked()  	}  } -void LLPanelPeople::onGroupInfoButtonClicked() -{ -	LLGroupActions::show(getCurrentItemID()); -} -  void LLPanelPeople::onChatButtonClicked()  {  	LLUUID group_id = getCurrentItemID(); @@ -1203,6 +1117,14 @@ void LLPanelPeople::onChatButtonClicked()  		LLGroupActions::startIM(group_id);  } +void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn) +{ +	uuid_vec_t selected_uuids; +	getCurrentItemIDs(selected_uuids); +	// Spawn at bottom left corner of the button. +	LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0); +} +  void LLPanelPeople::onImButtonClicked()  {  	uuid_vec_t selected_uuids; @@ -1219,11 +1141,6 @@ void LLPanelPeople::onImButtonClicked()  	}  } -void LLPanelPeople::onActivateButtonClicked() -{ -	LLGroupActions::activate(mGroupList->getSelectedUUID()); -} -  // static  void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)  { @@ -1231,19 +1148,15 @@ void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAv  		LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName());  } -void LLPanelPeople::onGroupPlusButtonClicked() +bool LLPanelPeople::onGroupPlusButtonValidate()  {  	if (!gAgent.canJoinGroups())  	{  		LLNotificationsUtil::add("JoinedTooManyGroups"); -		return; +		return false;  	} -	LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); -	if (!plus_menu) -		return; - -	showGroupMenu(plus_menu); +	return true;  }  void LLPanelPeople::onGroupMinusButtonClicked() @@ -1288,10 +1201,6 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)  		mAllFriendList->showPermissions(show_permissions);  		mOnlineFriendList->showPermissions(show_permissions);  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) @@ -1324,10 +1233,6 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)  	{  		setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) @@ -1361,10 +1266,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)  	{  		mRecentList->toggleIcons();  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata)  @@ -1393,40 +1294,6 @@ bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata)  	return false;  } -void LLPanelPeople::onCallButtonClicked() -{ -	uuid_vec_t selected_uuids; -	getCurrentItemIDs(selected_uuids); - -	if (selected_uuids.size() == 1) -	{ -		// initiate a P2P voice chat with the selected user -		LLAvatarActions::startCall(getCurrentItemID()); -	} -	else if (selected_uuids.size() > 1) -	{ -		// initiate an ad-hoc voice chat with multiple users -		LLAvatarActions::startAdhocCall(selected_uuids); -	} -} - -void LLPanelPeople::onGroupCallButtonClicked() -{ -	LLGroupActions::startCall(getCurrentItemID()); -} - -void LLPanelPeople::onTeleportButtonClicked() -{ -	uuid_vec_t selected_uuids; -	getCurrentItemIDs(selected_uuids); -	LLAvatarActions::offerTeleport(selected_uuids); -} - -void LLPanelPeople::onShareButtonClicked() -{ -	LLAvatarActions::share(getCurrentItemID()); -} -  void LLPanelPeople::onMoreButtonClicked()  {  	// *TODO: not implemented yet diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 46c58cd139..da27f83074 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -80,31 +80,22 @@ private:  	std::string				getActiveTabName() const;  	LLUUID					getCurrentItemID() const;  	void					getCurrentItemIDs(uuid_vec_t& selected_uuids) const; -	void					buttonSetVisible(std::string btn_name, BOOL visible); -	void					buttonSetEnabled(const std::string& btn_name, bool enabled); -	void					buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb);  	void					showGroupMenu(LLMenuGL* menu);  	void					setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true);  	// UI callbacks  	void					onFilterEdit(const std::string& search_string);  	void					onTabSelected(const LLSD& param); -	void					onViewProfileButtonClicked();  	void					onAddFriendButtonClicked();  	void					onAddFriendWizButtonClicked();  	void					onDeleteFriendButtonClicked(); -	void					onGroupInfoButtonClicked();  	void					onChatButtonClicked(); +	void					onGearButtonClicked(LLUICtrl* btn);  	void					onImButtonClicked(); -	void					onCallButtonClicked(); -	void					onGroupCallButtonClicked(); -	void					onTeleportButtonClicked(); -	void					onShareButtonClicked();  	void					onMoreButtonClicked(); -	void					onActivateButtonClicked();  	void					onAvatarListDoubleClicked(LLUICtrl* ctrl);  	void					onAvatarListCommitted(LLAvatarList* list); -	void					onGroupPlusButtonClicked(); +	bool					onGroupPlusButtonValidate();  	void					onGroupMinusButtonClicked();  	void					onGroupPlusMenuItemClicked(const LLSD& userdata); @@ -113,8 +104,6 @@ private:  	void					onGroupsViewSortMenuItemClicked(const LLSD& userdata);  	void					onRecentViewSortMenuItemClicked(const LLSD& userdata); -	//returns false only if group is "none" -	bool					isRealGroup();  	bool					onFriendsViewSortMenuItemCheck(const LLSD& userdata);  	bool					onRecentViewSortMenuItemCheck(const LLSD& userdata);  	bool					onNearbyViewSortMenuItemCheck(const LLSD& userdata); @@ -135,7 +124,6 @@ private:  	bool					isAccordionCollapsedByUser(LLUICtrl* acc_tab);  	bool					isAccordionCollapsedByUser(const std::string& name); -	LLFilterEditor*			mFilterEditor;  	LLTabContainer*			mTabContainer;  	LLAvatarList*			mOnlineFriendList;  	LLAvatarList*			mAllFriendList; @@ -144,24 +132,13 @@ private:  	LLGroupList*			mGroupList;  	LLNetMap*				mMiniMap; -	LLHandle<LLView>		mGroupPlusMenuHandle; -	LLHandle<LLView>		mNearbyViewSortMenuHandle; -	LLHandle<LLView>		mFriendsViewSortMenuHandle; -	LLHandle<LLView>		mGroupsViewSortMenuHandle; -	LLHandle<LLView>		mRecentViewSortMenuHandle; +	std::vector<std::string> mSavedOriginalFilters; +	std::vector<std::string> mSavedFilters;  	Updater*				mFriendListUpdater;  	Updater*				mNearbyListUpdater;  	Updater*				mRecentListUpdater;  	Updater*				mButtonsUpdater; - -	LLMenuButton*			mNearbyGearButton; -	LLMenuButton*			mFriendsGearButton; -	LLMenuButton*			mGroupsGearButton; -	LLMenuButton*			mRecentGearButton; - -	std::string				mFilterSubString; -	std::string				mFilterSubStringOrig;  };  #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index f12c4de2f7..c9eebe24d3 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -51,6 +51,7 @@ LLContextMenu* NearbyMenu::createMenu()  	// set up the callbacks for all of the avatar menu items  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +	LLContextMenu* menu;  	if ( mUUIDs.size() == 1 )  	{ @@ -67,20 +68,21 @@ LLContextMenu* NearbyMenu::createMenu()  		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::share,					id));  		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));  		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id)); +		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id));  		enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem,	this, _2));  		enable_registrar.add("Avatar.CheckItem",  boost::bind(&NearbyMenu::checkContextMenuItem,	this, _2));  		// create the context menu from the XUI -		return createFromFile("menu_people_nearby.xml"); +		menu = createFromFile("menu_people_nearby.xml");  	}  	else  	{  		// Set up for multi-selected People  		// registrar.add("Avatar.AddFriend",	boost::bind(&LLAvatarActions::requestFriendshipDialog,	mUUIDs)); // *TODO: unimplemented -		registrar.add("Avatar.IM",			boost::bind(&LLAvatarActions::startConference,			mUUIDs)); -		registrar.add("Avatar.Call",		boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs)); +		registrar.add("Avatar.IM",			boost::bind(&LLAvatarActions::startConference,			mUUIDs, LLUUID::null)); +		registrar.add("Avatar.Call",		boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs, LLUUID::null));  		registrar.add("Avatar.OfferTeleport",	boost::bind(&NearbyMenu::offerTeleport,					this));  		registrar.add("Avatar.RemoveFriend",boost::bind(&LLAvatarActions::removeFriendsDialog,		mUUIDs));  		// registrar.add("Avatar.Share",		boost::bind(&LLAvatarActions::startIM,					mUUIDs)); // *TODO: unimplemented @@ -88,8 +90,10 @@ LLContextMenu* NearbyMenu::createMenu()  		enable_registrar.add("Avatar.EnableItem",	boost::bind(&NearbyMenu::enableContextMenuItem,	this, _2));  		// create the context menu from the XUI -		return createFromFile("menu_people_nearby_multiselect.xml"); +		menu = createFromFile("menu_people_nearby_multiselect.xml");  	} + +    return menu;  }  bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index 280cc11179..854deb00d0 100644 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -230,7 +230,7 @@ void LLPanelTopInfoBar::buildLocationString(std::string& loc_str, bool show_coor  void LLPanelTopInfoBar::setParcelInfoText(const std::string& new_text)  {  	LLRect old_rect = getRect(); -	const LLFontGL* font = mParcelInfoText->getDefaultFont(); +	const LLFontGL* font = mParcelInfoText->getFont();  	S32 new_text_width = font->getWidth(new_text);  	mParcelInfoText->setText(new_text); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 975a6c67d8..47518a365f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -32,6 +32,7 @@  #include "llagent.h"  #include "llimview.h" +#include "llpanelpeoplemenus.h"  #include "llnotificationsutil.h"  #include "llparticipantlist.h"  #include "llspeakers.h" @@ -197,10 +198,10 @@ private:  	uuid_set_t mAvalineCallers;  }; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  									 LLAvatarList* avatar_list,  									 bool use_context_menu/* = true*/, -									 bool exclude_agent /*= true*/,  +									 bool exclude_agent /*= true*/,  									 bool can_toggle_icons /*= true*/) :  	mSpeakerMgr(data_source),  	mAvatarList(avatar_list), @@ -233,8 +234,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  	if (use_context_menu)  	{ -		mParticipantListMenu = new LLParticipantListMenu(*this); -		mAvatarList->setContextMenu(mParticipantListMenu); +		//mParticipantListMenu = new LLParticipantListMenu(*this); +		//mAvatarList->setContextMenu(mParticipantListMenu); +		mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);  	}  	else  	{ @@ -473,6 +475,7 @@ void LLParticipantList::update()  {  	mSpeakerMgr->update(true); +	// Need to resort the participant list if it's in sort by recent speaker order.  	if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered())  	{  		// Resort avatar list @@ -670,7 +673,7 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::  	return mParent.onSpeakerMuteEvent(event, userdata);  } -LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() +/*LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  {  	// set up the callbacks for all of the avatar menu items  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -708,7 +711,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	main_menu->arrangeAndClear();  	return main_menu; -} +}*/  void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y)  { diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index fe4cc0f55f..ebd9604c5b 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -85,34 +85,33 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  { +	std::vector<std::string> items; +	std::vector<std::string> disabled_items; + +	LLInventoryPanel* inv_panel = mInventoryPanel.get(); +	bool is_open = false; +	if (inv_panel)  	{ -		std::vector<std::string> items; -		std::vector<std::string> disabled_items; +		LLFolderViewFolder* folder =  dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); +		is_open = (NULL != folder) && folder->isOpen(); +	} -		LLInventoryPanel* inv_panel = mInventoryPanel.get(); -		bool is_open = false; -		if (inv_panel) -		{ -			LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); -			is_open = (NULL != folder) && folder->isOpen(); -		} +	// collect all items' names +	fill_items_with_menu_items(items, menu); -		// collect all items' names -		fill_items_with_menu_items(items, menu); +	// remove expand or collapse menu item depend on folder state +	std::string collapse_expand_item_to_hide(is_open ? "expand" :  "collapse"); +	std::vector<std::string>::iterator it = std::find(items.begin(),  items.end(), collapse_expand_item_to_hide); +	if (it != items.end())	items.erase(it); -		// remove expand or collapse menu item depend on folder state -		std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); -		std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); -		if (it != items.end())	items.erase(it); -		// Disabled items are processed via LLLandmarksPanel::isActionEnabled() -		// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601  +	// Disabled items are processed via LLLandmarksPanel::isActionEnabled() +	// they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601  -		// repeat parent functionality - 		sSelf = getHandle(); // necessary for "New Folder" functionality +	// repeat parent functionality + 	sSelf = getHandle(); // necessary for "New Folder" functionality -		hide_context_entries(menu, items, disabled_items); -	} +	hide_context_entries(menu, items, disabled_items);  }  //virtual @@ -140,7 +139,7 @@ LLFolderViewFolder* LLPlacesFolderBridge::getFolder()  	LLInventoryPanel* inv_panel = mInventoryPanel.get();  	if (inv_panel)  	{ -		folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); +		folder =    dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID));  	}  	return folder; @@ -152,6 +151,7 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  	LLAssetType::EType actual_asset_type,  	LLInventoryType::EType inv_type,  	LLInventoryPanel* inventory, +	LLFolderViewModelInventory* view_model,  	LLFolderView* root,  	const LLUUID& uuid,  	U32 flags/* = 0x00*/) const @@ -170,11 +170,12 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)  		{  			// *TODO: Create a link folder handler instead if it is necessary -			new_listener = LLInventoryFVBridgeBuilder::createBridge( +			new_listener = LLInventoryFolderViewModelBuilder::createBridge(  				asset_type,  				actual_asset_type,  				inv_type,  				inventory, +				view_model,  				root,  				uuid,  				flags); @@ -183,11 +184,12 @@ LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(  		new_listener = new LLPlacesFolderBridge(inv_type, inventory, root, uuid);  		break;  	default: -		new_listener = LLInventoryFVBridgeBuilder::createBridge( +		new_listener = LLInventoryFolderViewModelBuilder::createBridge(  			asset_type,  			actual_asset_type,  			inv_type,  			inventory, +			view_model,  			root,  			uuid,  			flags); diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h index 52beacef9c..07d18d03c5 100644 --- a/indra/newview/llplacesinventorybridge.h +++ b/indra/newview/llplacesinventorybridge.h @@ -82,13 +82,14 @@ protected:   *   * It builds Bridges for Landmarks and Folders in Places Landmarks Panel   */ -class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +class LLPlacesInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder  {  public:  	/*virtual*/ LLInvFVBridge* createBridge(LLAssetType::EType asset_type,  											LLAssetType::EType actual_asset_type,  											LLInventoryType::EType inv_type,  											LLInventoryPanel* inventory, +											LLFolderViewModelInventory* view_model,  											LLFolderView* root,  											const LLUUID& uuid,  											U32 flags = 0x00) const; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index f7823f4fe8..db3f245389 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -30,7 +30,8 @@  #include "llplacesinventorypanel.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" +#include "llfolderview.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llpanellandmarks.h" @@ -57,44 +58,6 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel()  	delete mSavedFolderState;  } -void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) -{ -	// Determine the root folder in case specified, and -	// build the views starting with that folder. -	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder); - -	LLUUID root_id; - -	if ("LIBRARY" == params.start_folder()) -	{ -		root_id = gInventory.getLibraryRootFolderID(); -	} -	else -	{ -		root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); -	} - -	LLRect folder_rect(0, -		0, -		getRect().getWidth(), -		0); -	LLPlacesFolderView::Params p; -	p.name = getName(); -	p.title = getLabel(); -	p.rect = folder_rect; -	p.listener =  mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, -													LLAssetType::AT_CATEGORY, -													LLInventoryType::IT_CATEGORY, -													this, -													NULL, -													root_id); -	p.parent_panel = this; -	p.allow_multiselect = mAllowMultiSelect; -	p.use_ellipses = true;	// truncate inventory item text so remove horizontal scroller -	mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); -} - -  // save current folder open state  void LLPlacesInventoryPanel::saveFolderState()  { @@ -161,7 +124,7 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask)  	// then determine its type and set necessary menu handle  	if (getCurSelectedItem())  	{ -		LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); +		LLInventoryType::EType inventory_type = static_cast<LLFolderViewModelItemInventory*>(getCurSelectedItem()->getViewModelItem())->getInventoryType();  		inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type);  		if (it_handle != mMenuHandlesByInventoryType.end()) diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h index f647e7f970..1544b51aed 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -46,8 +46,6 @@ public:  	LLPlacesInventoryPanel(const Params& p);  	~LLPlacesInventoryPanel(); -	/*virtual*/ void buildFolderView(const LLInventoryPanel::Params& params); -  	void saveFolderState();  	void restoreFolderState(); @@ -57,7 +55,7 @@ private:  	LLSaveFolderState*			mSavedFolderState;  }; - +//TODO RN: this class is currently unused, make sure that behavior remains  class LLPlacesFolderView : public LLFolderView  {  public: @@ -77,8 +75,6 @@ public:  		mParentLandmarksPanel = panel;  	} -	S32 getSelectedCount() { return (S32)mSelectedItems.size(); } -  private:  	/**  	 * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 88727bf59b..29eb5ce69e 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -305,7 +305,11 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask)  {  	if (mEditorCore)  	{ -		return mEditorCore->handleKeyHere(key, mask); +		BOOL handled = mEditorCore->handleKeyHere(key, mask); +		if (!handled) +		{ +			LLFloater::handleKeyHere(key, mask); +		}  	}  	return FALSE; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index d340b304ca..a4a0198305 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -253,12 +253,26 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  {  	bool store_toast = false, show_toast = false; -	mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); +	if (mDisplayToastsAlways) +	{ +		show_toast = true; +	} +	else +	{ +		show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); +	}  	store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;  	if(!show_toast && !store_toast)  	{ -		mRejectToastSignal(p.notif_id); +		LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id); + +		if (notification && +			(!notification->canLogToIM() || !notification->hasFormElements())) +		{ +			// only cancel notification if it isn't being used in IM session +			LLNotifications::instance().cancel(notification); +		}  		return;  	} @@ -371,7 +385,7 @@ void LLScreenChannel::storeToast(ToastElem& toast_elem)  	const LLToast* toast = toast_elem.getToast();  	if (toast)  	{ -		mStoredToastList.push_back(toast_elem); +	mStoredToastList.push_back(toast_elem);  		mOnStoreToast(toast->getPanel(), toast->getNotificationID());  	}  } @@ -410,14 +424,14 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  	LLToast* toast = it->getToast();  	if (toast)  	{ -		if(toast->getVisible()) -		{ -			// toast is already in channel -			return; -		} +	if(toast->getVisible()) +	{ +		// toast is already in channel +		return; +	} -		toast->setIsHidden(false); -		toast->startTimer(); +	toast->setIsHidden(false); +	toast->startTimer();  		mToastList.push_back(*it);  	} @@ -425,34 +439,12 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  }  //-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) -{ -	// *TODO: may be remove this function -	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if( it == mStoredToastList.end() ) -		return; - -	const LLToast* toast = it->getToast(); -	if (toast) -	{ -		mRejectToastSignal(toast->getNotificationID()); -	} - -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid. -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); -	if (it != mStoredToastList.end()) -	{ -		mStoredToastList.erase(it); -	} -} - -//--------------------------------------------------------------------------  void LLScreenChannel::killToastByNotificationID(LLUUID id)  {  	// searching among toasts on a screen  	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (!notification) return;  	if( it != mToastList.end())  	{ @@ -465,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  		//			the toast will be destroyed.  		if(toast && toast->isNotificationValid())  		{ -			mRejectToastSignal(toast->getNotificationID()); +			if (!notification->canLogToIM() || !notification->hasFormElements()) +			{ +				// only cancel notification if it isn't being used in IM session +				LLNotifications::instance().cancel(notification); +			}  		}  		else  		{ - -			deleteToast(toast); -			mToastList.erase(it); -			redrawToasts(); +			removeToastByNotificationID(id);  		} -		return;  	} - -	// searching among stored toasts -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if (it != mStoredToastList.end()) +	else  	{ -		LLToast* toast = it->getToast(); -		if (toast) +		// searching among stored toasts +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + +		if( it != mStoredToastList.end() )  		{ -			// send signal to a listener to let him perform some action on toast rejecting -			mRejectToastSignal(toast->getNotificationID()); -			deleteToast(toast); +			LLToast* toast = it->getToast(); +			if (toast) +			{ +				if (!notification->canLogToIM() || !notification->hasFormElements()) +				{ +					// only cancel notification if it isn't being used in IM session +					LLNotifications::instance().cancel(notification); +				} +				deleteToast(toast); +			} +		} +	 +		// Call find() once more, because the mStoredToastList could have been changed +		// via notification cancellation and the iterator could have become invalid. +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +		if (it != mStoredToastList.end()) +		{ +			mStoredToastList.erase(it);  		}  	} +} + +void LLScreenChannel::removeToastByNotificationID(LLUUID id) +{ +	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	while( it != mToastList.end()) +	{ +		deleteToast(it->getToast()); +		mToastList.erase(it); +		redrawToasts(); +		// find next toast with matching id +		it = find(mToastList.begin(), mToastList.end(), id); +	} -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid.  	it = find(mStoredToastList.begin(), mStoredToastList.end(), id);  	if (it != mStoredToastList.end())  	{ +		deleteToast(it->getToast());  		mStoredToastList.erase(it);  	} -  } +  void LLScreenChannel::killMatchedToasts(const Matcher& matcher)  {  	std::list<const LLToast*> to_delete = findToasts(matcher); @@ -521,11 +538,11 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)  		LLToast* toast = it->getToast();  		if (toast)  		{ -			LLPanel* old_panel = toast->getPanel(); -			toast->removeChild(old_panel); -			delete old_panel; -			toast->insertPanel(panel); -			toast->startTimer(); +		LLPanel* old_panel = toast->getPanel(); +		toast->removeChild(old_panel); +		delete old_panel; +		toast->insertPanel(panel); +		toast->startTimer();  		}  		redrawToasts();  	} @@ -679,7 +696,7 @@ void LLScreenChannel::showToastsCentre()  		return;  	} -	LLRect	toast_rect; +	LLRect	toast_rect;	  	S32		bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2;  	std::vector<ToastElem>::reverse_iterator it; diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 56a9cf8b4b..e5f4807ab7 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -84,6 +84,7 @@ public:  	// kill or modify a toast by its ID  	virtual void		killToastByNotificationID(LLUUID id) {};  	virtual void		modifyToastNotificationByID(LLUUID id, LLSD data) {}; +	virtual void		removeToastByNotificationID(LLUUID id){};  	// hide all toasts from screen, but not remove them from a channel  	virtual void		hideToastsFromScreen() {}; @@ -175,6 +176,7 @@ public:  	void		addToast(const LLToast::Params& p);  	// kill or modify a toast by its ID  	void		killToastByNotificationID(LLUUID id); +	void		removeToastByNotificationID(LLUUID id);  	void		killMatchedToasts(const Matcher& matcher);  	void		modifyToastByNotificationID(LLUUID id, LLPanel* panel);  	// hide all toasts from screen, but not remove them from a channel @@ -195,8 +197,6 @@ public:  	void		loadStoredToastsToChannel();  	// finds a toast among stored by its Notification ID and throws it on a screen to a channel  	void		loadStoredToastByNotificationIDToChannel(LLUUID id); -	// removes a toast from stored finding it by its Notification ID  -	void		removeStoredToastByNotificationID(LLUUID id);  	// removes from channel all toasts that belongs to the certain IM session   	void		removeToastsBySessionID(LLUUID id);  	// remove all storable toasts from screen and store them @@ -227,16 +227,12 @@ public:  	// Channel's signals  	// signal on storing of faded toasts event -	typedef boost::function<void (LLPanel* info_panel, const LLUUID id)> store_tost_callback_t; -	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_tost_signal_t; -	store_tost_signal_t mOnStoreToast;	 -	boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); } -	// signal on rejecting of a toast event -	typedef boost::function<void (LLUUID id)> reject_tost_callback_t; -	typedef boost::signals2::signal<void (LLUUID id)> reject_tost_signal_t; -	reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } +	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t; +	boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); }  private: +	store_toast_signal_t mOnStoreToast;	 +  	class ToastElem  	{  	public: diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 853656905c..b143240187 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -38,7 +38,7 @@  #include "llfiltereditor.h"  #include "llfloaterreg.h"  #include "llfloaterworldmap.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "lloutfitobserver.h"  #include "llpaneleditwearable.h"  #include "llpaneloutfitsinventory.h" @@ -267,11 +267,11 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked()  		if (inventory_panel)  		{  			LLFolderView* root = inventory_panel->getRootFolder(); -			LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); +			LLFolderViewItem *outfit_folder =    inventory_panel->getItemByID(outfit_link->getLinkedUUID());  			if (outfit_folder)  			{  				outfit_folder->setOpen(!outfit_folder->isOpen()); -				root->setSelectionFromRoot(outfit_folder,TRUE); +				root->setSelection(outfit_folder,TRUE);  				root->scrollToShowSelection();  			}  		} diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 4f9ab318a5..acb232c77f 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -36,6 +36,7 @@  #include "llfirstuse.h"  #include "llfloatersidepanelcontainer.h"  #include "llfoldertype.h" +#include "llfolderview.h"  #include "llhttpclient.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h" @@ -259,9 +260,8 @@ void LLSidepanelInventory::updateInbox()  	//  	const bool do_not_create_folder = false; -	const bool do_not_find_in_library = false; -	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library); +	const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder);  	// Set up observer to listen for creation of inbox if at least one of them doesn't exist  	if (inbox_id.isNull()) @@ -383,10 +383,10 @@ void LLSidepanelInventory::onToggleInboxBtn()  	{  		inboxPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight"));  		if (inboxPanel->isInVisibleChain()) -		{ -			gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); -		} +	{ +		gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());  	} +}  	else  	{  		gSavedPerAccountSettings.setS32("InventoryInboxHeight", inboxPanel->getTargetDim()); @@ -472,7 +472,7 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action)  		}  	} -	current_item->getListener()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); +	static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->performAction(mPanelMainInventory->getActivePanel()->getModel(), action);  }  void LLSidepanelInventory::onWearButtonClicked() @@ -662,7 +662,7 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()  			return NULL;  		}  	} -	const LLUUID &item_id = current_item->getListener()->getUUID(); +	const LLUUID &item_id = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getUUID();  	LLInventoryItem *item = gInventory.getItem(item_id);  	return item;  } @@ -671,7 +671,7 @@ U32 LLSidepanelInventory::getSelectedCount()  {  	int count = 0; -	std::set<LLUUID> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); +	std::set<LLFolderViewItem*> selection_list =    mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList();  	count += selection_list.size();  	if ((count == 0) && mInboxEnabled && (mInventoryPanelInbox != NULL)) @@ -722,9 +722,9 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox)  	updateVerbs();  } -std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() +std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList()  { -	std::set<LLUUID> inventory_selected_uuids; +	std::set<LLFolderViewItem*> inventory_selected_uuids;  	if (mInboxEnabled && (mInventoryPanelInbox != NULL))  	{ diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index a33607f50d..e8b2808d4f 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -63,7 +63,7 @@ public:  	BOOL isMainInventoryPanelActive() const;  	void clearSelections(bool clearMain, bool clearInbox); -	std::set<LLUUID> getInboxSelectionList(); +    std::set<LLFolderViewItem*> getInboxSelectionList();  	void showItemInfoPanel();  	void showTaskInfoPanel(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 78c905f6ff..44d32f7d93 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2776,7 +2776,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)  void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)  { -	gGL.diffuseColor4fv(color.mV); +	gGL.color4fv(color.mV);  	gGL.begin(LLRender::LINES);  	{  		gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); @@ -4024,7 +4024,7 @@ void renderAgentTarget(LLVOAvatar* avatar)  	if (avatar->isSelf())  	{  		renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); -		renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); +		renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f));  		renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f));  		renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f));  	} diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index b9358cf37c..1c6f51e131 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -29,7 +29,6 @@  #include "llevent.h"  #include "lleventtimer.h" -#include "llspeakers.h"  #include "llvoicechannel.h"  class LLSpeakerMgr; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a28d8d3546..ba9c2c9e2f 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -63,7 +63,7 @@  #include "llmemorystream.h"  #include "llmessageconfig.h"  #include "llmoveview.h" -#include "llnearbychat.h" +#include "llimfloatercontainer.h"  #include "llnotifications.h"  #include "llnotificationsutil.h"  #include "llteleporthistory.h" @@ -94,6 +94,7 @@  #include "llcallingcard.h"  #include "llconsole.h"  #include "llcontainerview.h" +#include "llconversationlog.h"  #include "lldebugview.h"  #include "lldrawable.h"  #include "lleventnotifier.h" @@ -1268,6 +1269,8 @@ bool idle_startup()  		display_startup();  		LLStartUp::setStartupState( STATE_MULTIMEDIA_INIT ); +		LLConversationLog::getInstance(); +  		return FALSE;  	} @@ -1378,14 +1381,9 @@ bool idle_startup()  		LLVoiceClient::getInstance()->updateSettings();  		display_startup(); -		//gCacheName is required for nearby chat history loading -		//so I just moved nearby history loading a few states further -		if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) -		{ -			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			if (nearby_chat) nearby_chat->loadHistory(); -		} -		display_startup(); +		// create a container's instance for start a controlling conversation windows +		// by the voice's events +		LLIMFloaterContainer::getInstance();  		// *Note: this is where gWorldMap used to be initialized. @@ -2165,7 +2163,6 @@ bool idle_startup()  		LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); -		LLIMFloater::initIMFloater();  		display_startup();  		llassert(LLPathfindingManager::getInstance() != NULL); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 0cb6c85012..18e0d9d0d2 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -433,13 +433,19 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas  //////////////////////////////////////////////////////////////////////////  // PUBLIC METHODS +LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) +:	LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), +	mWellWindow(well_window) +{ +	connectToChannel("Notifications"); +	connectToChannel("Group Notifications"); +	connectToChannel("Offer"); +} +  LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) -: LLSysWellWindow(key) +:	LLSysWellWindow(key)  { -	// init connections to the list's update events -	connectListUpdaterToSignal("notify"); -	connectListUpdaterToSignal("groupnotify"); -	connectListUpdaterToSignal("offer"); +	mNotificationUpdates.reset(new WellNotificationChannel(this));  }  // static @@ -519,7 +525,7 @@ void LLNotificationWellWindow::initChannel()  	LLSysWellWindow::initChannel();  	if(mChannel)  	{ -		mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); +		mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2));  	}  } @@ -546,20 +552,6 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)  	addItem(p);  } -void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); -	} -	else -	{ -		llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; -	} -} -  void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)  {  	LLUUID id = item->getID(); @@ -574,6 +566,12 @@ void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)  		mChannel->killToastByNotificationID(id);  } +void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) +{ +	removeItemByID(notify->getID()); +} + +  /************************************************************************/ @@ -867,4 +865,4 @@ bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& respo  	return false;  } -// EOF + diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 272e9cfcb1..8758c8c4e5 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -34,6 +34,7 @@  #include "llscreenchannel.h"  #include "llscrollcontainer.h"  #include "llimview.h" +#include "llnotifications.h"  #include "boost/shared_ptr.hpp" @@ -111,7 +112,7 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible); - +	/*virtual*/ void onAdd(LLNotificationPtr notify);  	// Operating with items  	void addItem(LLSysWellItem::Params p); @@ -119,6 +120,18 @@ public:  	void closeAll();  protected: +	struct WellNotificationChannel : public LLNotificationChannel +	{ +		WellNotificationChannel(LLNotificationWellWindow*); +		void onDelete(LLNotificationPtr notify) +		{ +			mWellWindow->removeItemByID(notify->getID()); +		}  + +		LLNotificationWellWindow* mWellWindow; +	}; + +	LLNotificationChannelPtr mNotificationUpdates;  	/*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; }  private: @@ -126,12 +139,8 @@ private:  	void initChannel();  	void clearScreenChannels(); -  	void onStoreToast(LLPanel* info_panel, LLUUID id); -	// connect counter and list updaters to the corresponding signals -	void connectListUpdaterToSignal(std::string notification_type); -  	// Handlers  	void onItemClick(LLSysWellItem* item);  	void onItemClose(LLSysWellItem* item); @@ -160,6 +169,7 @@ public:  	// LLIMSessionObserver observe triggers  	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	/*virtual*/ void sessionVoiceOrIMStarted(const LLUUID& session_id) {};  	/*virtual*/ void sessionRemoved(const LLUUID& session_id);  	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ec36cf48c2..65f0290060 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -39,7 +39,7 @@  #include "llfocusmgr.h"  #include "llviewertexture.h"  #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h"  #include "llinventory.h"  #include "llinventoryfunctions.h"  #include "llinventorymodelbackgroundfetch.h" @@ -58,6 +58,7 @@  #include "lltoolmgr.h"  #include "lltoolpipette.h"  #include "llfiltereditor.h" +#include "llwindow.h"  #include "lltool.h"  #include "llviewerwindow.h" @@ -186,7 +187,7 @@ protected:  	F32					mContextConeOpacity;  	LLSaveFolderState	mSavedFolderState;  	BOOL				mSelectedItemPinned; -	 +  	LLRadioGroup*		mModeSelector;  	LLScrollListCtrl*	mLocalScrollCtrl; @@ -372,7 +373,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)  		{  			if (!root_folder->getCurSelectedItem())  			{ -				LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); +				LLFolderViewItem* itemp =    mInventoryPanel->getItemByID(gInventory.getRootFolderID());  				if (itemp)  				{  					root_folder->setSelection(itemp, FALSE, FALSE); @@ -454,7 +455,7 @@ BOOL LLFloaterTexturePicker::postBuild()  		// Commented out to scroll to currently selected texture. See EXT-5403.  		// // store this filter as the default one -		// mInventoryPanel->getRootFolder()->getFilter()->markDefault(); +		// mInventoryPanel->getRootFolder()->getFilter().markDefault();  		// Commented out to stop opening all folders with textures  		// mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); @@ -637,11 +638,10 @@ void LLFloaterTexturePicker::draw()  		LLFolderView* folder_view = mInventoryPanel->getRootFolder();  		if (!folder_view) return; -		LLInventoryFilter* filter = folder_view->getFilter(); -		if (!filter) return; +		LLFolderViewFilter& filter = static_cast<LLFolderViewModelInventory*>(folder_view->getFolderViewModel())->getFilter(); -		bool is_filter_active = folder_view->getCompletedFilterGeneration() < filter->getCurrentGeneration() && -				filter->isNotDefault(); +		bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() && +				filter.isNotDefault();  		// After inventory panel filter is applied we have to update  		// constraint rect for the selected item because of folder view @@ -651,8 +651,9 @@ void LLFloaterTexturePicker::draw()  		if (!is_filter_active && !mSelectedItemPinned)  		{  			folder_view->setPinningSelectedItem(mSelectedItemPinned); -			folder_view->dirtyFilter(); -			folder_view->arrangeFromRoot(); +			folder_view->getViewModelItem()->dirtyFilter(); +			//TODO RN: test..still works without this? +			//folder_view->arrangeFromRoot();  			mSelectedItemPinned = TRUE;  		} @@ -815,7 +816,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem  	if (items.size())  	{  		LLFolderViewItem* first_item = items.front(); -		LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); +		LLInventoryItem* itemp = gInventory.getItem(static_cast<LLFolderViewModelItemInventory*>(first_item->getViewModelItem())->getUUID());  		mNoCopyTextureSelected = FALSE;  		if (itemp)  		{ @@ -1011,7 +1012,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  	else if (mInventoryPanel->getFilterSubString().empty())  	{  		// first letter in search term, save existing folder open state -		if (!mInventoryPanel->getRootFolder()->isFilterModified()) +		if (!mInventoryPanel->getFilter().isNotDefault())  		{  			mSavedFolderState.setApply(FALSE);  			mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); @@ -1325,7 +1326,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  		// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.  		else if (mCommitOnSelection || op == TEXTURE_SELECT)  			mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - +			  		if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work.  		{  			setTentative( FALSE ); @@ -1337,10 +1338,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)  			}  			else  			{ -				mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); -				lldebugs << "mImageItemID: " << mImageItemID << llendl; -				mImageAssetID = floaterp->getAssetID(); -				lldebugs << "mImageAssetID: " << mImageAssetID << llendl; +			mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); +			lldebugs << "mImageItemID: " << mImageItemID << llendl; +			mImageAssetID = floaterp->getAssetID(); +			lldebugs << "mImageAssetID: " << mImageAssetID << llendl;  			}  			if (op == TEXTURE_SELECT && mOnSelectCallback) diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..ea62f758f8 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -169,6 +169,7 @@ public:  	// get/set Toast's flags or states  	// get information whether the notification corresponding to the toast is valid or not  	bool isNotificationValid(); +  	// get toast's Notification ID  	const LLUUID getNotificationID() const { return mNotificationID;}  	// get toast's Session ID @@ -212,7 +213,7 @@ private:  	//LLRootHandle<LLToast>	mHandle; -	LLPanel* mWrapperPanel; +	LLPanel*	 mWrapperPanel;  	// timer counts a lifetime of a toast  	std::auto_ptr<LLToastLifeTimer> mTimer; @@ -220,8 +221,8 @@ private:  	F32			mToastLifetime; // in seconds  	F32			mToastFadingTime; // in seconds -	LLPanel*		mPanel; -	LLButton*		mHideBtn; +	LLPanel*	mPanel; +	LLButton*	mHideBtn;  	LLColor4	mBgColor;  	bool		mCanFade; diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 75178a6ef8..ed350ea144 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -51,7 +51,7 @@  const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT	= 7; -LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) +LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notification)  :	LLToastPanel(notification),  	mInventoryOffer(NULL)  { @@ -112,7 +112,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification  		style.font = date_font;  	pMessageText->appendText(timeStr + "\n", TRUE, style); -	style.font = pMessageText->getDefaultFont(); +	style.font = pMessageText->getFont();  	pMessageText->appendText(message, TRUE, style);  	//attachment diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 7794ec9f63..dfdc6ae559 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -47,13 +47,10 @@ class LLToastGroupNotifyPanel  public:  	void close(); -	static bool onNewNotification(const LLSD& notification); - -  	// Non-transient messages.  You can specify non-default button  	// layouts (like one for script dialogs) by passing various  	// numbers in for "layout". -	LLToastGroupNotifyPanel(LLNotificationPtr& notification); +	LLToastGroupNotifyPanel(const LLNotificationPtr& notification);  	/*virtual*/ ~LLToastGroupNotifyPanel();  protected: diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index a803387576..279dd69bc7 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -41,11 +41,11 @@ public:  	struct Params  	{  		LLNotificationPtr	notification; -		LLUUID				avatar_id; -		LLUUID				session_id; -		std::string			from; -		std::string			time; -		std::string			message; +		LLUUID				avatar_id, +							session_id; +		std::string			from, +							time, +							message;  		Params() {}  	}; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index d629f3abac..4a49922656 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,9 @@  const S32 BOTTOM_PAD = VPAD * 3;  const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding  S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  +  //static  const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -52,172 +55,12 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;  LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : -LLToastPanel(notification), -mTextBox(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false), -mCloseNotificationOnDestroy(true) +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)  +:	LLToastPanel(notification), +	LLInstanceTracker<LLToastNotifyPanel, LLUUID>(notification->getID())  { -	buildFromFile( "panel_notification.xml"); -	if(rect != LLRect::null) -	{ -		this->setShape(rect); -	}		  -	mInfoPanel = getChild<LLPanel>("info_panel"); -	mControlPanel = getChild<LLPanel>("control_panel"); -	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); -	// customize panel's attributes -	// is it intended for displaying a tip? -	mIsTip = notification->getType() == "notifytip"; -	// is it a script dialog? -	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); -	// is it a caution? -	// -	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the -	// notify xml template specifies that it is a caution -	// tip-style notification handle 'caution' differently -they display the tip in a different color -	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - -	// setup parameters -	// get a notification message -	mMessage = notification->getMessage(); -	// init font variables -	if (!sFont) -	{ -		sFont = LLFontGL::getFontSansSerif(); -		sFontSmall = LLFontGL::getFontSansSerifSmall(); -	} -	// initialize -	setFocusRoot(!mIsTip); -	// get a form for the notification -	LLNotificationFormPtr form(notification->getForm()); -	// get number of elements -	mNumOptions = form->getNumElements(); - -	// customize panel's outfit -	// preliminary adjust panel's layout -	//move to the end  -	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - -	// adjust text options according to the notification type -	// add a caution textbox at the top of a caution notification -	if (mIsCaution && !mIsTip) -	{ -		mTextBox = getChild<LLTextBox>("caution_text_box"); -	} -	else -	{ -		mTextBox = getChild<LLTextEditor>("text_editor_box");  -	} - -	// *TODO: magic numbers(???) - copied from llnotify.cpp(250) -	const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  - -	mTextBox->setMaxTextLength(MAX_LENGTH); -	mTextBox->setVisible(TRUE); -	mTextBox->setPlainText(!show_images); -	mTextBox->setValue(notification->getMessage()); - -	// add buttons for a script notification -	if (mIsTip) -	{ -		adjustPanelForTipNotice(); +	init(rect, show_images);  	} -	else -	{ -		std::vector<index_button_pair_t> buttons; -		buttons.reserve(mNumOptions); -		S32 buttons_width = 0; -		// create all buttons and accumulate they total width to reshape mControlPanel -		for (S32 i = 0; i < mNumOptions; i++) -		{ -			LLSD form_element = form->getElement(i); -			if (form_element["type"].asString() != "button") -			{ -				// not a button. -				continue; -			} -			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) -			{ -				// a textbox pretending to be a button. -				continue; -			} -			LLButton* new_button = createButton(form_element, TRUE); -			buttons_width += new_button->getRect().getWidth(); -			S32 index = form_element["index"].asInteger(); -			buttons.push_back(index_button_pair_t(index,new_button)); -		} -		if (buttons.empty()) -		{ -			addDefaultButton(); -		} -		else -		{ -			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel -			S32 button_panel_height = mControlPanel->getRect().getHeight(); -			//try get an average h_pad to spread out buttons -			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); -			if(h_pad < 2*HPAD) -			{ -				/* -				 * Probably it is a scriptdialog toast -				 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. -				 * In last case set default h_pad to avoid heaping of buttons  -				 */ -				S32 button_per_row = button_panel_width / BUTTON_WIDTH; -				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    -				if(h_pad < 2*HPAD) // still not enough space between buttons ? -				{ -					h_pad = 2*HPAD; -				} -			} -			if (mIsScriptDialog) -			{ -				// we are using default width for script buttons so we can determinate button_rows -				//to get a number of rows we divide the required width of the buttons to button_panel_width -				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); -				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; -				//reserve one row for the ignore_btn -				button_rows++; -				//calculate required panel height for scripdialog notification. -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; -			} -			else -			{ -				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width -				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); -				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); -				//calculate required panel height  -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD; -			} -		 -			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed -			adjustPanelForScriptNotice(button_panel_width, button_panel_height); -			updateButtonsLayout(buttons, h_pad); -			// save buttons for later use in disableButtons() -			mButtons.assign(buttons.begin(), buttons.end()); -		} -	} -	// adjust panel's height to the text size -	mInfoPanel->setFollowsAll(); -	snapToMessageHeight(mTextBox, MAX_LENGTH); - -	if(notification->isReusable()) -	{ -		mButtonClickConnection = sButtonClickSignal.connect( -			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); - -		if(notification->isRespondedTo()) -		{ -			// User selected an option in toast, now disable required buttons in IM window -			disableRespondedOptions(notification); -		} -	} -}  void LLToastNotifyPanel::addDefaultButton()  {  	LLSD form_element; @@ -235,7 +78,6 @@ void LLToastNotifyPanel::addDefaultButton()  }  LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option)  { -  	InstanceAndS32* userdata = new InstanceAndS32;  	userdata->mSelf = this;  	userdata->mButtonName = is_option ? form_element["name"].asString() : ""; @@ -245,14 +87,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt  	LLButton::Params p;  	bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2;  	const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog -	p.name(form_element["name"].asString()); -	p.label(form_element["text"].asString()); -	p.font(font); +	p.name = form_element["name"].asString(); +	p.label = form_element["text"].asString(); +	p.font = font;  	p.rect.height = BTN_HEIGHT;  	p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));  	p.rect.width = BUTTON_WIDTH;  	p.auto_resize = false;  	p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); +	p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean();  	if (mIsCaution)  	{  		p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); @@ -287,16 +130,11 @@ LLToastNotifyPanel::~LLToastNotifyPanel()  	mButtonClickConnection.disconnect();  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL) -	{ -		// let reusable notification be deleted -		mNotification->setReusable(false); -		if (!mNotification->isPersistent()) +	if (mIsTip)  		{  			LLNotifications::getInstance()->cancel(mNotification);  		}  	} -}  void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad)  { @@ -393,210 +231,374 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()  	}  } -typedef std::set<std::string> button_name_set_t; -typedef std::map<std::string, button_name_set_t> disable_button_map_t; +//typedef std::set<std::string> button_name_set_t; +//typedef std::map<std::string, button_name_set_t> disable_button_map_t; +// +//disable_button_map_t initUserGiveItemDisableButtonMap() +//{ +//	// see EXT-5905 for disable rules +// +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Show"); +//	disable_map.insert(std::make_pair("Show", buttons)); +// +//	buttons.insert("Discard"); +//	disable_map.insert(std::make_pair("Discard", buttons)); +// +//	buttons.insert("Mute"); +//	disable_map.insert(std::make_pair("Mute", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initTeleportOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Teleport"); +//	buttons.insert("Cancel"); +// +//	disable_map.insert(std::make_pair("Teleport", buttons)); +//	disable_map.insert(std::make_pair("Cancel", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initFriendshipOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Accept"); +//	buttons.insert("Decline"); +// +//	disable_map.insert(std::make_pair("Accept", buttons)); +//	disable_map.insert(std::make_pair("Decline", buttons)); +// +//	return disable_map; +//} +// +//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +//{ +//	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +//	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +//	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); +// +//	disable_button_map_t::const_iterator it; +//	disable_button_map_t::const_iterator it_end; +//	disable_button_map_t search_map; +// +//	if("UserGiveItem" == notification_name) +//	{ +//		search_map = user_give_item_disable_map; +//	} +//	else if("TeleportOffered" == notification_name) +//	{ +//		search_map = teleport_offered_disable_map; +//	} +//	else if("OfferFriendship" == notification_name) +//	{ +//		search_map = friendship_offered_disable_map; +//	} +// +//	it = search_map.find(button_name); +//	it_end = search_map.end(); +// +//	if(it_end != it) +//	{ +//		return it->second; +//	} +//	return button_name_set_t(); +//} + +//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +//{ +	//button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + +	//std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); +	//for ( ; it != mButtons.end(); it++) +	//{ +	//	LLButton* btn = it->second; +	//	if(buttons.find(btn->getName()) != buttons.end()) +	//	{ +	//		btn->setEnabled(FALSE); +	//	} +	//} +//} -disable_button_map_t initUserGiveItemDisableButtonMap() +// static +void LLToastNotifyPanel::onClickButton(void* data)  { -	// see EXT-5905 for disable rules - -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Show"); -	disable_map.insert(std::make_pair("Show", buttons)); +	InstanceAndS32* self_and_button = (InstanceAndS32*)data; +	LLToastNotifyPanel* self = self_and_button->mSelf; +	std::string button_name = self_and_button->mButtonName; -	buttons.insert("Discard"); -	disable_map.insert(std::make_pair("Discard", buttons)); +	LLSD response = self->mNotification->getResponseTemplate(); +	if (!self->mAddedDefaultBtn && !button_name.empty()) +	{ +		response[button_name] = true; +	} -	buttons.insert("Mute"); -	disable_map.insert(std::make_pair("Mute", buttons)); +	// disable all buttons +	self->mControlPanel->setEnabled(FALSE); -	return disable_map; +	// this might repost notification with new form data/enabled buttons +	self->mNotification->respond(response);  } -disable_button_map_t initTeleportOfferedDisableButtonMap() +void LLToastNotifyPanel::init( LLRect rect, bool show_images )  { -	disable_button_map_t disable_map; -	button_name_set_t buttons; +	deleteAllChildren(); -	buttons.insert("Teleport"); -	buttons.insert("Cancel"); +	mTextBox = NULL; +	mInfoPanel = NULL; +	mControlPanel = NULL; +	mNumOptions = 0; +	mNumButtons = 0; +	mAddedDefaultBtn = false; -	disable_map.insert(std::make_pair("Teleport", buttons)); -	disable_map.insert(std::make_pair("Cancel", buttons)); +	buildFromFile( "panel_notification.xml"); +	if(rect != LLRect::null) +	{ +		this->setShape(rect); +	}		  +	mInfoPanel = getChild<LLPanel>("info_panel"); +	mInfoPanel->setFollowsAll(); -	return disable_map; -} +	mControlPanel = getChild<LLPanel>("control_panel"); +	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); +	// customize panel's attributes +	// is it intended for displaying a tip? +	mIsTip = mNotification->getType() == "notifytip"; +	// is it a script dialog? +	mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); +	// is it a caution? +	// +	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the +	// notify xml template specifies that it is a caution +	// tip-style notification handle 'caution' differently -they display the tip in a different color +	mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; -disable_button_map_t initFriendshipOfferedDisableButtonMap() +	// setup parameters +	// get a notification message +	mMessage = mNotification->getMessage(); +	// init font variables +	if (!sFont)  { -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Accept"); -	buttons.insert("Decline"); - -	disable_map.insert(std::make_pair("Accept", buttons)); -	disable_map.insert(std::make_pair("Decline", buttons)); - -	return disable_map; +		sFont = LLFontGL::getFontSansSerif(); +		sFontSmall = LLFontGL::getFontSansSerifSmall();  } +	// initialize +	setFocusRoot(!mIsTip); +	// get a form for the notification +	LLNotificationFormPtr form(mNotification->getForm()); +	// get number of elements +	mNumOptions = form->getNumElements(); -button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -{ -	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); -	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); -	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); - -	disable_button_map_t::const_iterator it; -	disable_button_map_t::const_iterator it_end; -	disable_button_map_t search_map; +	// customize panel's outfit +	// preliminary adjust panel's layout +	//move to the end  +	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); -	if("UserGiveItem" == notification_name) -	{ -		search_map = user_give_item_disable_map; -	} -	else if(("TeleportOffered" == notification_name) || ("TeleportOffered_MaturityExceeded" == notification_name)) +	// adjust text options according to the notification type +	// add a caution textbox at the top of a caution notification +	if (mIsCaution && !mIsTip)  	{ -		search_map = teleport_offered_disable_map; +		mTextBox = getChild<LLTextBox>("caution_text_box");  	} -	else if("OfferFriendship" == notification_name) +	else  	{ -		search_map = friendship_offered_disable_map; +		mTextBox = getChild<LLTextEditor>("text_editor_box");   	} -	it = search_map.find(button_name); -	it_end = search_map.end(); +	mTextBox->setMaxTextLength(MAX_LENGTH); +	mTextBox->setVisible(TRUE); +	mTextBox->setPlainText(!show_images); +	mTextBox->setValue(mNotification->getMessage()); -	if(it_end != it) +	// add buttons for a script notification +	if (mIsTip)  	{ -		return it->second; +		adjustPanelForTipNotice();  	} -	return button_name_set_t(); -} - -void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +	else  { -	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - -	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); -	for ( ; it != mButtons.end(); it++) +		std::vector<index_button_pair_t> buttons; +		buttons.reserve(mNumOptions); +		S32 buttons_width = 0; +		// create all buttons and accumulate they total width to reshape mControlPanel +		for (S32 i = 0; i < mNumOptions; i++)  	{ -		LLButton* btn = it->second; -		if(buttons.find(btn->getName()) != buttons.end()) +			LLSD form_element = form->getElement(i); +			if (form_element["type"].asString() != "button")  		{ -			btn->setEnabled(FALSE); +				// not a button. +				continue;  		} +			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) +			{ +				// a textbox pretending to be a button. +				continue;  	} +			LLButton* new_button = createButton(form_element, TRUE); +			buttons_width += new_button->getRect().getWidth(); +			S32 index = form_element["index"].asInteger(); +			buttons.push_back(index_button_pair_t(index,new_button));  } - -// static -void LLToastNotifyPanel::onClickButton(void* data) +		if (buttons.empty())  { -	InstanceAndS32* self_and_button = (InstanceAndS32*)data; -	LLToastNotifyPanel* self = self_and_button->mSelf; -	std::string button_name = self_and_button->mButtonName; - -	LLSD response = self->mNotification->getResponseTemplate(); -	if (!self->mAddedDefaultBtn && !button_name.empty()) -	{ -		response[button_name] = true; +			addDefaultButton();  	} -	 -	bool is_reusable = self->mNotification->isReusable(); -	// When we call respond(), LLOfferInfo will delete itself in inventory_offer_callback(),  -	// lets copy it while it's still valid. -	LLOfferInfo* old_info = static_cast<LLOfferInfo*>(self->mNotification->getResponder()); -	LLOfferInfo* new_info = NULL; -	if(is_reusable && old_info) +		else  	{ -		new_info = new LLOfferInfo(*old_info); -		self->mNotification->setResponder(new_info); -	} - -	self->mNotification->respond(response); - -	if(is_reusable) +			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel +			S32 button_panel_height = mControlPanel->getRect().getHeight(); +			//try get an average h_pad to spread out buttons +			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); +			if(h_pad < 2*HPAD)  	{ -		sButtonClickSignal(self->mNotification->getID(), button_name); -	} -	else +				/* +				* Probably it is a scriptdialog toast +				* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. +				* In last case set default h_pad to avoid heaping of buttons  +				*/ +				S32 button_per_row = button_panel_width / BUTTON_WIDTH; +				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    +				if(h_pad < 2*HPAD) // still not enough space between buttons ?  	{ -		// disable all buttons -		self->mControlPanel->setEnabled(FALSE); +					h_pad = 2*HPAD;  	}  } - -void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +			if (mIsScriptDialog)  { -	if(mNotification->getID() == notification_id) +				// we are using default width for script buttons so we can determinate button_rows +				//to get a number of rows we divide the required width of the buttons to button_panel_width +				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); +				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; +				//reserve one row for the ignore_btn +				button_rows++; +				//calculate required panel height for scripdialog notification. +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; +			} +			else  	{ -		disableButtons(mNotification->getName(), btn_name); -	} +				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width +				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); +				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); +				//calculate required panel height  +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD;  } -void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) -{ -	LLSD response = notification->getResponse(); -	for (LLSD::map_const_iterator response_it = response.beginMap();  -		response_it != response.endMap(); ++response_it) -	{ -		if (response_it->second.isBoolean() && response_it->second.asBoolean()) -		{ -			// that after multiple responses there can be many pressed buttons -			// need to process them all -			disableButtons(notification->getName(), response_it->first); +			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed +			adjustPanelForScriptNotice(button_panel_width, button_panel_height); +			updateButtonsLayout(buttons, h_pad); +			// save buttons for later use in disableButtons() +			//mButtons.assign(buttons.begin(), buttons.end());  		}  	} +	// adjust panel's height to the text size +	snapToMessageHeight(mTextBox, MAX_LENGTH);  } + +//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +//{ +//	if(mNotification->getID() == notification_id) +//	{ +//		disableButtons(mNotification->getName(), btn_name); +//	} +//} + +//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) +//{ +//	LLSD response = notification->getResponse(); +//	for (LLSD::map_const_iterator response_it = response.beginMap();  +//		response_it != response.endMap(); ++response_it) +//	{ +//		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +//		{ +//			// that after multiple responses there can be many pressed buttons +//			// need to process them all +//			disableButtons(notification->getName(), response_it->first); +//		} +//	} +//} + +  //////////////////////////////////////////////////////////////////////////  LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, -										   bool show_images /* = true */) - : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images) +										   bool show_images /* = true */, LLTextBase* parent_text) +:	mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), +	mParentText(parent_text)  { -	mTextBox->setFollowsAll(); +	compactButtons();  }  LLIMToastNotifyPanel::~LLIMToastNotifyPanel()  { -	// We shouldn't delete notification when IM floater exists -	// since that notification will be reused by IM floater. -	// This may happened when IM floater reloads messages, exactly when user -	// changes layout of IM chat log(disable/enable plaintext mode). -	// See EXT-6500 -	LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); -	if (im_floater != NULL && !im_floater->isDead()) -	{ -		mCloseNotificationOnDestroy = false; -	}  }  void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +	{ +	LLToastPanel::reshape(width, height, called_from_parent); + +	snapToMessageHeight(mTextBox, MAX_LENGTH); +	} + +void LLIMToastNotifyPanel::compactButtons()  { -	S32 text_height = mTextBox->getTextBoundingRect().getHeight(); -	S32 widget_height = mTextBox->getRect().getHeight(); -	S32 delta = text_height - widget_height; -	LLRect rc = getRect(); +	mTextBox->setFollowsAll(); -	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); -	height = rc.getHeight(); -	width = rc.getWidth(); +	//we can't set follows in xml since it broke toasts behavior +	setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); -	bool is_width_changed = width != getRect().getWidth(); +	const child_list_t* children = getControlPanel()->getChildList(); +	S32 offset = 0; +	// Children were added by addChild() which uses push_front to insert them into list, +	// so to get buttons in correct order reverse iterator is used (EXT-5906)  +	for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++) +	{ +		LLButton * button = dynamic_cast<LLButton*> (*it); +		if (button != NULL) +		{ +			button->setOrigin( offset,button->getRect().mBottom); +			button->setLeftHPad(2 * HPAD); +			button->setRightHPad(2 * HPAD); +			// set zero width before perform autoResize() +			button->setRect(LLRect(button->getRect().mLeft, +				button->getRect().mTop,  +				button->getRect().mLeft, +				button->getRect().mBottom)); +			button->setAutoResize(true); +			button->autoResize(); +			offset += HPAD + button->getRect().getWidth(); +			button->setFollowsNone(); +		} +	} -	LLToastPanel::reshape(width, height, called_from_parent); +	if (mParentText) +	{ +		mParentText->needsReflow(); +	} +} -	// Notification height required to display the text message depends on -	// the width of the text box thus if panel width is changed the text box -	// width is also changed then reshape() is called to adjust proper height. -	if (is_width_changed) +void LLIMToastNotifyPanel::updateNotification()  	{ -		reshape(width, height, called_from_parent); +	init(LLRect(), true);  	} + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ +	LLToastNotifyPanel::init(LLRect(), show_images); + +	compactButtons();  } +  // EOF + diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index db517ec858..f93c7745af 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm;   * @deprecated this class will be removed after all toast panel types are   *  implemented in separate classes.   */ -class LLToastNotifyPanel: public LLToastPanel  +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID>  {  public:  	/** @@ -61,10 +61,14 @@ public:  	 * implement right class for desired toast panel. @see LLGenericTipPanel as example.  	 */  	LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + +	virtual void init( LLRect rect, bool show_images ); +  	virtual ~LLToastNotifyPanel();  	LLPanel * getControlPanel() { return mControlPanel; } -	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; } +	virtual void updateNotification() {} +  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,8 +80,6 @@ protected:  	};  	std::vector<InstanceAndS32*> mBtnCallbackData; -	bool mCloseNotificationOnDestroy; -  	typedef std::pair<int,LLButton*> index_button_pair_t;   	void adjustPanelForScriptNotice(S32 max_width, S32 max_height);  	void adjustPanelForTipNotice(); @@ -93,9 +95,9 @@ protected:  	/**  	 * Disable specific button(s) based on notification name and clicked button  	 */ -	void disableButtons(const std::string& notification_name, const std::string& selected_button); +	//void disableButtons(const std::string& notification_name, const std::string& selected_button); -	std::vector<index_button_pair_t> mButtons; +	//std::vector<index_button_pair_t> mButtons;  	// panel elements  	LLTextBase*		mTextBox; @@ -118,7 +120,7 @@ protected:  	/**  	 * Process response data. Will disable selected options  	 */ -	void disableRespondedOptions(const LLNotificationPtr& notification); +	//void disableRespondedOptions(const LLNotificationPtr& notification);  	bool mIsTip;  	bool mAddedDefaultBtn; @@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel  {  public: -	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true); +	LLIMToastNotifyPanel(LLNotificationPtr& pNotification,  +						const LLUUID& session_id,  +						const LLRect& rect = LLRect::null,  +						bool show_images = true,  +						LLTextBase* parent_text = NULL); + +	void compactButtons(); + +	virtual void updateNotification(); +	virtual void init( LLRect rect, bool show_images );  	~LLIMToastNotifyPanel();  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  protected: +	LLTextBase* mParentText;  	LLUUID	mSessionID;  }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index c33fde99c5..187aee207c 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -70,7 +70,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  	if (message->getVisible())  	{  		S32 heightDelta = 0; -		S32 maxTextHeight = message->getDefaultFont()->getLineHeight() * maxLineCount; +		S32 maxTextHeight = message->getFont()->getLineHeight() * maxLineCount;  		LLRect messageRect = message->getRect();  		S32 oldTextHeight = messageRect.getHeight(); @@ -80,11 +80,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  		S32 requiredTextHeight = message->getTextBoundingRect().getHeight();  		S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); -		//Calculate last delta height deducting previous heightDelta  -		heightDelta = newTextHeight - oldTextHeight - heightDelta; +		heightDelta = newTextHeight - oldTextHeight; +		S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT);  		//reshape the panel with new height -		reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); +		if (new_panel_height != getRect().getHeight()) +		{ +			reshape( getRect().getWidth(), new_panel_height); +		}  	}  } @@ -98,7 +101,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(  	if ("notifytip" == notification->getType())  	{  		// if it is online/offline notification -		if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) +		if ("FriendOnlineOffline" == notification->getName())  		{  			res = new LLPanelOnlineStatus(notification);  		} diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 346e014d73..c22557206b 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -33,19 +33,13 @@  #include <string> -class LLToastPanelBase: public LLPanel  -{ -public: -	virtual void init(LLSD& data){}; -}; -  /**   * Base class for all panels that can be added to the toast.   * All toast panels should contain necessary logic for representing certain notification   * but shouldn't contain logic related to this panel lifetime control and positioning   * on the parent view.   */ -class LLToastPanel: public LLPanel { +class LLToastPanel : public LLPanel {  public:  	LLToastPanel(const LLNotificationPtr&);  	virtual ~LLToastPanel() = 0; diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp index feeb8ca77b..91ba8c0247 100644 --- a/indra/newview/lltoastscriptquestion.cpp +++ b/indra/newview/lltoastscriptquestion.cpp @@ -66,8 +66,8 @@ void LLToastScriptQuestion::snapToMessageHeight()  	if (mMessage->getVisible() && mFooter->getVisible())  	{  		S32 heightDelta = 0; -		S32 maxTextHeight = (mMessage->getDefaultFont()->getLineHeight() * MAX_LINES_COUNT) -						  + (mFooter->getDefaultFont()->getLineHeight() * MAX_LINES_COUNT); +		S32 maxTextHeight = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) +						  + (mFooter->getFont()->getLineHeight() * MAX_LINES_COUNT);  		LLRect messageRect = mMessage->getRect();  		LLRect footerRect  = mFooter->getRect(); diff --git a/indra/newview/lltoastscripttextbox.cpp b/indra/newview/lltoastscripttextbox.cpp index 2529ec865a..45fbabad59 100644 --- a/indra/newview/lltoastscripttextbox.cpp +++ b/indra/newview/lltoastscripttextbox.cpp @@ -65,7 +65,7 @@ LLToastScriptTextbox::LLToastScriptTextbox(const LLNotificationPtr& notification  	pMessageText->clear();  	LLStyle::Params style; -	style.font = pMessageText->getDefaultFont(); +	style.font = pMessageText->getFont();  	pMessageText->appendText(message, TRUE, style);  	//submit button diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h index 8e69d8834d..7d33446248 100644 --- a/indra/newview/lltoastscripttextbox.h +++ b/indra/newview/lltoastscripttextbox.h @@ -39,8 +39,6 @@ class LLToastScriptTextbox  public:  	void close(); -	static bool onNewNotification(const LLSD& notification); -  	// Non-transient messages.  You can specify non-default button  	// layouts (like one for script dialogs) by passing various  	// numbers in for "layout". diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index 81ad96f39e..2b5acdc1e8 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -603,7 +603,7 @@ BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetTyp  BOOL LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar)  {  	BOOL handled = FALSE; -	LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; +	LLInventoryObject* inv_item = static_cast<LLInventoryObject*>(cargo_data);  	LLAssetType::EType type = inv_item->getType();  	if (type == LLAssetType::AT_WIDGET) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index c69999981c..94c97158a8 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -58,7 +58,6 @@  #include "llviewerwindow.h"  #include "llvoavatarself.h"  #include "llworld.h" -#include "llclipboard.h"  // syntactic sugar  #define callMemberFunction(object,ptrToMember)  ((object).*(ptrToMember)) @@ -654,33 +653,41 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  		sOperationId++;  	} +	// For people drag and drop we don't need an actual inventory object, +	// instead we need the current cargo id, which should be a person id. +	bool is_uuid_dragged = (mSource == SOURCE_PEOPLE); +  	if (top_view)  	{  		handled = TRUE;  		for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  		{ -			LLInventoryObject* cargo = locateInventory(item, cat); +			S32 local_x, local_y; +			top_view->screenPointToLocal( x, y, &local_x, &local_y ); +			EAcceptance item_acceptance = ACCEPT_NO; +			LLInventoryObject* cargo = locateInventory(item, cat);  			if (cargo)  			{ -				S32 local_x, local_y; -				top_view->screenPointToLocal( x, y, &local_x, &local_y ); -				EAcceptance item_acceptance = ACCEPT_NO;  				handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE,  													mCargoTypes[mCurItemIndex],  													(void*)cargo,  													&item_acceptance,  													mToolTipMsg); -				if (handled) -				{ -					// use sort order to determine priority of acceptance -					*acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); -				}  			} -			else +			else if (is_uuid_dragged)  			{ -				return;		 +				handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, +													mCargoTypes[mCurItemIndex], +													(void*)&mCargoIDs[mCurItemIndex], +													&item_acceptance, +													mToolTipMsg); +			} +			if (handled) +			{ +				// use sort order to determine priority of acceptance +				*acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);  			}  		} @@ -697,20 +704,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  			for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  			{ -				LLInventoryObject* cargo = locateInventory(item, cat); +				S32 local_x, local_y; +				EAcceptance item_acceptance; +				top_view->screenPointToLocal( x, y, &local_x, &local_y ); +				LLInventoryObject* cargo = locateInventory(item, cat);  				if (cargo)  				{ -					S32 local_x, local_y; - -					EAcceptance item_acceptance; -					top_view->screenPointToLocal( x, y, &local_x, &local_y );  					handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE,  														mCargoTypes[mCurItemIndex],  														(void*)cargo,  														&item_acceptance,  														mToolTipMsg);  				} +				else if (is_uuid_dragged) +				{ +					handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, +														mCargoTypes[mCurItemIndex], +														(void*)&mCargoIDs[mCurItemIndex], +														&item_acceptance, +														mToolTipMsg); +				}  			}  		}  		if (handled) @@ -727,17 +741,27 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  		for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  		{ +			EAcceptance item_acceptance = ACCEPT_NO; +  			LLInventoryObject* cargo = locateInventory(item, cat);  			// fix for EXT-3191 -			if (NULL == cargo) return; - -			EAcceptance item_acceptance = ACCEPT_NO; -			handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, -												mCargoTypes[mCurItemIndex], -												(void*)cargo, -												&item_acceptance, -												mToolTipMsg); +			if (cargo) +			{ +				handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, +													mCargoTypes[mCurItemIndex], +													(void*)cargo, +													&item_acceptance, +													mToolTipMsg); +			} +			else if (is_uuid_dragged) +			{ +				handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, +													mCargoTypes[mCurItemIndex], +													(void*)&mCargoIDs[mCurItemIndex], +													&item_acceptance, +													mToolTipMsg); +			}  			if (handled)  			{  				// use sort order to determine priority of acceptance @@ -757,17 +781,25 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  			for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)  			{ -				LLInventoryObject* cargo = locateInventory(item, cat); +				EAcceptance item_acceptance; +				LLInventoryObject* cargo = locateInventory(item, cat);  				if (cargo)  				{ -					EAcceptance item_acceptance;  					handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE,  											  mCargoTypes[mCurItemIndex],  											  (void*)cargo,  											  &item_acceptance,  											  mToolTipMsg);  				} +				else if (is_uuid_dragged) +				{ +					handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, +											  mCargoTypes[mCurItemIndex], +											  (void*)&mCargoIDs[mCurItemIndex], +											  &item_acceptance, +											  mToolTipMsg); +				}  			}  		} @@ -780,7 +812,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,  	if (!handled)  	{  		// Disallow drag and drop to 3D from the outbox -		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); +		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);  		if (outbox_id.notNull())  		{  			for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) @@ -2509,7 +2541,13 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(  {  	item = NULL;  	cat = NULL; -	if(mCargoIDs.empty()) return NULL; + +	if (mCargoIDs.empty() +		|| (mSource == SOURCE_PEOPLE)) ///< There is no inventory item for people drag and drop. +	{ +		return NULL; +	} +  	if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))  	{  		// The object should be in user inventory. @@ -2545,6 +2583,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(  	{  		item = (LLViewerInventoryItem*)gToolBarView->getDragItem();  	} +  	if(item) return item;  	if(cat) return cat;  	return NULL; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 41aee484db..f17300a76a 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -67,7 +67,8 @@ public:  		SOURCE_WORLD,  		SOURCE_NOTECARD,  		SOURCE_LIBRARY, -		SOURCE_VIEWER +		SOURCE_VIEWER, +		SOURCE_PEOPLE  	};  	void beginDrag(EDragAndDropType type, diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index a4b1c2155f..08ba5a5f25 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -83,6 +83,8 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()  	addEntry(LLViewerAssetType::AT_WIDGET, 				new ViewerAssetEntry(DAD_WIDGET)); +	addEntry(LLViewerAssetType::AT_PERSON, 				new ViewerAssetEntry(DAD_PERSON)); +  	addEntry(LLViewerAssetType::AT_NONE, 				new ViewerAssetEntry(DAD_NONE));  }; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1f7cf0cdd4..50735d10bd 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -50,6 +50,8 @@  #include "llfloaterbump.h"  #include "llfloaterbvhpreview.h"  #include "llfloatercamera.h" +#include "llfloaterconversationlog.h" +#include "llfloaterconversationpreview.h"  #include "llfloaterdeleteenvpreset.h"  #include "llfloaterdisplayname.h"  #include "llfloatereditdaycycle.h" @@ -114,6 +116,7 @@  #include "llfloatertranslationsettings.h"  #include "llfloateruipreview.h"  #include "llfloatervoiceeffect.h" +#include "llfloatervoicevolume.h"  #include "llfloaterwhitelistentry.h"  #include "llfloaterwindowsize.h"  #include "llfloaterworldmap.h" @@ -137,7 +140,6 @@  #include "llscriptfloater.h"  #include "llfloatermodelpreview.h"  #include "llcommandhandler.h" -#include "llnearbychatbar.h"  // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -190,9 +192,9 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);  	LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); -	LLFloaterReg::add("chat_bar", "floater_chat_bar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChatBar>); - +	LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);  	LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); +	LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>);  	LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); @@ -224,6 +226,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLInspectGroupUtil::registerFloater();  	LLInspectObjectUtil::registerFloater();  	LLInspectRemoteObjectUtil::registerFloater(); +	LLFloaterVoiceVolumeUtil::registerFloater();  	LLNotificationsUI::registerFloater();  	LLFloaterDisplayNameUtil::registerFloater(); @@ -268,6 +271,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("picks", "floater_picks.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);  	LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);  	LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview"); +	LLFloaterReg::add("preview_conversation", "floater_conversation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationPreview>);  	LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview");  	LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewNotecard>, "preview");  	LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLSL>, "preview"); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a32a78cbf9..c7d37e102e 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -40,7 +40,7 @@  #include "llviewermessage.h" // send_guid_sound_trigger  #include "llviewernetwork.h"  #include "llagent.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  // Globals  LLViewerGestureList gGestureList; @@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat )  	{  		// Don't play nodding animation, since that might not blend  		// with the gesture animation. -		LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); +		LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);  	}  } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b47a41c44c..a187318eb7 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1030,12 +1030,7 @@ void CreateGestureCallback::fire(const LLUUID& inv_item)  	gFloaterView->adjustToFitScreen(preview, FALSE);  } -void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) -{ -	if (mTargetLandmarkId.isNull()) return; -	gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); -}  LLInventoryCallbackManager gInventoryCallbacks; @@ -1308,7 +1303,7 @@ const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably  const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)  // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... -void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) +void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)  {  	std::string type_name = userdata.asString(); @@ -1332,7 +1327,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons  		LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);  		gInventory.notifyObservers(); -		root->setSelectionByID(category, TRUE); +		panel->setSelectionByID(category, TRUE);  	}  	else if ("lsl" == type_name)  	{ @@ -1375,7 +1370,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons  			llwarns << "Can't create unrecognized type " << type_name << llendl;  		}  	} -	root->setNeedsAutoRename(TRUE);	 +	panel->getRootFolder()->setNeedsAutoRename(TRUE);	  }  LLAssetType::EType LLViewerInventoryItem::getType() const @@ -1449,348 +1444,6 @@ const std::string& LLViewerInventoryItem::getName() const  	return  LLInventoryItem::getName();  } -/** - * Class to store sorting order of favorites landmarks in a local file. EXT-3985. - * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. - * Data are stored in user home directory. - */ -class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> -	, public LLDestroyClass<LLFavoritesOrderStorage> -{ -	LOG_CLASS(LLFavoritesOrderStorage); -public: -	/** -	 * Sets sort index for specified with LLUUID favorite landmark -	 */ -	void setSortIndex(const LLUUID& inv_item_id, S32 sort_index); - -	/** -	 * Gets sort index for specified with LLUUID favorite landmark -	 */ -	S32 getSortIndex(const LLUUID& inv_item_id); -	void removeSortIndex(const LLUUID& inv_item_id); - -	void getSLURL(const LLUUID& asset_id); - -	/** -	 * Implementation of LLDestroyClass. Calls cleanup() instance method. -	 * -	 * It is important this callback is called before gInventory is cleaned. -	 * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), -	 * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. -	 * @see cleanup() -	 */ -	static void destroyClass(); - -	const static S32 NO_INDEX; -private: -	friend class LLSingleton<LLFavoritesOrderStorage>; -	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } -	~LLFavoritesOrderStorage() { save(); } - -	/** -	 * Removes sort indexes for items which are not in Favorites bar for now. -	 */ -	void cleanup(); - -	const static std::string SORTING_DATA_FILE_NAME; - -	void load(); -	void save(); - -	void saveFavoritesSLURLs(); - -	// Remove record of current user's favorites from file on disk. -	void removeFavoritesRecordOfUser(); - -	void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark); -	void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); - -	typedef std::map<LLUUID, S32> sort_index_map_t; -	sort_index_map_t mSortIndexes; - -	typedef std::map<LLUUID, std::string> slurls_map_t; -	slurls_map_t mSLURLs; - -	bool mIsDirty; - -	struct IsNotInFavorites -	{ -		IsNotInFavorites(const LLInventoryModel::item_array_t& items) -			: mFavoriteItems(items) -		{ - -		} - -		/** -		 * Returns true if specified item is not found among inventory items -		 */ -		bool operator()(const sort_index_map_t::value_type& id_index_pair) const -		{ -			LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); -			if (item.isNull()) return true; - -			LLInventoryModel::item_array_t::const_iterator found_it = -				std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); - -			return found_it == mFavoriteItems.end(); -		} -	private: -		LLInventoryModel::item_array_t mFavoriteItems; -	}; - -}; - -const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; -const S32 LLFavoritesOrderStorage::NO_INDEX = -1; - -void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index) -{ -	mSortIndexes[inv_item_id] = sort_index; -	mIsDirty = true; -} - -S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) -{ -	sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); -	if (it != mSortIndexes.end()) -	{ -		return it->second; -	} -	return NO_INDEX; -} - -void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) -{ -	mSortIndexes.erase(inv_item_id); -	mIsDirty = true; -} - -void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) -{ -	slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); -	if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached - -	LLLandmark* lm = gLandmarkList.getAsset(asset_id, -			boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); -	if (lm) -	{ -		onLandmarkLoaded(asset_id, lm); -	} -} - -// static -void LLFavoritesOrderStorage::destroyClass() -{ -	LLFavoritesOrderStorage::instance().cleanup(); -	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) -	{ -		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); -	} -	else -	{ -		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); -	} -} - -void LLFavoritesOrderStorage::load() -{ -	// load per-resident sorting information -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); - -	LLSD settings_llsd; -	llifstream file; -	file.open(filename); -	if (file.is_open()) -	{ -		LLSDSerialize::fromXML(settings_llsd, file); -	} - -	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); -		iter != settings_llsd.endMap(); ++iter) -	{ -		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); -	} -} - -void LLFavoritesOrderStorage::saveFavoritesSLURLs() -{ -	// Do not change the file if we are not logged in yet. -	if (!LLLoginInstance::getInstance()->authSuccess()) -	{ -		llwarns << "Cannot save favorites: not logged in" << llendl; -		return; -	} -	 -	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); -	if (user_dir.empty()) -	{ -		llwarns << "Cannot save favorites: empty user dir name" << llendl; -		return; -	} - -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); -	llifstream in_file; -	in_file.open(filename); -	LLSD fav_llsd; -	if (in_file.is_open()) -	{ -		LLSDSerialize::fromXML(fav_llsd, in_file); -	} - -	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -	LLSD user_llsd; -	for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) -	{ -		LLSD value; -		value["name"] = (*it)->getName(); -		value["asset_id"] = (*it)->getAssetUUID(); - -		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); -		if (slurl_iter != mSLURLs.end()) -		{ -			lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl; -			value["slurl"] = slurl_iter->second; -			user_llsd[(*it)->getSortField()] = value; -		} -		else -		{ -			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; -		} -	} - -	LLAvatarName av_name; -	LLAvatarNameCache::get( gAgentID, &av_name ); -	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl; -	fav_llsd[av_name.getLegacyName()] = user_llsd; - -	llofstream file; -	file.open(filename); -	LLSDSerialize::toPrettyXML(fav_llsd, file); -} - -void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() -{ -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); -	LLSD fav_llsd; -	llifstream file; -	file.open(filename); -	if (!file.is_open()) return; -	LLSDSerialize::fromXML(fav_llsd, file); - -	LLAvatarName av_name; -	LLAvatarNameCache::get( gAgentID, &av_name ); -	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl; -	if (fav_llsd.has(av_name.getLegacyName())) -	{ -		fav_llsd.erase(av_name.getLegacyName()); -	} - -	llofstream out_file; -	out_file.open(filename); -	LLSDSerialize::toPrettyXML(fav_llsd, out_file); - -} - -void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) -{ -	if (!landmark) return; - -	LLVector3d pos_global; -	if (!landmark->getGlobalPos(pos_global)) -	{ -		// If global position was unknown on first getGlobalPos() call -		// it should be set for the subsequent calls. -		landmark->getGlobalPos(pos_global); -	} - -	if (!pos_global.isExactlyZero()) -	{ -		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, -				boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); -	} -} - -void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) -{ -	lldebugs << "Saving landmark SLURL: " << slurl << llendl; -	mSLURLs[asset_id] = slurl; -} - -void LLFavoritesOrderStorage::save() -{ -	// nothing to save if clean -	if (!mIsDirty) return; - -	// If we quit from the login screen we will not have an SL account -	// name.  Don't try to save, otherwise we'll dump a file in -	// C:\Program Files\SecondLife\ or similar. JC -	std::string user_dir = gDirUtilp->getLindenUserDir(); -	if (!user_dir.empty()) -	{ -		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); -		LLSD settings_llsd; - -		for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) -		{ -			settings_llsd[iter->first.asString()] = iter->second; -		} - -		llofstream file; -		file.open(filename); -		LLSDSerialize::toPrettyXML(settings_llsd, file); -	} -} - -void LLFavoritesOrderStorage::cleanup() -{ -	// nothing to clean -	if (!mIsDirty) return; - -	const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -	LLInventoryModel::cat_array_t cats; -	LLInventoryModel::item_array_t items; -	gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -	IsNotInFavorites is_not_in_fav(items); - -	sort_index_map_t  aTempMap; -	//copy unremoved values from mSortIndexes to aTempMap -	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  -		inserter(aTempMap, aTempMap.begin()), -		is_not_in_fav); - -	//Swap the contents of mSortIndexes and aTempMap -	mSortIndexes.swap(aTempMap); -} - - -S32 LLViewerInventoryItem::getSortField() const -{ -	return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); -} - -void LLViewerInventoryItem::setSortField(S32 sortField) -{ -	LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); -	getSLURL(); -} - -void LLViewerInventoryItem::getSLURL() -{ -	LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); -} - -const LLPermissions& LLViewerInventoryItem::getPermissions() const -{ -	// Use the actual permissions of the symlink, not its parent. -	return LLInventoryItem::getPermissions();	 -} -  const LLUUID& LLViewerInventoryItem::getCreatorUUID() const  {  	if (const LLViewerInventoryItem *linked_item = getLinkedItem()) @@ -1861,17 +1514,6 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const  	return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);  } - -time_t LLViewerInventoryItem::getCreationDate() const -{ -	return LLInventoryItem::getCreationDate(); -} - -U32 LLViewerInventoryItem::getCRC32() const -{ -	return LLInventoryItem::getCRC32();	 -} -  // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985  static char getSeparator() { return '@'; }  BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7822ef4da6..3cf03c3bc5 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -34,7 +34,7 @@  #include <boost/signals2.hpp>	// boost::signals2::trackable -class LLFolderView; +class LLInventoryPanel;  class LLFolderBridge;  class LLViewerInventoryCategory; @@ -60,10 +60,6 @@ public:  	virtual const LLUUID& getAssetUUID() const;  	virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user  	virtual const std::string& getName() const; -	virtual S32 getSortField() const; -	virtual void setSortField(S32 sortField); -	virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. -	virtual const LLPermissions& getPermissions() const;  	virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied  	virtual const LLUUID& getCreatorUUID() const;  	virtual const std::string& getDescription() const; @@ -72,8 +68,11 @@ public:  	virtual bool isWearableType() const;  	virtual LLWearableType::EType getWearableType() const;  	virtual U32 getFlags() const; -	virtual time_t getCreationDate() const; -	virtual U32 getCRC32() const; // really more of a checksum. + +    using LLInventoryItem::getPermissions; +	using LLInventoryItem::getCreationDate; +	using LLInventoryItem::setCreationDate; +	using LLInventoryItem::getCRC32;  	static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); @@ -285,18 +284,6 @@ public:  	void fire(const LLUUID& inv_item);  }; -class AddFavoriteLandmarkCallback : public LLInventoryCallback -{ -public: -	AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} -	void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } - -private: -	void fire(const LLUUID& inv_item); - -	LLUUID mTargetLandmarkId; -}; -  // misc functions  //void inventory_reliable_callback(void**, S32 status); @@ -372,7 +359,7 @@ void copy_inventory_from_notecard(const LLUUID& destination_id,  								  U32 callback_id = 0); -void menu_create_inventory_item(LLFolderView* root, +void menu_create_inventory_item(LLInventoryPanel* root,  								LLFolderBridge* bridge,  								const LLSD& userdata,  								const LLUUID& default_parent_uuid = LLUUID::null); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 1aa9fd8a45..385d3cd29a 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -31,7 +31,7 @@  #include "llmath.h"  #include "llagent.h"  #include "llagentcamera.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llviewercontrol.h"  #include "llfocusmgr.h"  #include "llmorphview.h" @@ -534,7 +534,7 @@ void stop_moving( EKeystate s )  void start_chat( EKeystate s )  {  	// start chat -	LLNearbyChatBar::startChat(NULL); +	LLNearbyChat::startChat(NULL);  }  void start_gesture( EKeystate s ) @@ -543,15 +543,15 @@ void start_gesture( EKeystate s )  	if (KEYSTATE_UP == s &&  		! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))  	{ - 		if (LLNearbyChatBar::getInstance()->getCurrentChat().empty()) + 		if (LLNearbyChat::getInstance()->getCurrentChat().empty())   		{   			// No existing chat in chat editor, insert '/' - 			LLNearbyChatBar::startChat("/"); + 			LLNearbyChat::startChat("/");   		}   		else   		{   			// Don't overwrite existing text in chat editor - 			LLNearbyChatBar::startChat(NULL); + 			LLNearbyChat::startChat(NULL);   		}  	}  } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 01a54509ef..a993d195b5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3263,15 +3263,6 @@ bool enable_freeze_eject(const LLSD& avatar_id)  	return new_value;  } - -void login_done(S32 which, void *user) -{ -	llinfos << "Login done " << which << llendl; - -	LLPanelLogin::closePanel(); -} - -  bool callback_leave_group(const LLSD& notification, const LLSD& response)  {  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 903f4437a7..b20b86a582 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -184,6 +184,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	LLMessageSystem* msg = gMessageSystem;  	const LLSD& payload = notification["payload"]; +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());  	// add friend to recent people list  	LLRecentPeople::instance().add(payload["from_id"]); @@ -209,7 +210,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		msg->sendReliable(LLHost(payload["sender"].asString()));  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipAcceptedByMe",  				notification["substitutions"], payload);  		break; @@ -217,7 +217,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	case 1: // Decline  	{  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipDeclinedByMe",  				notification["substitutions"], payload);  	} @@ -246,6 +245,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		break;  	} +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Accept", false); +	modified_form->setElementEnabled("Decline", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); @@ -726,7 +731,7 @@ static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& item  		LLFolderView* fv = inventory_panel->getRootFolder();  		if (fv)  		{ -			LLFolderViewItem* fv_item = fv->getItemByID(item_id); +			LLFolderViewItem* fv_item = inventory_panel->getItemByID(item_id);  			if (fv_item)  			{  				LLFolderViewItem* fv_folder = fv_item->getParentFolder(); @@ -814,7 +819,13 @@ private:  		mSelectedItems.clear();  		if (LLInventoryPanel::getActiveInventoryPanel())  		{ -			mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +			std::set<LLFolderViewItem*> selection =    LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +			for (std::set<LLFolderViewItem*>::iterator it = selection.begin(),    end_it = selection.end(); +				it != end_it; +				++it) +			{ +				mSelectedItems.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +			}  		}  		mSelectedItems.erase(mMoveIntoFolderID);  	} @@ -849,7 +860,15 @@ private:  		}  		// get selected items (without destination folder) -		selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList(); +		selected_items_t selected_items; + 		 + 		std::set<LLFolderViewItem*> selection =    LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); +		for (std::set<LLFolderViewItem*>::iterator it = selection.begin(),    end_it = selection.end(); +			it != end_it; +			++it) +		{ +			selected_items.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID()); +		}  		selected_items.erase(mMoveIntoFolderID);  		// compare stored & current sets of selected items @@ -1155,7 +1174,7 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)  		}  	}  } - +   // Return "true" if we have a preview method for that asset type, "false" otherwise  bool check_asset_previewable(const LLAssetType::EType asset_type)  { @@ -1478,16 +1497,15 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);  	} +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); +	  	// For muting, we need to add the mute, then decline the offer.  	// This must be done here because:  	// * callback may be called immediately,  	// * adding the mute sends a message,  	// * we can't build two messages at once. -	if (2 == button) // Block +	if (IOR_MUTE == button) // Block  	{ -		LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - -		llassert(notification_ptr != NULL);  		if (notification_ptr != NULL)  		{  			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); @@ -1502,6 +1520,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	bool busy = gAgent.getBusy(); +	LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm()); +  	switch(button)  	{  	case IOR_SHOW: @@ -1545,6 +1565,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break;  		} + +		if (modified_form != NULL) +		{ +			modified_form->setElementEnabled("Show", false); +		}  		break;  		// end switch (mIM) @@ -1557,9 +1582,14 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			args["MESSAGE"] = log_message;  			LLNotificationsUtil::add("SystemMessageTip", args);  		} +  		break;  	case IOR_MUTE: +		if (modified_form != NULL) +		{ +			modified_form->setElementEnabled("Mute", false); +		}  		// MUTE falls through to decline  	case IOR_DECLINE:  		{ @@ -1595,6 +1625,13 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			{  				busy_message(gMessageSystem, mFromID);  			} + +			if (modified_form != NULL) +			{ +				modified_form->setElementEnabled("Show", false); +				modified_form->setElementEnabled("Discard", false); +			} +  			break;  		}  	default: @@ -1614,6 +1651,13 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	{  		delete this;  	} + +	if (notification_ptr != NULL) +	{ +		notification_ptr->updateForm(modified_form); +		notification_ptr->repost(); +	} +  	return false;  } @@ -1991,6 +2035,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response)  					   lure_id);  		break;  	} + +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Teleport", false); +	modified_form->setElementEnabled("Cancel", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); @@ -2386,6 +2439,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				from_id,  				name,  				buffer, +				IM_OFFLINE == offline,  				LLStringUtil::null,  				dialog,  				parent_estate_id, @@ -2420,12 +2474,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;  			bool mute_im = is_muted; -			if (accept_im_from_only_friend && !is_friend) +			if(accept_im_from_only_friend&&!is_friend)  			{  				if (!gIMMgr->isNonFriendSessionNotified(session_id))  				{  					std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); -					gIMMgr->addMessage(session_id, from_id, name, message); +					gIMMgr->addMessage(session_id, from_id, name, message, IM_OFFLINE == offline);  					gIMMgr->addNotifiedNonFriendSessionID(session_id);  				} @@ -2438,6 +2492,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  					from_id,  					name,  					buffer, +					IM_OFFLINE == offline,  					LLStringUtil::null,  					dialog,  					parent_estate_id, @@ -2778,6 +2833,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			from_id,  			name,  			buffer, +			IM_OFFLINE == offline,  			ll_safe_string((char*)binary_bucket),  			IM_SESSION_INVITE,  			parent_estate_id, @@ -2847,7 +2903,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				chat.mOwnerID = from_id;  				LLSD args;  				args["slurl"] = location; -				args["type"] = LLNotificationsUI::NT_NEARBYCHAT;  				// Look for IRC-style emotes here so object name formatting is correct  				std::string prefix = message.substr(0, 4); @@ -3591,7 +3646,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)  		// pass owner_id to chat so that we can display the remote  		// object inspect for an object that is chatting with you  		LLSD args; -		args["type"] = LLNotificationsUI::NT_NEARBYCHAT;  		chat.mOwnerID = owner_id;  		if (gSavedSettings.getBOOL("TranslateChat") && chat.mSourceType != CHAT_SOURCE_SYSTEM) @@ -6798,7 +6852,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  				//*TODO please rewrite all keys to the same case, lower or upper  				payload["from_id"] = target_id; -				payload["SUPPRESS_TOAST"] = true;  				LLNotificationsUtil::add("TeleportOfferSent", args, payload);  				// Add the recepient to the recent people list. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index af2eec9ba8..1bcf15913f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -56,6 +56,7 @@  // linden library includes  #include "llaudioengine.h"		// mute on minimize +#include "llchatentry.h"  #include "indra_constants.h"  #include "llassetstorage.h"  #include "llerrorcontrol.h" @@ -187,7 +188,7 @@  #include "llviewerjoystick.h"  #include "llviewernetwork.h"  #include "llpostprocess.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llagentui.h"  #include "llwearablelist.h" @@ -1550,11 +1551,12 @@ LLViewerWindow::LLViewerWindow(const Params& p)  	// boost::lambda::var() constructs such a functor on the fly.  	mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard)));  	mViewerWindowListener.reset(new LLViewerWindowListener(this)); -	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); -	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); -	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert); -	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert); +	mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); +	mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); + +	mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); +	mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert);  	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));  	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl; @@ -2495,11 +2497,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// Traverses up the hierarchy  	if( keyboard_focus )  	{ -		LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar"); +		LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar");  		if (nearby_chat)  		{ -			LLLineEditor* chat_editor = nearby_chat->getChatBox(); +			LLChatEntry* chat_editor = nearby_chat->getChatBox();  		// arrow keys move avatar while chatting hack  		if (chat_editor && chat_editor->hasFocus()) @@ -2562,11 +2564,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&   		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )  	{ -		LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox(); +		LLChatEntry* chat_editor = LLNearbyChat::getInstance()->getChatBox();  		if (chat_editor)  		{  			// passing NULL here, character will be added later when it is handled by character handler. -			LLNearbyChatBar::getInstance()->startChat(NULL); +			LLNearbyChat::getInstance()->startChat(NULL);  			return TRUE;  		}  	} diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6efcaeaf18..ee6a7793f8 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -418,6 +418,9 @@ private:  	bool			mActive;  	bool			mUIVisible; +	boost::shared_ptr<class LLNotificationChannel>	mAlertsChannel, +													mModalAlertsChannel; +  	LLRect			mWindowRectRaw;				// whole window, including UI  	LLRect			mWindowRectScaled;			// whole window, scaled by UI size  	LLRect			mWorldViewRectRaw;			// area of screen for 3D world diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 05febdf93b..54465ba731 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -34,6 +34,8 @@  #include "llvoavatar.h" +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot +  #include <stdio.h>  #include <ctype.h> @@ -62,6 +64,7 @@  #include "llhudmanager.h"  #include "llhudnametag.h"  #include "llhudtext.h"				// for mText/mDebugText +#include "llinitparam.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h"  #include "llkeyframewalkmotion.h" @@ -191,6 +194,9 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN;  const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12;  const F32 CHAT_FADE_TIME = 8.0;  const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f;  const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -222,55 +228,62 @@ struct LLTextureMaskData   **/  //------------------------------------------------------------------------ -// LLVOBoneInfo +// LLVOAvatarBoneInfo  // Trans/Scale/Rot etc. info about each avatar bone.  Used by LLVOAvatarSkeleton.  //------------------------------------------------------------------------ -class LLVOAvatarBoneInfo +struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarCollisionVolumeInfo>  { -	friend class LLVOAvatar; -	friend class LLVOAvatarSkeletonInfo; -public: -	LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} -	~LLVOAvatarBoneInfo() +	LLVOAvatarCollisionVolumeInfo()  +	:	name("name"), +		pos("pos"), +		rot("rot"), +		scale("scale") +	{} + +	Mandatory<std::string>	name; +	Mandatory<LLVector3>	pos, +							rot, +							scale; +}; + +struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint>  	{ -		std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); -	} -	BOOL parseXml(LLXmlTreeNode* node); +	Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> >	bone; +	Alternative<LLVOAvatarCollisionVolumeInfo>		collision_volume; -private: -	std::string mName; -	BOOL mIsJoint; -	LLVector3 mPos; -	LLVector3 mRot; -	LLVector3 mScale; -	LLVector3 mPivot; -	typedef std::vector<LLVOAvatarBoneInfo*> child_list_t; -	child_list_t mChildList; +	LLVOAvatarChildJoint() +	:	bone("bone"), +		collision_volume("collision_volume") +	{} +}; + +struct LLVOAvatarBoneInfo : public LLInitParam::Block<LLVOAvatarBoneInfo, LLVOAvatarCollisionVolumeInfo> +{ +	LLVOAvatarBoneInfo()  +	:	pivot("pivot") +	{} +	 +	Mandatory<LLVector3>					pivot; +	Multiple<LLVOAvatarChildJoint>			children;  };  //------------------------------------------------------------------------  // LLVOAvatarSkeletonInfo  // Overall avatar skeleton  //------------------------------------------------------------------------ -class LLVOAvatarSkeletonInfo +struct LLVOAvatarSkeletonInfo : public LLInitParam::Block<LLVOAvatarSkeletonInfo>  { -	friend class LLVOAvatar; -public: -	LLVOAvatarSkeletonInfo() : -		mNumBones(0), mNumCollisionVolumes(0) {} -	~LLVOAvatarSkeletonInfo() -	{ -		std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); -	} -	BOOL parseXml(LLXmlTreeNode* node); -	S32 getNumBones() const { return mNumBones; } -	S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } +	LLVOAvatarSkeletonInfo() +	:	skeleton_root(""), +		num_bones("num_bones"), +		num_collision_volumes("num_collision_volumes"), +		version("version") +	{} -private: -	S32 mNumBones; -	S32 mNumCollisionVolumes; -	typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t; -	bone_info_list_t mBoneInfoList; +	Mandatory<std::string>			version; +	Mandatory<S32>					num_bones, +									num_collision_volumes; +	Mandatory<LLVOAvatarChildJoint>	skeleton_root;  };  //----------------------------------------------------------------------------- @@ -595,7 +608,7 @@ private:  // Static Data  //-----------------------------------------------------------------------------  LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; +LLXMLNodePtr LLVOAvatar::sSkeletonXMLTree;  LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;  LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;  LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; @@ -698,9 +711,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	//VTResume();  // VTune +#ifdef XXX_STINSON_CHUI_REWORK  	// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline  	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job  	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); +#else // XXX_STINSON_CHUI_REWORK +	mVoiceVisualizer = new LLVoiceVisualizer(); +#endif // XXX_STINSON_CHUI_REWORK  	lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; @@ -805,14 +822,14 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c  //------------------------------------------------------------------------  LLVOAvatar::~LLVOAvatar()  { -	if (!mFullyLoaded) -	{ +		if (!mFullyLoaded) +		{  		debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); -	} -	else -	{ +		} +		else +		{  		debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); -	} +		}  	lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; @@ -876,7 +893,11 @@ void LLVOAvatar::markDead()  		mNameText = NULL;  		sNumVisibleChatBubbles--;  	} +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceVisualizer->markDead(); +#else // XXX_STINSON_CHUI_REWORK +	mVoiceVisualizer->setStopSpeaking(); +#endif // XXX_STINSON_CHUI_REWORK  	LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;  	LLViewerObject::markDead();  } @@ -1214,18 +1235,6 @@ void LLVOAvatar::initClass()  		llerrs << "Error parsing skeleton file: " << skeleton_path << llendl;  	} -	// Process XML data - -	// avatar_skeleton.xml -	if (sAvatarSkeletonInfo) -	{ //this can happen if a login attempt failed -		delete sAvatarSkeletonInfo; -	} -	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; -	if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) -	{ -		llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; -	}  	// parse avatar_lad.xml  	if (sAvatarXmlInfo)  	{ //this can happen if a login attempt failed @@ -1274,7 +1283,7 @@ void LLVOAvatar::initClass()  void LLVOAvatar::cleanupClass()  {  	deleteAndClear(sAvatarXmlInfo); -	sSkeletonXMLTree.cleanup(); +	sSkeletonXMLTree = NULL;  	sXMLTree.cleanup();  } @@ -1420,7 +1429,9 @@ void LLVOAvatar::initInstance(void)  	//VTPause();  // VTune +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); +#endif // XXX_STINSON_CHUI_REWORK  } @@ -1744,33 +1755,39 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)  	//-------------------------------------------------------------------------  	// parse the file  	//------------------------------------------------------------------------- -	BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); -	if (!parsesuccess) +	LLXMLNodePtr skeleton_xml; +	BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); + +	if (!parsesuccess || skeleton_xml.isNull())  	{  		llerrs << "Can't parse skeleton file: " << filename << llendl;  		return FALSE;  	} -	// now sanity check xml file -	LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); -	if (!root)  +	// Process XML data +	if (sAvatarSkeletonInfo) +	{ //this can happen if a login attempt failed +		delete sAvatarSkeletonInfo; +	} +	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + +	LLXUIParser parser; +	parser.readXUI(skeleton_xml, *sAvatarSkeletonInfo, filename); +	if (!sAvatarSkeletonInfo->validateBlock())  	{ -		llerrs << "No root node found in avatar skeleton file: " << filename << llendl; -		return FALSE; +		llerrs << "Error parsing skeleton XML file: " << filename << llendl;  	} -	if( !root->hasName( "linden_skeleton" ) ) +	if( !skeleton_xml->hasName( "linden_skeleton" ) )  	{  		llerrs << "Invalid avatar skeleton file header: " << filename << llendl;  		return FALSE;  	} -	std::string version; -	static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); -	if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) +	if (sAvatarSkeletonInfo->version() != "1.0")  	{ -		llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; +		llerrs << "Invalid avatar skeleton file version: " << sAvatarSkeletonInfo->version() << " in file: " << filename << llendl;  		return FALSE;  	} @@ -1779,14 +1796,13 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)  //-----------------------------------------------------------------------------  // setupBone() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) +//----------------------------------------------------------- +BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num)  {  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	LLViewerJoint* joint = NULL; - -	if (info->mIsJoint) +	if (info.bone.isChosen())  	{  		joint = (LLViewerJoint*)getCharacterJoint(joint_num);  		if (!joint) @@ -1794,7 +1810,23 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  			llwarns << "Too many bones" << llendl;  			return FALSE;  		} -		joint->setName( info->mName ); +		joint->setName( info.bone().name ); +		joint->setPosition(info.bone().pos); +		joint->setRotation(mayaQ(info.bone().rot().mV[VX], info.bone().rot().mV[VY], info.bone().rot().mV[VZ], LLQuaternion::XYZ)); +		joint->setScale(info.bone().scale); +		joint->setSkinOffset( info.bone().pivot ); +		joint_num++; + +		for (LLInitParam::ParamIterator<LLVOAvatarChildJoint>::const_iterator child_it = info.bone().children.begin(), +				end_it = info.bone().children.end(); +			child_it != end_it; +			++child_it) +		{ +			if (!setupBone(*child_it, joint, volume_num, joint_num)) +			{ +				return FALSE; +			} +	}  	}  	else // collision volume  	{ @@ -1804,7 +1836,11 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  			return FALSE;  		}  		joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); -		joint->setName( info->mName ); +		joint->setName( info.collision_volume.name); +		joint->setPosition(info.collision_volume.pos); +		joint->setRotation(mayaQ(info.collision_volume.rot().mV[VX], info.collision_volume.rot().mV[VY], info.collision_volume.rot().mV[VZ], LLQuaternion::XYZ)); +		joint->setScale(info.collision_volume.scale); +		volume_num++;  	}  	// add to parent @@ -1813,34 +1849,8 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  		parent->addChild( joint );  	} -	joint->setPosition(info->mPos); -	joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], -							 info->mRot.mV[VZ], LLQuaternion::XYZ)); -	joint->setScale(info->mScale); -  	joint->setDefaultFromCurrentXform(); -	if (info->mIsJoint) -	{ -		joint->setSkinOffset( info->mPivot ); -		joint_num++; -	} -	else // collision volume -	{ -		volume_num++; -	} - -	// setup children -	LLVOAvatarBoneInfo::child_list_t::const_iterator iter; -	for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) -	{ -		LLVOAvatarBoneInfo *child_info = *iter; -		if (!setupBone(child_info, joint, volume_num, joint_num)) -		{ -			return FALSE; -		} -	} -  	return TRUE;  } @@ -1854,36 +1864,32 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)  	//-------------------------------------------------------------------------  	// allocate joints  	//------------------------------------------------------------------------- -	if (!allocateCharacterJoints(info->mNumBones)) +	if (!allocateCharacterJoints(info->num_bones))  	{ -		llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; +		llerrs << "Can't allocate " << info->num_bones() << " joints" << llendl;  		return FALSE;  	}  	//-------------------------------------------------------------------------  	// allocate volumes  	//------------------------------------------------------------------------- -	if (info->mNumCollisionVolumes) +	if (info->num_collision_volumes)  	{ -		if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) +		if (!allocateCollisionVolumes(info->num_collision_volumes))  		{ -			llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; +			llerrs << "Can't allocate " << info->num_collision_volumes() << " collision volumes" << llendl;  			return FALSE;  		}  	}  	S32 current_joint_num = 0;  	S32 current_volume_num = 0; -	LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; -	for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + +	if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num))  	{ -		LLVOAvatarBoneInfo *info = *iter; -		if (!setupBone(info, NULL, current_volume_num, current_joint_num)) -		{  			llerrs << "Error parsing bone in skeleton file" << llendl;  			return FALSE;  		} -	}  	return TRUE;  } @@ -2096,15 +2102,15 @@ void LLVOAvatar::releaseMeshData()  		LLFace* facep = mDrawable->getFace(0);  		if (facep)  		{ -			facep->setSize(0, 0); -			for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) -			{ -				facep = mDrawable->getFace(i); +		facep->setSize(0, 0); +		for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) +		{ +			facep = mDrawable->getFace(i);  				if (facep)  				{ -					facep->setSize(0, 0); -				} -			} +			facep->setSize(0, 0); +		} +	}  		}  	} @@ -2353,11 +2359,11 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,  	U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);  	// Print out arrival information once we have name of avatar. -	if (has_name && getNVPair("FirstName")) -	{ -		mDebugExistenceTimer.reset(); +		if (has_name && getNVPair("FirstName")) +		{ +			mDebugExistenceTimer.reset();  		debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); -	} +		}  	if(retval & LLViewerObject::INVALID_UPDATE)  	{ @@ -2525,6 +2531,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  { +#ifdef XXX_STINSON_CHUI_REWORK  	bool render_visualizer = voice_enabled;  	// Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. @@ -2537,6 +2544,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  	}  	mVoiceVisualizer->setVoiceEnabled(render_visualizer); +#endif // XXX_STINSON_CHUI_REWORK  	if ( voice_enabled )  	{		 @@ -2612,6 +2620,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  			}  		} +#ifdef XXX_STINSON_CHUI_REWORK  		//--------------------------------------------------------------------------------------------  		// here we get the approximate head position and set as sound source for the voice symbol  		// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) @@ -2629,6 +2638,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  			tagPos[VZ] += ( mBodySize[VZ] + 0.125f );  			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );  		} +#endif // XXX_STINSON_CHUI_REWORK  	}//if ( voiceEnabled )  }		 @@ -2868,8 +2878,8 @@ void LLVOAvatar::idleUpdateLoadingEffect()  		{  			LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL;  			mFirstFullyVisible = FALSE; -			LLAppearanceMgr::instance().onFirstFullyVisible(); -		} +				LLAppearanceMgr::instance().onFirstFullyVisible(); +			}  		if (isFullyLoaded() && mFirstFullyVisible && !isSelf())  		{  			LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; @@ -3017,43 +3027,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  		return;  	} -	BOOL new_name = FALSE; -	if (visible_chat != mVisibleChat) -	{ -		mVisibleChat = visible_chat; -		new_name = TRUE; -	} -		 -	if (sRenderGroupTitles != mRenderGroupTitles) -	{ -		mRenderGroupTitles = sRenderGroupTitles; -		new_name = TRUE; -	} - -	// First Calculate Alpha -	// If alpha > 0, create mNameText if necessary, otherwise delete it -	F32 alpha = 0.f; -	if (mAppAngle > 5.f) -	{ -		const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; -		if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) +		BOOL new_name = FALSE; +		if (visible_chat != mVisibleChat)  		{ -			alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; +			mVisibleChat = visible_chat; +			new_name = TRUE;  		} -		else +		 +		if (sRenderGroupTitles != mRenderGroupTitles)  		{ -			// ...not fading, full alpha -			alpha = 1.f; +			mRenderGroupTitles = sRenderGroupTitles; +			new_name = TRUE;  		} -	} -	else if (mAppAngle > 2.f) -	{ -		// far away is faded out also -		alpha = (mAppAngle-2.f)/3.f; -	} + +		// First Calculate Alpha +		// If alpha > 0, create mNameText if necessary, otherwise delete it +			F32 alpha = 0.f; +			if (mAppAngle > 5.f) +			{ +				const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; +				if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) +				{ +					alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; +				} +				else +				{ +					// ...not fading, full alpha +					alpha = 1.f; +				} +			} +			else if (mAppAngle > 2.f) +			{ +				// far away is faded out also +				alpha = (mAppAngle-2.f)/3.f; +			}  	if (alpha <= 0.f) -	{ +			{  		if (mNameText)  		{  			mNameText->markDead(); @@ -3063,22 +3073,21 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  		return;  	} -	if (!mNameText) -	{ +				if (!mNameText) +				{  		mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject( -													LLHUDObject::LL_HUD_NAME_TAG) ); +			LLHUDObject::LL_HUD_NAME_TAG) );  		//mNameText->setMass(10.f); -		mNameText->setSourceObject(this); +					mNameText->setSourceObject(this);  		mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); -		mNameText->setVisibleOffScreen(TRUE); -		mNameText->setMaxLines(11); -		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); -		sNumVisibleChatBubbles++; -		new_name = TRUE; -	} +					mNameText->setVisibleOffScreen(TRUE); +					mNameText->setMaxLines(11); +					mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); +					sNumVisibleChatBubbles++; +					new_name = TRUE; +				} -	LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); -	mNameText->setPositionAgent(name_position);				 +	idleUpdateNameTagPosition(root_pos_last);  	idleUpdateNameTagText(new_name);			  	idleUpdateNameTagAlpha(new_name, alpha);  } @@ -3166,7 +3175,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			// trim last ", "  			line.resize( line.length() - 2 );  			addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, -						   LLFontGL::getFontSansSerifSmall()); +				LLFontGL::getFontSansSerifSmall());  		}  		if (sRenderGroupTitles @@ -3175,7 +3184,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			std::string title_str = title->getString();  			LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);  			addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, -						   LLFontGL::getFontSansSerifSmall()); +				LLFontGL::getFontSansSerifSmall());  		}  		static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames"); @@ -3189,14 +3198,14 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  				// ...call this function back when the name arrives  				// and force a rebuild  				LLAvatarNameCache::get(getID(), -									   boost::bind(&LLVOAvatar::clearNameTag, this)); +					boost::bind(&LLVOAvatar::clearNameTag, this));  			}  			// Might be blank if name not available yet, that's OK  			if (show_display_names)  			{  				addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL, -							   LLFontGL::getFontSansSerif()); +					LLFontGL::getFontSansSerif());  			}  			// Suppress SLID display if display name matches exactly (ugh)  			if (show_usernames && !av_name.mIsDisplayNameDefault) @@ -3204,14 +3213,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  				// *HACK: Desaturate the color  				LLColor4 username_color = name_tag_color * 0.83f;  				addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL, -							   LLFontGL::getFontSansSerifSmall()); +					LLFontGL::getFontSansSerifSmall());  			}  		}  		else  		{  			const LLFontGL* font = LLFontGL::getFontSansSerif(); -			std::string full_name = -				LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); +			std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() );  			addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font);  		} @@ -3231,7 +3239,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  		mNameText->setFont(LLFontGL::getFontSansSerif());  		mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT);  		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); -			 +  		char line[MAX_STRING];		/* Flawfinder: ignore */  		line[0] = '\0';  		std::deque<LLChat>::iterator chat_iter = mChats.begin(); @@ -3251,13 +3259,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			LLFontGL::StyleFlags style;  			switch(chat_iter->mChatType)  			{ -				case CHAT_TYPE_WHISPER: +			case CHAT_TYPE_WHISPER:  				style = LLFontGL::ITALIC;  				break; -				case CHAT_TYPE_SHOUT: +			case CHAT_TYPE_SHOUT:  				style = LLFontGL::BOLD;  				break; -				default: +			default:  				style = LLFontGL::NORMAL;  				break;  			} @@ -3284,13 +3292,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  			S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1;  			switch(dot_count)  			{ -				case 1: +			case 1:  				mNameText->addLine(".", new_chat);  				break; -				case 2: +			case 2:  				mNameText->addLine("..", new_chat);  				break; -				case 3: +			case 3:  				mNameText->addLine("...", new_chat);  				break;  			} @@ -3354,34 +3362,45 @@ void LLVOAvatar::invalidateNameTags()  		if (avatar->isDead()) continue;  		avatar->clearNameTag(); -  	}  }  // Compute name tag position during idle update -LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)  {  	LLQuaternion root_rot = mRoot.getWorldRotation(); +	LLQuaternion inv_root_rot = ~root_rot;  	LLVector3 pixel_right_vec;  	LLVector3 pixel_up_vec;  	LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);  	LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();  	camera_to_av.normalize(); -	LLVector3 local_camera_at = camera_to_av * ~root_rot; +	LLVector3 local_camera_at = camera_to_av * inv_root_rot;  	LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();  	local_camera_up.normalize(); -	local_camera_up = local_camera_up * ~root_rot; +	local_camera_up = local_camera_up * inv_root_rot; + +	LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, +								mBodySize.mV[VY] * 0.4f, +								mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); -	local_camera_up.scaleVec(mBodySize * 0.5f); -	local_camera_at.scaleVec(mBodySize * 0.5f); +	local_camera_up.scaleVec(avatar_ellipsoid); +	local_camera_at.scaleVec(avatar_ellipsoid); -	LLVector3 name_position = mRoot.getWorldPosition(); -	name_position[VZ] -= mPelvisToFoot; -	name_position[VZ] += (mBodySize[VZ]* 0.55f); +	LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; + +	if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) +	{ +		mTargetRootToHeadOffset = head_offset; +	} +	 +	mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + +	LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot);  	name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av));	 -	name_position += pixel_up_vec * 15.f; +	name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; -	return name_position; +	mNameText->setPositionAgent(name_position);				  }  void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) @@ -3454,9 +3473,9 @@ bool LLVOAvatar::isVisuallyMuted() const  	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");  	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); -	return LLMuteList::getInstance()->isMuted(getID()) || -			(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || -			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +	return LLMuteList::getInstance()->isMuted(getID())  +			|| (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0)  +			|| (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);  }  //------------------------------------------------------------------------ @@ -3497,8 +3516,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		}  	} -	LLVector3d root_pos_global; -  	if (!mIsBuilt)  	{  		return FALSE; @@ -3513,7 +3530,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		mTimeVisible.reset();  	} -	  	//--------------------------------------------------------------------  	// the rest should only be done occasionally for far away avatars  	//-------------------------------------------------------------------- @@ -3916,10 +3932,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		if ( playSound )  		{ -//			F32 gain = clamp_rescale( mSpeedAccum, -//							AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -//							AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); -  			const F32 STEP_VOLUME = 0.1f;  			const LLUUID& step_sound_id = getStepSound(); @@ -4136,13 +4148,6 @@ void LLVOAvatar::updateVisibility()  		{  			releaseMeshData();  		} -		// this breaks off-screen chat bubbles -		//if (mNameText) -		//{ -		//	mNameText->markDead(); -		//	mNameText = NULL; -		//	sNumVisibleChatBubbles--; -		//}  	}  	mVisible = visible; @@ -4158,46 +4163,6 @@ bool LLVOAvatar::shouldAlphaMask()  } -U32 LLVOAvatar::renderSkinnedAttachments() -{ -	/*U32 num_indices = 0; -	 -	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX |  -							LLVertexBuffer::MAP_NORMAL |  -							LLVertexBuffer::MAP_TEXCOORD0 | -							LLVertexBuffer::MAP_COLOR | -							LLVertexBuffer::MAP_WEIGHT4; - -	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  -		 iter != mAttachmentPoints.end(); -		 ++iter) -	{ -		LLViewerJointAttachment* attachment = iter->second; -		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -			 attachment_iter != attachment->mAttachedObjects.end(); -			 ++attachment_iter) -		{ -			const LLViewerObject* attached_object = (*attachment_iter); -			if (attached_object && !attached_object->isHUDAttachment()) -			{ -				const LLDrawable* drawable = attached_object->mDrawable; -				if (drawable) -				{ -					for (S32 i = 0; i < drawable->getNumFaces(); ++i) -					{ -						LLFace* face = drawable->getFace(i); -						if (face->isState(LLFace::RIGGED)) -						{ -							 -				} -			} -		} -	} - -	return num_indices;*/ -	return 0; -} -  //-----------------------------------------------------------------------------  // renderSkinned()  //----------------------------------------------------------------------------- @@ -4218,11 +4183,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  	{	//LOD changed or new mesh created, allocate new vertex buffer if needed  		if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4)  		{ -			updateMeshData(); +		updateMeshData();  			mDirtyMesh = 0; -			mNeedsSkin = TRUE; -			mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); -		} +		mNeedsSkin = TRUE; +		mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); +	}  	}  	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -4251,13 +4216,13 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  			if (face)  			{  				LLVertexBuffer* vb = face->getVertexBuffer(); -				if (vb) -				{ -					vb->flush(); -				} +			if (vb) +			{ +				vb->flush();  			}  		}  	} +	}  	else  	{  		mNeedsSkin = FALSE; @@ -5900,7 +5865,6 @@ BOOL LLVOAvatar::updateJointLODs()  	F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor);  	F32 area_scale = 0.16f; -	{  		if (isSelf())  		{  			if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) @@ -5930,7 +5894,6 @@ BOOL LLVOAvatar::updateJointLODs()  			dirtyMesh(2);  			return TRUE;  		} -	}  	return FALSE;  } @@ -6219,14 +6182,9 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  		if ( pVObj )  		{  			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); -			if ( pSkinData ) -			{ -				const int jointCnt = pSkinData->mJointNames.size(); -				bool fullRig = ( jointCnt>=20 ) ? true : false; -				if ( fullRig ) -				{ -					const int bindCnt = pSkinData->mAlternateBindMatrix.size();							 -					if ( bindCnt > 0 ) +			if (pSkinData  +				&& pSkinData->mJointNames.size() > 20				// full rig +				&& pSkinData->mAlternateBindMatrix.size() > 0)  					{  						LLVOAvatar::resetJointPositionsToDefault();  						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing  @@ -6241,8 +6199,6 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  				}  			}				  		} -	}	 -}  //-----------------------------------------------------------------------------  // detachObject()  //----------------------------------------------------------------------------- @@ -6391,11 +6347,7 @@ void LLVOAvatar::getOffObject()  		at_axis.mV[VZ] = 0.f;  		at_axis.normalize();  		gAgent.resetAxes(at_axis); - -		//reset orientation -//		mRoot.setRotation(avWorldRot);  		gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); -  		gAgentCamera.setSitCamera(LLUUID::null);  	}  } @@ -6445,7 +6397,6 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const  	}  	else  	{ -//		return LLColor4( .5f, .5f, .5f, .5f );  		return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color  	}  } @@ -6610,8 +6561,8 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading)  	mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); -	if (!mPreviousFullyLoaded && !loading && mFullyLoaded) -	{ +		if (!mPreviousFullyLoaded && !loading && mFullyLoaded) +		{  		debugAvatarRezTime("AvatarRezNotification","fully loaded");  	} @@ -7204,10 +7155,6 @@ LLBBox LLVOAvatar::getHUDBBox() const  	return bbox;  } -void LLVOAvatar::rebuildHUD() -{ -} -  //-----------------------------------------------------------------------------  // onFirstTEMessageReceived()  //----------------------------------------------------------------------------- @@ -7333,7 +7280,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )  			&& baked_index != BAKED_SKIRT)  		{  			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,  -				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); +						LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex,  +																TRUE,  +																LLViewerTexture::BOOST_NONE,  +																LLViewerTexture::LOD_TEXTURE));  		}  	} @@ -7592,7 +7542,7 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTextu  	LLUUID *avatar_idp = (LLUUID *)userdata;  	LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); -	 +  	if (selfp)  	{  		LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; @@ -7643,13 +7593,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success,  // Called when baked texture is loaded and also when we start up with a baked texture  void LLVOAvatar::useBakedTexture( const LLUUID& id )  { - -	 -	/* if(id == head_baked->getID()) -		 mHeadBakedLoaded = TRUE; -		 mLastHeadBakedID = id; -		 mHeadMesh0.setTexture( head_baked ); -		 mHeadMesh1.setTexture( head_baked ); */  	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)  	{  		LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); @@ -7893,111 +7836,111 @@ LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()  	std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());  } -//----------------------------------------------------------------------------- -// LLVOAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ -	if (node->hasName("bone")) -	{ -		mIsJoint = TRUE; -		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -		if (!node->getFastAttributeString(name_string, mName)) -		{ -			llwarns << "Bone without name" << llendl; -			return FALSE; -		} -	} -	else if (node->hasName("collision_volume")) -	{ -		mIsJoint = FALSE; -		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -		if (!node->getFastAttributeString(name_string, mName)) -		{ -			mName = "Collision Volume"; -		} -	} -	else -	{ -		llwarns << "Invalid node " << node->getName() << llendl; -		return FALSE; -	} - -	static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); -	if (!node->getFastAttributeVector3(pos_string, mPos)) -	{ -		llwarns << "Bone without position" << llendl; -		return FALSE; -	} - -	static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); -	if (!node->getFastAttributeVector3(rot_string, mRot)) -	{ -		llwarns << "Bone without rotation" << llendl; -		return FALSE; -	} -	 -	static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); -	if (!node->getFastAttributeVector3(scale_string, mScale)) -	{ -		llwarns << "Bone without scale" << llendl; -		return FALSE; -	} - -	if (mIsJoint) -	{ -		static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); -		if (!node->getFastAttributeVector3(pivot_string, mPivot)) -		{ -			llwarns << "Bone without pivot" << llendl; -			return FALSE; -		} -	} - -	// parse children -	LLXmlTreeNode* child; -	for( child = node->getFirstChild(); child; child = node->getNextChild() ) -	{ -		LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; -		if (!child_info->parseXml(child)) -		{ -			delete child_info; -			return FALSE; -		} -		mChildList.push_back(child_info); -	} -	return TRUE; -} - -//----------------------------------------------------------------------------- -// LLVOAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ -	static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); -	if (!node->getFastAttributeS32(num_bones_string, mNumBones)) -	{ -		llwarns << "Couldn't find number of bones." << llendl; -		return FALSE; -	} - -	static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); -	node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - -	LLXmlTreeNode* child; -	for( child = node->getFirstChild(); child; child = node->getNextChild() ) -	{ -		LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; -		if (!info->parseXml(child)) -		{ -			delete info; -			llwarns << "Error parsing bone in skeleton file" << llendl; -			return FALSE; -		} -		mBoneInfoList.push_back(info); -	} -	return TRUE; -} +////----------------------------------------------------------------------------- +//// LLVOAvatarBoneInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +//{ +//	if (node->hasName("bone")) +//	{ +//		mIsJoint = TRUE; +//		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +//		if (!node->getFastAttributeString(name_string, mName)) +//		{ +//			llwarns << "Bone without name" << llendl; +//			return FALSE; +//		} +//	} +//	else if (node->hasName("collision_volume")) +//	{ +//		mIsJoint = FALSE; +//		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +//		if (!node->getFastAttributeString(name_string, mName)) +//		{ +//			mName = "Collision Volume"; +//		} +//	} +//	else +//	{ +//		llwarns << "Invalid node " << node->getName() << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); +//	if (!node->getFastAttributeVector3(pos_string, mPos)) +//	{ +//		llwarns << "Bone without position" << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); +//	if (!node->getFastAttributeVector3(rot_string, mRot)) +//	{ +//		llwarns << "Bone without rotation" << llendl; +//		return FALSE; +//	} +//	 +//	static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); +//	if (!node->getFastAttributeVector3(scale_string, mScale)) +//	{ +//		llwarns << "Bone without scale" << llendl; +//		return FALSE; +//	} +// +//	if (mIsJoint) +//	{ +//		static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); +//		if (!node->getFastAttributeVector3(pivot_string, mPivot)) +//		{ +//			llwarns << "Bone without pivot" << llendl; +//			return FALSE; +//		} +//	} +// +//	// parse children +//	LLXmlTreeNode* child; +//	for( child = node->getFirstChild(); child; child = node->getNextChild() ) +//	{ +//		LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; +//		if (!child_info->parseXml(child)) +//		{ +//			delete child_info; +//			return FALSE; +//		} +//		mChildList.push_back(child_info); +//	} +//	return TRUE; +//} +// +////----------------------------------------------------------------------------- +//// LLVOAvatarSkeletonInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +//{ +//	static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); +//	if (!node->getFastAttributeS32(num_bones_string, mNumBones)) +//	{ +//		llwarns << "Couldn't find number of bones." << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); +//	node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); +// +//	LLXmlTreeNode* child; +//	for( child = node->getFirstChild(); child; child = node->getNextChild() ) +//	{ +//		LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; +//		if (!info->parseXml(child)) +//		{ +//			delete info; +//			llwarns << "Error parsing bone in skeleton file" << llendl; +//			return FALSE; +//		} +//		mBoneInfoList.push_back(info); +//	} +//	return TRUE; +//}  //-----------------------------------------------------------------------------  // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index f5692bb52f..3dffb9d029 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -67,8 +67,9 @@ class LLVoiceVisualizer;  class LLHUDNameTag;  class LLHUDEffectSpiral;  class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +struct LLVOAvatarBoneInfo; +struct LLVOAvatarChildJoint; +struct LLVOAvatarSkeletonInfo;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // LLVOAvatar @@ -243,7 +244,7 @@ public:  	void 			idleUpdateWindEffect();  	void 			idleUpdateNameTag(const LLVector3& root_pos_last);  	void			idleUpdateNameTagText(BOOL new_name); -	LLVector3		idleUpdateNameTagPosition(const LLVector3& root_pos_last); +	void			idleUpdateNameTagPosition(const LLVector3& root_pos_last);  	void			idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);  	LLColor4		getNameTagColor(bool is_friend);  	void			clearNameTag(); @@ -363,6 +364,8 @@ public:  	F32					mLastPelvisToFoot;  	F32					mPelvisFixup;  	F32					mLastPelvisFixup; +	LLVector3			mCurRootToHeadOffset; +	LLVector3			mTargetRootToHeadOffset;  	LLVector3			mHeadOffset; // current head position  	LLViewerJoint		mRoot; @@ -375,7 +378,7 @@ protected:  	void				buildCharacter();  	virtual BOOL		loadAvatar(); -	BOOL				setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); +	BOOL				setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num);  	BOOL				buildSkeleton(const LLVOAvatarSkeletonInfo *info);  private:  	BOOL				mIsBuilt; // state of deferred character building @@ -419,7 +422,7 @@ public:  	//--------------------------------------------------------------------  private:  	static LLXmlTree 	sXMLTree; // avatar config file -	static LLXmlTree 	sSkeletonXMLTree; // avatar skeleton file +	static LLXMLNodePtr	sSkeletonXMLTree; // avatar skeleton file  /**                    Skeleton   **                                                                            ** @@ -437,7 +440,6 @@ public:  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass);  	F32			getLastSkinTime() { return mLastSkinTime; } -	U32			renderSkinnedAttachments();  	U32 		renderTransparent(BOOL first_pass);  	void 		renderCollisionVolumes();  	static void	deleteCachedImages(bool clearAll=true); @@ -786,7 +788,6 @@ public:  public:  	BOOL 				hasHUDAttachment() const;  	LLBBox 				getHUDBBox() const; -	void 				rebuildHUD();  	void 				resetHUDAttachments();  	BOOL				canAttachMoreObjects() const;  	BOOL				canAttachMoreObjects(U32 n) const; diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 47060720e7..d380a8672f 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -45,6 +45,7 @@  //29de489d-0491-fb00-7dab-f9e686d31e83 +#ifdef XXX_STINSON_CHUI_REWORK  //--------------------------------------------------------------------------------------  // sound symbol constants  //-------------------------------------------------------------------------------------- @@ -60,6 +61,7 @@ const F32	BASE_BRIGHTNESS		= 0.7f;		// gray level of the voice indicator when qu  const F32	DOT_SIZE			= 0.05f;	// size of the dot billboard texture  const F32	DOT_OPACITY			= 0.7f;		// how opaque the dot is  const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a function of speaking amplitude +#endif // XXX_STINSON_CHUI_REWORK  //--------------------------------------------------------------------------------------  // gesticulation constants @@ -67,22 +69,13 @@ const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a  const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE	= 0.2f;   const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE	= 1.0f; +#ifdef XXX_STINSON_CHUI_REWORK  //--------------------------------------------------------------------------------------  // other constants  //--------------------------------------------------------------------------------------  const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.   const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL - - -//------------------------------------------------------------------ -// handles parameter updates -//------------------------------------------------------------------ -static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) -{ -	// Note: Ignore the specific event value, we look up the ones we want -	LLVoiceVisualizer::setPreferences(); -	return true; -} +#endif // XXX_STINSON_CHUI_REWORK  //------------------------------------------------------------------  // Initialize the statics @@ -105,12 +98,28 @@ F32	 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f;  //-----------------------------------------------  // constructor  //----------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) -:LLHUDEffect( type ) +	: LLHUDEffect(type) +#else // XXX_STINSON_CHUI_REWORK +LLVoiceVisualizer::LLVoiceVisualizer() +	: LLRefCount(), +	mTimer(), +	mStartTime(0.0), +	mCurrentlySpeaking(false), +	mSpeakingAmplitude(0.0f), +	mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE), +	mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE) +#endif // XXX_STINSON_CHUI_REWORK  { +#ifdef XXX_STINSON_CHUI_REWORK  	mCurrentTime					= mTimer.getTotalSeconds();  	mPreviousTime					= mCurrentTime;  	mStartTime						= mCurrentTime; +#else // XXX_STINSON_CHUI_REWORK +	mStartTime						= mTimer.getTotalSeconds(); +#endif // XXX_STINSON_CHUI_REWORK +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceSourceWorldPosition		= LLVector3( 0.0f, 0.0f, 0.0f );  	mSpeakingAmplitude				= 0.0f;  	mCurrentlySpeaking				= false; @@ -119,9 +128,11 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )  	mMaxGesticulationAmplitude		= DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;  	mSoundSymbol.mActive			= true;  	mSoundSymbol.mPosition			= LLVector3( 0.0f, 0.0f, 0.0f ); +#endif // XXX_STINSON_CHUI_REWORK  	mTimer.reset(); +#ifdef XXX_STINSON_CHUI_REWORK  	const char* sound_level_img[] =   	{  		"voice_meter_dot.j2c", @@ -143,6 +154,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )  	}  	mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +#endif // XXX_STINSON_CHUI_REWORK  	// The first instance loads the initial state from prefs.  	if (!sPrefsInitialized) @@ -150,18 +162,19 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )  		setPreferences();  		// Set up our listener to get updates on all prefs values we care about. -		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); +		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));  		sPrefsInitialized = true;  	}  }//--------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )  { @@ -182,13 +195,16 @@ void LLVoiceVisualizer::setVoiceEnabled( bool v )  	mVoiceEnabled = v;  }//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  void LLVoiceVisualizer::setStartSpeaking()  {  	mStartTime				= mTimer.getTotalSeconds();  	mCurrentlySpeaking		= true; +#ifdef XXX_STINSON_CHUI_REWORK  	mSoundSymbol.mActive	= true; +#endif // XXX_STINSON_CHUI_REWORK  }//--------------------------------------------------- @@ -217,6 +233,15 @@ void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )  }//--------------------------------------------------- +//------------------------------------------------------------------ +// handles parameter updates +//------------------------------------------------------------------ +bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) +{ +	// Note: Ignore the specific event value, we look up the ones we want +	LLVoiceVisualizer::setPreferences(); +	return true; +}  //---------------------------------------------------  void LLVoiceVisualizer::setPreferences( ) @@ -334,6 +359,7 @@ void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah )  }//--------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  // this method is inherited from HUD Effect  //--------------------------------------------------- @@ -526,16 +552,13 @@ void LLVoiceVisualizer::render()  }//--------------------------------------------------- - - - -  //---------------------------------------------------  void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )  {  	mVoiceSourceWorldPosition	= p;  }//--------------------------------------------------- +#endif // XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() @@ -566,6 +589,7 @@ LLVoiceVisualizer::~LLVoiceVisualizer()  }//---------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  //---------------------------------------------------  // "packData" is inherited from HUDEffect  //--------------------------------------------------- @@ -616,10 +640,4 @@ void LLVoiceVisualizer::markDead()  	LLHUDEffect::markDead();  }//------------------------------------------------------------------ - - - - - - - +#endif // XXX_STINSON_CHUI_REWORK diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index e434c7f3f1..5da592c48e 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -42,7 +42,12 @@  #ifndef LL_VOICE_VISUALIZER_H  #define LL_VOICE_VISUALIZER_H +#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot +#ifdef XXX_STINSON_CHUI_REWORK  #include "llhudeffect.h" +#else // XXX_STINSON_CHUI_REWORK +#include "llpointer.h" +#endif // XXX_STINSON_CHUI_REWORK  //-----------------------------------------------------------------------------------------------  // The values of voice gesticulation represent energy levels for avatar animation, based on  @@ -60,34 +65,45 @@ enum VoiceGesticulationLevel  	NUM_VOICE_GESTICULATION_LEVELS  }; +#ifdef XXX_STINSON_CHUI_REWORK  const static int NUM_VOICE_SYMBOL_WAVES = 7; +#endif // XXX_STINSON_CHUI_REWORK  //----------------------------------------------------  // LLVoiceVisualizer class   //---------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  class LLVoiceVisualizer : public LLHUDEffect +#else // XXX_STINSON_CHUI_REWORK +class LLVoiceVisualizer : public LLRefCount +#endif // XXX_STINSON_CHUI_REWORK  {  	//---------------------------------------------------  	// public methods   	//---------------------------------------------------  	public: -		LLVoiceVisualizer ( const U8 type );	//constructor +#ifdef XXX_STINSON_CHUI_REWORK +		LLVoiceVisualizer( const U8 type );	//constructor +#else // XXX_STINSON_CHUI_REWORK +		LLVoiceVisualizer();	//constructor +#endif // XXX_STINSON_CHUI_REWORK  		~LLVoiceVisualizer();					//destructor -		 -		friend class LLHUDObject; +#ifdef XXX_STINSON_CHUI_REWORK  		void					setVoiceSourceWorldPosition( const LLVector3 &p );		// this should be the position of the speaking avatar's head  		void					setMinGesticulationAmplitude( F32 );					// the lower range of meaningful amplitude for setting gesticulation level   		void					setMaxGesticulationAmplitude( F32 );					// the upper range of meaningful amplitude for setting gesticulation level  +#endif // XXX_STINSON_CHUI_REWORK  		void					setStartSpeaking();										// tell me when the av starts speaking +#ifdef XXX_STINSON_CHUI_REWORK  		void					setVoiceEnabled( bool );								// tell me whether or not the user is voice enabled +#endif // XXX_STINSON_CHUI_REWORK  		void					setSpeakingAmplitude( F32 );							// tell me how loud the av is speaking (ranges from 0 to 1)  		void					setStopSpeaking();										// tell me when the av stops speaking  		bool					getCurrentlySpeaking();									// the get for the above set  		VoiceGesticulationLevel	getCurrentGesticulationLevel();							// based on voice amplitude, I'll give you the current "energy level" of avatar speech -		static void				setPreferences( ); -		static void				lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats  		void					lipSyncOohAah( F32& ooh, F32& aah ); +#ifdef XXX_STINSON_CHUI_REWORK  		void					render();												// inherited from HUD Effect  		void 					packData(LLMessageSystem *mesgsys);						// inherited from HUD Effect  		void 					unpackData(LLMessageSystem *mesgsys, S32 blocknum);		// inherited from HUD Effect @@ -103,12 +119,17 @@ class LLVoiceVisualizer : public LLHUDEffect  		//----------------------------------------------------------------------------------------------  		void setMaxGesticulationAmplitude();   		void setMinGesticulationAmplitude();  +#endif // XXX_STINSON_CHUI_REWORK  	//---------------------------------------------------  	// private members   	//---------------------------------------------------  	private: -	 +		static bool				handleVoiceVisualizerPrefsChanged(const LLSD& newvalue); +		static void				setPreferences( ); +		static void				lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats + +#ifdef XXX_STINSON_CHUI_REWORK  		struct SoundSymbol  		{  			F32						mWaveExpansion			[ NUM_VOICE_SYMBOL_WAVES ]; @@ -119,15 +140,20 @@ class LLVoiceVisualizer : public LLHUDEffect  			bool					mActive;  			LLVector3				mPosition;  		}; +#endif // XXX_STINSON_CHUI_REWORK  		LLFrameTimer			mTimer;							// so I can ask the current time in seconds  		F64						mStartTime;						// time in seconds when speaking started +#ifdef XXX_STINSON_CHUI_REWORK  		F64						mCurrentTime;					// current time in seconds, captured every step  		F64						mPreviousTime;					// copy of "current time" from last frame  		SoundSymbol				mSoundSymbol;					// the sound symbol that appears over the avatar's head  		bool					mVoiceEnabled;					// if off, no rendering should happen +#endif // XXX_STINSON_CHUI_REWORK  		bool					mCurrentlySpeaking;				// is the user currently speaking? +#ifdef XXX_STINSON_CHUI_REWORK  		LLVector3				mVoiceSourceWorldPosition;		// give this to me every step - I need it to update the sound symbol +#endif // XXX_STINSON_CHUI_REWORK  		F32						mSpeakingAmplitude;				// this should be set as often as possible when the user is speaking  		F32						mMaxGesticulationAmplitude;		// this is the upper-limit of the envelope of detectable gesticulation leves  		F32						mMinGesticulationAmplitude;		// this is the lower-limit of the envelope of detectable gesticulation leves diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 820d1d73e1..f1bf4a6d75 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -3964,6 +3964,7 @@ void LLVivoxVoiceClient::messageEvent(  						session->mCallerID,  						session->mName.c_str(),  						message.c_str(), +						false,  						LLStringUtil::null,		// default arg  						IM_NOTHING_SPECIAL,		// default arg  						0,						// default arg diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 9cce68fff6..a88418a5a2 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -152,8 +152,8 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)  void LLVOPartGroup::freeVBSlot(S32 idx)  {  	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); -	llassert(sVBSlotCursor > sVBSlotFree); -	llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); +	//llassert(sVBSlotCursor > sVBSlotFree); +	//llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT));  	if (sVBSlotCursor > sVBSlotFree)  	{ diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7140515e46..76c27aaa08 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5206,11 +5206,6 @@ void LLPipeline::rebuildPools()  		}  		max_count--;  	} - -	if (isAgentAvatarValid()) -	{ -		gAgentAvatarp->rebuildHUD(); -	}  }  void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) @@ -5698,7 +5693,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)  				// crazy cast so that we can overwrite the fade value  				// even though gcc enforces sets as const  				// (fade value doesn't affect sort so this is safe) -				Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin())))); +				Light* farthest_light = (const_cast<Light*>(&(*(mNearbyLights.rbegin()))));  				if (light->dist < farthest_light->dist)  				{  					if (farthest_light->fade >= 0.f) @@ -6729,7 +6724,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)  }  void LLPipeline::resetVertexBuffers() -{ +{	  	mResetVertexBuffers = true;  } diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 9bf2922033..05230b8bd5 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -1,103 +1,103 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <colors> -  <!-- Named Colors --> -  <color -      name="EmphasisColor" -      value="0.38 0.694 0.573 1" /> -  <color -      name="EmphasisColor_13" -      value="0.38 0.694 0.573 0.13" /> -  <color -      name="EmphasisColor_35" -      value="0.38 0.694 0.573 0.35" /> -  <color -      name="White" -      value="1 1 1 1" /> -  <color -      name="White_05" -      value="1 1 1 0.05" /> -  <color -      name="White_10" -      value="1 1 1 0.1" /> -  <color -      name="White_25" -      value="1 1 1 0.25" /> -  <color -      name="White_50" -      value="1 1 1 0.5" /> -  <color -      name="LtGray" -      value="0.75 0.75 0.75 1" /> -  <color -      name="LtGray_35" -      value="0.75 0.75 0.75 0.35" /> -  <color -      name="LtGray_50" -      value="0.75 0.75 0.75 0.50" /> -  <color -      name="Gray" -      value="0.5 0.5 0.5 1" /> -  <color -      name="DkGray" -      value="0.125 0.125 0.125 1" /> -  <color -      name="DkGray_66" -      value="0.125 0.125 0.125 .66" /> -  <color -      name="DkGray2" -      value="0.169 0.169 0.169 1" /> -  <color -      name="MouseGray" -      value="0.191 0.191 0.191 1" /> -  <color -      name="Black" -      value="0 0 0 1" /> -  <colork -      name="Black_10" -      value="0 0 0 0.1" /> -  <color -      name="Black_25" -      value="0 0 0 0.25" /> -  <color -      name="Black_50" -      value="0 0 0 0.5" /> -  <color -      name="FrogGreen" -      value="0.26 0.345 0.263 1" /> -  <color -      name="Red" -      value="1 0 0 1" /> -  <color -      name="Blue" -      value="0 0 1 1" /> -  <color -      name="Yellow" -      value="1 1 0 1" /> -  <color -      name="Green" -      value="0 1 0 1" /> -  <color -      name="Transparent" -      value="0 0 0 0" /> -  <color -      name="Purple" -      value="1 0 1 1" /> -  <color -      name="Lime" -      value=".8 1 .73 1" /> -  <color -      name="LtYellow" -      value="1 1 .79 1" /> -  <color -      name="DrYellow" -      value="1 0.86 0 1" /> -  <color -      name="LtOrange" -      value="1 .85 .73 1" /> -  <color -      name="MdBlue" -      value=".07 .38 .51 1" /> +	<!-- Named Colors --> +	<color +	 name="EmphasisColor" +	 value="0.38 0.694 0.573 1" /> +	<color +	 name="EmphasisColor_13" +	 value="0.38 0.694 0.573 0.13" /> +	<color +	 name="EmphasisColor_35" +	 value="0.38 0.694 0.573 0.35" /> +	<color +	 name="White" +	 value="1 1 1 1" /> +	<color +	 name="White_05" +	 value="1 1 1 0.05" /> +	<color +	 name="White_10" +	 value="1 1 1 0.1" /> +	<color +	 name="White_25" +	 value="1 1 1 0.25" /> +	<color +	 name="White_50" +	 value="1 1 1 0.5" /> +	<color +	 name="LtGray" +	 value="0.75 0.75 0.75 1" /> +	<color +	 name="LtGray_35" +	 value="0.75 0.75 0.75 0.35" /> +	<color +	 name="LtGray_50" +	 value="0.75 0.75 0.75 0.50" /> +	<color +	 name="Gray" +	 value="0.5 0.5 0.5 1" /> +	<color +	 name="DkGray" +	 value="0.125 0.125 0.125 1" /> +	<color +	 name="DkGray_66" +	 value="0.125 0.125 0.125 .66" /> +	<color +	 name="DkGray2" +	 value="0.169 0.169 0.169 1" /> +	<color +	 name="MouseGray" +	 value="0.191 0.191 0.191 1" /> +	<color +	 name="Black" +	 value="0 0 0 1" /> +	<colork +	 name="Black_10" +	 value="0 0 0 0.1" /> +	<color +	 name="Black_25" +	 value="0 0 0 0.25" /> +	<color +	 name="Black_50" +	 value="0 0 0 0.5" /> +	<color +	name="FrogGreen" +	value="0.26 0.345 0.263 1" /> +	<color +	 name="Red" +	 value="1 0 0 1" /> +	<color +	 name="Blue" +	 value="0 0 1 1" /> +	<color +	 name="Yellow" +	 value="1 1 0 1" /> +	<color +	 name="Green" +	 value="0 1 0 1" /> +	<color +	 name="Transparent" +	 value="0 0 0 0" /> +	<color +	name="Purple" +	value="1 0 1 1" /> +	<color +	name="Lime" +	value=".8 1 .73 1" /> +	<color +	name="LtYellow" +	value="1 1 .79 1" /> +	<color +	name="DrYellow" +	value="1 0.86 0 1" /> +	<color +	name="LtOrange" +	value="1 .85 .73 1" /> +	<color +	name="MdBlue" +	value=".07 .38 .51 1" />    <color        name="LtRed"        value="1 0.2 0.2 1" /> @@ -115,527 +115,527 @@        value="0 0 1 0.8" />    <!-- This color name makes potentially unused colors show up bright purple. -       Leave this here until all Unused? are removed below, otherwise -       the viewer generates many warnings on startup. --> +  Leave this here until all Unused? are removed below, otherwise +  the viewer generates many warnings on startup. -->    <color -      name="Unused?" -      value=".831 1 0 1" /> +	 name="Unused?" +	 value=".831 1 0 1" />    <!-- UI Definitions --> -  <color -      name="AccordionHeaderTextColor" -      reference="LtGray" /> -  <color -      name="AgentChatColor" -      reference="White" /> -  <color -      name="AlertBoxColor" -      value="0.24 0.24 0.24 1" /> -  <color -      name="AlertCautionBoxColor" -      value="1 0.82 0.46 1" /> -  <color -      name="AlertCautionTextColor" -      reference="LtYellow" /> -  <color -      name="AvatarListItemIconDefaultColor" -      reference="White" /> -  <color -      name="AvatarListItemIconOnlineColor" -      reference="White" /> -  <color -      name="AvatarListItemIconOfflineColor" -      value="0.5 0.5 0.5 0.5" /> -  <color -      name="AvatarListItemIconVoiceInvitedColor" -      reference="AvatarListItemIconOfflineColor" /> -  <color -      name="AvatarListItemIconVoiceJoinedColor" -      reference="AvatarListItemIconOnlineColor" /> -  <color -      name="AvatarListItemIconVoiceLeftColor" -      reference="AvatarListItemIconOfflineColor" /> -  <color -      name="BadgeImageColor" -      value="1.0 0.40 0.0 1.0" /> -  <color -      name="BadgeBorderColor" -      value="0.9 0.9 0.9 1.0" /> -  <color -      name="BadgeLabelColor" -      reference="White" /> -  <color -      name="ButtonBorderColor" -      reference="Unused?" /> -  <color -      name="ButtonCautionImageColor" -      reference="Unused?" /> -  <color -      name="ButtonColor" -      reference="Unused?" /> -  <color -      name="ButtonFlashBgColor" -      reference="Unused?" /> -  <color -      name="ButtonImageColor" -      reference="White" /> -  <color -      name="ButtonLabelColor" -      reference="LtGray" /> -  <color -      name="ButtonLabelDisabledColor" -      reference="White_25" /> -  <color -      name="ButtonLabelSelectedColor" -      reference="White" /> -  <color -      name="ButtonLabelSelectedDisabledColor" -      reference="White_25" /> -  <color -      name="ButtonSelectedBgColor" -      reference="Unused?" /> -  <color -      name="ButtonSelectedColor" -      reference="Unused?" /> -  <color -      name="ButtonUnselectedBgColor" -      reference="Unused?" /> -  <color -      name="ButtonUnselectedFgColor" -      reference="Unused?" /> -  <color -      name="ChatHistoryBgColor" -      reference="Transparent" /> -  <color -      name="ChatHistoryTextColor" -      reference="LtGray" /> -  <color -      name="ChicletFlashColor" -      value="0.114 0.65 0.1" /> -  <color -      name="ColorDropShadow" -      reference="Black_50" /> -  <color -      name="ColorPaletteEntry01" -      reference="Black" /> -  <color -      name="ColorPaletteEntry02" -      reference="Gray" /> -  <color -      name="ColorPaletteEntry03" -      value="0.5 0 0 1" /> -  <color -      name="ColorPaletteEntry04" -      value="0.5 0.5 0 1" /> -  <color -      name="ColorPaletteEntry05" -      value="0 0.5 0 1" /> -  <color -      name="ColorPaletteEntry06" -      value="0 0.5 0.5 1" /> -  <color -      name="ColorPaletteEntry07" -      value="0 0 0.5 1" /> -  <color -      name="ColorPaletteEntry08" -      value="0.5 0 0.5 1" /> -  <color -      name="ColorPaletteEntry09" -      value="0.5 0.5 0 1" /> -  <color -      name="ColorPaletteEntry10" -      value="0 0.25 0.25 1" /> -  <color -      name="ColorPaletteEntry11" -      value="0 0.5 1 1" /> -  <color -      name="ColorPaletteEntry12" -      value="0 0.25 0.5 1" /> -  <color -      name="ColorPaletteEntry13" -      value="0.5 0 1 1" /> -  <color -      name="ColorPaletteEntry14" -      value="0.5 0.25 0 1" /> -  <color -      name="ColorPaletteEntry15" -      reference="White" /> -  <color -      name="ColorPaletteEntry16" -      reference="LtYellow" /> -  <color -      name="ColorPaletteEntry17" -      reference="White" /> -  <color -      name="ColorPaletteEntry18" -      reference="LtGray" /> -  <color -      name="ColorPaletteEntry19" -      reference="Red" /> -  <color -      name="ColorPaletteEntry20" -      reference="Yellow" /> -  <color -      name="ColorPaletteEntry21" -      reference="Green" /> -  <color -      name="ColorPaletteEntry22" -      value="0 1 1 1" /> -  <color -      name="ColorPaletteEntry23" -      reference="Blue" /> -  <color -      name="ColorPaletteEntry24" -      reference="Purple" /> -  <color -      name="ColorPaletteEntry25" -      value="1 1 0.5 1" /> -  <color -      name="ColorPaletteEntry26" -      value="0 1 0.5 1" /> -  <color -      name="ColorPaletteEntry27" -      value="0.5 1 1 1" /> -  <color -      name="ColorPaletteEntry28" -      value="0.5 0.5 1 1" /> -  <color -      name="ColorPaletteEntry29" -      value="1 0 0.5 1" /> -  <color -      name="ColorPaletteEntry30" -      value="1 0.5 0 1" /> -  <color -      name="ColorPaletteEntry31" -      reference="White" /> -  <color -      name="ColorPaletteEntry32" -      reference="White" /> -  <color -      name="ComboListBgColor" -      reference="DkGray" /> -  <color -      name="ConsoleBackground" -      reference="Black" /> -  <color -      name="ContextSilhouetteColor" -      reference="EmphasisColor" /> -  <color -      name="DefaultHighlightDark" -      reference="White_10" /> -  <color -      name="DefaultHighlightLight" -      reference="White_25" /> -  <color -      name="DefaultShadowDark" -      reference="Black_50" /> -  <color -      name="DefaultShadowLight" -      reference="Black_50" /> -  <color -      name="EffectColor" -      reference="White" /> -  <color -      name="FilterBackgroundColor" -      reference="Black" /> -  <color -      name="FilterTextColor" -      value="0.38 0.69 0.57 1" /> -  <color -      name="FloaterButtonImageColor" -      reference="LtGray" /> -  <color -      name="FloaterDefaultBackgroundColor" -      reference="DkGray_66" /> -  <color -      name="FloaterFocusBackgroundColor" -      reference="DkGray2" /> -  <color -      name="FloaterFocusBorderColor" -      reference="Black_50" /> -  <color -      name="FloaterUnfocusBorderColor" -      reference="Black_50" /> -  <color -      name="FocusColor" -      reference="EmphasisColor" /> -  <color -      name="FolderViewLoadingMessageTextColor" -      value="0.3344 0.5456 0.5159 1" /> -  <color -      name="GridFocusPointColor" -      reference="White_50" /> -  <color -      name="GridlineBGColor" -      value="0.92 0.92 1 0.78" /> -  <color -      name="GridlineColor" -      reference="White" /> -  <color -      name="GridlineShadowColor" -      value="0 0 0 0.31" /> -  <color -      name="GroupNotifyBoxColor" -      value="0.3344 0.5456 0.5159 1" /> -  <color -      name="GroupNotifyTextColor" -      reference="White"/> -  <color -      name="GroupNotifyDimmedTextColor" -      reference="LtGray" /> -  <color -      name="GroupOverTierColor" -      value="0.43 0.06 0.06 1" /> -  <color -      name="HTMLLinkColor" -      reference="EmphasisColor" /> -  <color -      name="HealthTextColor" -      reference="White" /> -  <color -      name="HelpBgColor" -      reference="Unused?" /> -  <color -      name="HelpFgColor" -      reference="Unused?" /> -  <color -      name="HelpScrollHighlightColor" -      reference="Unused?" /> -  <color -      name="HelpScrollShadowColor" -      reference="Unused?" /> -  <color -      name="HelpScrollThumbColor" -      reference="Unused?" /> -  <color -      name="HelpScrollTrackColor" -      reference="Unused?" /> -  <color -      name="HighlightChildColor" -      reference="Yellow" /> -  <color -      name="HighlightInspectColor" -      value="1 0 1 1" /> -  <color -      name="HighlightParentColor" -      value="0.67 0.83 0.96 1" /> -  <color -      name="IMHistoryBgColor" -      reference="Unused?" /> -  <color -      name="IMHistoryTextColor" -      reference="Unused?" /> -  <color -      name="IconDisabledColor" -      reference="White_25" /> -  <color -      name="IconEnabledColor" -      reference="White" /> -  <color -      name="InventoryBackgroundColor" -      reference="DkGray2" /> -  <color -      name="InventoryFocusOutlineColor" -      reference="White_25" /> -  <color -      name="InventoryItemSuffixColor" -      reference="White_25" /> -  <color -      name="InventoryItemLibraryColor" -      reference="EmphasisColor" /> -  <color -      name="InventoryItemLinkColor" -      reference="LtGray_50" /> -  <color -      name="InventoryMouseOverColor" -      reference="LtGray_35" /> -  <color -      name="InventorySearchStatusColor" -      reference="EmphasisColor" /> -  <color -      name="LabelDisabledColor" -      reference="White_25" /> -  <color -      name="LabelSelectedColor" -      reference="White" /> -  <color -      name="LabelSelectedDisabledColor" -      reference="White_25" /> -  <color -      name="LabelTextColor" -      reference="LtGray" /> -  <color -      name="LoginProgressBarBgColor" -      reference="Unused?" /> -  <color -      name="LoginProgressBarFgColor" -      reference="Unused?" /> -  <color -      name="LoginProgressBoxBorderColor" -      value="0 0.12 0.24 0" /> -  <color -      name="LoginProgressBoxCenterColor" -      value="0 0 0 0.78" /> -  <color -      name="LoginProgressBoxShadowColor" -      value="0 0 0 0.78" /> -  <color -      name="LoginProgressBoxTextColor" -      reference="White" /> -  <color -      name="MapAvatarColor" -      reference="Green" /> -  <color -      name="MapAvatarFriendColor" -      reference="Yellow" /> -  <color -      name="MapAvatarSelfColor" -      value="0.53125 0 0.498047 1" /> -  <color -      name="MapFrustumColor" -      reference="White_10" /> -  <color -      name="MapFrustumRotatingColor" -      value="1 1 1 0.2" /> -  <color -      name="MapTrackColor" -      reference="Red" /> -  <color -      name="MapTrackDisabledColor" -      value="0.5 0 0 1" /> -  <color -      name="MenuBarBgColor" -      reference="DkGray" /> -  <color -      name="MenuBarGodBgColor" -      reference="FrogGreen" /> -  <color -      name="MenuDefaultBgColor" -      reference="DkGray2" /> -  <color -      name="MenuItemDisabledColor" -      reference="LtGray_50" /> -  <color -      name="MenuItemEnabledColor" -      reference="LtGray" /> -  <color -      name="MenuItemHighlightBgColor" -      reference="EmphasisColor_35" /> -  <color -      name="MenuItemHighlightFgColor" -      reference="White" /> -  <color -      name="MenuNonProductionBgColor" -      reference="Black" /> -  <color -      name="MenuNonProductionGodBgColor" -      value="0.263 0.325 0.345 1" /> -  <color -      name="MenuPopupBgColor" -      reference="DkGray2" /> -  <color -      name="ModelUploaderLabels" -      value="1 0.6 0 1" />	   -  <color -      name="MultiSliderDisabledThumbColor" -      reference="Black" /> -  <color -      name="MultiSliderThumbCenterColor" -      reference="White" /> -  <color -      name="MultiSliderThumbCenterSelectedColor" -      reference="Green" /> -  <color -      name="MultiSliderThumbOutlineColor" -      reference="Unused?" /> -  <color -      name="MultiSliderTrackColor" -      reference="LtGray" /> -  <color -      name="MultiSliderTriangleColor" -      reference="Yellow" /> +    <color +     name="AccordionHeaderTextColor" +     reference="LtGray" /> +    <color +     name="AgentChatColor" +     reference="White" /> +    <color +     name="AlertBoxColor" +     value="0.24 0.24 0.24 1" /> +    <color +     name="AlertCautionBoxColor" +     value="1 0.82 0.46 1" /> +    <color +     name="AlertCautionTextColor" +     reference="LtYellow" /> +    <color +     name="AvatarListItemIconDefaultColor" +     reference="White" /> +    <color +     name="AvatarListItemIconOnlineColor" +     reference="White" /> +    <color +     name="AvatarListItemIconOfflineColor" +     value="0.5 0.5 0.5 0.5" /> +    <color +     name="AvatarListItemIconVoiceInvitedColor" +     reference="AvatarListItemIconOfflineColor" /> +    <color +     name="AvatarListItemIconVoiceJoinedColor" +     reference="AvatarListItemIconOnlineColor" /> +    <color +     name="AvatarListItemIconVoiceLeftColor" +     reference="AvatarListItemIconOfflineColor" /> +    <color +     name="BadgeImageColor" +     value="1.0 0.40 0.0 1.0" /> +    <color +     name="BadgeBorderColor" +     value="0.9 0.9 0.9 1.0" /> +    <color +     name="BadgeLabelColor" +     reference="White" /> +    <color +     name="ButtonBorderColor" +     reference="Unused?" /> +    <color +     name="ButtonCautionImageColor" +     reference="Unused?" /> +    <color +     name="ButtonColor" +     reference="Unused?" /> +    <color +     name="ButtonFlashBgColor" +     reference="Unused?" /> +    <color +     name="ButtonImageColor" +     reference="White" /> +    <color +     name="ButtonLabelColor" +     reference="LtGray" /> +    <color +     name="ButtonLabelDisabledColor" +     reference="White_25" /> +    <color +     name="ButtonLabelSelectedColor" +     reference="White" /> +    <color +     name="ButtonLabelSelectedDisabledColor" +     reference="White_25" /> +    <color +     name="ButtonSelectedBgColor" +     reference="Unused?" /> +    <color +     name="ButtonSelectedColor" +     reference="Unused?" /> +    <color +     name="ButtonUnselectedBgColor" +     reference="Unused?" /> +    <color +     name="ButtonUnselectedFgColor" +     reference="Unused?" /> +    <color +     name="ChatHistoryBgColor" +     reference="Transparent" /> +    <color +     name="ChatHistoryTextColor" +     reference="LtGray" /> +    <color +     name="ChicletFlashColor" +     value="0.114 0.65 0.1" /> +    <color +     name="ColorDropShadow" +     reference="Black_50" /> +    <color +     name="ColorPaletteEntry01" +     reference="Black" /> +    <color +     name="ColorPaletteEntry02" +     reference="Gray" /> +    <color +     name="ColorPaletteEntry03" +     value="0.5 0 0 1" /> +    <color +     name="ColorPaletteEntry04" +     value="0.5 0.5 0 1" /> +    <color +     name="ColorPaletteEntry05" +     value="0 0.5 0 1" /> +    <color +     name="ColorPaletteEntry06" +     value="0 0.5 0.5 1" /> +    <color +     name="ColorPaletteEntry07" +     value="0 0 0.5 1" /> +    <color +     name="ColorPaletteEntry08" +     value="0.5 0 0.5 1" /> +    <color +     name="ColorPaletteEntry09" +     value="0.5 0.5 0 1" /> +    <color +     name="ColorPaletteEntry10" +     value="0 0.25 0.25 1" /> +    <color +     name="ColorPaletteEntry11" +     value="0 0.5 1 1" /> +    <color +     name="ColorPaletteEntry12" +     value="0 0.25 0.5 1" /> +    <color +     name="ColorPaletteEntry13" +     value="0.5 0 1 1" /> +    <color +     name="ColorPaletteEntry14" +     value="0.5 0.25 0 1" /> +    <color +     name="ColorPaletteEntry15" +     reference="White" /> +    <color +     name="ColorPaletteEntry16" +     reference="LtYellow" /> +    <color +     name="ColorPaletteEntry17" +     reference="White" /> +    <color +     name="ColorPaletteEntry18" +     reference="LtGray" /> +    <color +     name="ColorPaletteEntry19" +     reference="Red" /> +    <color +     name="ColorPaletteEntry20" +     reference="Yellow" /> +    <color +     name="ColorPaletteEntry21" +     reference="Green" /> +    <color +     name="ColorPaletteEntry22" +     value="0 1 1 1" /> +    <color +     name="ColorPaletteEntry23" +     reference="Blue" /> +    <color +     name="ColorPaletteEntry24" +     reference="Purple" /> +    <color +     name="ColorPaletteEntry25" +     value="1 1 0.5 1" /> +    <color +     name="ColorPaletteEntry26" +     value="0 1 0.5 1" /> +    <color +     name="ColorPaletteEntry27" +     value="0.5 1 1 1" /> +    <color +     name="ColorPaletteEntry28" +     value="0.5 0.5 1 1" /> +    <color +     name="ColorPaletteEntry29" +     value="1 0 0.5 1" /> +    <color +     name="ColorPaletteEntry30" +     value="1 0.5 0 1" /> +    <color +     name="ColorPaletteEntry31" +     reference="White" /> +    <color +     name="ColorPaletteEntry32" +     reference="White" /> +    <color +     name="ComboListBgColor" +     reference="DkGray" /> +    <color +     name="ConsoleBackground" +     reference="Black" /> +    <color +     name="ContextSilhouetteColor" +     reference="EmphasisColor" /> +    <color +     name="DefaultHighlightDark" +     reference="White_10" /> +    <color +     name="DefaultHighlightLight" +     reference="White_25" /> +    <color +     name="DefaultShadowDark" +     reference="Black_50" /> +    <color +     name="DefaultShadowLight" +     reference="Black_50" /> +    <color +     name="EffectColor" +     reference="White" /> +     <color +     name="FilterBackgroundColor" +     reference="Black" /> +    <color +     name="FilterTextColor" +     value="0.38 0.69 0.57 1" /> +     <color +     name="FloaterButtonImageColor" +     reference="LtGray" /> +    <color +     name="FloaterDefaultBackgroundColor" +     reference="DkGray_66" /> +    <color +     name="FloaterFocusBackgroundColor" +     reference="DkGray2" /> +    <color +     name="FloaterFocusBorderColor" +     reference="Black_50" /> +    <color +     name="FloaterUnfocusBorderColor" +     reference="Black_50" /> +    <color +     name="FocusColor" +     reference="EmphasisColor" /> +    <color +     name="FolderViewLoadingMessageTextColor" +     value="0.3344 0.5456 0.5159 1" /> +    <color +     name="GridFocusPointColor" +     reference="White_50" /> +    <color +     name="GridlineBGColor" +     value="0.92 0.92 1 0.78" /> +    <color +     name="GridlineColor" +     reference="White" /> +    <color +     name="GridlineShadowColor" +     value="0 0 0 0.31" /> +    <color +     name="GroupNotifyBoxColor" +     value="0.3344 0.5456 0.5159 1" /> +    <color +     name="GroupNotifyTextColor" +     reference="White"/> +    <color +     name="GroupNotifyDimmedTextColor" +     reference="LtGray" /> +    <color +     name="GroupOverTierColor" +     value="0.43 0.06 0.06 1" /> +    <color +     name="HTMLLinkColor" +     reference="EmphasisColor" /> +    <color +     name="HealthTextColor" +     reference="White" /> +    <color +     name="HelpBgColor" +     reference="Unused?" /> +    <color +     name="HelpFgColor" +     reference="Unused?" /> +    <color +     name="HelpScrollHighlightColor" +     reference="Unused?" /> +    <color +     name="HelpScrollShadowColor" +     reference="Unused?" /> +    <color +     name="HelpScrollThumbColor" +     reference="Unused?" /> +    <color +     name="HelpScrollTrackColor" +     reference="Unused?" /> +    <color +     name="HighlightChildColor" +     reference="Yellow" /> +    <color +     name="HighlightInspectColor" +     value="1 0 1 1" /> +    <color +     name="HighlightParentColor" +     value="0.67 0.83 0.96 1" /> +    <color +     name="IMHistoryBgColor" +     reference="Unused?" /> +    <color +     name="IMHistoryTextColor" +     reference="Unused?" /> +    <color +     name="IconDisabledColor" +	 reference="White_25" /> +    <color +     name="IconEnabledColor" +     reference="White" /> +    <color +     name="InventoryBackgroundColor" +     reference="DkGray2" /> +    <color +     name="InventoryFocusOutlineColor" +     reference="White_25" /> +    <color +     name="InventoryItemSuffixColor" +     reference="White_25" /> +    <color +     name="InventoryItemLibraryColor" +     reference="EmphasisColor" /> +    <color +     name="InventoryItemLinkColor" +     reference="LtGray_50" /> +    <color +     name="InventoryMouseOverColor" +     reference="LtGray_35" /> +    <color +     name="InventorySearchStatusColor" +     reference="EmphasisColor" /> +    <color +     name="LabelDisabledColor" +     reference="White_25" /> +    <color +     name="LabelSelectedColor" +     reference="White" /> +    <color +     name="LabelSelectedDisabledColor" +     reference="White_25" /> +    <color +     name="LabelTextColor" +     reference="LtGray" /> +    <color +     name="LoginProgressBarBgColor" +     reference="Unused?" /> +    <color +     name="LoginProgressBarFgColor" +     reference="Unused?" /> +    <color +     name="LoginProgressBoxBorderColor" +     value="0 0.12 0.24 0" /> +    <color +     name="LoginProgressBoxCenterColor" +     value="0 0 0 0.78" /> +    <color +     name="LoginProgressBoxShadowColor" +     value="0 0 0 0.78" /> +    <color +     name="LoginProgressBoxTextColor" +     reference="White" /> +    <color +     name="MapAvatarColor" +     reference="Green" /> +    <color +     name="MapAvatarFriendColor" +     reference="Yellow" /> +    <color +     name="MapAvatarSelfColor" +     value="0.53125 0 0.498047 1" /> +    <color +     name="MapFrustumColor" +     reference="White_10" /> +    <color +     name="MapFrustumRotatingColor" +     value="1 1 1 0.2" /> +    <color +     name="MapTrackColor" +     reference="Red" /> +    <color +     name="MapTrackDisabledColor" +     value="0.5 0 0 1" /> +    <color +     name="MenuBarBgColor" +     reference="DkGray" /> +    <color +     name="MenuBarGodBgColor" +     reference="FrogGreen" /> +    <color +     name="MenuDefaultBgColor" +     reference="DkGray2" /> +    <color +     name="MenuItemDisabledColor" +	 reference="LtGray_50" /> +    <color +     name="MenuItemEnabledColor" +     reference="LtGray" /> +    <color +     name="MenuItemHighlightBgColor" +     reference="EmphasisColor_35" /> +    <color +     name="MenuItemHighlightFgColor" +     reference="White" /> +    <color +     name="MenuNonProductionBgColor" +     reference="Black" /> +    <color +     name="MenuNonProductionGodBgColor" +     value="0.263 0.325 0.345 1" /> +    <color +     name="MenuPopupBgColor" +	  reference="DkGray2" /> +    <color +     name="ModelUploaderLabels" +     value="1 0.6 0 1" />	   +    <color +     name="MultiSliderDisabledThumbColor" +     reference="Black" /> +    <color +     name="MultiSliderThumbCenterColor" +     reference="White" /> +    <color +     name="MultiSliderThumbCenterSelectedColor" +     reference="Green" /> +    <color +     name="MultiSliderThumbOutlineColor" +     reference="Unused?" /> +    <color +     name="MultiSliderTrackColor" +     reference="LtGray" /> +    <color +     name="MultiSliderTriangleColor" +     reference="Yellow" />    <!-- -      <color +    <color        name="NameTagBackground"        value="0.85 0.85 0.85 0.80" /> -  --> -  <color +      --> +    <color        name="NameTagBackground"        value="0 0 0 1" /> -  <color -      name="NameTagChat" -      reference="White" /> -  <color -      name="NameTagFriend" -      value="0.447 0.784 0.663 1" /> -  <color -      name="NameTagLegacy" -      reference="White" /> -  <color -      name="NameTagMatch" -      reference="White" /> -  <color -      name="NameTagMismatch" -      reference="White" /> -  <color -      name="NetMapBackgroundColor" -      value="0 0 0 1" /> -  <color -      name="NetMapGroupOwnAboveWater" -      reference="Purple" /> -  <color -      name="NetMapGroupOwnBelowWater" -      value="0.78 0 0.78 1" /> -  <color -      name="NetMapOtherOwnAboveWater" -      value="0.24 0.24 0.24 1" /> -  <color -      name="NetMapOtherOwnBelowWater" -      value="0.12 0.12 0.12 1" /> -  <color -      name="NetMapYouOwnAboveWater" -      value="0 1 1 1" /> -  <color -      name="NetMapYouOwnBelowWater" -      value="0 0.78 0.78 1" /> -  <color -      name="NotifyBoxColor" -      value="LtGray" /> -  <color -      name="NotifyCautionBoxColor" -      value="1 0.82 0.46 1" /> -  <color -      name="NotifyCautionWarnColor" -      reference="White" /> -  <color -      name="NotifyTextColor" -      reference="White" /> -  <color -      name="ObjectBubbleColor" -      reference="DkGray_66" /> -  <color -      name="ObjectChatColor" -      reference="EmphasisColor" /> -  <color -      name="OverdrivenColor" -      reference="Red" /> -  <color -      name="PanelDefaultBackgroundColor" -      reference="DkGray" /> -  <color -      name="PanelDefaultHighlightLight" -      reference="White_50" /> -  <color -      name="PanelFocusBackgroundColor" -      reference="DkGray2" /> -  <color -      name="PanelNotificationBackground" -      value="1 0.3 0.3 0" /> -  <color -      name="ParcelHoverColor" -      reference="White" /> -  <color +    <color +     name="NameTagChat" +     reference="White" /> +    <color +     name="NameTagFriend" +     value="0.447 0.784 0.663 1" /> +    <color +     name="NameTagLegacy" +     reference="White" /> +    <color +     name="NameTagMatch" +     reference="White" /> +    <color +     name="NameTagMismatch" +     reference="White" /> +    <color +     name="NetMapBackgroundColor" +     value="0 0 0 1" /> +    <color +     name="NetMapGroupOwnAboveWater" +     reference="Purple" /> +    <color +     name="NetMapGroupOwnBelowWater" +     value="0.78 0 0.78 1" /> +    <color +     name="NetMapOtherOwnAboveWater" +     value="0.24 0.24 0.24 1" /> +    <color +     name="NetMapOtherOwnBelowWater" +     value="0.12 0.12 0.12 1" /> +    <color +     name="NetMapYouOwnAboveWater" +     value="0 1 1 1" /> +    <color +     name="NetMapYouOwnBelowWater" +     value="0 0.78 0.78 1" /> +    <color +     name="NotifyBoxColor" +     value="LtGray" /> +    <color +     name="NotifyCautionBoxColor" +     value="1 0.82 0.46 1" /> +    <color +     name="NotifyCautionWarnColor" +     reference="White" /> +    <color +     name="NotifyTextColor" +     reference="White" /> +    <color +     name="ObjectBubbleColor" +     reference="DkGray_66" /> +    <color +     name="ObjectChatColor" +     reference="EmphasisColor" /> +    <color +     name="OverdrivenColor" +     reference="Red" /> +    <color +     name="PanelDefaultBackgroundColor" +     reference="DkGray" /> +    <color +     name="PanelDefaultHighlightLight" +     reference="White_50" /> +    <color +     name="PanelFocusBackgroundColor" +     reference="DkGray2" /> +    <color +     name="PanelNotificationBackground" +     value="1 0.3 0.3 0" /> +    <color +     name="ParcelHoverColor" +     reference="White" /> +    <color        name="PathfindingErrorColor"        reference="LtRed" />    <color @@ -657,205 +657,205 @@        name="PathfindingCharacterBeaconColor"        reference="Red_80" />    <color -      name="PieMenuBgColor" -      value="0.24 0.24 0.24 0.59" /> -  <color -      name="PieMenuLineColor" -      value="0 0 0 0.5" /> -  <color -      name="PieMenuSelectedColor" -      value="0.72 0.72 0.74 0.3" /> -  <color -      name="PropertyColorAuction" -      value="0.5 0 1 0.4" /> -  <color -      name="PropertyColorAvail" -      reference="Transparent" /> -  <color -      name="PropertyColorForSale" -      value="1 0.5 0 0.4" /> -  <color -      name="PropertyColorGroup" -      value="0 0.72 0.72 0.4" /> -  <color -      name="PropertyColorOther" -      value="1 0 0 0.4" /> -  <color -      name="PropertyColorSelf" -      value="0 1 0 0.4" /> -  <color -      name="ScriptBgReadOnlyColor" -      value="0.39 0.39 0.39 1" /> -  <color -      name="ScriptErrorColor" -      reference="Red" /> -  <color -      name="ScrollBGStripeColor" -      reference="Transparent" /> -  <color -      name="ScrollBgReadOnlyColor" +     name="PieMenuBgColor" +     value="0.24 0.24 0.24 0.59" /> +    <color +     name="PieMenuLineColor" +     value="0 0 0 0.5" /> +    <color +     name="PieMenuSelectedColor" +     value="0.72 0.72 0.74 0.3" /> +    <color +     name="PropertyColorAuction" +     value="0.5 0 1 0.4" /> +    <color +     name="PropertyColorAvail" +     reference="Transparent" /> +    <color +     name="PropertyColorForSale" +     value="1 0.5 0 0.4" /> +    <color +     name="PropertyColorGroup" +     value="0 0.72 0.72 0.4" /> +    <color +     name="PropertyColorOther" +     value="1 0 0 0.4" /> +    <color +     name="PropertyColorSelf" +     value="0 1 0 0.4" /> +    <color +     name="ScriptBgReadOnlyColor" +     value="0.39 0.39 0.39 1" /> +    <color +     name="ScriptErrorColor" +     reference="Red" /> +    <color +     name="ScrollBGStripeColor" +     reference="Transparent" /> +    <color +     name="ScrollBgReadOnlyColor"        reference="Transparent" /> -  <color -      name="ScrollBgWriteableColor" -      reference="White_05" /> -  <color -      name="ScrollDisabledColor" -      reference="White_25" /> -  <color -      name="ScrollHighlightedColor" -      reference="Unused?" /> -  <color -      name="ScrollHoveredColor" -      reference="EmphasisColor_13" /> -  <color -      name="ScrollSelectedBGColor" -      reference="EmphasisColor_35" /> -  <color -      name="ScrollSelectedFGColor" -      reference="White" /> -  <color -      name="ScrollUnselectedColor" -      reference="LtGray" /> -  <color -      name="ScrollbarThumbColor" -      reference="White" /> -  <color -      name="ScrollbarTrackColor" -      reference="Black" /> -  <color -      name="SelectedOutfitTextColor" -      reference="EmphasisColor" /> -  <color -      name="SilhouetteChildColor" -      value="0.13 0.42 0.77 1" /> -  <color -      name="SilhouetteParentColor" -      reference="Yellow" /> -  <color -      name="SliderDisabledThumbColor" -      reference="White_25" /> -  <color -      name="SliderThumbCenterColor" -      reference="White" /> -  <color -      name="SliderThumbOutlineColor" -      reference="White" /> -  <color -      name="SliderTrackColor" -      reference="Unused?" /> -  <color -      name="SpeakingColor" -      reference="FrogGreen" /> -  <color -      name="SystemChatColor" -      reference="LtGray" /> -  <color -      name="TextBgFocusColor" -      reference="White" /> -  <color -      name="TextBgReadOnlyColor" -      reference="White_05" /> -  <color -      name="TextBgWriteableColor" -      reference="LtGray" /> -  <color -      name="TextCursorColor" -      reference="Black" /> -  <color -      name="TextDefaultColor" -      reference="Black" /> -  <color -      name="TextEmbeddedItemColor" -      value="0 0 0.5 1" /> -  <color -      name="TextEmbeddedItemReadOnlyColor" -      reference="Unused?" /> -  <color -      name="TextFgColor" -      value="0.102 0.102 0.102 1" /> -  <color -      name="TextFgReadOnlyColor" -      reference="LtGray" /> -  <color -      name="TextFgTentativeColor" -      value="0.4 0.4 0.4 1" /> -  <color -      name="TimeTextColor" -      reference="LtGray" /> -  <color -      name="TitleBarFocusColor" -      reference="White_10" /> -  <color -      name="ToastBackground" -      value="0.3 0.3 0.3 0" /> -  <color -      name="ToolTipBgColor" -      value="0.937 0.89 0.655 1" /> -  <color -      name="ToolTipBorderColor" -      value="0.812 0.753 0.451 1" /> -  <color -      name="ToolTipTextColor" -      reference="DkGray2" /> -  <color -      name="InspectorTipTextColor" -      reference="LtGray" /> -  <color -      name="UserChatColor" -      reference="White" /> -  <color -      name="llOwnerSayChatColor" -      reference="LtYellow" /> +    <color +     name="ScrollBgWriteableColor" +     reference="White_05" /> +    <color +     name="ScrollDisabledColor" +     reference="White_25" /> +    <color +     name="ScrollHighlightedColor" +     reference="Unused?" /> +    <color +     name="ScrollHoveredColor" +     reference="EmphasisColor_13" /> +    <color +     name="ScrollSelectedBGColor" +     reference="EmphasisColor_35" /> +    <color +     name="ScrollSelectedFGColor" +     reference="White" /> +    <color +     name="ScrollUnselectedColor" +     reference="LtGray" /> +    <color +     name="ScrollbarThumbColor" +     reference="White" /> +    <color +     name="ScrollbarTrackColor" +     reference="Black" /> +    <color +     name="SelectedOutfitTextColor" +     reference="EmphasisColor" /> +    <color +     name="SilhouetteChildColor" +     value="0.13 0.42 0.77 1" /> +    <color +     name="SilhouetteParentColor" +     reference="Yellow" /> +    <color +     name="SliderDisabledThumbColor" +     reference="White_25" /> +    <color +     name="SliderThumbCenterColor" +     reference="White" /> +    <color +     name="SliderThumbOutlineColor" +     reference="White" /> +    <color +     name="SliderTrackColor" +     reference="Unused?" /> +    <color +     name="SpeakingColor" +     reference="FrogGreen" /> +    <color +     name="SystemChatColor" +     reference="LtGray" /> +    <color +     name="TextBgFocusColor" +     reference="White" /> +    <color +     name="TextBgReadOnlyColor" +	 reference="White_05" /> +    <color +     name="TextBgWriteableColor" +     reference="LtGray" /> +    <color +     name="TextCursorColor" +     reference="Black" /> +    <color +     name="TextDefaultColor" +     reference="Black" /> +    <color +     name="TextEmbeddedItemColor" +     value="0 0 0.5 1" /> +    <color +     name="TextEmbeddedItemReadOnlyColor" +     reference="Unused?" /> +    <color +     name="TextFgColor" +     value="0.102 0.102 0.102 1" /> +    <color +     name="TextFgReadOnlyColor" +     reference="LtGray" /> +    <color +     name="TextFgTentativeColor" +     value="0.4 0.4 0.4 1" /> +    <color +     name="TimeTextColor" +     reference="LtGray" /> +    <color +     name="TitleBarFocusColor" +     reference="White_10" /> +    <color +     name="ToastBackground" +     value="0.3 0.3 0.3 0" /> +    <color +     name="ToolTipBgColor" +     value="0.937 0.89 0.655 1" /> +    <color +     name="ToolTipBorderColor" +     value="0.812 0.753 0.451 1" /> +    <color +     name="ToolTipTextColor" +     reference="DkGray2" /> +    <color +     name="InspectorTipTextColor" +     reference="LtGray" /> +    <color +     name="UserChatColor" +     reference="Yellow" /> +    <color +     name="llOwnerSayChatColor" +     reference="LtYellow" /> -  <!-- New Colors --> -  <color -      name="OutputMonitorMutedColor" -      reference="DkGray2" /> -  <color -      name="SysWellItemUnselected" -      value="0 0 0 0" /> -  <color -      name="SysWellItemSelected" -      value="0.3 0.3 0.3 1.0" /> -  <color -      name="ColorSwatchBorderColor" -      value="0.45098 0.517647 0.607843 1"/> -  <color -      name="ChatTimestampColor" -      reference="White" /> -  <color -      name="MenuBarProjectBgColor" -      reference="MdBlue" /> +    <!-- New Colors --> +    <color +     name="OutputMonitorMutedColor" +     reference="DkGray2" /> +    <color +     name="SysWellItemUnselected" +     value="0 0 0 0" /> +    <color +     name="SysWellItemSelected" +     value="0.3 0.3 0.3 1.0" /> +    <color +    name="ColorSwatchBorderColor" +    value="0.45098 0.517647 0.607843 1"/> +    <color +     name="ChatTimestampColor" +     reference="White" /> +    <color +     name="MenuBarProjectBgColor" +     reference="MdBlue" /> -  <color +    <color        name="MeshImportTableNormalColor"        value="1 1 1 1"/> -  <color +    <color        name="MeshImportTableHighlightColor"        value="0.2 0.8 1 1"/> -  <color -      name="DirectChatColor" -      reference="LtOrange" /> +    <color +     name="DirectChatColor" +     reference="LtOrange" /> -  <color +    <color        name="ToolbarDropZoneColor"        value=".48 .69 1 .5" /> -  <!-- Generic color names (legacy) --> +    <!-- Generic color names (legacy) -->    <color -      name="white" -      value="1 1 1 1"/> +    name="white" +    value="1 1 1 1"/>    <color -      name="black" -      value="0 0 0 1"/> +    name="black" +    value="0 0 0 1"/>    <color -      name="red" -      value="1 0 0 1"/> +    name="red" +    value="1 0 0 1"/>    <color -      name="green" -      value="0 1 0 1"/> +    name="green" +    value="0 1 0 1"/>    <color -      name="blue" -      value="0 0 1 1"/> +    name="blue" +    value="0 0 1 1"/>  </colors> diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png Binary files differnew file mode 100755 index 0000000000..f024c733f3 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png Binary files differnew file mode 100755 index 0000000000..a19e720d42 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png Binary files differnew file mode 100755 index 0000000000..7f3f42639d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png Binary files differnew file mode 100755 index 0000000000..2880eb766a --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png Binary files differnew file mode 100755 index 0000000000..25a939d7f5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png Binary files differnew file mode 100755 index 0000000000..82baabde47 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png Binary files differnew file mode 100755 index 0000000000..7d64abb042 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png Binary files differnew file mode 100755 index 0000000000..f0da962c2d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png Binary files differnew file mode 100755 index 0000000000..0db001dcdb --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png Binary files differnew file mode 100755 index 0000000000..0cf7edc2d4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png Binary files differnew file mode 100755 index 0000000000..a0c15a6d3e --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 06f8f8c670..212f05d284 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -162,7 +162,21 @@ with the same filename but different name    <texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />    <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" /> +    <texture name="Container" file_name="containers/Container.png" preload="false" /> + +  <texture name="Conv_toolbar_add_person" file_name="icons/Conv_toolbar_add_person.png" preload="false" /> +  <texture name="Conv_toolbar_arrow_ne" file_name="icons/Conv_toolbar_arrow_ne.png" preload="false" /> +  <texture name="Conv_toolbar_arrow_sw" file_name="icons/Conv_toolbar_arrow_sw.png" preload="false" /> +  <texture name="Conv_toolbar_call_log" file_name="icons/Conv_toolbar_call_log.png" preload="false" /> +  <texture name="Conv_toolbar_close" file_name="icons/Conv_toolbar_close.png" preload="false" /> +  <texture name="Conv_toolbar_collapse" file_name="icons/Conv_toolbar_collapse.png" preload="false" /> +  <texture name="Conv_toolbar_expand" file_name="icons/Conv_toolbar_expand.png" preload="false" /> +  <texture name="Conv_toolbar_hang_up" file_name="icons/Conv_toolbar_hang_up.png" preload="false" /> +  <texture name="Conv_toolbar_open_call" file_name="icons/Conv_toolbar_open_call.png" preload="false" /> +  <texture name="Conv_toolbar_plus" file_name="icons/Conv_toolbar_plus.png" preload="false" /> +  <texture name="Conv_toolbar_sort" file_name="icons/Conv_toolbar_sort.png" preload="false" /> +    <texture name="Copy" file_name="icons/Copy.png" preload="false" />    <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml deleted file mode 100644 index 405557242f..0000000000 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ /dev/null @@ -1,85 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="specified" - left="10" - bottom="-10" - height="60" - layout="topleft" - legacy_header_height="25" - single_instance="true" - title="NEARBY CHAT" - save_rect="true" - save_visibility="true" - can_close="true" - can_minimize="true" - help_topic="chat_bar" - min_height="60" - min_width="150" - can_resize="true" - default_tab_group="1" - name="chat_bar" - width="300"> -    <panel -        top="20" -        class="panel_nearby_chat" -        follow="all" -        width="300" -        height="0" -        visible="false" -        filename="panel_nearby_chat.xml" -        name="nearby_chat" /> -    <panel width="300"  -           height="31"  -           left="0"  -           name="bottom_panel" -           bottom="-1"  -           follows="left|right|bottom"  -           tab_group="1"> -      <line_editor -        border_style="line" -        border_thickness="1" -        follows="left|right" -        height="23" -        label="Click here to chat." -        layout="topleft" -        left_delta="7" -        left="0" -        max_length_bytes="1023" -        name="chat_box" -        spellcheck="true" -        text_pad_left="5" -        text_pad_right="25" -        tool_tip="Press Enter to say, Ctrl+Enter to shout" -        top="2" -        width="255" /> -      <output_monitor -        auto_update="true" -        follows="right" -        draw_border="false" -        height="16" -        layout="topleft" -        left_pad="-24" -        mouse_opaque="true" -        name="chat_zone_indicator" -        top="6" -        visible="true" -        width="20" /> -      <button -        follows="right" -        is_toggle="true" -        width="20" -        top="2" -        layout="topleft" -        left_pad="12" -        image_disabled="ComboButton_UpOff" -        image_unselected="ComboButton_UpOff" -        image_selected="ComboButton_On" -        image_pressed="ComboButton_UpSelected" -        image_pressed_selected="ComboButton_Selected" -        height="23" -        chrome="true" -        name="show_nearby_chat" -        tool_tip="Shows/hides nearby chat log"> -      </button> -    </panel> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_conversation_log.xml b/indra/newview/skins/default/xui/en/floater_conversation_log.xml new file mode 100644 index 0000000000..9cdeb0d788 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_log.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> + +<floater +  can_resize="true" +  positioning="cascading" +  height="400" +  min_height="100" +  min_width="390" +  layout="topleft" +  name="floater_conversation_log" +  save_rect="true" +  single_instance="true" +  reuse_instance="true" +  title="CONVERSATION LOG" +  width="450"> +	<panel +      follows="left|top|right" +      height="27" +      layout="topleft" +      left="0" +      name="buttons_panel" +      top="0"> +        <filter_editor +          follows="left|top|right" +          height="23" +          layout="topleft" +          left="8" +          label="Filter People" +          max_length_chars="300" +          name="people_filter_input" +          text_color="Black" +          text_pad_left="10" +          top="4" +          width="364" /> +        <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="Conv_toolbar_sort" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="5" +          menu_filename="menu_conversation_log_view.xml" +          menu_position="bottomleft" +          name="conversation_view_btn" +          top="3" +          width="31" /> +        <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="OptionsMenu_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="2" +          name="conversations_gear_btn" +          top="3" +          width="31" /> +    </panel> +    <panel +      follows="all" +      height="370" +      layout="topleft" +      left="5" +      name="buttons_panel" +      right="-5" +      top_pad="5"> +    <conversation_log_list +      opaque="true" +      allow_select="true" +      follows="all" +      height="360" +      layout="topleft" +      left="3" +      keep_selection_visible_on_reshape="true" +      item_pad="2" +      multi_select="false" +      name="conversation_log_list" +      right="-3" +      top="5" /> +    </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_conversation_preview.xml b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml new file mode 100644 index 0000000000..27b744aefb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_conversation_preview.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + default_tab_group="1" + height="361" + layout="topleft" + min_height="243" + min_width="234" + name="preview_conversation" + title="CONVERSATION:" + width="400"> +    <floater.string +     name="Title"> +        CONVERSATION: [NAME] +    </floater.string> +    <text +     type="string" +     length="1" +     follows="left|top" +     font="SansSerif" +     height="19" +     layout="topleft" +     left="10" +     name="desc txt" +     top="22" +     width="90"> +        Description: +    </text> +    <line_editor +     border_style="line" +     border_thickness="1" +     enabled="false" +     follows="left|top|right" +     font="SansSerif" +     height="22" +     layout="topleft" +     left_pad="0" +     max_length_bytes="127" +     name="description" +     width="296" /> +    <chat_history +     font="SansSerifSmall" +     follows="all" +     visible="true" +     height="310" +     name="chat_history" +     parse_highlights="true" +     parse_urls="true" +     left="5" +     width="390"> +    </chat_history> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e123de46c2..ea6fd65b95 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -1,49 +1,127 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <multi_floater - can_close="false"   + can_close="true"     can_minimize="true"   can_resize="true" - height="390" + height="430"   layout="topleft" + min_height="50"   name="floater_im_box"   help_topic="floater_im_box"   save_rect="true"   save_visibility="true"   single_instance="true"   title="CONVERSATIONS" - width="396"> -    <tab_container -     follows="left|right|top|bottom" -     height="390" + width="680"> +    <string +     name="collapse_icon" +     value="Conv_toolbar_collapse"/> +    <string +     name="expand_icon" +     value="Conv_toolbar_expand"/> +    <layout_stack +     animate="true"  +     follows="all" +     height="430"       layout="topleft" -     left="1" -     name="im_box_tab_container" -     tab_position="bottom" -     tab_width="64" -     tab_max_width = "134" -     tab_height="16" -     use_custom_icon_ctrl="true" -     tab_icon_ctrl_pad="2" -     halign="left" -     use_ellipses="true" +     left="0" +     name="conversations_stack" +     orientation="horizontal"       top="0" -     width="394"> -      <first_tab -       tab_bottom_image_flash="Toolbar_Left_Flash"/> -      <middle_tab -       tab_bottom_image_flash="Toolbar_Middle_Flash"/> -      <last_tab -       tab_bottom_image_flash="Toolbar_Right_Flash"/> -    </tab_container> -    <icon -     color="DefaultShadowLight" -     enabled="false" -     follows="left|right|bottom" -     height="17" -     image_name="tabarea.tga" -     layout="bottomleft" -     left="1" -     name="im_box_tab_container_icon" -     bottom="10" -     width="394" /> +     width="680"> +        <layout_panel +         auto_resize="true" +         user_resize="true"         +         height="430" +         name="conversations_layout_panel" +         min_dim="51" +         width="268" +         min_width="120"> +            <layout_stack +             animate="false"  +             follows="left|top|right" +             height="35" +             layout="topleft" +             left="0" +             name="conversations_pane_buttons_stack" +             orientation="horizontal" +             top="0" +             width="268"> +                <layout_panel +                 auto_resize="true" +                 height="35" +                 name="conversations_pane_buttons_expanded"> +                    <menu_button +                     follows="top|left" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_sort" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     menu_filename="menu_participant_view.xml" +                     layout="topleft" +                     left="10" +                     name="sort_btn" +                     top="5" +                     width="31" /> +                    <button +                     follows="top|left" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_plus" +                     image_selected="Toolbar_Middle_Selected" +                      image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="5" +                     left_pad="4" +                     name="add_btn" +                     tool_tip="Add button on the left panel" +                     width="31"/> +                </layout_panel> +                <layout_panel +                 auto_resize="false" +                 height="35" +                 name="conversations_pane_buttons_collapsed" +                 width="41"> +                    <button +                     follows="right|top" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="Conv_toolbar_collapse" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="5" +                     left="5" +                     name="expand_collapse_btn" +                     width="31" /> +                </layout_panel> +            </layout_stack> +            <panel +             follows="all" +             layout="topleft" +             name="conversations_list_panel" +             opaque="true" +             top_pad="0" +             left="5" +             height="390" +             width="263"/> +        </layout_panel> +        <layout_panel +         auto_resize="true" +         user_resize="true" +         height="430" +         name="messages_layout_panel" +         width="412" +         min_width="205"> +            <panel_container +             follows="all" +             height="430" +             layout="topleft" +             left="0" +             name="im_box_tab_container" +             top="0" +             width="412"/> +        </layout_panel> +    </layout_stack>  </multi_floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 040b66623e..4abe4d6941 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater - legacy_header_height="18"   background_visible="true"   default_tab_group="1"   height="355" @@ -10,84 +9,253 @@   can_dock="false"   can_minimize="true"   can_close="true" + save_rect="true"   visible="false"   width="394"   can_resize="true" + can_tear_off="false"   min_width="250" - min_height="190"> + min_height="190" + positioning="relative"> +    <floater.string  +     name="NearbyChatTitle" +     value="Nearby Chat"/> +    <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> +    <floater.string name="call_btn_stop">Conv_toolbar_hang_up</floater.string> +    <floater.string +     name="collapse_icon" +     value="Conv_toolbar_collapse"/> +    <floater.string +     name="expand_icon" +     value="Conv_toolbar_expand"/> +    <floater.string +     name="tear_off_icon" +     value="Conv_toolbar_arrow_ne"/> +    <floater.string +     name="return_icon" +     value="Conv_toolbar_arrow_sw"/> +    <view +        follows="all" +        layout="topleft" +        name="contents_view" +        top="0" +        left="0" +        height="355" +        width="394">  +     <panel +         follows="left|top|right" +         layout="topleft" +         name="toolbar_panel" +         top="0" +         left="0" +         height="35" +         width="394">          +             <menu_button +                 menu_filename="menu_im_session_showmodes.xml" +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left="5" +                 name="view_options_btn" +                 top="5" +                 width="31" /> +             <button +                 enabled="false" +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_add_person" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="4" +                 name="add_btn" +                 width="31"/> +             <button +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_open_call" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="4" +                 name="voice_call_btn" +                 width="31"/> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_close" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left="283" +                 name="close_btn" +                 width="31" /> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_collapse" +                 image_selected="Toolbar_Middle_Selected" +             	 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="5" +                 name="expand_collapse_btn" +                 width="31" /> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_arrow_ne" +                 image_selected="Toolbar_Middle_Selected" +             	 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="5" +                 name="tear_off_btn" +                 width="31" /> +     </panel>    <layout_stack     animate="true"      default_tab_group="2"    follows="all" -  height="320" +  height="310"    width="394"    layout="topleft"    orientation="horizontal"    name="im_panels"    tab_group="1" -  top="20" +  top_pad="0"    left="0">      <layout_panel -      name="im_control_panel_holder" +      name="speakers_list_panel" +      follows="all"        min_width="115"        width="150"  -      height="320"  +      height="310"         auto_resize="false"> -      <panel -        name="panel_im_control_panel" +            <avatar_list +             color="DkGray2" +             follows="all" +             height="310" +             ignore_online_status="true"          layout="topleft" -        height="320" -        width="150"  -        follows="all"/> +             name="speakers_list" +             opaque="false" +             show_info_btn="true" +             show_profile_btn="false" +             show_speaking_indicator="false" +             width="150" />        </layout_panel>      <layout_panel         default_tab_group="3"         left="0"         tab_group="2" +       follows="all"         top="0" -       height="200" -	     width="244" -       user_resize="true"> -        <button -          height="20" -          follows="left|top" -          top="0" -          left="2" -          image_overlay="TabIcon_Open_Off" +       height="310" +	   width="244" +       layout="topleft" +       user_resize="true" +       auto_resize="true" +       visible="true" +       name="left_part_holder"> +        <panel +         name="trnsAndChat_panel" +         follows="all" +         layout="topleft" +         visible="true" +         height="275" +         width="244"> +         <layout_stack +          animate="true"  +          default_tab_group="2" +          follows="all" +          height="275" +          width="244"            layout="topleft" -          width="25" -          name="slide_left_btn" /> -         <button -          height="20" -          follows="left|top" +          visible="true" +          orientation="vertical" +          name="translate_and_chat_stack" +          tab_group="1" +          left_pad="0"            top="0" -          left="2" -          image_overlay="TabIcon_Close_Off" -          width="25" -          name="slide_right_btn" /> +          left="0"> +            <layout_panel +             auto_resize="false" +             height="26" +             layout="topleft" +             left_delta="0" +             name="translate_chat_checkbox_lp" +             top_delta="0" +             visible="true" +             width="230"> +                <check_box +                 top="10" +                 control_name="TranslateChat" +                 enabled="true" +                 height="16" +                 label="Translate chat" +                 layout="topleft" +                 left="5" +                 name="translate_chat_checkbox" +                 width="230" /> +            </layout_panel> +            <layout_panel +             height="248" +             width="230" +             layout="topleft" +             follows="all" +             left_delta="0" +             top_delta="0" +             bottom="0" +             visible="true" +             user_resize="true" +             auto_resize="true" +             name="chat_holder">                <chat_history  	 font="SansSerifSmall" -         follows="left|right|top|bottom" -         height="150" +             		follows="all" +             		visible="true" +             		height="240"           name="chat_history"           parse_highlights="true"           parse_urls="true" -        left="1" -         width="238"> +       	 width="230" +       	 left="0">          </chat_history> -        <line_editor -         bottom="0" -         left="3" -         follows="left|right|bottom" -	 font="SansSerifSmall" -         height="20" -         label="To" -         layout="bottomleft" -         name="chat_editor" -         spellcheck="true" -         tab_group="3" -         width="236"> -        </line_editor> +            </layout_panel> +           </layout_stack> +           </panel> +            <chat_editor +             bottom="0" +             expand_lines_count="5" +             follows="left|right|bottom" +	         font="SansSerifSmall" +             visible="true" +             height="20" +             is_expandable="true" +             label="To" +             layout="bottomleft" +             name="chat_editor" +             max_length="1023" +             spellcheck="true" +             tab_group="3" +             width="220" +             left="10" +             wrap="true"> +            </chat_editor>      </layout_panel>    </layout_stack> +    </view>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index 08d0b00a83..8e143623ab 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -7,20 +7,20 @@    height="570"    help_topic="sidebar_people"    min_height="440" -  min_width="333" +  min_width="390"    layout="topleft"    name="floater_people"    save_rect="true"    single_instance="true"    reuse_instance="true"    title="PEOPLE" -  width="333"> +  width="390">      <panel_container        default_panel_name="panel_people"        follows="all"        height="570"        name="main_panel" -      width="333"> +      width="390">        <panel          class="panel_people"          name="panel_people" @@ -31,11 +31,5 @@          filename="panel_group_info_sidetray.xml"          label="Group Profile"          font="SansSerifBold"/> -      <panel -        class="panel_block_list_sidetray" -        name="panel_block_list_sidetray" -        filename="panel_block_list_sidetray.xml" -        label="Blocked Residents & Objects" -        font="SansSerifBold"/>      </panel_container>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_voice_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_volume.xml new file mode 100644 index 0000000000..9346295d5b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_volume.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- +  Not can_close / no title to avoid window chrome +  Single instance - only have one at a time, recycle it each spawn +--> +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="90" + layout="topleft" + name="floater_voice_volume" + single_instance="true" + sound_flags="0" + title="VOICE VOLUME" + visible="true" + width="245"> +    <text +     follows="top|left|right" +     font="SansSerifSmall" +     height="21" +     left="10" +     name="avatar_name" +     parse_urls="false" +     top="35" +     text_color="White" +     translate="false" +     use_ellipses="true" +     value="TestString PleaseIgnore" +     width="225" /> +    <slider +     follows="top|left" +     height="23" +     increment="0.01" +     left="1" +     max_val="0.95" +     min_val="0.05" +     name="volume_slider" +     show_text="false" +     tool_tip="Voice volume" +     top_pad="0" +     value="0.5" +     width="200" /> +    <button +     follows="top|left" +     height="16" +     image_disabled="Audio_Off" +     image_disabled_selected="AudioMute_Off" +     image_hover_selected="AudioMute_Over" +     image_selected="AudioMute_Off" +     image_unselected="Audio_Off" +     is_toggle="true" +     left_pad="0" +     top_delta="4" +     name="mute_btn" +     width="16" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index bc3bcd331b..c3481e6d4c 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -9,7 +9,7 @@   bg_opaque_image="Inspector_Background"   can_close="false"   can_minimize="false" - height="164" + height="130"   layout="topleft"   name="inspect_avatar"   single_instance="true" @@ -94,32 +94,17 @@       use_ellipses="true"       width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot      </text> -    <slider -     follows="top|left" -     height="23" -     increment="0.01" -     left="1" -     max_val="0.95" -     min_val="0.05" -     name="volume_slider" -     show_text="false" -     tool_tip="Voice volume" -     top_pad="0" -     value="0.5" -     width="200" /> -    <button +    <text       follows="top|left"       height="16" -     image_disabled="Audio_Off" -     image_disabled_selected="AudioMute_Off" -     image_hover_selected="AudioMute_Over" -     image_selected="AudioMute_Off" -     image_unselected="Audio_Off" -     is_toggle="true" -     left_pad="0" -     top_delta="4" -     name="mute_btn" -     width="16" /> +     left="8" +     name="avatar_profile_link" +     font="SansSerifSmall" +     text_color="White" +     top_pad="5" +     translate="false" +     value="[[LINK] View full profile]" +     width="175" />      <avatar_icon       follows="top|left"       height="38" @@ -130,83 +115,4 @@       name="avatar_icon"       top="10"       width="38" /> -<!-- Overlapping buttons for default actions -    llinspectavatar.cpp makes visible the most likely default action  ---> -    <button -     follows="top|left" -     height="20" -     label="Add Friend" -     left="8" -     top="135" -     name="add_friend_btn" -     width="90" /> -    <button -     follows="top|left" -     height="20" -     label="IM" -     left_delta="0" -     top_delta="0" -     name="im_btn" -     width="80" -     commit_callback.function="InspectAvatar.IM"/> -	<button -     follows="top|left" -     height="20" -     label="Profile" -     layout="topleft" -     name="view_profile_btn" -     left_delta="96" -     top_delta="0" -     tab_stop="false" -     width="80" /> -      <!--  gear buttons here --> -  <menu_button -     follows="top|left" -     height="20" -     layout="topleft" -     image_overlay="OptionsMenu_Off" -     menu_filename="menu_inspect_avatar_gear.xml" -     name="gear_btn" -     right="-5" -     top_delta="0" -     width="35" /> -	<menu_button -     follows="top|left" -     height="20" -     image_overlay="OptionsMenu_Off" -     menu_filename="menu_inspect_self_gear.xml" -     name="gear_self_btn" -     right="-5" -     top_delta="0" -     width="35" /> -  <panel  -    follows="top|left"  -    top="164"  -    left="0"  -    height="60"  -    width="228"  -    visible="false" -    background_visible="true" -    name="moderator_panel" -    background_opaque="true"  -    bg_opaque_color="MouseGray"> -    <button -      name="disable_voice" -      label="Disable Voice" -      top="20" -      width="95" -      height="20" -      left="10" -      commit_callback.function="InspectAvatar.DisableVoice"/> -    <button -      name="enable_voice" -      label="Enable Voice" -      top="20" -      width="95" -      height="20" -      left="10" -      visible="false"  -      commit_callback.function="InspectAvatar.EnableVoice"/> -  </panel>  </floater> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml new file mode 100644 index 0000000000..b8d0eef956 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_gear.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="Conversation Context Menu"> +    <menu_item_call +     label="IM..." +     layout="topleft" +     name="IM"> +        <on_click +         function="Calllog.Action" +         parameter="im" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_im" /> +    </menu_item_call> +    <menu_item_call +     label="Voice call..." +     layout="topleft" +     name="Call"> +        <on_click +         function="Calllog.Action" +         parameter="call" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_call" /> +    </menu_item_call> +    <menu_item_call +     label="Open chat history..." +     layout="topleft" +     name="Chat history"> +        <on_click +         function="Calllog.Action" +         parameter="chat_history" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_view_chat_history" /> +    </menu_item_call> +    <menu_item_call +     label="View Profile" +     layout="topleft" +     name="View Profile"> +        <on_click +         function="Calllog.Action" +         parameter="view_profile" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_view_profile" /> +    </menu_item_call> +    <menu_item_call +    label="Offer Teleport" +    name="teleport"> +      <on_click +       function="Calllog.Action" +       parameter="offer_teleport"/> +      <on_enable +      function="Calllog.Enable" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_check +     label="Add friend/Remove friend" +     layout="topleft" +     name="Friend_add_remove"> +        <menu_item_check.on_click +         function="Calllog.Action" +         parameter="add_rem_friend" /> +        <menu_item_check.on_check +         function="Calllog.Check" +         parameter="is_friend" /> +        <menu_item_check.on_enable +         function="Calllog.Enable" +         parameter="add_rem_friend" /> +    </menu_item_check> +    <menu_item_call +     label="Invite to group..." +     layout="topleft" +     name="Invite"> +        <on_click +         function="Calllog.Action" +         parameter="invite_to_group"/> +        <on_enable +         function="Calllog.Enable" +         parameter="can_invite_to_group" /> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_call +     label="Map" +     layout="topleft" +     name="Map"> +        <on_click +         function="Calllog.Action" +         parameter="show_on_map" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_show_on_map" /> +    </menu_item_call> +    <menu_item_call +     label="Share" +     layout="topleft" +     name="Share"> +        <on_click +         function="Calllog.Action" +         parameter="share" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_share" /> +    </menu_item_call> +    <menu_item_call +     label="Pay" +     layout="topleft" +     name="Pay"> +        <on_click +         function="Calllog.Action" +         parameter="pay" /> +        <on_enable +         function="Calllog.Enable" +         parameter="can_pay" /> +    </menu_item_call> +    <menu_item_check +     label="Block/Unblock" +     layout="topleft" +     name="Block/Unblock"> +        <menu_item_check.on_click +         function="Calllog.Action" +         parameter="block"/> +        <menu_item_check.on_check +         function="Calllog.Check" +         parameter="is_blocked" /> +        <menu_item_check.on_enable +         function="Calllog.Enable" +         parameter="can_block" /> +    </menu_item_check> + +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml new file mode 100644 index 0000000000..4ab8cb4f7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation_log_view.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu +     name="menu_conversation_view" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_check +   label="Sort by name" +   name="sort_by_name"> +      <on_click +       function="CallLog.Action" +       parameter="sort_by_name"/> +      <on_check +       function="CallLog.Check" +       parameter="sort_by_name"/> +  </menu_item_check> +  <menu_item_check +   label="Sort by date" +   name="sort_by_date"> +      <on_click +       function="CallLog.Action" +       parameter="sort_by_date" /> +      <on_check +       function="CallLog.Check" +       parameter="sort_by_date" /> +  </menu_item_check> +  <menu_item_separator /> +  <menu_item_check +   label="Sort friends on top" +   name="sort_by_friends"> +      <on_click +       function="CallLog.Action" +       parameter="sort_friends_on_top" /> +      <on_check +       function="CallLog.Check" +       parameter="sort_friends_on_top" /> +  </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml index fce7414d80..eca9e7f3c9 100644 --- a/indra/newview/skins/default/xui/en/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus"       left="0" bottom="0" visible="false"       mouse_opaque="false">    <menu_item_call name="item_join" label="Join Group..."> @@ -8,4 +8,4 @@    <menu_item_call name="item_new" label="New Group...">      <menu_item_call.on_click function="People.Group.Plus.Action" userdata="new_group" />    </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml new file mode 100644 index 0000000000..483f24afd0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_modes" + left="0" bottom="0" visible="false" + mouse_opaque="false"> +    <menu_item_check +       label="Compact view" +       name="compact_view"> +      <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="compact_view"/> +      <menu_item_check.on_check +         function="IMSession.Menu.CompactExpandedModes.CheckItem" +         parameter="compact_view"/> +    </menu_item_check> +    <menu_item_check +       label="Expanded view" +       name="expanded_view"> +      <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="expanded_view"/> +      <menu_item_check.on_check +         function="IMSession.Menu.CompactExpandedModes.CheckItem" +         parameter="expanded_view"/> +    </menu_item_check> +    <menu_item_separator layout="topleft" /> +    <menu_item_check name="IMShowTime" label="Show time"> +        <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="IMShowTime" /> +        <menu_item_check.on_check +         function="IMSession.Menu.ShowModes.CheckItem" +         parameter="IMShowTime" /> +        <menu_item_check.on_enable +         function="IMSession.Menu.ShowModes.Enable" +         parameter="IMShowTime" /> +    </menu_item_check> +    <menu_item_check name="IMShowNamesForP2PConv" label="Show names in one-to-one conversations"> +        <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="IMShowNamesForP2PConv" /> +        <menu_item_check.on_check +         function="IMSession.Menu.ShowModes.CheckItem" +         parameter="IMShowNamesForP2PConv" /> +        <menu_item_check.on_enable +         function="IMSession.Menu.ShowModes.Enable" +         parameter="IMShowNamesForP2PConv" /> +          +    </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml deleted file mode 100644 index 76b188220d..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ /dev/null @@ -1,143 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<toggleable_menu -         create_jump_keys="true" -         layout="topleft" -         mouse_opaque="false" -         visible="false" -         name="Gear Menu"> -  <menu_item_call -   label="View Profile" -   enabled="true"  -   name="view_profile"> -    <menu_item_call.on_click -     function="InspectAvatar.ViewProfile"/> -  </menu_item_call> -  <menu_item_call -   label="Add Friend" -   name="add_friend"> -    <menu_item_call.on_click -     function="InspectAvatar.AddFriend"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.Enable"/> -  </menu_item_call> -  <menu_item_call -   label="IM" -   name="im"> -    <menu_item_call.on_click -     function="InspectAvatar.IM"/> -  </menu_item_call> -  <menu_item_call -   label="Call" -   enabled="true" -   name="call"> -    <menu_item_call.on_click -     function="InspectAvatar.Call"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.EnableCall"/> -  </menu_item_call> -  <menu_item_call -   label="Teleport" -   name="teleport"> -    <menu_item_call.on_click -     function="InspectAvatar.Teleport"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.EnableTeleportOffer"/> -  </menu_item_call> -  <menu_item_call -   label="Invite to Group" -   name="invite_to_group"> -    <menu_item_call.on_click -     function="InspectAvatar.InviteToGroup"/> -  </menu_item_call> -  <menu_item_separator /> -  <menu_item_call -   label="Block" -   name="block"> -    <menu_item_call.on_click -     function="InspectAvatar.ToggleMute"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableMute" /> -  </menu_item_call> -  <menu_item_call -   label="Unblock" -   name="unblock"> -    <menu_item_call.on_click -     function="InspectAvatar.ToggleMute"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableUnmute" /> -  </menu_item_call> -  <menu_item_call -   label="Report" -   name="report"> -    <menu_item_call.on_click -     function="InspectAvatar.Report"/> -  </menu_item_call>   -  <menu_item_call -   label="Freeze" -   name="freeze"> -    <menu_item_call.on_click -     function="InspectAvatar.Freeze"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleFreeze"/> -  </menu_item_call> -  <menu_item_call -   label="Eject" -   name="eject"> -    <menu_item_call.on_click -     function="InspectAvatar.Eject"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleEject"/> -  </menu_item_call> -  <menu_item_call -   label="Kick" -   name="kick"> -    <menu_item_call.on_click -     function="InspectAvatar.Kick"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableGod"/> -  </menu_item_call> -  <menu_item_call -  label="CSR" -  name="csr"> -    <menu_item_call.on_click -     function="InspectAvatar.CSR" /> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableGod" /> -  </menu_item_call> -  <menu_item_call -   label="Debug Textures" -   name="debug"> -    <menu_item_call.on_click -     function="Avatar.Debug"/> -    <menu_item_call.on_visible -     function="IsGodCustomerService"/> -  </menu_item_call> -  <menu_item_call -   label="Find On Map" -   name="find_on_map"> -    <menu_item_call.on_click -     function="InspectAvatar.FindOnMap"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleFindOnMap"/> -  </menu_item_call> -  <menu_item_call -   label="Zoom In" -   name="zoom_in"> -    <menu_item_call.on_click -     function="InspectAvatar.ZoomIn"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleZoomIn"/> -  </menu_item_call>   -  <menu_item_call -   label="Pay" -   name="pay"> -    <menu_item_call.on_click -     function="InspectAvatar.Pay"/> -  </menu_item_call> -  <menu_item_call -   label="Share" -   name="share"> -    <menu_item_call.on_click -     function="InspectAvatar.Share"/> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml deleted file mode 100644 index 5e7b16ed4a..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ /dev/null @@ -1,252 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - layout="topleft" - name="Self Pie"> -  <menu_item_call -   label="Sit Down" -   layout="topleft" -   name="Sit Down Here"> -    <menu_item_call.on_click -     function="Self.SitDown" -     parameter="" /> -    <menu_item_call.on_enable -     function="Self.EnableSitDown" /> -  </menu_item_call> -  <menu_item_call -   label="Stand Up" -   layout="topleft" -   name="Stand Up"> -    <menu_item_call.on_click -     function="Self.StandUp" -     parameter="" /> -    <menu_item_call.on_enable -     function="Self.EnableStandUp" /> -  </menu_item_call> -  <context_menu -   label="Take Off" -   layout="topleft" -   name="Take Off >"> -    <context_menu -     label="Clothes" -     layout="topleft" -     name="Clothes >"> -      <menu_item_call -       enabled="false" -       label="Shirt" -       layout="topleft" -       name="Shirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="shirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="shirt" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Pants" -       layout="topleft" -       name="Pants"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="pants" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="pants" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Skirt" -       layout="topleft" -       name="Skirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="skirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="skirt" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Shoes" -       layout="topleft" -       name="Shoes"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="shoes" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="shoes" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Socks" -       layout="topleft" -       name="Socks"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="socks" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="socks" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Jacket" -       layout="topleft" -       name="Jacket"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="jacket" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="jacket" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Gloves" -       layout="topleft" -       name="Gloves"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="gloves" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="gloves" /> -      </menu_item_call> -      <menu_item_call -            enabled="false" -            label="Undershirt" -            layout="topleft" -            name="Self Undershirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="undershirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="undershirt" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Underpants" -        layout="topleft" -        name="Self Underpants"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="underpants" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="underpants" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Tattoo" -        layout="topleft" -        name="Self Tattoo"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="tattoo" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="tattoo" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Alpha" -        layout="topleft" -        name="Self Alpha"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="alpha" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="alpha" /> -      </menu_item_call> -      <menu_item_separator -       layout="topleft" /> -      <menu_item_call -       label="All Clothes" -       layout="topleft" -       name="All Clothes"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="all" /> -      </menu_item_call> -    </context_menu> -    <context_menu -     label="HUD" -     layout="topleft" -     name="Object Detach HUD" /> -    <context_menu -     label="Detach" -     layout="topleft" -     name="Object Detach" /> -    <menu_item_call -     label="Detach All" -     layout="topleft" -     name="Detach All"> -      <menu_item_call.on_click -       function="Self.RemoveAllAttachments" -       parameter="" /> -      <menu_item_call.on_enable -       function="Self.EnableRemoveAllAttachments" /> -    </menu_item_call> -  </context_menu> -  <menu_item_call -  label="Change Outfit" -  layout="topleft" -  name="Chenge Outfit"> -    <menu_item_call.on_click -     function="CustomizeAvatar" /> -    <menu_item_call.on_enable -     function="Edit.EnableCustomizeAvatar" /> -  </menu_item_call> -  <menu_item_call label="Edit My Outfit" -  layout="topleft" -  name="Edit Outfit"> -    <menu_item_call.on_click -     function="EditOutfit" /> -    <menu_item_call.on_enable -     function="Edit.EnableCustomizeAvatar" /> -  </menu_item_call> -  <menu_item_call label="Edit My Shape" -  layout="topleft" -  name="Edit My Shape"> -    <menu_item_call.on_click -     function="EditShape" /> -    <menu_item_call.on_enable -     function="Edit.EnableEditShape" /> -  </menu_item_call> -  <menu_item_call -    label="My Friends" -    layout="topleft" -    name="Friends..."> -    <menu_item_call.on_click -     function="SideTray.PanelPeopleTab" -     parameter="friends_panel" /> -  </menu_item_call> -  <menu_item_call -   label="My Groups" -   layout="topleft" -   name="Groups..."> -    <menu_item_call.on_click -     function="SideTray.PanelPeopleTab" -     parameter="groups_panel" /> -  </menu_item_call> -  <menu_item_call -    label="My Profile" -    layout="topleft" -    name="Profile..."> -    <menu_item_call.on_click -     function="ShowAgentProfile" -     parameter="agent" /> -  </menu_item_call> -  <menu_item_call -   label="Debug Textures" -       name="Debug..."> -    <menu_item_call.on_click -     function="Avatar.Debug" /> -    <menu_item_call.on_visible -     function="IsGodCustomerService"/> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_participant_view.xml b/indra/newview/skins/default/xui/en/menu_participant_view.xml new file mode 100644 index 0000000000..6401b0e3b7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_participant_view.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + layout="topleft" + name="participant_manu_view"> +    <menu_item_check +         label="Open conversation log" +         name="Conversation" +         visible="true"> +        <menu_item_check.on_check +         function="Floater.Visible" +         parameter="conversation" /> +        <menu_item_check.on_click +         function="Floater.Toggle" +         parameter="conversation" /> +      </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml new file mode 100644 index 0000000000..63295ea27b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_gear.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu  +     name="menu_blocked_gear" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_call +   label="Unblock" +   name="unblock"> +      <on_click +       function="Block.Action" +       parameter="unblock_item" /> +      <on_enable +       function="Block.Enable" +       parameter="unblock_item" />  +  </menu_item_call> +  <menu_item_call +   label="Profile..." +   name="profile"> +      <on_click +       function="Block.Action" +       parameter="profile_item"/> +      <on_enable +       function="Block.Enable" +       parameter="profile_item" /> +  </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml new file mode 100644 index 0000000000..0c7155667e --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_plus.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu  +     name="menu_blocked_plus" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_call +   label="Block Resident by name..." +   name="block_resident_by_name"> +      <on_click +       function="Block.Action" +       parameter="block_res_by_name"/> +  </menu_item_call> +  <menu_item_call +   label="Block object by name" +   name="block_object_by_name"> +      <on_click +       function="Block.Action" +       parameter="block_obj_by_name"/> +  </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml b/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml new file mode 100644 index 0000000000..2efb70ee37 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_blocked_view.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu  +     name="menu_blocked_view" +     left="0" bottom="0" visible="false" +     mouse_opaque="false"> +  <menu_item_check +   label="Sort by name" +   name="sort_by_name"> +      <on_click +       function="Block.Action" +       parameter="sort_by_name"/> +      <on_check +       function="Block.Check" +       parameter="sort_by_name"/> +  </menu_item_check> +  <menu_item_check +   label="Sort by type" +   name="sort_by_type"> +      <on_click +       function="Block.Action" +       parameter="sort_by_type" /> +      <on_check +       function="Block.Check" +       parameter="sort_by_type" /> +  </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index b452f96e7a..eab7b8c085 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -40,8 +40,4 @@       function="CheckControl"       parameter="FriendsListShowPermissions" />    </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Friends.ViewSort.Action" parameter="panel_block_list_sidetray" /> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml index 8f89d37dbb..1e0364b84e 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -1,8 +1,18 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus"   left="0" bottom="0" visible="false"   mouse_opaque="false" opaque="true" color="MenuDefaultBgColor">    <menu_item_call +   label="Activate" +   name="Activate"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="activate" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="activate" /> +  </menu_item_call> +  <menu_item_call     label="View Info"     name="View Info">      <menu_item_call.on_click @@ -23,7 +33,7 @@       parameter="chat" />    </menu_item_call>    <menu_item_call -   label="Call" +   label="Voice call"     name="Call">      <menu_item_call.on_click       function="People.Groups.Action" @@ -34,17 +44,6 @@    </menu_item_call>    <menu_item_separator />    <menu_item_call -   label="Activate" -   name="Activate"> -    <menu_item_call.on_click -     function="People.Groups.Action" -     parameter="activate" /> -    <menu_item_call.on_enable -     function="People.Groups.Enable" -     parameter="activate" /> -  </menu_item_call> -  <menu_item_separator /> -  <menu_item_call     label="Leave"     name="Leave">      <menu_item_call.on_click @@ -54,4 +53,4 @@       function="People.Groups.Enable"       parameter="leave" />    </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml index c710fe3b9b..73f79f1e70 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml @@ -14,13 +14,4 @@         function="CheckControl"         parameter="GroupListShowIcons" />    </menu_item_check> -  <menu_item_call -   label="Leave Selected Group" -   layout="topleft" -   name="Leave Selected Group"> -      <menu_item_call.on_click -       function="People.Group.Minus.Action"/> -      <menu_item_call.on_enable -       function="People.Group.Minus.Enable"/> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index d2e35e4cc0..b7c9ab1fe3 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -10,12 +10,39 @@           function="Avatar.Profile" />      </menu_item_call>      <menu_item_call +     label="IM" +     layout="topleft" +     name="IM"> +        <menu_item_call.on_click +         function="Avatar.IM" /> +    </menu_item_call> +    <menu_item_call +    label="Offer Teleport" +    name="teleport"> +      <menu_item_call.on_click +       function="Avatar.OfferTeleport"/> +      <menu_item_call.on_enable +      function="Avatar.EnableItem" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call +     label="Voice call" +     layout="topleft" +     name="Call"> +        <menu_item_call.on_click +         function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="Avatar.EnableItem" +         parameter="can_call" /> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_call       label="Add Friend"       layout="topleft"       name="Add Friend">          <menu_item_call.on_click           function="Avatar.AddFriend" /> -        <menu_item_call.on_enable +        <menu_item_call.on_visible           function="Avatar.EnableItem"           parameter="can_add" />      </menu_item_call> @@ -30,22 +57,13 @@           parameter="can_delete" />      </menu_item_call>      <menu_item_call -     label="IM" +     label="Invite to group..."       layout="topleft" -     name="IM"> +     name="Invite">          <menu_item_call.on_click -         function="Avatar.IM" /> -    </menu_item_call> -    <menu_item_call -     label="Call" -     layout="topleft" -     name="Call"> -        <menu_item_call.on_click -         function="Avatar.Call" /> -        <menu_item_call.on_enable -         function="Avatar.EnableItem" -         parameter="can_call" /> +         function="Avatar.InviteToGroup" />      </menu_item_call> +    <menu_item_separator />      <menu_item_call       label="Map"       layout="topleft" @@ -83,13 +101,5 @@           function="Avatar.EnableItem"           parameter="can_block" />      </menu_item_check> -    <menu_item_call -    label="Offer Teleport" -    name="teleport"> -      <menu_item_call.on_click -       function="Avatar.OfferTeleport"/> -      <menu_item_call.on_enable -      function="Avatar.EnableItem" -      parameter="can_offer_teleport"/> -    </menu_item_call> +  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml new file mode 100644 index 0000000000..da88ca9f4d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> +    <menu_item_check +       label="Sort by Recent Speakers" +       name="sort_by_recent_speakers"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +       parameter="sort_by_recent_speakers"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_by_recent_speakers"/> +    </menu_item_check> +    <menu_item_check +       label="Sort by Name" +       name="sort_name"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="sort_name"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_name"/> +    </menu_item_check> +    <menu_item_check +       label="Sort by Distance" +       name="sort_distance"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="sort_distance"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_distance"/> +    </menu_item_check> +    <menu_item_separator layout="topleft" /> +    <menu_item_check name="view_icons" label="View People Icons"> +        <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="view_icons" /> +        <menu_item_check.on_check +         function="CheckControl" +         parameter="NearbyListShowIcons" /> +    </menu_item_check> +    <menu_item_check name ="view_map" label="View Map"> +        <menu_item_check.on_check +         function="CheckControl" +         parameter="NearbyListShowMap" /> +        <menu_item_check.on_click +         function="ToggleControl" +         parameter="NearbyListShowMap" /> +    </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml deleted file mode 100644 index 614dd693c5..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu -     name="menu_group_plus" -     left="0" bottom="0" visible="false" -     mouse_opaque="false"> -  <menu_item_check -     label="Sort by Recent Speakers" -     name="sort_by_recent_speakers"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_by_recent_speakers"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_by_recent_speakers"/> -  </menu_item_check> -  <menu_item_check -     label="Sort by Name" -     name="sort_name"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_name"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_name"/> -  </menu_item_check> -  <menu_item_check -     label="Sort by Distance" -     name="sort_distance"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_distance"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_distance"/> -  </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_check name="view_icons" label="View People Icons"> -    <menu_item_check.on_click -     function="People.Nearby.ViewSort.Action" -     parameter="view_icons" /> -    <menu_item_check.on_check -     function="CheckControl" -     parameter="NearbyListShowIcons" /> -  </menu_item_check> -  <menu_item_check name ="view_map" label="View Map"> -    <menu_item_check.on_check -      function="CheckControl" -      parameter="NearbyListShowMap" /> -    <menu_item_check.on_click -      function="ToggleControl" -      parameter="NearbyListShowMap" /> -  </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="panel_block_list_sidetray" /> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml index 485a5a658c..1dbc90dd2b 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -32,8 +32,4 @@       function="CheckControl"       parameter="RecentListShowIcons" />    </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="panel_block_list_sidetray" /> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 13f073a1c2..6df02a25af 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3048,6 +3048,7 @@ Would you like to trust this authority?     icon="alertmodal.tga"     name="GrantedModifyRights"     persist="true" +   log_to_im="true"        type="notify">  [NAME] has given you permission to edit their objects.    </notification> @@ -3056,6 +3057,7 @@ Would you like to trust this authority?     icon="alertmodal.tga"     name="RevokedModifyRights"     persist="true" +   log_to_im="true"        type="notify">  Your privilege to modify [NAME]'s objects has been revoked    </notification> @@ -4240,6 +4242,8 @@ Are you sure you want to change the Estate Covenant?    <notification     icon="notifytip.tga"     name="RegionEntryAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">     <tag>fail</tag>  The region you're trying to visit contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content. @@ -4248,6 +4252,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu    <notification     icon="notifytip.tga"     name="RegionEntryAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <tag>fail</tag>      The region you're trying to visit contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4319,6 +4325,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu    <notification     icon="notifytip.tga"     name="TeleportEntryAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <unique>        <context>REGIONMATURITY</context> @@ -4330,6 +4338,8 @@ The region you're trying to visit contains [REGIONMATURITY] content, but your cu    <notification     icon="notifytip.tga"     name="TeleportEntryAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <unique>        <context>REGIONMATURITY</context> @@ -4450,6 +4460,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandClaimAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      The land you're trying to claim contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content.      <tag>fail</tag> @@ -4458,6 +4470,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandClaimAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <tag>fail</tag>      The land you're trying to claim contains [REGIONMATURITY] content, which is accessible to adults only. @@ -4515,6 +4529,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandBuyAccessBlocked_Notify" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      The land you're trying to buy contains [REGIONMATURITY] content, but your current preferences are set to exclude [REGIONMATURITY] content.      <tag>fail</tag> @@ -4523,6 +4539,8 @@ You won't receive any more notifications that you're about to visit a region wit    <notification     icon="notifytip.tga"     name="LandBuyAccessBlocked_NotifyAdultsOnly" +   log_to_im="false" +   log_to_chat="true"     type="notifytip">      <tag>fail</tag>      The land you're trying to buy contains [REGIONMATURITY] content, which is accessible to adults only. @@ -5464,6 +5482,8 @@ The string [STRING_NAME] is missing from strings.xml    <notification     icon="notifytip.tga"     name="IMSystemMessageTip" +   log_to_im="true"    +   log_to_chat="false"        type="notifytip">  [MESSAGE]    </notification> @@ -5507,18 +5527,14 @@ Topic: [SUBJECT], Message: [MESSAGE]    <notification     icon="notifytip.tga" -   name="FriendOnline" +   name="FriendOnlineOffline" +   log_to_chat="false"     type="notifytip">      <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online -  </notification> - -  <notification -   icon="notifytip.tga" -   name="FriendOffline" -   type="notifytip"> -    <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +<nolink>[NAME]</nolink> is [STATUS] +    <unique combine="cancel_old"> +      <context>NAME</context> +    </unique>    </notification>    <notification @@ -5762,6 +5778,8 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryAccepted" +   log_to_im="true"    +   log_to_chat="false"     type="notifytip">  [NAME] received your inventory offer.    </notification> @@ -5769,6 +5787,8 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryDeclined" +   log_to_im="true"    +   log_to_chat="false"     type="notifytip">  [NAME] declined your inventory offer.    </notification> @@ -5850,6 +5870,7 @@ Please select at least one type of content to search (General, Moderate, or Adul    <notification     icon="notify.tga"     name="PaymentReceived" +   log_to_im="true"        persist="true"     type="notify">      <tag>funds</tag> @@ -5859,6 +5880,7 @@ Please select at least one type of content to search (General, Moderate, or Adul    <notification     icon="notify.tga"     name="PaymentSent" +   log_to_im="true"        persist="true"     type="notify">      <tag>funds</tag> @@ -6003,6 +6025,7 @@ The objects on the selected parcel that are NOT owned by you have been returned    <notification     icon="notify.tga"     name="ServerObjectMessage" +   log_to_im="true"        persist="true"     type="notify">  Message from [NAME]: @@ -6421,6 +6444,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="UserGiveItem" +   log_to_im ="true"     type="offer">  [NAME_SLURL] has given you this [OBJECTTYPE]:  [ITEM_SLURL] @@ -6476,6 +6500,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOffered" +   log_to_im="true" +   log_to_chat="false"     type="offer">  [NAME_SLURL] has offered to teleport you to their location: @@ -6497,6 +6523,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOffered_MaturityExceeded" +   log_to_im="true" +   log_to_chat="false"     type="offer">  [NAME_SLURL] has offered to teleport you to their location: @@ -6520,6 +6548,8 @@ This region contains [REGION_CONTENT_MATURITY] content, but your current prefere    <notification     icon="notify.tga"     name="TeleportOffered_MaturityBlocked" +   log_to_im="true" +   log_to_chat="false"     type="notifytip">  [NAME_SLURL] has offered to teleport you to their location: @@ -6533,6 +6563,9 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="TeleportOfferSent" +   log_to_im="true" +   log_to_chat="false" +   show_toast="false"     type="offer">  	Teleport offer sent to [TO_NAME]    </notification> @@ -6560,6 +6593,7 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="OfferFriendship" +   log_to_im="true"     type="offer">      <tag>friendship</tag>      <tag>confirm</tag> @@ -6583,6 +6617,8 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="FriendshipOffered" +   log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  	You have offered friendship to [TO_NAME] @@ -6612,6 +6648,7 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="FriendshipAccepted" +   log_to_im="true"        type="offer">      <tag>friendship</tag>  <nolink>[NAME]</nolink> accepted your friendship offer. @@ -6620,6 +6657,7 @@ However, this region contains content accessible to adults only.    <notification     icon="notify.tga"     name="FriendshipDeclined" +   log_to_im="true"        persist="true"     type="notify">      <tag>friendship</tag> @@ -6629,6 +6667,8 @@ However, this region contains content accessible to adults only.      <notification     icon="notify.tga"     name="FriendshipAcceptedByMe" +   log_to_im="true"    +   show_toast="false"     type="offer">      <tag>friendship</tag>  Friendship offer accepted. @@ -6637,6 +6677,8 @@ Friendship offer accepted.    <notification     icon="notify.tga"     name="FriendshipDeclinedByMe" +   log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  Friendship offer declined. diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml deleted file mode 100644 index d68fa6ca6c..0000000000 --- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="215" - name="panel_im_control_panel" - width="150"> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="215" -     layout="topleft" -     left="3" -     name="vertical_stack" -     orientation="vertical" -     top="0" -     width="147"> -        <layout_panel -         auto_resize="true" -         follows="top|left" -         height="130" -         layout="topleft" -         left="0" -         min_height="0" -         mouse_opaque="false" -         width="147" -         top="0" -         name="speakers_list_panel"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="130" -             ignore_online_status="true" -             layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="147" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Call" -             name="call_btn" -             width="130" -             top="0" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Leave Call" -             name="end_call_btn" -             top="0"/> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Voice Controls" -             name="voice_ctrls_btn" -             top="0" -             use_ellipses="true" /> -        </layout_panel> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 7c67fd7f83..24f7d44cce 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -4,88 +4,95 @@   follows="left|top|right|bottom"   height="305"   layout="topleft" + left="0"   name="block_list_panel"   help_topic="blocked_list"   min_height="350"   min_width="240" - width="280"> -        <button -     follows="top|left" -     height="24" -     image_hover_unselected="BackButton_Over" -     image_pressed="BackButton_Press" -     image_unselected="BackButton_Off" -     layout="topleft" -     name="back" -     left="4" -     tab_stop="false" -     top="1" -     width="30"/> -    <text -     follows="top|left|right" -     font="SansSerifLargeBold" -     height="20" -     layout="topleft" -     left_pad="10" -     name="title_text" -     text_color="White" -     top="5" -     width="250"> -        Block List -     </text> -    <scroll_list + width="323"> +     <panel +      follows="left|top|right" +      height="27" +      label="bottom_panel" +      layout="topleft" +      left="0" +      name="blocked_buttons_panel" +      right="-1" +      top="0"> +         <filter_editor +          follows="left|top|right" +          height="23" +          layout="topleft" +          left="6" +          label="Filter" +          max_length_chars="300" +          name="blocked_filter_input" +          text_color="Black" +          text_pad_left="10" +          top="4" +          width="177" /> +         <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="OptionsMenu_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="8" +          menu_filename="menu_people_blocked_gear.xml" +          menu_position="bottomleft" +          name="blocked_gear_btn" +          top="3" +          width="31" /> +         <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="Conv_toolbar_sort" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="2" +          menu_filename="menu_people_blocked_view.xml" +          menu_position="bottomleft" +          name="view_btn" +          top_delta="0" +          width="31" /> +         <menu_button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="AddItem_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          layout="topleft" +          left_pad="2" +          menu_filename="menu_people_blocked_plus.xml" +          menu_position="bottomleft" +          name="plus_btn" +          top_delta="0" +          width="31"/> +          <button +          follows="right" +          height="25" +          image_hover_unselected="Toolbar_Middle_Over" +          image_overlay="TrashItem_Off" +          image_selected="Toolbar_Middle_Selected" +          image_unselected="Toolbar_Middle_Off" +          left_pad="2" +          layout="topleft" +          name="unblock_btn" +          top_delta="0" +          width="31"/> +     </panel> +    <block_list       follows="all" -     height="190" +     height="273"       layout="topleft" -     left="5" +     left="3"       name="blocked"       tool_tip="List of currently blocked Residents" -     top="30" -     width="270"> -        <scroll_list.columns -         name="item_name" /> -        <scroll_list.columns -         name="item_type" -         width="96" /> -    </scroll_list> -    <button -     follows="left|bottom" -     height="23" -     label="Block person" -     layout="topleft" -     left_delta="0" -     name="Block resident..." -     tool_tip="Pick a Resident to block" -     top_pad="4" -     width="210"> -        <button.commit_callback -         function="Block.ClickPick" /> -    </button> -    <button -     follows="left|bottom" -     height="23" -     label="Block object by name" -     layout="topleft" -     left_delta="0" -     name="Block object by name..." -     tool_tip="Pick an object to block by name" -     top_pad="4" -     width="210" > -        <button.commit_callback -         function="Block.ClickBlockByName" /> -    </button> -    <button -     enabled="false" -     follows="left|bottom" -     height="23" -     label="Unblock" -     layout="topleft" -     left_delta="0" -     name="Unblock" -     tool_tip="Remove Resident or object from blocked list" -     top_pad="4" -     width="210" > -        <button.commit_callback -         function="Block.ClickRemove" /> -    </button> +     top="31" +  	 right="-1"/>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml new file mode 100644 index 0000000000..84e7e467b1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_blocked_list_item.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="23" + layout="topleft" + left="0" + name="blocked_list_item" + top="0" + width="380"> +    <icon +     height="24" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     follows="top|right|left" +     height="24" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <avatar_icon +     default_icon_name="Generic_Person" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <group_icon +     default_icon_name="Generic_Group" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <icon +     follows="top|left" +     height="16" +     image_name="Inv_Object" +     layout="topleft" +     left="7" +     name="object_icon" +     top="4" +     visible="false" +     width="16" /> +    <text +     follows="left|right" +     font="SansSerifSmall" +     font.color="DkGray" +     height="15" +     layout="topleft" +     left_pad="5" +     name="item_name" +     parse_urls="false" +     top="6" +     use_ellipses="true" +     width="180" /> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml new file mode 100644 index 0000000000..3c98e32e7d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_conversation_log_list_item.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="23" + layout="topleft" + left="0" + name="conversation_log_list_item" + top="0" + width="380"> +    <icon +     height="24" +     follows="top|right|left" +     image_name="ListItem_Select" +     layout="topleft" +     left="0" +     name="selected_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     follows="top|right|left" +     height="24" +     image_name="ListItem_Over" +     layout="topleft" +     left="0" +     name="hovered_icon" +     top="0" +     visible="false" +     width="380" /> +    <icon +     default_icon_name="voice_session_icon" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     image_name="Audio_Press" +     mouse_opaque="true" +     name="voice_session_icon" +     top="2" +     visible="false" +     width="20" /> +    <icon +     default_icon_name="incoming_unread_im_icon" +     follows="top|left" +     height="20" +     layout="topleft" +     left="5" +     image_name="Movement_Backward_Off" +     mouse_opaque="false" +     name="unread_ims_icon" +     top="2" +     visible="false" +     width="20" /> +    <avatar_icon +     default_icon_name="Generic_Person" +     follows="top|left" +     height="20" +     layout="topleft" +     left_pad="5" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <group_icon +     default_icon_name="Generic_Group" +     follows="top|left" +     height="20" +     layout="topleft" +     mouse_opaque="true" +     top="2" +     visible="false" +     width="20" /> +    <text +     follows="left|right" +     font="SansSerifSmall" +     font.color="DkGray" +     height="15" +     layout="topleft" +     left_pad="5" +     name="conversation_name" +     parse_urls="false" +     top="6" +     use_ellipses="true" +     width="180" /> +    <text +     follows="right" +     font="SansSerifSmall" +     font.color="DkGray" +     height="15" +     layout="topleft" +     left_pad="5" +     name="date_time" +     parse_urls="false" +     top="6" +     use_ellipses="true" +     width="110"/> +    <button +     name="delete_btn" +     layout="topleft" +     follows="top|right" +     image_unselected="Toast_CloseBtn" +     image_selected="Toast_CloseBtn" +     top="5" +     left_pad="0" +     height="14" +     width="14" +     tab_stop="false"/> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml deleted file mode 100644 index ad10e53a4e..0000000000 --- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml +++ /dev/null @@ -1,109 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="238" - name="panel_im_control_panel" - width="150"> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="238" -     layout="topleft" -     left="5" -     name="vertical_stack" -     orientation="vertical" -     top="0" -     width="145"> -        <layout_panel -         auto_resize="true" -         follows="top|left" -         height="100" -         layout="topleft" -         min_height="0" -         mouse_opaque="false" -         width="145" -         top="0" -         name="speakers_list_panel"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="100" -             ignore_online_status="true" -             layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="145" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="group_info_btn_panel"> -            <button -             follows="left|right|bottom" -             height="23" -             label="Group Profile" -             name="group_info_btn" -             use_ellipses="true" -             top="5" -             width="130" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="call_btn_panel"> -            <button -             follows="all" -             height="23" -             label="Call Group" -             name="call_btn" -             use_ellipses="true"  -             width="130" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="23" -             label="Leave Call" -             name="end_call_btn" -             use_ellipses="true" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="23" -             label="Open Voice Controls" -             name="voice_ctrls_btn" -             use_ellipses="true" /> -        </layout_panel> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml deleted file mode 100644 index 8fcd6ccbaf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ /dev/null @@ -1,166 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - height="300" - name="panel_im_control_panel" - width="150"> -    <avatar_icon -     follows="left|top" -     height="105" -     left_delta="20" -     name="avatar_icon" -     top="-5" -     width="114"/> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="183" -     layout="topleft" -     left="5" -     name="button_stack" -     orientation="vertical" -     top_pad="5" -     width="145"> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="20" -         layout="topleft" -         left="2"  -         min_height="20" -         width="140" -         name="view_profile_btn_panel" -         top="0" > -            <button -             follows="left|top|right" -             height="23" -             label="Profile" -             name="view_profile_btn" -             top="0" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="add_friend_btn_panel"> -            <button -             follows="left|top|right" -             height="23" -             label="Add Friend" -             name="add_friend_btn" -             top="5" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="teleport_btn_panel"> -        <button -             auto_resize="false" -             follows="left|top|right" -             height="23" -             label="Teleport" -             name="teleport_btn" -             tool_tip = "Offer to teleport this person" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="share_btn_panel"> -           <button -             auto_resize="true" -             follows="left|top|right" -             height="23" -             label="Share" -             name="share_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="pay_btn_panel"> -           <button -             auto_resize="true" -             follows="left|top|right" -             height="23" -             label="Pay" -             name="pay_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="call_btn_panel"> -            <button -             follows="left|top|right" -             height="23" -             label="Call" -             name="call_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="left|top|right" -             height="23" -             label="End Call" -             name="end_call_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="left|top|right" -             height="23" -             label="Voice Controls" -             name="voice_ctrls_btn" -             width="140" /> -        </layout_panel> -      <layout_panel -       mouse_opaque="false" -       auto_resize="true" -       follows="top|left" -       height="0" -       layout="topleft" -       min_height="0" -       width="140" -       name="spacer"/> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index 413e22e444..433a3181cd 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -2,7 +2,7 @@  <inbox_inventory_panel      accepts_drag_and_drop="false"      name="inventory_inbox" -    start_folder="Received Items" +    start_folder.type="inbox"      follows="all" layout="topleft"      top="0" left="0" height="165" width="308"      top_pad="0" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 2a5933e3e9..67a09949ce 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -35,7 +35,9 @@               left="0"               mouse_opaque="true"               name="favorites_list" -             start_folder="Favorites" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="Favorites"               width="307"/>          </accordion_tab>          <accordion_tab @@ -51,7 +53,9 @@               left="0"               mouse_opaque="true"               name="landmarks_list" -             start_folder="Landmarks" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="Landmarks"               width="307"/>          </accordion_tab>          <accordion_tab @@ -67,7 +71,9 @@               left="0"               mouse_opaque="true"               name="my_inventory_list" -             start_folder="My Inventory" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="My Inventory"               width="307"/>            </accordion_tab>            <accordion_tab @@ -83,7 +89,9 @@               left="0"               mouse_opaque="true"               name="library_list" -             start_folder="LIBRARY" +             scroll.hide_scrollbar="true" +             folder_view.use_ellipses="true" +             start_folder.name="LIBRARY"               width="313"/>          </accordion_tab>      </accordion> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d683116eb8..4de56b424e 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,20 +1,22 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel   follows="all" - height="300" + top="0" + bottom_delta="10"   help_topic="nearby_chat"   layout="topleft"   name="nearby_chat" - width="320"> + width="242" + height="169">    <layout_stack     follows="all" -   height="295" +   height="164"     layout="topleft"     left="0"     name="stack"     top="5"     orientation="vertical" -   width="320"> +   width="242">      <layout_panel       auto_resize="false"       height="26" @@ -23,7 +25,7 @@       name="translate_chat_checkbox_lp"       top_delta="0"       visible="true" -     width="313"> +     width="230">        <check_box         top="10"         control_name="TranslateChat" @@ -33,15 +35,15 @@         layout="topleft"         left="5"         name="translate_chat_checkbox" -       width="300" /> +       width="230" />      </layout_panel>      <layout_panel       auto_resize="true" -     height="277" +     height="138"       left_delta="0"       layout="topleft"       name="chat_history_lp" -     width="318"> +     width="242">        <chat_history         bg_readonly_color="ChatHistoryBgColor"         bg_writeable_color="ChatHistoryBgColor" @@ -49,7 +51,7 @@         layout="topleft"         left="5"         left_widget_pad="0" -       height="272" +       height="138"         name="chat_history"         parse_highlights="true"         parse_urls="true" @@ -57,7 +59,7 @@         text_color="ChatHistoryTextColor"         text_readonly_color="ChatHistoryTextColor"         top="0" -       width="313" /> +       width="237" />      </layout_panel>    </layout_stack>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index a3d39e55af..203febbf18 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -1,7 +1,10 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel +<inventory_panel      name="inventory_outbox" -    start_folder="Outbox" +    start_folder.name="Outbox" +    show_empty_message="false" +    show_load_status="false" +    start_folder.type="outbox"      follows="all" layout="topleft"      top="0" left="0" height="165" width="308"      top_pad="0" @@ -12,6 +15,11 @@      bevel_style="none"      show_item_link_overlays="true"      tool_tip="Drag and drop items here to prepare them for sale on your storefront" -    > -    <scroll reserve_scroll_corner="false" /> -</outbox_inventory_panel> +    scroll.reserve_scroll_corner="false"> +      <folder folder_arrow_image="Folder_Arrow" +              folder_indentation="8" +              item_height="20" +              item_top_pad="4" +              selection_image="Rounded_Square"/> +      <item allow_open="false"/> +</inventory_panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 98c7c49ff4..09156b41b5 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -38,12 +38,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       name="no_filtered_friends_msg">           Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search].      </string> -    <string -     name="people_filter_label" -     value="Filter People" /> -    <string -     name="groups_filter_label" -     value="Filter Groups" />       <!--       *WORKAROUND: for group_list.no_items_msg & group_list.no_filtered_items_msg attributes.       They are not defined as translatable in VLT. See EXT-5931 @@ -60,21 +54,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M  	<string  	 name="AltMiniMapToolTipMsg"  	 value="[REGION](Double-click to teleport, shift-drag to pan)"/> -	<filter_editor -     follows="left|top|right" -     height="23" -     layout="topleft" -     left="10" -     label="Filter" -     max_length_chars="300" -     name="filter_input" -     text_color="Black" -     text_pad_left="10" -     top="3" -     width="303" />      <tab_container +     bottom="-10"       follows="all" -     height="383"       layout="topleft"       left="3"       name="tabs" @@ -82,31 +64,116 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       tab_min_width="70"       tab_height="30"       tab_position="top" -     top_pad="10" +     top="0"       halign="center" -     width="319"> -     	<panel +     right="-5"> + +<!-- ================================= NEARBY tab =========================== --> + +        <panel           background_opaque="true"           background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="NEARBY"           layout="topleft"           left="0"           help_topic="people_nearby_tab"           name="nearby_panel" -         top="0" -         width="313"> +         right="-1" +         top="0"> +            <panel +             follows="left|top|right" +             height="27" +             label="bottom_panel" +             layout="topleft" +             left="0" +             name="nearby_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="nearby_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="178" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="7" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_nearby_view.xml" +                 menu_position="bottomleft" +                 name="nearby_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 name="add_friend_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriend" /> +                </button> +                <dnd_button +                 enabled="false" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="nearby_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                 </dnd_button> +            </panel>           <layout_stack             clip="false"             follows="all" -           height="355" +           height="410"             layout="topleft" +           left="0"             mouse_opaque="false"             orientation="vertical" -           width="313"> +           right="-1" +           top_pad="0">             <layout_panel               height="142"               layout="topleft" @@ -123,16 +190,16 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                 left="3"                 mouse_opaque="false"                 name="Net Map" -               top="4" -               width="305"/> +               right="-1" +               top="4" />             </layout_panel>             <layout_panel               height="213"               layout="topleft"               min_dim="100"               mouse_opaque="false" -             user_resize="true" -             width="313"> +             right="-1" +             user_resize="true">               <avatar_list                 allow_select="true"                 follows="all" @@ -143,84 +210,118 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                 keep_one_selected="false"                 multi_select="true"                 name="avatar_list" -               top="2" -               width="306" /> +               right="-1" +               top="2" />             </layout_panel>           </layout_stack> -         <panel -             background_visible="true" -             follows="left|right|bottom" -             height="27" -             label="bottom_panel" -             layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -             <menu_button -             follows="bottom|left" -             height="25" -             image_hover_unselected="Toolbar_Left_Over" -             image_overlay="OptionsMenu_Off" -             image_selected="Toolbar_Left_Selected" -             image_unselected="Toolbar_Left_Off" -             layout="topleft" -             left="0" -             name="nearby_view_sort_btn" -             tool_tip="Options" -             top="1" -             width="31" /> -             <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -             	 image_overlay="AddItem_Off" -                 image_selected="Toolbar_Middle_Selected" -             	 image_unselected="Toolbar_Middle_Off" -                 layout="topleft" -                 left_pad="1" -                 name="add_friend_btn" -                 tool_tip="Add selected Resident to your friends List" -                 width="31"> -               <commit_callback -                  function="People.addFriend" /> -             </button> -             <icon -             follows="bottom|left|right" -             height="25" -             image_name="Toolbar_Right_Off" -             layout="topleft" -             left_pad="1" -             name="dummy_icon" -             width="243" -             /> -            </panel>          </panel> + +<!-- ================================= FRIENDS tab ========================== --> +          <panel           background_opaque="true"         background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="MY FRIENDS"           layout="topleft"           left="0"           help_topic="people_friends_tab"           name="friends_panel" -         top="0" -         width="313"> +         right="-1" +         top="0"> +            <panel +             follows="left|top|right" +             height="27" +             label="bottom_panel" +             layout="topleft" +             left="0" +             name="friends_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="friends_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="8" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_friends_view.xml" +                 menu_position="bottomleft" +                 name="friends_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 name="friends_add_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriendWizard" /> +                </button> +                <dnd_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="friends_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                </dnd_button> +            </panel>              <accordion         		 background_visible="true"         		 bg_alpha_color="DkGray2"         		 bg_opaque_color="DkGray2"               follows="all" -             height="356" +             height="408"               layout="topleft"               left="3"               name="friends_accordion" -             top="0" -             width="307"> +             right="-2" +             top_pad="2">                  <accordion_tab                   layout="topleft"                   height="172" @@ -257,247 +358,129 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                           width="307" />                  </accordion_tab>              </accordion> -            <panel -             background_visible="true" -             follows="left|right|bottom" -             height="27" -             label="bottom_panel" -             layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -              -             	  <layout_stack -				   animate="false" -				   border_size="0" -				   follows="left|right|bottom" -				   height="25" -				   layout="topleft" -				   orientation="horizontal" -				   top_pad="1" -				   left="0" -				   name="bottom_panel" -				   width="308"> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="options_gear_btn_panel" -				       width="32"> -				          <menu_button -				           follows="bottom|left" -				           tool_tip="Show additional options" -				           height="25" -				           image_hover_unselected="Toolbar_Left_Over" -				           image_overlay="OptionsMenu_Off" -				           image_selected="Toolbar_Left_Selected" -				           image_unselected="Toolbar_Left_Off" -				           layout="topleft" -				           left="0" -				           name="friends_viewsort_btn" -				           top="0" -				           width="31" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="add_btn_panel" -				       width="32"> -				          <button -				           follows="bottom|left" -				           height="25" -				           image_hover_unselected="Toolbar_Middle_Over" -				           image_overlay="AddItem_Off" -				           image_selected="Toolbar_Middle_Selected" -				           image_unselected="Toolbar_Middle_Off" -				           layout="topleft" -				           left="0" -				           name="add_btn" -				           tool_tip="Offer friendship to a Resident" -				           top="0" -				           width="31" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="true" -				       height="25" -				       layout="topleft" -				       name="dummy_panel" -				       width="210"> -				          <icon -				           follows="bottom|left|right" -				           height="25" -				           image_name="Toolbar_Middle_Off" -				           layout="topleft" -				           left="0" -				           top="0" -				           name="dummy_icon" -				           width="210" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="trash_btn_panel" -				       width="31"> -				          <dnd_button -				           follows="bottom|left" -				           height="25" -				           image_hover_unselected="Toolbar_Right_Over" -				           image_overlay="TrashItem_Off" -				           image_selected="Toolbar_Right_Selected" -				           image_unselected="Toolbar_Right_Off" -				           left="0" -				           layout="topleft" -				           name="del_btn" -				           tool_tip="Remove selected person from your Friends list" -				           top="0" -				           width="31"/> -				      </layout_panel> -				  </layout_stack><!-- -              -               <button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               left="0" -               name="friends_viewsort_btn" -               top="1" -               width="31" /> -                <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -             	 image_overlay="AddItem_Off" -             	 image_selected="Toolbar_Middle_Selected" -             	 image_unselected="Toolbar_Middle_Off" -                 layout="topleft" -                 left_pad="1" -                 name="add_btn" -                 tool_tip="Offer friendship to a Resident" -                 width="31" /> -                <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Middle_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="209" -             /> -                <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Right_Over" -                 image_overlay="TrashItem_Off" -                 image_selected="Toolbar_Right_Selected" -                 image_unselected="Toolbar_Right_Off" -                 layout="topleft" -                 left_pad="1" -                 name="del_btn" -                 tool_tip="Remove selected person from your Friends list" -                 width="31" /> -            --></panel>              <text               follows="all"               height="450"               left="13"               name="no_friends_help_text" -             top="10" -             width="293" +             right="-13" +             top="37"               wrap="true" />          </panel> + +<!-- ================================= GROUPS tab =========================== --> +          <panel           background_opaque="true"         background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="MY GROUPS"           layout="topleft"           left="0"           help_topic="people_groups_tab"           name="groups_panel" -         top="0" -         width="313"> +         right="-1" +         top="0">      <!--       *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931       Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild()      --> -            <group_list -             allow_select="true"  -             follows="all" -             height="356" -             layout="topleft" -             left="3" -             name="group_list" -             top="0" -             width="307" />              <panel -             background_visible="true" -             follows="left|right|bottom" +             follows="left|top|right"               height="27"               label="bottom_panel"               layout="topleft"               left="0" -             name="bottom_panel" -             top_pad="0" -             width="313"> -               <menu_button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               left="3" -               name="groups_viewsort_btn" -               top="1" -               width="31" /> -                <button -                 follows="bottom|left" +             name="groups_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter Groups" +                 max_length_chars="300" +                 name="groups_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <menu_button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="AddItem_Off" +                 image_overlay="OptionsMenu_Off"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" -                 name="plus_btn" -                 tool_tip="Join group/Create new group" +                 left_pad="8" +                 name="groups_gear_btn" +                 top="3"                   width="31" /> -                <button -                 follows="bottom|left" +                <menu_button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="Activate_Checkmark" +                 image_overlay="Conv_toolbar_sort"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" -                 name="activate_btn" -                 tool_tip="Activate selected group" +                 left_pad="2" +                 menu_filename="menu_people_groups_view.xml" +                 menu_position="bottomleft" +                 name="groups_view_btn" +                 top_delta="0"                   width="31" /> -                 <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Right_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="212" -             /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_group_plus.xml" +                 menu_position="bottomleft" +                 name="plus_btn" +                 top_delta="0" +                 width="31"> +                    <validate_callback +                     function="People.Group.Plus.Validate" /> +                </menu_button> +                <dnd_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="minus_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.Group.Minus" /> +                </dnd_button>              </panel> +            <group_list +             allow_select="true"  +             follows="all" +             height="406" +             layout="topleft" +             left="3" +             name="group_list" +             right="-2" +             top_pad="4" />          </panel> + +<!-- ================================= RECENT tab =========================== --> +          <panel           background_opaque="true"         background_visible="true" @@ -510,265 +493,129 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M           left="0"           help_topic="people_recent_tab"           name="recent_panel" -         top="0" -         width="313"> -            <avatar_list -             allow_select="true" -             follows="all" -             height="356" -             layout="topleft" -             left="3" -             multi_select="true" -             name="avatar_list" -             show_last_interaction_time="true" -             top="0" -             width="307" /> +         right="-1" +         top="0">              <panel -             background_visible="true" -             follows="left|right|bottom" +             follows="left|top|right"               height="27"               label="bottom_panel"               layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -               <menu_button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               name="recent_viewsort_btn" -               top="1" -               width="31" /> -              <button -                 follows="bottom|left" +             left="0" +             name="recent_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="recent_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="8" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Conv_toolbar_sort" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_recent_view.xml" +                 menu_position="bottomleft" +                 name="recent_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over"                   image_overlay="AddItem_Off"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" +                 left_pad="2"                   name="add_friend_btn" -                 tool_tip="Add selected Resident to your friends List" +                 top_delta="0"                   width="31"> -                <commit_callback -                   function="People.addFriend" /> -              </button> -              <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Right_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="244" -             /> +                    <commit_callback +                     function="People.AddFriend" /> +                </button> +                <dnd_button +                 enabled="false" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="recent_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                 </dnd_button>              </panel> +            <avatar_list +             allow_select="true" +             follows="all" +             height="351" +             layout="topleft" +             left="3" +             multi_select="true" +             name="avatar_list" +             show_last_interaction_time="true" +             right="-2" +             top_pad="4" />          </panel> -    </tab_container> -    <panel -     follows="bottom|left|right" -     height="23" -     layout="topleft" -     left="8" -     top_pad="4" -     name="button_bar" -     width="313"> -<!--********************************Profile; IM; Call, Share, Teleport********************************--> 	 -     	<layout_stack -     	follows="bottom|left|right" -		height="23" -		layout="topleft" -		name="bottom_bar_ls" -		left="0" -		orientation="horizontal" -		top_pad="0" -		width="313"> +<!-- ================================= BLOCKED tab ========================== --> -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left="0" -			name="view_profile_btn_lp" -		    auto_resize="true" -			width="68"> -				<button -		         follows="bottom|left|right" -		         height="23" -		         label="Profile" -		         layout="topleft" -		         left="1" -		         name="view_profile_btn" -		         tool_tip="Show picture, groups, and other Residents information" -		         top="0" -		         width="67" />	 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="im_btn_lp" -		    auto_resize="true" -			width="41"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="IM" -		         layout="topleft" -		         name="im_btn" -		         tool_tip="Open instant message session" -		         top="0" -		         width="40" />			 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="call_btn_lp" -		    auto_resize="true" -			width="52"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Call" -		         layout="topleft" -		         name="call_btn" -		         tool_tip="Call this Resident" -		         top="0" -		         width="51" />		 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="share_btn_lp" -		    auto_resize="true" -			width="66"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Share" -		         layout="topleft" -		         name="share_btn" -		         tool_tip="Share an inventory item" -		         top="0" -		         width="65" />	 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="teleport_btn_lp" -		    auto_resize="true" -			width="77"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Teleport" -		         layout="topleft" -		         name="teleport_btn" -		         tool_tip="Offer teleport" -		         top="0" -		         width="76" />		 -			</layout_panel> -		</layout_stack> -		 -<!--********************************Group Profile; Group Chat; Group Call buttons************************-->			 -		<layout_stack -     	follows="bottom|left|right" -		height="23" -		layout="topleft" -		mouse_opaque="false" -		name="bottom_bar_ls1" -		left="0" -		orientation="horizontal" -		top="0" -		width="313">	 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left="0"			 -			mouse_opaque="false" -			name="group_info_btn_lp" -		    auto_resize="true" -			width="108"> -				<button -		        follows="bottom|left|right" -		        left="1" -		        height="23" -		        label="Group Profile" -		        layout="topleft" -				mouse_opaque="false" -		        name="group_info_btn" -		        tool_tip="Show group information" -		        top="0" -		        width="107" />		 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			mouse_opaque="false" -			name="chat_btn_lp" -		    auto_resize="true" -			width="101"> -				<button -		        follows="bottom|left|right" -		        left="1" -		        height="23" -		        label="Group Chat" -		        layout="topleft" -				mouse_opaque="false" -		        name="chat_btn" -		        tool_tip="Open chat session" -		        top="0" -		        width="100" />			 -			</layout_panel> -		 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			mouse_opaque="false" -			name="group_call_btn_lp" -		    auto_resize="true" -			width="96"> -				<button -				follows="bottom|left|right" -				left="1" -				height="23" -         		label="Group Call" -         		layout="topleft" -				mouse_opaque="false" -         		name="group_call_btn" -         		tool_tip="Call this group" -		        top="0" -         		width="95" />			 -			</layout_panel>		 -		</layout_stack> -    </panel> +        <panel +         background_opaque="true" +         background_visible="true" +         bg_alpha_color="DkGray" +         bg_opaque_color="DkGray" +         follows="all" +         height="383" +         label="BLOCKED" +         layout="topleft" +         left="0" +         help_topic="people_blocked_tab" +         name="blocked_panel" +         right="-1" +         top="0"> +          <panel +           class="panel_block_list_sidetray" +           height="383" +           name="panel_block_list_sidetray" +           filename="panel_block_list_sidetray.xml" +           follows="all" +           label="Blocked Residents & Objects" +           layout="topleft" +           left="0" +           font="SansSerifBold" +           top="0" +           right="-1" /> +        </panel> +    </tab_container>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 27193a984f..c76a3cfaaf 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -76,15 +76,6 @@       top_pad="5"       width="400" />      <check_box -     enabled="false" -     height="16" -     label="Enable plain text IM and chat history" -     layout="topleft" -     left_delta="0" -     name="plain_text_chat_history" -     top_pad="5" -     width="400" /> -    <check_box       control_name="UseChatBubbles"       follows="left|top"       height="16" @@ -95,55 +86,6 @@       name="bubble_text_chat"       width="150" />           <text -     name="show_ims_in_label" -     follows="left|top" -     layout="topleft" -     left="30" -     height="20" -     width="170" -     top_pad="15"> -     Show IMs in: -    </text> -    <text -     name="requires_restart_label" -     follows="left|top" -     layout="topleft" -     top_delta="0"  -     left="170"  -  	 height="20" -	 width="130" -     text_color="White_25"> -      (requires restart) -      </text> -    <radio_group -     follows="left|top" -     height="30" -     left="40" -     control_name="ChatWindow" -     name="chat_window" -     top_pad="0" -     tool_tip="Show your Instant Messages in separate floaters, or in one floater with many tabs (Requires restart)" -     width="150"> -     <radio_item -      height="16" -      label="Separate Windows" -      layout="topleft" -      left="0" -      name="radio" -      value="0" -      top="0" -      width="150" /> -     <radio_item -      height="16" -      label="Tabs" -      layout="topleft" -      left_delta="0" -      name="radio2" -      value="1" -      top_pad="5" -      width="150" /> -    </radio_group> -    <text       name="disable_toast_label"       follows="left|top"       layout="topleft" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d5186e4c1b..2806bcaa2e 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -404,9 +404,10 @@ Please try logging in again in a minute.</string>  	<string name="AddAndRemoveJoints">Add and remove joints with other objects</string>  	<string name="ChangePermissions">Change its permissions</string>  	<string name="TrackYourCamera">Track your camera</string> -  <string name="ControlYourCamera">Control your camera</string> -  <string name="TeleportYourAgent">Teleport you</string> -  <string name="NotConnected">Not Connected</string> +	<string name="ControlYourCamera">Control your camera</string> +	<string name="NotConnected">Not Connected</string> +	<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> +    <string name="TeleportYourAgent">Teleport you</string>  	<!-- Sim Access labels -->  	<string name="SIM_ACCESS_PG">General</string> @@ -2270,8 +2271,10 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale  	<string name="InvFolder Gestures">Gestures</string>  	<string name="InvFolder Favorite">My Favorites</string>    <!-- historically default name of the Favorites folder can start from either "f" or "F" letter. -  We should localize both of them with the same value --> +      Also, it can be written as "Favorite" or "Favorites". +  We should localize all variants of them with the same value -->  	<string name="InvFolder favorite">My Favorites</string> +	<string name="InvFolder Favorites">My Favorites</string>  	<string name="InvFolder Current Outfit">Current Outfit</string>  	<string name="InvFolder Initial Outfits">Initial Outfits</string>  	<string name="InvFolder My Outfits">My Outfits</string> @@ -2280,6 +2283,7 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale    <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->  	<string name="InvFolder Friends">Friends</string> +	<string name="InvFolder Received Items">Received Items</string>  	<string name="InvFolder All">All</string>  	<string name="no_attachments">No attachments worn</string> @@ -2579,9 +2583,6 @@ Drag folders to this area and click "Send to Marketplace" to list them for sale  	<string name="GroupMoneyDebits">Debits</string>  	<string name="GroupMoneyDate">[weekday,datetime,utc] [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]</string> -	<!-- viewer object --> -	<string name="ViewerObjectContents">Contents</string> -  	<!-- Viewer menu -->  	<string name="AcquiredItems">Acquired Items</string>  	<string name="Cancel">Cancel</string> @@ -3377,6 +3378,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="IM_moderator_label">(Moderator)</string>  	<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string>  	<string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> +  <string name="OnlineStatus">Online</string> +  <string name="OfflineStatus">Offline</string>  	<!-- voice calls -->  	<string name="answered_call">Your call has been answered</string> @@ -3823,6 +3826,7 @@ Try enclosing path to the editor with double quotes.    <string name="Command_Avatar_Label">Avatar</string>    <string name="Command_Build_Label">Build</string>    <string name="Command_Chat_Label">Chat</string> +  <string name="Command_Conversations_Label">Conversations</string>    <string name="Command_Compass_Label">Compass</string>    <string name="Command_Destinations_Label">Destinations</string>    <string name="Command_Gestures_Label">Gestures</string> @@ -3849,6 +3853,7 @@ Try enclosing path to the editor with double quotes.    <string name="Command_Avatar_Tooltip">Choose a complete avatar</string>    <string name="Command_Build_Tooltip">Building objects and reshaping terrain</string>    <string name="Command_Chat_Tooltip">Chat with people nearby using text</string> +  <string name="Command_Conversations_Tooltip">Converse with everyone</string>    <string name="Command_Compass_Tooltip">Compass</string>    <string name="Command_Destinations_Tooltip">Destinations of interest</string>    <string name="Command_Gestures_Tooltip">Gestures for your avatar</string> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_editor.xml b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml new file mode 100644 index 0000000000..f9facb593a --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chat_editor.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chat_editor +  name="chat_editor" +  show_context_menu="true"/> diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml index 830c27bdac..d5b10e7f51 100644 --- a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml +++ b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml @@ -1,2 +1,3 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<inbox_inventory_panel show_load_status="false" /> +<inbox_inventory_panel show_load_status="false" +                       start_folder.type="inbox"/> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml deleted file mode 100644 index d19c47f54f..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_folder_view_folder -  folder_arrow_image="Folder_Arrow" -  folder_indentation="8" -  item_height="20"  -  item_top_pad="4" -  selection_image="Rounded_Square" -  > -</outbox_folder_view_folder> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml deleted file mode 100644 index 3964569da2..0000000000 --- a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<outbox_inventory_panel show_empty_message="false" show_load_status="false" /> diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml index 134f2d7522..2102074674 100644 --- a/indra/newview/skins/default/xui/en/widgets/text.xml +++ b/indra/newview/skins/default/xui/en/widgets/text.xml @@ -9,6 +9,7 @@        h_pad="0"         allow_scroll="false"        text_readonly_color="LabelTextColor" +      text_tentative_color="TextFgTentativeColor"        bg_writeable_color="FloaterDefaultBackgroundColor"         use_ellipses="false"        bg_visible="false"   | 
