Merge with viewer-chui
commit
fbc414c02b
|
|
@ -71,7 +71,6 @@ set(llui_SOURCE_FILES
|
|||
llmultislider.cpp
|
||||
llmultisliderctrl.cpp
|
||||
llnotifications.cpp
|
||||
llnotificationslistener.cpp
|
||||
llnotificationsutil.cpp
|
||||
llpanel.cpp
|
||||
llprogressbar.cpp
|
||||
|
|
@ -181,7 +180,6 @@ set(llui_HEADER_FILES
|
|||
llmultislider.h
|
||||
llnotificationptr.h
|
||||
llnotifications.h
|
||||
llnotificationslistener.h
|
||||
llnotificationsutil.h
|
||||
llnotificationtemplate.h
|
||||
llnotificationvisibilityrule.h
|
||||
|
|
|
|||
|
|
@ -613,30 +613,6 @@ void LLButton::draw()
|
|||
static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true);
|
||||
F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency();
|
||||
|
||||
bool flash = false;
|
||||
if (mFlashingTimer)
|
||||
{
|
||||
mFlashing = mFlashingTimer->isFlashingInProgress();
|
||||
flash = mFlashing && (!sEnableButtonFlashing || mFlashingTimer->isCurrentlyHighlighted());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mFlashing)
|
||||
{
|
||||
if ( sEnableButtonFlashing)
|
||||
{
|
||||
F32 elapsed = mFrameTimer.getElapsedTimeF32();
|
||||
S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f);
|
||||
// flash on or off?
|
||||
flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f);
|
||||
}
|
||||
else
|
||||
{ // otherwise just highlight button in flash color
|
||||
flash = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool pressed_by_keyboard = FALSE;
|
||||
if (hasFocus())
|
||||
{
|
||||
|
|
@ -660,9 +636,21 @@ void LLButton::draw()
|
|||
bool selected = getToggleState();
|
||||
|
||||
bool use_glow_effect = FALSE;
|
||||
LLColor4 glow_color = LLColor4::white;
|
||||
LLColor4 highlighting_color = LLColor4::white;
|
||||
LLColor4 glow_color;
|
||||
LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA;
|
||||
LLUIImage* imagep = NULL;
|
||||
|
||||
// Cancel sticking of color, if the button is pressed,
|
||||
// or when a flashing of the previously selected button is ended
|
||||
if (mFlashingTimer
|
||||
&& ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed))
|
||||
{
|
||||
mFlashing = false;
|
||||
}
|
||||
|
||||
bool flash = mFlashing && sEnableButtonFlashing;
|
||||
|
||||
if (pressed && mDisplayPressedState)
|
||||
{
|
||||
imagep = selected ? mImagePressedSelected : mImagePressed;
|
||||
|
|
@ -728,15 +716,20 @@ void LLButton::draw()
|
|||
imagep = mImageFlash;
|
||||
}
|
||||
// else use usual flashing via flash_color
|
||||
else
|
||||
else if (mFlashingTimer)
|
||||
{
|
||||
LLColor4 flash_color = mFlashBgColor.get();
|
||||
use_glow_effect = TRUE;
|
||||
glow_type = LLRender::BT_ALPHA; // blend the glow
|
||||
if (mNeedsHighlight) // highlighted AND flashing
|
||||
glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity
|
||||
else
|
||||
|
||||
if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress())
|
||||
{
|
||||
glow_color = flash_color;
|
||||
}
|
||||
else if (mNeedsHighlight)
|
||||
{
|
||||
glow_color = highlighting_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -785,8 +778,7 @@ void LLButton::draw()
|
|||
if (use_glow_effect)
|
||||
{
|
||||
mCurGlowStrength = lerp(mCurGlowStrength,
|
||||
mFlashing ? (flash? 1.0 : 0.0)
|
||||
: mHoverGlowStrength,
|
||||
mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength,
|
||||
LLCriticalDamp::getInterpolant(0.05f));
|
||||
}
|
||||
else
|
||||
|
|
@ -973,23 +965,18 @@ void LLButton::setToggleState(BOOL b)
|
|||
{
|
||||
setControlValue(b); // will fire LLControlVariable callbacks (if any)
|
||||
setValue(b); // may or may not be redundant
|
||||
setFlashing(false); // stop flash state whenever the selected/unselected state if reset
|
||||
// Unselected label assignments
|
||||
autoResize();
|
||||
}
|
||||
}
|
||||
|
||||
void LLButton::setFlashing( bool b )
|
||||
void LLButton::setFlashing(bool b)
|
||||
{
|
||||
if (mFlashingTimer)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
mFlashingTimer->startFlashing();
|
||||
}
|
||||
else
|
||||
{
|
||||
mFlashingTimer->stopFlashing();
|
||||
}
|
||||
mFlashing = b;
|
||||
(b ? mFlashingTimer->startFlashing() : mFlashingTimer->stopFlashing());
|
||||
}
|
||||
else if (b != mFlashing)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1913,14 +1913,15 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu)
|
|||
|
||||
// Successively filter out invalid options
|
||||
|
||||
U32 flags = FIRST_SELECTED_ITEM;
|
||||
U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0);
|
||||
U32 flags = multi_select_flag | FIRST_SELECTED_ITEM;
|
||||
for (selected_items_t::iterator item_itor = mSelectedItems.begin();
|
||||
item_itor != mSelectedItems.end();
|
||||
++item_itor)
|
||||
{
|
||||
LLFolderViewItem* selected_item = (*item_itor);
|
||||
selected_item->buildContextMenu(*menu, flags);
|
||||
flags = 0x0;
|
||||
flags = multi_select_flag;
|
||||
}
|
||||
|
||||
addNoOptions(menu);
|
||||
|
|
|
|||
|
|
@ -400,5 +400,6 @@ public:
|
|||
// Flags for buildContextMenu()
|
||||
const U32 SUPPRESS_OPEN_ITEM = 0x1;
|
||||
const U32 FIRST_SELECTED_ITEM = 0x2;
|
||||
const U32 ITEM_IN_MULTI_SELECTION = 0x4;
|
||||
|
||||
#endif // LL_LLFOLDERVIEW_H
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts
|
|||
bool LLFolderViewItem::sColorSetInitialized = false;
|
||||
LLUIColor LLFolderViewItem::sFgColor;
|
||||
LLUIColor LLFolderViewItem::sHighlightBgColor;
|
||||
LLUIColor LLFolderViewItem::sFlashBgColor;
|
||||
LLUIColor LLFolderViewItem::sFocusOutlineColor;
|
||||
LLUIColor LLFolderViewItem::sMouseOverColor;
|
||||
LLUIColor LLFolderViewItem::sFilterBGColor;
|
||||
|
|
@ -151,6 +152,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
|
|||
{
|
||||
sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
|
||||
sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
|
||||
sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE);
|
||||
sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
|
||||
sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
|
||||
sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
|
||||
|
|
@ -686,26 +688,31 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L
|
|||
return mIsCurSelection;
|
||||
}
|
||||
|
||||
void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor,
|
||||
void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor,
|
||||
const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor)
|
||||
{
|
||||
|
||||
//--------------------------------------------------------------------------------//
|
||||
// Draw highlight for selected items
|
||||
//
|
||||
|
||||
const S32 focus_top = getRect().getHeight();
|
||||
const S32 focus_bottom = getRect().getHeight() - mItemHeight;
|
||||
const bool folder_open = (getRect().getHeight() > mItemHeight + 4);
|
||||
const S32 FOCUS_LEFT = 1;
|
||||
|
||||
// Determine which background color to use for highlighting
|
||||
LLUIColor bgColor = (isFlashing() ? flashColor : selectColor);
|
||||
|
||||
if (isHighlightAllowed()) // always render "current" item (only render other selected items if
|
||||
// mShowSingleSelection is FALSE) or flashing item
|
||||
//--------------------------------------------------------------------------------//
|
||||
// Draw highlight for selected items
|
||||
// Note: Always render "current" item or flashing item, only render other selected
|
||||
// items if mShowSingleSelection is FALSE.
|
||||
//
|
||||
if (isHighlightAllowed())
|
||||
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
LLColor4 bg_color = bgColor;
|
||||
if (!isHighlightActive())
|
||||
|
||||
// Highlight for selected but not current items
|
||||
if (!isHighlightActive() && !isFlashing())
|
||||
{
|
||||
LLColor4 bg_color = bgColor;
|
||||
// do time-based fade of extra objects
|
||||
F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f);
|
||||
if (getRoot() && getRoot()->getShowSingleSelection())
|
||||
|
|
@ -718,25 +725,30 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo
|
|||
// fading in
|
||||
bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]);
|
||||
}
|
||||
gl_rect_2d(FOCUS_LEFT,
|
||||
focus_top,
|
||||
getRect().getWidth() - 2,
|
||||
focus_bottom,
|
||||
bg_color, hasKeyboardFocus);
|
||||
}
|
||||
|
||||
if (isHighlightAllowed() || isHighlightActive())
|
||||
// Highlight for currently selected or flashing item
|
||||
if (isHighlightActive())
|
||||
{
|
||||
// Background
|
||||
gl_rect_2d(FOCUS_LEFT,
|
||||
focus_top,
|
||||
getRect().getWidth() - 2,
|
||||
focus_bottom,
|
||||
bg_color, hasKeyboardFocus);
|
||||
}
|
||||
|
||||
if (isHighlightActive())
|
||||
{
|
||||
bgColor, hasKeyboardFocus);
|
||||
// Outline
|
||||
gl_rect_2d(FOCUS_LEFT,
|
||||
focus_top,
|
||||
getRect().getWidth() - 2,
|
||||
focus_bottom,
|
||||
focusOutlineColor, FALSE);
|
||||
}
|
||||
|
||||
if (folder_open)
|
||||
{
|
||||
gl_rect_2d(FOCUS_LEFT,
|
||||
|
|
@ -810,7 +822,7 @@ void LLFolderViewItem::draw()
|
|||
|
||||
drawOpenFolderArrow(default_params, sFgColor);
|
||||
|
||||
drawHighlight(show_context, filled, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
|
||||
//--------------------------------------------------------------------------------//
|
||||
// Draw open icon
|
||||
|
|
@ -1481,17 +1493,20 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)
|
|||
|
||||
void LLFolderViewFolder::destroyView()
|
||||
{
|
||||
std::for_each(mItems.begin(), mItems.end(), DeletePointer());
|
||||
mItems.clear();
|
||||
while (!mItems.empty())
|
||||
{
|
||||
LLFolderViewItem *itemp = mItems.back();
|
||||
itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems
|
||||
}
|
||||
|
||||
while (!mFolders.empty())
|
||||
{
|
||||
LLFolderViewFolder *folderp = mFolders.back();
|
||||
folderp->destroyView(); // removes entry from mFolders
|
||||
folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders
|
||||
}
|
||||
|
||||
LLFolderViewItem::destroyView();
|
||||
}
|
||||
}
|
||||
|
||||
// extractItem() removes the specified item from the folder, but
|
||||
// doesn't delete it.
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ protected:
|
|||
static LLUIColor sFgColor;
|
||||
static LLUIColor sFgDisabledColor;
|
||||
static LLUIColor sHighlightBgColor;
|
||||
static LLUIColor sFlashBgColor;
|
||||
static LLUIColor sFocusOutlineColor;
|
||||
static LLUIColor sMouseOverColor;
|
||||
static LLUIColor sFilterBGColor;
|
||||
|
|
@ -141,6 +142,8 @@ protected:
|
|||
virtual void addFolder(LLFolderViewFolder*) { }
|
||||
virtual bool isHighlightAllowed();
|
||||
virtual bool isHighlightActive();
|
||||
virtual bool isFlashing() { return false; }
|
||||
virtual void setFlashState(bool) { }
|
||||
|
||||
static LLFontGL* getLabelFontForStyle(U8 style);
|
||||
|
||||
|
|
@ -269,7 +272,7 @@ public:
|
|||
// virtual void handleDropped();
|
||||
virtual void draw();
|
||||
void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color);
|
||||
void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &bgColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor);
|
||||
void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor);
|
||||
void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);
|
||||
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
||||
EDragAndDropType cargo_type,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "lllocalcliprect.h"
|
||||
#include "llpanel.h"
|
||||
#include "llresizebar.h"
|
||||
#include "llcriticaldamp.h"
|
||||
#include "boost/foreach.hpp"
|
||||
|
||||
|
|
@ -796,6 +795,11 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
|
|||
}
|
||||
else
|
||||
{
|
||||
if (new_auto_resize_headroom < 1.f)
|
||||
{
|
||||
new_auto_resize_headroom = 1.f;
|
||||
}
|
||||
|
||||
F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)
|
||||
/ new_auto_resize_headroom,
|
||||
MIN_FRACTIONAL_SIZE,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#define LL_LLLAYOUTSTACK_H
|
||||
|
||||
#include "llpanel.h"
|
||||
#include "llresizebar.h"
|
||||
|
||||
|
||||
class LLLayoutPanel;
|
||||
|
|
@ -178,6 +179,7 @@ public:
|
|||
F32 getAutoResizeFactor() const;
|
||||
F32 getVisibleAmount() const;
|
||||
S32 getVisibleDim() const;
|
||||
LLResizeBar* getResizeBar() { return mResizeBar; }
|
||||
|
||||
bool isCollapsed() const { return mCollapsed;}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
|
|||
mTabContainer(NULL),
|
||||
mTabPos(LLTabContainer::TOP),
|
||||
mAutoResize(TRUE),
|
||||
mOrigMinWidth(0),
|
||||
mOrigMinHeight(0)
|
||||
mOrigMinWidth(params.min_width),
|
||||
mOrigMinHeight(params.min_height)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include "lldir.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "lltrans.h"
|
||||
#include "llnotificationslistener.h"
|
||||
#include "llstring.h"
|
||||
#include "llsdparam.h"
|
||||
#include "llsdutil.h"
|
||||
|
|
@ -993,10 +992,12 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
|
|||
bool abortProcessing = false;
|
||||
if (passesFilter)
|
||||
{
|
||||
onFilterPass(pNotification);
|
||||
abortProcessing = mPassedFilter(payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
onFilterFail(pNotification);
|
||||
abortProcessing = mFailedFilter(payload);
|
||||
}
|
||||
|
||||
|
|
@ -1168,8 +1169,6 @@ LLNotifications::LLNotifications()
|
|||
mIgnoreAllNotifications(false)
|
||||
{
|
||||
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
|
||||
|
||||
mListener.reset(new LLNotificationsListener(*this));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@
|
|||
#include "llevents.h"
|
||||
#include "llfunctorregistry.h"
|
||||
#include "llinitparam.h"
|
||||
#include "llnotificationslistener.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include "llpointer.h"
|
||||
#include "llrefcount.h"
|
||||
|
|
@ -681,7 +680,6 @@ namespace LLNotificationComparators
|
|||
};
|
||||
|
||||
typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter;
|
||||
typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator;
|
||||
typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet;
|
||||
typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;
|
||||
|
||||
|
|
@ -776,6 +774,9 @@ protected:
|
|||
virtual void onDelete(LLNotificationPtr p) {}
|
||||
virtual void onChange(LLNotificationPtr p) {}
|
||||
|
||||
virtual void onFilterPass(LLNotificationPtr p) {}
|
||||
virtual void onFilterFail(LLNotificationPtr p) {}
|
||||
|
||||
bool updateItem(const LLSD& payload, LLNotificationPtr pNotification);
|
||||
LLNotificationFilter mFilter;
|
||||
};
|
||||
|
|
@ -831,7 +832,6 @@ public:
|
|||
private:
|
||||
std::string mName;
|
||||
std::string mParent;
|
||||
LLNotificationComparator mComparator;
|
||||
};
|
||||
|
||||
// An interface class to provide a clean linker seam to the LLNotifications class.
|
||||
|
|
@ -951,7 +951,6 @@ private:
|
|||
|
||||
bool mIgnoreAllNotifications;
|
||||
|
||||
boost::scoped_ptr<LLNotificationsListener> mListener;
|
||||
std::vector<LLNotificationChannelPtr> mDefaultChannels;
|
||||
};
|
||||
|
||||
|
|
@ -1030,7 +1029,7 @@ protected:
|
|||
|
||||
// Stores only persistent notifications.
|
||||
// Class users can use connectChanged() to process persistent notifications
|
||||
// (see LLNotificationStorage for example).
|
||||
// (see LLPersistentNotificationStorage for example).
|
||||
class LLPersistentNotificationChannel : public LLNotificationChannel
|
||||
{
|
||||
LOG_CLASS(LLPersistentNotificationChannel);
|
||||
|
|
|
|||
|
|
@ -1,354 +0,0 @@
|
|||
/**
|
||||
* @file llnotificationslistener.cpp
|
||||
* @author Brad Kittenbrink
|
||||
* @date 2009-07-08
|
||||
* @brief Implementation for llnotificationslistener.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&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 "linden_common.h"
|
||||
#include "llnotificationslistener.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationtemplate.h"
|
||||
#include "llsd.h"
|
||||
#include "llui.h"
|
||||
|
||||
LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
|
||||
LLEventAPI("LLNotifications",
|
||||
"LLNotifications listener to (e.g.) pop up a notification"),
|
||||
mNotifications(notifications)
|
||||
{
|
||||
add("requestAdd",
|
||||
"Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
|
||||
"If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
|
||||
&LLNotificationsListener::requestAdd);
|
||||
add("listChannels",
|
||||
"Post to [\"reply\"] a map of info on existing channels",
|
||||
&LLNotificationsListener::listChannels,
|
||||
LLSD().with("reply", LLSD()));
|
||||
add("listChannelNotifications",
|
||||
"Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
|
||||
&LLNotificationsListener::listChannelNotifications,
|
||||
LLSD().with("reply", LLSD()).with("channel", LLSD()));
|
||||
add("respond",
|
||||
"Respond to notification [\"uuid\"] with data in [\"response\"]",
|
||||
&LLNotificationsListener::respond,
|
||||
LLSD().with("uuid", LLSD()));
|
||||
add("cancel",
|
||||
"Cancel notification [\"uuid\"]",
|
||||
&LLNotificationsListener::cancel,
|
||||
LLSD().with("uuid", LLSD()));
|
||||
add("ignore",
|
||||
"Ignore future notification [\"name\"]\n"
|
||||
"(from <notification name= > in notifications.xml)\n"
|
||||
"according to boolean [\"ignore\"].\n"
|
||||
"If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n"
|
||||
"Note that ignored notifications are not forwarded unless intercepted before\n"
|
||||
"the \"Ignore\" channel.",
|
||||
&LLNotificationsListener::ignore);
|
||||
add("forward",
|
||||
"Forward to [\"pump\"] future notifications on channel [\"channel\"]\n"
|
||||
"according to boolean [\"forward\"]. When enabled, only types matching\n"
|
||||
"[\"types\"] are forwarded, as follows:\n"
|
||||
"omitted or undefined: forward all notifications\n"
|
||||
"string: forward only the specific named [sig]type\n"
|
||||
"array of string: forward any notification matching any named [sig]type.\n"
|
||||
"When boolean [\"respond\"] is true, we auto-respond to each forwarded\n"
|
||||
"notification.",
|
||||
&LLNotificationsListener::forward,
|
||||
LLSD().with("channel", LLSD()));
|
||||
}
|
||||
|
||||
// This is here in the .cpp file so we don't need the definition of class
|
||||
// Forwarder in the header file.
|
||||
LLNotificationsListener::~LLNotificationsListener()
|
||||
{
|
||||
}
|
||||
|
||||
void LLNotificationsListener::requestAdd(const LLSD& event_data) const
|
||||
{
|
||||
if(event_data.has("reply"))
|
||||
{
|
||||
mNotifications.add(event_data["name"],
|
||||
event_data["substitutions"],
|
||||
event_data["payload"],
|
||||
boost::bind(&LLNotificationsListener::NotificationResponder,
|
||||
this,
|
||||
event_data["reply"].asString(),
|
||||
_1, _2
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
mNotifications.add(event_data["name"],
|
||||
event_data["substitutions"],
|
||||
event_data["payload"]);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,
|
||||
const LLSD& notification,
|
||||
const LLSD& response) const
|
||||
{
|
||||
LLSD reponse_event;
|
||||
reponse_event["notification"] = notification;
|
||||
reponse_event["response"] = response;
|
||||
LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
|
||||
}
|
||||
|
||||
void LLNotificationsListener::listChannels(const LLSD& params) const
|
||||
{
|
||||
LLReqID reqID(params);
|
||||
LLSD response(reqID.makeResponse());
|
||||
for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()),
|
||||
cmend(LLNotificationChannel::endInstances());
|
||||
cmi != cmend; ++cmi)
|
||||
{
|
||||
LLSD channelInfo;
|
||||
//channelInfo["parent"] = cmi->second->getParentChannelName();
|
||||
response[cmi->getName()] = channelInfo;
|
||||
}
|
||||
LLEventPumps::instance().obtain(params["reply"]).post(response);
|
||||
}
|
||||
|
||||
void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
|
||||
{
|
||||
LLReqID reqID(params);
|
||||
LLSD response(reqID.makeResponse());
|
||||
LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"]));
|
||||
if (channel)
|
||||
{
|
||||
LLSD notifications(LLSD::emptyArray());
|
||||
for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end());
|
||||
ni != nend; ++ni)
|
||||
{
|
||||
notifications.append(asLLSD(*ni));
|
||||
}
|
||||
response["notifications"] = notifications;
|
||||
}
|
||||
LLEventPumps::instance().obtain(params["reply"]).post(response);
|
||||
}
|
||||
|
||||
void LLNotificationsListener::respond(const LLSD& params) const
|
||||
{
|
||||
LLNotificationPtr notification(mNotifications.find(params["uuid"]));
|
||||
if (notification)
|
||||
{
|
||||
notification->respond(params["response"]);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNotificationsListener::cancel(const LLSD& params) const
|
||||
{
|
||||
LLNotificationPtr notification(mNotifications.find(params["uuid"]));
|
||||
if (notification)
|
||||
{
|
||||
mNotifications.cancel(notification);
|
||||
}
|
||||
}
|
||||
|
||||
void LLNotificationsListener::ignore(const LLSD& params) const
|
||||
{
|
||||
// Calling a method named "ignore", but omitting its "ignore" Boolean
|
||||
// argument, should by default cause something to be ignored. Explicitly
|
||||
// pass ["ignore"] = false to cancel ignore.
|
||||
bool ignore = true;
|
||||
if (params.has("ignore"))
|
||||
{
|
||||
ignore = params["ignore"].asBoolean();
|
||||
}
|
||||
// This method can be used to affect either a single notification name or
|
||||
// all future notifications. The two use substantially different mechanisms.
|
||||
if (params["name"].isDefined())
|
||||
{
|
||||
// ["name"] was passed: ignore just that notification
|
||||
LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]);
|
||||
if (templatep)
|
||||
{
|
||||
templatep->mForm->setIgnored(ignore);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no ["name"]: ignore all future notifications
|
||||
mNotifications.setIgnoreAllNotifications(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
class LLNotificationsListener::Forwarder: public LLEventTrackable
|
||||
{
|
||||
LOG_CLASS(LLNotificationsListener::Forwarder);
|
||||
public:
|
||||
Forwarder(LLNotifications& llnotifications, const std::string& channel):
|
||||
mNotifications(llnotifications),
|
||||
mRespond(false)
|
||||
{
|
||||
// Connect to the specified channel on construction. Because
|
||||
// LLEventTrackable is a base, we should automatically disconnect when
|
||||
// destroyed.
|
||||
LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
|
||||
if (channelptr)
|
||||
{
|
||||
// Insert our processing as a "passed filter" listener. This way
|
||||
// we get to run before all the "changed" listeners, and we get to
|
||||
// swipe it (hide it from the other listeners) if desired.
|
||||
channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1));
|
||||
}
|
||||
}
|
||||
|
||||
void setPumpName(const std::string& name) { mPumpName = name; }
|
||||
void setTypes(const LLSD& types) { mTypes = types; }
|
||||
void setRespond(bool respond) { mRespond = respond; }
|
||||
|
||||
private:
|
||||
bool handle(const LLSD& notification) const;
|
||||
bool matchType(const LLSD& filter, const std::string& type) const;
|
||||
|
||||
LLNotifications& mNotifications;
|
||||
std::string mPumpName;
|
||||
LLSD mTypes;
|
||||
bool mRespond;
|
||||
};
|
||||
|
||||
void LLNotificationsListener::forward(const LLSD& params)
|
||||
{
|
||||
std::string channel(params["channel"]);
|
||||
// First decide whether we're supposed to start forwarding or stop it.
|
||||
// Default to true.
|
||||
bool forward = true;
|
||||
if (params.has("forward"))
|
||||
{
|
||||
forward = params["forward"].asBoolean();
|
||||
}
|
||||
if (! forward)
|
||||
{
|
||||
// This is a request to stop forwarding notifications on the specified
|
||||
// channel. The rest of the params don't matter.
|
||||
// Because mForwarders contains scoped_ptrs, erasing the map entry
|
||||
// DOES delete the heap Forwarder object. Because Forwarder derives
|
||||
// from LLEventTrackable, destroying it disconnects it from the
|
||||
// channel.
|
||||
mForwarders.erase(channel);
|
||||
return;
|
||||
}
|
||||
// From here on, we know we're being asked to start (or modify) forwarding
|
||||
// on the specified channel. Find or create an appropriate Forwarder.
|
||||
ForwarderMap::iterator
|
||||
entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first);
|
||||
if (! entry->second)
|
||||
{
|
||||
entry->second.reset(new Forwarder(mNotifications, channel));
|
||||
}
|
||||
// Now, whether this Forwarder is brand-new or not, update it with the new
|
||||
// request info.
|
||||
Forwarder& fwd(*entry->second);
|
||||
fwd.setPumpName(params["pump"]);
|
||||
fwd.setTypes(params["types"]);
|
||||
fwd.setRespond(params["respond"]);
|
||||
}
|
||||
|
||||
bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL;
|
||||
if (notification["sigtype"].asString() == "delete")
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
|
||||
// let other listeners see the "delete" operation
|
||||
return false;
|
||||
}
|
||||
LLNotificationPtr note(mNotifications.find(notification["id"]));
|
||||
if (! note)
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
if (! matchType(mTypes, note->getType()))
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
|
||||
// We're not supposed to intercept this particular notification. Let
|
||||
// other listeners process it.
|
||||
return false;
|
||||
}
|
||||
LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
|
||||
// This is a notification we care about. Forward it through specified
|
||||
// LLEventPump.
|
||||
LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note));
|
||||
// Are we also being asked to auto-respond?
|
||||
if (mRespond)
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL;
|
||||
note->respond(LLSD::emptyMap());
|
||||
// Did that succeed in removing the notification? Only cancel() if
|
||||
// it's still around -- otherwise we get an LL_ERRS crash!
|
||||
note = mNotifications.find(notification["id"]);
|
||||
if (note)
|
||||
{
|
||||
LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL;
|
||||
mNotifications.cancel(note);
|
||||
}
|
||||
}
|
||||
// If we've auto-responded to this notification, then it's going to be
|
||||
// deleted. Other listeners would get the change operation, try to look it
|
||||
// up and be baffled by lookup failure. So when we auto-respond, suppress
|
||||
// this notification: don't pass it to other listeners.
|
||||
return mRespond;
|
||||
}
|
||||
|
||||
bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
|
||||
{
|
||||
// Decide whether this notification matches filter:
|
||||
// undefined: forward all notifications
|
||||
if (filter.isUndefined())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// array of string: forward any notification matching any named type
|
||||
if (filter.isArray())
|
||||
{
|
||||
for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray());
|
||||
ti != tend; ++ti)
|
||||
{
|
||||
if (ti->asString() == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Didn't match any entry in the array
|
||||
return false;
|
||||
}
|
||||
// string: forward only the specific named type
|
||||
return (filter.asString() == type);
|
||||
}
|
||||
|
||||
LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
|
||||
{
|
||||
LLSD notificationInfo(note->asLLSD());
|
||||
// For some reason the following aren't included in LLNotification::asLLSD().
|
||||
notificationInfo["summary"] = note->summarize();
|
||||
notificationInfo["id"] = note->id();
|
||||
notificationInfo["type"] = note->getType();
|
||||
notificationInfo["message"] = note->getMessage();
|
||||
notificationInfo["label"] = note->getLabel();
|
||||
return notificationInfo;
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/**
|
||||
* @file llnotificationslistener.h
|
||||
* @author Brad Kittenbrink
|
||||
* @date 2009-07-08
|
||||
* @brief Wrap subset of LLNotifications API in event API for test scripts.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&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_LLNOTIFICATIONSLISTENER_H
|
||||
#define LL_LLNOTIFICATIONSLISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class LLNotifications;
|
||||
class LLSD;
|
||||
|
||||
class LLNotificationsListener : public LLEventAPI
|
||||
{
|
||||
public:
|
||||
LLNotificationsListener(LLNotifications & notifications);
|
||||
~LLNotificationsListener();
|
||||
|
||||
private:
|
||||
void requestAdd(LLSD const & event_data) const;
|
||||
|
||||
void NotificationResponder(const std::string& replypump,
|
||||
const LLSD& notification,
|
||||
const LLSD& response) const;
|
||||
|
||||
void listChannels(const LLSD& params) const;
|
||||
void listChannelNotifications(const LLSD& params) const;
|
||||
void respond(const LLSD& params) const;
|
||||
void cancel(const LLSD& params) const;
|
||||
void ignore(const LLSD& params) const;
|
||||
void forward(const LLSD& params);
|
||||
|
||||
static LLSD asLLSD(LLNotificationPtr);
|
||||
|
||||
class Forwarder;
|
||||
typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
|
||||
ForwarderMap mForwarders;
|
||||
LLNotifications & mNotifications;
|
||||
};
|
||||
|
||||
#endif // LL_LLNOTIFICATIONSLISTENER_H
|
||||
|
|
@ -49,7 +49,6 @@
|
|||
//#include "llfunctorregistry.h"
|
||||
//#include "llpointer.h"
|
||||
#include "llinitparam.h"
|
||||
//#include "llnotificationslistener.h"
|
||||
//#include "llnotificationptr.h"
|
||||
//#include "llcachename.h"
|
||||
#include "llnotifications.h"
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
|
|||
mSide( p.side ),
|
||||
mSnappingEnabled(p.snapping_enabled),
|
||||
mAllowDoubleClickSnapping(p.allow_double_click_snapping),
|
||||
mResizingView(p.resizing_view)
|
||||
mResizingView(p.resizing_view),
|
||||
mResizeListener(NULL)
|
||||
{
|
||||
setFollowsNone();
|
||||
// set up some generically good follow code.
|
||||
|
|
@ -261,6 +262,11 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
|
|||
}
|
||||
}
|
||||
|
||||
if (mResizeListener)
|
||||
{
|
||||
mResizeListener(NULL);
|
||||
}
|
||||
|
||||
return handled;
|
||||
} // end LLResizeBar::handleHover
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; }
|
||||
void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }
|
||||
bool canResize() { return getEnabled() && mMaxSize > mMinSize; }
|
||||
void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;}
|
||||
|
||||
private:
|
||||
S32 mDragLastScreenX;
|
||||
|
|
@ -84,6 +85,7 @@ private:
|
|||
BOOL mSnappingEnabled;
|
||||
BOOL mAllowDoubleClickSnapping;
|
||||
LLView* mResizingView;
|
||||
boost::function<void(void*)> mResizeListener;
|
||||
};
|
||||
|
||||
#endif // LL_RESIZEBAR_H
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@
|
|||
#include "lltexteditor.h"
|
||||
#include "lltextbox.h"
|
||||
|
||||
static const S32 LINE_HEIGHT = 15;
|
||||
|
||||
S32 LLView::sDepth = 0;
|
||||
bool LLView::sDebugRects = false;
|
||||
bool LLView::sDebugRectsShowNames = true;
|
||||
|
|
@ -1203,11 +1205,24 @@ void LLView::drawDebugRect()
|
|||
&& preview_iter == sPreviewHighlightedElements.end()
|
||||
&& sDebugRectsShowNames)
|
||||
{
|
||||
//char temp[256];
|
||||
S32 x, y;
|
||||
gGL.color4fv( border_color.mV );
|
||||
x = debug_rect.getWidth()/2;
|
||||
y = debug_rect.getHeight()/2;
|
||||
|
||||
x = debug_rect.getWidth() / 2;
|
||||
|
||||
S32 rect_height = debug_rect.getHeight();
|
||||
S32 lines = rect_height / LINE_HEIGHT + 1;
|
||||
|
||||
S32 depth = 0;
|
||||
LLView * viewp = this;
|
||||
while (NULL != viewp)
|
||||
{
|
||||
viewp = viewp->getParent();
|
||||
depth++;
|
||||
}
|
||||
|
||||
y = rect_height - LINE_HEIGHT * (depth % lines + 1);
|
||||
|
||||
std::string debug_text = llformat("%s (%d x %d)", getName().c_str(),
|
||||
debug_rect.getWidth(), debug_rect.getHeight());
|
||||
LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ set(viewer_SOURCE_FILES
|
|||
llcommanddispatcherlistener.cpp
|
||||
llcommandhandler.cpp
|
||||
llcommandlineparser.cpp
|
||||
llcommunicationchannel.cpp
|
||||
llcompilequeue.cpp
|
||||
llconfirmationmanager.cpp
|
||||
llconversationlog.cpp
|
||||
|
|
@ -152,6 +153,7 @@ set(viewer_SOURCE_FILES
|
|||
lldebugview.cpp
|
||||
lldelayedgestureerror.cpp
|
||||
lldirpicker.cpp
|
||||
lldonotdisturbnotificationstorage.cpp
|
||||
lldndbutton.cpp
|
||||
lldrawable.cpp
|
||||
lldrawpool.cpp
|
||||
|
|
@ -448,6 +450,7 @@ set(viewer_SOURCE_FILES
|
|||
llpathfindingobject.cpp
|
||||
llpathfindingobjectlist.cpp
|
||||
llpathfindingpathtool.cpp
|
||||
llpersistentnotificationstorage.cpp
|
||||
llphysicsmotion.cpp
|
||||
llphysicsshapebuilderutil.cpp
|
||||
llplacesinventorybridge.cpp
|
||||
|
|
@ -722,6 +725,7 @@ set(viewer_HEADER_FILES
|
|||
llcommanddispatcherlistener.h
|
||||
llcommandhandler.h
|
||||
llcommandlineparser.h
|
||||
llcommunicationchannel.h
|
||||
llcompilequeue.h
|
||||
llconfirmationmanager.h
|
||||
llconversationlog.h
|
||||
|
|
@ -737,6 +741,7 @@ set(viewer_HEADER_FILES
|
|||
lldebugview.h
|
||||
lldelayedgestureerror.h
|
||||
lldirpicker.h
|
||||
lldonotdisturbnotificationstorage.h
|
||||
lldndbutton.h
|
||||
lldrawable.h
|
||||
lldrawpool.h
|
||||
|
|
@ -1021,6 +1026,7 @@ set(viewer_HEADER_FILES
|
|||
llpathfindingobject.h
|
||||
llpathfindingobjectlist.h
|
||||
llpathfindingpathtool.h
|
||||
llpersistentnotificationstorage.h
|
||||
llphysicsmotion.h
|
||||
llphysicsshapebuilderutil.h
|
||||
llplacesinventorybridge.h
|
||||
|
|
|
|||
|
|
@ -4676,7 +4676,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>LandBrushSize</key>
|
||||
<map>
|
||||
|
|
@ -13173,7 +13173,7 @@
|
|||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.25</real>
|
||||
<real>0.5</real>
|
||||
</map>
|
||||
<key>WindLightUseAtmosShaders</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>268</integer>
|
||||
<integer>205</integer>
|
||||
</map>
|
||||
<key>ConversationsMessagePaneCollapsed</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "llchannelmanager.h"
|
||||
#include "llchicletbar.h"
|
||||
#include "llconsole.h"
|
||||
#include "lldonotdisturbnotificationstorage.h"
|
||||
#include "llenvmanager.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llfloatercamera.h"
|
||||
|
|
@ -1389,11 +1390,16 @@ BOOL LLAgent::getAFK() const
|
|||
//-----------------------------------------------------------------------------
|
||||
// setDoNotDisturb()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAgent::setDoNotDisturb(bool pIsDotNotDisturb)
|
||||
void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb)
|
||||
{
|
||||
mIsDoNotDisturb = pIsDotNotDisturb;
|
||||
sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDotNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP));
|
||||
LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDotNotDisturb);
|
||||
bool isDoNotDisturbSwitchedOff = (mIsDoNotDisturb && !pIsDoNotDisturb);
|
||||
mIsDoNotDisturb = pIsDoNotDisturb;
|
||||
sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, (pIsDoNotDisturb ? ANIM_REQUEST_START : ANIM_REQUEST_STOP));
|
||||
LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(pIsDoNotDisturb);
|
||||
if (isDoNotDisturbSwitchedOff)
|
||||
{
|
||||
LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -2541,51 +2547,21 @@ void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReas
|
|||
|
||||
U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent)
|
||||
{
|
||||
// stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code,
|
||||
// if you attempted to change the preferred maturity to the same value, the response content would be an
|
||||
// undefined LLSD block. In the new server code with pathfinding, the response content should always be
|
||||
// defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged
|
||||
// into server trunk and fully deployed.
|
||||
U8 maturity = SIM_ACCESS_MIN;
|
||||
if (pContent.isUndefined())
|
||||
|
||||
llassert(!pContent.isUndefined());
|
||||
llassert(pContent.isMap());
|
||||
llassert(pContent.has("access_prefs"));
|
||||
llassert(pContent.get("access_prefs").isMap());
|
||||
llassert(pContent.get("access_prefs").has("max"));
|
||||
llassert(pContent.get("access_prefs").get("max").isString());
|
||||
if (!pContent.isUndefined() && pContent.isMap() && pContent.has("access_prefs")
|
||||
&& pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max")
|
||||
&& pContent.get("access_prefs").get("max").isString())
|
||||
{
|
||||
maturity = mPreferredMaturity;
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(!pContent.isUndefined());
|
||||
llassert(pContent.isMap());
|
||||
|
||||
if (!pContent.isUndefined() && pContent.isMap())
|
||||
{
|
||||
// stinson 05/24/2012 Pathfinding regions have re-defined the response syntax. The if statement catches
|
||||
// the new syntax, and the else statement catches the old syntax. After pathfinding is merged into
|
||||
// server trunk and fully deployed, we can remove the else statement.
|
||||
if (pContent.has("access_prefs"))
|
||||
{
|
||||
llassert(pContent.has("access_prefs"));
|
||||
llassert(pContent.get("access_prefs").isMap());
|
||||
llassert(pContent.get("access_prefs").has("max"));
|
||||
llassert(pContent.get("access_prefs").get("max").isString());
|
||||
if (pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") &&
|
||||
pContent.get("access_prefs").get("max").isString())
|
||||
{
|
||||
LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString();
|
||||
LLStringUtil::trim(actualPreference);
|
||||
maturity = LLViewerRegion::shortStringToAccess(actualPreference);
|
||||
}
|
||||
}
|
||||
else if (pContent.has("max"))
|
||||
{
|
||||
llassert(pContent.get("max").isString());
|
||||
if (pContent.get("max").isString())
|
||||
{
|
||||
LLSD::String actualPreference = pContent.get("max").asString();
|
||||
LLStringUtil::trim(actualPreference);
|
||||
maturity = LLViewerRegion::shortStringToAccess(actualPreference);
|
||||
}
|
||||
}
|
||||
}
|
||||
LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString();
|
||||
LLStringUtil::trim(actualPreference);
|
||||
maturity = LLViewerRegion::shortStringToAccess(actualPreference);
|
||||
}
|
||||
|
||||
return maturity;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@
|
|||
|
||||
using namespace LLNotificationsUI;
|
||||
|
||||
LLBrowserNotification::LLBrowserNotification()
|
||||
: LLSystemNotificationHandler("Browser", "browser")
|
||||
{
|
||||
}
|
||||
|
||||
bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification)
|
||||
{
|
||||
LLUUID media_id = notification->getPayload()["media_id"].asUUID();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@
|
|||
#include "llchannelmanager.h"
|
||||
|
||||
#include "llappviewer.h"
|
||||
#include "llnotificationstorage.h"
|
||||
#include "lldonotdisturbnotificationstorage.h"
|
||||
#include "llpersistentnotificationstorage.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llrootview.h"
|
||||
|
|
@ -138,6 +139,9 @@ void LLChannelManager::onLoginCompleted()
|
|||
}
|
||||
|
||||
LLPersistentNotificationStorage::getInstance()->loadNotifications();
|
||||
|
||||
LLDoNotDisturbNotificationStorage::getInstance()->initialize();
|
||||
LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -669,47 +669,3 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl)
|
|||
mGestureCombo->setFocus(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Cruft - global gChatHandler declared below has been commented out,
|
||||
so this class is never used. See similar code in llfloaterimnearbychatbar.cpp
|
||||
class LLChatHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
// not allowed from outside the app
|
||||
LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
|
||||
|
||||
// Your code here
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
bool retval = false;
|
||||
// Need at least 2 tokens to have a valid message.
|
||||
if (tokens.size() < 2)
|
||||
{
|
||||
retval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 channel = tokens[0].asInteger();
|
||||
// VWR-19499 Restrict function to chat channels greater than 0.
|
||||
if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG))
|
||||
{
|
||||
retval = true;
|
||||
// Say mesg on channel
|
||||
std::string mesg = tokens[1].asString();
|
||||
send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = false;
|
||||
// Tell us this is an unsupported SLurl.
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
// Creating the object registers with the dispatcher.
|
||||
//LLChatHandler gChatHandler;
|
||||
cruft */
|
||||
|
|
|
|||
|
|
@ -27,15 +27,17 @@
|
|||
#include "llviewerprecompiledheaders.h" // must be first include
|
||||
#include "llchiclet.h"
|
||||
|
||||
#include "llchicletbar.h"
|
||||
#include "llfloaterimsession.h"
|
||||
#include "llfloaterimcontainer.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lllocalcliprect.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llscriptfloater.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llsyswellwindow.h"
|
||||
|
||||
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
|
||||
static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
|
||||
static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");
|
||||
static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");
|
||||
|
||||
|
|
@ -46,6 +48,195 @@ boost::signals2::signal<LLChiclet* (const LLUUID&),
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLSysWellChiclet::Params::Params()
|
||||
: button("button")
|
||||
, unread_notifications("unread_notifications")
|
||||
, max_displayed_count("max_displayed_count", 99)
|
||||
{
|
||||
button.name = "button";
|
||||
button.tab_stop = FALSE;
|
||||
button.label = LLStringUtil::null;
|
||||
}
|
||||
|
||||
LLSysWellChiclet::LLSysWellChiclet(const Params& p)
|
||||
: LLChiclet(p)
|
||||
, mButton(NULL)
|
||||
, mCounter(0)
|
||||
, mMaxDisplayedCount(p.max_displayed_count)
|
||||
, mIsNewMessagesState(false)
|
||||
, mFlashToLitTimer(NULL)
|
||||
, mContextMenu(NULL)
|
||||
{
|
||||
LLButton::Params button_params = p.button;
|
||||
mButton = LLUICtrlFactory::create<LLButton>(button_params);
|
||||
addChild(mButton);
|
||||
|
||||
mFlashToLitTimer = new LLFlashTimer(boost::bind(&LLSysWellChiclet::changeLitState, this, _1));
|
||||
}
|
||||
|
||||
LLSysWellChiclet::~LLSysWellChiclet()
|
||||
{
|
||||
mFlashToLitTimer->unset();
|
||||
}
|
||||
|
||||
void LLSysWellChiclet::setCounter(S32 counter)
|
||||
{
|
||||
// do nothing if the same counter is coming. EXT-3678.
|
||||
if (counter == mCounter) return;
|
||||
|
||||
// note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)
|
||||
std::string s_count;
|
||||
if(counter != 0)
|
||||
{
|
||||
static std::string more_messages_exist("+");
|
||||
std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
|
||||
s_count = llformat("%d%s"
|
||||
, llmin(counter, mMaxDisplayedCount)
|
||||
, more_messages.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
mButton->setLabel(s_count);
|
||||
|
||||
mCounter = counter;
|
||||
}
|
||||
|
||||
boost::signals2::connection LLSysWellChiclet::setClickCallback(
|
||||
const commit_callback_t& cb)
|
||||
{
|
||||
return mButton->setClickedCallback(cb);
|
||||
}
|
||||
|
||||
void LLSysWellChiclet::setToggleState(BOOL toggled) {
|
||||
mButton->setToggleState(toggled);
|
||||
}
|
||||
|
||||
void LLSysWellChiclet::changeLitState(bool blink)
|
||||
{
|
||||
setNewMessagesState(!mIsNewMessagesState);
|
||||
}
|
||||
|
||||
void LLSysWellChiclet::setNewMessagesState(bool new_messages)
|
||||
{
|
||||
/*
|
||||
Emulate 4 states of button by background images, see detains in EXT-3147
|
||||
xml attribute Description
|
||||
image_unselected "Unlit" - there are no new messages
|
||||
image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
|
||||
image_pressed "Lit" - there are new messages
|
||||
image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
|
||||
*/
|
||||
mButton->setForcePressedState(new_messages);
|
||||
|
||||
mIsNewMessagesState = new_messages;
|
||||
}
|
||||
|
||||
void LLSysWellChiclet::updateWidget(bool is_window_empty)
|
||||
{
|
||||
mButton->setEnabled(!is_window_empty);
|
||||
|
||||
if (LLChicletBar::instanceExists())
|
||||
{
|
||||
LLChicletBar::getInstance()->showWellButton(getName(), !is_window_empty);
|
||||
}
|
||||
}
|
||||
// virtual
|
||||
BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if(!mContextMenu)
|
||||
{
|
||||
createMenu();
|
||||
}
|
||||
if (mContextMenu)
|
||||
{
|
||||
mContextMenu->show(x, y);
|
||||
LLMenuGL::showPopup(this, mContextMenu, x, y);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* LLNotificationChiclet implementation */
|
||||
/************************************************************************/
|
||||
LLNotificationChiclet::LLNotificationChiclet(const Params& p)
|
||||
: LLSysWellChiclet(p),
|
||||
mUreadSystemNotifications(0)
|
||||
{
|
||||
mNotificationChannel.reset(new ChicletNotificationChannel(this));
|
||||
// ensure that notification well window exists, to synchronously
|
||||
// handle toast add/delete events.
|
||||
LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);
|
||||
}
|
||||
|
||||
void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
|
||||
{
|
||||
std::string action = user_data.asString();
|
||||
if("close all" == action)
|
||||
{
|
||||
LLNotificationWellWindow::getInstance()->closeAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
|
||||
{
|
||||
std::string item = user_data.asString();
|
||||
if (item == "can close all")
|
||||
{
|
||||
return mUreadSystemNotifications != 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLNotificationChiclet::createMenu()
|
||||
{
|
||||
if(mContextMenu)
|
||||
{
|
||||
llwarns << "Menu already exists" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
|
||||
registrar.add("NotificationWellChicletMenu.Action",
|
||||
boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2));
|
||||
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
enable_registrar.add("NotificationWellChicletMenu.EnableItem",
|
||||
boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
|
||||
|
||||
mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
|
||||
("menu_notification_well_button.xml",
|
||||
LLMenuGL::sMenuContainer,
|
||||
LLViewerMenuHolderGL::child_registry_t::instance());
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLNotificationChiclet::setCounter(S32 counter)
|
||||
{
|
||||
LLSysWellChiclet::setCounter(counter);
|
||||
updateWidget(getCounter() == 0);
|
||||
|
||||
}
|
||||
|
||||
bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification )
|
||||
{
|
||||
if (notification->getName() == "ScriptDialog")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !(notification->canLogToIM() && notification->hasFormElements())
|
||||
&& (!notification->getPayload().has("give_inventory_notification")
|
||||
|| notification->getPayload()["give_inventory_notification"]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLChiclet::Params::Params()
|
||||
: show_counter("show_counter", true)
|
||||
, enable_counter("enable_counter", false)
|
||||
|
|
@ -57,12 +248,6 @@ LLChiclet::LLChiclet(const Params& p)
|
|||
, mSessionId(LLUUID::null)
|
||||
, mShowCounter(p.show_counter)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LLChiclet::~LLChiclet()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
boost::signals2::connection LLChiclet::setLeftButtonClickCallback(
|
||||
|
|
@ -125,6 +310,15 @@ BOOL LLIMChiclet::postBuild()
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void LLIMChiclet::enableCounterControl(bool enable)
|
||||
{
|
||||
mCounterEnabled = enable;
|
||||
if(!enable)
|
||||
{
|
||||
LLChiclet::setShowCounter(false);
|
||||
}
|
||||
}
|
||||
|
||||
void LLIMChiclet::setRequiredWidth()
|
||||
{
|
||||
S32 required_width = mDefaultWidth;
|
||||
|
|
@ -791,13 +985,19 @@ bool LLChicletPanel::isAnyIMFloaterDoked()
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
LLChicletNotificationCounterCtrl::Params::Params()
|
||||
: max_displayed_count("max_displayed_count", 99)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p)
|
||||
: LLAvatarIconCtrl(p)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -29,10 +29,70 @@
|
|||
|
||||
#include "llavatariconctrl.h"
|
||||
#include "llbutton.h"
|
||||
#include "llnotifications.h"
|
||||
#include "lltextbox.h"
|
||||
|
||||
class LLMenuGL;
|
||||
class LLFloaterIMSession;
|
||||
|
||||
/**
|
||||
* Class for displaying amount of messages/notifications(unread).
|
||||
*/
|
||||
class LLChicletNotificationCounterCtrl : public LLTextBox
|
||||
{
|
||||
public:
|
||||
|
||||
struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
|
||||
{
|
||||
/**
|
||||
* Contains maximum displayed count of unread messages. Default value is 9.
|
||||
*
|
||||
* If count is less than "max_unread_count" will be displayed as is.
|
||||
* Otherwise 9+ will be shown (for default value).
|
||||
*/
|
||||
Optional<S32> max_displayed_count;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets number of notifications
|
||||
*/
|
||||
virtual void setCounter(S32 counter);
|
||||
|
||||
/**
|
||||
* Returns number of notifications
|
||||
*/
|
||||
virtual S32 getCounter() const { return mCounter; }
|
||||
|
||||
/**
|
||||
* Returns width, required to display amount of notifications in text form.
|
||||
* Width is the only valid value.
|
||||
*/
|
||||
/*virtual*/ LLRect getRequiredRect();
|
||||
|
||||
/**
|
||||
* Sets number of notifications using LLSD
|
||||
*/
|
||||
/*virtual*/ void setValue(const LLSD& value);
|
||||
|
||||
/**
|
||||
* Returns number of notifications wrapped in LLSD
|
||||
*/
|
||||
/*virtual*/ LLSD getValue() const;
|
||||
|
||||
protected:
|
||||
|
||||
LLChicletNotificationCounterCtrl(const Params& p);
|
||||
friend class LLUICtrlFactory;
|
||||
|
||||
private:
|
||||
|
||||
S32 mCounter;
|
||||
S32 mInitialWidth;
|
||||
S32 mMaxDisplayedCount;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for displaying avatar's icon in P2P chiclet.
|
||||
*/
|
||||
|
|
@ -104,7 +164,7 @@ public:
|
|||
Params();
|
||||
};
|
||||
|
||||
/*virtual*/ ~LLChiclet();
|
||||
virtual ~LLChiclet() {}
|
||||
|
||||
/**
|
||||
* Associates chat session id with chiclet.
|
||||
|
|
@ -116,6 +176,11 @@ public:
|
|||
*/
|
||||
virtual const LLUUID& getSessionId() const { return mSessionId; }
|
||||
|
||||
/**
|
||||
* Sets show counter state.
|
||||
*/
|
||||
virtual void setShowCounter(bool show) { mShowCounter = show; }
|
||||
|
||||
/**
|
||||
* Connects chiclet clicked event with callback.
|
||||
*/
|
||||
|
|
@ -194,6 +259,22 @@ public:
|
|||
*/
|
||||
BOOL postBuild();
|
||||
|
||||
/**
|
||||
* Sets IM session name. This name will be displayed in chiclet tooltip.
|
||||
*/
|
||||
virtual void setIMSessionName(const std::string& name) { setToolTip(name); }
|
||||
|
||||
/**
|
||||
* Sets id of person/group user is chatting with.
|
||||
* Session id should be set before calling this
|
||||
*/
|
||||
virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; }
|
||||
|
||||
/**
|
||||
* Enables/disables the counter control for a chiclet.
|
||||
*/
|
||||
virtual void enableCounterControl(bool enable);
|
||||
|
||||
/**
|
||||
* Sets required width for a chiclet according to visible controls.
|
||||
*/
|
||||
|
|
@ -366,6 +447,131 @@ private:
|
|||
LLChicletInvOfferIconCtrl* mChicletIconCtrl;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements notification chiclet. Used to display total amount of unread messages
|
||||
* across all IM sessions, total amount of system notifications. See EXT-3147 for details
|
||||
*/
|
||||
class LLSysWellChiclet : public LLChiclet
|
||||
{
|
||||
public:
|
||||
|
||||
struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
|
||||
{
|
||||
Optional<LLButton::Params> button;
|
||||
|
||||
Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
|
||||
|
||||
/**
|
||||
* Contains maximum displayed count of unread messages. Default value is 9.
|
||||
*
|
||||
* If count is less than "max_unread_count" will be displayed as is.
|
||||
* Otherwise 9+ will be shown (for default value).
|
||||
*/
|
||||
Optional<S32> max_displayed_count;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
||||
/*virtual*/ void setCounter(S32 counter);
|
||||
|
||||
// *TODO: mantipov: seems getCounter is not necessary for LLNotificationChiclet
|
||||
// but inherited interface requires it to implement.
|
||||
// Probably it can be safe removed.
|
||||
/*virtual*/S32 getCounter() { return mCounter; }
|
||||
|
||||
boost::signals2::connection setClickCallback(const commit_callback_t& cb);
|
||||
|
||||
/*virtual*/ ~LLSysWellChiclet();
|
||||
|
||||
void setToggleState(BOOL toggled);
|
||||
|
||||
void setNewMessagesState(bool new_messages);
|
||||
//this method should change a widget according to state of the SysWellWindow
|
||||
virtual void updateWidget(bool is_window_empty);
|
||||
|
||||
protected:
|
||||
|
||||
LLSysWellChiclet(const Params& p);
|
||||
friend class LLUICtrlFactory;
|
||||
|
||||
/**
|
||||
* Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa.
|
||||
*
|
||||
* There is an assumption that it will be called 2*N times to do not change its start state.
|
||||
* @see FlashToLitTimer
|
||||
*/
|
||||
void changeLitState(bool blink);
|
||||
|
||||
/**
|
||||
* Displays menu.
|
||||
*/
|
||||
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
|
||||
|
||||
virtual void createMenu() = 0;
|
||||
|
||||
protected:
|
||||
class FlashToLitTimer;
|
||||
LLButton* mButton;
|
||||
S32 mCounter;
|
||||
S32 mMaxDisplayedCount;
|
||||
bool mIsNewMessagesState;
|
||||
|
||||
LLFlashTimer* mFlashToLitTimer;
|
||||
LLContextMenu* mContextMenu;
|
||||
};
|
||||
|
||||
class LLNotificationChiclet : public LLSysWellChiclet
|
||||
{
|
||||
LOG_CLASS(LLNotificationChiclet);
|
||||
|
||||
friend class LLUICtrlFactory;
|
||||
public:
|
||||
struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{};
|
||||
|
||||
protected:
|
||||
struct ChicletNotificationChannel : public LLNotificationChannel
|
||||
{
|
||||
ChicletNotificationChannel(LLNotificationChiclet* chiclet)
|
||||
: LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString()))
|
||||
, mChiclet(chiclet)
|
||||
{
|
||||
// connect counter handlers to the signals
|
||||
connectToChannel("Group Notifications");
|
||||
connectToChannel("Offer");
|
||||
connectToChannel("Notifications");
|
||||
}
|
||||
|
||||
static bool filterNotification(LLNotificationPtr notify);
|
||||
// connect counter updaters to the corresponding signals
|
||||
/*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); }
|
||||
/*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); }
|
||||
|
||||
LLNotificationChiclet* const mChiclet;
|
||||
};
|
||||
|
||||
boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel;
|
||||
|
||||
LLNotificationChiclet(const Params& p);
|
||||
|
||||
/**
|
||||
* Processes clicks on chiclet menu.
|
||||
*/
|
||||
void onMenuItemClicked(const LLSD& user_data);
|
||||
|
||||
/**
|
||||
* Enables chiclet menu items.
|
||||
*/
|
||||
bool enableMenuItem(const LLSD& user_data);
|
||||
|
||||
/**
|
||||
* Creates menu.
|
||||
*/
|
||||
/*virtual*/ void createMenu();
|
||||
|
||||
/*virtual*/ void setCounter(S32 counter);
|
||||
S32 mUreadSystemNotifications;
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage class for all IM chiclets. Provides mechanism to display,
|
||||
* scroll, create, remove chiclets.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llchiclet.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "llpaneltopinfobar.h"
|
||||
#include "llsyswellwindow.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -58,6 +59,8 @@ BOOL LLChicletBar::postBuild()
|
|||
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
|
||||
mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
|
||||
|
||||
showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty());
|
||||
|
||||
LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this));
|
||||
LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this));
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @file llcommunicationchannel.cpp
|
||||
* @brief Implementation of llcommunicationchannel
|
||||
* @author Stinson@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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 "llcommunicationchannel.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "llagent.h"
|
||||
#include "lldate.h"
|
||||
#include "llnotifications.h"
|
||||
|
||||
|
||||
LLCommunicationChannel::LLCommunicationChannel(const std::string& pName, const std::string& pParentName)
|
||||
: LLNotificationChannel(pName, pParentName, filterByDoNotDisturbStatus)
|
||||
, mHistory()
|
||||
{
|
||||
}
|
||||
|
||||
LLCommunicationChannel::~LLCommunicationChannel()
|
||||
{
|
||||
}
|
||||
|
||||
bool LLCommunicationChannel::filterByDoNotDisturbStatus(LLNotificationPtr)
|
||||
{
|
||||
return !gAgent.isDoNotDisturb();
|
||||
}
|
||||
|
||||
LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::beginHistory() const
|
||||
{
|
||||
return mHistory.begin();
|
||||
}
|
||||
|
||||
LLCommunicationChannel::history_list_t::const_iterator LLCommunicationChannel::endHistory() const
|
||||
{
|
||||
return mHistory.end();
|
||||
}
|
||||
|
||||
void LLCommunicationChannel::clearHistory()
|
||||
{
|
||||
mHistory.clear();
|
||||
}
|
||||
|
||||
void LLCommunicationChannel::onFilterFail(LLNotificationPtr pNotificationPtr)
|
||||
{
|
||||
std::string notificationType = pNotificationPtr->getType();
|
||||
if ((notificationType == "groupnotify")
|
||||
|| (notificationType == "offer")
|
||||
|| (notificationType == "notifytoast"))
|
||||
{
|
||||
mHistory.insert(std::make_pair<LLDate, LLNotificationPtr>(pNotificationPtr->getDate(), pNotificationPtr));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file llcommunicationchannel.h
|
||||
* @brief Header file for llcommunicationchannel
|
||||
* @author Stinson@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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_LLCOMMUNICATIONCHANNEL_H
|
||||
#define LL_LLCOMMUNICATIONCHANNEL_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "lldate.h"
|
||||
#include "llerror.h"
|
||||
#include "llnotifications.h"
|
||||
|
||||
class LLCommunicationChannel : public LLNotificationChannel
|
||||
{
|
||||
LOG_CLASS(LLCommunicationChannel);
|
||||
public:
|
||||
LLCommunicationChannel(const std::string& pName, const std::string& pParentName);
|
||||
virtual ~LLCommunicationChannel();
|
||||
|
||||
static bool filterByDoNotDisturbStatus(LLNotificationPtr);
|
||||
|
||||
typedef std::multimap<LLDate, LLNotificationPtr> history_list_t;
|
||||
history_list_t::const_iterator beginHistory() const;
|
||||
history_list_t::const_iterator endHistory() const;
|
||||
|
||||
void clearHistory();
|
||||
|
||||
protected:
|
||||
virtual void onFilterFail(LLNotificationPtr pNotificationPtr);
|
||||
|
||||
private:
|
||||
|
||||
history_list_t mHistory;
|
||||
};
|
||||
|
||||
#endif // LL_LLCOMMUNICATIONCHANNEL_H
|
||||
|
||||
|
|
@ -188,15 +188,23 @@ void LLConversationLogFriendObserver::changed(U32 mask)
|
|||
LLConversationLog::LLConversationLog() :
|
||||
mAvatarNameCacheConnection()
|
||||
{
|
||||
LLControlVariable* ctrl = gSavedPerAccountSettings.getControl("LogInstantMessages").get();
|
||||
if (ctrl)
|
||||
LLControlVariable* log_instant_message = gSavedPerAccountSettings.getControl("LogInstantMessages").get();
|
||||
LLControlVariable* keep_convers_log = gSavedSettings.getControl("KeepConversationLogTranscripts").get();
|
||||
bool is_log_message = false;
|
||||
bool is_keep_log = false;
|
||||
|
||||
if (log_instant_message)
|
||||
{
|
||||
ctrl->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
|
||||
if (ctrl->getValue().asBoolean())
|
||||
{
|
||||
enableLogging(true);
|
||||
}
|
||||
log_instant_message->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
|
||||
is_log_message = log_instant_message->getValue().asBoolean();
|
||||
}
|
||||
if (keep_convers_log)
|
||||
{
|
||||
keep_convers_log->getSignal()->connect(boost::bind(&LLConversationLog::enableLogging, this, _2));
|
||||
is_keep_log = keep_convers_log->getValue().asBoolean();
|
||||
}
|
||||
|
||||
enableLogging(is_log_message && is_keep_log);
|
||||
}
|
||||
|
||||
void LLConversationLog::enableLogging(bool enable)
|
||||
|
|
@ -229,17 +237,20 @@ void LLConversationLog::logConversation(const LLUUID& session_id, BOOL has_offli
|
|||
const LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
|
||||
LLConversation* conversation = findConversation(session);
|
||||
|
||||
if (session && conversation)
|
||||
if (session)
|
||||
{
|
||||
if(has_offline_msg)
|
||||
if (conversation)
|
||||
{
|
||||
updateOfflineIMs(session, has_offline_msg);
|
||||
if(has_offline_msg)
|
||||
{
|
||||
updateOfflineIMs(session, has_offline_msg);
|
||||
}
|
||||
updateConversationTimestamp(conversation);
|
||||
}
|
||||
else
|
||||
{
|
||||
createConversation(session);
|
||||
}
|
||||
updateConversationTimestamp(conversation);
|
||||
}
|
||||
else if (session && !conversation)
|
||||
{
|
||||
createConversation(session);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -304,19 +315,17 @@ void LLConversationLog::updateConversationTimestamp(LLConversation* conversation
|
|||
|
||||
LLConversation* LLConversationLog::findConversation(const LLIMModel::LLIMSession* session)
|
||||
{
|
||||
if (!session)
|
||||
if (session)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID;
|
||||
|
||||
const LLUUID session_id = session->isOutgoingAdHoc() ? session->generateOutgouigAdHocHash() : session->mSessionID;
|
||||
|
||||
conversations_vec_t::iterator conv_it = mConversations.begin();
|
||||
for(; conv_it != mConversations.end(); ++conv_it)
|
||||
{
|
||||
if (conv_it->getSessionID() == session_id)
|
||||
conversations_vec_t::iterator conv_it = mConversations.begin();
|
||||
for(; conv_it != mConversations.end(); ++conv_it)
|
||||
{
|
||||
return &*conv_it;
|
||||
if (conv_it->getSessionID() == session_id)
|
||||
{
|
||||
return &*conv_it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,8 +417,8 @@ bool LLConversationLog::saveToFile(const std::string& filename)
|
|||
// [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe|
|
||||
// [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a|
|
||||
|
||||
fprintf(fp, "[%d] %d %d %d %s| %s %s %s|\n",
|
||||
(S32)conv_it->getTime(),
|
||||
fprintf(fp, "[%lld] %d %d %d %s| %s %s %s|\n",
|
||||
(S64)conv_it->getTime(),
|
||||
(S32)conv_it->getConversationType(),
|
||||
(S32)0,
|
||||
(S32)conv_it->hasOfflineMessages(),
|
||||
|
|
@ -443,7 +452,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
|
|||
char history_file_name[MAX_STRING];
|
||||
int has_offline_ims;
|
||||
int stype;
|
||||
S32 time;
|
||||
time_t time;
|
||||
// before CHUI-348 it was a flag of conversation voice state
|
||||
int prereserved_unused;
|
||||
|
||||
|
|
@ -453,7 +462,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
|
|||
part_id_buffer[0] = '\0';
|
||||
conv_id_buffer[0] = '\0';
|
||||
|
||||
sscanf(buffer, "[%d] %d %d %d %[^|]| %s %s %[^|]|",
|
||||
sscanf(buffer, "[%ld] %d %d %d %[^|]| %s %s %[^|]|",
|
||||
&time,
|
||||
&stype,
|
||||
&prereserved_unused,
|
||||
|
|
|
|||
|
|
@ -102,35 +102,44 @@ void LLConversationItem::showProperties(void)
|
|||
{
|
||||
}
|
||||
|
||||
void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items)
|
||||
void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags)
|
||||
{
|
||||
items.push_back(std::string("view_profile"));
|
||||
items.push_back(std::string("im"));
|
||||
items.push_back(std::string("offer_teleport"));
|
||||
items.push_back(std::string("voice_call"));
|
||||
items.push_back(std::string("chat_history"));
|
||||
items.push_back(std::string("separator_chat_history"));
|
||||
items.push_back(std::string("add_friend"));
|
||||
items.push_back(std::string("remove_friend"));
|
||||
items.push_back(std::string("invite_to_group"));
|
||||
items.push_back(std::string("separator_invite_to_group"));
|
||||
items.push_back(std::string("map"));
|
||||
items.push_back(std::string("share"));
|
||||
items.push_back(std::string("pay"));
|
||||
items.push_back(std::string("block_unblock"));
|
||||
items.push_back(std::string("MuteText"));
|
||||
|
||||
if(this->getType() != CONV_SESSION_1_ON_1 && mDisplayModeratorOptions)
|
||||
if (flags & ITEM_IN_MULTI_SELECTION)
|
||||
{
|
||||
items.push_back(std::string("Moderator Options Separator"));
|
||||
items.push_back(std::string("Moderator Options"));
|
||||
items.push_back(std::string("AllowTextChat"));
|
||||
items.push_back(std::string("moderate_voice_separator"));
|
||||
items.push_back(std::string("ModerateVoiceToggleMuteSelected"));
|
||||
items.push_back(std::string("ModerateVoiceMute"));
|
||||
items.push_back(std::string("ModerateVoiceUnmute"));
|
||||
items.push_back(std::string("im"));
|
||||
items.push_back(std::string("offer_teleport"));
|
||||
items.push_back(std::string("voice_call"));
|
||||
items.push_back(std::string("remove_friends"));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.push_back(std::string("view_profile"));
|
||||
items.push_back(std::string("im"));
|
||||
items.push_back(std::string("offer_teleport"));
|
||||
items.push_back(std::string("voice_call"));
|
||||
items.push_back(std::string("chat_history"));
|
||||
items.push_back(std::string("separator_chat_history"));
|
||||
items.push_back(std::string("add_friend"));
|
||||
items.push_back(std::string("remove_friend"));
|
||||
items.push_back(std::string("invite_to_group"));
|
||||
items.push_back(std::string("separator_invite_to_group"));
|
||||
items.push_back(std::string("map"));
|
||||
items.push_back(std::string("share"));
|
||||
items.push_back(std::string("pay"));
|
||||
items.push_back(std::string("block_unblock"));
|
||||
items.push_back(std::string("MuteText"));
|
||||
|
||||
if ((getType() != CONV_SESSION_1_ON_1) && mDisplayModeratorOptions)
|
||||
{
|
||||
items.push_back(std::string("Moderator Options Separator"));
|
||||
items.push_back(std::string("Moderator Options"));
|
||||
items.push_back(std::string("AllowTextChat"));
|
||||
items.push_back(std::string("moderate_voice_separator"));
|
||||
items.push_back(std::string("ModerateVoiceToggleMuteSelected"));
|
||||
items.push_back(std::string("ModerateVoiceMute"));
|
||||
items.push_back(std::string("ModerateVoiceUnmute"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -306,7 +315,7 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
{
|
||||
items.push_back(std::string("close_conversation"));
|
||||
items.push_back(std::string("separator_disconnect_from_voice"));
|
||||
buildParticipantMenuOptions(items);
|
||||
buildParticipantMenuOptions(items, flags);
|
||||
}
|
||||
else if(this->getType() == CONV_SESSION_GROUP)
|
||||
{
|
||||
|
|
@ -475,7 +484,7 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
menuentry_vec_t items;
|
||||
menuentry_vec_t disabled_items;
|
||||
|
||||
buildParticipantMenuOptions(items);
|
||||
buildParticipantMenuOptions(items, flags);
|
||||
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ public:
|
|||
|
||||
void postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant);
|
||||
|
||||
void buildParticipantMenuOptions(menuentry_vec_t& items);
|
||||
void buildParticipantMenuOptions(menuentry_vec_t& items, U32 flags);
|
||||
|
||||
protected:
|
||||
std::string mName; // Name of the session or the participant
|
||||
|
|
|
|||
|
|
@ -81,7 +81,9 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes
|
|||
mSpeakingIndicator(NULL),
|
||||
mVoiceClientObserver(NULL),
|
||||
mCollapsedMode(false),
|
||||
mHasArrow(true)
|
||||
mHasArrow(true),
|
||||
mFlashStateOn(false),
|
||||
mFlashStarted(false)
|
||||
{
|
||||
mFlashTimer = new LLFlashTimer();
|
||||
}
|
||||
|
|
@ -101,7 +103,17 @@ LLConversationViewSession::~LLConversationViewSession()
|
|||
void LLConversationViewSession::setFlashState(bool flash_state)
|
||||
{
|
||||
mFlashStateOn = flash_state;
|
||||
(flash_state ? mFlashTimer->startFlashing() : mFlashTimer->stopFlashing());
|
||||
mFlashStarted = false;
|
||||
mFlashTimer->stopFlashing();
|
||||
}
|
||||
|
||||
void LLConversationViewSession::startFlashing()
|
||||
{
|
||||
if (mFlashStateOn && !mFlashStarted)
|
||||
{
|
||||
mFlashStarted = true;
|
||||
mFlashTimer->startFlashing();
|
||||
}
|
||||
}
|
||||
|
||||
bool LLConversationViewSession::isHighlightAllowed()
|
||||
|
|
@ -198,8 +210,11 @@ void LLConversationViewSession::draw()
|
|||
drawOpenFolderArrow(default_params, sFgColor);
|
||||
}
|
||||
|
||||
// Indicate that flash can start (moot operation if already started, done or not flashing)
|
||||
startFlashing();
|
||||
|
||||
// draw highlight for selected items
|
||||
drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
drawHighlight(show_context, true, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
|
||||
// Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap.
|
||||
bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen();
|
||||
|
|
@ -231,6 +246,7 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask )
|
|||
if(result && getRoot()->getCurSelectedItem() == this)
|
||||
{
|
||||
LLFloaterIMContainer *im_container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
im_container->clearAllFlashStates();
|
||||
im_container->selectConversationPair(session_id, false);
|
||||
im_container->collapseMessagesPane(false);
|
||||
}
|
||||
|
|
@ -427,6 +443,7 @@ void LLConversationViewParticipant::draw()
|
|||
static LLUIColor sFgDisabledColor = LLUIColorTable::instance().getColor("MenuItemDisabledColor", DEFAULT_WHITE);
|
||||
static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
|
||||
static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
|
||||
static LLUIColor sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE);
|
||||
static LLUIColor sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
|
||||
static LLUIColor sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
|
||||
|
||||
|
|
@ -450,7 +467,7 @@ void LLConversationViewParticipant::draw()
|
|||
color = mIsSelected ? sHighlightFgColor : sFgColor;
|
||||
}
|
||||
|
||||
drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
drawLabel(font, text_left, y, color, right_x);
|
||||
refresh();
|
||||
|
||||
|
|
@ -530,27 +547,6 @@ void LLConversationViewParticipant::onMouseLeave(S32 x, S32 y, MASK mask)
|
|||
LLFolderViewItem::onMouseLeave(x, y, mask);
|
||||
}
|
||||
|
||||
BOOL LLConversationViewParticipant::handleMouseDown( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
LLConversationItem* item = NULL;
|
||||
LLConversationViewSession* session_widget =
|
||||
dynamic_cast<LLConversationViewSession *>(this->getParentFolder());
|
||||
if (session_widget)
|
||||
{
|
||||
item = dynamic_cast<LLConversationItem*>(session_widget->getViewModelItem());
|
||||
}
|
||||
LLUUID session_id = item? item->getUUID() : LLUUID();
|
||||
BOOL result = LLFolderViewItem::handleMouseDown(x, y, mask);
|
||||
|
||||
if(result)
|
||||
{
|
||||
(LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"))->
|
||||
selectConversationPair(session_id, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
S32 LLConversationViewParticipant::getLabelXPos()
|
||||
{
|
||||
return getIndentation() + mAvatarIcon->getRect().getWidth() + mIconPad;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ protected:
|
|||
|
||||
/*virtual*/ bool isHighlightAllowed();
|
||||
/*virtual*/ bool isHighlightActive();
|
||||
/*virtual*/ bool isFlashing() { return mFlashStateOn; }
|
||||
|
||||
LLFloaterIMContainer* mContainer;
|
||||
|
||||
|
|
@ -83,11 +84,12 @@ public:
|
|||
|
||||
virtual void refresh();
|
||||
|
||||
void setFlashState(bool flash_state);
|
||||
/*virtual*/ void setFlashState(bool flash_state);
|
||||
|
||||
private:
|
||||
|
||||
void onCurrentVoiceSessionChanged(const LLUUID& session_id);
|
||||
void startFlashing();
|
||||
|
||||
LLPanel* mItemPanel;
|
||||
LLPanel* mCallIconLayoutPanel;
|
||||
|
|
@ -95,6 +97,7 @@ private:
|
|||
LLOutputMonitorCtrl* mSpeakingIndicator;
|
||||
LLFlashTimer* mFlashTimer;
|
||||
bool mFlashStateOn;
|
||||
bool mFlashStarted;
|
||||
|
||||
bool mCollapsedMode;
|
||||
bool mHasArrow;
|
||||
|
|
@ -129,8 +132,6 @@ public:
|
|||
void addToFolder(LLFolderViewFolder* folder);
|
||||
void addToSession(const LLUUID& session_id);
|
||||
|
||||
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
|
||||
|
||||
void onMouseEnter(S32 x, S32 y, MASK mask);
|
||||
void onMouseLeave(S32 x, S32 y, MASK mask);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* @file lldonotdisturbnotificationstorage.cpp
|
||||
* @brief Implementation of lldonotdisturbnotificationstorage
|
||||
* @author Stinson@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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"
|
||||
|
||||
#include "lldonotdisturbnotificationstorage.h"
|
||||
|
||||
#include "llcommunicationchannel.h"
|
||||
#include "lldir.h"
|
||||
#include "llerror.h"
|
||||
#include "llfasttimer_class.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationhandler.h"
|
||||
#include "llnotificationstorage.h"
|
||||
#include "llscriptfloater.h"
|
||||
#include "llsd.h"
|
||||
#include "llsingleton.h"
|
||||
#include "lluuid.h"
|
||||
|
||||
LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
|
||||
: LLSingleton<LLDoNotDisturbNotificationStorage>()
|
||||
, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"))
|
||||
{
|
||||
}
|
||||
|
||||
LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage()
|
||||
{
|
||||
}
|
||||
|
||||
void LLDoNotDisturbNotificationStorage::initialize()
|
||||
{
|
||||
getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1));
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications");
|
||||
|
||||
void LLDoNotDisturbNotificationStorage::saveNotifications()
|
||||
{
|
||||
LLFastTimer _(FTM_SAVE_DND_NOTIFICATIONS);
|
||||
|
||||
LLNotificationChannelPtr channelPtr = getCommunicationChannel();
|
||||
const LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
|
||||
llassert(commChannel != NULL);
|
||||
|
||||
LLSD output = LLSD::emptyMap();
|
||||
LLSD& data = output["data"];
|
||||
data = LLSD::emptyArray();
|
||||
|
||||
for (LLCommunicationChannel::history_list_t::const_iterator historyIter = commChannel->beginHistory();
|
||||
historyIter != commChannel->endHistory(); ++historyIter)
|
||||
{
|
||||
LLNotificationPtr notificationPtr = historyIter->second;
|
||||
|
||||
if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired())
|
||||
{
|
||||
data.append(notificationPtr->asLLSD());
|
||||
}
|
||||
}
|
||||
|
||||
writeNotifications(output);
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications");
|
||||
|
||||
void LLDoNotDisturbNotificationStorage::loadNotifications()
|
||||
{
|
||||
LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS);
|
||||
|
||||
LLSD input;
|
||||
if (!readNotifications(input) ||input.isUndefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD& data = input["data"];
|
||||
if (data.isUndefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLNotifications& instance = LLNotifications::instance();
|
||||
|
||||
for (LLSD::array_const_iterator notification_it = data.beginArray();
|
||||
notification_it != data.endArray();
|
||||
++notification_it)
|
||||
{
|
||||
LLSD notification_params = *notification_it;
|
||||
LLNotificationPtr notification(new LLNotification(notification_params));
|
||||
|
||||
const LLUUID& notificationID = notification->id();
|
||||
if (instance.find(notificationID))
|
||||
{
|
||||
instance.update(notification);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationResponderInterface* responder = createResponder(notification_params["name"], notification_params["responder"]);
|
||||
if (responder == NULL)
|
||||
{
|
||||
LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '"
|
||||
<< notification->getType() << "'" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLNotificationResponderPtr responderPtr(responder);
|
||||
notification->setResponseFunctor(responderPtr);
|
||||
}
|
||||
|
||||
instance.add(notification);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the communication channel history and rewrite the save file to empty it as well
|
||||
LLNotificationChannelPtr channelPtr = getCommunicationChannel();
|
||||
LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
|
||||
llassert(commChannel != NULL);
|
||||
commChannel->clearHistory();
|
||||
|
||||
saveNotifications();
|
||||
}
|
||||
|
||||
LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const
|
||||
{
|
||||
LLNotificationChannelPtr channelPtr = LLNotifications::getInstance()->getChannel("Communication");
|
||||
llassert(channelPtr);
|
||||
return channelPtr;
|
||||
}
|
||||
|
||||
|
||||
bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload)
|
||||
{
|
||||
if (pPayload["sigtype"].asString() != "load")
|
||||
{
|
||||
saveNotifications();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file lldonotdisturbnotificationstorage.h
|
||||
* @brief Header file for lldonotdisturbnotificationstorage
|
||||
* @author Stinson@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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_LLDONOTDISTURBNOTIFICATIONSTORAGE_H
|
||||
#define LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H
|
||||
|
||||
#include "llerror.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationstorage.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage
|
||||
{
|
||||
LOG_CLASS(LLDoNotDisturbNotificationStorage);
|
||||
public:
|
||||
LLDoNotDisturbNotificationStorage();
|
||||
~LLDoNotDisturbNotificationStorage();
|
||||
|
||||
void initialize();
|
||||
|
||||
void saveNotifications();
|
||||
void loadNotifications();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
LLNotificationChannelPtr getCommunicationChannel() const;
|
||||
bool onChannelChanged(const LLSD& pPayload);
|
||||
};
|
||||
|
||||
#endif // LL_LLDONOTDISTURBNOTIFICATIONSTORAGE_H
|
||||
|
||||
|
|
@ -444,7 +444,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
|
|||
return ;
|
||||
}
|
||||
|
||||
// stinson 11/12/2012: Need to check with davep on the following.
|
||||
// Fix for MAINT-1894
|
||||
// Skipping the flexible update if render res is negative. If we were to continue with a negative value,
|
||||
// the subsequent S32 num_render_sections = 1<<mRenderRes; code will specify a really large number of
|
||||
// render sections which will then create a length exception in the std::vector::resize() method.
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ BOOL LLFloaterConversationLog::postBuild()
|
|||
if (ctrl)
|
||||
{
|
||||
ctrl->getSignal()->connect(boost::bind(&LLFloaterConversationLog::onCallLoggingEnabledDisabled, this, _2));
|
||||
onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean());
|
||||
onCallLoggingEnabledDisabled(ctrl->getValue().asBoolean()
|
||||
&& gSavedSettings.getBOOL("KeepConversationLogTranscripts"));
|
||||
}
|
||||
|
||||
return LLFloater::postBuild();
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@
|
|||
#include "llconversationview.h"
|
||||
#include "llcallbacklist.h"
|
||||
#include "llworld.h"
|
||||
|
||||
#include "llsdserialize.h"
|
||||
|
||||
//
|
||||
// LLFloaterIMContainer
|
||||
//
|
||||
|
|
@ -171,6 +171,9 @@ BOOL LLFloaterIMContainer::postBuild()
|
|||
// Open IM session with selected participant on double click event
|
||||
mConversationsListPanel->setDoubleClickCallback(boost::bind(&LLFloaterIMContainer::doToSelected, this, LLSD("im")));
|
||||
|
||||
// The resize limits for LLFloaterIMContainer should be updated, based on current values of width of conversation and message panels
|
||||
mConversationsPane->getResizeBar()->setResizeListener(boost::bind(&LLFloaterIMContainer::assignResizeLimits, this));
|
||||
|
||||
// Create the root model and view for all conversation sessions
|
||||
LLConversationItem* base_item = new LLConversationItem(getRootViewModel());
|
||||
|
||||
|
|
@ -247,6 +250,7 @@ void LLFloaterIMContainer::onOpen(const LLSD& key)
|
|||
{
|
||||
LLMultiFloater::onOpen(key);
|
||||
openNearbyChat();
|
||||
assignResizeLimits();
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
@ -308,26 +312,6 @@ void LLFloaterIMContainer::onCloseFloater(LLUUID& id)
|
|||
setFocus(TRUE);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterIMContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height)
|
||||
{
|
||||
// possibly increase floater's minimum height according to children's minimums
|
||||
for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
|
||||
{
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx));
|
||||
if (floaterp)
|
||||
{
|
||||
new_min_height = llmax(new_min_height, floaterp->getMinHeight());
|
||||
}
|
||||
}
|
||||
|
||||
S32 conversations_pane_min_dim = mConversationsPane->getRelevantMinDim();
|
||||
S32 messages_pane_min_dim = mMessagesPane->getRelevantMinDim();
|
||||
|
||||
// set floater's minimum width according to relevant minimal children's dimensionals
|
||||
new_min_width = conversations_pane_min_dim + messages_pane_min_dim + LLPANEL_BORDER_WIDTH*2;
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::onNewMessageReceived(const LLSD& data)
|
||||
{
|
||||
LLUUID session_id = data["session_id"].asUUID();
|
||||
|
|
@ -621,6 +605,12 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
|
|||
LLMultiFloater::setVisible(visible);
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::updateResizeLimits()
|
||||
{
|
||||
LLMultiFloater::updateResizeLimits();
|
||||
assignResizeLimits();
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::collapseMessagesPane(bool collapse)
|
||||
{
|
||||
if (mMessagesPane->isCollapsed() == collapse)
|
||||
|
|
@ -694,6 +684,7 @@ void LLFloaterIMContainer::collapseConversationsPane(bool collapse)
|
|||
{
|
||||
widget->setOpen(false);
|
||||
}
|
||||
widget->requestArrange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -728,6 +719,15 @@ void LLFloaterIMContainer::updateState(bool collapse, S32 delta_width)
|
|||
setResizeLimits(expanded_min_size, expanded_min_size);
|
||||
}
|
||||
|
||||
assignResizeLimits();
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::assignResizeLimits()
|
||||
{
|
||||
const LLRect& conv_rect = mConversationsPane->isCollapsed() ? LLRect() : mConversationsPane->getRect();
|
||||
S32 msg_limits = mMessagesPane->isCollapsed() ? 0 : mMessagesPane->getExpandedMinDim();
|
||||
S32 x_limits = conv_rect.getWidth() + msg_limits;
|
||||
setResizeLimits(x_limits + LLPANEL_BORDER_WIDTH * 3, getMinHeight());
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::onAddButtonClicked()
|
||||
|
|
@ -1108,7 +1108,27 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
|
|||
uuid_vec_t uuids;
|
||||
getParticipantUUIDs(uuids);
|
||||
|
||||
if("can_activate_group" == item)
|
||||
if ("conversation_log" == item)
|
||||
{
|
||||
return gSavedSettings.getBOOL("KeepConversationLogTranscripts");
|
||||
}
|
||||
|
||||
//Enable Chat history item for ad-hoc and group conversations
|
||||
if ("can_chat_history" == item)
|
||||
{
|
||||
if (getCurSelectedViewModelItem()->getType() != LLConversationItem::CONV_PARTICIPANT)
|
||||
{
|
||||
return isConversationLoggingAllowed();
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing is selected(and selected item is not group chat), everything needs to be disabled
|
||||
if (uuids.size() <= 0)
|
||||
{
|
||||
return getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP;
|
||||
}
|
||||
|
||||
if("can_activate_group" == item)
|
||||
{
|
||||
LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID();
|
||||
return gAgent.getGroupID() != selected_group_id;
|
||||
|
|
@ -1119,17 +1139,6 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
|
|||
|
||||
bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_vec_t& uuids)
|
||||
{
|
||||
if ("conversation_log" == item)
|
||||
{
|
||||
return gSavedSettings.getBOOL("KeepConversationLogTranscripts");
|
||||
}
|
||||
|
||||
// If nothing is selected, everything needs to be disabled
|
||||
if (uuids.size() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract the single select info
|
||||
bool is_single_select = (uuids.size() == 1);
|
||||
const LLUUID& single_id = uuids.front();
|
||||
|
|
@ -1236,6 +1245,19 @@ void LLFloaterIMContainer::showConversation(const LLUUID& session_id)
|
|||
selectConversationPair(session_id, true);
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::clearAllFlashStates()
|
||||
{
|
||||
conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
|
||||
for (;widget_it != mConversationsWidgets.end(); ++widget_it)
|
||||
{
|
||||
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second);
|
||||
if (widget)
|
||||
{
|
||||
widget->setFlashState(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::selectConversation(const LLUUID& session_id)
|
||||
{
|
||||
selectConversationPair(session_id, true);
|
||||
|
|
@ -1247,17 +1269,6 @@ BOOL LLFloaterIMContainer::selectConversationPair(const LLUUID& session_id, bool
|
|||
BOOL handled = TRUE;
|
||||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id);
|
||||
|
||||
// On selection, stop the flash state on all conversation widgets
|
||||
conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
|
||||
for (;widget_it != mConversationsWidgets.end(); ++widget_it)
|
||||
{
|
||||
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second);
|
||||
if (widget)
|
||||
{
|
||||
widget->setFlashState(false);
|
||||
}
|
||||
}
|
||||
|
||||
/* widget processing */
|
||||
if (select_widget)
|
||||
{
|
||||
|
|
@ -1419,14 +1430,14 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
|
|||
// Delete the widget and the associated conversation item
|
||||
// Note : since the mConversationsItems is also the listener to the widget, deleting
|
||||
// the widget will also delete its listener
|
||||
bool isWidgetSelected = false;
|
||||
bool is_widget_selected = false;
|
||||
LLFolderViewItem* new_selection = NULL;
|
||||
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
|
||||
if (widget)
|
||||
{
|
||||
isWidgetSelected = widget->isSelected();
|
||||
is_widget_selected = widget->isSelected();
|
||||
new_selection = mConversationsRoot->getNextFromChild(widget);
|
||||
if(new_selection == NULL)
|
||||
if (!new_selection)
|
||||
{
|
||||
new_selection = mConversationsRoot->getPreviousFromChild(widget);
|
||||
}
|
||||
|
|
@ -1441,18 +1452,24 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
|
|||
if (change_focus)
|
||||
{
|
||||
setFocus(TRUE);
|
||||
if(new_selection != NULL)
|
||||
if (new_selection)
|
||||
{
|
||||
if (mConversationsWidgets.size() == 1)
|
||||
new_selection = new_selection->getParentFolder();
|
||||
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem());
|
||||
if(vmi != NULL)
|
||||
{
|
||||
selectConversationPair(vmi->getUUID(), true);
|
||||
// If only one widget is left, it has to be the Nearby Chat. Select it directly.
|
||||
selectConversationPair(LLUUID(NULL), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(new_selection->getViewModelItem());
|
||||
if (vmi)
|
||||
{
|
||||
selectConversationPair(vmi->getUUID(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isWidgetSelected;
|
||||
return is_widget_selected;
|
||||
}
|
||||
|
||||
LLConversationViewSession* LLFloaterIMContainer::createConversationItemWidget(LLConversationItem* item)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ public:
|
|||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void setVisible(BOOL visible);
|
||||
/*virtual*/ void updateResizeLimits();
|
||||
void onCloseFloater(LLUUID& id);
|
||||
|
||||
/*virtual*/ void addFloater(LLFloater* floaterp,
|
||||
|
|
@ -69,6 +70,7 @@ public:
|
|||
void showConversation(const LLUUID& session_id);
|
||||
void selectConversation(const LLUUID& session_id);
|
||||
BOOL selectConversationPair(const LLUUID& session_id, bool select_widget);
|
||||
void clearAllFlashStates();
|
||||
|
||||
/*virtual*/ void tabClose();
|
||||
void showStub(bool visible);
|
||||
|
|
@ -105,12 +107,14 @@ public:
|
|||
bool enableContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS);
|
||||
void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS);
|
||||
|
||||
void assignResizeLimits();
|
||||
|
||||
private:
|
||||
typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;
|
||||
avatarID_panel_map_t mSessions;
|
||||
boost::signals2::connection mNewMessageConnection;
|
||||
|
||||
/*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height);
|
||||
/*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height) {}
|
||||
|
||||
void onNewMessageReceived(const LLSD& data);
|
||||
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ BOOL LLFloaterIMNearbyChat::postBuild()
|
|||
BOOL result = LLFloaterIMSessionTab::postBuild();
|
||||
|
||||
mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this));
|
||||
mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this));
|
||||
mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this));
|
||||
mInputEditor->setKeystrokeCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxKeystroke, this));
|
||||
mInputEditor->setFocusLostCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusLost, this));
|
||||
mInputEditor->setFocusReceivedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxFocusReceived, this));
|
||||
mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle"));
|
||||
|
||||
|
|
@ -354,13 +354,11 @@ BOOL LLFloaterIMNearbyChat::matchChatTypeTrigger(const std::string& in_str, std:
|
|||
return string_was_found;
|
||||
}
|
||||
|
||||
void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userdata)
|
||||
void LLFloaterIMNearbyChat::onChatBoxKeystroke()
|
||||
{
|
||||
LLFirstUse::otherAvatarChatFirst(false);
|
||||
|
||||
LLFloaterIMNearbyChat* self = (LLFloaterIMNearbyChat *)userdata;
|
||||
|
||||
LLWString raw_text = self->mInputEditor->getWText();
|
||||
LLWString raw_text = mInputEditor->getWText();
|
||||
|
||||
// Can't trim the end, because that will cause autocompletion
|
||||
// to eat trailing spaces that might be part of a gesture.
|
||||
|
|
@ -386,8 +384,8 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userd
|
|||
// the selection will already be deleted, but we need to trim
|
||||
// off the character before
|
||||
std::string new_text = raw_text.substr(0, length-1);
|
||||
self->mInputEditor->setText( new_text );
|
||||
self->mInputEditor->setCursorToEnd();
|
||||
mInputEditor->setText( new_text );
|
||||
mInputEditor->setCursorToEnd();
|
||||
length = length - 1;
|
||||
}
|
||||
*/
|
||||
|
|
@ -407,17 +405,17 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userd
|
|||
if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
self->mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
|
||||
mInputEditor->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
|
||||
|
||||
// Select to end of line, starting from the character
|
||||
// after the last one the user typed.
|
||||
self->mInputEditor->selectNext(rest_of_match, false);
|
||||
mInputEditor->selectNext(rest_of_match, false);
|
||||
}
|
||||
else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
|
||||
{
|
||||
std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
|
||||
self->mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part
|
||||
self->mInputEditor->endOfDoc();
|
||||
mInputEditor->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part
|
||||
mInputEditor->endOfDoc();
|
||||
}
|
||||
|
||||
//llinfos << "GESTUREDEBUG " << trigger
|
||||
|
|
@ -428,7 +426,7 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke(LLTextEditor* caller, void* userd
|
|||
}
|
||||
|
||||
// static
|
||||
void LLFloaterIMNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata)
|
||||
void LLFloaterIMNearbyChat::onChatBoxFocusLost()
|
||||
{
|
||||
// stop typing animation
|
||||
gAgent.stopTyping();
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ public:
|
|||
|
||||
protected:
|
||||
static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str);
|
||||
static void onChatBoxKeystroke(LLTextEditor* caller, void* userdata);
|
||||
static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata);
|
||||
void onChatBoxKeystroke();
|
||||
void onChatBoxFocusLost();
|
||||
void onChatBoxFocusReceived();
|
||||
|
||||
void sendChat( EChatType type );
|
||||
|
|
|
|||
|
|
@ -73,8 +73,7 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id)
|
|||
mTypingTimer(),
|
||||
mTypingTimeoutTimer(),
|
||||
mPositioned(false),
|
||||
mSessionInitialized(false),
|
||||
mStartConferenceInSameFloater(false)
|
||||
mSessionInitialized(false)
|
||||
{
|
||||
mIsNearbyChat = false;
|
||||
|
||||
|
|
@ -83,8 +82,11 @@ LLFloaterIMSession::LLFloaterIMSession(const LLUUID& session_id)
|
|||
setOverlapsScreenChannel(true);
|
||||
|
||||
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
|
||||
mEnableCallbackRegistrar.add("Avatar.EnableGearItem", boost::bind(&LLFloaterIMSession::enableGearMenuItem, this, _2));
|
||||
mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&LLFloaterIMSession::GearDoToSelected, this, _2));
|
||||
mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&LLFloaterIMSession::checkGearMenuItem, this, _2));
|
||||
|
||||
setDocked(true);
|
||||
setDocked(true);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -190,6 +192,36 @@ void LLFloaterIMSession::onSendMsg( LLUICtrl* ctrl, void* userdata )
|
|||
self->setTyping(false);
|
||||
}
|
||||
|
||||
bool LLFloaterIMSession::enableGearMenuItem(const LLSD& userdata)
|
||||
{
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
selected_uuids.push_back(mOtherParticipantUUID);
|
||||
|
||||
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
|
||||
return floater_container->enableContextMenuItem(command, selected_uuids);
|
||||
}
|
||||
|
||||
void LLFloaterIMSession::GearDoToSelected(const LLSD& userdata)
|
||||
{
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
selected_uuids.push_back(mOtherParticipantUUID);
|
||||
|
||||
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
|
||||
floater_container->doToParticipants(command, selected_uuids);
|
||||
}
|
||||
|
||||
bool LLFloaterIMSession::checkGearMenuItem(const LLSD& userdata)
|
||||
{
|
||||
std::string command = userdata.asString();
|
||||
uuid_vec_t selected_uuids;
|
||||
selected_uuids.push_back(mOtherParticipantUUID);
|
||||
|
||||
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
|
||||
return floater_container->checkContextMenuItem(command, selected_uuids);
|
||||
}
|
||||
|
||||
void LLFloaterIMSession::sendMsgFromInputEditor()
|
||||
{
|
||||
if (gAgent.isGodlike()
|
||||
|
|
@ -429,8 +461,6 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con
|
|||
return;
|
||||
}
|
||||
|
||||
mStartConferenceInSameFloater = true;
|
||||
|
||||
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
|
||||
|
||||
// first check whether this is a voice session
|
||||
|
|
@ -724,7 +754,7 @@ void LLFloaterIMSession::sessionInitReplyReceived(const LLUUID& im_session_id)
|
|||
}
|
||||
|
||||
initIMFloater();
|
||||
|
||||
LLFloaterIMSessionTab::updateGearBtn();
|
||||
//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
|
||||
|
||||
//need to send delayed messages collected while waiting for session initialization
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ public:
|
|||
void setPositioned(bool b) { mPositioned = b; };
|
||||
|
||||
void onVisibilityChange(const LLSD& new_visibility);
|
||||
bool enableGearMenuItem(const LLSD& userdata);
|
||||
void GearDoToSelected(const LLSD& userdata);
|
||||
bool checkGearMenuItem(const LLSD& userdata);
|
||||
|
||||
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
|
||||
// button when voice is available
|
||||
|
|
@ -124,8 +127,6 @@ public:
|
|||
//used as a callback on receiving new IM message
|
||||
static void sRemoveTypingIndicator(const LLSD& data);
|
||||
static void onIMChicletCreated(const LLUUID& session_id);
|
||||
|
||||
bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; }
|
||||
const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;}
|
||||
|
||||
static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb);
|
||||
|
|
@ -185,8 +186,6 @@ private:
|
|||
bool mSessionInitialized;
|
||||
LLSD mQueuedMsgsForInit;
|
||||
|
||||
bool mStartConferenceInSameFloater;
|
||||
|
||||
uuid_vec_t mInvitedParticipants;
|
||||
|
||||
// connection to voice channel state change signal
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
|
|||
LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
|
||||
{
|
||||
delete mRefreshTimer;
|
||||
|
||||
// Select Nearby Chat session
|
||||
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
if (container)
|
||||
{
|
||||
container->selectConversationPair(LLUUID(NULL), true);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -177,6 +184,7 @@ void LLFloaterIMSessionTab::addToHost(const LLUUID& session_id)
|
|||
// LLFloater::mLastHostHandle = floater_container (a "future" host)
|
||||
conversp->setHost(floater_container);
|
||||
conversp->setHost(NULL);
|
||||
conversp->forceReshape();
|
||||
}
|
||||
// Added floaters share some state (like sort order) with their host
|
||||
conversp->setSortOrder(floater_container->getSortOrder());
|
||||
|
|
@ -197,6 +205,8 @@ BOOL LLFloaterIMSessionTab::postBuild()
|
|||
mTearOffBtn = getChild<LLButton>("tear_off_btn");
|
||||
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
|
||||
|
||||
mGearBtn = getChild<LLButton>("gear_btn");
|
||||
|
||||
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
|
||||
|
||||
// Add a scroller for the folder (participant) view
|
||||
|
|
@ -224,7 +234,8 @@ BOOL LLFloaterIMSessionTab::postBuild()
|
|||
|
||||
setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);
|
||||
|
||||
mSaveRect = isTornOff();
|
||||
mSaveRect = isNearbyChat()
|
||||
&& !gSavedSettings.getBOOL("NearbyChatIsNotTornOff");
|
||||
initRectControl();
|
||||
|
||||
if (isChatMultiTab())
|
||||
|
|
@ -236,14 +247,31 @@ BOOL LLFloaterIMSessionTab::postBuild()
|
|||
result = LLDockableFloater::postBuild();
|
||||
}
|
||||
|
||||
// Now ready to build the conversation and participants list
|
||||
// Create the root using an ad-hoc base item
|
||||
LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel);
|
||||
LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
|
||||
p.rect = LLRect(0, 0, getRect().getWidth(), 0);
|
||||
p.parent_panel = mParticipantListPanel;
|
||||
p.listener = base_item;
|
||||
p.view_model = &mConversationViewModel;
|
||||
p.root = NULL;
|
||||
p.use_ellipses = true;
|
||||
p.options_menu = "menu_conversation.xml";
|
||||
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
|
||||
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
|
||||
// Attach that root to the scroller
|
||||
mScroller->addChild(mConversationsRoot);
|
||||
mConversationsRoot->setScrollContainer(mScroller);
|
||||
mConversationsRoot->setFollowsAll();
|
||||
mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox);
|
||||
|
||||
buildConversationViewParticipant();
|
||||
refreshConversation();
|
||||
|
||||
|
||||
// Zero expiry time is set only once to allow initial update.
|
||||
mRefreshTimer->setTimerExpirySec(0);
|
||||
mRefreshTimer->start();
|
||||
|
||||
initBtns();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -301,10 +329,10 @@ void LLFloaterIMSessionTab::onFocusReceived()
|
|||
|
||||
LLTransientDockableFloater::onFocusReceived();
|
||||
|
||||
LLFloaterIMContainer* container = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
LLFloaterIMContainer* container = LLFloaterReg::findTypedInstance<LLFloaterIMContainer>("im_container");
|
||||
if (container)
|
||||
{
|
||||
container->selectConversationPair(mSessionID, ! getHost());
|
||||
container->selectConversationPair(mSessionID, true);
|
||||
container->showStub(! getHost());
|
||||
}
|
||||
}
|
||||
|
|
@ -384,31 +412,6 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
|
|||
return;
|
||||
}
|
||||
|
||||
// Create or recreate the root folder: this is a dummy folder (not shown) but required by the LLFolderView architecture
|
||||
// We need to redo this when rebuilding as the session id (mSessionID) *may* have changed
|
||||
if (mConversationsRoot)
|
||||
{
|
||||
// Remove the old root if any
|
||||
mScroller->removeChild(mConversationsRoot);
|
||||
}
|
||||
// Create the root using an ad-hoc base item
|
||||
LLConversationItem* base_item = new LLConversationItem(mSessionID, mConversationViewModel);
|
||||
LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
|
||||
p.rect = LLRect(0, 0, getRect().getWidth(), 0);
|
||||
p.parent_panel = mParticipantListPanel;
|
||||
p.listener = base_item;
|
||||
p.view_model = &mConversationViewModel;
|
||||
p.root = NULL;
|
||||
p.use_ellipses = true;
|
||||
p.options_menu = "menu_conversation.xml";
|
||||
mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);
|
||||
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
|
||||
// Attach that root to the scroller
|
||||
mScroller->addChild(mConversationsRoot);
|
||||
mConversationsRoot->setScrollContainer(mScroller);
|
||||
mConversationsRoot->setFollowsAll();
|
||||
mConversationsRoot->addChild(mConversationsRoot->mStatusTextBox);
|
||||
|
||||
// Create the participants widgets now
|
||||
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = item->getChildrenBegin();
|
||||
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd();
|
||||
|
|
@ -610,8 +613,8 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
|||
// prevent start conversation before its container
|
||||
LLFloaterIMContainer::getInstance();
|
||||
|
||||
bool is_torn_off = checkIfTornOff();
|
||||
if (!is_torn_off)
|
||||
bool is_not_torn_off = !checkIfTornOff();
|
||||
if (is_not_torn_off)
|
||||
{
|
||||
hideAllStandardButtons();
|
||||
}
|
||||
|
|
@ -620,7 +623,7 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
|||
|
||||
// Participant list should be visible only in torn off floaters.
|
||||
bool is_participant_list_visible =
|
||||
is_torn_off
|
||||
!is_not_torn_off
|
||||
&& gSavedSettings.getBOOL("IMShowControlPanel")
|
||||
&& !mIsP2PChat;
|
||||
|
||||
|
|
@ -628,27 +631,42 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar()
|
|||
|
||||
// Display collapse image (<<) if the floater is hosted
|
||||
// or if it is torn off but has an open control panel.
|
||||
bool is_expanded = !is_torn_off || is_participant_list_visible;
|
||||
bool is_expanded = is_not_torn_off || is_participant_list_visible;
|
||||
mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon"));
|
||||
mExpandCollapseBtn->setToolTip(
|
||||
is_not_torn_off?
|
||||
getString("expcol_button_not_tearoff_tooltip") :
|
||||
(is_expanded?
|
||||
getString("expcol_button_tearoff_and_expanded_tooltip") :
|
||||
getString("expcol_button_tearoff_and_collapsed_tooltip")));
|
||||
|
||||
// toggle floater's drag handle and title visibility
|
||||
if (mDragHandle)
|
||||
{
|
||||
mDragHandle->setTitleVisible(is_torn_off);
|
||||
mDragHandle->setTitleVisible(!is_not_torn_off);
|
||||
}
|
||||
|
||||
// The button (>>) should be disabled for torn off P2P conversations.
|
||||
mExpandCollapseBtn->setEnabled(!is_torn_off || !mIsP2PChat);
|
||||
mExpandCollapseBtn->setEnabled(is_not_torn_off || !mIsP2PChat);
|
||||
|
||||
mTearOffBtn->setImageOverlay(getString(is_torn_off? "return_icon" : "tear_off_icon"));
|
||||
mTearOffBtn->setToolTip(getString(!is_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window"));
|
||||
mTearOffBtn->setImageOverlay(getString(is_not_torn_off? "tear_off_icon" : "return_icon"));
|
||||
mTearOffBtn->setToolTip(getString(is_not_torn_off? "tooltip_to_separate_window" : "tooltip_to_main_window"));
|
||||
|
||||
mCloseBtn->setVisible(!is_torn_off && !mIsNearbyChat);
|
||||
mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat);
|
||||
|
||||
enableDisableCallBtn();
|
||||
|
||||
showTranslationCheckbox();
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::forceReshape()
|
||||
{
|
||||
LLRect floater_rect = getRect();
|
||||
reshape(llmax(floater_rect.getWidth(), this->getMinWidth()),
|
||||
llmax(floater_rect.getHeight(), this->getMinHeight()),
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterIMSessionTab::reshapeChatHistory()
|
||||
{
|
||||
|
|
@ -735,19 +753,6 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
|
|||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterIMSessionTab::onClose(bool app_quitting)
|
||||
{
|
||||
// Always suppress the IM from the conversations list on close if present for any reason
|
||||
if (LLFloaterIMSessionTab::isChatMultiTab())
|
||||
{
|
||||
LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance();
|
||||
if (im_box)
|
||||
{
|
||||
im_box->removeConversationListItem(mKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::onTearOffClicked()
|
||||
{
|
||||
|
|
@ -755,7 +760,58 @@ void LLFloaterIMSessionTab::onTearOffClicked()
|
|||
mSaveRect = isTornOff();
|
||||
initRectControl();
|
||||
LLFloater::onClickTearOff(this);
|
||||
if (isTornOff())
|
||||
{
|
||||
forceReshape();
|
||||
}
|
||||
refreshConversation();
|
||||
updateGearBtn();
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::updateGearBtn()
|
||||
{
|
||||
|
||||
BOOL prevVisibility = mGearBtn->getVisible();
|
||||
mGearBtn->setVisible(checkIfTornOff() && mIsP2PChat);
|
||||
|
||||
|
||||
// Move buttons if Gear button changed visibility
|
||||
if(prevVisibility != mGearBtn->getVisible())
|
||||
{
|
||||
LLRect gear_btn_rect = mGearBtn->getRect();
|
||||
LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect();
|
||||
LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect();
|
||||
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
|
||||
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
|
||||
if(mGearBtn->getVisible())
|
||||
{
|
||||
// Move buttons to the right to give space for Gear button
|
||||
add_btn_rect.translate(right_shift,0);
|
||||
call_btn_rect.translate(right_shift,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_btn_rect.translate(-right_shift,0);
|
||||
call_btn_rect.translate(-right_shift,0);
|
||||
}
|
||||
getChild<LLButton>("add_btn")->setRect(add_btn_rect);
|
||||
getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterIMSessionTab::initBtns()
|
||||
{
|
||||
LLRect gear_btn_rect = mGearBtn->getRect();
|
||||
LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect();
|
||||
LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect();
|
||||
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
|
||||
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
|
||||
|
||||
add_btn_rect.translate(-right_shift,0);
|
||||
call_btn_rect.translate(-right_shift,0);
|
||||
|
||||
getChild<LLButton>("add_btn")->setRect(add_btn_rect);
|
||||
getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ public:
|
|||
|
||||
// LLFloater overrides
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
/*virtual*/ void onClose(bool app_quitting);
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void setVisible(BOOL visible);
|
||||
|
|
@ -92,10 +91,13 @@ public:
|
|||
|
||||
void setSortOrder(const LLConversationSort& order);
|
||||
virtual void onTearOffClicked();
|
||||
|
||||
void updateGearBtn();
|
||||
void initBtns();
|
||||
virtual void updateMessages() {}
|
||||
LLConversationItem* getCurSelectedViewModelItem();
|
||||
|
||||
void forceReshape();
|
||||
|
||||
protected:
|
||||
|
||||
// callback for click on any items of the visual states menu
|
||||
|
|
@ -157,6 +159,8 @@ protected:
|
|||
LLButton* mExpandCollapseBtn;
|
||||
LLButton* mTearOffBtn;
|
||||
LLButton* mCloseBtn;
|
||||
LLButton* mGearBtn;
|
||||
|
||||
|
||||
private:
|
||||
// Handling selection and contextual menu
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@
|
|||
/// LLOutboxNotification class
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
LLNotificationsUI::LLOutboxNotification::LLOutboxNotification()
|
||||
: LLSystemNotificationHandler("Outbox", "outbox")
|
||||
{
|
||||
}
|
||||
|
||||
bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify)
|
||||
{
|
||||
LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox");
|
||||
|
|
@ -60,10 +65,10 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotifi
|
|||
|
||||
void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p)
|
||||
{
|
||||
LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
|
||||
if (sys_handler)
|
||||
LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
|
||||
if (notification_handler)
|
||||
{
|
||||
sys_handler->onDelete(p);
|
||||
notification_handler->onDelete(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -524,9 +529,9 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)
|
|||
|
||||
void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification)
|
||||
{
|
||||
LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
|
||||
llassert(sys_handler);
|
||||
LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
|
||||
llassert(notification_handler);
|
||||
|
||||
sys_handler->processNotification(notification);
|
||||
notification_handler->processNotification(notification);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,11 +232,9 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)
|
|||
case LL_HUD_EFFECT_LOOKAT:
|
||||
hud_objectp = new LLHUDEffectLookAt(type);
|
||||
break;
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
case LL_HUD_EFFECT_VOICE_VISUALIZER:
|
||||
hud_objectp = new LLVoiceVisualizer(type);
|
||||
break;
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
case LL_HUD_EFFECT_POINTAT:
|
||||
hud_objectp = new LLHUDEffectPointAt(type);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@
|
|||
#include "lldrawpool.h" // TODO: eliminate, unused below
|
||||
#include <list>
|
||||
|
||||
#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot
|
||||
|
||||
class LLViewerCamera;
|
||||
class LLFontGL;
|
||||
class LLFace;
|
||||
|
|
@ -96,9 +94,7 @@ public:
|
|||
LL_HUD_EFFECT_EDIT,
|
||||
LL_HUD_EFFECT_LOOKAT,
|
||||
LL_HUD_EFFECT_POINTAT,
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
LL_HUD_NAME_TAG,
|
||||
LL_HUD_EFFECT_BLOB
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ using namespace LLNotificationsUI;
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
LLIMHandler::LLIMHandler()
|
||||
: LLSysHandler("IM Notifications", "notifytoast")
|
||||
: LLCommunicationNotificationHandler("IM Notifications", "notifytoast")
|
||||
{
|
||||
// Getting a Channel for our notifications
|
||||
mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle();
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ void on_new_message(const LLSD& msg)
|
|||
LLUUID session_id = msg["session_id"].asUUID();
|
||||
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
|
||||
|
||||
// determine action for this session
|
||||
// determine action for this session
|
||||
|
||||
if (session_id.isNull())
|
||||
{
|
||||
|
|
@ -148,8 +148,8 @@ void on_new_message(const LLSD& msg)
|
|||
action = gSavedSettings.getString("NotificationGroupChatOptions");
|
||||
}
|
||||
|
||||
// do not show notification in "do not disturb" mode or it goes from agent
|
||||
if (gAgent.isDoNotDisturb() || gAgent.getID() == participant_id)
|
||||
// do not show notification which goes from agent
|
||||
if (gAgent.getID() == participant_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -160,67 +160,69 @@ void on_new_message(const LLSD& msg)
|
|||
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
|
||||
|
||||
//session floater not focused (visible or not)
|
||||
bool sessionFloaterNotFocused = session_floater && !session_floater->hasFocus();
|
||||
bool session_floater_not_focused = session_floater && !session_floater->hasFocus();
|
||||
|
||||
//conv. floater is closed
|
||||
bool conversation_floater_is_closed =
|
||||
!( im_box
|
||||
&& im_box->isInVisibleChain()
|
||||
&& !im_box->isMinimized());
|
||||
|
||||
//conversation floater not focused (visible or not)
|
||||
bool conversationFloaterNotFocused = im_box && !im_box->hasFocus();
|
||||
bool conversation_floater_not_focused =
|
||||
conversation_floater_is_closed || !im_box->hasFocus();
|
||||
|
||||
if ("toast" == action)
|
||||
{
|
||||
// Skip toasting if we have open window of IM with this session id
|
||||
if (
|
||||
session_floater
|
||||
// Skip toasting and flashing if we have open window of IM with this session id
|
||||
if (session_floater
|
||||
&& session_floater->isInVisibleChain()
|
||||
&& session_floater->hasFocus()
|
||||
&& !session_floater->isMinimized()
|
||||
&& !(session_floater->getHost()
|
||||
&& session_floater->getHost()->isMinimized())
|
||||
&& !(session_floater->getHost() && session_floater->getHost()->isMinimized())
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip toasting for system messages and for nearby chat
|
||||
if (participant_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//User is not focused on conversation containing the message
|
||||
if(sessionFloaterNotFocused)
|
||||
if(session_floater_not_focused)
|
||||
{
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
|
||||
//The conversation floater isn't focused/open
|
||||
if(conversationFloaterNotFocused)
|
||||
if(conversation_floater_not_focused)
|
||||
{
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
|
||||
//Show IM toasts (upper right toasts)
|
||||
if(session_id.notNull())
|
||||
// Skip toasting for system messages and for nearby chat
|
||||
if(session_id.notNull() && participant_id.notNull())
|
||||
{
|
||||
LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if ("flash" == action)
|
||||
{
|
||||
//User is not focused on conversation containing the message
|
||||
if(sessionFloaterNotFocused && conversationFloaterNotFocused)
|
||||
{
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
}
|
||||
//conversation floater is open but a different conversation is focused
|
||||
else if(sessionFloaterNotFocused)
|
||||
{
|
||||
if (conversation_floater_not_focused)
|
||||
{
|
||||
if(session_floater_not_focused)
|
||||
{
|
||||
//User is not focused on conversation containing the message
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
}
|
||||
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
}
|
||||
}
|
||||
|
||||
else if("openconversations" == action)
|
||||
{
|
||||
//User is not focused on conversation containing the message
|
||||
if(sessionFloaterNotFocused)
|
||||
if(session_floater_not_focused)
|
||||
{
|
||||
//Flash line item
|
||||
im_box->flashConversationItemWidget(session_id, true);
|
||||
|
|
@ -863,7 +865,8 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
|
|||
|
||||
bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
|
||||
{
|
||||
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
|
||||
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages")
|
||||
&& gSavedSettings.getBOOL("KeepConversationLogTranscripts"))
|
||||
{
|
||||
std::string from_name = from;
|
||||
|
||||
|
|
@ -960,7 +963,7 @@ const std::string LLIMModel::getName(const LLUUID& session_id) const
|
|||
{
|
||||
LLIMSession* session = findIMSession(session_id);
|
||||
|
||||
if (!session)
|
||||
if (!session)
|
||||
{
|
||||
llwarns << "session " << session_id << "does not exist " << llendl;
|
||||
return LLTrans::getString("no_session_message");
|
||||
|
|
@ -2487,17 +2490,24 @@ void LLIMMgr::addMessage(
|
|||
new_session_id = computeSessionID(dialog, other_participant_id);
|
||||
}
|
||||
|
||||
// Open conversation log if offline messages are present
|
||||
// Open conversation log if offline messages are present and user allows a Call Log
|
||||
if (is_offline_msg)
|
||||
{
|
||||
LLFloaterConversationLog* floater_log =
|
||||
LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation");
|
||||
if (floater_log && !(floater_log->isFrontmost()))
|
||||
{
|
||||
if (gSavedSettings.getBOOL("KeepConversationLogTranscripts"))
|
||||
{
|
||||
floater_log->openFloater();
|
||||
floater_log->setFrontmost(TRUE);
|
||||
LLFloaterConversationLog* floater_log =
|
||||
LLFloaterReg::getTypedInstance<LLFloaterConversationLog>("conversation");
|
||||
if (floater_log && !(floater_log->isFrontmost()))
|
||||
{
|
||||
floater_log->openFloater();
|
||||
floater_log->setFrontmost(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gToolBarView->flashCommand(LLCommandId("chat"), true);
|
||||
}
|
||||
}
|
||||
|
||||
//*NOTE session_name is empty in case of incoming P2P sessions
|
||||
std::string fixed_session_name = from;
|
||||
|
|
@ -2552,7 +2562,7 @@ void LLIMMgr::addMessage(
|
|||
}
|
||||
|
||||
//Play sound for new conversations
|
||||
if(gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE)
|
||||
if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE))
|
||||
{
|
||||
make_ui_sound("UISndNewIncomingIMSession");
|
||||
}
|
||||
|
|
@ -2708,12 +2718,13 @@ LLUUID LLIMMgr::addSession(
|
|||
{
|
||||
LLFloaterIMSession* im_floater = LLFloaterIMSession::findInstance(floater_id);
|
||||
|
||||
if (im_floater && im_floater->getStartConferenceInSameFloater())
|
||||
if (im_floater)
|
||||
{
|
||||
// The IM floater should be initialized with a new session_id
|
||||
// so that it is found by that id when creating a chiclet in LLFloaterIMSession::onIMChicletCreated,
|
||||
// and a new floater is not created.
|
||||
im_floater->initIMSession(session_id);
|
||||
im_floater->reloadMessages();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "llnotificationhandler.h"
|
||||
|
||||
#include "llagentcamera.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llprogressview.h"
|
||||
#include "lltoastnotifypanel.h"
|
||||
|
|
@ -41,7 +42,7 @@ using namespace LLNotificationsUI;
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal)
|
||||
: LLSysHandler(name, notification_type),
|
||||
: LLSystemNotificationHandler(name, notification_type),
|
||||
mIsModal(is_modal)
|
||||
{
|
||||
LLScreenChannelBase::Params p;
|
||||
|
|
@ -123,3 +124,28 @@ void LLAlertHandler::onChange( LLNotificationPtr notification )
|
|||
if(channel)
|
||||
channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
LLViewerAlertHandler::LLViewerAlertHandler(const std::string& name, const std::string& notification_type)
|
||||
: LLSystemNotificationHandler(name, notification_type)
|
||||
{
|
||||
}
|
||||
|
||||
bool LLViewerAlertHandler::processNotification(const LLNotificationPtr& p)
|
||||
{
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
LL_INFOS("LLViewerAlertHandler") << "Alert: " << p->getName() << LL_ENDL;
|
||||
}
|
||||
|
||||
// If we're in mouselook, the mouse is hidden and so the user can't click
|
||||
// the dialog buttons. In that case, change to First Person instead.
|
||||
if( gAgentCamera.cameraMouselook() )
|
||||
{
|
||||
gAgentCamera.changeCameraToDefault();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ using namespace LLNotificationsUI;
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
LLGroupHandler::LLGroupHandler()
|
||||
: LLSysHandler("Group Notifications", "groupnotify")
|
||||
: LLCommunicationNotificationHandler("Group Notifications", "groupnotify")
|
||||
{
|
||||
// Getting a Channel for our notifications
|
||||
LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#ifndef LL_LLNOTIFICATIONHANDLER_H
|
||||
#define LL_LLNOTIFICATIONHANDLER_H
|
||||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#include "llwindow.h"
|
||||
|
||||
|
|
@ -86,22 +87,37 @@ protected:
|
|||
/**
|
||||
* Handler for system notifications.
|
||||
*/
|
||||
class LLSysHandler : public LLEventHandler, public LLNotificationChannel
|
||||
class LLNotificationHandler : public LLEventHandler, public LLNotificationChannel
|
||||
{
|
||||
public:
|
||||
LLSysHandler(const std::string& name, const std::string& notification_type);
|
||||
virtual ~LLSysHandler() {};
|
||||
LLNotificationHandler(const std::string& name, const std::string& notification_type, const std::string& parentName);
|
||||
virtual ~LLNotificationHandler() {};
|
||||
|
||||
// base interface functions
|
||||
/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());}
|
||||
virtual void onAdd(LLNotificationPtr p) { processNotification(p); }
|
||||
virtual void onChange(LLNotificationPtr p) { processNotification(p); }
|
||||
virtual void onLoad(LLNotificationPtr p) { processNotification(p); }
|
||||
virtual void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());}
|
||||
|
||||
virtual bool processNotification(const LLNotificationPtr& notify)=0;
|
||||
virtual bool processNotification(const LLNotificationPtr& notify) = 0;
|
||||
};
|
||||
|
||||
class LLSystemNotificationHandler : public LLNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLSystemNotificationHandler(const std::string& name, const std::string& notification_type);
|
||||
virtual ~LLSystemNotificationHandler() {};
|
||||
};
|
||||
|
||||
class LLCommunicationNotificationHandler : public LLNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLCommunicationNotificationHandler(const std::string& name, const std::string& notification_type);
|
||||
virtual ~LLCommunicationNotificationHandler() {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for chat message notifications.
|
||||
* Handler for chat message notifications.
|
||||
*/
|
||||
class LLChatHandler : public LLEventHandler
|
||||
{
|
||||
|
|
@ -115,67 +131,62 @@ public:
|
|||
* Handler for IM notifications.
|
||||
* It manages life time of IMs, group messages.
|
||||
*/
|
||||
class LLIMHandler : public LLSysHandler
|
||||
class LLIMHandler : public LLCommunicationNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLIMHandler();
|
||||
virtual ~LLIMHandler();
|
||||
bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
bool processNotification(const LLNotificationPtr& p);
|
||||
/*virtual*/ void initChannel();
|
||||
virtual void initChannel();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for system informational notices.
|
||||
* It manages life time of tip notices.
|
||||
*/
|
||||
class LLTipHandler : public LLSysHandler
|
||||
class LLTipHandler : public LLSystemNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLTipHandler();
|
||||
virtual ~LLTipHandler();
|
||||
|
||||
// base interface functions
|
||||
/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ bool processNotification(const LLNotificationPtr& p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
/*virtual*/ void initChannel();
|
||||
virtual void initChannel();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for system informational notices.
|
||||
* It manages life time of script notices.
|
||||
*/
|
||||
class LLScriptHandler : public LLSysHandler
|
||||
class LLScriptHandler : public LLSystemNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLScriptHandler();
|
||||
virtual ~LLScriptHandler();
|
||||
|
||||
/*virtual*/ void onDelete(LLNotificationPtr p);
|
||||
// base interface functions
|
||||
/*virtual*/ bool processNotification(const LLNotificationPtr& p);
|
||||
virtual void onDelete(LLNotificationPtr p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
/*virtual*/ void onDeleteToast(LLToast* toast);
|
||||
/*virtual*/ void initChannel();
|
||||
virtual void onDeleteToast(LLToast* toast);
|
||||
virtual void initChannel();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for group system notices.
|
||||
*/
|
||||
class LLGroupHandler : public LLSysHandler
|
||||
class LLGroupHandler : public LLCommunicationNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLGroupHandler();
|
||||
virtual ~LLGroupHandler();
|
||||
|
||||
// base interface functions
|
||||
/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ bool processNotification(const LLNotificationPtr& p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void initChannel();
|
||||
|
|
@ -184,15 +195,14 @@ protected:
|
|||
/**
|
||||
* Handler for alert system notices.
|
||||
*/
|
||||
class LLAlertHandler : public LLSysHandler
|
||||
class LLAlertHandler : public LLSystemNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal);
|
||||
virtual ~LLAlertHandler();
|
||||
|
||||
/*virtual*/ void onChange(LLNotificationPtr p);
|
||||
/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ bool processNotification(const LLNotificationPtr& p);
|
||||
virtual void onChange(LLNotificationPtr p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void initChannel();
|
||||
|
|
@ -200,67 +210,85 @@ protected:
|
|||
bool mIsModal;
|
||||
};
|
||||
|
||||
class LLViewerAlertHandler : public LLSystemNotificationHandler
|
||||
{
|
||||
LOG_CLASS(LLViewerAlertHandler);
|
||||
public:
|
||||
LLViewerAlertHandler(const std::string& name, const std::string& notification_type);
|
||||
virtual ~LLViewerAlertHandler() {};
|
||||
|
||||
virtual void onDelete(LLNotificationPtr p) {};
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void initChannel() {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for offers notices.
|
||||
* It manages life time of offer notices.
|
||||
*/
|
||||
class LLOfferHandler : public LLSysHandler
|
||||
class LLOfferHandler : public LLCommunicationNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLOfferHandler();
|
||||
virtual ~LLOfferHandler();
|
||||
|
||||
// base interface functions
|
||||
/*virtual*/ void onChange(LLNotificationPtr p);
|
||||
/*virtual*/ void onDelete(LLNotificationPtr notification);
|
||||
/*virtual*/ bool processNotification(const LLNotificationPtr& p);
|
||||
virtual void onChange(LLNotificationPtr p);
|
||||
virtual void onDelete(LLNotificationPtr notification);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
/*virtual*/ void initChannel();
|
||||
virtual void initChannel();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for UI hints.
|
||||
*/
|
||||
class LLHintHandler : public LLNotificationChannel
|
||||
class LLHintHandler : public LLSystemNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint"))
|
||||
{}
|
||||
LLHintHandler();
|
||||
virtual ~LLHintHandler() {}
|
||||
|
||||
/*virtual*/ void onAdd(LLNotificationPtr p);
|
||||
/*virtual*/ void onLoad(LLNotificationPtr p);
|
||||
/*virtual*/ void onDelete(LLNotificationPtr p);
|
||||
virtual void onAdd(LLNotificationPtr p);
|
||||
virtual void onLoad(LLNotificationPtr p);
|
||||
virtual void onDelete(LLNotificationPtr p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void initChannel() {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for browser notifications
|
||||
*/
|
||||
class LLBrowserNotification : public LLNotificationChannel
|
||||
class LLBrowserNotification : public LLSystemNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLBrowserNotification()
|
||||
: LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser"))
|
||||
{}
|
||||
/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); }
|
||||
bool processNotification(const LLNotificationPtr& p);
|
||||
LLBrowserNotification();
|
||||
virtual ~LLBrowserNotification() {}
|
||||
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void initChannel() {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for outbox notifications
|
||||
*/
|
||||
class LLOutboxNotification : public LLNotificationChannel
|
||||
class LLOutboxNotification : public LLSystemNotificationHandler
|
||||
{
|
||||
public:
|
||||
LLOutboxNotification()
|
||||
: LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox"))
|
||||
{}
|
||||
/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); }
|
||||
/*virtual*/ void onChange(LLNotificationPtr p) { }
|
||||
/*virtual*/ void onDelete(LLNotificationPtr p);
|
||||
bool processNotification(const LLNotificationPtr& p);
|
||||
LLOutboxNotification();
|
||||
virtual ~LLOutboxNotification() {};
|
||||
virtual void onChange(LLNotificationPtr p) { }
|
||||
virtual void onDelete(LLNotificationPtr p);
|
||||
virtual bool processNotification(const LLNotificationPtr& p);
|
||||
|
||||
protected:
|
||||
virtual void initChannel() {};
|
||||
};
|
||||
|
||||
class LLHandlerUtil
|
||||
|
|
|
|||
|
|
@ -41,8 +41,16 @@
|
|||
|
||||
using namespace LLNotificationsUI;
|
||||
|
||||
LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type)
|
||||
: LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type))
|
||||
LLNotificationHandler::LLNotificationHandler(const std::string& name, const std::string& notification_type, const std::string& parentName)
|
||||
: LLNotificationChannel(name, parentName, LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type))
|
||||
{}
|
||||
|
||||
LLSystemNotificationHandler::LLSystemNotificationHandler(const std::string& name, const std::string& notification_type)
|
||||
: LLNotificationHandler(name, notification_type, "System")
|
||||
{}
|
||||
|
||||
LLCommunicationNotificationHandler::LLCommunicationNotificationHandler(const std::string& name, const std::string& notification_type)
|
||||
: LLNotificationHandler(name, notification_type, "Communication")
|
||||
{}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -33,6 +33,27 @@
|
|||
|
||||
using namespace LLNotificationsUI;
|
||||
|
||||
void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); }
|
||||
void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); }
|
||||
void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); }
|
||||
LLHintHandler::LLHintHandler()
|
||||
: LLSystemNotificationHandler("Hints", "hint")
|
||||
{
|
||||
}
|
||||
|
||||
void LLHintHandler::onAdd(LLNotificationPtr p)
|
||||
{
|
||||
LLHints::show(p);
|
||||
}
|
||||
|
||||
void LLHintHandler::onLoad(LLNotificationPtr p)
|
||||
{
|
||||
LLHints::show(p);
|
||||
}
|
||||
|
||||
void LLHintHandler::onDelete(LLNotificationPtr p)
|
||||
{
|
||||
LLHints::hide(p);
|
||||
}
|
||||
|
||||
bool LLHintHandler::processNotification(const LLNotificationPtr& p)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ using namespace LLNotificationsUI;
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
LLOfferHandler::LLOfferHandler()
|
||||
: LLSysHandler("Offer", "offer")
|
||||
: LLCommunicationNotificationHandler("Offer", "offer")
|
||||
{
|
||||
// Getting a Channel for our notifications
|
||||
LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ using namespace LLNotificationsUI;
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
LLScriptHandler::LLScriptHandler()
|
||||
: LLSysHandler("Notifications", "notify")
|
||||
: LLSystemNotificationHandler("Notifications", "notify")
|
||||
{
|
||||
// Getting a Channel for our notifications
|
||||
LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();
|
||||
|
|
|
|||
|
|
@ -25,207 +25,143 @@
|
|||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h" // must be first include
|
||||
|
||||
#include "llnotificationstorage.h"
|
||||
|
||||
#include "llxmlnode.h" // for linux compilers
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "llchannelmanager.h"
|
||||
#include "llscreenchannel.h"
|
||||
#include "llscriptfloater.h"
|
||||
#include "llerror.h"
|
||||
#include "llfile.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llpointer.h"
|
||||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llviewermessage.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LLResponderRegistry
|
||||
class LLResponderRegistry : public LLSingleton<LLResponderRegistry>
|
||||
{
|
||||
public:
|
||||
|
||||
static void registerResponders();
|
||||
|
||||
static LLNotificationResponderInterface* createResponder(const std::string& notification_name, const LLSD& params);
|
||||
|
||||
LLResponderRegistry();
|
||||
~LLResponderRegistry();
|
||||
|
||||
LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
template<typename RESPONDER_TYPE>
|
||||
static LLNotificationResponderInterface* create(const LLSD& params)
|
||||
{
|
||||
RESPONDER_TYPE* responder = new RESPONDER_TYPE();
|
||||
responder->fromLLSD(params);
|
||||
return responder;
|
||||
}
|
||||
|
||||
template<typename RESPONDER_TYPE> static LLNotificationResponderInterface* create(const LLSD& pParams);
|
||||
|
||||
typedef boost::function<LLNotificationResponderInterface* (const LLSD& params)> responder_constructor_t;
|
||||
|
||||
static void add(const std::string& notification_name, const responder_constructor_t& ctr);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void add(const std::string& pNotificationName, const responder_constructor_t& pConstructor);
|
||||
|
||||
typedef std::map<std::string, responder_constructor_t> build_map_t;
|
||||
|
||||
static build_map_t sBuildMap;
|
||||
build_map_t mBuildMap;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLPersistentNotificationStorage::LLPersistentNotificationStorage()
|
||||
LLNotificationStorage::LLNotificationStorage(std::string pFileName)
|
||||
: mFileName(pFileName)
|
||||
{
|
||||
mFileName = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" );
|
||||
}
|
||||
|
||||
bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)
|
||||
LLNotificationStorage::~LLNotificationStorage()
|
||||
{
|
||||
// we ignore "load" messages, but rewrite the persistence file on any other
|
||||
const std::string sigtype = payload["sigtype"].asString();
|
||||
if ("load" != sigtype)
|
||||
{
|
||||
saveNotifications();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications");
|
||||
|
||||
void LLPersistentNotificationStorage::saveNotifications()
|
||||
bool LLNotificationStorage::writeNotifications(const LLSD& pNotificationData) const
|
||||
{
|
||||
LLFastTimer _(FTM_SAVE_NOTIFICATIONS);
|
||||
|
||||
llofstream notify_file(mFileName.c_str());
|
||||
if (!notify_file.is_open())
|
||||
llofstream notifyFile(mFileName.c_str());
|
||||
bool didFileOpen = notifyFile.is_open();
|
||||
|
||||
if (!didFileOpen)
|
||||
{
|
||||
llwarns << "Failed to open " << mFileName << llendl;
|
||||
return;
|
||||
LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
|
||||
formatter->format(pNotificationData, notifyFile, LLSDFormatter::OPTIONS_PRETTY);
|
||||
}
|
||||
|
||||
LLSD output;
|
||||
LLSD& data = output["data"];
|
||||
return didFileOpen;
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent"));
|
||||
if (!history_channel)
|
||||
bool LLNotificationStorage::readNotifications(LLSD& pNotificationData) const
|
||||
{
|
||||
bool didFileRead;
|
||||
|
||||
pNotificationData.clear();
|
||||
|
||||
llifstream notifyFile(mFileName.c_str());
|
||||
didFileRead = notifyFile.is_open();
|
||||
if (!didFileRead)
|
||||
{
|
||||
return;
|
||||
LL_WARNS("LLNotificationStorage") << "Failed to open file '" << mFileName << "'" << LL_ENDL;
|
||||
}
|
||||
|
||||
for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory();
|
||||
it != end_it;
|
||||
++it)
|
||||
else
|
||||
{
|
||||
LLNotificationPtr notification = *it;
|
||||
|
||||
// After a notification was placed in Persist channel, it can become
|
||||
// responded, expired or canceled - in this case we are should not save it
|
||||
if(notification->isRespondedTo() || notification->isCancelled()
|
||||
|| notification->isExpired())
|
||||
LLPointer<LLSDParser> parser = new LLSDXMLParser();
|
||||
didFileRead = (parser->parse(notifyFile, pNotificationData, LLSDSerialize::SIZE_UNLIMITED) >= 0);
|
||||
if (!didFileRead)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
data.append(notification->asLLSD());
|
||||
}
|
||||
|
||||
LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
|
||||
formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications");
|
||||
|
||||
void LLPersistentNotificationStorage::loadNotifications()
|
||||
{
|
||||
LLFastTimer _(FTM_LOAD_NOTIFICATIONS);
|
||||
LLResponderRegistry::registerResponders();
|
||||
|
||||
LLNotifications::instance().getChannel("Persistent")->
|
||||
connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
|
||||
|
||||
llifstream notify_file(mFileName.c_str());
|
||||
if (!notify_file.is_open())
|
||||
{
|
||||
llwarns << "Failed to open " << mFileName << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD input;
|
||||
LLPointer<LLSDParser> parser = new LLSDXMLParser();
|
||||
if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0)
|
||||
{
|
||||
llwarns << "Failed to parse open notifications" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.isUndefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD& data = input["data"];
|
||||
if (data.isUndefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace LLNotificationsUI;
|
||||
LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
|
||||
LLNotifications& instance = LLNotifications::instance();
|
||||
|
||||
for (LLSD::array_const_iterator notification_it = data.beginArray();
|
||||
notification_it != data.endArray();
|
||||
++notification_it)
|
||||
{
|
||||
LLSD notification_params = *notification_it;
|
||||
LLNotificationPtr notification(new LLNotification(notification_params));
|
||||
|
||||
LLNotificationResponderPtr responder(LLResponderRegistry::
|
||||
createResponder(notification_params["name"], notification_params["responder"]));
|
||||
notification->setResponseFunctor(responder);
|
||||
|
||||
instance.add(notification);
|
||||
|
||||
// hide script floaters so they don't confuse the user and don't overlap startup toast
|
||||
LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false);
|
||||
|
||||
if(notification_channel)
|
||||
{
|
||||
// hide saved toasts so they don't confuse the user
|
||||
notification_channel->hideToast(notification->getID());
|
||||
LL_WARNS("LLNotificationStorage") << "Failed to parse open notifications from file '" << mFileName
|
||||
<< "'" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
return didFileRead;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLResponderRegistry::build_map_t LLResponderRegistry::sBuildMap;
|
||||
|
||||
void LLResponderRegistry::registerResponders()
|
||||
LLNotificationResponderInterface* LLNotificationStorage::createResponder(const std::string& pNotificationName, const LLSD& pParams) const
|
||||
{
|
||||
sBuildMap.clear();
|
||||
return LLResponderRegistry::getInstance()->createResponder(pNotificationName, pParams);
|
||||
}
|
||||
|
||||
LLResponderRegistry::LLResponderRegistry()
|
||||
: LLSingleton<LLResponderRegistry>()
|
||||
, mBuildMap()
|
||||
{
|
||||
add("ObjectGiveItem", &create<LLOfferInfo>);
|
||||
add("OwnObjectGiveItem", &create<LLOfferInfo>);
|
||||
add("UserGiveItem", &create<LLOfferInfo>);
|
||||
|
||||
add("TeleportOffered", &create<LLOfferInfo>);
|
||||
add("TeleportOffered_MaturityExceeded", &create<LLOfferInfo>);
|
||||
|
||||
add("OfferFriendship", &create<LLOfferInfo>);
|
||||
}
|
||||
|
||||
LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& notification_name, const LLSD& params)
|
||||
LLResponderRegistry::~LLResponderRegistry()
|
||||
{
|
||||
build_map_t::const_iterator it = sBuildMap.find(notification_name);
|
||||
if(sBuildMap.end() == it)
|
||||
}
|
||||
|
||||
LLNotificationResponderInterface* LLResponderRegistry::createResponder(const std::string& pNotificationName, const LLSD& pParams)
|
||||
{
|
||||
build_map_t::const_iterator it = mBuildMap.find(pNotificationName);
|
||||
if(mBuildMap.end() == it)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
responder_constructor_t ctr = it->second;
|
||||
return ctr(params);
|
||||
return ctr(pParams);
|
||||
}
|
||||
|
||||
void LLResponderRegistry::add(const std::string& notification_name, const responder_constructor_t& ctr)
|
||||
template<typename RESPONDER_TYPE> LLNotificationResponderInterface* LLResponderRegistry::create(const LLSD& pParams)
|
||||
{
|
||||
if(sBuildMap.find(notification_name) != sBuildMap.end())
|
||||
{
|
||||
llwarns << "Responder is already registered : " << notification_name << llendl;
|
||||
llassert(!"Responder already registered");
|
||||
}
|
||||
sBuildMap[notification_name] = ctr;
|
||||
RESPONDER_TYPE* responder = new RESPONDER_TYPE();
|
||||
responder->fromLLSD(pParams);
|
||||
return responder;
|
||||
}
|
||||
|
||||
void LLResponderRegistry::add(const std::string& pNotificationName, const responder_constructor_t& pConstructor)
|
||||
{
|
||||
if (mBuildMap.find(pNotificationName) != mBuildMap.end())
|
||||
{
|
||||
LL_ERRS("LLResponderRegistry") << "Responder is already registered : " << pNotificationName << LL_ENDL;
|
||||
}
|
||||
mBuildMap.insert(std::make_pair<std::string, responder_constructor_t>(pNotificationName, pConstructor));
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
|||
|
|
@ -27,32 +27,27 @@
|
|||
#ifndef LL_NOTIFICATIONSTORAGE_H
|
||||
#define LL_NOTIFICATIONSTORAGE_H
|
||||
|
||||
#include "llnotifications.h"
|
||||
#include <string>
|
||||
|
||||
// Class that saves not responded(unread) notifications.
|
||||
// Unread notifications are saved in open_notifications.xml in SL account folder
|
||||
//
|
||||
// Notifications that should be saved(if unread) are marked with persist="true" in notifications.xml
|
||||
// Notifications using functor responders are saved automatically (see llviewermessage.cpp
|
||||
// lure_callback_reg for example).
|
||||
// Notifications using object responders(LLOfferInfo) need additional tuning. Responder object should
|
||||
// be a) serializable(implement LLNotificationResponderInterface),
|
||||
// b) registered with LLResponderRegistry (found in llnotificationstorage.cpp).
|
||||
class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>
|
||||
#include "llerror.h"
|
||||
|
||||
class LLNotificationResponderInterface;
|
||||
class LLSD;
|
||||
|
||||
class LLNotificationStorage
|
||||
{
|
||||
LOG_CLASS(LLPersistentNotificationStorage);
|
||||
LOG_CLASS(LLNotificationStorage);
|
||||
public:
|
||||
LLNotificationStorage(std::string pFileName);
|
||||
~LLNotificationStorage();
|
||||
|
||||
LLPersistentNotificationStorage();
|
||||
protected:
|
||||
bool writeNotifications(const LLSD& pNotificationData) const;
|
||||
bool readNotifications(LLSD& pNotificationData) const;
|
||||
|
||||
void saveNotifications();
|
||||
|
||||
void loadNotifications();
|
||||
LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const;
|
||||
|
||||
private:
|
||||
|
||||
bool onPersistentChannelChanged(const LLSD& payload);
|
||||
|
||||
std::string mFileName;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ using namespace LLNotificationsUI;
|
|||
|
||||
//--------------------------------------------------------------------------
|
||||
LLTipHandler::LLTipHandler()
|
||||
: LLSysHandler("NotificationTips", "notifytip")
|
||||
: LLSystemNotificationHandler("NotificationTips", "notifytip")
|
||||
{
|
||||
// Getting a Channel for our notifications
|
||||
LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ void LLPanelBlockedList::updateButtons()
|
|||
{
|
||||
bool hasSelected = NULL != mBlockedList->getSelectedItem();
|
||||
getChildView("unblock_btn")->setEnabled(hasSelected);
|
||||
getChildView("blocked_gear_btn")->setEnabled(hasSelected);
|
||||
}
|
||||
|
||||
void LLPanelBlockedList::unblockItem()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @file llpersistentnotificationstorage.cpp
|
||||
* @brief Implementation of llpersistentnotificationstorage
|
||||
* @author Stinson@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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"
|
||||
|
||||
#include "llpersistentnotificationstorage.h"
|
||||
|
||||
#include "llchannelmanager.h"
|
||||
#include "llnotificationstorage.h"
|
||||
#include "llscreenchannel.h"
|
||||
#include "llscriptfloater.h"
|
||||
#include "llviewermessage.h"
|
||||
|
||||
LLPersistentNotificationStorage::LLPersistentNotificationStorage()
|
||||
: LLSingleton<LLPersistentNotificationStorage>()
|
||||
, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml"))
|
||||
{
|
||||
}
|
||||
|
||||
LLPersistentNotificationStorage::~LLPersistentNotificationStorage()
|
||||
{
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications");
|
||||
|
||||
void LLPersistentNotificationStorage::saveNotifications()
|
||||
{
|
||||
LLFastTimer _(FTM_SAVE_NOTIFICATIONS);
|
||||
|
||||
boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent"));
|
||||
if (!history_channel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD output = LLSD::emptyMap();
|
||||
LLSD& data = output["data"];
|
||||
|
||||
for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory();
|
||||
it != end_it;
|
||||
++it)
|
||||
{
|
||||
LLNotificationPtr notification = *it;
|
||||
|
||||
// After a notification was placed in Persist channel, it can become
|
||||
// responded, expired or canceled - in this case we are should not save it
|
||||
if(notification->isRespondedTo() || notification->isCancelled()
|
||||
|| notification->isExpired())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
data.append(notification->asLLSD());
|
||||
}
|
||||
|
||||
writeNotifications(output);
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications");
|
||||
|
||||
void LLPersistentNotificationStorage::loadNotifications()
|
||||
{
|
||||
LLFastTimer _(FTM_LOAD_NOTIFICATIONS);
|
||||
|
||||
LLNotifications::instance().getChannel("Persistent")->
|
||||
connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1));
|
||||
|
||||
LLSD input;
|
||||
if (!readNotifications(input) ||input.isUndefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD& data = input["data"];
|
||||
if (data.isUndefined())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace LLNotificationsUI;
|
||||
LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->
|
||||
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
|
||||
|
||||
LLNotifications& instance = LLNotifications::instance();
|
||||
|
||||
for (LLSD::array_const_iterator notification_it = data.beginArray();
|
||||
notification_it != data.endArray();
|
||||
++notification_it)
|
||||
{
|
||||
LLSD notification_params = *notification_it;
|
||||
LLNotificationPtr notification(new LLNotification(notification_params));
|
||||
|
||||
LLNotificationResponderPtr responder(createResponder(notification_params["name"], notification_params["responder"]));
|
||||
notification->setResponseFunctor(responder);
|
||||
|
||||
instance.add(notification);
|
||||
|
||||
// hide script floaters so they don't confuse the user and don't overlap startup toast
|
||||
LLScriptFloaterManager::getInstance()->setFloaterVisible(notification->getID(), false);
|
||||
|
||||
if(notification_channel)
|
||||
{
|
||||
// hide saved toasts so they don't confuse the user
|
||||
notification_channel->hideToast(notification->getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload)
|
||||
{
|
||||
// we ignore "load" messages, but rewrite the persistence file on any other
|
||||
const std::string sigtype = payload["sigtype"].asString();
|
||||
if ("load" != sigtype)
|
||||
{
|
||||
saveNotifications();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file llpersistentnotificationstorage.h
|
||||
* @brief Header file for llpersistentnotificationstorage
|
||||
* @author Stinson@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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_LLPERSISTENTNOTIFICATIONSTORAGE_H
|
||||
#define LL_LLPERSISTENTNOTIFICATIONSTORAGE_H
|
||||
|
||||
#include "llerror.h"
|
||||
#include "llnotificationstorage.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
// Class that saves not responded(unread) notifications.
|
||||
// Unread notifications are saved in open_notifications.xml in SL account folder
|
||||
//
|
||||
// Notifications that should be saved(if unread) are marked with persist="true" in notifications.xml
|
||||
// Notifications using functor responders are saved automatically (see llviewermessage.cpp
|
||||
// lure_callback_reg for example).
|
||||
// Notifications using object responders(LLOfferInfo) need additional tuning. Responder object should
|
||||
// be a) serializable(implement LLNotificationResponderInterface),
|
||||
// b) registered with LLResponderRegistry (found in llpersistentnotificationstorage.cpp).
|
||||
|
||||
class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>, public LLNotificationStorage
|
||||
{
|
||||
LOG_CLASS(LLPersistentNotificationStorage);
|
||||
public:
|
||||
LLPersistentNotificationStorage();
|
||||
~LLPersistentNotificationStorage();
|
||||
|
||||
void saveNotifications();
|
||||
void loadNotifications();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
bool onPersistentChannelChanged(const LLSD& payload);
|
||||
};
|
||||
|
||||
#endif // LL_LLPERSISTENTNOTIFICATIONSTORAGE_H
|
||||
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key),
|
||||
mChannel(NULL),
|
||||
mMessageList(NULL),
|
||||
mSysWellChiclet(NULL),
|
||||
NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"),
|
||||
IM_WELL_ANCHOR_NAME("im_well_panel"),
|
||||
mIsReshapedByUser(false)
|
||||
|
|
@ -79,6 +80,15 @@ void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
|
|||
setVisible(TRUE);
|
||||
}
|
||||
|
||||
void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet)
|
||||
{
|
||||
mSysWellChiclet = chiclet;
|
||||
if(NULL != mSysWellChiclet)
|
||||
{
|
||||
mSysWellChiclet->updateWidget(isWindowEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
LLSysWellWindow::~LLSysWellWindow()
|
||||
{
|
||||
|
|
@ -89,6 +99,10 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)
|
|||
{
|
||||
if(mMessageList->removeItemByValue(id))
|
||||
{
|
||||
if (NULL != mSysWellChiclet)
|
||||
{
|
||||
mSysWellChiclet->updateWidget(isWindowEmpty());
|
||||
}
|
||||
reshapeWindow();
|
||||
}
|
||||
else
|
||||
|
|
@ -334,6 +348,7 @@ void LLNotificationWellWindow::addItem(LLSysWellItem::Params p)
|
|||
LLSysWellItem* new_item = new LLSysWellItem(p);
|
||||
if (mMessageList->addItem(new_item, value, ADD_TOP))
|
||||
{
|
||||
mSysWellChiclet->updateWidget(isWindowEmpty());
|
||||
reshapeWindow();
|
||||
new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1));
|
||||
new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1));
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ public:
|
|||
|
||||
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;
|
||||
|
|
@ -84,6 +86,11 @@ protected:
|
|||
LLNotificationsUI::LLScreenChannel* mChannel;
|
||||
LLFlatListView* mMessageList;
|
||||
|
||||
/**
|
||||
* Reference to an appropriate Well chiclet to release "new message" state. EXT-3147
|
||||
*/
|
||||
LLSysWellChiclet* mSysWellChiclet;
|
||||
|
||||
bool mIsReshapedByUser;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7586,6 +7586,20 @@ void handle_web_content_test(const LLSD& param)
|
|||
LLWeb::loadURLInternal(url);
|
||||
}
|
||||
|
||||
void handle_show_url(const LLSD& param)
|
||||
{
|
||||
std::string url = param.asString();
|
||||
if(gSavedSettings.getBOOL("UseExternalBrowser"))
|
||||
{
|
||||
LLWeb::loadURLExternal(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLWeb::loadURLInternal(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void handle_buy_currency_test(void*)
|
||||
{
|
||||
std::string url =
|
||||
|
|
@ -8415,6 +8429,7 @@ void initialize_menus()
|
|||
// Advanced > UI
|
||||
commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser
|
||||
commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater
|
||||
commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2));
|
||||
view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
|
||||
view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
|
||||
view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
|
||||
|
|
|
|||
|
|
@ -3169,17 +3169,16 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
|
|||
payload["online"] = (offline == IM_ONLINE);
|
||||
payload["sender"] = msg->getSender().getIPandPort();
|
||||
|
||||
if (is_do_not_disturb)
|
||||
{
|
||||
send_do_not_disturb_message(msg, from_id);
|
||||
LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
|
||||
}
|
||||
else if (is_muted)
|
||||
if (is_muted)
|
||||
{
|
||||
LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_do_not_disturb)
|
||||
{
|
||||
send_do_not_disturb_message(msg, from_id);
|
||||
}
|
||||
args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString();
|
||||
if(message.empty())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,8 +37,10 @@
|
|||
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llcommunicationchannel.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llmeshrepository.h"
|
||||
#include "llnotificationhandler.h"
|
||||
#include "llpanellogin.h"
|
||||
#include "llviewerkeyboard.h"
|
||||
#include "llviewermenu.h"
|
||||
|
|
@ -127,6 +129,7 @@
|
|||
#include "llmorphview.h"
|
||||
#include "llmoveview.h"
|
||||
#include "llnavigationbar.h"
|
||||
#include "llnotificationhandler.h"
|
||||
#include "llpanelpathfindingrebakenavmesh.h"
|
||||
#include "llpaneltopinfobar.h"
|
||||
#include "llpopupview.h"
|
||||
|
|
@ -1554,11 +1557,11 @@ LLViewerWindow::LLViewerWindow(const Params& p)
|
|||
mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard)));
|
||||
mViewerWindowListener.reset(new LLViewerWindowListener(this));
|
||||
|
||||
mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")));
|
||||
mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")));
|
||||
mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything));
|
||||
mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible"));
|
||||
mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert"));
|
||||
mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal"));
|
||||
|
||||
mAlertsChannel->connectChanged(&LLViewerWindow::onAlert);
|
||||
mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert);
|
||||
bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications");
|
||||
LLNotifications::instance().setIgnoreAllNotifications(ignore);
|
||||
if (ignore)
|
||||
|
|
@ -5044,25 +5047,6 @@ LLRect LLViewerWindow::getChatConsoleRect()
|
|||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//static
|
||||
bool LLViewerWindow::onAlert(const LLSD& notify)
|
||||
{
|
||||
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
|
||||
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
llinfos << "Alert: " << notification->getName() << llendl;
|
||||
}
|
||||
|
||||
// If we're in mouselook, the mouse is hidden and so the user can't click
|
||||
// the dialog buttons. In that case, change to First Person instead.
|
||||
if( gAgentCamera.cameraMouselook() )
|
||||
{
|
||||
gAgentCamera.changeCameraToDefault();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLViewerWindow::setUIVisibility(bool visible)
|
||||
{
|
||||
mUIVisible = visible;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "llstat.h"
|
||||
#include "llmousehandler.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llhandle.h"
|
||||
#include "llinitparam.h"
|
||||
|
||||
|
|
@ -401,7 +402,6 @@ public:
|
|||
|
||||
private:
|
||||
bool shouldShowToolTipFor(LLMouseHandler *mh);
|
||||
static bool onAlert(const LLSD& notify);
|
||||
|
||||
void switchToolByMask(MASK mask);
|
||||
void destroyWindow();
|
||||
|
|
@ -418,8 +418,10 @@ private:
|
|||
bool mActive;
|
||||
bool mUIVisible;
|
||||
|
||||
boost::shared_ptr<class LLNotificationChannel> mAlertsChannel,
|
||||
mModalAlertsChannel;
|
||||
LLNotificationChannelPtr mSystemChannel;
|
||||
LLNotificationChannelPtr mCommunicationChannel;
|
||||
LLNotificationChannelPtr mAlertsChannel;
|
||||
LLNotificationChannelPtr mModalAlertsChannel;
|
||||
|
||||
LLRect mWindowRectRaw; // whole window, including UI
|
||||
LLRect mWindowRectScaled; // whole window, scaled by UI size
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@
|
|||
|
||||
#include "llvoavatar.h"
|
||||
|
||||
#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
|
@ -711,13 +709,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
LLMemType mt(LLMemType::MTYPE_AVATAR);
|
||||
//VTResume(); // VTune
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline
|
||||
const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
|
||||
mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
mVoiceVisualizer = new LLVoiceVisualizer();
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl;
|
||||
|
||||
|
|
@ -893,11 +887,7 @@ void LLVOAvatar::markDead()
|
|||
mNameText = NULL;
|
||||
sNumVisibleChatBubbles--;
|
||||
}
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
mVoiceVisualizer->markDead();
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
mVoiceVisualizer->setStopSpeaking();
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
|
||||
LLViewerObject::markDead();
|
||||
}
|
||||
|
|
@ -1429,9 +1419,7 @@ void LLVOAvatar::initInstance(void)
|
|||
|
||||
//VTPause(); // VTune
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) );
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2529,7 +2517,6 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||
|
||||
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
|
||||
{
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
bool render_visualizer = voice_enabled;
|
||||
|
||||
// Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled.
|
||||
|
|
@ -2542,7 +2529,6 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
|
|||
}
|
||||
|
||||
mVoiceVisualizer->setVoiceEnabled(render_visualizer);
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
if ( voice_enabled )
|
||||
{
|
||||
|
|
@ -2618,7 +2604,6 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// here we get the approximate head position and set as sound source for the voice symbol
|
||||
// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)
|
||||
|
|
@ -2636,7 +2621,6 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
|
|||
tagPos[VZ] += ( mBodySize[VZ] + 0.125f );
|
||||
mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );
|
||||
}
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
}//if ( voiceEnabled )
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -541,6 +541,7 @@ void LLVoiceClient::setMuteMic(bool muted)
|
|||
{
|
||||
mMuteMic = muted;
|
||||
updateMicMuteLogic();
|
||||
mMicroChangedSignal();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
//29de489d-0491-fb00-7dab-f9e686d31e83
|
||||
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
//--------------------------------------------------------------------------------------
|
||||
// sound symbol constants
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
|
@ -61,7 +60,6 @@ const F32 BASE_BRIGHTNESS = 0.7f; // gray level of the voice indicator when qu
|
|||
const F32 DOT_SIZE = 0.05f; // size of the dot billboard texture
|
||||
const F32 DOT_OPACITY = 0.7f; // how opaque the dot is
|
||||
const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a function of speaking amplitude
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// gesticulation constants
|
||||
|
|
@ -69,13 +67,11 @@ const F32 WAVE_MOTION_RATE = 1.5f; // scalar applied to consecutive waves as a
|
|||
const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE = 0.2f;
|
||||
const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f;
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
//--------------------------------------------------------------------------------------
|
||||
// other constants
|
||||
//--------------------------------------------------------------------------------------
|
||||
const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.
|
||||
const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Initialize the statics
|
||||
|
|
@ -98,28 +94,12 @@ F32 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f;
|
|||
//-----------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
|
||||
: LLHUDEffect(type)
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
LLVoiceVisualizer::LLVoiceVisualizer()
|
||||
: LLRefCount(),
|
||||
mTimer(),
|
||||
mStartTime(0.0),
|
||||
mCurrentlySpeaking(false),
|
||||
mSpeakingAmplitude(0.0f),
|
||||
mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE),
|
||||
mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE)
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
{
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
mCurrentTime = mTimer.getTotalSeconds();
|
||||
mPreviousTime = mCurrentTime;
|
||||
mStartTime = mCurrentTime;
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
mStartTime = mTimer.getTotalSeconds();
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f );
|
||||
mSpeakingAmplitude = 0.0f;
|
||||
mCurrentlySpeaking = false;
|
||||
|
|
@ -128,11 +108,9 @@ LLVoiceVisualizer::LLVoiceVisualizer()
|
|||
mMaxGesticulationAmplitude = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;
|
||||
mSoundSymbol.mActive = true;
|
||||
mSoundSymbol.mPosition = LLVector3( 0.0f, 0.0f, 0.0f );
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
mTimer.reset();
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
const char* sound_level_img[] =
|
||||
{
|
||||
"voice_meter_dot.j2c",
|
||||
|
|
@ -154,7 +132,6 @@ LLVoiceVisualizer::LLVoiceVisualizer()
|
|||
}
|
||||
|
||||
mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
// The first instance loads the initial state from prefs.
|
||||
if (!sPrefsInitialized)
|
||||
|
|
@ -174,7 +151,6 @@ LLVoiceVisualizer::LLVoiceVisualizer()
|
|||
|
||||
}//---------------------------------------------------
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
//---------------------------------------------------
|
||||
void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )
|
||||
{
|
||||
|
|
@ -195,16 +171,13 @@ void LLVoiceVisualizer::setVoiceEnabled( bool v )
|
|||
mVoiceEnabled = v;
|
||||
|
||||
}//---------------------------------------------------
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//---------------------------------------------------
|
||||
void LLVoiceVisualizer::setStartSpeaking()
|
||||
{
|
||||
mStartTime = mTimer.getTotalSeconds();
|
||||
mCurrentlySpeaking = true;
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
mSoundSymbol.mActive = true;
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
}//---------------------------------------------------
|
||||
|
||||
|
|
@ -359,7 +332,6 @@ void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah )
|
|||
}//---------------------------------------------------
|
||||
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
//---------------------------------------------------
|
||||
// this method is inherited from HUD Effect
|
||||
//---------------------------------------------------
|
||||
|
|
@ -558,7 +530,6 @@ void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )
|
|||
mVoiceSourceWorldPosition = p;
|
||||
|
||||
}//---------------------------------------------------
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//---------------------------------------------------
|
||||
VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel()
|
||||
|
|
@ -589,7 +560,6 @@ LLVoiceVisualizer::~LLVoiceVisualizer()
|
|||
}//----------------------------------------------
|
||||
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
//---------------------------------------------------
|
||||
// "packData" is inherited from HUDEffect
|
||||
//---------------------------------------------------
|
||||
|
|
@ -639,5 +609,3 @@ void LLVoiceVisualizer::markDead()
|
|||
|
||||
LLHUDEffect::markDead();
|
||||
}//------------------------------------------------------------------
|
||||
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
|
|
|||
|
|
@ -42,12 +42,7 @@
|
|||
#ifndef LL_VOICE_VISUALIZER_H
|
||||
#define LL_VOICE_VISUALIZER_H
|
||||
|
||||
#define XXX_STINSON_CHUI_REWORK // temporarily re-enabling the in-world voice-dot
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
#include "llhudeffect.h"
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
#include "llpointer.h"
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// The values of voice gesticulation represent energy levels for avatar animation, based on
|
||||
|
|
@ -65,45 +60,30 @@ enum VoiceGesticulationLevel
|
|||
NUM_VOICE_GESTICULATION_LEVELS
|
||||
};
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
const static int NUM_VOICE_SYMBOL_WAVES = 7;
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//----------------------------------------------------
|
||||
// LLVoiceVisualizer class
|
||||
//----------------------------------------------------
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
class LLVoiceVisualizer : public LLHUDEffect
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
class LLVoiceVisualizer : public LLRefCount
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
{
|
||||
//---------------------------------------------------
|
||||
// public methods
|
||||
//---------------------------------------------------
|
||||
public:
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
LLVoiceVisualizer( const U8 type ); //constructor
|
||||
#else // XXX_STINSON_CHUI_REWORK
|
||||
LLVoiceVisualizer(); //constructor
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
~LLVoiceVisualizer(); //destructor
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
void setVoiceSourceWorldPosition( const LLVector3 &p ); // this should be the position of the speaking avatar's head
|
||||
void setMinGesticulationAmplitude( F32 ); // the lower range of meaningful amplitude for setting gesticulation level
|
||||
void setMaxGesticulationAmplitude( F32 ); // the upper range of meaningful amplitude for setting gesticulation level
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
void setStartSpeaking(); // tell me when the av starts speaking
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
void setVoiceEnabled( bool ); // tell me whether or not the user is voice enabled
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
void setSpeakingAmplitude( F32 ); // tell me how loud the av is speaking (ranges from 0 to 1)
|
||||
void setStopSpeaking(); // tell me when the av stops speaking
|
||||
bool getCurrentlySpeaking(); // the get for the above set
|
||||
VoiceGesticulationLevel getCurrentGesticulationLevel(); // based on voice amplitude, I'll give you the current "energy level" of avatar speech
|
||||
void lipSyncOohAah( F32& ooh, F32& aah );
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
void render(); // inherited from HUD Effect
|
||||
void packData(LLMessageSystem *mesgsys); // inherited from HUD Effect
|
||||
void unpackData(LLMessageSystem *mesgsys, S32 blocknum); // inherited from HUD Effect
|
||||
|
|
@ -119,7 +99,6 @@ class LLVoiceVisualizer : public LLRefCount
|
|||
//----------------------------------------------------------------------------------------------
|
||||
void setMaxGesticulationAmplitude();
|
||||
void setMinGesticulationAmplitude();
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
//---------------------------------------------------
|
||||
// private members
|
||||
|
|
@ -129,7 +108,6 @@ class LLVoiceVisualizer : public LLRefCount
|
|||
static void setPreferences( );
|
||||
static void lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats
|
||||
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
struct SoundSymbol
|
||||
{
|
||||
F32 mWaveExpansion [ NUM_VOICE_SYMBOL_WAVES ];
|
||||
|
|
@ -140,20 +118,15 @@ class LLVoiceVisualizer : public LLRefCount
|
|||
bool mActive;
|
||||
LLVector3 mPosition;
|
||||
};
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
|
||||
LLFrameTimer mTimer; // so I can ask the current time in seconds
|
||||
F64 mStartTime; // time in seconds when speaking started
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
F64 mCurrentTime; // current time in seconds, captured every step
|
||||
F64 mPreviousTime; // copy of "current time" from last frame
|
||||
SoundSymbol mSoundSymbol; // the sound symbol that appears over the avatar's head
|
||||
bool mVoiceEnabled; // if off, no rendering should happen
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
bool mCurrentlySpeaking; // is the user currently speaking?
|
||||
#ifdef XXX_STINSON_CHUI_REWORK
|
||||
LLVector3 mVoiceSourceWorldPosition; // give this to me every step - I need it to update the sound symbol
|
||||
#endif // XXX_STINSON_CHUI_REWORK
|
||||
F32 mSpeakingAmplitude; // this should be set as often as possible when the user is speaking
|
||||
F32 mMaxGesticulationAmplitude; // this is the upper-limit of the envelope of detectable gesticulation leves
|
||||
F32 mMinGesticulationAmplitude; // this is the lower-limit of the envelope of detectable gesticulation leves
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
<color
|
||||
name="EmphasisColor_35"
|
||||
value="0.38 0.694 0.573 0.35" />
|
||||
<color
|
||||
name="BeaconColor"
|
||||
value="0.749 0.298 0 1" />
|
||||
<color
|
||||
name="White"
|
||||
value="1 1 1 1" />
|
||||
|
|
@ -522,6 +525,9 @@
|
|||
<color
|
||||
name="MenuItemHighlightBgColor"
|
||||
reference="EmphasisColor_35" />
|
||||
<color
|
||||
name="MenuItemFlashBgColor"
|
||||
reference="BeaconColor" />
|
||||
<color
|
||||
name="MenuItemHighlightFgColor"
|
||||
reference="White" />
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -365,6 +365,8 @@ with the same filename but different name
|
|||
|
||||
<texture name="Nearby_chat_icon" file_name="icons/nearby_chat_icon.png" preload="false" />
|
||||
|
||||
<texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" />
|
||||
|
||||
<texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" />
|
||||
<texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" />
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Luk alle" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Alle schließen" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -1,91 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
|
||||
<floater
|
||||
can_resize="true"
|
||||
positioning="cascading"
|
||||
height="400"
|
||||
min_height="100"
|
||||
min_width="390"
|
||||
layout="topleft"
|
||||
name="floater_conversation_log"
|
||||
save_rect="true"
|
||||
single_instance="true"
|
||||
reuse_instance="true"
|
||||
title="CONVERSATION LOG"
|
||||
width="450">
|
||||
|
||||
can_resize="true"
|
||||
positioning="cascading"
|
||||
height="200"
|
||||
min_height="100"
|
||||
min_width="230"
|
||||
layout="topleft"
|
||||
name="floater_conversation_log"
|
||||
save_rect="true"
|
||||
single_instance="true"
|
||||
reuse_instance="true"
|
||||
title="CONVERSATION LOG"
|
||||
width="300">
|
||||
<string name="logging_calls_disabled">
|
||||
Conversations are not being logged. To log conversations in the future, select "Save IM logs on my computer" under Preferences > Privacy.
|
||||
</string>
|
||||
|
||||
<panel
|
||||
follows="left|top|right"
|
||||
height="27"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="buttons_panel"
|
||||
top="0">
|
||||
<filter_editor
|
||||
follows="left|top|right"
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
label="Filter People"
|
||||
max_length_chars="300"
|
||||
name="people_filter_input"
|
||||
text_color="Black"
|
||||
text_pad_left="10"
|
||||
top="4"
|
||||
width="364" />
|
||||
<menu_button
|
||||
follows="right"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="Conv_toolbar_sort"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
left_pad="5"
|
||||
menu_filename="menu_conversation_log_view.xml"
|
||||
menu_position="bottomleft"
|
||||
name="conversation_view_btn"
|
||||
tool_tip="View/sort options"
|
||||
top="3"
|
||||
width="31" />
|
||||
<menu_button
|
||||
follows="right"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="OptionsMenu_Off"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
left_pad="2"
|
||||
name="conversations_gear_btn"
|
||||
tool_tip="Actions on selected person or group"
|
||||
top="3"
|
||||
width="31" />
|
||||
</panel>
|
||||
<panel
|
||||
follows="all"
|
||||
height="370"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="buttons_panel"
|
||||
right="-5"
|
||||
top_pad="5">
|
||||
<panel
|
||||
follows="left|top|right"
|
||||
height="32"
|
||||
left="0"
|
||||
name="buttons_panel"
|
||||
top="0">
|
||||
<filter_editor
|
||||
follows="left|top|right"
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left="8"
|
||||
label="Filter People"
|
||||
max_length_chars="300"
|
||||
name="people_filter_input"
|
||||
text_color="Black"
|
||||
text_pad_left="10"
|
||||
top="4"
|
||||
width="204" />
|
||||
<menu_button
|
||||
follows="top|right"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="Conv_toolbar_sort"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
left_pad="8"
|
||||
menu_filename="menu_conversation_log_view.xml"
|
||||
menu_position="bottomleft"
|
||||
name="conversation_view_btn"
|
||||
tool_tip="View/sort options"
|
||||
top="3"
|
||||
width="31" />
|
||||
<menu_button
|
||||
follows="top|right"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="OptionsMenu_Off"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
left_pad="8"
|
||||
name="conversations_gear_btn"
|
||||
tool_tip="Actions on selected person or group"
|
||||
top="3"
|
||||
width="31" />
|
||||
</panel>
|
||||
<panel
|
||||
bottom="-1"
|
||||
follows="all"
|
||||
left="0"
|
||||
name="log_panel"
|
||||
right="-1"
|
||||
top="32">
|
||||
<conversation_log_list
|
||||
opaque="true"
|
||||
allow_select="true"
|
||||
follows="all"
|
||||
height="360"
|
||||
layout="topleft"
|
||||
left="3"
|
||||
keep_selection_visible_on_reshape="true"
|
||||
item_pad="2"
|
||||
multi_select="false"
|
||||
name="conversation_log_list"
|
||||
right="-3"
|
||||
top="5" />
|
||||
</panel>
|
||||
allow_select="true"
|
||||
bottom="-8"
|
||||
opaque="true"
|
||||
follows="all"
|
||||
left="8"
|
||||
keep_selection_visible_on_reshape="true"
|
||||
item_pad="2"
|
||||
multi_select="false"
|
||||
name="conversation_log_list"
|
||||
right="-8"
|
||||
top="0" />
|
||||
</panel>
|
||||
</floater>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
can_close="true"
|
||||
can_minimize="true"
|
||||
can_resize="true"
|
||||
height="230"
|
||||
height="210"
|
||||
layout="topleft"
|
||||
min_height="50"
|
||||
name="floater_im_box"
|
||||
help_topic="floater_im_box"
|
||||
save_rect="true"
|
||||
|
|
@ -24,22 +23,20 @@
|
|||
value="Conv_toolbar_expand"/>
|
||||
<layout_stack
|
||||
animate="true"
|
||||
bottom="-1"
|
||||
follows="all"
|
||||
height="230"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="conversations_stack"
|
||||
orientation="horizontal"
|
||||
top="0"
|
||||
width="450">
|
||||
right="-1"
|
||||
top="0">
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
user_resize="true"
|
||||
height="430"
|
||||
name="conversations_layout_panel"
|
||||
min_dim="38"
|
||||
width="268"
|
||||
expanded_min_dim="120">
|
||||
expanded_min_dim="156">
|
||||
<layout_stack
|
||||
animate="false"
|
||||
follows="left|top|right"
|
||||
|
|
@ -48,8 +45,8 @@
|
|||
left="0"
|
||||
name="conversations_pane_buttons_stack"
|
||||
orientation="horizontal"
|
||||
top="0"
|
||||
width="268">
|
||||
right="-1"
|
||||
top="0">
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
height="35"
|
||||
|
|
@ -109,46 +106,44 @@
|
|||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left="5"
|
||||
left="1"
|
||||
name="expand_collapse_btn"
|
||||
tool_tip="Collapse/Expand this list"
|
||||
width="31" />
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
<panel
|
||||
bottom="-5"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="conversations_list_panel"
|
||||
opaque="true"
|
||||
top_pad="0"
|
||||
top="35"
|
||||
left="5"
|
||||
height="390"
|
||||
width="263"/>
|
||||
right="-1"/>
|
||||
</layout_panel>
|
||||
<layout_panel
|
||||
auto_resize="true"
|
||||
user_resize="true"
|
||||
height="430"
|
||||
name="messages_layout_panel"
|
||||
width="412"
|
||||
expanded_min_dim="225">
|
||||
expanded_min_dim="222">
|
||||
<panel_container
|
||||
bottom="-5"
|
||||
follows="all"
|
||||
height="430"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="im_box_tab_container"
|
||||
top="0"
|
||||
width="412">
|
||||
right="-1"
|
||||
top="0">
|
||||
<panel
|
||||
bottom="-1"
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
name="stub_panel"
|
||||
opaque="true"
|
||||
top_pad="0"
|
||||
left="0"
|
||||
height="430"
|
||||
width="412">
|
||||
right="-1">
|
||||
<button
|
||||
follows="right|top"
|
||||
height="25"
|
||||
|
|
|
|||
|
|
@ -49,6 +49,15 @@
|
|||
<floater.string
|
||||
name="end_call_button_tooltip"
|
||||
value="Close voice connection"/>
|
||||
<floater.string
|
||||
name="expcol_button_not_tearoff_tooltip"
|
||||
value="Collapse this pane"/>
|
||||
<floater.string
|
||||
name="expcol_button_tearoff_and_expanded_tooltip"
|
||||
value="Collapse participant list"/>
|
||||
<floater.string
|
||||
name="expcol_button_tearoff_and_collapsed_tooltip"
|
||||
value="Expand participant list"/>
|
||||
<view
|
||||
follows="all"
|
||||
layout="topleft"
|
||||
|
|
@ -79,6 +88,21 @@
|
|||
tool_tip="View/sort options"
|
||||
top="5"
|
||||
width="31" />
|
||||
<menu_button
|
||||
menu_filename="menu_im_conversation.xml"
|
||||
follows="top|left"
|
||||
height="25"
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_overlay="OptionsMenu_Off"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
layout="topleft"
|
||||
top="5"
|
||||
left_pad="4"
|
||||
name="gear_btn"
|
||||
visible="false"
|
||||
tool_tip="Actions on selected person"
|
||||
width="31"/>
|
||||
<button
|
||||
enabled="false"
|
||||
follows="top|left"
|
||||
|
|
@ -191,7 +215,7 @@
|
|||
auto_resize="true"
|
||||
visible="true"
|
||||
name="left_part_holder"
|
||||
min_width="225">
|
||||
min_width="221">
|
||||
<panel
|
||||
name="trnsAndChat_panel"
|
||||
follows="all"
|
||||
|
|
|
|||
|
|
@ -75,6 +75,13 @@
|
|||
<on_click function="Avatar.DoToSelected" parameter="remove_friend" />
|
||||
<on_enable function="Avatar.EnableItem" parameter="can_delete" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Remove friends"
|
||||
layout="topleft"
|
||||
name="remove_friends">
|
||||
<on_click function="Avatar.DoToSelected" parameter="remove_friend" />
|
||||
<on_enable function="Avatar.EnableItem" parameter="can_delete" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Invite to group..."
|
||||
layout="topleft"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<toggleable_menu
|
||||
layout="topleft"
|
||||
name="Conversation Gear Menu">
|
||||
<menu_item_call
|
||||
label="View Profile"
|
||||
layout="topleft"
|
||||
name="View Profile">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="view_profile" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_view_profile" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Add Friend"
|
||||
layout="topleft"
|
||||
name="Add Friend">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="add_friend" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_add" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Remove friend"
|
||||
layout="topleft"
|
||||
name="remove_friend">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="remove_friend" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_delete" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Offer teleport"
|
||||
layout="topleft"
|
||||
name="offer_teleport">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="offer_teleport"/>
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_offer_teleport"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Invite to group..."
|
||||
layout="topleft"
|
||||
name="invite_to_group">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="invite_to_group" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_invite" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator
|
||||
layout="topleft"
|
||||
name="View Icons Separator" />
|
||||
<menu_item_call
|
||||
label="Chat history..."
|
||||
layout="topleft"
|
||||
name="chat_history">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="chat_history"/>
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_chat_history"/>
|
||||
</menu_item_call>
|
||||
<menu_item_separator
|
||||
layout="topleft"/>
|
||||
<menu_item_call
|
||||
label="Map"
|
||||
layout="topleft"
|
||||
name="map">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="map" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_show_on_map" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Share"
|
||||
layout="topleft"
|
||||
name="Share">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="share" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_share" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Pay"
|
||||
layout="topleft"
|
||||
name="Pay">
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="pay" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_pay" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator
|
||||
layout="topleft"/>
|
||||
<menu_item_check
|
||||
label="Block Voice"
|
||||
layout="topleft"
|
||||
name="Block/Unblock">
|
||||
<on_check function="Avatar.CheckGearItem" parameter="is_blocked" />
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="block_unblock" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_block" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Block Text"
|
||||
layout="topleft"
|
||||
name="MuteText">
|
||||
<on_check function="Avatar.CheckGearItem" parameter="is_muted" />
|
||||
<on_click function="Avatar.GearDoToSelected" parameter="mute_unmute" />
|
||||
<on_enable function="Avatar.EnableGearItem" parameter="can_block" />
|
||||
</menu_item_check>
|
||||
<menu_item_separator
|
||||
layout="topleft"/>
|
||||
</toggleable_menu>
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<context_menu
|
||||
layout="topleft"
|
||||
name="Notification Well Button Context Menu">
|
||||
<menu_item_call
|
||||
label="Close All"
|
||||
layout="topleft"
|
||||
name="Close All">
|
||||
<menu_item_call.on_click
|
||||
function="NotificationWellChicletMenu.Action"
|
||||
parameter="close all" />
|
||||
<menu_item_call.on_enable
|
||||
function="NotificationWellChicletMenu.EnableItem"
|
||||
parameter="can close all" />
|
||||
</menu_item_call>
|
||||
</context_menu>
|
||||
|
|
@ -1267,7 +1267,58 @@
|
|||
function="Floater.Show"
|
||||
parameter="hud" />
|
||||
</menu_item_call>-->
|
||||
|
||||
<menu_item_separator/>
|
||||
|
||||
<menu_item_call
|
||||
label="User’s guide"
|
||||
name="User’s guide">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="http://community.secondlife.com/t5/English-Knowledge-Base/Second-Life-User-s-Guide/ta-p/1244857"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Knowledge Base"
|
||||
name="Knowledge Base">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="http://community.secondlife.com/t5/tkb/communitypage"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Wiki"
|
||||
name="Wiki">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="http://wiki.secondlife.com"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Community Forums"
|
||||
name="Community Forums">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="http://community.secondlife.com/t5/Forums/ct-p/Forums"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Support portal"
|
||||
name="Support portal">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="https://support.secondlife.com/"/>
|
||||
</menu_item_call>
|
||||
<menu_item_separator/>
|
||||
<menu_item_call
|
||||
label="[SECOND_LIFE] News"
|
||||
name="Second Life News">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="http://community.secondlife.com/t5/Featured-News/bg-p/blog_feature_news"/>
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="[SECOND_LIFE] Blogs"
|
||||
name="Second Life Blogs">
|
||||
<menu_item_call.on_click
|
||||
function="Advanced.ShowURL"
|
||||
parameter="http://community.secondlife.com/t5/Blogs/ct-p/Blogs"/>
|
||||
</menu_item_call>
|
||||
<menu_item_separator/>
|
||||
|
||||
<menu_item_call
|
||||
|
|
|
|||
|
|
@ -3696,7 +3696,6 @@ Do Not Disturb is on. You will not be notified of incoming communications.
|
|||
- Other residents will receive your Do Not Disturb response (set in Preferences > General).
|
||||
- Teleportation offers will be declined.
|
||||
- Voice calls will be rejected.
|
||||
- Inventory offers will go to your Trash.
|
||||
<usetemplate
|
||||
ignoretext="I change my status to Do Not Disturb mode"
|
||||
name="okignore"
|
||||
|
|
@ -6584,7 +6583,7 @@ However, this region contains content accessible to adults only.
|
|||
log_to_im="true"
|
||||
log_to_chat="false"
|
||||
show_toast="false"
|
||||
type="offer">
|
||||
type="notify">
|
||||
Teleport offer sent to [TO_NAME]
|
||||
</notification>
|
||||
|
||||
|
|
@ -6637,7 +6636,7 @@ However, this region contains content accessible to adults only.
|
|||
name="FriendshipOffered"
|
||||
log_to_im="true"
|
||||
show_toast="false"
|
||||
type="offer">
|
||||
type="notify">
|
||||
<tag>friendship</tag>
|
||||
You have offered friendship to [TO_NAME]
|
||||
</notification>
|
||||
|
|
@ -6667,7 +6666,7 @@ However, this region contains content accessible to adults only.
|
|||
icon="notify.tga"
|
||||
name="FriendshipAccepted"
|
||||
log_to_im="true"
|
||||
type="offer">
|
||||
type="notify">
|
||||
<tag>friendship</tag>
|
||||
<nolink>[NAME]</nolink> accepted your friendship offer.
|
||||
</notification>
|
||||
|
|
@ -6687,7 +6686,7 @@ However, this region contains content accessible to adults only.
|
|||
name="FriendshipAcceptedByMe"
|
||||
log_to_im="true"
|
||||
show_toast="false"
|
||||
type="offer">
|
||||
type="notify">
|
||||
<tag>friendship</tag>
|
||||
Friendship offer accepted.
|
||||
</notification>
|
||||
|
|
@ -6697,7 +6696,7 @@ Friendship offer accepted.
|
|||
name="FriendshipDeclinedByMe"
|
||||
log_to_im="true"
|
||||
show_toast="false"
|
||||
type="offer">
|
||||
type="notify">
|
||||
<tag>friendship</tag>
|
||||
Friendship offer declined.
|
||||
</notification>
|
||||
|
|
|
|||
|
|
@ -77,5 +77,49 @@
|
|||
width="12" />
|
||||
</chiclet_panel>
|
||||
</layout_panel>
|
||||
<layout_panel auto_resize="false"
|
||||
width="4"
|
||||
min_width="4"/>
|
||||
<layout_panel
|
||||
auto_resize="false"
|
||||
follows="right"
|
||||
height="28"
|
||||
layout="topleft"
|
||||
min_height="28"
|
||||
min_width="37"
|
||||
name="notification_well_panel"
|
||||
top="0"
|
||||
width="37">
|
||||
<chiclet_notification
|
||||
follows="right"
|
||||
height="23"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
max_displayed_count="99"
|
||||
name="notification_well"
|
||||
top="5"
|
||||
width="35">
|
||||
<button
|
||||
auto_resize="false"
|
||||
bottom_pad="3"
|
||||
follows="right"
|
||||
halign="center"
|
||||
height="23"
|
||||
image_overlay="Notices_Unread"
|
||||
image_overlay_alignment="center"
|
||||
image_pressed="WellButton_Lit"
|
||||
image_pressed_selected="WellButton_Lit_Selected"
|
||||
image_selected="PushButton_Press"
|
||||
label_color="Black"
|
||||
left="0"
|
||||
name="Unread"
|
||||
tool_tip="Notifications"
|
||||
width="34">
|
||||
<init_callback
|
||||
function="Button.SetDockableFloaterToggle"
|
||||
parameter="notification_well_window" />
|
||||
</button>
|
||||
</chiclet_notification>
|
||||
</layout_panel>
|
||||
</layout_stack>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@
|
|||
image_overlay_alignment="left"
|
||||
use_ellipses="true"
|
||||
auto_resize="true"
|
||||
button_flash_count="3"
|
||||
button_flash_rate="0.25"
|
||||
flash_color="EmphasisColor"/>
|
||||
button_flash_count="4"
|
||||
button_flash_rate="0.5"
|
||||
flash_color="BeaconColor"/>
|
||||
<button_icon pad_left="10"
|
||||
pad_right="10"
|
||||
image_bottom_pad="10"
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
chrome="true"
|
||||
use_ellipses="true"
|
||||
auto_resize="true"
|
||||
button_flash_count="3"
|
||||
button_flash_rate="0.25"
|
||||
flash_color="EmphasisColor"/>
|
||||
button_flash_count="4"
|
||||
button_flash_rate="0.5"
|
||||
flash_color="BeaconColor"/>
|
||||
</toolbar>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Cerrar todo" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Tout fermer" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Chiudi tutto" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="すべて閉じる" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Zamknij" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Fechar tudo" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Закрыть все" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="Tümünü Kapat" name="Close All"/>
|
||||
</context_menu>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<context_menu name="Notification Well Button Context Menu">
|
||||
<menu_item_call label="全部關閉" name="Close All"/>
|
||||
</context_menu>
|
||||
Loading…
Reference in New Issue