diff options
Diffstat (limited to 'indra/newview/llsyswellwindow.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/llsyswellwindow.cpp | 734 |
1 files changed, 391 insertions, 343 deletions
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 6714fe908f..8babb874f8 100644..100755 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -1,61 +1,52 @@ /** * @file llsyswellwindow.cpp * @brief // TODO - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * 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 + * 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. * - * 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 + * 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. * - * 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. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - #include "llviewerprecompiledheaders.h" // must be first include - -#include "llflatlistview.h" - #include "llsyswellwindow.h" -#include "llbottomtray.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" - #include "llchiclet.h" -#include "lltoastpanel.h" +#include "llchicletbar.h" +#include "llflatlistview.h" +#include "llfloaterreg.h" #include "llnotificationmanager.h" - +#include "llnotificationsutil.h" +#include "llscriptfloater.h" +#include "llspeakers.h" +#include "lltoastpanel.h" //--------------------------------------------------------------------------------- -LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key), +LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key), mChannel(NULL), mMessageList(NULL), - mSeparator(NULL) -{ - LLIMMgr::getInstance()->addSessionObserver(this); - LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLSysWellWindow::findIMChiclet, this, _1)); + mSysWellChiclet(NULL), + NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"), + IM_WELL_ANCHOR_NAME("im_well_panel"), + mIsReshapedByUser(false) - mTypedItemsCount[IT_NOTIFICATION] = 0; - mTypedItemsCount[IT_INSTANT_MESSAGE] = 0; +{ + setOverlapsScreenChannel(true); } //--------------------------------------------------------------------------------- @@ -63,106 +54,44 @@ BOOL LLSysWellWindow::postBuild() { mMessageList = getChild<LLFlatListView>("notification_list"); - // init connections to the list's update events - connectListUpdaterToSignal("notify"); - connectListUpdaterToSignal("groupnotify"); - // get a corresponding channel initChannel(); - LLPanel::Params params; - mSeparator = LLUICtrlFactory::create<LLPanel>(params); - LLUICtrlFactory::instance().buildPanel(mSeparator, "panel_separator.xml"); - - LLRect rc = mSeparator->getRect(); - rc.setOriginAndSize(0, 0, mMessageList->getItemsRect().getWidth(), rc.getHeight()); - mSeparator->setRect(rc); - mSeparator->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); - mSeparator->setVisible(FALSE); - - mMessageList->addItem(mSeparator); - - return LLDockableFloater::postBuild(); + return LLTransientDockableFloater::postBuild(); } //--------------------------------------------------------------------------------- void LLSysWellWindow::setMinimized(BOOL minimize) { - // we don't show empty Message Well window - if (!minimize) - { - setVisible(!isWindowEmpty()); - } - - LLDockableFloater::setMinimized(minimize); -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::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(&LLSysWellWindow::removeItemByID, this, _1)); - } - else - { - llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; - } + LLTransientDockableFloater::setMinimized(minimize); } //--------------------------------------------------------------------------------- -void LLSysWellWindow::onChicletClick() +void LLSysWellWindow::handleReshape(const LLRect& rect, bool by_user) { - // 1 - remove StartUp toast and channel if present - if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) - { - LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); - } - - // 2 - toggle instance of SysWell's chiclet-window - toggleWindow(); + mIsReshapedByUser |= by_user; // mark floater that it is reshaped by user + LLTransientDockableFloater::handleReshape(rect, by_user); } //--------------------------------------------------------------------------------- -LLSysWellWindow::~LLSysWellWindow() +void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask) { - LLIMMgr::getInstance()->removeSessionObserver(this); + // just set floater visible. Screen channels will be cleared. + setVisible(TRUE); } -//--------------------------------------------------------------------------------- -void LLSysWellWindow::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)) +void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) +{ + mSysWellChiclet = chiclet; + if(NULL != mSysWellChiclet) { - handleItemAdded(IT_NOTIFICATION); - - reshapeWindow(); - - new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); - new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); - } - else - { - llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id - << ", title: " << p.title - << llendl; - - new_item->die(); + mSysWellChiclet->updateWidget(isWindowEmpty()); } } //--------------------------------------------------------------------------------- -void LLSysWellWindow::clear() +LLSysWellWindow::~LLSysWellWindow() { - mMessageList->clear(); } //--------------------------------------------------------------------------------- @@ -170,13 +99,16 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) { if(mMessageList->removeItemByValue(id)) { - handleItemRemoved(IT_NOTIFICATION); + if (NULL != mSysWellChiclet) + { + mSysWellChiclet->updateWidget(isWindowEmpty()); + } reshapeWindow(); } else { - llwarns << "Unable to remove notification from the list, ID: " << id - << llendl; + LL_WARNS() << "Unable to remove notification from the list, ID: " << id + << LL_ENDL; } // hide chiclet window if there are no items left @@ -186,117 +118,61 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) } } -//--------------------------------------------------------------------------------- -void LLSysWellWindow::onItemClick(LLSysWellItem* item) + LLPanel * LLSysWellWindow::findItemByID(const LLUUID& id) { - LLUUID id = item->getID(); - if(mChannel) - mChannel->loadStoredToastByNotificationIDToChannel(id); + return mMessageList->getItemByValue(id); } //--------------------------------------------------------------------------------- -void LLSysWellWindow::onItemClose(LLSysWellItem* item) -{ - LLUUID id = item->getID(); - removeItemByID(id); - if(mChannel) - mChannel->killToastByNotificationID(id); -} - -//-------------------------------------------------------------------------- -void LLSysWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) -{ - LLSysWellItem::Params p; - p.notification_id = id; - p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); - addItem(p); -} - //--------------------------------------------------------------------------------- void LLSysWellWindow::initChannel() { LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); - if(mChannel) - { - mChannel->setOnStoreToastCallback(boost::bind(&LLSysWellWindow::onStoreToast, this, _1, _2)); - } - else - { - llwarns << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << llendl; - } -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::getAllowedRect(LLRect& rect) -{ - rect = gViewerWindow->getWorldViewRect(); -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::toggleWindow() -{ - if (getDockControl() == NULL) - { - setDockControl(new LLDockControl( - LLBottomTray::getInstance()->getSysWell(), this, - getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1))); - } - - if(!getVisible() || isMinimized()) - { - if(isWindowEmpty()) - { - return; - } - - setVisible(TRUE); - } - else if (isDocked()) + if(NULL == mChannel) { - setVisible(FALSE); + LL_WARNS() << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << LL_ENDL; } - //set window in foreground - setFocus(getVisible()); } //--------------------------------------------------------------------------------- void LLSysWellWindow::setVisible(BOOL visible) { - if(visible) - { - if (LLBottomTray::instanceExists()) - { - LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE); - } - } - else + if (visible) { - if (LLBottomTray::instanceExists()) + if (NULL == getDockControl() && getDockTongue().notNull()) { - LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE); + setDockControl(new LLDockControl( + LLChicletBar::getInstance()->getChild<LLView>(getAnchorViewName()), this, + getDockTongue(), LLDockControl::BOTTOM)); } } - LLDockableFloater::setVisible(visible); + // do not show empty window + if (NULL == mMessageList || isWindowEmpty()) visible = FALSE; + + LLTransientDockableFloater::setVisible(visible); // update notification channel state + initChannel(); // make sure the channel still exists if(mChannel) { mChannel->updateShowToastsState(); + mChannel->redrawToasts(); } } //--------------------------------------------------------------------------------- void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock) { - LLDockableFloater::setDocked(docked, pop_on_undock); + LLTransientDockableFloater::setDocked(docked, pop_on_undock); // update notification channel state if(mChannel) { mChannel->updateShowToastsState(); + mChannel->redrawToasts(); } } @@ -307,20 +183,24 @@ void LLSysWellWindow::reshapeWindow() // 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(); - S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth(); + 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(); + LLRect curRect = getRect(); - S32 new_window_height = notif_list_height + parent_list_delta_height; + S32 new_window_height = notif_list_height + parent_list_delta_height; - if (new_window_height > MAX_WINDOW_HEIGHT) - { - new_window_height = MAX_WINDOW_HEIGHT; + if (new_window_height > MAX_WINDOW_HEIGHT) + { + new_window_height = MAX_WINDOW_HEIGHT; + } + S32 newWidth = curRect.getWidth() < MIN_WINDOW_WIDTH ? MIN_WINDOW_WIDTH : curRect.getWidth(); + + curRect.setLeftTopAndSize(curRect.mLeft, curRect.mTop, newWidth, new_window_height); + reshape(curRect.getWidth(), curRect.getHeight(), TRUE); + setRect(curRect); } - S32 newY = curRect.mTop + new_window_height - curRect.getHeight(); - curRect.setLeftTopAndSize(curRect.mLeft, newY, MIN_WINDOW_WIDTH, 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 @@ -331,224 +211,392 @@ void LLSysWellWindow::reshapeWindow() } //--------------------------------------------------------------------------------- -LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId) +bool LLSysWellWindow::isWindowEmpty() { - LLChiclet* res = NULL; - RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId); - if (panel != NULL) - { - res = panel->mChiclet; - } + return mMessageList->size() == 0; +} - return res; +/************************************************************************/ +/* ObjectRowPanel implementation */ +/************************************************************************/ + +LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& notification_id, bool new_message/* = false*/) + : LLPanel() + , mChiclet(NULL) +{ + buildFromFile( "panel_active_object_row.xml"); + + 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)); } //--------------------------------------------------------------------------------- -void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, - const std::string& name, const LLUUID& otherParticipantId) +LLIMWellWindow::ObjectRowPanel::~ObjectRowPanel() { - RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); - if (mMessageList->insertItemAfter(mSeparator, item, sessionId)) - { - handleItemAdded(IT_INSTANT_MESSAGE); - } - else - { - llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId - << ", name: " << name - << ", other participant ID: " << otherParticipantId - << llendl; - - item->die(); - } } //--------------------------------------------------------------------------------- -void LLSysWellWindow::delIMRow(const LLUUID& sessionId) +void LLIMWellWindow::ObjectRowPanel::onClosePanel() { - if (mMessageList->removeItemByValue(sessionId)) - { - handleItemRemoved(IT_INSTANT_MESSAGE); - } - else + 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)) { - llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId - << llendl; + case LLScriptFloaterManager::OBJ_GIVE_INVENTORY: + mChiclet = getChild<LLInvOfferChiclet>("inv_offer_chiclet"); + break; + default: + mChiclet = getChild<LLScriptChiclet>("object_chiclet"); + break; } - // remove all toasts that belong to this session from a screen - if(mChannel) - mChannel->removeToastsBySessionID(sessionId); + mChiclet->setVisible(true); + mChiclet->setSessionId(notification_id); +} - // hide chiclet window if there are no items left - if(isWindowEmpty()) - { - setVisible(FALSE); - } +//--------------------------------------------------------------------------------- +void LLIMWellWindow::ObjectRowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +{ + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); } //--------------------------------------------------------------------------------- -bool LLSysWellWindow::isWindowEmpty() +void LLIMWellWindow::ObjectRowPanel::onMouseLeave(S32 x, S32 y, MASK mask) { - // keep in mind, mSeparator is always in the list - return mMessageList->size() == 1; + setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); } //--------------------------------------------------------------------------------- -//virtual -void LLSysWellWindow::sessionAdded(const LLUUID& session_id, - const std::string& name, const LLUUID& other_participant_id) +// virtual +BOOL LLIMWellWindow::ObjectRowPanel::handleMouseDown(S32 x, S32 y, MASK mask) { - //*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB) - if (mMessageList->getItemByValue(session_id) == NULL) + // 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() { - S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id); - if (chicletCounter > -1) - { - addIMRow(session_id, chicletCounter, name, other_participant_id); - reshapeWindow(); - } + mChiclet->onMouseDown(); + return TRUE; } + + return LLPanel::handleMouseDown(x, y, mask); } -//--------------------------------------------------------------------------------- -//virtual -void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) +// virtual +BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) { - delIMRow(sessionId); - reshapeWindow(); - LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); + return mChiclet->handleRightMouseDown(x, y, mask); +} + +/************************************************************************/ +/* LLNotificationWellWindow implementation */ +/************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) +: LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), + mWellWindow(well_window) +{ + connectToChannel("Notifications"); + connectToChannel("Group Notifications"); + connectToChannel("Offer"); +} + +LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) +: LLSysWellWindow(key) +{ + mNotificationUpdates.reset(new WellNotificationChannel(this)); +} + +// 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; } -void LLSysWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +// virtual +void LLNotificationWellWindow::setVisible(BOOL visible) { - //for outgoing ad-hoc and group im sessions only - LLChiclet* chiclet = findIMChiclet(old_session_id); - if (chiclet) + if (visible) { - chiclet->setSessionId(new_session_id); - mMessageList->updateValue(old_session_id, new_session_id); + // when Notification channel is cleared, storable toasts will be added into the list. + clearScreenChannels(); } + + LLSysWellWindow::setVisible(visible); } -void LLSysWellWindow::handleItemAdded(EItemType added_item_type) +//--------------------------------------------------------------------------------- +void LLNotificationWellWindow::addItem(LLSysWellItem::Params p) { - bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type); + LLSD value = p.notification_id; + // do not add clones + if( mMessageList->getItemByValue(value)) + return; - if (should_be_shown && !mSeparator->getVisible()) + 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 { - mSeparator->setVisible(TRUE); + LL_WARNS() << "Unable to add Notification into the list, notification ID: " << p.notification_id + << ", title: " << p.title + << LL_ENDL; - // refresh list to recalculate mSeparator position - mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight()); + new_item->die(); } } -void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type) +void LLNotificationWellWindow::closeAll() { - bool should_be_hidden = --mTypedItemsCount[removed_item_type] == 0; - - if (should_be_hidden && mSeparator->getVisible()) + // 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) { - mSeparator->setVisible(FALSE); + LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter); + if (sys_well_item) + onItemClose(sys_well_item); + } +} - // refresh list to recalculate mSeparator position - mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight()); +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +void LLNotificationWellWindow::initChannel() +{ + LLSysWellWindow::initChannel(); + if(mChannel) + { + mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); } } -bool LLSysWellWindow::anotherTypeExists(EItemType item_type) +void LLNotificationWellWindow::clearScreenChannels() { - bool exists = false; - switch(item_type) + // 1 - remove StartUp toast and channel if present + if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) { - case IT_INSTANT_MESSAGE: - if (mTypedItemsCount[IT_NOTIFICATION] > 0) - { - exists = true; - } - break; - case IT_NOTIFICATION: - if (mTypedItemsCount[IT_INSTANT_MESSAGE] > 0) - { - exists = true; - } - break; + LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); + } + + // 2 - remove toasts in Notification channel + if(mChannel) + { + mChannel->removeAndStoreAllStorableToasts(); } - return exists; } -//--------------------------------------------------------------------------------- -LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, - S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : - LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) +void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL); + LLSysWellItem::Params p; + p.notification_id = id; + p.title = static_cast<LLToastPanel*>(info_panel)->getTitle(); + addItem(p); +} - // Choose which of the pre-created chiclets (IM/group) to use. - // The other one gets hidden. +void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) +{ + LLUUID id = item->getID(); + LLFloaterReg::showInstance("inspect_toast", id); +} - LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId); - switch (im_chiclet_type) +void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) +{ + LLUUID id = item->getID(); + + if(mChannel) { - case LLIMChiclet::TYPE_GROUP: - case LLIMChiclet::TYPE_AD_HOC: - mChiclet = getChild<LLIMChiclet>("group_chiclet"); - childSetVisible("p2p_chiclet", false); - break; - case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway - case LLIMChiclet::TYPE_IM: - mChiclet = getChild<LLIMChiclet>("p2p_chiclet"); - childSetVisible("group_chiclet", false); - break; + // removeItemByID() is invoked from killToastByNotificationID() and item will removed; + mChannel->killToastByNotificationID(id); } + else + { + // removeItemByID() should be called one time for each item to remove it from notification well + removeItemByID(id); + } + +} + +void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) +{ + removeItemByID(notify->getID()); +} - // Initialize chiclet. - mChiclet->setCounter(chicletCounter); - mChiclet->setSessionId(sessionId); - mChiclet->setIMSessionName(name); - mChiclet->setOtherParticipantId(otherParticipantId); +/************************************************************************/ +/* LLIMWellWindow implementation */ +/************************************************************************/ - LLTextBox* contactName = getChild<LLTextBox>("contact_name"); - contactName->setValue(name); +////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS +LLIMWellWindow::LLIMWellWindow(const LLSD& key) +: LLSysWellWindow(key) +{ +} - mCloseBtn = getChild<LLButton>("hide_btn"); - mCloseBtn->setCommitCallback(boost::bind(&LLSysWellWindow::RowPanel::onClosePanel, this)); +LLIMWellWindow::~LLIMWellWindow() +{ } -//--------------------------------------------------------------------------------- -LLSysWellWindow::RowPanel::~RowPanel() +// static +LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/) { + return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key); } -//--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::onClosePanel() + +// static +LLIMWellWindow* LLIMWellWindow::findInstance(const LLSD& key /*= LLSD()*/) { - gIMMgr->removeSession(mChiclet->getSessionId()); - // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved(). + return LLFloaterReg::findTypedInstance<LLIMWellWindow>("im_well_window", key); } -//--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask) +BOOL LLIMWellWindow::postBuild() { - setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); + BOOL rv = LLSysWellWindow::postBuild(); + setTitle(getString("title_im_well_window")); + + LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1)); + + return rv; } -//--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask) +LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id) { - setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); + if (!mMessageList) return NULL; + + LLChiclet* res = NULL; + ObjectRowPanel* panel = mMessageList->getTypedItemByValue<ObjectRowPanel>(notification_id); + if (panel != NULL) + { + res = panel->mChiclet; + } + + return res; } -//--------------------------------------------------------------------------------- -// virtual -BOOL LLSysWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS + +void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_message/* = false*/) { - // 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(); + if (mMessageList->getItemByValue(notification_id) == NULL) + { + ObjectRowPanel* item = new ObjectRowPanel(notification_id, new_message); + if (!mMessageList->addItem(item, notification_id)) + { + LL_WARNS() << "Unable to add Object Row into the list, notificationID: " << notification_id << LL_ENDL; + item->die(); + } + reshapeWindow(); + } +} - return LLPanel::handleMouseDown(x, y, mask); +void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id) +{ + if (!mMessageList->removeItemByValue(notification_id)) + { + LL_WARNS() << "Unable to remove Object Row from the list, notificationID: " << notification_id << LL_ENDL; + } + + reshapeWindow(); + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } +} + +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); + + ObjectRowPanel* obj_panel = dynamic_cast <ObjectRowPanel*> (panel); + if (obj_panel) + { + LLScriptFloaterManager::instance().removeNotification(*iter); + } + } } -// EOF +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; +} + + |