diff options
Diffstat (limited to 'indra/newview/llchiclet.cpp')
-rw-r--r-- | indra/newview/llchiclet.cpp | 304 |
1 files changed, 256 insertions, 48 deletions
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 30967677e8..21a0381495 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -53,6 +53,7 @@ #include "llgroupmgr.h" #include "llnotificationmanager.h" #include "lltransientfloatermgr.h" +#include "llsyswellwindow.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well"); @@ -65,11 +66,13 @@ 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); -static const LLRect VOICE_INDICATOR_RECT(25, 25, 45, 0); +static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0); +static const LLRect COUNTER_RECT(25, 25, 50, 0); static const S32 OVERLAY_ICON_SHIFT = 2; // used for shifting of an overlay icon for new massages in a chiclet // static const S32 LLChicletPanel::s_scroll_ratio = 10; +const S32 LLChicletNotificationCounterCtrl::MAX_DISPLAYED_COUNT = 99; boost::signals2::signal<LLChiclet* (const LLUUID&), @@ -88,6 +91,14 @@ class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer { public: typedef boost::function<void()> callback_t; + + /** + * Constructor. + * + * @param count - how many times callback should be called (twice to not change original state) + * @param period - how frequently callback should be called + * @param cb - callback to be called each tick + */ FlashToLitTimer(S32 count, F32 period, callback_t cb) : LLEventTimer(period) , mCallback(cb) @@ -111,8 +122,17 @@ public: mEventTimer.start(); } + void stopFlashing() + { + mEventTimer.stop(); + } + private: callback_t mCallback; + + /** + * How many times Well will blink. + */ S32 mFlashCount; S32 mCurrentFlashCount; }; @@ -134,7 +154,9 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) , mButton(NULL) , mCounter(0) , mMaxDisplayedCount(p.max_displayed_count) +, mIsNewMessagesState(false) , mFlashToLitTimer(NULL) +, mContextMenu(NULL) { LLButton::Params button_params = p.button; mButton = LLUICtrlFactory::create<LLButton>(button_params); @@ -150,6 +172,7 @@ LLSysWellChiclet::~LLSysWellChiclet() void LLSysWellChiclet::setCounter(S32 counter) { + // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter) std::string s_count; if(counter != 0) { @@ -163,20 +186,20 @@ void LLSysWellChiclet::setCounter(S32 counter) 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); + setNewMessagesState(counter > 0); - if (mCounter == 0 && counter > 0) + // we have to flash to 'Lit' state each time new unread message is comming. + if (counter > mCounter) { mFlashToLitTimer->flash(); } + else if (counter == 0) + { + // if notification is resolved while well is flashing it can leave in the 'Lit' state + // when flashing finishes itself. Let break flashing here. + mFlashToLitTimer->stopFlashing(); + } + mCounter = counter; } @@ -192,11 +215,37 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) { void LLSysWellChiclet::changeLitState() { - static bool set_lit = false; + setNewMessagesState(!mIsNewMessagesState); +} - mButton->setForcePressedState(set_lit); +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; +} - set_lit ^= true; +// virtual +BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if(!mContextMenu) + { + createMenu(); + } + if (mContextMenu) + { + mContextMenu->show(x, y); + LLMenuGL::showPopup(this, mContextMenu, x, y); + } + return TRUE; } /************************************************************************/ @@ -209,6 +258,8 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p) LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1)); LLIMMgr::getInstance()->addSessionObserver(this); + + LLIMWellWindow::getInstance()->setSysWellChiclet(this); } LLIMWellChiclet::~LLIMWellChiclet() @@ -216,10 +267,50 @@ LLIMWellChiclet::~LLIMWellChiclet() LLIMMgr::getInstance()->removeSessionObserver(this); } +void LLIMWellChiclet::onMenuItemClicked(const LLSD& user_data) +{ + std::string action = user_data.asString(); + if("close all" == action) + { + LLIMWellWindow::getInstance()->closeAll(); + } +} + +bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data) +{ + std::string item = user_data.asString(); + if (item == "can close all") + { + return !LLIMWellWindow::getInstance()->isWindowEmpty(); + } + return true; +} + +void LLIMWellChiclet::createMenu() +{ + if(mContextMenu) + { + llwarns << "Menu already exists" << llendl; + return; + } + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("IMWellChicletMenu.Action", + boost::bind(&LLIMWellChiclet::onMenuItemClicked, this, _2)); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + enable_registrar.add("IMWellChicletMenu.EnableItem", + boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2)); + + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> + ("menu_im_well_button.xml", + LLMenuGL::sMenuContainer, + LLViewerMenuHolderGL::child_registry_t::instance()); +} + void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) { - S32 total_unread = LLIMMgr::instance().getNumberOfUnreadParticipantMessages(); - setCounter(total_unread); + setCounter(LLBottomTray::getInstance()->getTotalUnreadIMCount()); } /************************************************************************/ @@ -233,6 +324,10 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) connectCounterUpdatersToSignal("notify"); connectCounterUpdatersToSignal("groupnotify"); connectCounterUpdatersToSignal("offer"); + + // ensure that notification well window exists, to synchronously + // handle toast add/delete events. + LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); } void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) @@ -246,6 +341,47 @@ void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& no } } +void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) +{ + std::string action = user_data.asString(); + if("close all" == action) + { + LLNotificationWellWindow::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(mContextMenu) + { + llwarns << "Menu already exists" << llendl; + 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)); + + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> + ("menu_notification_well_button.xml", + LLMenuGL::sMenuContainer, + LLViewerMenuHolderGL::child_registry_t::instance()); +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -330,7 +466,7 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) // shift an icon a little bit to the right and up corner of a chiclet overlay_icon_rect.translate(OVERLAY_ICON_SHIFT, OVERLAY_ICON_SHIFT); - setShowCounter(false); + enableCounterControl(false); } void LLIMChiclet::setShowSpeaker(bool show) @@ -343,30 +479,87 @@ void LLIMChiclet::setShowSpeaker(bool show) onChicletSizeChanged(); } } + +void LLIMChiclet::enableCounterControl(bool enable) +{ + mCounterEnabled = enable; + if(!enable) + { + LLChiclet::setShowCounter(false); + } +} + +void LLIMChiclet::setShowCounter(bool show) +{ + if(!mCounterEnabled) + { + return; + } + + bool needs_resize = getShowCounter() != show; + if(needs_resize) + { + LLChiclet::setShowCounter(show); + toggleCounterControl(); + onChicletSizeChanged(); + } +} + void LLIMChiclet::initSpeakerControl() { // virtual } -void LLIMChiclet::toggleSpeakerControl() +void LLIMChiclet::setRequiredWidth() { - LLRect speaker_rect = mSpeakerCtrl->getRect(); - S32 required_width = getRect().getWidth(); + bool show_speaker = getShowSpeaker(); + bool show_counter = getShowCounter(); + S32 required_width = CHICLET_RECT.getWidth(); - if(getShowSpeaker()) + if (show_counter) { - required_width = required_width + speaker_rect.getWidth(); - initSpeakerControl(); + required_width += COUNTER_RECT.getWidth(); } - else + if (show_speaker) { - required_width = required_width - speaker_rect.getWidth(); - } - + required_width += VOICE_INDICATOR_RECT.getWidth(); + } + reshape(required_width, getRect().getHeight()); +} + +void LLIMChiclet::toggleSpeakerControl() +{ + if(getShowSpeaker()) + { + if(getShowCounter()) + { + mSpeakerCtrl->setRect(VOICE_INDICATOR_RECT); + } + else + { + mSpeakerCtrl->setRect(COUNTER_RECT); + } + initSpeakerControl(); + } + + setRequiredWidth(); mSpeakerCtrl->setVisible(getShowSpeaker()); } +void LLIMChiclet::setCounter(S32 counter) +{ + mCounterCtrl->setCounter(counter); + setShowCounter(counter); + setShowNewMessagesIcon(counter); +} + +void LLIMChiclet::toggleCounterControl() +{ + setRequiredWidth(); + mCounterCtrl->setVisible(getShowCounter()); +} + void LLIMChiclet::setShowNewMessagesIcon(bool show) { if(mNewMessagesIcon) @@ -467,6 +660,7 @@ LLIMP2PChiclet::Params::Params() unread_notifications.v_pad(5); unread_notifications.text_color(LLColor4::white); unread_notifications.mouse_opaque(false); + unread_notifications.rect(COUNTER_RECT); unread_notifications.visible(false); speaker.name("speaker"); @@ -505,12 +699,6 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) mSpeakerCtrl->setVisible(getShowSpeaker()); } -void LLIMP2PChiclet::setCounter(S32 counter) -{ - mCounterCtrl->setCounter(counter); - setShowNewMessagesIcon(counter); -} - void LLIMP2PChiclet::initSpeakerControl() { mSpeakerCtrl->setSpeakerId(getOtherParticipantId()); @@ -623,6 +811,7 @@ LLAdHocChiclet::Params::Params() unread_notifications.v_pad(5); unread_notifications.text_color(LLColor4::white); unread_notifications.mouse_opaque(false); + unread_notifications.rect(COUNTER_RECT); unread_notifications.visible(false); @@ -697,12 +886,6 @@ void LLAdHocChiclet::switchToCurrentSpeaker() mSpeakerCtrl->setSpeakerId(speaker_id); } -void LLAdHocChiclet::setCounter(S32 counter) -{ - mCounterCtrl->setCounter(counter); - setShowNewMessagesIcon(counter); -} - void LLAdHocChiclet::createPopupMenu() { if(mPopupMenu) @@ -774,6 +957,7 @@ LLIMGroupChiclet::Params::Params() unread_notifications.font_halign(LLFontGL::HCENTER); unread_notifications.v_pad(5); unread_notifications.text_color(LLColor4::white); + unread_notifications.rect(COUNTER_RECT); unread_notifications.visible(false); speaker.name("speaker"); @@ -814,12 +998,6 @@ LLIMGroupChiclet::~LLIMGroupChiclet() LLGroupMgr::getInstance()->removeObserver(this); } -void LLIMGroupChiclet::setCounter(S32 counter) -{ - mCounterCtrl->setCounter(counter); - setShowNewMessagesIcon(counter); -} - void LLIMGroupChiclet::draw() { switchToCurrentSpeaker(); @@ -1493,14 +1671,34 @@ bool LLChicletPanel::isAnyIMFloaterDoked() return res; } +S32 LLChicletPanel::getTotalUnreadIMCount() +{ + S32 count = 0; + chiclet_list_t::const_iterator it = mChicletList.begin(); + for( ; mChicletList.end() != it; ++it) + { + LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); + if(chiclet) + { + count += chiclet->getCounter(); + } + } + return count; +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +LLChicletNotificationCounterCtrl::Params::Params() +: max_displayed_count("max_displayed_count", MAX_DISPLAYED_COUNT) +{ +} LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p) : LLTextBox(p) , mCounter(0) , mInitialWidth(0) + , mMaxDisplayedCount(p.max_displayed_count) { mInitialWidth = getRect().getWidth(); } @@ -1509,11 +1707,21 @@ void LLChicletNotificationCounterCtrl::setCounter(S32 counter) { mCounter = counter; - std::stringstream stream; - stream << getCounter(); + // note same code in LLSysWellChiclet::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() + ); + } + if(mCounter != 0) { - setText(stream.str()); + setText(s_count); } else { |