/** * @file llchiclet.h * @brief LLChiclet class header file * * $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$ */ #ifndef LL_LLCHICLET_H #define LL_LLCHICLET_H #include "llavatariconctrl.h" #include "llbutton.h" #include "llpanel.h" #include "lltextbox.h" #include "lloutputmonitorctrl.h" #include "llgroupmgr.h" class LLVoiceControlPanel; class LLMenuGL; class LLIMFloater; /* * Class for displaying amount of messages/notifications(unread). */ class LLChicletNotificationCounterCtrl : public LLTextBox { public: struct Params : public LLInitParam::Block<Params, LLTextBox::Params> { Params() {}; }; /* * Sets number of notifications */ virtual void setCounter(S32 counter); /* * Returns number of notifications */ virtual S32 getCounter() const { return mCounter; } /* * Returns width, required to display amount of notifications in text form. * Width is the only valid value. */ /*virtual*/ LLRect getRequiredRect(); /* * Sets number of notifications using LLSD */ /*virtual*/ void setValue(const LLSD& value); /* * Returns number of notifications wrapped in LLSD */ /*virtual*/ LLSD getValue() const; protected: LLChicletNotificationCounterCtrl(const Params& p); friend class LLUICtrlFactory; private: S32 mCounter; S32 mInitialWidth; }; /* * Class for displaying avatar's icon in P2P chiclet. */ class LLChicletAvatarIconCtrl : public LLAvatarIconCtrl { public: struct Params : public LLInitParam::Block<Params, LLAvatarIconCtrl::Params> { Params() { draw_tooltip(FALSE); mouse_opaque(FALSE); default_icon_name("Generic_Person"); }; }; protected: LLChicletAvatarIconCtrl(const Params& p); friend class LLUICtrlFactory; }; /** * Class for displaying group's icon in Group chiclet. */ class LLChicletGroupIconCtrl : public LLIconCtrl { public: struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params> { Optional<std::string> default_icon; Params() : default_icon("default_icon", "Generic_Group") { }; }; /** * Sets icon, if value is LLUUID::null - default icon will be set. */ virtual void setValue(const LLSD& value ); protected: LLChicletGroupIconCtrl(const Params& p); friend class LLUICtrlFactory; std::string mDefaultIcon; }; /* * Class for displaying of speaker's voice indicator */ class LLChicletSpeakerCtrl : public LLOutputMonitorCtrl { public: struct Params : public LLInitParam::Block<Params, LLOutputMonitorCtrl::Params> { Params(){}; }; protected: LLChicletSpeakerCtrl(const Params&p); friend class LLUICtrlFactory; }; /* * Base class for all chiclets. */ class LLChiclet : public LLUICtrl { public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { Optional<bool> show_counter; Params(); }; /*virtual*/ ~LLChiclet(); /* * Associates chat session id with chiclet. */ virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; } /* * Returns associated chat session. */ virtual const LLUUID& getSessionId() const { return mSessionId; } /* * Sets number of unread notifications. */ virtual void setCounter(S32 counter) = 0; /* * Returns number of unread notifications. */ virtual S32 getCounter() = 0; /* * Sets show counter state. */ virtual void setShowCounter(bool show) { mShowCounter = show; } /* * Returns show counter state. */ virtual bool getShowCounter() {return mShowCounter;}; /* * Connects chiclet clicked event with callback. */ /*virtual*/ boost::signals2::connection setLeftButtonClickCallback( const commit_callback_t& cb); typedef boost::function<void (LLChiclet* ctrl, const LLSD& param)> chiclet_size_changed_callback_t; /* * Connects chiclets size changed event with callback. */ virtual boost::signals2::connection setChicletSizeChangedCallback( const chiclet_size_changed_callback_t& cb); /* * Sets IM Session id using LLSD */ /*virtual*/ LLSD getValue() const; /* * Returns IM Session id using LLSD */ /*virtual*/ void setValue(const LLSD& value); protected: friend class LLUICtrlFactory; LLChiclet(const Params& p); /* * Notifies subscribers about click on chiclet. */ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /* * Notifies subscribers about chiclet size changed event. */ virtual void onChicletSizeChanged(); private: LLUUID mSessionId; bool mShowCounter; typedef boost::signals2::signal<void (LLChiclet* ctrl, const LLSD& param)> chiclet_size_changed_signal_t; chiclet_size_changed_signal_t mChicletSizeChangedSignal; }; /* * Base class for Instant Message chiclets. * IMChiclet displays icon, number of unread messages(optional) * and voice chat status(optional). */ class LLIMChiclet : public LLChiclet { public: enum EType { TYPE_UNKNOWN, TYPE_IM, TYPE_GROUP, TYPE_AD_HOC }; struct Params : public LLInitParam::Block<Params, LLChiclet::Params> { Optional<std::string> new_messages_icon_name; Params() : new_messages_icon_name("new_messages_icon_name", "icn_voice-localchat.tga") {} }; /*virtual*/ ~LLIMChiclet() {}; /* * Sets IM session name. This name will be displayed in chiclet tooltip. */ virtual void setIMSessionName(const std::string& name) { setToolTip(name); } /* * Sets id of person/group user is chatting with. * Session id should be set before calling this */ virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; } /* * Gets id of person/group user is chatting with. */ virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; } /* * Init Speaker Control with speaker's ID */ virtual void initSpeakerControl(); /* * set status (Shows/Hide) for voice control. */ virtual void setShowSpeaker(bool show); /* * Returns voice chat status control visibility. */ virtual bool getShowSpeaker() {return mShowSpeaker;}; /* * Shows/Hides for voice control for a chiclet. */ virtual void toggleSpeakerControl(); /* * Shows/hides overlay icon concerning new unread messages. */ virtual void setShowNewMessagesIcon(bool show); /* * Returns visibility of overlay icon concerning new unread messages. */ virtual bool getShowNewMessagesIcon(); virtual void draw(); /** * Determine whether given ID refers to a group or an IM chat session. * * This is used when we need to chose what IM chiclet (P2P/group) * class to instantiate. * * @param session_id session ID. * @return TYPE_GROUP in case of group chat session, * TYPE_IM in case of P2P session, * TYPE_UNKNOWN otherwise. */ static EType getIMSessionType(const LLUUID& session_id); /** * The action taken on mouse down event. * * Made public so that it can be triggered from outside * (more specifically, from the Active IM window). */ void onMouseDown(); protected: LLIMChiclet(const LLIMChiclet::Params& p); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); protected: bool mShowSpeaker; LLIconCtrl* mNewMessagesIcon; LLChicletNotificationCounterCtrl* mCounterCtrl; LLChicletSpeakerCtrl* mSpeakerCtrl; /** the id of another participant, either an avatar id or a group id*/ LLUUID mOtherParticipantId; template<typename Container> struct CollectChicletCombiner { typedef Container result_type; template<typename InputIterator> Container operator()(InputIterator first, InputIterator last) const { Container c = Container(); for (InputIterator iter = first; iter != last; iter++) { if (*iter != NULL) { c.push_back(*iter); } } return c; } }; public: static boost::signals2::signal<LLChiclet* (const LLUUID&), CollectChicletCombiner<std::list<LLChiclet*> > > sFindChicletsSignal; }; /** * Implements P2P chiclet. */ class LLIMP2PChiclet : public LLIMChiclet { public: struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params> { Optional<LLChicletAvatarIconCtrl::Params> avatar_icon; Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; Optional<LLChicletSpeakerCtrl::Params> speaker; Optional<bool> show_speaker; Params(); }; /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id); /* * Sets number of unread messages. Will update chiclet's width if number text * exceeds size of counter and notify it's parent about size change. */ /*virtual*/ void setCounter(S32); /* * Init Speaker Control with speaker's ID */ /*virtual*/ void initSpeakerControl(); /* * Returns number of unread messages. */ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } protected: LLIMP2PChiclet(const Params& p); friend class LLUICtrlFactory; /* * Creates chiclet popup menu. Will create P2P or Group IM Chat menu * based on other participant's id. */ virtual void createPopupMenu(); /* * Processes clicks on chiclet popup menu. */ virtual void onMenuItemClicked(const LLSD& user_data); /* * Displays popup menu. */ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /* * Enables/disables menus based on relationship with other participant. */ virtual void updateMenuItems(); private: LLChicletAvatarIconCtrl* mChicletIconCtrl; LLMenuGL* mPopupMenu; }; /** * Implements AD-HOC chiclet. */ class LLAdHocChiclet : public LLIMChiclet { public: struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params> { Optional<LLChicletAvatarIconCtrl::Params> avatar_icon; Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; Optional<LLChicletSpeakerCtrl::Params> speaker; Optional<bool> show_speaker; Optional<LLColor4> avatar_icon_color; Params(); }; /** * Sets session id. * Session ID for group chat is actually Group ID. */ /*virtual*/ void setSessionId(const LLUUID& session_id); /* * Sets number of unread messages. Will update chiclet's width if number text * exceeds size of counter and notify it's parent about size change. */ /*virtual*/ void setCounter(S32); /* * Keep Speaker Control with actual speaker's ID */ /*virtual*/ void draw(); /* * Init Speaker Control with speaker's ID */ /*virtual*/ void initSpeakerControl(); /* * Returns number of unread messages. */ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } protected: LLAdHocChiclet(const Params& p); friend class LLUICtrlFactory; /* * Displays popup menu. */ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /* * Finds a current speaker and resets the SpeakerControl with speaker's ID */ /*virtual*/ void switchToCurrentSpeaker(); private: LLChicletAvatarIconCtrl* mChicletIconCtrl; LLMenuGL* mPopupMenu; }; /** * Implements Group chat chiclet. */ class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver { public: struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params> { Optional<LLChicletGroupIconCtrl::Params> group_icon; Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; Optional<LLChicletSpeakerCtrl::Params> speaker; Optional<bool> show_speaker; Params(); }; /** * Sets session id. * Session ID for group chat is actually Group ID. */ /*virtual*/ void setSessionId(const LLUUID& session_id); /* * Keep Speaker Control with actual speaker's ID */ /*virtual*/ void draw(); /** * Callback for LLGroupMgrObserver, we get this when group data is available or changed. * Sets group icon. */ /*virtual*/ void changed(LLGroupChange gc); /* * Sets number of unread messages. Will update chiclet's width if number text * exceeds size of counter and notify it's parent about size change. */ /*virtual*/ void setCounter(S32); /* * Init Speaker Control with speaker's ID */ /*virtual*/ void initSpeakerControl(); /* * Returns number of unread messages. */ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } ~LLIMGroupChiclet(); protected: LLIMGroupChiclet(const Params& p); friend class LLUICtrlFactory; /* * Finds a current speaker and resets the SpeakerControl with speaker's ID */ /*virtual*/ void switchToCurrentSpeaker(); /* * Creates chiclet popup menu. Will create P2P or Group IM Chat menu * based on other participant's id. */ virtual void createPopupMenu(); /* * Processes clicks on chiclet popup menu. */ virtual void onMenuItemClicked(const LLSD& user_data); /* * Displays popup menu. */ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); private: LLChicletGroupIconCtrl* mChicletIconCtrl; LLMenuGL* mPopupMenu; }; /* * Implements notification chiclet. Used to display total amount of unread messages * across all IM sessions, total amount of system notifications. */ class LLNotificationChiclet : public LLChiclet { public: struct Params : public LLInitParam::Block<Params, LLChiclet::Params> { Optional<LLButton::Params> button; Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications; Params(); }; /*virtual*/ void setCounter(S32 counter); /*virtual*/S32 getCounter() { return mCounterCtrl->getCounter(); } /*virtual*/ void setShowCounter(bool show); boost::signals2::connection setClickCallback(const commit_callback_t& cb); /*virtual*/ ~ LLNotificationChiclet(); // methods for updating a number of unread System notifications void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); } void setToggleState(BOOL toggled); protected: // connect counter updaters to the corresponding signals void connectCounterUpdatersToSignal(std::string notification_type); LLNotificationChiclet(const Params& p); friend class LLUICtrlFactory; static S32 mUreadSystemNotifications; protected: LLButton* mButton; LLChicletNotificationCounterCtrl* mCounterCtrl; }; /* * Storage class for all IM chiclets. Provides mechanism to display, * scroll, create, remove chiclets. */ class LLChicletPanel : public LLPanel { public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> { Optional<S32> chiclet_padding, scrolling_offset; Optional<S32> min_width; Params(); }; virtual ~LLChicletPanel(); /* * Creates chiclet and adds it to chiclet list at specified index. */ template<class T> T* createChiclet(const LLUUID& session_id, S32 index); /* * Creates chiclet and adds it to chiclet list at right. */ template<class T> T* createChiclet(const LLUUID& session_id); /* * Returns pointer to chiclet of specified type at specified index. */ template<class T> T* getChiclet(S32 index); /* * Returns pointer to LLChiclet at specified index. */ LLChiclet* getChiclet(S32 index) { return getChiclet<LLChiclet>(index); } /* * Searches a chiclet using IM session id. */ template<class T> T* findChiclet(const LLUUID& im_session_id); /* * Returns number of hosted chiclets. */ S32 getChicletCount() {return mChicletList.size();}; /* * Returns index of chiclet in list. */ S32 getChicletIndex(const LLChiclet* chiclet); /* * Removes chiclet by index. */ void removeChiclet(S32 index); /* * Removes chiclet by pointer. */ void removeChiclet(LLChiclet* chiclet); /* * Removes chiclet by IM session id. */ void removeChiclet(const LLUUID& im_session_id); /* * Removes all chiclets. */ void removeAll(); /* * Scrolls the panel to the specified chiclet */ void scrollToChiclet(const LLChiclet* chiclet); boost::signals2::connection setChicletClickedCallback( const commit_callback_t& cb); /*virtual*/ BOOL postBuild(); /* * Handler for the Voice Client's signal. Finds a corresponding chiclet and toggles its SpeakerControl */ void onCurrentVoiceChannelChanged(const LLUUID& session_id); /* * Reshapes controls and rearranges chiclets if needed. */ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE ); /*virtual*/ void draw(); S32 getMinWidth() const { return mMinWidth; } protected: LLChicletPanel(const Params&p); friend class LLUICtrlFactory; S32 calcChickletPanleWidth(); /* * Adds chiclet to list and rearranges all chiclets. */ bool addChiclet(LLChiclet*, S32 index); /* * Arranges chiclets. */ void arrange(); /* * Returns true if chiclets can be scrolled right. */ bool canScrollRight(); /* * Returns true if chiclets can be scrolled left. */ bool canScrollLeft(); /* * Shows or hides chiclet scroll buttons if chiclets can or can not be scrolled. */ void showScrollButtonsIfNeeded(); /* * Shifts chiclets left or right. */ void shiftChiclets(S32 offset, S32 start_index = 0); /* * Removes gaps between first chiclet and scroll area left side, * last chiclet and scroll area right side. */ void trimChiclets(); /* * Scrolls chiclets to right or left. */ void scroll(S32 offset); /* * Verifies that chiclets can be scrolled left, then calls scroll() */ void scrollLeft(); /* * Verifies that chiclets can be scrolled right, then calls scroll() */ void scrollRight(); /* * Callback for left scroll button clicked */ void onLeftScrollClick(); /* * Callback for right scroll button clicked */ void onRightScrollClick(); /* * Callback for right scroll button held down event */ void onLeftScrollHeldDown(); /* * Callback for left scroll button held down event */ void onRightScrollHeldDown(); /* * Callback for mouse wheel scrolled, calls scrollRight() or scrollLeft() */ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); /* * Notifies subscribers about click on chiclet. * Do not place any code here, instead subscribe on event (see setChicletClickedCallback). */ void onChicletClick(LLUICtrl*ctrl,const LLSD¶m); /* * Callback for chiclet size changed event, rearranges chiclets. */ void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param); typedef std::vector<LLChiclet*> chiclet_list_t; /* * Removes chiclet from scroll area and chiclet list. */ void removeChiclet(chiclet_list_t::iterator it); S32 getChicletPadding() { return mChicletPadding; } S32 getScrollingOffset() { return mScrollingOffset; } bool isAnyIMFloaterDoked(); protected: chiclet_list_t mChicletList; LLButton* mLeftScrollButton; LLButton* mRightScrollButton; LLPanel* mScrollArea; S32 mChicletPadding; S32 mScrollingOffset; S32 mMinWidth; bool mShowControls; static const S32 s_scroll_ratio; }; template<class T> T* LLChicletPanel::createChiclet(const LLUUID& session_id, S32 index) { typename T::Params params; T* chiclet = LLUICtrlFactory::create<T>(params); if(!chiclet) { llwarns << "Could not create chiclet" << llendl; return NULL; } if(!addChiclet(chiclet, index)) { delete chiclet; llwarns << "Could not add chiclet to chiclet panel" << llendl; return NULL; } if (!isAnyIMFloaterDoked()) { scrollToChiclet(chiclet); } chiclet->setSessionId(session_id); return chiclet; } template<class T> T* LLChicletPanel::createChiclet(const LLUUID& session_id) { return createChiclet<T>(session_id, mChicletList.size()); } template<class T> T* LLChicletPanel::findChiclet(const LLUUID& im_session_id) { if(im_session_id.isNull()) { return NULL; } chiclet_list_t::const_iterator it = mChicletList.begin(); for( ; mChicletList.end() != it; ++it) { LLChiclet* chiclet = *it; if(chiclet->getSessionId() == im_session_id) { T* result = dynamic_cast<T*>(chiclet); if(!result && chiclet) { llwarns << "Found chiclet but of wrong type " << llendl; } return result; } } return NULL; } template<class T> T* LLChicletPanel::getChiclet(S32 index) { if(index < 0 || index >= getChicletCount()) { return NULL; } LLChiclet* chiclet = mChicletList[index]; T*result = dynamic_cast<T*>(chiclet); if(!result && chiclet) { llwarns << "Found chiclet but of wrong type " << llendl; } return result; } #endif // LL_LLCHICLET_H