summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llfolderview.cpp2
-rwxr-xr-xindra/llui/llfolderviewitem.cpp32
-rwxr-xr-xindra/llui/llfolderviewitem.h2
-rw-r--r--indra/llui/llfolderviewmodel.h7
-rwxr-xr-xindra/newview/llconversationview.cpp31
-rwxr-xr-xindra/newview/llconversationview.h1
-rw-r--r--indra/newview/llimconversation.cpp193
-rw-r--r--indra/newview/llimconversation.h24
-rw-r--r--indra/newview/llimfloater.cpp57
-rw-r--r--indra/newview/llimfloater.h4
-rw-r--r--indra/newview/llimfloatercontainer.cpp157
-rw-r--r--indra/newview/llimfloatercontainer.h3
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml20
-rwxr-xr-xindra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml2
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