diff options
Diffstat (limited to 'indra/newview/llimfloatercontainer.cpp')
-rw-r--r-- | indra/newview/llimfloatercontainer.cpp | 191 |
1 files changed, 139 insertions, 52 deletions
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 4af170b3db..5c1105531e 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -50,6 +50,7 @@ #include "llcallbacklist.h" #include "llworld.h" +#include "llsdserialize.h" // // LLIMFloaterContainer // @@ -57,6 +58,7 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) : LLMultiFloater(seed), mExpandCollapseBtn(NULL), mConversationsRoot(NULL), + mConversationsEventStream("ConversationsEvents"), mInitialized(false) { mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); @@ -77,6 +79,8 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) LLIMFloaterContainer::~LLIMFloaterContainer() { + mConversationsEventStream.stopListening("ConversationsRefresh"); + gIdleCallbacks.deleteFunction(idle, this); mNewMessageConnection.disconnect(); @@ -94,19 +98,23 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id); + addConversationListItem(session_id, true); +} + +void LLIMFloaterContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) +{ + setItemSelect(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { LLIMFloater::addToHost(session_id, true); - addConversationListItem(session_id); + addConversationListItem(session_id, true); } void LLIMFloaterContainer::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) { - removeConversationListItem(old_session_id); - addConversationListItem(new_session_id); + addConversationListItem(new_session_id, removeConversationListItem(old_session_id)); } void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id) @@ -138,6 +146,9 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsListPanel = getChild<LLPanel>("conversations_list_panel"); + // Open IM session with selected participant on double click event + mConversationsListPanel->setDoubleClickCallback(boost::bind(&LLIMFloaterContainer::doToSelected, this, LLSD("im"))); + // Create the root model and view for all conversation sessions LLConversationItem* base_item = new LLConversationItem(getRootViewModel()); @@ -155,6 +166,9 @@ BOOL LLIMFloaterContainer::postBuild() mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + // Add listener to conversation model events + mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLIMFloaterContainer::onConversationModelEvent, this, _1)); + // a scroller for folder view LLRect scroller_view_rect = mConversationsListPanel->getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); @@ -397,62 +411,81 @@ void LLIMFloaterContainer::idle(void* user_data) self->mConversationsRoot->update(); } -void LLIMFloaterContainer::draw() +bool LLIMFloaterContainer::onConversationModelEvent(const LLSD& event) { - // CHUI Notes - // Currently, the model is not responsible for creating the view which is a good thing. This means that - // the model could change substantially and the view could decide to echo only a portion of this model. - // Consequently, the participant views need to be created either by the session view or by the container panel. - // For the moment, we create them here (which makes for complicated code...) to conform to the pattern - // implemented in llinventorypanel.cpp (see LLInventoryPanel::buildNewViews()). - // The best however would be to have an observer on the model so that we would not pool on each draw to know - // if the view needs refresh. The current implementation (testing for change on draw) is less - // efficient perf wise than a listener/observer scheme. We will implement that shortly. + // For debug only + //std::ostringstream llsd_value; + //llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl; + //llinfos << "Merov debug : onConversationModelEvent, event = " << llsd_value.str() << llendl; + // end debug - // On each session in mConversationsItems - for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + // Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that + // the model could change substantially and the view could echo only a portion of this model (though currently the + // conversation view does echo the conversation model 1 to 1). + // Consequently, the participant views need to be created either by the session view or by the container panel. + // For the moment, we create them here, at the container level, to conform to the pattern implemented in llinventorypanel.cpp + // (see LLInventoryPanel::buildNewViews()). + + std::string type = event.get("type").asString(); + 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]); + if (!session_view) { - // Get the current session descriptors - LLConversationItem* session_model = it_session->second; - LLUUID session_id = it_session->first; - LLConversationViewSession* session_view = dynamic_cast<LLConversationViewSession*>(mConversationsWidgets[session_id]); - // If the session model has been changed, refresh the corresponding view - if (session_model->needsRefresh()) + // We skip events that are not associated to a session + return false; + } + LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); + + if (type == "remove_participant") + { + if (participant_view) { + session_view->extractItem(participant_view); + delete participant_view; session_view->refresh(); + mConversationsRoot->arrangeAll(); } - // Iterate through each model participant child - LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); - LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); - while (current_participant_model != end_participant_model) + } + else if (type == "add_participant") + { + if (!participant_view) { - LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); - LLUUID participant_id = participant_model->getUUID(); - LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id); - // Is there a corresponding view? If not create it - if (!participant_view) + LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]); + if (session_model) { - participant_view = createConversationViewParticipant(participant_model); - participant_view->addToFolder(session_view); - participant_view->setVisible(TRUE); - } - else - // Else, see if it needs refresh - { - if (participant_model->needsRefresh()) + LLConversationItemParticipant* participant_model = session_model->findParticipant(participant_id); + if (participant_model) { - participant_view->refresh(); + participant_view = createConversationViewParticipant(participant_model); + participant_view->addToFolder(session_view); + participant_view->setVisible(TRUE); } } - // Reset the need for refresh - session_model->resetRefresh(); - mConversationViewModel.requestSortAll(); - mConversationsRoot->arrangeAll(); - // Next participant - current_participant_model++; + + } + } + else if (type == "update_participant") + { + if (participant_view) + { + participant_view->refresh(); } } + else if (type == "update_session") + { + session_view->refresh(); + } + mConversationViewModel.requestSortAll(); + mConversationsRoot->arrangeAll(); + + return false; +} + +void LLIMFloaterContainer::draw() +{ if (mTabContainer->getTabCount() == 0) { // Do not close the container when every conversation is torn off because the user @@ -527,12 +560,25 @@ void LLIMFloaterContainer::collapseMessagesPane(bool collapse) gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); } + // Save left pane rectangle before collapsing/expanding right pane. + LLRect prevRect = mConversationsPane->getRect(); + // Show/hide the messages pane. mConversationsStack->collapsePanel(mMessagesPane, collapse); + if (!collapse) + { + // Make sure layout is updated before resizing conversation pane. + mConversationsStack->updateLayout(); + } + updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); + if (!collapse) + { + // Restore conversation's pane previous width after expanding messages pane. + mConversationsPane->setTargetDim(prevRect.getWidth()); + } } - void LLIMFloaterContainer::collapseConversationsPane(bool collapse) { if (mConversationsPane->isCollapsed() == collapse) @@ -862,7 +908,13 @@ void LLIMFloaterContainer::doToSelectedConversation(const std::string& command, } else if("chat_history" == command) { - LLAvatarActions::viewChatHistory(conversationItem->getUUID()); + const LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()); + + if (NULL != session) + { + const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID; + LLFloaterReg::showInstance("preview_conversation", session_id, true); + } } else { @@ -914,6 +966,12 @@ bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t mUUIDs; getParticipantUUIDs(mUUIDs); + if(item == std::string("can_activate_group")) + { + LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); + return gAgent.getGroupID() != selected_group_id; + } + if(mUUIDs.size() <= 0) { return false; @@ -1014,6 +1072,7 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) return false; } +//Will select only the conversation item void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; @@ -1024,6 +1083,26 @@ void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) } } +//Will select the conversation/participant item +void LLIMFloaterContainer::setItemSelect(const LLUUID& session_id) +{ + + if(mConversationsRoot->getCurSelectedItem() && mConversationsRoot->getCurSelectedItem()->getParentFolder()) + { + //Retreive the conversation id. When a participant is selected, then have to to get the converation id from the parent. + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(mConversationsRoot->getCurSelectedItem()->getParentFolder()->getViewModelItem()); + + //Will allow selection/highlighting of the conversation/participant + if(session_id != vmi->getUUID()) + { + mSelectedSession = session_id; + LLFolderViewItem* widget = mConversationsWidgets[session_id]; + (widget->getRoot())->setSelection(widget, FALSE, FALSE); + } + } +} + + void LLIMFloaterContainer::setTimeNow(const LLUUID& session_id, const LLUUID& participant_id) { conversations_items_map::iterator item_it = mConversationsItems.find(session_id); @@ -1070,7 +1149,7 @@ void LLIMFloaterContainer::setNearbyDistances() } } -void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) +void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid, bool isWidgetSelected /*= false*/) { bool is_nearby_chat = uuid.isNull(); @@ -1089,7 +1168,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) removeConversationListItem(uuid,false); // Create a conversation session model - LLConversationItem* item = NULL; + LLConversationItemSession* item = NULL; LLSpeakerMgr* speaker_manager = (is_nearby_chat ? (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()) : LLIMModel::getInstance()->getSpeakerManager(uuid)); if (speaker_manager) { @@ -1101,6 +1180,7 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) return; } item->renameItem(display_name); + item->updateParticipantName(NULL); mConversationsItems[uuid] = item; @@ -1124,7 +1204,10 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) current_participant_model++; } - setConvItemSelect(uuid); + if (isWidgetSelected) + { + setConvItemSelect(uuid); + } // set the widget to minimized mode if conversations pane is collapsed widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); @@ -1132,17 +1215,19 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) return; } -void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) +bool LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool change_focus) { // Delete the widget and the associated conversation item // Note : since the mConversationsItems is also the listener to the widget, deleting // the widget will also delete its listener + bool isWidgetSelected = false; conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(uuid); if (widget_it != mConversationsWidgets.end()) { LLFolderViewItem* widget = widget_it->second; if (widget) { + isWidgetSelected = widget->isSelected(); widget->destroyView(); } } @@ -1158,10 +1243,12 @@ void LLIMFloaterContainer::removeConversationListItem(const LLUUID& uuid, bool c conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); if (widget_it != mConversationsWidgets.end()) { + mSelectedSession = widget_it->first; LLFolderViewItem* widget = widget_it->second; widget->selectItem(); } } + return isWidgetSelected; } LLConversationViewSession* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item) |