diff options
Diffstat (limited to 'indra/newview/llchiclet.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/llchiclet.cpp | 1347 |
1 files changed, 575 insertions, 772 deletions
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 340b0fa22c..46b7679915 100644..100755 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1,65 +1,45 @@ /** -* @file llchiclet.cpp -* @brief LLChiclet class implementation -* -* $LicenseInfo:firstyear=2002&license=viewergpl$ -* -* Copyright (c) 2002-2009, Linden Research, Inc. -* -* Second Life Viewer Source Code -* The source code in this file ("Source Code") is provided by Linden Lab -* to you under the terms of the GNU General Public License, version 2.0 -* ("GPL"), unless you have obtained a separate licensing agreement -* ("Other License"), formally executed by you and Linden Lab. Terms of -* the GPL can be found in doc/GPL-license.txt in this distribution, or -* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 -* -* There are special exceptions to the terms and conditions of the GPL as -* it is applied to this Source Code. View the full text of the exception -* in the file doc/FLOSS-exception.txt in this software distribution, or -* online at -* http://secondlifegrid.net/programs/open_source/licensing/flossexception -* -* By copying, modifying or distributing this software, you acknowledge -* that you have read and understood your obligations described above, -* and agree to abide by those obligations. -* -* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO -* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -* COMPLETENESS OR PERFORMANCE. -* $/LicenseInfo$ -*/ + * @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 "llagent.h" -#include "llavataractions.h" -#include "llbottomtray.h" -#include "llgroupactions.h" -#include "lliconctrl.h" -#include "llimpanel.h" // LLFloaterIMPanel -#include "llimfloater.h" -#include "llimview.h" + +#include "llchicletbar.h" +#include "llfloaterimsession.h" +#include "llfloaterimcontainer.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" -#include "llmenugl.h" -#include "lloutputmonitorctrl.h" -#include "lltextbox.h" -#include "llvoiceclient.h" -#include "llvoicecontrolpanel.h" -#include "llgroupmgr.h" -#include "llnotificationmanager.h" -#include "lltransientfloatermgr.h" +#include "llscriptfloater.h" +#include "llsingleton.h" +#include "llsyswellwindow.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); -static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk"); -static LLDefaultChildRegistry::Register<LLNotificationChiclet> t3("chiclet_notification"); -static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t4("chiclet_im_p2p"); -static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t5("chiclet_im_group"); - -S32 LLNotificationChiclet::mUreadSystemNotifications = 0; -S32 LLNotificationChiclet::mUreadIMNotifications = 0; - +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*> > > @@ -68,399 +48,251 @@ boost::signals2::signal<LLChiclet* (const LLUUID&), ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLNotificationChiclet::Params::Params() -: button("button") -, unread_notifications("unread_notifications") +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); - - unread_notifications.name("unread"); - unread_notifications.font(LLFontGL::getFontSansSerif()); - unread_notifications.text_color=(LLColor4::white); - unread_notifications.font_halign(LLFontGL::HCENTER); - unread_notifications.mouse_opaque(FALSE); + button.name = "button"; + button.tab_stop = FALSE; + button.label = LLStringUtil::null; } -LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLChiclet(p) -, mButton(NULL) -, mCounterCtrl(NULL) +LLSysWellChiclet::LLSysWellChiclet(const Params& p) + : LLChiclet(p) + , mButton(NULL) + , mCounter(0) + , mMaxDisplayedCount(p.max_displayed_count) + , mIsNewMessagesState(false) + , mFlashToLitTimer(NULL) + , mContextMenu(NULL) { LLButton::Params button_params = p.button; - button_params.rect(p.rect()); mButton = LLUICtrlFactory::create<LLButton>(button_params); addChild(mButton); - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); - addChild(mCounterCtrl); - - // connect counter handlers to the signals - connectCounterUpdatersToSignal("notify"); - connectCounterUpdatersToSignal("groupnotify"); - connectCounterUpdatersToSignal("notifytoast"); + mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1)); } -LLNotificationChiclet::~LLNotificationChiclet() +LLSysWellChiclet::~LLSysWellChiclet() { - + mFlashToLitTimer->unset(); } -void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notification_type) +void LLSysWellChiclet::setCounter(S32 counter) { - LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); - LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); - if(n_handler) + // 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) { - if(notification_type == "notifytoast") - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this)); - } - else - { - n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); - n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); - } + 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() + ); } -} -void LLNotificationChiclet::setCounter(S32 counter) -{ - mCounterCtrl->setCounter(counter); -} + mButton->setLabel(s_count); -void LLNotificationChiclet::setShowCounter(bool show) -{ - LLChiclet::setShowCounter(show); - mCounterCtrl->setVisible(getShowCounter()); + 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 LLNotificationChiclet::updateUreadIMNotifications() +void LLSysWellChiclet::changeLitState(bool blink) { - mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM(); - setCounter(mUreadSystemNotifications + mUreadIMNotifications); + setNewMessagesState(!mIsNewMessagesState); } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChiclet::Params::Params() - : show_counter("show_counter") -{ - show_counter = true; -} - -LLChiclet::LLChiclet(const Params& p) -: LLUICtrl(p) -, mSessionId(LLUUID::null) -, mShowCounter(p.show_counter) +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; } -LLChiclet::~LLChiclet() +void LLSysWellChiclet::updateWidget(bool is_window_empty) { + mButton->setEnabled(!is_window_empty); + if (LLChicletBar::instanceExists()) + { + LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty); + } } - -boost::signals2::connection LLChiclet::setLeftButtonClickCallback( - const commit_callback_t& cb) -{ - return mCommitSignal.connect(cb); -} - -BOOL LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask) +// virtual +BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { - onCommit(); - childrenHandleMouseDown(x,y,mask); + if(!mContextMenu) + { + createMenu(); + } + if (mContextMenu) + { + mContextMenu->show(x, y); + LLMenuGL::showPopup(this, mContextMenu, x, y); + } return TRUE; } -boost::signals2::connection LLChiclet::setChicletSizeChangedCallback( - const chiclet_size_changed_callback_t& cb) +/************************************************************************/ +/* LLNotificationChiclet implementation */ +/************************************************************************/ +LLNotificationChiclet::LLNotificationChiclet(const Params& p) +: LLSysWellChiclet(p), + mUreadSystemNotifications(0) { - return mChicletSizeChangedSignal.connect(cb); + mNotificationChannel.reset(new ChicletNotificationChannel(this)); + // ensure that notification well window exists, to synchronously + // handle toast add/delete events. + LLNotificationWellWindow::getInstance()->setSysWellChiclet(this); } -void LLChiclet::onChicletSizeChanged() +void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data) { - mChicletSizeChangedSignal(this, getValue()); + std::string action = user_data.asString(); + if("close all" == action) + { + LLNotificationWellWindow::getInstance()->closeAll(); + LLIMWellWindow::getInstance()->closeAll(); + } } -LLSD LLChiclet::getValue() const +bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) { - return LLSD(getSessionId()); + std::string item = user_data.asString(); + if (item == "can close all") + { + return mUreadSystemNotifications != 0; + } + return true; } -void LLChiclet::setValue(const LLSD& value) +void LLNotificationChiclet::createMenu() { - if(value.isUUID()) - setSessionId(value.asUUID()); -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// + if(mContextMenu) + { + LL_WARNS() << "Menu already exists" << LL_ENDL; + return; + } -LLIMChiclet::LLIMChiclet(const LLChiclet::Params& p) -: LLChiclet(p) -{ -} + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("NotificationWellChicletMenu.Action", + boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2)); -void LLIMChiclet::onMouseDown() -{ - LLIMFloater::toggle(getSessionId()); - setCounter(0); -} + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + enable_registrar.add("NotificationWellChicletMenu.EnableItem", + boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); -BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask) -{ - onMouseDown(); - return LLChiclet::handleMouseDown(x, y, mask); + llassert(LLMenuGL::sMenuContainer != NULL); + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> + ("menu_notification_well_button.xml", + LLMenuGL::sMenuContainer, + LLViewerMenuHolderGL::child_registry_t::instance()); } -void LLIMChiclet::draw() +/*virtual*/ +void LLNotificationChiclet::setCounter(S32 counter) { - LLUICtrl::draw(); - - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE); + LLSysWellChiclet::setCounter(counter); + updateWidget(getCounter() == 0); + } -// static -LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) { - EType type = TYPE_UNKNOWN; - - if(session_id.isNull()) - return type; - - EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id); - if (IM_COUNT == im_type) + 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())) + ) { - llassert_always(0 && "IM session not found"); // should never happen - return type; + displayNotification = false; } - - switch(im_type) + else if( !(notification->canLogToIM() && notification->hasFormElements()) + && (!notification->getPayload().has("give_inventory_notification") + || notification->getPayload()["give_inventory_notification"])) { - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - type = TYPE_IM; - break; - case IM_SESSION_GROUP_START: - case IM_SESSION_INVITE: - if (gAgent.isInGroup(session_id)) - { - type = TYPE_GROUP; - } - else - { - type = TYPE_AD_HOC; - } - break; - case IM_SESSION_CONFERENCE_START: - type = TYPE_AD_HOC; - default: - break; + displayNotification = true; } - - return type; + else + { + displayNotification = false; + } + return displayNotification; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLIMP2PChiclet::Params::Params() -: avatar_icon("avatar_icon") -, unread_notifications("unread_notifications") -, speaker("speaker") -, show_speaker("show_speaker") -{ - // *TODO Vadim: Get rid of hardcoded values. - rect(LLRect(0, 25, 45, 0)); - - avatar_icon.name("avatar_icon"); - avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - - // *NOTE dzaporozhan - // Changed icon height from 25 to 24 to fix ticket EXT-794. - // In some cases(after changing UI scale) 25 pixel height icon was - // drawn incorrectly, i'm not sure why. - avatar_icon.rect(LLRect(0, 24, 25, 0)); - avatar_icon.mouse_opaque(false); - - unread_notifications.name("unread"); - unread_notifications.rect(LLRect(25, 25, 45, 0)); - unread_notifications.font(LLFontGL::getFontSansSerif()); - unread_notifications.font_halign(LLFontGL::HCENTER); - unread_notifications.v_pad(5); - unread_notifications.text_color(LLColor4::white); - unread_notifications.mouse_opaque(false); - - speaker.name("speaker"); - speaker.rect(LLRect(45, 25, 65, 0)); - - show_speaker = false; -} - -LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) -: LLIMChiclet(p) -, mChicletIconCtrl(NULL) -, mCounterCtrl(NULL) -, mSpeakerCtrl(NULL) -, mPopupMenu(NULL) +LLChiclet::Params::Params() + : show_counter("show_counter", true) + , enable_counter("enable_counter", false) { - LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params); - addChild(mSpeakerCtrl); - - setShowSpeaker(p.show_speaker); } -void LLIMP2PChiclet::setCounter(S32 counter) -{ - mCounterCtrl->setCounter(counter); - - if(getShowCounter()) - { - LLRect counter_rect = mCounterCtrl->getRect(); - LLRect required_rect = mCounterCtrl->getRequiredRect(); - bool needs_resize = required_rect.getWidth() != counter_rect.getWidth(); - - if(needs_resize) - { - counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth(); - mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight()); - mCounterCtrl->setRect(counter_rect); - - onChicletSizeChanged(); - } - } -} - -LLRect LLIMP2PChiclet::getRequiredRect() +LLChiclet::LLChiclet(const Params& p) +: LLUICtrl(p) +, mSessionId(LLUUID::null) +, mShowCounter(p.show_counter) { - LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0); - if(getShowCounter()) - { - rect.mRight += mCounterCtrl->getRequiredRect().getWidth(); - } - if(getShowSpeaker()) - { - rect.mRight += mSpeakerCtrl->getRect().getWidth(); - } - return rect; } -void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id) +boost::signals2::connection LLChiclet::setLeftButtonClickCallback( + const commit_callback_t& cb) { - LLIMChiclet::setOtherParticipantId(other_participant_id); - mChicletIconCtrl->setValue(getOtherParticipantId()); + return setCommitCallback(cb); } -void LLIMP2PChiclet::updateMenuItems() +BOOL LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask) { - if(!mPopupMenu) - return; - if(getSessionId().isNull()) - return; - - bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); - - mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend); - mPopupMenu->getChild<LLUICtrl>("Remove Friend")->setEnabled(is_friend); + onCommit(); + childrenHandleMouseDown(x,y,mask); + return TRUE; } -BOOL LLIMP2PChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) +boost::signals2::connection LLChiclet::setChicletSizeChangedCallback( + const chiclet_size_changed_callback_t& cb) { - if(!mPopupMenu) - { - createPopupMenu(); - } - - if (mPopupMenu) - { - updateMenuItems(); - mPopupMenu->arrangeAndClear(); - LLMenuGL::showPopup(this, mPopupMenu, x, y); - } - - return TRUE; + return mChicletSizeChangedSignal.connect(cb); } -void LLIMP2PChiclet::createPopupMenu() +void LLChiclet::onChicletSizeChanged() { - if(mPopupMenu) - { - llwarns << "Menu already exists" << llendl; - return; - } - if(getSessionId().isNull()) - { - return; - } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mChicletSizeChangedSignal(this, getValue()); } -void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data) +LLSD LLChiclet::getValue() const { - std::string level = user_data.asString(); - LLUUID other_participant_id = getOtherParticipantId(); - - if("profile" == level) - { - LLAvatarActions::showProfile(other_participant_id); - } - else if("im" == level) - { - LLAvatarActions::startIM(other_participant_id); - } - else if("add" == level) - { - LLAvatarActions::requestFriendshipDialog(other_participant_id); - } + return LLSD(getSessionId()); } -void LLIMP2PChiclet::setShowSpeaker(bool show) +void LLChiclet::setValue(const LLSD& value) { - LLIMChiclet::setShowSpeaker(show); - - bool needs_resize = getShowSpeaker() != show; - mSpeakerCtrl->setVisible(getShowSpeaker()); - if(needs_resize) + if(value.isUUID()) { - onChicletSizeChanged(); + setSessionId(value.asUUID()); } } @@ -468,133 +300,66 @@ void LLIMP2PChiclet::setShowSpeaker(bool show) ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLIMGroupChiclet::Params::Params() -: group_icon("group_icon") -{ - rect(LLRect(0, 25, 45, 0)); - - group_icon.name("group_icon"); - - // *NOTE dzaporozhan - // Changed icon height from 25 to 24 to fix ticket EXT-794. - // In some cases(after changing UI scale) 25 pixel height icon was - // drawn incorrectly, i'm not sure why. - group_icon.rect(LLRect(0, 24, 25, 0)); - - unread_notifications.name("unread"); - unread_notifications.rect(LLRect(25, 25, 45, 0)); - unread_notifications.font(LLFontGL::getFontSansSerif()); - unread_notifications.font_halign(LLFontGL::HCENTER); - unread_notifications.v_pad(5); - unread_notifications.text_color(LLColor4::white); - - speaker.name("speaker"); - speaker.rect(LLRect(45, 25, 65, 0)); - - show_speaker = false; -} - -LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) -: LLIMChiclet(p) -, LLGroupMgrObserver(LLUUID::null) -, mChicletIconCtrl(NULL) -, mCounterCtrl(NULL) -, mSpeakerCtrl(NULL) +LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) +: LLChiclet(p) +, mShowSpeaker(false) +, mDefaultWidth(p.rect().getWidth()) +, mNewMessagesIcon(NULL) +, mChicletButton(NULL) , mPopupMenu(NULL) { - LLChicletGroupIconCtrl::Params avatar_params = p.group_icon; - mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params); - addChild(mChicletIconCtrl); - - LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; - mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params); - addChild(mCounterCtrl); - - setCounter(getCounter()); - setShowCounter(getShowCounter()); - - LLChicletSpeakerCtrl::Params speaker_params = p.speaker; - mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params); - addChild(mSpeakerCtrl); - - setShowSpeaker(p.show_speaker); } -LLIMGroupChiclet::~LLIMGroupChiclet() +/* virtual*/ +BOOL LLIMChiclet::postBuild() { - LLGroupMgr::getInstance()->removeObserver(this); + mChicletButton = getChild<LLButton>("chiclet_button"); + mChicletButton->setCommitCallback(boost::bind(&LLIMChiclet::onMouseDown, this)); + mChicletButton->setDoubleClickCallback(boost::bind(&LLIMChiclet::onMouseDown, this)); + return TRUE; } -void LLIMGroupChiclet::setCounter(S32 counter) +void LLIMChiclet::enableCounterControl(bool enable) { - mCounterCtrl->setCounter(counter); - - if(getShowCounter()) + mCounterEnabled = enable; + if(!enable) { - LLRect counter_rect = mCounterCtrl->getRect(); - LLRect required_rect = mCounterCtrl->getRequiredRect(); - bool needs_resize = required_rect.getWidth() != counter_rect.getWidth(); - - if(needs_resize) - { - counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth(); - mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight()); - mCounterCtrl->setRect(counter_rect); - - onChicletSizeChanged(); - } + LLChiclet::setShowCounter(false); } } -LLRect LLIMGroupChiclet::getRequiredRect() +void LLIMChiclet::setRequiredWidth() { - LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0); - if(getShowCounter()) - { - rect.mRight += mCounterCtrl->getRequiredRect().getWidth(); - } - if(getShowSpeaker()) + S32 required_width = mDefaultWidth; + reshape(required_width, getRect().getHeight()); + onChicletSizeChanged(); +} + +void LLIMChiclet::setShowNewMessagesIcon(bool show) +{ + if(mNewMessagesIcon) { - rect.mRight += mSpeakerCtrl->getRect().getWidth(); + mNewMessagesIcon->setVisible(show); } - return rect; + setRequiredWidth(); } -void LLIMGroupChiclet::setSessionId(const LLUUID& session_id) +bool LLIMChiclet::getShowNewMessagesIcon() { - LLChiclet::setSessionId(session_id); + return mNewMessagesIcon->getVisible(); +} - LLGroupMgr* grp_mgr = LLGroupMgr::getInstance(); - LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id); - if (group_data && group_data->mInsigniaID.notNull()) - { - mChicletIconCtrl->setValue(group_data->mInsigniaID); - } - else - { - if(getSessionId() != mID) - { - grp_mgr->removeObserver(this); - mID = getSessionId(); - grp_mgr->addObserver(this); - } - grp_mgr->sendGroupPropertiesRequest(session_id); - } +void LLIMChiclet::onMouseDown() +{ + LLFloaterIMSession::toggle(getSessionId()); } -void LLIMGroupChiclet::changed(LLGroupChange gc) +void LLIMChiclet::setToggleState(bool toggle) { - if (GC_PROPERTIES == gc) - { - LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId()); - if (group_data) - { - mChicletIconCtrl->setValue(group_data->mInsigniaID); - } - } + mChicletButton->setToggleState(toggle); } -BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) +BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { if(!mPopupMenu) { @@ -603,6 +368,7 @@ BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) if (mPopupMenu) { + updateMenuItems(); mPopupMenu->arrangeAndClear(); LLMenuGL::showPopup(this, mPopupMenu, x, y); } @@ -610,50 +376,26 @@ BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) return TRUE; } -void LLIMGroupChiclet::createPopupMenu() +void LLIMChiclet::hidePopupMenu() { - if(mPopupMenu) - { - llwarns << "Menu already exists" << llendl; - return; - } - if(getSessionId().isNull()) + if (mPopupMenu) { - return; + mPopupMenu->setVisible(FALSE); } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2)); - - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> - ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); } -void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data) +bool LLIMChiclet::canCreateMenu() { - std::string level = user_data.asString(); - LLUUID group_id = getSessionId(); - - if("group chat" == level) - { - LLGroupActions::startChat(group_id); - } - else if("info" == level) + if(mPopupMenu) { - LLGroupActions::show(group_id); + LL_WARNS() << "Menu already exists" << LL_ENDL; + return false; } -} - -void LLIMGroupChiclet::setShowSpeaker(bool show) -{ - LLIMChiclet::setShowSpeaker(show); - - bool needs_resize = getShowSpeaker() != show; - mSpeakerCtrl->setVisible(getShowSpeaker()); - if(needs_resize) + if(getSessionId().isNull()) { - onChicletSizeChanged(); + return false; } + return true; } ////////////////////////////////////////////////////////////////////////// @@ -663,31 +405,10 @@ void LLIMGroupChiclet::setShowSpeaker(bool show) LLChicletPanel::Params::Params() : chiclet_padding("chiclet_padding") , scrolling_offset("scrolling_offset") -, left_scroll_button("left_scroll_button") -, right_scroll_button("right_scroll_button") +, scroll_button_hpad("scroll_button_hpad") +, scroll_ratio("scroll_ratio") , min_width("min_width") { - chiclet_padding = 3; - scrolling_offset = 40; - min_width = 70; - - LLRect scroll_button_rect(0, 25, 19, 5); - - left_scroll_button.name("left_scroll"); - left_scroll_button.label(LLStringUtil::null); - left_scroll_button.rect(scroll_button_rect); - left_scroll_button.tab_stop(false); - left_scroll_button.image_selected(LLUI::getUIImage("bottom_tray_scroll_left.tga")); - left_scroll_button.image_unselected(LLUI::getUIImage("bottom_tray_scroll_left.tga")); - left_scroll_button.image_hover_selected(LLUI::getUIImage("bottom_tray_scroll_left.tga")); - - right_scroll_button.name("right_scroll"); - right_scroll_button.label(LLStringUtil::null); - right_scroll_button.rect(scroll_button_rect); - right_scroll_button.tab_stop(false); - right_scroll_button.image_selected(LLUI::getUIImage("bottom_tray_scroll_right.tga")); - right_scroll_button.image_unselected(LLUI::getUIImage("bottom_tray_scroll_right.tga")); - right_scroll_button.image_hover_selected(LLUI::getUIImage("bottom_tray_scroll_right.tga")); }; LLChicletPanel::LLChicletPanel(const Params&p) @@ -697,25 +418,13 @@ LLChicletPanel::LLChicletPanel(const Params&p) , 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) { - LLButton::Params scroll_button_params = p.left_scroll_button; - - mLeftScrollButton = LLUICtrlFactory::create<LLButton>(scroll_button_params); - addChild(mLeftScrollButton); - - mLeftScrollButton->setClickedCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this)); - mLeftScrollButton->setEnabled(false); - - scroll_button_params = p.right_scroll_button; - mRightScrollButton = LLUICtrlFactory::create<LLButton>(scroll_button_params); - addChild(mRightScrollButton); - - mRightScrollButton->setClickedCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this)); - mRightScrollButton->setEnabled(false); - 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 @@ -726,62 +435,134 @@ LLChicletPanel::LLChicletPanel(const Params&p) 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 im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){ - - LLUUID session_id = data["session_id"].asUUID(); - std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id); +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++) { - LLChiclet* chiclet = *iter; + for (iter = chiclets.begin(); iter != chiclets.end(); iter++) + { + LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter); if (chiclet != NULL) { - chiclet->setCounter(data["num_unread"].asInteger()); + chiclet->setShowNewMessagesIcon(new_message); } - else - { - llwarns << "Unable to set counter for chiclet " << session_id << llendl; - } } - } - BOOL LLChicletPanel::postBuild() { LLPanel::postBuild(); - LLIMModel::instance().addChangedCallback(boost::bind(im_chiclet_callback, this, _1)); + 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)) { - S32 offset = 0; + // chiclets should be aligned to right edge of scroll panel + S32 left_shift = 0; - // if index == 0 and chickelt list isn't empty insert chiclet before first in the list - // without scrolling, so other visible chicklets aren't change screen position - if (0 == index && !mChicletList.empty()) + if (!canScrollLeft()) { - offset = getChiclet(0)->getRect().mLeft - - (chiclet->getRequiredRect().getWidth() - + getChicletPadding()); + // 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); - getChiclet(0)->translate(offset, 0); + // 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(); - showScrollButtonsIfNeeded(); + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet); return true; } @@ -791,40 +572,26 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) { - S32 chiclet_width = ctrl->getRect().getWidth(); - S32 chiclet_new_width = ctrl->getRequiredRect().getWidth(); - - if(chiclet_new_width == chiclet_width) - { - return; - } - - LLRect chiclet_rect = ctrl->getRect(); - chiclet_rect.mRight = chiclet_rect.mLeft + chiclet_new_width; - - ctrl->setRect(chiclet_rect); - - S32 offset = chiclet_new_width - chiclet_width; - S32 index = getChicletIndex(ctrl); - - shiftChiclets(offset, index + 1); - trimChiclets(); - showScrollButtonsIfNeeded(); + arrange(); } void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) { - mCommitSignal(ctrl,param); + if (mCommitSignal) + { + (*mCommitSignal)(ctrl,param); + } } void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it) { - mScrollArea->removeChild(*it); + LLChiclet* chiclet = *it; + mScrollArea->removeChild(chiclet); mChicletList.erase(it); arrange(); - trimChiclets(); - showScrollButtonsIfNeeded(); + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet); + chiclet->die(); } void LLChicletPanel::removeChiclet(S32 index) @@ -917,25 +684,76 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) { LLPanel::reshape(width,height,called_from_parent); - static const S32 SCROLL_BUTTON_PAD = 5; - + //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,height,scroll_button_rect.getWidth(), - height - scroll_button_rect.getHeight())); - + 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(),height, - width, height - scroll_button_rect.getHeight())); - - mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, - height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); + mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop, + width, scroll_button_rect.mBottom)); + - mShowControls = width > mMinWidth; + 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() @@ -943,8 +761,8 @@ 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) { @@ -958,32 +776,52 @@ void LLChicletPanel::arrange() 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(canScrollLeft() && !canScrollRight()) + 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) + if(last_chiclet_right < scroll_width || first_chiclet_left > 0) { shiftChiclets(scroll_width - last_chiclet_right); } } +} - // trim left - if(!mChicletList.empty()) - { - LLRect first_chiclet_rect = getChiclet(0)->getRect(); - if(first_chiclet_rect.mLeft > 0) - { - shiftChiclets( - first_chiclet_rect.mLeft); - } - } +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(); @@ -1108,10 +946,26 @@ 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 mCommitSignal.connect(cb); + return setCommitCallback(cb); } BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks) @@ -1133,7 +987,7 @@ bool LLChicletPanel::isAnyIMFloaterDoked() for (chiclet_list_t::iterator it = mChicletList.begin(); it != mChicletList.end(); it++) { - LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>( + LLFloaterIMSession* im_floater = LLFloaterReg::findTypedInstance<LLFloaterIMSession>( "impanel", (*it)->getSessionId()); if (im_floater != NULL && im_floater->getVisible() && !im_floater->isMinimized() && im_floater->isDocked()) @@ -1149,234 +1003,183 @@ bool LLChicletPanel::isAnyIMFloaterDoked() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// - -// *TODO Vadim: Move this out of llchiclet.cpp. - -LLTalkButton::Params::Params() - : speak_button("speak_button") - , show_button("show_button") - , monitor("monitor") -{ - // *TODO Vadim: move hardcoded labels (!) and other params to XUI. - speak_button.name("left"); - speak_button.label("Speak"); - speak_button.label_selected("Speak"); - speak_button.font(LLFontGL::getFontSansSerifSmall()); - speak_button.tab_stop(false); - speak_button.is_toggle(true); - speak_button.picture_style(true); - // Use default button art. JC - //speak_button.image_selected(LLUI::getUIImage("SegmentedBtn_Left_Selected")); - //speak_button.image_unselected(LLUI::getUIImage("SegmentedBtn_Left_Off")); - - show_button.name("right"); - show_button.label(LLStringUtil::null); - show_button.rect(LLRect(0, 0, 20, 0)); - show_button.tab_stop(false); - show_button.is_toggle(true); - show_button.picture_style(true); - show_button.image_selected(LLUI::getUIImage("ComboButton_Selected")); - show_button.image_unselected(LLUI::getUIImage("ComboButton_Off")); - - monitor.name("monitor"); - // *TODO: Make this data driven. - monitor.rect(LLRect(0, 18, 18, 0)); -} - -LLTalkButton::LLTalkButton(const Params& p) -: LLUICtrl(p) -, mPrivateCallPanel(NULL) -, mOutputMonitor(NULL) -, mSpeakBtn(NULL) -, mShowBtn(NULL) +LLChicletNotificationCounterCtrl::Params::Params() + : max_displayed_count("max_displayed_count", 99) { - LLRect rect = p.rect(); - LLRect speak_rect(0, rect.getHeight(), rect.getWidth(), 0); - LLRect show_rect = p.show_button.rect(); - show_rect.set(0, rect.getHeight(), show_rect.getWidth(), 0); - - speak_rect.mRight -= show_rect.getWidth(); - show_rect.mLeft = speak_rect.getWidth(); - show_rect.mRight = rect.getWidth(); - - LLButton::Params speak_params = p.speak_button; - speak_params.rect(speak_rect); - mSpeakBtn = LLUICtrlFactory::create<LLButton>(speak_params); - addChild(mSpeakBtn); - LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn); - - mSpeakBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_SpeakBtn, this)); - mSpeakBtn->setToggleState(FALSE); - - LLButton::Params show_params = p.show_button; - show_params.rect(show_rect); - mShowBtn = LLUICtrlFactory::create<LLButton>(show_params); - addChild(mShowBtn); - LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn); - - mShowBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_ShowBtn, this)); - mShowBtn->setToggleState(FALSE); - - static const S32 MONITOR_RIGHT_PAD = 2; - - LLRect monitor_rect = p.monitor.rect(); - S32 monitor_height = monitor_rect.getHeight(); - monitor_rect.mLeft = speak_rect.getWidth() - monitor_rect.getWidth() - MONITOR_RIGHT_PAD; - monitor_rect.mRight = speak_rect.getWidth() - MONITOR_RIGHT_PAD; - monitor_rect.mBottom = (rect.getHeight() / 2) - (monitor_height / 2); - monitor_rect.mTop = monitor_rect.mBottom + monitor_height; - - LLOutputMonitorCtrl::Params monitor_params = p.monitor; - monitor_params.draw_border(false); - monitor_params.rect(monitor_rect); - monitor_params.auto_update(true); - monitor_params.speaker_id(gAgentID); - mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_params); - mSpeakBtn->addChild(mOutputMonitor); - - // never show "muted" because you can't mute yourself - mOutputMonitor->setIsMuted(false); } -LLTalkButton::~LLTalkButton() +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p) + : LLAvatarIconCtrl(p) { } -void LLTalkButton::setSpeakBtnToggleState(bool state) -{ - mSpeakBtn->setToggleState(state); -} +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// -void LLTalkButton::onClick_SpeakBtn() +LLChicletInvOfferIconCtrl::LLChicletInvOfferIconCtrl(const Params& p) +: LLChicletAvatarIconCtrl(p) + , mDefaultIcon(p.default_icon) { - bool speaking = mSpeakBtn->getToggleState(); - gVoiceClient->setUserPTTState(speaking); } -void LLTalkButton::onClick_ShowBtn() +void LLChicletInvOfferIconCtrl::setValue(const LLSD& value ) { - if(!mShowBtn->getToggleState()) + if(value.asUUID().isNull()) { - mPrivateCallPanel->onClickClose(mPrivateCallPanel); - delete mPrivateCallPanel; - mPrivateCallPanel = NULL; - mShowBtn->setToggleState(FALSE); - return; + LLIconCtrl::setValue(mDefaultIcon); } + else + { + LLChicletAvatarIconCtrl::setValue(value); + } +} - S32 x = mSpeakBtn->getRect().mLeft; - S32 y = 0; +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// - localPointToScreen(x, y, &x, &y); +LLScriptChiclet::Params::Params() + : icon("icon") + , chiclet_button("chiclet_button") + , new_message_icon("new_message_icon") +{ +} - mPrivateCallPanel = new LLVoiceControlPanel; - getRootView()->addChild(mPrivateCallPanel); +LLScriptChiclet::LLScriptChiclet(const Params&p) + : LLIMChiclet(p) + , mChicletIconCtrl(NULL) +{ + LLButton::Params button_params = p.chiclet_button; + mChicletButton = LLUICtrlFactory::create<LLButton>(button_params); + addChild(mChicletButton); - y = LLBottomTray::getInstance()->getRect().getHeight() + mPrivateCallPanel->getRect().getHeight(); + LLIconCtrl::Params new_msg_params = p.new_message_icon; + mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params); + addChild(mNewMessagesIcon); - LLRect rect; - rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight()); - mPrivateCallPanel->setRect(rect); + LLIconCtrl::Params icon_params = p.icon; + mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params); + addChild(mChicletIconCtrl); + sendChildToFront(mNewMessagesIcon); +} - LLAvatarListItem* item = new LLAvatarListItem(); - item->showStatus(true); - item->showInfoBtn(true); - item->showSpeakingIndicator(true); - item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE); +void LLScriptChiclet::setSessionId(const LLUUID& session_id) +{ + setShowNewMessagesIcon( getSessionId() != session_id ); - mPrivateCallPanel->addItem(item); - mPrivateCallPanel->setVisible(TRUE); - mPrivateCallPanel->setFrontmost(TRUE); + LLIMChiclet::setSessionId(session_id); - mShowBtn->setToggleState(TRUE); + setToolTip(LLScriptFloaterManager::getObjectName(session_id)); } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p) - : LLTextBox(p) - , mCounter(0) - , mInitialWidth(0) +void LLScriptChiclet::onMouseDown() { - mInitialWidth = getRect().getWidth(); + LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); } -void LLChicletNotificationCounterCtrl::setCounter(S32 counter) +void LLScriptChiclet::onMenuItemClicked(const LLSD& user_data) { - mCounter = counter; + std::string action = user_data.asString(); - std::stringstream stream; - stream << getCounter(); - if(mCounter != 0) - { - setText(stream.str()); - } - else + if("end" == action) { - setText(std::string("")); + LLScriptFloaterManager::instance().removeNotification(getSessionId()); } } -LLRect LLChicletNotificationCounterCtrl::getRequiredRect() +void LLScriptChiclet::createPopupMenu() { - LLRect rc; - S32 text_width = getContentsRect().getWidth(); - - rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth); - - return rc; -} + if(!canCreateMenu()) + return; -void LLChicletNotificationCounterCtrl::setValue(const LLSD& value) -{ - if(value.isInteger()) - setCounter(value.asInteger()); -} + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2)); -LLSD LLChicletNotificationCounterCtrl::getValue() const -{ - return LLSD(getCounter()); + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> + ("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p) - : LLAvatarIconCtrl(p) +static const std::string INVENTORY_USER_OFFER ("UserGiveItem"); + +LLInvOfferChiclet::Params::Params() + : icon("icon") + , chiclet_button("chiclet_button") + , new_message_icon("new_message_icon") { } -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p) -: LLIconCtrl(p) -, mDefaultIcon(p.default_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 LLChicletGroupIconCtrl::setValue(const LLSD& value ) +void LLInvOfferChiclet::setSessionId(const LLUUID& session_id) { - if(value.asUUID().isNull()) + 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 ) { - LLIconCtrl::setValue(mDefaultIcon); + mChicletIconCtrl->setValue(notification->getPayload()["from_id"]); } else { - LLIconCtrl::setValue(value); + 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()); + } +} -LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) - : LLIconCtrl(p) +void LLInvOfferChiclet::createPopupMenu() { + if(!canCreateMenu()) + return; + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2)); + + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> + ("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); } + +// EOF |