summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorpavelk_productengine <none@none>2015-01-09 20:17:39 +0200
committerpavelk_productengine <none@none>2015-01-09 20:17:39 +0200
commite5d6a14f05f857ecbbbd9b464db3ece82d1d099f (patch)
tree65954afb82a7b2e1df300ea714afd88460ac3660 /indra/newview
parent4ec9bce3c2a715f53938e4568c95b7a2bdfc9e16 (diff)
MAINT-4734 (Separate transaction notices from group notice/invites) - initial version
Works: 1) All new notices shown on "Invites" tab of new floater "NOTIFICATIONS TABBED" in condensed view To be done: 1) Show other types of notices, like transactions and system 2) Separate notices between tabs "Invites", "System", "Transactions" 3) Design full notice view (in addition to condensed view)
Diffstat (limited to 'indra/newview')
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rwxr-xr-xindra/newview/llchannelmanager.cpp4
-rwxr-xr-xindra/newview/llchiclet.cpp10
-rwxr-xr-xindra/newview/llchicletbar.cpp4
-rw-r--r--indra/newview/llfloaternotificationstabbed.cpp377
-rw-r--r--indra/newview/llfloaternotificationstabbed.h143
-rwxr-xr-xindra/newview/llsyswellitem.cpp80
-rwxr-xr-xindra/newview/llsyswellitem.h54
-rwxr-xr-xindra/newview/llviewerfloaterreg.cpp6
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Attachment_Large.pngbin0 -> 4182 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Attachment_Small.pngbin0 -> 3774 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Group_Large.pngbin0 -> 12280 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Group_Small.pngbin0 -> 4473 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Notification_Condense.pngbin0 -> 262 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Notification_Expand.pngbin0 -> 239 bytes
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml134
-rwxr-xr-xindra/newview/skins/default/xui/en/language_settings.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_login.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification_tabbed_item.xml53
20 files changed, 870 insertions, 8 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e8f4144e70..b17811d644 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -262,6 +262,7 @@ set(viewer_SOURCE_FILES
llfloatermodeluploadbase.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
+ llfloaternotificationstabbed.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloateroutbox.cpp
@@ -870,6 +871,7 @@ set(viewer_HEADER_FILES
llfloatermodeluploadbase.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
+ llfloaternotificationstabbed.h
llfloaterobjectweights.h
llfloateropenobject.h
llfloateroutbox.h
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index b0537a83f1..49a71b0018 100755
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -35,6 +35,7 @@
#include "llviewerwindow.h"
#include "llrootview.h"
#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
#include "llfloaterreg.h"
#include <algorithm>
@@ -131,7 +132,8 @@ void LLChannelManager::onLoginCompleted()
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
- mStartUpChannel->setMouseDownCallback(boost::bind(&LLNotificationWellWindow::onStartUpToastClick, LLNotificationWellWindow::getInstance(), _2, _3, _4));
+ //mStartUpChannel->setMouseDownCallback(boost::bind(&LLNotificationWellWindow::onStartUpToastClick, LLNotificationWellWindow::getInstance(), _2, _3, _4));
+ mStartUpChannel->setMouseDownCallback(boost::bind(&LLFloaterNotificationsTabbed::onStartUpToastClick, LLFloaterNotificationsTabbed::getInstance(), _2, _3, _4));
mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index c0823182c0..6435c934b9 100755
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -35,6 +35,7 @@
#include "llscriptfloater.h"
#include "llsingleton.h"
#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
@@ -165,7 +166,8 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p)
mNotificationChannel.reset(new ChicletNotificationChannel(this));
// ensure that notification well window exists, to synchronously
// handle toast add/delete events.
- LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);
+ //LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);
+ LLFloaterNotificationsTabbed::getInstance()->setSysWellChiclet(this);
}
void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
@@ -173,7 +175,8 @@ void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
std::string action = user_data.asString();
if("close all" == action)
{
- LLNotificationWellWindow::getInstance()->closeAll();
+ //LLNotificationWellWindow::getInstance()->closeAll();
+ LLFloaterNotificationsTabbed::getInstance()->closeAll();
LLIMWellWindow::getInstance()->closeAll();
}
}
@@ -224,7 +227,8 @@ bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNo
bool displayNotification;
if ( (notification->getName() == "ScriptDialog") // special case for scripts
// if there is no toast window for the notification, filter it
- || (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
+ //|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
+ || (!LLFloaterNotificationsTabbed::getInstance()->findItemByID(notification->getID()))
)
{
displayNotification = false;
diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp
index 28e367fbe1..45510d0824 100755
--- a/indra/newview/llchicletbar.cpp
+++ b/indra/newview/llchicletbar.cpp
@@ -31,6 +31,7 @@
#include "lllayoutstack.h"
#include "llpaneltopinfobar.h"
#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
namespace
{
@@ -59,7 +60,8 @@ BOOL LLChicletBar::postBuild()
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
- showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty());
+ //showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty());
+ showWellButton("notification_well", !LLFloaterNotificationsTabbed::getInstance()->isWindowEmpty());
LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this));
LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this));
diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp
new file mode 100644
index 0000000000..09f0a0ed5e
--- /dev/null
+++ b/indra/newview/llfloaternotificationstabbed.cpp
@@ -0,0 +1,377 @@
+/**
+ * @file llfloaternotificationstabbed.cpp
+ * @brief // TODO
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+#include "llfloaternotificationstabbed.h"
+
+#include "llchiclet.h"
+#include "llchicletbar.h"
+#include "llflatlistview.h"
+#include "llfloaterreg.h"
+#include "llnotificationmanager.h"
+#include "llnotificationsutil.h"
+#include "llscriptfloater.h"
+#include "llspeakers.h"
+#include "lltoastpanel.h"
+#include "lltoastnotifypanel.h"
+
+//---------------------------------------------------------------------------------
+LLFloaterNotificationsTabbed::LLFloaterNotificationsTabbed(const LLSD& key) : LLTransientDockableFloater(NULL, true, key),
+ mChannel(NULL),
+ mMessageList(NULL),
+ mSysWellChiclet(NULL),
+ NOTIFICATION_TABBED_ANCHOR_NAME("notification_well_panel"),
+ IM_WELL_ANCHOR_NAME("im_well_panel"),
+ mIsReshapedByUser(false)
+
+{
+ setOverlapsScreenChannel(true);
+ mNotificationUpdates.reset(new NotificationTabbedChannel(this));
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLFloaterNotificationsTabbed::postBuild()
+{
+ mMessageList = getChild<LLFlatListView>("notification_list");
+
+ // get a corresponding channel
+ initChannel();
+ BOOL rv = LLTransientDockableFloater::postBuild();
+
+ //LLNotificationWellWindow::postBuild()
+ //--------------------------
+ setTitle(getString("title_notification_tabbed_window"));
+ return rv;
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setMinimized(BOOL minimize)
+{
+ LLTransientDockableFloater::setMinimized(minimize);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::handleReshape(const LLRect& rect, bool by_user)
+{
+ mIsReshapedByUser |= by_user; // mark floater that it is reshaped by user
+ LLTransientDockableFloater::handleReshape(rect, by_user);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+ // just set floater visible. Screen channels will be cleared.
+ setVisible(TRUE);
+}
+
+void LLFloaterNotificationsTabbed::setSysWellChiclet(LLSysWellChiclet* chiclet)
+{
+ mSysWellChiclet = chiclet;
+ if(NULL != mSysWellChiclet)
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ }
+}
+
+//---------------------------------------------------------------------------------
+LLFloaterNotificationsTabbed::~LLFloaterNotificationsTabbed()
+{
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::removeItemByID(const LLUUID& id)
+{
+ if(mMessageList->removeItemByValue(id))
+ {
+ if (NULL != mSysWellChiclet)
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ }
+ reshapeWindow();
+ }
+ else
+ {
+ LL_WARNS() << "Unable to remove notification from the list, ID: " << id
+ << LL_ENDL;
+ }
+
+ // hide chiclet window if there are no items left
+ if(isWindowEmpty())
+ {
+ setVisible(FALSE);
+ }
+}
+
+//---------------------------------------------------------------------------------
+LLPanel * LLFloaterNotificationsTabbed::findItemByID(const LLUUID& id)
+{
+ return mMessageList->getItemByValue(id);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::initChannel()
+{
+ LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
+ LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
+ mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel);
+ if(NULL == mChannel)
+ {
+ LL_WARNS() << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << LL_ENDL;
+ }
+
+ //LLSysWellWindow::initChannel();
+ //---------------------------------------------------------------------------------
+ if(mChannel)
+ {
+ mChannel->addOnStoreToastCallback(boost::bind(&LLFloaterNotificationsTabbed::onStoreToast, this, _1, _2));
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setVisible(BOOL visible)
+{
+ //LLNotificationWellWindow::setVisible
+ //--------------------------
+ if (visible)
+ {
+ // when Notification channel is cleared, storable toasts will be added into the list.
+ clearScreenChannels();
+ }
+ //--------------------------
+ if (visible)
+ {
+ if (NULL == getDockControl() && getDockTongue().notNull())
+ {
+ setDockControl(new LLDockControl(
+ LLChicletBar::getInstance()->getChild<LLView>(getAnchorViewName()), this,
+ getDockTongue(), LLDockControl::BOTTOM));
+ }
+ }
+
+ // do not show empty window
+ if (NULL == mMessageList || isWindowEmpty()) visible = FALSE;
+
+ LLTransientDockableFloater::setVisible(visible);
+
+ // update notification channel state
+ initChannel(); // make sure the channel still exists
+ if(mChannel)
+ {
+ mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setDocked(bool docked, bool pop_on_undock)
+{
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
+
+ // update notification channel state
+ if(mChannel)
+ {
+ mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::reshapeWindow()
+{
+ // save difference between floater height and the list height to take it into account while calculating new window height
+ // it includes height from floater top to list top and from floater bottom and list bottom
+ static S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight();
+
+ if (!mIsReshapedByUser) // Don't reshape Well window, if it ever was reshaped by user. See EXT-5715.
+ {
+ S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth();
+
+ LLRect curRect = getRect();
+
+ S32 new_window_height = notif_list_height + parent_list_delta_height;
+
+ if (new_window_height > MAX_WINDOW_HEIGHT)
+ {
+ new_window_height = MAX_WINDOW_HEIGHT;
+ }
+ S32 newWidth = curRect.getWidth() < MIN_WINDOW_WIDTH ? MIN_WINDOW_WIDTH : curRect.getWidth();
+
+ curRect.setLeftTopAndSize(curRect.mLeft, curRect.mTop, newWidth, new_window_height);
+ reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
+ setRect(curRect);
+ }
+
+ // update notification channel state
+ // update on a window reshape is important only when a window is visible and docked
+ if(mChannel && getVisible() && isDocked())
+ {
+ mChannel->updateShowToastsState();
+ }
+}
+
+//---------------------------------------------------------------------------------
+bool LLFloaterNotificationsTabbed::isWindowEmpty()
+{
+ return mMessageList->size() == 0;
+}
+
+LLFloaterNotificationsTabbed::NotificationTabbedChannel::NotificationTabbedChannel(LLFloaterNotificationsTabbed* notifications_tabbed_window)
+ : LLNotificationChannel(LLNotificationChannel::Params().name(notifications_tabbed_window->getPathname())),
+ mNotificationsTabbedWindow(notifications_tabbed_window)
+{
+ connectToChannel("Notifications");
+ connectToChannel("Group Notifications");
+ connectToChannel("Offer");
+}
+
+/*
+LLFloaterNotificationsTabbed::LLNotificationWellWindow(const LLSD& key)
+ : LLSysWellWindow(key)
+{
+ mNotificationUpdates.reset(new NotificationTabbedChannel(this));
+}
+*/
+
+// static
+LLFloaterNotificationsTabbed* LLFloaterNotificationsTabbed::getInstance(const LLSD& key /*= LLSD()*/)
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterNotificationsTabbed>("notification_well_window", key);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::addItem(LLNotificationTabbedItem::Params p)
+{
+ LLSD value = p.notification_id;
+ // do not add clones
+ if( mMessageList->getItemByValue(value))
+ return;
+
+ LLNotificationTabbedItem* new_item = new LLNotificationTabbedItem(p);
+ if (mMessageList->addItem(new_item, value, ADD_TOP))
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ reshapeWindow();
+ new_item->setOnItemCloseCallback(boost::bind(&LLFloaterNotificationsTabbed::onItemClose, this, _1));
+ new_item->setOnItemClickCallback(boost::bind(&LLFloaterNotificationsTabbed::onItemClick, this, _1));
+ }
+ else
+ {
+ LL_WARNS() << "Unable to add Notification into the list, notification ID: " << p.notification_id
+ << ", title: " << p.title
+ << LL_ENDL;
+
+ new_item->die();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::closeAll()
+{
+ // Need to clear notification channel, to add storable toasts into the list.
+ clearScreenChannels();
+ std::vector<LLPanel*> items;
+ mMessageList->getItems(items);
+ for (std::vector<LLPanel*>::iterator
+ iter = items.begin(),
+ iter_end = items.end();
+ iter != iter_end; ++iter)
+ {
+ LLNotificationTabbedItem* sys_well_item = dynamic_cast<LLNotificationTabbedItem*>(*iter);
+ if (sys_well_item)
+ onItemClose(sys_well_item);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE METHODS
+//void LLFloaterNotificationsTabbed::initChannel()
+//{
+// LLFloaterNotificationsTabbed::initChannel();
+// if(mChannel)
+// {
+// mChannel->addOnStoreToastCallback(boost::bind(&LLFloaterNotificationsTabbed::onStoreToast, this, _1, _2));
+// }
+//}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::clearScreenChannels()
+{
+ // 1 - remove StartUp toast and channel if present
+ if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown())
+ {
+ LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose();
+ }
+
+ // 2 - remove toasts in Notification channel
+ if(mChannel)
+ {
+ mChannel->removeAndStoreAllStorableToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onStoreToast(LLPanel* info_panel, LLUUID id)
+{
+ LLNotificationTabbedItem::Params p;
+ p.notification_id = id;
+ p.title = static_cast<LLToastPanel*>(info_panel)->getTitle();
+ LLNotificationsUI::LLToast* toast = mChannel->getToastByNotificationID(id);
+ LLSD payload = toast->getNotification()->getPayload();
+ LLDate time_stamp = toast->getNotification()->getDate();
+ p.group_id = payload["group_id"];
+ p.sender = payload["name"];
+ p.time_stamp = time_stamp;
+ addItem(p);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onItemClick(LLNotificationTabbedItem* item)
+{
+ LLUUID id = item->getID();
+ LLFloaterReg::showInstance("inspect_toast", id);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onItemClose(LLNotificationTabbedItem* item)
+{
+ LLUUID id = item->getID();
+
+ if(mChannel)
+ {
+ // removeItemByID() is invoked from killToastByNotificationID() and item will removed;
+ mChannel->killToastByNotificationID(id);
+ }
+ else
+ {
+ // removeItemByID() should be called one time for each item to remove it from notification well
+ removeItemByID(id);
+ }
+
+}
+
+void LLFloaterNotificationsTabbed::onAdd( LLNotificationPtr notify )
+{
+ removeItemByID(notify->getID());
+}
diff --git a/indra/newview/llfloaternotificationstabbed.h b/indra/newview/llfloaternotificationstabbed.h
new file mode 100644
index 0000000000..1fd60826cb
--- /dev/null
+++ b/indra/newview/llfloaternotificationstabbed.h
@@ -0,0 +1,143 @@
+/**
+ * @file llfloaternotificationstabbed.h
+ * @brief // TODO
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FLOATERNOTIFICATIONSTABBED_H
+#define LL_FLOATERNOTIFICATIONSTABBED_H
+
+#include "llimview.h"
+#include "llnotifications.h"
+#include "llscreenchannel.h"
+#include "llsyswellitem.h"
+#include "lltransientdockablefloater.h"
+
+class LLAvatarName;
+class LLChiclet;
+class LLFlatListView;
+class LLIMChiclet;
+class LLScriptChiclet;
+class LLSysWellChiclet;
+
+class LLFloaterNotificationsTabbed : public LLTransientDockableFloater
+{
+public:
+ LOG_CLASS(LLFloaterNotificationsTabbed);
+
+ LLFloaterNotificationsTabbed(const LLSD& key);
+ virtual ~LLFloaterNotificationsTabbed();
+ BOOL postBuild();
+
+ // other interface functions
+ // check is window empty
+ bool isWindowEmpty();
+
+ // Operating with items
+ void removeItemByID(const LLUUID& id);
+ LLPanel * findItemByID(const LLUUID& id);
+
+ // Operating with outfit
+ virtual void setVisible(BOOL visible);
+ void adjustWindowPosition();//not used - ?
+
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+ // override LLFloater's minimization according to EXT-1216
+ /*virtual*/ void setMinimized(BOOL minimize);
+ /*virtual*/ void handleReshape(const LLRect& rect, bool by_user);
+
+ void onStartUpToastClick(S32 x, S32 y, MASK mask);
+
+ void setSysWellChiclet(LLSysWellChiclet* chiclet);
+
+ // size constants for the window and for its elements
+ static const S32 MAX_WINDOW_HEIGHT = 200;
+ static const S32 MIN_WINDOW_WIDTH = 318;
+
+protected:
+ // init Window's channel
+ virtual void initChannel();
+
+ const std::string NOTIFICATION_TABBED_ANCHOR_NAME;
+ const std::string IM_WELL_ANCHOR_NAME;
+ //virtual const std::string& getAnchorViewName() = 0;
+
+ void reshapeWindow();
+
+ // pointer to a corresponding channel's instance
+ LLNotificationsUI::LLScreenChannel* mChannel;
+ LLFlatListView* mMessageList;
+
+ /**
+ * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147
+ */
+ LLSysWellChiclet* mSysWellChiclet;
+
+ bool mIsReshapedByUser;
+
+public:
+ static LLFloaterNotificationsTabbed* getInstance(const LLSD& key = LLSD());
+
+ /*virtual*/ //BOOL postBuild();
+ /*virtual*/ //void setVisible(BOOL visible);
+ /*virtual*/ void onAdd(LLNotificationPtr notify);
+ // Operating with items
+ void addItem(LLNotificationTabbedItem::Params p);
+
+ // Closes all notifications and removes them from the Notification Well
+ void closeAll();
+
+protected:
+ struct NotificationTabbedChannel : public LLNotificationChannel
+ {
+ NotificationTabbedChannel(LLFloaterNotificationsTabbed*);
+ void onDelete(LLNotificationPtr notify)
+ {
+ mNotificationsTabbedWindow->removeItemByID(notify->getID());
+ }
+
+ LLFloaterNotificationsTabbed* mNotificationsTabbedWindow;
+ };
+
+ LLNotificationChannelPtr mNotificationUpdates;
+ virtual const std::string& getAnchorViewName() { return NOTIFICATION_TABBED_ANCHOR_NAME; }
+
+private:
+ // init Window's channel
+ // void initChannel();
+ void clearScreenChannels();
+
+ void onStoreToast(LLPanel* info_panel, LLUUID id);
+
+ // Handlers
+ void onItemClick(LLNotificationTabbedItem* item);
+ void onItemClose(LLNotificationTabbedItem* item);
+
+ // ID of a toast loaded by user (by clicking notification well item)
+ LLUUID mLoadedToastId;
+};
+
+#endif // LL_FLOATERNOTIFICATIONSTABBED_H
+
+
+
diff --git a/indra/newview/llsyswellitem.cpp b/indra/newview/llsyswellitem.cpp
index 057d80457c..bc8333d5fc 100755
--- a/indra/newview/llsyswellitem.cpp
+++ b/indra/newview/llsyswellitem.cpp
@@ -31,6 +31,7 @@
#include "llwindow.h"
#include "v4color.h"
+#include "lltrans.h"
#include "lluicolortable.h"
//---------------------------------------------------------------------------------
@@ -90,4 +91,83 @@ void LLSysWellItem::onMouseLeave(S32 x, S32 y, MASK mask)
//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+LLNotificationTabbedItem::LLNotificationTabbedItem(const Params& p) : LLPanel(p),
+ mTitle(NULL),
+ mSender(NULL),
+ mCloseBtn(NULL)
+{
+ buildFromFile( "panel_notification_tabbed_item.xml");
+
+ mTitle = getChild<LLTextBox>("GroupName_NoticeTitle");
+ mSender = getChild<LLTextBox>("Sender_Resident");
+ mTimeBox = getChild<LLTextBox>("Time_Box");
+ mGroupIcon = getChild<LLIconCtrl>("group_icon_small");
+ mCloseBtn = getChild<LLButton>("close_btn");
+
+ mTitle->setValue(p.title);
+ mSender->setValue("Sender: " + p.sender);
+ mTimeBox->setValue(buildNotificationDate(p.time_stamp));
+ mGroupIcon->setValue(p.group_id);
+
+ mCloseBtn->setClickedCallback(boost::bind(&LLNotificationTabbedItem::onClickCloseBtn,this));
+
+ mID = p.notification_id;
+}
+
+//---------------------------------------------------------------------------------
+LLNotificationTabbedItem::~LLNotificationTabbedItem()
+{
+}
+//---------------------------------------------------------------------------------
+//static
+std::string LLNotificationTabbedItem::buildNotificationDate(const LLDate& time_stamp)
+{
+ std::string timeStr = "[" + LLTrans::getString("LTimeMthNum") + "]/["
+ +LLTrans::getString("LTimeDay")+"]/["
+ +LLTrans::getString("LTimeYear")+"] ["
+ +LLTrans::getString("LTimeHour")+"]:["
+ +LLTrans::getString("LTimeMin")+"]";
+
+ LLSD substitution;
+ substitution["datetime"] = time_stamp;
+ LLStringUtil::format(timeStr, substitution);
+ return timeStr;
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationTabbedItem::setTitle( std::string title )
+{
+ mTitle->setValue(title);
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationTabbedItem::onClickCloseBtn()
+{
+ mOnItemClose(this);
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLNotificationTabbedItem::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL res = LLPanel::handleMouseDown(x, y, mask);
+ if(!mCloseBtn->getRect().pointInRect(x, y))
+ //if(!mCloseBtn->getRect().pointInRect(x, y))
+ //if(!mCloseBtn->getLocalRect().pointInRect(x, y))
+ mOnItemClick(this);
+
+ return res;
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationTabbedItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ //setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemSelected" ));
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationTabbedItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ //setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" ));
+}
diff --git a/indra/newview/llsyswellitem.h b/indra/newview/llsyswellitem.h
index d961708a01..4379b8dc22 100755
--- a/indra/newview/llsyswellitem.h
+++ b/indra/newview/llsyswellitem.h
@@ -32,6 +32,8 @@
#include "llbutton.h"
#include "lliconctrl.h"
+#include "llgroupmgr.h"
+
#include <string>
class LLSysWellItem : public LLPanel
@@ -76,6 +78,58 @@ private:
LLUUID mID;
};
+class LLNotificationTabbedItem : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ LLUUID notification_id;
+ LLUUID group_id;
+ std::string title;
+ std::string sender;
+ LLDate time_stamp;
+ Params() {};
+ };
+
+
+ LLNotificationTabbedItem(const Params& p);
+ virtual ~LLNotificationTabbedItem();
+
+ // title
+ void setTitle( std::string title );
+ void setGroupID(const LLUUID& group_id);
+ void setGroupIconID(const LLUUID& group_icon_id);
+ void setGroupName(const std::string& group_name);
+
+ // get item's ID
+ LLUUID getID() { return mID; }
+
+ // handlers
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ //callbacks
+ typedef boost::function<void (LLNotificationTabbedItem* item)> item_callback_t;
+ typedef boost::signals2::signal<void (LLNotificationTabbedItem* item)> item_signal_t;
+ item_signal_t mOnItemClose;
+ item_signal_t mOnItemClick;
+ boost::signals2::connection setOnItemCloseCallback(item_callback_t cb) { return mOnItemClose.connect(cb); }
+ boost::signals2::connection setOnItemClickCallback(item_callback_t cb) { return mOnItemClick.connect(cb); }
+
+private:
+ static std::string buildNotificationDate(const LLDate&);
+ void onClickCloseBtn();
+
+ LLTextBox* mTitle;
+ LLTextBox* mSender;
+ LLTextBox* mTimeBox;
+ LLIconCtrl* mGroupIcon;
+ LLButton* mCloseBtn;
+ LLUUID mID;
+ LLUUID mGroupID;
+};
+
#endif // LL_LLSYSWELLITEM_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index e19fe9ca75..d20b8e342a 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -85,6 +85,7 @@
#include "llfloatermodelpreview.h"
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
+#include "llfloaternotificationstabbed.h"
#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
#include "llfloateroutbox.h"
@@ -255,7 +256,10 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
- LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);
+
+ LLFloaterReg::add("notification_well_window", "floater_notifications_tabbed.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationsTabbed>);
+ //LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);
+ //LLFloaterReg::add("notifications_tabbed", "floater_notifications_tabbed.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationsTabbed>);
LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png
new file mode 100644
index 0000000000..0732a33d93
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png
new file mode 100644
index 0000000000..8124554902
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Group_Large.png b/indra/newview/skins/default/textures/icons/Icon_Group_Large.png
new file mode 100644
index 0000000000..6dc0cbda0b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Group_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Group_Small.png b/indra/newview/skins/default/textures/icons/Icon_Group_Small.png
new file mode 100644
index 0000000000..ef2b521a1f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Group_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png b/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png
new file mode 100644
index 0000000000..4d245eb57a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png b/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png
new file mode 100644
index 0000000000..186822da43
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 1f10d966d5..0744962064 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -795,4 +795,11 @@ with the same filename but different name
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+ <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="Icon_Group_Small" file_name="icons/Icon_Group_Small.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="Icon_Group_Large" file_name="icons/Icon_Group_Large.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+
</textures>
diff --git a/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml
new file mode 100644
index 0000000000..b627707056
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+ legacy_header_height="18"
+ bevel_style="in"
+ layout="topleft"
+ name="floater_notifications_tabbed"
+ help_topic="notification_chiclet"
+ save_rect="true"
+ title="NOTIFICATIONS"
+ width="350"
+ min_width="320"
+ height="550"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_dock="true"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+>
+ <string
+ name="title_notification_tabbed_window">
+ NOTIFICATIONS TABBED
+ </string>
+ <layout_stack width="336" height="550" enabled="true" orientation="vertical" name="TabButtonsStack" follows="left|top|right|bottom">
+ <layout_panel width="336" height="550" enabled="true" name="TabButtonsLayoutPanel">
+ <tab_container
+ follows="left|top|right|bottom"
+ halign="center"
+ layout="topleft"
+ tab_position="top"
+ left="7"
+ top="24"
+ width="336"
+ height="491"
+ mouse_opaque="true"
+ name="NotificationsTab">
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="System (2)"
+ layout="topleft"
+ name="SystemNotificationsTab">
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="Transactions (15)"
+ layout="topleft"
+ name="TransactionNotificationsTab">
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="Invites (2)"
+ layout="topleft"
+ name="InviteNotificationsTab">
+ <flat_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="notification_list"
+ left="0"
+ top="5"
+ height="0"
+ width="330"/>
+ </panel>
+ </tab_container>
+
+ <layout_stack width="336" height="26" enabled="true" orientation="horizontal" follows="left|right" name="ButtonsStack">
+ <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="CondenseAllButtonPanel">
+ <button width="93" height="21" left="2" label="Condense All" name="CondenseAllButton">
+ </button>
+ </layout_panel>
+ <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="GapLayoutPanel">
+ <panel width="90" height="21" left="2" label="Condense All" border="false" name="GapPanel">
+ </panel>
+ </layout_panel>
+ <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="DeleteAllButtonPanel">
+ <button width="93" height="21" left="2" label="Delete All" name="DeleteAllButton">
+ </button>
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ </layout_stack>
+ </floater>
+
+<!--
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+ legacy_header_height="18"
+ bevel_style="in"
+ layout="topleft"
+ name="notifications_tabbed_window"
+ help_topic="notification_chiclet"
+ save_rect="true"
+ title="NOTIFICATIONS"
+ width="320"
+ min_width="320"
+ height="23"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_dock="true"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+>
+ <string
+ name="title_im_well_window">
+ CONVERSATIONS
+ </string>
+ <string
+ name="title_notification_well_window">
+ NOTIFICATIONS1
+ </string>
+
+ <flat_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="notification_list"
+ left="1"
+ top="20"
+ height="0"
+ width="318"/>
+</floater>
+-->
+
diff --git a/indra/newview/skins/default/xui/en/language_settings.xml b/indra/newview/skins/default/xui/en/language_settings.xml
index 51779e4bfd..3ad0f04469 100755
--- a/indra/newview/skins/default/xui/en/language_settings.xml
+++ b/indra/newview/skins/default/xui/en/language_settings.xml
@@ -50,7 +50,7 @@
<string name="LTimeSec">second,datetime,local</string>
<string name="LTimeHour">hour,datetime,local</string>
<string name="LTimeMin">min,datetime,local</string>
- <string name="LTimeYear">year,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
<string name="UTCTimeWeek">weekday,datetime,utc</string>
<string name="UTCTimeDay">day,datetime,utc</string>
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index e91eea04d1..0d9612990d 100755
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -303,7 +303,7 @@
<menu_item_call
label="Show Notifications Console"
name="Show Notifications Console"
- visible="false"
+ visible="true"
shortcut="control|shift|5">
<on_click
function="Floater.Toggle"
diff --git a/indra/newview/skins/default/xui/en/panel_notification_tabbed_item.xml b/indra/newview/skins/default/xui/en/panel_notification_tabbed_item.xml
new file mode 100644
index 0000000000..bc4f90858b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notification_tabbed_item.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel
+ translate="false"
+ name="sys_well_item"
+ title="sys_well_item"
+ visible="true"
+ top="0"
+ left="0"
+ width="331"
+ height="50"
+ can_resize="false"
+ layout="topleft"
+ follows="left|right"
+ background_opaque="false"
+ background_visible="true"
+ bg_alpha_color="SysWellItemUnselected" >
+
+ <panel border="true" top="0" left="3" width="327" height="44" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="GroupNameNoticeTitlePanel">
+ <layout_stack top="0" left="0" width="325" height="50" orientation="horizontal" follows="left|top|right|bottom" name="HorizontalStack">
+ <layout_panel width="30" height="22" orientation="horizontal" follows="left|top|right|bottom" name="LayoutPanel">
+ <group_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="group_icon_small" tool_tip="Group" default_icon_name="Generic_Group"/>
+ </layout_panel>
+ <layout_panel width="260" height="50" orientation="horizontal" follows="left|top|right|bottom" name="LayoutPanel">
+ <panel border="false" top="0" width="260" height="38" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="MainInfoBlockPanel">
+ <panel border="false" top="0" left="0" width="260" height="19" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="GroupNameNoticeTitlePanel">
+ <text allow_scroll="false" font="SansSerifLarge" top="2" left="0" width="267" height="17" layout="topleft" follows="right|left" text_color="White"
+ use_ellipses="true" word_wrap="true" mouse_opaque="false" name="GroupName_NoticeTitle" >
+ Group Name:Notice Title
+ </text>
+ <icon top="0" right="-1" width="21" height="21" image_name="Icon_Attachment_Small" follows="right" mouse_opaque="true" name="icon_attachment_small" tool_tip="Attachment"/>
+ </panel>
+ <panel border="false" top="23" left="0" width="260" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="SenderAndTimePanel" height="15">
+ <text allow_scroll="false" font="SansSerifSmall" top="0" left="0" width="250" height="13" layout="topleft" follows="right|left"
+ use_ellipses="true" word_wrap="true" mouse_opaque="false" name="Sender_Resident" >
+ Sender.Resident
+ </text>
+ <text allow_scroll="false" font="SansSerifSmall" top="0" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
+ name="Time_Box" right="-5" value="2014/12/24 23:30" />
+ </panel>
+ </panel>
+ </layout_panel>
+ <layout_panel name="LayoutPanel3" width="18" height="39" orientation="horizontal" follows="left|top|right|bottom">
+ <panel name="CloseExpandButtonsPanel" border="false" top="0" left="0" width="17" height="39" bevel_style="none" follows="left|top|right|bottom" layout="topleft">
+ <button top="0" left="0" width="17" height="17" layout="topleft" follows="top" name="close_btn" mouse_opaque="true"
+ tab_stop="false" image_unselected="Icon_Close_Foreground" image_selected="Icon_Close_Press" />
+ <button top="22" left="0" width="17" height="17" layout="topleft" follows="top" name="expand_btn" mouse_opaque="true"
+ tab_stop="false" image_unselected="Notification_Expand" image_selected="Notification_Expand" />
+ </panel>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>