diff options
| author | Steve Bennetts <steve@lindenlab.com> | 2009-12-07 17:09:19 -0800 | 
|---|---|---|
| committer | Steve Bennetts <steve@lindenlab.com> | 2009-12-07 17:09:19 -0800 | 
| commit | 5c2686bc6323cb162d9b3e4effa6a8d34fb95836 (patch) | |
| tree | 8162047cfafa9027dbcdc03597f8a0a2ad92c9ee /indra/newview | |
| parent | b65334a4c133984fed9466db60df92756e8de05d (diff) | |
| parent | 5245fb69721bf4b70de85211da6721b0e0137e07 (diff) | |
Merge
Diffstat (limited to 'indra/newview')
57 files changed, 1228 insertions, 599 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 76b967eb82..9f525d82b9 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -410,6 +410,7 @@ set(viewer_SOURCE_FILES      lltexturestats.cpp      lltexturestatsuploader.cpp      lltextureview.cpp +    lltextutil.cpp      lltoast.cpp      lltoastalertpanel.cpp      lltoastgroupnotifypanel.cpp @@ -913,6 +914,7 @@ set(viewer_HEADER_FILES      lltexturestats.h      lltexturestatsuploader.h      lltextureview.h +    lltextutil.h      lltoast.h      lltoastalertpanel.h      lltoastgroupnotifypanel.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index a7a6da3ac2..5af023f565 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -487,6 +487,13 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri  					 IM_ONLINE,  					 IM_FRIENDSHIP_OFFERED,  					 calling_card_folder_id); + +	LLSD args; +	args["TO_NAME"] = target_name; +	LLSD payload; +	payload["SESSION_NAME"] = target_name; +	payload["SUPPRES_TOST"] = true; +	LLNotificationsUtil::add("FriendshipOffered", args, payload);  }  //static diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 202fbdebd4..3bd4f898c8 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -262,9 +262,18 @@ void LLAvatarList::refresh()  	bool dirty = add_limit_exceeded || (have_filter && !have_names);  	setDirty(dirty); -	// Refreshed all items, lets send refresh_complete signal. +	// Refreshed all items.  	if(!dirty)  	{ +		// Highlight items matching the filter. +		std::vector<LLPanel*> items; +		getItems(items); +		for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++) +		{ +			static_cast<LLAvatarListItem*>(*it)->setHighlight(mNameFilter); +		} + +		// Send refresh_complete signal.  		std::vector<LLSD> cur_values;  		getValues(cur_values);  		mRefreshCompleteSignal(this, LLSD((S32)cur_values.size())); diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 59ed391c06..072eebdf2d 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -40,6 +40,7 @@  #include "llagent.h"  #include "lloutputmonitorctrl.h"  #include "llavatariconctrl.h" +#include "lltextutil.h"  #include "llbutton.h"  LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) @@ -155,13 +156,8 @@ void LLAvatarListItem::setOnline(bool online)  	mOnlineStatus = (EOnlineStatus) online;  	// Change avatar name font style depending on the new online status. -	LLStyle::Params style_params; -	style_params.color = online ? LLColor4::white : LLColor4::grey; - -	// Rebuild the text to change its style. -	std::string text = mAvatarName->getText(); -	mAvatarName->setText(LLStringUtil::null); -	mAvatarName->appendText(text, false, style_params); +	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); @@ -169,8 +165,12 @@ void LLAvatarListItem::setOnline(bool online)  void LLAvatarListItem::setName(const std::string& name)  { -	mAvatarName->setValue(name); -	mAvatarName->setToolTip(name); +	setNameInternal(name, mHighlihtSubstring); +} + +void LLAvatarListItem::setHighlight(const std::string& highlight) +{ +	setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);  }  void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes) @@ -310,11 +310,18 @@ const std::string LLAvatarListItem::getAvatarName() const  	return mAvatarName->getValue();  } +//== PRIVATE SECITON ========================================================== + +void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight) +{ +	LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight); +	mAvatarName->setToolTip(name); +} +  void LLAvatarListItem::onNameCache(const std::string& first_name, const std::string& last_name)  {  	std::string name = first_name + " " + last_name; -	mAvatarName->setValue(name); -	mAvatarName->setToolTip(name); +	setName(name);  }  void LLAvatarListItem::reshapeAvatarName() diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index a7b080098d..aa1b7593f5 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -37,6 +37,7 @@  #include "lloutputmonitorctrl.h"  #include "llbutton.h"  #include "lltextbox.h" +#include "llstyle.h"  #include "llcallingcard.h" // for LLFriendObserver @@ -71,6 +72,7 @@ public:  	void setOnline(bool online);  	void setName(const std::string& name); +	void setHighlight(const std::string& highlight);  	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 @@ -112,6 +114,7 @@ private:  		E_UNKNOWN,  	} EOnlineStatus; +	void setNameInternal(const std::string& name, const std::string& highlight);  	void onNameCache(const std::string& first_name, const std::string& last_name);  	std::string formatSeconds(U32 secs); @@ -119,12 +122,14 @@ private:  	LLAvatarIconCtrl* mAvatarIcon;  	LLTextBox* mAvatarName;  	LLTextBox* mLastInteractionTime; +	LLStyle::Params mAvatarNameStyle;  	LLButton* mInfoBtn;  	LLButton* mProfileBtn;  	ContextMenu* mContextMenu;  	LLUUID mAvatarId; +	std::string mHighlihtSubstring; // substring to highlight  	EOnlineStatus mOnlineStatus;  	//Flag indicating that info/profile button shouldn't be shown at all.  	//Speaker indicator and avatar name coords are translated accordingly diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 6d3d61d4fe..8c793873f4 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -54,25 +54,24 @@ template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();  LLBottomTray::LLBottomTray(const LLSD&)  :	mChicletPanel(NULL), -	mSysWell(NULL),  	mSpeakPanel(NULL),  	mSpeakBtn(NULL),  	mNearbyChatBar(NULL),  	mToolbarStack(NULL)  ,	mMovementButton(NULL)  ,	mResizeState(RS_NORESIZE) -// Add more members +,	mBottomTrayContextMenu(NULL) +,	mMovementPanel(NULL) +,	mCamPanel(NULL) +,	mSnapshotPanel(NULL) +,	mGesturePanel(NULL) +,	mCamButton(NULL)  {  	mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);  	LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml");  	mChicletPanel = getChild<LLChicletPanel>("chiclet_list"); -	mSysWell = getChild<LLNotificationChiclet>("sys_well"); - -	// init mSysWell -	// set handler for a Click operation -	mSysWell->setClickCallback(boost::bind(&LLSysWellWindow::onChicletClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window")));  	mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 91ec01654b..fa204ee9ea 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -66,7 +66,6 @@ public:  	BOOL postBuild();  	LLChicletPanel*		getChicletPanel()	{return mChicletPanel;} -	LLNotificationChiclet*	getSysWell()	{return mSysWell;}  	LLNearbyChatBar*		getNearbyChatBar()	{return mNearbyChatBar;}  	void onCommitGesture(LLUICtrl* ctrl); @@ -189,7 +188,6 @@ protected:  	LLIMChiclet* createIMChiclet(const LLUUID& session_id);  	LLChicletPanel* 	mChicletPanel; -	LLNotificationChiclet* 	mSysWell;  	LLPanel*			mSpeakPanel;  	LLSpeakButton* 		mSpeakBtn;  	LLNearbyChatBar*	mNearbyChatBar; diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index ad59c780f3..895b4ed80e 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -127,7 +127,7 @@ void LLCallFloater::onOpen(const LLSD& /*key*/)  void LLCallFloater::leaveCall()  {  	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); -	if (voice_channel && voice_channel->isActive()) +	if (voice_channel)  	{  		voice_channel->deactivate();  	} diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 94c303a30f..415c118ff1 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -129,7 +129,7 @@ void LLChannelManager::onLoginCompleted()  	S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");   	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");  	mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound); -	mStartUpChannel->setMouseDownCallback(boost::bind(&LLSysWellWindow::onStartUpToastClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window"), _2, _3, _4)); +	mStartUpChannel->setMouseDownCallback(boost::bind(&LLNotificationWellWindow::onStartUpToastClick, LLNotificationWellWindow::getInstance(), _2, _3, _4));  	mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));  	mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime")); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 96b5ae5908..efe9ea4c35 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -211,6 +211,10 @@ public:  		{  			icon->setValue(chat.mFromID);  		} +		else if (userName->getValue().asString()==LLTrans::getString("SECOND_LIFE")) +		{ +			icon->setValue(LLSD("SL_Logo")); +		}  	}  diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 588855d088..4b3b7a99d8 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -55,6 +55,7 @@  #include "lltransientfloatermgr.h"  static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); +static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well");  static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");  static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p");  static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); @@ -69,7 +70,6 @@ static const S32	OVERLAY_ICON_SHIFT = 2;	// used for shifting of an overlay icon  // static  const S32 LLChicletPanel::s_scroll_ratio = 10; -S32 LLNotificationChiclet::mUreadSystemNotifications = 0;  boost::signals2::signal<LLChiclet* (const LLUUID&),  		LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > > @@ -78,7 +78,7 @@ boost::signals2::signal<LLChiclet* (const LLUUID&),  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// -LLNotificationChiclet::Params::Params() +LLSysWellChiclet::Params::Params()  : button("button")  , unread_notifications("unread_notifications")  { @@ -88,7 +88,7 @@ LLNotificationChiclet::Params::Params()  } -LLNotificationChiclet::LLNotificationChiclet(const Params& p) +LLSysWellChiclet::LLSysWellChiclet(const Params& p)  : LLChiclet(p)  , mButton(NULL)  , mCounter(0) @@ -96,30 +96,14 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p)  	LLButton::Params button_params = p.button;  	mButton = LLUICtrlFactory::create<LLButton>(button_params);  	addChild(mButton); - -	// connect counter handlers to the signals -	connectCounterUpdatersToSignal("notify"); -	connectCounterUpdatersToSignal("groupnotify"); -	connectCounterUpdatersToSignal("offer");  } -LLNotificationChiclet::~LLNotificationChiclet() +LLSysWellChiclet::~LLSysWellChiclet()  {  } -void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); -		n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); -	} -} - -void LLNotificationChiclet::setCounter(S32 counter) +void LLSysWellChiclet::setCounter(S32 counter)  {  	std::string s_count;  	if(counter != 0) @@ -132,16 +116,64 @@ void LLNotificationChiclet::setCounter(S32 counter)  	mCounter = counter;  } -boost::signals2::connection LLNotificationChiclet::setClickCallback( +boost::signals2::connection LLSysWellChiclet::setClickCallback(  	const commit_callback_t& cb)  {  	return mButton->setClickedCallback(cb);  } -void LLNotificationChiclet::setToggleState(BOOL toggled) { +void LLSysWellChiclet::setToggleState(BOOL toggled) {  	mButton->setToggleState(toggled);  } + +/************************************************************************/ +/*               LLIMWellChiclet implementation                         */ +/************************************************************************/ +LLIMWellChiclet::LLIMWellChiclet(const Params& p) +: LLSysWellChiclet(p) +{ +	LLIMModel::instance().addNewMsgCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); +	LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); + +	LLIMMgr::getInstance()->addSessionObserver(this); +} + +LLIMWellChiclet::~LLIMWellChiclet() +{ +	LLIMMgr::getInstance()->removeSessionObserver(this); +} + +void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) +{ +	S32 total_unread = LLIMMgr::instance().getNumberOfUnreadParticipantMessages(); +	setCounter(total_unread); +} + +/************************************************************************/ +/*               LLNotificationChiclet implementation                   */ +/************************************************************************/ +LLNotificationChiclet::LLNotificationChiclet(const Params& p) +: LLSysWellChiclet(p) +, mUreadSystemNotifications(0) +{ +	// connect counter handlers to the signals +	connectCounterUpdatersToSignal("notify"); +	connectCounterUpdatersToSignal("groupnotify"); +	connectCounterUpdatersToSignal("offer"); +} + +void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) +{ +	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); +	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); +	if(n_handler) +	{ +		n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); +		n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); +	} +} +  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// @@ -395,6 +427,10 @@ 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::setCounter(S32 counter) @@ -880,16 +916,7 @@ LLChicletPanel::~LLChicletPanel()  void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){  	LLUUID session_id = data["session_id"].asUUID(); -	LLUUID from_id = data["from_id"].asUUID(); -	const std::string from = data["from"].asString(); -	S32 unread = data["num_unread"].asInteger(); - -	// if new message came -	if(unread != 0) -	{ -		//we do not show balloon (indicator of new messages) for system messages and our own messages -		if (from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from) return; -	} +	S32 unread = data["participant_unread"].asInteger();  	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);  	if (im_floater && im_floater->getVisible()) diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index c75ad2b546..609ce16713 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -39,6 +39,7 @@  #include "lltextbox.h"  #include "lloutputmonitorctrl.h"  #include "llgroupmgr.h" +#include "llimview.h"  class LLVoiceControlPanel;  class LLMenuGL; @@ -746,7 +747,7 @@ private:   * Implements notification chiclet. Used to display total amount of unread messages    * across all IM sessions, total amount of system notifications.   */ -class LLNotificationChiclet : public LLChiclet +class LLSysWellChiclet : public LLChiclet  {  public: @@ -768,28 +769,68 @@ public:  	boost::signals2::connection setClickCallback(const commit_callback_t& cb); -	/*virtual*/ ~LLNotificationChiclet(); +	/*virtual*/ ~LLSysWellChiclet(); -	// methods for updating a number of unread System notifications -	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } -	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }  	void setToggleState(BOOL toggled);  protected: -	// connect counter updaters to the corresponding signals -	void connectCounterUpdatersToSignal(std::string notification_type); -	LLNotificationChiclet(const Params& p); +	LLSysWellChiclet(const Params& p);  	friend class LLUICtrlFactory; -	static S32 mUreadSystemNotifications; -  protected:  	LLButton* mButton;  	S32 mCounter;  };  /** + * Class represented a chiclet for IM Well Icon. + * + * It displays a count of unread messages from other participants in all IM sessions. + */ +class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver +{ +	friend class LLUICtrlFactory; +public: +	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {} +	virtual void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); } +	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {} + +	~LLIMWellChiclet(); +protected: +	LLIMWellChiclet(const Params& p); + +	/** +	 * Handles changes in a session (message was added, messages were read, etc.) +	 * +	 * It get total count of unread messages from a LLIMMgr in all opened sessions and display it. +	 * +	 * @param[in] session_data contains session related data, is not used now +	 *		["session_id"] - id of an appropriate session +	 *		["participant_unread"] - count of unread messages from "real" participants. +	 * +	 * @see LLIMMgr::getNumberOfUnreadParticipantMessages() +	 */ +	void messageCountChanged(const LLSD& session_data); +}; + +class LLNotificationChiclet : public LLSysWellChiclet +{ +	friend class LLUICtrlFactory; +protected: +	LLNotificationChiclet(const Params& p); + +	// connect counter updaters to the corresponding signals +	void connectCounterUpdatersToSignal(const std::string& notification_type); + +	// methods for updating a number of unread System notifications +	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } +	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); } + +	S32 mUreadSystemNotifications; +}; + +/**   * Storage class for all IM chiclets. Provides mechanism to display,    * scroll, create, remove chiclets.   */ diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 07bb6f832b..6e3d5499a2 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -140,9 +140,14 @@ BOOL LLFloaterAvatarPicker::postBuild()  	return TRUE;  } +void LLFloaterAvatarPicker::setOkBtnEnableCb(validate_callback_t cb) +{ +	mOkButtonValidateSignal.connect(cb); +} +  void LLFloaterAvatarPicker::onTabChanged()  { -	childSetEnabled("ok_btn", visibleItemsSelected()); +	childSetEnabled("ok_btn", isSelectBtnEnabled());  }  // Destroys the object @@ -175,6 +180,10 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata)  {  	LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata; +	// If select btn not enabled then do not callback +	if (!self || !self->isSelectBtnEnabled()) +		return; +  	if(self->mCallback)  	{  		std::string acvtive_panel_name; @@ -244,7 +253,7 @@ void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata)  	LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;  	if (self)  	{ -		self->childSetEnabled("ok_btn", self->visibleItemsSelected()); +		self->childSetEnabled("ok_btn", self->isSelectBtnEnabled());  	}  } @@ -477,3 +486,43 @@ BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask)  	return LLFloater::handleKeyHere(key, mask);  } + +bool LLFloaterAvatarPicker::isSelectBtnEnabled() +{ +	bool ret_val = visibleItemsSelected(); + +	if ( ret_val && mOkButtonValidateSignal.num_slots() ) +	{ +		std::string acvtive_panel_name; +		LLScrollListCtrl* list =  NULL; +		LLPanel* active_panel = childGetVisibleTab("ResidentChooserTabs"); + +		if(active_panel) +		{ +			acvtive_panel_name = active_panel->getName(); +		} + +		if(acvtive_panel_name == "SearchPanel") +		{ +			list = getChild<LLScrollListCtrl>("SearchResults"); +		} +		else if(acvtive_panel_name == "NearMePanel") +		{ +			list = getChild<LLScrollListCtrl>("NearMe"); +		} +		else if (acvtive_panel_name == "FriendsPanel") +		{ +			list = getChild<LLScrollListCtrl>("Friends"); +		} + +		if(list) +		{ +			std::vector<LLUUID> avatar_ids; +			std::vector<std::string> avatar_names; +			getSelectedAvatarData(list, avatar_names, avatar_ids); +			return mOkButtonValidateSignal(avatar_ids); +		} +	} + +	return ret_val; +} diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index b8ace985d9..13e491834e 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -40,6 +40,9 @@  class LLFloaterAvatarPicker : public LLFloater  {  public: +	typedef boost::signals2::signal<bool(const std::vector<LLUUID>&), boost_boolean_combiner> validate_signal_t; +	typedef validate_signal_t::slot_type validate_callback_t; +  	// Call this to select an avatar.  	// The callback function will be called with an avatar name and UUID.  	typedef void(*callback_t)(const std::vector<std::string>&, const std::vector<LLUUID>&, void*); @@ -53,6 +56,8 @@ public:  	virtual	BOOL postBuild(); +	void setOkBtnEnableCb(validate_callback_t cb); +  	static void processAvatarPickerReply(class LLMessageSystem* msg, void**);  private: @@ -65,7 +70,8 @@ private:  	static void onBtnClose(void* userdata);  	static void onList(class LLUICtrl* ctrl, void* userdata);  		   void onTabChanged(); -	 +		   bool isSelectBtnEnabled(); +  	void populateNearMe();  	void populateFriend();  	BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected. @@ -83,6 +89,7 @@ private:  	void (*mCallback)(const std::vector<std::string>& name, const std::vector<LLUUID>& id, void* userdata);  	void* mCallbackUserdata; +	validate_signal_t mOkButtonValidateSignal;  };  #endif diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 97cf139f1d..80b706a215 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -44,6 +44,7 @@  #include "llagent.h"  #include "llgroupactions.h"  #include "llfloaterreg.h" +#include "lltextutil.h"  #include "llviewercontrol.h"	// for gSavedSettings  static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); @@ -133,17 +134,17 @@ void LLGroupList::refresh()  		const LLGroupData& group_data = gAgent.mGroups.get(i);  		if (have_filter && !findInsensitive(group_data.mName, mNameFilter))  			continue; -		addNewItem(id, group_data.mName, group_data.mInsigniaID, highlight_id == id, ADD_BOTTOM); +		addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM);  	}  	// Sort the list.  	sort(); -	// add "none" to list at top +	// Add "none" to list at top if filter not set (what's the point of filtering "none"?). +	if (!have_filter)  	{  		std::string loc_none = LLTrans::getString("GroupsNone"); -		if (have_filter || findInsensitive(loc_none, mNameFilter)) -			addNewItem(LLUUID::null, loc_none, LLUUID::null, highlight_id.isNull(), ADD_TOP); +		addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);  	}  	selectItemByUUID(highlight_id); @@ -171,12 +172,12 @@ void LLGroupList::toggleIcons()  // PRIVATE Section  ////////////////////////////////////////////////////////////////////////// -void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos) +void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos)  {  	LLGroupListItem* item = new LLGroupListItem(); -	item->setName(name);  	item->setGroupID(id); +	item->setName(name, mNameFilter);  	item->setGroupIconID(icon_id);  //	item->setContextMenu(mContextMenu); @@ -267,10 +268,10 @@ void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)  	LLPanel::onMouseLeave(x, y, mask);  } -void LLGroupListItem::setName(const std::string& name) +void LLGroupListItem::setName(const std::string& name, const std::string& highlight)  {  	mGroupName = name; -	mGroupNameBox->setValue(name); +	LLTextUtil::textboxSetHighlightedVal(mGroupNameBox, mGroupNameStyle, name, highlight);  	mGroupNameBox->setToolTip(name);  } @@ -308,6 +309,8 @@ void LLGroupListItem::setGroupIconVisible(bool visible)  //////////////////////////////////////////////////////////////////////////  void LLGroupListItem::setActive(bool active)  { +	// *BUG: setName() overrides the style params. +  	// Active group should be bold.  	LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->getFontDesc()); @@ -316,15 +319,12 @@ void LLGroupListItem::setActive(bool active)  	// is predefined as bold (SansSerifSmallBold, for example)  	new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);  	LLFontGL* new_font = LLFontGL::getFont(new_desc); -	LLStyle::Params style_params; -	style_params.font = new_font; +	mGroupNameStyle.font = new_font;  	// *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. -	std::string text = mGroupNameBox->getText(); -	mGroupNameBox->setText(LLStringUtil::null); -	mGroupNameBox->appendText(text, false, style_params); +	mGroupNameBox->setText(mGroupName, mGroupNameStyle);  }  void LLGroupListItem::onInfoBtnClick() diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 8dbc13997c..41b4d01711 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -37,6 +37,7 @@  #include "llflatlistview.h"  #include "llpanel.h"  #include "llpointer.h" +#include "llstyle.h"  /**   * Auto-updating list of agent groups. @@ -66,7 +67,7 @@ public:  private:  	void setDirty(bool val = true)		{ mDirty = val; }  	void refresh(); -	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); +	void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM);  	bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes  	bool mShowIcons; @@ -90,7 +91,7 @@ public:  	const LLUUID& getGroupID() const			{ return mGroupID; }  	const std::string& getGroupName() const		{ return mGroupName; } -	void setName(const std::string& name); +	void setName(const std::string& name, const std::string& highlight = LLStringUtil::null);  	void setGroupID(const LLUUID& group_id);  	void setGroupIconID(const LLUUID& group_icon_id);  	void setGroupIconVisible(bool visible); @@ -106,6 +107,7 @@ private:  	LLButton*	mInfoBtn;  	std::string	mGroupName; +	LLStyle::Params mGroupNameStyle;  	static S32	sIconWidth; // icon width + padding  }; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 9de0b1f827..2bc07d0c27 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -237,7 +237,6 @@ BOOL LLIMFloater::postBuild()  	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name); -	LLStringUtil::toUpper(session_name);  	setTitle(session_name);  	childSetCommitCallback("chat_editor", onSendMsg, this); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index d3058e67af..6c4af0522f 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -88,6 +88,10 @@ const static std::string IM_TEXT("message");  const static std::string IM_FROM("from");  const static std::string IM_FROM_ID("from_id"); +std::string LLCallDialogManager::sPreviousSessionlName = ""; +std::string LLCallDialogManager::sCurrentSessionlName = ""; +LLIMModel::LLIMSession* LLCallDialogManager::sSession = NULL; +  //  // Globals  // @@ -144,11 +148,13 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  :	mSessionID(session_id),  	mName(name),  	mType(type), +	mParticipantUnreadMessageCount(0),  	mNumUnread(0),  	mOtherParticipantID(other_participant_id),  	mInitialTargetIDs(ids),  	mVoiceChannel(NULL),  	mSpeakers(NULL), +	mCallDialogManager(NULL),  	mSessionInitialized(false),  	mCallBackEnabled(true),  	mTextIMPossible(true), @@ -167,6 +173,9 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  	{  		mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2));  	} +	// define what type of session was opened +	setSessionType(); +	  	mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);  	// All participants will be added to the list of people we've recently interacted with. @@ -199,8 +208,35 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  	}  } +void LLIMModel::LLIMSession::setSessionType() +{ +	// set P2P type by default +	mSessionType = P2P_SESSION; + +	if (dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel) && !mOtherParticipantIsAvatar) // P2P AVALINE channel was opened +	{ +		mSessionType = AVALINE_SESSION; +		return; +	}  +	else if(dynamic_cast<LLVoiceChannelGroup*>(mVoiceChannel)) // GROUP channel was opened +	{ +		if (mType == IM_SESSION_CONFERENCE_START) +		{ +			mSessionType = ADHOC_SESSION; +			return; +		}  +		else if(mType == IM_SESSION_GROUP_START) +		{ +			mSessionType = GROUP_SESSION; +			return; +		}		 +	} +} +  void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)  { +	// *TODO: remove hardcoded string!!!!!!!!!!! +  	bool is_p2p_session = dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel);  	bool is_incoming_call = false;  	std::string other_avatar_name; @@ -251,6 +287,9 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES  LLIMModel::LLIMSession::~LLIMSession()  { +	delete mCallDialogManager; +	mCallDialogManager = NULL; +  	delete mSpeakers;  	mSpeakers = NULL; @@ -458,10 +497,12 @@ void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages,  	}  	session->mNumUnread = 0; +	session->mParticipantUnreadMessageCount = 0;  	LLSD arg;  	arg["session_id"] = session_id;  	arg["num_unread"] = 0; +	arg["participant_unread"] = session->mParticipantUnreadMessageCount;  	mNoUnreadMsgsSignal(arg);  } @@ -538,10 +579,18 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co  	session->mNumUnread++; +	//update count of unread messages from real participant +	if (!(from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from)) +	{ +		++(session->mParticipantUnreadMessageCount); +	} + +  	// notify listeners  	LLSD arg;  	arg["session_id"] = session_id;  	arg["num_unread"] = session->mNumUnread; +	arg["participant_unread"] = session->mParticipantUnreadMessageCount;  	arg["message"] = utf8_text;  	arg["from"] = from;  	arg["from_id"] = from_id; @@ -1184,21 +1233,141 @@ LLIMMgr::onConfirmForceCloseError(  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLOutgoingCallDialog +// Class LLCallDialogManager  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) : -	LLDockableFloater(NULL, false, payload), -	mPayload(payload) + +LLCallDialogManager::LLCallDialogManager() +{ +} + +LLCallDialogManager::~LLCallDialogManager() +{ +} + +void LLCallDialogManager::initClass() +{ +	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(LLCallDialogManager::onVoiceChannelChanged); +} + +void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id) +{ +	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); +	if(!session) +	{		 +		sPreviousSessionlName = sCurrentSessionlName; +		sCurrentSessionlName = ""; // Empty string results in "Nearby Voice Chat" after substitution +		return; +	} +	sSession = session; +	sSession->mVoiceChannel->setStateChangedCallback(LLCallDialogManager::onVoiceChannelStateChanged); +	sPreviousSessionlName = sCurrentSessionlName; +	sCurrentSessionlName = session->mName; +} + +void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +{ +	LLSD mCallDialogPayload; +	LLOutgoingCallDialog* ocd; + +	mCallDialogPayload["session_id"] = sSession->mSessionID; +	mCallDialogPayload["session_name"] = sSession->mName; +	mCallDialogPayload["other_user_id"] = sSession->mOtherParticipantID; +	mCallDialogPayload["old_channel_name"] = sPreviousSessionlName; + +	switch(new_state) +	{			 +	case LLVoiceChannel::STATE_CALL_STARTED : +		// do not show "Calling to..." if it is incoming P2P call +		if(sSession->mSessionType == LLIMModel::LLIMSession::P2P_SESSION && static_cast<LLVoiceChannelP2P*>(sSession->mVoiceChannel)->isIncomingCall()) +		{ +			return; +		} + +		ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); +		if (ocd) +		{ +			ocd->getChild<LLTextBox>("calling")->setVisible(true); +			ocd->getChild<LLTextBox>("leaving")->setVisible(true); +			ocd->getChild<LLTextBox>("connecting")->setVisible(false); +			ocd->getChild<LLTextBox>("noanswer")->setVisible(false); +		} +		return; + +	case LLVoiceChannel::STATE_RINGING : +		ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); +		if (ocd) +		{ +			ocd->getChild<LLTextBox>("calling")->setVisible(false); +			ocd->getChild<LLTextBox>("leaving")->setVisible(true); +			ocd->getChild<LLTextBox>("connecting")->setVisible(true); +			ocd->getChild<LLTextBox>("noanswer")->setVisible(false); +		} +		return; + +	case LLVoiceChannel::STATE_ERROR : +		ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); +		if (ocd) +		{ +			ocd->getChild<LLTextBox>("calling")->setVisible(false); +			ocd->getChild<LLTextBox>("leaving")->setVisible(false); +			ocd->getChild<LLTextBox>("connecting")->setVisible(false); +			ocd->getChild<LLTextBox>("noanswer")->setVisible(true); +		} +		return; + +	case LLVoiceChannel::STATE_CONNECTED : +	case LLVoiceChannel::STATE_HUNG_UP : +		ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); +		if (ocd) +		{ +			ocd->closeFloater(); +		} +		return; + +	default: +		break; +	} + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLCallDialog +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LLCallDialog::LLCallDialog(const LLSD& payload) : +LLDockableFloater(NULL, false, payload), +mPayload(payload)  {  } -void LLOutgoingCallDialog::getAllowedRect(LLRect& rect) +void LLCallDialog::getAllowedRect(LLRect& rect)  {  	rect = gViewerWindow->getWorldViewRectScaled();  } +void LLCallDialog::onOpen(const LLSD& key) +{ +	// dock the dialog to the Speak Button, where other sys messages appear +	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getChild<LLPanel>("speak_panel"), +		this, getDockTongue(), LLDockControl::TOP, boost::bind(&LLCallDialog::getAllowedRect, this, _1))); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLOutgoingCallDialog +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) : +LLCallDialog(payload) +{ +	LLOutgoingCallDialog* instance = LLFloaterReg::findTypedInstance<LLOutgoingCallDialog>("outgoing_call", payload); +	if(instance && instance->getVisible()) +	{ +		instance->onCancel(instance); +	}	 +} +  void LLOutgoingCallDialog::onOpen(const LLSD& key)  { +	LLCallDialog::onOpen(key); +  	// tell the user which voice channel they are leaving  	if (!mPayload["old_channel_name"].asString().empty())  	{ @@ -1246,22 +1415,15 @@ BOOL LLOutgoingCallDialog::postBuild()  	childSetAction("Cancel", onCancel, this); -	// dock the dialog to the sys well, where other sys messages appear -	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getChild<LLPanel>("speak_panel"), -					 this, getDockTongue(), LLDockControl::TOP, -					 boost::bind(&LLOutgoingCallDialog::getAllowedRect, this, _1))); -  	return success;  } -  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLIncomingCallDialog  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) : -	LLDockableFloater(NULL, false, payload), -	mPayload(payload) +LLCallDialog(payload)  {  } @@ -1305,13 +1467,11 @@ BOOL LLIncomingCallDialog::postBuild()  	return TRUE;  } -void LLIncomingCallDialog::getAllowedRect(LLRect& rect) -{ -	rect = gViewerWindow->getWorldViewRectScaled(); -}  void LLIncomingCallDialog::onOpen(const LLSD& key)  { +	LLCallDialog::onOpen(key); +  	// tell the user which voice channel they would be leaving  	LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel();  	if (voice && !voice->getSessionName().empty()) @@ -1322,11 +1482,6 @@ void LLIncomingCallDialog::onOpen(const LLSD& key)  	{  		childSetTextArg("question", "[CURRENT_CHAT]", getString("localchat"));  	} - -	// dock the dialog to the sys well, where other sys messages appear -	setDockControl(new LLDockControl(LLBottomTray::getInstance()->getChild<LLPanel>("speak_panel"), -									 this, getDockTongue(), LLDockControl::TOP, -									 boost::bind(&LLIncomingCallDialog::getAllowedRect, this, _1)));  }  //static @@ -1751,6 +1906,19 @@ S32 LLIMMgr::getNumberOfUnreadIM()  	return num;  } +S32 LLIMMgr::getNumberOfUnreadParticipantMessages() +{ +	std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it; + +	S32 num = 0; +	for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it) +	{ +		num += (*it).second->mParticipantUnreadMessageCount; +	} + +	return num; +} +  void LLIMMgr::clearNewIMNotification()  {  	mIMReceived = FALSE; @@ -1966,18 +2134,7 @@ void LLIMMgr::inviteToSession(  		}  		else  		{ -			if (notify_box_type == "VoiceInviteP2P" || notify_box_type == "VoiceInviteAdHoc") -			{ -				LLFloaterReg::showInstance("incoming_call", payload, TRUE); -			} -			else -			{ -				LLSD args; -				args["NAME"] = caller_name; -				args["GROUP"] = session_name; - -				LLNotificationsUtil::add(notify_box_type, args, payload, &inviteUserResponse); -			} +			LLFloaterReg::showInstance("incoming_call", payload, TRUE);  		}  		mPendingInvitations[session_id.asString()] = LLSD();  	} @@ -1990,21 +2147,7 @@ void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::stri  	std::string notify_box_type = payload["notify_box_type"].asString(); -	if (notify_box_type == "VoiceInviteP2P" || notify_box_type == "VoiceInviteAdHoc") -	{ -		LLFloaterReg::showInstance("incoming_call", payload, TRUE); -	} -	else -	{ -		LLSD args; -		args["NAME"] = payload["caller_name"].asString(); -	 -		LLNotificationsUtil::add( -			payload["notify_box_type"].asString(), -			args,  -			payload, -			&inviteUserResponse); -	} +	LLFloaterReg::showInstance("incoming_call", payload, TRUE);  }  void LLIMMgr::disconnectAllSessions() diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 8a0f57deb0..c002434a18 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -48,6 +48,7 @@ class LLFloaterChatterBox;  class LLUUID;  class LLFloaterIMPanel;  class LLFriendObserver; +class LLCallDialogManager;	  class LLIMModel :  public LLSingleton<LLIMModel>  { @@ -55,12 +56,20 @@ public:  	struct LLIMSession  	{ +		typedef enum e_session_type +		{   // for now we have 4 predefined types for a session +			P2P_SESSION, +			GROUP_SESSION, +			ADHOC_SESSION, +			AVALINE_SESSION, +		} SType; +  		LLIMSession(const LLUUID& session_id, const std::string& name,   			const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids);  		virtual ~LLIMSession();  		void sessionInitReplyReceived(const LLUUID& new_session_id); - +		void setSessionType(); //define what type of session was opened  		void addMessagesFromHistory(const std::list<LLSD>& history);  		void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);  		void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); @@ -69,13 +78,18 @@ public:  		LLUUID mSessionID;  		std::string mName;  		EInstantMessage mType; +		SType mSessionType;  		LLUUID mOtherParticipantID;  		std::vector<LLUUID> mInitialTargetIDs; +		LLCallDialogManager* mCallDialogManager;  		// connection to voice channel state change signal  		boost::signals2::connection mVoiceChannelStateChangeConnection; -		//does NOT include system messages +		//does NOT include system messages and agent's messages +		S32 mParticipantUnreadMessageCount; + +		// does include all incoming messages  		S32 mNumUnread;  		std::list<LLSD> mMsgs; @@ -319,9 +333,14 @@ public:  	// IM received that you haven't seen yet  	BOOL getIMReceived() const; -	// Calc number of unread IMs +	// Calc number of all unread IMs  	S32 getNumberOfUnreadIM(); +	/** +	 * Calculates number of unread IMs from real participants in all stored sessions +	 */ +	S32 getNumberOfUnreadParticipantMessages(); +  	// This method is used to go through all active sessions and  	// disable all of them. This method is usally called when you are  	// forced to log out or similar situations where you do not have a @@ -419,7 +438,36 @@ private:  	LLSD mPendingAgentListUpdates;  }; -class LLIncomingCallDialog : public LLDockableFloater +class LLCallDialogManager : public LLInitClass<LLCallDialogManager> +{ +public: +	LLCallDialogManager(); +	~LLCallDialogManager(); + +	static void initClass(); +	static void onVoiceChannelChanged(const LLUUID &session_id); +	static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); + +protected: +	static std::string sPreviousSessionlName; +	static std::string sCurrentSessionlName; +	static LLIMModel::LLIMSession* sSession; +}; + +class LLCallDialog : public LLDockableFloater +{ +public: +	LLCallDialog(const LLSD& payload); +	~LLCallDialog() {} + +	virtual void onOpen(const LLSD& key); + +protected: +	virtual void getAllowedRect(LLRect& rect); +	LLSD mPayload; +}; + +class LLIncomingCallDialog : public LLCallDialog  {  public:  	LLIncomingCallDialog(const LLSD& payload); @@ -433,12 +481,9 @@ public:  private:  	void processCallResponse(S32 response); -	void getAllowedRect(LLRect& rect); - -	LLSD mPayload;  }; -class LLOutgoingCallDialog : public LLDockableFloater +class LLOutgoingCallDialog : public LLCallDialog  {  public:  	LLOutgoingCallDialog(const LLSD& payload); @@ -449,9 +494,6 @@ public:  	static void onCancel(void* user_data);  private: -	void getAllowedRect(LLRect& rect); - -	LLSD mPayload;  };  // Globals diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 54f528de8d..4cbf27b725 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -903,10 +903,13 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)  	if (!auto_open) return NULL;  	// D. Open the inventory side panel and use that. -	LLSD key; +	LLSideTray *side_tray = LLSideTray::getInstance();  	LLSidepanelInventory *sidepanel_inventory = -		dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->showPanel("sidepanel_inventory", key)); -	if (sidepanel_inventory) +		dynamic_cast<LLSidepanelInventory *>(side_tray->getPanel("sidepanel_inventory")); + +	// Use the inventory side panel only if it is already active. +	// Activating it may unexpectedly switch off the currently active tab in some cases. +	if (sidepanel_inventory && (LLPanel*)side_tray->getActiveTab() == (LLPanel*)sidepanel_inventory)  	{  		return sidepanel_inventory->getActivePanel();  	} diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 9e46a4422a..c17427bec1 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -603,7 +603,7 @@ BOOL LLPanelStandStopFlying::handleToolTip(S32 x, S32 y, MASK mask)  		LLToolTipMgr::instance().show(mStopFlyingButton->getToolTip());  	} -	return TRUE; +	return LLPanel::handleToolTip(x, y, mask);  }  void LLPanelStandStopFlying::reparent(LLFloaterMove* move_view) diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index da8928321a..5c240aa54a 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -266,6 +266,11 @@ public:  	static bool canLogToIM(const LLNotificationPtr& notification);  	/** +	 * Checks sufficient conditions to spawn IM session. +	 */ +	static bool canSpawnIMSession(const LLNotificationPtr& notification); + +	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 857b7e9796..6748bd7982 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -43,14 +43,27 @@ using namespace LLNotificationsUI;  const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),  		REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), OBJECT_GIVE_ITEM(  				"ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER( -				"ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"); +				"ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"), +						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), +						USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"), +						FRIENDSHIP_ACCEPTED("FriendshipAccepted"), +						FRIENDSHIP_OFFERED("FriendshipOffered");  // static  bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)  {  	return GRANTED_MODIFY_RIGHTS == notification->getName()  			|| REVOKED_MODIFY_RIGHTS == notification->getName() -			|| PAYMENT_RECIVED == notification->getName(); +			|| PAYMENT_RECIVED == notification->getName() +			|| FRIENDSHIP_OFFERED == notification->getName(); +} + +// static +bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) +{ +	return ADD_FRIEND_WITH_MESSAGE == notification->getName() +			|| OFFER_FRIENDSHIP == notification->getName() +			|| FRIENDSHIP_ACCEPTED == notification->getName();  }  // static @@ -92,13 +105,16 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)  					notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"]  							: notification->getSubstitutions()["[NAME]"]; +	const std::string session_name = notification->getPayload().has( +			"SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name; +  	// don't create IM p2p session with objects, it's necessary condition to log  	if (notification->getName() != OBJECT_GIVE_ITEM && notification->getName()  			!= OBJECT_GIVE_ITEM_UNKNOWN_USER)  	{  		LLUUID from_id = notification->getPayload()["from_id"]; -		logToIM(IM_NOTHING_SPECIAL, name, name, notification->getMessage(), +		logToIM(IM_NOTHING_SPECIAL, session_name, name, notification->getMessage(),  				from_id, from_id);  	}  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 4f353bf6a5..4d64c5c0e4 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -40,6 +40,8 @@  #include "llnotificationmanager.h"  #include "llnotifications.h"  #include "llscriptfloater.h" +#include "llimview.h" +#include "llnotificationsutil.h"  using namespace LLNotificationsUI; @@ -101,20 +103,48 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  		}  		else  		{ -			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - -			LLToast::Params p; -			p.notif_id = notification->getID(); -			p.notification = notification; -			p.panel = notify_box; -			p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); -			 -			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); -			if(channel) -				channel->addToast(p); - -			// send a signal to the counter manager -			mNewNotificationSignal(); +			if (LLHandlerUtil::canSpawnIMSession(notification)) +			{ +				const std::string name = notification->getSubstitutions().has( +						"NAME") ? notification->getSubstitutions()["NAME"] +						: notification->getSubstitutions()["[NAME]"]; + +				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); +				} +			} + +			if (notification->getPayload().has("SUPPRES_TOST") +						&& notification->getPayload()["SUPPRES_TOST"]) +			{ +				LLNotificationsUtil::cancel(notification); +			} +			else +			{ +				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + +				LLToast::Params p; +				p.notif_id = notification->getID(); +				p.notification = notification; +				p.panel = notify_box; +				p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); + +				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); +				if(channel) +					channel->addToast(p); + +				// send a signal to the counter manager +				mNewNotificationSignal(); +			}  		}  	}  	else if (notify["sigtype"].asString() == "delete") diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index d731da0ec7..e87b70f6a5 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -125,7 +125,10 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)  		tab->setVisible(TRUE);  		// expand accordion to see matched items in each one. See EXT-2014. -		tab->changeOpenClose(false); +		if (string != "") +		{ +			tab->changeOpenClose(false); +		}  		LLInventorySubTreePanel* inventory_list = dynamic_cast<LLInventorySubTreePanel*>(tab->getAccordionView());  		if (NULL == inventory_list) continue; diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index 046118cf75..ece93125b3 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -71,7 +71,7 @@ void LLPanelMe::onOpen(const LLSD& key)  	LLPanelProfile::onOpen(key);  } -void LLPanelMe::notifyChildren(const LLSD& info) +bool LLPanelMe::notifyChildren(const LLSD& info)  {  	if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")  	{ @@ -104,10 +104,10 @@ void LLPanelMe::notifyChildren(const LLSD& info)  		if (on_default_view)  			LLSideTray::getInstance()->collapseSideBar(); -		return; // this notification is only supposed to be handled by task panels  +		return true; // this notification is only supposed to be handled by task panels   	} -	LLPanel::notifyChildren(info); +	return LLPanel::notifyChildren(info);  }  void LLPanelMe::buildEditPanel() @@ -220,6 +220,7 @@ BOOL LLPanelMyProfileEdit::postBuild()  	initTexturePickerMouseEvents();  	childSetTextArg("partner_edit_link", "[URL]", getString("partner_edit_link_url")); +	childSetTextArg("my_account_link", "[URL]", getString("my_account_link_url"));  	return LLPanelAvatarProfile::postBuild();  } diff --git a/indra/newview/llpanelme.h b/indra/newview/llpanelme.h index 17d367132e..1325192bbf 100644 --- a/indra/newview/llpanelme.h +++ b/indra/newview/llpanelme.h @@ -54,7 +54,7 @@ public:  	LLPanelMe();  	/*virtual*/ void onOpen(const LLSD& key); -	/*virtual*/ void notifyChildren(const LLSD& info); +	/*virtual*/ bool notifyChildren(const LLSD& info);  	/*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 1743df52fc..1e4682701e 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1003,10 +1003,28 @@ void LLPanelPeople::onAddFriendButtonClicked()  	}  } +bool LLPanelPeople::isItemsFreeOfFriends(const std::vector<LLUUID>& uuids) +{ +	const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); +	for ( std::vector<LLUUID>::const_iterator +			  id = uuids.begin(), +			  id_end = uuids.end(); +		  id != id_end; ++id ) +	{ +		if (av_tracker.isBuddy (*id)) +		{ +			return false; +		} +	} +	return true; +} +  void LLPanelPeople::onAddFriendWizButtonClicked()  {  	// Show add friend wizard.  	LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onAvatarPicked, NULL, FALSE, TRUE); +	// Need to disable 'ok' button when friend occurs in selection +	if (picker)	picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1));  	LLFloater* root_floater = gFloaterView->getParentFloater(this);  	if (root_floater)  	{ @@ -1284,7 +1302,7 @@ void	LLPanelPeople::onOpen(const LLSD& key)  		reSelectedCurrentTab();  } -void LLPanelPeople::notifyChildren(const LLSD& info) +bool LLPanelPeople::notifyChildren(const LLSD& info)  {  	if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")  	{ @@ -1292,7 +1310,7 @@ void LLPanelPeople::notifyChildren(const LLSD& info)  		if (!container)  		{  			llwarns << "Cannot find People panel container" << llendl; -			return; +			return true;  		}  		if (container->getCurrentPanelIndex() > 0)  @@ -1303,10 +1321,10 @@ void LLPanelPeople::notifyChildren(const LLSD& info)  		else  			LLSideTray::getInstance()->collapseSideBar(); -		return; // this notification is only supposed to be handled by task panels +		return true; // this notification is only supposed to be handled by task panels  	} -	LLPanel::notifyChildren(info); +	return LLPanel::notifyChildren(info);  }  void LLPanelPeople::showAccordion(const std::string name, bool show) diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 5ac5bcc1d7..a9cc6d0ccb 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -51,7 +51,7 @@ public:  	/*virtual*/ BOOL 	postBuild();  	/*virtual*/ void	onOpen(const LLSD& key); -	/*virtual*/ void	notifyChildren(const LLSD& info); +	/*virtual*/ bool	notifyChildren(const LLSD& info);  	// internals  	class Updater; @@ -72,6 +72,7 @@ private:  	void					updateRecentList();  	bool					isFriendOnline(const LLUUID& id); +	bool					isItemsFreeOfFriends(const std::vector<LLUUID>& uuids);  	void					updateButtons();  	std::string				getActiveTabName() const; diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index cc6e88a9d2..59a68bc12d 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -161,6 +161,9 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)  			std::string name, second_name;  			gCacheName->getName(getAvatarId(),name,second_name);  			childSetTextArg("pick_title", "[NAME]",name); +			 +			// Save selection, to be able to edit same item after saving changes. See EXT-3023. +			LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID];  			mPicksList->clear(); @@ -186,6 +189,10 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)  				mPicksList->addItem(picture, pick_value); +				// Restore selection by item id.  +				if ( pick_id == selected_id ) +					mPicksList->selectItemByValue(pick_value); +  				picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickPickItem, this, _1));  				picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4));  				picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 1830d00f68..3274820174 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -220,15 +220,15 @@ void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params)  	panel->setRect(new_rect);  } -void LLPanelProfile::notifyParent(const LLSD& info) +S32 LLPanelProfile::notifyParent(const LLSD& info)  {  	std::string action = info["action"];  	// lets update Picks list after Pick was saved  	if("save_new_pick" == action)  	{  		onOpen(info); -		return; +		return 1;  	} -	LLPanel::notifyParent(info); +	return LLPanel::notifyParent(info);  } diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index 067beb248b..bcf4bdd0ec 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -55,7 +55,7 @@ public:  	virtual void openPanel(LLPanel* panel, const LLSD& params); -	void notifyParent(const LLSD& info); +	S32 notifyParent(const LLSD& info);  protected: diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 523487fa14..43f80f6d6a 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -38,6 +38,8 @@  #include "llsidetray.h"  #include "llworldmap.h"  #include "llteleporthistorystorage.h" +#include "lltextutil.h" +  #include "llaccordionctrl.h"  #include "llaccordionctrltab.h"  #include "llflatlistview.h" @@ -57,7 +59,7 @@ static const std::string COLLAPSED_BY_USER = "collapsed_by_user";  class LLTeleportHistoryFlatItem : public LLPanel  {  public: -	LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name); +	LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl);  	virtual ~LLTeleportHistoryFlatItem() {};  	virtual BOOL postBuild(); @@ -82,13 +84,15 @@ private:  	S32 mIndex;  	std::string mRegionName; +	std::string mHighlight;  }; -LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name) +LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, const std::string &hl)  :	LLPanel(),  	mIndex(index),  	mContextMenu(context_menu), -	mRegionName(region_name) +	mRegionName(region_name), +	mHighlight(hl)  {  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml");  } @@ -96,8 +100,7 @@ LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistor  //virtual  BOOL LLTeleportHistoryFlatItem::postBuild()  { -	LLTextBox *region = getChild<LLTextBox>("region"); -	region->setValue(mRegionName); +	LLTextUtil::textboxSetHighlightedVal(getChild<LLTextBox>("region"), LLStyle::Params(), mRegionName, mHighlight);  	mProfileBtn = getChild<LLButton>("profile_btn"); @@ -316,11 +319,8 @@ void LLTeleportHistoryPanel::draw()  // virtual  void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)  { -	if (sFilterSubString != string) -	{ -		sFilterSubString = string; -		showTeleportHistory(); -	} +	sFilterSubString = string; +	showTeleportHistory();  }  // virtual @@ -521,7 +521,7 @@ void LLTeleportHistoryPanel::refresh()  		if (curr_flat_view)  		{ -			LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle); +			LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, mFilterSubString);  			curr_flat_view->addItem(item);  			if (mLastSelectedItemIndex == mCurrentItem) @@ -568,7 +568,8 @@ 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 +									history_items[history_items.size() - 1].mTitle, // Most recent item, it was +									mFilterSubString);  															 // added instead of removed  	fv->addItem(item, LLUUID::null, ADD_TOP); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 24ba288c49..4f0c873c61 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -162,6 +162,8 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  	if(mControlHovering)  	{  		new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); +		new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopFadingToasts, this)); +		new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startFadingToasts, this));  	}  	if(show_toast) @@ -586,6 +588,37 @@ void LLScreenChannel::closeStartUpToast()  	}  } +void LLNotificationsUI::LLScreenChannel::stopFadingToasts() +{ +	if (!mToastList.size()) return; + +	if (!mHoveredToast) return; + +	std::vector<ToastElem>::iterator it = mToastList.begin(); +	while (it != mToastList.end()) +	{ +		ToastElem& elem = *it; +		elem.toast->stopFading(); +		++it; +	} +} + +void LLNotificationsUI::LLScreenChannel::startFadingToasts() +{ +	if (!mToastList.size()) return; + +	//because onMouseLeave is processed after onMouseEnter +	if (mHoveredToast) return; + +	std::vector<ToastElem>::iterator it = mToastList.begin(); +	while (it != mToastList.end()) +	{ +		ToastElem& elem = *it; +		elem.toast->startFading(); +		++it; +	} +} +  //--------------------------------------------------------------------------  void LLScreenChannel::hideToastsFromScreen()  { @@ -713,6 +746,8 @@ void LLScreenChannel::updateShowToastsState()  		}  	} +	// *TODO: mantipov: what we have to do with derived classes: LLNotificationWellWindow & LLIMWelWindow? +	// See EXT-3081 for details  	// for Message Well floater showed in a docked state - adjust channel's height  	if(dynamic_cast<LLSysWellWindow*>(floater))  	{ diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index f39b94b89d..67f1c9bdc6 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -184,6 +184,13 @@ public:  	// close the StartUp Toast  	void		closeStartUpToast(); + +	/** Stop fading all toasts */ +	virtual void stopFadingToasts(); + +	/** Start fading all toasts */ +	virtual void startFadingToasts(); +  	// get StartUp Toast's state  	static bool	getStartUpToastShown() { return mWasStartUpToastShown; }  	// tell all channels that the StartUp toast was shown and allow them showing of toasts diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 088884178b..8de99a48aa 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -207,11 +207,22 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  		return;  	} +	// Need to indicate of "new message" for object chiclets according to requirements +	// specified in the Message Bar design specification. See EXT-3142. +	bool set_new_message = false; +  	// If an Object spawns more-than-one floater, only the newest one is shown.   	// The previous is automatically closed.  	script_notification_map_t::iterator it = mNotifications.find(object_id);  	if(it != mNotifications.end())  	{ +		LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->second.notification_id); +		if(floater) +		{ +			// Generate chiclet with a "new message" indicator if a docked window was opened. See EXT-3142. +			set_new_message = floater->isShown(); +		} +  		onRemoveNotification(it->second.notification_id);  	} @@ -229,7 +240,7 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  		LLBottomTray::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(object_id);  	} -	toggleScriptFloater(object_id); +	toggleScriptFloater(object_id, set_new_message);  }  void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) @@ -278,13 +289,13 @@ void LLScriptFloaterManager::removeNotificationByObjectId(const LLUUID& object_i  	}  } -void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id) +void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool set_new_message)  {  	// hide "new message" icon from chiclet  	LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id);  	if(chiclet)  	{ -		chiclet->setShowNewMessagesIcon(false); +		chiclet->setShowNewMessagesIcon(set_new_message);  	}  	// kill toast diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index 8b5a266691..8de7a28d0f 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -70,7 +70,7 @@ public:  	 * Toggles script floater.  	 * Removes "new message" icon from chiclet and removes notification toast.  	 */ -	void toggleScriptFloater(const LLUUID& object_id); +	void toggleScriptFloater(const LLUUID& object_id, bool set_new_message = false);  	LLUUID findObjectId(const LLUUID& notification_id); diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index cf2f6992d5..de2cfe9711 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -103,6 +103,11 @@ public:      LLPanel*	getActivePanel	();      bool		isPanelActive	(const std::string& panel_name);  	/* +	 * get currently active tab +	 */ +    const LLSideTrayTab*	getActiveTab() const { return mActiveTab; } + +	/*       * collapse SideBar, hiding visible tab and moving tab buttons       * to the right corner of the screen       */ diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 539536b527..bef7f5d6aa 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -33,6 +33,7 @@  #include "llviewerprecompiledheaders.h" // must be first include  #include "llflatlistview.h" +#include "llfloaterreg.h"  #include "llsyswellwindow.h" @@ -44,16 +45,15 @@  #include "lltoastpanel.h"  #include "llnotificationmanager.h" -  //---------------------------------------------------------------------------------  LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),  													mChannel(NULL),  													mMessageList(NULL), -													mSeparator(NULL) -{ -	LLIMMgr::getInstance()->addSessionObserver(this); -	LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLSysWellWindow::findIMChiclet, this, _1)); +													mSeparator(NULL), +													NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), +													IM_WELL_ANCHOR_NAME("im_well_panel") +{  	mTypedItemsCount[IT_NOTIFICATION] = 0;  	mTypedItemsCount[IT_INSTANT_MESSAGE] = 0;  } @@ -63,11 +63,6 @@ BOOL LLSysWellWindow::postBuild()  {  	mMessageList = getChild<LLFlatListView>("notification_list"); -	// init connections to the list's update events -	connectListUpdaterToSignal("notify"); -	connectListUpdaterToSignal("groupnotify"); -	connectListUpdaterToSignal("offer"); -  	// get a corresponding channel  	initChannel(); @@ -89,81 +84,19 @@ BOOL LLSysWellWindow::postBuild()  //---------------------------------------------------------------------------------  void LLSysWellWindow::setMinimized(BOOL minimize)  { -	// we don't show empty Message Well window -	if (!minimize && isWindowEmpty()) -	{ -		return; -	} -  	LLDockableFloater::setMinimized(minimize);  }  //--------------------------------------------------------------------------------- -void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNotificationIDCallback(boost::bind(&LLSysWellWindow::removeItemByID, this, _1)); -	} -	else -	{ -		llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; -	} -} - -//---------------------------------------------------------------------------------  void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)  { -	onChicletClick(); -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::onChicletClick() -{ -	// 1 - remove StartUp toast and channel if present -	if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) -	{ -		LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); -	} - -	// 2 - toggle instance of SysWell's chiclet-window -	toggleWindow(); +	// just set floater visible. Screen channels will be cleared. +	setVisible(TRUE);  }  //---------------------------------------------------------------------------------  LLSysWellWindow::~LLSysWellWindow()  { -	LLIMMgr::getInstance()->removeSessionObserver(this); -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::addItem(LLSysWellItem::Params p) -{ -	LLSD value = p.notification_id; -	// do not add clones -	if( mMessageList->getItemByValue(value)) -		return; - -	LLSysWellItem* new_item = new LLSysWellItem(p); -	if (mMessageList->addItem(new_item, value, ADD_TOP)) -	{ -		handleItemAdded(IT_NOTIFICATION); - -		reshapeWindow(); - -		new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); -		new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); -	} -	else -	{ -		llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id -			<< ", title: " << p.title -			<< llendl; - -		new_item->die(); -	}  }  //--------------------------------------------------------------------------------- @@ -194,42 +127,13 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)  }  //--------------------------------------------------------------------------------- -void LLSysWellWindow::onItemClick(LLSysWellItem* item) -{ -	LLUUID id = item->getID(); -	if(mChannel) -		mChannel->loadStoredToastByNotificationIDToChannel(id); -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::onItemClose(LLSysWellItem* item) -{ -	LLUUID id = item->getID(); -	removeItemByID(id); -	if(mChannel) -		mChannel->killToastByNotificationID(id); -} - -//-------------------------------------------------------------------------- -void LLSysWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) -{ -	LLSysWellItem::Params p;	 -	p.notification_id = id; -	p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); -	addItem(p); -} -  //---------------------------------------------------------------------------------  void LLSysWellWindow::initChannel()   {  	LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(  																LLUUID(gSavedSettings.getString("NotificationChannelUUID")));  	mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); -	if(mChannel) -	{ -		mChannel->setOnStoreToastCallback(boost::bind(&LLSysWellWindow::onStoreToast, this, _1, _2)); -	} -	else +	if(NULL == mChannel)  	{  		llwarns << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << llendl;  	} @@ -242,57 +146,24 @@ void LLSysWellWindow::getAllowedRect(LLRect& rect)  }  //--------------------------------------------------------------------------------- -void LLSysWellWindow::toggleWindow() -{ -	if (getDockControl() == NULL) -	{ -		setDockControl(new LLDockControl( -				LLBottomTray::getInstance()->getSysWell(), this, -				getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1))); -	} -	if(!getVisible() || isMinimized()) -	{ -		if(mChannel) -		{ -			mChannel->removeAndStoreAllStorableToasts(); -		} -		if(isWindowEmpty()) -		{ -			return; -		} - -		setVisible(TRUE); -	} -	else if (isDocked()) -	{ -		setVisible(FALSE); -	} -	else if(!isDocked()) -	{ -		// bring to front undocked floater -		setVisible(TRUE); -	} -}  //---------------------------------------------------------------------------------  void LLSysWellWindow::setVisible(BOOL visible)  { -	if(visible) +	if (visible)  	{ -		if (LLBottomTray::instanceExists()) +		if (NULL == getDockControl() && getDockTongue().notNull())  		{ -			LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE); -		} -	} -	else -	{ -		if (LLBottomTray::instanceExists()) -		{ -			LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE); +			setDockControl(new LLDockControl( +				LLBottomTray::getInstance()->getChild<LLView>(getAnchorViewName()), this, +				getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1)));  		}  	} +	// do not show empty window +	if (NULL == mMessageList || isWindowEmpty()) visible = FALSE; +  	LLDockableFloater::setVisible(visible);  	// update notification channel state	 @@ -303,6 +174,12 @@ void LLSysWellWindow::setVisible(BOOL visible)  }  //--------------------------------------------------------------------------------- +void LLSysWellWindow::onFocusLost() +{ +	setVisible(false); +} + +//---------------------------------------------------------------------------------  void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock)  {  	LLDockableFloater::setDocked(docked, pop_on_undock); @@ -347,104 +224,13 @@ void LLSysWellWindow::reshapeWindow()  }  //--------------------------------------------------------------------------------- -LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId) -{ -	LLChiclet* res = NULL; -	RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId); -	if (panel != NULL) -	{ -		res = panel->mChiclet; -	} - -	return res; -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, -		const std::string& name, const LLUUID& otherParticipantId) -{ -	RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); -	if (mMessageList->insertItemAfter(mSeparator, item, sessionId)) -	{ -		handleItemAdded(IT_INSTANT_MESSAGE); -	} -	else -	{ -		llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId -			<< ", name: " << name -			<< ", other participant ID: " << otherParticipantId -			<< llendl; - -		item->die(); -	} -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::delIMRow(const LLUUID& sessionId) -{ -	if (mMessageList->removeItemByValue(sessionId)) -	{ -		handleItemRemoved(IT_INSTANT_MESSAGE); -	} -	else -	{ -		llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId -			<< llendl; -	} - -	// remove all toasts that belong to this session from a screen -	if(mChannel) -		mChannel->removeToastsBySessionID(sessionId); - -	// hide chiclet window if there are no items left -	if(isWindowEmpty()) -	{ -		setVisible(FALSE); -	} -} - -//---------------------------------------------------------------------------------  bool LLSysWellWindow::isWindowEmpty()  {  	// keep in mind, mSeparator is always in the list  	return mMessageList->size() == 1;  } -//--------------------------------------------------------------------------------- -//virtual -void LLSysWellWindow::sessionAdded(const LLUUID& session_id, -		const std::string& name, const LLUUID& other_participant_id) -{ -	if (mMessageList->getItemByValue(session_id) == NULL) -	{ -		S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id); -		if (chicletCounter > -1) -		{ -			addIMRow(session_id, chicletCounter, name, other_participant_id);	 -			reshapeWindow(); -		} -	} -} - -//--------------------------------------------------------------------------------- -//virtual -void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) -{ -	delIMRow(sessionId); -	reshapeWindow(); -} - -void LLSysWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) -{ -	//for outgoing ad-hoc and group im sessions only -	LLChiclet* chiclet = findIMChiclet(old_session_id); -	if (chiclet) -	{ -		chiclet->setSessionId(new_session_id); -		mMessageList->updateValue(old_session_id, new_session_id); -	} -} - +// *TODO: mantipov: probably is deprecated  void LLSysWellWindow::handleItemAdded(EItemType added_item_type)  {  	bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type); @@ -492,8 +278,12 @@ bool LLSysWellWindow::anotherTypeExists(EItemType item_type)  	return exists;  } +/************************************************************************/ +/*         RowPanel implementation                                      */ +/************************************************************************/ +  //--------------------------------------------------------------------------------- -LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, +LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId,  		S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) :  		LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent)  { @@ -528,36 +318,36 @@ LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&  	contactName->setValue(name);  	mCloseBtn = getChild<LLButton>("hide_btn"); -	mCloseBtn->setCommitCallback(boost::bind(&LLSysWellWindow::RowPanel::onClosePanel, this)); +	mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this));  }  //--------------------------------------------------------------------------------- -LLSysWellWindow::RowPanel::~RowPanel() +LLIMWellWindow::RowPanel::~RowPanel()  {  }  //--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::onClosePanel() +void LLIMWellWindow::RowPanel::onClosePanel()  {  	gIMMgr->leaveSession(mChiclet->getSessionId());  	// This row panel will be removed from the list in LLSysWellWindow::sessionRemoved().  }  //--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +void LLIMWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask)  {  	setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected"));  }  //--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask) +void LLIMWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask)  {  	setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected"));  }  //---------------------------------------------------------------------------------  // virtual -BOOL LLSysWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask)  {  	// Pass the mouse down event to the chiclet (EXT-596).  	if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() @@ -566,4 +356,263 @@ BOOL LLSysWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask)  	return LLPanel::handleMouseDown(x, y, mask);  } + + +/************************************************************************/ +/*         LLNotificationWellWindow implementation                      */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) +: LLSysWellWindow(key) +{ +	// init connections to the list's update events +	connectListUpdaterToSignal("notify"); +	connectListUpdaterToSignal("groupnotify"); +	connectListUpdaterToSignal("offer"); +} + +// static +LLNotificationWellWindow* LLNotificationWellWindow::getInstance(const LLSD& key /*= LLSD()*/) +{ +	return LLFloaterReg::getTypedInstance<LLNotificationWellWindow>("notification_well_window", key); +} + +// virtual +BOOL LLNotificationWellWindow::postBuild() +{ +	BOOL rv = LLSysWellWindow::postBuild(); +	setTitle(getString("title_notification_well_window")); +	return rv; +} + +// virtual +void LLNotificationWellWindow::setVisible(BOOL visible) +{ +	if (visible) +	{ +		// when Notification channel is cleared, storable toasts will be added into the list. +		clearScreenChannels(); +	} + +	LLSysWellWindow::setVisible(visible); +} + +//--------------------------------------------------------------------------------- +void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) +{ +	LLSD value = p.notification_id; +	// do not add clones +	if( mMessageList->getItemByValue(value)) +		return; + +	LLSysWellItem* new_item = new LLSysWellItem(p); +	if (mMessageList->addItem(new_item, value, ADD_TOP)) +	{ +		handleItemAdded(IT_NOTIFICATION); + +		reshapeWindow(); + +		new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1)); +		new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1)); +	} +	else +	{ +		llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id +			<< ", title: " << p.title +			<< llendl; + +		new_item->die(); +	} +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +void LLNotificationWellWindow::initChannel()  +{ +	LLSysWellWindow::initChannel(); +	if(mChannel) +	{ +		mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); +	} +} + +void LLNotificationWellWindow::clearScreenChannels() +{ +	// 1 - remove StartUp toast and channel if present +	if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) +	{ +		LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); +	} + +	// 2 - remove toasts in Notification channel +	if(mChannel) +	{ +		mChannel->removeAndStoreAllStorableToasts(); +	} +} + +void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) +{ +	LLSysWellItem::Params p;	 +	p.notification_id = id; +	p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); +	addItem(p); +} + +void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) +{ +	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); +	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); +	if(n_handler) +	{ +		n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); +	} +	else +	{ +		llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; +	} +} + +void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) +{ +	LLUUID id = item->getID(); +	if(mChannel) +		mChannel->loadStoredToastByNotificationIDToChannel(id); +} + +void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) +{ +	LLUUID id = item->getID(); +	removeItemByID(id); +	if(mChannel) +		mChannel->killToastByNotificationID(id); +} + + + +/************************************************************************/ +/*         LLIMWellWindow  implementation                               */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +LLIMWellWindow::LLIMWellWindow(const LLSD& key) +: LLSysWellWindow(key) +{ +	LLIMMgr::getInstance()->addSessionObserver(this); +	LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1)); +} + +LLIMWellWindow::~LLIMWellWindow() +{ +	LLIMMgr::getInstance()->removeSessionObserver(this); +} + +// static +LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/) +{ +	return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key); +} + +BOOL LLIMWellWindow::postBuild() +{ +	BOOL rv = LLSysWellWindow::postBuild(); +	setTitle(getString("title_im_well_window")); +	return rv; +} + +//virtual +void LLIMWellWindow::sessionAdded(const LLUUID& session_id, +								   const std::string& name, const LLUUID& other_participant_id) +{ +	if (mMessageList->getItemByValue(session_id) == NULL) +	{ +		S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id); +		if (chicletCounter > -1) +		{ +			addIMRow(session_id, chicletCounter, name, other_participant_id);	 +			reshapeWindow(); +		} +	} +} + +//virtual +void LLIMWellWindow::sessionRemoved(const LLUUID& sessionId) +{ +	delIMRow(sessionId); +	reshapeWindow(); +} + +//virtual +void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ +	//for outgoing ad-hoc and group im sessions only +	LLChiclet* chiclet = findIMChiclet(old_session_id); +	if (chiclet) +	{ +		chiclet->setSessionId(new_session_id); +		mMessageList->updateValue(old_session_id, new_session_id); +	} +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId) +{ +	LLChiclet* res = NULL; +	RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId); +	if (panel != NULL) +	{ +		res = panel->mChiclet; +	} + +	return res; +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, +							   const std::string& name, const LLUUID& otherParticipantId) +{ +	RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); +	if (mMessageList->insertItemAfter(mSeparator, item, sessionId)) +	{ +		handleItemAdded(IT_INSTANT_MESSAGE); +	} +	else +	{ +		llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId +			<< ", name: " << name +			<< ", other participant ID: " << otherParticipantId +			<< llendl; + +		item->die(); +	} +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::delIMRow(const LLUUID& sessionId) +{ +	if (mMessageList->removeItemByValue(sessionId)) +	{ +		handleItemRemoved(IT_INSTANT_MESSAGE); +	} +	else +	{ +		llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId +			<< llendl; +	} + +	// remove all toasts that belong to this session from a screen +	if(mChannel) +		mChannel->removeToastsBySessionID(sessionId); + +	// hide chiclet window if there are no items left +	if(isWindowEmpty()) +	{ +		setVisible(FALSE); +	} +} +  // EOF diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 3e4cdbdcbe..adbc83677d 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -47,7 +47,9 @@ class LLFlatListView;  class LLChiclet;  class LLIMChiclet; -class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver + + +class LLSysWellWindow : public LLDockableFloater  {  public:      LLSysWellWindow(const LLSD& key); @@ -59,31 +61,28 @@ public:  	bool isWindowEmpty();  	// Operating with items -	void addItem(LLSysWellItem::Params p);      void clear( void );  	void removeItemByID(const LLUUID& id);  	// Operating with outfit  	virtual void setVisible(BOOL visible);  	void adjustWindowPosition(); -	void toggleWindow(); -	/*virtual*/ BOOL	canClose() { return FALSE; }  	/*virtual*/ void	setDocked(bool docked, bool pop_on_undock = true);  	// override LLFloater's minimization according to EXT-1216  	/*virtual*/ void	setMinimized(BOOL minimize); -	// Handlers -	void onItemClick(LLSysWellItem* item); -	void onItemClose(LLSysWellItem* item); -	void onStoreToast(LLPanel* info_panel, LLUUID id); -	void onChicletClick(); +	/**  +	 * Hides window when user clicks away from it (EXT-3084) +	 */ +	/*virtual*/ void onFocusLost(); +  	void onStartUpToastClick(S32 x, S32 y, MASK mask);  	// size constants for the window and for its elements  	static const S32 MAX_WINDOW_HEIGHT		= 200;  	static const S32 MIN_WINDOW_WIDTH		= 318; -private: +protected:  	typedef enum{  		IT_NOTIFICATION, @@ -92,25 +91,19 @@ private:  	// gets a rect that bounds possible positions for the SysWellWindow on a screen (EXT-1111)  	void getAllowedRect(LLRect& rect); -	// connect counter and list updaters to the corresponding signals -	void connectListUpdaterToSignal(std::string notification_type); + +  	// init Window's channel -	void initChannel(); +	virtual void initChannel();  	void handleItemAdded(EItemType added_item_type);  	void handleItemRemoved(EItemType removed_item_type);  	bool anotherTypeExists(EItemType item_type) ; +	const std::string NOTIFICATION_WELL_ANCHOR_NAME; +	const std::string IM_WELL_ANCHOR_NAME; +	virtual const std::string& getAnchorViewName() = 0; - -	class RowPanel;  	void reshapeWindow(); -	LLChiclet * findIMChiclet(const LLUUID& sessionId); -	void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); -	void delIMRow(const LLUUID& sessionId); -	// LLIMSessionObserver observe triggers -	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); -	virtual void sessionRemoved(const LLUUID& session_id); -	void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);  	// pointer to a corresponding channel's instance  	LLNotificationsUI::LLScreenChannel*	mChannel; @@ -126,7 +119,77 @@ private:  	typedef std::map<EItemType, S32> typed_items_count_t;  	typed_items_count_t mTypedItemsCount; +}; + +/** + * Class intended to manage incoming notifications. + *  + * It contains a list of notifications that have not been responded to. + */ +class LLNotificationWellWindow : public LLSysWellWindow, public LLInitClass<LLNotificationWellWindow> +{ +public: +	LLNotificationWellWindow(const LLSD& key); +	static LLNotificationWellWindow* getInstance(const LLSD& key = LLSD()); + +	static void initClass() { getInstance(); } + +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void setVisible(BOOL visible); + +	// Operating with items +	void addItem(LLSysWellItem::Params p); + +protected: +	/*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; } + +private: +	// init Window's channel +	void initChannel(); +	void clearScreenChannels(); + + +	void onStoreToast(LLPanel* info_panel, LLUUID id); + +	// connect counter and list updaters to the corresponding signals +	void connectListUpdaterToSignal(std::string notification_type); + +	// Handlers +	void onItemClick(LLSysWellItem* item); +	void onItemClose(LLSysWellItem* item); + +}; + +/** + * Class intended to manage incoming messages in IM chats. + *  + * It contains a list list of all active IM sessions. + */ +class LLIMWellWindow : public LLSysWellWindow, LLIMSessionObserver, LLInitClass<LLIMWellWindow> +{ +public: +	LLIMWellWindow(const LLSD& key); +	~LLIMWellWindow(); + +	static LLIMWellWindow* getInstance(const LLSD& key = LLSD()); +	static void initClass() { getInstance(); } + +	/*virtual*/ BOOL postBuild(); + +	// LLIMSessionObserver observe triggers +	/*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id); +	/*virtual*/ void sessionRemoved(const LLUUID& session_id); +	/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id); + +protected: +	/*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; } +  private: +	LLChiclet * findIMChiclet(const LLUUID& sessionId); +	void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); +	void delIMRow(const LLUUID& sessionId); + +  	/**  	 * Scrolling row panel.  	 */ diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index bf485b7e65..fc7c029a17 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -244,15 +244,15 @@ void LLToast::onMouseEnter(S32 x, S32 y, MASK mask)  	mOnToastHoverSignal(this, MOUSE_ENTER);  	setBackgroundOpaque(TRUE); -	if(mCanFade) -	{ -		mTimer.stop(); -	} + +	//toasts fading is management by Screen Channel  	sendChildToFront(mHideBtn);  	if(mHideBtn && mHideBtn->getEnabled())  		mHideBtn->setVisible(TRUE);  	mOnMouseEnterSignal(this); + +	LLModalDialog::onMouseEnter(x, y, mask);  }  //-------------------------------------------------------------------------- @@ -260,10 +260,8 @@ void LLToast::onMouseLeave(S32 x, S32 y, MASK mask)  {	  	mOnToastHoverSignal(this, MOUSE_LEAVE); -	if(mCanFade) -	{ -		mTimer.start(); -	} +	//toasts fading is management by Screen Channel +  	if(mHideBtn && mHideBtn->getEnabled())  	{  		if( mHideBtnPressed ) @@ -273,6 +271,25 @@ void LLToast::onMouseLeave(S32 x, S32 y, MASK mask)  		}  		mHideBtn->setVisible(FALSE);		  	} + +	LLModalDialog::onMouseLeave(x, y, mask); +} + + +void LLNotificationsUI::LLToast::stopFading() +{ +	if(mCanFade) +	{ +		stopTimer(); +	} +} + +void LLNotificationsUI::LLToast::startFading() +{ +	if(mCanFade) +	{ +		resetTimer(); +	}  }  //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 769b2ba122..d08e46e160 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -88,6 +88,15 @@ public:  	virtual void onMouseEnter(S32 x, S32 y, MASK mask);  	virtual void onMouseLeave(S32 x, S32 y, MASK mask); +	//Fading + +	/** Stop fading timer */ +	virtual void stopFading(); + +	/** Start fading timer */ +	virtual void startFading(); + +  	// Operating with toasts  	// insert a panel to a toast  	void insertPanel(LLPanel* panel); diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index f928b5f243..7beba59c83 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -40,8 +40,7 @@ const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT	= 6;  //--------------------------------------------------------------------------  LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notification),  															mAvatar(NULL), mUserName(NULL), -															mTime(NULL), mMessage(NULL), -															mReplyBtn(NULL) +															mTime(NULL), mMessage(NULL)  {  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_instant_message.xml"); @@ -50,7 +49,6 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  	mUserName = getChild<LLTextBox>("user_name");  	mTime = getChild<LLTextBox>("time_box");  	mMessage = getChild<LLTextBox>("message"); -	mReplyBtn = getChild<LLButton>("reply");	  	LLStyle::Params style_params;  	style_params.font.name(LLFontGL::nameFromFont(style_params.font)); @@ -76,18 +74,10 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  	mSessionID = p.session_id;  	mNotification = p.notification; -	// if message comes from the system - there shouldn't be a reply btn  	if(p.from == SYSTEM_FROM)  	{  		mAvatar->setVisible(FALSE);  		sys_msg_icon->setVisible(TRUE); - -		mReplyBtn->setVisible(FALSE); -		S32 btn_height = mReplyBtn->getRect().getHeight(); -		LLRect msg_rect = mMessage->getRect(); -		mMessage->reshape(msg_rect.getWidth(), msg_rect.getHeight() + btn_height); -		msg_rect.setLeftTopAndSize(msg_rect.mLeft, msg_rect.mTop, msg_rect.getWidth(), msg_rect.getHeight() + btn_height); -		mMessage->setRect(msg_rect);  	}  	else  	{ @@ -95,7 +85,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) :	LLToastPanel(p.notif  		sys_msg_icon->setVisible(FALSE);  		mAvatar->setValue(p.avatar_id); -		mReplyBtn->setClickedCallback(boost::bind(&LLToastIMPanel::onClickReplyBtn, this)); +		setMouseDownCallback(boost::bind(&LLToastIMPanel::onClickToastIM, this));  	}  	S32 maxLinesCount; @@ -113,7 +103,7 @@ LLToastIMPanel::~LLToastIMPanel()  }  //-------------------------------------------------------------------------- -void LLToastIMPanel::onClickReplyBtn() +void LLToastIMPanel::onClickToastIM()  {  	mNotification->respond(mNotification->getResponseTemplate());  } diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index af21b07a3d..23f08ef610 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -61,7 +61,7 @@ public:  private:  	static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT; -	void onClickReplyBtn(); +	void onClickToastIM();  	LLNotificationPtr	mNotification;  	LLUUID				mSessionID; @@ -69,7 +69,6 @@ private:  	LLTextBox*			mUserName;  	LLTextBox*			mTime;  	LLTextBox*			mMessage; -	LLButton*			mReplyBtn;  };  #endif // LLTOASTIMPANEL_H_ diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 158c857031..35c9a1d367 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -176,6 +176,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);  	LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>); +	LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>);  	LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);  	LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>);  	LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>); @@ -195,11 +196,10 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);  	LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);  	LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>); -	LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>);  	LLFloaterReg::add("nearby_media", "floater_nearby_media.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNearbyMedia>); -	  	LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>); +	LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);  	LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);  	LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 5da77ecdb9..4482683400 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -85,7 +85,8 @@ public:  		{  			std::vector<LLUUID> items_to_open;  			items_to_open.push_back(inventory_id); -			open_inventory_offer(items_to_open, ""); +			//inventory_handler is just a stub, because we don't know from who this offer +			open_inventory_offer(items_to_open, "inventory_handler");  			return true;  		} diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 507e34348b..8c0529e344 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -74,6 +74,7 @@  #include "llimview.h"  #include "lltrans.h"  #include "llviewerfoldertype.h" +#include "lluri.h"  #include "llviewergenericmessage.h"  #include "llviewermenu.h"  #include "llviewerobjectlist.h" @@ -859,6 +860,7 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f  		const LLAssetType::EType asset_type = item->getType();  		if (check_offer_throttle(from_name, false)) // If we are throttled, don't display  		{ +			LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID()  << LL_ENDL;  			// If we opened this ourselves, focus it  			const BOOL take_focus = from_name.empty() ? TAKE_FOCUS_YES : TAKE_FOCUS_NO;  			switch(asset_type) @@ -871,18 +873,28 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f  			  case LLAssetType::AT_LANDMARK:  			  	{  					LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID()); -					LLSD args; -					args["LANDMARK_NAME"] = item->getName(); -					args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown"); -					LLNotificationsUtil::add("LandmarkCreated", args); - -					// Created landmark is passed to Places panel to allow its editing. -					LLPanelPlaces *places_panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", LLSD())); -					if (places_panel) +					if ("inventory_handler" == from_name)  					{ -						places_panel->setItem(item); +						//we have to filter inventory_handler messages to avoid notification displaying +						LLSideTray::getInstance()->showPanel("panel_places",  +								LLSD().with("type", "landmark").with("id", item->getUUID()));  					} -			  	} +					else if(from_name.empty()) +					{ +						// we receive a message from LLOpenTaskOffer, it mean that new landmark has been added. +						LLSD args; +						args["LANDMARK_NAME"] = item->getName(); +						args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown"); +						LLNotificationsUtil::add("LandmarkCreated", args); +						// Created landmark is passed to Places panel to allow its editing. In fact panel should be already displayed. +						//TODO*:: dserduk(7/12/09) remove LLPanelPlaces dependency from here +						LLPanelPlaces *places_panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", LLSD())); +						if (places_panel) +						{ +							places_panel->setItem(item); +						} +					} +				}  				break;  			  case LLAssetType::AT_TEXTURE:  			  { @@ -1448,7 +1460,7 @@ void inventory_offer_handler(LLOfferInfo* info)  	args["OBJECTFROMNAME"] = info->mFromName;  	args["NAME"] = info->mFromName;  	args["NAME_SLURL"] = LLSLURL::buildCommand("agent", info->mFromID, "about"); -	std::string verb = "select?name=" + msg; +	std::string verb = "select?name=" + LLURI::escape(msg);  	args["ITEM_SLURL"] = LLSLURL::buildCommand("inventory", info->mObjectID, verb.c_str());  	LLNotification::Params p("ObjectGiveItem"); @@ -1487,14 +1499,15 @@ void inventory_offer_handler(LLOfferInfo* info)  	}  	// Pop up inv offer notification and let the user accept (keep), or reject (and silently delete) the inventory. -	 LLNotifications::instance().add(p); +	LLNotifications::instance().add(p); +	// TODO(EM): Recheck this after we will know how script notifications should look like.  	// Inform user that there is a script floater via toast system -	{ -		payload["give_inventory_notification"] = TRUE; -		LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload));  -		LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID()); -	} +	// { +	// 	payload["give_inventory_notification"] = TRUE; +	// 	LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload));  +	// 	LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID()); +	// }  }  bool lure_callback(const LLSD& notification, const LLSD& response) @@ -1997,13 +2010,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  	case IM_INVENTORY_ACCEPTED:  	{  		args["NAME"] = name; -		LLNotificationsUtil::add("InventoryAccepted", args); +		LLSD payload; +		payload["from_id"] = from_id; +		LLNotificationsUtil::add("InventoryAccepted", args, payload);  		break;  	}  	case IM_INVENTORY_DECLINED:  	{  		args["NAME"] = name; -		LLNotificationsUtil::add("InventoryDeclined", args); +		LLSD payload; +		payload["from_id"] = from_id; +		LLNotificationsUtil::add("InventoryDeclined", args, payload);  		break;  	}  	// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856 diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 608060174a..175b6f1d10 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -316,6 +316,8 @@ void LLVoiceChannel::activate()  		}  	} +	sCurrentVoiceChannelChangedSignal(this->mSessionID); +  	if (mState == STATE_NO_CHANNEL_INFO)  	{  		// responsible for setting status to active @@ -325,8 +327,6 @@ void LLVoiceChannel::activate()  	{  		setState(STATE_CALL_STARTED);  	} - -	sCurrentVoiceChannelChangedSignal(this->mSessionID);  }  void LLVoiceChannel::getChannelInfo() @@ -874,61 +874,6 @@ void LLVoiceChannelP2P::setState(EState state)  			return;  		}  	} -	else // outgoing call -	{ -		mCallDialogPayload["session_id"] = mSessionID; -		mCallDialogPayload["session_name"] = mSessionName; -		mCallDialogPayload["other_user_id"] = mOtherUserID; -		if (state == STATE_RINGING || -		    state == STATE_CALL_STARTED) -		{ -			// *HACK: open outgoing call floater if needed, might be better done elsewhere. -			// *TODO: should move this squirrelly ui-fudging crap into LLOutgoingCallDialog itself -			if (!mSessionName.empty()) -			{ -				LLOutgoingCallDialog *ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); -				if (ocd) -				{ -					ocd->getChild<LLTextBox>("calling")->setVisible(true); -					ocd->getChild<LLTextBox>("leaving")->setVisible(true); -					ocd->getChild<LLTextBox>("connecting")->setVisible(false); -					ocd->getChild<LLTextBox>("noanswer")->setVisible(false); -				} -			} -		} -		/*else if (state == STATE_CONNECTED) -		{ -				LLOutgoingCallDialog *ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); -				if (ocd) -				{ -					ocd->getChild<LLTextBox>("calling")->setVisible(false); -					ocd->getChild<LLTextBox>("leaving")->setVisible(false); -					ocd->getChild<LLTextBox>("connecting")->setVisible(true); -					ocd->getChild<LLTextBox>("noanswer")->setVisible(false); -				}			 -				}*/ -		else if (state == STATE_ERROR) -		{ -			LLOutgoingCallDialog *ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); -			if (ocd) -			{ -				ocd->getChild<LLTextBox>("calling")->setVisible(false); -				ocd->getChild<LLTextBox>("leaving")->setVisible(false); -				ocd->getChild<LLTextBox>("connecting")->setVisible(false); -				ocd->getChild<LLTextBox>("noanswer")->setVisible(true); -			}			 -		} -		else if (state == STATE_HUNG_UP || -			 state == STATE_CONNECTED) -		{ -			// hide popup -			LLOutgoingCallDialog *ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE)); -			if (ocd) -			{ -				ocd->closeFloater(); -			}			 -		} -	}  	LLVoiceChannel::setState(state);  } diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b1116dc0d2..7e309d2bad 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -204,9 +204,6 @@ with the same filename but different name    <texture name="Icon_Restore_Foreground" file_name="windows/Icon_Restore_Foreground.png" preload="false" />    <texture name="Icon_Restore_Press" file_name="windows/Icon_Restore_Press.png" preload="false" /> -  <texture name="Icon_Undock_Foreground" file_name="windows/Icon_Undock_Foreground.png" preload="false" /> -  <texture name="Icon_Undock_Press" file_name="windows/Icon_Undock_Press.png" preload="false" /> -    <texture name="Info" file_name="icons/Info.png" preload="false" />    <texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />    <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" /> @@ -483,6 +480,7 @@ with the same filename but different name    <texture name="SliderThumb_Off" file_name="widgets/SliderThumb_Off.png" />    <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />    <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" /> +  <texture name="SL_Logo" file_name="map_infohub.tga" />    <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />    <texture name="Snapshot_Over" file_name="bottomtray/Snapshot_Over.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml index be6d63716c..3fc57372de 100644 --- a/indra/newview/skins/default/xui/en/floater_sys_well.xml +++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml @@ -6,20 +6,30 @@   top="0"    follows="right|bottom"   layout="topleft" - name="notification_chiclet" + name="sys_well_window"   help_topic="notification_chiclet"   save_rect="true"   title="NOTIFICATIONS"    width="320"   min_width="320"   height="23" - can_minimize="true" + can_minimize="false"   can_tear_off="false"   can_resize="true"   can_drag_on_left="false" - can_close="false"   can_dock="true" + save_visibility="true" + single_instance="true"  > +    <string +     name="title_im_well_window"> +        IM SESSIONS +    </string> +    <string +     name="title_notification_well_window"> +        NOTIFICATIONS +    </string> +           <flat_list_view  	    color="FloaterDefaultBackgroundColor"  	    follows="all" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d8eb65322b..f659062cfe 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4499,14 +4499,14 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryAccepted" -   type="notifytip"> +   type="offer">  [NAME] received your inventory offer.    </notification>    <notification     icon="notifytip.tga"     name="InventoryDeclined" -   type="notifytip"> +   type="offer">  [NAME] declined your inventory offer.    </notification> @@ -5128,6 +5128,13 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O         text="Decline"/>      </form>    </notification> +   +  <notification +   icon="notify.tga" +   name="FriendshipOffered" +   type="offer"> +	You have offered friendship to [TO_NAME] +  </notification>    <notification     icon="notify.tga" diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index ec3f7ea7c5..7f847237ce 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -319,38 +319,82 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.           layout="topleft"           min_height="28"           top="0" -         name="sys_well_panel" -         width="54" -         min_width="54" +         name="im_well_panel" +         width="34" +         min_width="34" +         user_resize="false"> +            <chiclet_im_well +             follows="right" +             height="23" +             layout="topleft" +             left="0" +             name="im_well" +             top="4" +             width="34"> +                <button +                 auto_resize="true" +                 flash_color="EmphasisColor" +                 follows="right" +                 halign="center" +                 height="23" +                 image_overlay="Notices_Unread" +                 image_overlay_alignment="center"  +                 image_pressed="PushButton_Press" +                 image_pressed_selected="PushButton_Selected_Press" +                 image_selected="PushButton_Selected_Press" +                 left="0" +                 name="Unread IM messages" +                 pad_left="0" +                 pad_right="0" +                 width="34" > +                    <button.init_callback +                     function="Button.SetDockableFloaterToggle" +                     parameter="im_well_window" /> +                </button> +            </chiclet_im_well> +        </layout_panel> +        <layout_panel +         auto_resize="false" +         follows="right" +         height="28" +         layout="topleft" +         min_height="28" +         top="0" +         name="notification_well_panel" +         width="34" +         min_width="34"           user_resize="false">              <chiclet_notification               follows="right"               height="23"               layout="topleft"               left="0" -             name="sys_well" +             name="notification_well"               top="4" -             width="54"> +             width="34">                <button                   image_selected="PushButton_Selected_Press"                   image_pressed="PushButton_Press"  		 image_pressed_selected="PushButton_Selected_Press"                auto_resize="true" -               halign="right" +               halign="center"                 height="23"                 follows="right"                 flash_color="EmphasisColor"                 left="0"                 name="Unread"                 image_overlay="Notices_Unread" -               image_overlay_alignment="right"  -               pad_right="6" -               pad_left="6" -               width="54" -               /> +               image_overlay_alignment="center"  +               pad_right="0" +               pad_left="0" +               width="34" > +                  <button.init_callback +                   function="Button.SetDockableFloaterToggle" +                   parameter="notification_well_window" /> +              </button>  	    </chiclet_notification>          </layout_panel> -       <icon +        <icon           auto_resize="false"           color="0 0 0 0"           follows="left|right" diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index a833ad97d9..bbf86089cb 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -51,6 +51,10 @@         http://www.secondlife.com/account/partners.php?lang=en     </string>     <string +    name="my_account_link_url"> +       http://secondlife.com/my +   </string> +   <string      name="no_partner_text"      value="None" />   <scroll_container @@ -256,7 +260,7 @@           layout="topleft"           left="10"           name="my_account_link" -	 value="Go to My Dashboard" +         value="[[URL] Go to My Dashboard]"           width="285" />          <text           follows="left|top|right" diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index 5bae5c2711..a5bab3232c 100644 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -367,7 +367,7 @@ things in this group. There's a broad variety of Abilities.          <text_editor           type="string"           halign="left" -         height="50" +         height="35"           layout="topleft"           left="0"           max_length="295" @@ -426,6 +426,10 @@ things in this group. There's a broad variety of Abilities.           width="300">              <scroll_list.columns               label="" +             name="icon" +             width="2" /> +            <scroll_list.columns +             label=""               name="checkbox"               width="20" />              <scroll_list.columns diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml index 1e570bf207..ccd754ac5e 100644 --- a/indra/newview/skins/default/xui/en/panel_instant_message.xml +++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   background_visible="true" - height="175" + height="152"   label="im_panel"   layout="topleft"   left="0" @@ -83,13 +83,4 @@       width="285"       word_wrap="true"       max_length="350" /> -    <button -     follows="bottom" -     height="23" -     label="Reply" -     layout="topleft" -     left="100" -     name="reply" -     top="144" -     width="100" />  </panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2449820958..df991b173a 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -88,7 +88,6 @@  	<string name="BUTTON_MINIMIZE">Minimize</string>  	<string name="BUTTON_TEAR_OFF">Tear Off</string>  	<string name="BUTTON_DOCK">Dock</string> -	<string name="BUTTON_UNDOCK">Undock</string>  	<string name="BUTTON_HELP">Show Help</string>  	<!-- searching - generic --> diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index b2bd9c38c9..19fb520b44 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -16,13 +16,11 @@   minimize_image="Icon_Minimize_Foreground"   tear_off_image="tearoffbox.tga"   dock_image="Icon_Dock_Foreground" - undock_image="Icon_Undock_Foreground"   help_image="Icon_Help_Foreground"   close_pressed_image="Icon_Close_Press"   restore_pressed_image="Icon_Restore_Press"   minimize_pressed_image="Icon_Minimize_Press"   tear_off_pressed_image="tearoff_pressed.tga"   dock_pressed_image="Icon_Dock_Press" - undock_pressed_image="Icon_Undock_Press"   help_pressed_image="Icon_Help_Press"    /> | 
