/** * @file llsyswellwindow.cpp * @brief // TODO * $LicenseInfo:firstyear=2000&license=viewergpl$ * * Copyright (c) 2000-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" // must be first include #include "llsyswellwindow.h" #include "llbottomtray.h" #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llchiclet.h" //--------------------------------------------------------------------------------- LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key), mChannel(NULL), mScrollContainer(NULL), mNotificationList(NULL) { LLIMMgr::getInstance()->addSessionObserver(this); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLSysWellWindow::findIMChiclet, this, _1)); } //--------------------------------------------------------------------------------- BOOL LLSysWellWindow::postBuild() { mScrollContainer = getChild("notification_list_container"); mTwinListPanel = getChild("twin_list_panel"); mNotificationList = getChild("notification_list"); mIMRowList = getChild("im_row_panel_list"); mScrollContainer->setBorderVisible(FALSE); return LLDockableFloater::postBuild(); } //--------------------------------------------------------------------------------- LLSysWellWindow::~LLSysWellWindow() { LLIMMgr::getInstance()->removeSessionObserver(this); } //--------------------------------------------------------------------------------- void LLSysWellWindow::addItem(LLSysWellItem::Params p) { // do not add clones if( findItemByID(p.notification_id) >= 0 ) return; LLSysWellItem* new_item = new LLSysWellItem(p); mNotificationList->addPanel(dynamic_cast(new_item)); reshapeWindow(); new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); } //--------------------------------------------------------------------------------- void LLSysWellWindow::clear() { // *TODO: fill later } //--------------------------------------------------------------------------------- S32 LLSysWellWindow::findItemByID(const LLUUID& id) { const LLScrollingPanelList::panel_list_t list = mNotificationList->getPanelList(); if(list.size() == 0) return -1; LLScrollingPanelList::panel_list_t::const_iterator it; S32 index = 0; for(it = list.begin(); it != list.end(); ++it, ++index) { if( dynamic_cast(*it)->getID() == id ) break; } if(it == list.end()) return -1; else return index; } //--------------------------------------------------------------------------------- void LLSysWellWindow::removeItemByID(const LLUUID& id) { S32 index = findItemByID(id); if(index >= 0) mNotificationList->removePanel(index); else return; reshapeWindow(); } //--------------------------------------------------------------------------------- void LLSysWellWindow::onItemClick(LLSysWellItem* item) { LLUUID id = item->getID(); if(mChannel) mChannel->loadStoredToastByIDToChannel(id); } //--------------------------------------------------------------------------------- void LLSysWellWindow::onItemClose(LLSysWellItem* item) { LLUUID id = item->getID(); removeItemByID(id); if(mChannel) mChannel->killToastByNotificationID(id); // hide chiclet window if there are no items left setVisible(!isWindowEmpty()); } //--------------------------------------------------------------------------------- void LLSysWellWindow::toggleWindow() { if (getDockControl() == NULL) { setDockControl(new LLDockControl( LLBottomTray::getInstance()->getSysWell(), this, getDockTongue(), LLDockControl::TOP, isDocked())); } setVisible(!getVisible()); } //--------------------------------------------------------------------------------- void LLSysWellWindow::setVisible(BOOL visible) { // on Show adjust position of SysWell chiclet's window if(visible) { if (LLBottomTray::instanceExists()) { LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE); } if(mChannel) mChannel->removeAndStoreAllVisibleToasts(); } else { if (LLBottomTray::instanceExists()) { LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE); } } if(mChannel) mChannel->setShowToasts(!visible); LLFloater::setVisible(visible); } //--------------------------------------------------------------------------------- void LLSysWellWindow::reshapeWindow() { // Get size for scrollbar and floater's header const LLUICachedControl SCROLLBAR_SIZE("UIScrollbarSize", 0); const LLUICachedControl HEADER_SIZE("UIFloaterHeaderSize", 0); LLRect notif_list_rect = mNotificationList->getRect(); LLRect im_list_rect = mIMRowList->getRect(); LLRect panel_rect = mTwinListPanel->getRect(); S32 notif_list_height = notif_list_rect.getHeight(); S32 im_list_height = im_list_rect.getHeight(); S32 new_panel_height = notif_list_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + im_list_height; S32 new_window_height = new_panel_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + HEADER_SIZE; U32 twinListWidth = 0; if (new_window_height > MAX_WINDOW_HEIGHT) { twinListWidth = MIN_PANELLIST_WIDTH - SCROLLBAR_SIZE; new_window_height = MAX_WINDOW_HEIGHT; } else { twinListWidth = MIN_PANELLIST_WIDTH; } reshape(MIN_WINDOW_WIDTH, new_window_height, FALSE); mTwinListPanel->reshape(twinListWidth, new_panel_height, TRUE); mNotificationList->reshape(twinListWidth, notif_list_height, TRUE); mIMRowList->reshape(twinListWidth, im_list_height, TRUE); // arrange panel and lists // move panel panel_rect.setLeftTopAndSize(1, new_panel_height, twinListWidth, new_panel_height); mTwinListPanel->setRect(panel_rect); // move notif list panel notif_list_rect.setLeftTopAndSize(notif_list_rect.mLeft, new_panel_height, twinListWidth, notif_list_height); mNotificationList->setRect(notif_list_rect); // move IM list panel im_list_rect.setLeftTopAndSize(im_list_rect.mLeft, notif_list_rect.mBottom - LLScrollingPanelList::GAP_BETWEEN_PANELS, twinListWidth, im_list_height); mIMRowList->setRect(im_list_rect); mNotificationList->updatePanels(TRUE); mIMRowList->updatePanels(TRUE); } //--------------------------------------------------------------------------------- LLSysWellWindow::RowPanel * LLSysWellWindow::findIMRow(const LLUUID& sessionId) { RowPanel * res = NULL; const LLScrollingPanelList::panel_list_t &list = mIMRowList->getPanelList(); if (!list.empty()) { for (LLScrollingPanelList::panel_list_t::const_iterator iter = list.begin(); iter != list.end(); ++iter) { RowPanel *panel = static_cast (*iter); if (panel->mChiclet->getSessionId() == sessionId) { res = panel; break; } } } return res; } //--------------------------------------------------------------------------------- LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId) { LLChiclet* res = NULL; RowPanel* panel = findIMRow(sessionId); if (panel != NULL) { res = panel->mChiclet; } return res; } //--------------------------------------------------------------------------------- void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) { mIMRowList->addPanel(new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId)); } //--------------------------------------------------------------------------------- void LLSysWellWindow::delIMRow(const LLUUID& sessionId) { RowPanel *panel = findIMRow(sessionId); if (panel != NULL) { mIMRowList->removePanel(panel); } // hide chiclet window if there are no items left setVisible(!isWindowEmpty()); } //--------------------------------------------------------------------------------- bool LLSysWellWindow::isWindowEmpty() { if(mIMRowList->getPanelList().size() == 0 && LLBottomTray::getInstance()->getSysWell()->getCounter() == 0) { return true; } else { return false; } } //--------------------------------------------------------------------------------- //virtual void LLSysWellWindow::sessionAdded(const LLUUID& sessionId, const std::string& name, const LLUUID& otherParticipantId) { if (findIMRow(sessionId) == NULL) { S32 chicletCounter = 0; LLIMModel::LLIMSession* session = get_if_there(LLIMModel::sSessionsMap, sessionId, (LLIMModel::LLIMSession*) NULL); if (session != NULL) { chicletCounter = session->mNumUnread; } addIMRow(sessionId, chicletCounter, name, otherParticipantId); reshapeWindow(); } } //--------------------------------------------------------------------------------- //virtual void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) { delIMRow(sessionId); reshapeWindow(); LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); } //--------------------------------------------------------------------------------- LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : LLScrollingPanel(LLPanel::Params()), mParent(parent) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL); mChiclet = getChild("chiclet"); mChiclet->setCounter(chicletCounter); mChiclet->setSessionId(sessionId); mChiclet->setIMSessionName(name); mChiclet->setOtherParticipantId(otherParticipantId); LLTextBox* contactName = getChild("contact_name"); contactName->setValue(name); mCloseBtn = getChild("hide_btn"); mCloseBtn->setCommitCallback(boost::bind(&LLSysWellWindow::RowPanel::onClose, this)); } //--------------------------------------------------------------------------------- LLSysWellWindow::RowPanel::~RowPanel() { } //--------------------------------------------------------------------------------- void LLSysWellWindow::RowPanel::onClose() { mParent->mIMRowList->removePanel(this); gIMMgr->removeSession(mChiclet->getSessionId()); } //--------------------------------------------------------------------------------- void LLSysWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask) { setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected")); } //--------------------------------------------------------------------------------- void LLSysWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask) { setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected")); } //--------------------------------------------------------------------------------- // virtual BOOL LLSysWellWindow::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 LLPanel::handleMouseDown(x, y, mask); } //--------------------------------------------------------------------------------- void LLSysWellWindow::RowPanel::updatePanel(BOOL allow_modify) { S32 parent_width = getParent()->getRect().getWidth(); S32 panel_height = getRect().getHeight(); reshape(parent_width, panel_height, TRUE); } //---------------------------------------------------------------------------------