summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt38
-rw-r--r--indra/newview/llbottomtray.cpp18
-rw-r--r--indra/newview/llbottomtray.h3
-rw-r--r--indra/newview/llchannelmanager.cpp133
-rw-r--r--indra/newview/llchannelmanager.h116
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp525
-rw-r--r--indra/newview/llchatitemscontainerctrl.h152
-rw-r--r--indra/newview/llchatmsgbox.cpp390
-rw-r--r--indra/newview/llchatmsgbox.h163
-rw-r--r--indra/newview/llchiclet.cpp9
-rw-r--r--indra/newview/llnearbychat.cpp362
-rw-r--r--indra/newview/llnearbychat.h98
-rw-r--r--indra/newview/llnearbychathandler.cpp118
-rw-r--r--indra/newview/llnearbychathandler.h60
-rw-r--r--indra/newview/llnotificationalerthandler.cpp116
-rw-r--r--indra/newview/llnotificationgrouphandler.cpp117
-rw-r--r--indra/newview/llnotificationhandler.h178
-rw-r--r--indra/newview/llnotificationmanager.cpp127
-rw-r--r--indra/newview/llnotificationmanager.h79
-rw-r--r--indra/newview/llscreenchannel.cpp357
-rw-r--r--indra/newview/llscreenchannel.h136
-rw-r--r--indra/newview/llsidetray.cpp34
-rw-r--r--indra/newview/llsidetray.h4
-rw-r--r--indra/newview/lltoast.cpp236
-rw-r--r--indra/newview/lltoast.h114
-rw-r--r--indra/newview/lltoastalertpanel.cpp474
-rw-r--r--indra/newview/lltoastalertpanel.h124
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp137
-rw-r--r--indra/newview/lltoastgroupnotifypanel.h82
-rw-r--r--indra/newview/lltoastnotifypanel.cpp435
-rw-r--r--indra/newview/lltoastnotifypanel.h86
-rw-r--r--indra/newview/lltoastpanel.cpp42
-rw-r--r--indra/newview/lltoastpanel.h53
-rw-r--r--indra/newview/llviewerfloaterreg.cpp5
-rw-r--r--indra/newview/llviewermedia.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp19
-rw-r--r--indra/newview/llviewerwindow.cpp46
-rw-r--r--indra/newview/llviewerwindow.h1
-rw-r--r--indra/newview/macview_Prefix.h1
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_nearby_chat.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_item.xml38
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notify.xml31
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml118
-rw-r--r--indra/newview/skins/default/xui/en/panel_toast.xml65
47 files changed, 5322 insertions, 130 deletions
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>