diff options
| -rw-r--r-- | indra/llui/llfolderview.cpp | 2 | ||||
| -rwxr-xr-x | indra/llui/llfolderviewitem.cpp | 32 | ||||
| -rwxr-xr-x | indra/llui/llfolderviewitem.h | 2 | ||||
| -rw-r--r-- | indra/llui/llfolderviewmodel.h | 7 | ||||
| -rwxr-xr-x | indra/newview/llconversationview.cpp | 31 | ||||
| -rwxr-xr-x | indra/newview/llconversationview.h | 1 | ||||
| -rw-r--r-- | indra/newview/llimconversation.cpp | 193 | ||||
| -rw-r--r-- | indra/newview/llimconversation.h | 24 | ||||
| -rw-r--r-- | indra/newview/llimfloater.cpp | 57 | ||||
| -rw-r--r-- | indra/newview/llimfloater.h | 4 | ||||
| -rw-r--r-- | indra/newview/llimfloatercontainer.cpp | 157 | ||||
| -rw-r--r-- | indra/newview/llimfloatercontainer.h | 3 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_im_session.xml | 20 | ||||
| -rwxr-xr-x | indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml | 2 | 
14 files changed, 375 insertions, 160 deletions
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c31a832141..a33ffc4240 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -566,7 +566,7 @@ void LLFolderView::sanitizeSelection()  				parent_folder;  				parent_folder = parent_folder->getParentFolder())  			{ -				if (parent_folder->getViewModelItem()->potentiallyVisible()) +				if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible())  				{  					// give initial selection to first ancestor folder that potentially passes the filter  					if (!new_selection) diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 7c63cad1b7..c5231c4f08 100755 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -169,7 +169,6 @@ BOOL LLFolderViewItem::postBuild()  // Destroys the object  LLFolderViewItem::~LLFolderViewItem( void )  { -	delete mViewModelItem;  	mViewModelItem = NULL;  } @@ -473,8 +472,9 @@ void LLFolderViewItem::rename(const std::string& new_name)  const std::string& LLFolderViewItem::getName( void ) const  { -	return getViewModelItem()->getName(); -	} +	static const std::string noName(""); +	return getViewModelItem() ? getViewModelItem()->getName() : noName; +}  // LLView functionality  BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) @@ -1563,7 +1563,7 @@ BOOL LLFolderViewFolder::isRemovable()  void LLFolderViewFolder::addItem(LLFolderViewItem* item)  {  	if (item->getParentFolder()) -{ +	{  		item->getParentFolder()->extractItem(item);  	}  	item->setParentFolder(this); @@ -1574,7 +1574,13 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item)  	item->setVisible(FALSE);  	addChild(item); -	getViewModelItem()->addChild(item->getViewModelItem()); + +	// When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it +	// Note: this happens when models are created before views or shared between views +	if (!item->getViewModelItem()->hasParent()) +	{ +		getViewModelItem()->addChild(item->getViewModelItem()); +	}  	//TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria  	//// Traverse parent folders and update creation date and resort, if necessary @@ -1593,11 +1599,11 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item)  // this is an internal method used for adding items to folders.   void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -	{ +{  	if (folder->mParentFolder) -		{ +	{  		folder->mParentFolder->extractItem(folder); -		} +	}  	folder->mParentFolder = this;  	mFolders.push_back(folder);  	folder->setOrigin(0, 0); @@ -1607,9 +1613,15 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)  	//folder->requestArrange();  	//requestSort(); -	addChild( folder ); -	getViewModelItem()->addChild(folder->getViewModelItem()); +	addChild(folder); + +	// When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it +	// Note: this happens when models are created before views or shared between views +	if (!folder->getViewModelItem()->hasParent()) +	{ +		getViewModelItem()->addChild(folder->getViewModelItem());  	} +}  void LLFolderViewFolder::requestArrange()  {  diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 7cbe70fb8b..7e37e06064 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -87,7 +87,7 @@ protected:  	bool						mLabelWidthDirty;      S32                         mLabelPaddingRight;  	LLFolderViewFolder*			mParentFolder; -	LLFolderViewModelItem*		mViewModelItem; +	LLPointer<LLFolderViewModelItem> mViewModelItem;  	LLFontGL::StyleFlags		mLabelStyle;  	std::string					mLabelSuffix;  	LLUIImagePtr				mIcon, diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index c6030c9b71..7019857c0f 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -129,10 +129,11 @@ public:  // This is am abstract base class that users of the folderview classes  // would use to bridge the folder view with the underlying data -class LLFolderViewModelItem +class LLFolderViewModelItem : public LLRefCount  {  public: -	virtual ~LLFolderViewModelItem( void ) {}; +	LLFolderViewModelItem() { } +	virtual ~LLFolderViewModelItem() { }  	virtual void update() {}	//called when drawing  	virtual const std::string& getName() const = 0; @@ -201,6 +202,7 @@ public:  	virtual S32 getSortVersion() = 0;  	virtual void setSortVersion(S32 version) = 0;  	virtual void setParent(LLFolderViewModelItem* parent) = 0; +	virtual bool hasParent() = 0;  protected: @@ -331,6 +333,7 @@ public:  protected:  	virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } +	virtual bool hasParent() { return mParent != NULL; }  	S32						mSortVersion;  	bool					mPassedFilter; diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index de0c65e24f..81212a9141 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -234,9 +234,9 @@ void LLConversationViewSession::toggleOpen()  void LLConversationViewSession::selectItem()  { -	 -	LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); -	LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); +	LLFolderViewModelItem* item = mViewModelItem; +	LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); +	LLFloater* session_floater = LLIMConversation::getConversation(session_uuid);  	LLMultiFloater* host_floater = session_floater->getHost();  	if (host_floater == mContainer) @@ -250,7 +250,7 @@ void LLConversationViewSession::selectItem()  	// Set the focus on the selected floater  	session_floater->setFocus(TRUE);      // Store the active session -    LLIMFloaterContainer::getInstance()->setSelectedSession(item->getUUID()); +    LLIMFloaterContainer::getInstance()->setSelectedSession(session_uuid);  	LLFolderViewItem::selectItem(); @@ -272,8 +272,9 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)  {  	// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized  	// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here -	LLConversationItem* item = dynamic_cast<LLConversationItem*>(mViewModelItem); -	LLFloater* session_floater = LLIMConversation::getConversation(item->getUUID()); +	LLFolderViewModelItem* item = mViewModelItem; +	LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID(); +	LLFloater* session_floater = LLIMConversation::getConversation(session_uuid);  	if (session_floater && !session_floater->getHost() && !session_floater->isMinimized())  	{ @@ -431,6 +432,22 @@ void LLConversationViewParticipant::draw()      LLView::draw();  } +// virtual +S32 LLConversationViewParticipant::arrange(S32* width, S32* height) +{ +    //Need to call arrange first since it computes value used in getIndentation() +    S32 arranged = LLFolderViewItem::arrange(width, height); + +    //Adjusts the avatar icon based upon the indentation +    LLRect avatarRect(getIndentation(),  +                        mAvatarIcon->getRect().mTop, +                        getIndentation() + mAvatarIcon->getRect().getWidth(), +                        mAvatarIcon->getRect().mBottom); +    mAvatarIcon->setShape(avatarRect); + +    return arranged; +} +  void LLConversationViewParticipant::selectItem()  {      LLConversationItem* vmi = this->getParentFolder() ? static_cast<LLConversationItem*>(this->getParentFolder()->getViewModelItem()) : NULL; @@ -506,7 +523,7 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask)  S32 LLConversationViewParticipant::getLabelXPos()  { -    return mAvatarIcon->getRect().mRight + mIconPad; +    return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad;  }  // static diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 4d77a4ade0..d50e527007 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -131,6 +131,7 @@ protected:  	void initFromParams(const Params& params);  	BOOL postBuild();      /*virtual*/ void draw(); +    /*virtual*/ S32 arrange(S32* width, S32* height);  	void onInfoBtnClick(); diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp index b687e18cae..920666ef90 100644 --- a/indra/newview/llimconversation.cpp +++ b/indra/newview/llimconversation.cpp @@ -49,7 +49,8 @@ LLIMConversation::LLIMConversation(const LLSD& session_id)    ,  mTearOffBtn(NULL)    ,  mCloseBtn(NULL)    ,  mSessionID(session_id.asUUID()) -  , mParticipantList(NULL) +//  , mParticipantList(NULL) +  , mConversationsRoot(NULL)    , mChatHistory(NULL)    , mInputEditor(NULL)    , mInputEditorTopPad(0) @@ -73,11 +74,13 @@ LLIMConversation::LLIMConversation(const LLSD& session_id)  LLIMConversation::~LLIMConversation()  { +	/*  	if (mParticipantList)  	{  		delete mParticipantList;  		mParticipantList = NULL;  	} +	 */  	delete mRefreshTimer;  } @@ -176,11 +179,39 @@ BOOL LLIMConversation::postBuild()  	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");  	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); -	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); -  	mTearOffBtn = getChild<LLButton>("tear_off_btn");  	mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); +	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); +	 +	// Create a root view folder for all participants +	LLConversationItem* base_item = new LLConversationItem(mConversationViewModel); +    LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>()); +    p.rect = LLRect(0, 0, getRect().getWidth(), 0); +    p.parent_panel = mParticipantListPanel; +    p.listener = base_item; +    p.view_model = &mConversationViewModel; +    p.root = NULL; +    p.use_ellipses = true; +	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); +    mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); +	 +	// Add a scroller for the folder (participant) view +	LLRect scroller_view_rect = mParticipantListPanel->getRect(); +	scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); +	LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>()); +	scroller_params.rect(scroller_view_rect); +	LLScrollContainer* scroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); +	scroller->setFollowsAll(); +	 +	// Insert that scroller into the panel widgets hierarchy and folder view +	mParticipantListPanel->addChild(scroller); +	scroller->addChild(mConversationsRoot); +	mConversationsRoot->setScrollContainer(scroller); +	mConversationsRoot->setFollowsAll(); +	mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox); +	 +	  	mChatHistory = getChild<LLChatHistory>("chat_history");  	mInputEditor = getChild<LLChatEntry>("chat_editor"); @@ -193,7 +224,7 @@ BOOL LLIMConversation::postBuild()  	setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); -	buildParticipantList(); +	buildConversationViewParticipant();  	updateHeaderAndToolbar(); @@ -216,15 +247,20 @@ BOOL LLIMConversation::postBuild()  	return result;  } +LLParticipantList* LLIMConversation::getParticipantList() +{ +	return dynamic_cast<LLParticipantList*>(LLIMFloaterContainer::getInstance()->getSessionModel(mSessionID)); +} +  void LLIMConversation::draw()  {  	LLTransientDockableFloater::draw();  	if (mRefreshTimer->hasExpired())  	{ -		if (mParticipantList) +		if (getParticipantList())  		{ -			mParticipantList->update(); +			getParticipantList()->update();  		}  		refresh(); @@ -314,30 +350,144 @@ void LLIMConversation::appendMessage(const LLChat& chat, const LLSD &args)  } -void LLIMConversation::buildParticipantList() +void LLIMConversation::buildConversationViewParticipant() +{ +	// Clear the widget list since we are rebuilding afresh from the model +	conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); +	while (widget_it != mConversationsWidgets.end()) +	{ +		removeConversationViewParticipant(widget_it->first); +		// Iterators are invalidated by erase so we need to pick begin again +		widget_it = mConversationsWidgets.begin(); +	} +	 +	// Get the model list +	LLParticipantList* item = getParticipantList(); +	if (!item) +	{ +		// Nothing to do if the model list is empty +		return; +	} + +	// Create the participants widgets now +	LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); +	LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); +	while (current_participant_model != end_participant_model) +	{ +		LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); +		addConversationViewParticipant(participant_model); +		current_participant_model++; +	} +} + +void LLIMConversation::addConversationViewParticipant(LLConversationItem* participant_model)  { -	if (mIsNearbyChat) +	// Check if the model already has an associated view +	LLUUID uuid = participant_model->getUUID(); +	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); +	 +	// If not already present, create the participant view and attach it to the root, otherwise, just refresh it +	if (widget)  	{ -		LLLocalSpeakerMgr* speaker_manager = LLLocalSpeakerMgr::getInstance(); -		mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); +		updateConversationViewParticipant(uuid); // overkill?  	}  	else  	{ -		LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); -		// for group and ad-hoc chat we need to include agent into list -		if(!mIsP2PChat && mSessionID.notNull() && speaker_manager) +		LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); +		mConversationsWidgets[uuid] = participant_view; +		participant_view->addToFolder(mConversationsRoot); +		participant_view->setVisible(TRUE); +		refreshConversation(); +	} +} + +void LLIMConversation::removeConversationViewParticipant(const LLUUID& participant_id) +{ +	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); +	if (widget) +	{ +		mConversationsRoot->extractItem(widget); +		delete widget; +		mConversationsWidgets.erase(participant_id); +		refreshConversation(); +	} +} + +void LLIMConversation::updateConversationViewParticipant(const LLUUID& participant_id) +{ +	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); +	if (widget) +	{ +		widget->refresh(); +		refreshConversation(); +	} +} + +void LLIMConversation::refreshConversation() +{ +	// Debug : Check that all participant models do have a view (debug consistency check) +	/* +	LLParticipantList* item = getParticipantList(); +	llinfos << "Merov debug : Start consistency check" << llendl; +	LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin(); +	LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); +	while (current_participant_model != end_participant_model) +	{ +		LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); +		if (participant_model != NULL) +		{ +			LLUUID uuid = participant_model->getUUID(); +			LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); +			if (!widget) +			{ +				llinfos << "Merov debug : Consistency error! Couldn't find widget for " << participant_model->getName() << llendl; +			} +			else  +			{ +				llinfos << "Merov debug : Consistency check pass for " << participant_model->getName() << llendl; +			} +		} +		else  		{ -			delete mParticipantList; // remove the old list and create a new one if the session id has changed -			mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), mConversationViewModel, true, false); +			llinfos << "Merov debug : Consistency check, skip non participant child" << llendl;  		} +		current_participant_model++;  	} -	updateHeaderAndToolbar(); +	llinfos << "Merov debug : End consistency check" << llendl; +	 */ +		 +	conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); +	while (widget_it != mConversationsWidgets.end()) +	{ +		widget_it->second->refresh(); +		widget_it->second->setVisible(TRUE); +		++widget_it; +	} +	mConversationViewModel.requestSortAll(); +	mConversationsRoot->arrangeAll(); +	mConversationsRoot->update(); +} + +// Copied from LLIMFloaterContainer::createConversationViewParticipant(). Refactor opportunity! +LLConversationViewParticipant* LLIMConversation::createConversationViewParticipant(LLConversationItem* item) +{ +    LLRect panel_rect = mParticipantListPanel->getRect(); +	 +	LLConversationViewParticipant::Params params; +	params.name = item->getDisplayName(); +	params.root = mConversationsRoot; +	params.listener = item; +	params.rect = LLRect (0, 24, panel_rect.getWidth(), 0); // *TODO: use conversation_view_participant.xml itemHeight value in lieu of 24 +	params.tool_tip = params.name; +	params.participant_id = item->getUUID(); +	 +	return LLUICtrlFactory::create<LLConversationViewParticipant>(params);  }  void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata)  {  	// TODO: Check this code when sort order menu will be added. (EM) -	if (!mParticipantList) +	if (!getParticipantList())  	{  		return;  	} @@ -346,7 +496,7 @@ void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata)  	if (chosen_item == "sort_name")  	{ -		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); +		getParticipantList()->setSortOrder(LLParticipantList::E_SORT_BY_NAME);  	}  } @@ -407,6 +557,12 @@ void LLIMConversation::hideOrShowTitle()  	floater_contents->setShape(contents_rect);  } +void LLIMConversation::updateSessionName(const std::string& name) +{ +	llinfos << "Merov debug : updateSessionName, name = " << name << llendl; +	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + name); +} +  void LLIMConversation::hideAllStandardButtons()  {  	for (S32 i = 0; i < BUTTON_COUNT; i++) @@ -565,6 +721,7 @@ void LLIMConversation::onTearOffClicked()      initRectControl();  	LLFloater::onClickTearOff(this);  	updateHeaderAndToolbar(); +	refreshConversation();  }  // static diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h index bff4cb4a31..cb306c4d8d 100644 --- a/indra/newview/llimconversation.h +++ b/indra/newview/llimconversation.h @@ -35,6 +35,7 @@  #include "lleventtimer.h"  #include "llimview.h"  #include "llconversationmodel.h" +#include "llconversationview.h"  class LLPanelChatControlPanel;  class LLChatEntry; @@ -79,6 +80,13 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void draw();  	/*virtual*/ void setVisible(BOOL visible); +	 +	// Handle the left hand participant list widgets +	void addConversationViewParticipant(LLConversationItem* item); +	void removeConversationViewParticipant(const LLUUID& participant_id); +	void updateConversationViewParticipant(const LLUUID& participant_id); +	void refreshConversation(); +	void buildConversationViewParticipant();  protected: @@ -98,7 +106,6 @@ protected:  	// refresh a visual state of the Call button  	void updateCallBtnState(bool callIsActive); -	void buildParticipantList();  	void onSortMenuItemClicked(const LLSD& userdata);  	void hideOrShowTitle(); // toggle the floater's drag handle @@ -107,6 +114,9 @@ protected:  	/// Update floater header and toolbar buttons when hosted/torn off state is toggled.  	void updateHeaderAndToolbar(); +	// Update the input field help text and other places that need the session name +	virtual void updateSessionName(const std::string& name); +  	// set the enable/disable state for the Call button  	virtual void enableDisableCallBtn(); @@ -124,10 +134,16 @@ protected:  	LLIMModel::LLIMSession* mSession; -	LLLayoutPanel* mParticipantListPanel; -	LLParticipantList* mParticipantList; -	LLUUID mSessionID; +	// Participants list: model and view +	LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item); +	 +	LLUUID mSessionID;  +	LLLayoutPanel* mParticipantListPanel;	// add the widgets to that see mConversationsListPanel +	//LLParticipantList* mParticipantList; get this from the mConversationsItems for the moment +	LLParticipantList* getParticipantList(); +	conversations_widgets_map mConversationsWidgets;  	LLConversationViewModel mConversationViewModel; +	LLFolderView* mConversationsRoot;  	LLChatHistory* mChatHistory;  	LLChatEntry* mInputEditor; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3545b8ff18..607cdbd265 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -243,7 +243,6 @@ void LLIMFloater::initIMSession(const LLUUID& session_id)  	{  		mIsP2PChat = mSession->isP2PSessionType();  		mSessionInitialized = mSession->mSessionInitialized; -  		mDialog = mSession->mType;  	}  } @@ -281,7 +280,7 @@ void LLIMFloater::initIMFloater()  	else  	{  		std::string session_name(LLIMModel::instance().getName(mSessionID)); -		updateSessionName(session_name, session_name); +		updateSessionName(session_name);  		// For ad hoc conferences we should update the title with participants names.  		if ((IM_SESSION_INVITE == mDialog && !gAgent.isInGroup(mSessionID)) @@ -292,6 +291,8 @@ void LLIMFloater::initIMFloater()  				mParticipantsListRefreshConnection.disconnect();  			} +			// CHUI-441: We shouldn't have any avatar_list anymore... see floater_im_session.xml +			// *TODO: Track and delete if not necessary anymore  			LLAvatarList* avatar_list = getChild<LLAvatarList>("speakers_list");  			mParticipantsListRefreshConnection = avatar_list->setRefreshCompleteCallback(  					boost::bind(&LLIMFloater::onParticipantsListChanged, this, _1)); @@ -525,20 +526,21 @@ void LLIMFloater::onVoiceChannelStateChanged(  	updateCallBtnState(callIsActive);  } -void LLIMFloater::updateSessionName(const std::string& ui_title, -									const std::string& ui_label) +void LLIMFloater::updateSessionName(const std::string& name)  { -	mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label); -	setTitle(ui_title);	 +	LLIMConversation::updateSessionName(name); +	setTitle(name);	  }  void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,  									const LLAvatarName& av_name)  { -	// Use display name only for labels, as the extended name will be in the -	// floater title +	// Use display name for label +	updateSessionName(av_name.mDisplayName); +	 +	// Overwrite the floater title with the extended name  	std::string ui_title = av_name.getCompleteName(); -	updateSessionName(ui_title, av_name.mDisplayName); +	setTitle(ui_title);	  	mTypingStart.setArg("[NAME]", ui_title);  } @@ -550,35 +552,45 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl)  		return;  	} -	bool all_names_resolved = true;  	std::vector<LLSD> participants_uuids;  	uuid_vec_t temp_uuids; // uuids vector for building the added participants' names string +	LLUUID unfound_id;  	avatar_list->getValues(participants_uuids); -	// Check whether we have all participants names in LLAvatarNameCache +	// Check participants names in LLAvatarNameCache      for (std::vector<LLSD>::const_iterator it = participants_uuids.begin(); it != participants_uuids.end(); ++it)  	{  		const LLUUID& id = it->asUUID(); -		temp_uuids.push_back(id);  		LLAvatarName av_name;          if (!LLAvatarNameCache::get(id, &av_name))          { -			all_names_resolved = false; - -			// If a name is not found in cache, request it and continue the process recursively -			// until all ids are resolved into names. -			LLAvatarNameCache::get(id, -					boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list)); -			break; +			// Keep the first not found avatar id +			if (unfound_id.isNull()) +			{ +				unfound_id = id; +			}          } +		else +		{ +			// Add the participant to the list of existing names +			temp_uuids.push_back(id); +		}  	} -	if (all_names_resolved) +	if (temp_uuids.size() != 0)  	{ +		// Build the session name and update it  		std::string ui_title;  		LLAvatarActions::buildResidentsString(temp_uuids, ui_title); -		updateSessionName(ui_title, ui_title); +		updateSessionName(ui_title); +	} + +	if (unfound_id.notNull()) +	{ +		// If a name is not found in cache, request it and continue the process recursively +		// until all ids are resolved into names. +		LLAvatarNameCache::get(unfound_id, boost::bind(&LLIMFloater::onParticipantsListChanged, this, avatar_list));  	}  } @@ -784,8 +796,7 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  	if (mSessionID != im_session_id)  	{  		initIMSession(im_session_id); - -		buildParticipantList(); +		buildConversationViewParticipant();  	}  	initIMFloater(); diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 6c69ed3462..39210546fb 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -138,8 +138,8 @@ private:  	/*virtual*/ void onClickCloseBtn(); -	// Update the window title, input field help text, etc. -	void updateSessionName(const std::string& ui_title, const std::string& ui_label); +	// Update the window title and input field help text +	/*virtual*/ void updateSessionName(const std::string& name);  	// For display name lookups for IM window titles  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index f85aa9a353..72e0f90f8c 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -98,8 +98,8 @@ LLIMFloaterContainer::~LLIMFloaterContainer()  void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)  { -	LLIMConversation::addToHost(session_id);  	addConversationListItem(session_id); +	LLIMConversation::addToHost(session_id);  }  void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) @@ -109,12 +109,13 @@ void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std:  void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id)  { -	LLIMConversation::addToHost(session_id);  	addConversationListItem(session_id); +	LLIMConversation::addToHost(session_id);  }  void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)  { +	// CHUI-441 : We should do this *without* delete and recreate  	addConversationListItem(new_session_id, removeConversationListItem(old_session_id));  } @@ -384,7 +385,7 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)  	// For debug only  	//std::ostringstream llsd_value;  	//llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; -	//llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl; +	//llinfos << "LLIMFloaterContainer::onConversationModelEvent, event = " << llsd_value.str() << llendl;  	// end debug  	// Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that @@ -398,16 +399,18 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)  	LLUUID session_id = event.get("session_uuid").asUUID();  	LLUUID participant_id = event.get("participant_uuid").asUUID(); -	LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); +	LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(get_ptr_in_map(mConversationsWidgets,session_id));  	if (!session_view)  	{ -		// We skip events that are not associated to a session +		// We skip events that are not associated with a session  		return false;  	}  	LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); +    LLIMConversation *conversation_floater = (session_id.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(session_id)));  	if (type == "remove_participant")  	{ +		// Remove a participant view from the hierarchical conversation list  		if (participant_view)  		{  			session_view->extractItem(participant_view); @@ -415,35 +418,49 @@ bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event)  			session_view->refresh();  			mConversationsRoot->arrangeAll();  		} +		// Remove a participant view from the conversation floater  +		if (conversation_floater) +		{ +			conversation_floater->removeConversationViewParticipant(participant_id); +		}  	}  	else if (type == "add_participant")  	{ -		if (!participant_view) +		LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); +		LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL); +		// Add a participant view to the hierarchical conversation list +		if (!participant_view && session_model && participant_model)  		{ -			LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); -			if (session_model) -			{ -				LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); -				if (participant_model) -				{ -					participant_view = createConversationViewParticipant(participant_model); -					participant_view->addToFolder(session_view); -					participant_view->setVisible(TRUE); -				} -			} - +			participant_view = createConversationViewParticipant(participant_model); +			participant_view->addToFolder(session_view); +			participant_view->setVisible(TRUE); +		} +		// Add a participant view to the conversation floater  +		if (conversation_floater && participant_model) +		{ +			conversation_floater->addConversationViewParticipant(participant_model);  		}  	}  	else if (type == "update_participant")  	{ +		// Update the participant view in the hierarchical conversation list  		if (participant_view)  		{  			participant_view->refresh();  		} +		// Update the participant view in the conversation floater  +		if (conversation_floater) +		{ +			conversation_floater->updateConversationViewParticipant(participant_id); +		}  	}  	else if (type == "update_session")  	{  		session_view->refresh(); +		if (conversation_floater) +		{ +			conversation_floater->refreshConversation(); +		}  	}  	mConversationViewModel.requestSortAll(); @@ -1074,10 +1091,10 @@ void LLIMFloaterContainer::showConversation(const LLUUID& session_id)      selectConversation(session_id);      } -//Will select only the conversation item +// Will select only the conversation item  void LLIMFloaterContainer::selectConversation(const LLUUID& session_id)  { -	LLFolderViewItem* widget = mConversationsWidgets[session_id]; +	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,session_id);  	if (widget)  	{  		(widget->getRoot())->setSelection(widget, FALSE, FALSE); @@ -1087,63 +1104,55 @@ void LLIMFloaterContainer::selectConversation(const LLUUID& session_id)  void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id)  { -	conversations_items_map::iterator item_it = mConversationsItems.find(session_id); -	if (item_it != mConversationsItems.end()) +	LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,session_id)); +	if (item)  	{ -		LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second); -		if (item) -		{ -			item->setTimeNow(participant_id); -			mConversationViewModel.requestSortAll(); -			mConversationsRoot->arrangeAll(); -		} +		item->setTimeNow(participant_id); +		mConversationViewModel.requestSortAll(); +		mConversationsRoot->arrangeAll();  	}  }  void LLIMFloaterContainer::setNearbyDistances()  { -	// Get the nearby chat session: that's the one with uuid nul in mConversationsItems -	conversations_items_map::iterator item_it = mConversationsItems.find(LLUUID()); -	if (item_it != mConversationsItems.end()) -	{ -		LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(item_it->second); -		if (item) +	// Get the nearby chat session: that's the one with uuid nul +	LLConversationItemSession* item = dynamic_cast<LLConversationItemSession*>(get_ptr_in_map(mConversationsItems,LLUUID())); +	if (item) +	{ +		// Get the positions of the nearby avatars and their ids +		std::vector<LLVector3d> positions; +		uuid_vec_t avatar_ids; +		LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); +		// Get the position of the agent +		const LLVector3d& me_pos = gAgent.getPositionGlobal(); +		// For each nearby avatar, compute and update the distance +		int avatar_count = positions.size(); +		for (int i = 0; i < avatar_count; i++)  		{ -			// Get the positions of the nearby avatars and their ids -			std::vector<LLVector3d> positions; -			uuid_vec_t avatar_ids; -			LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); -			// Get the position of the agent -			const LLVector3d& me_pos = gAgent.getPositionGlobal(); -			// For each nearby avatar, compute and update the distance -			int avatar_count = positions.size(); -			for (int i = 0; i < avatar_count; i++) -			{ -				F64 dist = dist_vec_squared(positions[i], me_pos); -				item->setDistance(avatar_ids[i],dist); -			} -			// Also does it for the agent itself -			item->setDistance(gAgent.getID(),0.0f); -			// Request resort -			mConversationViewModel.requestSortAll(); -			mConversationsRoot->arrangeAll(); +			F64 dist = dist_vec_squared(positions[i], me_pos); +			item->setDistance(avatar_ids[i],dist);  		} +		// Also does it for the agent itself +		item->setDistance(gAgent.getID(),0.0f); +		// Request resort +		mConversationViewModel.requestSortAll(); +		mConversationsRoot->arrangeAll();  	}  } -void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) +LLConversationItem* LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/)  {  	bool is_nearby_chat = uuid.isNull(); -    //Stores the display name for the conversation line item +    // Stores the display name for the conversation line item  	std::string display_name = is_nearby_chat ? LLTrans::getString("NearbyChatLabel") : LLIMModel::instance().getName(uuid); -	// Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do) +	// Check if the item is not already in the list, exit (nothing to do)  	// Note: this happens often, when reattaching a torn off conversation for instance  	conversations_items_map::iterator item_it = mConversationsItems.find(uuid);  	if (item_it != mConversationsItems.end())  	{ -		return; +		return item_it->second;  	}  	// Remove the conversation item that might exist already: it'll be recreated anew further down anyway @@ -1160,7 +1169,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi  	if (!item)  	{  		llwarns << "Couldn't create conversation session item : " << display_name << llendl; -		return; +		return NULL;  	}  	item->renameItem(display_name);  	item->updateParticipantName(NULL); @@ -1186,6 +1195,12 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi  		participant_view->addToFolder(widget);  		current_participant_model++;  	} +	// Do that too for the conversation dialog +    LLIMConversation *conversation_floater = (uuid.isNull() ? (LLIMConversation*)(LLFloaterReg::findTypedInstance<LLNearbyChat>("nearby_chat")) : (LLIMConversation*)(LLIMFloater::findInstance(uuid))); +	if (conversation_floater) +	{ +		conversation_floater->buildConversationViewParticipant(); +	}  	// set the widget to minimized mode if conversations pane is collapsed  	widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); @@ -1197,7 +1212,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWi          mConversationsRoot->scrollToShowSelection();      } -	return; +	return item;  }  bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) @@ -1207,20 +1222,16 @@ bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c  	// the widget will also delete its listener  	bool isWidgetSelected = false;  	LLFolderViewItem* new_selection = NULL; -	conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); -	if (widget_it != mConversationsWidgets.end()) +	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid); +	if (widget)  	{ -		LLFolderViewItem* widget = widget_it->second; -		if (widget) +		isWidgetSelected = widget->isSelected(); +		new_selection = mConversationsRoot->getNextFromChild(widget); +		if(new_selection == NULL)  		{ -			isWidgetSelected = widget->isSelected(); -			new_selection = mConversationsRoot->getNextFromChild(widget); -			if(new_selection == NULL) -			{ -				new_selection = mConversationsRoot->getPreviousFromChild(widget); -			} -			widget->destroyView(); +			new_selection = mConversationsRoot->getPreviousFromChild(widget);  		} +		widget->destroyView();  	}  	// Suppress the conversation items and widgets from their respective maps @@ -1262,9 +1273,6 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti      LLRect panel_rect = mConversationsListPanel->getRect();  	params.name = item->getDisplayName(); -	//params.icon = bridge->getIcon(); -	//params.icon_open = bridge->getOpenIcon(); -	//params.creation_date = bridge->getCreationDate();  	params.root = mConversationsRoot;  	params.listener = item; @@ -1272,7 +1280,8 @@ LLConversationViewParticipant* LLIMFloaterContainer::createConversationViewParti  	params.rect = LLRect (0, 24, panel_rect.getWidth(), 0);  	params.tool_tip = params.name;  	params.participant_id = item->getUUID(); -	 +    params.folder_indentation = 42; +  	return LLUICtrlFactory::create<LLConversationViewParticipant>(params);  } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 05ea94019b..a6f8677e46 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -91,6 +91,7 @@ public:  	LLConversationViewModel& getRootViewModel() { return mConversationViewModel; }      LLUUID getSelectedSession() { return mSelectedSession; }      void setSelectedSession(LLUUID sessionID) { mSelectedSession = sessionID; } +	LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); }  private:  	typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; @@ -151,7 +152,7 @@ private:  	// Conversation list implementation  public:  	bool removeConversationListItem(const LLUUID& uuid, bool change_focus = true); -	void addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false); +	LLConversationItem* addConversationListItem(const LLUUID& uuid, bool isWidgetSelected = false);  	void setTimeNow(const LLUUID& session_id, const LLUUID& participant_id);  	void setNearbyDistances(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 2b542595c5..a889eb7933 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -14,7 +14,7 @@   width="394"   can_resize="true"   can_tear_off="false" - min_width="250" + min_width="340"   min_height="190"   positioning="relative">      <floater.string name="call_btn_start">Conv_toolbar_open_call</floater.string> @@ -157,19 +157,8 @@        min_width="115"        width="150"         height="310"  -      auto_resize="false"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="310" -             ignore_online_status="true" -        layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="150" /> +      user_resize="true" +      auto_resize="true">        </layout_panel>      <layout_panel         default_tab_group="3" @@ -183,7 +172,8 @@         user_resize="true"         auto_resize="true"         visible="true" -       name="left_part_holder"> +       name="left_part_holder" +       min_width="225">          <panel           name="trnsAndChat_panel"           follows="all" diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index 0024decd4c..b83d9122f7 100755 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml @@ -1,7 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <conversation_view_participant    folder_arrow_image="Folder_Arrow" -  folder_indentation="0"    item_height="24"     item_top_pad="0"    selection_image="Rounded_Square" @@ -20,7 +19,6 @@       height="20"       default_icon_name="Generic_Person"  	 layout="topleft" -     left="50"  	 top="2"       width="20" />  <info_button  | 
