llchatbar.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llchatbar.h"
00035 
00036 #include "imageids.h"
00037 #include "llfontgl.h"
00038 #include "llrect.h"
00039 #include "llerror.h"
00040 #include "llparcel.h"
00041 #include "llstring.h"
00042 #include "message.h"
00043 #include "llfocusmgr.h"
00044 
00045 #include "llagent.h"
00046 #include "llbutton.h"
00047 #include "llcombobox.h"
00048 #include "llviewercontrol.h"
00049 #include "llfloaterchat.h"
00050 #include "llgesturemgr.h"
00051 #include "llkeyboard.h"
00052 #include "lllineeditor.h"
00053 #include "llstatusbar.h"
00054 #include "lltextbox.h"
00055 #include "lluiconstants.h"
00056 #include "llviewergesture.h"                    // for triggering gestures
00057 #include "llviewermenu.h"               // for deleting object with DEL key
00058 #include "llviewerstats.h"
00059 #include "llviewerwindow.h"
00060 #include "llframetimer.h"
00061 #include "llresmgr.h"
00062 #include "llworld.h"
00063 #include "llinventorymodel.h"
00064 #include "llmultigesture.h"
00065 #include "llui.h"
00066 #include "llviewermenu.h"
00067 #include "llvieweruictrlfactory.h"
00068 
00069 #include <stdio.h>
00070 
00071 //
00072 // Globals
00073 //
00074 const F32 AGENT_TYPING_TIMEOUT = 5.f;   // seconds
00075 
00076 LLChatBar *gChatBar = NULL;
00077 
00078 // legacy calllback glue
00079 void toggleChatHistory(void* user_data);
00080 
00081 
00082 class LLChatBarGestureObserver : public LLGestureManagerObserver
00083 {
00084 public:
00085         LLChatBarGestureObserver(LLChatBar* chat_barp) : mChatBar(chat_barp){}
00086         virtual ~LLChatBarGestureObserver() {}
00087         virtual void changed() { mChatBar->refreshGestures(); }
00088 private:
00089         LLChatBar* mChatBar;
00090 };
00091 
00092 
00093 //
00094 // Functions
00095 //
00096 
00097 //inline constructor
00098 // for chat bars embedded in floaters, etc
00099 LLChatBar::LLChatBar(const std::string& name) 
00100 :       LLPanel(name, LLRect(), BORDER_NO),
00101         mInputEditor(NULL),
00102         mGestureLabelTimer(),
00103         mLastSpecialChatChannel(0),
00104         mIsBuilt(FALSE),
00105         mDynamicLayout(FALSE),
00106         mGestureCombo(NULL),
00107         mObserver(NULL)
00108 {
00109 }
00110 
00111 LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) 
00112 :       LLPanel(name, rect, BORDER_NO),
00113         mInputEditor(NULL),
00114         mGestureLabelTimer(),
00115         mLastSpecialChatChannel(0),
00116         mIsBuilt(FALSE),
00117         mDynamicLayout(TRUE),
00118         mGestureCombo(NULL),
00119         mObserver(NULL)
00120 {
00121         setIsChrome(TRUE);
00122         
00123         gUICtrlFactory->buildPanel(this,"panel_chat_bar.xml");
00124         
00125         mIsFocusRoot = TRUE;
00126 
00127         setRect(rect); // override xml rect
00128         
00129         setBackgroundOpaque(TRUE);
00130         setBackgroundVisible(TRUE);
00131 
00132         // Start visible if we left the app while chatting.
00133         setVisible( gSavedSettings.getBOOL("ChatVisible") );
00134 
00135         // Apply custom layout.
00136         layout();
00137 
00138 #if !LL_RELEASE_FOR_DOWNLOAD
00139         childDisplayNotFound();
00140 #endif
00141         
00142 }
00143 
00144 
00145 LLChatBar::~LLChatBar()
00146 {
00147         delete mObserver;
00148         mObserver = NULL;
00149         // LLView destructor cleans up children
00150 }
00151 
00152 BOOL LLChatBar::postBuild()
00153 {
00154         childSetAction("History", toggleChatHistory, this);
00155         childSetAction("Say", onClickSay, this);
00156         childSetAction("Shout", onClickShout, this);
00157 
00158         // attempt to bind to an existing combo box named gesture
00159         setGestureCombo(LLUICtrlFactory::getComboBoxByName(this, "Gesture"));
00160 
00161         LLButton * sayp = static_cast<LLButton*>(getChildByName("Say", TRUE));
00162         if(sayp)
00163         {
00164                 setDefaultBtn(sayp);
00165         }
00166 
00167         mInputEditor = LLUICtrlFactory::getLineEditorByName(this, "Chat Editor");
00168         if (mInputEditor)
00169         {
00170                 mInputEditor->setCallbackUserData(this);
00171                 mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke);
00172                 mInputEditor->setFocusLostCallback(&onInputEditorFocusLost);
00173                 mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus );
00174                 mInputEditor->setCommitOnFocusLost( FALSE );
00175                 mInputEditor->setRevertOnEsc( FALSE );
00176                 mInputEditor->setIgnoreTab(TRUE);
00177                 mInputEditor->setPassDelete(TRUE);
00178 
00179                 mInputEditor->setMaxTextLength(1023);
00180                 mInputEditor->setEnableLineHistory(TRUE);
00181         }
00182 
00183         mIsBuilt = TRUE;
00184 
00185         return TRUE;
00186 }
00187 
00188 //-----------------------------------------------------------------------
00189 // Overrides
00190 //-----------------------------------------------------------------------
00191 
00192 // virtual
00193 void LLChatBar::reshape(S32 width, S32 height, BOOL called_from_parent)
00194 {
00195         LLPanel::reshape(width, height, called_from_parent);
00196         if (mIsBuilt)
00197         {
00198                 layout();
00199         }
00200 }
00201 
00202 // virtual
00203 BOOL LLChatBar::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
00204 {
00205         BOOL handled = FALSE;
00206 
00207         if( getVisible() && getEnabled() && !called_from_parent)
00208         {
00209                 // ALT-RETURN is reserved for windowed/fullscreen toggle
00210                 if( KEY_RETURN == key )
00211                 {
00212                         //if (childGetValue("Chat Editor").asString().empty())
00213                         //{
00214                         //      // no text, just close chat bar
00215                         //      stopChat();
00216                         //      return TRUE;
00217                         //}
00218 
00219                         if (mask == MASK_CONTROL)
00220                         {
00221                                 // shout
00222                                 sendChat(CHAT_TYPE_SHOUT);
00223                                 handled = TRUE;
00224                         }
00225                         else if (mask == MASK_NONE)
00226                         {
00227                                 // say
00228                                 sendChat( CHAT_TYPE_NORMAL );
00229                                 handled = TRUE;
00230                         }
00231                 }
00232                 // only do this in main chatbar
00233                 else if ( KEY_ESCAPE == key && gChatBar == this)
00234                 {
00235                         stopChat();
00236 
00237                         handled = TRUE;
00238                 }
00239         }
00240         return handled;
00241 }
00242 
00243 
00244 void LLChatBar::layout()
00245 {
00246         if (!mDynamicLayout) return;
00247 
00248         S32 rect_width = mRect.getWidth();
00249         S32 count = 9; // number of elements in LLToolBar
00250         S32 pad = 4;
00251 
00252         LLRect gesture_rect;
00253         S32 gesture_width = 0;
00254         if (childGetRect("Gesture", gesture_rect))
00255         {
00256                 gesture_width = gesture_rect.getWidth();
00257         }
00258         F32 segment_width = (F32)(rect_width - (pad + gesture_width)) / (F32)count;
00259 
00260         S32 btn_width = lltrunc(segment_width-pad);
00261 
00262         S32 x = 0;
00263         S32 y = 1;
00264         LLRect r;
00265 
00266         x = llround(0 * segment_width);
00267         r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT);
00268         childSetRect("History", r);
00269 
00270         x = llround(1 * segment_width);
00271         // Hack this one up so it looks nice.
00272         if (mInputEditor)
00273         {
00274                 r.setOriginAndSize(x, y+2, llfloor(6*segment_width-pad), 18);
00275                 mInputEditor->reshape(r.getWidth(), r.getHeight(), TRUE);
00276                 mInputEditor->setRect(r);
00277         }
00278         
00279         x = llround(7 * segment_width);
00280         r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT);
00281         childSetRect("Say", r);
00282 
00283         x = llround(8 * segment_width);
00284         r.setOriginAndSize(x, y, btn_width, BTN_HEIGHT);
00285         childSetRect("Shout", r);
00286 
00287         x = rect_width - (pad + gesture_width);
00288         r.setOriginAndSize(x, y, gesture_width, BTN_HEIGHT);
00289         childSetRect("Gesture", r);
00290 }
00291 
00292 
00293 void LLChatBar::refresh()
00294 {
00295         //BOOL chat_mode = gSavedSettings.getBOOL("ChatVisible");
00296 
00298         //if (!gFocusMgr.getKeyboardFocus()
00299         //      && chat_mode)
00300         //{
00301         //      childSetFocus("Chat Editor", TRUE);
00302         //}
00303 
00304         // Only show this view when user wants to be chatting
00305         //setVisible(chat_mode);
00306 
00307         // hide in mouselook, but keep previous visibility state
00308         //BOOL mouselook = gAgent.cameraMouselook();
00309         // call superclass setVisible so that we don't overwrite the saved setting
00310         if (mDynamicLayout)
00311         {
00312                 LLPanel::setVisible(gSavedSettings.getBOOL("ChatVisible"));
00313         }
00314 
00315         // HACK: Leave the name of the gesture in place for a few seconds.
00316         const F32 SHOW_GESTURE_NAME_TIME = 2.f;
00317         if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME)
00318         {
00319                 LLCtrlListInterface* gestures = mGestureCombo ? mGestureCombo->getListInterface() : NULL;
00320                 if (gestures) gestures->selectFirstItem();
00321                 mGestureLabelTimer.stop();
00322         }
00323 
00324         if ((gAgent.getTypingTime() > AGENT_TYPING_TIMEOUT) && (gAgent.getRenderState() & AGENT_STATE_TYPING))
00325         {
00326                 gAgent.stopTyping();
00327         }
00328 
00329         childSetValue("History", LLFloaterChat::instanceVisible(LLSD()));
00330 
00331         childSetEnabled("Say", mInputEditor->getText().size() > 0);
00332         childSetEnabled("Shout", mInputEditor->getText().size() > 0);
00333 
00334 }
00335 
00336 void LLChatBar::refreshGestures()
00337 {
00338         LLCtrlListInterface* gestures = mGestureCombo ? mGestureCombo->getListInterface() : NULL;
00339         if (mGestureCombo && gestures)
00340         {
00341                 //store current selection so we can maintain it
00342                 LLString cur_gesture = mGestureCombo->getValue().asString();
00343                 gestures->selectFirstItem();
00344                 LLString label = mGestureCombo->getValue().asString();;
00345                 // clear
00346                 gestures->clearRows();
00347 
00348                 // collect list of unique gestures
00349                 std::map <std::string, BOOL> unique;
00350                 LLGestureManager::item_map_t::iterator it;
00351                 for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it)
00352                 {
00353                         LLMultiGesture* gesture = (*it).second;
00354                         if (gesture)
00355                         {
00356                                 if (!gesture->mTrigger.empty())
00357                                 {
00358                                         unique[gesture->mTrigger] = TRUE;
00359                                 }
00360                         }
00361                 }
00362 
00363                 // ad unique gestures
00364                 std::map <std::string, BOOL>::iterator it2;
00365                 for (it2 = unique.begin(); it2 != unique.end(); ++it2)
00366                 {
00367                         gestures->addSimpleElement((*it2).first);
00368                 }
00369                 
00370                 gestures->sortByColumn(0, TRUE);
00371                 // Insert label after sorting
00372                 gestures->addSimpleElement(label, ADD_TOP);
00373                 
00374                 if (!cur_gesture.empty())
00375                 {
00376                         gestures->selectByValue(LLSD(cur_gesture));
00377                 }
00378                 else
00379                 {
00380                         gestures->selectFirstItem();
00381                 }
00382         }
00383 }
00384 
00385 // Move the cursor to the correct input field.
00386 void LLChatBar::setKeyboardFocus(BOOL focus)
00387 {
00388         if (focus)
00389         {
00390                 if (mInputEditor)
00391                 {
00392                         mInputEditor->setFocus(TRUE);
00393                         mInputEditor->selectAll();
00394                 }
00395         }
00396         else if (gFocusMgr.childHasKeyboardFocus(this))
00397         {
00398                 if (mInputEditor)
00399                 {
00400                         mInputEditor->deselect();
00401                 }
00402                 setFocus(FALSE);
00403         }
00404 }
00405 
00406 
00407 // Ignore arrow keys in chat bar
00408 void LLChatBar::setIgnoreArrowKeys(BOOL b)
00409 {
00410         if (mInputEditor)
00411         {
00412                 mInputEditor->setIgnoreArrowKeys(b);
00413         }
00414 }
00415 
00416 BOOL LLChatBar::inputEditorHasFocus()
00417 {
00418         return mInputEditor && mInputEditor->hasFocus();
00419 }
00420 
00421 LLString LLChatBar::getCurrentChat()
00422 {
00423         return mInputEditor ? mInputEditor->getText() : LLString::null;
00424 }
00425 
00426 void LLChatBar::setGestureCombo(LLComboBox* combo)
00427 {
00428         mGestureCombo = combo;
00429         if (mGestureCombo)
00430         {
00431                 mGestureCombo->setCommitCallback(onCommitGesture);
00432                 mGestureCombo->setCallbackUserData(this);
00433 
00434                 // now register observer since we have a place to put the results
00435                 mObserver = new LLChatBarGestureObserver(this);
00436                 gGestureManager.addObserver(mObserver);
00437 
00438                 // refresh list from current active gestures
00439                 refreshGestures();
00440         }
00441 }
00442 
00443 //-----------------------------------------------------------------------
00444 // Internal functions
00445 //-----------------------------------------------------------------------
00446 
00447 // If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20.
00448 // Otherwise returns input and channel 0.
00449 LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel)
00450 {
00451         if (mesg[0] == '/'
00452                 && mesg[1] == '/')
00453         {
00454                 // This is a "repeat channel send"
00455                 *channel = mLastSpecialChatChannel;
00456                 return mesg.substr(2, mesg.length() - 2);
00457         }
00458         else if (mesg[0] == '/'
00459                          && mesg[1]
00460                          && LLStringOps::isDigit(mesg[1]))
00461         {
00462                 // This a special "/20" speak on a channel
00463                 S32 pos = 0;
00464 
00465                 // Copy the channel number into a string
00466                 llwchar channel_string[64];
00467                 llwchar c;
00468                 do
00469                 {
00470                         c = mesg[pos+1];
00471                         channel_string[pos] = c;
00472                         pos++;
00473                 }
00474                 while(c && pos < 64 && LLStringOps::isDigit(c));
00475                 
00476                 // Move the pointer forward to the first non-whitespace char
00477                 // Check isspace before looping, so we can handle "/33foo"
00478                 // as well as "/33 foo"
00479                 while(c && iswspace(c))
00480                 {
00481                         c = mesg[pos+1];
00482                         pos++;
00483                 }
00484 
00485                 
00486                 mLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10);
00487                 *channel = mLastSpecialChatChannel;
00488                 return mesg.substr(pos, mesg.length() - pos);
00489         }
00490         else
00491         {
00492                 // This is normal chat.
00493                 *channel = 0;
00494                 return mesg;
00495         }
00496 }
00497 
00498 
00499 void LLChatBar::sendChat( EChatType type )
00500 {
00501         LLWString text;
00502         if (mInputEditor) text = mInputEditor->getWText();
00503         LLWString::trim(text);
00504 
00505         if (!text.empty())
00506         {
00507                 // store sent line in history, duplicates will get filtered
00508                 if (mInputEditor) mInputEditor->updateHistory();
00509                 // Check if this is destined for another channel
00510                 S32 channel = 0;
00511                 stripChannelNumber(text, &channel);
00512 
00513                 std::string utf8text = wstring_to_utf8str(text);
00514                 // Try to trigger a gesture, if not chat to a script.
00515                 std::string utf8_revised_text;
00516                 if (0 == channel)
00517                 {
00518                         // discard returned "found" boolean
00519                         gGestureManager.triggerAndReviseString(utf8text, &utf8_revised_text);
00520                 }
00521                 else
00522                 {
00523                         utf8_revised_text = utf8text;
00524                 }
00525 
00526                 utf8_revised_text = utf8str_trim(utf8_revised_text);
00527 
00528                 if (!utf8_revised_text.empty())
00529                 {
00530                         // Chat with animation
00531                         sendChatFromViewer(utf8_revised_text, type, TRUE);
00532                 }
00533         }
00534         childSetValue("Chat Editor", LLString::null);
00535 
00536         gAgent.stopTyping();
00537 
00538         // If the user wants to stop chatting on hitting return, lose focus
00539         // and go out of chat mode.
00540         if (gChatBar == this && gSavedSettings.getBOOL("CloseChatOnReturn"))
00541         {
00542                 stopChat();
00543         }
00544 }
00545 
00546 
00547 //-----------------------------------------------------------------------
00548 // Static functions
00549 //-----------------------------------------------------------------------
00550 
00551 // static 
00552 void LLChatBar::startChat(void* userdata)
00553 {
00554         const char* line = (const char*)userdata;
00555 
00556         gChatBar->setVisible(TRUE);
00557         gChatBar->setKeyboardFocus(TRUE);
00558         gSavedSettings.setBOOL("ChatVisible", TRUE);
00559 
00560         if (line && gChatBar->mInputEditor)
00561         {
00562                 std::string line_string(line);
00563                 gChatBar->mInputEditor->setText(line_string);
00564         }
00565         // always move cursor to end so users don't obliterate chat when accidentally hitting WASD
00566         gChatBar->mInputEditor->setCursorToEnd();
00567 }
00568 
00569 
00570 // Exit "chat mode" and do the appropriate focus changes
00571 // static
00572 void LLChatBar::stopChat()
00573 {
00574         // In simple UI mode, we never release focus from the chat bar
00575         gChatBar->setKeyboardFocus(FALSE);
00576 
00577         // If we typed a movement key and pressed return during the
00578         // same frame, the keyboard handlers will see the key as having
00579         // gone down this frame and try to move the avatar.
00580         gKeyboard->resetKeys();
00581         gKeyboard->resetMaskKeys();
00582 
00583         // stop typing animation
00584         gAgent.stopTyping();
00585 
00586         // hide chat bar so it doesn't grab focus back
00587         gChatBar->setVisible(FALSE);
00588 }
00589 
00590 void LLChatBar::setVisible(BOOL visible)
00591 {
00592         gSavedSettings.setBOOL("ChatVisible", visible);
00593         LLPanel::setVisible(visible);
00594 }
00595 
00596 // static
00597 void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata )
00598 {
00599         LLChatBar* self = (LLChatBar *)userdata;
00600 
00601         LLWString raw_text;
00602         if (self->mInputEditor) raw_text = self->mInputEditor->getWText();
00603 
00604         // Can't trim the end, because that will cause autocompletion
00605         // to eat trailing spaces that might be part of a gesture.
00606         LLWString::trimHead(raw_text);
00607 
00608         S32 length = raw_text.length();
00609 
00610         if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences
00611         {
00612                 gAgent.startTyping();
00613         }
00614         else
00615         {
00616                 gAgent.stopTyping();
00617         }
00618 
00619         /* Doesn't work -- can't tell the difference between a backspace
00620            that killed the selection vs. backspace at the end of line.
00621         if (length > 1 
00622                 && text[0] == '/'
00623                 && key == KEY_BACKSPACE)
00624         {
00625                 // the selection will already be deleted, but we need to trim
00626                 // off the character before
00627                 LLString new_text = raw_text.substr(0, length-1);
00628                 self->mInputEditor->setText( new_text );
00629                 self->mInputEditor->setCursorToEnd();
00630                 length = length - 1;
00631         }
00632         */
00633 
00634         KEY key = gKeyboard->currentKey();
00635 
00636         // Ignore "special" keys, like backspace, arrows, etc.
00637         if (length > 1 
00638                 && raw_text[0] == '/'
00639                 && key < KEY_SPECIAL)
00640         {
00641                 // we're starting a gesture, attempt to autocomplete
00642 
00643                 std::string utf8_trigger = wstring_to_utf8str(raw_text);
00644                 std::string utf8_out_str(utf8_trigger);
00645 
00646                 if (gGestureManager.matchPrefix(utf8_trigger, &utf8_out_str))
00647                 {
00648                         if (self->mInputEditor)
00649                         {
00650                                 self->mInputEditor->setText(utf8_out_str);
00651                                 S32 outlength = self->mInputEditor->getLength(); // in characters
00652                         
00653                                 // Select to end of line, starting from the character
00654                                 // after the last one the user typed.
00655                                 self->mInputEditor->setSelection(length, outlength);
00656                         }
00657                 }
00658 
00659                 //llinfos << "GESTUREDEBUG " << trigger 
00660                 //      << " len " << length
00661                 //      << " outlen " << out_str.getLength()
00662                 //      << llendl;
00663         }
00664 
00665         LLString keytext = "";
00666         switch(key)
00667         {
00668                 case KEY_BACKSPACE: keytext = "BACKSPACE"; break;
00669                 case KEY_DELETE: keytext = "DELETE"; break;
00670                 case KEY_RETURN: keytext = "ENTER";break;
00671                 default:
00672                         if ( key < KEY_SPECIAL )
00673                         {
00674                                 char tmp[8];
00675                                 sprintf(tmp, "%c", key);
00676                                 keytext = tmp;
00677                         }
00678         }
00679 
00680         S32 relay_channel = gSavedPerAccountSettings.getS32("RealtimeChatRelayChannel");
00681 
00682         if ( !keytext.empty() && relay_channel != 0 )
00683         {
00684                 LLMessageSystem* msg = gMessageSystem;
00685                 msg->newMessageFast(_PREHASH_ChatFromViewer);
00686                 msg->nextBlockFast(_PREHASH_AgentData);
00687                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00688                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00689                 msg->nextBlockFast(_PREHASH_ChatData);
00690                 msg->addStringFast(_PREHASH_Message, keytext);
00691                 msg->addU8Fast(_PREHASH_Type, CHAT_TYPE_WHISPER);
00692                 msg->addS32("Channel", relay_channel);
00693         
00694                 gAgent.sendReliableMessage();
00695         }
00696 
00697 
00698 }
00699 
00700 // static
00701 void LLChatBar::onInputEditorFocusLost( LLUICtrl* caller, void* userdata)
00702 {
00703         // stop typing animation
00704         gAgent.stopTyping();
00705 }
00706 
00707 // static
00708 void LLChatBar::onInputEditorGainFocus( LLUICtrl* caller, void* userdata )
00709 {
00710         LLFloaterChat::setHistoryCursorAndScrollToEnd();
00711 }
00712 
00713 // static
00714 void LLChatBar::onClickSay( void* userdata )
00715 {
00716         LLChatBar* self = (LLChatBar*) userdata;
00717         self->sendChat( CHAT_TYPE_NORMAL );
00718 }
00719 
00720 // static
00721 void LLChatBar::onClickShout( void* userdata )
00722 {
00723         LLChatBar *self = (LLChatBar *)userdata;
00724         self->sendChat( CHAT_TYPE_SHOUT );
00725 }
00726 
00727 void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate)
00728 {
00729         sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate);
00730 }
00731 
00732 void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
00733 {
00734         // Look for "/20 foo" channel chats.
00735         S32 channel = 0;
00736         LLWString out_text = stripChannelNumber(wtext, &channel);
00737         std::string utf8_out_text = wstring_to_utf8str(out_text);
00738         std::string utf8_text = wstring_to_utf8str(wtext);
00739 
00740         utf8_text = utf8str_trim(utf8_text);
00741         if (!utf8_text.empty())
00742         {
00743                 utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
00744         }
00745 
00746         gAgent.sendChat(utf8_out_text, channel, type, animate);
00747 }
00748 
00749 
00750 // static
00751 void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data)
00752 {
00753         LLChatBar* self = (LLChatBar*)data;
00754         LLCtrlListInterface* gestures = self->mGestureCombo ? self->mGestureCombo->getListInterface() : NULL;
00755         if (gestures)
00756         {
00757                 S32 index = gestures->getFirstSelectedIndex();
00758                 if (index == 0)
00759                 {
00760                         return;
00761                 }
00762                 const std::string& trigger = gestures->getSimpleSelectedValue().asString();
00763 
00764                 // pretend the user chatted the trigger string, to invoke
00765                 // substitution and logging.
00766                 std::string text(trigger);
00767                 std::string revised_text;
00768                 gGestureManager.triggerAndReviseString(text, &revised_text);
00769 
00770                 revised_text = utf8str_trim(revised_text);
00771                 if (!revised_text.empty())
00772                 {
00773                         // Don't play nodding animation
00774                         self->sendChatFromViewer(revised_text, CHAT_TYPE_NORMAL, FALSE);
00775                 }
00776         }
00777         self->mGestureLabelTimer.start();
00778         if (self->mGestureCombo != NULL)
00779         {
00780                 // free focus back to chat bar
00781                 self->mGestureCombo->setFocus(FALSE);
00782         }
00783 }
00784 
00785 void toggleChatHistory(void* user_data)
00786 {
00787         LLFloaterChat::toggleInstance(LLSD());
00788 }

Generated on Thu Jul 1 06:08:21 2010 for Second Life Viewer by  doxygen 1.4.7