summaryrefslogtreecommitdiff
path: root/indra/newview/llchiclet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llchiclet.cpp')
-rw-r--r--indra/newview/llchiclet.cpp941
1 files changed, 645 insertions, 296 deletions
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index d8e844d291..f71ea9f8ad 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -32,72 +32,60 @@
#include "llviewerprecompiledheaders.h" // must be first include
#include "llchiclet.h"
-#include "llfloaterreg.h"
-#include "llvoiceclient.h"
#include "llagent.h"
-#include "lltextbox.h"
+#include "llavataractions.h"
+#include "llbottomtray.h"
+#include "llgroupactions.h"
#include "lliconctrl.h"
-#include "llvoicecontrolpanel.h"
-#include "lloutputmonitorctrl.h"
+#include "llimpanel.h" // LLFloaterIMPanel
#include "llimview.h"
-#include "llbottomtray.h"
+#include "llfloatergroupinfo.h"
+#include "llmenugl.h"
+#include "lloutputmonitorctrl.h"
+#include "lltextbox.h"
+#include "llvoiceclient.h"
+#include "llvoicecontrolpanel.h"
+
+static const std::string P2P_MENU_NAME = "IMChiclet P2P Menu";
+static const std::string GROUP_MENU_NAME = "IMChiclet Group Menu";
-static const S32 CHICLET_HEIGHT = 25;
-static const S32 CHICLET_SPACING = 0;
-static const S32 CHICLET_PADDING = 3;
-static const S32 AVATAR_WIDTH = 25;
-static const S32 SPEAKER_WIDTH = 20;
-static const S32 COUNTER_WIDTH = 20;
-static const S32 SCROLL_BUTTON_WIDTH = 19;
-static const S32 SCROLL_BUTTON_HEIGHT = 20;
-static const S32 NOTIFICATION_TEXT_TOP_PAD = 5;
-
-static LLDefaultWidgetRegistry::Register<LLChicletPanel> t1("chiclet_panel");
-static LLDefaultWidgetRegistry::Register<LLTalkButton> t2("chiclet_talk");
-static LLDefaultWidgetRegistry::Register<LLNotificationChiclet> t3("chiclet_notification");
-static LLDefaultWidgetRegistry::Register<LLChicletPanel> t4("chiclet_panel");
+static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
+static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk");
+static LLDefaultChildRegistry::Register<LLNotificationChiclet> t3("chiclet_notification");
+static LLDefaultChildRegistry::Register<LLIMChiclet> t4("chiclet_im");
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
LLNotificationChiclet::Params::Params()
-: image_unselected("image_unselected")
-, image_selected("image_selected")
-, image_overlay("image_overlay")
+: button("button")
+, unread_notifications("unread_notifications")
{
+ 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);
}
LLNotificationChiclet::LLNotificationChiclet(const Params& p)
: LLChiclet(p)
, mButton(NULL)
-, mCounterText(NULL)
-{
- LLRect rc(p.rect);
-
- LLButton::Params button_params;
- button_params.name("btn");
- button_params.label(LLStringUtil::null);
- button_params.rect(LLRect(0,rc.getHeight(),rc.getWidth(),0));
- button_params.image_overlay(p.image_overlay);
- button_params.image_unselected(p.image_unselected);
- button_params.image_selected(p.image_selected);
- button_params.tab_stop(false);
+, mCounterCtrl(NULL)
+{
+ LLButton::Params button_params = p.button;
+ button_params.rect(p.rect());
mButton = LLUICtrlFactory::create<LLButton>(button_params);
addChild(mButton);
- LLTextBox::Params textbox_params;
- textbox_params.name("txt");
- textbox_params.rect(LLRect(p.label_left,rc.getHeight(),
- rc.getWidth()-p.label_left,0));
- textbox_params.mouse_opaque(false);
- textbox_params.v_pad(NOTIFICATION_TEXT_TOP_PAD);
- textbox_params.font.style("SansSerif");
- textbox_params.font_halign(LLFontGL::HCENTER);
- mCounterText = LLUICtrlFactory::create<LLTextBox>(textbox_params);
- addChild(mCounterText);
- mCounterText->setColor(LLColor4::white);
- mCounterText->setText(LLStringUtil::null);
+ LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
+ mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
+ addChild(mCounterCtrl);
}
LLNotificationChiclet::~LLNotificationChiclet()
@@ -105,18 +93,15 @@ LLNotificationChiclet::~LLNotificationChiclet()
}
-LLChiclet* LLNotificationChiclet::create(const Params& p)
+void LLNotificationChiclet::setCounter(S32 counter)
{
- LLChiclet* chiclet = new LLNotificationChiclet(p);
- return chiclet;
+ mCounterCtrl->setCounter(counter);
}
-void LLNotificationChiclet::setCounter(S32 counter)
+void LLNotificationChiclet::setShowCounter(bool show)
{
- std::stringstream stream;
- mCounter = counter;
- stream << mCounter;
- mCounterText->setText(stream.str());
+ LLChiclet::setShowCounter(show);
+ mCounterCtrl->setVisible(getShowCounter());
}
boost::signals2::connection LLNotificationChiclet::setClickCallback(
@@ -129,10 +114,16 @@ boost::signals2::connection LLNotificationChiclet::setClickCallback(
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLChiclet::Params::Params()
+ : show_counter("show_counter")
+{
+ show_counter = true;
+}
+
LLChiclet::LLChiclet(const Params& p)
: LLUICtrl(p)
-, mCounter(0)
-, mShowCounter(true)
+, mSessionId(LLUUID::null)
+, mShowCounter(p.show_counter)
{
}
@@ -155,47 +146,81 @@ BOOL LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
return TRUE;
}
+boost::signals2::connection LLChiclet::setChicletSizeChangedCallback(
+ const chiclet_size_changed_callback_t& cb)
+{
+ return mChicletSizeChangedSignal.connect(cb);
+}
+
+void LLChiclet::onChicletSizeChanged()
+{
+ mChicletSizeChangedSignal(this, getValue());
+}
+
+LLSD LLChiclet::getValue() const
+{
+ return LLSD(getSessionId());
+}
+
+void LLChiclet::setValue(const LLSD& value)
+{
+ if(value.isUUID())
+ setSessionId(value.asUUID());
+}
+
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-LLIMChiclet::LLIMChiclet(const LLChiclet::Params& p)
+LLIMChiclet::Params::Params()
+: avatar_icon("avatar_icon")
+, unread_notifications("unread_notifications")
+, speaker("speaker")
+, show_speaker("show_speaker")
+{
+ rect(LLRect(0, 25, 45, 0));
+
+ avatar_icon.name("avatar_icon");
+ avatar_icon.rect(LLRect(0, 25, 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;
+}
+
+LLIMChiclet::LLIMChiclet(const Params& p)
: LLChiclet(p)
-, mAvatar(NULL)
-, mCounterText(NULL)
-, mSpeaker(NULL)
-, mIMSessionId()
-, mShowSpeaker(false)
-, mSpeakerStatus(SPEAKER_IDLE)
-{
- LLAvatarIconCtrl::Params avatar_params;
- avatar_params.control_name("avatar");
- avatar_params.draw_tooltip = FALSE;
- mAvatar = LLUICtrlFactory::create<LLAvatarIconCtrl>(avatar_params);
-
- addChild(mAvatar);
-
- LLTextBox::Params unread_params;
- unread_params.font.style("SansSerif");
- unread_params.font_halign(LLFontGL::HCENTER);
- unread_params.v_pad(5);
- mCounterText = LLUICtrlFactory::create<LLTextBox>(unread_params);
- addChild(mCounterText);
- mCounterText->setColor(LLColor4::white);
+, mAvatarCtrl(NULL)
+, mCounterCtrl(NULL)
+, mSpeakerCtrl(NULL)
+, mShowSpeaker(p.show_speaker)
+, mPopupMenu(NULL)
+, mDockTongueVisible(false)
+{
+ LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
+ mAvatarCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
+ addChild(mAvatarCtrl);
+
+ LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
+ mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
+ addChild(mCounterCtrl);
+
setCounter(getCounter());
+ setShowCounter(getShowCounter());
- LLIconCtrl::Params speaker_params;
- speaker_params.image( LLUI::getUIImage("icn_voice_ptt-on-lvl2.tga") );
- mSpeaker = LLUICtrlFactory::create<LLIconCtrl>(speaker_params);
- addChild(mSpeaker);
- mSpeaker->setVisible(getShowSpeaker());
+ LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
+ mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
+ addChild(mSpeakerCtrl);
- S32 left = 0;
- mAvatar->setRect(LLRect(left,CHICLET_HEIGHT,AVATAR_WIDTH,0));
- left += AVATAR_WIDTH + CHICLET_SPACING;
- mCounterText->setRect(LLRect(left,CHICLET_HEIGHT,left + COUNTER_WIDTH,0));
- left += COUNTER_WIDTH + CHICLET_SPACING;
- mSpeaker->setRect(LLRect(left,CHICLET_HEIGHT,left + SPEAKER_WIDTH,0));
+ setShowSpeaker(getShowSpeaker());
}
LLIMChiclet::~LLIMChiclet()
@@ -203,43 +228,57 @@ LLIMChiclet::~LLIMChiclet()
}
-LLChiclet* LLIMChiclet::create(LLSD* imSessionId /* = NULL */)
+void LLIMChiclet::setDockTongueVisible(bool visible)
{
- LLIMChiclet* chiclet = new LLIMChiclet(LLChiclet::Params());
- chiclet->setIMSessionId(imSessionId);
- return chiclet;
+ mDockTongueVisible = visible;
}
void LLIMChiclet::setCounter(S32 counter)
{
- mCounter = counter;
- std::stringstream stream;
- stream << mCounter;
- mCounterText->setText(stream.str());
+ mCounterCtrl->setCounter(counter);
+
+ if(getShowCounter())
+ {
+ LLRect counter_rect = mCounterCtrl->getRect();
+ LLRect required_rect = mCounterCtrl->getRequiredRect();
+ bool needs_resize = required_rect.getWidth() != counter_rect.getWidth();
- LLRect rc = mCounterText->getRect();
- rc.mRight = rc.mLeft + calcCounterWidth();
- mCounterText->setRect(rc);
+ 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 LLIMChiclet::getRequiredRect()
{
- LLRect rect(0,CHICLET_HEIGHT,AVATAR_WIDTH,0);
+ LLRect rect(0, 0, mAvatarCtrl->getRect().getWidth(), 0);
if(getShowCounter())
{
- rect.mRight += CHICLET_SPACING + calcCounterWidth();
+ rect.mRight += mCounterCtrl->getRequiredRect().getWidth();
}
if(getShowSpeaker())
{
- rect.mRight += CHICLET_SPACING + SPEAKER_WIDTH;
+ rect.mRight += mSpeakerCtrl->getRect().getWidth();
}
return rect;
}
void LLIMChiclet::setShowCounter(bool show)
{
+ bool needs_resize = getShowCounter() != show;
+
LLChiclet::setShowCounter(show);
- mCounterText->setVisible(getShowCounter());
+ mCounterCtrl->setVisible(getShowCounter());
+
+ if(needs_resize)
+ {
+ onChicletSizeChanged();
+ }
}
void LLIMChiclet::setIMSessionName(const std::string& name)
@@ -249,63 +288,195 @@ void LLIMChiclet::setIMSessionName(const std::string& name)
void LLIMChiclet::setOtherParticipantId(const LLUUID& other_participant_id)
{
- if (mAvatar)
+ if (mAvatarCtrl)
{
- mAvatar->setValue(other_participant_id);
+ mAvatarCtrl->setValue(other_participant_id);
+ }
+}
+
+void LLIMChiclet::updateMenuItems()
+{
+ if(!mPopupMenu)
+ return;
+ if(getSessionId().isNull())
+ return;
+
+ if(P2P_MENU_NAME == mPopupMenu->getName())
+ {
+ bool is_friend = LLAvatarActions::isFriend(mAvatarCtrl->getAvatarId());
+
+ mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);
+ mPopupMenu->getChild<LLUICtrl>("Remove Friend")->setEnabled(is_friend);
}
}
void LLIMChiclet::setShowSpeaker(bool show)
{
+ bool needs_resize = getShowSpeaker() != show;
+
mShowSpeaker = show;
- mSpeaker->setVisible(getShowSpeaker());
+ mSpeakerCtrl->setVisible(getShowSpeaker());
+
+ if(needs_resize)
+ {
+ onChicletSizeChanged();
+ }
}
void LLIMChiclet::draw()
{
LLUICtrl::draw();
- gl_rect_2d(1, getRect().getHeight(), getRect().getWidth(), 1, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE);
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE);
+
+ if (mDockTongueVisible)
+ {
+ LLUIImagePtr flyout_tongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
+ // was previously AVATAR_WIDTH-16 and CHICLET_HEIGHT-6
+ flyout_tongue->draw( getRect().getWidth()-31, getRect().getHeight()-5);
+ }
+}
+
+BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(!mPopupMenu)
+ createPopupMenu();
+
+ updateMenuItems();
+
+ if (mPopupMenu)
+ {
+ mPopupMenu->arrangeAndClear();
+ }
+
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+
+ return TRUE;
+}
+
+void LLIMChiclet::createPopupMenu()
+{
+ if(mPopupMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+ if(getSessionId().isNull())
+ return;
+
+ LLFloaterIMPanel*floater = gIMMgr->findFloaterBySession(getSessionId());
+ if(!floater)
+ return;
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMChicletMenu.Action", boost::bind(&LLIMChiclet::onMenuItemClicked, this, _2));
+
+ switch(floater->getDialogType())
+ {
+ case IM_SESSION_GROUP_START:
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ break;
+ case IM_NOTHING_SPECIAL:
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ break;
+ default:
+ llwarns << "Unexpected dialog type" << llendl;
+ break;
+ }
}
-S32 LLIMChiclet::calcCounterWidth()
+void LLIMChiclet::onMenuItemClicked(const LLSD& user_data)
{
- S32 font_width = mCounterText->getFont()->getWidth("0");
- S32 text_size = mCounterText->getText().size();
+ std::string level = user_data.asString();
+ LLUUID other_participant_id = mAvatarCtrl->getAvatarId();
- return llmax(font_width * text_size, COUNTER_WIDTH);
+ if("profile" == level)
+ {
+ LLAvatarActions::showProfile(other_participant_id);
+ }
+ else if("im" == level)
+ {
+ LLAvatarActions::startIM(other_participant_id);
+ }
+ else if("add" == level)
+ {
+ std::string name;
+ gCacheName->getFullName(other_participant_id,name);
+ LLAvatarActions::requestFriendshipDialog(other_participant_id,name);
+ }
+ else if("remove" == level)
+ {
+ LLAvatarActions::removeFriendDialog(other_participant_id);
+ }
+ else if("group chat" == level)
+ {
+ LLGroupActions::startChat(other_participant_id);
+ }
+ else if("info" == level)
+ {
+ LLFloaterGroupInfo::showFromUUID(other_participant_id);
+ }
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLChicletPanel::Params::Params()
+: chiclet_padding("chiclet_padding")
+, scrolling_offset("scrolling_offset")
+, left_scroll_button("left_scroll_button")
+, right_scroll_button("right_scroll_button")
+, 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)
: LLPanel(p)
-, mLeftScroll(NULL)
-, mRightScroll(NULL)
-, mFirstToShow(0)
-{
- LLButton::Params params;
-
- params.name("scroll_left");
- params.label(LLStringUtil::null);
- params.tab_stop(false);
- params.image_selected(LLUI::getUIImage("scroll_left.tga"));
- params.image_unselected(LLUI::getUIImage("scroll_left.tga"));
- params.image_hover_selected(LLUI::getUIImage("scroll_left.tga"));
- mLeftScroll = LLUICtrlFactory::create<LLButton>(params);
- addChild(mLeftScroll);
- mLeftScroll->setClickedCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this));
- mLeftScroll->setEnabled(false);
-
- params.name("scroll_right");
- params.image_selected(LLUI::getUIImage("scroll_right.tga"));
- params.image_unselected(LLUI::getUIImage("scroll_right.tga"));
- params.image_hover_selected(LLUI::getUIImage("scroll_right.tga"));
- mRightScroll = LLUICtrlFactory::create<LLButton>(params);
- addChild(mRightScroll);
- mRightScroll->setClickedCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this));
- mRightScroll->setEnabled(false);
+, mScrollArea(NULL)
+, mLeftScrollButton(NULL)
+, mRightScrollButton(NULL)
+, mChicletPadding(p.chiclet_padding)
+, mScrollingOffset(p.scrolling_offset)
+, 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;
mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this);
@@ -317,44 +488,55 @@ LLChicletPanel::~LLChicletPanel()
}
-LLChicletPanel* LLChicletPanel::create()
-{
- LLChicletPanel* panel = new LLChicletPanel(LLChicletPanel::Params());
- return panel;
+void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
+
+ LLUUID session_id = data["session_id"].asUUID();
+ LLChiclet* chiclet = panel->findChiclet<LLChiclet>(session_id);
+
+ if (chiclet)
+ {
+ chiclet->setCounter(data["num_unread"].asInteger());
+ }
+ 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));
return TRUE;
}
-LLChiclet* LLChicletPanel::createChiclet(LLSD* imSessionId, S32 pos)
+bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
{
- LLChiclet* chiclet = LLIMChiclet::create(imSessionId);
- if(!chiclet)
- {
- assert(false);
- return NULL;
- }
-
- if(!addChiclet(chiclet, pos))
+ if(mScrollArea->addChild(chiclet))
{
- assert(false);
- return NULL;
- }
+ S32 offset = 0;
+ // Do not scroll chiclets if chiclets are scrolled right and new
+ // chiclet is added to the beginning of the list
+ if(canScrollLeft())
+ {
+ offset = - (chiclet->getRequiredRect().getWidth() + getChicletPadding());
+ if(0 == index)
+ {
+ offset += getChiclet(0)->getRect().mLeft;
+ }
+ }
- return chiclet;
-}
+ mChicletList.insert(mChicletList.begin() + index, chiclet);
-bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 pos)
-{
- if(mScrollArea->addChild(chiclet))
- {
- mChicletList.insert(mChicletList.begin() + pos, chiclet);
+ getChiclet(0)->translate(offset, 0);
chiclet->setLeftButtonClickCallback(boost::bind(&LLChicletPanel::onChicletClick, this, _1, _2));
+ chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
+
+ arrange();
+ showScrollButtonsIfNeeded();
return true;
}
@@ -362,57 +544,65 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 pos)
return false;
}
-void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD&param)
+void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
{
- LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(ctrl);
- if (chiclet)
+ S32 chiclet_width = ctrl->getRect().getWidth();
+ S32 chiclet_new_width = ctrl->getRequiredRect().getWidth();
+
+ if(chiclet_new_width == chiclet_width)
{
- LLFloaterReg::showInstance("communicate", chiclet->getIMSessionId().asUUID());
+ return;
}
- mCommitSignal(ctrl,param);
-}
+ LLRect chiclet_rect = ctrl->getRect();
+ chiclet_rect.mRight = chiclet_rect.mLeft + chiclet_new_width;
-LLChiclet* LLChicletPanel::findIMChiclet(LLSD* imSessionId)
-{
- chiclet_list_t::const_iterator it = mChicletList.begin();
- for( ; mChicletList.end() != it; ++it)
- {
- LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
- if(!chiclet)
- {
- continue;
- }
+ ctrl->setRect(chiclet_rect);
- if(chiclet->getIMSessionId().asUUID() == imSessionId->asUUID())
- {
- return chiclet;
- }
- }
- return NULL;
+ S32 offset = chiclet_new_width - chiclet_width;
+ S32 index = getChicletIndex(ctrl);
+
+ shiftChiclets(offset, index + 1);
+ trimChiclets();
+ showScrollButtonsIfNeeded();
}
-LLChiclet* LLChicletPanel::getChiclet(S32 pos)
+void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD&param)
{
- return mChicletList.at(pos);
+ mCommitSignal(ctrl,param);
}
void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
{
mScrollArea->removeChild(*it);
- delete *it;
mChicletList.erase(it);
- mLeftScroll->setEnabled(canScrollLeft());
- mRightScroll->setEnabled(canScrollRight());
+
+ arrange();
+ trimChiclets();
+ showScrollButtonsIfNeeded();
}
-void LLChicletPanel::removeChiclet(S32 pos)
+void LLChicletPanel::removeChiclet(S32 index)
{
- if(0 > pos || getChicletCount() >= pos)
+ if(index >= 0 && index < getChicletCount())
{
- return;
+ removeChiclet(mChicletList.begin() + index);
+ }
+}
+
+S32 LLChicletPanel::getChicletIndex(const LLChiclet* chiclet)
+{
+ if(mChicletList.empty())
+ return -1;
+
+ S32 size = getChicletCount();
+ for(int n = 0; n < size; ++n)
+ {
+ if(chiclet == mChicletList[n])
+ return n;
}
- removeChiclet(mChicletList.begin() + pos);
+
+ return -1;
}
void LLChicletPanel::removeChiclet(LLChiclet*chiclet)
@@ -429,18 +619,14 @@ void LLChicletPanel::removeChiclet(LLChiclet*chiclet)
}
}
-void LLChicletPanel::removeIMChiclet(LLSD* imSessionId)
+void LLChicletPanel::removeChiclet(const LLUUID& im_session_id)
{
chiclet_list_t::iterator it = mChicletList.begin();
for( ; mChicletList.end() != it; ++it)
{
LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
- if(!chiclet)
- {
- continue;
- }
- if(chiclet->getIMSessionId().asUUID() == imSessionId->asUUID())
+ if(chiclet->getSessionId() == im_session_id)
{
removeChiclet(it);
return;
@@ -450,54 +636,104 @@ void LLChicletPanel::removeIMChiclet(LLSD* imSessionId)
void LLChicletPanel::removeAll()
{
- mScrollArea->deleteAllChildren();
+ S32 size = getChicletCount();
+ for(S32 n = 0; n < size; ++n)
+ {
+ mScrollArea->removeChild(mChicletList[n]);
+ }
mChicletList.erase(mChicletList.begin(), mChicletList.end());
- mLeftScroll->setEnabled(false);
- mRightScroll->setEnabled(false);
+
+ showScrollButtonsIfNeeded();
}
void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
{
LLPanel::reshape(width,height,called_from_parent);
- mLeftScroll->setRect(LLRect(0,CHICLET_HEIGHT,SCROLL_BUTTON_WIDTH,
- CHICLET_HEIGHT - SCROLL_BUTTON_HEIGHT));
- mRightScroll->setRect(LLRect(getRect().getWidth()-SCROLL_BUTTON_WIDTH,CHICLET_HEIGHT,
- getRect().getWidth(),CHICLET_HEIGHT - SCROLL_BUTTON_HEIGHT));
+ static const S32 SCROLL_BUTTON_PAD = 5;
- mScrollArea->setRect(LLRect(SCROLL_BUTTON_WIDTH + 5,CHICLET_HEIGHT + 1,
- getRect().getWidth() - SCROLL_BUTTON_WIDTH - 5, 0));
+ LLRect scroll_button_rect = mLeftScrollButton->getRect();
+ mLeftScrollButton->setRect(LLRect(0,height,scroll_button_rect.getWidth(),
+ height - scroll_button_rect.getHeight()));
+ scroll_button_rect = mRightScrollButton->getRect();
+ mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),height,
+ width, height - scroll_button_rect.getHeight()));
- arrange();
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD,
+ height + 7, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));
+
+ mShowControls = width > mMinWidth;
+ mScrollArea->setVisible(mShowControls);
+
+ trimChiclets();
+
+ showScrollButtonsIfNeeded();
}
void LLChicletPanel::arrange()
{
- S32 left = 0;
- S32 size = getChicletCount();
+ if(mChicletList.empty())
+ return;
- for( int n = mFirstToShow; n < size; ++n)
+ S32 chiclet_left = getChiclet(0)->getRect().mLeft;
+
+ S32 size = getChicletCount();
+ for( int n = 0; n < size; ++n)
{
LLChiclet* chiclet = getChiclet(n);
+
S32 chiclet_width = chiclet->getRequiredRect().getWidth();
- LLRect rc(left, CHICLET_HEIGHT, left + chiclet_width, 0);
+ LLRect rect = chiclet->getRect();
+ rect.set(chiclet_left, rect.mTop, chiclet_left + chiclet_width, rect.mBottom);
- chiclet->setRect(rc);
- chiclet->reshape(rc.getWidth(),rc.getHeight());
+ chiclet->setRect(rect);
- left += chiclet_width + CHICLET_PADDING;
+ chiclet_left += chiclet_width + getChicletPadding();
}
+}
- mLeftScroll->setEnabled(canScrollLeft());
- mRightScroll->setEnabled(canScrollRight());
+void LLChicletPanel::trimChiclets()
+{
+ // trim right
+ if(canScrollLeft() && !canScrollRight())
+ {
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+ S32 scroll_width = mScrollArea->getRect().getWidth();
+ if(last_chiclet_right < scroll_width)
+ {
+ 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);
+ }
+ }
}
-void LLChicletPanel::draw()
+void LLChicletPanel::showScrollButtonsIfNeeded()
{
- //gl_rect_2d(0,getRect().getHeight(),getRect().getWidth(),0,LLColor4(0.f,1.f,1.f,1.f),TRUE);
+ bool can_scroll_left = canScrollLeft();
+ bool can_scroll_right = canScrollRight();
+
+ mLeftScrollButton->setEnabled(can_scroll_left);
+ mRightScrollButton->setEnabled(can_scroll_right);
+
+ bool show_scroll_buttons = (can_scroll_left || can_scroll_right) && mShowControls;
+ mLeftScrollButton->setVisible(show_scroll_buttons);
+ mRightScrollButton->setVisible(show_scroll_buttons);
+}
+
+void LLChicletPanel::draw()
+{
child_list_const_iter_t it = getChildList()->begin();
for( ; getChildList()->end() != it; ++it)
{
@@ -516,38 +752,39 @@ void LLChicletPanel::draw()
bool LLChicletPanel::canScrollRight()
{
- S32 width = 0;
- LLRect visible_rect = mScrollArea->getRect();
+ if(mChicletList.empty())
+ return false;
+
+ S32 scroll_width = mScrollArea->getRect().getWidth();
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+
+ if(last_chiclet_right > scroll_width)
+ return true;
- chiclet_list_t::const_iterator it = mChicletList.begin() + mFirstToShow;
- for(;mChicletList.end() != it; ++it)
- {
- LLChiclet* chiclet = *it;
- width += chiclet->getRect().getWidth() + CHICLET_PADDING;
- if(width > visible_rect.getWidth())
- return true;
- }
return false;
}
bool LLChicletPanel::canScrollLeft()
{
- return mFirstToShow > 0;
+ if(mChicletList.empty())
+ return false;
+
+ return getChiclet(0)->getRect().mLeft < 0;
}
-void LLChicletPanel::scroll(ScrollDirection direction)
+void LLChicletPanel::scroll(S32 offset)
{
- S32 elem = 0;
- if(SCROLL_LEFT == direction)
- elem = mFirstToShow;
- else if(SCROLL_RIGHT)
- elem = mFirstToShow - 1;
+ shiftChiclets(offset);
+}
- S32 offset = mChicletList[elem]->getRect().getWidth() +
- CHICLET_PADDING;
- offset *= direction;
+void LLChicletPanel::shiftChiclets(S32 offset, S32 start_index /* = 0 */)
+{
+ if(start_index < 0 || start_index >= getChicletCount())
+ {
+ return;
+ }
- chiclet_list_t::const_iterator it = mChicletList.begin();
+ chiclet_list_t::const_iterator it = mChicletList.begin() + start_index;
for(;mChicletList.end() != it; ++it)
{
LLChiclet* chiclet = *it;
@@ -559,10 +796,18 @@ void LLChicletPanel::scrollLeft()
{
if(canScrollLeft())
{
- --mFirstToShow;
- scroll(SCROLL_LEFT);
- mLeftScroll->setEnabled(canScrollLeft());
- mRightScroll->setEnabled(canScrollRight());
+ S32 offset = getScrollingOffset();
+ LLRect first_chiclet_rect = getChiclet(0)->getRect();
+
+ // shift chiclets in case first chiclet is partially visible
+ if(first_chiclet_rect.mLeft < 0 && first_chiclet_rect.mRight > 0)
+ {
+ offset = llabs(first_chiclet_rect.mLeft);
+ }
+
+ scroll(offset);
+
+ showScrollButtonsIfNeeded();
}
}
@@ -570,10 +815,20 @@ void LLChicletPanel::scrollRight()
{
if(canScrollRight())
{
- ++mFirstToShow;
- scroll(SCROLL_RIGHT);
- mLeftScroll->setEnabled(canScrollLeft());
- mRightScroll->setEnabled(canScrollRight());
+ S32 offset = - getScrollingOffset();
+
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+ S32 scroll_rect_width = mScrollArea->getRect().getWidth();
+ // if after scrolling, the last chiclet will not be aligned to
+ // scroll area right side - align it.
+ if( last_chiclet_right + offset < scroll_rect_width )
+ {
+ offset = scroll_rect_width - last_chiclet_right;
+ }
+
+ scroll(offset);
+
+ showScrollButtonsIfNeeded();
}
}
@@ -587,7 +842,7 @@ void LLChicletPanel::onRightScrollClick()
scrollRight();
}
-boost::signals2::connection LLChicletPanel::setChicletClickCallback(
+boost::signals2::connection LLChicletPanel::setChicletClickedCallback(
const commit_callback_t& cb)
{
return mCommitSignal.connect(cb);
@@ -606,62 +861,87 @@ BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks)
return TRUE;
}
-LLTalkButton::LLTalkButton(const LLUICtrl::Params& p)
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLTalkButton::Params::Params()
+ : speak_button("speak_button")
+ , show_button("show_button")
+ , monitor("monitor")
+{
+ 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);
+ 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");
+ monitor.rect(LLRect(0, 10, 16, 0));
+}
+
+LLTalkButton::LLTalkButton(const Params& p)
: LLUICtrl(p)
+, mPrivateCallPanel(NULL)
+, mOutputMonitor(NULL)
+, mSpeakBtn(NULL)
+, mShowBtn(NULL)
{
- static S32 DROPDOWN_BTN_WIDTH = 20;
-
- LLRect rc(p.rect);
-
- LLButton::Params speak_params;
- speak_params.name("left");
- speak_params.rect(LLRect(0,rc.getHeight(),rc.getWidth()-DROPDOWN_BTN_WIDTH,0));
- speak_params.label("Speak");
- speak_params.label_selected("Speak");
- speak_params.font(LLFontGL::getFontSansSerifSmall());
- speak_params.label_color(LLColor4::black);
- speak_params.label_color_selected(LLColor4::black);
- speak_params.tab_stop(false);
- speak_params.is_toggle(true);
- speak_params.picture_style(true);
- speak_params.image_selected(LLUI::getUIImage("flyout_btn_left_selected.tga"));
- speak_params.image_unselected(LLUI::getUIImage("flyout_btn_left.tga"));
+ 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);
mSpeakBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_SpeakBtn, this));
- mSpeakBtn->setToggleState(false);
-
- LLButton::Params show_params;
- show_params.name("right");
- show_params.rect(LLRect(rc.getWidth()-DROPDOWN_BTN_WIDTH,rc.getHeight(),rc.getWidth(),0));
- show_params.label("");
- show_params.tab_stop(false);
- show_params.is_toggle(true);
- show_params.picture_style(true);
- show_params.image_selected(LLUI::getUIImage("show_btn_selected.tga"));
- show_params.image_unselected(LLUI::getUIImage("show_btn.tga"));
+ mSpeakBtn->setToggleState(FALSE);
+
+ LLButton::Params show_params = p.show_button;
+ show_params.rect(show_rect);
mShowBtn = LLUICtrlFactory::create<LLButton>(show_params);
addChild(mShowBtn);
mShowBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_ShowBtn, this));
- mShowBtn->setToggleState(false);
-
- mSpeakBtn->setToggleState(FALSE);
mShowBtn->setToggleState(FALSE);
- rc = mSpeakBtn->getRect();
+ static const S32 MONITOR_RIGHT_PAD = 2;
- LLOutputMonitorCtrl::Params monitor_param;
- monitor_param.name("monitor");
- monitor_param.draw_border(false);
- monitor_param.rect(LLRect(rc.getWidth()-20,18,rc.getWidth()-3,2));
- monitor_param.visible(true);
- mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_param);
+ 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);
+ mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_params);
mSpeakBtn->addChild(mOutputMonitor);
- mPrivateCallPanel = NULL;
+ // never show "muted" because you can't mute yourself
+ mOutputMonitor->setIsMuted(false);
}
LLTalkButton::~LLTalkButton()
@@ -670,19 +950,22 @@ LLTalkButton::~LLTalkButton()
void LLTalkButton::draw()
{
- if(mSpeakBtn->getToggleState())
- {
- mOutputMonitor->setPower(gVoiceClient->getCurrentPower(gAgent.getID()));
- }
+ // Always provide speaking feedback. User can trigger speaking
+ // with keyboard or middle-mouse shortcut.
+ mOutputMonitor->setPower(gVoiceClient->getCurrentPower(gAgent.getID()));
LLUICtrl::draw();
}
+void LLTalkButton::setSpeakBtnToggleState(bool state)
+{
+ mSpeakBtn->setToggleState(state);
+}
+
void LLTalkButton::onClick_SpeakBtn()
{
bool speaking = mSpeakBtn->getToggleState();
gVoiceClient->setUserPTTState(speaking);
- mOutputMonitor->setIsMuted(!speaking);
}
void LLTalkButton::onClick_ShowBtn()
@@ -704,8 +987,7 @@ void LLTalkButton::onClick_ShowBtn()
mPrivateCallPanel = new LLVoiceControlPanel;
getRootView()->addChild(mPrivateCallPanel);
- y = LLBottomTray::getInstance()->getRect().getHeight()
- + mPrivateCallPanel->getRect().getHeight();
+ y = LLBottomTray::getInstance()->getRect().getHeight() + mPrivateCallPanel->getRect().getHeight();
LLRect rect;
rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight());
@@ -723,3 +1005,70 @@ void LLTalkButton::onClick_ShowBtn()
mShowBtn->setToggleState(TRUE);
}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p)
+ : LLTextBox(p)
+ , mCounter(0)
+ , mInitialWidth(0)
+{
+ mInitialWidth = getRect().getWidth();
+}
+
+void LLChicletNotificationCounterCtrl::setCounter(S32 counter)
+{
+ mCounter = counter;
+
+ std::stringstream stream;
+ stream << getCounter();
+ if(mCounter != 0)
+ {
+ setText(stream.str());
+ }
+ else
+ {
+ setText(std::string(""));
+ }
+}
+
+LLRect LLChicletNotificationCounterCtrl::getRequiredRect()
+{
+ LLRect rc;
+ S32 text_width = getFont()->getWidth(getText());
+
+ rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth);
+
+ return rc;
+}
+
+void LLChicletNotificationCounterCtrl::setValue(const LLSD& value)
+{
+ if(value.isInteger())
+ setCounter(value.asInteger());
+}
+
+LLSD LLChicletNotificationCounterCtrl::getValue() const
+{
+ return LLSD(getCounter());
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p)
+ : LLAvatarIconCtrl(p)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)
+ : LLIconCtrl(p)
+{
+}