diff options
| author | Steven Bennetts <steve@lindenlab.com> | 2009-07-21 00:59:14 +0000 | 
|---|---|---|
| committer | Steven Bennetts <steve@lindenlab.com> | 2009-07-21 00:59:14 +0000 | 
| commit | cef46d16453873691406c22be39ce0ee5e8076d1 (patch) | |
| tree | d7df442ce4af8e8001d7e7bf5647f116b35f929e | |
| parent | 73a97010e6c8c7874fdc1778ab46e492f77d9394 (diff) | |
merge https://svn.aws.productengine.com/secondlife/pe/stable-1/indra -r 1078-1091 -> viewer-2.0.0-3
48 files changed, 5326 insertions, 133 deletions
| diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 5a609a2e40..b1d33f48e9 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -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; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ac3163a1bd..5dec4a8688 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -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 diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index e37b660951..d84dd09812 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -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 diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 1d4e271f80..330afeb647 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -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; diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp new file mode 100644 index 0000000000..723bf2a248 --- /dev/null +++ b/indra/newview/llchannelmanager.cpp @@ -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(); +		} +	} +} + +//-------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------- + + + + + + + diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h new file mode 100644 index 0000000000..564535ff24 --- /dev/null +++ b/indra/newview/llchannelmanager.h @@ -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 + diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp new file mode 100644 index 0000000000..27ebccfe25 --- /dev/null +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -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); +	} +} + + diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h new file mode 100644 index 0000000000..f5791078aa --- /dev/null +++ b/indra/newview/llchatitemscontainerctrl.h @@ -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 + + diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp new file mode 100644 index 0000000000..8fb4b78cb8 --- /dev/null +++ b/indra/newview/llchatmsgbox.cpp @@ -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; +	} +} + diff --git a/indra/newview/llchatmsgbox.h b/indra/newview/llchatmsgbox.h new file mode 100644 index 0000000000..c0e1964afa --- /dev/null +++ b/indra/newview/llchatmsgbox.h @@ -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 + diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index bd946a79d6..38a7494b5b 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -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; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp new file mode 100644 index 0000000000..411aa72690 --- /dev/null +++ b/indra/newview/llnearbychat.cpp @@ -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); +} + diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h new file mode 100644 index 0000000000..61ff8890ea --- /dev/null +++ b/indra/newview/llnearbychat.h @@ -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 + + diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp new file mode 100644 index 0000000000..ab66421d35 --- /dev/null +++ b/indra/newview/llnearbychathandler.cpp @@ -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) +{ + +} + +} + diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h new file mode 100644 index 0000000000..89ac08b9f0 --- /dev/null +++ b/indra/newview/llnearbychathandler.h @@ -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 */ diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp new file mode 100644 index 0000000000..757a0e5999 --- /dev/null +++ b/indra/newview/llnotificationalerthandler.cpp @@ -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) +{ +} + +//-------------------------------------------------------------------------- + + diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp new file mode 100644 index 0000000000..cde7efe901 --- /dev/null +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -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) +{ +} + +//-------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------- + diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h new file mode 100644 index 0000000000..7f53809c07 --- /dev/null +++ b/indra/newview/llnotificationhandler.h @@ -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 + diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp new file mode 100644 index 0000000000..3eda0d0d14 --- /dev/null +++ b/indra/newview/llnotificationmanager.cpp @@ -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; +	} +} + +//-------------------------------------------------------------------------- + + + + diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h new file mode 100644 index 0000000000..838a00ee11 --- /dev/null +++ b/indra/newview/llnotificationmanager.h @@ -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 + diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp new file mode 100644 index 0000000000..78091ef05b --- /dev/null +++ b/indra/newview/llscreenchannel.cpp @@ -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(); +} + +//-------------------------------------------------------------------------- + + + + diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h new file mode 100644 index 0000000000..5a9946f772 --- /dev/null +++ b/indra/newview/llscreenchannel.h @@ -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 diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index d8be1386c3..37262b736e 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -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	() diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index acc7c83cd7..7487c71bfc 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -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;  }; diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp new file mode 100644 index 0000000000..954418f7fb --- /dev/null +++ b/indra/newview/lltoast.cpp @@ -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); +	} +} + +//-------------------------------------------------------------------------- + + + + diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h new file mode 100644 index 0000000000..2e2ac5b36c --- /dev/null +++ b/indra/newview/lltoast.h @@ -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 diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp new file mode 100644 index 0000000000..afaa01a77a --- /dev/null +++ b/indra/newview/lltoastalertpanel.cpp @@ -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); +} diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h new file mode 100644 index 0000000000..f714630c77 --- /dev/null +++ b/indra/newview/lltoastalertpanel.h @@ -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 diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp new file mode 100644 index 0000000000..83c25ddc77 --- /dev/null +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -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); +} diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h new file mode 100644 index 0000000000..f00f840e94 --- /dev/null +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -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 diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp new file mode 100644 index 0000000000..c43618d330 --- /dev/null +++ b/indra/newview/lltoastnotifypanel.cpp @@ -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; +} diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h new file mode 100644 index 0000000000..df58c06f25 --- /dev/null +++ b/indra/newview/lltoastnotifypanel.h @@ -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_ */ diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp new file mode 100644 index 0000000000..79a7d45bbf --- /dev/null +++ b/indra/newview/lltoastpanel.cpp @@ -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() { +} diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h new file mode 100644 index 0000000000..82e2a74672 --- /dev/null +++ b/indra/newview/lltoastpanel.h @@ -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 */ diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 403b710459..5c38be86d5 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -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>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index bfc258506f..abaac42874 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -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" diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index e46748edf0..8f1b105ba6 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -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);  		}  	}  } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1468b376b0..24479485ef 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -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(); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index a1120b303b..35173c8922 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -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); diff --git a/indra/newview/macview_Prefix.h b/indra/newview/macview_Prefix.h index 33cf7d8cb0..a273320b3d 100644 --- a/indra/newview/macview_Prefix.h +++ b/indra/newview/macview_Prefix.h @@ -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" diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index afac4a4051..3052571b1e 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -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> diff --git a/indra/newview/skins/default/xui/en/menu_nearby_chat.xml b/indra/newview/skins/default/xui/en/menu_nearby_chat.xml index 5eb4b10af9..02a2f83d14 100644 --- a/indra/newview/skins/default/xui/en/menu_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/menu_nearby_chat.xml @@ -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" /> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 7006203dcd..7ac068df4b 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -301,9 +301,11 @@                 height="20"                 left="22"                 top="23"/> +<!--   			  <chiclet_notification.commit_callback  				 function="Notification.Show"  				 parameter="ClickUnimplemented" /> + -->               				   			</chiclet_notification>          </layout_panel>          <icon diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml new file mode 100644 index 0000000000..b628ee3aa1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml @@ -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> + diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml new file mode 100644 index 0000000000..1757197372 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml @@ -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> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 366c3ecf6c..1743e016ee 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -81,7 +81,7 @@       top_delta="0"       width="60" />      <button -     enabled="false" +     enabled="true"       follows="bottom|right"       font="SansSerifSmallBold"       height="25" diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 01052f4bbe..76a92a1087 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -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>   -->  diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml new file mode 100644 index 0000000000..8952ea1307 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -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>  | 
