Steven Bennetts 2009-07-21 00:59:14 +00:00
parent 73a97010e6
commit cef46d1645
48 changed files with 5326 additions and 133 deletions

View File

@ -333,12 +333,13 @@ protected:
open_signal_t mOpenSignal;
close_signal_t mCloseSignal;
LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg
private:
LLRect mExpandedRect;
LLDragHandle* mDragHandle;
LLResizeBar* mResizeBar[4];
LLResizeHandle* mResizeHandle[4];
private:
LLRect mExpandedRect;
LLUIString mTitle;
LLUIString mShortTitle;

View File

@ -64,7 +64,7 @@ include_directories(
set(viewer_SOURCE_FILES
llaccordionctrltab.cpp
llaccordionpanel.cpp
llaccordionctrl.cpp
llagent.cpp
llagentaccess.cpp
llagentdata.cpp
@ -88,7 +88,9 @@ set(viewer_SOURCE_FILES
llcallingcard.cpp
llcapabilitylistener.cpp
llcaphttpsender.cpp
llchathistoryscroll.cpp
llchannelmanager.cpp
llchatitemscontainerctrl.cpp
llchatmsgbox.cpp
llchiclet.cpp
llclassifiedinfo.cpp
llclassifiedstatsresponder.cpp
@ -104,7 +106,6 @@ set(viewer_SOURCE_FILES
lldebugview.cpp
lldelayedgestureerror.cpp
lldirpicker.cpp
lldraggerbar.cpp
lldrawable.cpp
lldrawpoolalpha.cpp
lldrawpoolavatar.cpp
@ -266,8 +267,13 @@ set(viewer_SOURCE_FILES
llnameeditor.cpp
llnamelistctrl.cpp
llnavigationbar.cpp
llnearbychathistory.cpp
llnearbychat.cpp
llnearbychathandler.cpp
llnetmap.cpp
llnotificationalerthandler.cpp
llnotificationgrouphandler.cpp
llnotificationinfohandler.cpp
llnotificationmanager.cpp
llnotify.cpp
lloutputmonitorctrl.cpp
lloverlaybar.cpp
@ -329,6 +335,7 @@ set(viewer_SOURCE_FILES
llregionposition.cpp
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llscreenchannel.cpp
llselectmgr.cpp
llsidetray.cpp
llsky.cpp
@ -349,6 +356,11 @@ set(viewer_SOURCE_FILES
lltexturectrl.cpp
lltexturefetch.cpp
lltextureview.cpp
lltoast.cpp
lltoastalertpanel.cpp
lltoastgroupnotifypanel.cpp
lltoastnotifypanel.cpp
lltoastpanel.cpp
lltoggleablemenu.cpp
lltoolbar.cpp
lltoolbrush.cpp
@ -484,7 +496,7 @@ set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
llaccordionctrltab.h
llaccordionpanel.h
llaccordionctrl.h
llagent.h
llagentaccess.h
llagentdata.h
@ -510,7 +522,9 @@ set(viewer_HEADER_FILES
llcapabilitylistener.h
llcapabilityprovider.h
llcaphttpsender.h
llchathistoryscroll.h
llchannelmanager.h
llchatitemscontainerctrl.h
llchatmsgbox.h
llchiclet.h
llclassifiedinfo.h
llclassifiedstatsresponder.h
@ -526,7 +540,6 @@ set(viewer_HEADER_FILES
lldebugview.h
lldelayedgestureerror.h
lldirpicker.h
lldraggerbar.h
lldrawable.h
lldrawpool.h
lldrawpoolalpha.h
@ -690,8 +703,11 @@ set(viewer_HEADER_FILES
llnameeditor.h
llnamelistctrl.h
llnavigationbar.h
llnearbychathistory.h
llnearbychat.h
llnearbychathandler.h
llnetmap.h
llnotificationhandler.h
llnotificationmanager.h
llnotify.h
lloutputmonitorctrl.h
lloverlaybar.h
@ -754,6 +770,7 @@ set(viewer_HEADER_FILES
llremoteparcelrequest.h
llresourcedata.h
llrootview.h
llscreenchannel.h
llsavedsettingsglue.h
llselectmgr.h
llsidetray.h
@ -776,6 +793,11 @@ set(viewer_HEADER_FILES
lltexturectrl.h
lltexturefetch.h
lltextureview.h
lltoast.h
lltoastalertpanel.h
lltoastgroupnotifypanel.h
lltoastnotifypanel.h
lltoastpanel.h
lltoggleablemenu.h
lltool.h
lltoolbar.h

View File

@ -47,7 +47,7 @@
#include "llselectmgr.h"
#include "llvoavatarself.h"
S32 LLBottomTray::mLastSpecialChatChannel = 0;
S32 LLBottomTray::sLastSpecialChatChannel = 0;
// legacy calllback glue
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
@ -412,16 +412,6 @@ void LLBottomTray::refreshStandUp()
moveChildToBackOfTabGroup(mStandUpBtn);
}
}
void LLBottomTray::updateRightPosition(const S32 new_right_position)
{
LLRect rc = getRect();
if (new_right_position != rc.mRight)
{
rc.mRight = new_right_position;
reshape(rc.getWidth(), rc.getHeight(), FALSE);
setRect(rc);
}
}
//FIXME: temporary, for stand up proto
void LLBottomTray::onCommitStandUp(LLUICtrl* ctrl)
@ -624,7 +614,7 @@ LLWString LLBottomTray::stripChannelNumber(const LLWString &mesg, S32* channel)
&& mesg[1] == '/')
{
// This is a "repeat channel send"
*channel = mLastSpecialChatChannel;
*channel = sLastSpecialChatChannel;
return mesg.substr(2, mesg.length() - 2);
}
else if (mesg[0] == '/'
@ -654,8 +644,8 @@ LLWString LLBottomTray::stripChannelNumber(const LLWString &mesg, S32* channel)
pos++;
}
mLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10);
*channel = mLastSpecialChatChannel;
sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10);
*channel = sLastSpecialChatChannel;
return mesg.substr(pos, mesg.length() - pos);
}
else

View File

@ -89,7 +89,6 @@ public:
/*virtual*/void draw();
void refreshStandUp();
void updateRightPosition(const S32 new_right_position);
void onCommitGesture(LLUICtrl* ctrl);
void onCommitStandUp(LLUICtrl* ctrl);
@ -118,7 +117,7 @@ protected:
void setChicletPanelVisible(bool visible);
// Which non-zero channel did we last chat on?
static S32 mLastSpecialChatChannel;
static S32 sLastSpecialChatChannel;
LLLineEditor* mChatBox;
LLChicletPanel* mChicletPanel;

View File

@ -0,0 +1,133 @@
/**
* @file llchannelmanager.cpp
* @brief This class rules screen notification channels.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "llchannelmanager.h"
#include <algorithm>
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
LLChannelManager::LLChannelManager()
{
}
//--------------------------------------------------------------------------
LLChannelManager::~LLChannelManager()
{
//All channels are being deleted by Parent View
}
//--------------------------------------------------------------------------
LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p)
{
LLScreenChannel* new_channel = NULL;
if(!p.chiclet)
{
new_channel = getChannelByID(p.id);
}
else
{
new_channel = getChannelByChiclet(p.chiclet);
}
if(new_channel)
return new_channel;
new_channel = new LLScreenChannel();
new_channel->init(p.channel_right_bound - p.channel_width, getRootView());
new_channel->setToastAlignment(p.align);
ChannelElem new_elem;
new_elem.id = p.id;
new_elem.chiclet = p.chiclet;
new_elem.channel = new_channel;
mChannelList.push_back(new_elem); //TODO: remove chiclet from ScreenChannel?
return new_channel;
}
//--------------------------------------------------------------------------
LLScreenChannel* LLChannelManager::getChannelByID(const LLUUID id)
{
std::vector<ChannelElem>::iterator it = find(mChannelList.begin(), mChannelList.end(), id);
if(it != mChannelList.end())
{
return (*it).channel;
}
return NULL;
}
//--------------------------------------------------------------------------
LLScreenChannel* LLChannelManager::getChannelByChiclet(const LLChiclet* chiclet)
{
std::vector<ChannelElem>::iterator it = find(mChannelList.begin(), mChannelList.end(), chiclet);
if(it != mChannelList.end())
{
return (*it).channel;
}
return NULL;
}
//--------------------------------------------------------------------------
void LLChannelManager::reshape(S32 width, S32 height, BOOL called_from_parent)
{
for(std::vector<ChannelElem>::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it)
{
if((*it).channel->getToastAlignment() == NA_CENTRE)
{
LLRect channel_rect = (*it).channel->getRect();
S32 screen_width = getRootView()->getRect().getWidth();
channel_rect.setLeftTopAndSize(screen_width/2, channel_rect.mTop, channel_rect.getWidth(), channel_rect.getHeight());
(*it).channel->setRect(channel_rect);
(*it).channel->showToasts();
}
}
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

View File

@ -0,0 +1,116 @@
/**
* @file llchannelmanager.h
* @brief This class rules screen notification channels.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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_LLCHANNELMANAGER_H
#define LL_LLCHANNELMANAGER_H
#include "llchiclet.h"
#include "llscreenchannel.h"
#include "lluuid.h"
#include <map>
#include <boost/shared_ptr.hpp>
namespace LLNotificationsUI
{
/**
* Manager for screen channels.
* Responsible for instantiating and retrieving screen channels.
*/
class LLChannelManager : public LLUICtrl, public LLSingleton<LLChannelManager>
{
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<LLUUID> id;
Optional<LLChiclet*> chiclet;
Optional<S32> channel_right_bound;
Optional<S32> channel_width;
Optional<EToastAlignment> align;
Params(): id("id", LLUUID("")),
chiclet("chiclet", NULL),
channel_right_bound("channel_right_bound", 0),
channel_width("channel_width", 0),
align("align", NA_BOTTOM)
{}
};
struct ChannelElem
{
LLUUID id;
LLChiclet* chiclet;
LLScreenChannel* channel;
ChannelElem() : id(LLUUID("")), chiclet(NULL), channel(NULL) { }
ChannelElem(const ChannelElem &elem)
{
id = elem.id;
chiclet = elem.chiclet;
channel = elem.channel;
}
bool operator == (const LLUUID &id_op) const
{
return (id == id_op);
}
bool operator == (const LLChiclet* chiclet_op) const
{
return (chiclet == chiclet_op);
}
};
LLChannelManager();
virtual ~LLChannelManager();
//TODO: make protected? in order to be shure that channels are created only by notification handlers
LLScreenChannel* createChannel(LLChannelManager::Params& p);
LLScreenChannel* getChannelByID(const LLUUID id);
LLScreenChannel* getChannelByChiclet(const LLChiclet* chiclet);
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
private:
std::vector<ChannelElem> mChannelList;
};
}
#endif

View File

@ -0,0 +1,525 @@
/**
* @file llchatitemscontainer.cpp
* @brief chat history scrolling panel implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 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$
*/
#include "llviewerprecompiledheaders.h"
#include "llchatitemscontainerctrl.h"
#include "lltextbox.h"
#include "llchatmsgbox.h"
#include "llavatariconctrl.h"
#include "llfloaterreg.h"
#include "lltrans.h"
#include "llviewercontrol.h"
static const S32 BORDER_MARGIN = 2;
static const S32 PARENT_BORDER_MARGIN = 0;
static const S32 HORIZONTAL_MULTIPLE = 8;
static const S32 VERTICAL_MULTIPLE = 16;
static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
#define MAX_CHAT_HISTORY 100
static LLDefaultChildRegistry::Register<LLChatItemsContainerCtrl> t2("chat_items_container");
//*******************************************************************************************************************
//LLChatItemCtrl
//*******************************************************************************************************************
LLChatItemCtrl* LLChatItemCtrl::createInstance()
{
LLChatItemCtrl* item = new LLChatItemCtrl();
LLUICtrlFactory::getInstance()->buildPanel(item, "panel_chat_item.xml");
return item;
}
void LLChatItemCtrl::draw()
{
LLPanel::draw();
}
void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent )
{
LLPanel::reshape(width, height,called_from_parent);
LLPanel* caption = getChild<LLPanel>("msg_caption",false,false);
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text",false,false);
if(caption && msg_text)
{
LLRect caption_rect = caption->getRect();
caption_rect.setLeftTopAndSize( 2, height, width - 4, caption_rect.getHeight());
caption->reshape( width - 4, caption_rect.getHeight(), 1);
caption->setRect(caption_rect);
LLRect msg_text_rect = msg_text->getRect();
msg_text_rect.setLeftTopAndSize( 10, height - caption_rect.getHeight() , width - 20, height - caption_rect.getHeight());
msg_text->reshape( width - 20, height - caption_rect.getHeight(), 1);
msg_text->setRect(msg_text_rect);
}
}
BOOL LLChatItemCtrl::postBuild()
{
return LLPanel::postBuild();
}
std::string LLChatItemCtrl::appendTime()
{
time_t utc_time;
utc_time = time_corrected();
std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
+LLTrans::getString("TimeMin")+"] ";
LLSD substitution;
substitution["datetime"] = (S32) utc_time;
LLStringUtil::format (timeStr, substitution);
return timeStr;
}
void LLChatItemCtrl::addText (const std::string& message)
{
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text",false,false);
if(msg_text)
msg_text->addText(message);
mMessages.push_back(message);
}
void LLChatItemCtrl::setMessage (const LLChat& msg)
{
LLPanel* caption = getChild<LLPanel>("msg_caption",false,false);
if(!caption)
return;
caption->getChild<LLTextBox>("sender_name",false,false)->setText(msg.mFromName);
std::string tt = appendTime();
caption->getChild<LLTextBox>("msg_time",false,false)->setText(tt);
caption->getChild<LLAvatarIconCtrl>("avatar_icon",false,false)->setValue(msg.mFromID);
mOriginalMessage = msg;
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text",false,false);
if(msg_text)
msg_text->setText(msg.mText);
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT)
msg_inspector->setVisible(false);
mMessages.clear();
}
void LLChatItemCtrl::setWidth(S32 width)
{
LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text",false,false);
if(!text_box)
return;///actually assert fits better
text_box->reshape(width - 20,100/*its not magic number, we just need any number*/);
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text",false,false);
if(msg_text && mOriginalMessage.mText.length())
msg_text->setText(mOriginalMessage.mText);
for(size_t i=0;i<mMessages.size();++i)
msg_text->addText(mMessages[i]);
S32 new_height = text_box->getTextPixelHeight();
LLRect panel_rect = getRect();
panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, width , 35 + new_height);
reshape( width, panel_rect.getHeight(), 1);
setRect(panel_rect);
}
void LLChatItemCtrl::onMouseLeave (S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("msg_caption",false,false);
if(!caption)
return;
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
if(msg_inspector)
msg_inspector->setVisible(false);
}
void LLChatItemCtrl::onMouseEnter (S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("msg_caption",false,false);
if(!caption)
return;
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
if(msg_inspector)
msg_inspector->setVisible(true);
}
BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("msg_caption",false,false);
if(mOriginalMessage.mSourceType == CHAT_SOURCE_AGENT && caption)
{
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
if(msg_inspector)
{
S32 local_x = x - msg_inspector->getRect().mLeft - caption->getRect().mLeft;
S32 local_y = y - msg_inspector->getRect().mBottom - caption->getRect().mBottom;
if(msg_inspector->pointInView(local_x, local_y))
{
LLFloaterReg::showInstance("mini_inspector", mOriginalMessage.mFromID);
}
}
}
return LLPanel::handleMouseDown(x,y,mask);
}
void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e)
{
LLPanel* caption = getChild<LLPanel>("msg_caption",false,false);
if(!caption)
return;
LLUICtrl* icon = caption->getChild<LLUICtrl>("avatar_icon",false,false);
LLUICtrl* name = caption->getChild<LLUICtrl>("sender_name",false,false);
if(icon == 0 || name == 0)
return;
icon->setVisible(e == CHATITEMHEADER_SHOW_ONLY_ICON || e==CHATITEMHEADER_SHOW_BOTH);
name->setVisible(e == CHATITEMHEADER_SHOW_ONLY_NAME || e==CHATITEMHEADER_SHOW_BOTH);
}
bool LLChatItemCtrl::canAddText ()
{
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text",false,false);
if(!msg_text )
return false;
return msg_text->getTextLinesNum()<10;
}
//*******************************************************************************************************************
//LLChatItemsContainerCtrl
//*******************************************************************************************************************
LLChatItemsContainerCtrl::LLChatItemsContainerCtrl(const Params& params):LLPanel(params)
{
mEShowItemHeader = CHATITEMHEADER_SHOW_BOTH;
}
void LLChatItemsContainerCtrl::addMessage(const LLChat& msg)
{
/*
if(msg.mChatType == CHAT_TYPE_DEBUG_MSG)
return;
*/
if(mItems.size() >= MAX_CHAT_HISTORY)
{
LLChatItemCtrl* item = mItems[0];
removeChild(item);
delete item;
}
if(mItems.size() > 0 && msg.mFromID == mItems[mItems.size()-1]->getMessage().mFromID && mItems[mItems.size()-1]->canAddText())
{
mItems[mItems.size()-1]->addText(msg.mText);
mItems[mItems.size()-1]->setWidth(getRect().getWidth() - 16);
}
else
{
LLChatItemCtrl* item = LLChatItemCtrl::createInstance();
mItems.push_back(item);
addChild(item,0);
item->setWidth(getRect().getWidth() - 16);
item->setMessage(msg);
item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names"));
item->setVisible(true);
}
arrange(getRect().getWidth(),getRect().getHeight());
updateLayout(getRect().getWidth(),getRect().getHeight());
scrollToBottom();
}
void LLChatItemsContainerCtrl::scrollToBottom ()
{
if(mScrollbar->getVisible())
{
mScrollbar->setDocPos(mScrollbar->getDocPosMax());
onScrollPosChangeCallback(0,0);
}
}
void LLChatItemsContainerCtrl::draw()
{
LLLocalClipRect clip(getRect());
LLPanel::draw();
}
void LLChatItemsContainerCtrl::reshape (S32 width, S32 height, BOOL called_from_parent )
{
S32 delta_width = width - getRect().getWidth();
S32 delta_height = height - getRect().getHeight();
if (delta_width || delta_height || sForceReshape)
{
arrange(width, height);
}
updateBoundingRect();
}
void LLChatItemsContainerCtrl::arrange (S32 width, S32 height)
{
S32 delta_width = width - getRect().getWidth();
if(delta_width)//width changed...too bad. now we need to reformat all items
reformatHistoryScrollItems(width);
calcRecuiredHeight();
show_hide_scrollbar(width,height);
updateLayout(width,height);
}
void LLChatItemsContainerCtrl::reformatHistoryScrollItems(S32 width)
{
for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it)
{
(*it)->setWidth(width);
}
}
S32 LLChatItemsContainerCtrl::calcRecuiredHeight ()
{
S32 rec_height = 0;
std::vector<LLChatItemCtrl*>::iterator it;
for(it=mItems.begin(); it!=mItems.end(); ++it)
{
rec_height += (*it)->getRect().getHeight();
}
mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
return mInnerRect.getHeight();
}
void LLChatItemsContainerCtrl::updateLayout (S32 width, S32 height)
{
S32 panel_top = height - BORDER_MARGIN ;
S32 panel_width = width;
if(mScrollbar->getVisible())
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
panel_top+=mScrollbar->getDocPos();
panel_width-=scrollbar_size;
}
//set sizes for first pannels and dragbars
for(size_t i=0;i<mItems.size();++i)
{
LLRect panel_rect = mItems[i]->getRect();
panelSetLeftTopAndSize(mItems[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
panel_top-=panel_rect.getHeight();
}
}
void LLChatItemsContainerCtrl::show_hide_scrollbar (S32 width, S32 height)
{
calcRecuiredHeight();
if(getRecuiredHeight() > height )
showScrollbar(width, height);
else
hideScrollbar(width, height);
}
void LLChatItemsContainerCtrl::showScrollbar (S32 width, S32 height)
{
bool was_visible = mScrollbar->getVisible();
mScrollbar->setVisible(true);
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
panelSetLeftTopAndSize(mScrollbar,width-scrollbar_size
,height-PARENT_BORDER_MARGIN,scrollbar_size,height-2*PARENT_BORDER_MARGIN);
mScrollbar->setPageSize(height);
mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
if(was_visible)
{
S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
mScrollbar->setDocPos(scroll_pos);
updateLayout(width,height);
return;
}
}
void LLChatItemsContainerCtrl::hideScrollbar (S32 width, S32 height)
{
if(mScrollbar->getVisible() == false)
return;
mScrollbar->setVisible(false);
mScrollbar->setDocPos(0);
if(mItems.size()>0)
{
S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel
S32 diff = panel_top - mItems[0]->getRect().mTop;
shiftPanels(diff);
}
}
//---------------------------------------------------------------------------------
void LLChatItemsContainerCtrl::panelSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
{
if(!panel)
return;
LLRect panel_rect = panel->getRect();
panel_rect.setLeftTopAndSize( left, top, width, height);
panel->reshape( width, height, 1);
panel->setRect(panel_rect);
}
void LLChatItemsContainerCtrl::panelShiftVertical(LLView* panel,S32 delta)
{
if(!panel)
return;
panel->translate(0,delta);
}
void LLChatItemsContainerCtrl::shiftPanels(S32 delta)
{
//Arrange panels
for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it)
{
panelShiftVertical((*it),delta);
}
}
//---------------------------------------------------------------------------------
void LLChatItemsContainerCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
{
updateLayout(getRect().getWidth(),getRect().getHeight());
}
BOOL LLChatItemsContainerCtrl::postBuild()
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
LLRect scroll_rect;
scroll_rect.setOriginAndSize(
getRect().getWidth() - scrollbar_size,
1,
scrollbar_size,
getRect().getHeight() - 1);
LLScrollbar::Params sbparams;
sbparams.name("scrollable vertical");
sbparams.rect(scroll_rect);
sbparams.orientation(LLScrollbar::VERTICAL);
sbparams.doc_size(mInnerRect.getHeight());
sbparams.doc_pos(0);
sbparams.page_size(mInnerRect.getHeight());
sbparams.step_size(VERTICAL_MULTIPLE);
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.change_callback(boost::bind(&LLChatItemsContainerCtrl::onScrollPosChangeCallback, this, _1, _2));
mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
LLView::addChild( mScrollbar );
mScrollbar->setVisible( true );
mScrollbar->setFollowsRight();
mScrollbar->setFollowsTop();
mScrollbar->setFollowsBottom();
reformatHistoryScrollItems(getRect().getWidth());
arrange(getRect().getWidth(),getRect().getHeight());
return LLPanel::postBuild();
}
BOOL LLChatItemsContainerCtrl::handleMouseDown (S32 x, S32 y, MASK mask)
{
return LLPanel::handleMouseDown(x,y,mask);
}
BOOL LLChatItemsContainerCtrl::handleKeyHere (KEY key, MASK mask)
{
if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
return TRUE;
return LLPanel::handleKeyHere(key,mask);
}
BOOL LLChatItemsContainerCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks )
{
if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
return TRUE;
return false;
}
void LLChatItemsContainerCtrl::setHeaderVisibility(EShowItemHeader e)
{
if(e == mEShowItemHeader)
return;
mEShowItemHeader = e;
for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it)
{
(*it)->setHeaderVisibility(e);
}
}

View File

@ -0,0 +1,152 @@
/**
* @file llchatitemscontainer.h
* @brief chat history scrolling panel implementation
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-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_LLCHATITEMSCONTAINER_H_
#define LL_LLCHATITEMSCONTAINER_H_
#include "llpanel.h"
#include "llscrollbar.h"
#include "string"
#include "llchat.h"
typedef enum e_show_item_header
{
CHATITEMHEADER_SHOW_ONLY_NAME = 0,
CHATITEMHEADER_SHOW_ONLY_ICON = 1,
CHATITEMHEADER_SHOW_BOTH
} EShowItemHeader;
class LLChatItemCtrl: public LLPanel
{
protected:
LLChatItemCtrl(){};
public:
~LLChatItemCtrl(){}
static LLChatItemCtrl* createInstance();
void draw();
const LLChat& getMessage() const { return mOriginalMessage;}
void addText (const std::string& message);
void setMessage (const LLChat& msg);
void setWidth (S32 width);
bool canAddText ();
void onMouseLeave (S32 x, S32 y, MASK mask);
void onMouseEnter (S32 x, S32 y, MASK mask);
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
virtual BOOL postBuild();
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
void setHeaderVisibility(EShowItemHeader e);
private:
std::string appendTime ();
private:
LLChat mOriginalMessage;
std::vector<std::string> mMessages;
};
class LLChatItemsContainerCtrl: public LLPanel
{
public:
struct Params
: public LLInitParam::Block<Params, LLPanel::Params>
{
Params(){};
};
LLChatItemsContainerCtrl(const Params& params);
~LLChatItemsContainerCtrl(){}
void addMessage (const LLChat& msg);
void draw();
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
void onScrollPosChangeCallback(S32, LLScrollbar*);
virtual BOOL postBuild();
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
BOOL handleKeyHere (KEY key, MASK mask);
BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
void scrollToBottom ();
void setHeaderVisibility(EShowItemHeader e);
EShowItemHeader getHeaderVisibility() const { return mEShowItemHeader;};
private:
void reformatHistoryScrollItems(S32 width);
void arrange (S32 width, S32 height);
S32 calcRecuiredHeight ();
S32 getRecuiredHeight () const { return mInnerRect.getHeight(); }
void updateLayout (S32 width, S32 height);
void show_hide_scrollbar (S32 width, S32 height);
void showScrollbar (S32 width, S32 height);
void hideScrollbar (S32 width, S32 height);
void panelSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height);
void panelShiftVertical (LLView* panel,S32 delta);
void shiftPanels (S32 delta);
private:
std::vector<LLChatItemCtrl*> mItems;
EShowItemHeader mEShowItemHeader;
LLRect mInnerRect;
LLScrollbar* mScrollbar;
};
#endif

View File

@ -0,0 +1,390 @@
/**
* @file llchatmsgbox.cpp
* @brief chat history text box, able to show array of strings with separator
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-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$
*/
#include "llviewerprecompiledheaders.h"
#include "llchatmsgbox.h"
#include "llwindow.h"
#include "llfocusmgr.h"
static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
LLChatMsgBox::Params::Params()
: text_color("text_color"),
highlight_on_hover("hover", false),
border_visible("border_visible", false),
border_drop_shadow_visible("border_drop_shadow_visible", false),
bg_visible("bg_visible", false),
use_ellipses("use_ellipses"),
word_wrap("word_wrap", false),
hover_color("hover_color"),
disabled_color("disabled_color"),
background_color("background_color"),
border_color("border_color"),
v_pad("v_pad", 0),
h_pad("h_pad", 0),
line_spacing("line_spacing", 0),
text("text"),
font_shadow("font_shadow", LLFontGL::NO_SHADOW)
{}
LLChatMsgBox::LLChatMsgBox(const LLChatMsgBox::Params& p)
: LLUICtrl(p),
mFontGL(p.font),
mHoverActive( p.highlight_on_hover ),
mHasHover( FALSE ),
mBackgroundVisible( p.bg_visible ),
mBorderVisible( p.border_visible ),
mShadowType( p.font_shadow ),
mBorderDropShadowVisible( p.border_drop_shadow_visible ),
mUseEllipses( p.use_ellipses ),
mHPad(p.h_pad),
mVPad(p.v_pad),
mVAlign( LLFontGL::TOP ),
mClickedCallback(NULL),
mTextColor(p.text_color()),
mDisabledColor(p.disabled_color()),
mBackgroundColor(p.background_color()),
mBorderColor(p.border_color()),
mHoverColor(p.hover_color()),
mHAlign(p.font_halign),
mLineSpacing(p.line_spacing),
mWordWrap( p.word_wrap ),
mFontStyle(LLFontGL::getStyleFromString(p.font.style))
{
setText( p.text() );
}
BOOL LLChatMsgBox::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
// HACK: Only do this if there actually is a click callback, so that
// overly large text boxes in the older UI won't start eating clicks.
if (mClickedCallback)
{
handled = TRUE;
// Route future Mouse messages here preemptively. (Release on mouse up.)
gFocusMgr.setMouseCapture( this );
if (getSoundFlags() & MOUSE_DOWN)
{
make_ui_sound("UISndClick");
}
}
return handled;
}
BOOL LLChatMsgBox::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
// We only handle the click if the click both started and ended within us
// HACK: Only do this if there actually is a click callback, so that
// overly large text boxes in the older UI won't start eating clicks.
if (mClickedCallback
&& hasMouseCapture())
{
handled = TRUE;
// Release the mouse
gFocusMgr.setMouseCapture( NULL );
if (getSoundFlags() & MOUSE_UP)
{
make_ui_sound("UISndClickRelease");
}
// DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
// If mouseup in the widget, it's been clicked
if (mClickedCallback)
{
mClickedCallback();
}
}
return handled;
}
BOOL LLChatMsgBox::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = LLView::handleHover(x,y,mask);
if(mHoverActive)
{
mHasHover = TRUE; // This should be set every frame during a hover.
getWindow()->setCursor(UI_CURSOR_ARROW);
}
return (handled || mHasHover);
}
void LLChatMsgBox::addText( const LLStringExplicit& text )
{
boost::shared_ptr<text_block> t(new text_block());
t->text = wrapText(text);
setLineLengths(*t);
mTextStrings.push_back(t);
}
void LLChatMsgBox::setText(const LLStringExplicit& text)
{
mTextStrings.clear();
addText(text);
}
void LLChatMsgBox::resetLineLengths()
{
for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
it!=mTextStrings.end();++it)
{
boost::shared_ptr<text_block> tblock = *it;
setLineLengths(*tblock);
}
}
void LLChatMsgBox::setLineLengths(text_block& t)
{
t.lines.clear();
std::string::size_type cur = 0;
std::string::size_type len = t.text.length();
while (cur < len)
{
std::string::size_type end = t.text.getWString().find('\n', cur);
std::string::size_type runLen;
if (end == std::string::npos)
{
runLen = len - cur;
cur = len;
}
else
{
runLen = end - cur;
cur = end + 1; // skip the new line character
}
t.lines.push_back( (S32)runLen );
}
}
std::string LLChatMsgBox::wrapText(const LLStringExplicit& in_text, F32 max_width)
{
if (max_width < 0.0f)
{
max_width = (F32)getRect().getWidth();
}
LLWString wtext = utf8str_to_wstring(in_text);
LLWString final_wtext;
LLWString::size_type cur = 0;;
LLWString::size_type len = wtext.size();
while (cur < len)
{
LLWString::size_type end = wtext.find('\n', cur);
if (end == LLWString::npos)
{
end = len;
}
LLWString::size_type runLen = end - cur;
if (runLen > 0)
{
LLWString run(wtext, cur, runLen);
LLWString::size_type useLen =
mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
final_wtext.append(wtext, cur, useLen);
cur += useLen;
// not enough room to add any more characters
if (useLen == 0) break;
}
if (cur < len)
{
if (wtext[cur] == '\n')
cur += 1;
else
final_wtext += '\n';
}
}
std::string final_text = wstring_to_utf8str(final_wtext);
return final_text;
}
S32 LLChatMsgBox::getTextLinesNum()
{
S32 num_lines = 0;
for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
it!=mTextStrings.end();++it)
{
boost::shared_ptr<text_block> tblock = *it;
num_lines+=tblock->lines.size();
}
if( num_lines < 1 )
{
num_lines = 1;
}
return num_lines;
}
S32 LLChatMsgBox::getTextPixelHeight()
{
S32 num_lines = getTextLinesNum();
return (S32)(num_lines * mFontGL->getLineHeight() + (num_lines-1)*4);
}
void LLChatMsgBox::setValue(const LLSD& value )
{
setText(value.asString());
}
void LLChatMsgBox::draw()
{
if (mBorderVisible)
{
gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
}
if( mBorderDropShadowVisible )
{
static LLUICachedControl<LLColor4> color_drop_shadow ("ColorDropShadow", *(new LLColor4));
static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0);
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
color_drop_shadow, drop_shadow_tooltip);
}
if (mBackgroundVisible)
{
LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
gl_rect_2d( r, mBackgroundColor.get() );
}
S32 text_x = 0;
switch( mHAlign )
{
case LLFontGL::LEFT:
text_x = mHPad;
break;
case LLFontGL::HCENTER:
text_x = getRect().getWidth() / 2;
break;
case LLFontGL::RIGHT:
text_x = getRect().getWidth() - mHPad;
break;
}
S32 text_y = getRect().getHeight() - mVPad;
if ( getEnabled() )
{
if(mHasHover)
{
drawText( text_x, text_y, mHoverColor.get() );
}
else
{
drawText( text_x, text_y, mTextColor.get() );
}
}
else
{
drawText( text_x, text_y, mDisabledColor.get() );
}
if (sDebugRects)
{
drawDebugRect();
}
//// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
//std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
//if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
//{
// drawDebugRect();
//}
mHasHover = FALSE; // This is reset every frame.
}
void LLChatMsgBox::reshape(S32 width, S32 height, BOOL called_from_parent)
{
// reparse line lengths
LLView::reshape(width, height, called_from_parent);
resetLineLengths();
}
void LLChatMsgBox::drawText( S32 x, S32 y, const LLColor4& color )
{
S32 width = getRect().getWidth()-10;
for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
it!=mTextStrings.end();++it)
{
boost::shared_ptr<text_block> tblock = *it;
S32 cur_pos = 0;
for (std::vector<S32>::iterator iter = tblock->lines.begin();
iter != tblock->lines.end(); ++iter)
{
S32 line_length = *iter;
mFontGL->render(tblock->text, cur_pos, (F32)x, (F32)y, color,
mHAlign, mVAlign,
mFontStyle,
mShadowType,
line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses );
cur_pos += line_length + 1;
y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing;
}
std::vector< boost::shared_ptr<text_block> >::iterator next = it;
++next;
if(next == mTextStrings.end())
break;
//separator
gl_line_2d(5,y-2,width,y-2,LLColor4::grey);
y-=4;
}
}

View File

@ -0,0 +1,163 @@
/**
* @file llchatmsgbox.h
* @brief chat history text box, able to show array of strings with separator
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-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_LLCHATMSGBOX_H
#define LL_LLCHATMSGBOX_H
#include "lluictrl.h"
#include "v4color.h"
#include "llstring.h"
#include "lluistring.h"
class LLChatMsgBox
: public LLUICtrl
{
protected:
struct text_block
{
LLUIString text;
std::vector<S32> lines;
};
public:
typedef boost::function<void (void)> callback_t;
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<std::string> text;
Optional<bool> highlight_on_hover,
border_visible,
border_drop_shadow_visible,
bg_visible,
use_ellipses,
word_wrap;
Optional<LLFontGL::ShadowType> font_shadow;
Optional<LLUIColor> text_color,
hover_color,
disabled_color,
background_color,
border_color;
Optional<S32> v_pad,
h_pad,
line_spacing;
Params();
};
protected:
LLChatMsgBox(const Params&);
friend class LLUICtrlFactory;
public:
virtual void draw();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
void setColor( const LLColor4& c ) { mTextColor = c; }
void setDisabledColor( const LLColor4& c) { mDisabledColor = c; }
void setBackgroundColor( const LLColor4& c) { mBackgroundColor = c; }
void setBorderColor( const LLColor4& c) { mBorderColor = c; }
void setHoverColor( const LLColor4& c ) { mHoverColor = c; }
void setHoverActive( BOOL active ) { mHoverActive = active; }
void setText( const LLStringExplicit& text );
void addText( const LLStringExplicit& text );
void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; }
void setBorderVisible(BOOL visible) { mBorderVisible = visible; }
void setBorderDropshadowVisible(BOOL visible){ mBorderDropShadowVisible = visible; }
void setHPad(S32 pixels) { mHPad = pixels; }
void setVPad(S32 pixels) { mVPad = pixels; }
void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button
const LLFontGL* getFont() const { return mFontGL; }
S32 getTextPixelHeight();
S32 getTextLinesNum();
virtual void setValue(const LLSD& value );
private:
std::string wrapText (const LLStringExplicit& in_text, F32 max_width = -1.0);
void setLineLengths (text_block& t);
void resetLineLengths ();
void drawText (S32 x, S32 y, const LLColor4& color );
const LLFontGL* mFontGL;
LLUIColor mTextColor;
LLUIColor mDisabledColor;
LLUIColor mBackgroundColor;
LLUIColor mBorderColor;
LLUIColor mHoverColor;
BOOL mHoverActive;
BOOL mHasHover;
BOOL mBackgroundVisible;
BOOL mBorderVisible;
BOOL mWordWrap;
U8 mFontStyle; // style bit flags for font
LLFontGL::ShadowType mShadowType;
BOOL mBorderDropShadowVisible;
BOOL mUseEllipses;
S32 mLineSpacing;
S32 mHPad;
S32 mVPad;
LLFontGL::HAlign mHAlign;
LLFontGL::VAlign mVAlign;
callback_t mClickedCallback;
//same as mLineLengthList and mText in LLTextBox
std::vector< boost::shared_ptr<text_block> > mTextStrings;
};
#endif

View File

@ -62,9 +62,11 @@ LLNotificationChiclet::Params::Params()
: 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);
@ -327,9 +329,12 @@ BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
createPopupMenu();
updateMenuItems();
mPopupMenu->arrangeAndClear();
if (mPopupMenu)
{
mPopupMenu->arrangeAndClear();
}
LLMenuGL::showPopup(this, mPopupMenu, x, y);
return TRUE;

View File

@ -0,0 +1,362 @@
/**
* @file LLNearbyChat.cpp
* @brief Nearby chat history scrolling panel implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 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$
*/
#include "llviewerprecompiledheaders.h"
#include "llnearbychat.h"
#include "llviewercontrol.h"
#include "llviewerwindow.h"
#include "llrootview.h"
#include "llchatitemscontainerctrl.h"
#include "lliconctrl.h"
#include "llsidetray.h"
#include "llfocusmgr.h"
#include "llresizebar.h"
#include "llresizehandle.h"
#include "llmenugl.h"
#include "llviewermenu.h"//for gMenuHolder
static const S32 RESIZE_BAR_THICKNESS = 3;
LLNearbyChat::LLNearbyChat(const LLSD& key) :
LLFloater(key),
mEChatTearofState(CHAT_PINNED)
{
}
LLNearbyChat::~LLNearbyChat()
{
}
BOOL LLNearbyChat::postBuild()
{
//resize bars
setCanResize(true);
mResizeBar[LLResizeBar::BOTTOM]->setVisible(false);
mResizeBar[LLResizeBar::LEFT]->setVisible(false);
mResizeBar[LLResizeBar::RIGHT]->setVisible(false);
mResizeHandle[0]->setVisible(false);
mResizeHandle[1]->setVisible(false);
mResizeHandle[2]->setVisible(false);
mResizeHandle[3]->setVisible(false);
//menu
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2));
registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2));
LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(menu)
mPopupMenuHandle = menu->getHandle();
gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true);
LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false);
if(panel)
{
panel->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names"));
}
reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
return LLFloater::postBuild();
}
void LLNearbyChat::addMessage(const LLChat& message)
{
LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false);
if(!panel)
return;
panel->addMessage(message);
}
void LLNearbyChat::onNearbySpeakers()
{
LLSD param = "nearby_panel";
LLSideTray::getInstance()->showPanel("panel_people",param);
}
void LLNearbyChat::onTearOff()
{
if(mEChatTearofState == CHAT_PINNED)
float_panel();
else
pinn_panel();
}
void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLFloater::reshape(width, height, called_from_parent);
LLPanel* caption = getChild<LLPanel>("chat_caption",false,false);
LLRect resize_rect;
resize_rect.setLeftTopAndSize( 0, height, width, RESIZE_BAR_THICKNESS);
if (mResizeBar[LLResizeBar::TOP])
{
mResizeBar[LLResizeBar::TOP]->reshape(width,RESIZE_BAR_THICKNESS);
mResizeBar[LLResizeBar::TOP]->setRect(resize_rect);
}
resize_rect.setLeftTopAndSize( 0, RESIZE_BAR_THICKNESS, width, RESIZE_BAR_THICKNESS);
if (mResizeBar[LLResizeBar::BOTTOM])
{
mResizeBar[LLResizeBar::BOTTOM]->reshape(width,RESIZE_BAR_THICKNESS);
mResizeBar[LLResizeBar::BOTTOM]->setRect(resize_rect);
}
resize_rect.setLeftTopAndSize( 0, height, RESIZE_BAR_THICKNESS, height);
if (mResizeBar[LLResizeBar::LEFT])
{
mResizeBar[LLResizeBar::LEFT]->reshape(RESIZE_BAR_THICKNESS,height);
mResizeBar[LLResizeBar::LEFT]->setRect(resize_rect);
}
resize_rect.setLeftTopAndSize( width - RESIZE_BAR_THICKNESS, height, RESIZE_BAR_THICKNESS, height);
if (mResizeBar[LLResizeBar::RIGHT])
{
mResizeBar[LLResizeBar::RIGHT]->reshape(RESIZE_BAR_THICKNESS,height);
mResizeBar[LLResizeBar::RIGHT]->setRect(resize_rect);
}
LLRect caption_rect;
if (caption)
{
caption_rect = caption->getRect();
caption_rect.setLeftTopAndSize( 2, height - RESIZE_BAR_THICKNESS, width - 4, caption_rect.getHeight());
caption->reshape( width - 4, caption_rect.getHeight(), 1);
caption->setRect(caption_rect);
}
LLPanel* scroll_panel = getChild<LLPanel>("chat_history",false,false);
if (scroll_panel)
{
LLRect scroll_rect = scroll_panel->getRect();
scroll_rect.setLeftTopAndSize( 2, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS, width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2);
scroll_panel->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1);
scroll_panel->setRect(scroll_rect);
}
//
if(mEChatTearofState == CHAT_PINNED)
{
const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
LLRect panel_rect;
panel_rect.setLeftTopAndSize( parent_rect.mLeft+2, parent_rect.mBottom+height+4, width, height);
setRect(panel_rect);
}
else
{
LLRect panel_rect;
panel_rect.setLeftTopAndSize( getRect().mLeft, getRect().mTop, width, height);
setRect(panel_rect);
}
}
BOOL LLNearbyChat::handleMouseDown (S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("chat_caption",false,false);
if(caption)
{
LLUICtrl* nearby_speakers_btn = caption->getChild<LLUICtrl>("nearby_speakers_btn");
LLUICtrl* tearoff_btn = caption->getChild<LLUICtrl>("tearoff_btn");
LLUICtrl* close_btn = caption->getChild<LLUICtrl>("close_btn");
S32 caption_local_x = x - caption->getRect().mLeft;
S32 caption_local_y = y - caption->getRect().mBottom;
if(nearby_speakers_btn && tearoff_btn)
{
S32 local_x = caption_local_x - nearby_speakers_btn->getRect().mLeft;
S32 local_y = caption_local_y - nearby_speakers_btn->getRect().mBottom;
if(nearby_speakers_btn->pointInView(local_x, local_y))
{
onNearbySpeakers();
bringToFront( x, y );
return true;
}
local_x = caption_local_x - tearoff_btn->getRect().mLeft;
local_y = caption_local_y- tearoff_btn->getRect().mBottom;
if(tearoff_btn->pointInView(local_x, local_y))
{
onTearOff();
bringToFront( x, y );
return true;
}
if(close_btn)
{
local_x = caption_local_x - close_btn->getRect().mLeft;
local_y = caption_local_y - close_btn->getRect().mBottom;
if(close_btn->pointInView(local_x, local_y))
{
setVisible(false);
bringToFront( x, y );
return true;
}
}
}
if(mEChatTearofState == CHAT_UNPINNED && caption->pointInView(caption_local_x, caption_local_y) )
{
//start draggind
gFocusMgr.setMouseCapture(this);
mStart_Y = y;
mStart_X = x;
bringToFront( x, y );
return true;
}
}
return LLFloater::handleMouseDown(x,y,mask);
}
BOOL LLNearbyChat::handleMouseUp(S32 x, S32 y, MASK mask)
{
if( hasMouseCapture() )
{
// Release the mouse
gFocusMgr.setMouseCapture( NULL );
mStart_X = 0;
mStart_Y = 0;
return true;
}
return LLFloater::handleMouseUp(x,y,mask);
}
BOOL LLNearbyChat::handleHover(S32 x, S32 y, MASK mask)
{
if( hasMouseCapture() )
{
translate(x-mStart_X,y-mStart_Y);
return true;
}
return LLFloater::handleHover(x,y,mask);
}
void LLNearbyChat::pinn_panel()
{
mEChatTearofState = CHAT_PINNED;
LLPanel* caption = getChild<LLPanel>("chat_caption",false,false);
LLIconCtrl* tearoff_btn = caption->getChild<LLIconCtrl>("tearoff_btn",false,false);
tearoff_btn->setValue("inv_item_landmark_visited.tga");
const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
LLRect panel_rect;
panel_rect.setLeftTopAndSize( parent_rect.mLeft+2, parent_rect.mBottom+getRect().getHeight()+4, getRect().getWidth(), getRect().getHeight());
setRect(panel_rect);
mResizeBar[LLResizeBar::BOTTOM]->setVisible(false);
mResizeBar[LLResizeBar::LEFT]->setVisible(false);
mResizeBar[LLResizeBar::RIGHT]->setVisible(false);
}
void LLNearbyChat::float_panel()
{
mEChatTearofState = CHAT_UNPINNED;
LLPanel* caption = getChild<LLPanel>("chat_caption",false,false);
LLIconCtrl* tearoff_btn = caption->getChild<LLIconCtrl>("tearoff_btn",false,false);
tearoff_btn->setValue("inv_item_landmark.tga");
mResizeBar[LLResizeBar::BOTTOM]->setVisible(true);
mResizeBar[LLResizeBar::LEFT]->setVisible(true);
mResizeBar[LLResizeBar::RIGHT]->setVisible(true);
}
void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)
{
LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false);
if(!panel)
return;
std::string str = userdata.asString();
if(str == "show_buddy_icons")
panel->setHeaderVisibility(CHATITEMHEADER_SHOW_ONLY_ICON);
else if(str == "show_names")
panel->setHeaderVisibility(CHATITEMHEADER_SHOW_ONLY_NAME);
else if(str == "show_icons_and_names")
panel->setHeaderVisibility(CHATITEMHEADER_SHOW_BOTH);
gSavedSettings.setS32("nearbychat_showicons_and_names", (S32)panel->getHeaderVisibility());
}
bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)
{
LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false);
if(!panel)
return false;
std::string str = userdata.asString();
if(str == "show_buddy_icons")
return panel->getHeaderVisibility() == CHATITEMHEADER_SHOW_ONLY_ICON;
else if(str == "show_names")
return panel->getHeaderVisibility() == CHATITEMHEADER_SHOW_ONLY_NAME;
else if(str == "show_icons_and_names")
return panel->getHeaderVisibility() == CHATITEMHEADER_SHOW_BOTH;
else if(str == "nearby_people")
onNearbySpeakers();
return false;
}
BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("chat_caption",false,false);
if(caption && caption->pointInView(x - caption->getRect().mLeft, y - caption->getRect().mBottom) )
{
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
if(menu)
{
menu->buildDrawLabels();
menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, menu, x, y);
}
return true;
}
return LLFloater::handleRightMouseDown(x, y, mask);
}

View File

@ -0,0 +1,98 @@
/**
* @file llnearbychat.h
* @brief nearby chat history scrolling panel implementation
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-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_LLNEARBYCHAT_H_
#define LL_LLNEARBYCHAT_H_
#include "llfloater.h"
#include "llscrollbar.h"
#include "llchat.h"
class LLResizeBar;
class LLNearbyChat: public LLFloater
{
public:
// enumerations used by the chat system
typedef enum e_chat_tearof_state
{
CHAT_PINNED = 0,
CHAT_UNPINNED = 1,
} EChatTearofState;
enum { RESIZE_BAR_COUNT=4 };
LLNearbyChat(const LLSD& key);
~LLNearbyChat();
LLNearbyChat():mEChatTearofState(CHAT_PINNED){};
LLNearbyChat(const Params& params):mEChatTearofState(CHAT_PINNED){};
//static LLNearbyChat* createInstance();
//static LLNearbyChat* getInstance ();
BOOL postBuild ();
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
BOOL handleMouseUp (S32 x, S32 y, MASK mask);
BOOL handleHover (S32 x, S32 y, MASK mask);
BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
void addMessage (const LLChat& message);
void onNearbySpeakers ();
void onTearOff();
void onNearbyChatContextMenuItemClicked(const LLSD& userdata);
bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
virtual void onClose(bool app_quitting) { if(app_quitting) destroy(); else setVisible(false); }
private:
void pinn_panel();
void float_panel();
private:
EChatTearofState mEChatTearofState;
S32 mStart_X;
S32 mStart_Y;
//LLResizeBar* mResizeBar[RESIZE_BAR_COUNT];
LLHandle<LLView> mPopupMenuHandle;
};
#endif

View File

@ -0,0 +1,118 @@
/**
* @file LLNearbyChatHandler.cpp
* @brief Nearby chat notification managment
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 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$
*/
#include "llviewerprecompiledheaders.h"
#include "llnearbychathandler.h"
#include "llchatitemscontainerctrl.h"
#include "llnearbychat.h"
#include "llrecentpeople.h"
#include "llviewercontrol.h"
#include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance
//add LLNearbyChatHandler to LLNotificationsUI namespace
namespace LLNotificationsUI{
LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id)
{
mType = type;
LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
/////////////////////////////////////////////////////
LLChannelManager::Params p; //TODO: check and correct
p.id = LLUUID(NEARBY_CHAT_ID);
p.channel_right_bound = nearby_chat->getRect().mRight;
p.channel_width = nearby_chat->getRect().mRight - 16; //HACK: 16 - ?
/////////////////////////////////////////////////////
// Getting a Channel for our notifications
mChannel = LLChannelManager::getInstance()->createChannel(p);
mChannel->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_TOP);
mChannel->setStoreToasts(false);
}
LLNearbyChatHandler::~LLNearbyChatHandler()
{
}
void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
{
if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull())
LLRecentPeople::instance().add(chat_msg.mFromID);
LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
nearby_chat->addMessage(chat_msg);
if(nearby_chat->getVisible())
return;//no need in toast if chat is visible
LLUUID id;
id.generate();
LLChatItemCtrl* item = LLChatItemCtrl::createInstance();
item->setMessage(chat_msg);
item->setWidth(nearby_chat->getRect().getWidth() - 16);
item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names"));
item->setVisible(true);
LLToast* toast = mChannel->addToast(id, item);
toast->setOnMouseEnterCallback(boost::bind(&LLNearbyChatHandler::onToastDestroy, this, toast));
toast->setAndStartTimer(10); //TODO: set correct time
}
void LLNearbyChatHandler::onToastDestroy(LLToast* toast)
{
//TODO: what should be done to toasts here? may be htey are to be destroyed?
//toast->hide();
if(mChannel)
mChannel->removeToastsFromChannel();
else if(toast)
toast->hide();
LLFloaterReg::showTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
}
void LLNearbyChatHandler::onChicletClick(void)
{
}
void LLNearbyChatHandler::onChicletClose(void)
{
}
}

View File

@ -0,0 +1,60 @@
/**
* @file llnearbychathandler.h
* @brief nearby chat notify
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-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_LLNEARBYCHATHANDLER_H
#define LL_LLNEARBYCHATHANDLER_H
#include "llnotificationhandler.h"
#define NEARBY_CHAT_ID "E1158BD6-661C-4981-9DAD-4DCBFF062502"
//add LLNearbyChatHandler to LLNotificationsUI namespace
namespace LLNotificationsUI{
class LLNearbyChatHandler : public LLChatHandler
{
public:
LLNearbyChatHandler(e_notification_type type,const LLSD& id);
virtual ~LLNearbyChatHandler();
virtual void processChat(const LLChat& chat_msg);
virtual void onToastDestroy(LLToast* toast);
virtual void onChicletClick(void);
virtual void onChicletClose(void);
protected:
};
}
#endif /* LL_LLNEARBYCHATHANDLER_H */

View File

@ -0,0 +1,116 @@
/**
* @file llnotificationalerthandler.cpp
* @brief Notification Handler Class for Alert Notifications
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "llnotificationhandler.h"
#include "lltoastnotifypanel.h"
#include "llbottomtray.h"
#include "llviewercontrol.h"
#include "lltoastalertpanel.h"
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false)
{
mType = type;
LLBottomTray* tray = LLBottomTray::getInstance();
LLChannelManager::Params p;
p.id = LLUUID("F3E07BC8-A973-476D-8C7F-F3B7293975D1");
p.channel_right_bound = tray->getRect().getWidth() / 2;
p.channel_width = 0;
p.align = NA_CENTRE;
// Getting a Channel for our notifications
mChannel = LLChannelManager::getInstance()->createChannel(p);
mChannel->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP);
}
//--------------------------------------------------------------------------
LLAlertHandler::~LLAlertHandler()
{
}
//--------------------------------------------------------------------------
void LLAlertHandler::processNotification(const LLSD& notify)
{
LLToast* toast = NULL;
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load")
{
LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);
toast = mChannel->addToast(notification->getID(), (LLToastPanel*)alert_dialog);
if(!toast)
return;
toast->setHideButtonEnabled(false);
toast->setOnToastDestroyCallback((boost::bind(&LLAlertHandler::onToastDestroy, this, toast)));
toast->setCanFade(false);
toast->setModal(mIsModal);
}
else if (notify["sigtype"].asString() == "change")
{
LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);
mChannel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);
}
else
{
mChannel->killToastByNotificationID(notification->getID());
}
}
//--------------------------------------------------------------------------
void LLAlertHandler::onToastDestroy(LLToast* toast)
{
toast->close();
}
//--------------------------------------------------------------------------
void LLAlertHandler::onChicletClick(void)
{
}
//--------------------------------------------------------------------------
void LLAlertHandler::onChicletClose(void)
{
}
//--------------------------------------------------------------------------

View File

@ -0,0 +1,117 @@
/**
* @file llnotificationgrouphandler.cpp
* @brief Notification Handler Class for Group Notifications
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "llnotificationhandler.h"
#include "lltoastgroupnotifypanel.h"
#include "llagent.h"
#include "llbottomtray.h"
#include "llviewercontrol.h"
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id)
{
mType = type;
// getting a Chiclet and creating params for a channel
LLBottomTray* tray = LLBottomTray::getInstance();
mChiclet = tray->getSysWell();
LLChannelManager::Params p;
p.chiclet = mChiclet;
p.channel_right_bound = tray->getRect().mRight - 10; //HACK: need to correctly resolve SysWell's position
p.channel_width = gSavedSettings.getS32("NotifyBoxWidth");
// Getting a Channel for our notifications
mChannel = LLChannelManager::getInstance()->createChannel(p);
}
//--------------------------------------------------------------------------
LLGroupHandler::~LLGroupHandler()
{
}
//--------------------------------------------------------------------------
void LLGroupHandler::processNotification(const LLSD& notify)
{
LLToast* toast = NULL;
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
{
LLPanel* notify_box = new LLToastGroupNotifyPanel(notification);
toast = mChannel->addToast(notification->getID(), notify_box);
if(!toast)
return;
toast->setAndStartTimer(5);
toast->setOnToastDestroyCallback((boost::bind(&LLGroupHandler::onToastDestroy, this, toast)));
mChiclet->setCounter(mChiclet->getCounter() + 1);
}
else if (notify["sigtype"].asString() == "delete")
{
mChannel->killToastByNotificationID(notification->getID());
}
}
//--------------------------------------------------------------------------
void LLGroupHandler::onToastDestroy(LLToast* toast)
{
mChiclet->setCounter(mChiclet->getCounter() - 1);
toast->close();
}
//--------------------------------------------------------------------------
void LLGroupHandler::onChicletClick(void)
{
}
//--------------------------------------------------------------------------
void LLGroupHandler::onChicletClose(void)
{
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

View File

@ -0,0 +1,178 @@
/**
* @file llnotificationhandler.h
* @brief Here are implemented Notification Handling Classes.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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_LLNOTIFICATIONHANDLER_H
#define LL_LLNOTIFICATIONHANDLER_H
#include "llwindow.h"
#include "llnotifications.h"
#include "llchannelmanager.h"
#include "llchat.h"
namespace LLNotificationsUI
{
// ENotificationType enumerates all possible types of notifications that could be met
//
typedef enum e_notification_type
{
NT_NOTIFY,
NT_NOTIFYTIP,
NT_GROUPNOTIFY,
NT_IMCHAT,
NT_GROUPCHAT,
NT_NEARBYCHAT,
NT_ALERT,
NT_ALERTMODAL
} ENotificationType;
/**
* Handler of notification events.
* This handler manages events related to toasts and chicklets. This is base class
* for chat and system notification handlers.
*/
// LLEventHandler is a base class that specifies a common interface for all
// notification handlers. It states, that every handler must react on the follofing
// events:
// - destroying of a toast;
// - clicking on a correspondet chiclet;
// - closing of a correspondent chiclet.
// Also every handler must have the following attributes:
// - type of the notification that this handler is responsible to;
// - pointer to a correspondent chiclet;
// - pointer to a correspondent screen channel, in which all toasts of the handled notification's
// type should be displayed
//
class LLEventHandler
{
public:
virtual ~LLEventHandler() {};
virtual void onToastDestroy(LLToast* toast)=0;
virtual void onChicletClick(void)=0;
virtual void onChicletClose(void)=0;
LLScreenChannel* mChannel;
LLChiclet* mChiclet;
e_notification_type mType;
};
// LLSysHandler and LLChatHandler are more specific base classes
// that divide all notification handlers on to groups:
// - handlers for different system notifications (script dialogs, tips, group notices and alerts);
// - handlers for different messaging notifications (nearby chat, IM chat, group chat etc.)
/**
* Handler for system notifications.
*/
class LLSysHandler : public LLEventHandler
{
public:
virtual ~LLSysHandler() {};
virtual void processNotification(const LLSD& notify)=0;
};
/**
* Handler for chat message notifications.
*/
class LLChatHandler : public LLEventHandler
{
public:
virtual ~LLChatHandler() {};
virtual void processChat(const LLChat& chat_msg)=0;
};
/**
* Handler for system informational notices.
* It manages life time of tip and script notices.
*/
class LLInfoHandler : public LLSysHandler
{
public:
LLInfoHandler(e_notification_type type, const LLSD& id);
virtual ~LLInfoHandler();
virtual void processNotification(const LLSD& notify);
virtual void onToastDestroy(LLToast* toast);
virtual void onChicletClick(void);
virtual void onChicletClose(void);
protected:
};
/**
* Handler for group system notices.
*/
class LLGroupHandler : public LLSysHandler
{
public:
LLGroupHandler(e_notification_type type, const LLSD& id);
virtual ~LLGroupHandler();
virtual void processNotification(const LLSD& notify);
virtual void onToastDestroy(LLToast* toast);
virtual void onChicletClick(void);
virtual void onChicletClose(void);
protected:
};
/**
* Handler for alert system notices.
*/
class LLAlertHandler : public LLSysHandler
{
public:
LLAlertHandler(e_notification_type type, const LLSD& id);
virtual ~LLAlertHandler();
void setAlertMode(bool is_modal) { mIsModal = is_modal; }
virtual void processNotification(const LLSD& notify);
virtual void onToastDestroy(LLToast* toast);
virtual void onChicletClick(void);
virtual void onChicletClose(void);
protected:
bool mIsModal;
};
}
#endif

View File

@ -0,0 +1,127 @@
/**
* @file llnotificationmanager.cpp
* @brief Class implements a brige between the old and a new notification sistems
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "llnotificationmanager.h"
#include "llnearbychathandler.h"
#include "boost/bind.hpp"
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
LLNotificationManager::LLNotificationManager()
{
mNotifyHandlers.clear();
init();
}
//--------------------------------------------------------------------------
LLNotificationManager::~LLNotificationManager()
{
}
//--------------------------------------------------------------------------
void LLNotificationManager::init()
{
LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify"));
LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip"));
LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify"));
LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLInfoHandler(NT_NOTIFY, LLSD()));
mNotifyHandlers["notifytip"] = mNotifyHandlers["notify"];
mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD()));
mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD()));
mNotifyHandlers["alertmodal"] = mNotifyHandlers["alert"];
mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD()));
}
//--------------------------------------------------------------------------
bool LLNotificationManager::onNotification(const LLSD& notify)
{
LLSysHandler* handle = NULL;
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (!notification)
return false;
std::string notification_type = notification->getType();
handle = dynamic_cast<LLSysHandler*>(mNotifyHandlers[notification_type].get());
if(!handle)
return false;
if( notification_type == "alertmodal" )
dynamic_cast<LLAlertHandler*>(handle)->setAlertMode(true);
handle->processNotification(notify);
return true;
}
//--------------------------------------------------------------------------
void LLNotificationManager::onChat(const LLChat& msg,ENotificationType type)
{
switch(type)
{
case NT_NEARBYCHAT:
{
LLNearbyChatHandler* handle = dynamic_cast<LLNearbyChatHandler*>(mNotifyHandlers["nearbychat"].get());
if(handle)
handle->processChat(msg);
}
break;
default: //no need to handle all enum types
break;
}
}
//--------------------------------------------------------------------------

View File

@ -0,0 +1,79 @@
// Notification Manager Class
/**
* @file llnotificationmanager.h
* @brief Class implements a brige between the old and a new notification sistems
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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_LLNOTIFICATIONMANAGER_H
#define LL_LLNOTIFICATIONMANAGER_H
#include "lluictrl.h"
#include "llnotificationhandler.h"
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
namespace LLNotificationsUI {
class LLToast;
/**
* Responsible for registering notification handlers.
*/
class LLNotificationManager : public LLUICtrl, public LLSingleton<LLNotificationManager>
{
typedef std::pair<std::string, LLEventHandler*> eventhandlers;
public:
LLNotificationManager();
virtual ~LLNotificationManager();
//TODO: make private
// this method initialize handlers' map for different types of notifications
void init(void);
//TODO: combine processing and storage (*)
// this method reacts on system notifications and calls an appropriate handler
bool onNotification(const LLSD& notification);
// this method reacts on chat notifications and calls an appropriate handler
void onChat(const LLChat& msg,ENotificationType type);
private:
//TODO (*)
std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers;
std::map<std::string, LLChatHandler*> mChatHandlers;
};
}
#endif

View File

@ -0,0 +1,357 @@
/**
* @file llscreenchannel.cpp
* @brief Class implements a channel on a screen in which appropriate toasts may appear.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "lliconctrl.h"
#include "lltextbox.h"
#include "llscreenchannel.h"
#include <algorithm>
using namespace LLNotificationsUI;
#define TOAST_MARGIN 5
#define BOTTOMPANEL_MARGIN 35
#define NAVBAR_MARGIN 60
//--------------------------------------------------------------------------
LLScreenChannel::LLScreenChannel(): mUnreadToastsPanel(NULL),
mToastAlignment(NA_BOTTOM),
mStoreToasts(true),
mOverflowToastHidden(false),
mIsHovering(false),
mControlHovering(false)
{
setFollows(FOLLOWS_RIGHT | FOLLOWS_BOTTOM | FOLLOWS_TOP);
}
void LLScreenChannel::init(S32 channel_position, LLView* root_view)
{
root_view->addChild(this);
setRect( LLRect(channel_position, root_view->getRect().getHeight() - NAVBAR_MARGIN,
channel_position, root_view->getRect().mBottom + BOTTOMPANEL_MARGIN));
}
//--------------------------------------------------------------------------
LLScreenChannel::~LLScreenChannel()
{
}
//--------------------------------------------------------------------------
void LLScreenChannel::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLUICtrl::reshape(width, height, called_from_parent);
if(mToastAlignment != NA_CENTRE)
showToasts();
}
//--------------------------------------------------------------------------
LLToast* LLScreenChannel::addToast(LLUUID id, LLPanel* panel)
{
ToastElem new_toast_elem(id, panel);
mOverflowToastHidden = false;
mToastList.push_back(new_toast_elem);
getRootView()->addChild(new_toast_elem.toast);
new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, new_toast_elem.toast));
if(mControlHovering)
{
new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
}
showToasts();
return new_toast_elem.toast;
}
//--------------------------------------------------------------------------
void LLScreenChannel::onToastFade(LLToast* toast)
{
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
bool destroy_toast = toast->isViewed() || !mStoreToasts || !toast->getCanBeStored();
if(destroy_toast)
{
mToastList.erase(it);
toast->mOnToastDestroy(toast, LLSD());
}
else
{
storeToast((*it));
mToastList.erase(it);
}
showToasts();
}
//--------------------------------------------------------------------------
void LLScreenChannel::storeToast(ToastElem& toast_elem)
{
mStoredToastList.push_back(toast_elem);
}
//--------------------------------------------------------------------------
void LLScreenChannel::loadStoredToastsToChannel()
{
std::vector<ToastElem>::iterator it;
if(mStoredToastList.size() == 0)
return;
mOverflowToastHidden = false;
for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
{
(*it).toast->resetTimer();
mToastList.push_back((*it));
}
mStoredToastList.clear();
showToasts();
}
//--------------------------------------------------------------------------
void LLScreenChannel::killToastByNotificationID(LLUUID id)
{
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
if( it != mToastList.end())
{
LLToast* toast = (*it).toast;
mToastList.erase(it);
toast->mOnToastDestroy(toast, LLSD());
showToasts();
}
}
//--------------------------------------------------------------------------
void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
{
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
if( it != mToastList.end() && panel)
{
LLToast* toast = (*it).toast;
LLPanel* old_panel = toast->getPanel();
toast->removeChild(old_panel);
delete old_panel;
toast->arrange(panel);
toast->resetTimer();
showToasts();
}
}
//--------------------------------------------------------------------------
void LLScreenChannel::showToasts()
{
if(mToastList.size() == 0 || mIsHovering)
return;
hideToastsFromScreen();
switch(mToastAlignment)
{
case NA_TOP :
showToastsTop();
break;
case NA_CENTRE :
showToastsCentre();
break;
case NA_BOTTOM :
showToastsBottom();
}
}
//--------------------------------------------------------------------------
void LLScreenChannel::showToastsBottom()
{
LLRect toast_rect;
S32 bottom = getRect().mBottom;
std::vector<ToastElem>::reverse_iterator it;
for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
{
if(it != mToastList.rbegin())
{
bottom = (*(it-1)).toast->getRect().mTop;
}
toast_rect = (*it).toast->getRect();
toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+TOAST_MARGIN, toast_rect.getWidth() ,toast_rect.getHeight());
(*it).toast->setRect(toast_rect);
if((*it).toast->getRect().mTop > getRect().getHeight())
break;
(*it).toast->setVisible(TRUE);
}
if(it != mToastList.rend() && !mOverflowToastHidden)
{
mHiddenToastsNum = 0;
for(; it != mToastList.rend(); it++)
{
mHiddenToastsNum++;
}
createOverflowToast(bottom);
}
}
//--------------------------------------------------------------------------
void LLScreenChannel::showToastsCentre()
{
LLRect toast_rect;
S32 bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2;
std::vector<ToastElem>::reverse_iterator it;
for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
{
toast_rect = (*it).toast->getRect();
toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + TOAST_MARGIN, toast_rect.getWidth() ,toast_rect.getHeight());
(*it).toast->setRect(toast_rect);
(*it).toast->setVisible(TRUE);
}
}
//--------------------------------------------------------------------------
void LLScreenChannel::showToastsTop()
{
}
//--------------------------------------------------------------------------
void LLScreenChannel::createOverflowToast(S32 bottom)
{
LLRect toast_rect;
mUnreadToastsPanel = new LLToast(NULL);
if(!mUnreadToastsPanel)
return;
mUnreadToastsPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this));
LLTextBox* text_box = mUnreadToastsPanel->getChild<LLTextBox>("text");
LLIconCtrl* icon = mUnreadToastsPanel->getChild<LLIconCtrl>("icon");
std::string toastsNumStr = llformat("%d", mHiddenToastsNum);
std::string text = "You have " + toastsNumStr + " new notifications.";
text_box->setText(text);
text_box->setVisible(TRUE);
icon->setVisible(TRUE);
toast_rect = mUnreadToastsPanel->getRect();
toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+TOAST_MARGIN, toast_rect.getWidth() ,toast_rect.getHeight());
mUnreadToastsPanel->setRect(toast_rect);
mUnreadToastsPanel->setAndStartTimer(5);
getRootView()->addChild(mUnreadToastsPanel);
mUnreadToastsPanel->setVisible(TRUE);
}
//--------------------------------------------------------------------------
void LLScreenChannel::onOverflowToastHide()
{
mOverflowToastHidden = true;
}
//--------------------------------------------------------------------------
void LLScreenChannel::hideToastsFromScreen()
{
if(mUnreadToastsPanel)
{
mUnreadToastsPanel->close();
delete mUnreadToastsPanel;
mUnreadToastsPanel = NULL;
}
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
(*it).toast->setVisible(FALSE);
}
//--------------------------------------------------------------------------
void LLScreenChannel::removeToastsFromChannel()
{
hideToastsFromScreen();
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
{
(*it).toast->close();
//toast->mOnToastDestroy(toast, LLSD()); //TODO: check OnToastDestroy handler for chat
}
mToastList.clear();
}
//--------------------------------------------------------------------------
void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
{
// because of LLViewerWindow::updateUI() that ALWAYS calls onMouseEnter BEFORE onMouseLeave
// we must check this to prevent incorrect setting for hovering in a channel
std::map<LLToast*, bool>::iterator it_first, it_second;
S32 stack_size = mToastEventStack.size();
mIsHovering = mouse_enter;
switch(stack_size)
{
case 0:
mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter));
break;
case 1:
it_first = mToastEventStack.begin();
if((*it_first).second && !mouse_enter && ((*it_first).first != toast) )
{
mToastEventStack.clear();
mIsHovering = true;
}
else
{
mToastEventStack.clear();
mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter));
}
break;
default:
LL_ERRS ("LLScreenChannel::onToastHover: stack size error " ) << stack_size << llendl;
}
if(!mIsHovering)
showToasts();
}
//--------------------------------------------------------------------------

View File

@ -0,0 +1,136 @@
/**
* @file llscreenchannel.h
* @brief Class implements a channel on a screen in which appropriate toasts may appear.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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_LLSCREENCHANNEL_H
#define LL_LLSCREENCHANNEL_H
#include "lltoast.h"
#include <map>
#include <boost/shared_ptr.hpp>
namespace LLNotificationsUI
{
typedef enum e_notification_toast_alignment
{
NA_TOP,
NA_CENTRE,
NA_BOTTOM,
} EToastAlignment;
/**
* Screen channel manages toasts visibility and positioning on the screen.
*/
class LLScreenChannel : public LLUICtrl
{
public:
LLScreenChannel();
virtual ~LLScreenChannel();
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
LLToast* addToast(LLUUID id, LLPanel* panel);
void init(S32 channel_position, LLView* root_view);
void killToastByNotificationID(LLUUID id);
void modifyToastByNotificationID(LLUUID id, LLPanel* panel);
void setToastAlignment(e_notification_toast_alignment align) {mToastAlignment = align;}
void setControlHovering(bool control) { mControlHovering = control; }
void setHovering(bool hovering) { mIsHovering = hovering; }
void removeToastsFromChannel();
void hideToastsFromScreen();
void setStoreToasts(bool store) { mStoreToasts = store; }
void loadStoredToastsToChannel();
void showToasts();
e_notification_toast_alignment getToastAlignment() {return mToastAlignment;}
private:
struct ToastElem
{
LLUUID id;
LLToast* toast;
ToastElem(LLUUID lluuid, LLPanel* panel) : id(lluuid)
{
toast = new LLToast(panel);
}
ToastElem(const ToastElem& toast_elem)
{
id = toast_elem.id;
toast = toast_elem.toast;
}
bool operator == (const LLUUID &id_op) const
{
return (id == id_op);
}
bool operator == (LLPanel* panel_op) const
{
return (toast == panel_op);
}
};
void onToastHover(LLToast* toast, bool mouse_enter);
void onToastFade(LLToast* toast);
void storeToast(ToastElem& toast_elem);
void showToastsBottom();
void showToastsCentre();
void showToastsTop();
void createOverflowToast(S32 bottom);
void onOverflowToastHide();
bool mControlHovering;
bool mIsHovering;
bool mStoreToasts;
bool mOverflowToastHidden;
S32 mHiddenToastsNum;
LLToast* mUnreadToastsPanel;
std::vector<ToastElem> mToastList;
std::vector<ToastElem> mStoredToastList;
e_notification_toast_alignment mToastAlignment;
std::map<LLToast*, bool> mToastEventStack;
};
}
#endif

View File

@ -36,7 +36,7 @@
#include "llsidetray.h"
#include "llviewerwindow.h"
#include "llaccordionpanel.h"
#include "llaccordionctrl.h"
#include "llfocusmgr.h"
#include "llrootview.h"
@ -113,7 +113,7 @@ bool LLSideTray::instanceCreated ()
return sInstance!=0;
}
LLSideTrayTab::LLSideTrayTab(const Params& params):mAccordionPanel(0)
LLSideTrayTab::LLSideTrayTab(const Params& params):mAccordionCtrl(0)
{
mImagePath = params.image_path;
@ -131,18 +131,18 @@ void LLSideTrayTab::addPanel(LLPanel* panel)
bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
{
if(mAccordionPanel == 0)
if(mAccordionCtrl == 0)
{
mAccordionPanel = new LLAccordionPanel();
mAccordionPanel->setVisible(TRUE);
LLPanel::addChild(mAccordionPanel,tab_group);
mAccordionCtrl = new LLAccordionCtrl();
mAccordionCtrl->setVisible(TRUE);
LLPanel::addChild(mAccordionCtrl,tab_group);
}
bool res = true;
if(TAB_PANEL_CAPTION_NAME != view->getName())//skip our caption panel
{
mAccordionPanel->addCollapsibleCtrl(view);
mAccordionCtrl->addCollapsibleCtrl(view);
}
else
res = LLPanel::addChild(view,tab_group);
@ -185,17 +185,17 @@ void LLSideTrayTab::arrange(S32 width, S32 height )
offset = title_panel->getRect().getHeight();
}
LLRect sRect = mAccordionPanel->getRect();
LLRect sRect = mAccordionCtrl->getRect();
sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin);
mAccordionPanel->setRect(sRect);
mAccordionCtrl->setRect(sRect);
mAccordionPanel->setMaxWidth(sRect.getWidth());
mAccordionPanel->arrange();
mAccordionCtrl->setMaxWidth(sRect.getWidth());
mAccordionCtrl->arrange();
}
void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent )
{
if(!mAccordionPanel)
if(!mAccordionCtrl)
return;
S32 offset = 0;
@ -210,12 +210,12 @@ void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent )
LLRect sRect = mAccordionPanel->getRect();
LLRect sRect = mAccordionCtrl->getRect();
sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin);
mAccordionPanel->setMaxWidth(sRect.getWidth());
mAccordionPanel->reshape(sRect.getWidth(), sRect.getHeight());
mAccordionCtrl->setMaxWidth(sRect.getWidth());
mAccordionCtrl->reshape(sRect.getWidth(), sRect.getHeight());
mAccordionPanel->setRect(sRect);
mAccordionCtrl->setRect(sRect);
}
@ -231,7 +231,7 @@ void LLSideTrayTab::draw()
void LLSideTrayTab::onOpen (const LLSD& key)
{
mAccordionPanel->onOpen(key);
mAccordionCtrl->onOpen(key);
}
LLSideTrayTab* LLSideTrayTab::createInstance ()

View File

@ -37,7 +37,7 @@
#include "string"
class LLSideTray;
class LLAccordionPanel;
class LLAccordionCtrl;
class LLSideTrayTab: public LLPanel
{
@ -86,7 +86,7 @@ private:
std::string mImagePath;
std::string mDescription;
LLAccordionPanel* mAccordionPanel;
LLAccordionCtrl* mAccordionCtrl;
};

236
indra/newview/lltoast.cpp Normal file
View File

@ -0,0 +1,236 @@
/**
* @file lltoast.cpp
* @brief This class implements a placeholder for any notification panel.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "llfocusmgr.h"
#include "lltoast.h"
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
LLToast::LLToast(LLPanel* panel) :
LLFloater(),
mTimerValue(5),
mIsViewed(false),
mPanel(panel),
mCanFade(true),
mHideBtn(NULL),
mIsModal(false),
mCanBeStored(true)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_toast.xml");
mHideBtn = getChild<LLButton>("hide_btn");
if(mHideBtn)
{
mHideBtn->setClickedCallback(boost::bind(&LLToast::hide,this));
}
if(mPanel)
{
arrange(mPanel);
}
// disable unnecessary Floater's functionality
setTitleVisible(FALSE);
setCanMinimize(FALSE);
setCanClose(FALSE);
setCanTearOff(FALSE);
setCanResize(FALSE);
setCanDrag(FALSE);
}
//--------------------------------------------------------------------------
void LLToast::setHideButtonEnabled(bool enabled)
{
if(mHideBtn)
mHideBtn->setEnabled(enabled);
}
//--------------------------------------------------------------------------
LLToast::~LLToast()
{
if(mIsModal)
{
gFocusMgr.unlockFocus();
gFocusMgr.releaseFocusIfNeeded( this );
}
}
//--------------------------------------------------------------------------
void LLToast::setAndStartTimer(F32 period)
{
if(mCanFade)
{
mTimerValue = period;
mTimer.start();
}
}
//--------------------------------------------------------------------------
bool LLToast::timerHasExpired()
{
if (mTimer.getStarted())
{
F32 elapsed_time = mTimer.getElapsedTimeF32();
if (elapsed_time > 4)
{
setBackgroundOpaque(FALSE);
}
if (elapsed_time > mTimerValue)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------
void LLToast::hide()
{
setVisible(FALSE); //TODO: store in Chiclet's history
mIsViewed = false;
mTimer.stop();
mOnFade(this, LLSD());
}
//--------------------------------------------------------------------------
void LLToast::setCanFade(bool can_fade)
{
mCanFade = can_fade;
if(!mCanFade)
mTimer.stop();
}
//--------------------------------------------------------------------------
void LLToast::tick()
{
if(mCanFade)
{
setVisible(FALSE);
mTimer.stop();
mOnFade(this, LLSD());
}
}
//--------------------------------------------------------------------------
void LLToast::arrange(LLPanel* panel)
{
LLRect panel_rect, toast_rect;
panel_rect = panel->getRect();
reshape(panel_rect.getWidth(), panel_rect.getHeight());
panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
panel->setRect(panel_rect);
addChild(panel);
}
//--------------------------------------------------------------------------
void LLToast::draw()
{
if(timerHasExpired())
{
tick();
}
LLFloater::draw();
}
//--------------------------------------------------------------------------
void LLToast::setModal(bool modal)
{
mIsModal = modal;
if(mIsModal)
{
gFocusMgr.setMouseCapture( this );
gFocusMgr.setTopCtrl( this );
setFocus(TRUE);
}
}
//--------------------------------------------------------------------------
void LLToast::setVisible(BOOL show)
{
if(show)
{
setBackgroundOpaque(TRUE);
}
LLPanel::setVisible(show);
if(mPanel)
{
if(!mPanel->isDead())
{
mPanel->setVisible(show);
}
}
}
//--------------------------------------------------------------------------
void LLToast::onMouseEnter(S32 x, S32 y, MASK mask)
{
mOnToastHover(this, MOUSE_ENTER);
setVisibleAndFrontmost();
setBackgroundOpaque(TRUE);
if(mCanFade && !mIsViewed)
{
mTimer.stop();
}
sendChildToFront(mHideBtn);
if(mHideBtn && mHideBtn->getEnabled())
mHideBtn->setVisible(TRUE);
mOnMousEnter(this, LLSD());
}
//--------------------------------------------------------------------------
void LLToast::onMouseLeave(S32 x, S32 y, MASK mask)
{
mOnToastHover(this, MOUSE_LEAVE);
if(mCanFade && !mIsViewed)
{
mTimer.start();
}
if(mHideBtn && mHideBtn->getEnabled())
{
if( mHideBtn->getRect().pointInRect(x, y) )
return;
mHideBtn->setVisible(FALSE);
}
}
//--------------------------------------------------------------------------

114
indra/newview/lltoast.h Normal file
View File

@ -0,0 +1,114 @@
/**
* @file lltoast.h
* @brief This class implements a placeholder for any notification panel.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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_LLTOAST_H
#define LL_LLTOAST_H
#include "llpanel.h"
#include "llfloater.h"
#include "lltimer.h"
#include "lldate.h"
#define MOUSE_LEAVE false
#define MOUSE_ENTER true
namespace LLNotificationsUI
{
/**
* Represents toast pop-up.
* This is a parent view for all toast panels.
*/
class LLToast : public LLFloater
{
public:
LLToast(LLPanel* panel);
virtual ~LLToast();
//
bool isViewed() { return mIsViewed; }
void setCanFade(bool can_fade);
void setHideButtonEnabled(bool enabled);
void setCanBeStored(bool can_be_stored) { mCanBeStored = can_be_stored; }
bool getCanBeStored() { return mCanBeStored; }
//
void setAndStartTimer(F32 period);
//
void resetTimer() { mTimer.start(); }
void close() { die(); }
virtual void draw();
virtual void setVisible(BOOL show);
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void hide();
LLPanel* getPanel() { return mPanel; }
void arrange(LLPanel* panel);
void setModal(bool modal);
// Registers callbacks for events
boost::signals2::connection setOnFadeCallback(commit_callback_t cb) { return mOnFade.connect(cb); }
boost::signals2::connection setOnMouseEnterCallback(commit_callback_t cb) { return mOnMousEnter.connect(cb); }
boost::signals2::connection setOnToastDestroyCallback(commit_callback_t cb) { return mOnToastDestroy.connect(cb); }
typedef boost::function<void (LLToast* toast, bool mouse_enter)> toast_hover_check_callback_t;
typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t;
toast_hover_check_signal_t mOnToastHover;
boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHover.connect(cb); }
commit_signal_t mOnFade;
commit_signal_t mOnMousEnter;
commit_signal_t mOnToastDestroy;
private:
bool timerHasExpired();
void tick();
LLTimer mTimer;
F32 mTimerValue;
LLPanel* mPanel;
LLButton* mHideBtn;
LLColor4 mBgColor;
bool mIsViewed;
bool mCanFade;
bool mIsModal;
bool mCanBeStored;
};
}
#endif

View File

@ -0,0 +1,474 @@
/**
* @file lltoastalertpanel.cpp
* @brief Panel for alert toasts.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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$
*/
#include "llviewerprecompiledheaders.h" // must be first include
#include "linden_common.h"
#include "llboost.h"
#include "lltoastalertpanel.h"
#include "llfontgl.h"
#include "lltextbox.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llkeyboard.h"
#include "llfocusmgr.h"
#include "lliconctrl.h"
#include "llui.h"
#include "lllineeditor.h"
#include "lluictrlfactory.h"
#include "llnotifications.h"
#include "llfunctorregistry.h"
const S32 MAX_ALLOWED_MSG_WIDTH = 400;
const F32 DEFAULT_BUTTON_DELAY = 0.5f;
const S32 MSG_PAD = 8;
/*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL;
/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader;
//-----------------------------------------------------------------------------
// Private methods
static const S32 VPAD = 16;
static const S32 HPAD = 25;
static const S32 BTN_HPAD = 8;
LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
: LLToastPanel(notification),
mDefaultOption( 0 ),
mCheck(NULL),
mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
mLabel(notification->getName()),
mLineEditor(NULL)
{
const LLFontGL* font = LLFontGL::getFontSansSerif();
const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
const S32 EDITOR_HEIGHT = 20;
LLNotificationFormPtr form = mNotification->getForm();
std::string edit_text_name;
std::string edit_text_contents;
bool is_password = false;
LLToastPanel::setBackgroundVisible(FALSE);
LLToastPanel::setBackgroundOpaque(TRUE);
typedef std::vector<std::pair<std::string, std::string> > options_t;
options_t supplied_options;
// for now, get LLSD to iterator over form elements
LLSD form_sd = form->asLLSD();
S32 option_index = 0;
for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it)
{
std::string type = (*it)["type"].asString();
if (type == "button")
{
if((*it)["default"])
{
mDefaultOption = option_index;
}
supplied_options.push_back(std::make_pair((*it)["name"].asString(), (*it)["text"].asString()));
ButtonData data;
if (option_index == mNotification->getURLOption())
{
data.mURL = mNotification->getURL();
data.mURLExternal = mNotification->getURLOpenExternally();
}
mButtonData.push_back(data);
option_index++;
}
else if (type == "text")
{
edit_text_contents = (*it)["value"].asString();
edit_text_name = (*it)["name"].asString();
}
else if (type == "password")
{
edit_text_contents = (*it)["value"].asString();
edit_text_name = (*it)["name"].asString();
is_password = true;
}
}
// Buttons
options_t options;
if (supplied_options.empty())
{
options.push_back(std::make_pair(std::string("close"), LLNotifications::instance().getGlobalString("implicitclosebutton")));
// add data for ok button.
ButtonData ok_button;
mButtonData.push_back(ok_button);
mDefaultOption = 0;
}
else
{
options = supplied_options;
}
S32 num_options = options.size();
// Calc total width of buttons
S32 button_width = 0;
S32 sp = font->getWidth(std::string("OO"));
for( S32 i = 0; i < num_options; i++ )
{
S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
button_width = llmax( w, button_width );
}
S32 btn_total_width = button_width;
if( num_options > 1 )
{
btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD);
}
// Message: create text box using raw string, as text has been structure deliberately
// Use size of created text box to generate dialog box size
std::string msg = mNotification->getMessage();
llwarns << "Alert: " << msg << llendl;
LLTextBox::Params params;
params.name("Alert message");
params.font(font);
params.tab_stop(false);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params);
// Compute max allowable height for the dialog text, so we can allocate
// space before wrapping the text to fit.
S32 max_allowed_msg_height =
gFloaterView->getRect().getHeight()
- LINE_HEIGHT // title bar
- 3*VPAD - BTN_HEIGHT;
msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );
msg_box->setWrappedText(msg, (F32)MAX_ALLOWED_MSG_WIDTH);
msg_box->reshapeToFitText();
const LLRect& text_rect = msg_box->getRect();
S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD;
S32 dialog_height = text_rect.getHeight() + 3 * VPAD + BTN_HEIGHT;
if (hasTitleBar())
{
dialog_height += LINE_HEIGHT; // room for title bar
}
// it's ok for the edit text body to be empty, but we want the name to exist if we're going to draw it
if (!edit_text_name.empty())
{
dialog_height += EDITOR_HEIGHT + VPAD;
dialog_width = llmax(dialog_width, (S32)(font->getWidth( edit_text_contents ) + 0.99f));
}
if (mCaution)
{
// Make room for the caution icon.
dialog_width += 32 + HPAD;
}
LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
S32 msg_y = LLToastPanel::getRect().getHeight() - VPAD;
S32 msg_x = HPAD;
if (hasTitleBar())
{
msg_y -= LINE_HEIGHT; // room for title
}
static LLUIColor alert_caution_text_color = LLUIColorTable::instance().getColor("AlertCautionTextColor");
static LLUIColor alert_text_color = LLUIColorTable::instance().getColor("AlertTextColor");
if (mCaution)
{
LLIconCtrl::Params params;
params.name("icon");
params.rect(LLRect(msg_x, msg_y, msg_x+32, msg_y-32));
params.mouse_opaque(false);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
params.tab_stop(false);
LLIconCtrl * icon = LLUICtrlFactory::create<LLIconCtrl> (params);
icon->setValue ("notify_caution_icon.tga");
icon->setMouseOpaque(FALSE);
LLToastPanel::addChild(icon);
msg_x += 32 + HPAD;
msg_box->setColor( alert_caution_text_color );
}
else
{
msg_box->setColor( alert_text_color );
}
LLRect rect;
rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() );
msg_box->setRect( rect );
LLToastPanel::addChild(msg_box);
// Buttons
S32 button_left = (LLToastPanel::getRect().getWidth() - btn_total_width) / 2;
for( S32 i = 0; i < num_options; i++ )
{
LLRect button_rect;
button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT );
LLButton::Params p;
p.name(options[i].first);
p.rect(button_rect);
p.click_callback.function(boost::bind(&LLToastAlertPanel::onButtonPressed, this, _2, i));
p.font(font);
p.label(options[i].second);
LLButton* btn = LLUICtrlFactory::create<LLButton>(p);
mButtonData[i].mButton = btn;
LLToastPanel::addChild(btn);
if( i == mDefaultOption )
{
btn->setFocus(TRUE);
}
button_left += button_width + BTN_HPAD;
}
// (Optional) Edit Box
if (!edit_text_name.empty())
{
S32 y = VPAD + BTN_HEIGHT + VPAD/2;
LLLineEditor::Params params;
params.name(edit_text_name);
params.rect(LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y));
params.default_text(edit_text_contents);
params.max_length_bytes(STD_STRING_STR_LEN);
mLineEditor = LLUICtrlFactory::create<LLLineEditor> (params);
// make sure all edit keys get handled properly (DEV-22396)
mLineEditor->setHandleEditKeysDirectly(TRUE);
LLToastPanel::addChild(mLineEditor);
}
if (mLineEditor)
{
mLineEditor->setDrawAsterixes(is_password);
setEditTextArgs(notification->getSubstitutions());
}
std::string ignore_label;
if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
{
setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
}
else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
{
setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
}
gFloaterView->adjustToFitScreen(this, FALSE);
LLFloater::setFocus(TRUE);
if (mLineEditor)
{
mLineEditor->setFocus(TRUE);
mLineEditor->selectAll();
}
if(mDefaultOption >= 0)
{
// delay before enabling default button
mDefaultBtnTimer.start();
mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
}
}
bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )
{
const LLFontGL* font = LLFontGL::getFontSansSerif();
const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
// Extend dialog for "check next time"
S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16;
max_msg_width = llmax(max_msg_width, check_width);
S32 dialog_width = max_msg_width + 2 * HPAD;
S32 dialog_height = LLToastPanel::getRect().getHeight();
dialog_height += LINE_HEIGHT;
dialog_height += LINE_HEIGHT / 2;
LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
LLCheckBoxCtrl::Params p;
p.name("check");
p.rect.left(msg_x).bottom(VPAD+BTN_HEIGHT+LINE_HEIGHT/2).width(max_msg_width).height(LINE_HEIGHT);
p.label(check_title);
p.font(font);
p.commit_callback.function(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
mCheck = LLUICtrlFactory::create<LLCheckBoxCtrl>(p);
LLToastPanel::addChild(mCheck);
return true;
}
void LLToastAlertPanel::setVisible( BOOL visible )
{
LLToastPanel::setVisible( visible );
if( visible )
{
make_ui_sound("UISndAlert");
}
}
void LLToastAlertPanel::onClose(bool app_quitting)
{
LLFloater::onClose(app_quitting);
}
LLToastAlertPanel::~LLToastAlertPanel()
{
}
BOOL LLToastAlertPanel::hasTitleBar() const
{
return (getCurrentTitle() != "" && getCurrentTitle() != " ") // has title
|| isMinimizeable()
|| isCloseable();
}
BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask )
{
if( KEY_RETURN == key && mask == MASK_NONE )
{
return TRUE;
}
else if (KEY_RIGHT == key)
{
LLToastPanel::focusNextItem(FALSE);
return TRUE;
}
else if (KEY_LEFT == key)
{
LLToastPanel::focusPrevItem(FALSE);
return TRUE;
}
else if (KEY_TAB == key && mask == MASK_NONE)
{
LLToastPanel::focusNextItem(FALSE);
return TRUE;
}
else if (KEY_TAB == key && mask == MASK_SHIFT)
{
LLToastPanel::focusPrevItem(FALSE);
return TRUE;
}
else
{
return TRUE;
}
}
// virtual
void LLToastAlertPanel::draw()
{
// if the default button timer has just expired, activate the default button
if(mDefaultBtnTimer.hasExpired() && mDefaultBtnTimer.getStarted())
{
mDefaultBtnTimer.stop(); // prevent this block from being run more than once
LLToastPanel::setDefaultBtn(mButtonData[mDefaultOption].mButton);
}
static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow");
static LLUICachedControl<S32> shadow_lines ("DropShadowFloater");
gl_drop_shadow( 0, LLToastPanel::getRect().getHeight(), LLToastPanel::getRect().getWidth(), 0,
shadow_color, shadow_lines);
LLToastPanel::draw();
}
void LLToastAlertPanel::setEditTextArgs(const LLSD& edit_args)
{
if (mLineEditor)
{
std::string msg = mLineEditor->getText();
mLineEditor->setText(msg);
}
else
{
llwarns << "LLToastAlertPanel::setEditTextArgs called on dialog with no line editor" << llendl;
}
}
void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
{
ButtonData* button_data = &mButtonData[button];
LLSD response = mNotification->getResponseTemplate();
if (mLineEditor)
{
response[mLineEditor->getName()] = mLineEditor->getValue();
}
response[button_data->mButton->getName()] = true;
// If we declared a URL and chose the URL option, go to the url
if (!button_data->mURL.empty() && sURLLoader != NULL)
{
sURLLoader->load(button_data->mURL, button_data->mURLExternal);
}
mNotification->respond(response); // new notification reponse
closeFloater(); // deletes self
}
void LLToastAlertPanel::onClickIgnore(LLUICtrl* ctrl)
{
// checkbox sometimes means "hide and do the default" and
// other times means "warn me again". Yuck. JC
BOOL check = ctrl->getValue().asBoolean();
if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
{
// question was "show again" so invert value to get "ignore"
check = !check;
}
mNotification->setIgnored(check);
}

View File

@ -0,0 +1,124 @@
/**
* @file lltoastalertpanel.h
* @brief Panel for alert toasts.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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_TOASTALERTPANEL_H
#define LL_TOASTALERTPANEL_H
#include "lltoastpanel.h"
#include "llfloater.h"
#include "llui.h"
#include "llnotifications.h"
class LLButton;
class LLCheckBoxCtrl;
class LLAlertDialogTemplate;
class LLLineEditor;
/**
* Toast panel for alert notification.
* Alerts notifications doesn't require user interaction.
*
* Replaces class LLAlertDialog.
* https://wiki.lindenlab.com/mediawiki/index.php?title=LLAlertDialog&oldid=81388
*/
class LLToastAlertPanel
: public LLToastPanel,
public LLFloater
{
public:
typedef bool (*display_callback_t)(S32 modal);
class URLLoader
{
public:
virtual void load(const std::string& url, bool force_open_externally = 0 ) = 0;
virtual ~URLLoader() {}
};
static void setURLLoader(URLLoader* loader)
{
sURLLoader = loader;
}
public:
// User's responsibility to call show() after creating these.
LLToastAlertPanel( LLNotificationPtr notep, bool is_modal );
virtual BOOL handleKeyHere(KEY key, MASK mask );
virtual void draw();
virtual void setVisible( BOOL visible );
virtual void onClose(bool app_quitting);
bool setCheckBox( const std::string&, const std::string& );
void setCaution(BOOL val = TRUE) { mCaution = val; }
// If mUnique==TRUE only one copy of this message should exist
void setUnique(BOOL val = TRUE) { mUnique = val; }
void setEditTextArgs(const LLSD& edit_args);
void onClickIgnore(LLUICtrl* ctrl);
void onButtonPressed(const LLSD& data, S32 button);
private:
static std::map<std::string, LLToastAlertPanel*> sUniqueActiveMap;
virtual ~LLToastAlertPanel();
// No you can't kill it. It can only kill itself.
// Does it have a readable title label, or minimize or close buttons?
BOOL hasTitleBar() const;
private:
static URLLoader* sURLLoader;
static LLControlGroup* sSettings;
struct ButtonData
{
LLButton* mButton;
std::string mURL;
U32 mURLExternal;
};
std::vector<ButtonData> mButtonData;
S32 mDefaultOption;
LLCheckBoxCtrl* mCheck;
BOOL mCaution;
BOOL mUnique;
LLUIString mLabel;
LLFrameTimer mDefaultBtnTimer;
// For Dialogs that take a line as text as input:
LLLineEditor* mLineEditor;
};
#endif // LL_TOASTALERTPANEL_H

View File

@ -0,0 +1,137 @@
/**
* @file lltoastgroupnotifypanel.cpp
* @brief Panel for group notify toasts.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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$
*/
#include "llviewerprecompiledheaders.h"
#include "lltoastgroupnotifypanel.h"
#include "llfocusmgr.h"
#include "llbutton.h"
#include "lliconctrl.h"
#include "llnotify.h"
#include "lltextbox.h"
#include "llviewertexteditor.h"
#include "lluiconstants.h"
#include "llui.h"
#include "llviewercontrol.h"
#include "llfloatergroupinfo.h"
#include "lltrans.h"
#include "llinitparam.h"
#include "llglheaders.h"
#include "llagent.h"
#include "llavatariconctrl.h"
LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification)
: LLToastPanel(notification),
mInventoryOffer(NULL)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_notify.xml");
const LLSD& payload = notification->getPayload();
LLGroupData groupData;
if (!gAgent.getGroupData(payload["group_id"].asUUID(),groupData))
{
llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
}
//group icon
LLIconCtrl* pGroupIcon = getChild<LLIconCtrl>("group_icon", TRUE);
pGroupIcon->setValue(groupData.mInsigniaID);
//header title
const std::string& from_name = payload["sender_name"].asString();
std::stringstream from;
from << from_name << "/" << groupData.mName;
LLTextBox* pTitleText = this->getChild<LLTextBox>("title", TRUE, FALSE);
pTitleText->setValue(from.str());
//message body
const std::string& message = payload["message"].asString();
LLTextEditor* pMessageText = getChild< LLTextEditor>("message", TRUE, FALSE);
pMessageText->setEnabled(FALSE);
pMessageText->setTakesFocus(FALSE);
pMessageText->setValue(message);
//attachment
BOOL hasInventory = payload["inventory_offer"].isDefined();
LLTextBox * pAttachLink = getChild<LLTextBox>("attachment", TRUE, FALSE);
pAttachLink->setVisible(hasInventory);
if (hasInventory) {
pAttachLink->setValue(payload["inventory_name"]);
mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]);
childSetActionTextbox("attachment", boost::bind(
&LLToastGroupNotifyPanel::onClickAttachment, this));
}
//ok button
LLButton* pOkBtn = getChild<LLButton>("btn_ok", TRUE, FALSE);
pOkBtn->setClickedCallback((boost::bind(&LLToastGroupNotifyPanel::onClickOk, this)));
setDefaultBtn(pOkBtn);
}
// virtual
LLToastGroupNotifyPanel::~LLToastGroupNotifyPanel()
{
}
void LLToastGroupNotifyPanel::close()
{
// The group notice dialog may be an inventory offer.
// If it has an inventory save button and that button is still enabled
// Then we need to send the inventory declined message
if(mInventoryOffer != NULL)
{
mInventoryOffer->forceResponse(IOR_DECLINE);
mInventoryOffer = NULL;
}
die();
}
void LLToastGroupNotifyPanel::onClickOk()
{
LLSD response = mNotification->getResponseTemplate();
mNotification->respond(response);
close();
}
void LLToastGroupNotifyPanel::onClickAttachment()
{
mInventoryOffer->forceResponse(IOR_ACCEPT);
mInventoryOffer = NULL;
LLTextBox * pAttachLink = getChild<LLTextBox>("attachment", TRUE, FALSE);
pAttachLink->setVisible(FALSE);
}

View File

@ -0,0 +1,82 @@
/**
* @file lltoastgroupnotifypanel.h
* @brief Panel for group notify toasts.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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_LLGROUPNOTIFY_H
#define LL_LLGROUPNOTIFY_H
#include "llfontgl.h"
#include "lltoastpanel.h"
#include "lldarray.h"
#include "lltimer.h"
#include "llviewermessage.h"
#include "llnotifications.h"
class LLButton;
/**
* Toast panel for group notification.
*
* Replaces class LLGroupNotifyBox.
*/
class LLToastGroupNotifyPanel
: public LLToastPanel
{
public:
void close();
static bool onNewNotification(const LLSD& notification);
// Non-transient messages. You can specify non-default button
// layouts (like one for script dialogs) by passing various
// numbers in for "layout".
LLToastGroupNotifyPanel(LLNotificationPtr& notification);
/*virtual*/ ~LLToastGroupNotifyPanel();
protected:
void onClickOk();
void onClickAttachment();
private:
LLButton* mSaveInventoryBtn;
LLUUID mGroupID;
LLOfferInfo* mInventoryOffer;
};
// This view contains the stack of notification windows.
//extern LLView* gGroupNotifyBoxView;
const S32 GROUP_LAYOUT_DEFAULT = 0;
const S32 GROUP_LAYOUT_SCRIPT_DIALOG = 1;
#endif

View File

@ -0,0 +1,435 @@
/**
* @file lltoastnotifypanel.cpp
* @brief Panel for notify toasts.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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$
*/
#include "llviewerprecompiledheaders.h"
#include "lltoastnotifypanel.h"
#include "llviewercontrol.h"
#include "lluiconstants.h"
#include "llrect.h"
#include "lliconctrl.h"
#include "lltexteditor.h"
#include "lltextbox.h"
#include "lldbstrings.h"
#include "llchat.h"
#include "llfloaterchat.h"
#include "lltrans.h"
#include "lloverlaybar.h"
const S32 BOTTOM_PAD = VPAD * 3;
//static
const LLFontGL* LLToastNotifyPanel::sFont = NULL;
const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToastPanel(notification) {
mIsTip = notification->getType() == "notifytip";
mNumOptions = 0;
mNumButtons = 0;
mIsScriptDialog = (notification->getName() == "ScriptDialog"
|| notification->getName() == "ScriptDialogGroup");
mAddedDefaultBtn = false;
// clicking on a button does not steal current focus
setIsChrome(TRUE);
// class init
if (!sFont)
{
sFont = LLFontGL::getFontSansSerif();
sFontSmall = LLFontGL::getFontSansSerifSmall();
}
// setup paramaters
mMessage = notification->getMessage();
// initialize
setFocusRoot(!mIsTip);
// caution flag can be set explicitly by specifying it in the
// notification payload, or it can be set implicitly if the
// notify xml template specifies that it is a caution
//
// tip-style notification handle 'caution' differently -
// they display the tip in a different color
mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
LLNotificationFormPtr form(notification->getForm());
mNumOptions = form->getNumElements();
LLRect rect = mIsTip ? getNotifyTipRect(mMessage)
: getNotifyRect(mNumOptions, mIsScriptDialog, mIsCaution);
setRect(rect);
setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
setBackgroundVisible(FALSE);
setBackgroundOpaque(TRUE);
LLIconCtrl* icon;
LLTextEditor* text;
const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
const S32 BOTTOM = (S32)sFont->getLineHeight();
S32 x = HPAD + HPAD;
S32 y = TOP;
LLIconCtrl::Params common_params;
common_params.rect(LLRect(x, y, x+32, TOP-32));
common_params.mouse_opaque(false);
common_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
common_params.tab_stop(false);
if (mIsTip)
{
// use the tip notification icon
common_params.image(LLUI::getUIImage("notify_tip_icon.tga"));
icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
}
else if (mIsCaution)
{
// use the caution notification icon
common_params.image(LLUI::getUIImage("notify_caution_icon.tga"));
icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
}
else
{
// use the default notification icon
common_params.image(LLUI::getUIImage("notify_box_icon.tga"));
icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
}
icon->setMouseOpaque(FALSE);
addChild(icon);
x += HPAD + HPAD + 32;
// add a caution textbox at the top of a caution notification
LLTextBox* caution_box = NULL;
if (mIsCaution && !mIsTip)
{
S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD;
LLTextBox::Params params;
params.name("caution_box");
params.rect(LLRect(x, y, getRect().getWidth() - 2, caution_height));
params.font(sFont);
params.mouse_opaque(false);
params.font.style("BOLD");
params.text_color(LLUIColorTable::instance().getColor("NotifyCautionWarnColor"));
params.background_color(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
params.border_visible(false);
caution_box = LLUICtrlFactory::create<LLTextBox> (params);
caution_box->setWrappedText(notification->getMessage());
addChild(caution_box);
// adjust the vertical position of the next control so that
// it appears below the caution textbox
y = y - caution_height;
}
else
{
const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);
// Tokenization on \n is handled by LLTextBox
const S32 MAX_LENGTH = 512 + 20 +
DB_FIRST_NAME_BUF_SIZE +
DB_LAST_NAME_BUF_SIZE +
DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title.
LLTextEditor::Params params;
params.name("box");
params.rect(LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16));
params.max_text_length(MAX_LENGTH);
params.default_text(mMessage);
params.font(sFont);
params.allow_embedded_items(false);
params.word_wrap(true);
params.tab_stop(false);
params.mouse_opaque(false);
params.bg_readonly_color(LLColor4::transparent);
params.text_readonly_color(LLUIColorTable::instance().getColor("NotifyTextColor"));
params.takes_non_scroll_clicks(false);
params.hide_scrollbar(true);
params.enabled(false);
params.hide_border(true);
text = LLUICtrlFactory::create<LLTextEditor> (params);
addChild(text);
}
if (mIsTip)
{
// TODO: Make a separate archive for these.
LLChat chat(mMessage);
chat.mSourceType = CHAT_SOURCE_SYSTEM;
LLFloaterChat::addChatHistory(chat);
}
else
{
LLButton::Params p;
p.name(std::string("next"));
p.rect(LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD));
p.image_selected.name("notify_next.png");
p.image_unselected.name("notify_next.png");
p.font(sFont);
p.scale_image(true);
p.tool_tip(LLTrans::getString("next").c_str());
for (S32 i = 0; i < mNumOptions; i++)
{
LLSD form_element = form->getElement(i);
if (form_element["type"].asString() != "button")
{
continue;
}
addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean());
}
if (mNumButtons == 0)
{
addButton("OK", LLTrans::getString("ok"), FALSE, TRUE);
mAddedDefaultBtn = true;
}
}
}
LLToastNotifyPanel::~LLToastNotifyPanel() {
std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
}
LLRect LLToastNotifyPanel::getNotifyRect(S32 num_options, BOOL mIsScriptDialog, BOOL is_caution)
{
S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight");
if (is_caution)
{
// make caution-style dialog taller to accomodate extra text,
// as well as causing the accept/decline buttons to be drawn
// in a different position, to help prevent "quick-click-through"
// of many permissions prompts
notify_height = gSavedSettings.getS32("PermissionsCautionNotifyBoxHeight");
}
const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
const S32 TOP = getRect().getHeight();
const S32 RIGHT =getRect().getWidth();
const S32 LEFT = RIGHT - NOTIFY_WIDTH;
if (num_options < 1)
{
num_options = 1;
}
// Add two "blank" option spaces.
if (mIsScriptDialog)
{
num_options += 2;
}
S32 additional_lines = (num_options-1) / 3;
notify_height += additional_lines * (BTN_HEIGHT + VPAD);
return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
}
// static
LLRect LLToastNotifyPanel::getNotifyTipRect(const std::string &utf8message)
{
S32 line_count = 1;
LLWString message = utf8str_to_wstring(utf8message);
S32 message_len = message.length();
const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
// Make room for the icon area.
const S32 text_area_width = NOTIFY_WIDTH - HPAD * 4 - 32;
const llwchar* wchars = message.c_str();
const llwchar* start = wchars;
const llwchar* end;
S32 total_drawn = 0;
BOOL done = FALSE;
do
{
line_count++;
for (end=start; *end != 0 && *end != '\n'; end++)
;
if( *end == 0 )
{
end = wchars + message_len;
done = TRUE;
}
S32 remaining = end - start;
while( remaining )
{
S32 drawn = sFont->maxDrawableChars( start, (F32)text_area_width, remaining, TRUE );
if( 0 == drawn )
{
drawn = 1; // Draw at least one character, even if it doesn't all fit. (avoids an infinite loop)
}
total_drawn += drawn;
start += drawn;
remaining -= drawn;
if( total_drawn < message_len )
{
if( (wchars[ total_drawn ] != '\n') )
{
// wrap because line was too long
line_count++;
}
}
else
{
done = TRUE;
}
}
total_drawn++; // for '\n'
end++;
start = end;
} while( !done );
const S32 MIN_NOTIFY_HEIGHT = 72;
const S32 MAX_NOTIFY_HEIGHT = 600;
S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight());
if(gOverlayBar)
{
notify_height += gOverlayBar->getBoundingRect().mTop;
}
else
{
// *FIX: this is derived from the padding caused by the
// rounded rects, shouldn't be a const here.
notify_height += 10;
}
notify_height += VPAD;
notify_height = llclamp(notify_height, MIN_NOTIFY_HEIGHT, MAX_NOTIFY_HEIGHT);
const S32 RIGHT = getRect().getWidth();
const S32 LEFT = RIGHT - NOTIFY_WIDTH;
return LLRect(LEFT, notify_height, RIGHT, 0);
}
// static
void LLToastNotifyPanel::onClickButton(void* data)
{
InstanceAndS32* self_and_button = (InstanceAndS32*)data;
LLToastNotifyPanel* self = self_and_button->mSelf;
std::string button_name = self_and_button->mButtonName;
LLSD response = self->mNotification->getResponseTemplate();
if (!self->mAddedDefaultBtn && !button_name.empty())
{
response[button_name] = true;
}
self->mNotification->respond(response);
}
// virtual
LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default)
{
// make caution notification buttons slightly narrower
// so that 3 of them can fit without overlapping the "next" button
S32 btn_width = mIsCaution? 84 : 90;
LLRect btn_rect;
LLButton* btn;
S32 btn_height= BTN_HEIGHT;
const LLFontGL* font = sFont;
S32 ignore_pad = 0;
S32 button_index = mNumButtons;
S32 index = button_index;
S32 x = (HPAD * 4) + 32;
if (mIsScriptDialog)
{
// Add two "blank" option spaces, before the "Ignore" button
index = button_index + 2;
if (button_index == 0)
{
// Ignore button is smaller, less wide
btn_height = BTN_HEIGHT_SMALL;
font = sFontSmall;
ignore_pad = 10;
}
}
btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad,
BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD),
btn_width - 2*ignore_pad,
btn_height);
InstanceAndS32* userdata = new InstanceAndS32;
userdata->mSelf = this;
userdata->mButtonName = is_option ? name : "";
mBtnCallbackData.push_back(userdata);
LLButton::Params p;
p.name(name);
p.label(label);
p.rect(btn_rect);
p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));
p.font(font);
if (mIsCaution)
{
p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
}
btn = LLUICtrlFactory::create<LLButton>(p);
addChild(btn, -1);
if (is_default)
{
setDefaultBtn(btn);
}
mNumButtons++;
return btn;
}

View File

@ -0,0 +1,86 @@
/**
* @file lltoastnotifypanel.h
* @brief Panel for notify toasts.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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 LLTOASTNOTIFYPANEL_H_
#define LLTOASTNOTIFYPANEL_H_
#include "llpanel.h"
#include "llfontgl.h"
#include "llnotifications.h"
#include "llbutton.h"
#include "lltoastpanel.h"
/**
* Toast panel for notification.
* Notification panel should be used for notifications that require a response from the user.
*
* Replaces class LLNotifyBox.
*/
class LLToastNotifyPanel: public LLToastPanel {
public:
LLToastNotifyPanel(LLNotificationPtr&);
virtual ~LLToastNotifyPanel();
bool isTip() {return mIsTip;}
static LLToastNotifyPanel * buildNotifyPanel(LLNotificationPtr notification);
protected:
LLButton* addButton(std::string const &name, const std::string& label, BOOL is_option, BOOL is_default);
// Used for callbacks
struct InstanceAndS32
{
LLToastNotifyPanel* mSelf;
std::string mButtonName;
};
std::vector<InstanceAndS32*> mBtnCallbackData;
private:
// Returns the rect, relative to gNotifyView, where this
// notify box should be placed.
LLRect getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution);
LLRect getNotifyTipRect(const std::string &message);
// internal handler for button being clicked
static void onClickButton(void* data);
bool mIsTip;
bool mAddedDefaultBtn;
bool mIsScriptDialog;
bool mIsCaution; // is this a caution notification?
std::string mMessage;
S32 mNumOptions;
S32 mNumButtons;
static const LLFontGL* sFont;
static const LLFontGL* sFontSmall;
};
#endif /* LLTOASTNOTIFYPANEL_H_ */

View File

@ -0,0 +1,42 @@
/**
* @file lltoastpanel.cpp
* @brief Creates a panel of a specific kind for a toast
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-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$
*/
#include "llviewerprecompiledheaders.h"
#include "lltoastpanel.h"
LLToastPanel::LLToastPanel(LLNotificationPtr& notification) {
mNotification = notification;
}
LLToastPanel::~LLToastPanel() {
}

View File

@ -0,0 +1,53 @@
/**
* @file lltoastpanel.h
* @brief Creates a panel of a specific kind for a toast.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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_LLTOASTPANEL_H
#define LL_LLTOASTPANEL_H
#include "llpanel.h"
#include "llnotifications.h"
/**
* Base class for all panels that can be added to the toast.
* All toast panels should contain necessary logic for representing certain notification
* but shouldn't contain logic related to this panel lifetime control and positioning
* on the parent view.
*/
class LLToastPanel: public LLPanel {
public:
LLToastPanel(LLNotificationPtr&);
virtual ~LLToastPanel() = 0;
protected:
LLNotificationPtr mNotification;
};
#endif /* LL_TOASTPANEL_H */

View File

@ -81,7 +81,7 @@
#include "llfloaterinventory.h"
#include "llmediaremotectrl.h"
#include "llmoveview.h"
#include "llnearbychathistory.h"
#include "llnearbychat.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
@ -109,6 +109,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
LLFloaterReg::add("chat", "floater_chat_history.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChat>);
LLFloaterReg::add("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);
LLFloaterReg::add("communicate", "floater_chatterbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatterBox>);
LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
LLFloaterReg::add("contacts", "floater_my_friends.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyFriends>);
@ -134,7 +135,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("mini_inspector", "panel_mini_inspector.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMiniInspector>);
LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
LLFloaterReg::add("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChatHistory>);
LLFloaterReg::add("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);

View File

@ -43,6 +43,8 @@
#include "llviewertexture.h"
#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
#include "llviewerparcelmedia.h"
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
#include "llversionviewer.h"
#include "llviewertexturelist.h"

View File

@ -143,6 +143,9 @@
#include "llwindebug.h" // For the invalid message handler
#endif
//#include "llnearbychathistory.h"
#include "llnotificationmanager.h"
//
// Constants
//
@ -2370,15 +2373,15 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
switch(chat.mChatType)
{
case CHAT_TYPE_WHISPER:
verb = " " + LLTrans::getString("whisper") + " ";
verb = "(" + LLTrans::getString("whisper") + ")";
break;
case CHAT_TYPE_DEBUG_MSG:
case CHAT_TYPE_OWNER:
case CHAT_TYPE_NORMAL:
verb = ": ";
verb = "";
break;
case CHAT_TYPE_SHOUT:
verb = " " + LLTrans::getString("shout") + " ";
verb = "(" + LLTrans::getString("shout") + ")";
break;
case CHAT_TYPE_START:
case CHAT_TYPE_STOP:
@ -2386,12 +2389,12 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
break;
default:
LL_WARNS("Messaging") << "Unknown type " << chat.mChatType << " in chat!" << LL_ENDL;
verb = " say, ";
verb = "";
break;
}
chat.mText = from_name;
chat.mText = "";
chat.mText += verb;
chat.mText += mesg;
}
@ -2419,12 +2422,14 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
&& (is_linden || !is_busy || is_owned_by_me))
{
// show on screen and add to history
LLFloaterChat::addChat(chat, FALSE, FALSE);
LLNotificationsUI::LLNotificationManager::instance().onChat(
chat, LLNotificationsUI::NT_NEARBYCHAT);
}
else
{
LLNotificationsUI::LLNotificationManager::instance().onChat(
chat, LLNotificationsUI::NT_NEARBYCHAT);
// just add to chat history
LLFloaterChat::addChatHistory(chat);
}
}
}

View File

@ -184,9 +184,11 @@
#include "llpostprocess.h"
#include "llbottomtray.h"
#include "llnotificationmanager.h"
#include "llfloaternotificationsconsole.h"
#include "llnearbychathistory.h"
#include "llnearbychat.h"
#if LL_WINDOWS
#include <tchar.h> // For Unicode conversion methods
@ -1641,6 +1643,15 @@ void LLViewerWindow::initWorldUI()
getRootView()->sendChildToFront(gNotifyBoxView);
// menu holder appears on top to get first pass at all mouse events
getRootView()->sendChildToFront(gMenuHolder);
//Channel Manager
LLNotificationsUI::LLChannelManager * channel_manager
= LLNotificationsUI::LLChannelManager::getInstance();
getRootView()->addChild(channel_manager);
//Notification Manager
LLNotificationsUI::LLNotificationManager* notify_manager =
LLNotificationsUI::LLNotificationManager::getInstance();
getRootView()->addChild(notify_manager);
}
// Destroy the UI
@ -2384,6 +2395,29 @@ void LLViewerWindow::moveCursorToCenter()
LLUI::setCursorPositionScreen(x, y);
}
void LLViewerWindow::updateBottomTrayRect()
{
if(LLBottomTray::instanceExists() && LLSideTray::instanceCreated())
{
S32 side_tray_width = 0;
if(LLSideTray::getInstance()->getVisible())
{
side_tray_width = LLSideTray::getInstance()->getTrayWidth();
}
LLBottomTray* bottom_tray = LLBottomTray::getInstance();
S32 right = llround((F32)mWindowRect.mRight / mDisplayScale.mV[VX]) - side_tray_width;
LLRect rc = bottom_tray->getRect();
if (right != rc.mRight)
{
rc.mRight = right;
bottom_tray->reshape(rc.getWidth(), rc.getHeight(), FALSE);
bottom_tray->setRect(rc);
}
}
}
//////////////////////////////////////////////////////////////////////
//
// Hover handlers
@ -2397,15 +2431,7 @@ void LLViewerWindow::updateUI()
updateWorldViewRect();
if(LLBottomTray::instanceExists() && LLSideTray::instanceCreated())
{
S32 delta = 0;
if(LLSideTray::getInstance()->getVisible())
{
delta = llround((F32)LLSideTray::getInstance()->getTrayWidth() * mDisplayScale.mV[VX]);
}
LLBottomTray::getInstance()->updateRightPosition(mWindowRect.mRight - delta);
}
updateBottomTrayRect();
LLView::sMouseHandlerMessage.clear();

View File

@ -278,6 +278,7 @@ public:
void updatePicking(S32 x, S32 y, MASK mask);
void updateWorldViewRect(bool use_full_window=false);
void updateBottomTrayRect();
BOOL handleKey(KEY key, MASK mask);
void handleScrollWheel (S32 clicks);

View File

@ -75,7 +75,6 @@
#include "llfloatertools.h"
#include "llhudeffectlookat.h"
#include "llhudmanager.h"
#include "llinventoryview.h"
#include "lljoystickbutton.h"
#include "llmenugl.h"
#include "llmorphview.h"

View File

@ -28,5 +28,5 @@
color="1 1 1 1" enabled="true" image_name="closebox.tga"
name="close_btn"/>
</panel>
<chat_history_view bottom="0" width="250" height="320" follows="left|right|top|bottom" name="chat_scroll" />
<chat_items_container bottom="0" width="250" height="320" follows="left|right|top|bottom" name="chat_history" />
</floater>

View File

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<menu bottom="100" color="MenuDefaultBgColor" drop_shadow="true" height="101" left="100"
mouse_opaque="false" name="NearBy Chat Menu" opaque="true" width="128" visible="false">
<menu_item_call bottom_delta="-18" height="18" label="Keep Visible" left="0" mouse_opaque="true"
name="keep_visible" width="128">
<menu_item_call.on_click function="NearbyChat.Action" userdata="keep_visible" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="Show Nearby People..." left="0" mouse_opaque="true"
name="nearby_people" width="128">
<menu_item_call.on_click function="NearbyChat.Action" userdata="nearby_people" />

View File

@ -301,9 +301,11 @@
height="20"
left="22"
top="23"/>
<!--
<chiclet_notification.commit_callback
function="Notification.Show"
parameter="ClickUnimplemented" />
-->
</chiclet_notification>
</layout_panel>
<icon

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- All our XML is utf-8 encoded. -->
<panel
name="instant_message"
width="300"
height="180"
background_opaque="false"
background_visible="true"
follows="left|top|right|bottom"
bg_alpha_color="0.3 0.3 0.3 1.0">
<panel width="250" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="msg_caption">
<avatar_icon
top="25" left="10" width="20" height="20" follows="left|top"
color="1 1 1 1" enabled="true" name="avatar_icon"
/>
<text
width="160" top="25" left="40" height="20" follows="left|right|top"
font="SansSerifBigBold" text_color="white" word_wrap="true"
mouse_opaque="true" name="sender_name" >
Jerry Knight
</text>
<icon top="22" left="170" width="15" height="15" follows="top|right"
image_name="icn_voice-pvtfocus.tga" visible="false" name="msg_inspector"/>
<icon top="22" left="190" width="10" height="10" follows="top|right"
image_name="speaking_indicator.tga" name="msg_icon"/>
<text width="35" top="22" left="205" height="20" follows="right|top"
text_color="white" word_wrap="true" mouse_opaque="true" name="msg_time" >
10:32
</text>
</panel>
<text_chat
top="-35" left="10" right="-10" height="120" follows="left|right|bottom"
font="SansSerifSmall" text_color="white" word_wrap="true"
mouse_opaque="true" name="msg_text" >
</text_chat>
</panel>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel background_visible="true" bevel_style="in" bg_alpha_color="0 0 0 0"
height="200" label="instant_message" layout="topleft" left="0"
name="panel_group_notify" top="0" width="350">
<panel background_visible="true" bevel_style="in" bg_alpha_color="black"
height="50" label="header" layout="topleft" left="0" name="header"
top="0" width="350">
<icon follows="left|top|right|bottom" height="40" width="40" layout="topleft"
top="5" left="5" mouse_opaque="true" name="group_icon"/>
<text type="string" length="1" follows="left|top|right|bottom"
font="SansSerifBigBold" height="20" layout="topleft" left="60" name="title"
text_color="white" top="20" width="300">
Sender Name / Group Name
</text>
</panel>
<text_editor type="string" length="1" bg_readonly_color="0 0 0 0"
follows="left|top|right|bottom" height="70" hide_scrollbar="true"
hide_border="true" layout="topleft" top="55" left="25" name="message"
text_color="white" text_readonly_color="white" width="300" word_wrap="true">
Message
Body
</text_editor>
<text font="SansSerif" font.style="UNDERLINE" font_shadow="hard"
type="string" length="1" follows="left|top|right|bottom" layout="topleft"
left="25" top="135" height="15" width="300" name="attachment"
text_color="white">
Attachment
</text>
<button label="OK" layout="topleft" top="170" left="140" height="20"
width="70" name="btn_ok" />
</panel>

View File

@ -81,7 +81,7 @@
top_delta="0"
width="60" />
<button
enabled="false"
enabled="true"
follows="bottom|right"
font="SansSerifSmallBold"
height="25"

View File

@ -17,7 +17,7 @@
background_visible="true"
bg_opaque_color="0.5 0.5 0.5 1.0"
>
<accordionctrl_tab
<accordion_tab
name="people_accordion"
title="People"
collapsable="true"
@ -35,7 +35,7 @@
label="People"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
<!-- *TODO Vadim: isn't the sidetray_tab "label" attribute redundant since we have "tab_title" ? -->
<sidetray_tab
@ -48,7 +48,7 @@
background_visible="true"
bg_opaque_color="0.5 0.5 0.5 1.0"
>
<accordionctrl_tab
<accordion_tab
name="places_accordian"
title="Places"
collapsable="true"
@ -63,7 +63,7 @@
label="Places"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
<sidetray_tab
@ -75,7 +75,7 @@
background_visible="true"
bg_opaque_color="0.5 0.5 0.5 1.0"
>
<accordionctrl_tab
<accordion_tab
name="me_accordion"
title="Me"
collapsable="false"
@ -90,7 +90,7 @@
label="Me"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
<!--
@ -103,7 +103,7 @@
tab_title="Groups"
description="Manage Groups."
>
<accordionctrl_tab
<accordion_tab
name="group_accordion"
title="Group General"
expanded="true"
@ -119,8 +119,8 @@
label="Group"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="groupland_accordion"
title="Group Land and Money"
expanded="false"
@ -136,8 +136,8 @@
label="Group"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="groupnotices_accordion"
title="Group Notices"
expanded="false"
@ -153,8 +153,8 @@
label="Group"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="grouproles_accordion"
title="Group Roles"
expanded="false"
@ -170,7 +170,7 @@
label="Group"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
@ -184,7 +184,7 @@
tab_title="Previews"
description="Previews."
>
<accordionctrl_tab
<accordion_tab
name="floater_preview_animation"
title="Preview Animation"
collapsable="true"
@ -202,8 +202,8 @@
label="Preview_Animation"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_preview_gesture"
title="Preview Gesture"
collapsable="true"
@ -221,8 +221,8 @@
label="Preview_Gesture"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_preview_existing_landmark"
title="Preview Existing Landmark"
collapsable="true"
@ -240,8 +240,8 @@
label="Preview_Existing_Landmark"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_preview_sound"
title="Preview Sound"
collapsable="true"
@ -259,8 +259,8 @@
label="Preview_Sound"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_preview_url"
title="Preview URL"
collapsable="true"
@ -278,8 +278,8 @@
label="Preview_URL"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_URL_entry"
title="URL Entry"
collapsable="true"
@ -297,7 +297,7 @@
label="URL_entry"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
<sidetray_tab
@ -310,7 +310,7 @@
tab_title="Region"
description="Region."
>
<accordionctrl_tab
<accordion_tab
name="panel_region_covenant"
title="Region Covenant"
collapsable="true"
@ -328,8 +328,8 @@
label="Panel_Region_Covenant"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="panel_region_debug"
title="Region Debug"
collapsable="true"
@ -347,8 +347,8 @@
label="Panel_Region_Debug"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="panel_region_estate"
title="Region Estate"
collapsable="true"
@ -366,8 +366,8 @@
label="Panel_Region_Estate"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="panel_region_general"
title="Region General"
collapsable="true"
@ -385,8 +385,8 @@
label="Panel_Region_General"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="panel_region_terrain"
title="Region Terrain"
collapsable="true"
@ -404,8 +404,8 @@
label="Panel_Region_Terrain"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="panel_region_texture"
title="Region Texture"
collapsable="true"
@ -423,8 +423,8 @@
label="Panel_Region_Texture"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_region_info"
title="Region Info"
collapsable="true"
@ -442,7 +442,7 @@
label="Floater_Region_Info"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
<sidetray_tab
@ -455,7 +455,7 @@
tab_title="Build"
description="Build"
>
<accordionctrl_tab
<accordion_tab
name="floater_tools"
title="Tools"
collapsable="true"
@ -473,8 +473,8 @@
label="Tools"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_bulk_perms"
title="Bulk Perms"
collapsable="true"
@ -492,8 +492,8 @@
label="Tools"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_build_options"
title="Build Options"
collapsable="true"
@ -511,7 +511,7 @@
label="Tools"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
@ -525,7 +525,7 @@
tab_title="Other Tools"
description="Other Tools"
>
<accordionctrl_tab
<accordion_tab
name="floater_gesture"
title="Gestures"
collapsable="true"
@ -543,9 +543,9 @@
label="Gesture"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
<accordionctrl_tab
<accordion_tab
name="floater_buy_contents"
title="Buy Contents"
collapsable="true"
@ -563,8 +563,8 @@
label="buy_contents"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_buy_object"
title="Buy Object"
collapsable="true"
@ -583,7 +583,7 @@
border="true"
/>
</collapsible_ctrl>
<accordionctrl_tab
<accordion_tab
name="floater_inventory_view_finder"
title="Inventory View Finder"
collapsable="true"
@ -601,8 +601,8 @@
label="view_finder"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_mute"
title="Mute"
collapsable="true"
@ -620,8 +620,8 @@
label="mute"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_sell_land"
title="Sell Land"
collapsable="true"
@ -639,8 +639,8 @@
label="sell_land"
border="true"
/>
</accordionctrl_tab>
<accordionctrl_tab
</accordion_tab>
<accordion_tab
name="floater_telehub"
title="Telehub"
collapsable="true"
@ -658,7 +658,7 @@
label="telehub"
border="true"
/>
</accordionctrl_tab>
</accordion_tab>
</sidetray_tab>
-->

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- All our XML is utf-8 encoded. -->
<panel
name="toast"
title="toast"
visible="false"
layout="topleft"
width="350"
height="72"
left="100"
top="500"
follows="right|bottom"
background_opaque="true"
background_visible="true"
bevel_style="in"
bg_alpha_color="0.3 0.3 0.3 1.0">
<text
type="string"
visible="false"
follows="left|top|right|bottom"
font="SansSerifBold"
height="40"
layout="topleft"
left="60"
name="text"
text_color="white"
top="30"
width="290">
Toast text;
</text>
<icon
top="20"
left="10"
width="32"
height="32"
follows="top|left"
layout="topleft"
visible="false"
color="1 1 1 1"
enabled="true"
image_name="notify_tip_icon.tga"
mouse_opaque="true"
name="icon"
/>
<button
layout="topleft"
top="-5"
left="335"
width="20"
height="20"
follows="top|right"
visible="false"
enabled="true"
mouse_opaque="true"
name="hide_btn"
label=""
image_unselected="toast_hide_btn.tga"
image_disabled="toast_hide_btn.tga"
image_selected="toast_hide_btn.tga"
image_hover_selected="toast_hide_btn.tga"
image_disabled_selected="toast_hide_btn.tga"
/>
</panel>