/** * @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 "llfloaterchatterbox.h" #include "lluictrlfactory.h" #include "llfloaterchat.h" #include "llfloaterfriends.h" #include "llfloatergroups.h" #include "llviewercontrol.h" #include "llimview.h" #include "llimpanel.h" // // LLFloaterMyFriends // LLFloaterMyFriends::LLFloaterMyFriends(const LLSD& seed) { mFactoryMap["friends_panel"] = LLCallbackMap(LLFloaterMyFriends::createFriendsPanel, NULL); mFactoryMap["groups_panel"] = LLCallbackMap(LLFloaterMyFriends::createGroupsPanel, NULL); // do not automatically open singleton floaters (as result of getInstance()) BOOL no_open = FALSE; LLUICtrlFactory::getInstance()->buildFloater(this, "floater_my_friends.xml", &getFactoryMap(), no_open); } LLFloaterMyFriends::~LLFloaterMyFriends() { } BOOL LLFloaterMyFriends::postBuild() { mTabs = getChild("friends_and_groups"); return TRUE; } void LLFloaterMyFriends::onClose(bool app_quitting) { setVisible(FALSE); } //static void* LLFloaterMyFriends::createFriendsPanel(void* data) { return new LLPanelFriends(); } //static void* LLFloaterMyFriends::createGroupsPanel(void* data) { return new LLPanelGroups(); } // // LLFloaterChatterBox // static std::string sTitle = ""; static int sIMUnreadCount = 0; LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed) : mActiveVoiceFloater(NULL) { mAutoResize = FALSE; // check if vertical tabs is selected if (gSavedSettings.getBOOL("VerticalIMTabs")) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_chatterbox_vertical.xml", NULL, FALSE); } else { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_chatterbox.xml", NULL, FALSE); } if (gSavedSettings.getBOOL("ContactsTornOff")) { LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance(0); // 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(0), TRUE); } if (gSavedSettings.getBOOL("ChatHistoryTornOff")) { LLFloaterChat* floater_chat = LLFloaterChat::getInstance(); // 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(LLSD()), FALSE); } mTabContainer->lockTabs(); sTitle = getTitle(); } LLFloaterChatterBox::~LLFloaterChatterBox() { } 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->close(); } else { // close chatterbox window if frontmost tab is reserved, non-closeable tab // such as contacts or near me close(); } } 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() { gSavedSettings.setBOOL("ShowCommunicate", TRUE); } void LLFloaterChatterBox::onClose(bool app_quitting) { setVisible(FALSE); gSavedSettings.setBOOL("ShowCommunicate", FALSE); } void LLFloaterChatterBox::setMinimized(BOOL minimized) { LLFloater::setMinimized(minimized); // HACK: potentially need to toggle console LLFloaterChat::getInstance()->updateConsoleVisibility(); } void LLFloaterChatterBox::markAsUnread(bool unread) { LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance(); // Update IM unread count here as tabs are clicked if (unread) { sIMUnreadCount++; } else { sIMUnreadCount--; } if (floater) { // Update the title message with the number of unread IMs. // Remove the message when we hit 0. if (sIMUnreadCount > 0) { // Check for plurals std::string unread_string; if (sIMUnreadCount == 1) { unread_string = floater->getString("unread_count_string_singular"); } else { unread_string = floater->getString("unread_count_string_plural"); } std::ostringstream unread_count_message; unread_count_message << sTitle << " - " << sIMUnreadCount << " " << unread_string; // Update the floater title floater->setTitle(unread_count_message.str()); } else { sIMUnreadCount = 0; // Update the floater title floater->setTitle(sTitle); } } } void LLFloaterChatterBox::removeFloater(LLFloater* floaterp) { 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) { S32 num_locked_tabs = mTabContainer->getNumLockedTabs(); // already here if (floaterp->getHost() == this) 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); } // make sure active voice icon shows up for new tab if (floaterp == mActiveVoiceFloater) { mTabContainer->setTabImage(floaterp, "active_voice_tab.tga"); } } //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(LLSD()); } else { LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance(LLSD()); // 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; if (im_floaterp->getVoiceChannel() == LLVoiceChannel::getCurrentVoiceChannel()) { return im_floaterp; } } } } return NULL; }