diff options
Diffstat (limited to 'indra/newview/llsyswellwindow.cpp')
-rw-r--r-- | indra/newview/llsyswellwindow.cpp | 850 |
1 files changed, 850 insertions, 0 deletions
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp new file mode 100644 index 0000000000..99342bb564 --- /dev/null +++ b/indra/newview/llsyswellwindow.cpp @@ -0,0 +1,850 @@ +/** + * @file llsyswellwindow.cpp + * @brief // TODO + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llagent.h" + +#include "llflatlistview.h" +#include "llfloaterreg.h" +#include "llnotifications.h" + +#include "llsyswellwindow.h" + +#include "llbottomtray.h" +#include "llscriptfloater.h" +#include "llviewercontrol.h" +#include "llviewerwindow.h" + +#include "llchiclet.h" +#include "lltoastpanel.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" +#include "llspeakers.h" + +//--------------------------------------------------------------------------------- +LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), + mChannel(NULL), + mMessageList(NULL), + mSysWellChiclet(NULL), + NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), + IM_WELL_ANCHOR_NAME("im_well_panel"), + mIsReshapedByUser(false) + +{ + setOverlapsScreenChannel(true); +} + +//--------------------------------------------------------------------------------- +BOOL LLSysWellWindow::postBuild() +{ + mMessageList = getChild<LLFlatListView>("notification_list"); + + // get a corresponding channel + initChannel(); + + // click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147. + // mouse up callback is not called in this case. + setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this)); + + return LLTransientDockableFloater::postBuild(); +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::setMinimized(BOOL minimize) +{ + LLTransientDockableFloater::setMinimized(minimize); +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::handleReshape(const LLRect& rect, bool by_user) +{ + mIsReshapedByUser |= by_user; // mark floater that it is reshaped by user + LLTransientDockableFloater::handleReshape(rect, by_user); +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) +{ + // just set floater visible. Screen channels will be cleared. + setVisible(TRUE); +} + +void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) +{ + mSysWellChiclet = chiclet; + if(mSysWellChiclet) + mSysWellChiclet->updateWidget(isWindowEmpty()); +} +//--------------------------------------------------------------------------------- +LLSysWellWindow::~LLSysWellWindow() +{ +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::removeItemByID(const LLUUID& id) +{ + if(mMessageList->removeItemByValue(id)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + reshapeWindow(); + } + else + { + llwarns << "Unable to remove notification from the list, ID: " << id + << llendl; + } + + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } +} + +//--------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------- +void LLSysWellWindow::initChannel() +{ + LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); + if(NULL == mChannel) + { + llwarns << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << llendl; + } +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::getAllowedRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRectScaled(); +} + +//--------------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::setVisible(BOOL visible) +{ + if (visible) + { + if (NULL == getDockControl() && getDockTongue().notNull()) + { + setDockControl(new LLDockControl( + LLBottomTray::getInstance()->getChild<LLView>(getAnchorViewName()), this, + getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1))); + } + } + + // do not show empty window + if (NULL == mMessageList || isWindowEmpty()) visible = FALSE; + + LLTransientDockableFloater::setVisible(visible); + + // update notification channel state + if(mChannel) + { + mChannel->updateShowToastsState(); + mChannel->redrawToasts(); + } + + if (visible) + { + releaseNewMessagesState(); + } +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock) +{ + LLTransientDockableFloater::setDocked(docked, pop_on_undock); + + // update notification channel state + if(mChannel) + { + mChannel->updateShowToastsState(); + mChannel->redrawToasts(); + } +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::reshapeWindow() +{ + // save difference between floater height and the list height to take it into account while calculating new window height + // it includes height from floater top to list top and from floater bottom and list bottom + static S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight(); + + if (!mIsReshapedByUser) // Don't reshape Well window, if it ever was reshaped by user. See EXT-5715. + { + S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth(); + + LLRect curRect = getRect(); + + S32 new_window_height = notif_list_height + parent_list_delta_height; + + if (new_window_height > MAX_WINDOW_HEIGHT) + { + new_window_height = MAX_WINDOW_HEIGHT; + } + S32 newY = curRect.mTop + new_window_height - curRect.getHeight(); + S32 newWidth = curRect.getWidth() < MIN_WINDOW_WIDTH ? MIN_WINDOW_WIDTH + : curRect.getWidth(); + curRect.setLeftTopAndSize(curRect.mLeft, newY, newWidth, new_window_height); + reshape(curRect.getWidth(), curRect.getHeight(), TRUE); + setRect(curRect); + } + + // update notification channel state + // update on a window reshape is important only when a window is visible and docked + if(mChannel && getVisible() && isDocked()) + { + mChannel->updateShowToastsState(); + } +} + +void LLSysWellWindow::releaseNewMessagesState() +{ + if (NULL != mSysWellChiclet) + { + mSysWellChiclet->setNewMessagesState(false); + } +} + +//--------------------------------------------------------------------------------- +bool LLSysWellWindow::isWindowEmpty() +{ + return mMessageList->size() == 0; +} + +/************************************************************************/ +/* RowPanel implementation */ +/************************************************************************/ + +//--------------------------------------------------------------------------------- +LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, + S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : + LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) +{ + buildFromFile( "panel_activeim_row.xml", NULL); + + // Choose which of the pre-created chiclets (IM/group) to use. + // The other one gets hidden. + + LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId); + switch (im_chiclet_type) + { + case LLIMChiclet::TYPE_GROUP: + mChiclet = getChild<LLIMGroupChiclet>("group_chiclet"); + break; + case LLIMChiclet::TYPE_AD_HOC: + mChiclet = getChild<LLAdHocChiclet>("adhoc_chiclet"); + break; + case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway + case LLIMChiclet::TYPE_IM: + mChiclet = getChild<LLIMP2PChiclet>("p2p_chiclet"); + break; + } + + // Initialize chiclet. + mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2)); + mChiclet->enableCounterControl(true); + mChiclet->setCounter(chicletCounter); + mChiclet->setSessionId(sessionId); + mChiclet->setIMSessionName(name); + mChiclet->setOtherParticipantId(otherParticipantId); + mChiclet->setVisible(true); + + LLTextBox* contactName = getChild<LLTextBox>("contact_name"); + contactName->setValue(name); + + mCloseBtn = getChild<LLButton>("hide_btn"); + mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this)); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) +{ + LLTextBox* text = getChild<LLTextBox>("contact_name"); + S32 new_text_left = mChiclet->getRect().mRight + CHICLET_HPAD; + LLRect text_rect = text->getRect(); + text_rect.mLeft = new_text_left; + text->setRect(text_rect); +} + +//--------------------------------------------------------------------------------- +LLIMWellWindow::RowPanel::~RowPanel() +{ +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::RowPanel::onClosePanel() +{ + gIMMgr->leaveSession(mChiclet->getSessionId()); + // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved(). +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); +} + +//--------------------------------------------------------------------------------- +// virtual +BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) +{ + // Pass the mouse down event to the chiclet (EXT-596). + if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() + { + mChiclet->onMouseDown(); + return TRUE; + } + + return LLPanel::handleMouseDown(x, y, mask); +} + +// virtual +BOOL LLIMWellWindow::RowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return mChiclet->handleRightMouseDown(x, y, mask); +} +/************************************************************************/ +/* ObjectRowPanel implementation */ +/************************************************************************/ + +LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& notification_id, bool new_message/* = false*/) + : LLPanel() + , mChiclet(NULL) +{ + buildFromFile( "panel_active_object_row.xml", NULL); + + initChiclet(notification_id); + + LLTextBox* obj_name = getChild<LLTextBox>("object_name"); + obj_name->setValue(LLScriptFloaterManager::getObjectName(notification_id)); + + mCloseBtn = getChild<LLButton>("hide_btn"); + mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::ObjectRowPanel::onClosePanel, this)); +} + +//--------------------------------------------------------------------------------- +LLIMWellWindow::ObjectRowPanel::~ObjectRowPanel() +{ +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onClosePanel() +{ + LLScriptFloaterManager::getInstance()->removeNotification(mChiclet->getSessionId()); +} + +void LLIMWellWindow::ObjectRowPanel::initChiclet(const LLUUID& notification_id, bool new_message/* = false*/) +{ + // Choose which of the pre-created chiclets to use. + switch(LLScriptFloaterManager::getObjectType(notification_id)) + { + case LLScriptFloaterManager::OBJ_GIVE_INVENTORY: + mChiclet = getChild<LLInvOfferChiclet>("inv_offer_chiclet"); + break; + default: + mChiclet = getChild<LLScriptChiclet>("object_chiclet"); + break; + } + + mChiclet->setVisible(true); + mChiclet->setSessionId(notification_id); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseLeave(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); +} + +//--------------------------------------------------------------------------------- +// virtual +BOOL LLIMWellWindow::ObjectRowPanel::handleMouseDown(S32 x, S32 y, MASK mask) +{ + // Pass the mouse down event to the chiclet (EXT-596). + if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown() + { + mChiclet->onMouseDown(); + return TRUE; + } + + return LLPanel::handleMouseDown(x, y, mask); +} + +// virtual +BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + return mChiclet->handleRightMouseDown(x, y, mask); +} + +/************************************************************************/ +/* LLNotificationWellWindow implementation */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) +: LLSysWellWindow(key) +{ + // init connections to the list's update events + connectListUpdaterToSignal("notify"); + connectListUpdaterToSignal("groupnotify"); + connectListUpdaterToSignal("offer"); +} + +// static +LLNotificationWellWindow* LLNotificationWellWindow::getInstance(const LLSD& key /*= LLSD()*/) +{ + return LLFloaterReg::getTypedInstance<LLNotificationWellWindow>("notification_well_window", key); +} + +// virtual +BOOL LLNotificationWellWindow::postBuild() +{ + BOOL rv = LLSysWellWindow::postBuild(); + setTitle(getString("title_notification_well_window")); + return rv; +} + +// virtual +void LLNotificationWellWindow::setVisible(BOOL visible) +{ + if (visible) + { + // when Notification channel is cleared, storable toasts will be added into the list. + clearScreenChannels(); + } + + LLSysWellWindow::setVisible(visible); +} + +//--------------------------------------------------------------------------------- +void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) +{ + LLSD value = p.notification_id; + // do not add clones + if( mMessageList->getItemByValue(value)) + return; + + LLSysWellItem* new_item = new LLSysWellItem(p); + if (mMessageList->addItem(new_item, value, ADD_TOP)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + reshapeWindow(); + + new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1)); + new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1)); + } + else + { + llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id + << ", title: " << p.title + << llendl; + + new_item->die(); + } +} + +void LLNotificationWellWindow::closeAll() +{ + // Need to clear notification channel, to add storable toasts into the list. + clearScreenChannels(); + std::vector<LLPanel*> items; + mMessageList->getItems(items); + for (std::vector<LLPanel*>::iterator + iter = items.begin(), + iter_end = items.end(); + iter != iter_end; ++iter) + { + LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter); + if (sys_well_item) + onItemClose(sys_well_item); + } +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +void LLNotificationWellWindow::initChannel() +{ + LLSysWellWindow::initChannel(); + if(mChannel) + { + mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); + } +} + +void LLNotificationWellWindow::clearScreenChannels() +{ + // 1 - remove StartUp toast and channel if present + if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) + { + LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); + } + + // 2 - remove toasts in Notification channel + if(mChannel) + { + mChannel->removeAndStoreAllStorableToasts(); + } +} + +void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) +{ + LLSysWellItem::Params p; + p.notification_id = id; + p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); + addItem(p); +} + +void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) +{ + LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); + LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + if(n_handler) + { + n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); + } + else + { + llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; + } +} + +void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) +{ + LLUUID id = item->getID(); + LLFloaterReg::showInstance("inspect_toast", id); +} + +void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) +{ + LLUUID id = item->getID(); + removeItemByID(id); + if(mChannel) + mChannel->killToastByNotificationID(id); +} + + + +/************************************************************************/ +/* LLIMWellWindow implementation */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +LLIMWellWindow::LLIMWellWindow(const LLSD& key) +: LLSysWellWindow(key) +{ + LLIMMgr::getInstance()->addSessionObserver(this); +} + +LLIMWellWindow::~LLIMWellWindow() +{ + LLIMMgr::getInstance()->removeSessionObserver(this); +} + +// static +LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/) +{ + return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key); +} + +BOOL LLIMWellWindow::postBuild() +{ + BOOL rv = LLSysWellWindow::postBuild(); + setTitle(getString("title_im_well_window")); + + LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1)); + LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1)); + + return rv; +} + +//virtual +void LLIMWellWindow::sessionAdded(const LLUUID& session_id, + const std::string& name, const LLUUID& other_participant_id) +{ + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id); + if (!session) return; + + // no need to spawn chiclets for participants in P2P calls called through Avaline + if (session->isP2P() && session->isOtherParticipantAvaline()) return; + + if (mMessageList->getItemByValue(session_id)) return; + + addIMRow(session_id, 0, name, other_participant_id); + reshapeWindow(); +} + +//virtual +void LLIMWellWindow::sessionRemoved(const LLUUID& sessionId) +{ + delIMRow(sessionId); + reshapeWindow(); +} + +//virtual +void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ + //for outgoing ad-hoc and group im sessions only + LLChiclet* chiclet = findIMChiclet(old_session_id); + if (chiclet) + { + chiclet->setSessionId(new_session_id); + mMessageList->updateValue(old_session_id, new_session_id); + } +} + +LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id) +{ + if (!mMessageList) return NULL; + + LLChiclet* res = NULL; + ObjectRowPanel* panel = mMessageList->getTypedItemByValue<ObjectRowPanel>(notification_id); + if (panel != NULL) + { + res = panel->mChiclet; + } + + return res; +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId) +{ + if (!mMessageList) return NULL; + + LLChiclet* res = NULL; + RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId); + if (panel != NULL) + { + res = panel->mChiclet; + } + + return res; +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, + const std::string& name, const LLUUID& otherParticipantId) +{ + RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); + if (mMessageList->addItem(item, sessionId)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } + else + { + llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId + << ", name: " << name + << ", other participant ID: " << otherParticipantId + << llendl; + + item->die(); + } +} + +//--------------------------------------------------------------------------------- +void LLIMWellWindow::delIMRow(const LLUUID& sessionId) +{ + //fix for EXT-3252 + //without this line LLIMWellWindow receive onFocusLost + //and hide itself. It was becaue somehow LLIMChicklet was in focus group for + //LLIMWellWindow... + //But I didn't find why this happen.. + gFocusMgr.clearLastFocusForGroup(this); + + if (mMessageList->removeItemByValue(sessionId)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } + else + { + llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId + << llendl; + } + + // remove all toasts that belong to this session from a screen + if(mChannel) + mChannel->removeToastsBySessionID(sessionId); + + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } + else + { + setFocus(true); + } +} + +void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_message/* = false*/) +{ + if (mMessageList->getItemByValue(notification_id) == NULL) + { + ObjectRowPanel* item = new ObjectRowPanel(notification_id, new_message); + if (mMessageList->addItem(item, notification_id)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } + else + { + llwarns << "Unable to add Object Row into the list, notificationID: " << notification_id << llendl; + item->die(); + } + reshapeWindow(); + } +} + +void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id) +{ + if (mMessageList->removeItemByValue(notification_id)) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } + else + { + llwarns << "Unable to remove Object Row from the list, notificationID: " << notification_id << llendl; + } + + reshapeWindow(); + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } +} + + +void LLIMWellWindow::addIMRow(const LLUUID& session_id) +{ + if (hasIMRow(session_id)) return; + + LLIMModel* im_model = LLIMModel::getInstance(); + addIMRow(session_id, 0, im_model->getName(session_id), im_model->getOtherParticipantID(session_id)); + reshapeWindow(); +} + +bool LLIMWellWindow::hasIMRow(const LLUUID& session_id) +{ + return mMessageList->getItemByValue(session_id); +} + +void LLIMWellWindow::closeAll() +{ + // Generate an ignorable alert dialog if there is an active voice IM sesion + bool need_confirmation = false; + const LLIMModel& im_model = LLIMModel::instance(); + std::vector<LLSD> values; + mMessageList->getValues(values); + for (std::vector<LLSD>::iterator + iter = values.begin(), + iter_end = values.end(); + iter != iter_end; ++iter) + { + LLIMSpeakerMgr* speaker_mgr = im_model.getSpeakerManager(*iter); + if (speaker_mgr && speaker_mgr->isVoiceActive()) + { + need_confirmation = true; + break; + } + } + if ( need_confirmation ) + { + //Bring up a confirmation dialog + LLNotificationsUtil::add + ("ConfirmCloseAll", LLSD(), LLSD(), + boost::bind(&LLIMWellWindow::confirmCloseAll, this, _1, _2)); + } + else + { + closeAllImpl(); + } +} + +void LLIMWellWindow::closeAllImpl() +{ + std::vector<LLSD> values; + mMessageList->getValues(values); + + for (std::vector<LLSD>::iterator + iter = values.begin(), + iter_end = values.end(); + iter != iter_end; ++iter) + { + LLPanel* panel = mMessageList->getItemByValue(*iter); + + RowPanel* im_panel = dynamic_cast <RowPanel*> (panel); + if (im_panel) + { + gIMMgr->leaveSession(*iter); + continue; + } + + ObjectRowPanel* obj_panel = dynamic_cast <ObjectRowPanel*> (panel); + if (obj_panel) + { + LLScriptFloaterManager::instance().removeNotification(*iter); + } + } +} + +bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) + { + case 0: + { + closeAllImpl(); + return true; + } + default: + break; + } + return false; +} + +// EOF |