diff options
| author | Ychebotarev ProductEngine <ychebotarev@productengine.com> | 2010-01-22 15:26:20 +0200 | 
|---|---|---|
| committer | Ychebotarev ProductEngine <ychebotarev@productengine.com> | 2010-01-22 15:26:20 +0200 | 
| commit | a63a1afea649433ae5e50b668fcdd6b43df93c40 (patch) | |
| tree | cae7775867ccf342a38b9cd6520e0181e1c2c495 | |
| parent | 682fd146b0978363e6264569c74e018f0cb971fa (diff) | |
| parent | 951d6e9d8ce636ae01aab37f7e67c7389ebcea11 (diff) | |
merge
--HG--
branch : product-engine
36 files changed, 657 insertions, 127 deletions
| diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index e9f6288f44..9ce8ce8d55 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -1022,6 +1022,20 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a  	}  } +void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color) +{ +	if (image_id.isNull()) +	{ +		mImageOverlay = NULL; +	} +	else +	{ +		mImageOverlay = LLUI::getUIImageByID(image_id); +		mImageOverlayAlignment = alignment; +		mImageOverlayColor = color; +	} +} +  void LLButton::onMouseCaptureLost()  {  	resetMouseDownTimer(); diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 5e28b8cdff..cd149e3113 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -200,6 +200,7 @@ public:  	void			setDisabledSelectedLabelColor( const LLColor4& c )	{ mDisabledSelectedLabelColor = c; }  	void			setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); +	void 			setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);  	LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }  	void            autoResize();	// resize with label of current btn state  diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 327dd01612..43c44f2253 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1507,6 +1507,37 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L  	}  } +void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color) +{ +	static LLUICachedControl<S32> tab_padding ("UITabPadding", 0); +	LLTabTuple* tuple = getTabByPanel(child); +	if( tuple ) +	{ +		tuple->mButton->setImageOverlay(image_id, LLFontGL::RIGHT, color); + +		if (!mIsVertical) +		{ +			// remove current width from total tab strip width +			mTotalTabWidth -= tuple->mButton->getRect().getWidth(); + +			S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? +				tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : +				0; + +			tuple->mPadding = image_overlay_width; + +			tuple->mButton->setRightHPad(6); +			tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), +									tuple->mButton->getRect().getHeight()); +			// add back in button width to total tab strip width +			mTotalTabWidth += tuple->mButton->getRect().getWidth(); + +			// tabs have changed size, might need to scroll to see current tab +			updateMaxScrollPos(); +		} +	} +} +  void LLTabContainer::setTitle(const std::string& title)  {	  	if (mTitleBox) diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 5d0f194bf9..33c49e0d6f 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -172,6 +172,7 @@ public:  	BOOL        getTabPanelFlashing(LLPanel* child);  	void		setTabPanelFlashing(LLPanel* child, BOOL state);  	void 		setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white); +	void 		setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);  	void		setTitle( const std::string& title );  	const std::string getPanelTitle(S32 index); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a4fc095727..c29a3a0035 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10070,6 +10070,18 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>SpeakerParticipantRemoveDelay</key> +    <map> +      <key>Comment</key> +      <string>Timeout to remove participants who is not in channel before removed from list of active speakers (text/voice chat)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>F32</string> +      <key>Value</key> +      <real>10.0</real> +    </map> +      <key>UseStartScreen</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 8da207f887..f1de4e2982 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1272,6 +1272,7 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)  		chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));  		arrange(); +		LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);  		return true;  	} @@ -1299,6 +1300,7 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)  	mChicletList.erase(it);  	arrange(); +	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);  	chiclet->die();  } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 4789adb604..73597e7de3 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -110,6 +110,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  		}  	}  	setOverlapsScreenChannel(true); + +	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);  }  void LLIMFloater::onFocusLost() @@ -228,6 +230,7 @@ void LLIMFloater::sendMsg()  LLIMFloater::~LLIMFloater()  { +	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);  }  //virtual @@ -351,13 +354,15 @@ void* LLIMFloater::createPanelAdHocControl(void* userdata)  void LLIMFloater::onSlide()  { -	LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel"); -	im_control_panel->setVisible(!im_control_panel->getVisible()); +	mControlPanel->setVisible(!mControlPanel->getVisible()); + +	gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getVisible()); -	gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible()); +	getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getVisible()); +	getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getVisible()); -	getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible()); -	getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible()); +	LLLayoutStack* stack = getChild<LLLayoutStack>("im_panels"); +	if (stack) stack->setAnimate(true);  }  //static @@ -511,14 +516,14 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  	if(!isChatMultiTab())  	{  		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (floater && floater->getVisible()) +		if (floater && floater->getVisible() && floater->hasFocus())  		{  			// clicking on chiclet to close floater just hides it to maintain existing  			// scroll/text entry state  			floater->setVisible(false);  			return false;  		} -		else if(floater && !floater->isDocked()) +		else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))  		{  			floater->setVisible(TRUE);  			floater->setFocus(TRUE); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index d9db385d06..0ca0325451 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -116,6 +116,8 @@ public:  	static void onIMChicletCreated(const LLUUID& session_id); +	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } +  private:  	// process focus events to set a currently active session  	/* virtual */ void onFocusLost(); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6cc985aef4..06a7b4a29c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -35,19 +35,22 @@  #include "llimfloatercontainer.h"  #include "llfloaterreg.h" +#include "llimview.h" +#include "llavatariconctrl.h" +#include "llagent.h"  //  // LLIMFloaterContainer  //  LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -:	LLMultiFloater(seed), -	mActiveVoiceFloater(NULL) +:	LLMultiFloater(seed)  {  	mAutoResize = FALSE;  }  LLIMFloaterContainer::~LLIMFloaterContainer()  { +	LLGroupMgr::getInstance()->removeObserver(this);  }  BOOL LLIMFloaterContainer::postBuild() @@ -87,13 +90,84 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  	LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); -	// make sure active voice icon shows up for new tab -	if (floaterp == mActiveVoiceFloater) +	LLUUID session_id = floaterp->getKey(); + +	if(gAgent.isInGroup(session_id)) +	{ +		mSessions[session_id] = floaterp; +		mID = session_id; +		mGroupID.push_back(session_id); +		LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(session_id); +		LLGroupMgr* gm = LLGroupMgr::getInstance(); +		gm->addObserver(this); + +		if (group_data && group_data->mInsigniaID.notNull()) +		{ +			mTabContainer->setTabImage(get_ptr_in_map(mSessions, session_id), group_data->mInsigniaID); +		} +		else +		{ +			gm->sendGroupPropertiesRequest(session_id); +		} +	} +	else +	{ +		LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id); +		LLAvatarPropertiesProcessor& app = LLAvatarPropertiesProcessor::instance(); +		app.addObserver(avatar_id, this); +		floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, avatar_id)); +		mSessions[avatar_id] = floaterp; + +		LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(avatar_id); +		if(!icon_id_ptr) +		{ +			app.sendAvatarPropertiesRequest(avatar_id); +		} +		else +		{ +			mTabContainer->setTabImage(floaterp, *icon_id_ptr); +		} +	} +} + +void LLIMFloaterContainer::processProperties(void* data, enum EAvatarProcessorType type) +{ +	if (APT_PROPERTIES == type) +	{ +			LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); +			if (avatar_data) +			{ +				LLUUID avatar_id = avatar_data->avatar_id; +				if(avatar_data->image_id != *LLAvatarIconIDCache::getInstance()->get(avatar_id)) +				{ +					LLAvatarIconIDCache::getInstance()->add(avatar_id,avatar_data->image_id); +				} +				mTabContainer->setTabImage(get_ptr_in_map(mSessions, avatar_id), avatar_data->image_id); +			} +	} +} + +void LLIMFloaterContainer::changed(LLGroupChange gc) +{ +	if (GC_PROPERTIES == gc)  	{ -		mTabContainer->setTabImage(floaterp, "active_voice_tab.tga");	 +		for(groupIDs_t::iterator it = mGroupID.begin(); it!=mGroupID.end(); it++) +		{ +			LLUUID group_id = *it; +			LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id); +			if (group_data && group_data->mInsigniaID.notNull()) +			{ +				mTabContainer->setTabImage(get_ptr_in_map(mSessions, group_id), group_data->mInsigniaID); +			} +		}  	}  } +void LLIMFloaterContainer::onCloseFloater(LLUUID id) +{ +	LLAvatarPropertiesProcessor::instance().removeObserver(id, this); +} +  LLIMFloaterContainer* LLIMFloaterContainer::findInstance()  {  	return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container"); diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index d4a542dfc2..1333b098bc 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -33,12 +33,17 @@  #ifndef LL_LLIMFLOATERCONTAINER_H  #define LL_LLIMFLOATERCONTAINER_H +#include <map> +#include <vector> +  #include "llfloater.h"  #include "llmultifloater.h" +#include "llavatarpropertiesprocessor.h" +#include "llgroupmgr.h"  class LLTabContainer; -class LLIMFloaterContainer : public LLMultiFloater +class LLIMFloaterContainer : public LLMultiFloater, public LLAvatarPropertiesObserver, public LLGroupMgrObserver  {  public:  	LLIMFloaterContainer(const LLSD& seed); @@ -51,15 +56,23 @@ public:  								BOOL select_added_floater,   								LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); +	void processProperties(void* data, EAvatarProcessorType type); +	void changed(LLGroupChange gc); +  	static LLFloater* getCurrentVoiceFloater();  	static LLIMFloaterContainer* findInstance();  	static LLIMFloaterContainer* getInstance(); -protected: -	 -	LLFloater* mActiveVoiceFloater; +private: +	typedef std::map<LLUUID,LLPanel*> avatarID_panel_map_t; +	avatarID_panel_map_t mSessions; + +	typedef std::vector<LLUUID> groupIDs_t; +	groupIDs_t mGroupID; + +	void onCloseFloater(LLUUID avatar_id);  };  #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 099f863dc9..2f4f285065 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3687,18 +3687,6 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,  	return rv;  } -BOOL LLCallingCardBridge::removeItem() -{ -	if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) -	{ -		LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); -		return FALSE; -	} -	else -	{ -		return LLItemBridge::removeItem(); -	} -}  // +=================================================+  // |        LLNotecardBridge                         |  // +=================================================+ diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index fced0047e8..759d0cba18 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -448,7 +448,6 @@ public:  							EDragAndDropType cargo_type,  							void* cargo_data);  	void refreshFolderViewItem(); -	BOOL removeItem();  protected:  	LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ); diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 404e266806..7f49a7defb 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -43,8 +43,11 @@  #include "lltrans.h"  #include "lluictrlfactory.h"  #include "lltooltip.h" +#include "llnotificationsutil.h" +#include "llregionflags.h"  // newview includes +#include "llagent.h"  #include "llinventoryobserver.h"  #include "lllandmarkactions.h"  #include "lllandmarklist.h" @@ -56,6 +59,7 @@  #include "lltrans.h"  #include "llviewerinventory.h"  #include "llviewerparcelmgr.h" +#include "llviewerregion.h"  #include "llviewercontrol.h"  #include "llviewermenu.h"  #include "llurllineeditorctrl.h" @@ -256,36 +260,42 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)  	voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");  	voice_icon.mouse_opaque = true;  	mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon); +	mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));  	addChild(mParcelIcon[VOICE_ICON]);  	LLIconCtrl::Params fly_icon = p.fly_icon;  	fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");  	fly_icon.mouse_opaque = true;  	mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon); +	mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));  	addChild(mParcelIcon[FLY_ICON]);  	LLIconCtrl::Params push_icon = p.push_icon;  	push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");  	push_icon.mouse_opaque = true;  	mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon); +	mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));  	addChild(mParcelIcon[PUSH_ICON]);  	LLIconCtrl::Params build_icon = p.build_icon;  	build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");  	build_icon.mouse_opaque = true;  	mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon); +	mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));  	addChild(mParcelIcon[BUILD_ICON]);  	LLIconCtrl::Params scripts_icon = p.scripts_icon;  	scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");  	scripts_icon.mouse_opaque = true;  	mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon); +	mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));  	addChild(mParcelIcon[SCRIPTS_ICON]);  	LLIconCtrl::Params damage_icon = p.damage_icon;  	damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");  	damage_icon.mouse_opaque = true;  	mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon); +	mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));  	addChild(mParcelIcon[DAMAGE_ICON]);  	LLTextBox::Params damage_text = p.damage_text; @@ -918,3 +928,45 @@ bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata)  	return false;  } + +void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon) +{ +	switch (icon) +	{ +	case VOICE_ICON: +		LLNotificationsUtil::add("NoVoice"); +		break; +	case FLY_ICON: +		LLNotificationsUtil::add("NoFly"); +		break; +	case PUSH_ICON: +		LLNotificationsUtil::add("PushRestricted"); +		break; +	case BUILD_ICON: +		LLNotificationsUtil::add("NoBuild"); +		break; +	case SCRIPTS_ICON: +	{ +		LLViewerRegion* region = gAgent.getRegion(); +		if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) +		{ +			LLNotificationsUtil::add("ScriptsStopped"); +		} +		else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) +		{ +			LLNotificationsUtil::add("ScriptsNotRunning"); +		} +		else +		{ +			LLNotificationsUtil::add("NoOutsideScripts"); +		} +		break; +	} +	case DAMAGE_ICON: +		LLNotificationsUtil::add("NotSafe"); +		break; +	case ICON_COUNT: +		break; +	// no default to get compiler warning when a new icon gets added +	} +} diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 7959fab2de..607ccd4da6 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -102,6 +102,18 @@ public:  	void					handleLoginComplete();  private: + +	enum EParcelIcon +	{ +		VOICE_ICON = 0, +		FLY_ICON, +		PUSH_ICON, +		BUILD_ICON, +		SCRIPTS_ICON, +		DAMAGE_ICON, +		ICON_COUNT +	}; +  	friend class LLUICtrlFactory;  	LLLocationInputCtrl(const Params&);  	virtual ~LLLocationInputCtrl(); @@ -138,6 +150,7 @@ private:  	// callbacks  	bool					onLocationContextMenuItemEnabled(const LLSD& userdata);  	void 					onLocationContextMenuItemClicked(const LLSD& userdata); +	void					onParcelIconClick(EParcelIcon icon);  	LLMenuGL*				mLocationContextMenu;  	LLButton*				mAddLandmarkBtn; @@ -146,16 +159,6 @@ private:  	S32						mIconHPad;			// pad between all icons  	S32						mAddLandmarkHPad;	// pad to left of landmark star -	enum EParcelIcon -	{ -		VOICE_ICON = 0, -		FLY_ICON, -		PUSH_ICON, -		BUILD_ICON, -		SCRIPTS_ICON, -		DAMAGE_ICON, -		ICON_COUNT -	};  	LLIconCtrl*	mParcelIcon[ICON_COUNT];  	LLTextBox* mDamageText; diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index b1cdb4d81f..86bdee7c7d 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -264,9 +264,6 @@ LLPanelGroupControlPanel::~LLPanelGroupControlPanel()  // virtual  void LLPanelGroupControlPanel::draw()  { -	//Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update() -	//so we need update it to raise needed event -	mSpeakerManager->update(true);  	// Need to resort the participant list if it's in sort by recent speaker order.  	if (mParticipantList)  		mParticipantList->updateRecentSpeakersOrder(); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index d6e407a0ed..47feef496a 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -305,6 +305,29 @@ void LLLandmarksPanel::updateShowFolderState()  		);  } +void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus) +{ +	if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus)) +	{ +		return; +	} + +	if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus)) +	{ +		return; +	} + +	if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus)) +	{ +		return; +	} + +	if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus)) +	{ +		return; +	} +} +  //////////////////////////////////////////////////////////////////////////  // PROTECTED METHODS  ////////////////////////////////////////////////////////////////////////// @@ -350,6 +373,36 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const  	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;  } +LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, +															 const std::string& tab_name, +															 const LLUUID& obj_id, +															 BOOL take_keyboard_focus) const +{ +	if (!inventory_list) +		return NULL; + +	LLFolderView* folder_view = inventory_list->getRootFolder(); + +	LLFolderViewItem* item = folder_view->getItemByID(obj_id); +	if (!item) +		return NULL; + +	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(tab_name); +	if (!tab->isExpanded()) +	{ +		tab->changeOpenClose(false); +	} + +	folder_view->setSelection(item, FALSE, take_keyboard_focus); + +	LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion"); +	LLRect screen_rc; +	localRectToScreen(item->getRect(), &screen_rc); +	accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); + +	return item; +} +  void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)  {  	if(!panel) return;  diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 569739237d..96b790844c 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -73,6 +73,11 @@ public:  	 */  	void updateShowFolderState(); +	/** +	 * Selects item with "obj_id" in one of accordion tabs. +	 */ +	void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus); +  protected:  	/**  	 * @return true - if current selected panel is not null and selected item is a landmark @@ -81,6 +86,17 @@ protected:  	bool isReceivedFolderSelected() const;  	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);  	LLFolderViewItem* getCurSelectedItem() const; + +	/** +	 * Selects item with "obj_id" in "inventory_list" and scrolls accordion +	 * scrollbar to show the item. +	 * Returns pointer to the item if it is found in "inventory_list", otherwise NULL. +	 */ +	LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, +											   const std::string& tab_name, +											   const LLUUID& obj_id, +											   BOOL take_keyboard_focus) const; +  	void updateSortOrder(LLInventoryPanel* panel, bool byDate);  	//LLRemoteParcelInfoObserver interface diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index a71c8d8958..b037674c37 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -842,6 +842,19 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)  			mPlaceProfile->setVisible(FALSE);  		} +		else +		{ +			LLLandmarksPanel* landmarks_panel = +					dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks")); +			if (landmarks_panel && mItem.notNull()) +			{ +				// If a landmark info is being closed we open the landmarks tab +				// and set this landmark selected. +				mTabContainer->selectTabPanel(landmarks_panel); + +				landmarks_panel->setItemSelected(mItem->getUUID(), TRUE); +			} +		}  	}  } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index b049f914ad..88b706fb6b 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -125,6 +125,8 @@ LLParticipantList::~LLParticipantList()  		delete mParticipantListMenu;  		mParticipantListMenu = NULL;  	} + +	mAvatarList->setContextMenu(NULL);  }  void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) @@ -431,6 +433,10 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(  		"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); +	// Don't show sort options for P2P chat +	bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); +	main_menu->setItemVisible("SortByName", is_sort_visible); +	main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible);  	main_menu->setItemVisible("Moderator Options", isGroupModerator());  	main_menu->arrangeAndClear(); @@ -456,11 +462,6 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const  		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);  		LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);  	} - -	// Don't show sort options for P2P chat -	bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1); -	LLMenuGL::sMenuContainer->childSetVisible("SortByName", is_sort_visible); -	LLMenuGL::sMenuContainer->childSetVisible("SortByRecentSpeakers", is_sort_visible);  }  void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata) diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 0dd9203c6d..9608cd1263 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -44,7 +44,6 @@  #include "llvoavatar.h"  #include "llworld.h" -const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers  const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);  const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f); @@ -73,8 +72,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy  	}  	gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id)); - -	mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);  } @@ -164,6 +161,89 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo  	return(	lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );  } +LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id) +: LLEventTimer(action_period) +, mActionCallback(action_cb) +, mSpeakerId(speaker_id) +{ +} + +BOOL LLSpeakerActionTimer::tick() +{ +	if (mActionCallback) +	{ +		return (BOOL)mActionCallback(mSpeakerId); +	} +	return TRUE; +} + +LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay) +: mActionCallback(action_cb) +, mActionDelay(action_delay) +{ +} + +LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage() +{ +	removeAllTimers(); +} + +void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id) +{ +	bool not_found = true; +	if (mActionTimersMap.size() > 0) +	{ +		not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end(); +	} + +	// If there is already a started timer for the passed UUID don't do anything. +	if (not_found) +	{ +		// Starting a timer to remove an participant after delay is completed +		mActionTimersMap.insert(LLSpeakerActionTimer::action_value_t(speaker_id, +			new LLSpeakerActionTimer( +				boost::bind(&LLSpeakersDelayActionsStorage::onTimerActionCallback, this, _1), +				mActionDelay, speaker_id))); +	} +} + +void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id) +{ +	if (mActionTimersMap.size() == 0) return; + +	LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id); + +	if (it_speaker != mActionTimersMap.end()) +	{ +		delete it_speaker->second; +		mActionTimersMap.erase(it_speaker); +	} +} + +void LLSpeakersDelayActionsStorage::removeAllTimers() +{ +	LLSpeakerActionTimer::action_timer_iter_t iter = mActionTimersMap.begin(); +	for (; iter != mActionTimersMap.end(); ++iter) +	{ +		delete iter->second; +	} +	mActionTimersMap.clear(); +} + +bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id) +{ +	unsetActionTimer(speaker_id); + +	if (mActionCallback) +	{ +		mActionCallback(speaker_id); +	} + +	// do not return true to avoid deleting of an timer twice: +	// in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass() +	return false; +} +  //  // LLSpeakerMgr @@ -172,10 +252,14 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo  LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :   	mVoiceChannel(channelp)  { +	static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0); + +	mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);  }  LLSpeakerMgr::~LLSpeakerMgr()  { +	delete mSpeakerDelayRemover;  }  LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) @@ -198,7 +282,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin  		{  			// keep highest priority status (lowest value) instead of overriding current value  			speakerp->mStatus = llmin(speakerp->mStatus, status); -			speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);  			// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id  			// we need to override speakers that we think are objects when we find out they are really  			// residents @@ -210,6 +293,8 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin  		}  	} +	mSpeakerDelayRemover->unsetActionTimer(speakerp->mID); +  	return speakerp;  } @@ -314,7 +399,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)  	S32 sort_index = 0;  	speaker_list_t::iterator sorted_speaker_it;  	for(sorted_speaker_it = mSpeakersSorted.begin();  -		sorted_speaker_it != mSpeakersSorted.end(); ) +		sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)  	{  		LLPointer<LLSpeaker> speakerp = *sorted_speaker_it; @@ -327,19 +412,6 @@ void LLSpeakerMgr::update(BOOL resort_ok)  		// stuff sort ordinal into speaker so the ui can sort by this value  		speakerp->mSortIndex = sort_index++; - -		// remove speakers that have been gone too long -		if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired()) -		{ -			fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove"); - -			mSpeakers.erase(speakerp->mID); -			sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it); -		} -		else -		{ -			++sorted_speaker_it; -		}  	}  } @@ -363,6 +435,35 @@ void LLSpeakerMgr::updateSpeakerList()  	}  } +void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) +{ +	speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; +	speakerp->mDotColor = INACTIVE_COLOR; +	mSpeakerDelayRemover->setActionTimer(speakerp->mID); +} + +bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id) +{ +	mSpeakers.erase(speaker_id); + +	speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin(); +	 +	for(; sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it) +	{ +		if (speaker_id == (*sorted_speaker_it)->mID) +		{ +			mSpeakersSorted.erase(sorted_speaker_it); +			break; +		} +	} + +	fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove"); + +	update(TRUE); + +	return false; +} +  LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)  {  	//In some conditions map causes crash if it is empty(Windows only), adding check (EK) @@ -511,9 +612,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)  			{  				if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())  				{ -					speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; -					speakerp->mDotColor = INACTIVE_COLOR; -					speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); +					setSpeakerNotInChannel(speakerp);  				}  				else if (agent_data["transition"].asString() == "ENTER")  				{ @@ -563,9 +662,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)  			std::string agent_transition = update_it->second.asString();  			if (agent_transition == "LEAVE" && speakerp.notNull())  			{ -				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; -				speakerp->mDotColor = INACTIVE_COLOR; -				speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); +				setSpeakerNotInChannel(speakerp);  			}  			else if ( agent_transition == "ENTER")  			{ @@ -734,12 +831,13 @@ void LLActiveSpeakerMgr::updateSpeakerList()  	mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();  	// always populate from active voice channel -	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) +	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false  	{  		fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");  		mSpeakers.clear();  		mSpeakersSorted.clear();  		mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel(); +		mSpeakerDelayRemover->removeAllTimers();  	}  	LLSpeakerMgr::updateSpeakerList(); @@ -800,9 +898,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()  			LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);  			if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)  			{ -				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; -				speakerp->mDotColor = INACTIVE_COLOR; -				speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); +				setSpeakerNotInChannel(speakerp);  			}  		}  	} diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index da8dfdf548..63237204c8 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -73,7 +73,6 @@ public:  	F32				mLastSpokeTime;		// timestamp when this speaker last spoke  	F32				mSpeechVolume;		// current speech amplitude (timea average rms amplitude?)  	std::string		mDisplayName;		// cache user name for this speaker -	LLFrameTimer	mActivityTimer;	// time out speakers when they are not part of current voice channel  	BOOL			mHasSpoken;			// has this speaker said anything this session?  	BOOL			mHasLeftCurrentCall;	// has this speaker left the current voice call?  	LLColor4		mDotColor; @@ -120,6 +119,92 @@ private:  	const LLUUID& mSpeakerID;  }; +/** + * class LLSpeakerActionTimer + *  + * Implements a timer that calls stored callback action for stored speaker after passed period. + * + * Action is called until callback returns "true". + * In this case the timer will be removed via LLEventTimer::updateClass(). + * Otherwise it should be deleted manually in place where it is used. + * If action callback is not set timer will tick only once and deleted. + */ +class LLSpeakerActionTimer : public LLEventTimer +{ +public: +	typedef boost::function<bool(const LLUUID&)>	action_callback_t; +	typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t; +	typedef action_timers_map_t::value_type			action_value_t; +	typedef action_timers_map_t::const_iterator		action_timer_const_iter_t; +	typedef action_timers_map_t::iterator			action_timer_iter_t; + +	/** +	 * Constructor. +	 * +	 * @param action_cb - callback which will be called each time after passed action period. +	 * @param action_period - time in seconds timer should tick. +	 * @param speaker_id - LLUUID of speaker which will be passed into action callback. +	 */ +	LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id); +	virtual ~LLSpeakerActionTimer() {}; + +	/** +	 * Implements timer "tick". +	 * +	 * If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass(). +	 */ +	virtual BOOL tick(); + +private: +	action_callback_t	mActionCallback; +	LLUUID				mSpeakerId; +}; + +/** + * Represents a functionality to store actions for speakers with delay. + * Is based on LLSpeakerActionTimer. + */ +class LLSpeakersDelayActionsStorage +{ +public: +	LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay); +	~LLSpeakersDelayActionsStorage(); + +	/** +	 * Sets new LLSpeakerActionTimer with passed speaker UUID. +	 */ +	void setActionTimer(const LLUUID& speaker_id); + +	/** +	 * Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it. +	 * +	 * @see onTimerActionCallback() +	 */ +	void unsetActionTimer(const LLUUID& speaker_id); + +	void removeAllTimers(); +private: +	/** +	 * Callback of the each instance of LLSpeakerActionTimer. +	 * +	 * Unsets an appropriate timer instance and calls action callback for specified speacker_id. +	 * It always returns false to not use LLEventTimer::updateClass functionality of timer deleting. +	 * +	 * @see unsetActionTimer() +	 */ +	bool onTimerActionCallback(const LLUUID& speaker_id); + +	LLSpeakerActionTimer::action_timers_map_t	mActionTimersMap; +	LLSpeakerActionTimer::action_callback_t		mActionCallback; + +	/** +	 * Delay to call action callback for speakers after timer was set. +	 */ +	F32	mActionDelay; + +}; + +  class LLSpeakerMgr : public LLOldEvents::LLObservable  {  public: @@ -144,6 +229,8 @@ public:  protected:  	virtual void updateSpeakerList(); +	void setSpeakerNotInChannel(LLSpeaker* speackerp); +	bool removeSpeaker(const LLUUID& speaker_id);  	typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;  	speaker_map_t		mSpeakers; @@ -151,6 +238,11 @@ protected:  	speaker_list_t		mSpeakersSorted;  	LLFrameTimer		mSpeechTimer;  	LLVoiceChannel*		mVoiceChannel; + +	/** +	 * time out speakers when they are not part of current session +	 */ +	LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;  };  class LLIMSpeakerMgr : public LLSpeakerMgr diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp index 7e4d4988d1..c9bfe178ce 100644 --- a/indra/newview/lltransientdockablefloater.cpp +++ b/indra/newview/lltransientdockablefloater.cpp @@ -42,6 +42,7 @@ LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockContro  		LLDockableFloater(dockControl, uniqueDocking, key, params)  {  	LLTransientFloaterMgr::getInstance()->registerTransientFloater(this); +	LLTransientFloater::init(this);  }  LLTransientDockableFloater::~LLTransientDockableFloater() diff --git a/indra/newview/lltransientdockablefloater.h b/indra/newview/lltransientdockablefloater.h index 6e8a3afd22..e0541d6597 100644 --- a/indra/newview/lltransientdockablefloater.h +++ b/indra/newview/lltransientdockablefloater.h @@ -37,12 +37,13 @@  #include "llfloater.h"  #include "lldockcontrol.h"  #include "lldockablefloater.h" +#include "lltransientfloatermgr.h"  /**   * Represents floater that can dock and managed by transient floater manager.   * Transient floaters should be hidden if user click anywhere except defined view list.   */ -class LLTransientDockableFloater : public LLDockableFloater +class LLTransientDockableFloater : public LLDockableFloater, LLTransientFloater  {  public:  	LOG_CLASS(LLTransientDockableFloater); @@ -52,6 +53,7 @@ public:  	/*virtual*/ void setVisible(BOOL visible);  	/* virtual */void setDocked(bool docked, bool pop_on_undock = true); +	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }  };  #endif /* LL_TRANSIENTDOCKABLEFLOATER_H */ diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp index 347399f239..8f1a738453 100644 --- a/indra/newview/lltransientfloatermgr.cpp +++ b/indra/newview/lltransientfloatermgr.cpp @@ -44,57 +44,68 @@ LLTransientFloaterMgr::LLTransientFloaterMgr()  {  	gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(  			&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3)); + +	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>())); +	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));  } -void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater) +void LLTransientFloaterMgr::registerTransientFloater(LLTransientFloater* floater)  {  	mTransSet.insert(floater);  } -void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater) +void LLTransientFloaterMgr::unregisterTransientFloater(LLTransientFloater* floater)  {  	mTransSet.erase(floater);  } +void LLTransientFloaterMgr::addControlView(ETransientGroup group, LLView* view) +{ +	mGroupControls.find(group)->second.insert(view); +} + +void LLTransientFloaterMgr::removeControlView(ETransientGroup group, LLView* view) +{ +	mGroupControls.find(group)->second.erase(view); +} +  void LLTransientFloaterMgr::addControlView(LLView* view)  { -	mControlsSet.insert(view); +	addControlView(GLOBAL, view);  }  void LLTransientFloaterMgr::removeControlView(LLView* view)  {  	// we will still get focus lost callbacks on this view, but that's ok  	// since we run sanity checking logic every time -	mControlsSet.erase(view); +	removeControlView(GLOBAL, view);  } -void LLTransientFloaterMgr::hideTransientFloaters() +void LLTransientFloaterMgr::hideTransientFloaters(S32 x, S32 y)  { -	for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it +	for (std::set<LLTransientFloater*>::iterator it = mTransSet.begin(); it  			!= mTransSet.end(); it++)  	{ -		LLFloater* floater = *it; -		if (floater->isDocked()) +		LLTransientFloater* floater = *it; +		if (floater->isTransientDocked())  		{ -			floater->setVisible(FALSE); +			ETransientGroup group = floater->getGroup(); + +			bool hide = isControlClicked(mGroupControls.find(group)->second, x, y); +			if (hide) +			{ +				floater->setTransientVisible(FALSE); +			}  		}  	}  } -void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y, -		MASK mask) +bool LLTransientFloaterMgr::isControlClicked(std::set<LLView*>& set, S32 x, S32 y)  { -	bool hide = true; -	for (controls_set_t::iterator it = mControlsSet.begin(); it -			!= mControlsSet.end(); it++) +	bool res = true; +	for (controls_set_t::iterator it = set.begin(); it +			!= set.end(); it++)  	{ -		// don't hide transient floater if any context menu opened -		if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL) -		{ -			hide = false; -			break; -		} -  		LLView* control_view = *it;  		if (!control_view->getVisible())  		{ @@ -105,14 +116,32 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,  		// if click inside view rect  		if (rect.pointInRect(x, y))  		{ -			hide = false; +			res = false;  			break;  		}  	} +	return res; +} + +void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y, +		MASK mask) +{ +	// don't hide transient floater if any context menu opened +	if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL) +	{ +		return; +	} +	bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);  	if (hide)  	{ -		hideTransientFloaters(); +		hideTransientFloaters(x, y);  	}  } +void LLTransientFloater::init(LLFloater* thiz) +{ +	// used since LLTransientFloater(this) can't be used in descendant constructor parameter initialization. +	mFloater = thiz; +} + diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h index cef6e1fe45..1f99325a7f 100644 --- a/indra/newview/lltransientfloatermgr.h +++ b/indra/newview/lltransientfloatermgr.h @@ -37,27 +37,60 @@  #include "llsingleton.h"  #include "llfloater.h" +class LLTransientFloater;  /**   * Provides functionality to hide transient floaters.   */  class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>  { -public: +protected:  	LLTransientFloaterMgr(); -	void registerTransientFloater(LLFloater* floater); -	void unregisterTransientFloater(LLFloater* floater); +	friend class LLSingleton<LLTransientFloaterMgr>; + +public: +	enum ETransientGroup +	{ +		GLOBAL, IM +	}; + +	void registerTransientFloater(LLTransientFloater* floater); +	void unregisterTransientFloater(LLTransientFloater* floater); +	void addControlView(ETransientGroup group, LLView* view); +	void removeControlView(ETransientGroup group, LLView* view);  	void addControlView(LLView* view);  	void removeControlView(LLView* view);  private: -	void hideTransientFloaters(); +	void hideTransientFloaters(S32 x, S32 y);  	void leftMouseClickCallback(S32 x, S32 y, MASK mask); - +	bool isControlClicked(std::set<LLView*>& set, S32 x, S32 y);  private: -	std::set<LLFloater*> mTransSet; +	std::set<LLTransientFloater*> mTransSet; +  	typedef std::set<LLView*> controls_set_t; -	controls_set_t mControlsSet; +	typedef std::map<ETransientGroup, std::set<LLView*> > group_controls_t; +	group_controls_t mGroupControls; +}; + +/** + * An abstract class declares transient floater interfaces. + */ +class LLTransientFloater +{ +protected: +	/** +	 * Class initialization method. +	 * Should be called from descendant constructor. +	 */ +	void init(LLFloater* thiz); +public: +	virtual LLTransientFloaterMgr::ETransientGroup getGroup() = 0; +	bool isTransientDocked() { return mFloater->isDocked(); }; +	void setTransientVisible(BOOL visible) {mFloater->setVisible(visible); } + +private: +	LLFloater* mFloater;  };  #endif  // LL_LLTRANSIENTFLOATERMGR_H diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d57bc0af1d..7487fa9997 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2009,7 +2009,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  		// Someone has offered us some inventory.  		{  			LLOfferInfo* info = new LLOfferInfo; -			bool mute_im = false;  			if (IM_INVENTORY_OFFERED == dialog)  			{  				struct offer_agent_bucket_t @@ -2026,11 +2025,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];  				info->mType = (LLAssetType::EType) bucketp->asset_type;  				info->mObjectID = bucketp->object_id; -				 -				if(accept_im_from_only_friend&&!is_friend) -				{ -					mute_im = true; -				}  			}  			else  			{ @@ -2061,7 +2055,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			info->mDesc = message;  			info->mHost = msg->getSender();  			//if (((is_busy && !is_owned_by_me) || is_muted)) -			if ( is_muted || mute_im) +			if (is_muted)  			{  				// Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)  				LLInventoryFetchObserver::item_ref_t items; diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 1d51d19a4a..bd25288a9e 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -1,6 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <multi_floater - can_minimize="false" + can_close="false"   + can_minimize="true"   can_resize="true"   height="390"   layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 243b63db00..613530b7aa 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -17,6 +17,7 @@   min_width="250"   min_height="190">    <layout_stack +   animate="false"     follows="all"    height="320"    width="360" diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index a666b8a427..9796f7b5b6 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -58,8 +58,10 @@       height="35"       left="8"       name="user_details" +     right="-10"       word_wrap="true"       top_pad="6" +     use_ellipses="true"       width="220">This is my second life description and I really think it is great.      </text>      <slider diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml index 2659156ba8..34cde61252 100644 --- a/indra/newview/skins/default/xui/en/panel_my_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml @@ -51,6 +51,7 @@           top="0"           left="0"           height="505" +         user_resize="false"           width="313">          <scroll_container           color="DkGray2" @@ -365,6 +366,7 @@       top_pad="0"       name="profile_me_buttons_panel"       visible="false" +     user_resize="false"        auto_resize="false"        height="28"       width="313"> diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml index 45b64d5e26..ac100a2c06 100644 --- a/indra/newview/skins/default/xui/en/panel_notes.xml +++ b/indra/newview/skins/default/xui/en/panel_notes.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   follows="all" - height="535" + height="540"   label="Notes & Privacy"   layout="topleft"   left="0" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 8a02637817..da3a2274c9 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -3,7 +3,7 @@  <panel  background_visible="true"   follows="all" - height="570" + height="575"   label="People"   layout="topleft"   min_height="350" @@ -337,7 +337,7 @@ background_visible="true"      </tab_container>      <panel       follows="bottom|left" -     height="25" +     height="35"       layout="topleft"       left="10"       name="button_bar" diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml index 822e049eec..65ccd10cf0 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml @@ -39,7 +39,7 @@       height="500"       layout="topleft"       left="10" -     top_pad="10" +     top_pad="5"       name="profile_scroll"       width="313">      <panel @@ -102,7 +102,7 @@      </scroll_container>      <panel       follows="left|right|bottom" -     height="20" +     height="35"       layout="topleft"       top_pad="8"       left="10" diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index a2b0adf9d9..d31f4d039f 100644 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ b/indra/newview/skins/default/xui/en/panel_picks.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   follows="all" - height="535" + height="540"   label="Picks"   layout="topleft"   left="0" @@ -121,7 +121,7 @@          <panel           layout="topleft"           left="0" -         height="25" +         height="30"           top_pad="10"           name="buttons_cucks"           width="313"> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 2b907ed251..812dc5ce59 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   follows="all" - height="535" + height="540"   label="Profile"   layout="topleft"   left="0" @@ -284,7 +284,7 @@        </layout_panel>        <layout_panel                follows="bottom|left" -         height="28" +         height="30"           layout="topleft"           name="profile_buttons_panel"           auto_resize="false"  @@ -355,7 +355,7 @@          </layout_panel>        <layout_panel           follows="bottom|left" -         height="28" +         height="30"           layout="topleft"           name="profile_me_buttons_panel"           visible="false" @@ -364,7 +364,7 @@           follows="bottom|right"           height="23"           left="20" -	 top="0" +         top="0"           label="Edit Profile"           name="edit_profile_btn"           tool_tip="Edit your personal information" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index c51447eaf0..d46e1f9852 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -60,7 +60,7 @@       tab_min_width="80"       tab_height="30"       tab_position="top" -     top_pad="10" +     top_pad="5"       width="313">          <panel           class="panel_profile" | 
