summaryrefslogtreecommitdiff
path: root/indra/newview/llimpanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llimpanel.cpp')
-rw-r--r--indra/newview/llimpanel.cpp620
1 files changed, 308 insertions, 312 deletions
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 6acd174fc3..248a8dbc4c 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -45,22 +45,26 @@
#include "llagent.h"
#include "llbutton.h"
+#include "llbottomtray.h"
#include "llcallingcard.h"
#include "llchat.h"
+#include "llchiclet.h"
#include "llconsole.h"
#include "llfloater.h"
#include "llfloatercall.h"
#include "llfloatergroupinfo.h"
-#include "llfriendactions.h"
+#include "llavataractions.h"
#include "llimview.h"
#include "llinventory.h"
#include "llinventorymodel.h"
-#include "llinventoryview.h"
-#include "llfloateractivespeakers.h"
+#include "llfloaterinventory.h"
#include "llfloaterchat.h"
+#include "lliconctrl.h"
+#include "llimview.h" // for LLIMModel to get other avatar id in chat
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llnotify.h"
+#include "llpanelimcontrolpanel.h"
#include "llrecentpeople.h"
#include "llresmgr.h"
#include "lltrans.h"
@@ -101,190 +105,7 @@ LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
BOOL LLVoiceChannel::sSuspended = FALSE;
-void session_starter_helper(
- const LLUUID& temp_session_id,
- const LLUUID& other_participant_id,
- EInstantMessage im_type)
-{
- LLMessageSystem *msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id);
- msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addU8Fast(_PREHASH_Dialog, im_type);
- msg->addUUIDFast(_PREHASH_ID, temp_session_id);
- msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
-
- std::string name;
- gAgent.buildFullname(name);
-
- msg->addStringFast(_PREHASH_FromAgentName, name);
- msg->addStringFast(_PREHASH_Message, LLStringUtil::null);
- msg->addU32Fast(_PREHASH_ParentEstateID, 0);
- msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
- msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-}
-
-void start_deprecated_conference_chat(
- const LLUUID& temp_session_id,
- const LLUUID& creator_id,
- const LLUUID& other_participant_id,
- const LLSD& agents_to_invite)
-{
- U8* bucket;
- U8* pos;
- S32 count;
- S32 bucket_size;
-
- // *FIX: this could suffer from endian issues
- count = agents_to_invite.size();
- bucket_size = UUID_BYTES * count;
- bucket = new U8[bucket_size];
- pos = bucket;
-
- for(S32 i = 0; i < count; ++i)
- {
- LLUUID agent_id = agents_to_invite[i].asUUID();
-
- memcpy(pos, &agent_id, UUID_BYTES);
- pos += UUID_BYTES;
- }
-
- session_starter_helper(
- temp_session_id,
- other_participant_id,
- IM_SESSION_CONFERENCE_START);
-
- gMessageSystem->addBinaryDataFast(
- _PREHASH_BinaryBucket,
- bucket,
- bucket_size);
-
- gAgent.sendReliableMessage();
-
- delete[] bucket;
-}
-
-class LLStartConferenceChatResponder : public LLHTTPClient::Responder
-{
-public:
- LLStartConferenceChatResponder(
- const LLUUID& temp_session_id,
- const LLUUID& creator_id,
- const LLUUID& other_participant_id,
- const LLSD& agents_to_invite)
- {
- mTempSessionID = temp_session_id;
- mCreatorID = creator_id;
- mOtherParticipantID = other_participant_id;
- mAgents = agents_to_invite;
- }
-
- virtual void error(U32 statusNum, const std::string& reason)
- {
- //try an "old school" way.
- if ( statusNum == 400 )
- {
- start_deprecated_conference_chat(
- mTempSessionID,
- mCreatorID,
- mOtherParticipantID,
- mAgents);
- }
-
- //else throw an error back to the client?
- //in theory we should have just have these error strings
- //etc. set up in this file as opposed to the IMMgr,
- //but the error string were unneeded here previously
- //and it is not worth the effort switching over all
- //the possible different language translations
- }
-
-private:
- LLUUID mTempSessionID;
- LLUUID mCreatorID;
- LLUUID mOtherParticipantID;
- LLSD mAgents;
-};
-
-// Returns true if any messages were sent, false otherwise.
-// Is sort of equivalent to "does the server need to do anything?"
-bool send_start_session_messages(
- const LLUUID& temp_session_id,
- const LLUUID& other_participant_id,
- const std::vector<LLUUID>& ids,
- EInstantMessage dialog)
-{
- if ( dialog == IM_SESSION_GROUP_START )
- {
- session_starter_helper(
- temp_session_id,
- other_participant_id,
- dialog);
-
- switch(dialog)
- {
- case IM_SESSION_GROUP_START:
- gMessageSystem->addBinaryDataFast(
- _PREHASH_BinaryBucket,
- EMPTY_BINARY_BUCKET,
- EMPTY_BINARY_BUCKET_SIZE);
- break;
- default:
- break;
- }
- gAgent.sendReliableMessage();
-
- return true;
- }
- else if ( dialog == IM_SESSION_CONFERENCE_START )
- {
- LLSD agents;
- for (int i = 0; i < (S32) ids.size(); i++)
- {
- agents.append(ids[i]);
- }
-
- //we have a new way of starting conference calls now
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string url = region->getCapability(
- "ChatSessionRequest");
- LLSD data;
- data["method"] = "start conference";
- data["session-id"] = temp_session_id;
-
- data["params"] = agents;
-
- LLHTTPClient::post(
- url,
- data,
- new LLStartConferenceChatResponder(
- temp_session_id,
- gAgent.getID(),
- other_participant_id,
- data["params"]));
- }
- else
- {
- start_deprecated_conference_chat(
- temp_session_id,
- gAgent.getID(),
- other_participant_id,
- agents);
- }
- }
-
- return false;
-}
class LLVoiceCallCapResponder : public LLHTTPClient::Responder
{
@@ -1200,7 +1021,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
if ( !mSessionInitialized )
{
- if ( !send_start_session_messages(
+ if ( !LLIMModel::instance().sendStartSession(
mSessionUUID,
mOtherParticipantUUID,
mSessionInitialTargetIDs,
@@ -1222,7 +1043,7 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
addHistoryLine(
session_start,
- gSavedSkinSettings.getColor4("SystemChatColor"),
+ LLUIColorTable::instance().getColor("SystemChatColor"),
false);
}
}
@@ -1542,34 +1363,42 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
prepend_newline = false;
}
+ std::string separator_string(": ");
+
// 'name' is a sender name that we want to hotlink so that clicking on it opens a profile.
if (!name.empty()) // If name exists, then add it to the front of the message.
{
// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.
if (name == SYSTEM_FROM)
{
- mHistoryEditor->appendColoredText(name,false,prepend_newline,color);
+ mHistoryEditor->appendColoredText(name + separator_string, false, prepend_newline, color);
}
else
{
// Convert the name to a hotlink and add to message.
const LLStyleSP &source_style = LLStyleMap::instance().lookupAgent(source);
- mHistoryEditor->appendStyledText(name,false,prepend_newline,source_style);
+ mHistoryEditor->appendStyledText(name + separator_string, false, prepend_newline, source_style);
}
prepend_newline = false;
}
mHistoryEditor->appendColoredText(utf8msg, false, prepend_newline, color);
-
- if (log_to_file
- && gSavedPerAccountSettings.getBOOL("LogInstantMessages") )
+ S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
+ if (log_to_file && (im_log_option!=LOG_CHAT))
{
std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("IMLogTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + name + utf8msg;
+ if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
+ histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + name + separator_string + utf8msg;
else
- histstr = name + utf8msg;
+ histstr = name + separator_string + utf8msg;
- LLLogChat::saveHistory(getTitle(),histstr);
+ if(im_log_option==LOG_BOTH_TOGETHER)
+ {
+ LLLogChat::saveHistory(std::string("chat"),histstr);
+ }
+ else
+ {
+ LLLogChat::saveHistory(getTitle(),histstr);
+ }
}
if (!isInVisibleChain())
@@ -1620,7 +1449,6 @@ void LLFloaterIMPanel::selectNone()
mInputEditor->deselect();
}
-
BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask )
{
BOOL handled = FALSE;
@@ -1752,7 +1580,7 @@ void LLFloaterIMPanel::onClickProfile( void* userdata )
if (self->getOtherParticipantID().notNull())
{
- LLFriendActions::showProfile(self->getOtherParticipantID());
+ LLAvatarActions::showProfile(self->getOtherParticipantID());
}
}
@@ -1847,23 +1675,8 @@ void LLFloaterIMPanel::onClose(bool app_quitting)
{
setTyping(FALSE);
- if(mSessionUUID.notNull())
- {
- std::string name;
- gAgent.buildFullname(name);
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- mOtherParticipantUUID,
- name,
- LLStringUtil::null,
- IM_ONLINE,
- IM_SESSION_LEAVE,
- mSessionUUID);
- gAgent.sendReliableMessage();
- }
+ LLIMModel::instance().sendLeaveSession(mSessionUUID, mOtherParticipantUUID);
+
gIMMgr->removeSession(mSessionUUID);
// *HACK hide the voice floater
@@ -1884,79 +1697,6 @@ void LLFloaterIMPanel::onVisibilityChange(BOOL new_visibility)
mSessionUUID);
}
-void deliver_message(const std::string& utf8_text,
- const LLUUID& im_session_id,
- const LLUUID& other_participant_id,
- EInstantMessage dialog)
-{
- std::string name;
- bool sent = false;
- gAgent.buildFullname(name);
-
- const LLRelationship* info = NULL;
- info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
-
- U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
-
- if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
- {
- // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
- sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
- }
-
- if(!sent)
- {
- // Send message normally.
-
- // default to IM_SESSION_SEND unless it's nothing special - in
- // which case it's probably an IM to everyone.
- U8 new_dialog = dialog;
-
- if ( dialog != IM_NOTHING_SPECIAL )
- {
- new_dialog = IM_SESSION_SEND;
- }
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- other_participant_id,
- name.c_str(),
- utf8_text.c_str(),
- offline,
- (EInstantMessage)new_dialog,
- im_session_id);
- gAgent.sendReliableMessage();
- }
-
- // If there is a mute list and this is not a group chat...
- if ( LLMuteList::getInstance() )
- {
- // ... the target should not be in our mute list for some message types.
- // Auto-remove them if present.
- switch( dialog )
- {
- case IM_NOTHING_SPECIAL:
- case IM_GROUP_INVITATION:
- case IM_INVENTORY_OFFERED:
- case IM_SESSION_INVITE:
- case IM_SESSION_P2P_INVITE:
- case IM_SESSION_CONFERENCE_START:
- case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing.
- case IM_LURE_USER:
- case IM_GODLIKE_LURE_USER:
- case IM_FRIENDSHIP_OFFERED:
- LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM);
- break;
- default: ; // do nothing
- }
- }
-
- // Add the recipient to the recent people list.
- LLRecentPeople::instance().add(other_participant_id);
-}
-
void LLFloaterIMPanel::sendMsg()
{
if (!gAgent.isGodlike()
@@ -1978,7 +1718,7 @@ void LLFloaterIMPanel::sendMsg()
if ( mSessionInitialized )
{
- deliver_message(utf8_text,
+ LLIMModel::sendMessage(utf8_text,
mSessionUUID,
mOtherParticipantUUID,
mDialog);
@@ -2004,7 +1744,7 @@ void LLFloaterIMPanel::sendMsg()
BOOL other_was_typing = mOtherTyping;
- addHistoryLine(history_echo, gSavedSkinSettings.getColor("IMChatColor"), true, gAgent.getID());
+ addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID());
if (other_was_typing)
{
@@ -2084,7 +1824,7 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
iter != mQueuedMsgsForInit.endArray();
++iter)
{
- deliver_message(
+ LLIMModel::sendMessage(
iter->asString(),
mSessionUUID,
mOtherParticipantUUID,
@@ -2135,23 +1875,10 @@ void LLFloaterIMPanel::sendTypingState(BOOL typing)
// much network traffic. Only send in person-to-person IMs.
if (mDialog != IM_NOTHING_SPECIAL) return;
- std::string name;
- gAgent.buildFullname(name);
-
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- mOtherParticipantUUID,
- name,
- std::string("typing"),
- IM_ONLINE,
- (typing ? IM_TYPING_START : IM_TYPING_STOP),
- mSessionUUID);
- gAgent.sendReliableMessage();
+ LLIMModel::instance().sendTypingState(mSessionUUID, mOtherParticipantUUID, typing);
}
+
void LLFloaterIMPanel::processIMTyping(const LLIMInfo* im_info, BOOL typing)
{
if (typing)
@@ -2175,7 +1902,7 @@ void LLFloaterIMPanel::addTypingIndicator(const std::string &name)
mTypingLineStartIndex = mHistoryEditor->getWText().length();
LLUIString typing_start = sTypingStartString;
typing_start.setArg("[NAME]", name);
- addHistoryLine(typing_start, gSavedSkinSettings.getColor4("SystemChatColor"), false);
+ addHistoryLine(typing_start, LLUIColorTable::instance().getColor("SystemChatColor"), false);
mOtherTypingName = name;
mOtherTyping = TRUE;
}
@@ -2206,19 +1933,19 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata;
std::string message = line;
-
+ S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
switch (type)
{
case LLLogChat::LOG_EMPTY:
// add warning log enabled message
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+ if (im_log_option!=LOG_CHAT)
{
message = LLTrans::getString("IM_logging_string");
}
break;
case LLLogChat::LOG_END:
// add log end message
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+ if (im_log_option!=LOG_CHAT)
{
message = LLTrans::getString("IM_logging_string");
}
@@ -2232,7 +1959,7 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string
}
//self->addHistoryLine(line, LLColor4::grey, FALSE);
- self->mHistoryEditor->appendColoredText(message, false, true, gSavedSkinSettings.getColor4("ChatHistoryTextColor"));
+ self->mHistoryEditor->appendColoredText(message, false, true, LLUIColorTable::instance().getColor("ChatHistoryTextColor"));
}
void LLFloaterIMPanel::showSessionStartError(
@@ -2318,5 +2045,274 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const
}
return false;
}
+
+
+std::map<LLUUID, LLIMFloater*> LLIMFloater::sIMFloaterMap;
+
+LLIMFloater::LLIMFloater(const LLUUID& session_id,
+ const std::string title,
+ EInstantMessage dialog)
+: mSessionID(session_id),
+ mLastMessageIndex(-1),
+ mDialog(dialog)
+{
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml");
+ sIMFloaterMap[mSessionID] = this;
+
+ LLPanelIMControlPanel* im_control_panel = getChild<LLPanelIMControlPanel>("panel_im_control_panel");
+
+ LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, session_id, (LLIMModel::LLIMSession*)NULL);
+ if(session)
+ {
+ mOtherParticipantUUID = session->mOtherParticipantID;
+ im_control_panel->setAvatarId(session->mOtherParticipantID);
+ }
+
+ LLButton* slide_left = getChild<LLButton>("slide_left_btn");
+ slide_left->setVisible(im_control_panel->getVisible());
+ slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+
+ LLButton* slide_right = getChild<LLButton>("slide_right_btn");
+ slide_right->setVisible(!im_control_panel->getVisible());
+ slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+
+ setTitle(title);
+ setDocked(true);
+
+ mInputEditor = getChild<LLLineEditor>("chat_editor");
+
+
+ mInputEditor->setMaxTextLength(1023);
+ // enable line history support for instant message bar
+ mInputEditor->setEnableLineHistory(TRUE);
+
+ mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this );
+ mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this );
+ mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this );
+ mInputEditor->setCommitOnFocusLost( FALSE );
+ mInputEditor->setRevertOnEsc( FALSE );
+ mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
+
+ childSetCommitCallback("chat_editor", onSendMsg, this);
+}
+
+/* static */
+void LLIMFloater::newIMCallback(const LLSD& data){
+
+ if (data["num_unread"].asInteger() > 0)
+ {
+ LLUUID session_id = data["session_id"].asUUID();
+
+ LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL);
+
+ if (floater == NULL)
+ {
+ llwarns << "new_im_callback for non-existent session_id " << session_id << llendl;
+ return;
+ }
+
+ // update if visible, otherwise will be updated when opened
+ if (floater->getVisible())
+ {
+ floater->updateMessages();
+ }
+ }
+}
+
+void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
+{
+ LLIMFloater* self = (LLIMFloater*) userdata;
+ self->sendMsg();
+}
+
+void LLIMFloater::sendMsg()
+{
+ if (!gAgent.isGodlike()
+ && (mDialog == IM_NOTHING_SPECIAL)
+ && mOtherParticipantUUID.isNull())
+ {
+ llinfos << "Cannot send IM to everyone unless you're a god." << llendl;
+ return;
+ }
+
+ if (mInputEditor)
+ {
+ LLWString text = mInputEditor->getConvertedText();
+ if(!text.empty())
+ {
+ // Truncate and convert to UTF8 for transport
+ std::string utf8_text = wstring_to_utf8str(text);
+ utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
+
+ LLIMModel::sendMessage(utf8_text,
+ mSessionID,
+ mOtherParticipantUUID,
+ mDialog);
+
+ mInputEditor->setText(LLStringUtil::null);
+
+ updateMessages();
+ }
+ }
+}
+
+
+
+LLIMFloater::~LLIMFloater()
+{
+ sIMFloaterMap.erase(mSessionID);
+}
+
+//virtual
+BOOL LLIMFloater::postBuild()
+{
+ mHistoryEditor = getChild<LLViewerTextEditor>("im_text", true, false);
+ mChiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID);
+
+ if (!mChiclet)
+ {
+ llwarns << "No chiclet found for the IMFloter" << llendl;
+ }
+ setDocked(false);
+ return TRUE;
+}
+
+const U32 UNDOCK_LEAP_HEIGHT = 12;
+const U32 DOCK_ICON_HEIGHT = 6;
+
+//virtual
+void LLIMFloater::onFocusLost()
+{
+ // spec says close if docked to bottom tray and user has clicked away
+ // (hence we are no longer focused)
+ if (isDocked())
+ {
+ // app not quitting
+ closeFloater(false);
+ }
+}
+
+
+//virtual
+void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ LLFloater::setDocked(docked);
+ mChiclet->setDockTongueVisible(docked);
+ if (docked)
+ {
+ S32 x, y;
+ mChiclet->localPointToScreen((mChiclet->getRect().getWidth())/2, 0, &x, &y);
+ translate(x - getRect().getCenterX(), DOCK_ICON_HEIGHT - getRect().mBottom);
+ }
+ else if (pop_on_undock)
+ {
+ // visually pop up a little bit to emphasize the undocking
+ translate(0, UNDOCK_LEAP_HEIGHT);
+ }
+}
+
+
+void LLIMFloater::onClose(bool app_quitting)
+{
+ mChiclet->setDockTongueVisible(false);
+ LLFloater::onClose(app_quitting);
+}
+
+void LLIMFloater::onSlide()
+{
+ LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
+ im_control_panel->setVisible(!im_control_panel->getVisible());
+
+ getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible());
+ getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible());
+}
+
+//static
+LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
+{
+ LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL);
+
+ if (floater == NULL)
+ {
+ floater = new LLIMFloater(session_id, LLIMModel::instance().getName(session_id), IM_NOTHING_SPECIAL);
+ }
+
+ //hide all
+ for (std::map<LLUUID, LLIMFloater*>::iterator iter = sIMFloaterMap.begin();
+ iter != sIMFloaterMap.end(); ++iter)
+ {
+ LLIMFloater* floater = (*iter).second;
+ floater->setVisible(false);
+ floater->mChiclet->setDockTongueVisible(false);
+
+ }
+
+ floater->setVisibleAndFrontmost(true);
+
+ if (floater->isDocked())
+ {
+ floater->mChiclet->setDockTongueVisible(true);
+ }
+
+ floater->updateMessages();
+ return floater;
+}
+
+void LLIMFloater::updateMessages()
+{
+
+ std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
+
+ if (messages.size())
+ {
+ std::ostringstream message;
+ std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
+ std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
+ for (; iter != iter_end; ++iter)
+ {
+ LLSD msg = *iter;
+
+ message << msg["from"].asString() << " : " << msg["time"].asString() << "\n " << msg["message"].asString() << "\n";
+
+ mLastMessageIndex = msg["index"].asInteger();
+ }
+
+ mHistoryEditor->appendText(message.str(), false, false);
+ mHistoryEditor->setCursorAndScrollToEnd();
+ }
+
+}
+// static
+void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata )
+{
+ LLIMFloater* self= (LLIMFloater*) userdata;
+ self->mHistoryEditor->setCursorAndScrollToEnd();
+}
+
+// static
+void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
+{
+ LLIMFloater* self = (LLIMFloater*) userdata;
+ self->setTyping(FALSE);
+}
+// static
+void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
+{
+ LLIMFloater* self = (LLIMFloater*)userdata;
+ std::string text = self->mInputEditor->getText();
+ if (!text.empty())
+ {
+ self->setTyping(TRUE);
+ }
+ else
+ {
+ // Deleting all text counts as stopping typing.
+ self->setTyping(FALSE);
+ }
+}
+//just a stub for now
+void LLIMFloater::setTyping(BOOL typing)
+{
+}