diff options
Diffstat (limited to 'indra/newview/llchiclet.cpp')
-rw-r--r-- | indra/newview/llchiclet.cpp | 325 |
1 files changed, 289 insertions, 36 deletions
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 90f246ddaf..30967677e8 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -32,6 +32,7 @@ #include "llviewerprecompiledheaders.h" // must be first include #include "llchiclet.h" + #include "llagent.h" #include "llavataractions.h" #include "llbottomtray.h" @@ -42,6 +43,8 @@ #include "llfloaterreg.h" #include "lllocalcliprect.h" #include "llmenugl.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "lloutputmonitorctrl.h" #include "llscriptfloater.h" #include "lltextbox.h" @@ -52,11 +55,13 @@ #include "lltransientfloatermgr.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); +static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well"); static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification"); static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p"); static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc"); static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script"); +static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer"); static const LLRect CHICLET_RECT(0, 25, 25, 0); static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0); @@ -66,7 +71,6 @@ static const S32 OVERLAY_ICON_SHIFT = 2; // used for shifting of an overlay icon // static const S32 LLChicletPanel::s_scroll_ratio = 10; -S32 LLNotificationChiclet::mUreadSystemNotifications = 0; boost::signals2::signal<LLChiclet* (const LLUUID&), LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > > @@ -75,70 +79,173 @@ boost::signals2::signal<LLChiclet* (const LLUUID&), ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLNotificationChiclet::Params::Params() +/** + * Updates the Well's 'Lit' state to flash it when "new messages" are come. + * + * It gets callback which will be called 2*N times with passed period. See EXT-3147 + */ +class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer +{ +public: + typedef boost::function<void()> callback_t; + FlashToLitTimer(S32 count, F32 period, callback_t cb) + : LLEventTimer(period) + , mCallback(cb) + , mFlashCount(2 * count) + , mCurrentFlashCount(0) + { + mEventTimer.stop(); + } + + BOOL tick() + { + mCallback(); + + if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop(); + return FALSE; + } + + void flash() + { + mCurrentFlashCount = 0; + mEventTimer.start(); + } + +private: + callback_t mCallback; + S32 mFlashCount; + S32 mCurrentFlashCount; +}; + +LLSysWellChiclet::Params::Params() : button("button") , unread_notifications("unread_notifications") +, max_displayed_count("max_displayed_count", 9) +, flash_to_lit_count("flash_to_lit_count", 3) +, flash_period("flash_period", 0.5F) { button.name("button"); button.tab_stop(FALSE); button.label(LLStringUtil::null); - } -LLNotificationChiclet::LLNotificationChiclet(const Params& p) +LLSysWellChiclet::LLSysWellChiclet(const Params& p) : LLChiclet(p) , mButton(NULL) , mCounter(0) +, mMaxDisplayedCount(p.max_displayed_count) +, mFlashToLitTimer(NULL) { LLButton::Params button_params = p.button; mButton = LLUICtrlFactory::create<LLButton>(button_params); addChild(mButton); - // connect counter handlers to the signals - connectCounterUpdatersToSignal("notify"); - connectCounterUpdatersToSignal("groupnotify"); - connectCounterUpdatersToSignal("offer"); + mFlashToLitTimer = new FlashToLitTimer(p.flash_to_lit_count, p.flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this)); } -LLNotificationChiclet::~LLNotificationChiclet() +LLSysWellChiclet::~LLSysWellChiclet() { - + delete mFlashToLitTimer; } -void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notification_type) -{ - LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); - LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); - if(n_handler) - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); - } -} - -void LLNotificationChiclet::setCounter(S32 counter) +void LLSysWellChiclet::setCounter(S32 counter) { std::string s_count; if(counter != 0) { - s_count = llformat("%d", counter); + 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); + /* + 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(counter > 0); + + if (mCounter == 0 && counter > 0) + { + mFlashToLitTimer->flash(); + } mCounter = counter; } -boost::signals2::connection LLNotificationChiclet::setClickCallback( +boost::signals2::connection LLSysWellChiclet::setClickCallback( const commit_callback_t& cb) { return mButton->setClickedCallback(cb); } -void LLNotificationChiclet::setToggleState(BOOL toggled) { +void LLSysWellChiclet::setToggleState(BOOL toggled) { mButton->setToggleState(toggled); } +void LLSysWellChiclet::changeLitState() +{ + static bool set_lit = false; + + mButton->setForcePressedState(set_lit); + + set_lit ^= true; +} + +/************************************************************************/ +/* LLIMWellChiclet implementation */ +/************************************************************************/ +LLIMWellChiclet::LLIMWellChiclet(const Params& p) +: LLSysWellChiclet(p) +{ + LLIMModel::instance().addNewMsgCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); + LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); + + LLIMMgr::getInstance()->addSessionObserver(this); +} + +LLIMWellChiclet::~LLIMWellChiclet() +{ + LLIMMgr::getInstance()->removeSessionObserver(this); +} + +void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) +{ + S32 total_unread = LLIMMgr::instance().getNumberOfUnreadParticipantMessages(); + setCounter(total_unread); +} + +/************************************************************************/ +/* LLNotificationChiclet implementation */ +/************************************************************************/ +LLNotificationChiclet::LLNotificationChiclet(const Params& p) +: LLSysWellChiclet(p) +, mUreadSystemNotifications(0) +{ + // connect counter handlers to the signals + connectCounterUpdatersToSignal("notify"); + connectCounterUpdatersToSignal("groupnotify"); + connectCounterUpdatersToSignal("offer"); +} + +void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) +{ + LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); + LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + if(n_handler) + { + n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); + n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); + } +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -392,6 +499,10 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) sendChildToFront(mNewMessagesIcon); setShowSpeaker(p.show_speaker); + + //since mShowSpeaker initialized with false + //setShowSpeaker(false) will not hide mSpeakerCtrl + mSpeakerCtrl->setVisible(getShowSpeaker()); } void LLIMP2PChiclet::setCounter(S32 counter) @@ -592,8 +703,49 @@ void LLAdHocChiclet::setCounter(S32 counter) setShowNewMessagesIcon(counter); } +void LLAdHocChiclet::createPopupMenu() +{ + if(mPopupMenu) + { + llwarns << "Menu already exists" << llendl; + return; + } + if(getSessionId().isNull()) + { + return; + } + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2)); + + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> + ("menu_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +} + +void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data) +{ + std::string level = user_data.asString(); + LLUUID group_id = getSessionId(); + + if("end" == level) + { + LLGroupActions::endIM(group_id); + } +} + BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { + if(!mPopupMenu) + { + createPopupMenu(); + } + + if (mPopupMenu) + { + mPopupMenu->arrangeAndClear(); + LLMenuGL::showPopup(this, mPopupMenu, x, y); + } + return TRUE; } @@ -836,16 +988,7 @@ LLChicletPanel::~LLChicletPanel() void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ LLUUID session_id = data["session_id"].asUUID(); - LLUUID from_id = data["from_id"].asUUID(); - const std::string from = data["from"].asString(); - S32 unread = data["num_unread"].asInteger(); - - // if new message came - if(unread != 0) - { - //we do not show balloon (indicator of new messages) for system messages and our own messages - if (from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from) return; - } + S32 unread = data["participant_unread"].asInteger(); LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); if (im_floater && im_floater->getVisible()) @@ -868,12 +1011,34 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ } } +void object_chiclet_callback(const LLSD& data) +{ + LLUUID object_id = data["object_id"]; + bool new_message = data["new_message"]; + + std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(object_id); + std::list<LLChiclet *>::iterator iter; + for (iter = chiclets.begin(); iter != chiclets.end(); iter++) + { + LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter); + if (chiclet != NULL) + { + if(data.has("unread")) + { + chiclet->setCounter(data["unread"]); + } + chiclet->setShowNewMessagesIcon(new_message); + } + } +} BOOL LLChicletPanel::postBuild() { LLPanel::postBuild(); LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1)); LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1)); + LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(object_chiclet_callback, _1)); + LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(object_chiclet_callback, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1)); LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1)); @@ -1359,7 +1524,7 @@ void LLChicletNotificationCounterCtrl::setCounter(S32 counter) LLRect LLChicletNotificationCounterCtrl::getRequiredRect() { LLRect rc; - S32 text_width = getContentsRect().getWidth(); + S32 text_width = getTextPixelWidth(); rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth); @@ -1412,6 +1577,28 @@ void LLChicletGroupIconCtrl::setValue(const LLSD& value ) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +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); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) : LLOutputMonitorCtrl(p) { @@ -1452,6 +1639,11 @@ void LLScriptChiclet::setSessionId(const LLUUID& session_id) } } +void LLScriptChiclet::setCounter(S32 counter) +{ + setShowNewMessagesIcon( counter > 0 ); +} + void LLScriptChiclet::onMouseDown() { LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); @@ -1463,4 +1655,65 @@ BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask) return LLChiclet::handleMouseDown(x, y, mask); } +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +static const std::string INVENTORY_USER_OFFER ("UserGiveItem"); + +LLInvOfferChiclet::Params::Params() +{ + // *TODO Vadim: Get rid of hardcoded values. + rect(CHICLET_RECT); + icon.rect(CHICLET_ICON_RECT); +} + +LLInvOfferChiclet::LLInvOfferChiclet(const Params&p) + : LLIMChiclet(p) + , mChicletIconCtrl(NULL) +{ + LLChicletInvOfferIconCtrl::Params icon_params = p.icon; + mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params); + // Let "new message" icon be on top, else it will be hidden behind chiclet icon. + addChildInBack(mChicletIconCtrl); +} + +void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) +{ + setShowNewMessagesIcon( getSessionId() != session_id ); + + LLIMChiclet::setSessionId(session_id); + LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(session_id); + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(notification) + { + setToolTip(notification->getSubstitutions()["TITLE"].asString()); + } + + if ( notification && notification->getName() == INVENTORY_USER_OFFER ) + { + mChicletIconCtrl->setValue(notification->getPayload()["from_id"]); + } + else + { + mChicletIconCtrl->setValue(LLUUID::null); + } +} + +void LLInvOfferChiclet::setCounter(S32 counter) +{ + setShowNewMessagesIcon( counter > 0 ); +} + +void LLInvOfferChiclet::onMouseDown() +{ + LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId()); +} + +BOOL LLInvOfferChiclet::handleMouseDown(S32 x, S32 y, MASK mask) +{ + onMouseDown(); + return LLChiclet::handleMouseDown(x, y, mask); +} + // EOF |