summaryrefslogtreecommitdiff
path: root/indra/newview/llimfloatercontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llimfloatercontainer.cpp')
-rw-r--r--indra/newview/llimfloatercontainer.cpp406
1 files changed, 390 insertions, 16 deletions
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index 0f0ae896a2..c2c0ddddea 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -27,20 +27,34 @@
#include "llviewerprecompiledheaders.h"
+#include "llimfloater.h"
#include "llimfloatercontainer.h"
+
#include "llfloaterreg.h"
-#include "llimview.h"
+#include "lllayoutstack.h"
+#include "llnearbychat.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
#include "llavatariconctrl.h"
+#include "llavatarnamecache.h"
#include "llgroupiconctrl.h"
-#include "llagent.h"
+#include "llfloateravatarpicker.h"
+#include "llimview.h"
#include "lltransientfloatermgr.h"
+#include "llviewercontrol.h"
//
// LLIMFloaterContainer
//
LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
-: LLMultiFloater(seed)
+: LLMultiFloater(seed),
+ mExpandCollapseBtn(NULL),
+ mConversationsRoot(NULL)
{
+ // Firstly add our self to IMSession observers, so we catch session events
+ LLIMMgr::getInstance()->addSessionObserver(this);
+
mAutoResize = FALSE;
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
}
@@ -49,6 +63,26 @@ LLIMFloaterContainer::~LLIMFloaterContainer()
{
mNewMessageConnection.disconnect();
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
+
+ gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed());
+ gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed());
+
+ if (!LLSingleton<LLIMMgr>::destroyed())
+ {
+ LLIMMgr::getInstance()->removeSessionObserver(this);
+ }
+}
+
+void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id)
+{
+ LLIMFloater::show(session_id);
+}
+
+void LLIMFloaterContainer::sessionRemoved(const LLUUID& session_id)
+{
+ LLIMFloater* floaterp = LLIMFloater::findInstance(session_id);
+ LLFloater::onClickClose(floaterp);
+ removeConversationListItem(floaterp);
}
BOOL LLIMFloaterContainer::postBuild()
@@ -56,24 +90,47 @@ BOOL LLIMFloaterContainer::postBuild()
mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1));
// Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button
// mTabContainer will be initialized in LLMultiFloater::addChild()
+
+ setTabContainer(getChild<LLTabContainer>("im_box_tab_container"));
+
+ mConversationsStack = getChild<LLLayoutStack>("conversations_stack");
+ mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel");
+ mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel");
+
+ mConversationsListPanel = getChild<LLPanel>("conversations_list_panel");
+
+ // CHUI-98 : View Model for conversations
+ LLConversationItem* base_item = new LLConversationItem(this);
+ LLFolderView::Params p;
+ p.view_model = &mConversationViewModel;
+ p.parent_panel = mConversationsListPanel;
+ p.rect = mConversationsListPanel->getLocalRect();
+ p.follows.flags = FOLLOWS_ALL;
+ p.listener = base_item;
+ p.root = NULL;
+
+ mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
+ mConversationsListPanel->addChild(mConversationsRoot);
+
+ mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
+ mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this));
+
+ childSetAction("add_btn", boost::bind(&LLIMFloaterContainer::onAddButtonClicked, this));
+
+ collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
+ collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"));
+ LLAvatarNameCache::addUseDisplayNamesCallback(
+ boost::bind(&LLIMConversation::processChatHistoryStyleUpdate));
+
return TRUE;
}
void LLIMFloaterContainer::onOpen(const LLSD& key)
{
LLMultiFloater::onOpen(key);
-/*
- if (key.isDefined())
- {
- LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID());
- if (im_floater)
- {
- im_floater->openFloater();
- }
- }
-*/
}
+// virtual
void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point)
@@ -86,11 +143,15 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
openFloater(floaterp->getKey());
return;
}
+
+ // Make sure the message panel is open when adding a floater or it stays mysteriously hidden
+ collapseMessagesPane(false);
+ // Add the floater
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
LLUUID session_id = floaterp->getKey();
-
+
LLIconCtrl* icon = 0;
if(gAgent.isInGroup(session_id, TRUE))
@@ -113,15 +174,52 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
mSessions[session_id] = floaterp;
floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id));
}
+
+ // forced resize of the floater
+ LLRect wrapper_rect = this->mTabContainer->getLocalRect();
+ floaterp->setRect(wrapper_rect);
+
mTabContainer->setTabImage(floaterp, icon);
}
+
void LLIMFloaterContainer::onCloseFloater(LLUUID& id)
{
mSessions.erase(id);
setFocus(TRUE);
}
+// virtual
+void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height)
+{
+ bool is_left_pane_expanded = !mConversationsPane->isCollapsed();
+ bool is_right_pane_expanded = !mMessagesPane->isCollapsed();
+
+ S32 conversations_pane_min_dim = mConversationsPane->getMinDim();
+
+ if (is_right_pane_expanded)
+ {
+ S32 conversations_pane_width =
+ (is_left_pane_expanded ? gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") : conversations_pane_min_dim);
+
+ // possibly increase minimum size constraint due to children's minimums.
+ for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
+ {
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx));
+ if (floaterp)
+ {
+ new_min_width = llmax(new_min_width,
+ floaterp->getMinWidth() + conversations_pane_width + LLPANEL_BORDER_WIDTH * 2);
+ new_min_height = llmax(new_min_height, floaterp->getMinHeight());
+ }
+ }
+ }
+ else
+ {
+ new_min_width = conversations_pane_min_dim;
+ }
+}
+
void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)
{
LLUUID session_id = data["session_id"].asUUID();
@@ -136,6 +234,21 @@ void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)
}
}
+void LLIMFloaterContainer::onExpandCollapseButtonClicked()
+{
+ if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed()
+ && gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst"))
+ {
+ // Expand the messages pane from ultra minimized state
+ // if it was collapsed last in order.
+ collapseMessagesPane(false);
+ }
+ else
+ {
+ collapseConversationsPane(!mConversationsPane->isCollapsed());
+ }
+}
+
LLIMFloaterContainer* LLIMFloaterContainer::findInstance()
{
return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container");
@@ -151,8 +264,6 @@ void LLIMFloaterContainer::setMinimized(BOOL b)
if (isMinimized() == b) return;
LLMultiFloater::setMinimized(b);
- // Hide minimized floater (see EXT-5315)
- setVisible(!b);
if (isMinimized()) return;
@@ -162,4 +273,267 @@ void LLIMFloaterContainer::setMinimized(BOOL b)
}
}
+void LLIMFloaterContainer::draw()
+{
+ if (mTabContainer->getTabCount() == 0)
+ {
+ // Do not close the container when every conversation is torn off because the user
+ // still needs the conversation list. Simply collapse the message pane in that case.
+ collapseMessagesPane(true);
+ }
+ LLFloater::draw();
+
+ repositioningWidgets();
+}
+
+void LLIMFloaterContainer::tabClose()
+{
+ if (mTabContainer->getTabCount() == 0)
+ {
+ // Do not close the container when every conversation is torn off because the user
+ // still needs the conversation list. Simply collapse the message pane in that case.
+ collapseMessagesPane(true);
+ }
+}
+
+void LLIMFloaterContainer::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ // Make sure we have the Nearby Chat present when showing the conversation container
+ LLFloater* nearby_chat = LLFloaterReg::findInstance("chat_bar");
+ if (nearby_chat == NULL)
+ {
+ // If not found, force the creation of the nearby chat conversation panel
+ // *TODO: find a way to move this to XML as a default panel or something like that
+ LLSD name("chat_bar");
+ LLFloaterReg::toggleInstanceOrBringToFront(name);
+ }
+ }
+
+ // We need to show/hide all the associated conversations that have been torn off
+ // (and therefore, are not longer managed by the multifloater),
+ // so that they show/hide with the conversations manager.
+ conversations_items_map::iterator item_it = mConversationsItems.begin();
+ for (;item_it != mConversationsItems.end(); ++item_it)
+ {
+ LLConversationItem* item = item_it->second;
+ item->setVisibleIfDetached(visible);
+ }
+
+ // Now, do the normal multifloater show/hide
+ LLMultiFloater::setVisible(visible);
+
+}
+
+void LLIMFloaterContainer::collapseMessagesPane(bool collapse)
+{
+ if (mMessagesPane->isCollapsed() == collapse)
+ {
+ return;
+ }
+
+ if (collapse)
+ {
+ // Save the messages pane width before collapsing it.
+ gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth());
+
+ // Save the order in which the panels are closed to reverse user's last action.
+ gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed());
+ }
+
+ // Show/hide the messages pane.
+ mConversationsStack->collapsePanel(mMessagesPane, collapse);
+
+ updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth"));
+}
+
+void LLIMFloaterContainer::collapseConversationsPane(bool collapse)
+{
+ if (mConversationsPane->isCollapsed() == collapse)
+ {
+ return;
+ }
+
+ LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded");
+ button_panel->setVisible(!collapse);
+ mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon"));
+
+ if (collapse)
+ {
+ // Save the conversations pane width before collapsing it.
+ gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth());
+
+ // Save the order in which the panels are closed to reverse user's last action.
+ gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed());
+ }
+
+ mConversationsStack->collapsePanel(mConversationsPane, collapse);
+
+ S32 collapsed_width = mConversationsPane->getMinDim();
+ updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width);
+}
+
+void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width)
+{
+ LLRect floater_rect = getRect();
+ floater_rect.mRight += ((collapse ? -1 : 1) * delta_width);
+
+ // Set by_user = true so that reshaped rect is saved in user_settings.
+ setShape(floater_rect, true);
+
+ updateResizeLimits();
+
+ bool is_left_pane_expanded = !mConversationsPane->isCollapsed();
+ bool is_right_pane_expanded = !mMessagesPane->isCollapsed();
+
+ setCanResize(is_left_pane_expanded || is_right_pane_expanded);
+ setCanMinimize(is_left_pane_expanded || is_right_pane_expanded);
+}
+
+void LLIMFloaterContainer::onAddButtonClicked()
+{
+ LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLIMFloaterContainer::onAvatarPicked, this, _1), TRUE, TRUE);
+ LLFloater* root_floater = gFloaterView->getParentFloater(this);
+ if (picker && root_floater)
+ {
+ root_floater->addDependentFloater(picker);
+ }
+}
+
+void LLIMFloaterContainer::onAvatarPicked(const uuid_vec_t& ids)
+{
+ if (ids.size() == 1)
+ {
+ LLAvatarActions::startIM(ids.back());
+ }
+ else
+ {
+ LLAvatarActions::startConference(ids);
+ }
+}
+
+void LLIMFloaterContainer::repositioningWidgets()
+{
+ LLRect panel_rect = mConversationsListPanel->getRect();
+ S32 item_height = 16;
+ int index = 0;
+ for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
+ widget_it != mConversationsWidgets.end();
+ widget_it++, ++index)
+ {
+ LLFolderViewItem* widget = widget_it->second;
+ widget->setVisible(TRUE);
+ widget->setRect(LLRect(0,
+ panel_rect.getHeight() - item_height*index,
+ panel_rect.getWidth(),
+ panel_rect.getHeight() - item_height*(index+1)));
+ }
+}
+
+// CHUI-137 : Temporary implementation of conversations list
+void LLIMFloaterContainer::addConversationListItem(std::string name, const LLUUID& uuid, LLFloater* floaterp)
+{
+ // Check if the item is not already in the list, exit if it is and has the same name and uuid (nothing to do)
+ // Note: this happens often, when reattaching a torn off conversation for instance
+ conversations_items_map::iterator item_it = mConversationsItems.find(floaterp);
+ if (item_it != mConversationsItems.end())
+ {
+ LLConversationItem* item = item_it->second;
+ // Check if the item has changed
+ if (item->hasSameValues(name,uuid))
+ {
+ // If it hasn't changed, nothing to do -> exit
+ return;
+ }
+ }
+
+ // Remove the conversation item that might exist already: it'll be recreated anew further down anyway
+ // and nothing wrong will happen removing it if it doesn't exist
+ removeConversationListItem(floaterp,false);
+
+ // Create a conversation item
+ LLConversationItem* item = new LLConversationItem(name, uuid, floaterp, this);
+ mConversationsItems[floaterp] = item;
+
+ // Create a widget from it
+ LLFolderViewItem* widget = createConversationItemWidget(item);
+ mConversationsWidgets[floaterp] = widget;
+
+ // Add a new conversation widget to the root folder of a folder view.
+ widget->addToFolder(mConversationsRoot);
+
+ // Add it to the UI
+ widget->setVisible(TRUE);
+
+ repositioningWidgets();
+
+ mConversationsListPanel->addChild(widget);
+
+ return;
+}
+
+void LLIMFloaterContainer::removeConversationListItem(LLFloater* floaterp, 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
+ conversations_widgets_map::iterator widget_it = mConversationsWidgets.find(floaterp);
+ if (widget_it != mConversationsWidgets.end())
+ {
+ LLFolderViewItem* widget = widget_it->second;
+ widget->destroyView();
+ }
+
+ // Suppress the conversation items and widgets from their respective maps
+ mConversationsItems.erase(floaterp);
+ mConversationsWidgets.erase(floaterp);
+
+ repositioningWidgets();
+
+ // Don't let the focus fall IW, select and refocus on the first conversation in the list
+ if (change_focus)
+ {
+ setFocus(TRUE);
+ conversations_items_map::iterator item_it = mConversationsItems.begin();
+ if (item_it != mConversationsItems.end())
+ {
+ LLConversationItem* item = item_it->second;
+ item->selectItem();
+ }
+ }
+ return;
+}
+
+LLFloater* LLIMFloaterContainer::findConversationItem(LLUUID& uuid)
+{
+ LLFloater* floaterp = NULL;
+ for (conversations_items_map::iterator item_it = mConversationsItems.begin(); item_it != mConversationsItems.end(); ++item_it)
+ {
+ LLConversationItem* item = item_it->second;
+ if (item->hasSameValue(uuid))
+ {
+ floaterp = item_it->first;
+ break;
+ }
+ }
+ return floaterp;
+}
+
+LLFolderViewItem* LLIMFloaterContainer::createConversationItemWidget(LLConversationItem* item)
+{
+ LLFolderViewItem::Params params;
+
+ params.name = item->getDisplayName();
+ //params.icon = bridge->getIcon();
+ //params.icon_open = bridge->getOpenIcon();
+ //params.creation_date = bridge->getCreationDate();
+ params.root = mConversationsRoot;
+ params.listener = item;
+ params.rect = LLRect (0, 0, 0, 0);
+ params.tool_tip = params.name;
+
+ return LLUICtrlFactory::create<LLFolderViewItem>(params);
+}
+
// EOF