llfloaterchat.cpp

Go to the documentation of this file.
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 // project include
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 //#include "lllineeditor.h"
00060 #include "llmutelist.h"
00061 //#include "llresizehandle.h"
00062 #include "llchatbar.h"
00063 #include "llstatusbar.h"
00064 #include "llviewertexteditor.h"
00065 #include "llviewergesture.h"                    // for triggering gestures
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 // Used for LCD display
00078 extern void AddNewIMToLCD(const LLString &newLine);
00079 extern void AddNewChatToLCD(const LLString &newLine);
00080 //
00081 // Constants
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 // Global statics
00090 //
00091 LLColor4 get_text_color(const LLChat& chat);
00092 
00093 //
00094 // Member Functions
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         // do not automatically open singleton floaters (as result of getInstance())
00104         BOOL no_open = FALSE;
00105         LLUICtrlFactory::getInstance()->buildFloater(this,"floater_chat_history.xml",&getFactoryMap(),no_open);
00106 
00107         childSetCommitCallback("show mutes",onClickToggleShowMute,this); //show mutes
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         // Children all cleaned up by default view destructor.
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         // enable say and shout only when text available
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 // public virtual
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         // Hide the chat overlay when our history is visible.
00166         updateConsoleVisibility();
00167 
00168         // stop chat history tab from flashing when it appears
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         // determine whether we should show console due to not being visible
00187         gConsole->setVisible( !isInVisibleChain()                                                               // are we not in part of UI being drawn?
00188                                                         || isMinimized()                                                                // are we minimized?
00189                                                         || (getHost() && getHost()->isMinimized() ));   // are we hosted in a minimized floater?
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         // If the msg is not from an agent (not yourself though),
00203         // extract out the sender name and replace it with the hotlinked name.
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 // static
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;       //Recap from log file.
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         // could flash the chat button in the status bar here. JC
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                 // desaturate muted chat
00265                 LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f);
00266                 add_timestamped_line(history_editor_with_mute, chat, color);
00267         }
00268         
00269         // add objects as transient speakers that can be muted
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         // start tab flashing on incoming text from other users (ignoring system text, etc)
00276         if (!chat_floater->isInVisibleChain() && chat.mSourceType == CHAT_SOURCE_AGENT)
00277         {
00278                 LLFloaterChatterBox::getInstance()->setFloaterFlashing(chat_floater, TRUE);
00279         }
00280 }
00281 
00282 // static
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 //static 
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 //static
00319 void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data)
00320 {
00321         LLFloaterChat* floater = (LLFloaterChat*)data;
00322 
00323 
00324         //LLCheckBoxCtrl*       
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         //BOOL show_mute = floater->mShowMuteCheckBox->get();
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 // Put a line of chat in all the right places
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         // add into LCD displays
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                                 // diminish far-off chat
00450                                 text_color.mV[VALPHA] = 0.8f;
00451                         }
00452                 }
00453         }
00454 
00455         return text_color;
00456 }
00457 
00458 //static
00459 void LLFloaterChat::loadHistory()
00460 {
00461         LLLogChat::loadHistory("chat", &chatFromLogFile, (void *)LLFloaterChat::getInstance(LLSD())); 
00462 }
00463 
00464 //static
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                 // *TODO: nice message from XML file here
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                 // nothing
00482                 break;
00483         }
00484 }
00485 
00486 //static
00487 void* LLFloaterChat::createSpeakersPanel(void* data)
00488 {
00489         return new LLPanelActiveSpeakers(LLLocalSpeakerMgr::getInstance(), TRUE);
00490 }
00491 
00492 //static
00493 void* LLFloaterChat::createChatPanel(void* data)
00494 {
00495         LLChatBar* chatp = new LLChatBar();
00496         return chatp;
00497 }
00498 
00499 // static
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 //static 
00508 bool LLFloaterChat::visible(LLFloater* instance, const LLSD& key)
00509 {
00510         return VisibilityPolicy<LLFloater>::visible(instance, key);
00511 }
00512 
00513 //static 
00514 void LLFloaterChat::show(LLFloater* instance, const LLSD& key)
00515 {
00516         VisibilityPolicy<LLFloater>::show(instance, key);
00517 }
00518 
00519 //static 
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 }

Generated on Fri May 16 08:33:23 2008 for SecondLife by  doxygen 1.5.5