summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-xindra/llui/llchatentry.cpp6
-rwxr-xr-xindra/llui/llchatentry.h4
-rwxr-xr-xindra/llui/llfloater.cpp33
-rwxr-xr-xindra/llui/llfloater.h5
-rwxr-xr-xindra/llui/llfolderview.cpp26
-rwxr-xr-xindra/llui/llfolderviewitem.cpp30
-rwxr-xr-xindra/llui/llfolderviewitem.h1
-rwxr-xr-xindra/llui/llfolderviewmodel.cpp2
-rwxr-xr-xindra/llui/llfolderviewmodel.h31
-rwxr-xr-xindra/llui/lllayoutstack.cpp102
-rwxr-xr-xindra/llui/lllayoutstack.h10
-rwxr-xr-xindra/llui/llmenugl.cpp12
-rwxr-xr-xindra/llui/llresizebar.cpp110
-rwxr-xr-xindra/llui/llresizebar.h52
-rwxr-xr-xindra/llui/lltextbase.cpp31
-rwxr-xr-xindra/llui/lltexteditor.cpp7
-rwxr-xr-xindra/llui/lltexteditor.h1
-rwxr-xr-xindra/llwindow/llwindowwin32.cpp3
-rwxr-xr-xindra/newview/app_settings/settings.xml134
-rwxr-xr-xindra/newview/llagent.cpp13
-rwxr-xr-xindra/newview/llconversationmodel.cpp4
-rwxr-xr-xindra/newview/llconversationmodel.h9
-rwxr-xr-xindra/newview/llconversationview.cpp21
-rwxr-xr-xindra/newview/llconversationview.h3
-rwxr-xr-xindra/newview/lldonotdisturbnotificationstorage.cpp16
-rwxr-xr-xindra/newview/llfloaterimcontainer.cpp172
-rwxr-xr-xindra/newview/llfloaterimcontainer.h12
-rwxr-xr-xindra/newview/llfloaterimnearbychat.cpp5
-rwxr-xr-xindra/newview/llfloaterimnearbychathandler.cpp1
-rwxr-xr-xindra/newview/llfloaterimsession.cpp20
-rwxr-xr-xindra/newview/llfloaterimsessiontab.cpp44
-rwxr-xr-xindra/newview/llfloaterimsessiontab.h3
-rwxr-xr-xindra/newview/llfloaterpreference.cpp4
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.cpp69
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.h3
-rwxr-xr-xindra/newview/llgroupactions.cpp125
-rwxr-xr-xindra/newview/llgroupactions.h8
-rwxr-xr-xindra/newview/llimview.cpp295
-rwxr-xr-xindra/newview/llinventoryfilter.cpp42
-rwxr-xr-xindra/newview/llinventoryfilter.h17
-rwxr-xr-xindra/newview/llinventorypanel.cpp3
-rwxr-xr-xindra/newview/lllogchat.cpp45
-rwxr-xr-xindra/newview/lllogchat.h3
-rwxr-xr-xindra/newview/llnotificationtiphandler.cpp7
-rwxr-xr-xindra/newview/llpanelmaininventory.cpp7
-rwxr-xr-xindra/newview/llpanelmaininventory.h1
-rwxr-xr-xindra/newview/lltoastimpanel.cpp26
-rwxr-xr-xindra/newview/lltoastimpanel.h2
-rwxr-xr-xindra/newview/llviewermessage.cpp4
-rwxr-xr-xindra/newview/llviewerwindow.cpp1
-rwxr-xr-xindra/newview/skins/default/colors.xml15
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml3
-rw-r--r--indra/newview/skins/default/textures/widgets/horizontal_drag_handle.pngbin0 -> 197 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/vertical_drag_handle.pngbin0 -> 196 bytes
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_im_container.xml102
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_im_session.xml86
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml13
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_chat.xml140
58 files changed, 1381 insertions, 563 deletions
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index 6a1b48a08a..416c3e65e4 100755
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -165,12 +165,14 @@ bool LLChatEntry::useLabel()
void LLChatEntry::onFocusReceived()
{
-
+ LLUICtrl::onFocusReceived();
+ updateAllowingLanguageInput();
}
void LLChatEntry::onFocusLost()
{
-
+ LLTextEditor::focusLostHelper();
+ LLUICtrl::onFocusLost();
}
BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h
index 49c8d21450..3a5e87e8c8 100755
--- a/indra/llui/llchatentry.h
+++ b/indra/llui/llchatentry.h
@@ -62,8 +62,8 @@ public:
virtual void draw();
virtual void onCommit();
- /*virtual*/ void onFocusReceived();
- /*virtual*/ void onFocusLost();
+ /*virtual*/ void onFocusReceived();
+ /*virtual*/ void onFocusLost();
void enableSingleLineMode(bool single_line_mode);
boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb);
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 09e27a264a..273ceb4038 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -507,22 +507,11 @@ LLFloater::~LLFloater()
{
LLFloaterReg::removeInstance(mInstanceName, mKey);
-// delete mNotificationContext;
-// mNotificationContext = NULL;
-
- //// am I not hosted by another floater?
- //if (mHostHandle.isDead())
- //{
- // LLFloaterView* parent = (LLFloaterView*) getParent();
-
- // if( parent )
- // {
- // parent->removeChild( this );
- // }
- //}
-
- // Just in case we might still have focus here, release it.
- releaseFocus();
+ if( gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // Just in case we might still have focus here, release it.
+ releaseFocus();
+ }
// This is important so that floaters with persistent rects (i.e., those
// created with rect control rather than an LLRect) are restored in their
@@ -1486,6 +1475,7 @@ void LLFloater::moveResizeHandlesToFront()
}
}
+/*virtual*/
BOOL LLFloater::isFrontmost()
{
LLFloaterView* floater_view = getParentByType<LLFloaterView>();
@@ -1504,7 +1494,7 @@ void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition)
floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));
floaterp->setSnapTarget(getHandle());
}
- gFloaterView->adjustToFitScreen(floaterp, FALSE);
+ gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE);
if (floaterp->isFrontmost())
{
// make sure to bring self and sibling floaters to front
@@ -2735,7 +2725,7 @@ void LLFloaterView::refresh()
const S32 FLOATER_MIN_VISIBLE_PIXELS = 16;
-void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside)
+void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars/* = false*/)
{
if (floater->getParent() != this)
{
@@ -2788,7 +2778,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
}
// move window fully onscreen
- if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
+ if (floater->translateIntoRect( snap_in_toolbars ? getSnapRect() : gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
{
floater->clearSnapTarget();
}
@@ -3258,6 +3248,11 @@ bool LLFloater::isShown() const
return ! isMinimized() && isInVisibleChain();
}
+bool LLFloater::isDetachedAndNotMinimized()
+{
+ return !getHost() && !isMinimized();
+}
+
/* static */
bool LLFloater::isShown(const LLFloater* floater)
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 4dba1e645f..3482314698 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -238,6 +238,7 @@ public:
void center();
LLMultiFloater* getHost();
+ bool isDetachedAndNotMinimized();
void applyTitle();
std::string getCurrentTitle() const;
@@ -261,7 +262,7 @@ public:
static bool isVisible(const LLFloater* floater);
static bool isMinimized(const LLFloater* floater);
BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts
- BOOL isFrontmost();
+ virtual BOOL isFrontmost();
BOOL isDependent() { return !mDependeeHandle.isDead(); }
void setCanMinimize(BOOL can_minimize);
void setCanClose(BOOL can_close);
@@ -528,7 +529,7 @@ public:
LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor );
// Given a child of gFloaterView, make sure this view can fit entirely onscreen.
- void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside);
+ void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars = false);
void setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; }
void getMinimizePosition( S32 *left, S32 *bottom);
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 8aa1eb7cd5..cf449217f5 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -323,9 +323,11 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View");
void LLFolderView::filter( LLFolderViewFilter& filter )
{
+ // Entry point of inventory filtering (CHUI-849)
LLFastTimer t2(FTM_FILTER);
- filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
+ filter.resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32(mParentPanel->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100));
+ // Note: we filter the model, not the view
getViewModelItem()->filter(filter);
}
@@ -661,7 +663,7 @@ void LLFolderView::draw()
// get preferable text height...
S32 pixel_height = mStatusTextBox->getTextPixelHeight();
- bool height_changed = local_rect.getHeight() != pixel_height;
+ bool height_changed = (local_rect.getHeight() < pixel_height);
if (height_changed)
{
// ... if it does not match current height, lets rearrange current view.
@@ -1601,15 +1603,17 @@ void LLFolderView::update()
{
mNeedsAutoSelect = TRUE;
}
- // filter to determine visibility before arranging
+
+ // Filter to determine visibility before arranging
filter(getFolderViewModel()->getFilter());
- // Clear the modified setting on the filter only if the filter count is non-zero after running the filter process
- // Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items
- if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0))
+
+ // Clear the modified setting on the filter only if the filter finished after running the filter process
+ // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items
+ if (getFolderViewModel()->getFilter().isModified() && (!getFolderViewModel()->getFilter().isTimedOut()))
{
getFolderViewModel()->getFilter().clearModified();
}
-
+
// automatically show matching items, and select first one if we had a selection
if (mNeedsAutoSelect)
{
@@ -1649,11 +1653,13 @@ void LLFolderView::update()
BOOL is_visible = isInVisibleChain();
- //Puts folders/items in proper positions
- if ( is_visible )
+ // Puts folders/items in proper positions
+ // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849)
+ // It also handles the open/close folder animation
+ if (is_visible)
{
sanitizeSelection();
- if( needsArrange() )
+ if (needsArrange())
{
S32 height = 0;
S32 width = 0;
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index fdb4108afb..6c147ccc12 100755
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -274,6 +274,7 @@ void LLFolderViewItem::refresh()
}
mLabelWidthDirty = true;
+ // Dirty the filter flag of the model from the view (CHUI-849)
vmi.dirtyFilter();
}
@@ -943,11 +944,17 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
-// Finds width and height of this object and its children. Also
-// makes sure that this view and its children are the right size.
+// Make everything right and in the right place ready for drawing (CHUI-849)
+// * Sort everything correctly if necessary
+// * Turn widgets visible/invisible according to their model filtering state
+// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible)
+// * Reposition visible widgets so that they line up correctly with no gap
+// * Compute the width and height of the current folder and its children
+// * Makes sure that this view and its children are the right size
S32 LLFolderViewFolder::arrange( S32* width, S32* height )
{
- // sort before laying out contents
+ // Sort before laying out contents
+ // Note that we sort from the root (CHUI-849)
getRoot()->getFolderViewModel()->sort(this);
LLFastTimer t2(FTM_ARRANGE);
@@ -1613,16 +1620,13 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
}
void LLFolderViewFolder::requestArrange()
-{
- if ( mLastArrangeGeneration != -1)
- {
- mLastArrangeGeneration = -1;
- // flag all items up to root
- if (mParentFolder)
- {
- mParentFolder->requestArrange();
- }
- }
+{
+ mLastArrangeGeneration = -1;
+ // flag all items up to root
+ if (mParentFolder)
+ {
+ mParentFolder->requestArrange();
+ }
}
void LLFolderViewFolder::toggleOpen()
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index ca31931e19..a9b0201236 100755
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -316,7 +316,6 @@ protected:
F32 mAutoOpenCountdown;
S32 mLastArrangeGeneration;
S32 mLastCalculatedWidth;
- S32 mMostFilteredDescendantGeneration;
bool mNeedsSort;
public:
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index 3593804554..3363dc5316 100755
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -48,7 +48,7 @@ std::string LLFolderViewModelCommon::getStatusText()
void LLFolderViewModelCommon::filter()
{
- getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
+ getFilter().resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));
mFolderView->getViewModelItem()->filter(getFilter());
}
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 1b61212c0e..b1bcc8bbb4 100755
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -87,12 +87,11 @@ public:
virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0;
// +-------------------------------------------------------------------+
- // + Count
+ // + Time
// +-------------------------------------------------------------------+
- virtual void setFilterCount(S32 count) = 0;
- virtual S32 getFilterCount() const = 0;
- virtual void decrementFilterCount() = 0;
-
+ virtual void resetTime(S32 timeout) = 0;
+ virtual bool isTimedOut() = 0;
+
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
@@ -308,26 +307,28 @@ public:
virtual bool potentiallyVisible()
{
return passedFilter() // we've passed the filter
- || getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet
+ || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet
|| descendantsPassedFilter();
}
virtual bool passedFilter(S32 filter_generation = -1)
{
- if (filter_generation < 0)
+ if (filter_generation < 0)
+ {
filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
-
- bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation;
- bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation;
- return passed_folder_filter
- && (descendantsPassedFilter(filter_generation)
- || passed_filter);
+ }
+ bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation);
+ bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation);
+ return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));
}
virtual bool descendantsPassedFilter(S32 filter_generation = -1)
{
- if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
- return mMostFilteredDescendantGeneration >= filter_generation;
+ if (filter_generation < 0)
+ {
+ filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
+ }
+ return mMostFilteredDescendantGeneration >= filter_generation;
}
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index e33ac1d5c2..c89c0203b4 100755
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -214,8 +214,15 @@ LLLayoutStack::Params::Params()
open_time_constant("open_time_constant", 0.02f),
close_time_constant("close_time_constant", 0.03f),
resize_bar_overlap("resize_bar_overlap", 1),
- border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
-{}
+ border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)),
+ show_drag_handle("show_drag_handle", false),
+ drag_handle_first_indent("drag_handle_first_indent", 0),
+ drag_handle_second_indent("drag_handle_second_indent", 0),
+ drag_handle_thickness("drag_handle_thickness", 5),
+ drag_handle_shift("drag_handle_shift", 2)
+{
+ addSynonym(border_size, "drag_handle_gap");
+}
LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
: LLView(p),
@@ -227,8 +234,14 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
mClip(p.clip),
mOpenTimeConstant(p.open_time_constant),
mCloseTimeConstant(p.close_time_constant),
- mResizeBarOverlap(p.resize_bar_overlap)
-{}
+ mResizeBarOverlap(p.resize_bar_overlap),
+ mShowDragHandle(p.show_drag_handle),
+ mDragHandleFirstIndent(p.drag_handle_first_indent),
+ mDragHandleSecondIndent(p.drag_handle_second_indent),
+ mDragHandleThickness(p.drag_handle_thickness),
+ mDragHandleShift(p.drag_handle_shift)
+{
+}
LLLayoutStack::~LLLayoutStack()
{
@@ -262,6 +275,26 @@ void LLLayoutStack::draw()
drawChild(panelp, 0, 0, !clip_rect.isEmpty());
}
}
+
+ const LLView::child_list_t * child_listp = getChildList();
+ BOOST_FOREACH(LLView * childp, * child_listp)
+ {
+ LLResizeBar * resize_barp = dynamic_cast<LLResizeBar*>(childp);
+ if (resize_barp && resize_barp->isShowDragHandle() && resize_barp->getVisible() && resize_barp->getRect().isValid())
+ {
+ LLRect screen_rect = resize_barp->calcScreenRect();
+ if (LLUI::getRootView()->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
+ {
+ LLUI::pushMatrix();
+ {
+ const LLRect& rb_rect(resize_barp->getRect());
+ LLUI::translate(rb_rect.mLeft, rb_rect.mBottom);
+ resize_barp->draw();
+ }
+ LLUI::popMatrix();
+ }
+ }
+ }
}
void LLLayoutStack::removeChild(LLView* view)
@@ -390,7 +423,6 @@ void LLLayoutStack::updateLayout()
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim);
- F32 panel_visible_dim = panelp->getVisibleDim();
LLRect panel_rect;
if (mOrientation == HORIZONTAL)
@@ -407,27 +439,61 @@ void LLLayoutStack::updateLayout()
getRect().getWidth(),
llround(panel_dim));
}
- panelp->setIgnoreReshape(true);
- panelp->setShape(panel_rect);
- panelp->setIgnoreReshape(false);
LLRect resize_bar_rect(panel_rect);
-
+ LLResizeBar * resize_barp = panelp->getResizeBar();
+ bool show_drag_handle = resize_barp->isShowDragHandle();
F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount();
+ F32 panel_visible_dim = panelp->getVisibleDim();
+ S32 panel_spacing_round = (S32)(llround(panel_spacing));
+
if (mOrientation == HORIZONTAL)
{
- resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
- resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap;
-
cur_pos += panel_visible_dim + panel_spacing;
+
+ if (show_drag_handle && panel_spacing_round > mDragHandleThickness)
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift;
+ resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness;
+ }
+ else
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
+ resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap;
+ }
+
+ if (show_drag_handle)
+ {
+ resize_bar_rect.mBottom += mDragHandleSecondIndent;
+ resize_bar_rect.mTop -= mDragHandleFirstIndent;
+ }
+
}
else //VERTICAL
{
- resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
- resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap;
-
cur_pos -= panel_visible_dim + panel_spacing;
+
+ if (show_drag_handle && panel_spacing_round > mDragHandleThickness)
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift;
+ resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness;
+ }
+ else
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
+ resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap;
+ }
+
+ if (show_drag_handle)
+ {
+ resize_bar_rect.mLeft += mDragHandleFirstIndent;
+ resize_bar_rect.mRight -= mDragHandleSecondIndent;
+ }
}
+
+ panelp->setIgnoreReshape(true);
+ panelp->setShape(panel_rect);
+ panelp->setIgnoreReshape(false);
panelp->mResizeBar->setShape(resize_bar_rect);
}
@@ -475,14 +541,13 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)
{
if (lp->mResizeBar == NULL)
{
- LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
-
LLResizeBar::Params resize_params;
resize_params.name("resize");
resize_params.resizing_view(lp);
resize_params.min_size(lp->getRelevantMinDim());
- resize_params.side(side);
+ resize_params.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM);
resize_params.snapping_enabled(false);
+ resize_params.show_drag_handle(mShowDragHandle);
LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
lp->mResizeBar = resize_bar;
LLView::addChild(resize_bar, 0);
@@ -864,3 +929,4 @@ void LLLayoutStack::updateResizeBarLimits()
previous_visible_panelp = visible_panelp;
}
}
+
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 02c664f1a0..b570974bd6 100755
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -62,6 +62,11 @@ public:
Optional<F32> open_time_constant,
close_time_constant;
Optional<S32> resize_bar_overlap;
+ Optional<bool> show_drag_handle;
+ Optional<S32> drag_handle_first_indent;
+ Optional<S32> drag_handle_second_indent;
+ Optional<S32> drag_handle_thickness;
+ Optional<S32> drag_handle_shift;
Params();
};
@@ -126,6 +131,11 @@ private:
F32 mCloseTimeConstant;
bool mNeedsLayout;
S32 mResizeBarOverlap;
+ bool mShowDragHandle;
+ S32 mDragHandleFirstIndent;
+ S32 mDragHandleSecondIndent;
+ S32 mDragHandleThickness;
+ S32 mDragHandleShift;
}; // end class LLLayoutStack
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index f7bf39c897..f854e1785d 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3146,6 +3146,13 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
const S32 CURSOR_WIDTH = 12;
+ if (menu->getChildList()->empty())
+ {
+ return;
+ }
+
+ menu->setVisible( TRUE );
+
//Do not show menu if all menu items are disabled
BOOL item_enabled = false;
for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin();
@@ -3156,8 +3163,9 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
item_enabled = item_enabled || menu_item->getEnabled();
}
- if(menu->getChildList()->empty() || !item_enabled)
+ if(!item_enabled)
{
+ menu->setVisible( FALSE );
return;
}
@@ -3173,8 +3181,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
menu->mFirstVisibleItem = NULL;
}
- menu->setVisible( TRUE );
-
// Fix menu rect if needed.
menu->needsArrange();
menu->arrangeAndClear();
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 15e56cbfe5..e67b22c977 100755
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -28,14 +28,53 @@
#include "llresizebar.h"
+#include "lllocalcliprect.h"
#include "llmath.h"
#include "llui.h"
#include "llmenugl.h"
#include "llfocusmgr.h"
#include "llwindow.h"
+class LLImagePanel : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<bool> horizontal;
+ Params() : horizontal("horizontal", false) {}
+ };
+ LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {}
+ virtual ~LLImagePanel() {}
+
+ void draw()
+ {
+ const LLRect& parent_rect = getParent()->getRect();
+ const LLRect& rect = getRect();
+ LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2
+ , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom);
+ LLLocalClipRect clip(clip_rect);
+ LLPanel::draw();
+ }
+
+private:
+ bool mHorizontal;
+};
+
+static LLDefaultChildRegistry::Register<LLImagePanel> t1("resize_bar_image_panel");
+
+LLResizeBar::Params::Params()
+: max_size("max_size", S32_MAX),
+ snapping_enabled("snapping_enabled", true),
+ resizing_view("resizing_view"),
+ side("side"),
+ allow_double_click_snapping("allow_double_click_snapping", true),
+ show_drag_handle("show_drag_handle", false)
+{
+ name = "resize_bar";
+}
+
LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
-: LLView(p),
+: LLPanel(p),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
@@ -46,7 +85,9 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
mSnappingEnabled(p.snapping_enabled),
mAllowDoubleClickSnapping(p.allow_double_click_snapping),
mResizingView(p.resizing_view),
- mResizeListener(NULL)
+ mResizeListener(NULL),
+ mShowDragHandle(p.show_drag_handle),
+ mImagePanel(NULL)
{
setFollowsNone();
// set up some generically good follow code.
@@ -75,8 +116,37 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
default:
break;
}
+
+ if (mShowDragHandle)
+ {
+ LLViewBorder::Params border_params;
+ border_params.border_thickness = 1;
+ border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight");
+ border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark");
+
+ addBorder(border_params);
+ setBorderVisible(TRUE);
+
+ LLImagePanel::Params image_panel;
+ mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle");
+ image_panel.bg_alpha_image = mDragHandleImage;
+ image_panel.background_visible = true;
+ image_panel.horizontal = (LLResizeBar::BOTTOM == mSide);
+ mImagePanel = LLUICtrlFactory::create<LLImagePanel>(image_panel);
+ setImagePanel(mImagePanel);
+ }
}
+BOOL LLResizeBar::postBuild()
+{
+ if (mShowDragHandle)
+ {
+ setBackgroundVisible(TRUE);
+ setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody"));
+ }
+
+ return LLPanel::postBuild();
+}
BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -342,3 +412,39 @@ BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)
return TRUE;
}
+void LLResizeBar::setImagePanel(LLPanel * panelp)
+{
+ const LLView::child_list_t * children = getChildList();
+ if (getChildCount() == 2)
+ {
+ LLPanel * image_panelp = dynamic_cast<LLPanel*>(children->back());
+ if (image_panelp)
+ {
+ removeChild(image_panelp);
+ delete image_panelp;
+ }
+ }
+
+ addChild(panelp);
+ sendChildToBack(panelp);
+}
+
+LLPanel * LLResizeBar::getImagePanel() const
+{
+ return getChildCount() > 0 ? (LLPanel *)getChildList()->back() : NULL;
+}
+
+void LLResizeBar::draw()
+{
+ if (mShowDragHandle)
+ {
+ S32 image_width = mDragHandleImage->getTextureWidth();
+ S32 image_height = mDragHandleImage->getTextureHeight();
+ const LLRect& panel_rect = getRect();
+ S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1;
+ S32 image_bottom = (panel_rect.getHeight() - image_height) / 2;
+ mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom));
+ }
+
+ LLPanel::draw();
+}
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index 8190a95a71..bcf8ea0b40 100755
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -27,15 +27,14 @@
#ifndef LL_RESIZEBAR_H
#define LL_RESIZEBAR_H
-#include "llview.h"
-#include "llcoord.h"
+#include "llpanel.h"
-class LLResizeBar : public LLView
+class LLResizeBar : public LLPanel
{
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM };
- struct Params : public LLInitParam::Block<Params, LLView::Params>
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Mandatory<LLView*> resizing_view;
Mandatory<Side> side;
@@ -44,24 +43,19 @@ public:
Optional<S32> max_size;
Optional<bool> snapping_enabled;
Optional<bool> allow_double_click_snapping;
+ Optional<bool> show_drag_handle;
- Params()
- : max_size("max_size", S32_MAX),
- snapping_enabled("snapping_enabled", true),
- resizing_view("resizing_view"),
- side("side"),
- allow_double_click_snapping("allow_double_click_snapping", true)
- {
- name = "resize_bar";
- }
+ Params();
};
protected:
LLResizeBar(const LLResizeBar::Params& p);
friend class LLUICtrlFactory;
+
+ /*virtual*/ BOOL postBuild();
public:
-// virtual void draw(); No appearance
+ virtual void draw();
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -72,20 +66,26 @@ public:
void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }
bool canResize() { return getEnabled() && mMaxSize > mMinSize; }
void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;}
+ BOOL isShowDragHandle() const { return mShowDragHandle; }
+ void setImagePanel(LLPanel * panelp);
+ LLPanel * getImagePanel() const;
private:
- S32 mDragLastScreenX;
- S32 mDragLastScreenY;
- S32 mLastMouseScreenX;
- S32 mLastMouseScreenY;
- LLCoordGL mLastMouseDir;
- S32 mMinSize;
- S32 mMaxSize;
- const Side mSide;
- BOOL mSnappingEnabled;
- BOOL mAllowDoubleClickSnapping;
- LLView* mResizingView;
- boost::function<void(void*)> mResizeListener;
+ S32 mDragLastScreenX;
+ S32 mDragLastScreenY;
+ S32 mLastMouseScreenX;
+ S32 mLastMouseScreenY;
+ LLCoordGL mLastMouseDir;
+ S32 mMinSize;
+ S32 mMaxSize;
+ const Side mSide;
+ BOOL mSnappingEnabled;
+ BOOL mAllowDoubleClickSnapping;
+ BOOL mShowDragHandle;
+ LLView* mResizingView;
+ boost::function<void(void*)> mResizeListener;
+ LLPointer<LLUIImage> mDragHandleImage;
+ LLPanel * mImagePanel;
};
#endif // LL_RESIZEBAR_H
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index e70992129a..391e6fd005 100755
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -653,6 +653,10 @@ void LLTextBase::drawText()
mSpellCheckEnd = end;
}
}
+ else
+ {
+ mMisspellRanges.clear();
+ }
LLTextSegmentPtr cur_segment = *seg_iter;
@@ -2602,21 +2606,18 @@ void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool
void LLTextBase::changeLine( S32 delta )
{
S32 line = getLineNumFromDocIndex(mCursorPos);
-
- S32 new_line = line;
- if( (delta < 0) && (line > 0 ) )
- {
- new_line = line - 1;
- }
- else if( (delta > 0) && (line < (getLineCount() - 1)) )
- {
- new_line = line + 1;
- }
-
- LLRect visible_region = getVisibleDocumentRect();
-
- S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
- setCursorPos(new_cursor_pos, true);
+ S32 max_line_nb = getLineCount() - 1;
+ max_line_nb = (max_line_nb < 0 ? 0 : max_line_nb);
+
+ S32 new_line = llclamp(line + delta, 0, max_line_nb);
+
+ if (new_line != line)
+ {
+ LLRect visible_region = getVisibleDocumentRect();
+ S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel,
+ mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
+ setCursorPos(new_cursor_pos, true);
+ }
}
bool LLTextBase::scrolledToStart()
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 834f213097..09caec7b73 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1964,8 +1964,7 @@ void LLTextEditor::onFocusReceived()
updateAllowingLanguageInput();
}
-// virtual, from LLView
-void LLTextEditor::onFocusLost()
+void LLTextEditor::focusLostHelper()
{
updateAllowingLanguageInput();
@@ -1982,7 +1981,11 @@ void LLTextEditor::onFocusLost()
// Make sure cursor is shown again
getWindow()->showCursorFromMouseMove();
+}
+void LLTextEditor::onFocusLost()
+{
+ focusLostHelper();
LLTextBase::onFocusLost();
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 969e072704..13f63a17ef 100755
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -255,6 +255,7 @@ protected:
S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
S32 remove(S32 pos, S32 length, bool group_with_next_op);
+ void focusLostHelper();
void updateAllowingLanguageInput();
BOOL hasPreeditString() const;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 43c0090993..ca9410de2e 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -159,9 +159,8 @@ LLWinImm LLWinImm::sTheInstance;
LLWinImm::LLWinImm() : mHImmDll(NULL)
{
// Check system metrics
- if ( !GetSystemMetrics( SM_DBCSENABLED ) )
+ if ( !GetSystemMetrics( SM_IMMENABLED ) )
return;
-
mHImmDll = LoadLibraryA("Imm32");
if (mHImmDll != NULL)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 31c730e0bc..f22dd576c3 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3457,16 +3457,27 @@
<key>Value</key>
<real>10.0</real>
</map>
- <key>FilterItemsPerFrame</key>
+ <key>FilterItemsMaxTimePerFrameVisible</key>
<map>
- <key>Comment</key>
- <string>Maximum number of inventory items to match against search filter every frame (lower to increase framerate while searching, higher to improve search speed)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>500</integer>
+ <key>Comment</key>
+ <string>Max time devoted to items filtering per frame for visible inventory listings (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>10</integer>
+ </map>
+ <key>FilterItemsMaxTimePerFrameUnvisible</key>
+ <map>
+ <key>Comment</key>
+ <string>Max time devoted to items filtering per frame for non visible inventory listings (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
</map>
<key>FindLandArea</key>
<map>
@@ -6398,7 +6409,10 @@
<key>NotificationConferenceIMOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Conference IM Notifications.</string>
+ <string>
+ Specifies how the UI responds to Conference IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6409,7 +6423,10 @@
<key>NotificationFriendIMOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Friend IM Notifications.</string>
+ <string>
+ Specifies how the UI responds to Friend IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6420,7 +6437,10 @@
<key>NotificationGroupChatOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Group Chat Notifications.</string>
+ <string>
+ Specifies how the UI responds to Group Chat Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6431,7 +6451,10 @@
<key>NotificationNearbyChatOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Nearby Chat Notifications.</string>
+ <string>
+ Specifies how the UI responds to Nearby Chat Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6442,7 +6465,10 @@
<key>NotificationNonFriendIMOptions</key>
<map>
<key>Comment</key>
- <string>Specifies how the UI responds to Non Friend IM Notifications.</string>
+ <string>
+ Specifies how the UI responds to Non Friend IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6450,6 +6476,20 @@
<key>Value</key>
<string>toast</string>
</map>
+ <key>NotificationObjectIMOptions</key>
+ <map>
+ <key>Comment</key>
+ <string>
+ Specifies how the UI responds to Object IM Notifications.
+ Allowed values: [openconversations,toast,flash,noaction]
+ </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>noaction</string>
+ </map>
<key>NotificationToastLifeTime</key>
<map>
<key>Comment</key>
@@ -6988,6 +7028,72 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>PlaySoundFriendIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when friend's IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundNonFriendIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when non-friend's IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundConferenceIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when conference IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundGroupChatIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when group chat IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundNearbyChatIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when nearby chat IM received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>PlaySoundObjectIM</key>
+ <map>
+ <key>Comment</key>
+ <string>Plays a sound when IM fom an object received.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>PlaySoundNewConversation</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 8c42defa73..d16945070a 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -46,6 +46,7 @@
#include "llenvmanager.h"
#include "llfirstuse.h"
#include "llfloatercamera.h"
+#include "llfloaterimcontainer.h"
#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llgroupactions.h"
@@ -91,6 +92,7 @@
#include "llworld.h"
#include "llworldmap.h"
#include "stringize.h"
+#include "boost/foreach.hpp"
using namespace LLAvatarAppearanceDefines;
@@ -2037,7 +2039,16 @@ void LLAgent::endAnimationUpdateUI()
{
skip_list.insert(LLFloaterReg::findInstance("mini_map"));
}
-
+
+ LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+ LLFloaterIMContainer::floater_list_t conversations;
+ im_box->getDetachedConversationFloaters(conversations);
+ BOOST_FOREACH(LLFloater* conversation, conversations)
+ {
+ llinfos << "skip_list.insert(session_floater): " << conversation->getTitle() << llendl;
+ skip_list.insert(conversation);
+ }
+
gFloaterView->popVisibleAll(skip_list);
#endif
mViewsPushed = FALSE;
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index c74ce24872..6e95df8383 100755
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -386,6 +386,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)
addVoiceOptions(items);
items.push_back(std::string("chat_history"));
}
+ else if(this->getType() == CONV_SESSION_NEARBY)
+ {
+ items.push_back(std::string("chat_history"));
+ }
hide_context_entries(menu, items, disabled_items);
}
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 8766585049..d8cdcdfc97 100755
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -252,11 +252,10 @@ public:
const std::string& getName() const { return mEmpty; }
const std::string& getFilterText() { return mEmpty; }
void setModified(EFilterModified behavior = FILTER_RESTART) { }
-
- void setFilterCount(S32 count) { }
- S32 getFilterCount() const { return 0; }
- void decrementFilterCount() { }
-
+
+ void resetTime(S32 timeout) { }
+ bool isTimedOut() { return false; }
+
bool isDefault() const { return true; }
bool isNotDefault() const { return false; }
void markDefault() { }
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index b6c53e5e30..42104ea20a 100755
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -118,6 +118,13 @@ void LLConversationViewSession::setFlashState(bool flash_state)
mFlashTimer->stopFlashing();
}
+void LLConversationViewSession::setHighlightState(bool hihglight_state)
+{
+ mFlashStateOn = hihglight_state;
+ mFlashStarted = true;
+ mFlashTimer->stopFlashing();
+}
+
void LLConversationViewSession::startFlashing()
{
if (isInVisibleChain() && mFlashStateOn && !mFlashStarted)
@@ -340,16 +347,20 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)
{
// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized
// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here
- LLFolderViewModelItem* item = mViewModelItem;
- LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
- LLFloater* session_floater = LLFloaterIMSessionTab::getConversation(session_uuid);
-
- if (session_floater && !session_floater->getHost() && !session_floater->isMinimized())
+ LLFloater* session_floater = getSessionFloater();
+ if (session_floater && session_floater->isDetachedAndNotMinimized())
{
session_floater->setVisible(visible);
}
}
+LLFloater* LLConversationViewSession::getSessionFloater()
+{
+ LLFolderViewModelItem* item = mViewModelItem;
+ LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
+ return LLFloaterIMSessionTab::getConversation(session_uuid);
+}
+
LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id)
{
// This is *not* a general tree parsing algorithm. We search only in the mItems list
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index 3eb2e63792..879d496dc7 100755
--- a/indra/newview/llconversationview.h
+++ b/indra/newview/llconversationview.h
@@ -86,6 +86,9 @@ public:
virtual void refresh();
/*virtual*/ void setFlashState(bool flash_state);
+ void setHighlightState(bool hihglight_state);
+
+ LLFloater* getSessionFloater();
private:
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 82affcf068..71bc4f15d2 100755
--- a/indra/newview/lldonotdisturbnotificationstorage.cpp
+++ b/indra/newview/lldonotdisturbnotificationstorage.cpp
@@ -115,7 +115,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications()
{
LLNotificationPtr notificationPtr = historyIter->second;
- if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired())
+ if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() &&
+ !notificationPtr->isExpired() && !notificationPtr->isPersistent())
{
data.append(notificationPtr->asLLSD(true));
}
@@ -210,12 +211,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
}
- if(imToastExists)
- {
- LLFloaterReg::showInstance("im_container");
- }
-
- if(group_ad_hoc_toast_exists)
+ bool isConversationLoggingAllowed = gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
+ if(group_ad_hoc_toast_exists && isConversationLoggingAllowed)
{
LLFloaterReg::showInstance("conversation");
}
@@ -266,11 +263,6 @@ void LLDoNotDisturbNotificationStorage::updateNotifications()
}
}
- if(imToastExists)
- {
- LLFloaterReg::showInstance("im_container");
- }
-
if(imToastExists || offerExists)
{
make_ui_sound("UISndNewIncomingIMSession");
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 58817485fb..700bc94105 100755
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -54,6 +54,7 @@
#include "llworld.h"
#include "llsdserialize.h"
#include "llviewerobjectlist.h"
+#include "boost/foreach.hpp"
//
// LLFloaterIMContainer
@@ -63,7 +64,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mExpandCollapseBtn(NULL),
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
- mInitialized(false)
+ mInitialized(false),
+ mIsFirstLaunch(true)
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@@ -204,6 +206,7 @@ BOOL LLFloaterIMContainer::postBuild()
// a scroller for folder view
LLRect scroller_view_rect = mConversationsListPanel->getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ scroller_view_rect.mBottom += getChild<LLLayoutStack>("conversations_pane_buttons_stack")->getRect().getHeight();
LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());
scroller_params.rect(scroller_view_rect);
@@ -221,7 +224,8 @@ BOOL LLFloaterIMContainer::postBuild()
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this));
mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn");
mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this));
- getChild<LLButton>("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));
+ mSpeakBtn = getChild<LLButton>("speak_btn");
+ mSpeakBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));
childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this));
@@ -659,10 +663,32 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLMultiFloater::setVisible(visible);
}
+void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& floaters)
+{
+ typedef conversations_widgets_map::value_type conv_pair;
+ BOOST_FOREACH(conv_pair item, mConversationsWidgets)
+ {
+ LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(item.second);
+ if (widget)
+ {
+ LLFloater* session_floater = widget->getSessionFloater();
+ if (session_floater && session_floater->isDetachedAndNotMinimized())
+ {
+ floaters.push_back(session_floater);
+ }
+ }
+ }
+}
+
void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLMultiFloater::setVisibleAndFrontmost(take_focus, key);
selectConversationPair(getSelectedSession(), false, take_focus);
+ if (mInitialized && mIsFirstLaunch)
+ {
+ collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed"));
+ mIsFirstLaunch = false;
+ }
}
void LLFloaterIMContainer::updateResizeLimits()
@@ -779,13 +805,6 @@ void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 d
setCanMinimize(at_least_one_panel_is_expanded);
assignResizeLimits();
-
- // force set correct size for the title after show/hide minimize button
- LLRect cur_rect = getRect();
- LLRect force_rect = cur_rect;
- force_rect.mRight = cur_rect.mRight + 1;
- setRect(force_rect);
- setRect(cur_rect);
}
void LLFloaterIMContainer::assignResizeLimits()
@@ -793,15 +812,12 @@ void LLFloaterIMContainer::assignResizeLimits()
bool is_conv_pane_expanded = !mConversationsPane->isCollapsed();
bool is_msg_pane_expanded = !mMessagesPane->isCollapsed();
- // With two panels visible number of borders is three, because the borders
- // between the panels are merged into one
- S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3);
- S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH;
- S32 conv_pane_target_width = is_conv_pane_expanded?
- (is_msg_pane_expanded?
- mConversationsPane->getRect().getWidth()
- : mConversationsPane->getExpandedMinDim())
- : mConversationsPane->getMinDim();
+ S32 summary_width_of_visible_borders = (is_msg_pane_expanded ? mConversationsStack->getPanelSpacing() : 0) + 1;
+
+ S32 conv_pane_target_width = is_conv_pane_expanded
+ ? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() )
+ : mConversationsPane->getMinDim();
+
S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0;
S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders;
@@ -1143,7 +1159,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
}
else if("chat_history" == command)
{
- if (selectedIDS.size() > 0)
+ if (selectedIDS.size() > 0)
{
LLAvatarActions::viewChatHistory(selectedIDS.front());
}
@@ -1156,6 +1172,17 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
}
}
}
+ //if there is no LLFloaterIMSession* instance for selected conversation it might be Nearby chat
+ else
+ {
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_NEARBY)
+ {
+ if("chat_history" == command)
+ {
+ LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true);
+ }
+ }
+ }
}
void LLFloaterIMContainer::doToSelected(const LLSD& userdata)
@@ -1185,7 +1212,7 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata)
if (action == "group_profile")
{
- LLGroupActions::show(mSelectedSession);
+ LLGroupActions::show(mSelectedSession);
}
else if (action == "activate_group")
{
@@ -1211,7 +1238,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
//Enable Chat history item for ad-hoc and group conversations
if ("can_chat_history" == item && uuids.size() > 0)
{
- return LLLogChat::isTranscriptExist(uuids.front());
+ //Disable menu item if selected participant is user agent
+ if(uuids.front() != gAgentID)
+ {
+ if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_NEARBY)
+ {
+ return LLLogChat::isNearbyTranscriptExist();
+ }
+ else
+ {
+ bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP);
+ return LLLogChat::isTranscriptExist(uuids.front(),is_group);
+ }
+ }
}
// If nothing is selected(and selected item is not group chat), everything needs to be disabled
@@ -1904,7 +1943,6 @@ void LLFloaterIMContainer::reSelectConversation()
void LLFloaterIMContainer::updateSpeakBtnState()
{
- LLButton* mSpeakBtn = getChild<LLButton>("speak_btn");
mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState());
mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak"));
}
@@ -1925,6 +1963,17 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id,
}
}
+void LLFloaterIMContainer::highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted)
+{
+ //Finds the conversation line item to highlight using the session_id
+ LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id));
+
+ if (widget)
+ {
+ widget->setHighlightState(is_highlighted);
+ }
+}
+
bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget)
{
llassert(conversation_item_widget != NULL);
@@ -1940,23 +1989,28 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve
BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )
{
+ BOOL handled = FALSE;
+
if(mask == MASK_ALT)
{
if (KEY_RETURN == key )
{
expandConversation();
+ handled = TRUE;
}
if ((KEY_DOWN == key ) || (KEY_RIGHT == key))
{
selectNextorPreviousConversation(true);
+ handled = TRUE;
}
if ((KEY_UP == key) || (KEY_LEFT == key))
{
selectNextorPreviousConversation(false);
+ handled = TRUE;
}
}
- return TRUE;
+ return handled;
}
bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected)
@@ -2013,7 +2067,18 @@ void LLFloaterIMContainer::expandConversation()
}
}
-void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
+// By default, if torn off session is currently frontmost, LLFloater::isFrontmost() will return FALSE, which can lead to some bugs
+// So LLFloater::isFrontmost() is overriden here to check both selected session and the IM floater itself
+/*virtual*/
+BOOL LLFloaterIMContainer::isFrontmost()
+{
+ LLFloaterIMSessionTab* selected_session = LLFloaterIMSessionTab::getConversation(mSelectedSession);
+ return (selected_session && selected_session->isFrontmost()) || LLFloater::isFrontmost();
+}
+
+// For conversations, closeFloater() (linked to Ctrl-W) does not actually close the floater but the active conversation.
+// This is intentional so it doesn't confuse the user. onClickCloseBtn() closes the whole floater.
+void LLFloaterIMContainer::onClickCloseBtn()
{
// Always unminimize before trying to close.
// Most of the time the user will never see this state.
@@ -2022,7 +2087,64 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
LLMultiFloater::setMinimized(FALSE);
}
- LLFloater::closeFloater(app_quitting);
+ LLFloater::closeFloater();
+}
+
+void LLFloaterIMContainer::closeHostedFloater()
+{
+ onClickCloseBtn();
+}
+
+void LLFloaterIMContainer::closeAllConversations()
+{
+ conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
+ for (;widget_it != mConversationsWidgets.end(); ++widget_it)
+ {
+ if (widget_it->first != LLUUID())
+ {
+ LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second);
+ if (widget)
+ {
+ widget->destroyView();
+ mConversationsItems.erase(widget_it->first);
+ mConversationsWidgets.erase(widget_it->first);
+ }
+ }
+ }
+}
+void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
+{
+ if(app_quitting)
+ {
+ gAgent.setDoNotDisturb(true);
+ closeAllConversations();
+ }
+
+ // Check for currently active session
+ LLUUID session_id = getSelectedSession();
+ // If current session is Nearby Chat or there is only one session remaining, close the floater
+ if (mConversationsItems.size() == 1 || session_id == LLUUID() || app_quitting)
+ {
+ onClickCloseBtn();
+ }
+
+ // Otherwise, close current conversation
+ LLFloaterIMSessionTab* active_conversation = LLFloaterIMSessionTab::getConversation(session_id);
+ if (active_conversation)
+ {
+ active_conversation->closeFloater();
+ if(app_quitting)
+ {
+ LLFloater::closeFloater(app_quitting);
+ }
+
+ }
+}
+
+void LLFloaterIMContainer::handleReshape(const LLRect& rect, bool by_user)
+{
+ LLMultiFloater::handleReshape(rect, by_user);
+ storeRectControl();
}
// EOF
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index e39d20ec35..5121e902cb 100755
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -63,6 +63,8 @@ public:
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void updateResizeLimits();
+ /*virtual*/ void handleReshape(const LLRect& rect, bool by_user);
+
void onCloseFloater(LLUUID& id);
/*virtual*/ void addFloater(LLFloater* floaterp,
@@ -116,6 +118,9 @@ public:
void assignResizeLimits();
virtual BOOL handleKeyHere(KEY key, MASK mask );
/*virtual*/ void closeFloater(bool app_quitting = false);
+ void closeAllConversations();
+ /*virtual*/ BOOL isFrontmost();
+
private:
typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;
@@ -130,6 +135,8 @@ private:
void onStubCollapseButtonClicked();
void processParticipantsStyleUpdate();
void onSpeakButtonClicked();
+ /*virtual*/ void onClickCloseBtn();
+ /*virtual*/ void closeHostedFloater();
void collapseConversationsPane(bool collapse, bool save_is_allowed=true);
@@ -169,6 +176,7 @@ private:
LLButton* mExpandCollapseBtn;
LLButton* mStubCollapseBtn;
+ LLButton* mSpeakBtn;
LLPanel* mStubPanel;
LLTextBox* mStubTextBox;
LLLayoutPanel* mMessagesPane;
@@ -176,6 +184,7 @@ private:
LLLayoutStack* mConversationsStack;
bool mInitialized;
+ bool mIsFirstLaunch;
LLUUID mSelectedSession;
std::string mGeneralTitle;
@@ -190,9 +199,12 @@ public:
void updateSpeakBtnState();
static bool isConversationLoggingAllowed();
void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes);
+ void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted);
bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget);
boost::signals2::connection mMicroChangedSignal;
S32 getConversationListItemSize() { return mConversationsWidgets.size(); }
+ typedef std::list<LLFloater*> floater_list_t;
+ void getDetachedConversationFloaters(floater_list_t& floaters);
private:
LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 49f36a2f32..7e472466ed 100755
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -568,7 +568,10 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
if (0 == channel)
{
// discard returned "found" boolean
- LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
+ if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text))
+ {
+ utf8_revised_text = utf8text;
+ }
}
else
{
diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp
index 9ce5e12897..cc00b6fd10 100755
--- a/indra/newview/llfloaterimnearbychathandler.cpp
+++ b/indra/newview/llfloaterimnearbychathandler.cpp
@@ -606,6 +606,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
//Don't show nearby toast, if conversation is visible and selected
if ((nearby_chat->hasFocus()) ||
+ (LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()) ||
((im_box->getSelectedSession().isNull() &&
((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost())
|| (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost())))))
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index 8ec85e1160..1de6effa2b 100755
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -109,7 +109,7 @@ void LLFloaterIMSession::refresh()
void LLFloaterIMSession::onTearOffClicked()
{
LLFloaterIMSessionTab::onTearOffClicked();
-
+ mSpeakingIndicator->setVisible(mIsP2PChat);
if(mIsP2PChat)
{
if(isTornOff())
@@ -442,8 +442,11 @@ void LLFloaterIMSession::addSessionParticipants(const uuid_vec_t& uuids)
}
else
{
- // remember whom we have invited, to notify others later, when the invited ones actually join
- mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ if(findInstance(mSessionID))
+ {
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ }
inviteToSession(uuids);
}
@@ -469,13 +472,18 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con
temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end());
// then we can close the current session
- onClose(false);
+ if(findInstance(mSessionID))
+ {
+ onClose(false);
+
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ }
// we start a new session so reset the initialization flag
mSessionInitialized = false;
- // remember whom we have invited, to notify others later, when the invited ones actually join
- mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+
// Start a new ad hoc voice call if we invite new participants to a P2P call,
// or start a text chat otherwise.
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index ce6e639305..cc2859c099 100755
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -212,7 +212,7 @@ void LLFloaterIMSessionTab::assignResizeLimits()
mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);
S32 participants_pane_target_width = is_participants_pane_collapsed?
- 0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH);
+ 0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());
S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
@@ -241,7 +241,10 @@ BOOL LLFloaterIMSessionTab::postBuild()
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
mGearBtn = getChild<LLButton>("gear_btn");
-
+ mAddBtn = getChild<LLButton>("add_btn");
+ mVoiceButton = getChild<LLButton>("voice_call_btn");
+ mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp");
+
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
@@ -372,7 +375,7 @@ void LLFloaterIMSessionTab::draw()
void LLFloaterIMSessionTab::enableDisableCallBtn()
{
- getChildView("voice_call_btn")->setEnabled(
+ mVoiceButton->setEnabled(
mSessionID.notNull()
&& mSession
&& mSession->mSessionInitialized
@@ -758,7 +761,7 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel()
void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)
{
- getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE);
+ mTranslationCheckBox->setVisible(mIsNearbyChat && show);
}
// static
@@ -805,15 +808,10 @@ void LLFloaterIMSessionTab::reloadEmptyFloaters()
void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive)
{
- LLButton* voiceButton = getChild<LLButton>("voice_call_btn");
- voiceButton->setImageOverlay(
- callIsActive? getString("call_btn_stop") : getString("call_btn_start"));
-
- voiceButton->setToolTip(
- callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));
+ mVoiceButton->setImageOverlay(callIsActive? getString("call_btn_stop") : getString("call_btn_start"));
+ mVoiceButton->setToolTip(callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));
enableDisableCallBtn();
-
}
void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
@@ -898,6 +896,7 @@ void LLFloaterIMSessionTab::restoreFloater()
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
setMessagePaneExpanded(true);
saveCollapsedState();
+ mInputEditor->enableSingleLineMode(false);
enableResizeCtrls(true, true, true);
}
}
@@ -953,8 +952,8 @@ void LLFloaterIMSessionTab::updateGearBtn()
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();
+ LLRect add_btn_rect = mAddBtn->getRect();
+ LLRect call_btn_rect = mVoiceButton->getRect();
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
if(mGearBtn->getVisible())
@@ -968,24 +967,24 @@ void LLFloaterIMSessionTab::updateGearBtn()
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);
+ mAddBtn->setRect(add_btn_rect);
+ mVoiceButton->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();
+ LLRect add_btn_rect = mAddBtn->getRect();
+ LLRect call_btn_rect = mVoiceButton->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);
+ mAddBtn->setRect(add_btn_rect);
+ mVoiceButton->setRect(call_btn_rect);
}
// static
@@ -1083,21 +1082,26 @@ void LLFloaterIMSessionTab::saveCollapsedState()
}
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
{
+ BOOL handled = FALSE;
+
if(mask == MASK_ALT)
{
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
if (KEY_RETURN == key && !isTornOff())
{
floater_container->expandConversation();
+ handled = TRUE;
}
if ((KEY_UP == key) || (KEY_LEFT == key))
{
floater_container->selectNextorPreviousConversation(false);
+ handled = TRUE;
}
if ((KEY_DOWN == key ) || (KEY_RIGHT == key))
{
floater_container->selectNextorPreviousConversation(true);
+ handled = TRUE;
}
}
- return TRUE;
+ return handled;
}
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 302d5a8066..ba80d2369a 100755
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -182,6 +182,9 @@ protected:
LLButton* mTearOffBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
+ LLButton* mAddBtn;
+ LLButton* mVoiceButton;
+ LLUICtrl* mTranslationCheckBox;
private:
// Handling selection and contextual menu
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index bbf88060c1..7ada4cfd00 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -452,6 +452,7 @@ BOOL LLFloaterPreference::postBuild()
getChild<LLComboBox>("ConferenceIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ConferenceIMOptions"));
getChild<LLComboBox>("GroupChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"GroupChatOptions"));
getChild<LLComboBox>("NearbyChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NearbyChatOptions"));
+ getChild<LLComboBox>("ObjectIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ObjectIMOptions"));
// if floater is opened before login set default localized do not disturb message
if (LLStartUp::getStartupState() < STATE_STARTED)
@@ -721,6 +722,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
onNotificationsChange("ConferenceIMOptions");
onNotificationsChange("GroupChatOptions");
onNotificationsChange("NearbyChatOptions");
+ onNotificationsChange("ObjectIMOptions");
LLPanelLogin::setAlwaysRefresh(true);
refresh();
@@ -928,7 +930,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName)
bool show_notifications_alert = true;
for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++)
{
- if(it_notification->second != "None")
+ if(it_notification->second != "No action")
{
show_notifications_alert = false;
break;
diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp
index 586965e5a0..c28657dbcd 100755
--- a/indra/newview/llfolderviewmodelinventory.cpp
+++ b/indra/newview/llfolderviewmodelinventory.cpp
@@ -74,6 +74,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
it != end_it;
++it)
{
+ // Recursive call to sort() on child (CHUI-849)
LLFolderViewFolder* child_folderp = *it;
sort(child_folderp);
@@ -129,12 +130,12 @@ void LLFolderViewModelItemInventory::requestSort()
void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size)
{
LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size);
-
- bool passed_filter_before = mPrevPassedAllFilters;
+ bool before = mPrevPassedAllFilters;
mPrevPassedAllFilters = passedFilter(filter_generation);
- if (passed_filter_before != mPrevPassedAllFilters)
+ if (before != mPrevPassedAllFilters)
{
+ // Need to rearrange the folder if the filtered state of the item changed
LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder();
if (parent_folder)
{
@@ -150,11 +151,11 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite
bool continue_filtering = true;
if (item->getLastFilterGeneration() < filter_generation)
{
- // recursive application of the filter for child items
+ // Recursive application of the filter for child items (CHUI-849)
continue_filtering = item->filter( filter );
}
- // track latest generation to pass any child items, for each folder up to root
+ // Update latest generation to pass filter in parent and propagate up to root
if (item->passedFilter())
{
LLFolderViewModelItemInventory* view_model = this;
@@ -174,53 +175,61 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter)
const S32 filter_generation = filter.getCurrentGeneration();
const S32 must_pass_generation = filter.getFirstRequiredGeneration();
- if (getLastFilterGeneration() >= must_pass_generation
+ if (getLastFilterGeneration() >= must_pass_generation
&& getLastFolderFilterGeneration() >= must_pass_generation
&& !passedFilter(must_pass_generation))
{
// failed to pass an earlier filter that was a subset of the current one
- // go ahead and flag this item as done
+ // go ahead and flag this item as not pass
setPassedFilter(false, filter_generation);
setPassedFolderFilter(false, filter_generation);
return true;
}
- const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)
- ? filter.checkFolder(this)
- : true;
+ // *TODO : Revise the logic for fast pass on less restrictive filter case
+ /*
+ const S32 sufficient_pass_generation = filter.getFirstSuccessGeneration();
+ if (getLastFilterGeneration() >= sufficient_pass_generation
+ && getLastFolderFilterGeneration() >= sufficient_pass_generation
+ && passedFilter(sufficient_pass_generation))
+ {
+ // passed an earlier filter that was a superset of the current one
+ // go ahead and flag this item as pass
+ setPassedFilter(true, filter_generation);
+ setPassedFolderFilter(true, filter_generation);
+ return true;
+ }
+ */
+
+ const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) ? filter.checkFolder(this) : true;
setPassedFolderFilter(passed_filter_folder, filter_generation);
- if(!mChildren.empty()
+ bool continue_filtering = true;
+
+ if (!mChildren.empty()
&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass
- || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
+ || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
{
// now query children
- for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end();
- iter != end_iter && filter.getFilterCount() > 0;
- ++iter)
+ for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); iter != end_iter; ++iter)
{
- if (!filterChildItem((*iter), filter))
+ continue_filtering = filterChildItem((*iter), filter);
+ if (!continue_filtering)
{
break;
}
}
}
- // if we didn't use all filter iterations
- // that means we filtered all of our descendants
- // so filter ourselves now
- if (filter.getFilterCount() > 0)
+ // If we didn't use all the filter time that means we filtered all of our descendants so we can filter ourselves now
+ if (continue_filtering)
{
- filter.decrementFilterCount();
-
+ // This is where filter check on the item done (CHUI-849)
const bool passed_filter = filter.check(this);
setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize());
- return true;
- }
- else
- {
- return false;
+ continue_filtering = !filter.isTimedOut();
}
+ return continue_filtering;
}
LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel()
@@ -307,8 +316,8 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a,
}
}
-LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )
- : LLFolderViewModelItemCommon(root_view_model),
- mPrevPassedAllFilters(false)
+LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) :
+ LLFolderViewModelItemCommon(root_view_model),
+ mPrevPassedAllFilters(false)
{
}
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 890d03d1c9..9dcfdfa185 100755
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -59,9 +59,8 @@ public:
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
virtual LLToolDragAndDrop::ESource getDragSource() const = 0;
-
protected:
- bool mPrevPassedAllFilters;
+ bool mPrevPassedAllFilters;
};
class LLInventorySort
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index a0f2918bd7..302d21c2e4 100755
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -116,6 +116,80 @@ public:
};
LLGroupHandler gGroupHandler;
+// This object represents a pending request for specified group member information
+// which is needed to check whether avatar can leave group
+class LLFetchGroupMemberData : public LLGroupMgrObserver
+{
+public:
+ LLFetchGroupMemberData(const LLUUID& group_id) :
+ mGroupId(group_id),
+ mRequestProcessed(false),
+ LLGroupMgrObserver(group_id)
+ {
+ llinfos << "Sending new group member request for group_id: "<< group_id << llendl;
+ LLGroupMgr* mgr = LLGroupMgr::getInstance();
+ // register ourselves as an observer
+ mgr->addObserver(this);
+ // send a request
+ mgr->sendGroupPropertiesRequest(group_id);
+ mgr->sendCapGroupMembersRequest(group_id);
+ }
+
+ ~LLFetchGroupMemberData()
+ {
+ if (!mRequestProcessed)
+ {
+ // Request is pending
+ llwarns << "Destroying pending group member request for group_id: "
+ << mGroupId << llendl;
+ }
+ // Remove ourselves as an observer
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+
+ void changed(LLGroupChange gc)
+ {
+ if (gc == GC_MEMBER_DATA && !mRequestProcessed)
+ {
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId);
+ if (!gdatap)
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData() was NULL" << llendl;
+ }
+ else if (!gdatap->isMemberDataComplete())
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << llendl;
+ }
+ else
+ {
+ processGroupData();
+ mRequestProcessed = true;
+ }
+ }
+ }
+
+ LLUUID getGroupId() { return mGroupId; }
+ virtual void processGroupData() = 0;
+protected:
+ LLUUID mGroupId;
+private:
+ bool mRequestProcessed;
+};
+
+class LLFetchLeaveGroupData: public LLFetchGroupMemberData
+{
+public:
+ LLFetchLeaveGroupData(const LLUUID& group_id)
+ : LLFetchGroupMemberData(group_id)
+ {}
+ void processGroupData()
+ {
+ LLGroupActions::processLeaveGroupDataResponse(mGroupId);
+ }
+};
+
+LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL;
+
// static
void LLGroupActions::search()
{
@@ -208,23 +282,52 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)
void LLGroupActions::leave(const LLUUID& group_id)
{
if (group_id.isNull())
+ {
return;
+ }
- S32 count = gAgent.mGroups.count();
- S32 i;
- for (i = 0; i < count; ++i)
+ LLGroupData group_data;
+ if (gAgent.getGroupData(group_id, group_data))
{
- if(gAgent.mGroups.get(i).mID == group_id)
- break;
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if (!gdatap || !gdatap->isMemberDataComplete())
+ {
+ if (gFetchLeaveGroupData != NULL)
+ {
+ delete gFetchLeaveGroupData;
+ gFetchLeaveGroupData = NULL;
+ }
+ gFetchLeaveGroupData = new LLFetchLeaveGroupData(group_id);
+ }
+ else
+ {
+ processLeaveGroupDataResponse(group_id);
+ }
}
- if (i < count)
+}
+
+//static
+void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id)
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ LLUUID agent_id = gAgent.getID();
+ LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(agent_id);
+ //get the member data for the group
+ if ( mit != gdatap->mMembers.end() )
{
- LLSD args;
- args["GROUP"] = gAgent.mGroups.get(i).mName;
- LLSD payload;
- payload["group_id"] = group_id;
- LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
+ LLGroupMemberData* member_data = (*mit).second;
+
+ if ( member_data && member_data->isOwner() && gdatap->mMemberCount == 1)
+ {
+ LLNotificationsUtil::add("OwnerCannotLeaveGroup");
+ return;
+ }
}
+ LLSD args;
+ args["GROUP"] = gdatap->mName;
+ LLSD payload;
+ payload["group_id"] = group_id;
+ LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
}
// static
diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h
index 3f9852f194..afc4686dd7 100755
--- a/indra/newview/llgroupactions.h
+++ b/indra/newview/llgroupactions.h
@@ -114,6 +114,14 @@ public:
private:
static bool onJoinGroup(const LLSD& notification, const LLSD& response);
static bool onLeaveGroup(const LLSD& notification, const LLSD& response);
+
+ /**
+ * This function is called by LLFetchLeaveGroupData upon receiving a response to a group
+ * members data request.
+ */
+ static void processLeaveGroupDataResponse(const LLUUID group_id);
+
+ friend class LLFetchLeaveGroupData;
};
#endif // LL_LLGROUPACTIONS_H
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 2c20409381..892038722d 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -103,6 +103,7 @@ BOOL LLSessionTimeoutTimer::tick()
}
+void notify_of_message(const LLSD& msg, bool is_dnd_msg);
void process_dnd_im(const LLSD& notification)
{
@@ -129,15 +130,9 @@ void process_dnd_im(const LLSD& notification)
fromID,
false,
false); //will need slight refactor to retrieve whether offline message or not (assume online for now)
+ }
- LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
-
- if (im_box)
- {
- im_box->flashConversationItemWidget(sessionID, true);
- }
-
- }
+ notify_of_message(data, true);
}
@@ -158,88 +153,120 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
}
-void on_new_message(const LLSD& msg)
+void notify_of_message(const LLSD& msg, bool is_dnd_msg)
{
- std::string user_preferences;
- LLUUID participant_id = msg["from_id"].asUUID();
- LLUUID session_id = msg["session_id"].asUUID();
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
-
- // do not show notification which goes from agent
- if (gAgent.getID() == participant_id)
- {
- return;
- }
+ std::string user_preferences;
+ LLUUID participant_id = msg[is_dnd_msg ? "FROM_ID" : "from_id"].asUUID();
+ LLUUID session_id = msg[is_dnd_msg ? "SESSION_ID" : "session_id"].asUUID();
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
- // determine state of conversations floater
- enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
+ // do not show notification which goes from agent
+ if (gAgent.getID() == participant_id)
+ {
+ return;
+ }
+ // determine state of conversations floater
+ enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
- LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+ LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id);
+ bool store_dnd_message = false; // flag storage of a dnd message
if (!LLFloater::isVisible(im_box) || im_box->isMinimized())
{
conversations_floater_status = CLOSED;
}
else if (!im_box->hasFocus() &&
- !(session_floater && LLFloater::isVisible(session_floater)
- && !session_floater->isMinimized() && session_floater->hasFocus()))
+ !(session_floater && LLFloater::isVisible(session_floater)
+ && !session_floater->isMinimized() && session_floater->hasFocus()))
{
conversations_floater_status = NOT_ON_TOP;
}
else if (im_box->getSelectedSession() != session_id)
{
conversations_floater_status = ON_TOP;
- }
+ }
else
{
conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED;
}
- // determine user prefs for this session
- if (session_id.isNull())
- {
- user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
- }
- else if(session->isP2PSessionType())
- {
- if (LLAvatarTracker::instance().isBuddy(participant_id))
- {
- user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
- }
- else
- {
- user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
- }
- }
- else if(session->isAdHocSessionType())
- {
- user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
- }
- else if(session->isGroupSessionType())
- {
- user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
- }
-
- // actions:
+ // determine user prefs for this session
+ if (session_id.isNull())
+ {
+ if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT)
+ {
+ user_preferences = gSavedSettings.getString("NotificationObjectIMOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundObjectIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ else
+ {
+ user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ }
+ else if(session->isP2PSessionType())
+ {
+ if (LLAvatarTracker::instance().isBuddy(participant_id))
+ {
+ user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ else
+ {
+ user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ }
+ else if(session->isAdHocSessionType())
+ {
+ user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ else if(session->isGroupSessionType())
+ {
+ user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
- // 0. nothing - exit
- if (("none" == user_preferences ||
- ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)
- && session_floater->isMessagePaneExpanded())
- {
- return;
- }
+ // actions:
- // 1. open floater and [optional] surface it
- if ("openconversations" == user_preferences &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- {
- if(!gAgent.isDoNotDisturb())
- {
+ // 0. nothing - exit
+ if (("noaction" == user_preferences ||
+ ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status)
+ && session_floater->isMessagePaneExpanded())
+ {
+ return;
+ }
+
+ // 1. open floater and [optional] surface it
+ if (("openconversations" == user_preferences &&
+ (CLOSED == conversations_floater_status
+ || NOT_ON_TOP == conversations_floater_status))
+ || is_dnd_msg )
+ {
+ if(!gAgent.isDoNotDisturb())
+ {
// Open conversations floater
LLFloaterReg::showInstance("im_container");
im_box->collapseMessagesPane(false);
@@ -261,57 +288,101 @@ void on_new_message(const LLSD& msg)
}
}
}
- else
- {
- //If in DND mode, allow notification to be stored so upon DND exit
- //useMostItrusiveIMNotification will be called to notify user a message exists
- if(session_id.notNull()
- && participant_id.notNull()
- && !session_floater->isShown())
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
- }
+ else
+ {
+ store_dnd_message = true;
+ }
- // 2. Flash line item
- if ("openconversations" == user_preferences
- || ON_TOP == conversations_floater_status
- || ("toast" == user_preferences && ON_TOP != conversations_floater_status)
- || ("flash" == user_preferences && CLOSED == conversations_floater_status))
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id))
- {
- im_box->flashConversationItemWidget(session_id, true);
- }
- }
+ }
- // 3. Flash FUI button
- if (("toast" == user_preferences || "flash" == user_preferences) &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id)
- && !gAgent.isDoNotDisturb())
- {
- gToolBarView->flashCommand(LLCommandId("chat"), true);
- }
- }
+ // 2. Flash line item
+ if ("openconversations" == user_preferences
+ || ON_TOP == conversations_floater_status
+ || ("toast" == user_preferences && ON_TOP != conversations_floater_status)
+ || ("flash" == user_preferences && CLOSED == conversations_floater_status)
+ || is_dnd_msg)
+ {
+ if(!LLMuteList::getInstance()->isMuted(participant_id))
+ {
+ if(gAgent.isDoNotDisturb())
+ {
+ store_dnd_message = true;
+ }
+ else
+ {
+ if (is_dnd_msg && (ON_TOP == conversations_floater_status ||
+ NOT_ON_TOP == conversations_floater_status ||
+ CLOSED == conversations_floater_status))
+ {
+ im_box->highlightConversationItemWidget(session_id, true);
+ }
+ else
+ {
+ im_box->flashConversationItemWidget(session_id, true);
+ }
+ }
+ }
+ }
- // 4. Toast
- if ((("toast" == user_preferences) &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- || !session_floater->isMessagePaneExpanded())
+ // 3. Flash FUI button
+ if (("toast" == user_preferences || "flash" == user_preferences) &&
+ (CLOSED == conversations_floater_status
+ || NOT_ON_TOP == conversations_floater_status)
+ && !is_dnd_msg) //prevent flashing FUI button because the conversation floater will have already opened
+ {
+ if(!LLMuteList::getInstance()->isMuted(participant_id))
+ {
+ if(!gAgent.isDoNotDisturb())
+ {
+ gToolBarView->flashCommand(LLCommandId("chat"), true);
+ }
+ else
+ {
+ store_dnd_message = true;
+ }
+ }
+ }
- {
- //Show IM toasts (upper right toasts)
- // 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));
- }
- }
+ // 4. Toast
+ if ((("toast" == user_preferences) &&
+ (ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status) &&
+ (!session_floater->isTornOff() || !LLFloater::isVisible(session_floater)))
+ || !session_floater->isMessagePaneExpanded())
+
+ {
+ //Show IM toasts (upper right toasts)
+ // Skip toasting for system messages and for nearby chat
+ if(session_id.notNull() && participant_id.notNull())
+ {
+ if(!is_dnd_msg)
+ {
+ if(gAgent.isDoNotDisturb())
+ {
+ store_dnd_message = true;
+ }
+ else
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
+ }
+ }
+ if (store_dnd_message)
+ {
+ // If in DND mode, allow notification to be stored so upon DND exit
+ // the user will be notified with some limitations (see 'is_dnd_msg' flag checks)
+ if(session_id.notNull()
+ && participant_id.notNull()
+ && !session_floater->isShown())
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
+}
+
+void on_new_message(const LLSD& msg)
+{
+ notify_of_message(msg, false);
}
LLIMModel::LLIMModel()
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 92f2d33073..3c6974cf6d 100755
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -70,11 +70,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
mFilterSubString(p.substring),
mCurrentGeneration(0),
mFirstRequiredGeneration(0),
- mFirstSuccessGeneration(0),
- mFilterCount(0)
+ mFirstSuccessGeneration(0)
{
- mNextFilterGeneration = mCurrentGeneration + 1;
-
// copy mFilterOps into mDefaultFilterOps
markDefault();
}
@@ -92,9 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
return passed_clipboard;
}
- std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos;
-
- BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos);
+ bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true);
passed = passed && checkAgainstFilterType(listener);
passed = passed && checkAgainstPermissions(listener);
passed = passed && checkAgainstFilterLinks(listener);
@@ -105,17 +100,12 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
bool LLInventoryFilter::check(const LLInventoryItem* item)
{
- std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos;
-
+ const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);
const bool passed_filtertype = checkAgainstFilterType(item);
const bool passed_permissions = checkAgainstPermissions(item);
- const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID());
- const bool passed = (passed_filtertype
- && passed_permissions
- && passed_clipboard
- && (mFilterSubString.size() == 0 || string_offset != std::string::npos));
+ const bool passed_clipboard = checkAgainstClipboard(item->getUUID());
- return passed;
+ return passed_filtertype && passed_permissions && passed_clipboard && passed_string;
}
bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const
@@ -439,7 +429,7 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
current_types = types;
if (more_bits_set && fewer_bits_set)
{
- // neither less or more restrive, both simultaneously
+ // neither less or more restrictive, both simultaneously
// so we need to filter from scratch
setModified(FILTER_RESTART);
}
@@ -714,7 +704,7 @@ void LLInventoryFilter::resetDefault()
void LLInventoryFilter::setModified(EFilterModified behavior)
{
mFilterText.clear();
- mCurrentGeneration = mNextFilterGeneration++;
+ mCurrentGeneration++;
if (mFilterModified == FILTER_NONE)
{
@@ -1021,21 +1011,19 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
return mFilterOps.mShowFolderState;
}
-void LLInventoryFilter::setFilterCount(S32 count)
-{
- mFilterCount = count;
-}
-S32 LLInventoryFilter::getFilterCount() const
+bool LLInventoryFilter::isTimedOut()
{
- return mFilterCount;
+ return mFilterTime.hasExpired();
}
-void LLInventoryFilter::decrementFilterCount()
-{
- mFilterCount--;
+void LLInventoryFilter::resetTime(S32 timeout)
+{
+ mFilterTime.reset();
+ F32 time_in_sec = (F32)(timeout)/1000.0;
+ mFilterTime.setTimerExpirySec(time_in_sec);
}
-S32 LLInventoryFilter::getCurrentGeneration() const
+S32 LLInventoryFilter::getCurrentGeneration() const
{
return mCurrentGeneration;
}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 4912b5ca91..ce516af0b9 100755
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -215,12 +215,11 @@ public:
void setModified(EFilterModified behavior = FILTER_RESTART);
// +-------------------------------------------------------------------+
- // + Count
+ // + Time
// +-------------------------------------------------------------------+
- void setFilterCount(S32 count);
- S32 getFilterCount() const;
- void decrementFilterCount();
-
+ void resetTime(S32 timeout);
+ bool isTimedOut();
+
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
@@ -262,13 +261,15 @@ private:
const std::string mName;
S32 mCurrentGeneration;
+ // The following makes checking for pass/no pass possible even if the item is not checked against the current generation
+ // Any item that *did not pass* the "required generation" will *not pass* the current one
+ // Any item that *passes* the "success generation" will *pass* the current one
S32 mFirstRequiredGeneration;
S32 mFirstSuccessGeneration;
- S32 mNextFilterGeneration;
- S32 mFilterCount;
EFilterModified mFilterModified;
-
+ LLTimer mFilterTime;
+
std::string mFilterText;
std::string mEmptyLookupMessage;
};
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index cf1fd4c0d0..e5b9e11d48 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -192,7 +192,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
p.show_item_link_overlays = mShowItemLinkOverlays;
p.root = NULL;
p.options_menu = "menu_inventory.xml";
-
+
return LLUICtrlFactory::create<LLFolderView>(p);
}
@@ -396,6 +396,7 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
return getFilter().getShowFolderState();
}
+// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)
void LLInventoryPanel::modelChanged(U32 mask)
{
static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 2d7454b636..379bbc5f8d 100755
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -631,7 +631,7 @@ void LLLogChat::deleteTranscripts()
}
// static
-bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)
+bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group)
{
std::vector<std::string> list_of_transcriptions;
LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
@@ -641,20 +641,53 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)
LLAvatarName avatar_name;
LLAvatarNameCache::get(avatar_id, &avatar_name);
std::string avatar_user_name = avatar_name.getAccountName();
- std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_');
-
- BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ if(!is_group)
{
- if (std::string::npos != transcript_file_name.find(avatar_user_name))
+ std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_');
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
{
- return true;
+ if (std::string::npos != transcript_file_name.find(avatar_user_name))
+ {
+ return true;
+ }
}
}
+ else
+ {
+ std::string file_name;
+ gCacheName->getGroupName(avatar_id, file_name);
+ file_name = makeLogFileName(file_name);
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ }
+
}
return false;
}
+bool LLLogChat::isNearbyTranscriptExist()
+{
+ std::vector<std::string> list_of_transcriptions;
+ LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
+
+ std::string file_name;
+ file_name = makeLogFileName("chat");
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//which are more strict by its nature (only firstname and secondname)
//Example, an object's name can be written like "Object <actual_object's_name>"
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index e819f00dd9..bd70dbaac9 100755
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -67,7 +67,8 @@ public:
std::vector<std::string>& listOfFilesToMove);
static void deleteTranscripts();
- static bool isTranscriptExist(const LLUUID& avatar_id);
+ static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);
+ static bool isNearbyTranscriptExist();
private:
static std::string cleanFileName(std::string filename);
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index a85335f1ba..4ca961c1f9 100755
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -83,13 +83,6 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification)
if (notification->canLogToChat())
{
LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM);
-
- // don't show toast if Nearby Chat is opened
- LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
- if (nearby_chat->isChatVisible())
- {
- return false;
- }
}
std::string session_name = notification->getPayload()["SESSION_NAME"];
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d6535c88e9..53deded2f2 100755
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -130,6 +130,8 @@ BOOL LLPanelMainInventory::postBuild()
mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
+ mCounterCtrl = getChild<LLUICtrl>("ItemcountText");
+
//panel->getFilter().markDefault();
// Set up the default inv. panel/filter settings.
@@ -566,7 +568,7 @@ void LLPanelMainInventory::draw()
void LLPanelMainInventory::updateItemcountText()
{
// *TODO: Calling setlocale() on each frame may be inefficient.
- LLLocale locale(LLStringUtil::getLocale());
+ //LLLocale locale(LLStringUtil::getLocale());
std::string item_count_string;
LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
@@ -589,8 +591,7 @@ void LLPanelMainInventory::updateItemcountText()
text = getString("ItemcountUnknown");
}
- // *TODO: Cache the LLUICtrl* for the ItemcountText control
- getChild<LLUICtrl>("ItemcountText")->setValue(text);
+ mCounterCtrl->setValue(text);
}
void LLPanelMainInventory::onFocusReceived()
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 899931aa89..394b004e20 100755
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -121,6 +121,7 @@ private:
LLFilterEditor* mFilterEditor;
LLTabContainer* mFilterTabs;
+ LLUICtrl* mCounterCtrl;
LLHandle<LLFloater> mFinderHandle;
LLInventoryPanel* mActivePanel;
bool mResortActivePanel;
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index 75e6e3d13a..025ef3945d 100755
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -28,6 +28,7 @@
#include "lltoastimpanel.h"
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llfloaterreg.h"
#include "llgroupactions.h"
#include "llgroupiconctrl.h"
@@ -61,6 +62,15 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
style_params.font.name(font_name);
style_params.font.size(font_size);
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id);
+ mIsGroupMsg = (im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION);
+ if(mIsGroupMsg)
+ {
+ mAvatarName->setValue(im_session->mName);
+ LLAvatarName avatar_name;
+ LLAvatarNameCache::get(p.avatar_id, &avatar_name);
+ p.message = "[From " + avatar_name.getDisplayName() + "]\n" + p.message;
+ }
//Handle IRC styled /me messages.
std::string prefix = p.message.substr(0, 4);
@@ -81,12 +91,17 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mMessage->setText(p.message, style_params);
}
- mAvatarName->setValue(p.from);
+ if(!mIsGroupMsg)
+ {
+ mAvatarName->setValue(p.from);
+ }
mTime->setValue(p.time);
mSessionID = p.session_id;
mAvatarID = p.avatar_id;
mNotification = p.notification;
+
+
initIcon();
S32 maxLinesCount;
@@ -147,7 +162,14 @@ void LLToastIMPanel::spawnNameToolTip()
LLToolTip::Params params;
params.background_visible(false);
- params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
+ if(!mIsGroupMsg)
+ {
+ params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
+ }
+ else
+ {
+ params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_group", LLSD().with("group_id", mSessionID), FALSE));
+ }
params.delay_time(0.0f); // spawn instantly on hover
params.image(LLUI::getUIImage("Info_Small"));
params.message("");
diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h
index 3eb11fb3bc..767617dabc 100755
--- a/indra/newview/lltoastimpanel.h
+++ b/indra/newview/lltoastimpanel.h
@@ -73,6 +73,8 @@ private:
LLTextBox* mAvatarName;
LLTextBox* mTime;
LLTextBox* mMessage;
+
+ bool mIsGroupMsg;
};
#endif // LLTOASTIMPANEL_H_
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ace16396db..3766b30438 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2649,7 +2649,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
send_do_not_disturb_message(msg, from_id);
}
- else
+
+ if (!is_muted)
{
LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;
// Read the binary bucket for more information.
@@ -3673,6 +3674,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
LLSD msg_notify = LLSD(LLSD::emptyMap());
msg_notify["session_id"] = LLUUID();
msg_notify["from_id"] = chat.mFromID;
+ msg_notify["source_type"] = chat.mSourceType;
on_new_message(msg_notify);
}
}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index fe4d5b3e4d..04e5447abf 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1811,7 +1811,6 @@ void LLViewerWindow::initBase()
gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
-
// Console
llassert( !gConsole );
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 42568775d9..fc6458c67e 100755
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -875,4 +875,19 @@
<color
name="blue"
value="0 0 1 1"/>
+
+ <!--Resize bar colors -->
+
+ <color
+ name="ResizebarBorderLight"
+ value="0.231 0.231 0.231 1"/>
+
+ <color
+ name="ResizebarBorderDark"
+ value="0.133 0.133 0.133 1"/>
+
+ <color
+ name="ResizebarBody"
+ value="0.208 0.208 0.208 1"/>
+
</colors>
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index fcab966dee..5b17ef94db 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -773,4 +773,7 @@ with the same filename but different name
<texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+
+ <texture name="Horizontal Drag Handle" file_name="widgets/horizontal_drag_handle.png"/>
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png"/>
</textures>
diff --git a/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png
new file mode 100644
index 0000000000..642eac4065
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png
new file mode 100644
index 0000000000..b06b70cf36
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 65f623a47e..da016462db 100755
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -24,24 +24,28 @@
value="Conv_toolbar_expand"/>
<layout_stack
animate="true"
- bottom="-1"
+ bottom="-5"
+ drag_handle_gap="6"
+ drag_handle_first_indent="27"
+ drag_handle_second_indent="10"
follows="all"
layout="topleft"
left="0"
name="conversations_stack"
orientation="horizontal"
right="-1"
+ show_drag_handle="true"
top="0">
<layout_panel
auto_resize="false"
user_resize="true"
name="conversations_layout_panel"
min_dim="38"
- expanded_min_dim="156">
+ expanded_min_dim="136">
<layout_stack
animate="false"
follows="left|top|right"
- height="35"
+ height="27"
layout="topleft"
left="0"
name="conversations_pane_buttons_stack"
@@ -50,7 +54,6 @@
top="0">
<layout_panel
auto_resize="true"
- height="35"
name="conversations_pane_buttons_expanded">
<menu_button
follows="top|left"
@@ -64,7 +67,7 @@
left="5"
name="sort_btn"
tool_tip="View/sort options"
- top="5"
+ top="1"
width="31" />
<button
follows="top|left"
@@ -74,7 +77,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="add_btn"
tool_tip="Start a new conversation"
@@ -87,7 +90,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="speak_btn"
tool_tip="Speak with people using your microphone"
@@ -95,9 +98,8 @@
</layout_panel>
<layout_panel
auto_resize="false"
- height="35"
name="conversations_pane_buttons_collapsed"
- width="41">
+ width="31">
<button
follows="right|top"
height="25"
@@ -106,8 +108,8 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
- left="1"
+ top="1"
+ left="0"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this list"
width="31" />
@@ -119,7 +121,7 @@
layout="topleft"
name="conversations_list_panel"
opaque="true"
- top="35"
+ top_pad="0"
left="5"
right="-1"/>
</layout_panel>
@@ -127,7 +129,7 @@
auto_resize="true"
user_resize="true"
name="messages_layout_panel"
- expanded_min_dim="222">
+ expanded_min_dim="212">
<panel_container
bottom="-1"
follows="all"
@@ -136,44 +138,44 @@
name="im_box_tab_container"
right="-1"
top="0">
- <panel
- bottom="-1"
- follows="all"
- layout="topleft"
- name="stub_panel"
- opaque="true"
- top_pad="0"
- left="0"
- right="-1">
- <button
- follows="right|top"
- height="25"
- image_hover_unselected="Toolbar_Middle_Over"
- image_overlay="Conv_toolbar_collapse"
- image_selected="Toolbar_Middle_Selected"
- image_unselected="Toolbar_Middle_Off"
+ <panel
+ bottom="-1"
+ follows="all"
layout="topleft"
- top="5"
- right="-10"
- name="stub_collapse_btn"
- tool_tip="Collapse this pane"
- width="31" />
- <text
- type="string"
- clip_partial="false"
- follows="left|top|right"
- layout="topleft"
- left="15"
- right="-15"
- name="stub_textbox"
- top="25"
- height="40"
- valign="center"
- parse_urls="true"
- wrap="true">
- This conversation is in a separate window. [secondlife:/// Bring it back.]
- </text>
- </panel>
+ name="stub_panel"
+ opaque="true"
+ top_pad="0"
+ left="0"
+ right="-1">
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Conv_toolbar_collapse"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="1"
+ right="-10"
+ name="stub_collapse_btn"
+ tool_tip="Collapse this pane"
+ width="31" />
+ <text
+ type="string"
+ clip_partial="false"
+ follows="left|top|right"
+ layout="topleft"
+ left="15"
+ right="-15"
+ name="stub_textbox"
+ top="25"
+ height="40"
+ valign="center"
+ parse_urls="true"
+ wrap="true">
+ This conversation is in a separate window. [secondlife:/// Bring it back.]
+ </text>
+ </panel>
</panel_container>
</layout_panel>
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 2152a9f6e9..8da4213c65 100755
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -70,26 +70,23 @@
top="0"
left="0"
right="-1"
- bottom="-3">
+ bottom="-1">
<layout_stack
animate="false"
+ bottom="-1"
default_tab_group="2"
follows="all"
- right="-5"
- bottom="-1"
- top="0"
- left="5"
- border_size="0"
+ left="3"
layout="topleft"
- orientation="vertical"
name="main_stack"
- tab_group="1">
+ right="-3"
+ orientation="vertical"
+ tab_group="1"
+ top="0">
<layout_panel
auto_resize="false"
name="toolbar_panel"
- height="35"
- right="-1"
- left="1">
+ height="25">
<menu_button
menu_filename="menu_im_session_showmodes.xml"
follows="top|left"
@@ -102,7 +99,7 @@
left="5"
name="view_options_btn"
tool_tip="View/sort options"
- top="5"
+ top="1"
width="31" />
<menu_button
menu_filename="menu_im_conversation.xml"
@@ -113,7 +110,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="gear_btn"
visible="false"
@@ -128,7 +125,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="add_btn"
tool_tip="Add someone to this conversation"
@@ -141,7 +138,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="voice_call_btn"
tool_tip="Open voice connection"
@@ -166,8 +163,8 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
- right="-67"
+ top="1"
+ right="-70"
name="close_btn"
tool_tip="End this conversation"
width="31" />
@@ -179,7 +176,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this pane"
@@ -194,18 +191,21 @@
layout="topleft"
left_pad="2"
name="tear_off_btn"
- top="5"
+ top="1"
width="31" />
</layout_panel>
<layout_panel
name="body_panel"
- top="1"
- bottom="-1">
+ height="235">
<layout_stack
default_tab_group="2"
+ drag_handle_gap="6"
+ drag_handle_first_indent="0"
+ drag_handle_second_indent="1"
follows="all"
orientation="horizontal"
name="im_panels"
+ show_drag_handle="true"
tab_group="1"
top="0"
right="-1"
@@ -217,14 +217,12 @@
min_dim="0"
width="150"
user_resize="true"
- auto_resize="false"
- bottom="-1" />
+ auto_resize="false" />
<layout_panel
default_tab_group="3"
tab_group="2"
name="right_part_holder"
- min_width="221"
- bottom="-1">
+ min_width="172">
<layout_stack
animate="true"
default_tab_group="2"
@@ -233,7 +231,7 @@
name="translate_and_chat_stack"
tab_group="1"
top="0"
- left="0"
+ left="1"
right="-1"
bottom="-1">
<layout_panel
@@ -259,7 +257,7 @@
parse_highlights="true"
parse_urls="true"
right="-1"
- left="5"
+ left="0"
top="0"
bottom="-1" />
</layout_panel>
@@ -268,10 +266,7 @@
</layout_stack>
</layout_panel>
<layout_panel
- top_delta="0"
- top="0"
- height="26"
- bottom="-1"
+ height="35"
auto_resize="false"
name="chat_layout_panel">
<layout_stack
@@ -281,15 +276,11 @@
orientation="horizontal"
name="input_panels"
top="0"
- bottom="-2"
+ bottom="-1"
left="0"
right="-1">
<layout_panel
- name="input_editor_layout_panel"
- auto_resize="true"
- user_resize="false"
- top="0"
- bottom="-1">
+ name="input_editor_layout_panel">
<chat_editor
layout="topleft"
expand_lines_count="5"
@@ -302,32 +293,27 @@
max_length="1023"
spellcheck="true"
tab_group="3"
- top="1"
- bottom="-2"
- left="4"
- right="-4"
+ bottom="-8"
+ left="5"
+ right="-5"
wrap="true" />
</layout_panel>
<layout_panel
auto_resize="false"
- user_resize="false"
name="input_button_layout_panel"
- width="30"
- top="0"
- bottom="-1">
+ width="32">
<button
- layout="topleft"
left="1"
- right="-1"
- top="1"
- height="22"
+ top="4"
+ height="25"
follows="left|right|top"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Conv_expand_one_line"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="minz_btn"
- tool_tip="Shows/hides message panel" />
+ tool_tip="Shows/hides message panel"
+ width="28" />
</layout_panel>
</layout_stack>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 970a11c6c4..9d1973f267 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3709,6 +3709,17 @@ Leave Group?
</notification>
<notification
+ icon="alertmodal.tga"
+ name="OwnerCannotLeaveGroup"
+ type="alertmodal">
+ Unable to leave group. You cannot leave the group because you are the last owner of the group. Please assign another member to the owner role first.
+ <tag>group</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alert.tga"
name="ConfirmKick"
type="alert">
@@ -6573,7 +6584,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
icon="notify.tga"
name="JoinGroup"
persist="true"
- type="notify">
+ type="offer">
<tag>group</tag>
[MESSAGE]
<form name="form">
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index bd096ebb88..2fd26e3f01 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -103,14 +103,6 @@
<text
layout="topleft"
height="12"
- name="notifications"
- left="0"
- width="120">
- Notifications
- </text>
- <text
- layout="topleft"
- height="12"
name="friend_ims"
width="145"
left="0"
@@ -138,17 +130,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundFriendIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_friend_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
height="12"
name="non_friend_ims"
width="145"
left="0"
- top_pad="9">
+ top_pad="11">
Non-friend IMs:
</text>
<combo_box
@@ -172,17 +174,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundNonFriendIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_non_friend_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
height="13"
name="conference_ims"
width="145"
- top_pad="9">
+ top_pad="11">
Conference IMs:
</text>
<combo_box
@@ -206,17 +218,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundConferenceIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_conference_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
height="13"
name="group_chat"
width="145"
- top_pad="9">
+ top_pad="11">
Group chat:
</text>
<combo_box
@@ -240,17 +262,27 @@
name="FlashToolbarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundGroupChatIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_group_chat_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"
height="12"
name="nearby_chat"
width="145"
- top_pad="9">
+ top_pad="11">
Nearby chat:
</text>
<combo_box
@@ -274,10 +306,64 @@
name="FlashToolBarButton"
value="flash"/>
<item
- label="None"
- name="None"
- value="none"/>
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
</combo_box>
+ <check_box
+ control_name="PlaySoundNearbyChatIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_nearby_chat_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
+ <text
+ layout="topleft"
+ left="0"
+ height="12"
+ name="object_ims"
+ width="145"
+ top_pad="11">
+ Object IMs:
+ </text>
+ <combo_box
+ control_name="NotificationObjectIMOptions"
+ height="23"
+ layout="topleft"
+ left_pad="5"
+ top_delta="-6"
+ name="ObjectIMOptions"
+ width="223">
+ <item
+ label="Open Conversations window"
+ name="OpenConversationsWindow"
+ value="openconversations"/>
+ <item
+ label="Pop up the message"
+ name="PopUpMessage"
+ value="toast"/>
+ <item
+ label="Flash toolbar button"
+ name="FlashToolBarButton"
+ value="flash"/>
+ <item
+ label="No action"
+ name="NoAction"
+ value="noaction"/>
+ </combo_box>
+ <check_box
+ control_name="PlaySoundObjectIM"
+ height="23"
+ label="Play sound"
+ layout="topleft"
+ name="play_sound_object_im"
+ left_pad="7"
+ top_delta="-3"
+ width="28">
+ </check_box>
<text
layout="topleft"
left="0"