/** * @file llfloaterchatterbox.cpp * @author Richard * @date 2007-05-08 * @brief Implementation of the chatterbox integrated conversation ui * * $LicenseInfo:firstyear=2007&license=viewergpl$ * * Copyright (c) 2007-2009, 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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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$ */ #include "llviewerprecompiledheaders.h" #include "llfloaterreg.h" #include "llfloaterchatterbox.h" #include "lluictrlfactory.h" #include "llfloaterchat.h" #include "llfloaterfriends.h" #include "llfloatergroups.h" #include "llviewercontrol.h" #include "llvoicechannel.h" #include "llimpanel.h" // // LLFloaterMyFriends // LLFloaterMyFriends::LLFloaterMyFriends(const LLSD& seed) : LLFloater(seed) { mFactoryMap["friends_panel"] = LLCallbackMap(LLFloaterMyFriends::createFriendsPanel, NULL); mFactoryMap["groups_panel"] = LLCallbackMap(LLFloaterMyFriends::createGroupsPanel, NULL); //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_my_friends.xml"); } LLFloaterMyFriends::~LLFloaterMyFriends() { } BOOL LLFloaterMyFriends::postBuild() { return TRUE; } void LLFloaterMyFriends::onOpen(const LLSD& key) { if (key.asString() == "friends") { childShowTab("friends_and_groups", "friends_panel"); } else if (key.asString() == "groups") { childShowTab("friends_and_groups", "groups_panel"); } } //static void* LLFloaterMyFriends::createFriendsPanel(void* data) { return new LLPanelFriends(); } //static void* LLFloaterMyFriends::createGroupsPanel(void* data) { return new LLPanelGroups(); } //static LLFloaterMyFriends* LLFloaterMyFriends::getInstance() { return LLFloaterReg::getTypedInstance<LLFloaterMyFriends>("contacts", "friends") ; } // // LLFloaterChatterBox // LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed) : LLMultiFloater(seed), mActiveVoiceFloater(NULL) { mAutoResize = FALSE; //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_chatterbox.xml", FALSE); } LLFloaterChatterBox::~LLFloaterChatterBox() { } BOOL LLFloaterChatterBox::postBuild() { setVisibleCallback(boost::bind(&LLFloaterChatterBox::onVisibilityChange, this, _2)); if (gSavedSettings.getBOOL("ContactsTornOff")) { LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance(); if(floater_contacts) { // add then remove to set up relationship for re-attach addFloater(floater_contacts, FALSE); removeFloater(floater_contacts); // reparent to floater view gFloaterView->addChild(floater_contacts); } } else { addFloater(LLFloaterMyFriends::getInstance(), TRUE); } if (gSavedSettings.getBOOL("ChatHistoryTornOff")) { LLFloaterChat* floater_chat = LLFloaterChat::getInstance(); if(floater_chat) { // add then remove to set up relationship for re-attach addFloater(floater_chat, FALSE); removeFloater(floater_chat); // reparent to floater view gFloaterView->addChild(floater_chat); } } else { addFloater(LLFloaterChat::getInstance(), FALSE); } mTabContainer->lockTabs(); return TRUE; } BOOL LLFloaterChatterBox::handleKeyHere(KEY key, MASK mask) { if (key == 'W' && mask == MASK_CONTROL) { LLFloater* floater = getActiveFloater(); // is user closeable and is system closeable if (floater && floater->canClose()) { if (floater->isCloseable()) { floater->closeFloater(); } else { // close chatterbox window if frontmost tab is reserved, non-closeable tab // such as contacts or near me closeFloater(); } } return TRUE; } return LLMultiFloater::handleKeyHere(key, mask); } void LLFloaterChatterBox::draw() { // clear new im notifications when chatterbox is visible if (!isMinimized()) { gIMMgr->clearNewIMNotification(); } LLFloater* current_active_floater = getCurrentVoiceFloater(); // set icon on tab for floater currently associated with active voice channel if(mActiveVoiceFloater != current_active_floater) { // remove image from old floater's tab if (mActiveVoiceFloater) { mTabContainer->setTabImage(mActiveVoiceFloater, ""); } } // update image on current active tab if (current_active_floater) { LLColor4 icon_color = LLColor4::white; LLVoiceChannel* channelp = LLVoiceChannel::getCurrentVoiceChannel(); if (channelp) { if (channelp->isActive()) { icon_color = LLColor4::green; } else if (channelp->getState() == LLVoiceChannel::STATE_ERROR) { icon_color = LLColor4::red; } else // active, but not connected { icon_color = LLColor4::yellow; } } mTabContainer->setTabImage(current_active_floater, "active_voice_tab.tga", icon_color); } mActiveVoiceFloater = current_active_floater; LLMultiFloater::draw(); } void LLFloaterChatterBox::onOpen(const LLSD& key) { //*TODO:Skinning show the session id associated with key if (key.asString() == "local") { LLFloaterChat* chat = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat"); chat->openFloater(); } else if (key.isDefined()) { LLFloaterIMPanel* impanel = gIMMgr->findFloaterBySession(key.asUUID()); if (impanel) { impanel->openFloater(); } } } void LLFloaterChatterBox::onVisibilityChange ( const LLSD& new_visibility ) { // HACK: potentially need to toggle console LLFloaterChat* instance = LLFloaterChat::getInstance(); if(instance) { instance->updateConsoleVisibility(); } } void LLFloaterChatterBox::removeFloater(LLFloater* floaterp) { if(!floaterp) return; if (floaterp->getName() == "chat floater") { // only my friends floater now locked mTabContainer->lockTabs(mTabContainer->getNumLockedTabs() - 1); gSavedSettings.setBOOL("ChatHistoryTornOff", TRUE); floaterp->setCanClose(TRUE); } else if (floaterp->getName() == "floater_my_friends") { // only chat floater now locked mTabContainer->lockTabs(mTabContainer->getNumLockedTabs() - 1); gSavedSettings.setBOOL("ContactsTornOff", TRUE); floaterp->setCanClose(TRUE); } LLMultiFloater::removeFloater(floaterp); } void LLFloaterChatterBox::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) { if(!floaterp) return; S32 num_locked_tabs = mTabContainer->getNumLockedTabs(); // already here if (floaterp->getHost() == this) { openFloater(floaterp->getKey()); return; } // make sure my friends and chat history both locked when re-attaching chat history if (floaterp->getName() == "chat floater") { mTabContainer->unlockTabs(); // add chat history as second tab if contact window is present, first tab otherwise if (getChildView("floater_my_friends")) { // assuming contacts window is first tab, select it mTabContainer->selectFirstTab(); // and add ourselves after LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::RIGHT_OF_CURRENT); } else { LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::START); } // make sure first two tabs are now locked mTabContainer->lockTabs(num_locked_tabs + 1); gSavedSettings.setBOOL("ChatHistoryTornOff", FALSE); floaterp->setCanClose(FALSE); } else if (floaterp->getName() == "floater_my_friends") { mTabContainer->unlockTabs(); // add contacts window as first tab LLMultiFloater::addFloater(floaterp, select_added_floater, LLTabContainer::START); // make sure first two tabs are now locked mTabContainer->lockTabs(num_locked_tabs + 1); gSavedSettings.setBOOL("ContactsTornOff", FALSE); floaterp->setCanClose(FALSE); } else { LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); // openFloater(floaterp->getKey()); } // make sure active voice icon shows up for new tab if (floaterp == mActiveVoiceFloater) { mTabContainer->setTabImage(floaterp, "active_voice_tab.tga"); } } //static LLFloaterChatterBox* LLFloaterChatterBox::getInstance() { return LLFloaterReg::getTypedInstance<LLFloaterChatterBox>("communicate", LLSD()) ; } //static LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater() { if (!LLVoiceClient::voiceEnabled()) { return NULL; } if (LLVoiceChannelProximal::getInstance() == LLVoiceChannel::getCurrentVoiceChannel()) { // show near me tab if in proximal channel return LLFloaterChat::getInstance(); } else { LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance(); if(!floater) return NULL; // iterator over all IM tabs (skip friends and near me) for (S32 i = 0; i < floater->getFloaterCount(); i++) { LLPanel* panelp = floater->mTabContainer->getPanelByIndex(i); if (panelp->getName() == "im_floater") { // only LLFloaterIMPanels are called "im_floater" LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)panelp; LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(im_floaterp->getSessionID()); if (voice_channel == LLVoiceChannel::getCurrentVoiceChannel()) { return im_floaterp; } } } } return NULL; }