phoenix-firestorm/indra/newview/llfloaterchat.cpp

463 lines
12 KiB
C++

/**
* @file llfloaterchat.cpp
* @brief LLFloaterChat class implementation
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2007, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
/**
* Actually the "Chat History" floater.
* Should be llfloaterchathistory, not llfloaterchat.
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterchat.h"
#include "llfloateractivespeakers.h"
#include "llfloaterscriptdebug.h"
#include "llchat.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
#include "llstring.h"
#include "message.h"
// project include
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llconsole.h"
#include "llfloaterchatterbox.h"
#include "llfloatermute.h"
#include "llkeyboard.h"
//#include "lllineeditor.h"
#include "llmutelist.h"
//#include "llresizehandle.h"
#include "llchatbar.h"
#include "llstatusbar.h"
#include "llviewertexteditor.h"
#include "llviewergesture.h" // for triggering gestures
#include "llviewermessage.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "llvieweruictrlfactory.h"
#include "llchatbar.h"
#include "lllogchat.h"
#include "lltexteditor.h"
#include "llfloaterhtml.h"
#include "llweb.h"
// Used for LCD display
extern void AddNewIMToLCD(const LLString &newLine);
extern void AddNewChatToLCD(const LLString &newLine);
//
// Constants
//
const F32 INSTANT_MSG_SIZE = 8.0f;
const F32 CHAT_MSG_SIZE = 8.0f;
const LLColor4 INSTANT_MSG_COLOR(1, 1, 1, 1);
const LLColor4 MUTED_MSG_COLOR(0.5f, 0.5f, 0.5f, 1.f);
const S32 MAX_CHATTER_COUNT = 16;
//
// Global statics
//
LLColor4 get_text_color(const LLChat& chat);
//
// Member Functions
//
LLFloaterChat::LLFloaterChat(const LLSD& seed)
: LLFloater("chat floater", "FloaterChatRect", "",
RESIZE_YES, 440, 100, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES),
mPanel(NULL)
{
mFactoryMap["chat_panel"] = LLCallbackMap(createChatPanel, NULL);
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL);
// do not automatically open singleton floaters (as result of getInstance())
BOOL no_open = FALSE;
gUICtrlFactory->buildFloater(this,"floater_chat_history.xml",&getFactoryMap(),no_open);
childSetCommitCallback("show mutes",onClickToggleShowMute,this); //show mutes
childSetVisible("Chat History Editor with mute",FALSE);
childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
setDefaultBtn("Chat");
}
LLFloaterChat::~LLFloaterChat()
{
// Children all cleaned up by default view destructor.
}
void LLFloaterChat::setVisible(BOOL visible)
{
LLFloater::setVisible( visible );
gSavedSettings.setBOOL("ShowChatHistory", visible);
}
void LLFloaterChat::draw()
{
// enable say and shout only when text available
childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel"));
LLChatBar* chat_barp = (LLChatBar*)getChildByName("chat_panel", TRUE);
if (chat_barp)
{
chat_barp->refresh();
}
mPanel->refreshSpeakers();
LLFloater::draw();
}
BOOL LLFloaterChat::postBuild()
{
mPanel = (LLPanelActiveSpeakers*)LLUICtrlFactory::getPanelByName(this, "active_speakers_panel");
LLChatBar* chat_barp = (LLChatBar*)getChildByName("chat_panel", TRUE);
if (chat_barp)
{
chat_barp->setGestureCombo(LLUICtrlFactory::getComboBoxByName(this, "Gesture"));
}
return TRUE;
}
// public virtual
void LLFloaterChat::onClose(bool app_quitting)
{
if (!app_quitting)
{
gSavedSettings.setBOOL("ShowChatHistory", FALSE);
}
setVisible(FALSE);
}
void LLFloaterChat::onVisibilityChange(BOOL new_visibility)
{
// Hide the chat overlay when our history is visible.
gConsole->setVisible( !new_visibility );
LLFloater::onVisibilityChange(new_visibility);
}
void add_timestamped_line(LLViewerTextEditor* edit, const LLString& line, const LLColor4& color)
{
bool prepend_newline = true;
if (gSavedSettings.getBOOL("ChatShowTimestamps"))
{
edit->appendTime(prepend_newline);
prepend_newline = false;
}
edit->appendColoredText(line, false, prepend_newline, color);
}
void log_chat_text(const LLChat& chat)
{
LLString histstr;
if (gSavedPerAccountSettings.getBOOL("LogChatTimestamp"))
histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText;
else
histstr = chat.mText;
LLLogChat::saveHistory("chat",histstr);
}
// static
void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
{
if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file)
{
log_chat_text(chat);
}
LLColor4 color = get_text_color(chat);
if (!log_to_file) color = LLColor4::grey; //Recap from log file.
if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
{
LLFloaterScriptDebug::addScriptLine(chat.mText,
chat.mFromName,
color,
chat.mFromID);
if (!gSavedSettings.getBOOL("ScriptErrorsAsChat"))
{
return;
}
}
// could flash the chat button in the status bar here. JC
LLFloaterChat* chat_floater = LLFloaterChat::getInstance(LLSD());
LLViewerTextEditor* history_editor = (LLViewerTextEditor*)chat_floater->getChildByName("Chat History Editor", TRUE);
LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)chat_floater->getChildByName("Chat History Editor with mute", TRUE);
history_editor->setParseHTML(TRUE);
history_editor_with_mute->setParseHTML(TRUE);
if (!chat.mMuted)
{
add_timestamped_line(history_editor, chat.mText, color);
add_timestamped_line(history_editor_with_mute, chat.mText, color);
}
else
{
// desaturate muted chat
LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f);
add_timestamped_line(history_editor_with_mute, chat.mText, color);
}
// add objects as transient speakers that can be muted
if (chat.mSourceType == CHAT_SOURCE_OBJECT)
{
chat_floater->mPanel->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT);
}
}
// static
void LLFloaterChat::setHistoryCursorAndScrollToEnd()
{
LLViewerTextEditor* history_editor = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor", TRUE);
LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)LLFloaterChat::getInstance(LLSD())->getChildByName("Chat History Editor with mute", TRUE);
history_editor->setCursorAndScrollToEnd();
history_editor_with_mute->setCursorAndScrollToEnd();
}
//static
void LLFloaterChat::onClickMute(void *data)
{
LLFloaterChat* self = (LLFloaterChat*)data;
LLComboBox* chatter_combo = LLUICtrlFactory::getComboBoxByName(self,"chatter combobox");
const LLString& name = chatter_combo->getSimple();
LLUUID id = chatter_combo->getCurrentID();
if (name.empty()) return;
LLMute mute(id);
mute.setFromDisplayName(name);
gMuteListp->add(mute);
if (gFloaterMute)
{
gFloaterMute->show();
}
}
//static
void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data)
{
LLFloaterChat* floater = (LLFloaterChat*)data;
//LLCheckBoxCtrl*
BOOL show_mute = LLUICtrlFactory::getCheckBoxByName(floater,"show mutes")->get();
LLViewerTextEditor* history_editor = (LLViewerTextEditor*)floater->getChildByName("Chat History Editor", TRUE);
LLViewerTextEditor* history_editor_with_mute = (LLViewerTextEditor*)floater->getChildByName("Chat History Editor with mute", TRUE);
if (!history_editor || !history_editor_with_mute)
return;
//BOOL show_mute = floater->mShowMuteCheckBox->get();
if (show_mute)
{
history_editor->setVisible(FALSE);
history_editor_with_mute->setVisible(TRUE);
history_editor_with_mute->setCursorAndScrollToEnd();
}
else
{
history_editor->setVisible(TRUE);
history_editor_with_mute->setVisible(FALSE);
history_editor->setCursorAndScrollToEnd();
}
}
// Put a line of chat in all the right places
void LLFloaterChat::addChat(const LLChat& chat,
BOOL from_instant_message,
BOOL local_agent)
{
LLColor4 text_color = get_text_color(chat);
BOOL invisible_script_debug_chat =
chat.mChatType == CHAT_TYPE_DEBUG_MSG
&& !gSavedSettings.getBOOL("ScriptErrorsAsChat");
#if LL_WINDOWS && LL_LCD_COMPILE
// add into LCD displays
if (!invisible_script_debug_chat)
{
if (!from_instant_message)
{
AddNewChatToLCD(chat.mText);
}
else
{
AddNewIMToLCD(chat.mText);
}
}
#endif
if (!invisible_script_debug_chat
&& !chat.mMuted
&& gConsole
&& !local_agent)
{
F32 size = CHAT_MSG_SIZE;
if(from_instant_message)
{
text_color = INSTANT_MSG_COLOR;
size = INSTANT_MSG_SIZE;
}
gConsole->addLine(chat.mText, size, text_color);
}
if(from_instant_message && gSavedPerAccountSettings.getBOOL("LogChatIM"))
log_chat_text(chat);
if(from_instant_message && gSavedSettings.getBOOL("IMInChatHistory"))
addChatHistory(chat,false);
if(!from_instant_message)
addChatHistory(chat);
}
LLColor4 get_text_color(const LLChat& chat)
{
LLColor4 text_color;
if(chat.mMuted)
{
text_color.setVec(0.8f, 0.8f, 0.8f, 1.f);
}
else
{
switch(chat.mSourceType)
{
case CHAT_SOURCE_SYSTEM:
text_color = gSavedSettings.getColor4("SystemChatColor");
break;
case CHAT_SOURCE_AGENT:
if (chat.mFromID.isNull())
{
text_color = gSavedSettings.getColor4("SystemChatColor");
}
else
{
text_color = gSavedSettings.getColor4("AgentChatColor");
}
break;
case CHAT_SOURCE_OBJECT:
if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
{
text_color = gSavedSettings.getColor4("ScriptErrorColor");
}
else if ( chat.mChatType == CHAT_TYPE_OWNER )
{
text_color = gSavedSettings.getColor4("llOwnerSayChatColor");
}
else
{
text_color = gSavedSettings.getColor4("ObjectChatColor");
}
break;
default:
text_color.setToWhite();
}
if (!chat.mPosAgent.isExactlyZero())
{
LLVector3 pos_agent = gAgent.getPositionAgent();
F32 distance = dist_vec(pos_agent, chat.mPosAgent);
if (distance > gAgent.getNearChatRadius())
{
// diminish far-off chat
text_color.mV[VALPHA] = 0.8f;
}
}
}
return text_color;
}
//static
void LLFloaterChat::loadHistory()
{
LLLogChat::loadHistory("chat", &chatFromLogFile, (void *)LLFloaterChat::getInstance(LLSD()));
}
//static
void LLFloaterChat::chatFromLogFile(LLString line, void* userdata)
{
LLChat chat;
chat.mText = line;
addChatHistory(chat, FALSE);
}
//static
void* LLFloaterChat::createSpeakersPanel(void* data)
{
return new LLPanelActiveSpeakers(gLocalSpeakerMgr, TRUE);
}
//static
void* LLFloaterChat::createChatPanel(void* data)
{
LLChatBar* chatp = new LLChatBar("floating_chat_bar");
return chatp;
}
//static
void LLFloaterChat::hideInstance(const LLSD& id)
{
LLFloaterChat* floaterp = LLFloaterChat::getInstance(LLSD());
// don't do anything when hosted in the chatterbox
if(floaterp->getHost())
{
LLFloaterChatterBox::hideInstance(LLSD());
}
else
{
LLUISingleton<LLFloaterChat>::hideInstance(id);
}
}
// static
void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata)
{
LLFloaterChat* self = (LLFloaterChat*)userdata;
self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel"));
}