diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
---|---|---|
committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llchiclet.cpp | |
parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (diff) |
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts:
# autobuild.xml
# indra/cmake/CMakeLists.txt
# indra/cmake/GoogleMock.cmake
# indra/llaudio/llaudioengine_fmodstudio.cpp
# indra/llaudio/llaudioengine_fmodstudio.h
# indra/llaudio/lllistener_fmodstudio.cpp
# indra/llaudio/lllistener_fmodstudio.h
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/llaudio/llstreamingaudio_fmodstudio.h
# indra/llcharacter/llmultigesture.cpp
# indra/llcharacter/llmultigesture.h
# indra/llimage/llimage.cpp
# indra/llimage/llimagepng.cpp
# indra/llimage/llimageworker.cpp
# indra/llimage/tests/llimageworker_test.cpp
# indra/llmessage/tests/llmockhttpclient.h
# indra/llprimitive/llgltfmaterial.h
# indra/llrender/llfontfreetype.cpp
# indra/llui/llcombobox.cpp
# indra/llui/llfolderview.cpp
# indra/llui/llfolderviewmodel.h
# indra/llui/lllineeditor.cpp
# indra/llui/lllineeditor.h
# indra/llui/lltextbase.cpp
# indra/llui/lltextbase.h
# indra/llui/lltexteditor.cpp
# indra/llui/lltextvalidate.cpp
# indra/llui/lltextvalidate.h
# indra/llui/lluictrl.h
# indra/llui/llview.cpp
# indra/llwindow/llwindowmacosx.cpp
# indra/newview/app_settings/settings.xml
# indra/newview/llappearancemgr.cpp
# indra/newview/llappearancemgr.h
# indra/newview/llavatarpropertiesprocessor.cpp
# indra/newview/llavatarpropertiesprocessor.h
# indra/newview/llbreadcrumbview.cpp
# indra/newview/llbreadcrumbview.h
# indra/newview/llbreastmotion.cpp
# indra/newview/llbreastmotion.h
# indra/newview/llconversationmodel.h
# indra/newview/lldensityctrl.cpp
# indra/newview/lldensityctrl.h
# indra/newview/llface.inl
# indra/newview/llfloatereditsky.cpp
# indra/newview/llfloatereditwater.cpp
# indra/newview/llfloateremojipicker.h
# indra/newview/llfloaterimsessiontab.cpp
# indra/newview/llfloaterprofiletexture.cpp
# indra/newview/llfloaterprofiletexture.h
# indra/newview/llgesturemgr.cpp
# indra/newview/llgesturemgr.h
# indra/newview/llimpanel.cpp
# indra/newview/llimpanel.h
# indra/newview/llinventorybridge.cpp
# indra/newview/llinventorybridge.h
# indra/newview/llinventoryclipboard.cpp
# indra/newview/llinventoryclipboard.h
# indra/newview/llinventoryfunctions.cpp
# indra/newview/llinventoryfunctions.h
# indra/newview/llinventorygallery.cpp
# indra/newview/lllistbrowser.cpp
# indra/newview/lllistbrowser.h
# indra/newview/llpanelobjectinventory.cpp
# indra/newview/llpanelprofile.cpp
# indra/newview/llpanelprofile.h
# indra/newview/llpreviewgesture.cpp
# indra/newview/llsavedsettingsglue.cpp
# indra/newview/llsavedsettingsglue.h
# indra/newview/lltooldraganddrop.cpp
# indra/newview/llurllineeditorctrl.cpp
# indra/newview/llvectorperfoptions.cpp
# indra/newview/llvectorperfoptions.h
# indra/newview/llviewerparceloverlay.cpp
# indra/newview/llviewertexlayer.cpp
# indra/newview/llviewertexturelist.cpp
# indra/newview/macmain.h
# indra/test/test.cpp
Diffstat (limited to 'indra/newview/llchiclet.cpp')
-rw-r--r-- | indra/newview/llchiclet.cpp | 2458 |
1 files changed, 1229 insertions, 1229 deletions
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index ad542e84cc..dcbdf6d8de 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1,1229 +1,1229 @@ -/** - * @file llchiclet.cpp - * @brief LLChiclet class implementation - * - * $LicenseInfo:firstyear=2002&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 "llchiclet.h" - -#include "llchicletbar.h" -#include "llfloaterimsession.h" -#include "llfloaterimcontainer.h" -#include "llfloaterreg.h" -#include "lllocalcliprect.h" -#include "llscriptfloater.h" -#include "llsingleton.h" -#include "llsyswellwindow.h" -#include "llfloaternotificationstabbed.h" -#include "llviewermenu.h" - -static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); -static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); -static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script"); -static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); - -boost::signals2::signal<LLChiclet* (const LLUUID&), - LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > > - LLIMChiclet::sFindChicletsSignal; -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLSysWellChiclet::Params::Params() - : button("button") - , unread_notifications("unread_notifications") - , max_displayed_count("max_displayed_count", 99) -{ - button.name = "button"; - button.tab_stop = false; - button.label = LLStringUtil::null; -} - -LLSysWellChiclet::LLSysWellChiclet(const Params& p) - : LLChiclet(p) - , mButton(NULL) - , mCounter(0) - , mMaxDisplayedCount(p.max_displayed_count) - , mIsNewMessagesState(false) - , mFlashToLitTimer(NULL) -{ - LLButton::Params button_params = p.button; - mButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mButton); - - mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); -} - -LLSysWellChiclet::~LLSysWellChiclet() -{ - mFlashToLitTimer->unset(); - LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); - if (menu) - { - menu->die(); - mContextMenuHandle.markDead(); - } -} - -void LLSysWellChiclet::setCounter(S32 counter) -{ - // do nothing if the same counter is coming. EXT-3678. - if (counter == mCounter) return; - - // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter) - std::string s_count; - if(counter != 0) - { - static std::string more_messages_exist("+"); - std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : ""); - s_count = llformat("%d%s" - , llmin(counter, mMaxDisplayedCount) - , more_messages.c_str() - ); - } - - mButton->setLabel(s_count); - - mCounter = counter; -} - -boost::signals2::connection LLSysWellChiclet::setClickCallback( - const commit_callback_t& cb) -{ - return mButton->setClickedCallback(cb); -} - -void LLSysWellChiclet::setToggleState(bool toggled) { - mButton->setToggleState(toggled); -} - -void LLSysWellChiclet::changeLitState(bool blink) -{ - setNewMessagesState(!mIsNewMessagesState); -} - -void LLSysWellChiclet::setNewMessagesState(bool new_messages) -{ - /* - Emulate 4 states of button by background images, see detains in EXT-3147 - xml attribute Description - image_unselected "Unlit" - there are no new messages - image_selected "Unlit" + "Selected" - there are no new messages and the Well is open - image_pressed "Lit" - there are new messages - image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open - */ - mButton->setForcePressedState(new_messages); - - mIsNewMessagesState = new_messages; -} - -void LLSysWellChiclet::updateWidget(bool is_window_empty) -{ - mButton->setEnabled(!is_window_empty); - - if (LLChicletBar::instanceExists()) - { - LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty); - } -} -// virtual -bool LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - LLContextMenu* menu_avatar = mContextMenuHandle.get(); - if(!menu_avatar) - { - createMenu(); - menu_avatar = mContextMenuHandle.get(); - } - if (menu_avatar) - { - menu_avatar->show(x, y); - LLMenuGL::showPopup(this, menu_avatar, x, y); - } - return true; -} - -/************************************************************************/ -/* LLNotificationChiclet implementation */ -/************************************************************************/ -LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p), - mUreadSystemNotifications(0) -{ - mNotificationChannel.reset(new ChicletNotificationChannel(this)); - // ensure that notification well window exists, to synchronously - // handle toast add/delete events. - LLFloaterNotificationsTabbed::getInstance()->setSysWellChiclet(this); -} - -LLNotificationChiclet::~LLNotificationChiclet() -{ - mNotificationChannel.reset(); -} - -void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string action = user_data.asString(); - if("close all" == action) - { - LLFloaterNotificationsTabbed::getInstance()->closeAll(); - LLIMWellWindow::getInstance()->closeAll(); - } -} - -bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) -{ - std::string item = user_data.asString(); - if (item == "can close all") - { - return mUreadSystemNotifications != 0; - } - return true; -} - -void LLNotificationChiclet::createMenu() -{ - if(mContextMenuHandle.get()) - { - LL_WARNS() << "Menu already exists" << LL_ENDL; - return; - } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("NotificationWellChicletMenu.Action", - boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2)); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - enable_registrar.add("NotificationWellChicletMenu.EnableItem", - boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); - - llassert(LLMenuGL::sMenuContainer != NULL); - LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> - ("menu_notification_well_button.xml", - LLMenuGL::sMenuContainer, - LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mContextMenuHandle = menu->getHandle(); - } -} - -/*virtual*/ -void LLNotificationChiclet::setCounter(S32 counter) -{ - LLSysWellChiclet::setCounter(counter); - updateWidget(getCounter() == 0); - -} - -bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) -{ - bool displayNotification; - if ( (notification->getName() == "ScriptDialog") // special case for scripts - // if there is no toast window for the notification, filter it - //|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID())) - || (!LLFloaterNotificationsTabbed::getInstance()->findItemByID(notification->getID(), notification->getName())) - ) - { - displayNotification = false; - } - else if( !(notification->canLogToIM() && notification->hasFormElements()) - && (!notification->getPayload().has("give_inventory_notification") - || notification->getPayload()["give_inventory_notification"])) - { - displayNotification = true; - } - else - { - displayNotification = false; - } - return displayNotification; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChiclet::Params::Params() - : show_counter("show_counter", true) - , enable_counter("enable_counter", false) -{ -} - -LLChiclet::LLChiclet(const Params& p) -: LLUICtrl(p) -, mSessionId(LLUUID::null) -, mShowCounter(p.show_counter) -{ -} - -boost::signals2::connection LLChiclet::setLeftButtonClickCallback( - const commit_callback_t& cb) -{ - return setCommitCallback(cb); -} - -bool LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask) -{ - onCommit(); - childrenHandleMouseDown(x,y,mask); - return true; -} - -boost::signals2::connection LLChiclet::setChicletSizeChangedCallback( - const chiclet_size_changed_callback_t& cb) -{ - return mChicletSizeChangedSignal.connect(cb); -} - -void LLChiclet::onChicletSizeChanged() -{ - mChicletSizeChangedSignal(this, getValue()); -} - -LLSD LLChiclet::getValue() const -{ - return LLSD(getSessionId()); -} - -void LLChiclet::setValue(const LLSD& value) -{ - if(value.isUUID()) - { - setSessionId(value.asUUID()); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) -: LLChiclet(p) -, mShowSpeaker(false) -, mDefaultWidth(p.rect().getWidth()) -, mNewMessagesIcon(NULL) -, mChicletButton(NULL) -{ -} - -LLIMChiclet::~LLIMChiclet() -{ - auto menu = mPopupMenuHandle.get(); - if (menu) - { - menu->die(); - mPopupMenuHandle.markDead(); - } -} - -/* virtual*/ -bool LLIMChiclet::postBuild() -{ - mChicletButton = getChild<LLButton>("chiclet_button"); - mChicletButton->setCommitCallback(boost::bind(&LLIMChiclet::onMouseDown, this)); - mChicletButton->setDoubleClickCallback(boost::bind(&LLIMChiclet::onMouseDown, this)); - return true; -} - -void LLIMChiclet::enableCounterControl(bool enable) -{ - mCounterEnabled = enable; - if(!enable) - { - LLChiclet::setShowCounter(false); - } -} - -void LLIMChiclet::setRequiredWidth() -{ - S32 required_width = mDefaultWidth; - reshape(required_width, getRect().getHeight()); - onChicletSizeChanged(); -} - -void LLIMChiclet::setShowNewMessagesIcon(bool show) -{ - if(mNewMessagesIcon) - { - mNewMessagesIcon->setVisible(show); - } - setRequiredWidth(); -} - -bool LLIMChiclet::getShowNewMessagesIcon() -{ - return mNewMessagesIcon->getVisible(); -} - -void LLIMChiclet::onMouseDown() -{ - LLFloaterIMSession::toggle(getSessionId()); -} - -void LLIMChiclet::setToggleState(bool toggle) -{ - mChicletButton->setToggleState(toggle); -} - -bool LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); - if(!menu) - { - createPopupMenu(); - menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); - } - - if (menu) - { - updateMenuItems(); - menu->arrangeAndClear(); - LLMenuGL::showPopup(this, menu, x, y); - } - - return true; -} - -void LLIMChiclet::hidePopupMenu() -{ - auto menu = mPopupMenuHandle.get(); - if (menu) - { - menu->setVisible(false); - } -} - -bool LLIMChiclet::canCreateMenu() -{ - if(mPopupMenuHandle.get()) - { - LL_WARNS() << "Menu already exists" << LL_ENDL; - return false; - } - if(getSessionId().isNull()) - { - return false; - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChicletPanel::Params::Params() -: chiclet_padding("chiclet_padding") -, scrolling_offset("scrolling_offset") -, scroll_button_hpad("scroll_button_hpad") -, scroll_ratio("scroll_ratio") -, min_width("min_width") -{ -}; - -LLChicletPanel::LLChicletPanel(const Params&p) -: LLPanel(p) -, mScrollArea(NULL) -, mLeftScrollButton(NULL) -, mRightScrollButton(NULL) -, mChicletPadding(p.chiclet_padding) -, mScrollingOffset(p.scrolling_offset) -, mScrollButtonHPad(p.scroll_button_hpad) -, mScrollRatio(p.scroll_ratio) -, mMinWidth(p.min_width) -, mShowControls(true) -{ - LLPanel::Params panel_params; - panel_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT); - mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this); - - // important for Show/Hide Camera and Move controls menu in bottom tray to work properly - mScrollArea->setMouseOpaque(false); - - addChild(mScrollArea); -} - -LLChicletPanel::~LLChicletPanel() -{ - if(LLTransientFloaterMgr::instanceExists()) - { - LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton); - LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton); - } -} - -void LLChicletPanel::onMessageCountChanged(const LLSD& data) -{ - // *TODO : we either suppress this method or return a value. Right now, it servers no purpose. - /* - - //LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id); - //if (im_floater && im_floater->getVisible() && im_floater->hasFocus()) - //{ - // unread = 0; - //} - */ -} - -void LLChicletPanel::objectChicletCallback(const LLSD& data) -{ - LLUUID notification_id = data["notification_id"]; - bool new_message = data["new_message"]; - - std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(notification_id); - std::list<LLChiclet *>::iterator iter; - for (iter = chiclets.begin(); iter != chiclets.end(); iter++) - { - LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter); - if (chiclet != NULL) - { - chiclet->setShowNewMessagesIcon(new_message); - } - } -} - -bool LLChicletPanel::postBuild() -{ - LLPanel::postBuild(); - LLIMModel::instance().addNewMsgCallback(boost::bind(&LLChicletPanel::onMessageCountChanged, this, _1)); - LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLChicletPanel::onMessageCountChanged, this, _1)); - LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(&LLChicletPanel::objectChicletCallback, this, _1)); - LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(&LLChicletPanel::objectChicletCallback, this, _1)); - LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1)); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1)); - - mLeftScrollButton=getChild<LLButton>("chicklet_left_scroll_button"); - LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton); - mLeftScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this)); - mLeftScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onLeftScrollHeldDown,this)); - mLeftScrollButton->setEnabled(false); - - mRightScrollButton=getChild<LLButton>("chicklet_right_scroll_button"); - LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton); - mRightScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this)); - mRightScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onRightScrollHeldDown,this)); - mRightScrollButton->setEnabled(false); - - return true; -} - -void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) -{ - static LLUUID s_previous_active_voice_session_id; - - std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id); - - for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it) - { - LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); - if(chiclet) - { - if (gSavedSettings.getBOOL("OpenIMOnVoice")) - { - LLFloaterIMContainer::getInstance()->showConversation(session_id); - } - } - } - - s_previous_active_voice_session_id = session_id; -} - -bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) -{ - if(mScrollArea->addChild(chiclet)) - { - // chiclets should be aligned to right edge of scroll panel - S32 left_shift = 0; - - if (!canScrollLeft()) - { - // init left shift for the first chiclet in the list... - if (mChicletList.empty()) - { - // ...start from the right border of the scroll area for the first added chiclet - left_shift = mScrollArea->getRect().getWidth(); - } - else - { - // ... start from the left border of the first chiclet minus padding - left_shift = getChiclet(0)->getRect().mLeft - getChicletPadding(); - } - - // take into account width of the being added chiclet - left_shift -= chiclet->getRequiredRect().getWidth(); - - // if we overflow the scroll area we do not need to shift chiclets - if (left_shift < 0) - { - left_shift = 0; - } - } - - mChicletList.insert(mChicletList.begin() + index, chiclet); - - // shift first chiclet to place it in correct position. - // rest ones will be placed in arrange() - if (!canScrollLeft()) - { - getChiclet(0)->translate(left_shift - getChiclet(0)->getRect().mLeft, 0); - } - - chiclet->setLeftButtonClickCallback(boost::bind(&LLChicletPanel::onChicletClick, this, _1, _2)); - chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index)); - - arrange(); - LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet); - - return true; - } - - return false; -} - -void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) -{ - arrange(); -} - -void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) -{ - if (mCommitSignal) - { - (*mCommitSignal)(ctrl,param); - } -} - -void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it) -{ - LLChiclet* chiclet = *it; - mScrollArea->removeChild(chiclet); - mChicletList.erase(it); - - arrange(); - LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet); - chiclet->die(); -} - -void LLChicletPanel::removeChiclet(S32 index) -{ - if(index >= 0 && index < getChicletCount()) - { - removeChiclet(mChicletList.begin() + index); - } -} - -S32 LLChicletPanel::getChicletIndex(const LLChiclet* chiclet) -{ - if(mChicletList.empty()) - return -1; - - S32 size = getChicletCount(); - for(int n = 0; n < size; ++n) - { - if(chiclet == mChicletList[n]) - return n; - } - - return -1; -} - -void LLChicletPanel::removeChiclet(LLChiclet*chiclet) -{ - chiclet_list_t::iterator it = mChicletList.begin(); - for( ; mChicletList.end() != it; ++it) - { - LLChiclet* temp = *it; - if(temp == chiclet) - { - removeChiclet(it); - return; - } - } -} - -void LLChicletPanel::removeChiclet(const LLUUID& im_session_id) -{ - chiclet_list_t::iterator it = mChicletList.begin(); - for( ; mChicletList.end() != it; ++it) - { - LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); - - if(chiclet->getSessionId() == im_session_id) - { - removeChiclet(it); - return; - } - } -} - -void LLChicletPanel::removeAll() -{ - S32 size = getChicletCount(); - for(S32 n = 0; n < size; ++n) - { - mScrollArea->removeChild(mChicletList[n]); - } - - mChicletList.erase(mChicletList.begin(), mChicletList.end()); - - showScrollButtonsIfNeeded(); -} - -void LLChicletPanel::scrollToChiclet(const LLChiclet* chiclet) -{ - const LLRect& rect = chiclet->getRect(); - - if (rect.mLeft < 0) - { - scroll(llabs(rect.mLeft)); - showScrollButtonsIfNeeded(); - } - else - { - S32 scrollWidth = mScrollArea->getRect().getWidth(); - - if (rect.mRight > scrollWidth) - { - scroll(-llabs(rect.mRight - scrollWidth)); - showScrollButtonsIfNeeded(); - } - } -} - -void LLChicletPanel::reshape(S32 width, S32 height, bool called_from_parent ) -{ - LLPanel::reshape(width,height,called_from_parent); - - //Needed once- to avoid error at first call of reshape() before postBuild() - if(!mLeftScrollButton||!mRightScrollButton) - return; - - LLRect scroll_button_rect = mLeftScrollButton->getRect(); - mLeftScrollButton->setRect(LLRect(0,scroll_button_rect.mTop,scroll_button_rect.getWidth(), - scroll_button_rect.mBottom)); - scroll_button_rect = mRightScrollButton->getRect(); - mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop, - width, scroll_button_rect.mBottom)); - - - bool need_show_scroll = needShowScroll(); - if(need_show_scroll) - { - mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, - height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0)); - } - else - { - mScrollArea->setRect(LLRect(0,height, width, 0)); - } - - mShowControls = width >= mMinWidth; - - mScrollArea->setVisible(mShowControls); - - trimChiclets(); - showScrollButtonsIfNeeded(); - -} - -S32 LLChicletPanel::notifyParent(const LLSD& info) -{ - if(info.has("notification")) - { - std::string str_notification = info["notification"]; - if(str_notification == "size_changes") - { - arrange(); - return 1; - } - } - return LLPanel::notifyParent(info); -} - -void LLChicletPanel::setChicletToggleState(const LLUUID& session_id, bool toggle) -{ - if(session_id.isNull()) - { - LL_WARNS() << "Null Session ID" << LL_ENDL; - } - - // toggle off all chiclets, except specified - S32 size = getChicletCount(); - for(int n = 0; n < size; ++n) - { - LLIMChiclet* chiclet = getChiclet<LLIMChiclet>(n); - if(chiclet && chiclet->getSessionId() != session_id) - { - chiclet->setToggleState(false); - } - } - - // toggle specified chiclet - LLIMChiclet* chiclet = findChiclet<LLIMChiclet>(session_id); - if(chiclet) - { - chiclet->setToggleState(toggle); - } -} - -void LLChicletPanel::arrange() -{ - if(mChicletList.empty()) - return; - - //initial arrange of chicklets positions - S32 chiclet_left = getChiclet(0)->getRect().mLeft; - S32 size = getChicletCount(); - for( int n = 0; n < size; ++n) - { - LLChiclet* chiclet = getChiclet(n); - - S32 chiclet_width = chiclet->getRequiredRect().getWidth(); - LLRect rect = chiclet->getRect(); - rect.set(chiclet_left, rect.mTop, chiclet_left + chiclet_width, rect.mBottom); - - chiclet->setRect(rect); - - chiclet_left += chiclet_width + getChicletPadding(); - } - - //reset size and pos on mScrollArea - LLRect rect = getRect(); - LLRect scroll_button_rect = mLeftScrollButton->getRect(); - - bool need_show_scroll = needShowScroll(); - if(need_show_scroll) - { - mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad, - rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0)); - } - else - { - mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0)); - } - - trimChiclets(); - showScrollButtonsIfNeeded(); -} - -void LLChicletPanel::trimChiclets() -{ - // trim right - if(!mChicletList.empty()) - { - S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight; - S32 first_chiclet_left = getChiclet(0)->getRect().mLeft; - S32 scroll_width = mScrollArea->getRect().getWidth(); - if(last_chiclet_right < scroll_width || first_chiclet_left > 0) - { - shiftChiclets(scroll_width - last_chiclet_right); - } - } -} - -bool LLChicletPanel::needShowScroll() -{ - if(mChicletList.empty()) - return false; - - S32 chicklet_width = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft; - - return chicklet_width>getRect().getWidth(); -} - - -void LLChicletPanel::showScrollButtonsIfNeeded() -{ - bool can_scroll_left = canScrollLeft(); - bool can_scroll_right = canScrollRight(); - - mLeftScrollButton->setEnabled(can_scroll_left); - mRightScrollButton->setEnabled(can_scroll_right); - - bool show_scroll_buttons = (can_scroll_left || can_scroll_right) && mShowControls; - - mLeftScrollButton->setVisible(show_scroll_buttons); - mRightScrollButton->setVisible(show_scroll_buttons); -} - -void LLChicletPanel::draw() -{ - child_list_const_iter_t it = getChildList()->begin(); - for( ; getChildList()->end() != it; ++it) - { - LLView* child = *it; - if(child == dynamic_cast<LLView*>(mScrollArea)) - { - LLLocalClipRect clip(mScrollArea->getRect()); - drawChild(mScrollArea); - } - else - { - drawChild(child); - } - } -} - -bool LLChicletPanel::canScrollRight() -{ - if(mChicletList.empty()) - return false; - - S32 scroll_width = mScrollArea->getRect().getWidth(); - S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight; - - if(last_chiclet_right > scroll_width) - return true; - - return false; -} - -bool LLChicletPanel::canScrollLeft() -{ - if(mChicletList.empty()) - return false; - - return getChiclet(0)->getRect().mLeft < 0; -} - -void LLChicletPanel::scroll(S32 offset) -{ - shiftChiclets(offset); -} - -void LLChicletPanel::shiftChiclets(S32 offset, S32 start_index /* = 0 */) -{ - if(start_index < 0 || start_index >= getChicletCount()) - { - return; - } - - chiclet_list_t::const_iterator it = mChicletList.begin() + start_index; - for(;mChicletList.end() != it; ++it) - { - LLChiclet* chiclet = *it; - chiclet->translate(offset,0); - } -} - -void LLChicletPanel::scrollLeft() -{ - if(canScrollLeft()) - { - S32 offset = getScrollingOffset(); - LLRect first_chiclet_rect = getChiclet(0)->getRect(); - - // shift chiclets in case first chiclet is partially visible - if(first_chiclet_rect.mLeft < 0 && first_chiclet_rect.mRight > 0) - { - offset = llabs(first_chiclet_rect.mLeft); - } - - scroll(offset); - - showScrollButtonsIfNeeded(); - } -} - -void LLChicletPanel::scrollRight() -{ - if(canScrollRight()) - { - S32 offset = - getScrollingOffset(); - - S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight; - S32 scroll_rect_width = mScrollArea->getRect().getWidth(); - // if after scrolling, the last chiclet will not be aligned to - // scroll area right side - align it. - if( last_chiclet_right + offset < scroll_rect_width ) - { - offset = scroll_rect_width - last_chiclet_right; - } - - scroll(offset); - - showScrollButtonsIfNeeded(); - } -} - -void LLChicletPanel::onLeftScrollClick() -{ - scrollLeft(); -} - -void LLChicletPanel::onRightScrollClick() -{ - scrollRight(); -} - -void LLChicletPanel::onLeftScrollHeldDown() -{ - S32 offset = mScrollingOffset; - mScrollingOffset = mScrollingOffset / mScrollRatio; - scrollLeft(); - mScrollingOffset = offset; -} - -void LLChicletPanel::onRightScrollHeldDown() -{ - S32 offset = mScrollingOffset; - mScrollingOffset = mScrollingOffset / mScrollRatio; - scrollRight(); - mScrollingOffset = offset; -} - -boost::signals2::connection LLChicletPanel::setChicletClickedCallback( - const commit_callback_t& cb) -{ - return setCommitCallback(cb); -} - -bool LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - if(clicks > 0) - { - scrollRight(); - } - else - { - scrollLeft(); - } - return true; -} - -bool LLChicletPanel::isAnyIMFloaterDoked() -{ - bool res = false; - for (chiclet_list_t::iterator it = mChicletList.begin(); it - != mChicletList.end(); it++) - { - LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>( - "impanel", (*it)->getSessionId()); - if (im_floater != NULL && im_floater->getVisible() - && !im_floater->isMinimized() && im_floater->isDocked()) - { - res = true; - break; - } - } - - return res; -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -LLChicletNotificationCounterCtrl::Params::Params() - : max_displayed_count("max_displayed_count", 99) -{ -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p) - : LLAvatarIconCtrl(p) -{ -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChicletInvOfferIconCtrl::LLChicletInvOfferIconCtrl(const Params& p) -: LLChicletAvatarIconCtrl(p) - , mDefaultIcon(p.default_icon) -{ -} - -void LLChicletInvOfferIconCtrl::setValue(const LLSD& value ) -{ - if(value.asUUID().isNull()) - { - LLIconCtrl::setValue(mDefaultIcon); - } - else - { - LLChicletAvatarIconCtrl::setValue(value); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLScriptChiclet::Params::Params() - : icon("icon") - , chiclet_button("chiclet_button") - , new_message_icon("new_message_icon") -{ -} - -LLScriptChiclet::LLScriptChiclet(const Params&p) - : LLIMChiclet(p) - , mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); - addChild(mNewMessagesIcon); - - LLIconCtrl::Params icon_params = p.icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); - addChild(mChicletIconCtrl); - - sendChildToFront(mNewMessagesIcon); -} - -void LLScriptChiclet::setSessionId(const LLUUID& session_id) -{ - setShowNewMessagesIcon( getSessionId() != session_id ); - - LLIMChiclet::setSessionId(session_id); - - setToolTip(LLScriptFloaterManager::getObjectName(session_id)); -} - -void LLScriptChiclet::onMouseDown() -{ - LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); -} - -void LLScriptChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string action = user_data.asString(); - - if("end" == action) - { - LLScriptFloaterManager::instance().removeNotification(getSessionId()); - } - else if ("close all" == action) - { - LLIMWellWindow::getInstance()->closeAll(); - } -} - -void LLScriptChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2)); - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mPopupMenuHandle = menu->getHandle(); - } - -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -static const std::string INVENTORY_USER_OFFER ("UserGiveItem"); - -LLInvOfferChiclet::Params::Params() - : icon("icon") - , chiclet_button("chiclet_button") - , new_message_icon("new_message_icon") -{ -} - -LLInvOfferChiclet::LLInvOfferChiclet(const Params&p) - : LLIMChiclet(p) - , mChicletIconCtrl(NULL) -{ - LLButton::Params button_params = p.chiclet_button; - mChicletButton = LLUICtrlFactory::create<LLButton>(button_params); - addChild(mChicletButton); - - LLIconCtrl::Params new_msg_params = p.new_message_icon; - mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); - addChild(mNewMessagesIcon); - - LLChicletInvOfferIconCtrl::Params icon_params = p.icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params); - addChild(mChicletIconCtrl); - - sendChildToFront(mNewMessagesIcon); -} - -void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) -{ - setShowNewMessagesIcon( getSessionId() != session_id ); - - setToolTip(LLScriptFloaterManager::getObjectName(session_id)); - - LLIMChiclet::setSessionId(session_id); - LLNotificationPtr notification = LLNotifications::getInstance()->find(session_id); - - if ( notification && notification->getName() == INVENTORY_USER_OFFER ) - { - mChicletIconCtrl->setValue(notification->getPayload()["from_id"]); - } - else - { - mChicletIconCtrl->setValue(LLUUID::null); - } -} - -void LLInvOfferChiclet::onMouseDown() -{ - LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId()); -} - -void LLInvOfferChiclet::onMenuItemClicked(const LLSD& user_data) -{ - std::string action = user_data.asString(); - - if("end" == action) - { - LLScriptFloaterManager::instance().removeNotification(getSessionId()); - } -} - -void LLInvOfferChiclet::createPopupMenu() -{ - if(!canCreateMenu()) - return; - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2)); - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mPopupMenuHandle = menu->getHandle(); - } -} - -// EOF +/**
+ * @file llchiclet.cpp
+ * @brief LLChiclet class implementation
+ *
+ * $LicenseInfo:firstyear=2002&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 "llchiclet.h"
+
+#include "llchicletbar.h"
+#include "llfloaterimsession.h"
+#include "llfloaterimcontainer.h"
+#include "llfloaterreg.h"
+#include "lllocalcliprect.h"
+#include "llscriptfloater.h"
+#include "llsingleton.h"
+#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
+#include "llviewermenu.h"
+
+static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
+static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
+static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");
+static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");
+
+boost::signals2::signal<LLChiclet* (const LLUUID&),
+ LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >
+ LLIMChiclet::sFindChicletsSignal;
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLSysWellChiclet::Params::Params()
+ : button("button")
+ , unread_notifications("unread_notifications")
+ , max_displayed_count("max_displayed_count", 99)
+{
+ button.name = "button";
+ button.tab_stop = false;
+ button.label = LLStringUtil::null;
+}
+
+LLSysWellChiclet::LLSysWellChiclet(const Params& p)
+ : LLChiclet(p)
+ , mButton(NULL)
+ , mCounter(0)
+ , mMaxDisplayedCount(p.max_displayed_count)
+ , mIsNewMessagesState(false)
+ , mFlashToLitTimer(NULL)
+{
+ LLButton::Params button_params = p.button;
+ mButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mButton);
+
+ mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1));
+}
+
+LLSysWellChiclet::~LLSysWellChiclet()
+{
+ mFlashToLitTimer->unset();
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
+}
+
+void LLSysWellChiclet::setCounter(S32 counter)
+{
+ // do nothing if the same counter is coming. EXT-3678.
+ if (counter == mCounter) return;
+
+ // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)
+ std::string s_count;
+ if(counter != 0)
+ {
+ static std::string more_messages_exist("+");
+ std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
+ s_count = llformat("%d%s"
+ , llmin(counter, mMaxDisplayedCount)
+ , more_messages.c_str()
+ );
+ }
+
+ mButton->setLabel(s_count);
+
+ mCounter = counter;
+}
+
+boost::signals2::connection LLSysWellChiclet::setClickCallback(
+ const commit_callback_t& cb)
+{
+ return mButton->setClickedCallback(cb);
+}
+
+void LLSysWellChiclet::setToggleState(bool toggled) {
+ mButton->setToggleState(toggled);
+}
+
+void LLSysWellChiclet::changeLitState(bool blink)
+{
+ setNewMessagesState(!mIsNewMessagesState);
+}
+
+void LLSysWellChiclet::setNewMessagesState(bool new_messages)
+{
+ /*
+ Emulate 4 states of button by background images, see detains in EXT-3147
+ xml attribute Description
+ image_unselected "Unlit" - there are no new messages
+ image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
+ image_pressed "Lit" - there are new messages
+ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
+ */
+ mButton->setForcePressedState(new_messages);
+
+ mIsNewMessagesState = new_messages;
+}
+
+void LLSysWellChiclet::updateWidget(bool is_window_empty)
+{
+ mButton->setEnabled(!is_window_empty);
+
+ if (LLChicletBar::instanceExists())
+ {
+ LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty);
+ }
+}
+// virtual
+bool LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLContextMenu* menu_avatar = mContextMenuHandle.get();
+ if(!menu_avatar)
+ {
+ createMenu();
+ menu_avatar = mContextMenuHandle.get();
+ }
+ if (menu_avatar)
+ {
+ menu_avatar->show(x, y);
+ LLMenuGL::showPopup(this, menu_avatar, x, y);
+ }
+ return true;
+}
+
+/************************************************************************/
+/* LLNotificationChiclet implementation */
+/************************************************************************/
+LLNotificationChiclet::LLNotificationChiclet(const Params& p)
+: LLSysWellChiclet(p),
+ mUreadSystemNotifications(0)
+{
+ mNotificationChannel.reset(new ChicletNotificationChannel(this));
+ // ensure that notification well window exists, to synchronously
+ // handle toast add/delete events.
+ LLFloaterNotificationsTabbed::getInstance()->setSysWellChiclet(this);
+}
+
+LLNotificationChiclet::~LLNotificationChiclet()
+{
+ mNotificationChannel.reset();
+}
+
+void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+ if("close all" == action)
+ {
+ LLFloaterNotificationsTabbed::getInstance()->closeAll();
+ LLIMWellWindow::getInstance()->closeAll();
+ }
+}
+
+bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
+{
+ std::string item = user_data.asString();
+ if (item == "can close all")
+ {
+ return mUreadSystemNotifications != 0;
+ }
+ return true;
+}
+
+void LLNotificationChiclet::createMenu()
+{
+ if(mContextMenuHandle.get())
+ {
+ LL_WARNS() << "Menu already exists" << LL_ENDL;
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("NotificationWellChicletMenu.Action",
+ boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2));
+
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("NotificationWellChicletMenu.EnableItem",
+ boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
+
+ llassert(LLMenuGL::sMenuContainer != NULL);
+ LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+ ("menu_notification_well_button.xml",
+ LLMenuGL::sMenuContainer,
+ LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mContextMenuHandle = menu->getHandle();
+ }
+}
+
+/*virtual*/
+void LLNotificationChiclet::setCounter(S32 counter)
+{
+ LLSysWellChiclet::setCounter(counter);
+ updateWidget(getCounter() == 0);
+
+}
+
+bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )
+{
+ bool displayNotification;
+ if ( (notification->getName() == "ScriptDialog") // special case for scripts
+ // if there is no toast window for the notification, filter it
+ //|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
+ || (!LLFloaterNotificationsTabbed::getInstance()->findItemByID(notification->getID(), notification->getName()))
+ )
+ {
+ displayNotification = false;
+ }
+ else if( !(notification->canLogToIM() && notification->hasFormElements())
+ && (!notification->getPayload().has("give_inventory_notification")
+ || notification->getPayload()["give_inventory_notification"]))
+ {
+ displayNotification = true;
+ }
+ else
+ {
+ displayNotification = false;
+ }
+ return displayNotification;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChiclet::Params::Params()
+ : show_counter("show_counter", true)
+ , enable_counter("enable_counter", false)
+{
+}
+
+LLChiclet::LLChiclet(const Params& p)
+: LLUICtrl(p)
+, mSessionId(LLUUID::null)
+, mShowCounter(p.show_counter)
+{
+}
+
+boost::signals2::connection LLChiclet::setLeftButtonClickCallback(
+ const commit_callback_t& cb)
+{
+ return setCommitCallback(cb);
+}
+
+bool LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onCommit();
+ childrenHandleMouseDown(x,y,mask);
+ return true;
+}
+
+boost::signals2::connection LLChiclet::setChicletSizeChangedCallback(
+ const chiclet_size_changed_callback_t& cb)
+{
+ return mChicletSizeChangedSignal.connect(cb);
+}
+
+void LLChiclet::onChicletSizeChanged()
+{
+ mChicletSizeChangedSignal(this, getValue());
+}
+
+LLSD LLChiclet::getValue() const
+{
+ return LLSD(getSessionId());
+}
+
+void LLChiclet::setValue(const LLSD& value)
+{
+ if(value.isUUID())
+ {
+ setSessionId(value.asUUID());
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
+: LLChiclet(p)
+, mShowSpeaker(false)
+, mDefaultWidth(p.rect().getWidth())
+, mNewMessagesIcon(NULL)
+, mChicletButton(NULL)
+{
+}
+
+LLIMChiclet::~LLIMChiclet()
+{
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
+}
+
+/* virtual*/
+bool LLIMChiclet::postBuild()
+{
+ mChicletButton = getChild<LLButton>("chiclet_button");
+ mChicletButton->setCommitCallback(boost::bind(&LLIMChiclet::onMouseDown, this));
+ mChicletButton->setDoubleClickCallback(boost::bind(&LLIMChiclet::onMouseDown, this));
+ return true;
+}
+
+void LLIMChiclet::enableCounterControl(bool enable)
+{
+ mCounterEnabled = enable;
+ if(!enable)
+ {
+ LLChiclet::setShowCounter(false);
+ }
+}
+
+void LLIMChiclet::setRequiredWidth()
+{
+ S32 required_width = mDefaultWidth;
+ reshape(required_width, getRect().getHeight());
+ onChicletSizeChanged();
+}
+
+void LLIMChiclet::setShowNewMessagesIcon(bool show)
+{
+ if(mNewMessagesIcon)
+ {
+ mNewMessagesIcon->setVisible(show);
+ }
+ setRequiredWidth();
+}
+
+bool LLIMChiclet::getShowNewMessagesIcon()
+{
+ return mNewMessagesIcon->getVisible();
+}
+
+void LLIMChiclet::onMouseDown()
+{
+ LLFloaterIMSession::toggle(getSessionId());
+}
+
+void LLIMChiclet::setToggleState(bool toggle)
+{
+ mChicletButton->setToggleState(toggle);
+}
+
+bool LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+ if(!menu)
+ {
+ createPopupMenu();
+ menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());
+ }
+
+ if (menu)
+ {
+ updateMenuItems();
+ menu->arrangeAndClear();
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+
+ return true;
+}
+
+void LLIMChiclet::hidePopupMenu()
+{
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
+ {
+ menu->setVisible(false);
+ }
+}
+
+bool LLIMChiclet::canCreateMenu()
+{
+ if(mPopupMenuHandle.get())
+ {
+ LL_WARNS() << "Menu already exists" << LL_ENDL;
+ return false;
+ }
+ if(getSessionId().isNull())
+ {
+ return false;
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletPanel::Params::Params()
+: chiclet_padding("chiclet_padding")
+, scrolling_offset("scrolling_offset")
+, scroll_button_hpad("scroll_button_hpad")
+, scroll_ratio("scroll_ratio")
+, min_width("min_width")
+{
+};
+
+LLChicletPanel::LLChicletPanel(const Params&p)
+: LLPanel(p)
+, mScrollArea(NULL)
+, mLeftScrollButton(NULL)
+, mRightScrollButton(NULL)
+, mChicletPadding(p.chiclet_padding)
+, mScrollingOffset(p.scrolling_offset)
+, mScrollButtonHPad(p.scroll_button_hpad)
+, mScrollRatio(p.scroll_ratio)
+, mMinWidth(p.min_width)
+, mShowControls(true)
+{
+ LLPanel::Params panel_params;
+ panel_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT);
+ mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this);
+
+ // important for Show/Hide Camera and Move controls menu in bottom tray to work properly
+ mScrollArea->setMouseOpaque(false);
+
+ addChild(mScrollArea);
+}
+
+LLChicletPanel::~LLChicletPanel()
+{
+ if(LLTransientFloaterMgr::instanceExists())
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
+ LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
+ }
+}
+
+void LLChicletPanel::onMessageCountChanged(const LLSD& data)
+{
+ // *TODO : we either suppress this method or return a value. Right now, it servers no purpose.
+ /*
+
+ //LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(session_id);
+ //if (im_floater && im_floater->getVisible() && im_floater->hasFocus())
+ //{
+ // unread = 0;
+ //}
+ */
+}
+
+void LLChicletPanel::objectChicletCallback(const LLSD& data)
+{
+ LLUUID notification_id = data["notification_id"];
+ bool new_message = data["new_message"];
+
+ std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(notification_id);
+ std::list<LLChiclet *>::iterator iter;
+ for (iter = chiclets.begin(); iter != chiclets.end(); iter++)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter);
+ if (chiclet != NULL)
+ {
+ chiclet->setShowNewMessagesIcon(new_message);
+ }
+ }
+}
+
+bool LLChicletPanel::postBuild()
+{
+ LLPanel::postBuild();
+ LLIMModel::instance().addNewMsgCallback(boost::bind(&LLChicletPanel::onMessageCountChanged, this, _1));
+ LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLChicletPanel::onMessageCountChanged, this, _1));
+ LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(&LLChicletPanel::objectChicletCallback, this, _1));
+ LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(&LLChicletPanel::objectChicletCallback, this, _1));
+ LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1));
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1));
+
+ mLeftScrollButton=getChild<LLButton>("chicklet_left_scroll_button");
+ LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton);
+ mLeftScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this));
+ mLeftScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onLeftScrollHeldDown,this));
+ mLeftScrollButton->setEnabled(false);
+
+ mRightScrollButton=getChild<LLButton>("chicklet_right_scroll_button");
+ LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton);
+ mRightScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this));
+ mRightScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onRightScrollHeldDown,this));
+ mRightScrollButton->setEnabled(false);
+
+ return true;
+}
+
+void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id)
+{
+ static LLUUID s_previous_active_voice_session_id;
+
+ std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id);
+
+ for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
+ if(chiclet)
+ {
+ if (gSavedSettings.getBOOL("OpenIMOnVoice"))
+ {
+ LLFloaterIMContainer::getInstance()->showConversation(session_id);
+ }
+ }
+ }
+
+ s_previous_active_voice_session_id = session_id;
+}
+
+bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
+{
+ if(mScrollArea->addChild(chiclet))
+ {
+ // chiclets should be aligned to right edge of scroll panel
+ S32 left_shift = 0;
+
+ if (!canScrollLeft())
+ {
+ // init left shift for the first chiclet in the list...
+ if (mChicletList.empty())
+ {
+ // ...start from the right border of the scroll area for the first added chiclet
+ left_shift = mScrollArea->getRect().getWidth();
+ }
+ else
+ {
+ // ... start from the left border of the first chiclet minus padding
+ left_shift = getChiclet(0)->getRect().mLeft - getChicletPadding();
+ }
+
+ // take into account width of the being added chiclet
+ left_shift -= chiclet->getRequiredRect().getWidth();
+
+ // if we overflow the scroll area we do not need to shift chiclets
+ if (left_shift < 0)
+ {
+ left_shift = 0;
+ }
+ }
+
+ mChicletList.insert(mChicletList.begin() + index, chiclet);
+
+ // shift first chiclet to place it in correct position.
+ // rest ones will be placed in arrange()
+ if (!canScrollLeft())
+ {
+ getChiclet(0)->translate(left_shift - getChiclet(0)->getRect().mLeft, 0);
+ }
+
+ chiclet->setLeftButtonClickCallback(boost::bind(&LLChicletPanel::onChicletClick, this, _1, _2));
+ chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
+
+ arrange();
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
+
+ return true;
+ }
+
+ return false;
+}
+
+void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
+{
+ arrange();
+}
+
+void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m)
+{
+ if (mCommitSignal)
+ {
+ (*mCommitSignal)(ctrl,param);
+ }
+}
+
+void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
+{
+ LLChiclet* chiclet = *it;
+ mScrollArea->removeChild(chiclet);
+ mChicletList.erase(it);
+
+ arrange();
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
+ chiclet->die();
+}
+
+void LLChicletPanel::removeChiclet(S32 index)
+{
+ if(index >= 0 && index < getChicletCount())
+ {
+ removeChiclet(mChicletList.begin() + index);
+ }
+}
+
+S32 LLChicletPanel::getChicletIndex(const LLChiclet* chiclet)
+{
+ if(mChicletList.empty())
+ return -1;
+
+ S32 size = getChicletCount();
+ for(int n = 0; n < size; ++n)
+ {
+ if(chiclet == mChicletList[n])
+ return n;
+ }
+
+ return -1;
+}
+
+void LLChicletPanel::removeChiclet(LLChiclet*chiclet)
+{
+ chiclet_list_t::iterator it = mChicletList.begin();
+ for( ; mChicletList.end() != it; ++it)
+ {
+ LLChiclet* temp = *it;
+ if(temp == chiclet)
+ {
+ removeChiclet(it);
+ return;
+ }
+ }
+}
+
+void LLChicletPanel::removeChiclet(const LLUUID& im_session_id)
+{
+ chiclet_list_t::iterator it = mChicletList.begin();
+ for( ; mChicletList.end() != it; ++it)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
+
+ if(chiclet->getSessionId() == im_session_id)
+ {
+ removeChiclet(it);
+ return;
+ }
+ }
+}
+
+void LLChicletPanel::removeAll()
+{
+ S32 size = getChicletCount();
+ for(S32 n = 0; n < size; ++n)
+ {
+ mScrollArea->removeChild(mChicletList[n]);
+ }
+
+ mChicletList.erase(mChicletList.begin(), mChicletList.end());
+
+ showScrollButtonsIfNeeded();
+}
+
+void LLChicletPanel::scrollToChiclet(const LLChiclet* chiclet)
+{
+ const LLRect& rect = chiclet->getRect();
+
+ if (rect.mLeft < 0)
+ {
+ scroll(llabs(rect.mLeft));
+ showScrollButtonsIfNeeded();
+ }
+ else
+ {
+ S32 scrollWidth = mScrollArea->getRect().getWidth();
+
+ if (rect.mRight > scrollWidth)
+ {
+ scroll(-llabs(rect.mRight - scrollWidth));
+ showScrollButtonsIfNeeded();
+ }
+ }
+}
+
+void LLChicletPanel::reshape(S32 width, S32 height, bool called_from_parent )
+{
+ LLPanel::reshape(width,height,called_from_parent);
+
+ //Needed once- to avoid error at first call of reshape() before postBuild()
+ if(!mLeftScrollButton||!mRightScrollButton)
+ return;
+
+ LLRect scroll_button_rect = mLeftScrollButton->getRect();
+ mLeftScrollButton->setRect(LLRect(0,scroll_button_rect.mTop,scroll_button_rect.getWidth(),
+ scroll_button_rect.mBottom));
+ scroll_button_rect = mRightScrollButton->getRect();
+ mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop,
+ width, scroll_button_rect.mBottom));
+
+
+ bool need_show_scroll = needShowScroll();
+ if(need_show_scroll)
+ {
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
+ height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
+ }
+ else
+ {
+ mScrollArea->setRect(LLRect(0,height, width, 0));
+ }
+
+ mShowControls = width >= mMinWidth;
+
+ mScrollArea->setVisible(mShowControls);
+
+ trimChiclets();
+ showScrollButtonsIfNeeded();
+
+}
+
+S32 LLChicletPanel::notifyParent(const LLSD& info)
+{
+ if(info.has("notification"))
+ {
+ std::string str_notification = info["notification"];
+ if(str_notification == "size_changes")
+ {
+ arrange();
+ return 1;
+ }
+ }
+ return LLPanel::notifyParent(info);
+}
+
+void LLChicletPanel::setChicletToggleState(const LLUUID& session_id, bool toggle)
+{
+ if(session_id.isNull())
+ {
+ LL_WARNS() << "Null Session ID" << LL_ENDL;
+ }
+
+ // toggle off all chiclets, except specified
+ S32 size = getChicletCount();
+ for(int n = 0; n < size; ++n)
+ {
+ LLIMChiclet* chiclet = getChiclet<LLIMChiclet>(n);
+ if(chiclet && chiclet->getSessionId() != session_id)
+ {
+ chiclet->setToggleState(false);
+ }
+ }
+
+ // toggle specified chiclet
+ LLIMChiclet* chiclet = findChiclet<LLIMChiclet>(session_id);
+ if(chiclet)
+ {
+ chiclet->setToggleState(toggle);
+ }
+}
+
+void LLChicletPanel::arrange()
+{
+ if(mChicletList.empty())
+ return;
+
+ //initial arrange of chicklets positions
+ S32 chiclet_left = getChiclet(0)->getRect().mLeft;
+ S32 size = getChicletCount();
+ for( int n = 0; n < size; ++n)
+ {
+ LLChiclet* chiclet = getChiclet(n);
+
+ S32 chiclet_width = chiclet->getRequiredRect().getWidth();
+ LLRect rect = chiclet->getRect();
+ rect.set(chiclet_left, rect.mTop, chiclet_left + chiclet_width, rect.mBottom);
+
+ chiclet->setRect(rect);
+
+ chiclet_left += chiclet_width + getChicletPadding();
+ }
+
+ //reset size and pos on mScrollArea
+ LLRect rect = getRect();
+ LLRect scroll_button_rect = mLeftScrollButton->getRect();
+
+ bool need_show_scroll = needShowScroll();
+ if(need_show_scroll)
+ {
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
+ rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
+ }
+ else
+ {
+ mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0));
+ }
+
+ trimChiclets();
+ showScrollButtonsIfNeeded();
+}
+
+void LLChicletPanel::trimChiclets()
+{
+ // trim right
+ if(!mChicletList.empty())
+ {
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+ S32 first_chiclet_left = getChiclet(0)->getRect().mLeft;
+ S32 scroll_width = mScrollArea->getRect().getWidth();
+ if(last_chiclet_right < scroll_width || first_chiclet_left > 0)
+ {
+ shiftChiclets(scroll_width - last_chiclet_right);
+ }
+ }
+}
+
+bool LLChicletPanel::needShowScroll()
+{
+ if(mChicletList.empty())
+ return false;
+
+ S32 chicklet_width = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft;
+
+ return chicklet_width>getRect().getWidth();
+}
+
+
+void LLChicletPanel::showScrollButtonsIfNeeded()
+{
+ bool can_scroll_left = canScrollLeft();
+ bool can_scroll_right = canScrollRight();
+
+ mLeftScrollButton->setEnabled(can_scroll_left);
+ mRightScrollButton->setEnabled(can_scroll_right);
+
+ bool show_scroll_buttons = (can_scroll_left || can_scroll_right) && mShowControls;
+
+ mLeftScrollButton->setVisible(show_scroll_buttons);
+ mRightScrollButton->setVisible(show_scroll_buttons);
+}
+
+void LLChicletPanel::draw()
+{
+ child_list_const_iter_t it = getChildList()->begin();
+ for( ; getChildList()->end() != it; ++it)
+ {
+ LLView* child = *it;
+ if(child == dynamic_cast<LLView*>(mScrollArea))
+ {
+ LLLocalClipRect clip(mScrollArea->getRect());
+ drawChild(mScrollArea);
+ }
+ else
+ {
+ drawChild(child);
+ }
+ }
+}
+
+bool LLChicletPanel::canScrollRight()
+{
+ if(mChicletList.empty())
+ return false;
+
+ S32 scroll_width = mScrollArea->getRect().getWidth();
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+
+ if(last_chiclet_right > scroll_width)
+ return true;
+
+ return false;
+}
+
+bool LLChicletPanel::canScrollLeft()
+{
+ if(mChicletList.empty())
+ return false;
+
+ return getChiclet(0)->getRect().mLeft < 0;
+}
+
+void LLChicletPanel::scroll(S32 offset)
+{
+ shiftChiclets(offset);
+}
+
+void LLChicletPanel::shiftChiclets(S32 offset, S32 start_index /* = 0 */)
+{
+ if(start_index < 0 || start_index >= getChicletCount())
+ {
+ return;
+ }
+
+ chiclet_list_t::const_iterator it = mChicletList.begin() + start_index;
+ for(;mChicletList.end() != it; ++it)
+ {
+ LLChiclet* chiclet = *it;
+ chiclet->translate(offset,0);
+ }
+}
+
+void LLChicletPanel::scrollLeft()
+{
+ if(canScrollLeft())
+ {
+ S32 offset = getScrollingOffset();
+ LLRect first_chiclet_rect = getChiclet(0)->getRect();
+
+ // shift chiclets in case first chiclet is partially visible
+ if(first_chiclet_rect.mLeft < 0 && first_chiclet_rect.mRight > 0)
+ {
+ offset = llabs(first_chiclet_rect.mLeft);
+ }
+
+ scroll(offset);
+
+ showScrollButtonsIfNeeded();
+ }
+}
+
+void LLChicletPanel::scrollRight()
+{
+ if(canScrollRight())
+ {
+ S32 offset = - getScrollingOffset();
+
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+ S32 scroll_rect_width = mScrollArea->getRect().getWidth();
+ // if after scrolling, the last chiclet will not be aligned to
+ // scroll area right side - align it.
+ if( last_chiclet_right + offset < scroll_rect_width )
+ {
+ offset = scroll_rect_width - last_chiclet_right;
+ }
+
+ scroll(offset);
+
+ showScrollButtonsIfNeeded();
+ }
+}
+
+void LLChicletPanel::onLeftScrollClick()
+{
+ scrollLeft();
+}
+
+void LLChicletPanel::onRightScrollClick()
+{
+ scrollRight();
+}
+
+void LLChicletPanel::onLeftScrollHeldDown()
+{
+ S32 offset = mScrollingOffset;
+ mScrollingOffset = mScrollingOffset / mScrollRatio;
+ scrollLeft();
+ mScrollingOffset = offset;
+}
+
+void LLChicletPanel::onRightScrollHeldDown()
+{
+ S32 offset = mScrollingOffset;
+ mScrollingOffset = mScrollingOffset / mScrollRatio;
+ scrollRight();
+ mScrollingOffset = offset;
+}
+
+boost::signals2::connection LLChicletPanel::setChicletClickedCallback(
+ const commit_callback_t& cb)
+{
+ return setCommitCallback(cb);
+}
+
+bool LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ if(clicks > 0)
+ {
+ scrollRight();
+ }
+ else
+ {
+ scrollLeft();
+ }
+ return true;
+}
+
+bool LLChicletPanel::isAnyIMFloaterDoked()
+{
+ bool res = false;
+ for (chiclet_list_t::iterator it = mChicletList.begin(); it
+ != mChicletList.end(); it++)
+ {
+ LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>(
+ "impanel", (*it)->getSessionId());
+ if (im_floater != NULL && im_floater->getVisible()
+ && !im_floater->isMinimized() && im_floater->isDocked())
+ {
+ res = true;
+ break;
+ }
+ }
+
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+LLChicletNotificationCounterCtrl::Params::Params()
+ : max_displayed_count("max_displayed_count", 99)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p)
+ : LLAvatarIconCtrl(p)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletInvOfferIconCtrl::LLChicletInvOfferIconCtrl(const Params& p)
+: LLChicletAvatarIconCtrl(p)
+ , mDefaultIcon(p.default_icon)
+{
+}
+
+void LLChicletInvOfferIconCtrl::setValue(const LLSD& value )
+{
+ if(value.asUUID().isNull())
+ {
+ LLIconCtrl::setValue(mDefaultIcon);
+ }
+ else
+ {
+ LLChicletAvatarIconCtrl::setValue(value);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLScriptChiclet::Params::Params()
+ : icon("icon")
+ , chiclet_button("chiclet_button")
+ , new_message_icon("new_message_icon")
+{
+}
+
+LLScriptChiclet::LLScriptChiclet(const Params&p)
+ : LLIMChiclet(p)
+ , mChicletIconCtrl(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLIconCtrl::Params icon_params = p.icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
+ addChild(mChicletIconCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+}
+
+void LLScriptChiclet::setSessionId(const LLUUID& session_id)
+{
+ setShowNewMessagesIcon( getSessionId() != session_id );
+
+ LLIMChiclet::setSessionId(session_id);
+
+ setToolTip(LLScriptFloaterManager::getObjectName(session_id));
+}
+
+void LLScriptChiclet::onMouseDown()
+{
+ LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId());
+}
+
+void LLScriptChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+
+ if("end" == action)
+ {
+ LLScriptFloaterManager::instance().removeNotification(getSessionId());
+ }
+ else if ("close all" == action)
+ {
+ LLIMWellWindow::getInstance()->closeAll();
+ }
+}
+
+void LLScriptChiclet::createPopupMenu()
+{
+ if(!canCreateMenu())
+ return;
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2));
+
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+static const std::string INVENTORY_USER_OFFER ("UserGiveItem");
+
+LLInvOfferChiclet::Params::Params()
+ : icon("icon")
+ , chiclet_button("chiclet_button")
+ , new_message_icon("new_message_icon")
+{
+}
+
+LLInvOfferChiclet::LLInvOfferChiclet(const Params&p)
+ : LLIMChiclet(p)
+ , mChicletIconCtrl(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLChicletInvOfferIconCtrl::Params icon_params = p.icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params);
+ addChild(mChicletIconCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+}
+
+void LLInvOfferChiclet::setSessionId(const LLUUID& session_id)
+{
+ setShowNewMessagesIcon( getSessionId() != session_id );
+
+ setToolTip(LLScriptFloaterManager::getObjectName(session_id));
+
+ LLIMChiclet::setSessionId(session_id);
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(session_id);
+
+ if ( notification && notification->getName() == INVENTORY_USER_OFFER )
+ {
+ mChicletIconCtrl->setValue(notification->getPayload()["from_id"]);
+ }
+ else
+ {
+ mChicletIconCtrl->setValue(LLUUID::null);
+ }
+}
+
+void LLInvOfferChiclet::onMouseDown()
+{
+ LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId());
+}
+
+void LLInvOfferChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+
+ if("end" == action)
+ {
+ LLScriptFloaterManager::instance().removeNotification(getSessionId());
+ }
+}
+
+void LLInvOfferChiclet::createPopupMenu()
+{
+ if(!canCreateMenu())
+ return;
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2));
+
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
+}
+
+// EOF
|