00001
00037 #include "llviewerprecompiledheaders.h"
00038
00039 #include "llfloaterchat.h"
00040 #include "llfloateractivespeakers.h"
00041 #include "llfloaterscriptdebug.h"
00042
00043 #include "llchat.h"
00044 #include "llfontgl.h"
00045 #include "llrect.h"
00046 #include "llerror.h"
00047 #include "llstring.h"
00048 #include "message.h"
00049
00050
00051 #include "llagent.h"
00052 #include "llbutton.h"
00053 #include "llcheckboxctrl.h"
00054 #include "llcombobox.h"
00055 #include "llconsole.h"
00056 #include "llfloaterchatterbox.h"
00057 #include "llfloatermute.h"
00058 #include "llkeyboard.h"
00059
00060 #include "llmutelist.h"
00061
00062 #include "llchatbar.h"
00063 #include "llstatusbar.h"
00064 #include "llviewertexteditor.h"
00065 #include "llviewergesture.h"
00066 #include "llviewermessage.h"
00067 #include "llviewerwindow.h"
00068 #include "llviewercontrol.h"
00069 #include "lluictrlfactory.h"
00070 #include "llchatbar.h"
00071 #include "lllogchat.h"
00072 #include "lltexteditor.h"
00073 #include "llfloaterhtml.h"
00074 #include "llweb.h"
00075 #include "llstylemap.h"
00076
00077
00078 extern void AddNewIMToLCD(const LLString &newLine);
00079 extern void AddNewChatToLCD(const LLString &newLine);
00080
00081
00082
00083 const F32 INSTANT_MSG_SIZE = 8.0f;
00084 const F32 CHAT_MSG_SIZE = 8.0f;
00085 const LLColor4 MUTED_MSG_COLOR(0.5f, 0.5f, 0.5f, 1.f);
00086 const S32 MAX_CHATTER_COUNT = 16;
00087
00088
00089
00090
00091 LLColor4 get_text_color(const LLChat& chat);
00092
00093
00094
00095
00096 LLFloaterChat::LLFloaterChat(const LLSD& seed)
00097 : LLFloater("chat floater", "FloaterChatRect", "",
00098 RESIZE_YES, 440, 100, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES),
00099 mPanel(NULL)
00100 {
00101 mFactoryMap["chat_panel"] = LLCallbackMap(createChatPanel, NULL);
00102 mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL);
00103
00104 BOOL no_open = FALSE;
00105 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_chat_history.xml",&getFactoryMap(),no_open);
00106
00107 childSetCommitCallback("show mutes",onClickToggleShowMute,this);
00108 childSetVisible("Chat History Editor with mute",FALSE);
00109 childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
00110 setDefaultBtn("Chat");
00111 }
00112
00113 LLFloaterChat::~LLFloaterChat()
00114 {
00115
00116 }
00117
00118 void LLFloaterChat::setVisible(BOOL visible)
00119 {
00120 LLFloater::setVisible( visible );
00121
00122 gSavedSettings.setBOOL("ShowChatHistory", visible);
00123 }
00124
00125 void LLFloaterChat::draw()
00126 {
00127
00128
00129 childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel"));
00130
00131 LLChatBar* chat_barp = getChild<LLChatBar>("chat_panel", TRUE);
00132 if (chat_barp)
00133 {
00134 chat_barp->refresh();
00135 }
00136
00137 mPanel->refreshSpeakers();
00138 LLFloater::draw();
00139 }
00140
00141 BOOL LLFloaterChat::postBuild()
00142 {
00143 mPanel = (LLPanelActiveSpeakers*)getChild<LLPanel>("active_speakers_panel");
00144
00145 LLChatBar* chat_barp = getChild<LLChatBar>("chat_panel", TRUE);
00146 if (chat_barp)
00147 {
00148 chat_barp->setGestureCombo(getChild<LLComboBox>( "Gesture"));
00149 }
00150 return TRUE;
00151 }
00152
00153
00154 void LLFloaterChat::onClose(bool app_quitting)
00155 {
00156 if (!app_quitting)
00157 {
00158 gSavedSettings.setBOOL("ShowChatHistory", FALSE);
00159 }
00160 setVisible(FALSE);
00161 }
00162
00163 void LLFloaterChat::onVisibilityChange(BOOL new_visibility)
00164 {
00165
00166 updateConsoleVisibility();
00167
00168
00169 if (new_visibility)
00170 {
00171 LLFloaterChatterBox::getInstance()->setFloaterFlashing(this, FALSE);
00172 }
00173
00174 LLFloater::onVisibilityChange(new_visibility);
00175 }
00176
00177 void LLFloaterChat::setMinimized(BOOL minimized)
00178 {
00179 LLFloater::setMinimized(minimized);
00180 updateConsoleVisibility();
00181 }
00182
00183
00184 void LLFloaterChat::updateConsoleVisibility()
00185 {
00186
00187 gConsole->setVisible( !isInVisibleChain()
00188 || isMinimized()
00189 || (getHost() && getHost()->isMinimized() ));
00190 }
00191
00192 void add_timestamped_line(LLViewerTextEditor* edit, const LLChat &chat, const LLColor4& color)
00193 {
00194 LLString line = chat.mText;
00195 bool prepend_newline = true;
00196 if (gSavedSettings.getBOOL("ChatShowTimestamps"))
00197 {
00198 edit->appendTime(prepend_newline);
00199 prepend_newline = false;
00200 }
00201
00202
00203
00204 if (chat.mSourceType == CHAT_SOURCE_AGENT &&
00205 chat.mFromID != LLUUID::null &&
00206 (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
00207 {
00208 line = line.substr(chat.mFromName.length());
00209 const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID);
00210 edit->appendStyledText(chat.mFromName, false, false, &sourceStyle);
00211 }
00212 edit->appendColoredText(line, false, prepend_newline, color);
00213 }
00214
00215 void log_chat_text(const LLChat& chat)
00216 {
00217 LLString histstr;
00218 if (gSavedPerAccountSettings.getBOOL("LogChatTimestamp"))
00219 histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText;
00220 else
00221 histstr = chat.mText;
00222
00223 LLLogChat::saveHistory("chat",histstr);
00224 }
00225
00226 void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
00227 {
00228 if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file)
00229 {
00230 log_chat_text(chat);
00231 }
00232
00233 LLColor4 color = get_text_color(chat);
00234
00235 if (!log_to_file) color = LLColor4::grey;
00236
00237 if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
00238 {
00239 LLFloaterScriptDebug::addScriptLine(chat.mText,
00240 chat.mFromName,
00241 color,
00242 chat.mFromID);
00243 if (!gSavedSettings.getBOOL("ScriptErrorsAsChat"))
00244 {
00245 return;
00246 }
00247 }
00248
00249
00250 LLFloaterChat* chat_floater = LLFloaterChat::getInstance(LLSD());
00251 LLViewerTextEditor* history_editor = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor");
00252 LLViewerTextEditor* history_editor_with_mute = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor with mute");
00253
00254 history_editor->setParseHTML(TRUE);
00255 history_editor_with_mute->setParseHTML(TRUE);
00256
00257 if (!chat.mMuted)
00258 {
00259 add_timestamped_line(history_editor, chat, color);
00260 add_timestamped_line(history_editor_with_mute, chat, color);
00261 }
00262 else
00263 {
00264
00265 LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f);
00266 add_timestamped_line(history_editor_with_mute, chat, color);
00267 }
00268
00269
00270 if (chat.mSourceType == CHAT_SOURCE_OBJECT)
00271 {
00272 chat_floater->mPanel->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT);
00273 }
00274
00275
00276 if (!chat_floater->isInVisibleChain() && chat.mSourceType == CHAT_SOURCE_AGENT)
00277 {
00278 LLFloaterChatterBox::getInstance()->setFloaterFlashing(chat_floater, TRUE);
00279 }
00280 }
00281
00282
00283 void LLFloaterChat::setHistoryCursorAndScrollToEnd()
00284 {
00285 LLViewerTextEditor* history_editor = LLFloaterChat::getInstance(LLSD())->getChild<LLViewerTextEditor>("Chat History Editor");
00286 LLViewerTextEditor* history_editor_with_mute = LLFloaterChat::getInstance(LLSD())->getChild<LLViewerTextEditor>("Chat History Editor with mute");
00287
00288 if (history_editor)
00289 {
00290 history_editor->setCursorAndScrollToEnd();
00291 }
00292 if (history_editor_with_mute)
00293 {
00294 history_editor_with_mute->setCursorAndScrollToEnd();
00295 }
00296 }
00297
00298
00299
00300 void LLFloaterChat::onClickMute(void *data)
00301 {
00302 LLFloaterChat* self = (LLFloaterChat*)data;
00303
00304 LLComboBox* chatter_combo = self->getChild<LLComboBox>("chatter combobox");
00305
00306 const LLString& name = chatter_combo->getSimple();
00307 LLUUID id = chatter_combo->getCurrentID();
00308
00309 if (name.empty()) return;
00310
00311 LLMute mute(id);
00312 mute.setFromDisplayName(name);
00313 LLMuteList::getInstance()->add(mute);
00314
00315 LLFloaterMute::showInstance();
00316 }
00317
00318
00319 void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data)
00320 {
00321 LLFloaterChat* floater = (LLFloaterChat*)data;
00322
00323
00324
00325 BOOL show_mute = floater->getChild<LLCheckBoxCtrl>("show mutes")->get();
00326 LLViewerTextEditor* history_editor = floater->getChild<LLViewerTextEditor>("Chat History Editor");
00327 LLViewerTextEditor* history_editor_with_mute = floater->getChild<LLViewerTextEditor>("Chat History Editor with mute");
00328
00329 if (!history_editor || !history_editor_with_mute)
00330 return;
00331
00332
00333 if (show_mute)
00334 {
00335 history_editor->setVisible(FALSE);
00336 history_editor_with_mute->setVisible(TRUE);
00337 history_editor_with_mute->setCursorAndScrollToEnd();
00338 }
00339 else
00340 {
00341 history_editor->setVisible(TRUE);
00342 history_editor_with_mute->setVisible(FALSE);
00343 history_editor->setCursorAndScrollToEnd();
00344 }
00345 }
00346
00347
00348 void LLFloaterChat::addChat(const LLChat& chat,
00349 BOOL from_instant_message,
00350 BOOL local_agent)
00351 {
00352 LLColor4 text_color = get_text_color(chat);
00353
00354 BOOL invisible_script_debug_chat =
00355 chat.mChatType == CHAT_TYPE_DEBUG_MSG
00356 && !gSavedSettings.getBOOL("ScriptErrorsAsChat");
00357
00358 #if LL_WINDOWS && LL_LCD_COMPILE
00359
00360 if (!invisible_script_debug_chat)
00361 {
00362 if (!from_instant_message)
00363 {
00364 AddNewChatToLCD(chat.mText);
00365 }
00366 else
00367 {
00368 AddNewIMToLCD(chat.mText);
00369 }
00370 }
00371 #endif
00372 if (!invisible_script_debug_chat
00373 && !chat.mMuted
00374 && gConsole
00375 && !local_agent)
00376 {
00377 F32 size = CHAT_MSG_SIZE;
00378 if (chat.mSourceType == CHAT_SOURCE_SYSTEM)
00379 {
00380 text_color = gSavedSettings.getColor("SystemChatColor");
00381 }
00382 else if(from_instant_message)
00383 {
00384 text_color = gSavedSettings.getColor("IMChatColor");
00385 size = INSTANT_MSG_SIZE;
00386 }
00387 gConsole->addLine(chat.mText, size, text_color);
00388 }
00389
00390 if(from_instant_message && gSavedPerAccountSettings.getBOOL("LogChatIM"))
00391 log_chat_text(chat);
00392
00393 if(from_instant_message && gSavedSettings.getBOOL("IMInChatHistory"))
00394 addChatHistory(chat,false);
00395
00396 if(!from_instant_message)
00397 addChatHistory(chat);
00398 }
00399
00400 LLColor4 get_text_color(const LLChat& chat)
00401 {
00402 LLColor4 text_color;
00403
00404 if(chat.mMuted)
00405 {
00406 text_color.setVec(0.8f, 0.8f, 0.8f, 1.f);
00407 }
00408 else
00409 {
00410 switch(chat.mSourceType)
00411 {
00412 case CHAT_SOURCE_SYSTEM:
00413 text_color = gSavedSettings.getColor4("SystemChatColor");
00414 break;
00415 case CHAT_SOURCE_AGENT:
00416 if (chat.mFromID.isNull())
00417 {
00418 text_color = gSavedSettings.getColor4("SystemChatColor");
00419 }
00420 else
00421 {
00422 text_color = gSavedSettings.getColor4("AgentChatColor");
00423 }
00424 break;
00425 case CHAT_SOURCE_OBJECT:
00426 if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
00427 {
00428 text_color = gSavedSettings.getColor4("ScriptErrorColor");
00429 }
00430 else if ( chat.mChatType == CHAT_TYPE_OWNER )
00431 {
00432 text_color = gSavedSettings.getColor4("llOwnerSayChatColor");
00433 }
00434 else
00435 {
00436 text_color = gSavedSettings.getColor4("ObjectChatColor");
00437 }
00438 break;
00439 default:
00440 text_color.setToWhite();
00441 }
00442
00443 if (!chat.mPosAgent.isExactlyZero())
00444 {
00445 LLVector3 pos_agent = gAgent.getPositionAgent();
00446 F32 distance = dist_vec(pos_agent, chat.mPosAgent);
00447 if (distance > gAgent.getNearChatRadius())
00448 {
00449
00450 text_color.mV[VALPHA] = 0.8f;
00451 }
00452 }
00453 }
00454
00455 return text_color;
00456 }
00457
00458
00459 void LLFloaterChat::loadHistory()
00460 {
00461 LLLogChat::loadHistory("chat", &chatFromLogFile, (void *)LLFloaterChat::getInstance(LLSD()));
00462 }
00463
00464
00465 void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , LLString line, void* userdata)
00466 {
00467 switch (type)
00468 {
00469 case LLLogChat::LOG_EMPTY:
00470 case LLLogChat::LOG_END:
00471
00472 break;
00473 case LLLogChat::LOG_LINE:
00474 {
00475 LLChat chat;
00476 chat.mText = line;
00477 addChatHistory(chat, FALSE);
00478 }
00479 break;
00480 default:
00481
00482 break;
00483 }
00484 }
00485
00486
00487 void* LLFloaterChat::createSpeakersPanel(void* data)
00488 {
00489 return new LLPanelActiveSpeakers(LLLocalSpeakerMgr::getInstance(), TRUE);
00490 }
00491
00492
00493 void* LLFloaterChat::createChatPanel(void* data)
00494 {
00495 LLChatBar* chatp = new LLChatBar();
00496 return chatp;
00497 }
00498
00499
00500 void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata)
00501 {
00502 LLFloaterChat* self = (LLFloaterChat*)userdata;
00503
00504 self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel"));
00505 }
00506
00507
00508 bool LLFloaterChat::visible(LLFloater* instance, const LLSD& key)
00509 {
00510 return VisibilityPolicy<LLFloater>::visible(instance, key);
00511 }
00512
00513
00514 void LLFloaterChat::show(LLFloater* instance, const LLSD& key)
00515 {
00516 VisibilityPolicy<LLFloater>::show(instance, key);
00517 }
00518
00519
00520 void LLFloaterChat::hide(LLFloater* instance, const LLSD& key)
00521 {
00522 if(instance->getHost())
00523 {
00524 LLFloaterChatterBox::hideInstance();
00525 }
00526 else
00527 {
00528 VisibilityPolicy<LLFloater>::hide(instance, key);
00529 }
00530 }