summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llfloater.cpp4
-rw-r--r--indra/llui/lllayoutstack.h2
-rw-r--r--indra/llui/llmultifloater.cpp36
-rw-r--r--indra/llui/llmultifloater.h3
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/app_settings/settings_per_account.xml55
-rw-r--r--indra/newview/llchathistory.cpp49
-rwxr-xr-xindra/newview/llfloaterpreference.cpp21
-rw-r--r--indra/newview/llimfloater.cpp441
-rw-r--r--indra/newview/llimfloater.h86
-rw-r--r--indra/newview/llimfloatercontainer.cpp155
-rw-r--r--indra/newview/llimfloatercontainer.h19
-rw-r--r--indra/newview/llimview.cpp18
-rw-r--r--indra/newview/llimview.h14
-rw-r--r--indra/newview/llnearbychat.cpp103
-rw-r--r--indra/newview/llnearbychat.h8
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp320
-rw-r--r--indra/newview/llpanelimcontrolpanel.h56
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp7
-rw-r--r--indra/newview/llparticipantlist.cpp14
-rw-r--r--indra/newview/llspeakers.h1
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml143
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml150
-rw-r--r--indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml50
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_control_panel.xml49
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml166
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
27 files changed, 1110 insertions, 883 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 51611d547c..b087205a5c 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1371,7 +1371,7 @@ void LLFloater::setHost(LLMultiFloater* host)
mButtonScale = 1.f;
//mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;
}
- updateTitleButtons();
+
if (host)
{
mHostHandle = host->getHandle();
@@ -1381,6 +1381,8 @@ void LLFloater::setHost(LLMultiFloater* host)
{
mHostHandle.markDead();
}
+
+ updateTitleButtons();
}
void LLFloater::moveResizeHandlesToFront()
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index d32caec5f9..58643868e8 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -177,6 +177,8 @@ public:
F32 getVisibleAmount() const;
S32 getVisibleDim() const;
+ bool isCollapsed() const { return mCollapsed;}
+
void setOrientation(LLLayoutStack::ELayoutOrientation orientation);
void storeOriginalDim();
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
index f3a48835b1..540ac74aee 100644
--- a/indra/llui/llmultifloater.cpp
+++ b/indra/llui/llmultifloater.cpp
@@ -468,23 +468,12 @@ BOOL LLMultiFloater::postBuild()
void LLMultiFloater::updateResizeLimits()
{
- static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
- const LLFloater::Params& default_params = LLFloater::getDefaultParams();
- S32 floater_header_size = default_params.header_height;
- S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
// initialize minimum size constraint to the original xml values.
S32 new_min_width = mOrigMinWidth;
S32 new_min_height = mOrigMinHeight;
- // possibly increase minimum size constraint due to children's minimums.
- for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
- {
- LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
- if (floaterp)
- {
- new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
- new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
- }
- }
+
+ computeResizeLimits(new_min_width, new_min_height);
+
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = getRect().getHeight();
@@ -510,3 +499,22 @@ void LLMultiFloater::updateResizeLimits()
gFloaterView->adjustToFitScreen(this, TRUE);
}
}
+
+void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height)
+{
+ static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
+ S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
+
+ // possibly increase minimum size constraint due to children's minimums.
+ for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
+ {
+ LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
+ if (floaterp)
+ {
+ new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
+ new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
+ }
+ }
+}
diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h
index 9fa917eca1..f299ae5dd3 100644
--- a/indra/llui/llmultifloater.h
+++ b/indra/llui/llmultifloater.h
@@ -93,6 +93,9 @@ protected:
LLTabContainer::TabPosition mTabPos;
BOOL mAutoResize;
S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
+
+private:
+ virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height);
};
#endif // LL_MULTI_FLOATER_H
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ee8c15752b..d1fc8bdb7e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -2,6 +2,28 @@
<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="llsd.xsd">
<map>
+ <key>IMShowTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable(disable) timestamp showing in the chat.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>IMShowNamesForP2PConv</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable(disable) showing of a names in the chat.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>CrashHostUrl</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 8cdd8ed838..fdc52b7394 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -22,6 +22,61 @@
<key>Value</key>
<string>The Resident you messaged is in &apos;busy mode&apos; which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string>
</map>
+ <key>ConversationsExpandMessagePaneFirst</key>
+ <map>
+ <key>Comment</key>
+ <string>Expand either messages or conversations list pane from Conversations compact mode.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ConversationsListPaneCollapsed</key>
+ <map>
+ <key>Comment</key>
+ <string>Stores the expanded/collapsed state of the conversations list pane in Conversations floater.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ConversationsListPaneWidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Conversations floater list pane width.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>268</integer>
+ </map>
+ <key>ConversationsMessagePaneCollapsed</key>
+ <map>
+ <key>Comment</key>
+ <string>Stores the expanded/collapsed state of Conversations floater message pane.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ConversationsMessagePaneWidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Conversations floater message pane width.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>412</integer>
+ </map>
<key>InstantMessageLogPath</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 3da868945b..c514261b60 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -700,9 +700,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
return;
}
+ bool from_me = chat.mFromID == gAgent.getID();
mEditor->setPlainText(use_plain_text_chat_history);
- if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty())
+ if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty())
{
mUnreadChatSources.insert(chat.mFromName);
mMoreChatPanel->setVisible(TRUE);
@@ -775,18 +776,28 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
style_params.readonly_color(LLColor4::grey);
}
+ bool prependNewLineState = mEditor->getText().size() != 0;
+
+ // show timestamps and names in the compact mode
if (use_plain_text_chat_history)
{
LLStyle::Params timestamp_style(style_params);
+
+ // timestams showing
+ if (args["show_time"].asBoolean())
+ {
if (!message_from_log)
{
LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor");
timestamp_style.color(timestamp_color);
timestamp_style.readonly_color(timestamp_color);
}
- mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style);
+ mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style);
+ prependNewLineState = false;
+ }
- if (utf8str_trim(chat.mFromName).size() != 0)
+ // names showing
+ if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0)
{
// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.
if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())
@@ -803,25 +814,40 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
link_params.is_link = true;
link_params.link_href = url;
- mEditor->appendText(chat.mFromName + delimiter,
- false, link_params);
+ mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params);
+ prependNewLineState = false;
}
else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)
{
LLStyle::Params link_params(style_params);
link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));
+ if (from_me)
+ { std::string localized_name;
+ bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst");
+ mEditor->appendText((is_localized? localized_name:"(You)") + delimiter,
+ prependNewLineState, link_params);
+ prependNewLineState = false;
+ }
+ else
+ {
// Add link to avatar's inspector and delimiter to message.
- mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params);
+ mEditor->appendText(std::string(link_params.link_href) + delimiter,
+ prependNewLineState, link_params);
+ prependNewLineState = false;
+ }
}
else
{
- mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params);
+ mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter,
+ prependNewLineState, style_params);
+ prependNewLineState = false;
}
}
}
- else
+ else // showing timestamp and name in the expanded mode
{
+ prependNewLineState = false;
LLView* view = NULL;
LLInlineViewSegment::Params p;
p.force_newline = true;
@@ -901,7 +927,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
//MESSAGE TEXT PROCESSING
//*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010)
- if (use_plain_text_chat_history && gAgentID != chat.mFromID && chat.mFromID.notNull())
+ if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull())
{
std::string slurl_about = SLURL_APP_AGENT + chat.mFromID.asString() + SLURL_ABOUT;
if (message.length() > slurl_about.length() &&
@@ -916,13 +942,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
message = chat.mFromName + message;
}
- mEditor->appendText(message, FALSE, style_params);
+ mEditor->appendText(message, prependNewLineState, style_params);
+ prependNewLineState = false;
}
mEditor->blockUndo();
// automatically scroll to end when receiving chat from myself
- if (chat.mFromID == gAgentID)
+ if (from_me)
{
mEditor->setCursorAndScrollToEnd();
}
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 1c29323594..3ed575086c 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -423,13 +423,13 @@ void LLFloaterPreference::saveAvatarProperties( void )
BOOL LLFloaterPreference::postBuild()
{
- gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2));
+ gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate));
- gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2));
+ gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate));
- gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2));
+ gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate));
- gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2));
+ gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate));
gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged));
@@ -457,14 +457,11 @@ BOOL LLFloaterPreference::postBuild()
void LLFloaterPreference::onBusyResponseChanged()
{
// set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise
- if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString())
- {
- gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE );
- }
- else
- {
- gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE );
- }
+ bool busy_flag =
+ LLTrans::getString("BusyModeResponseDefault")
+ != getChild<LLUICtrl>("busy_response")->getValue().asString();
+
+ gSavedPerAccountSettings.setBOOL("BusyResponseChanged", busy_flag );
}
LLFloaterPreference::~LLFloaterPreference()
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 724ae3c25e..cd795fcfc7 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -28,6 +28,7 @@
#include "llimfloater.h"
+#include "lldraghandle.h"
#include "llnotificationsutil.h"
#include "llagent.h"
@@ -43,6 +44,7 @@
#include "lllayoutstack.h"
#include "lllineeditor.h"
#include "lllogchat.h"
+#include "llnearbychat.h"
#include "llpanelimcontrolpanel.h"
#include "llscreenchannel.h"
#include "llsyswellwindow.h"
@@ -50,7 +52,6 @@
#include "llchathistory.h"
#include "llnotifications.h"
#include "llviewerwindow.h"
-#include "llvoicechannel.h"
#include "lltransientfloatermgr.h"
#include "llinventorymodel.h"
#include "llrootview.h"
@@ -58,18 +59,21 @@
#include "llviewerchat.h"
#include "llnotificationmanager.h"
-
LLIMFloater::LLIMFloater(const LLUUID& session_id)
: LLTransientDockableFloater(NULL, true, session_id),
mControlPanel(NULL),
mSessionID(session_id),
mLastMessageIndex(-1),
mDialog(IM_NOTHING_SPECIAL),
- mChatHistory(NULL),
mInputEditor(NULL),
+ mCloseBtn(NULL),
+ mExpandCollapseBtn(NULL),
+ mTearOffBtn(NULL),
mSavedTitle(),
mTypingStart(),
+ mIsP2PChat(false),
mShouldSendTypingState(false),
+ mChatHistory(NULL),
mMeTyping(false),
mOtherTyping(false),
mTypingTimer(),
@@ -77,17 +81,16 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mPositioned(false),
mSessionInitialized(false)
{
- LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID);
- if (im_session)
+ mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
+
+ if (mSession)
{
- mSessionInitialized = im_session->mSessionInitialized;
+ mIsP2PChat = mSession->isP2PSessionType();
+ mSessionInitialized = mSession->mSessionInitialized;
- mDialog = im_session->mType;
- switch(mDialog){
- case IM_NOTHING_SPECIAL:
- case IM_SESSION_P2P_INVITE:
- mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
- break;
+ mDialog = mSession->mType;
+ switch (mDialog)
+ {
case IM_SESSION_CONFERENCE_START:
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
break;
@@ -104,7 +107,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
}
break;
- default: break;
+ default:
+ break;
}
}
setOverlapsScreenChannel(true);
@@ -112,6 +116,54 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
setDocked(true);
+ mCommitCallbackRegistrar.add("IMSession.Menu.Action",
+ boost::bind(&LLIMFloater::onIMSessionMenuItemClicked, this, _2));
+ mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem",
+ boost::bind(&LLIMFloater::onIMCompactExpandedMenuItemCheck, this, _2));
+ mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem",
+ boost::bind(&LLIMFloater::onIMShowModesMenuItemCheck, this, _2));
+ mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable",
+ boost::bind(&LLIMFloater::onIMShowModesMenuItemEnable, this, _2));
+}
+
+bool LLIMFloater::onIMCompactExpandedMenuItemCheck(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory");
+
+ return is_plain_text_mode? item == "compact_view" : item == "expanded_view";
+}
+
+bool LLIMFloater::onIMShowModesMenuItemCheck(const LLSD& userdata)
+{
+ return gSavedSettings.getBOOL(userdata.asString());
+}
+
+// enable/disable states for the "show time" and "show names" items of the show-modes menu
+bool LLIMFloater::onIMShowModesMenuItemEnable(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory");
+ bool is_not_names = (item != "IMShowNamesForP2PConv");
+ return (plain_text && (is_not_names || mIsP2PChat));
+}
+
+void LLIMFloater::onIMSessionMenuItemClicked(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+
+ if (item == "compact_view" || item == "expanded_view")
+ {
+ gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view");
+ }
+ else
+ {
+ bool prev_value = gSavedSettings.getBOOL(item);
+ gSavedSettings.setBOOL(item, !prev_value);
+ }
+
+ LLIMFloater::processChatHistoryStyleUpdate();
+ LLNearbyChat::processChatHistoryStyleUpdate();
}
void LLIMFloater::onFocusLost()
@@ -133,6 +185,19 @@ void LLIMFloater::onFocusReceived()
}
}
+/*virtual*/
+void LLIMFloater::onOpen(const LLSD& key)
+{
+ LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost());
+ if (host_floater)
+ {
+ // Show the messages pane when opening a floater hosted in the Conversations
+ host_floater->collapseMessagesPane(false);
+ }
+
+ updateHeaderAndToolbar();
+}
+
// virtual
void LLIMFloater::onClose(bool app_quitting)
{
@@ -147,8 +212,8 @@ void LLIMFloater::onClose(bool app_quitting)
}
/* static */
-void LLIMFloater::newIMCallback(const LLSD& data){
-
+void LLIMFloater::newIMCallback(const LLSD& data)
+{
if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())
{
LLUUID session_id = data["session_id"].asUUID();
@@ -209,8 +274,7 @@ void LLIMFloater::sendMsg()
if (mSessionInitialized)
{
- LLIMModel::sendMessage(utf8_text, mSessionID,
- mOtherParticipantUUID,mDialog);
+ LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog);
}
else
{
@@ -225,32 +289,51 @@ void LLIMFloater::sendMsg()
}
}
-
-
LLIMFloater::~LLIMFloater()
{
+ mVoiceChannelStateChangeConnection.disconnect();
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver(this);
+ }
+
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
}
//virtual
BOOL LLIMFloater::postBuild()
{
- const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
+ const LLUUID& other_party_id =
+ LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
if (other_party_id.notNull())
{
mOtherParticipantUUID = other_party_id;
}
+ boundVoiceChannel();
+
+ mCloseBtn = getChild<LLButton>("close_btn");
+ mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));
+
+ mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
+ mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+
+ if (mControlPanel)
+ {
mControlPanel->setSessionId(mSessionID);
mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel"));
- LLButton* slide_left = getChild<LLButton>("slide_left_btn");
- slide_left->setVisible(mControlPanel->getParent()->getVisible());
- slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+ mExpandCollapseBtn->setImageOverlay(
+ getString(mControlPanel->getParent()->getVisible() ? "collapse_icon" : "expand_icon"));
+ }
+ else
+ {
+ mExpandCollapseBtn->setEnabled(false);
+ getChild<LLLayoutPanel>("im_control_panel_holder")->setVisible(false);
+ }
- LLButton* slide_right = getChild<LLButton>("slide_right_btn");
- slide_right->setVisible(!mControlPanel->getParent()->getVisible());
- slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+ mTearOffBtn = getChild<LLButton>("tear_off_btn");
+ mTearOffBtn->setCommitCallback(boost::bind(&LLIMFloater::onTearOffClicked, this));
mInputEditor = getChild<LLLineEditor>("chat_editor");
mInputEditor->setMaxTextLength(1023);
@@ -277,18 +360,16 @@ BOOL LLIMFloater::postBuild()
mTypingStart = LLTrans::getString("IM_typing_start_string");
// Disable input editor if session cannot accept text
- LLIMModel::LLIMSession* im_session =
- LLIMModel::instance().findIMSession(mSessionID);
- if( im_session && !im_session->mTextIMPossible )
+ if ( mSession && !mSession->mTextIMPossible )
{
mInputEditor->setEnabled(FALSE);
mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
}
- if ( im_session && im_session->isP2PSessionType())
+ if (mIsP2PChat)
{
// look up display name for window title
- LLAvatarNameCache::get(im_session->mOtherParticipantID,
+ LLAvatarNameCache::get(mSession->mOtherParticipantID,
boost::bind(&LLIMFloater::onAvatarNameCache,
this, _1, _2));
}
@@ -298,6 +379,10 @@ BOOL LLIMFloater::postBuild()
updateSessionName(session_name, session_name);
}
+ childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this));
+
+ LLVoiceClient::getInstance()->addObserver(this);
+
//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
//see LLFloaterIMPanel for how it is done (IB)
@@ -311,6 +396,94 @@ BOOL LLIMFloater::postBuild()
}
}
+void LLIMFloater::onTearOffClicked()
+{
+ onClickTearOff(this);
+
+ updateHeaderAndToolbar();
+}
+
+void LLIMFloater::boundVoiceChannel()
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+ if(voice_channel)
+ {
+ mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(
+ boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2));
+
+ //call (either p2p, group or ad-hoc) can be already in started state
+ updateCallState(voice_channel->getState());
+ }
+}
+
+void LLIMFloater::updateCallState(LLVoiceChannel::EState state)
+{
+ bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED;
+ getChild<LLButton>("voice_call_btn")->setImageOverlay(
+ is_call_started? getString("call_btn_stop") : getString("call_btn_start"));
+ enableDisableCallBtn();
+
+}
+
+void LLIMFloater::enableDisableCallBtn()
+{
+ bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled()
+ && LLVoiceClient::getInstance()->isVoiceWorking();
+
+ if (!mSession)
+ {
+ getChildView("voice_call_btn")->setEnabled(false);
+ return;
+ }
+
+ bool session_initialized = mSession->mSessionInitialized;
+ bool callback_enabled = mSession->mCallBackEnabled;
+
+ BOOL enable_connect = session_initialized
+ && voice_enabled
+ && callback_enabled;
+ getChildView("voice_call_btn")->setEnabled(enable_connect);
+}
+
+
+void LLIMFloater::onCallButtonClicked()
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+ if (voice_channel)
+ {
+ bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED;
+ if (is_call_active)
+ {
+ gIMMgr->endCall(mSessionID);
+ }
+ else
+ {
+ gIMMgr->startCall(mSessionID);
+ }
+ }
+}
+
+/*void LLIMFloater::onOpenVoiceControlsClicked()
+{
+ LLFloaterReg::showInstance("voice_controls");
+}*/
+
+void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal)
+{
+ if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
+ {
+ return;
+ }
+
+ enableDisableCallBtn();
+}
+
+void LLIMFloater::onVoiceChannelStateChanged(
+ const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+ updateCallState(new_state);
+}
+
void LLIMFloater::updateSessionName(const std::string& ui_title,
const std::string& ui_label)
{
@@ -343,17 +516,6 @@ void LLIMFloater::draw()
LLTransientDockableFloater::draw();
}
-
-// static
-void* LLIMFloater::createPanelIMControl(void* userdata)
-{
- LLIMFloater *self = (LLIMFloater*)userdata;
- self->mControlPanel = new LLPanelIMControlPanel();
- self->mControlPanel->setXMLFilename("panel_im_control_panel.xml");
- return self->mControlPanel;
-}
-
-
// static
void* LLIMFloater::createPanelGroupControl(void* userdata)
{
@@ -374,12 +536,26 @@ void* LLIMFloater::createPanelAdHocControl(void* userdata)
void LLIMFloater::onSlide()
{
- mControlPanel->getParent()->setVisible(!mControlPanel->getParent()->getVisible());
+ LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost());
+ if (host_floater)
+ {
+ // Hide the messages pane if a floater is hosted in the Conversations
+ host_floater->collapseMessagesPane(true);
+ }
+ else ///< floater is torn off
+ {
+ if (mControlPanel)
+ {
+ bool expand = !mControlPanel->getParent()->getVisible();
- gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getParent()->getVisible());
+ // Expand/collapse the IM control panel
+ mControlPanel->getParent()->setVisible(expand);
- getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible());
- getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible());
+ gSavedSettings.setBOOL("IMShowControlPanel", expand);
+
+ mExpandCollapseBtn->setImageOverlay(getString(expand ? "collapse_icon" : "expand_icon"));
+ }
+ }
}
//static
@@ -387,7 +563,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
{
closeHiddenIMToasts();
- if (!gIMMgr->hasSession(session_id)) return NULL;
+ if (!gIMMgr->hasSession(session_id))
+ return NULL;
if(!isChatMultiTab())
{
@@ -407,7 +584,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
bool exist = findInstance(session_id);
LLIMFloater* floater = getInstance(session_id);
- if (!floater) return NULL;
+ if (!floater)
+ return NULL;
if(isChatMultiTab())
{
@@ -521,7 +699,8 @@ BOOL LLIMFloater::getVisible()
{
if(isChatMultiTab())
{
- LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance();
+ LLIMFloaterContainer* im_container =
+ LLIMFloaterContainer::getInstance();
// Treat inactive floater as invisible.
bool is_active = im_container->getActiveFloater() == this;
@@ -533,7 +712,8 @@ BOOL LLIMFloater::getVisible()
}
// getVisible() returns TRUE when Tabbed IM window is minimized.
- return is_active && !im_container->isMinimized() && im_container->getVisible();
+ return is_active && !im_container->isMinimized()
+ && im_container->getVisible();
}
else
{
@@ -546,7 +726,8 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
{
if(!isChatMultiTab())
{
- LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+ LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>(
+ "impanel", session_id);
if (floater && floater->getVisible() && floater->hasFocus())
{
// clicking on chiclet to close floater just hides it to maintain existing
@@ -586,52 +767,61 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
if (mSessionID != im_session_id)
{
mSessionID = im_session_id;
+
setKey(im_session_id);
+ if (mControlPanel)
+ {
mControlPanel->setSessionId(im_session_id);
}
+ boundVoiceChannel();
- // updating "Call" button from group control panel here to enable it without placing into draw() (EXT-4796)
- if(gAgent.isInGroup(im_session_id))
- {
- mControlPanel->updateCallButton();
+ mSession = LLIMModel::getInstance()->findIMSession(mSessionID);
+ mIsP2PChat = mSession && mSession->isP2PSessionType();
}
//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
-
//need to send delayed messaged collected while waiting for session initialization
- if (!mQueuedMsgsForInit.size()) return;
+ if (!mQueuedMsgsForInit.size())
+ return;
LLSD::array_iterator iter;
for ( iter = mQueuedMsgsForInit.beginArray();
- iter != mQueuedMsgsForInit.endArray();
- ++iter)
+ iter != mQueuedMsgsForInit.endArray(); ++iter)
{
LLIMModel::sendMessage(iter->asString(), mSessionID,
mOtherParticipantUUID, mDialog);
}
}
-void LLIMFloater::updateMessages()
+void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args)
{
- bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");
+ LLChat& tmp_chat = const_cast<LLChat&>(chat);
+ if (!chat.mMuted)
+ {
+ tmp_chat.mFromName = chat.mFromName;
+ LLSD chat_args;
+ if (args) chat_args = args;
+ chat_args["use_plain_text_chat_history"] =
+ gSavedSettings.getBOOL("PlainTextChatHistory");
+ chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime");
+ chat_args["show_names_for_p2p_conv"] = !mIsP2PChat
+ || gSavedSettings.getBOOL("IMShowNamesForP2PConv");
+
+ mChatHistory->appendMessage(chat, chat_args);
+ }
+}
+
+void LLIMFloater::updateMessages()
+{
std::list<LLSD> messages;
// we shouldn't reset unread message counters if IM floater doesn't have focus
- if (hasFocus())
- {
- LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
- }
- else
- {
- LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1);
- }
+ LLIMModel::instance().getMessages(
+ mSessionID, messages, mLastMessageIndex + 1, hasFocus());
if (messages.size())
{
- LLSD chat_args;
- chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
-
std::ostringstream message;
std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
@@ -681,7 +871,7 @@ void LLIMFloater::updateMessages()
chat.mText = message;
}
- mChatHistory->appendMessage(chat, chat_args);
+ appendMessage(chat);
mLastMessageIndex = msg["index"].asInteger();
// if it is a notification - next message is a notification history log, so skip it
@@ -773,14 +963,16 @@ void LLIMFloater::setTyping(bool typing)
if ( mTypingTimer.getElapsedTimeF32() > 1.f )
{
// Still typing, send 'start typing' notification
- LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
+ LLIMModel::instance().sendTypingState(mSessionID,
+ mOtherParticipantUUID, TRUE);
mShouldSendTypingState = false;
}
}
else
{
// Send 'stop typing' notification immediately
- LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
+ LLIMModel::instance().sendTypingState(mSessionID,
+ mOtherParticipantUUID, FALSE);
mShouldSendTypingState = false;
}
}
@@ -807,7 +999,8 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
void LLIMFloater::processAgentListUpdates(const LLSD& body)
{
- if ( !body.isMap() ) return;
+ if (!body.isMap())
+ return;
if ( body.has("agent_updates") && body["agent_updates"].isMap() )
{
@@ -834,14 +1027,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body)
}
}
-void LLIMFloater::updateChatHistoryStyle()
-{
- mChatHistory->clear();
- mLastMessageIndex = -1;
- updateMessages();
-}
-
-void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue)
+void LLIMFloater::processChatHistoryStyleUpdate()
{
LLFontGL* font = LLViewerChat::getChatFont();
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
@@ -851,11 +1037,10 @@ void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue)
LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter);
if (floater)
{
- floater->updateChatHistoryStyle();
+ floater->reloadMessages();
floater->mInputEditor->setFont(font);
}
}
-
}
void LLIMFloater::processSessionUpdate(const LLSD& session_update)
@@ -869,7 +1054,8 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)
if (voice_moderated)
{
- setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
+ setTitle(session_label + std::string(" ")
+ + LLTrans::getString("IM_moderated_chat_label"));
}
else
{
@@ -887,7 +1073,6 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask,
void *cargo_data, EAcceptance *accept,
std::string& tooltip_msg)
{
-
if (mDialog == IM_NOTHING_SPECIAL)
{
LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop,
@@ -971,7 +1156,6 @@ BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop)
BOOL LLIMFloater::isInviteAllowed() const
{
-
return ( (IM_SESSION_CONFERENCE_START == mDialog)
|| (IM_SESSION_INVITE == mDialog) );
}
@@ -1023,8 +1207,7 @@ BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)
LLHTTPClient::post(
url,
data,
- new LLSessionInviteResponder(
- mSessionID));
+ new LLSessionInviteResponder(mSessionID));
}
else
{
@@ -1076,10 +1259,62 @@ void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
}
}
+ }
+}
+
+void LLIMFloater::updateHeaderAndToolbar()
+{
+ bool is_hosted = getHost() != NULL;
+
+ if (is_hosted)
+ {
+ for (S32 i = 0; i < BUTTON_COUNT; i++)
+ {
+ if (!mButtons[i])
+ {
+ continue;
+ }
+ // Hide the standard header buttons in a docked IM floater.
+ mButtons[i]->setVisible(false);
}
}
+ bool is_control_panel_visible = false;
+ if (mControlPanel)
+ {
+ // Control panel should be visible only in torn off floaters.
+ is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel");
+ mControlPanel->getParent()->setVisible(is_control_panel_visible);
+ }
+
+ // Display collapse image (<<) if the floater is hosted
+ // or if it is torn off but has an open control panel.
+ bool is_expanded = is_hosted || is_control_panel_visible;
+ mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));
+
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID);
+ if (session)
+ {
+ // The button (>>) should be disabled for torn off P2P conversations.
+ mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType());
+ }
+ else
+ {
+ llwarns << "IM session not found." << llendl;
+ }
+
+ if (mDragHandle)
+ {
+ // toggle floater's drag handle and title visibility
+ mDragHandle->setVisible(!is_hosted);
+ }
+
+ mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon"));
+
+ mCloseBtn->setVisible(is_hosted);
+}
+
// static
void LLIMFloater::closeHiddenIMToasts()
{
@@ -1093,7 +1328,8 @@ void LLIMFloater::closeHiddenIMToasts()
}
};
- LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();
+ LLNotificationsUI::LLScreenChannel* channel =
+ LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();
if (channel != NULL)
{
channel->closeHiddenToasts(IMToastMatcher());
@@ -1135,15 +1371,19 @@ void LLIMFloater::initIMFloater()
void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)
{
LLUUID session_id = data["session_id"];
- if (session_id.isNull()) return;
+ if (session_id.isNull())
+ return;
LLUUID from_id = data["from_id"];
- if (gAgentID == from_id || LLUUID::null == from_id) return;
+ if (gAgentID == from_id || LLUUID::null == from_id)
+ return;
LLIMFloater* floater = LLIMFloater::findInstance(session_id);
- if (!floater) return;
+ if (!floater)
+ return;
- if (IM_NOTHING_SPECIAL != floater->mDialog) return;
+ if (IM_NOTHING_SPECIAL != floater->mDialog)
+ return;
floater->removeTypingIndicator();
}
@@ -1154,9 +1394,11 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )
if (isChatMultiTab())
{
LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance();
- if (!im_box) return;
+ if (!im_box)
+ return;
- if (LLIMFloater::findInstance(session_id)) return;
+ if (LLIMFloater::findInstance(session_id))
+ return;
LLIMFloater* new_tab = LLIMFloater::getInstance(session_id);
@@ -1182,7 +1424,8 @@ void LLIMFloater::onClickCloseBtn()
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
- if (is_call_with_chat && voice_channel != NULL && voice_channel->isActive())
+ if (is_call_with_chat && voice_channel != NULL
+ && voice_channel->isActive())
{
LLSD payload;
payload["session_id"] = mSessionID;
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index f7cd35b5eb..8e7ab4cc21 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -27,12 +27,16 @@
#ifndef LL_IMFLOATER_H
#define LL_IMFLOATER_H
+#include "llimview.h"
#include "llinstantmessage.h"
#include "lllogchat.h"
#include "lltooldraganddrop.h"
+#include "llvoicechannel.h"
+#include "llvoiceclient.h"
#include "lltransientdockablefloater.h"
class LLAvatarName;
+class LLButton;
class LLLineEditor;
class LLPanelChatControlPanel;
class LLChatHistory;
@@ -43,14 +47,16 @@ class LLInventoryCategory;
* Individual IM window that appears at the bottom of the screen,
* optionally "docked" to the bottom tray.
*/
-class LLIMFloater : public LLTransientDockableFloater
+class LLIMFloater
+ : public LLTransientDockableFloater
+ , public LLVoiceClientStatusObserver
{
LOG_CLASS(LLIMFloater);
public:
LLIMFloater(const LLUUID& session_id);
virtual ~LLIMFloater();
-
+
// LLView overrides
/*virtual*/ BOOL postBuild();
/*virtual*/ void setVisible(BOOL visible);
@@ -59,6 +65,7 @@ public:
/*virtual*/ void draw();
// LLFloater overrides
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
@@ -78,7 +85,7 @@ public:
// get new messages from LLIMModel
void updateMessages();
void reloadMessages();
- static void onSendMsg( LLUICtrl*, void*);
+ static void onSendMsg(LLUICtrl*, void*);
void sendMsg();
// callback for LLIMModel on new messages
@@ -89,17 +96,26 @@ public:
void setPositioned(bool b) { mPositioned = b; };
void onVisibilityChange(const LLSD& new_visibility);
+
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ void onChange(EStatusType status, const std::string &channelURI,
+ bool proximal);
+
+ virtual void onVoiceChannelStateChanged(
+ const LLVoiceChannel::EState& old_state,
+ const LLVoiceChannel::EState& new_state);
+
void processIMTyping(const LLIMInfo* im_info, BOOL typing);
void processAgentListUpdates(const LLSD& body);
void processSessionUpdate(const LLSD& session_update);
- void updateChatHistoryStyle();
- static void processChatHistoryStyleUpdate(const LLSD& newvalue);
+ static void processChatHistoryStyleUpdate();
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop, EDragAndDropType cargo_type,
- void *cargo_data, EAcceptance *accept,
- std::string& tooltip_msg);
+ BOOL drop, EDragAndDropType cargo_type,
+ void *cargo_data, EAcceptance *accept,
+ std::string& tooltip_msg);
/**
* Returns true if chat is displayed in multi tabbed floater
@@ -117,8 +133,7 @@ public:
virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
protected:
- /* virtual */
- void onClickCloseBtn();
+ /* virtual */ void onClickCloseBtn();
private:
// process focus events to set a currently active session
@@ -127,24 +142,37 @@ private:
// Update the window title, input field help text, etc.
void updateSessionName(const std::string& ui_title, const std::string& ui_label);
-
+
// For display name lookups for IM window titles
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
-
+
BOOL dropCallingCard(LLInventoryItem* item, BOOL drop);
BOOL dropCategory(LLInventoryCategory* category, BOOL drop);
BOOL isInviteAllowed() const;
BOOL inviteToSession(const uuid_vec_t& agent_ids);
-
- static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
- static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
- static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
- void setTyping(bool typing);
- void onSlide();
- static void* createPanelIMControl(void* userdata);
- static void* createPanelGroupControl(void* userdata);
- static void* createPanelAdHocControl(void* userdata);
+ void appendMessage(const LLChat& chat, const LLSD &args = 0);
+ static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata );
+ static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
+ static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
+ void setTyping(bool typing);
+ void onSlide();
+ static void* createPanelGroupControl(void* userdata);
+ static void* createPanelAdHocControl(void* userdata);
+
+ void onTearOffClicked();
+
+ bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata);
+ bool onIMShowModesMenuItemCheck(const LLSD& userdata);
+ bool onIMShowModesMenuItemEnable(const LLSD& userdata);
+ void onIMSessionMenuItemClicked(const LLSD& userdata);
+ void onCallButtonClicked();
+
+ void boundVoiceChannel();
+ void enableDisableCallBtn();
+
+ // refresh a visual state of the Call button
+ void updateCallState(LLVoiceChannel::EState state);
// Add the "User is typing..." indicator.
void addTypingIndicator(const LLIMInfo* im_info);
@@ -152,17 +180,22 @@ private:
// Remove the "User is typing..." indicator.
void removeTypingIndicator(const LLIMInfo* im_info = NULL);
+ /// Update floater header and toolbar buttons when hosted/torn off state is toggled.
+ void updateHeaderAndToolbar();
+
static void closeHiddenIMToasts();
static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response);
LLPanelChatControlPanel* mControlPanel;
LLUUID mSessionID;
+ LLIMModel::LLIMSession* mSession;
S32 mLastMessageIndex;
+ LLChatHistory* mChatHistory;
+
EInstantMessage mDialog;
LLUUID mOtherParticipantUUID;
- LLChatHistory* mChatHistory;
LLLineEditor* mInputEditor;
bool mPositioned;
@@ -171,12 +204,19 @@ private:
bool mMeTyping;
bool mOtherTyping;
bool mShouldSendTypingState;
+ bool mIsP2PChat;
LLFrameTimer mTypingTimer;
LLFrameTimer mTypingTimeoutTimer;
bool mSessionInitialized;
LLSD mQueuedMsgsForInit;
-};
+ // connection to voice channel state change signal
+ boost::signals2::connection mVoiceChannelStateChangeConnection;
+
+ LLButton* mCloseBtn;
+ LLButton* mExpandCollapseBtn;
+ LLButton* mTearOffBtn;
+};
#endif // LL_IMFLOATER_H
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index c8e48b0d42..b051440589 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -28,18 +28,23 @@
#include "llviewerprecompiledheaders.h"
#include "llimfloatercontainer.h"
+
#include "llfloaterreg.h"
-#include "llimview.h"
+#include "lllayoutstack.h"
+
+#include "llagent.h"
#include "llavatariconctrl.h"
#include "llgroupiconctrl.h"
-#include "llagent.h"
+#include "llimview.h"
#include "lltransientfloatermgr.h"
+#include "llviewercontrol.h"
//
// LLIMFloaterContainer
//
LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
: LLMultiFloater(seed)
+ ,mExpandCollapseBtn(NULL)
{
mAutoResize = FALSE;
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
@@ -49,6 +54,9 @@ LLIMFloaterContainer::~LLIMFloaterContainer()
{
mNewMessageConnection.disconnect();
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
+
+ gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed());
+ gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed());
}
BOOL LLIMFloaterContainer::postBuild()
@@ -56,6 +64,19 @@ 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");
+
+ mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn");
+ mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this));
+
+ collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
+ collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"));
+
return TRUE;
}
@@ -74,6 +95,7 @@ void LLIMFloaterContainer::onOpen(const LLSD& key)
*/
}
+// virtual
void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point)
@@ -89,6 +111,12 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
+ LLView* floater_contents = floaterp->getChild<LLView>("contents_view");
+
+ // we don't show the header when the floater is hosted,
+ // so reshape floater contents to occupy the header space
+ floater_contents->setShape(floaterp->getRect());
+
LLUUID session_id = floaterp->getKey();
LLIconCtrl* icon = 0;
@@ -116,11 +144,56 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
mTabContainer->setTabImage(floaterp, icon);
}
+// virtual
+void LLIMFloaterContainer::removeFloater(LLFloater* floaterp)
+{
+ LLMultiFloater::removeFloater(floaterp);
+
+ LLRect contents_rect = floaterp->getRect();
+
+ // reduce the floater contents height by header height
+ contents_rect.mTop -= floaterp->getHeaderHeight();
+
+ LLView* floater_contents = floaterp->getChild<LLView>("contents_view");
+ floater_contents->setShape(contents_rect);
+}
+
void LLIMFloaterContainer::onCloseFloater(LLUUID& id)
{
mSessions.erase(id);
}
+// 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();
@@ -135,6 +208,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");
@@ -161,4 +249,67 @@ void LLIMFloaterContainer::setMinimized(BOOL b)
}
}
+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);
+ setShape(floater_rect);
+
+ 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);
+}
+
// EOF
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
index 892ecef48d..92938ff405 100644
--- a/indra/newview/llimfloatercontainer.h
+++ b/indra/newview/llimfloatercontainer.h
@@ -35,6 +35,9 @@
#include "llavatarpropertiesprocessor.h"
#include "llgroupmgr.h"
+class LLButton;
+class LLLayoutPanel;
+class LLLayoutStack;
class LLTabContainer;
class LLIMFloaterContainer : public LLMultiFloater
@@ -50,6 +53,7 @@ public:
/*virtual*/ void addFloater(LLFloater* floaterp,
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
+ /*virtual*/ void removeFloater(LLFloater* floaterp);
static LLFloater* getCurrentVoiceFloater();
@@ -59,12 +63,27 @@ public:
virtual void setMinimized(BOOL b);
+ void collapseMessagesPane(bool collapse);
+
private:
typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;
avatarID_panel_map_t mSessions;
boost::signals2::connection mNewMessageConnection;
+ /*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height);
+
void onNewMessageReceived(const LLSD& data);
+
+ void onExpandCollapseButtonClicked();
+
+ void collapseConversationsPane(bool collapse);
+
+ void updateState(bool collapse, S32 delta_width);
+
+ LLButton* mExpandCollapseBtn;
+ LLLayoutPanel* mMessagesPane;
+ LLLayoutPanel* mConversationsPane;
+ LLLayoutStack* mConversationsStack;
};
#endif // LL_LLIMFLOATERCONTAINER_H
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index a7c4618fa4..18d39b7aa4 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -716,6 +716,16 @@ bool LLIMModel::clearSession(const LLUUID& session_id)
return true;
}
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index, const bool sendNoUnreadMsgs)
+{
+ getMessagesSilently(session_id, messages, start_index);
+
+ if (sendNoUnreadMsgs)
+ {
+ sendNoUnreadMessages(session_id);
+ }
+}
+
void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
{
LLIMSession* session = findIMSession(session_id);
@@ -757,13 +767,6 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id)
mNoUnreadMsgsSignal(arg);
}
-void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
-{
- getMessagesSilently(session_id, messages, start_index);
-
- sendNoUnreadMessages(session_id);
-}
-
bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
LLIMSession* session = findIMSession(session_id);
@@ -2497,6 +2500,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());
}
// log message to file
+
else
{
std::string session_name;
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 7c2cd03d97..9d19af4b62 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -192,12 +192,6 @@ public:
bool clearSession(const LLUUID& session_id);
/**
- * Populate supplied std::list with messages starting from index specified by start_index without
- * emitting no unread messages signal.
- */
- void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
-
- /**
* Sends no unread messages signal.
*/
void sendNoUnreadMessages(const LLUUID& session_id);
@@ -205,7 +199,7 @@ public:
/**
* Populate supplied std::list with messages starting from index specified by start_index
*/
- void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
+ void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0, const bool sendNoUnreadMsgs = true);
/**
* Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id
@@ -288,6 +282,12 @@ public:
private:
/**
+ * Populate supplied std::list with messages starting from index specified by start_index without
+ * emitting no unread messages signal.
+ */
+ void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
+
+ /**
* Add message to a list of message associated with session specified by session_id
*/
bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index a7303ad035..3c4b0b9aae 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -25,7 +25,6 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llnearbychat.h"
#include "llviewercontrol.h"
#include "llviewerwindow.h"
@@ -55,8 +54,42 @@
#include "llfloaterreg.h"
#include "lltrans.h"
-static const S32 RESIZE_BAR_THICKNESS = 3;
+// --- 2 functions in the global namespace :( ---
+bool isWordsName(const std::string& name)
+{
+ // checking to see if it's display name plus username in parentheses
+ S32 open_paren = name.find(" (", 0);
+ S32 close_paren = name.find(')', 0);
+
+ if (open_paren != std::string::npos &&
+ close_paren == name.length()-1)
+ {
+ return true;
+ }
+ else
+ {
+ //checking for a single space
+ S32 pos = name.find(' ', 0);
+ return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos;
+ }
+}
+
+std::string appendTime()
+{
+ time_t utc_time;
+ utc_time = time_corrected();
+ std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
+ +LLTrans::getString("TimeMin")+"]";
+
+ LLSD substitution;
+
+ substitution["datetime"] = (S32) utc_time;
+ LLStringUtil::format (timeStr, substitution);
+ return timeStr;
+}
+
+static const S32 RESIZE_BAR_THICKNESS = 3;
static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat");
@@ -90,38 +123,32 @@ BOOL LLNearbyChat::postBuild()
return true;
}
-std::string appendTime()
-{
- time_t utc_time;
- utc_time = time_corrected();
- std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
- +LLTrans::getString("TimeMin")+"]";
-
- LLSD substitution;
-
- substitution["datetime"] = (S32) utc_time;
- LLStringUtil::format (timeStr, substitution);
-
- return timeStr;
-}
-
-void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
+void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args)
{
LLChat& tmp_chat = const_cast<LLChat&>(chat);
if(tmp_chat.mTimeStr.empty())
tmp_chat.mTimeStr = appendTime();
- bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");
-
if (!chat.mMuted)
{
tmp_chat.mFromName = chat.mFromName;
- LLSD chat_args = args;
- chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
+ LLSD chat_args;
+ if (args) chat_args = args;
+ chat_args["use_plain_text_chat_history"] =
+ gSavedSettings.getBOOL("PlainTextChatHistory");
+ chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime");
+ chat_args["show_names_for_p2p_conv"] = false
+ || gSavedSettings.getBOOL("IMShowNamesForP2PConv");
+
mChatHistory->appendMessage(chat, chat_args);
}
+}
+
+void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
+{
+ appendMessage(chat, args);
if(archive)
{
@@ -130,12 +157,9 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
mMessageArchive.erase(mMessageArchive.begin());
}
- if (args["do_not_log"].asBoolean())
- {
- return;
- }
-
- if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
+ // logging
+ if (!args["do_not_log"].asBoolean()
+ && gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
{
std::string from_name = chat.mFromName;
@@ -162,10 +186,10 @@ void LLNearbyChat::onNearbySpeakers()
LLFloaterSidePanelContainer::showPanel("people", "panel_people", param);
}
-
void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)
{
}
+
bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)
{
std::string str = userdata.asString();
@@ -213,7 +237,7 @@ void LLNearbyChat::updateChatHistoryStyle()
}
//static
-void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue)
+void LLNearbyChat::processChatHistoryStyleUpdate()
{
LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar");
LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat");
@@ -221,25 +245,6 @@ void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue)
nearby_chat->updateChatHistoryStyle();
}
-bool isWordsName(const std::string& name)
-{
- // checking to see if it's display name plus username in parentheses
- S32 open_paren = name.find(" (", 0);
- S32 close_paren = name.find(')', 0);
-
- if (open_paren != std::string::npos &&
- close_paren == name.length()-1)
- {
- return true;
- }
- else
- {
- //checking for a single space
- S32 pos = name.find(' ', 0);
- return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos;
- }
-}
-
void LLNearbyChat::loadHistory()
{
LLSD do_not_log;
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index 7c5975cbc5..47f4de1c6d 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -34,7 +34,8 @@
class LLResizeBar;
class LLChatHistory;
-class LLNearbyChat: public LLPanel
+class LLNearbyChat
+: public LLPanel
{
public:
LLNearbyChat(const Params& p = LLPanel::getDefaultParams());
@@ -57,7 +58,7 @@ public:
virtual void updateChatHistoryStyle();
- static void processChatHistoryStyleUpdate(const LLSD& newvalue);
+ static void processChatHistoryStyleUpdate();
void loadHistory();
@@ -67,7 +68,8 @@ public:
private:
void getAllowedRect (LLRect& rect);
-
+ // prepare chat's params and out one message to chatHistory
+ void appendMessage(const LLChat& chat, const LLSD &args = 0);
void onNearbySpeakers ();
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index eda0749cdb..bc4097cd93 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -1,31 +1,30 @@
-/**
+/**
* @file llpanelavatar.cpp
* @brief LLPanelAvatar and related class implementations
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
-
#include "llfloaterreg.h"
#include "llpanelimcontrolpanel.h"
@@ -39,92 +38,15 @@
#include "llavatarlist.h"
#include "llparticipantlist.h"
#include "llimview.h"
-#include "llvoicechannel.h"
#include "llspeakers.h"
#include "lltrans.h"
-void LLPanelChatControlPanel::onCallButtonClicked()
-{
- gIMMgr->startCall(mSessionId);
-}
-
-void LLPanelChatControlPanel::onEndCallButtonClicked()
-{
- gIMMgr->endCall(mSessionId);
-}
-
-void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
-{
- LLFloaterReg::showInstance("voice_controls");
-}
-
-void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal)
-{
- if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
- {
- return;
- }
-
- updateCallButton();
-}
-
-void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
-{
- updateButtons(new_state);
-}
-
-void LLPanelChatControlPanel::updateCallButton()
-{
- // hide/show call button
- bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
-
- LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
-
- if (!session)
- {
- getChildView("call_btn")->setEnabled(false);
- return;
- }
-
- bool session_initialized = session->mSessionInitialized;
- bool callback_enabled = session->mCallBackEnabled;
-
- BOOL enable_connect = session_initialized
- && voice_enabled
- && callback_enabled;
- getChildView("call_btn")->setEnabled(enable_connect);
-}
-
-void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state)
-{
- bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED;
- getChildView("end_call_btn_panel")->setVisible( is_call_started);
- getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel"));
- getChildView("call_btn_panel")->setVisible( ! is_call_started);
-
- getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED);
-
- updateCallButton();
-
-}
-
LLPanelChatControlPanel::~LLPanelChatControlPanel()
{
- mVoiceChannelStateChangeConnection.disconnect();
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->removeObserver(this);
- }
}
BOOL LLPanelChatControlPanel::postBuild()
{
- childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
- childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
- childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this));
-
- LLVoiceClient::getInstance()->addObserver(this);
-
return TRUE;
}
@@ -132,224 +54,8 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
{
//Method is called twice for AdHoc and Group chat. Second time when server init reply received
mSessionId = session_id;
- LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId);
- if(voice_channel)
- {
- mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
-
- //call (either p2p, group or ad-hoc) can be already in started state
- updateButtons(voice_channel->getState());
- }
-}
-
-LLPanelIMControlPanel::LLPanelIMControlPanel()
-{
-}
-
-LLPanelIMControlPanel::~LLPanelIMControlPanel()
-{
- LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this);
-}
-
-BOOL LLPanelIMControlPanel::postBuild()
-{
- childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this));
- childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this));
-
- childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
- childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this));
- childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this));
-
- childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this));
- childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this));
- childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this));
-
- getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2));
-
- getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
-
- setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this));
-
- return LLPanelChatControlPanel::postBuild();
-}
-
-void LLPanelIMControlPanel::draw()
-{
- bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID);
-
- getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted);
- getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted);
-
- if (getChildView("volume_ctrl_panel")->getVisible())
- {
-
- bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
-
- LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
- mute_btn->setValue( is_muted_voice );
-
- LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
- volume_slider->setEnabled( !is_muted_voice );
-
- F32 volume;
-
- if (is_muted_voice)
- {
- // it's clearer to display their volume as zero
- volume = 0.f;
- }
- else
- {
- // actual volume
- volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID);
- }
- volume_slider->setValue( (F64)volume );
- }
-
- LLPanelChatControlPanel::draw();
}
-void LLPanelIMControlPanel::onClickMuteVolume()
-{
- // By convention, we only display and toggle voice mutes, not all mutes
- LLMuteList* mute_list = LLMuteList::getInstance();
- bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
-
- LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
- if (!is_muted)
- {
- mute_list->add(mute, LLMute::flagVoiceChat);
- }
- else
- {
- mute_list->remove(mute, LLMute::flagVoiceChat);
- }
-}
-
-void LLPanelIMControlPanel::onClickBlock()
-{
- LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
-
- LLMuteList::getInstance()->add(mute);
-}
-
-void LLPanelIMControlPanel::onClickUnblock()
-{
- LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
-
- LLMuteList::getInstance()->remove(mute);
-}
-
-void LLPanelIMControlPanel::onVolumeChange(const LLSD& data)
-{
- F32 volume = (F32)data.asReal();
- LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
-}
-
-void LLPanelIMControlPanel::onTeleportButtonClicked()
-{
- LLAvatarActions::offerTeleport(mAvatarID);
-}
-void LLPanelIMControlPanel::onPayButtonClicked()
-{
- LLAvatarActions::pay(mAvatarID);
-}
-
-void LLPanelIMControlPanel::onViewProfileButtonClicked()
-{
- LLAvatarActions::showProfile(mAvatarID);
-}
-
-void LLPanelIMControlPanel::onAddFriendButtonClicked()
-{
- LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon");
- std::string full_name = avatar_icon->getFullName();
- LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name);
-}
-
-void LLPanelIMControlPanel::onShareButtonClicked()
-{
- LLAvatarActions::share(mAvatarID);
-}
-
-void LLPanelIMControlPanel::onFocusReceived()
-{
- // Disable all the buttons (Call, Teleport, etc) if disconnected.
- if (gDisconnected)
- {
- setAllChildrenEnabled(FALSE);
- }
-}
-
-void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
-{
- LLPanelChatControlPanel::setSessionId(session_id);
-
- LLIMModel& im_model = LLIMModel::instance();
-
- LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this);
- mAvatarID = im_model.getOtherParticipantID(session_id);
- LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this);
-
- // Disable "Add friend" button for friends.
- getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID));
-
- // Disable "Teleport" button if friend is offline
- if(LLAvatarActions::isFriend(mAvatarID))
- {
- getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID));
- }
-
- getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID);
-
- // Disable most profile buttons if the participant is
- // not really an SL avatar (e.g., an Avaline caller).
- LLIMModel::LLIMSession* im_session =
- im_model.findIMSession(session_id);
- if( im_session && !im_session->mOtherParticipantIsAvatar )
- {
- getChildView("view_profile_btn")->setEnabled(FALSE);
- getChildView("add_friend_btn")->setEnabled(FALSE);
-
- getChildView("share_btn")->setEnabled(FALSE);
- getChildView("teleport_btn")->setEnabled(FALSE);
- getChildView("pay_btn")->setEnabled(FALSE);
-
- getChild<LLTextBox>("avatar_name")->setValue(im_session->mName);
- getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName);
- }
- else
- {
- // If the participant is an avatar, fetch the currect name
- gCacheName->get(mAvatarID, false,
- boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3));
- }
-}
-
-//virtual
-void LLPanelIMControlPanel::changed(U32 mask)
-{
- getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID));
-
- // Disable "Teleport" button if friend is offline
- if(LLAvatarActions::isFriend(mAvatarID))
- {
- getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID));
- }
-}
-
-void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group)
-{
- if ( id == mAvatarID )
- {
- std::string avatar_name = full_name;
- getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
- getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
-
- bool is_linden = LLStringUtil::endsWith(full_name, " Linden");
- getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden);
- }
-}
LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
mParticipantList(NULL)
@@ -358,7 +64,6 @@ mParticipantList(NULL)
BOOL LLPanelGroupControlPanel::postBuild()
{
- childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this));
return LLPanelChatControlPanel::postBuild();
}
@@ -378,10 +83,6 @@ void LLPanelGroupControlPanel::draw()
LLPanelChatControlPanel::draw();
}
-void LLPanelGroupControlPanel::onGroupInfoButtonClicked()
-{
- LLGroupActions::show(mGroupID);
-}
void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata)
{
@@ -398,23 +99,17 @@ void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata)
}
-void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
-{
- LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state);
- mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
-}
-
void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
{
LLPanelChatControlPanel::setSessionId(session_id);
mGroupID = session_id;
- // for group and Ad-hoc chat we need to include agent into list
+ // for group and Ad-hoc chat we need to include agent into list
if(!mParticipantList)
{
LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id);
- mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false);
+ mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false);
}
}
@@ -428,4 +123,3 @@ BOOL LLPanelAdHocControlPanel::postBuild()
//We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat
return LLPanelChatControlPanel::postBuild();
}
-
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index bba847b5d4..02915ec4bb 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -28,14 +28,12 @@
#define LL_LLPANELIMCONTROLPANEL_H
#include "llpanel.h"
-#include "llvoicechannel.h"
#include "llcallingcard.h"
class LLParticipantList;
-class LLPanelChatControlPanel
+class LLPanelChatControlPanel
: public LLPanel
- , public LLVoiceClientStatusObserver
{
public:
LLPanelChatControlPanel() :
@@ -44,21 +42,6 @@ public:
virtual BOOL postBuild();
- void onCallButtonClicked();
- void onEndCallButtonClicked();
- void onOpenVoiceControlsClicked();
-
- // Implements LLVoiceClientStatusObserver::onChange() to enable the call
- // button when voice is available
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-
- virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
-
- void updateButtons(LLVoiceChannel::EState state);
-
- // Enables/disables call button depending on voice availability
- void updateCallButton();
-
virtual void setSessionId(const LLUUID& session_id);
const LLUUID& getSessionId() { return mSessionId; }
@@ -69,41 +52,6 @@ private:
boost::signals2::connection mVoiceChannelStateChangeConnection;
};
-
-class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver
-{
-public:
- LLPanelIMControlPanel();
- ~LLPanelIMControlPanel();
-
- BOOL postBuild();
-
- void setSessionId(const LLUUID& session_id);
-
- // LLFriendObserver trigger
- virtual void changed(U32 mask);
-
-protected:
- void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
-
-private:
- void onViewProfileButtonClicked();
- void onAddFriendButtonClicked();
- void onShareButtonClicked();
- void onTeleportButtonClicked();
- void onPayButtonClicked();
- void onFocusReceived();
-
- void onClickMuteVolume();
- void onClickBlock();
- void onClickUnblock();
- /*virtual*/ void draw();
- void onVolumeChange(const LLSD& data);
-
- LLUUID mAvatarID;
-};
-
-
class LLPanelGroupControlPanel : public LLPanelChatControlPanel
{
public:
@@ -121,9 +69,7 @@ protected:
LLParticipantList* mParticipantList;
private:
- void onGroupInfoButtonClicked();
void onSortMenuItemClicked(const LLSD& userdata);
- /*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
};
class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index 0d66b8f10b..c84790d839 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -51,6 +51,7 @@ LLContextMenu* NearbyMenu::createMenu()
// set up the callbacks for all of the avatar menu items
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ LLContextMenu* menu;
if ( mUUIDs.size() == 1 )
{
@@ -73,7 +74,7 @@ LLContextMenu* NearbyMenu::createMenu()
enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2));
// create the context menu from the XUI
- return createFromFile("menu_people_nearby.xml");
+ menu = createFromFile("menu_people_nearby.xml");
}
else
{
@@ -89,8 +90,10 @@ LLContextMenu* NearbyMenu::createMenu()
enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
// create the context menu from the XUI
- return createFromFile("menu_people_nearby_multiselect.xml");
+ menu = createFromFile("menu_people_nearby_multiselect.xml");
}
+
+ return menu;
}
bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 975a6c67d8..59d26edff2 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -32,6 +32,7 @@
#include "llagent.h"
#include "llimview.h"
+#include "llpanelpeoplemenus.h"
#include "llnotificationsutil.h"
#include "llparticipantlist.h"
#include "llspeakers.h"
@@ -197,10 +198,10 @@ private:
uuid_set_t mAvalineCallers;
};
-LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
LLAvatarList* avatar_list,
bool use_context_menu/* = true*/,
- bool exclude_agent /*= true*/,
+ bool exclude_agent /*= true*/,
bool can_toggle_icons /*= true*/) :
mSpeakerMgr(data_source),
mAvatarList(avatar_list),
@@ -233,8 +234,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
if (use_context_menu)
{
- mParticipantListMenu = new LLParticipantListMenu(*this);
- mAvatarList->setContextMenu(mParticipantListMenu);
+ //mParticipantListMenu = new LLParticipantListMenu(*this);
+ //mAvatarList->setContextMenu(mParticipantListMenu);
+ mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
}
else
{
@@ -670,7 +672,7 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::
return mParent.onSpeakerMuteEvent(event, userdata);
}
-LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
+/*LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
{
// set up the callbacks for all of the avatar menu items
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -708,7 +710,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
main_menu->arrangeAndClear();
return main_menu;
-}
+}*/
void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y)
{
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index b9358cf37c..1c6f51e131 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -29,7 +29,6 @@
#include "llevent.h"
#include "lleventtimer.h"
-#include "llspeakers.h"
#include "llvoicechannel.h"
class LLSpeakerMgr;
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index e123de46c2..ce40f44a64 100644
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -1,49 +1,122 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater
- can_close="false"
+ can_close="true"
can_minimize="true"
can_resize="true"
- height="390"
+ height="430"
layout="topleft"
+ min_height="50"
name="floater_im_box"
help_topic="floater_im_box"
save_rect="true"
save_visibility="true"
single_instance="true"
title="CONVERSATIONS"
- width="396">
- <tab_container
- follows="left|right|top|bottom"
- height="390"
+ width="680">
+ <string
+ name="collapse_icon"
+ value="TabIcon_Open_Off"/>
+ <string
+ name="expand_icon"
+ value="TabIcon_Close_Off"/>
+ <layout_stack
+ animate="true"
+ follows="all"
+ height="430"
layout="topleft"
- left="1"
- name="im_box_tab_container"
- tab_position="bottom"
- tab_width="64"
- tab_max_width = "134"
- tab_height="16"
- use_custom_icon_ctrl="true"
- tab_icon_ctrl_pad="2"
- halign="left"
- use_ellipses="true"
+ left="0"
+ name="conversations_stack"
+ orientation="horizontal"
top="0"
- width="394">
- <first_tab
- tab_bottom_image_flash="Toolbar_Left_Flash"/>
- <middle_tab
- tab_bottom_image_flash="Toolbar_Middle_Flash"/>
- <last_tab
- tab_bottom_image_flash="Toolbar_Right_Flash"/>
- </tab_container>
- <icon
- color="DefaultShadowLight"
- enabled="false"
- follows="left|right|bottom"
- height="17"
- image_name="tabarea.tga"
- layout="bottomleft"
- left="1"
- name="im_box_tab_container_icon"
- bottom="10"
- width="394" />
+ width="680">
+ <layout_panel
+ auto_resize="true"
+ height="430"
+ name="conversations_layout_panel"
+ min_dim="41"
+ width="268">
+ <layout_stack
+ animate="false"
+ follows="left|top|right"
+ height="35"
+ layout="topleft"
+ left="0"
+ name="conversations_pane_buttons_stack"
+ orientation="horizontal"
+ top="0"
+ width="268">
+ <layout_panel
+ auto_resize="true"
+ height="35"
+ name="conversations_pane_buttons_expanded">
+ <menu_button
+ follows="top|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="OptionsMenu_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ left="10"
+ name="sort_btn"
+ top="5"
+ width="31" />
+ <button
+ follows="top|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="AddItem_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="5"
+ left_pad="4"
+ name="add_btn"
+ tool_tip="Add button on the left panel"
+ width="31"/>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ height="35"
+ name="conversations_pane_buttons_collapsed"
+ width="41">
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="TabIcon_Open_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="5"
+ left="5"
+ name="expand_collapse_btn"
+ width="31" />
+ </layout_panel>
+ </layout_stack>
+ <panel
+ follows="all"
+ layout="topleft"
+ name="conversations_list_panel"
+ opaque="true"
+ top_pad="0"
+ left="5"
+ height="390"
+ width="263"/>
+ </layout_panel>
+ <layout_panel
+ auto_resize="true"
+ height="430"
+ name="messages_layout_panel"
+ width="412">
+ <panel_container
+ follows="all"
+ height="430"
+ layout="topleft"
+ left="10"
+ name="im_box_tab_container"
+ top="0"
+ width="402"/>
+ </layout_panel>
+ </layout_stack>
</multi_floater>
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 ca73883e53..a332bb5b12 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
- legacy_header_height="18"
background_visible="true"
default_tab_group="1"
height="355"
@@ -13,30 +12,141 @@
visible="false"
width="394"
can_resize="true"
+ can_tear_off="false"
min_width="250"
min_height="190">
+ <floater.string name="call_btn_start">VoicePTT_Off</floater.string>
+ <floater.string name="call_btn_stop">VoicePTT_On</floater.string>
+ <floater.string
+ name="collapse_icon"
+ value="TabIcon_Open_Off"/>
+ <floater.string
+ name="expand_icon"
+ value="TabIcon_Close_Off"/>
+ <floater.string
+ name="tear_off_icon"
+ value="tearoffbox.tga"/>
+ <floater.string
+ name="return_icon"
+ value="Icon_Dock_Foreground"/>
+ <view
+ follows="all"
+ layout="topleft"
+ name="contents_view"
+ top="0"
+ left="0"
+ height="355"
+ width="394">
+ <panel
+ follows="left|top|right"
+ layout="topleft"
+ name="toolbar_panel"
+ top="0"
+ left="0"
+ height="35"
+ width="394">
+ <menu_button
+ menu_filename="menu_im_session_showmodes.xml"
+ follows="top|left"
+ height="25"
+ image_hover_unselected="Toolbar_Left_Over"
+ image_overlay="OptionsMenu_Off"
+ image_selected="Toolbar_Left_Selected"
+ image_unselected="Toolbar_Left_Off"
+ layout="topleft"
+ left="5"
+ name="view_options_btn"
+ top="5"
+ width="31" />
+ <button
+ follows="top|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="AddItem_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="5"
+ left_pad="4"
+ name="add_btn"
+ width="31">
+ <commit_callback
+ function="Chats.add" />
+ </button>
+ <button
+ follows="top|left"
+ height="25"
+ image_hover_unselected="Toolbar_Right_Over"
+ image_overlay="VoicePTT_Off"
+ image_selected="Toolbar_Right_Selected"
+ image_unselected="Toolbar_Right_Off"
+ layout="topleft"
+ top="5"
+ left_pad="4"
+ name="voice_call_btn"
+ width="31">
+ <commit_callback
+ function="Chats.add" />
+ </button>
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Icon_Close_Foreground"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="5"
+ left="283"
+ name="close_btn"
+ width="31" />
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="TabIcon_Open_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="5"
+ left_pad="5"
+ name="expand_collapse_btn"
+ width="31" />
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="tearoffbox.tga"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="5"
+ left_pad="5"
+ name="tear_off_btn"
+ width="31" />
+ </panel>
<layout_stack
animate="true"
default_tab_group="2"
follows="all"
- height="320"
+ height="310"
width="394"
layout="topleft"
orientation="horizontal"
name="im_panels"
tab_group="1"
- top="20"
+ top_pad="0"
left="0">
<layout_panel
name="im_control_panel_holder"
min_width="115"
width="150"
- height="320"
+ height="310"
auto_resize="false">
<panel
name="panel_im_control_panel"
layout="topleft"
- height="320"
+ height="310"
width="150"
follows="all"/>
</layout_panel>
@@ -46,39 +156,22 @@
tab_group="2"
top="0"
height="200"
- width="254"
+ width="254"
user_resize="true">
- <button
- height="20"
- follows="left|top"
- top="0"
- left="2"
- image_overlay="TabIcon_Open_Off"
- layout="topleft"
- width="25"
- name="slide_left_btn" />
- <button
- height="20"
- follows="left|top"
- top="0"
- left="2"
- image_overlay="TabIcon_Close_Off"
- width="25"
- name="slide_right_btn" />
<chat_history
- font="SansSerifSmall"
- follows="left|right|top|bottom"
- height="150"
+ font="SansSerifSmall"
+ follows="all"
+ height="170"
name="chat_history"
parse_highlights="true"
parse_urls="true"
- left="1"
+ left="1"
width="249">
</chat_history>
<line_editor
bottom="0"
follows="left|right|bottom"
- font="SansSerifSmall"
+ font="SansSerifSmall"
height="20"
label="To"
layout="bottomleft"
@@ -88,4 +181,5 @@
</line_editor>
</layout_panel>
</layout_stack>
+ </view>
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml
new file mode 100644
index 0000000000..483f24afd0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ name="menu_modes"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false">
+ <menu_item_check
+ label="Compact view"
+ name="compact_view">
+ <menu_item_check.on_click
+ function="IMSession.Menu.Action"
+ parameter="compact_view"/>
+ <menu_item_check.on_check
+ function="IMSession.Menu.CompactExpandedModes.CheckItem"
+ parameter="compact_view"/>
+ </menu_item_check>
+ <menu_item_check
+ label="Expanded view"
+ name="expanded_view">
+ <menu_item_check.on_click
+ function="IMSession.Menu.Action"
+ parameter="expanded_view"/>
+ <menu_item_check.on_check
+ function="IMSession.Menu.CompactExpandedModes.CheckItem"
+ parameter="expanded_view"/>
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_check name="IMShowTime" label="Show time">
+ <menu_item_check.on_click
+ function="IMSession.Menu.Action"
+ parameter="IMShowTime" />
+ <menu_item_check.on_check
+ function="IMSession.Menu.ShowModes.CheckItem"
+ parameter="IMShowTime" />
+ <menu_item_check.on_enable
+ function="IMSession.Menu.ShowModes.Enable"
+ parameter="IMShowTime" />
+ </menu_item_check>
+ <menu_item_check name="IMShowNamesForP2PConv" label="Show names in one-to-one conversations">
+ <menu_item_check.on_click
+ function="IMSession.Menu.Action"
+ parameter="IMShowNamesForP2PConv" />
+ <menu_item_check.on_check
+ function="IMSession.Menu.ShowModes.CheckItem"
+ parameter="IMShowNamesForP2PConv" />
+ <menu_item_check.on_enable
+ function="IMSession.Menu.ShowModes.Enable"
+ parameter="IMShowNamesForP2PConv" />
+
+ </menu_item_check>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
index ad10e53a4e..a5295ebe01 100644
--- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -47,55 +47,6 @@
layout="topleft"
min_height="28"
width="130"
- name="group_info_btn_panel">
- <button
- follows="left|right|bottom"
- height="23"
- label="Group Profile"
- name="group_info_btn"
- use_ellipses="true"
- top="5"
- width="130" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="28"
- layout="topleft"
- min_height="28"
- width="130"
- name="call_btn_panel">
- <button
- follows="all"
- height="23"
- label="Call Group"
- name="call_btn"
- use_ellipses="true"
- width="130" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="28"
- layout="topleft"
- min_height="28"
- width="130"
- name="end_call_btn_panel"
- visible="false">
- <button
- follows="all"
- height="23"
- label="Leave Call"
- name="end_call_btn"
- use_ellipses="true" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="28"
- layout="topleft"
- min_height="28"
- width="130"
name="voice_ctrls_btn_panel"
visible="false">
<button
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
deleted file mode 100644
index 8fcd6ccbaf..0000000000
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel
- border="false"
- height="300"
- name="panel_im_control_panel"
- width="150">
- <avatar_icon
- follows="left|top"
- height="105"
- left_delta="20"
- name="avatar_icon"
- top="-5"
- width="114"/>
- <layout_stack
- mouse_opaque="false"
- border_size="0"
- clip="false"
- follows="all"
- height="183"
- layout="topleft"
- left="5"
- name="button_stack"
- orientation="vertical"
- top_pad="5"
- width="145">
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="20"
- layout="topleft"
- left="2"
- min_height="20"
- width="140"
- name="view_profile_btn_panel"
- top="0" >
- <button
- follows="left|top|right"
- height="23"
- label="Profile"
- name="view_profile_btn"
- top="0"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="add_friend_btn_panel">
- <button
- follows="left|top|right"
- height="23"
- label="Add Friend"
- name="add_friend_btn"
- top="5"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="teleport_btn_panel">
- <button
- auto_resize="false"
- follows="left|top|right"
- height="23"
- label="Teleport"
- name="teleport_btn"
- tool_tip = "Offer to teleport this person"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="share_btn_panel">
- <button
- auto_resize="true"
- follows="left|top|right"
- height="23"
- label="Share"
- name="share_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="pay_btn_panel">
- <button
- auto_resize="true"
- follows="left|top|right"
- height="23"
- label="Pay"
- name="pay_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="call_btn_panel">
- <button
- follows="left|top|right"
- height="23"
- label="Call"
- name="call_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="end_call_btn_panel"
- visible="false">
- <button
- follows="left|top|right"
- height="23"
- label="End Call"
- name="end_call_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="voice_ctrls_btn_panel"
- visible="false">
- <button
- follows="left|top|right"
- height="23"
- label="Voice Controls"
- name="voice_ctrls_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- mouse_opaque="false"
- auto_resize="true"
- follows="top|left"
- height="0"
- layout="topleft"
- min_height="0"
- width="140"
- name="spacer"/>
- </layout_stack>
-</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index e932310622..d7bc998b36 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -405,6 +405,7 @@ Please try logging in again in a minute.</string>
<string name="TrackYourCamera">Track your camera</string>
<string name="ControlYourCamera">Control your camera</string>
<string name="NotConnected">Not Connected</string>
+ <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
<!-- Sim Access labels -->
<string name="SIM_ACCESS_PG">General</string>