diff options
| author | callum <none@none> | 2009-12-28 13:45:57 -0800 | 
|---|---|---|
| committer | callum <none@none> | 2009-12-28 13:45:57 -0800 | 
| commit | 3519435bbfeec4c838d5ffbe008d0ac7bbc085a8 (patch) | |
| tree | 5d590d84a1fa6c8414adba0732a83a67a440dd37 /indra/newview | |
| parent | dd1fb1568e85a8e3622372cae21bcd3205051718 (diff) | |
| parent | 6008bf61b2d0475a274ad2b851b61e69496b5bf8 (diff) | |
Merge with (specific revision) and head
Diffstat (limited to 'indra/newview')
73 files changed, 1774 insertions, 562 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7d8e9268e5..a26aae3590 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -258,7 +258,6 @@ set(viewer_SOURCE_FILES      llinventorymodel.cpp      llinventoryobserver.cpp      llinventorypanel.cpp -    llinventorysubtreepanel.cpp      lljoystickbutton.cpp      lllandmarkactions.cpp      lllandmarklist.cpp @@ -354,6 +353,7 @@ set(viewer_SOURCE_FILES      llparticipantlist.cpp      llpatchvertexarray.cpp      llplacesinventorybridge.cpp +    llplacesinventorypanel.cpp      llpolymesh.cpp      llpolymorph.cpp      llpreview.cpp @@ -766,7 +766,6 @@ set(viewer_HEADER_FILES      llinventorymodel.h      llinventoryobserver.h      llinventorypanel.h -    llinventorysubtreepanel.h      lljoystickbutton.h      lllandmarkactions.h      lllandmarklist.h @@ -858,6 +857,7 @@ set(viewer_HEADER_FILES      llparticipantlist.h      llpatchvertexarray.h      llplacesinventorybridge.h +    llplacesinventorypanel.h      llpolymesh.h      llpolymorph.h      llpreview.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ff7c2b1f5e..ba78d80ad1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10378,6 +10378,17 @@        <key>Value</key>        <string>Default</string>      </map> +    <key>VoiceParticipantLeftRemoveDelay</key> +    <map> +      <key>Comment</key> +      <string>Timeout to remove participants who has left Voice chat from the list in Voice Controls Panel</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>10</integer> +    </map>      <key>VoicePort</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 5317cf2cd0..b3ef6464f6 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -51,6 +51,12 @@ static const F32 LIT_UPDATE_PERIOD = 5;  // Used to limit time spent for avatar list update per frame.  static const unsigned ADD_LIMIT = 50; +bool LLAvatarList::contains(const LLUUID& id) +{ +	const uuid_vector_t& ids = getIDs(); +	return std::find(ids.begin(), ids.end(), id) != ids.end(); +} +  void LLAvatarList::toggleIcons()  {  	// Save the new value for new items to use. diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index e913be0f62..0d2ce884ae 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -75,6 +75,7 @@ public:  	void setNameFilter(const std::string& filter);  	void setDirty(bool val = true)						{ mDirty = val; }  	uuid_vector_t& getIDs() 							{ return mIDs; } +	bool contains(const LLUUID& id);  	void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; } diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index c8544bc3fb..8bc11b0c1c 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -158,7 +158,6 @@ void LLAvatarListItem::changed(U32 mask)  void LLAvatarListItem::setOnline(bool online)  {  	// *FIX: setName() overrides font style set by setOnline(). Not an issue ATM. -	// *TODO: Make the colors configurable via XUI.  	if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online)  		return; @@ -166,11 +165,7 @@ void LLAvatarListItem::setOnline(bool online)  	mOnlineStatus = (EOnlineStatus) online;  	// Change avatar name font style depending on the new online status. -	mAvatarNameStyle.color = online ? LLColor4::white : LLColor4::grey; -	setNameInternal(mAvatarName->getText(), mHighlihtSubstring); - -	// Make the icon fade if the avatar goes offline. -	mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke); +	setStyle(online ? IS_ONLINE : IS_OFFLINE);  }  void LLAvatarListItem::setName(const std::string& name) @@ -183,28 +178,21 @@ void LLAvatarListItem::setHighlight(const std::string& highlight)  	setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);  } -void LLAvatarListItem::setStyle(const LLStyle::Params& new_style) +void LLAvatarListItem::setStyle(EItemStyle item_style)  { -//	LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle = new_style); - -	// Active group should be bold. -	LLFontDescriptor new_desc(mAvatarName->getDefaultFont()->getFontDesc()); +	item_style_map_t& item_styles_params_map = getItemStylesParams(); -	new_desc.setStyle(new_style.font()->getFontDesc().getStyle()); -	// *NOTE dzaporozhan -	// On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font  -	// is predefined as bold (SansSerifSmallBold, for example) -//	new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL); -	LLFontGL* new_font = LLFontGL::getFont(new_desc); - -//	 -	mAvatarNameStyle.font = new_font; +	mAvatarNameStyle = item_styles_params_map[item_style];  	// *NOTE: You cannot set the style on a text box anymore, you must  	// rebuild the text.  This will cause problems if the text contains  	// hyperlinks, as their styles will be wrong. -	mAvatarName->setText(mAvatarName->getText(), mAvatarNameStyle/* = new_style*/); +	setNameInternal(mAvatarName->getText(), mHighlihtSubstring); + +	icon_color_map_t& item_icon_color_map = getItemIconColorMap(); +	mAvatarIcon->setColor(item_icon_color_map[item_style]);  } +  void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)  {  	if (mAvatarId.notNull()) @@ -418,3 +406,90 @@ std::string LLAvatarListItem::formatSeconds(U32 secs)  	args["[COUNT]"] = llformat("%u", count);  	return getString(fmt, args);  } + +// static +LLAvatarListItem::item_style_map_t& LLAvatarListItem::getItemStylesParams() +{ +	static item_style_map_t item_styles_params_map; +	if (!item_styles_params_map.empty()) return item_styles_params_map; + +	LLPanel::Params params = LLUICtrlFactory::getDefaultParams<LLPanel>(); +	LLPanel* params_panel = LLUICtrlFactory::create<LLPanel>(params); + +	BOOL sucsess = LLUICtrlFactory::instance().buildPanel(params_panel, "panel_avatar_list_item_params.xml"); + +	if (sucsess) +	{ + +		item_styles_params_map.insert( +			std::make_pair(IS_DEFAULT, +			params_panel->getChild<LLTextBox>("default_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_VOICE_INVITED, +			params_panel->getChild<LLTextBox>("voice_call_invited_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_VOICE_JOINED, +			params_panel->getChild<LLTextBox>("voice_call_joined_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_VOICE_LEFT, +			params_panel->getChild<LLTextBox>("voice_call_left_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_ONLINE, +			params_panel->getChild<LLTextBox>("online_style")->getDefaultStyle())); + +		item_styles_params_map.insert( +			std::make_pair(IS_OFFLINE, +			params_panel->getChild<LLTextBox>("offline_style")->getDefaultStyle())); +	} +	else +	{ +		item_styles_params_map.insert(std::make_pair(IS_DEFAULT, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_VOICE_INVITED, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_VOICE_JOINED, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_VOICE_LEFT, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_ONLINE, LLStyle::Params())); +		item_styles_params_map.insert(std::make_pair(IS_OFFLINE, LLStyle::Params())); +	} +	if (params_panel) params_panel->die(); + +	return item_styles_params_map; +} + +// static +LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap() +{ +	static icon_color_map_t item_icon_color_map; +	if (!item_icon_color_map.empty()) return item_icon_color_map; + +	item_icon_color_map.insert( +		std::make_pair(IS_DEFAULT, +		LLUIColorTable::instance().getColor("AvatarListItemIconDefaultColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_VOICE_INVITED, +		LLUIColorTable::instance().getColor("AvatarListItemIconVoiceInvitedColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_VOICE_JOINED, +		LLUIColorTable::instance().getColor("AvatarListItemIconVoiceJoinedColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_VOICE_LEFT, +		LLUIColorTable::instance().getColor("AvatarListItemIconVoiceLeftColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_ONLINE, +		LLUIColorTable::instance().getColor("AvatarListItemIconOnlineColor", LLColor4::white))); + +	item_icon_color_map.insert( +		std::make_pair(IS_OFFLINE, +		LLUIColorTable::instance().getColor("AvatarListItemIconOfflineColor", LLColor4::white))); + +	return item_icon_color_map; +} + +// EOF diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 0e058f75db..79303b55cc 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -46,6 +46,15 @@ class LLAvatarIconCtrl;  class LLAvatarListItem : public LLPanel, public LLFriendObserver  {  public: +	typedef enum e_item_style_type { +		IS_DEFAULT, +		IS_VOICE_INVITED, +		IS_VOICE_JOINED, +		IS_VOICE_LEFT, +		IS_ONLINE, +		IS_OFFLINE, +	} EItemStyle; +  	class ContextMenu  	{  	public: @@ -73,7 +82,7 @@ public:  	void setOnline(bool online);  	void setName(const std::string& name);  	void setHighlight(const std::string& highlight); -	void setStyle(const LLStyle::Params& new_style); +	void setStyle(EItemStyle item_style);  	void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);  	void setLastInteractionTime(U32 secs_since);  	//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly @@ -105,6 +114,8 @@ protected:  	 */  	LLOutputMonitorCtrl* mSpeakingIndicator; +	LLAvatarIconCtrl* mAvatarIcon; +  private:  	typedef enum e_online_status { @@ -118,7 +129,12 @@ private:  	std::string formatSeconds(U32 secs); -	LLAvatarIconCtrl* mAvatarIcon; +	typedef std::map<EItemStyle, LLStyle::Params> item_style_map_t; +	static item_style_map_t& getItemStylesParams(); + +	typedef std::map<EItemStyle, LLColor4> icon_color_map_t; +	static icon_color_map_t& getItemIconColorMap(); +  	LLTextBox* mAvatarName;  	LLTextBox* mLastInteractionTime;  	LLStyle::Params mAvatarNameStyle; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 4d5d416907..976b312509 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -148,6 +148,12 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam  {  	if (!getChicletPanel()) return; +	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); +	if (!session) return; + +	// no need to spawn chiclets for participants in P2P calls called through Avaline +	if (session->isP2P() && session->isOtherParticipantAvaline()) return; +  	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;  	LLIMChiclet* chiclet = createIMChiclet(session_id); diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index c222ced98f..1b4c274bfb 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -40,6 +40,7 @@  #include "llagent.h"  #include "llagentdata.h" // for gAgentID +#include "llavatariconctrl.h"  #include "llavatarlist.h"  #include "llbottomtray.h"  #include "llimfloater.h" @@ -48,6 +49,7 @@  #include "llspeakers.h"  #include "lltransientfloatermgr.h" +static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);  class LLNonAvatarCaller : public LLAvatarListItem  { @@ -66,6 +68,8 @@ public:  			showLastInteractionTime(false);  			setShowProfileBtn(false);  			setShowInfoBtn(false); +			mAvatarIcon->setValue("Avaline_Icon"); +			mAvatarIcon->setToolTip(std::string(""));  		}  		return rv;  	} @@ -95,16 +99,10 @@ BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()  	return TRUE;  } - -LLCallFloater::Params::Params() -: voice_left_remove_delay("voice_left_remove_delay", 10) -{ -} -  LLCallFloater::LLCallFloater(const LLSD& key)  : LLDockableFloater(NULL, false, key)  , mSpeakerManager(NULL) -, mPaticipants(NULL) +, mParticipants(NULL)  , mAvatarList(NULL)  , mNonAvatarCaller(NULL)  , mVoiceType(VC_LOCAL_CHAT) @@ -112,8 +110,11 @@ LLCallFloater::LLCallFloater(const LLSD& key)  , mSpeakingIndicator(NULL)  , mIsModeratorMutedVoice(false)  , mInitParticipantsVoiceState(false) -, mVoiceLeftRemoveDelay(10) // TODO: mantipov: make xml driven +, mVoiceLeftRemoveDelay(10)  { +	static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10); +	mVoiceLeftRemoveDelay = voice_left_remove_delay; +  	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);  	LLVoiceClient::getInstance()->addObserver(this);  	LLTransientFloaterMgr::getInstance()->addControlView(this); @@ -123,8 +124,8 @@ LLCallFloater::~LLCallFloater()  {  	resetVoiceRemoveTimers(); -	delete mPaticipants; -	mPaticipants = NULL; +	delete mParticipants; +	mParticipants = NULL;  	mAvatarListRefreshConnection.disconnect(); @@ -188,8 +189,8 @@ void LLCallFloater::draw()  	}  	// Need to resort the participant list if it's in sort by recent speaker order. -	if (mPaticipants) -		mPaticipants->updateRecentSpeakersOrder(); +	if (mParticipants) +		mParticipants->updateRecentSpeakersOrder();  	LLDockableFloater::draw();  } @@ -197,9 +198,17 @@ void LLCallFloater::draw()  // virtual  void LLCallFloater::onChange()  { -	if (NULL == mPaticipants) return; +	if (NULL == mParticipants) return;  	updateParticipantsVoiceState(); + +	// Add newly joined participants. +	std::vector<LLUUID> speakers_uuids; +	get_voice_participants_uuids(speakers_uuids); +	for (std::vector<LLUUID>::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++) +	{ +		mParticipants->addAvatarIDExceptAgent(*it); +	}  } @@ -280,7 +289,7 @@ void LLCallFloater::updateSession()  	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;  	childSetVisible("leave_call_btn", !is_local_chat); -	refreshPartisipantList(); +	refreshParticipantList();  	updateAgentModeratorState();  	//show floater for voice calls @@ -291,20 +300,11 @@ void LLCallFloater::updateSession()  		if (show_me)   		{  			setVisible(true); -			// Workaround(EM): Set current call dialog to front most because -			// connect/leaving popups should appear on top of VCP. -			// See bug EXT-3628. -			LLOutgoingCallDialog* instance = -				LLFloaterReg::findTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY); -			if(instance && instance->getVisible()) -			{ -				instance->setFrontmost(); -			}  		}  	}  } -void LLCallFloater::refreshPartisipantList() +void LLCallFloater::refreshParticipantList()  {  	// lets forget states from the previous session  	// for timers... @@ -313,8 +313,8 @@ void LLCallFloater::refreshPartisipantList()  	// ...and for speaker state  	mSpeakerStateMap.clear(); -	delete mPaticipants; -	mPaticipants = NULL; +	delete mParticipants; +	mParticipants = NULL;  	mAvatarList->clear();  	bool non_avatar_caller = false; @@ -334,7 +334,8 @@ void LLCallFloater::refreshPartisipantList()  	if (!non_avatar_caller)  	{ -		mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT); +		mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT); +		mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));  		if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)  		{ @@ -459,7 +460,7 @@ void LLCallFloater::updateAgentModeratorState()  	mAgentPanel->childSetValue("user_text", name);  } -void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids) +static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)  {  	// Get a list of participants from VoiceClient  	LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList(); @@ -572,13 +573,23 @@ void LLCallFloater::updateParticipantsVoiceState()  			// HAS LEFT the call.  			if ((getState(participant_id) == STATE_JOINED))  			{ -				setState(item, STATE_LEFT); - -				LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId()); -				if (speaker.isNull()) -					continue; - -				speaker->mHasLeftCurrentCall = TRUE; +				if (mVoiceType == VC_LOCAL_CHAT) +				{ +					// Don't display avatars that aren't in our nearby chat range anymore as "left". Remove them immediately. +					removeVoiceLeftParticipant(participant_id); +				} +				else +				{ +					setState(item, STATE_LEFT); + +					LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId()); +					if (speaker.isNull()) +					{ +						continue; +					} + +					speaker->mHasLeftCurrentCall = TRUE; +				}  			}  			// If an avatarID is not found in a speakers list from VoiceClient and  			// a panel with this ID has a LEFT status this means that this person @@ -587,9 +598,12 @@ void LLCallFloater::updateParticipantsVoiceState()  			{  				setState(item, STATE_INVITED);  			} +			else +			{ +				llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName()  << llendl; +			}  		}  	} -  }  void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state) @@ -609,38 +623,25 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)  	setState(item->getAvatarId(), state); -	LLStyle::Params speaker_style; -	LLFontDescriptor new_desc(speaker_style.font()->getFontDesc()); -  	switch (state)  	{  	case STATE_INVITED: -		new_desc.setStyle(LLFontGL::NORMAL); +		item->setStyle(LLAvatarListItem::IS_VOICE_INVITED);  		break;  	case STATE_JOINED:  		removeVoiceRemoveTimer(item->getAvatarId()); -		new_desc.setStyle(LLFontGL::NORMAL); +		item->setStyle(LLAvatarListItem::IS_VOICE_JOINED);  		break;  	case STATE_LEFT:  		{  			setVoiceRemoveTimer(item->getAvatarId()); -			new_desc.setStyle(LLFontGL::ITALIC); +			item->setStyle(LLAvatarListItem::IS_VOICE_LEFT);  		}  		break;  	default:  		llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl;  		break;  	} - -	LLFontGL* new_font = LLFontGL::getFont(new_desc); -	speaker_style.font = new_font; -	item->setStyle(speaker_style); - -//	if () -	{ -		// found speaker is in voice, mark him as online -		item->setOnline(STATE_JOINED == state); -	}  }  void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id) @@ -709,4 +710,15 @@ void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)  	}  } +bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id) +{ +	if (mVoiceType != VC_LOCAL_CHAT) +		return true; + +	// A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice). +	std::vector<LLUUID> speakers; +	get_voice_participants_uuids(speakers); +	return std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end(); +} +  //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 537c57f671..3df9e333c5 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -57,12 +57,6 @@ class LLSpeakerMgr;  class LLCallFloater : public LLDockableFloater, LLVoiceClientParticipantObserver  {  public: -	struct Params :	public LLInitParam::Block<Params, LLDockableFloater::Params> -	{ -		Optional<S32>			voice_left_remove_delay; - -		Params(); -	};  	LOG_CLASS(LLCallFloater); @@ -114,7 +108,7 @@ private:  	/**  	 * Refreshes participant list according to current Voice Channel  	 */ -	void refreshPartisipantList(); +	void refreshParticipantList();  	/**  	 * Handles event on avatar list is refreshed after it was marked dirty. @@ -133,7 +127,7 @@ private:  	/**  	 * Sets initial participants voice states in avatar list (Invited, Joined, Has Left).  	 * -	 * @see refreshPartisipantList() +	 * @see refreshParticipantList()  	 * @see onAvatarListRefreshed()  	 * @see mInitParticipantsVoiceState  	 */ @@ -188,10 +182,20 @@ private:  	 */  	void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id); +	/** +	 * Called by LLParticipantList before adding a speaker to the participant list. +	 * +	 * If false is returned, the speaker will not be added to the list. +	 * +	 * @param speaker_id Speaker to validate. +	 * @return true if this is a valid speaker, false otherwise. +	 */ +	bool validateSpeaker(const LLUUID& speaker_id); +  private:  	speaker_state_map_t mSpeakerStateMap;  	LLSpeakerMgr* mSpeakerManager; -	LLParticipantList* mPaticipants; +	LLParticipantList* mParticipants;  	LLAvatarList* mAvatarList;  	LLNonAvatarCaller* mNonAvatarCaller;  	EVoiceControls mVoiceType; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 17ef1f41a4..c01202bb82 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -64,18 +64,6 @@ static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");  static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");  static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); -static const LLRect CHICLET_RECT(0, 25, 25, 0); -static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0); -static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0); -static const LLRect COUNTER_RECT(25, 25, 50, 0); -static const S32 OVERLAY_ICON_SHIFT = 2;	// used for shifting of an overlay icon for new massages in a chiclet -static const S32 SCROLL_BUTTON_PAD = 5; - -// static -const S32 LLChicletPanel::s_scroll_ratio = 10; -const S32 LLChicletNotificationCounterCtrl::MAX_DISPLAYED_COUNT = 99; - -  boost::signals2::signal<LLChiclet* (const LLUUID&),  		LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >  		LLIMChiclet::sFindChicletsSignal; @@ -173,6 +161,9 @@ LLSysWellChiclet::~LLSysWellChiclet()  void LLSysWellChiclet::setCounter(S32 counter)  { +	// do nothing if the same counter is coming. EXT-3678. +	if (counter == mCounter) return; +  	// note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)  	std::string s_count;  	if(counter != 0) @@ -388,9 +379,9 @@ void LLNotificationChiclet::createMenu()  //////////////////////////////////////////////////////////////////////////  LLChiclet::Params::Params() - : show_counter("show_counter") + : show_counter("show_counter", true) + , enable_counter("enable_counter", false)  { -	show_counter = true;  }  LLChiclet::LLChiclet(const Params& p) @@ -448,26 +439,12 @@ void LLChiclet::setValue(const LLSD& value)  LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)  : LLChiclet(p)  , mShowSpeaker(false) +, mDefaultWidth(p.rect().getWidth())  , mNewMessagesIcon(NULL)  , mSpeakerCtrl(NULL)  , mCounterCtrl(NULL)  { -	// initialize an overlay icon for new messages -	LLIconCtrl::Params icon_params; -	icon_params.visible = false; -	icon_params.image = LLUI::getUIImage(p.new_messages_icon_name); -	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(icon_params); -	addChild(mNewMessagesIcon); - -	// adjust size and position of an icon -	LLRect chiclet_rect = p.rect; -	LLRect overlay_icon_rect = LLRect(chiclet_rect.getWidth()/2, chiclet_rect.getHeight(), chiclet_rect.getWidth(), chiclet_rect.getHeight()/2);  -	mNewMessagesIcon->setRect(overlay_icon_rect); -	 -	// shift an icon a little bit to the right and up corner of a chiclet -	overlay_icon_rect.translate(OVERLAY_ICON_SHIFT, OVERLAY_ICON_SHIFT); - -	enableCounterControl(false); +	enableCounterControl(p.enable_counter);  }  void LLIMChiclet::setShowSpeaker(bool show) @@ -477,7 +454,6 @@ void LLIMChiclet::setShowSpeaker(bool show)  	{		  		mShowSpeaker = show;  		toggleSpeakerControl(); -		onChicletSizeChanged();		  	}  } @@ -502,7 +478,6 @@ void LLIMChiclet::setShowCounter(bool show)  	{		  		LLChiclet::setShowCounter(show);  		toggleCounterControl(); -		onChicletSizeChanged();		  	}  } @@ -515,32 +490,37 @@ void LLIMChiclet::setRequiredWidth()  {  	bool show_speaker = getShowSpeaker();  	bool show_counter = getShowCounter(); -	S32 required_width = CHICLET_RECT.getWidth(); +	S32 required_width = mDefaultWidth;  	if (show_counter)  	{ -		required_width += COUNTER_RECT.getWidth(); +		required_width += mCounterCtrl->getRect().getWidth();  	}  	if (show_speaker)  	{ -		required_width += VOICE_INDICATOR_RECT.getWidth(); +		required_width += mSpeakerCtrl->getRect().getWidth();  	}   	reshape(required_width, getRect().getHeight()); + +	onChicletSizeChanged();  }  void LLIMChiclet::toggleSpeakerControl()  {  	if(getShowSpeaker())  	{ +		// move speaker to the right of chiclet icon +		LLRect speaker_rc = mSpeakerCtrl->getRect(); +		speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight()); +		mSpeakerCtrl->setRect(speaker_rc); +  		if(getShowCounter())  		{ -			mSpeakerCtrl->setRect(VOICE_INDICATOR_RECT); -		} -		else -		{ -			mSpeakerCtrl->setRect(COUNTER_RECT); +			// move speaker to the right of counter +			mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0);  		} +  		initSpeakerControl();		  	} @@ -567,6 +547,7 @@ void LLIMChiclet::setShowNewMessagesIcon(bool show)  	{  		mNewMessagesIcon->setVisible(show);  	} +	setRequiredWidth();  }  bool LLIMChiclet::getShowNewMessagesIcon() @@ -640,36 +621,9 @@ LLIMP2PChiclet::Params::Params()  : avatar_icon("avatar_icon")  , unread_notifications("unread_notifications")  , speaker("speaker") +, new_message_icon("new_message_icon")  , show_speaker("show_speaker")  { -	// *TODO Vadim: Get rid of hardcoded values. -	rect(CHICLET_RECT); - -	avatar_icon.name("avatar_icon"); -	avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - -	// *NOTE dzaporozhan -	// Changed icon height from 25 to 24 to fix ticket EXT-794. -	// In some cases(after changing UI scale) 25 pixel height icon was  -	// drawn incorrectly, i'm not sure why. -	avatar_icon.rect(CHICLET_ICON_RECT); -	avatar_icon.mouse_opaque(false); - -	unread_notifications.name("unread"); -	unread_notifications.font(LLFontGL::getFontSansSerif()); -	unread_notifications.font_halign(LLFontGL::HCENTER); -	unread_notifications.v_pad(5); -	unread_notifications.text_color(LLColor4::white); -	unread_notifications.mouse_opaque(false); -	unread_notifications.rect(COUNTER_RECT); -	unread_notifications.visible(false); - -	speaker.name("speaker"); -	speaker.rect(VOICE_INDICATOR_RECT); -	speaker.auto_update(true); -	speaker.draw_border(false); - -	show_speaker = false;  }  LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) @@ -677,6 +631,10 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)  , mChicletIconCtrl(NULL)  , mPopupMenu(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);  	addChild(mChicletIconCtrl); @@ -694,10 +652,6 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)  	sendChildToFront(mNewMessagesIcon);  	setShowSpeaker(p.show_speaker); - -	//since mShowSpeaker initialized with false  -	//setShowSpeaker(false) will not hide mSpeakerCtrl -	mSpeakerCtrl->setVisible(getShowSpeaker());  }  void LLIMP2PChiclet::initSpeakerControl() @@ -718,8 +672,11 @@ void LLIMP2PChiclet::updateMenuItems()  	if(getSessionId().isNull())  		return; +	LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); +	bool open_window_exists = open_im_floater && open_im_floater->getVisible(); +	mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists); +	  	bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); -  	mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);  } @@ -790,38 +747,10 @@ LLAdHocChiclet::Params::Params()  : avatar_icon("avatar_icon")  , unread_notifications("unread_notifications")  , speaker("speaker") +, new_message_icon("new_message_icon")  , show_speaker("show_speaker")  , avatar_icon_color("avatar_icon_color", LLColor4::green)  { -	// *TODO Vadim: Get rid of hardcoded values. -	rect(CHICLET_RECT); - -	avatar_icon.name("avatar_icon"); -	avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - -	// *NOTE dzaporozhan -	// Changed icon height from 25 to 24 to fix ticket EXT-794. -	// In some cases(after changing UI scale) 25 pixel height icon was  -	// drawn incorrectly, i'm not sure why. -	avatar_icon.rect(CHICLET_ICON_RECT); -	avatar_icon.mouse_opaque(false); - -	unread_notifications.name("unread"); -	unread_notifications.font(LLFontGL::getFontSansSerif()); -	unread_notifications.font_halign(LLFontGL::HCENTER); -	unread_notifications.v_pad(5); -	unread_notifications.text_color(LLColor4::white); -	unread_notifications.mouse_opaque(false); -	unread_notifications.rect(COUNTER_RECT); -	unread_notifications.visible(false); - - -	speaker.name("speaker"); -	speaker.rect(VOICE_INDICATOR_RECT); -	speaker.auto_update(true); -	speaker.draw_border(false); - -	show_speaker = false;  }  LLAdHocChiclet::LLAdHocChiclet(const Params& p) @@ -829,6 +758,10 @@ LLAdHocChiclet::LLAdHocChiclet(const Params& p)  , mChicletIconCtrl(NULL)  , mPopupMenu(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);  	//Make the avatar modified @@ -941,32 +874,9 @@ LLIMGroupChiclet::Params::Params()  : group_icon("group_icon")  , unread_notifications("unread_notifications")  , speaker("speaker") +, new_message_icon("new_message_icon")  , show_speaker("show_speaker")  { -	rect(CHICLET_RECT); - -	group_icon.name("group_icon"); -	 -	// *NOTE dzaporozhan -	// Changed icon height from 25 to 24 to fix ticket EXT-794. -	// In some cases(after changing UI scale) 25 pixel height icon was  -	// drawn incorrectly, i'm not sure why. -	group_icon.rect(CHICLET_ICON_RECT); - -	unread_notifications.name("unread"); -	unread_notifications.font(LLFontGL::getFontSansSerif()); -	unread_notifications.font_halign(LLFontGL::HCENTER); -	unread_notifications.v_pad(5); -	unread_notifications.text_color(LLColor4::white); -	unread_notifications.rect(COUNTER_RECT); -	unread_notifications.visible(false); - -	speaker.name("speaker"); -	speaker.rect(VOICE_INDICATOR_RECT); -	speaker.auto_update(true); -	speaker.draw_border(false); - -	show_speaker = false;  }  LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) @@ -975,6 +885,10 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)  , mChicletIconCtrl(NULL)  , mPopupMenu(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletGroupIconCtrl::Params avatar_params = p.group_icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params);  	addChild(mChicletIconCtrl); @@ -1063,6 +977,18 @@ void LLIMGroupChiclet::changed(LLGroupChange gc)  	}  } +void LLIMGroupChiclet::updateMenuItems() +{ +	if(!mPopupMenu) +		return; +	if(getSessionId().isNull()) +		return; + +	LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId()); +	bool open_window_exists = open_im_floater && open_im_floater->getVisible(); +	mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists); +} +  BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	if(!mPopupMenu) @@ -1072,6 +998,7 @@ BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  	if (mPopupMenu)  	{ +		updateMenuItems();  		mPopupMenu->arrangeAndClear();  		LLMenuGL::showPopup(this, mPopupMenu, x, y);  	} @@ -1125,16 +1052,10 @@ void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)  LLChicletPanel::Params::Params()  : chiclet_padding("chiclet_padding")  , scrolling_offset("scrolling_offset") +, scroll_button_hpad("scroll_button_hpad") +, scroll_ratio("scroll_ratio")  , min_width("min_width")  { -	chiclet_padding = 3; -	scrolling_offset = 40; - -	if (!min_width.isProvided()) -	{ -		// min_width = 4 chiclets + 3 paddings -		min_width = 180 + 3*chiclet_padding; -	}  };  LLChicletPanel::LLChicletPanel(const Params&p) @@ -1144,6 +1065,8 @@ LLChicletPanel::LLChicletPanel(const Params&p)  , mRightScrollButton(NULL)  , mChicletPadding(p.chiclet_padding)  , mScrollingOffset(p.scrolling_offset) +, mScrollButtonHPad(p.scroll_button_hpad) +, mScrollRatio(p.scroll_ratio)  , mMinWidth(p.min_width)  , mShowControls(true)  { @@ -1445,8 +1368,8 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  	bool need_show_scroll = needShowScroll();  	if(need_show_scroll)  	{ -		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, -			height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, +			height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));  	}  	else  	{ @@ -1462,6 +1385,20 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  } +S32	LLChicletPanel::notifyParent(const LLSD& info) +{ +	if(info.has("notification")) +	{ +		std::string str_notification = info["notification"]; +		if(str_notification == "size_changes") +		{ +			arrange(); +			return 1; +		} +	} +	return LLPanel::notifyParent(info); +} +  void LLChicletPanel::arrange()  {  	if(mChicletList.empty()) @@ -1490,8 +1427,8 @@ void LLChicletPanel::arrange()  	bool need_show_scroll = needShowScroll();  	if(need_show_scroll)  	{ -		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, -			rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, +			rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));  	}  	else  	{ @@ -1655,7 +1592,7 @@ void LLChicletPanel::onRightScrollClick()  void LLChicletPanel::onLeftScrollHeldDown()  {  	S32 offset = mScrollingOffset; -	mScrollingOffset = mScrollingOffset / s_scroll_ratio; +	mScrollingOffset = mScrollingOffset / mScrollRatio;  	scrollLeft();  	mScrollingOffset = offset;  } @@ -1663,7 +1600,7 @@ void LLChicletPanel::onLeftScrollHeldDown()  void LLChicletPanel::onRightScrollHeldDown()  {  	S32 offset = mScrollingOffset; -	mScrollingOffset = mScrollingOffset / s_scroll_ratio; +	mScrollingOffset = mScrollingOffset / mScrollRatio;  	scrollRight();  	mScrollingOffset = offset;  } @@ -1725,7 +1662,7 @@ S32 LLChicletPanel::getTotalUnreadIMCount()  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  LLChicletNotificationCounterCtrl::Params::Params() -: max_displayed_count("max_displayed_count", MAX_DISPLAYED_COUNT) +: max_displayed_count("max_displayed_count", 99)  {  } @@ -1802,6 +1739,7 @@ LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p)  : LLIconCtrl(p)  , mDefaultIcon(p.default_icon)  { +	setValue(LLUUID::null);  }  void LLChicletGroupIconCtrl::setValue(const LLSD& value ) @@ -1853,20 +1791,23 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)  LLScriptChiclet::Params::Params()   : icon("icon") + , new_message_icon("new_message_icon")  { -	// *TODO Vadim: Get rid of hardcoded values. - 	rect(CHICLET_RECT); -	icon.rect(CHICLET_ICON_RECT);  }  LLScriptChiclet::LLScriptChiclet(const Params&p)   : LLIMChiclet(p)   , mChicletIconCtrl(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLIconCtrl::Params icon_params = p.icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); -	// Let "new message" icon be on top, else it will be hidden behind chiclet icon. -	addChildInBack(mChicletIconCtrl); +	addChild(mChicletIconCtrl); + +	sendChildToFront(mNewMessagesIcon);  }  void LLScriptChiclet::setSessionId(const LLUUID& session_id) @@ -1905,20 +1846,24 @@ BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask)  static const std::string INVENTORY_USER_OFFER	("UserGiveItem");  LLInvOfferChiclet::Params::Params() + : icon("icon") + , new_message_icon("new_message_icon")  { -	// *TODO Vadim: Get rid of hardcoded values. -	rect(CHICLET_RECT); -	icon.rect(CHICLET_ICON_RECT);  }  LLInvOfferChiclet::LLInvOfferChiclet(const Params&p)   : LLIMChiclet(p)   , mChicletIconCtrl(NULL)  { +	LLIconCtrl::Params new_msg_params = p.new_message_icon; +	mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); +	addChild(mNewMessagesIcon); +  	LLChicletInvOfferIconCtrl::Params icon_params = p.icon;  	mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params); -	// Let "new message" icon be on top, else it will be hidden behind chiclet icon. -	addChildInBack(mChicletIconCtrl); +	addChild(mChicletIconCtrl); + +	sendChildToFront(mNewMessagesIcon);  }  void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 2ab6abfb5b..ee9db10525 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -52,8 +52,6 @@ class LLChicletNotificationCounterCtrl : public LLTextBox  {  public: -	static const S32 MAX_DISPLAYED_COUNT; -  	struct Params :	public LLInitParam::Block<Params, LLTextBox::Params>  	{  		/** @@ -217,7 +215,8 @@ public:  	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>  	{ -		Optional<bool> show_counter; +		Optional<bool> show_counter, +					   enable_counter;  		Params();  	}; @@ -323,10 +322,7 @@ public:  	};  	struct Params : public LLInitParam::Block<Params, LLChiclet::Params>  	{ -		Optional<std::string> new_messages_icon_name; - -		Params() : new_messages_icon_name("new_messages_icon_name", "Unread_IM") -		{} +		Params(){}  	}; @@ -437,6 +433,8 @@ protected:  	bool mShowSpeaker;  	bool mCounterEnabled; +	/* initial width of chiclet, should not include counter or speaker width */ +	S32 mDefaultWidth;  	LLIconCtrl* mNewMessagesIcon;  	LLChicletNotificationCounterCtrl* mCounterCtrl; @@ -482,6 +480,8 @@ public:  		Optional<LLChicletSpeakerCtrl::Params> speaker; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Optional<bool>	show_speaker;  		Params(); @@ -521,6 +521,7 @@ protected:  	/**   	 * Enables/disables menus based on relationship with other participant. +	 * Enables/disables "show session" menu item depending on visible IM floater existence.  	 */  	virtual void updateMenuItems(); @@ -544,6 +545,8 @@ public:  		Optional<LLChicletSpeakerCtrl::Params> speaker; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Optional<bool>	show_speaker;  		Optional<LLColor4>	avatar_icon_color; @@ -614,6 +617,8 @@ public:  	{  		Optional<LLIconCtrl::Params> icon; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Params();  	}; @@ -654,6 +659,8 @@ public:  	{  		Optional<LLChicletInvOfferIconCtrl::Params> icon; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Params();  	}; @@ -697,6 +704,8 @@ public:  		Optional<LLChicletSpeakerCtrl::Params> speaker; +		Optional<LLIconCtrl::Params> new_message_icon; +  		Optional<bool>	show_speaker;  		Params(); @@ -752,6 +761,11 @@ protected:  	virtual void onMenuItemClicked(const LLSD& user_data);  	/** +	 * Enables/disables "show session" menu item depending on visible IM floater existence. +	 */ +	virtual void updateMenuItems(); + +	/**  	 * Displays popup menu.  	 */  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); @@ -931,7 +945,9 @@ public:  	struct Params :	public LLInitParam::Block<Params, LLPanel::Params>  	{  		Optional<S32> chiclet_padding, -					  scrolling_offset; +					  scrolling_offset, +					  scroll_button_hpad, +					  scroll_ratio;  		Optional<S32> min_width; @@ -1021,6 +1037,8 @@ public:  	S32 getTotalUnreadIMCount(); +	S32	notifyParent(const LLSD& info); +  protected:  	LLChicletPanel(const Params&p);  	friend class LLUICtrlFactory; @@ -1148,6 +1166,8 @@ protected:  	S32 mChicletPadding;  	S32 mScrollingOffset; +	S32 mScrollButtonHPad; +	S32 mScrollRatio;  	S32 mMinWidth;  	bool mShowControls;  	static const S32 s_scroll_ratio; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 832626e007..ee33c189f9 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -162,9 +162,22 @@ public:  		if (!region_name.empty())  		{  			LLToolTip::Params params; -			params.message = llformat("%s\n%s (%d, %d, %d)", getLabelSelected().c_str(), region_name.c_str(),  +			std::string extra_message = llformat("%s (%d, %d, %d)", region_name.c_str(),   				mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY(), mLandmarkInfoGetter.getPosZ()); -			params.sticky_rect = calcScreenRect(); + +			params.message = llformat("%s\n%s", getLabelSelected().c_str(), extra_message.c_str()); +			 +			LLRect rect = calcScreenRect(); +			LLFontGL* standart_font = LLFontGL::getFontSansSerif(); +			if(standart_font) +			{ +				S32 w = llmax((S32)(standart_font->getWidthF32(getLabelSelected())+0.5),(S32)(standart_font->getWidthF32(extra_message)+0.5)); +				rect.mRight = rect.mLeft + w; +				params.max_width = w; +			} +			 +			params.sticky_rect = rect;  +  			LLToolTipMgr::instance().show(params);  		}  		return TRUE; @@ -984,7 +997,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)  	if (action == "open")  	{ -		teleport_via_landmark(item->getAssetUUID()); +		onButtonClick(item->getUUID());  	}  	else if (action == "about")  	{ diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 9cca1b07db..474d2ca21f 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1822,6 +1822,13 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data,  											 accept, tooltip_msg); +	// When there are no visible children drag and drop is handled +	// by the folder which is the hierarchy root. +	if (!handled && !hasVisibleChildren()) +	{ +		handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); +	} +  	if (handled)  	{  		lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 0ce8d4b7cd..259f629bdd 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -109,6 +109,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  		default: break;  		}  	} +	setOverlapsScreenChannel(true);  }  void LLIMFloater::onFocusLost() diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 3549891bc5..37ab144934 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -243,10 +243,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  	std::string joined_call = LLTrans::getString("joined_call");  	std::string other_avatar_name = ""; +	std::string message; +  	switch(mSessionType)  	{  	case AVALINE_SESSION: -		// *TODO: test avaline calls (EXT-2211) +		// no text notifications +		break;  	case P2P_SESSION:  		gCacheName->getFullName(mOtherParticipantID, other_avatar_name); @@ -255,10 +258,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call); +				message = other_avatar_name + " " + started_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message); +				  				break;  			case LLVoiceChannel::STATE_CONNECTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call); +				message = you + " " + joined_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  			default:  				break;  			} @@ -268,37 +274,27 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call); +				message = you + " " + started_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  				break;  			case LLVoiceChannel::STATE_CONNECTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, joined_call); +				message = other_avatar_name + " " + joined_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  			default:  				break;  			}  		} - -		// Update speakers list when connected -		if (LLVoiceChannel::STATE_CONNECTED == new_state) -		{ -			mSpeakers->update(true); -		} -  		break;  	case GROUP_SESSION:  	case ADHOC_SESSION: -		// *TODO: determine call starter's name "other_avatar_name" (EXT-2211) -		//        decide how to show notifications for a group/adhoc chat already opened -		//		  for now there is no notification from voice channel for this case  		if(direction == LLVoiceChannel::INCOMING_CALL)  		{  			switch(new_state)  			{ -			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call); -				break;  			case LLVoiceChannel::STATE_CONNECTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call); +				message = you + " " + joined_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  			default:  				break;  			} @@ -308,19 +304,18 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  			switch(new_state)  			{  			case LLVoiceChannel::STATE_CALL_STARTED : -				LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call); +				message = you + " " + started_call; +				LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);  				break;  			default:  				break;  			}  		} - -		// Update speakers list when connected -		if (LLVoiceChannel::STATE_CONNECTED == new_state) -		{ -			mSpeakers->update(true); -		} -		break; +	} +	// Update speakers list when connected +	if (LLVoiceChannel::STATE_CONNECTED == new_state) +	{ +		mSpeakers->update(true);  	}  } @@ -473,6 +468,17 @@ bool LLIMModel::LLIMSession::isAdHoc()  	return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID));  } +bool LLIMModel::LLIMSession::isP2P() +{ +	return IM_NOTHING_SPECIAL == mType; +} + +bool LLIMModel::LLIMSession::isOtherParticipantAvaline() +{ +	return !mOtherParticipantIsAvatar; +} + +  void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)  {  	LLIMSession* session = findIMSession(old_session_id); @@ -1476,13 +1482,17 @@ LLCallDialog(payload)  	}	  } -void LLOutgoingCallDialog::draw() +void LLCallDialog::draw()  {  	if (lifetimeHasExpired())  	{  		onLifetimeExpired();  	} -	LLDockableFloater::draw(); + +	if (getDockControl() != NULL) +	{ +		LLDockableFloater::draw(); +	}  }  bool LLOutgoingCallDialog::lifetimeHasExpired() @@ -1490,7 +1500,7 @@ bool LLOutgoingCallDialog::lifetimeHasExpired()  	if (mLifetimeTimer.getStarted())  	{  		F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); -		if (elapsed_time > LIFETIME)  +		if (elapsed_time > mLifetime)   		{  			return true;  		} @@ -1511,6 +1521,13 @@ void LLOutgoingCallDialog::show(const LLSD& key)  	// hide all text at first  	hideAllText(); +	// init notification's lifetime +	std::istringstream ss( getString("lifetime") ); +	if (!(ss >> mLifetime)) +	{ +		mLifetime = DEFAULT_LIFETIME; +	} +  	// customize text strings  	// tell the user which voice channel they are leaving  	if (!mPayload["old_channel_name"].asString().empty()) @@ -1621,6 +1638,35 @@ LLCallDialog(payload)  {  } +bool LLIncomingCallDialog::lifetimeHasExpired() +{ +	if (mLifetimeTimer.getStarted()) +	{ +		F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); +		if (elapsed_time > mLifetime)  +		{ +			return true; +		} +	} +	return false; +} + +void LLIncomingCallDialog::onLifetimeExpired() +{ +	// check whether a call is valid or not +	if (LLVoiceClient::getInstance()->findSession(mPayload["caller_id"].asUUID())) +	{ +		// restart notification's timer if call is still valid +		mLifetimeTimer.start(); +	} +	else +	{ +		// close invitation if call is already not valid +		mLifetimeTimer.stop(); +		closeFloater(); +	} +} +  BOOL LLIncomingCallDialog::postBuild()  {  	LLCallDialog::postBuild(); @@ -1629,6 +1675,13 @@ BOOL LLIncomingCallDialog::postBuild()  	LLSD caller_id = mPayload["caller_id"];  	std::string caller_name = mPayload["caller_name"].asString(); +	// init notification's lifetime +	std::istringstream ss( getString("lifetime") ); +	if (!(ss >> mLifetime)) +	{ +		mLifetime = DEFAULT_LIFETIME; +	} +  	std::string call_type;  	if (gAgent.isInGroup(session_id))  	{ @@ -1659,13 +1712,30 @@ BOOL LLIncomingCallDialog::postBuild()  	LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");  	caller_name_widget->setValue(caller_name + " " + call_type);  	LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); -	icon->setValue(caller_id); +	if (is_avatar) +	{ +		icon->setValue(caller_id); +	} +	else +	{ +		icon->setValue("Avaline_Icon"); +	}  	childSetAction("Accept", onAccept, this);  	childSetAction("Reject", onReject, this);  	childSetAction("Start IM", onStartIM, this);  	childSetFocus("Accept"); +	if(mPayload["notify_box_type"] != "VoiceInviteGroup" && mPayload["notify_box_type"] != "VoiceInviteAdHoc") +	{ +		// starting notification's timer for P2P and AVALINE invitations +		mLifetimeTimer.start(); +	} +	else +	{ +		mLifetimeTimer.stop(); +	} +  	return TRUE;  } @@ -1796,6 +1866,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response)  					new LLViewerChatterBoxInvitationAcceptResponder(  						session_id,  						inv_type)); + +				// send notification message to the corresponding chat  +				if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc") +				{ +					std::string started_call = LLTrans::getString("started_call"); +					std::string message = mPayload["caller_name"].asString() + " " + started_call; +					LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message); +				}  			}  		}  		if (voice) @@ -2463,6 +2541,11 @@ void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body  	if (speaker_mgr)  	{  		speaker_mgr->updateSpeakers(body); + +		// also the same call is added into LLVoiceClient::participantUpdatedEvent because +		// sometimes it is called AFTER LLViewerChatterBoxSessionAgentListUpdates::post() +		// when moderation state changed too late. See EXT-3544. +		speaker_mgr->update(true);  	}  	else  	{ diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 3f46b0d754..cec9d1642f 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -75,6 +75,8 @@ public:  		static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);  		bool isAdHoc(); +		bool isP2P(); +		bool isOtherParticipantAvaline();  		LLUUID mSessionID;  		std::string mName; @@ -486,7 +488,18 @@ public:  	virtual BOOL postBuild(); +	// check timer state +	/*virtual*/ void draw(); +  protected: +	// lifetime timer for a notification +	LLTimer	mLifetimeTimer; +	// notification's lifetime in seconds +	S32		mLifetime; +	static const S32 DEFAULT_LIFETIME = 5; +	virtual bool lifetimeHasExpired() {return false;}; +	virtual void onLifetimeExpired() {}; +  	virtual void getAllowedRect(LLRect& rect);  	LLSD mPayload;  }; @@ -504,6 +517,8 @@ public:  	static void onStartIM(void* user_data);  private: +	/*virtual*/ bool lifetimeHasExpired(); +	/*virtual*/ void onLifetimeExpired();  	void processCallResponse(S32 response);  }; @@ -518,19 +533,11 @@ public:  	static void onCancel(void* user_data);  	static const LLUUID OCD_KEY; -	// check timer state -	/*virtual*/ void draw(); -  private: -  	// hide all text boxes  	void hideAllText(); -	// lifetime timer for NO_ANSWER notification -	LLTimer	mLifetimeTimer; -	// lifetime duration for NO_ANSWER notification -	static const S32 LIFETIME = 5; -	bool lifetimeHasExpired(); -	void onLifetimeExpired(); +	/*virtual*/ bool lifetimeHasExpired(); +	/*virtual*/ void onLifetimeExpired();  };  // Globals diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1eb8d1bc2c..711114173c 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2654,6 +2654,33 @@ void LLInventoryModel::buildParentChildMap()  		cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);  		if(catsp)  		{ +			// *HACK - fix root inventory folder +			// some accounts has pbroken inventory root folders +			 +			std::string name = "My Inventory"; +			LLUUID prev_root_id = mRootFolderID; +			for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), +					 it_end = mParentChildCategoryTree.end(); it != it_end; ++it) +			{ +				cat_array_t* cat_array = it->second; +				for (cat_array_t::const_iterator cat_it = cat_array->begin(), +						 cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it) +					{ +					LLPointer<LLViewerInventoryCategory> category = *cat_it; + +					if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY) +						continue; +					if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) ) +					{ +						if(category->getUUID()!=mRootFolderID) +						{ +							LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID); +							new_inv_root_folder_id = category->getUUID(); +						} +					} +				} +			} +  			// 'My Inventory',  			// root of the agent's inv found.  			// The inv tree is built. diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 082b7a9468..164e72e621 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -628,9 +628,15 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  								   EAcceptance* accept,  								   std::string& tooltip_msg)  { -  	BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); +	// If folder view is empty the (x, y) point won't be in its rect +	// so the handler must be called explicitly. +	if (!mFolders->hasVisibleChildren()) +	{ +		handled = mFolders->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); +	} +  	if (handled)  	{  		mFolders->setDragAndDropThisFrame(); diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 818e7e0db1..0ab3b07aea 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -684,7 +684,6 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick()  	gAgent.setFlying(FALSE);  	setFocus(FALSE); // EXT-482 -	setVisible(FALSE);  }  /** diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index c3df4cbaf4..52de8355e9 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -93,6 +93,19 @@ bool LLAlertHandler::processNotification(const LLSD& notify)  	if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load")  	{ +		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(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 515c86bae8..0fb438bfe9 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -277,6 +277,13 @@ public:  	static bool canSpawnIMSession(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); + +	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -298,6 +305,20 @@ public:  	 * Writes notification message to nearby chat.  	 */  	static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type); + +	/** +	 * Spawns IM session. +	 */ +	static void spawnIMSession(const std::string& name, const LLUUID& from_id); + +	/** +	 * Returns name from the notification's substitution. +	 * +	 * Methods gets "NAME" or "[NAME]" from the substitution map. +	 * +	 * @param notification - Notification which substitution's name will be returned. +	 */ +	static std::string getSubstitutionName(const LLNotificationPtr& notification);  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 5b54092c5c..fba5773602 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -47,11 +47,15 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),  				"ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER(  				"ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"),  						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), -						USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"), +						USER_GIVE_ITEM("UserGiveItem"), +						INVENTORY_ACCEPTED("InventoryAccepted"), +						INVENTORY_DECLINED("InventoryDeclined"), +						OFFER_FRIENDSHIP("OfferFriendship"),  						FRIENDSHIP_ACCEPTED("FriendshipAccepted"),  						FRIENDSHIP_OFFERED("FriendshipOffered"),  						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), -						SERVER_OBJECT_MESSAGE("ServerObjectMessage"); +						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), +						TELEPORT_OFFERED("TeleportOffered");  // static  bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) @@ -59,8 +63,11 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)  	return GRANTED_MODIFY_RIGHTS == notification->getName()  			|| REVOKED_MODIFY_RIGHTS == notification->getName()  			|| PAYMENT_RECIVED == notification->getName() +			|| OFFER_FRIENDSHIP == notification->getName()  			|| FRIENDSHIP_OFFERED == notification->getName() -			|| SERVER_OBJECT_MESSAGE == notification->getName(); +			|| SERVER_OBJECT_MESSAGE == notification->getName() +			|| INVENTORY_ACCEPTED == notification->getName() +			|| INVENTORY_DECLINED == notification->getName();  }  // static @@ -68,15 +75,25 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)  {  	return notification->getType() == "notifytip"  			&&  FRIEND_ONLINE != notification->getName() -			&& FRIEND_OFFLINE != notification->getName(); +			&& FRIEND_OFFLINE != notification->getName() +			&& INVENTORY_ACCEPTED != notification->getName() +			&& INVENTORY_DECLINED != notification->getName();  }  // static  bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)  { -	return ADD_FRIEND_WITH_MESSAGE == notification->getName() -			|| OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName(); +	return OFFER_FRIENDSHIP == notification->getName() +			|| FRIENDSHIP_ACCEPTED == notification->getName() +			|| USER_GIVE_ITEM == notification->getName() +			|| INVENTORY_ACCEPTED == notification->getName() +			|| INVENTORY_DECLINED == notification->getName(); +} + +// static +bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) +{ +	return canLogToIM(notification) && canSpawnIMSession(notification);  }  // static @@ -113,10 +130,7 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  // static  void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)  { -	const std::string -			name = -					notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"] -							: notification->getSubstitutions()["[NAME]"]; +	const std::string name = LLHandlerUtil::getSubstitutionName(notification);  	const std::string session_name = notification->getPayload().has(  			"SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name; @@ -169,3 +183,23 @@ void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChat  	}  } +// static +void LLHandlerUtil::spawnIMSession(const std::string& name, const LLUUID& from_id) +{ +	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); + +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( +			session_id); +	if (session == NULL) +	{ +		LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, from_id); +	} +} + +// static +std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notification) +{ +	return notification->getSubstitutions().has("NAME") +		? notification->getSubstitutions()["NAME"] +		: notification->getSubstitutions()["[NAME]"]; +} diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 4d64c5c0e4..dd66a6c507 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -105,22 +105,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  		{  			if (LLHandlerUtil::canSpawnIMSession(notification))  			{ -				const std::string name = notification->getSubstitutions().has( -						"NAME") ? notification->getSubstitutions()["NAME"] -						: notification->getSubstitutions()["[NAME]"]; +				const std::string name = LLHandlerUtil::getSubstitutionName(notification);  				LLUUID from_id = notification->getPayload()["from_id"]; -				LLUUID session_id = LLIMMgr::computeSessionID( -						IM_NOTHING_SPECIAL, from_id); - -				LLIMModel::LLIMSession* session = -						LLIMModel::instance().findIMSession(session_id); -				if (session == NULL) -				{ -					LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, -							from_id); -				} +				LLHandlerUtil::spawnIMSession(name, from_id);  			}  			if (notification->getPayload().has("SUPPRES_TOST") diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 9afaddae82..83a2215ac6 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -101,6 +101,19 @@ bool LLTipHandler::processNotification(const LLSD& notify)  			}  		} +		const std::string name = notification->getSubstitutions()["NAME"]; +		LLUUID from_id = notification->getPayload()["from_id"]; +		if (LLHandlerUtil::canLogToIM(notification)) +		{ +			LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, name, name, +					notification->getMessage(), from_id, from_id); +		} + +		if (LLHandlerUtil::canSpawnIMSession(notification)) +		{ +			LLHandlerUtil::spawnIMSession(name, from_id); +		} +  		LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);  		LLToast::Params p; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index fa16cb6473..63803469dd 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -64,10 +64,6 @@ LLOutputMonitorCtrl::Params::Params()  	auto_update("auto_update"),  	speaker_id("speaker_id")  { -	draw_border = true; -	name = "output_monitor"; -	follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP); -	mouse_opaque = false;  };  LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index e9131a342e..913152e259 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -179,6 +179,10 @@ void LLPanelAvatarNotes::onOpen(const LLSD& key)  void LLPanelAvatarNotes::fillRightsData()  { +	childSetValue("status_check", FALSE); +	childSetValue("map_check", FALSE); +	childSetValue("objects_check", FALSE); +  	const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());  	// If true - we are viewing friend's profile, enable check boxes and set values.  	if(relation) diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 3f309b3bf5..a8a75a1feb 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -65,7 +65,11 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked()  void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)  { -	bool is_call_started = ( new_state >= LLVoiceChannel::STATE_CALL_STARTED ); +	updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED); +} + +void LLPanelChatControlPanel::updateButtons(bool is_call_started) +{  	childSetVisible("end_call_btn", is_call_started);  	childSetVisible("voice_ctrls_btn", is_call_started);  	childSetVisible("call_btn", ! is_call_started); @@ -112,6 +116,9 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)  	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() >= LLVoiceChannel::STATE_CALL_STARTED);  	}  } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 711340efc7..c18be5a6df 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -57,6 +57,8 @@ public:  	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); +	void updateButtons(bool is_call_started); +  	virtual void setSessionId(const LLUUID& session_id);  	const LLUUID& getSessionId() { return mSessionId; } diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 5de7c3f851..597b8bdb2d 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -81,7 +81,8 @@ BOOL LLPanelLandmarkInfo::postBuild()  	mCreator = getChild<LLTextBox>("creator");  	mCreated = getChild<LLTextBox>("created"); -	mTitleEditor = getChild<LLLineEditor>("title_editor"); +	mLandmarkTitle = getChild<LLTextBox>("title_value"); +	mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor");  	mNotesEditor = getChild<LLTextEditor>("notes_editor");  	mFolderCombo = getChild<LLComboBox>("folder_combo"); @@ -101,7 +102,8 @@ void LLPanelLandmarkInfo::resetLocation()  	mCreator->setText(not_available);  	mOwner->setText(not_available);  	mCreated->setText(not_available); -	mTitleEditor->setText(LLStringUtil::null); +	mLandmarkTitle->setText(LLStringUtil::null); +	mLandmarkTitleEditor->setText(LLStringUtil::null);  	mNotesEditor->setText(LLStringUtil::null);  } @@ -122,7 +124,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)  		case CREATE_LANDMARK:  			mCurrentTitle = getString("title_create_landmark"); -			mTitleEditor->setEnabled(TRUE); +			mLandmarkTitle->setVisible(FALSE); +			mLandmarkTitleEditor->setVisible(TRUE);  			mNotesEditor->setEnabled(TRUE);  		break; @@ -130,7 +133,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)  		default:  			mCurrentTitle = getString("title_landmark"); -			mTitleEditor->setEnabled(FALSE); +			mLandmarkTitle->setVisible(TRUE); +			mLandmarkTitleEditor->setVisible(FALSE);  			mNotesEditor->setEnabled(FALSE);  		break;  	} @@ -185,12 +189,12 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data)  	{  		if (parcel_data.name.empty())  		{ -			mTitleEditor->setText(llformat("%s (%d, %d, %d)", +			mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)",  								  parcel_data.sim_name.c_str(), region_x, region_y, region_z));  		}  		else  		{ -			mTitleEditor->setText(parcel_data.name); +			mLandmarkTitleEditor->setText(parcel_data.name);  		}  		std::string desc; @@ -281,7 +285,8 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)  		mCreated->setText(timeStr);  	} -	mTitleEditor->setText(pItem->getName()); +	mLandmarkTitle->setText(pItem->getName()); +	mLandmarkTitleEditor->setText(pItem->getName());  	mNotesEditor->setText(pItem->getDescription());  } @@ -296,11 +301,14 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)  	else  	{  		mTitle->setText(mCurrentTitle); + +		mLandmarkTitle->setText(mLandmarkTitleEditor->getText());  	}  	if (mNotesEditor->getReadOnly() ==  (enabled == TRUE))  	{ -		mTitleEditor->setEnabled(enabled); +		mLandmarkTitle->setVisible(!enabled); +		mLandmarkTitleEditor->setVisible(enabled);  		mNotesEditor->setReadOnly(!enabled);  		mFolderCombo->setVisible(enabled);  		getChild<LLTextBox>("folder_label")->setVisible(enabled); @@ -313,7 +321,7 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)  const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const  { -	return mTitleEditor->getText(); +	return mLandmarkTitleEditor->getText();  }  const std::string LLPanelLandmarkInfo::getLandmarkNotes() const @@ -333,7 +341,7 @@ BOOL LLPanelLandmarkInfo::setLandmarkFolder(const LLUUID& id)  void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)  { -	std::string name = mTitleEditor->getText(); +	std::string name = mLandmarkTitleEditor->getText();  	std::string desc = mNotesEditor->getText();  	LLStringUtil::trim(name); diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index 73e0ddb9cc..2a9949ae41 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -77,7 +77,8 @@ private:  	LLTextBox*			mOwner;  	LLTextBox*			mCreator;  	LLTextBox*			mCreated; -	LLLineEditor*		mTitleEditor; +	LLTextBox*			mLandmarkTitle; +	LLLineEditor*		mLandmarkTitleEditor;  	LLTextEditor*		mNotesEditor;  	LLComboBox*			mFolderCombo;  }; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index e16bac2098..87abb16395 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -49,9 +49,9 @@  #include "llfloaterworldmap.h"  #include "llfolderviewitem.h"  #include "llinventorypanel.h" -#include "llinventorysubtreepanel.h"  #include "lllandmarkactions.h"  #include "llplacesinventorybridge.h" +#include "llplacesinventorypanel.h"  #include "llsidetray.h"  #include "llviewermenu.h"  #include "llviewerregion.h" @@ -66,15 +66,54 @@ static const std::string TRASH_BUTTON_NAME = "trash_btn";  // helper functions -static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); -static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list); +static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string); +static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);  /** - * Bridge to support knowing when the inventory has changed to update folder (open/close) state  - * for landmarks panels. - * - * Due to Inventory data are loaded in background we need to save folder state each time  - * next level is loaded. See EXT-3094. + * Functor counting expanded and collapsed folders in folder view tree to know + * when to enable or disable "Expand all folders" and "Collapse all folders" commands. + */ +class LLCheckFolderState : public LLFolderViewFunctor +{ +public: +	LLCheckFolderState() +	:	mCollapsedFolders(0), +		mExpandedFolders(0) +	{} +	virtual ~LLCheckFolderState() {} +	virtual void doFolder(LLFolderViewFolder* folder); +	virtual void doItem(LLFolderViewItem* item) {} +	S32 getCollapsedFolders() { return mCollapsedFolders; } +	S32 getExpandedFolders() { return mExpandedFolders; } + +private: +	S32 mCollapsedFolders; +	S32 mExpandedFolders; +}; + +// virtual +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->isOpen()) +		{ +			++mExpandedFolders; +		} +		else +		{ +			++mCollapsedFolders; +		} +	} +} + +/** + * Bridge to support knowing when the inventory has changed to update Landmarks tab + * ShowFolderState filter setting to show all folders when the filter string is empty and + * empty folder message when Landmarks inventory category has no children.   */  class LLLandmarksPanelObserver : public LLInventoryObserver  { @@ -89,7 +128,7 @@ private:  void LLLandmarksPanelObserver::changed(U32 mask)  { -	mLP->saveFolderStateIfNoFilter(); +	mLP->updateShowFolderState();  }  LLLandmarksPanel::LLLandmarksPanel() @@ -134,22 +173,12 @@ BOOL LLLandmarksPanel::postBuild()  	getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true);  	getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true); -	gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);  	return TRUE;  }  // virtual  void LLLandmarksPanel::onSearchEdit(const std::string& string)  { -	// show all folders in Landmarks Accordion for empty filter -	if (mLandmarksInventoryPanel->getFilter()) -	{ -		mLandmarksInventoryPanel->setShowFolderState(string.empty() ? -			LLInventoryFilter::SHOW_ALL_FOLDERS : -			LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS -			); -	} -  	// give FolderView a chance to be refreshed. So, made all accordions visible  	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)  	{ @@ -162,7 +191,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  			tab->changeOpenClose(false);  		} -		LLInventorySubTreePanel* inventory_list = dynamic_cast<LLInventorySubTreePanel*>(tab->getAccordionView()); +		LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());  		if (NULL == inventory_list) continue;  		if (inventory_list->getFilter()) @@ -173,6 +202,10 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  	if (sFilterSubString != string)  		sFilterSubString = string; + +	// show all folders in Landmarks Accordion for empty filter +	// only if Landmarks inventory folder is not empty +	updateShowFolderState();  }  // virtual @@ -226,7 +259,7 @@ void LLLandmarksPanel::updateVerbs()  	updateListCommands();  } -void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)  {  	if (user_action && (items.size() > 0))  	{ @@ -254,12 +287,21 @@ void LLLandmarksPanel::onSelectorButtonClicked()  	}  } -void LLLandmarksPanel::saveFolderStateIfNoFilter() +void LLLandmarksPanel::updateShowFolderState()  { -	save_folder_state_if_no_filter(mFavoritesInventoryPanel); -	save_folder_state_if_no_filter(mLandmarksInventoryPanel); -	save_folder_state_if_no_filter(mMyInventoryPanel); -	save_folder_state_if_no_filter(mLibraryInventoryPanel); +	if (!mLandmarksInventoryPanel->getFilter()) +		return; + +	bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); +	if (show_all_folders) +	{ +		show_all_folders = category_has_descendents(mLandmarksInventoryPanel); +	} + +	mLandmarksInventoryPanel->setShowFolderState(show_all_folders ? +		LLInventoryFilter::SHOW_ALL_FOLDERS : +		LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS +		);  }  ////////////////////////////////////////////////////////////////////////// @@ -361,7 +403,7 @@ void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)  void LLLandmarksPanel::initFavoritesInventoryPanel()  { -	mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list"); +	mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");  	initLandmarksPanel(mFavoritesInventoryPanel);  	mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems"); @@ -371,7 +413,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel()  void LLLandmarksPanel::initLandmarksInventoryPanel()  { -	mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list"); +	mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list");  	initLandmarksPanel(mLandmarksInventoryPanel); @@ -390,7 +432,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel()  void LLLandmarksPanel::initMyInventoryPanel()  { -	mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list"); +	mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list");  	initLandmarksPanel(mMyInventoryPanel); @@ -399,14 +441,14 @@ void LLLandmarksPanel::initMyInventoryPanel()  void LLLandmarksPanel::initLibraryInventoryPanel()  { -	mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list"); +	mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list");  	initLandmarksPanel(mLibraryInventoryPanel);  	initAccordion("tab_library", mLibraryInventoryPanel);  } -void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list) +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. @@ -430,7 +472,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis  	inventory_list->saveFolderState();  } -void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list)  {  	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name); @@ -440,7 +482,7 @@ void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLIn  	accordion_tab->setDisplayChildren(false);  } -void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list)  {  	bool expanded = param.asBoolean(); @@ -466,7 +508,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInvento  	}  } -void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list) +void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list)  {  	if (inventory_list != mFavoritesInventoryPanel)  	{ @@ -660,7 +702,12 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)  	}  	else if ("collapse_all" == command_name)  	{ -		root_folder->closeAllFolders(); +		root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + +		// The top level folder is invisible, it must be open to +		// display its sub-folders. +		root_folder->openTopLevelFolders(); +		root_folder->arrangeAll();  	}  	else if ( "sort_by_date" == command_name)  	{ @@ -722,6 +769,20 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const  			return false;  	} +	LLCheckFolderState checker; +	rootFolderView->applyFunctorRecursively(checker); + +	// We assume that the root folder is always expanded so we enable "collapse_all" +	// command when we have at least one more expanded folder. +	if (checker.getExpandedFolders() < 2 && "collapse_all" == command_name) +	{ +		return false; +	} + +	if (checker.getCollapsedFolders() < 1 && "expand_all" == command_name) +	{ +		return false; +	}  	if("category" == command_name)  	{ @@ -778,46 +839,6 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)  	}  } -void LLLandmarksPanel::updateFilteredAccordions() -{ -	LLInventoryPanel* inventory_list = NULL; -	LLAccordionCtrlTab* accordion_tab = NULL; -	bool needs_arrange = false; - -	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) -	{ -		accordion_tab = *iter; - -		accordion_tab->setVisible(TRUE); - -		inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView()); -		if (NULL == inventory_list) continue; - -		// This doesn't seem to work correctly.  Disabling for now. -Seraph -		// Enabled to show/hide accordions with/without landmarks. See EXT-2346. (Seth PE) -		LLFolderView* fv = inventory_list->getRootFolder(); - -		// arrange folder view contents to draw its descendants if it has any -		fv->arrangeFromRoot(); - -		bool has_descendants = fv->hasFilteredDescendants(); -		if (!has_descendants) -			needs_arrange = true; - -		accordion_tab->setVisible(has_descendants); - -		//accordion_tab->setVisible(TRUE); -	} - -	// we have to arrange accordion tabs for cases when filter string is less restrictive but -	// all items are still filtered. -	if (needs_arrange) -	{ -		static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion"); -		accordion->arrange(); -	} -} -  /*  Processes such actions: cut/rename/delete/paste actions @@ -926,13 +947,6 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg  	return true;  } -// static -void LLLandmarksPanel::doIdle(void* landmarks_panel) -{ -	LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel; -	panel->updateFilteredAccordions(); -} -  void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)  {  	LLVector3d landmark_global_pos; @@ -1028,10 +1042,10 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)  //////////////////////////////////////////////////////////////////////////  // HELPER FUNCTIONS  ////////////////////////////////////////////////////////////////////////// -static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string) +static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)  {  	// When search is cleared, restore the old folder state. -	if (string == "") +	if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "")  	{  		inventory_list->setFilterSubString(LLStringUtil::null);  		// Re-open folders that were open before @@ -1056,15 +1070,16 @@ static void filter_list(LLInventorySubTreePanel* inventory_list, const std::stri  	// Set new filter string  	inventory_list->setFilterSubString(string); -  } -static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list) +static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)  { -	// save current folder open state if no filter currently applied -	if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty()) +	LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID()); +	if (category)  	{ -		// inventory_list->saveFolderState(); // *TODO: commented out to fix build +		return category->getDescendentCount() > 0;  	} + +	return false;  }  // EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index b0e537f647..569739237d 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -46,7 +46,7 @@ class LLAccordionCtrlTab;  class LLFolderViewItem;  class LLMenuGL;  class LLInventoryPanel; -class LLInventorySubTreePanel; +class LLPlacesInventoryPanel;  class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver  { @@ -60,17 +60,18 @@ public:  	/*virtual*/ void onTeleport();  	/*virtual*/ void updateVerbs(); -	void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);  	void onSelectorButtonClicked(); -	void setCurrentSelectedList(LLInventorySubTreePanel* inventory_list) +	void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list)  	{  		mCurrentSelectedList = inventory_list;  	}  	/** -	 * Saves folder state for all Inventory Panels if there are no applied filter. +	 * 	Update filter ShowFolderState setting to show empty folder message +	 *  if Landmarks inventory folder is empty.  	 */ -	void saveFolderStateIfNoFilter(); +	void updateShowFolderState();  protected:  	/** @@ -92,10 +93,10 @@ private:  	void initLandmarksInventoryPanel();  	void initMyInventoryPanel();  	void initLibraryInventoryPanel(); -	void initLandmarksPanel(LLInventorySubTreePanel* inventory_list); -	void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list); -	void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list); -	void deselectOtherThan(const LLInventorySubTreePanel* inventory_list); +	void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list); +	void initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list); +	void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list); +	void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list);  	// List Commands Handlers  	void initListCommandsHandlers(); @@ -112,13 +113,6 @@ private:  	void onCustomAction(const LLSD& command_name);  	/** -	 * Updates accordions according to filtered items in lists. -	 * -	 * It hides accordion for empty lists -	 */ -	void updateFilteredAccordions(); - -	/**  	 * Determines if selected item can be modified via context/gear menu.  	 *  	 * It validates Places Landmarks rules first. And then LLFolderView permissions. @@ -133,11 +127,6 @@ private:  	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);  	/** -	 * Static callback for gIdleCallbacks to perform actions out of drawing -	 */ -	static void doIdle(void* landmarks_panel); - -	/**  	 * Landmark actions callbacks. Fire when a landmark is loaded from the list.  	 */  	void doShowOnMap(LLLandmark* landmark); @@ -148,14 +137,14 @@ private:  	void doCreatePick(LLLandmark* landmark);  private: -	LLInventorySubTreePanel*	mFavoritesInventoryPanel; -	LLInventorySubTreePanel*	mLandmarksInventoryPanel; -	LLInventorySubTreePanel*	mMyInventoryPanel; -	LLInventorySubTreePanel*	mLibraryInventoryPanel; +	LLPlacesInventoryPanel*	mFavoritesInventoryPanel; +	LLPlacesInventoryPanel*	mLandmarksInventoryPanel; +	LLPlacesInventoryPanel*	mMyInventoryPanel; +	LLPlacesInventoryPanel*	mLibraryInventoryPanel;  	LLMenuGL*					mGearLandmarkMenu;  	LLMenuGL*					mGearFolderMenu;  	LLMenuGL*					mMenuAdd; -	LLInventorySubTreePanel*	mCurrentSelectedList; +	LLPlacesInventoryPanel*	mCurrentSelectedList;  	LLInventoryObserver*		mInventoryObserver;  	LLPanel*					mListCommands; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index e5846c7318..5cc4d4aec6 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -965,6 +965,13 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	mFilterSubString = search_upper; +	//store accordion tabs state before any manipulation with accordion tabs +	if(!mFilterSubString.empty()) +	{ +		notifyChildren(LLSD().with("action","store_state")); +	} + +  	// Apply new filter.  	mNearbyList->setNameFilter(mFilterSubString);  	mOnlineFriendList->setNameFilter(mFilterSubString); @@ -976,6 +983,12 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	setAccordionCollapsedByUser("tab_all", false);  	showFriendsAccordionsIfNeeded(); + +	//restore accordion tabs state _after_ all manipulations... +	if(mFilterSubString.empty()) +	{ +		notifyChildren(LLSD().with("action","restore_state")); +	}  }  void LLPanelPeople::onTabSelected(const LLSD& param) @@ -984,6 +997,8 @@ void LLPanelPeople::onTabSelected(const LLSD& param)  	mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME);  	updateButtons(); +	showFriendsAccordionsIfNeeded(); +  	if (GROUP_TAB_NAME == tab_name)  		mFilterEditor->setLabel(getString("groups_filter_label"));  	else diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 839452d061..7a4dd3569d 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -284,6 +284,7 @@ void LLPanelPickInfo::setPickName(const std::string& name)  void LLPanelPickInfo::setPickDesc(const std::string& desc)  {  	childSetValue(XML_DESC, desc); +	updateContentPanelRect();  }  void LLPanelPickInfo::setPickLocation(const std::string& location) @@ -291,6 +292,31 @@ void LLPanelPickInfo::setPickLocation(const std::string& location)  	childSetValue(XML_LOCATION, location);  } +void LLPanelPickInfo::updateContentPanelRect() +{ +	LLTextBox* desc = getChild<LLTextBox>(XML_DESC); + +	S32 text_height = desc->getTextPixelHeight(); +	LLRect text_rect = desc->getRect(); + +	// let text-box height fit text height +	text_rect.set(text_rect.mLeft, text_rect.mTop, text_rect.mRight, text_rect.mTop - text_height); +	desc->setRect(text_rect); +	desc->reshape(text_rect.getWidth(), text_rect.getHeight()); +	// force reflow +	desc->setText(desc->getText()); + +	// bottom of description text-box will be bottom of content panel +	desc->localRectToOtherView(desc->getLocalRect(), &text_rect, getChild<LLView>("profile_scroll")); + +	LLPanel* content_panel = getChild<LLPanel>("scroll_content_panel"); +	LLRect content_rect = content_panel->getRect(); +	content_rect.set(content_rect.mLeft, content_rect.mTop, content_rect.mRight, text_rect.mBottom); +	// Somehow setRect moves all elements down. +	// Single reshape() updates rect and does not move anything. +	content_panel->reshape(content_rect.getWidth(), content_rect.getHeight()); +} +  void LLPanelPickInfo::onClickMap()  {  	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 95add387d0..12b5a116b4 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -140,6 +140,15 @@ protected:  	virtual LLVector3d& getPosGlobal() { return mPosGlobal; }  	/** +	 * Reshapes content panel to fit all elements. +	 * +	 * Assume that description text-box is the last element of panel. +	 * Reshape text-box to fit text height and then reshape content panel to fit  +	 * text-box bottom. EXT-1326 +	 */ +	void updateContentPanelRect(); + +	/**  	 * Callback for "Map" button, opens Map  	 */  	void onClickMap(); diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 596bd2909a..77c2fb7c8c 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -60,13 +60,18 @@ class LLTeleportHistoryFlatItem : public LLPanel  {  public:  	LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl); -	virtual ~LLTeleportHistoryFlatItem() {}; +	virtual ~LLTeleportHistoryFlatItem();  	virtual BOOL postBuild(); +	/*virtual*/ S32 notify(const LLSD& info); +  	S32 getIndex() { return mIndex; }  	void setIndex(S32 index) { mIndex = index; }  	const std::string& getRegionName() { return mRegionName;} +	void setRegionName(const std::string& name); +	void setHighlightedText(const std::string& text); +	void updateTitle();  	/*virtual*/ void setValue(const LLSD& value); @@ -75,18 +80,51 @@ public:  	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);  	static void showPlaceInfoPanel(S32 index); + +	LLHandle<LLTeleportHistoryFlatItem> getItemHandle()	{ mItemHandle.bind(this); return mItemHandle; } +  private:  	void onProfileBtnClick();  	LLButton* mProfileBtn; +	LLTextBox* mTitle;  	LLTeleportHistoryPanel::ContextMenu *mContextMenu;  	S32 mIndex;  	std::string mRegionName;  	std::string mHighlight; +	LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;  }; +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> { +protected: +	typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t; + +public: +	LLTeleportHistoryFlatItem* getFlatItemForPersistentItem ( +		LLTeleportHistoryPanel::ContextMenu *context_menu, +		const LLTeleportHistoryPersistentItem& persistent_item, +		const S32 cur_item_index, +		const std::string &hl); + +	void removeItem(LLTeleportHistoryFlatItem* item); + +	void purge(); + +private: + +	flat_item_list_t mItems; +}; + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +  LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl)  :	LLPanel(),  	mIndex(index), @@ -97,18 +135,37 @@ LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistor  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml");  } +LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem() +{ +} +  //virtual  BOOL LLTeleportHistoryFlatItem::postBuild()  { -	LLTextUtil::textboxSetHighlightedVal(getChild<LLTextBox>("region"), LLStyle::Params(), mRegionName, mHighlight); +	mTitle = getChild<LLTextBox>("region");  	mProfileBtn = getChild<LLButton>("profile_btn");  	mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this)); +	updateTitle(); +  	return true;  } +S32 LLTeleportHistoryFlatItem::notify(const LLSD& info) +{ +	if(info.has("detach")) +	{ +		delete mMouseDownSignal; +		mMouseDownSignal = NULL; +		delete mRightMouseDownSignal; +		mRightMouseDownSignal = NULL; +		return 1; +	} +	return 0; +} +  void LLTeleportHistoryFlatItem::setValue(const LLSD& value)  {  	if (!value.isMap()) return;; @@ -116,6 +173,25 @@ void LLTeleportHistoryFlatItem::setValue(const LLSD& value)  	childSetVisible("selected_icon", value["selected"]);  } +void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text) +{ +	mHighlight = text; +} + +void LLTeleportHistoryFlatItem::setRegionName(const std::string& name) +{ +	mRegionName = name; +} + +void LLTeleportHistoryFlatItem::updateTitle() +{ +	LLTextUtil::textboxSetHighlightedVal( +		mTitle, +		LLStyle::Params(), +		mRegionName, +		mHighlight); +} +  void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)  {  	childSetVisible("hovered_icon", true); @@ -155,6 +231,82 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick()  	LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);  } +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +LLTeleportHistoryFlatItem* +LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem ( +	LLTeleportHistoryPanel::ContextMenu *context_menu, +	const LLTeleportHistoryPersistentItem& persistent_item, +	const S32 cur_item_index, +	const std::string &hl) +{ +	LLTeleportHistoryFlatItem* item = NULL; +	if ( cur_item_index < (S32) mItems.size() ) +	{ +		item = mItems[cur_item_index].get(); +		if (item->getParent() == NULL) +		{ +			item->setIndex(cur_item_index); +			item->setRegionName(persistent_item.mTitle); +			item->setHighlightedText(hl); +			item->setVisible(TRUE); +			item->updateTitle(); +		} +		else +		{ +			// Item already added to parent +			item = NULL; +		} +	} + +	if ( !item ) +	{ +		item = new LLTeleportHistoryFlatItem(cur_item_index, +											 context_menu, +											 persistent_item.mTitle, +											 hl); +		mItems.push_back(item->getItemHandle()); +	} + +	return item; +} + +void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item) +{ +	if (item) +	{ +		flat_item_list_t::iterator item_iter = std::find(mItems.begin(), +														 mItems.end(), +														 item->getItemHandle()); +		if (item_iter != mItems.end()) +		{ +			mItems.erase(item_iter); +		} +	} +} + +void LLTeleportHistoryFlatItemStorage::purge() +{ +	for ( flat_item_list_t::iterator +			  it = mItems.begin(), +			  it_end = mItems.end(); +		  it != it_end; ++it ) +	{ +		LLHandle <LLTeleportHistoryFlatItem> item_handle = *it; +		if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL ) +		{ +			item_handle.get()->die(); +		} +	} +	mItems.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +  LLTeleportHistoryPanel::ContextMenu::ContextMenu() :  	mMenu(NULL)  { @@ -236,6 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()  LLTeleportHistoryPanel::~LLTeleportHistoryPanel()  { +	LLTeleportHistoryFlatItemStorage::instance().purge();  	LLView::deleteViewByHandle(mGearMenuHandle);  } @@ -478,16 +631,15 @@ void LLTeleportHistoryPanel::refresh()  	while (mCurrentItem >= 0)  	{  		// Filtering -		std::string landmark_title = items[mCurrentItem].mTitle; -		LLStringUtil::toUpper(landmark_title); - -		std::string::size_type match_offset = sFilterSubString.size() ? landmark_title.find(sFilterSubString) : std::string::npos; -		bool passed = sFilterSubString.size() == 0 || match_offset != std::string::npos; - -		if (!passed) +		if (!sFilterSubString.empty())  		{ -			mCurrentItem--; -			continue; +			std::string landmark_title(items[mCurrentItem].mTitle); +			LLStringUtil::toUpper(landmark_title); +			if( std::string::npos == landmark_title.find(sFilterSubString) ) +			{ +				mCurrentItem--; +				continue; +			}  		}  		// Checking whether date of item is earlier, than tab_boundary_date. @@ -507,6 +659,9 @@ void LLTeleportHistoryPanel::refresh()  			// Expand all accordion tabs when filtering  			if(!sFilterSubString.empty())  			{ +				//store accordion tab state when filter is not empty +				tab->notifyChildren(LLSD().with("action","store_state")); +				  				tab->setDisplayChildren(true);  			}  			// Restore each tab's expand state when not filtering @@ -514,6 +669,9 @@ void LLTeleportHistoryPanel::refresh()  			{  				bool collapsed = isAccordionCollapsedByUser(tab);  				tab->setDisplayChildren(!collapsed); +				 +				//restore accordion state after all those accodrion tabmanipulations +				tab->notifyChildren(LLSD().with("action","restore_state"));  			}  			curr_flat_view = getFlatListViewFromTab(tab); @@ -521,9 +679,14 @@ void LLTeleportHistoryPanel::refresh()  		if (curr_flat_view)  		{ -			LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, sFilterSubString); -			curr_flat_view->addItem(item); - +			LLTeleportHistoryFlatItem* item = +				LLTeleportHistoryFlatItemStorage::instance() +				.getFlatItemForPersistentItem(&mContextMenu, +											  items[mCurrentItem], +											  mCurrentItem, +											  sFilterSubString); +			if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) ) +				llerrs << "Couldn't add flat item to teleport history." << llendl;  			if (mLastSelectedItemIndex == mCurrentItem)  				curr_flat_view->selectItem(item, true);  		} @@ -534,6 +697,16 @@ void LLTeleportHistoryPanel::refresh()  			break;  	} +	for (S32 n = mItemContainers.size() - 1; n >= 0; --n) +	{ +		LLAccordionCtrlTab* tab = mItemContainers.get(n); +		LLFlatListView* fv = getFlatListViewFromTab(tab); +		if (fv) +		{ +			fv->notify(LLSD().with("rearrange", LLSD())); +		} +	} +  	mHistoryAccordion->arrange();  	updateVerbs(); @@ -566,11 +739,12 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)  	}  	const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems(); -	LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below -									&mContextMenu, -									history_items[history_items.size() - 1].mTitle, // Most recent item, it was -									sFilterSubString); -															 // added instead of removed +	LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance() +		.getFlatItemForPersistentItem(&mContextMenu, +									  history_items[history_items.size() - 1], // Most recent item, it was added instead of removed +									  history_items.size(), // index will be decremented inside loop below +									  sFilterSubString); +  	fv->addItem(item, LLUUID::null, ADD_TOP);  	// Index of each item, from last to removed item should be decremented @@ -598,6 +772,8 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)  			if (item->getIndex() == removed_index)  			{ +				LLTeleportHistoryFlatItemStorage::instance().removeItem(item); +  				fv->removeItem(item);  				// If flat list becames empty, then accordion tab should be hidden @@ -629,10 +805,12 @@ void LLTeleportHistoryPanel::showTeleportHistory()  		LLFlatListView* fv = getFlatListViewFromTab(tab);  		if (fv) -			fv->clear(); +		{ +			// Detached panels are managed by LLTeleportHistoryFlatItemStorage +			std::vector<LLPanel*> detached_items; +			fv->detachItems(detached_items); +		}  	} - -	refresh();  }  void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 7d5944ea2b..330e220af3 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -57,6 +57,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  	mSortOrder(E_SORT_BY_NAME)  ,	mParticipantListMenu(NULL)  ,	mExcludeAgent(exclude_agent) +,	mValidateSpeakerCallback(NULL)  {  	mSpeakerAddListener = new SpeakerAddListener(*this);  	mSpeakerRemoveListener = new SpeakerRemoveListener(*this); @@ -86,22 +87,23 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  	}  	//Lets fill avatarList with existing speakers -	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); -  	LLSpeakerMgr::speaker_list_t speaker_list;  	mSpeakerMgr->getSpeakerList(&speaker_list, true);  	for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)  	{  		const LLPointer<LLSpeaker>& speakerp = *it; -		addAvatarIDExceptAgent(group_members, speakerp->mID); +		addAvatarIDExceptAgent(speakerp->mID);  		if ( speakerp->mIsModerator )  		{  			mModeratorList.insert(speakerp->mID);  		} +		else +		{ +			mModeratorToRemoveList.insert(speakerp->mID); +		}  	}  	// we need to exclude agent id for non group chat -	mAvatarList->setDirty(true);  	sort();  } @@ -161,7 +163,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)  			{  				std::string name = item->getAvatarName();  				size_t found = name.find(moderator_indicator); -				if (found == std::string::npos) +				if (found != std::string::npos)  				{  					name.erase(found, moderator_indicator_len);  					item->setName(name); @@ -208,10 +210,17 @@ LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()  	return mSortOrder;  } +void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) +{ +	mValidateSpeakerCallback = cb; +} +  void LLParticipantList::updateRecentSpeakersOrder()  {  	if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())  	{ +		// Need to update speakers to sort list correctly +		mSpeakerMgr->update(true);  		// Resort avatar list  		sort();  	} @@ -219,19 +228,14 @@ void LLParticipantList::updateRecentSpeakersOrder()  bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)  { -	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();  	LLUUID uu_id = event->getValue().asUUID(); -	LLAvatarList::uuid_vector_t::iterator found = std::find(group_members.begin(), group_members.end(), uu_id); -	if(found != group_members.end()) +	if (mValidateSpeakerCallback && mValidateSpeakerCallback(uu_id))  	{ -		llinfos << "Already got a buddy" << llendl;  		return true;  	} -	addAvatarIDExceptAgent(group_members, uu_id); -	// Mark AvatarList as dirty one -	mAvatarList->setDirty(); +	addAvatarIDExceptAgent(uu_id);  	sort();  	return true;  } @@ -329,11 +333,13 @@ void LLParticipantList::sort()  	}  } -void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id) +void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)  {  	if (mExcludeAgent && gAgent.getID() == avatar_id) return; +	if (mAvatarList->contains(avatar_id)) return; -	existing_list.push_back(avatar_id); +	mAvatarList->getIDs().push_back(avatar_id); +	mAvatarList->setDirty();  	adjustParticipant(avatar_id);  } @@ -353,7 +359,7 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L  {  	/**  	 * We need to filter speaking objects. These objects shouldn't appear in the list -	 * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy +	 * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy  	 */  	const LLUUID& speaker_id = event->getValue().asUUID();  	LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id); @@ -575,33 +581,46 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&  	{  		return mUUIDs.front() != gAgentID;  	} -	else -		if (item == "can_allow_text_chat" || "can_moderate_voice" == item) +	else if (item == "can_allow_text_chat") +	{ +		return isGroupModerator(); +	} +	else if ("can_moderate_voice" == item) +	{ +		if (isGroupModerator())  		{ -			return isGroupModerator(); +			LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front()); +			if (speakerp.notNull()) +			{ +				// not in voice participants can not be moderated +				return speakerp->mStatus == LLSpeaker::STATUS_VOICE_ACTIVE +					|| speakerp->mStatus == LLSpeaker::STATUS_MUTED; +			}  		} +		return false; +	}  	else if (item == std::string("can_add")) -		{ -			// We can add friends if: -			// - there are selected people -			// - and there are no friends among selection yet. +	{ +		// We can add friends if: +		// - there are selected people +		// - and there are no friends among selection yet. -			bool result = (mUUIDs.size() > 0); +		bool result = (mUUIDs.size() > 0); -			std::vector<LLUUID>::const_iterator -				id = mUUIDs.begin(), -				uuids_end = mUUIDs.end(); +		std::vector<LLUUID>::const_iterator +			id = mUUIDs.begin(), +			uuids_end = mUUIDs.end(); -			for (;id != uuids_end; ++id) +		for (;id != uuids_end; ++id) +		{ +			if ( LLAvatarActions::isFriend(*id) )  			{ -				if ( LLAvatarActions::isFriend(*id) ) -				{ -					result = false; -					break; -				} +				result = false; +				break;  			} -			return result;  		} +		return result; +	}  	else if (item == "can_call")  	{  		return LLVoiceClient::voiceEnabled(); diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index c4eb180917..d15ec980db 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -44,6 +44,9 @@ class LLParticipantList  {  	LOG_CLASS(LLParticipantList);  	public: + +		typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; +  		LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);  		~LLParticipantList();  		void setSpeakingIndicatorsVisible(BOOL visible); @@ -54,6 +57,13 @@ class LLParticipantList  		} EParticipantSortOrder;  		/** +		 * Adds specified avatar ID to the existing list if it is not Agent's ID +		 * +		 * @param[in] avatar_id - Avatar UUID to be added into the list +		 */ +		void addAvatarIDExceptAgent(const LLUUID& avatar_id); + +		/**  		 * Set and sort Avatarlist by given order  		 */  		void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); @@ -64,6 +74,15 @@ class LLParticipantList  		 */  		void updateRecentSpeakersOrder(); +		/** +		 * Set a callback to be called before adding a speaker. Invalid speakers will not be added. +		 * +		 * If the callback is unset all speakers are considered as valid. +		 * +		 * @see onAddItemEvent() +		 */ +		void setValidateSpeakerCallback(validate_speaker_callback_t cb); +  	protected:  		/**  		 * LLSpeakerMgr event handlers @@ -218,14 +237,6 @@ class LLParticipantList  		void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);  		/** -		 * Adds specified avatar ID to the existing list if it is not Agent's ID -		 * -		 * @param[in, out] existing_list - vector with avatars' UUIDs already in the list -		 * @param[in] avatar_id - Avatar UUID to be added into the list -		 */ -		void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id); - -		/**  		 * Adjusts passed participant to work properly.  		 *  		 * Adds SpeakerMuteListener to process moderation actions. @@ -260,4 +271,5 @@ class LLParticipantList  		boost::signals2::connection mAvatarListReturnConnection;  		LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; +		validate_speaker_callback_t mValidateSpeakerCallback;  }; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp new file mode 100644 index 0000000000..4de953a59d --- /dev/null +++ b/indra/newview/llplacesinventorypanel.cpp @@ -0,0 +1,191 @@ +/**  + * @file llplacesinventorypanel.cpp + * @brief LLPlacesInventoryPanel  class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + *  + * Copyright (c) 2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llscrollcontainer.h" + +#include "llplacesinventorypanel.h" + +#include "llfoldervieweventlistener.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llpanellandmarks.h" +#include "llplacesinventorybridge.h" + +static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel"); + +static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER; + +LLPlacesInventoryPanel::LLPlacesInventoryPanel(const Params& p) :  +	LLInventoryPanel(p), +	mSavedFolderState(NULL) + +{ +	mInvFVBridgeBuilder = &PLACES_INVENTORY_BUILDER; +	mSavedFolderState = new LLSaveFolderState(); +	mSavedFolderState->setApply(FALSE); +} + + +LLPlacesInventoryPanel::~LLPlacesInventoryPanel() +{ +	delete mSavedFolderState; +} + +BOOL LLPlacesInventoryPanel::postBuild() +{ +	LLInventoryPanel::postBuild(); + +	// clear Contents(); +	{ +		mFolders->destroyView(); +		mFolders->getParent()->removeChild(mFolders); +		mFolders->die(); + +		if( mScroller ) +		{ +			removeChild( mScroller ); +			mScroller->die(); +			mScroller = NULL; +		} +		mFolders = NULL; +	} + + +	mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves + +	// create root folder +	{ +		LLRect folder_rect(0, +			0, +			getRect().getWidth(), +			0); +		LLPlacesFolderView::Params p; +		p.name = getName(); +		p.rect = folder_rect; +		p.parent_panel = this; +		mFolders = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); +		mFolders->setAllowMultiSelect(mAllowMultiSelect); +	} + +	mCommitCallbackRegistrar.popScope(); + +	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + +	// scroller +	{ +		LLRect scroller_view_rect = getRect(); +		scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +		LLScrollContainer::Params p; +		p.name("Inventory Scroller"); +		p.rect(scroller_view_rect); +		p.follows.flags(FOLLOWS_ALL); +		p.reserve_scroll_corner(true); +		p.tab_stop(true); +		mScroller = LLUICtrlFactory::create<LLScrollContainer>(p); +	} +	addChild(mScroller); +	mScroller->addChild(mFolders); + +	mFolders->setScrollContainer(mScroller); + + +	// cut subitems +	mFolders->setUseEllipses(true); + +	return TRUE; +} + +// save current folder open state +void LLPlacesInventoryPanel::saveFolderState() +{ +	mSavedFolderState->setApply(FALSE); +	getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +} + +// re-open folders which state was saved +void LLPlacesInventoryPanel::restoreFolderState() +{ +	mSavedFolderState->setApply(TRUE); +	getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +	LLOpenFoldersWithSelection opener; +	getRootFolder()->applyFunctorRecursively(opener); +	getRootFolder()->scrollToShowSelection(); +} + +/************************************************************************/ +/* PROTECTED METHODS                                                    */ +/************************************************************************/ + + + +/************************************************************************/ +/*              LLPlacesFolderView implementation                       */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +//  PUBLIC METHODS +////////////////////////////////////////////////////////////////////////// + +BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ +	// let children to change selection first +	childrenHandleRightMouseDown(x, y, mask); +	mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel()); + +	// then determine its type and set necessary menu handle +	if (getCurSelectedItem()) +	{ +		LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); +		inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); + +		if (it_handle != mMenuHandlesByInventoryType.end()) +		{ +			mPopupMenuHandle = (*it_handle).second; +		} +		else +		{ +			llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl; +		} + +	} + +	return LLFolderView::handleRightMouseDown(x, y, mask); +} + +void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle) +{ +	mMenuHandlesByInventoryType[asset_type] = menu_handle; +} + +// EOF diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h new file mode 100644 index 0000000000..7b34045d32 --- /dev/null +++ b/indra/newview/llplacesinventorypanel.h @@ -0,0 +1,96 @@ +/**  + * @file llplacesinventorypanel.h + * @brief LLPlacesInventoryPanel class declaration + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + *  + * Copyright (c) 2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYSUBTREEPANEL_H +#define LL_LLINVENTORYSUBTREEPANEL_H + +#include "llfloaterinventory.h" +#include "llinventorypanel.h" +#include "llfolderview.h" + +class LLLandmarksPanel; + +class LLPlacesInventoryPanel : public LLInventoryPanel +{ +public: +	struct Params  +		:	public LLInitParam::Block<Params, LLInventoryPanel::Params> +	{ +		Params() +		{} +	}; + +	LLPlacesInventoryPanel(const Params& p); +	~LLPlacesInventoryPanel(); + +	/*virtual*/ BOOL postBuild(); + +	void saveFolderState(); +	void restoreFolderState(); + +private: +	LLSaveFolderState*			mSavedFolderState; +}; + + +class LLPlacesFolderView : public LLFolderView +{ +public: +	LLPlacesFolderView(const LLFolderView::Params& p) : LLFolderView(p) {}; +	/** +	 *	Handles right mouse down +	 * +	 * Contains workaround for EXT-2786: sets current selected list for landmark +	 * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel +	 */ +	/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + +	void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle); + +	void setParentLandmarksPanel(LLLandmarksPanel* panel) +	{ +		mParentLandmarksPanel = panel; +	} + +	S32 getSelectedCount() { return (S32)mSelectedItems.size(); } + +private: +	/** +	 * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown +	 */ +	LLLandmarksPanel* mParentLandmarksPanel; +	typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t; +	inventory_type_menu_handle_t mMenuHandlesByInventoryType; + +}; + +#endif //LL_LLINVENTORYSUBTREEPANEL_H diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index c18fe8ad7e..8c3f3dc5fb 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -462,6 +462,8 @@ void LLScreenChannel::showToastsBottom()  	S32		toast_margin = 0;  	std::vector<ToastElem>::reverse_iterator it; +	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); +  	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)  	{  		if(it != mToastList.rbegin()) @@ -474,6 +476,16 @@ void LLScreenChannel::showToastsBottom()  		toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight());  		(*it).toast->setRect(toast_rect); +		// don't show toasts if there is not enough space +		if(floater && floater->overlapsScreenChannel()) +		{ +			LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); +			if(toast_rect.mTop + getOverflowToastHeight() + toast_margin > world_rect.mTop) +			{ +				break; +			} +		} +  		bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;  		if(!stop_showing_toasts) @@ -575,6 +587,18 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)  	toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());	  	mOverflowToastPanel->setRect(toast_rect); +	// don't show overflow toast if there is not enough space for it. +	LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get()); +	if(floater && floater->overlapsScreenChannel()) +	{ +		LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); +		if(toast_rect.mTop > world_rect.mTop) +		{ +			closeOverflowToastPanel(); +			return; +		} +	} +  	text_box->setValue(text);  	text_box->setVisible(TRUE); @@ -664,6 +688,24 @@ F32 LLScreenChannel::getHeightRatio()  	return ratio;  } +S32 LLScreenChannel::getOverflowToastHeight() +{ +	if(mOverflowToastPanel) +	{ +		return mOverflowToastPanel->getRect().getHeight(); +	} + +	static S32 height = 0; +	if(0 == height) +	{ +		LLToast::Params p; +		LLToast* toast = new LLToast(p); +		height = toast->getRect().getHeight(); +		delete toast; +	} +	return height; +} +  //--------------------------------------------------------------------------  void LLScreenChannel::updateStartUpString(S32 num)  { @@ -822,25 +864,22 @@ void LLScreenChannel::updateShowToastsState()  		return;  	} -	// for Message Well floater showed in a docked state - adjust channel's height -	if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater) -		|| dynamic_cast<LLScriptFloater*>(floater)) +	S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; +	LLRect this_rect = getRect(); + +	// adjust channel's height +	if(floater->overlapsScreenChannel())  	{ -		S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");; -		LLRect this_rect = getRect(); -		if(floater->getVisible() && floater->isDocked()) +		channel_bottom += floater->getRect().getHeight(); +		if(floater->getDockControl())  		{ -			channel_bottom += floater->getRect().getHeight(); -			if(floater->getDockControl()) -			{ -				channel_bottom += floater->getDockControl()->getTongueHeight(); -			} +			channel_bottom += floater->getDockControl()->getTongueHeight();  		} +	} -		if(channel_bottom != this_rect.mBottom) -		{ -			setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom)); -		} +	if(channel_bottom != this_rect.mBottom) +	{ +		setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));  	}  } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 321fb244a1..38f27f756b 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -281,6 +281,8 @@ private:  	 */  	static F32 getHeightRatio(); +	S32 getOverflowToastHeight(); +  	// Channel's flags  	static bool	mWasStartUpToastShown; diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 1962d871a6..cf62d47362 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -67,6 +67,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key)  , mScriptForm(NULL)  {  	setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this)); +	setOverlapsScreenChannel(true);  }  bool LLScriptFloater::toggle(const LLUUID& object_id) diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index 90214a1bd7..8f2c877c7a 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -123,7 +123,7 @@ LLSpeakButton::LLSpeakButton(const Params& p)  	mOutputMonitor->setIsAgentControl(true);  	//*TODO find a better place to do that -	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1)); +	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);  }  LLSpeakButton::~LLSpeakButton() diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 91b417c61f..010dfd1b33 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -615,6 +615,9 @@ private:  void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)  { +	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); +	if (!speakerp) return; +  	std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");  	LLSD data;  	data["method"] = "mute update"; @@ -623,7 +626,7 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)  	data["params"]["agent_id"] = speaker_id;  	data["params"]["mute_info"] = LLSD::emptyMap();  	//current value represents ability to type, so invert -	data["params"]["mute_info"]["text"] = !findSpeaker(speaker_id)->mModeratorMutedText; +	data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText;  	LLHTTPClient::post(url, data, new ModerationResponder(getSessionID()));  } diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 8c6ea59407..bcaefc3690 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -63,6 +63,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key)  {  	mTypedItemsCount[IT_NOTIFICATION] = 0;  	mTypedItemsCount[IT_INSTANT_MESSAGE] = 0; +	setOverlapsScreenChannel(true);  }  //--------------------------------------------------------------------------------- @@ -743,9 +744,13 @@ BOOL LLIMWellWindow::postBuild()  void LLIMWellWindow::sessionAdded(const LLUUID& session_id,  								   const std::string& name, const LLUUID& other_participant_id)  { -	if (mMessageList->getItemByValue(session_id)) return; +	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); +	if (!session) return; + +	// no need to spawn chiclets for participants in P2P calls called through Avaline +	if (session->isP2P() && session->isOtherParticipantAvaline()) return; -	if (!gIMMgr->hasSession(session_id)) return; +	if (mMessageList->getItemByValue(session_id)) return;  	addIMRow(session_id, 0, name, other_participant_id);	  	reshapeWindow(); diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index c48301fa1e..c3ccb9380b 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -279,7 +279,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  			mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());  			mLineEditor->setRect(leditor_rect);  			mLineEditor->setText(edit_text_contents); -			mLineEditor->setMaxTextLength(STD_STRING_STR_LEN); +			mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);  			// make sure all edit keys get handled properly (DEV-22396)  			mLineEditor->setHandleEditKeysDirectly(TRUE); @@ -385,6 +385,12 @@ BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask )  {  	if( KEY_RETURN == key && mask == MASK_NONE )  	{ +		LLButton* defaultBtn = getDefaultButton(); +		if(defaultBtn && defaultBtn->getVisible() && defaultBtn->getEnabled()) +		{ +			// If we have a default button, click it when return is pressed +			defaultBtn->onCommit(); +		}  		return TRUE;  	}  	else if (KEY_RIGHT == key) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 1676cc782c..87045d2abf 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -906,6 +906,18 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f  				  LLFloaterReg::showInstance("preview_texture", LLSD(item_id), take_focus);  				  break;  			  } +			  case LLAssetType::AT_ANIMATION: +				  LLFloaterReg::showInstance("preview_anim", LLSD(item_id), take_focus); +				  break; +			  case LLAssetType::AT_GESTURE: +				  LLFloaterReg::showInstance("preview_gesture", LLSD(item_id), take_focus); +				  break; +			  case LLAssetType::AT_SCRIPT: +				  LLFloaterReg::showInstance("preview_script", LLSD(item_id), take_focus); +				  break; +			  case LLAssetType::AT_SOUND: +				  LLFloaterReg::showInstance("preview_sound", LLSD(item_id), take_focus); +				  break;  			  default:  				break;  			} @@ -1146,9 +1158,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		default:  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break; -		}	// end switch (mIM) -			 -		// Show falls through to accept. +		} +		break; +		// end switch (mIM)  	case IOR_ACCEPT:  		msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); @@ -1837,7 +1849,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			// This is a block, modeless dialog.  			//*TODO: Translate  			args["MESSAGE"] = message; -			LLNotificationsUtil::add("SystemMessage", args); +			LLNotificationsUtil::add("SystemMessageTip", args);  		}  		break;  	case IM_GROUP_NOTICE: diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 69d2458217..993853b9a6 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -446,6 +446,17 @@ void LLVoiceChannel::resume()  	}  } +boost::signals2::connection LLVoiceChannel::setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front) +{ +	if (at_front) +	{ +		return sCurrentVoiceChannelChangedSignal.connect(cb,  boost::signals2::at_front); +	} +	else +	{ +		return sCurrentVoiceChannelChangedSignal.connect(cb); +	} +}  //  // LLVoiceChannelGroup diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 77801142cb..cb86671305 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -64,7 +64,7 @@ public:  	typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t;  	typedef boost::signals2::signal<void(const LLUUID& session_id)> channel_changed_signal_t;  	static channel_changed_signal_t sCurrentVoiceChannelChangedSignal; -	static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb) { return sCurrentVoiceChannelChangedSignal.connect(cb); } +	static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front = false);  	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index cfa1f05ec0..c2d26a1971 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -4443,6 +4443,33 @@ void LLVoiceClient::participantUpdatedEvent(  				participant->mPower = 0.0f;  			}  			participant->mVolume = volume; + +			 +			// *HACH: mantipov: added while working on EXT-3544 +			/* +			Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE  +			LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER. +			 +			participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted +			Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug. +			Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates. +			 +			But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post() +			voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager +			and event is not fired. + +			So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it +			in LLCallFloater::draw() +			*/ +			LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel(); +			if (voice_cnl) +			{ +				LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID()); +				if (speaker_manager) +				{ +					speaker_manager->update(true); +				} +			}  		}  		else  		{ diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 706245a479..cb511c2f0b 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -102,6 +102,24 @@       name="AvatarNameColor"       reference="White" />      <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="BackgroundChatColor"       reference="DkGray_66" />      <color diff --git a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpgBinary files differ new file mode 100644 index 0000000000..3bb7f7183c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 8a9126208a..95db84cb32 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -70,6 +70,8 @@ with the same filename but different name    <texture name="Audio_Over" file_name="icons/Audio_Over.png" preload="false" />    <texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" /> +  <texture name="Avaline_Icon" file_name="icons/avaline_default_icon.jpg" preload="true" /> +      <texture name="BackArrow_Disabled" file_name="icons/BackArrow_Disabled.png" preload="false" />    <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" />    <texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index 81c54ae55e..b9ce11600f 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -11,6 +11,10 @@   title="UNKNOWN PERSON IS CALLING"   width="410">      <floater.string +     name="lifetime"> +        5 +    </floater.string> +    <floater.string       name="localchat">          Nearby Voice Chat      </floater.string> diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index 58ba346e50..920f0c909a 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -16,6 +16,7 @@   can_dock="true"   bevel_style="in"   height="300" + min_width="150"   layout="topleft"   name="nearby_chat"   help_topic="nearby_chat" diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml index c6bc093c6c..104ac2143f 100644 --- a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml +++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml @@ -11,6 +11,10 @@   title="CALLING"   width="410">      <floater.string +     name="lifetime"> +        5 +    </floater.string> +    <floater.string       name="localchat">          Nearby Voice Chat      </floater.string> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index ec54522d3e..a36a1b591b 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -9,6 +9,7 @@   name="Snapshot"   help_topic="snapshot"   save_rect="true" + save_visibility="true"   title="SNAPSHOT PREVIEW"   width="215">      <floater.string diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml index c849188699..9b3948b29b 100644 --- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml +++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml @@ -104,6 +104,9 @@          <on_click           function="Places.LandmarksGear.Folding.Action"           parameter="expand_all" /> +        <on_enable +         function="Places.LandmarksGear.Enable" +         parameter="expand_all" />      </menu_item_call>      <menu_item_call       label="Collapse all folders" @@ -112,6 +115,9 @@          <on_click           function="Places.LandmarksGear.Folding.Action"           parameter="collapse_all" /> +        <on_enable +         function="Places.LandmarksGear.Enable" +         parameter="collapse_all" />      </menu_item_call>      <menu_item_check       label="Sort by Date" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d4b712e048..9d3c31c4e6 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4498,14 +4498,14 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryAccepted" -   type="offer"> +   type="notifytip">  [NAME] received your inventory offer.    </notification>    <notification     icon="notifytip.tga"     name="InventoryDeclined" -   type="offer"> +   type="notifytip">  [NAME] declined your inventory offer.    </notification> @@ -5022,9 +5022,9 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O  [ITEM_SLURL]      <form name="form">        <button -       index="0" -       name="Keep" -       text="Keep"/> +       index="4" +       name="Show" +       text="Show"/>        <button         index="1"         name="Discard" @@ -5106,7 +5106,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O    <notification     icon="notify.tga"     name="OfferFriendship" -   type="offer"> +   type="alertmodal">  [NAME] is offering friendship.  [MESSAGE] diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 5ae808581d..00eba94f47 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -227,16 +227,20 @@              <button  			 follows="left|right"               height="23" +             image_selected="PushButton_Selected_Press" +             image_pressed="PushButton_Press" +             image_pressed_selected="PushButton_Selected_Press"               left="0"               label=""               layout="topleft"               name="snapshots"               width="36"               top="4" +             is_toggle="true"               image_overlay="Snapshot_Off"               tool_tip="Take snapshot"> -				<button.commit_callback -				 function="Floater.Toggle" +				<button.init_callback +				 function="Button.SetFloaterToggle"  				 parameter="snapshot" />  			</button>  		</layout_panel> @@ -248,7 +252,7 @@           top="0"           name="chiclet_list_panel"           width="189" -         min_width="180" +         min_width="100"           user_resize="false"           auto_resize="true">  <!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same @@ -259,7 +263,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.               height="23"               layout="topleft"               left="1" -             min_width="180" +             min_width="110"               name="chiclet_list"               top="6"               chiclet_padding="4" diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index 859822dd81..39c4923f12 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -28,7 +28,7 @@        height="12"        layout="topleft"        left_pad="5" -      right="-60" +      right="-120"        name="user_name"        text_color="white"        bg_readonly_color="black" @@ -46,5 +46,5 @@       right="-5"       top="8"           value="23:30" -         width="50" /> +         width="110" />  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml index b5760e977f..1fbf7abda9 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -103,6 +103,7 @@           top_pad="2"           max_length="63"           name="classified_name" +         prevalidate_callback="ascii"           text_color="black"           width="290" />          <text diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index 9f06e64560..744ee43f57 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -228,6 +228,16 @@                   top_pad="10"                   value="Title:"                   width="290" /> +                <text +                 follows="left|top" +                 height="22" +                 layout="topleft" +                 left="0" +                 name="title_value" +                 text_color="white" +                 top_pad="5" +                 use_ellipses="true" +                 width="290" />                   <line_editor                   background_image_disabled="task_panel_background.png"                   follows="left|top|right" @@ -238,7 +248,7 @@                   name="title_editor"                   prevalidate_callback="ascii"                   text_readonly_color="white" -                 top_pad="5" +                 top_delta="0"                   width="290" />                  <text                   follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 1f211c0fed..c899dcb750 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -23,7 +23,7 @@           layout="topleft"           name="tab_favorites"           title="Favorites bar"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" @@ -39,7 +39,7 @@           layout="topleft"           name="tab_landmarks"           title="Landmarks"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" @@ -55,7 +55,7 @@           layout="topleft"           name="tab_inventory"           title="My Inventory"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" @@ -71,7 +71,7 @@             layout="topleft"             name="tab_library"             title="Library"> -            <inventory_subtree_panel +            <places_inventory_panel               allow_multi_select="true"               border="true"               bottom="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 32eae9d11d..447901f984 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2907,7 +2907,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].      Joining voice call...    </string>    <string name="connected-im"> -    Connected, click End Call to hang up +    Connected, click Leave Call to hang up    </string>    <string name="hang_up-im">      Left voice call @@ -2990,6 +2990,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].    <string name="mute">      Error while moderating.    </string> +  <!--Some times string name is getting from the body of server response. +  For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.  +  In case of the EXT-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name. +  So, let add string with name="removed" with the same value as "removed_from_group" --> +  <string name="removed"> +    You have been removed from the group. +  </string>    <string name="removed_from_group">      You have been removed from the group.    </string> diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml new file mode 100644 index 0000000000..7cb973f4c8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_adhoc + font="SansSerif" + height="25" + name="im_adhoc_chiclet" + show_speaker="false" + width="25"> +    <chiclet_im_adhoc.speaker +     auto_update="true" +     draw_border="false" +     height="25" +     left="25" +     name="speaker" +     visible="false" +     width="20"/> +    <chiclet_im_adhoc.avatar_icon +     follows="left|top|bottom" +     height="22" +     mouse_opaque="true" +     name="adhoc_icon" +     width="22"/> +    <chiclet_im_adhoc.unread_notifications +     font="SansSerif" +     font_halign="center" +     height="25" +     left="25" +     mouse_opaque="false" +     name="unread" +     text_color="white" +     v_pad="5" +     visible="false" +     width="20"/> +    <chiclet_im_adhoc.new_message_icon +     bottom="12" +     height="13" +     image_name="Unread_IM" +     left="12" +     name="new_message_icon" +     visible="false" +     width="13" /> +</chiclet_im_adhoc>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml new file mode 100644 index 0000000000..a9b567225e --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_group + font="SansSerif" + height="25" + name="im_group_chiclet" + show_speaker="false" + width="25"> +    <chiclet_im_group.speaker +     auto_update="true" +     draw_border="false" +     height="25" +     left="25" +     name="speaker" +     visible="false" +     width="20"/> +    <chiclet_im_group.group_icon +     default_icon="Generic_Group" +     follows="left|top|bottom" +     height="22" +     mouse_opaque="true" +     name="group_icon" +     width="22"/> +    <chiclet_im_group.unread_notifications +     height="25" +     font="SansSerif" +     font_halign="center" +     left="25" +     mouse_opaque="false" +     name="unread" +     text_color="white" +     v_pad="5" +     visible="false" +     width="20"/> +    <chiclet_im_group.new_message_icon +     bottom="12" +     height="13" +     image_name="Unread_IM" +     left="12" +     name="new_message_icon" +     visible="false" +     width="13" /> +</chiclet_im_group>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml new file mode 100644 index 0000000000..9283594a4c --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_im_p2p + font="SansSerif" + height="25" + name="im_p2p_chiclet" + show_speaker="false" + width="25"> +    <chiclet_im_p2p.speaker +     auto_update="true" +     draw_border="false" +     height="25" +     left="25" +     name="speaker" +     visible="false" +     width="20"/> +    <chiclet_im_p2p.avatar_icon +     follows="left|top|bottom" +     height="22" +     mouse_opaque="true" +     name="avatar_icon" +     width="22"/> +    <chiclet_im_p2p.unread_notifications +     height="25" +     font="SansSerif" +     font_halign="center" +     left="25" +     mouse_opaque="false" +     name="unread" +     text_color="white" +     v_pad="5" +     visible="false" +     width="20"/> +    <chiclet_im_p2p.new_message_icon +     bottom="12" +     height="13" +     image_name="Unread_IM" +     left="12" +     name="new_message_icon" +     visible="false" +     width="13" /> +</chiclet_im_p2p>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml new file mode 100644 index 0000000000..5a22563758 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_offer + font="SansSerif" + height="25" + name="offer_chiclet" + width="25"> + <chiclet_offer.icon +  default_icon="Generic_Object_Small"  +  follows="all" +  height="22" +  mouse_opaque="false" +  name="chiclet_icon" +  width="22"/> + <chiclet_offer.new_message_icon +  bottom="12" +  height="13" +  image_name="Unread_IM" +  left="12" +  name="new_message_icon" +  visible="false" +  width="13" /> +</chiclet_offer>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml new file mode 100644 index 0000000000..f3207ddeae --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_panel + name="chiclet_panel"  + chiclet_padding="3" + scrolling_offset="40" + scroll_button_hpad="5" + scroll_ratio="10" + min_width="180" + />
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml index e5af961a56..05a23b95f9 100644 --- a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml +++ b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml @@ -1,10 +1,22 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 -<chiclet_script
 - name="script_chiclet"
 - font="SansSerif">
 - <icon
 -  name="chiclet_icon"
 -  follows="all"
 -  mouse_opaque="false"
 -  image_name="Generic_Object_Small" />
 -</expandable_text>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<chiclet_script + font="SansSerif" + height="25" + name="script_chiclet" + width="25"> + <chiclet_script.icon +  follows="all" +  height="22" +  image_name="Generic_Object_Small"  +  mouse_opaque="false" +  name="chiclet_icon" +  width="22"/> + <chiclet_script.new_message_icon +  bottom="12" +  height="13" +  image_name="Unread_IM" +  left="12" +  name="new_message_icon" +  visible="false" +  width="13" /> +</chiclet_script>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml index 21b957d089..9d71ceca2f 100644 --- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml +++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml @@ -1,9 +1,13 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <output_monitor +  draw_border="true" +  follows="top|left"    image_mute="Parcel_VoiceNo_Light"    image_off="VoicePTT_Off"    image_on="VoicePTT_On"    image_level_1="VoicePTT_Lvl1"    image_level_2="VoicePTT_Lvl2"    image_level_3="VoicePTT_Lvl3" +  mouse_opaque="false" +  name="output_monitor"    /> | 
