summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcallum <none@none>2009-12-28 13:45:57 -0800
committercallum <none@none>2009-12-28 13:45:57 -0800
commit3519435bbfeec4c838d5ffbe008d0ac7bbc085a8 (patch)
tree5d590d84a1fa6c8414adba0732a83a67a440dd37
parentdd1fb1568e85a8e3622372cae21bcd3205051718 (diff)
parent6008bf61b2d0475a274ad2b851b61e69496b5bf8 (diff)
Merge with (specific revision) and head
-rw-r--r--indra/llui/lldockablefloater.cpp1
-rw-r--r--indra/llui/lldockablefloater.h21
-rw-r--r--indra/llui/lldockcontrol.cpp26
-rw-r--r--indra/llui/llflatlistview.cpp88
-rw-r--r--indra/llui/llflatlistview.h13
-rw-r--r--indra/llui/llfloater.cpp5
-rw-r--r--indra/llui/llmenugl.cpp5
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llavatarlist.cpp6
-rw-r--r--indra/newview/llavatarlist.h1
-rw-r--r--indra/newview/llavatarlistitem.cpp117
-rw-r--r--indra/newview/llavatarlistitem.h20
-rw-r--r--indra/newview/llbottomtray.cpp6
-rw-r--r--indra/newview/llcallfloater.cpp116
-rw-r--r--indra/newview/llcallfloater.h22
-rw-r--r--indra/newview/llchiclet.cpp247
-rw-r--r--indra/newview/llchiclet.h36
-rw-r--r--indra/newview/llfavoritesbar.cpp19
-rw-r--r--indra/newview/llfolderview.cpp7
-rw-r--r--indra/newview/llimfloater.cpp1
-rw-r--r--indra/newview/llimview.cpp145
-rw-r--r--indra/newview/llimview.h27
-rw-r--r--indra/newview/llinventorymodel.cpp27
-rw-r--r--indra/newview/llinventorypanel.cpp8
-rw-r--r--indra/newview/llmoveview.cpp1
-rw-r--r--indra/newview/llnotificationalerthandler.cpp13
-rw-r--r--indra/newview/llnotificationhandler.h21
-rw-r--r--indra/newview/llnotificationhandlerutil.cpp56
-rw-r--r--indra/newview/llnotificationofferhandler.cpp15
-rw-r--r--indra/newview/llnotificationtiphandler.cpp13
-rw-r--r--indra/newview/lloutputmonitorctrl.cpp4
-rw-r--r--indra/newview/llpanelavatar.cpp4
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp9
-rw-r--r--indra/newview/llpanelimcontrolpanel.h2
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp28
-rw-r--r--indra/newview/llpanellandmarkinfo.h3
-rw-r--r--indra/newview/llpanellandmarks.cpp193
-rw-r--r--indra/newview/llpanellandmarks.h41
-rw-r--r--indra/newview/llpanelpeople.cpp15
-rw-r--r--indra/newview/llpanelpick.cpp26
-rw-r--r--indra/newview/llpanelpick.h9
-rw-r--r--indra/newview/llpanelteleporthistory.cpp222
-rw-r--r--indra/newview/llparticipantlist.cpp85
-rw-r--r--indra/newview/llparticipantlist.h28
-rw-r--r--indra/newview/llplacesinventorypanel.cpp191
-rw-r--r--indra/newview/llplacesinventorypanel.h96
-rw-r--r--indra/newview/llscreenchannel.cpp69
-rw-r--r--indra/newview/llscreenchannel.h2
-rw-r--r--indra/newview/llscriptfloater.cpp1
-rw-r--r--indra/newview/llspeakbutton.cpp2
-rw-r--r--indra/newview/llspeakers.cpp5
-rw-r--r--indra/newview/llsyswellwindow.cpp9
-rw-r--r--indra/newview/lltoastalertpanel.cpp8
-rw-r--r--indra/newview/llviewermessage.cpp20
-rw-r--r--indra/newview/llvoicechannel.cpp11
-rw-r--r--indra/newview/llvoicechannel.h2
-rw-r--r--indra/newview/llvoiceclient.cpp27
-rw-r--r--indra/newview/skins/default/colors.xml18
-rw-r--r--indra/newview/skins/default/textures/icons/avaline_default_icon.jpgbin0 -> 3951 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_outgoing_call.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_snapshot.xml1
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_folder.xml6
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_header.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_classified.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmarks.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml9
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml41
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml42
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml41
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml22
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml9
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_script.xml32
-rw-r--r--indra/newview/skins/default/xui/en/widgets/output_monitor.xml4
81 files changed, 1928 insertions, 569 deletions
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 63faf44f9d..6a5b475134 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -54,6 +54,7 @@ void LLDockableFloater::init(LLDockableFloater* thiz)
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true)
+ , mOverlapsScreenChannel(false)
{
init(this);
}
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 2c339f4a3f..ae4f99e205 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -50,6 +50,16 @@ public:
LOG_CLASS(LLDockableFloater);
LLDockableFloater(LLDockControl* dockControl, const LLSD& key,
const Params& params = getDefaultParams());
+
+ /**
+ * Constructor.
+ * @param dockControl a pointer to the doc control instance
+ * @param uniqueDocking - a flag defines is docking should work as tab(at one
+ * moment only one docked floater can be shown), also this flag defines is dock
+ * tongue should be used.
+ * @params key a floater key.
+ * @params params a floater parameters
+ */
LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
const LLSD& key, const Params& params = getDefaultParams());
virtual ~LLDockableFloater();
@@ -85,6 +95,15 @@ public:
LLDockControl* getDockControl();
+ /**
+ * Returns true if screen channel should consider floater's size when drawing toasts.
+ *
+ * By default returns false.
+ */
+ virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); }
+ virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; }
+
+ bool getUniqueDocking() { return mUniqueDocking; }
private:
/**
* Provides unique of dockable floater.
@@ -105,6 +124,8 @@ private:
* non exclusively.
*/
bool mUniqueDocking;
+
+ bool mOverlapsScreenChannel;
};
#endif /* LL_DOCKABLEFLOATER_H */
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 456a2925a3..1c3c8449c5 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -182,6 +182,14 @@ void LLDockControl::moveDockable()
LLRect rootRect;
mGetAllowedRectCallback(rootRect);
+ bool unique_docking = false;
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if (dockable_floater != NULL)
+ {
+ unique_docking = dockable_floater->getUniqueDocking();
+ }
+
LLRect dockableRect = mDockableFloater->calcScreenRect();
S32 x = 0;
S32 y = 0;
@@ -208,7 +216,13 @@ void LLDockControl::moveDockable()
case TOP:
x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
- y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
+ y = dockRect.mTop + dockableRect.getHeight();
+ // unique docking used with dock tongue, so add tongue height o the Y coordinate
+ if (unique_docking)
+ {
+ y += mDockTongue->getHeight();
+ }
+
// check is dockable inside root view rect
if (x < rootRect.mLeft)
{
@@ -273,7 +287,15 @@ void LLDockControl::forceRecalculatePosition()
void LLDockControl::drawToungue()
{
- if (mEnabled)
+ bool unique_docking = false;
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if (dockable_floater != NULL)
+ {
+ unique_docking = dockable_floater->getUniqueDocking();
+ }
+
+ if (mEnabled && unique_docking)
{
mDockTongue->draw(mDockTongueX, mDockTongueY);
}
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 7b7a3139a4..3754d155cf 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -66,7 +66,7 @@ const LLRect& LLFlatListView::getItemsRect() const
return mItemsPanel->getRect();
}
-bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/)
+bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/)
{
if (!item) return false;
if (value.isUndefined()) return false;
@@ -97,8 +97,11 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*
// Children don't accept the focus
item->setTabStop(false);
- rearrangeItems();
- notifyParentItemsRectChanged();
+ if (rearrange)
+ {
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ }
return true;
}
@@ -980,7 +983,86 @@ S32 LLFlatListView::notify(const LLSD& info)
return 1;
}
}
+ else if (info.has("rearrange"))
+ {
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ return 1;
+ }
return 0;
}
+void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
+{
+ LLSD action;
+ action.with("detach", LLSD());
+ // Clear detached_items list
+ detached_items.clear();
+ // Go through items and detach valid items, remove them from items panel
+ // and add to detached_items.
+ for (pairs_iterator_t
+ iter = mItemPairs.begin(),
+ iter_end = mItemPairs.end();
+ iter != iter_end; ++iter)
+ {
+ LLPanel* pItem = (*iter)->first;
+ if (1 == pItem->notify(action))
+ {
+ selectItemPair((*iter), false);
+ mItemsPanel->removeChild(pItem);
+ detached_items.push_back(pItem);
+ }
+ }
+ if (!detached_items.empty())
+ {
+ // Some items were detached, clean ourself from unusable memory
+ if (detached_items.size() == mItemPairs.size())
+ {
+ // This way will be faster if all items were disconnected
+ for (pairs_iterator_t
+ iter = mItemPairs.begin(),
+ iter_end = mItemPairs.end();
+ iter != iter_end; ++iter)
+ {
+ (*iter)->first = NULL;
+ delete *iter;
+ }
+ mItemPairs.clear();
+ // Also set items panel height to zero.
+ // Reshape it to allow reshaping of non-item children.
+ LLRect rc = mItemsPanel->getRect();
+ rc.mBottom = rc.mTop;
+ mItemsPanel->reshape(rc.getWidth(), rc.getHeight());
+ mItemsPanel->setRect(rc);
+ setNoItemsCommentVisible(true);
+ }
+ else
+ {
+ for (std::vector<LLPanel*>::const_iterator
+ detached_iter = detached_items.begin(),
+ detached_iter_end = detached_items.end();
+ detached_iter != detached_iter_end; ++detached_iter)
+ {
+ LLPanel* pDetachedItem = *detached_iter;
+ for (pairs_iterator_t
+ iter = mItemPairs.begin(),
+ iter_end = mItemPairs.end();
+ iter != iter_end; ++iter)
+ {
+ item_pair_t* item_pair = *iter;
+ if (item_pair->first == pDetachedItem)
+ {
+ mItemPairs.erase(iter);
+ item_pair->first = NULL;
+ delete item_pair;
+ break;
+ }
+ }
+ }
+ rearrangeItems();
+ }
+ notifyParentItemsRectChanged();
+ }
+}
+
//EOF
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 26e84a6fe1..5999e79f61 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -124,6 +124,8 @@ public:
/** Returns full rect of child panel */
const LLRect& getItemsRect() const;
+ LLRect getRequiredRect() { return getItemsRect(); }
+
/** Returns distance between items */
const S32 getItemsPad() { return mItemPad; }
@@ -131,7 +133,7 @@ public:
* Adds and item and LLSD value associated with it to the list at specified position
* @return true if the item was added, false otherwise
*/
- virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM);
+ virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true);
/**
* Insert item_to_add along with associated value to the list right after the after_item.
@@ -269,6 +271,15 @@ public:
virtual void clear();
/**
+ * Removes all items that can be detached from the list but doesn't destroy
+ * them, caller responsible to manage items after they are detached.
+ * Detachable item should accept "detach" action via notify() method,
+ * where it disconnect all callbacks, does other valuable routines and
+ * return 1.
+ */
+ void detachItems(std::vector<LLPanel*>& detached_items);
+
+ /**
* Set comparator to use for future sorts.
*
* This class does NOT manage lifetime of the comparator
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index d7a692ec9b..845203b420 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2148,6 +2148,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
{
child->setFocus(TRUE);
+ // floater did not take focus, so relinquish focus to world
+ if (!child->hasFocus())
+ {
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
}
}
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 202ed04fbc..60ef01074b 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3610,6 +3610,11 @@ public:
LLContextMenuBranch(const Params&);
+ virtual ~LLContextMenuBranch()
+ {
+ delete mBranch;
+ }
+
// called to rebuild the draw label
virtual void buildDrawLabel( void );
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index c91578b637..038b9eaa62 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -184,6 +184,7 @@ public:
bool scrolledToEnd();
const LLFontGL* getDefaultFont() const { return mDefaultFont; }
+ LLStyle::Params getDefaultStyle();
public:
// Fired when a URL link is clicked
@@ -256,7 +257,6 @@ protected:
LLTextBase(const Params &p);
virtual ~LLTextBase();
void initFromParams(const Params& p);
- LLStyle::Params getDefaultStyle();
virtual void onValueChange(S32 start, S32 end);
// draw methods
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 7d8e9268e5..a26aae3590 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -258,7 +258,6 @@ set(viewer_SOURCE_FILES
llinventorymodel.cpp
llinventoryobserver.cpp
llinventorypanel.cpp
- llinventorysubtreepanel.cpp
lljoystickbutton.cpp
lllandmarkactions.cpp
lllandmarklist.cpp
@@ -354,6 +353,7 @@ set(viewer_SOURCE_FILES
llparticipantlist.cpp
llpatchvertexarray.cpp
llplacesinventorybridge.cpp
+ llplacesinventorypanel.cpp
llpolymesh.cpp
llpolymorph.cpp
llpreview.cpp
@@ -766,7 +766,6 @@ set(viewer_HEADER_FILES
llinventorymodel.h
llinventoryobserver.h
llinventorypanel.h
- llinventorysubtreepanel.h
lljoystickbutton.h
lllandmarkactions.h
lllandmarklist.h
@@ -858,6 +857,7 @@ set(viewer_HEADER_FILES
llparticipantlist.h
llpatchvertexarray.h
llplacesinventorybridge.h
+ llplacesinventorypanel.h
llpolymesh.h
llpolymorph.h
llpreview.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ff7c2b1f5e..ba78d80ad1 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10378,6 +10378,17 @@
<key>Value</key>
<string>Default</string>
</map>
+ <key>VoiceParticipantLeftRemoveDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Timeout to remove participants who has left Voice chat from the list in Voice Controls Panel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>10</integer>
+ </map>
<key>VoicePort</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 5317cf2cd0..b3ef6464f6 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -51,6 +51,12 @@ static const F32 LIT_UPDATE_PERIOD = 5;
// Used to limit time spent for avatar list update per frame.
static const unsigned ADD_LIMIT = 50;
+bool LLAvatarList::contains(const LLUUID& id)
+{
+ const uuid_vector_t& ids = getIDs();
+ return std::find(ids.begin(), ids.end(), id) != ids.end();
+}
+
void LLAvatarList::toggleIcons()
{
// Save the new value for new items to use.
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index e913be0f62..0d2ce884ae 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -75,6 +75,7 @@ public:
void setNameFilter(const std::string& filter);
void setDirty(bool val = true) { mDirty = val; }
uuid_vector_t& getIDs() { return mIDs; }
+ bool contains(const LLUUID& id);
void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index c8544bc3fb..8bc11b0c1c 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -158,7 +158,6 @@ void LLAvatarListItem::changed(U32 mask)
void LLAvatarListItem::setOnline(bool online)
{
// *FIX: setName() overrides font style set by setOnline(). Not an issue ATM.
- // *TODO: Make the colors configurable via XUI.
if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online)
return;
@@ -166,11 +165,7 @@ void LLAvatarListItem::setOnline(bool online)
mOnlineStatus = (EOnlineStatus) online;
// Change avatar name font style depending on the new online status.
- mAvatarNameStyle.color = online ? LLColor4::white : LLColor4::grey;
- setNameInternal(mAvatarName->getText(), mHighlihtSubstring);
-
- // Make the icon fade if the avatar goes offline.
- mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke);
+ setStyle(online ? IS_ONLINE : IS_OFFLINE);
}
void LLAvatarListItem::setName(const std::string& name)
@@ -183,28 +178,21 @@ void LLAvatarListItem::setHighlight(const std::string& highlight)
setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
}
-void LLAvatarListItem::setStyle(const LLStyle::Params& new_style)
+void LLAvatarListItem::setStyle(EItemStyle item_style)
{
-// LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle = new_style);
-
- // Active group should be bold.
- LLFontDescriptor new_desc(mAvatarName->getDefaultFont()->getFontDesc());
+ item_style_map_t& item_styles_params_map = getItemStylesParams();
- new_desc.setStyle(new_style.font()->getFontDesc().getStyle());
- // *NOTE dzaporozhan
- // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font
- // is predefined as bold (SansSerifSmallBold, for example)
-// new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);
- LLFontGL* new_font = LLFontGL::getFont(new_desc);
-
-//
- mAvatarNameStyle.font = new_font;
+ mAvatarNameStyle = item_styles_params_map[item_style];
// *NOTE: You cannot set the style on a text box anymore, you must
// rebuild the text. This will cause problems if the text contains
// hyperlinks, as their styles will be wrong.
- mAvatarName->setText(mAvatarName->getText(), mAvatarNameStyle/* = new_style*/);
+ setNameInternal(mAvatarName->getText(), mHighlihtSubstring);
+
+ icon_color_map_t& item_icon_color_map = getItemIconColorMap();
+ mAvatarIcon->setColor(item_icon_color_map[item_style]);
}
+
void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
{
if (mAvatarId.notNull())
@@ -418,3 +406,90 @@ std::string LLAvatarListItem::formatSeconds(U32 secs)
args["[COUNT]"] = llformat("%u", count);
return getString(fmt, args);
}
+
+// static
+LLAvatarListItem::item_style_map_t& LLAvatarListItem::getItemStylesParams()
+{
+ static item_style_map_t item_styles_params_map;
+ if (!item_styles_params_map.empty()) return item_styles_params_map;
+
+ LLPanel::Params params = LLUICtrlFactory::getDefaultParams<LLPanel>();
+ LLPanel* params_panel = LLUICtrlFactory::create<LLPanel>(params);
+
+ BOOL sucsess = LLUICtrlFactory::instance().buildPanel(params_panel, "panel_avatar_list_item_params.xml");
+
+ if (sucsess)
+ {
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_DEFAULT,
+ params_panel->getChild<LLTextBox>("default_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_VOICE_INVITED,
+ params_panel->getChild<LLTextBox>("voice_call_invited_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_VOICE_JOINED,
+ params_panel->getChild<LLTextBox>("voice_call_joined_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_VOICE_LEFT,
+ params_panel->getChild<LLTextBox>("voice_call_left_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_ONLINE,
+ params_panel->getChild<LLTextBox>("online_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_OFFLINE,
+ params_panel->getChild<LLTextBox>("offline_style")->getDefaultStyle()));
+ }
+ else
+ {
+ item_styles_params_map.insert(std::make_pair(IS_DEFAULT, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_VOICE_INVITED, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_VOICE_JOINED, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_VOICE_LEFT, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_ONLINE, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_OFFLINE, LLStyle::Params()));
+ }
+ if (params_panel) params_panel->die();
+
+ return item_styles_params_map;
+}
+
+// static
+LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap()
+{
+ static icon_color_map_t item_icon_color_map;
+ if (!item_icon_color_map.empty()) return item_icon_color_map;
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_DEFAULT,
+ LLUIColorTable::instance().getColor("AvatarListItemIconDefaultColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_VOICE_INVITED,
+ LLUIColorTable::instance().getColor("AvatarListItemIconVoiceInvitedColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_VOICE_JOINED,
+ LLUIColorTable::instance().getColor("AvatarListItemIconVoiceJoinedColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_VOICE_LEFT,
+ LLUIColorTable::instance().getColor("AvatarListItemIconVoiceLeftColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_ONLINE,
+ LLUIColorTable::instance().getColor("AvatarListItemIconOnlineColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_OFFLINE,
+ LLUIColorTable::instance().getColor("AvatarListItemIconOfflineColor", LLColor4::white)));
+
+ return item_icon_color_map;
+}
+
+// EOF
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index 0e058f75db..79303b55cc 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -46,6 +46,15 @@ class LLAvatarIconCtrl;
class LLAvatarListItem : public LLPanel, public LLFriendObserver
{
public:
+ typedef enum e_item_style_type {
+ IS_DEFAULT,
+ IS_VOICE_INVITED,
+ IS_VOICE_JOINED,
+ IS_VOICE_LEFT,
+ IS_ONLINE,
+ IS_OFFLINE,
+ } EItemStyle;
+
class ContextMenu
{
public:
@@ -73,7 +82,7 @@ public:
void setOnline(bool online);
void setName(const std::string& name);
void setHighlight(const std::string& highlight);
- void setStyle(const LLStyle::Params& new_style);
+ void setStyle(EItemStyle item_style);
void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
void setLastInteractionTime(U32 secs_since);
//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
@@ -105,6 +114,8 @@ protected:
*/
LLOutputMonitorCtrl* mSpeakingIndicator;
+ LLAvatarIconCtrl* mAvatarIcon;
+
private:
typedef enum e_online_status {
@@ -118,7 +129,12 @@ private:
std::string formatSeconds(U32 secs);
- LLAvatarIconCtrl* mAvatarIcon;
+ typedef std::map<EItemStyle, LLStyle::Params> item_style_map_t;
+ static item_style_map_t& getItemStylesParams();
+
+ typedef std::map<EItemStyle, LLColor4> icon_color_map_t;
+ static icon_color_map_t& getItemIconColorMap();
+
LLTextBox* mAvatarName;
LLTextBox* mLastInteractionTime;
LLStyle::Params mAvatarNameStyle;
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 4d5d416907..976b312509 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -148,6 +148,12 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam
{
if (!getChicletPanel()) return;
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!session) return;
+
+ // no need to spawn chiclets for participants in P2P calls called through Avaline
+ if (session->isP2P() && session->isOtherParticipantAvaline()) return;
+
if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
LLIMChiclet* chiclet = createIMChiclet(session_id);
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index c222ced98f..1b4c274bfb 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -40,6 +40,7 @@
#include "llagent.h"
#include "llagentdata.h" // for gAgentID
+#include "llavatariconctrl.h"
#include "llavatarlist.h"
#include "llbottomtray.h"
#include "llimfloater.h"
@@ -48,6 +49,7 @@
#include "llspeakers.h"
#include "lltransientfloatermgr.h"
+static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);
class LLNonAvatarCaller : public LLAvatarListItem
{
@@ -66,6 +68,8 @@ public:
showLastInteractionTime(false);
setShowProfileBtn(false);
setShowInfoBtn(false);
+ mAvatarIcon->setValue("Avaline_Icon");
+ mAvatarIcon->setToolTip(std::string(""));
}
return rv;
}
@@ -95,16 +99,10 @@ BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()
return TRUE;
}
-
-LLCallFloater::Params::Params()
-: voice_left_remove_delay("voice_left_remove_delay", 10)
-{
-}
-
LLCallFloater::LLCallFloater(const LLSD& key)
: LLDockableFloater(NULL, false, key)
, mSpeakerManager(NULL)
-, mPaticipants(NULL)
+, mParticipants(NULL)
, mAvatarList(NULL)
, mNonAvatarCaller(NULL)
, mVoiceType(VC_LOCAL_CHAT)
@@ -112,8 +110,11 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
, mInitParticipantsVoiceState(false)
-, mVoiceLeftRemoveDelay(10) // TODO: mantipov: make xml driven
+, mVoiceLeftRemoveDelay(10)
{
+ static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10);
+ mVoiceLeftRemoveDelay = voice_left_remove_delay;
+
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
LLTransientFloaterMgr::getInstance()->addControlView(this);
@@ -123,8 +124,8 @@ LLCallFloater::~LLCallFloater()
{
resetVoiceRemoveTimers();
- delete mPaticipants;
- mPaticipants = NULL;
+ delete mParticipants;
+ mParticipants = NULL;
mAvatarListRefreshConnection.disconnect();
@@ -188,8 +189,8 @@ void LLCallFloater::draw()
}
// Need to resort the participant list if it's in sort by recent speaker order.
- if (mPaticipants)
- mPaticipants->updateRecentSpeakersOrder();
+ if (mParticipants)
+ mParticipants->updateRecentSpeakersOrder();
LLDockableFloater::draw();
}
@@ -197,9 +198,17 @@ void LLCallFloater::draw()
// virtual
void LLCallFloater::onChange()
{
- if (NULL == mPaticipants) return;
+ if (NULL == mParticipants) return;
updateParticipantsVoiceState();
+
+ // Add newly joined participants.
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+ for (std::vector<LLUUID>::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++)
+ {
+ mParticipants->addAvatarIDExceptAgent(*it);
+ }
}
@@ -280,7 +289,7 @@ void LLCallFloater::updateSession()
bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
childSetVisible("leave_call_btn", !is_local_chat);
- refreshPartisipantList();
+ refreshParticipantList();
updateAgentModeratorState();
//show floater for voice calls
@@ -291,20 +300,11 @@ void LLCallFloater::updateSession()
if (show_me)
{
setVisible(true);
- // Workaround(EM): Set current call dialog to front most because
- // connect/leaving popups should appear on top of VCP.
- // See bug EXT-3628.
- LLOutgoingCallDialog* instance =
- LLFloaterReg::findTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
- if(instance && instance->getVisible())
- {
- instance->setFrontmost();
- }
}
}
}
-void LLCallFloater::refreshPartisipantList()
+void LLCallFloater::refreshParticipantList()
{
// lets forget states from the previous session
// for timers...
@@ -313,8 +313,8 @@ void LLCallFloater::refreshPartisipantList()
// ...and for speaker state
mSpeakerStateMap.clear();
- delete mPaticipants;
- mPaticipants = NULL;
+ delete mParticipants;
+ mParticipants = NULL;
mAvatarList->clear();
bool non_avatar_caller = false;
@@ -334,7 +334,8 @@ void LLCallFloater::refreshPartisipantList()
if (!non_avatar_caller)
{
- mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
+ mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
+ mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
{
@@ -459,7 +460,7 @@ void LLCallFloater::updateAgentModeratorState()
mAgentPanel->childSetValue("user_text", name);
}
-void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
+static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
{
// Get a list of participants from VoiceClient
LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList();
@@ -572,13 +573,23 @@ void LLCallFloater::updateParticipantsVoiceState()
// HAS LEFT the call.
if ((getState(participant_id) == STATE_JOINED))
{
- setState(item, STATE_LEFT);
-
- LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
- if (speaker.isNull())
- continue;
-
- speaker->mHasLeftCurrentCall = TRUE;
+ if (mVoiceType == VC_LOCAL_CHAT)
+ {
+ // Don't display avatars that aren't in our nearby chat range anymore as "left". Remove them immediately.
+ removeVoiceLeftParticipant(participant_id);
+ }
+ else
+ {
+ setState(item, STATE_LEFT);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
+ if (speaker.isNull())
+ {
+ continue;
+ }
+
+ speaker->mHasLeftCurrentCall = TRUE;
+ }
}
// If an avatarID is not found in a speakers list from VoiceClient and
// a panel with this ID has a LEFT status this means that this person
@@ -587,9 +598,12 @@ void LLCallFloater::updateParticipantsVoiceState()
{
setState(item, STATE_INVITED);
}
+ else
+ {
+ llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName() << llendl;
+ }
}
}
-
}
void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
@@ -609,38 +623,25 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
setState(item->getAvatarId(), state);
- LLStyle::Params speaker_style;
- LLFontDescriptor new_desc(speaker_style.font()->getFontDesc());
-
switch (state)
{
case STATE_INVITED:
- new_desc.setStyle(LLFontGL::NORMAL);
+ item->setStyle(LLAvatarListItem::IS_VOICE_INVITED);
break;
case STATE_JOINED:
removeVoiceRemoveTimer(item->getAvatarId());
- new_desc.setStyle(LLFontGL::NORMAL);
+ item->setStyle(LLAvatarListItem::IS_VOICE_JOINED);
break;
case STATE_LEFT:
{
setVoiceRemoveTimer(item->getAvatarId());
- new_desc.setStyle(LLFontGL::ITALIC);
+ item->setStyle(LLAvatarListItem::IS_VOICE_LEFT);
}
break;
default:
llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl;
break;
}
-
- LLFontGL* new_font = LLFontGL::getFont(new_desc);
- speaker_style.font = new_font;
- item->setStyle(speaker_style);
-
-// if ()
- {
- // found speaker is in voice, mark him as online
- item->setOnline(STATE_JOINED == state);
- }
}
void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
@@ -709,4 +710,15 @@ void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
}
}
+bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
+{
+ if (mVoiceType != VC_LOCAL_CHAT)
+ return true;
+
+ // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice).
+ std::vector<LLUUID> speakers;
+ get_voice_participants_uuids(speakers);
+ return std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end();
+}
+
//EOF
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 537c57f671..3df9e333c5 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -57,12 +57,6 @@ class LLSpeakerMgr;
class LLCallFloater : public LLDockableFloater, LLVoiceClientParticipantObserver
{
public:
- struct Params : public LLInitParam::Block<Params, LLDockableFloater::Params>
- {
- Optional<S32> voice_left_remove_delay;
-
- Params();
- };
LOG_CLASS(LLCallFloater);
@@ -114,7 +108,7 @@ private:
/**
* Refreshes participant list according to current Voice Channel
*/
- void refreshPartisipantList();
+ void refreshParticipantList();
/**
* Handles event on avatar list is refreshed after it was marked dirty.
@@ -133,7 +127,7 @@ private:
/**
* Sets initial participants voice states in avatar list (Invited, Joined, Has Left).
*
- * @see refreshPartisipantList()
+ * @see refreshParticipantList()
* @see onAvatarListRefreshed()
* @see mInitParticipantsVoiceState
*/
@@ -188,10 +182,20 @@ private:
*/
void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id);
+ /**
+ * Called by LLParticipantList before adding a speaker to the participant list.
+ *
+ * If false is returned, the speaker will not be added to the list.
+ *
+ * @param speaker_id Speaker to validate.
+ * @return true if this is a valid speaker, false otherwise.
+ */
+ bool validateSpeaker(const LLUUID& speaker_id);
+
private:
speaker_state_map_t mSpeakerStateMap;
LLSpeakerMgr* mSpeakerManager;
- LLParticipantList* mPaticipants;
+ LLParticipantList* mParticipants;
LLAvatarList* mAvatarList;
LLNonAvatarCaller* mNonAvatarCaller;
EVoiceControls mVoiceType;
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 17ef1f41a4..c01202bb82 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -64,18 +64,6 @@ static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");
static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");
static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");
-static const LLRect CHICLET_RECT(0, 25, 25, 0);
-static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0);
-static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0);
-static const LLRect COUNTER_RECT(25, 25, 50, 0);
-static const S32 OVERLAY_ICON_SHIFT = 2; // used for shifting of an overlay icon for new massages in a chiclet
-static const S32 SCROLL_BUTTON_PAD = 5;
-
-// static
-const S32 LLChicletPanel::s_scroll_ratio = 10;
-const S32 LLChicletNotificationCounterCtrl::MAX_DISPLAYED_COUNT = 99;
-
-
boost::signals2::signal<LLChiclet* (const LLUUID&),
LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >
LLIMChiclet::sFindChicletsSignal;
@@ -173,6 +161,9 @@ LLSysWellChiclet::~LLSysWellChiclet()
void LLSysWellChiclet::setCounter(S32 counter)
{
+ // do nothing if the same counter is coming. EXT-3678.
+ if (counter == mCounter) return;
+
// note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)
std::string s_count;
if(counter != 0)
@@ -388,9 +379,9 @@ void LLNotificationChiclet::createMenu()
//////////////////////////////////////////////////////////////////////////
LLChiclet::Params::Params()
- : show_counter("show_counter")
+ : show_counter("show_counter", true)
+ , enable_counter("enable_counter", false)
{
- show_counter = true;
}
LLChiclet::LLChiclet(const Params& p)
@@ -448,26 +439,12 @@ void LLChiclet::setValue(const LLSD& value)
LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
: LLChiclet(p)
, mShowSpeaker(false)
+, mDefaultWidth(p.rect().getWidth())
, mNewMessagesIcon(NULL)
, mSpeakerCtrl(NULL)
, mCounterCtrl(NULL)
{
- // initialize an overlay icon for new messages
- LLIconCtrl::Params icon_params;
- icon_params.visible = false;
- icon_params.image = LLUI::getUIImage(p.new_messages_icon_name);
- mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
- addChild(mNewMessagesIcon);
-
- // adjust size and position of an icon
- LLRect chiclet_rect = p.rect;
- LLRect overlay_icon_rect = LLRect(chiclet_rect.getWidth()/2, chiclet_rect.getHeight(), chiclet_rect.getWidth(), chiclet_rect.getHeight()/2);
- mNewMessagesIcon->setRect(overlay_icon_rect);
-
- // shift an icon a little bit to the right and up corner of a chiclet
- overlay_icon_rect.translate(OVERLAY_ICON_SHIFT, OVERLAY_ICON_SHIFT);
-
- enableCounterControl(false);
+ enableCounterControl(p.enable_counter);
}
void LLIMChiclet::setShowSpeaker(bool show)
@@ -477,7 +454,6 @@ void LLIMChiclet::setShowSpeaker(bool show)
{
mShowSpeaker = show;
toggleSpeakerControl();
- onChicletSizeChanged();
}
}
@@ -502,7 +478,6 @@ void LLIMChiclet::setShowCounter(bool show)
{
LLChiclet::setShowCounter(show);
toggleCounterControl();
- onChicletSizeChanged();
}
}
@@ -515,32 +490,37 @@ void LLIMChiclet::setRequiredWidth()
{
bool show_speaker = getShowSpeaker();
bool show_counter = getShowCounter();
- S32 required_width = CHICLET_RECT.getWidth();
+ S32 required_width = mDefaultWidth;
if (show_counter)
{
- required_width += COUNTER_RECT.getWidth();
+ required_width += mCounterCtrl->getRect().getWidth();
}
if (show_speaker)
{
- required_width += VOICE_INDICATOR_RECT.getWidth();
+ required_width += mSpeakerCtrl->getRect().getWidth();
}
reshape(required_width, getRect().getHeight());
+
+ onChicletSizeChanged();
}
void LLIMChiclet::toggleSpeakerControl()
{
if(getShowSpeaker())
{
+ // move speaker to the right of chiclet icon
+ LLRect speaker_rc = mSpeakerCtrl->getRect();
+ speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight());
+ mSpeakerCtrl->setRect(speaker_rc);
+
if(getShowCounter())
{
- mSpeakerCtrl->setRect(VOICE_INDICATOR_RECT);
- }
- else
- {
- mSpeakerCtrl->setRect(COUNTER_RECT);
+ // move speaker to the right of counter
+ mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0);
}
+
initSpeakerControl();
}
@@ -567,6 +547,7 @@ void LLIMChiclet::setShowNewMessagesIcon(bool show)
{
mNewMessagesIcon->setVisible(show);
}
+ setRequiredWidth();
}
bool LLIMChiclet::getShowNewMessagesIcon()
@@ -640,36 +621,9 @@ LLIMP2PChiclet::Params::Params()
: avatar_icon("avatar_icon")
, unread_notifications("unread_notifications")
, speaker("speaker")
+, new_message_icon("new_message_icon")
, show_speaker("show_speaker")
{
- // *TODO Vadim: Get rid of hardcoded values.
- rect(CHICLET_RECT);
-
- avatar_icon.name("avatar_icon");
- avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
-
- // *NOTE dzaporozhan
- // Changed icon height from 25 to 24 to fix ticket EXT-794.
- // In some cases(after changing UI scale) 25 pixel height icon was
- // drawn incorrectly, i'm not sure why.
- avatar_icon.rect(CHICLET_ICON_RECT);
- avatar_icon.mouse_opaque(false);
-
- unread_notifications.name("unread");
- unread_notifications.font(LLFontGL::getFontSansSerif());
- unread_notifications.font_halign(LLFontGL::HCENTER);
- unread_notifications.v_pad(5);
- unread_notifications.text_color(LLColor4::white);
- unread_notifications.mouse_opaque(false);
- unread_notifications.rect(COUNTER_RECT);
- unread_notifications.visible(false);
-
- speaker.name("speaker");
- speaker.rect(VOICE_INDICATOR_RECT);
- speaker.auto_update(true);
- speaker.draw_border(false);
-
- show_speaker = false;
}
LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
@@ -677,6 +631,10 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
, mChicletIconCtrl(NULL)
, mPopupMenu(NULL)
{
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
addChild(mChicletIconCtrl);
@@ -694,10 +652,6 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
sendChildToFront(mNewMessagesIcon);
setShowSpeaker(p.show_speaker);
-
- //since mShowSpeaker initialized with false
- //setShowSpeaker(false) will not hide mSpeakerCtrl
- mSpeakerCtrl->setVisible(getShowSpeaker());
}
void LLIMP2PChiclet::initSpeakerControl()
@@ -718,8 +672,11 @@ void LLIMP2PChiclet::updateMenuItems()
if(getSessionId().isNull())
return;
+ LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId());
+ bool open_window_exists = open_im_floater && open_im_floater->getVisible();
+ mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists);
+
bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId());
-
mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);
}
@@ -790,38 +747,10 @@ LLAdHocChiclet::Params::Params()
: avatar_icon("avatar_icon")
, unread_notifications("unread_notifications")
, speaker("speaker")
+, new_message_icon("new_message_icon")
, show_speaker("show_speaker")
, avatar_icon_color("avatar_icon_color", LLColor4::green)
{
- // *TODO Vadim: Get rid of hardcoded values.
- rect(CHICLET_RECT);
-
- avatar_icon.name("avatar_icon");
- avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
-
- // *NOTE dzaporozhan
- // Changed icon height from 25 to 24 to fix ticket EXT-794.
- // In some cases(after changing UI scale) 25 pixel height icon was
- // drawn incorrectly, i'm not sure why.
- avatar_icon.rect(CHICLET_ICON_RECT);
- avatar_icon.mouse_opaque(false);
-
- unread_notifications.name("unread");
- unread_notifications.font(LLFontGL::getFontSansSerif());
- unread_notifications.font_halign(LLFontGL::HCENTER);
- unread_notifications.v_pad(5);
- unread_notifications.text_color(LLColor4::white);
- unread_notifications.mouse_opaque(false);
- unread_notifications.rect(COUNTER_RECT);
- unread_notifications.visible(false);
-
-
- speaker.name("speaker");
- speaker.rect(VOICE_INDICATOR_RECT);
- speaker.auto_update(true);
- speaker.draw_border(false);
-
- show_speaker = false;
}
LLAdHocChiclet::LLAdHocChiclet(const Params& p)
@@ -829,6 +758,10 @@ LLAdHocChiclet::LLAdHocChiclet(const Params& p)
, mChicletIconCtrl(NULL)
, mPopupMenu(NULL)
{
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
//Make the avatar modified
@@ -941,32 +874,9 @@ LLIMGroupChiclet::Params::Params()
: group_icon("group_icon")
, unread_notifications("unread_notifications")
, speaker("speaker")
+, new_message_icon("new_message_icon")
, show_speaker("show_speaker")
{
- rect(CHICLET_RECT);
-
- group_icon.name("group_icon");
-
- // *NOTE dzaporozhan
- // Changed icon height from 25 to 24 to fix ticket EXT-794.
- // In some cases(after changing UI scale) 25 pixel height icon was
- // drawn incorrectly, i'm not sure why.
- group_icon.rect(CHICLET_ICON_RECT);
-
- unread_notifications.name("unread");
- unread_notifications.font(LLFontGL::getFontSansSerif());
- unread_notifications.font_halign(LLFontGL::HCENTER);
- unread_notifications.v_pad(5);
- unread_notifications.text_color(LLColor4::white);
- unread_notifications.rect(COUNTER_RECT);
- unread_notifications.visible(false);
-
- speaker.name("speaker");
- speaker.rect(VOICE_INDICATOR_RECT);
- speaker.auto_update(true);
- speaker.draw_border(false);
-
- show_speaker = false;
}
LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
@@ -975,6 +885,10 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
, mChicletIconCtrl(NULL)
, mPopupMenu(NULL)
{
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
LLChicletGroupIconCtrl::Params avatar_params = p.group_icon;
mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params);
addChild(mChicletIconCtrl);
@@ -1063,6 +977,18 @@ void LLIMGroupChiclet::changed(LLGroupChange gc)
}
}
+void LLIMGroupChiclet::updateMenuItems()
+{
+ if(!mPopupMenu)
+ return;
+ if(getSessionId().isNull())
+ return;
+
+ LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId());
+ bool open_window_exists = open_im_floater && open_im_floater->getVisible();
+ mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists);
+}
+
BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if(!mPopupMenu)
@@ -1072,6 +998,7 @@ BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
if (mPopupMenu)
{
+ updateMenuItems();
mPopupMenu->arrangeAndClear();
LLMenuGL::showPopup(this, mPopupMenu, x, y);
}
@@ -1125,16 +1052,10 @@ void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)
LLChicletPanel::Params::Params()
: chiclet_padding("chiclet_padding")
, scrolling_offset("scrolling_offset")
+, scroll_button_hpad("scroll_button_hpad")
+, scroll_ratio("scroll_ratio")
, min_width("min_width")
{
- chiclet_padding = 3;
- scrolling_offset = 40;
-
- if (!min_width.isProvided())
- {
- // min_width = 4 chiclets + 3 paddings
- min_width = 180 + 3*chiclet_padding;
- }
};
LLChicletPanel::LLChicletPanel(const Params&p)
@@ -1144,6 +1065,8 @@ LLChicletPanel::LLChicletPanel(const Params&p)
, mRightScrollButton(NULL)
, mChicletPadding(p.chiclet_padding)
, mScrollingOffset(p.scrolling_offset)
+, mScrollButtonHPad(p.scroll_button_hpad)
+, mScrollRatio(p.scroll_ratio)
, mMinWidth(p.min_width)
, mShowControls(true)
{
@@ -1445,8 +1368,8 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
bool need_show_scroll = needShowScroll();
if(need_show_scroll)
{
- mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD,
- height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
+ height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
}
else
{
@@ -1462,6 +1385,20 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
}
+S32 LLChicletPanel::notifyParent(const LLSD& info)
+{
+ if(info.has("notification"))
+ {
+ std::string str_notification = info["notification"];
+ if(str_notification == "size_changes")
+ {
+ arrange();
+ return 1;
+ }
+ }
+ return LLPanel::notifyParent(info);
+}
+
void LLChicletPanel::arrange()
{
if(mChicletList.empty())
@@ -1490,8 +1427,8 @@ void LLChicletPanel::arrange()
bool need_show_scroll = needShowScroll();
if(need_show_scroll)
{
- mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD,
- rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
+ rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
}
else
{
@@ -1655,7 +1592,7 @@ void LLChicletPanel::onRightScrollClick()
void LLChicletPanel::onLeftScrollHeldDown()
{
S32 offset = mScrollingOffset;
- mScrollingOffset = mScrollingOffset / s_scroll_ratio;
+ mScrollingOffset = mScrollingOffset / mScrollRatio;
scrollLeft();
mScrollingOffset = offset;
}
@@ -1663,7 +1600,7 @@ void LLChicletPanel::onLeftScrollHeldDown()
void LLChicletPanel::onRightScrollHeldDown()
{
S32 offset = mScrollingOffset;
- mScrollingOffset = mScrollingOffset / s_scroll_ratio;
+ mScrollingOffset = mScrollingOffset / mScrollRatio;
scrollRight();
mScrollingOffset = offset;
}
@@ -1725,7 +1662,7 @@ S32 LLChicletPanel::getTotalUnreadIMCount()
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
LLChicletNotificationCounterCtrl::Params::Params()
-: max_displayed_count("max_displayed_count", MAX_DISPLAYED_COUNT)
+: max_displayed_count("max_displayed_count", 99)
{
}
@@ -1802,6 +1739,7 @@ LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p)
: LLIconCtrl(p)
, mDefaultIcon(p.default_icon)
{
+ setValue(LLUUID::null);
}
void LLChicletGroupIconCtrl::setValue(const LLSD& value )
@@ -1853,20 +1791,23 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)
LLScriptChiclet::Params::Params()
: icon("icon")
+ , new_message_icon("new_message_icon")
{
- // *TODO Vadim: Get rid of hardcoded values.
- rect(CHICLET_RECT);
- icon.rect(CHICLET_ICON_RECT);
}
LLScriptChiclet::LLScriptChiclet(const Params&p)
: LLIMChiclet(p)
, mChicletIconCtrl(NULL)
{
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
LLIconCtrl::Params icon_params = p.icon;
mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
- // Let "new message" icon be on top, else it will be hidden behind chiclet icon.
- addChildInBack(mChicletIconCtrl);
+ addChild(mChicletIconCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
}
void LLScriptChiclet::setSessionId(const LLUUID& session_id)
@@ -1905,20 +1846,24 @@ BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
static const std::string INVENTORY_USER_OFFER ("UserGiveItem");
LLInvOfferChiclet::Params::Params()
+ : icon("icon")
+ , new_message_icon("new_message_icon")
{
- // *TODO Vadim: Get rid of hardcoded values.
- rect(CHICLET_RECT);
- icon.rect(CHICLET_ICON_RECT);
}
LLInvOfferChiclet::LLInvOfferChiclet(const Params&p)
: LLIMChiclet(p)
, mChicletIconCtrl(NULL)
{
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
LLChicletInvOfferIconCtrl::Params icon_params = p.icon;
mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params);
- // Let "new message" icon be on top, else it will be hidden behind chiclet icon.
- addChildInBack(mChicletIconCtrl);
+ addChild(mChicletIconCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
}
void LLInvOfferChiclet::setSessionId(const LLUUID& session_id)
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index 2ab6abfb5b..ee9db10525 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -52,8 +52,6 @@ class LLChicletNotificationCounterCtrl : public LLTextBox
{
public:
- static const S32 MAX_DISPLAYED_COUNT;
-
struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
{
/**
@@ -217,7 +215,8 @@ public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
- Optional<bool> show_counter;
+ Optional<bool> show_counter,
+ enable_counter;
Params();
};
@@ -323,10 +322,7 @@ public:
};
struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
{
- Optional<std::string> new_messages_icon_name;
-
- Params() : new_messages_icon_name("new_messages_icon_name", "Unread_IM")
- {}
+ Params(){}
};
@@ -437,6 +433,8 @@ protected:
bool mShowSpeaker;
bool mCounterEnabled;
+ /* initial width of chiclet, should not include counter or speaker width */
+ S32 mDefaultWidth;
LLIconCtrl* mNewMessagesIcon;
LLChicletNotificationCounterCtrl* mCounterCtrl;
@@ -482,6 +480,8 @@ public:
Optional<LLChicletSpeakerCtrl::Params> speaker;
+ Optional<LLIconCtrl::Params> new_message_icon;
+
Optional<bool> show_speaker;
Params();
@@ -521,6 +521,7 @@ protected:
/**
* Enables/disables menus based on relationship with other participant.
+ * Enables/disables "show session" menu item depending on visible IM floater existence.
*/
virtual void updateMenuItems();
@@ -544,6 +545,8 @@ public:
Optional<LLChicletSpeakerCtrl::Params> speaker;
+ Optional<LLIconCtrl::Params> new_message_icon;
+
Optional<bool> show_speaker;
Optional<LLColor4> avatar_icon_color;
@@ -614,6 +617,8 @@ public:
{
Optional<LLIconCtrl::Params> icon;
+ Optional<LLIconCtrl::Params> new_message_icon;
+
Params();
};
@@ -654,6 +659,8 @@ public:
{
Optional<LLChicletInvOfferIconCtrl::Params> icon;
+ Optional<LLIconCtrl::Params> new_message_icon;
+
Params();
};
@@ -697,6 +704,8 @@ public:
Optional<LLChicletSpeakerCtrl::Params> speaker;
+ Optional<LLIconCtrl::Params> new_message_icon;
+
Optional<bool> show_speaker;
Params();
@@ -752,6 +761,11 @@ protected:
virtual void onMenuItemClicked(const LLSD& user_data);
/**
+ * Enables/disables "show session" menu item depending on visible IM floater existence.
+ */
+ virtual void updateMenuItems();
+
+ /**
* Displays popup menu.
*/
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
@@ -931,7 +945,9 @@ public:
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Optional<S32> chiclet_padding,
- scrolling_offset;
+ scrolling_offset,
+ scroll_button_hpad,
+ scroll_ratio;
Optional<S32> min_width;
@@ -1021,6 +1037,8 @@ public:
S32 getTotalUnreadIMCount();
+ S32 notifyParent(const LLSD& info);
+
protected:
LLChicletPanel(const Params&p);
friend class LLUICtrlFactory;
@@ -1148,6 +1166,8 @@ protected:
S32 mChicletPadding;
S32 mScrollingOffset;
+ S32 mScrollButtonHPad;
+ S32 mScrollRatio;
S32 mMinWidth;
bool mShowControls;
static const S32 s_scroll_ratio;
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 832626e007..ee33c189f9 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -162,9 +162,22 @@ public:
if (!region_name.empty())
{
LLToolTip::Params params;
- params.message = llformat("%s\n%s (%d, %d, %d)", getLabelSelected().c_str(), region_name.c_str(),
+ std::string extra_message = llformat("%s (%d, %d, %d)", region_name.c_str(),
mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY(), mLandmarkInfoGetter.getPosZ());
- params.sticky_rect = calcScreenRect();
+
+ params.message = llformat("%s\n%s", getLabelSelected().c_str(), extra_message.c_str());
+
+ LLRect rect = calcScreenRect();
+ LLFontGL* standart_font = LLFontGL::getFontSansSerif();
+ if(standart_font)
+ {
+ S32 w = llmax((S32)(standart_font->getWidthF32(getLabelSelected())+0.5),(S32)(standart_font->getWidthF32(extra_message)+0.5));
+ rect.mRight = rect.mLeft + w;
+ params.max_width = w;
+ }
+
+ params.sticky_rect = rect;
+
LLToolTipMgr::instance().show(params);
}
return TRUE;
@@ -984,7 +997,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
if (action == "open")
{
- teleport_via_landmark(item->getAssetUUID());
+ onButtonClick(item->getUUID());
}
else if (action == "about")
{
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 9cca1b07db..474d2ca21f 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1822,6 +1822,13 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data,
accept, tooltip_msg);
+ // When there are no visible children drag and drop is handled
+ // by the folder which is the hierarchy root.
+ if (!handled && !hasVisibleChildren())
+ {
+ handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ }
+
if (handled)
{
lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl;
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 0ce8d4b7cd..259f629bdd 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -109,6 +109,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
default: break;
}
}
+ setOverlapsScreenChannel(true);
}
void LLIMFloater::onFocusLost()
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 3549891bc5..37ab144934 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -243,10 +243,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
std::string joined_call = LLTrans::getString("joined_call");
std::string other_avatar_name = "";
+ std::string message;
+
switch(mSessionType)
{
case AVALINE_SESSION:
- // *TODO: test avaline calls (EXT-2211)
+ // no text notifications
+ break;
case P2P_SESSION:
gCacheName->getFullName(mOtherParticipantID, other_avatar_name);
@@ -255,10 +258,13 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
switch(new_state)
{
case LLVoiceChannel::STATE_CALL_STARTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call);
+ message = other_avatar_name + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+
break;
case LLVoiceChannel::STATE_CONNECTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call);
+ message = you + " " + joined_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
default:
break;
}
@@ -268,37 +274,27 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
switch(new_state)
{
case LLVoiceChannel::STATE_CALL_STARTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call);
+ message = you + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
break;
case LLVoiceChannel::STATE_CONNECTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, joined_call);
+ message = other_avatar_name + " " + joined_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
default:
break;
}
}
-
- // Update speakers list when connected
- if (LLVoiceChannel::STATE_CONNECTED == new_state)
- {
- mSpeakers->update(true);
- }
-
break;
case GROUP_SESSION:
case ADHOC_SESSION:
- // *TODO: determine call starter's name "other_avatar_name" (EXT-2211)
- // decide how to show notifications for a group/adhoc chat already opened
- // for now there is no notification from voice channel for this case
if(direction == LLVoiceChannel::INCOMING_CALL)
{
switch(new_state)
{
- case LLVoiceChannel::STATE_CALL_STARTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call);
- break;
case LLVoiceChannel::STATE_CONNECTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call);
+ message = you + " " + joined_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
default:
break;
}
@@ -308,19 +304,18 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
switch(new_state)
{
case LLVoiceChannel::STATE_CALL_STARTED :
- LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call);
+ message = you + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
break;
default:
break;
}
}
-
- // Update speakers list when connected
- if (LLVoiceChannel::STATE_CONNECTED == new_state)
- {
- mSpeakers->update(true);
- }
- break;
+ }
+ // Update speakers list when connected
+ if (LLVoiceChannel::STATE_CONNECTED == new_state)
+ {
+ mSpeakers->update(true);
}
}
@@ -473,6 +468,17 @@ bool LLIMModel::LLIMSession::isAdHoc()
return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID));
}
+bool LLIMModel::LLIMSession::isP2P()
+{
+ return IM_NOTHING_SPECIAL == mType;
+}
+
+bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
+{
+ return !mOtherParticipantIsAvatar;
+}
+
+
void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
LLIMSession* session = findIMSession(old_session_id);
@@ -1476,13 +1482,17 @@ LLCallDialog(payload)
}
}
-void LLOutgoingCallDialog::draw()
+void LLCallDialog::draw()
{
if (lifetimeHasExpired())
{
onLifetimeExpired();
}
- LLDockableFloater::draw();
+
+ if (getDockControl() != NULL)
+ {
+ LLDockableFloater::draw();
+ }
}
bool LLOutgoingCallDialog::lifetimeHasExpired()
@@ -1490,7 +1500,7 @@ bool LLOutgoingCallDialog::lifetimeHasExpired()
if (mLifetimeTimer.getStarted())
{
F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32();
- if (elapsed_time > LIFETIME)
+ if (elapsed_time > mLifetime)
{
return true;
}
@@ -1511,6 +1521,13 @@ void LLOutgoingCallDialog::show(const LLSD& key)
// hide all text at first
hideAllText();
+ // init notification's lifetime
+ std::istringstream ss( getString("lifetime") );
+ if (!(ss >> mLifetime))
+ {
+ mLifetime = DEFAULT_LIFETIME;
+ }
+
// customize text strings
// tell the user which voice channel they are leaving
if (!mPayload["old_channel_name"].asString().empty())
@@ -1621,6 +1638,35 @@ LLCallDialog(payload)
{
}
+bool LLIncomingCallDialog::lifetimeHasExpired()
+{
+ if (mLifetimeTimer.getStarted())
+ {
+ F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32();
+ if (elapsed_time > mLifetime)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLIncomingCallDialog::onLifetimeExpired()
+{
+ // check whether a call is valid or not
+ if (LLVoiceClient::getInstance()->findSession(mPayload["caller_id"].asUUID()))
+ {
+ // restart notification's timer if call is still valid
+ mLifetimeTimer.start();
+ }
+ else
+ {
+ // close invitation if call is already not valid
+ mLifetimeTimer.stop();
+ closeFloater();
+ }
+}
+
BOOL LLIncomingCallDialog::postBuild()
{
LLCallDialog::postBuild();
@@ -1629,6 +1675,13 @@ BOOL LLIncomingCallDialog::postBuild()
LLSD caller_id = mPayload["caller_id"];
std::string caller_name = mPayload["caller_name"].asString();
+ // init notification's lifetime
+ std::istringstream ss( getString("lifetime") );
+ if (!(ss >> mLifetime))
+ {
+ mLifetime = DEFAULT_LIFETIME;
+ }
+
std::string call_type;
if (gAgent.isInGroup(session_id))
{
@@ -1659,13 +1712,30 @@ BOOL LLIncomingCallDialog::postBuild()
LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
caller_name_widget->setValue(caller_name + " " + call_type);
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
- icon->setValue(caller_id);
+ if (is_avatar)
+ {
+ icon->setValue(caller_id);
+ }
+ else
+ {
+ icon->setValue("Avaline_Icon");
+ }
childSetAction("Accept", onAccept, this);
childSetAction("Reject", onReject, this);
childSetAction("Start IM", onStartIM, this);
childSetFocus("Accept");
+ if(mPayload["notify_box_type"] != "VoiceInviteGroup" && mPayload["notify_box_type"] != "VoiceInviteAdHoc")
+ {
+ // starting notification's timer for P2P and AVALINE invitations
+ mLifetimeTimer.start();
+ }
+ else
+ {
+ mLifetimeTimer.stop();
+ }
+
return TRUE;
}
@@ -1796,6 +1866,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
new LLViewerChatterBoxInvitationAcceptResponder(
session_id,
inv_type));
+
+ // send notification message to the corresponding chat
+ if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc")
+ {
+ std::string started_call = LLTrans::getString("started_call");
+ std::string message = mPayload["caller_name"].asString() + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message);
+ }
}
}
if (voice)
@@ -2463,6 +2541,11 @@ void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body
if (speaker_mgr)
{
speaker_mgr->updateSpeakers(body);
+
+ // also the same call is added into LLVoiceClient::participantUpdatedEvent because
+ // sometimes it is called AFTER LLViewerChatterBoxSessionAgentListUpdates::post()
+ // when moderation state changed too late. See EXT-3544.
+ speaker_mgr->update(true);
}
else
{
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 3f46b0d754..cec9d1642f 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -75,6 +75,8 @@ public:
static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
bool isAdHoc();
+ bool isP2P();
+ bool isOtherParticipantAvaline();
LLUUID mSessionID;
std::string mName;
@@ -486,7 +488,18 @@ public:
virtual BOOL postBuild();
+ // check timer state
+ /*virtual*/ void draw();
+
protected:
+ // lifetime timer for a notification
+ LLTimer mLifetimeTimer;
+ // notification's lifetime in seconds
+ S32 mLifetime;
+ static const S32 DEFAULT_LIFETIME = 5;
+ virtual bool lifetimeHasExpired() {return false;};
+ virtual void onLifetimeExpired() {};
+
virtual void getAllowedRect(LLRect& rect);
LLSD mPayload;
};
@@ -504,6 +517,8 @@ public:
static void onStartIM(void* user_data);
private:
+ /*virtual*/ bool lifetimeHasExpired();
+ /*virtual*/ void onLifetimeExpired();
void processCallResponse(S32 response);
};
@@ -518,19 +533,11 @@ public:
static void onCancel(void* user_data);
static const LLUUID OCD_KEY;
- // check timer state
- /*virtual*/ void draw();
-
private:
-
// hide all text boxes
void hideAllText();
- // lifetime timer for NO_ANSWER notification
- LLTimer mLifetimeTimer;
- // lifetime duration for NO_ANSWER notification
- static const S32 LIFETIME = 5;
- bool lifetimeHasExpired();
- void onLifetimeExpired();
+ /*virtual*/ bool lifetimeHasExpired();
+ /*virtual*/ void onLifetimeExpired();
};
// Globals
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 1eb8d1bc2c..711114173c 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2654,6 +2654,33 @@ void LLInventoryModel::buildParentChildMap()
cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
if(catsp)
{
+ // *HACK - fix root inventory folder
+ // some accounts has pbroken inventory root folders
+
+ std::string name = "My Inventory";
+ LLUUID prev_root_id = mRootFolderID;
+ for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
+ it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
+ {
+ cat_array_t* cat_array = it->second;
+ for (cat_array_t::const_iterator cat_it = cat_array->begin(),
+ cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it)
+ {
+ LLPointer<LLViewerInventoryCategory> category = *cat_it;
+
+ if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY)
+ continue;
+ if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) )
+ {
+ if(category->getUUID()!=mRootFolderID)
+ {
+ LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID);
+ new_inv_root_folder_id = category->getUUID();
+ }
+ }
+ }
+ }
+
// 'My Inventory',
// root of the agent's inv found.
// The inv tree is built.
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 082b7a9468..164e72e621 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -628,9 +628,15 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EAcceptance* accept,
std::string& tooltip_msg)
{
-
BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ // If folder view is empty the (x, y) point won't be in its rect
+ // so the handler must be called explicitly.
+ if (!mFolders->hasVisibleChildren())
+ {
+ handled = mFolders->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ }
+
if (handled)
{
mFolders->setDragAndDropThisFrame();
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 818e7e0db1..0ab3b07aea 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -684,7 +684,6 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick()
gAgent.setFlying(FALSE);
setFocus(FALSE); // EXT-482
- setVisible(FALSE);
}
/**
diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp
index c3df4cbaf4..52de8355e9 100644
--- a/indra/newview/llnotificationalerthandler.cpp
+++ b/indra/newview/llnotificationalerthandler.cpp
@@ -93,6 +93,19 @@ bool LLAlertHandler::processNotification(const LLSD& notify)
if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load")
{
+ if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification))
+ {
+ const std::string name = LLHandlerUtil::getSubstitutionName(notification);
+
+ LLUUID from_id = notification->getPayload()["from_id"];
+
+ // firstly create session...
+ LLHandlerUtil::spawnIMSession(name, from_id);
+
+ // ...then log message to have IM Well notified about new message
+ LLHandlerUtil::logToIMP2P(notification);
+ }
+
LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);
LLToast::Params p;
p.notif_id = notification->getID();
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 515c86bae8..0fb438bfe9 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -277,6 +277,13 @@ public:
static bool canSpawnIMSession(const LLNotificationPtr& notification);
/**
+ * Checks if passed notification can create IM session and be written into it.
+ *
+ * This method uses canLogToIM() & canSpawnIMSession().
+ */
+ static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification);
+
+ /**
* Writes notification message to IM session.
*/
static void logToIM(const EInstantMessage& session_type,
@@ -298,6 +305,20 @@ public:
* Writes notification message to nearby chat.
*/
static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type);
+
+ /**
+ * Spawns IM session.
+ */
+ static void spawnIMSession(const std::string& name, const LLUUID& from_id);
+
+ /**
+ * Returns name from the notification's substitution.
+ *
+ * Methods gets "NAME" or "[NAME]" from the substitution map.
+ *
+ * @param notification - Notification which substitution's name will be returned.
+ */
+ static std::string getSubstitutionName(const LLNotificationPtr& notification);
};
}
diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp
index 5b54092c5c..fba5773602 100644
--- a/indra/newview/llnotificationhandlerutil.cpp
+++ b/indra/newview/llnotificationhandlerutil.cpp
@@ -47,11 +47,15 @@ const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),
"ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER(
"ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"),
ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"),
- USER_GIVE_ITEM("UserGiveItem"), OFFER_FRIENDSHIP("OfferFriendship"),
+ USER_GIVE_ITEM("UserGiveItem"),
+ INVENTORY_ACCEPTED("InventoryAccepted"),
+ INVENTORY_DECLINED("InventoryDeclined"),
+ OFFER_FRIENDSHIP("OfferFriendship"),
FRIENDSHIP_ACCEPTED("FriendshipAccepted"),
FRIENDSHIP_OFFERED("FriendshipOffered"),
FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"),
- SERVER_OBJECT_MESSAGE("ServerObjectMessage");
+ SERVER_OBJECT_MESSAGE("ServerObjectMessage"),
+ TELEPORT_OFFERED("TeleportOffered");
// static
bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)
@@ -59,8 +63,11 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)
return GRANTED_MODIFY_RIGHTS == notification->getName()
|| REVOKED_MODIFY_RIGHTS == notification->getName()
|| PAYMENT_RECIVED == notification->getName()
+ || OFFER_FRIENDSHIP == notification->getName()
|| FRIENDSHIP_OFFERED == notification->getName()
- || SERVER_OBJECT_MESSAGE == notification->getName();
+ || SERVER_OBJECT_MESSAGE == notification->getName()
+ || INVENTORY_ACCEPTED == notification->getName()
+ || INVENTORY_DECLINED == notification->getName();
}
// static
@@ -68,15 +75,25 @@ bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)
{
return notification->getType() == "notifytip"
&& FRIEND_ONLINE != notification->getName()
- && FRIEND_OFFLINE != notification->getName();
+ && FRIEND_OFFLINE != notification->getName()
+ && INVENTORY_ACCEPTED != notification->getName()
+ && INVENTORY_DECLINED != notification->getName();
}
// static
bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)
{
- return ADD_FRIEND_WITH_MESSAGE == notification->getName()
- || OFFER_FRIENDSHIP == notification->getName()
- || FRIENDSHIP_ACCEPTED == notification->getName();
+ return OFFER_FRIENDSHIP == notification->getName()
+ || FRIENDSHIP_ACCEPTED == notification->getName()
+ || USER_GIVE_ITEM == notification->getName()
+ || INVENTORY_ACCEPTED == notification->getName()
+ || INVENTORY_DECLINED == notification->getName();
+}
+
+// static
+bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification)
+{
+ return canLogToIM(notification) && canSpawnIMSession(notification);
}
// static
@@ -113,10 +130,7 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,
// static
void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)
{
- const std::string
- name =
- notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"]
- : notification->getSubstitutions()["[NAME]"];
+ const std::string name = LLHandlerUtil::getSubstitutionName(notification);
const std::string session_name = notification->getPayload().has(
"SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name;
@@ -169,3 +183,23 @@ void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChat
}
}
+// static
+void LLHandlerUtil::spawnIMSession(const std::string& name, const LLUUID& from_id)
+{
+ LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id);
+
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
+ session_id);
+ if (session == NULL)
+ {
+ LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, from_id);
+ }
+}
+
+// static
+std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notification)
+{
+ return notification->getSubstitutions().has("NAME")
+ ? notification->getSubstitutions()["NAME"]
+ : notification->getSubstitutions()["[NAME]"];
+}
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
index 4d64c5c0e4..dd66a6c507 100644
--- a/indra/newview/llnotificationofferhandler.cpp
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -105,22 +105,11 @@ bool LLOfferHandler::processNotification(const LLSD& notify)
{
if (LLHandlerUtil::canSpawnIMSession(notification))
{
- const std::string name = notification->getSubstitutions().has(
- "NAME") ? notification->getSubstitutions()["NAME"]
- : notification->getSubstitutions()["[NAME]"];
+ const std::string name = LLHandlerUtil::getSubstitutionName(notification);
LLUUID from_id = notification->getPayload()["from_id"];
- LLUUID session_id = LLIMMgr::computeSessionID(
- IM_NOTHING_SPECIAL, from_id);
-
- LLIMModel::LLIMSession* session =
- LLIMModel::instance().findIMSession(session_id);
- if (session == NULL)
- {
- LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL,
- from_id);
- }
+ LLHandlerUtil::spawnIMSession(name, from_id);
}
if (notification->getPayload().has("SUPPRES_TOST")
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 9afaddae82..83a2215ac6 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -101,6 +101,19 @@ bool LLTipHandler::processNotification(const LLSD& notify)
}
}
+ const std::string name = notification->getSubstitutions()["NAME"];
+ LLUUID from_id = notification->getPayload()["from_id"];
+ if (LLHandlerUtil::canLogToIM(notification))
+ {
+ LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, name, name,
+ notification->getMessage(), from_id, from_id);
+ }
+
+ if (LLHandlerUtil::canSpawnIMSession(notification))
+ {
+ LLHandlerUtil::spawnIMSession(name, from_id);
+ }
+
LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
LLToast::Params p;
diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp
index fa16cb6473..63803469dd 100644
--- a/indra/newview/lloutputmonitorctrl.cpp
+++ b/indra/newview/lloutputmonitorctrl.cpp
@@ -64,10 +64,6 @@ LLOutputMonitorCtrl::Params::Params()
auto_update("auto_update"),
speaker_id("speaker_id")
{
- draw_border = true;
- name = "output_monitor";
- follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
- mouse_opaque = false;
};
LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p)
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index e9131a342e..913152e259 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -179,6 +179,10 @@ void LLPanelAvatarNotes::onOpen(const LLSD& key)
void LLPanelAvatarNotes::fillRightsData()
{
+ childSetValue("status_check", FALSE);
+ childSetValue("map_check", FALSE);
+ childSetValue("objects_check", FALSE);
+
const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
// If true - we are viewing friend's profile, enable check boxes and set values.
if(relation)
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 3f309b3bf5..a8a75a1feb 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -65,7 +65,11 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
- bool is_call_started = ( new_state >= LLVoiceChannel::STATE_CALL_STARTED );
+ updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+}
+
+void LLPanelChatControlPanel::updateButtons(bool is_call_started)
+{
childSetVisible("end_call_btn", is_call_started);
childSetVisible("voice_ctrls_btn", is_call_started);
childSetVisible("call_btn", ! is_call_started);
@@ -112,6 +116,9 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
if(voice_channel)
{
mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
+
+ //call (either p2p, group or ad-hoc) can be already in started state
+ updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
}
}
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 711340efc7..c18be5a6df 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -57,6 +57,8 @@ public:
virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
+ void updateButtons(bool is_call_started);
+
virtual void setSessionId(const LLUUID& session_id);
const LLUUID& getSessionId() { return mSessionId; }
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index 5de7c3f851..597b8bdb2d 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -81,7 +81,8 @@ BOOL LLPanelLandmarkInfo::postBuild()
mCreator = getChild<LLTextBox>("creator");
mCreated = getChild<LLTextBox>("created");
- mTitleEditor = getChild<LLLineEditor>("title_editor");
+ mLandmarkTitle = getChild<LLTextBox>("title_value");
+ mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor");
mNotesEditor = getChild<LLTextEditor>("notes_editor");
mFolderCombo = getChild<LLComboBox>("folder_combo");
@@ -101,7 +102,8 @@ void LLPanelLandmarkInfo::resetLocation()
mCreator->setText(not_available);
mOwner->setText(not_available);
mCreated->setText(not_available);
- mTitleEditor->setText(LLStringUtil::null);
+ mLandmarkTitle->setText(LLStringUtil::null);
+ mLandmarkTitleEditor->setText(LLStringUtil::null);
mNotesEditor->setText(LLStringUtil::null);
}
@@ -122,7 +124,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)
case CREATE_LANDMARK:
mCurrentTitle = getString("title_create_landmark");
- mTitleEditor->setEnabled(TRUE);
+ mLandmarkTitle->setVisible(FALSE);
+ mLandmarkTitleEditor->setVisible(TRUE);
mNotesEditor->setEnabled(TRUE);
break;
@@ -130,7 +133,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)
default:
mCurrentTitle = getString("title_landmark");
- mTitleEditor->setEnabled(FALSE);
+ mLandmarkTitle->setVisible(TRUE);
+ mLandmarkTitleEditor->setVisible(FALSE);
mNotesEditor->setEnabled(FALSE);
break;
}
@@ -185,12 +189,12 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data)
{
if (parcel_data.name.empty())
{
- mTitleEditor->setText(llformat("%s (%d, %d, %d)",
+ mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)",
parcel_data.sim_name.c_str(), region_x, region_y, region_z));
}
else
{
- mTitleEditor->setText(parcel_data.name);
+ mLandmarkTitleEditor->setText(parcel_data.name);
}
std::string desc;
@@ -281,7 +285,8 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
mCreated->setText(timeStr);
}
- mTitleEditor->setText(pItem->getName());
+ mLandmarkTitle->setText(pItem->getName());
+ mLandmarkTitleEditor->setText(pItem->getName());
mNotesEditor->setText(pItem->getDescription());
}
@@ -296,11 +301,14 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)
else
{
mTitle->setText(mCurrentTitle);
+
+ mLandmarkTitle->setText(mLandmarkTitleEditor->getText());
}
if (mNotesEditor->getReadOnly() == (enabled == TRUE))
{
- mTitleEditor->setEnabled(enabled);
+ mLandmarkTitle->setVisible(!enabled);
+ mLandmarkTitleEditor->setVisible(enabled);
mNotesEditor->setReadOnly(!enabled);
mFolderCombo->setVisible(enabled);
getChild<LLTextBox>("folder_label")->setVisible(enabled);
@@ -313,7 +321,7 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)
const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const
{
- return mTitleEditor->getText();
+ return mLandmarkTitleEditor->getText();
}
const std::string LLPanelLandmarkInfo::getLandmarkNotes() const
@@ -333,7 +341,7 @@ BOOL LLPanelLandmarkInfo::setLandmarkFolder(const LLUUID& id)
void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)
{
- std::string name = mTitleEditor->getText();
+ std::string name = mLandmarkTitleEditor->getText();
std::string desc = mNotesEditor->getText();
LLStringUtil::trim(name);
diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h
index 73e0ddb9cc..2a9949ae41 100644
--- a/indra/newview/llpanellandmarkinfo.h
+++ b/indra/newview/llpanellandmarkinfo.h
@@ -77,7 +77,8 @@ private:
LLTextBox* mOwner;
LLTextBox* mCreator;
LLTextBox* mCreated;
- LLLineEditor* mTitleEditor;
+ LLTextBox* mLandmarkTitle;
+ LLLineEditor* mLandmarkTitleEditor;
LLTextEditor* mNotesEditor;
LLComboBox* mFolderCombo;
};
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index e16bac2098..87abb16395 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -49,9 +49,9 @@
#include "llfloaterworldmap.h"
#include "llfolderviewitem.h"
#include "llinventorypanel.h"
-#include "llinventorysubtreepanel.h"
#include "lllandmarkactions.h"
#include "llplacesinventorybridge.h"
+#include "llplacesinventorypanel.h"
#include "llsidetray.h"
#include "llviewermenu.h"
#include "llviewerregion.h"
@@ -66,15 +66,54 @@ static const std::string TRASH_BUTTON_NAME = "trash_btn";
// helper functions
-static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string);
-static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list);
+static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
+static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
/**
- * Bridge to support knowing when the inventory has changed to update folder (open/close) state
- * for landmarks panels.
- *
- * Due to Inventory data are loaded in background we need to save folder state each time
- * next level is loaded. See EXT-3094.
+ * Functor counting expanded and collapsed folders in folder view tree to know
+ * when to enable or disable "Expand all folders" and "Collapse all folders" commands.
+ */
+class LLCheckFolderState : public LLFolderViewFunctor
+{
+public:
+ LLCheckFolderState()
+ : mCollapsedFolders(0),
+ mExpandedFolders(0)
+ {}
+ virtual ~LLCheckFolderState() {}
+ virtual void doFolder(LLFolderViewFolder* folder);
+ virtual void doItem(LLFolderViewItem* item) {}
+ S32 getCollapsedFolders() { return mCollapsedFolders; }
+ S32 getExpandedFolders() { return mExpandedFolders; }
+
+private:
+ S32 mCollapsedFolders;
+ S32 mExpandedFolders;
+};
+
+// virtual
+void LLCheckFolderState::doFolder(LLFolderViewFolder* folder)
+{
+ // Counting only folders that pass the filter.
+ // The listener check allow us to avoid counting the folder view
+ // object itself because it has no listener assigned.
+ if (folder->hasFilteredDescendants() && folder->getListener())
+ {
+ if (folder->isOpen())
+ {
+ ++mExpandedFolders;
+ }
+ else
+ {
+ ++mCollapsedFolders;
+ }
+ }
+}
+
+/**
+ * Bridge to support knowing when the inventory has changed to update Landmarks tab
+ * ShowFolderState filter setting to show all folders when the filter string is empty and
+ * empty folder message when Landmarks inventory category has no children.
*/
class LLLandmarksPanelObserver : public LLInventoryObserver
{
@@ -89,7 +128,7 @@ private:
void LLLandmarksPanelObserver::changed(U32 mask)
{
- mLP->saveFolderStateIfNoFilter();
+ mLP->updateShowFolderState();
}
LLLandmarksPanel::LLLandmarksPanel()
@@ -134,22 +173,12 @@ BOOL LLLandmarksPanel::postBuild()
getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true);
getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true);
- gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);
return TRUE;
}
// virtual
void LLLandmarksPanel::onSearchEdit(const std::string& string)
{
- // show all folders in Landmarks Accordion for empty filter
- if (mLandmarksInventoryPanel->getFilter())
- {
- mLandmarksInventoryPanel->setShowFolderState(string.empty() ?
- LLInventoryFilter::SHOW_ALL_FOLDERS :
- LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
- );
- }
-
// give FolderView a chance to be refreshed. So, made all accordions visible
for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
{
@@ -162,7 +191,7 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)
tab->changeOpenClose(false);
}
- LLInventorySubTreePanel* inventory_list = dynamic_cast<LLInventorySubTreePanel*>(tab->getAccordionView());
+ LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());
if (NULL == inventory_list) continue;
if (inventory_list->getFilter())
@@ -173,6 +202,10 @@ void LLLandmarksPanel::onSearchEdit(const std::string& string)
if (sFilterSubString != string)
sFilterSubString = string;
+
+ // show all folders in Landmarks Accordion for empty filter
+ // only if Landmarks inventory folder is not empty
+ updateShowFolderState();
}
// virtual
@@ -226,7 +259,7 @@ void LLLandmarksPanel::updateVerbs()
updateListCommands();
}
-void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
{
if (user_action && (items.size() > 0))
{
@@ -254,12 +287,21 @@ void LLLandmarksPanel::onSelectorButtonClicked()
}
}
-void LLLandmarksPanel::saveFolderStateIfNoFilter()
+void LLLandmarksPanel::updateShowFolderState()
{
- save_folder_state_if_no_filter(mFavoritesInventoryPanel);
- save_folder_state_if_no_filter(mLandmarksInventoryPanel);
- save_folder_state_if_no_filter(mMyInventoryPanel);
- save_folder_state_if_no_filter(mLibraryInventoryPanel);
+ if (!mLandmarksInventoryPanel->getFilter())
+ return;
+
+ bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty();
+ if (show_all_folders)
+ {
+ show_all_folders = category_has_descendents(mLandmarksInventoryPanel);
+ }
+
+ mLandmarksInventoryPanel->setShowFolderState(show_all_folders ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS :
+ LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
+ );
}
//////////////////////////////////////////////////////////////////////////
@@ -361,7 +403,7 @@ void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
void LLLandmarksPanel::initFavoritesInventoryPanel()
{
- mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list");
+ mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");
initLandmarksPanel(mFavoritesInventoryPanel);
mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems");
@@ -371,7 +413,7 @@ void LLLandmarksPanel::initFavoritesInventoryPanel()
void LLLandmarksPanel::initLandmarksInventoryPanel()
{
- mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list");
+ mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list");
initLandmarksPanel(mLandmarksInventoryPanel);
@@ -390,7 +432,7 @@ void LLLandmarksPanel::initLandmarksInventoryPanel()
void LLLandmarksPanel::initMyInventoryPanel()
{
- mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list");
+ mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list");
initLandmarksPanel(mMyInventoryPanel);
@@ -399,14 +441,14 @@ void LLLandmarksPanel::initMyInventoryPanel()
void LLLandmarksPanel::initLibraryInventoryPanel()
{
- mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list");
+ mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list");
initLandmarksPanel(mLibraryInventoryPanel);
initAccordion("tab_library", mLibraryInventoryPanel);
}
-void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list)
+void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list)
{
// In case of a dummy widget further we have no Folder View widget and no Filter,
// so further initialization leads to crash.
@@ -430,7 +472,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis
inventory_list->saveFolderState();
}
-void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
+void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list)
{
LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
@@ -440,7 +482,7 @@ void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLIn
accordion_tab->setDisplayChildren(false);
}
-void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list)
+void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list)
{
bool expanded = param.asBoolean();
@@ -466,7 +508,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInvento
}
}
-void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list)
+void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list)
{
if (inventory_list != mFavoritesInventoryPanel)
{
@@ -660,7 +702,12 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
}
else if ("collapse_all" == command_name)
{
- root_folder->closeAllFolders();
+ root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
+
+ // The top level folder is invisible, it must be open to
+ // display its sub-folders.
+ root_folder->openTopLevelFolders();
+ root_folder->arrangeAll();
}
else if ( "sort_by_date" == command_name)
{
@@ -722,6 +769,20 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
return false;
}
+ LLCheckFolderState checker;
+ rootFolderView->applyFunctorRecursively(checker);
+
+ // We assume that the root folder is always expanded so we enable "collapse_all"
+ // command when we have at least one more expanded folder.
+ if (checker.getExpandedFolders() < 2 && "collapse_all" == command_name)
+ {
+ return false;
+ }
+
+ if (checker.getCollapsedFolders() < 1 && "expand_all" == command_name)
+ {
+ return false;
+ }
if("category" == command_name)
{
@@ -778,46 +839,6 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
}
}
-void LLLandmarksPanel::updateFilteredAccordions()
-{
- LLInventoryPanel* inventory_list = NULL;
- LLAccordionCtrlTab* accordion_tab = NULL;
- bool needs_arrange = false;
-
- for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
- {
- accordion_tab = *iter;
-
- accordion_tab->setVisible(TRUE);
-
- inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView());
- if (NULL == inventory_list) continue;
-
- // This doesn't seem to work correctly. Disabling for now. -Seraph
- // Enabled to show/hide accordions with/without landmarks. See EXT-2346. (Seth PE)
- LLFolderView* fv = inventory_list->getRootFolder();
-
- // arrange folder view contents to draw its descendants if it has any
- fv->arrangeFromRoot();
-
- bool has_descendants = fv->hasFilteredDescendants();
- if (!has_descendants)
- needs_arrange = true;
-
- accordion_tab->setVisible(has_descendants);
-
- //accordion_tab->setVisible(TRUE);
- }
-
- // we have to arrange accordion tabs for cases when filter string is less restrictive but
- // all items are still filtered.
- if (needs_arrange)
- {
- static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
- accordion->arrange();
- }
-}
-
/*
Processes such actions: cut/rename/delete/paste actions
@@ -926,13 +947,6 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
return true;
}
-// static
-void LLLandmarksPanel::doIdle(void* landmarks_panel)
-{
- LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel;
- panel->updateFilteredAccordions();
-}
-
void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)
{
LLVector3d landmark_global_pos;
@@ -1028,10 +1042,10 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)
//////////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////
-static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)
+static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)
{
// When search is cleared, restore the old folder state.
- if (string == "")
+ if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "")
{
inventory_list->setFilterSubString(LLStringUtil::null);
// Re-open folders that were open before
@@ -1056,15 +1070,16 @@ static void filter_list(LLInventorySubTreePanel* inventory_list, const std::stri
// Set new filter string
inventory_list->setFilterSubString(string);
-
}
-static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list)
+static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
{
- // save current folder open state if no filter currently applied
- if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty())
+ LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID());
+ if (category)
{
- // inventory_list->saveFolderState(); // *TODO: commented out to fix build
+ return category->getDescendentCount() > 0;
}
+
+ return false;
}
// EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index b0e537f647..569739237d 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -46,7 +46,7 @@ class LLAccordionCtrlTab;
class LLFolderViewItem;
class LLMenuGL;
class LLInventoryPanel;
-class LLInventorySubTreePanel;
+class LLPlacesInventoryPanel;
class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
{
@@ -60,17 +60,18 @@ public:
/*virtual*/ void onTeleport();
/*virtual*/ void updateVerbs();
- void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
void onSelectorButtonClicked();
- void setCurrentSelectedList(LLInventorySubTreePanel* inventory_list)
+ void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list)
{
mCurrentSelectedList = inventory_list;
}
/**
- * Saves folder state for all Inventory Panels if there are no applied filter.
+ * Update filter ShowFolderState setting to show empty folder message
+ * if Landmarks inventory folder is empty.
*/
- void saveFolderStateIfNoFilter();
+ void updateShowFolderState();
protected:
/**
@@ -92,10 +93,10 @@ private:
void initLandmarksInventoryPanel();
void initMyInventoryPanel();
void initLibraryInventoryPanel();
- void initLandmarksPanel(LLInventorySubTreePanel* inventory_list);
- void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list);
- void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list);
- void deselectOtherThan(const LLInventorySubTreePanel* inventory_list);
+ void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list);
+ void initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list);
+ void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list);
+ void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list);
// List Commands Handlers
void initListCommandsHandlers();
@@ -112,13 +113,6 @@ private:
void onCustomAction(const LLSD& command_name);
/**
- * Updates accordions according to filtered items in lists.
- *
- * It hides accordion for empty lists
- */
- void updateFilteredAccordions();
-
- /**
* Determines if selected item can be modified via context/gear menu.
*
* It validates Places Landmarks rules first. And then LLFolderView permissions.
@@ -133,11 +127,6 @@ private:
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
/**
- * Static callback for gIdleCallbacks to perform actions out of drawing
- */
- static void doIdle(void* landmarks_panel);
-
- /**
* Landmark actions callbacks. Fire when a landmark is loaded from the list.
*/
void doShowOnMap(LLLandmark* landmark);
@@ -148,14 +137,14 @@ private:
void doCreatePick(LLLandmark* landmark);
private:
- LLInventorySubTreePanel* mFavoritesInventoryPanel;
- LLInventorySubTreePanel* mLandmarksInventoryPanel;
- LLInventorySubTreePanel* mMyInventoryPanel;
- LLInventorySubTreePanel* mLibraryInventoryPanel;
+ LLPlacesInventoryPanel* mFavoritesInventoryPanel;
+ LLPlacesInventoryPanel* mLandmarksInventoryPanel;
+ LLPlacesInventoryPanel* mMyInventoryPanel;
+ LLPlacesInventoryPanel* mLibraryInventoryPanel;
LLMenuGL* mGearLandmarkMenu;
LLMenuGL* mGearFolderMenu;
LLMenuGL* mMenuAdd;
- LLInventorySubTreePanel* mCurrentSelectedList;
+ LLPlacesInventoryPanel* mCurrentSelectedList;
LLInventoryObserver* mInventoryObserver;
LLPanel* mListCommands;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index e5846c7318..5cc4d4aec6 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -965,6 +965,13 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
mFilterSubString = search_upper;
+ //store accordion tabs state before any manipulation with accordion tabs
+ if(!mFilterSubString.empty())
+ {
+ notifyChildren(LLSD().with("action","store_state"));
+ }
+
+
// Apply new filter.
mNearbyList->setNameFilter(mFilterSubString);
mOnlineFriendList->setNameFilter(mFilterSubString);
@@ -976,6 +983,12 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
setAccordionCollapsedByUser("tab_all", false);
showFriendsAccordionsIfNeeded();
+
+ //restore accordion tabs state _after_ all manipulations...
+ if(mFilterSubString.empty())
+ {
+ notifyChildren(LLSD().with("action","restore_state"));
+ }
}
void LLPanelPeople::onTabSelected(const LLSD& param)
@@ -984,6 +997,8 @@ void LLPanelPeople::onTabSelected(const LLSD& param)
mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME);
updateButtons();
+ showFriendsAccordionsIfNeeded();
+
if (GROUP_TAB_NAME == tab_name)
mFilterEditor->setLabel(getString("groups_filter_label"));
else
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index 839452d061..7a4dd3569d 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -284,6 +284,7 @@ void LLPanelPickInfo::setPickName(const std::string& name)
void LLPanelPickInfo::setPickDesc(const std::string& desc)
{
childSetValue(XML_DESC, desc);
+ updateContentPanelRect();
}
void LLPanelPickInfo::setPickLocation(const std::string& location)
@@ -291,6 +292,31 @@ void LLPanelPickInfo::setPickLocation(const std::string& location)
childSetValue(XML_LOCATION, location);
}
+void LLPanelPickInfo::updateContentPanelRect()
+{
+ LLTextBox* desc = getChild<LLTextBox>(XML_DESC);
+
+ S32 text_height = desc->getTextPixelHeight();
+ LLRect text_rect = desc->getRect();
+
+ // let text-box height fit text height
+ text_rect.set(text_rect.mLeft, text_rect.mTop, text_rect.mRight, text_rect.mTop - text_height);
+ desc->setRect(text_rect);
+ desc->reshape(text_rect.getWidth(), text_rect.getHeight());
+ // force reflow
+ desc->setText(desc->getText());
+
+ // bottom of description text-box will be bottom of content panel
+ desc->localRectToOtherView(desc->getLocalRect(), &text_rect, getChild<LLView>("profile_scroll"));
+
+ LLPanel* content_panel = getChild<LLPanel>("scroll_content_panel");
+ LLRect content_rect = content_panel->getRect();
+ content_rect.set(content_rect.mLeft, content_rect.mTop, content_rect.mRight, text_rect.mBottom);
+ // Somehow setRect moves all elements down.
+ // Single reshape() updates rect and does not move anything.
+ content_panel->reshape(content_rect.getWidth(), content_rect.getHeight());
+}
+
void LLPanelPickInfo::onClickMap()
{
LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h
index 95add387d0..12b5a116b4 100644
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -140,6 +140,15 @@ protected:
virtual LLVector3d& getPosGlobal() { return mPosGlobal; }
/**
+ * Reshapes content panel to fit all elements.
+ *
+ * Assume that description text-box is the last element of panel.
+ * Reshape text-box to fit text height and then reshape content panel to fit
+ * text-box bottom. EXT-1326
+ */
+ void updateContentPanelRect();
+
+ /**
* Callback for "Map" button, opens Map
*/
void onClickMap();
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 596bd2909a..77c2fb7c8c 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -60,13 +60,18 @@ class LLTeleportHistoryFlatItem : public LLPanel
{
public:
LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl);
- virtual ~LLTeleportHistoryFlatItem() {};
+ virtual ~LLTeleportHistoryFlatItem();
virtual BOOL postBuild();
+ /*virtual*/ S32 notify(const LLSD& info);
+
S32 getIndex() { return mIndex; }
void setIndex(S32 index) { mIndex = index; }
const std::string& getRegionName() { return mRegionName;}
+ void setRegionName(const std::string& name);
+ void setHighlightedText(const std::string& text);
+ void updateTitle();
/*virtual*/ void setValue(const LLSD& value);
@@ -75,18 +80,51 @@ public:
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
static void showPlaceInfoPanel(S32 index);
+
+ LLHandle<LLTeleportHistoryFlatItem> getItemHandle() { mItemHandle.bind(this); return mItemHandle; }
+
private:
void onProfileBtnClick();
LLButton* mProfileBtn;
+ LLTextBox* mTitle;
LLTeleportHistoryPanel::ContextMenu *mContextMenu;
S32 mIndex;
std::string mRegionName;
std::string mHighlight;
+ LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;
};
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> {
+protected:
+ typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t;
+
+public:
+ LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
+ LLTeleportHistoryPanel::ContextMenu *context_menu,
+ const LLTeleportHistoryPersistentItem& persistent_item,
+ const S32 cur_item_index,
+ const std::string &hl);
+
+ void removeItem(LLTeleportHistoryFlatItem* item);
+
+ void purge();
+
+private:
+
+ flat_item_list_t mItems;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl)
: LLPanel(),
mIndex(index),
@@ -97,18 +135,37 @@ LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistor
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml");
}
+LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
+{
+}
+
//virtual
BOOL LLTeleportHistoryFlatItem::postBuild()
{
- LLTextUtil::textboxSetHighlightedVal(getChild<LLTextBox>("region"), LLStyle::Params(), mRegionName, mHighlight);
+ mTitle = getChild<LLTextBox>("region");
mProfileBtn = getChild<LLButton>("profile_btn");
mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
+ updateTitle();
+
return true;
}
+S32 LLTeleportHistoryFlatItem::notify(const LLSD& info)
+{
+ if(info.has("detach"))
+ {
+ delete mMouseDownSignal;
+ mMouseDownSignal = NULL;
+ delete mRightMouseDownSignal;
+ mRightMouseDownSignal = NULL;
+ return 1;
+ }
+ return 0;
+}
+
void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
{
if (!value.isMap()) return;;
@@ -116,6 +173,25 @@ void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
childSetVisible("selected_icon", value["selected"]);
}
+void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text)
+{
+ mHighlight = text;
+}
+
+void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
+{
+ mRegionName = name;
+}
+
+void LLTeleportHistoryFlatItem::updateTitle()
+{
+ LLTextUtil::textboxSetHighlightedVal(
+ mTitle,
+ LLStyle::Params(),
+ mRegionName,
+ mHighlight);
+}
+
void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", true);
@@ -155,6 +231,82 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick()
LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
}
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistoryFlatItem*
+LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
+ LLTeleportHistoryPanel::ContextMenu *context_menu,
+ const LLTeleportHistoryPersistentItem& persistent_item,
+ const S32 cur_item_index,
+ const std::string &hl)
+{
+ LLTeleportHistoryFlatItem* item = NULL;
+ if ( cur_item_index < (S32) mItems.size() )
+ {
+ item = mItems[cur_item_index].get();
+ if (item->getParent() == NULL)
+ {
+ item->setIndex(cur_item_index);
+ item->setRegionName(persistent_item.mTitle);
+ item->setHighlightedText(hl);
+ item->setVisible(TRUE);
+ item->updateTitle();
+ }
+ else
+ {
+ // Item already added to parent
+ item = NULL;
+ }
+ }
+
+ if ( !item )
+ {
+ item = new LLTeleportHistoryFlatItem(cur_item_index,
+ context_menu,
+ persistent_item.mTitle,
+ hl);
+ mItems.push_back(item->getItemHandle());
+ }
+
+ return item;
+}
+
+void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item)
+{
+ if (item)
+ {
+ flat_item_list_t::iterator item_iter = std::find(mItems.begin(),
+ mItems.end(),
+ item->getItemHandle());
+ if (item_iter != mItems.end())
+ {
+ mItems.erase(item_iter);
+ }
+ }
+}
+
+void LLTeleportHistoryFlatItemStorage::purge()
+{
+ for ( flat_item_list_t::iterator
+ it = mItems.begin(),
+ it_end = mItems.end();
+ it != it_end; ++it )
+ {
+ LLHandle <LLTeleportHistoryFlatItem> item_handle = *it;
+ if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL )
+ {
+ item_handle.get()->die();
+ }
+ }
+ mItems.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
LLTeleportHistoryPanel::ContextMenu::ContextMenu() :
mMenu(NULL)
{
@@ -236,6 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
{
+ LLTeleportHistoryFlatItemStorage::instance().purge();
LLView::deleteViewByHandle(mGearMenuHandle);
}
@@ -478,16 +631,15 @@ void LLTeleportHistoryPanel::refresh()
while (mCurrentItem >= 0)
{
// Filtering
- std::string landmark_title = items[mCurrentItem].mTitle;
- LLStringUtil::toUpper(landmark_title);
-
- std::string::size_type match_offset = sFilterSubString.size() ? landmark_title.find(sFilterSubString) : std::string::npos;
- bool passed = sFilterSubString.size() == 0 || match_offset != std::string::npos;
-
- if (!passed)
+ if (!sFilterSubString.empty())
{
- mCurrentItem--;
- continue;
+ std::string landmark_title(items[mCurrentItem].mTitle);
+ LLStringUtil::toUpper(landmark_title);
+ if( std::string::npos == landmark_title.find(sFilterSubString) )
+ {
+ mCurrentItem--;
+ continue;
+ }
}
// Checking whether date of item is earlier, than tab_boundary_date.
@@ -507,6 +659,9 @@ void LLTeleportHistoryPanel::refresh()
// Expand all accordion tabs when filtering
if(!sFilterSubString.empty())
{
+ //store accordion tab state when filter is not empty
+ tab->notifyChildren(LLSD().with("action","store_state"));
+
tab->setDisplayChildren(true);
}
// Restore each tab's expand state when not filtering
@@ -514,6 +669,9 @@ void LLTeleportHistoryPanel::refresh()
{
bool collapsed = isAccordionCollapsedByUser(tab);
tab->setDisplayChildren(!collapsed);
+
+ //restore accordion state after all those accodrion tabmanipulations
+ tab->notifyChildren(LLSD().with("action","restore_state"));
}
curr_flat_view = getFlatListViewFromTab(tab);
@@ -521,9 +679,14 @@ void LLTeleportHistoryPanel::refresh()
if (curr_flat_view)
{
- LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle, sFilterSubString);
- curr_flat_view->addItem(item);
-
+ LLTeleportHistoryFlatItem* item =
+ LLTeleportHistoryFlatItemStorage::instance()
+ .getFlatItemForPersistentItem(&mContextMenu,
+ items[mCurrentItem],
+ mCurrentItem,
+ sFilterSubString);
+ if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) )
+ llerrs << "Couldn't add flat item to teleport history." << llendl;
if (mLastSelectedItemIndex == mCurrentItem)
curr_flat_view->selectItem(item, true);
}
@@ -534,6 +697,16 @@ void LLTeleportHistoryPanel::refresh()
break;
}
+ for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(n);
+ LLFlatListView* fv = getFlatListViewFromTab(tab);
+ if (fv)
+ {
+ fv->notify(LLSD().with("rearrange", LLSD()));
+ }
+ }
+
mHistoryAccordion->arrange();
updateVerbs();
@@ -566,11 +739,12 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
}
const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
- LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below
- &mContextMenu,
- history_items[history_items.size() - 1].mTitle, // Most recent item, it was
- sFilterSubString);
- // added instead of removed
+ LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
+ .getFlatItemForPersistentItem(&mContextMenu,
+ history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
+ history_items.size(), // index will be decremented inside loop below
+ sFilterSubString);
+
fv->addItem(item, LLUUID::null, ADD_TOP);
// Index of each item, from last to removed item should be decremented
@@ -598,6 +772,8 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
if (item->getIndex() == removed_index)
{
+ LLTeleportHistoryFlatItemStorage::instance().removeItem(item);
+
fv->removeItem(item);
// If flat list becames empty, then accordion tab should be hidden
@@ -629,10 +805,12 @@ void LLTeleportHistoryPanel::showTeleportHistory()
LLFlatListView* fv = getFlatListViewFromTab(tab);
if (fv)
- fv->clear();
+ {
+ // Detached panels are managed by LLTeleportHistoryFlatItemStorage
+ std::vector<LLPanel*> detached_items;
+ fv->detachItems(detached_items);
+ }
}
-
- refresh();
}
void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 7d5944ea2b..330e220af3 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -57,6 +57,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
mSortOrder(E_SORT_BY_NAME)
, mParticipantListMenu(NULL)
, mExcludeAgent(exclude_agent)
+, mValidateSpeakerCallback(NULL)
{
mSpeakerAddListener = new SpeakerAddListener(*this);
mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
@@ -86,22 +87,23 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
}
//Lets fill avatarList with existing speakers
- LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
-
LLSpeakerMgr::speaker_list_t speaker_list;
mSpeakerMgr->getSpeakerList(&speaker_list, true);
for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
{
const LLPointer<LLSpeaker>& speakerp = *it;
- addAvatarIDExceptAgent(group_members, speakerp->mID);
+ addAvatarIDExceptAgent(speakerp->mID);
if ( speakerp->mIsModerator )
{
mModeratorList.insert(speakerp->mID);
}
+ else
+ {
+ mModeratorToRemoveList.insert(speakerp->mID);
+ }
}
// we need to exclude agent id for non group chat
- mAvatarList->setDirty(true);
sort();
}
@@ -161,7 +163,7 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
{
std::string name = item->getAvatarName();
size_t found = name.find(moderator_indicator);
- if (found == std::string::npos)
+ if (found != std::string::npos)
{
name.erase(found, moderator_indicator_len);
item->setName(name);
@@ -208,10 +210,17 @@ LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
return mSortOrder;
}
+void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)
+{
+ mValidateSpeakerCallback = cb;
+}
+
void LLParticipantList::updateRecentSpeakersOrder()
{
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
{
+ // Need to update speakers to sort list correctly
+ mSpeakerMgr->update(true);
// Resort avatar list
sort();
}
@@ -219,19 +228,14 @@ void LLParticipantList::updateRecentSpeakersOrder()
bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
- LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
LLUUID uu_id = event->getValue().asUUID();
- LLAvatarList::uuid_vector_t::iterator found = std::find(group_members.begin(), group_members.end(), uu_id);
- if(found != group_members.end())
+ if (mValidateSpeakerCallback && mValidateSpeakerCallback(uu_id))
{
- llinfos << "Already got a buddy" << llendl;
return true;
}
- addAvatarIDExceptAgent(group_members, uu_id);
- // Mark AvatarList as dirty one
- mAvatarList->setDirty();
+ addAvatarIDExceptAgent(uu_id);
sort();
return true;
}
@@ -329,11 +333,13 @@ void LLParticipantList::sort()
}
}
-void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id)
+void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
{
if (mExcludeAgent && gAgent.getID() == avatar_id) return;
+ if (mAvatarList->contains(avatar_id)) return;
- existing_list.push_back(avatar_id);
+ mAvatarList->getIDs().push_back(avatar_id);
+ mAvatarList->setDirty();
adjustParticipant(avatar_id);
}
@@ -353,7 +359,7 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L
{
/**
* We need to filter speaking objects. These objects shouldn't appear in the list
- * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
+ * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
*/
const LLUUID& speaker_id = event->getValue().asUUID();
LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id);
@@ -575,33 +581,46 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&
{
return mUUIDs.front() != gAgentID;
}
- else
- if (item == "can_allow_text_chat" || "can_moderate_voice" == item)
+ else if (item == "can_allow_text_chat")
+ {
+ return isGroupModerator();
+ }
+ else if ("can_moderate_voice" == item)
+ {
+ if (isGroupModerator())
{
- return isGroupModerator();
+ LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front());
+ if (speakerp.notNull())
+ {
+ // not in voice participants can not be moderated
+ return speakerp->mStatus == LLSpeaker::STATUS_VOICE_ACTIVE
+ || speakerp->mStatus == LLSpeaker::STATUS_MUTED;
+ }
}
+ return false;
+ }
else if (item == std::string("can_add"))
- {
- // We can add friends if:
- // - there are selected people
- // - and there are no friends among selection yet.
+ {
+ // We can add friends if:
+ // - there are selected people
+ // - and there are no friends among selection yet.
- bool result = (mUUIDs.size() > 0);
+ bool result = (mUUIDs.size() > 0);
- std::vector<LLUUID>::const_iterator
- id = mUUIDs.begin(),
- uuids_end = mUUIDs.end();
+ std::vector<LLUUID>::const_iterator
+ id = mUUIDs.begin(),
+ uuids_end = mUUIDs.end();
- for (;id != uuids_end; ++id)
+ for (;id != uuids_end; ++id)
+ {
+ if ( LLAvatarActions::isFriend(*id) )
{
- if ( LLAvatarActions::isFriend(*id) )
- {
- result = false;
- break;
- }
+ result = false;
+ break;
}
- return result;
}
+ return result;
+ }
else if (item == "can_call")
{
return LLVoiceClient::voiceEnabled();
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index c4eb180917..d15ec980db 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -44,6 +44,9 @@ class LLParticipantList
{
LOG_CLASS(LLParticipantList);
public:
+
+ typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
+
LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);
~LLParticipantList();
void setSpeakingIndicatorsVisible(BOOL visible);
@@ -54,6 +57,13 @@ class LLParticipantList
} EParticipantSortOrder;
/**
+ * Adds specified avatar ID to the existing list if it is not Agent's ID
+ *
+ * @param[in] avatar_id - Avatar UUID to be added into the list
+ */
+ void addAvatarIDExceptAgent(const LLUUID& avatar_id);
+
+ /**
* Set and sort Avatarlist by given order
*/
void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
@@ -64,6 +74,15 @@ class LLParticipantList
*/
void updateRecentSpeakersOrder();
+ /**
+ * Set a callback to be called before adding a speaker. Invalid speakers will not be added.
+ *
+ * If the callback is unset all speakers are considered as valid.
+ *
+ * @see onAddItemEvent()
+ */
+ void setValidateSpeakerCallback(validate_speaker_callback_t cb);
+
protected:
/**
* LLSpeakerMgr event handlers
@@ -218,14 +237,6 @@ class LLParticipantList
void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
/**
- * Adds specified avatar ID to the existing list if it is not Agent's ID
- *
- * @param[in, out] existing_list - vector with avatars' UUIDs already in the list
- * @param[in] avatar_id - Avatar UUID to be added into the list
- */
- void addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id);
-
- /**
* Adjusts passed participant to work properly.
*
* Adds SpeakerMuteListener to process moderation actions.
@@ -260,4 +271,5 @@ class LLParticipantList
boost::signals2::connection mAvatarListReturnConnection;
LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
+ validate_speaker_callback_t mValidateSpeakerCallback;
};
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
new file mode 100644
index 0000000000..4de953a59d
--- /dev/null
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -0,0 +1,191 @@
+/**
+ * @file llplacesinventorypanel.cpp
+ * @brief LLPlacesInventoryPanel class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llscrollcontainer.h"
+
+#include "llplacesinventorypanel.h"
+
+#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llpanellandmarks.h"
+#include "llplacesinventorybridge.h"
+
+static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel");
+
+static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER;
+
+LLPlacesInventoryPanel::LLPlacesInventoryPanel(const Params& p) :
+ LLInventoryPanel(p),
+ mSavedFolderState(NULL)
+
+{
+ mInvFVBridgeBuilder = &PLACES_INVENTORY_BUILDER;
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+}
+
+
+LLPlacesInventoryPanel::~LLPlacesInventoryPanel()
+{
+ delete mSavedFolderState;
+}
+
+BOOL LLPlacesInventoryPanel::postBuild()
+{
+ LLInventoryPanel::postBuild();
+
+ // clear Contents();
+ {
+ mFolders->destroyView();
+ mFolders->getParent()->removeChild(mFolders);
+ mFolders->die();
+
+ if( mScroller )
+ {
+ removeChild( mScroller );
+ mScroller->die();
+ mScroller = NULL;
+ }
+ mFolders = NULL;
+ }
+
+
+ mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+
+ // create root folder
+ {
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLPlacesFolderView::Params p;
+ p.name = getName();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ mFolders = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
+ mFolders->setAllowMultiSelect(mAllowMultiSelect);
+ }
+
+ mCommitCallbackRegistrar.popScope();
+
+ mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ // scroller
+ {
+ LLRect scroller_view_rect = getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params p;
+ p.name("Inventory Scroller");
+ p.rect(scroller_view_rect);
+ p.follows.flags(FOLLOWS_ALL);
+ p.reserve_scroll_corner(true);
+ p.tab_stop(true);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ }
+ addChild(mScroller);
+ mScroller->addChild(mFolders);
+
+ mFolders->setScrollContainer(mScroller);
+
+
+ // cut subitems
+ mFolders->setUseEllipses(true);
+
+ return TRUE;
+}
+
+// save current folder open state
+void LLPlacesInventoryPanel::saveFolderState()
+{
+ mSavedFolderState->setApply(FALSE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+}
+
+// re-open folders which state was saved
+void LLPlacesInventoryPanel::restoreFolderState()
+{
+ mSavedFolderState->setApply(TRUE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ getRootFolder()->applyFunctorRecursively(opener);
+ getRootFolder()->scrollToShowSelection();
+}
+
+/************************************************************************/
+/* PROTECTED METHODS */
+/************************************************************************/
+
+
+
+/************************************************************************/
+/* LLPlacesFolderView implementation */
+/************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+// PUBLIC METHODS
+//////////////////////////////////////////////////////////////////////////
+
+BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ // let children to change selection first
+ childrenHandleRightMouseDown(x, y, mask);
+ mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel());
+
+ // then determine its type and set necessary menu handle
+ if (getCurSelectedItem())
+ {
+ LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType();
+ inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type);
+
+ if (it_handle != mMenuHandlesByInventoryType.end())
+ {
+ mPopupMenuHandle = (*it_handle).second;
+ }
+ else
+ {
+ llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl;
+ }
+
+ }
+
+ return LLFolderView::handleRightMouseDown(x, y, mask);
+}
+
+void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle)
+{
+ mMenuHandlesByInventoryType[asset_type] = menu_handle;
+}
+
+// EOF
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
new file mode 100644
index 0000000000..7b34045d32
--- /dev/null
+++ b/indra/newview/llplacesinventorypanel.h
@@ -0,0 +1,96 @@
+/**
+ * @file llplacesinventorypanel.h
+ * @brief LLPlacesInventoryPanel class declaration
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYSUBTREEPANEL_H
+#define LL_LLINVENTORYSUBTREEPANEL_H
+
+#include "llfloaterinventory.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+
+class LLLandmarksPanel;
+
+class LLPlacesInventoryPanel : public LLInventoryPanel
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {
+ Params()
+ {}
+ };
+
+ LLPlacesInventoryPanel(const Params& p);
+ ~LLPlacesInventoryPanel();
+
+ /*virtual*/ BOOL postBuild();
+
+ void saveFolderState();
+ void restoreFolderState();
+
+private:
+ LLSaveFolderState* mSavedFolderState;
+};
+
+
+class LLPlacesFolderView : public LLFolderView
+{
+public:
+ LLPlacesFolderView(const LLFolderView::Params& p) : LLFolderView(p) {};
+ /**
+ * Handles right mouse down
+ *
+ * Contains workaround for EXT-2786: sets current selected list for landmark
+ * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel
+ */
+ /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+
+ void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle);
+
+ void setParentLandmarksPanel(LLLandmarksPanel* panel)
+ {
+ mParentLandmarksPanel = panel;
+ }
+
+ S32 getSelectedCount() { return (S32)mSelectedItems.size(); }
+
+private:
+ /**
+ * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown
+ */
+ LLLandmarksPanel* mParentLandmarksPanel;
+ typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t;
+ inventory_type_menu_handle_t mMenuHandlesByInventoryType;
+
+};
+
+#endif //LL_LLINVENTORYSUBTREEPANEL_H
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index c18fe8ad7e..8c3f3dc5fb 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -462,6 +462,8 @@ void LLScreenChannel::showToastsBottom()
S32 toast_margin = 0;
std::vector<ToastElem>::reverse_iterator it;
+ LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
+
for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
{
if(it != mToastList.rbegin())
@@ -474,6 +476,16 @@ void LLScreenChannel::showToastsBottom()
toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight());
(*it).toast->setRect(toast_rect);
+ // don't show toasts if there is not enough space
+ if(floater && floater->overlapsScreenChannel())
+ {
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ if(toast_rect.mTop + getOverflowToastHeight() + toast_margin > world_rect.mTop)
+ {
+ break;
+ }
+ }
+
bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;
if(!stop_showing_toasts)
@@ -575,6 +587,18 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());
mOverflowToastPanel->setRect(toast_rect);
+ // don't show overflow toast if there is not enough space for it.
+ LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
+ if(floater && floater->overlapsScreenChannel())
+ {
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ if(toast_rect.mTop > world_rect.mTop)
+ {
+ closeOverflowToastPanel();
+ return;
+ }
+ }
+
text_box->setValue(text);
text_box->setVisible(TRUE);
@@ -664,6 +688,24 @@ F32 LLScreenChannel::getHeightRatio()
return ratio;
}
+S32 LLScreenChannel::getOverflowToastHeight()
+{
+ if(mOverflowToastPanel)
+ {
+ return mOverflowToastPanel->getRect().getHeight();
+ }
+
+ static S32 height = 0;
+ if(0 == height)
+ {
+ LLToast::Params p;
+ LLToast* toast = new LLToast(p);
+ height = toast->getRect().getHeight();
+ delete toast;
+ }
+ return height;
+}
+
//--------------------------------------------------------------------------
void LLScreenChannel::updateStartUpString(S32 num)
{
@@ -822,25 +864,22 @@ void LLScreenChannel::updateShowToastsState()
return;
}
- // for Message Well floater showed in a docked state - adjust channel's height
- if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater)
- || dynamic_cast<LLScriptFloater*>(floater))
+ S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
+ LLRect this_rect = getRect();
+
+ // adjust channel's height
+ if(floater->overlapsScreenChannel())
{
- S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
- LLRect this_rect = getRect();
- if(floater->getVisible() && floater->isDocked())
+ channel_bottom += floater->getRect().getHeight();
+ if(floater->getDockControl())
{
- channel_bottom += floater->getRect().getHeight();
- if(floater->getDockControl())
- {
- channel_bottom += floater->getDockControl()->getTongueHeight();
- }
+ channel_bottom += floater->getDockControl()->getTongueHeight();
}
+ }
- if(channel_bottom != this_rect.mBottom)
- {
- setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));
- }
+ if(channel_bottom != this_rect.mBottom)
+ {
+ setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));
}
}
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index 321fb244a1..38f27f756b 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -281,6 +281,8 @@ private:
*/
static F32 getHeightRatio();
+ S32 getOverflowToastHeight();
+
// Channel's flags
static bool mWasStartUpToastShown;
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 1962d871a6..cf62d47362 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -67,6 +67,7 @@ LLScriptFloater::LLScriptFloater(const LLSD& key)
, mScriptForm(NULL)
{
setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this));
+ setOverlapsScreenChannel(true);
}
bool LLScriptFloater::toggle(const LLUUID& object_id)
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index 90214a1bd7..8f2c877c7a 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -123,7 +123,7 @@ LLSpeakButton::LLSpeakButton(const Params& p)
mOutputMonitor->setIsAgentControl(true);
//*TODO find a better place to do that
- LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1));
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);
}
LLSpeakButton::~LLSpeakButton()
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 91b417c61f..010dfd1b33 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -615,6 +615,9 @@ private:
void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+ if (!speakerp) return;
+
std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
LLSD data;
data["method"] = "mute update";
@@ -623,7 +626,7 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
data["params"]["agent_id"] = speaker_id;
data["params"]["mute_info"] = LLSD::emptyMap();
//current value represents ability to type, so invert
- data["params"]["mute_info"]["text"] = !findSpeaker(speaker_id)->mModeratorMutedText;
+ data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText;
LLHTTPClient::post(url, data, new ModerationResponder(getSessionID()));
}
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 8c6ea59407..bcaefc3690 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -63,6 +63,7 @@ LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key)
{
mTypedItemsCount[IT_NOTIFICATION] = 0;
mTypedItemsCount[IT_INSTANT_MESSAGE] = 0;
+ setOverlapsScreenChannel(true);
}
//---------------------------------------------------------------------------------
@@ -743,9 +744,13 @@ BOOL LLIMWellWindow::postBuild()
void LLIMWellWindow::sessionAdded(const LLUUID& session_id,
const std::string& name, const LLUUID& other_participant_id)
{
- if (mMessageList->getItemByValue(session_id)) return;
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!session) return;
+
+ // no need to spawn chiclets for participants in P2P calls called through Avaline
+ if (session->isP2P() && session->isOtherParticipantAvaline()) return;
- if (!gIMMgr->hasSession(session_id)) return;
+ if (mMessageList->getItemByValue(session_id)) return;
addIMRow(session_id, 0, name, other_participant_id);
reshapeWindow();
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index c48301fa1e..c3ccb9380b 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -279,7 +279,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());
mLineEditor->setRect(leditor_rect);
mLineEditor->setText(edit_text_contents);
- mLineEditor->setMaxTextLength(STD_STRING_STR_LEN);
+ mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);
// make sure all edit keys get handled properly (DEV-22396)
mLineEditor->setHandleEditKeysDirectly(TRUE);
@@ -385,6 +385,12 @@ BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask )
{
if( KEY_RETURN == key && mask == MASK_NONE )
{
+ LLButton* defaultBtn = getDefaultButton();
+ if(defaultBtn && defaultBtn->getVisible() && defaultBtn->getEnabled())
+ {
+ // If we have a default button, click it when return is pressed
+ defaultBtn->onCommit();
+ }
return TRUE;
}
else if (KEY_RIGHT == key)
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 1676cc782c..87045d2abf 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -906,6 +906,18 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f
LLFloaterReg::showInstance("preview_texture", LLSD(item_id), take_focus);
break;
}
+ case LLAssetType::AT_ANIMATION:
+ LLFloaterReg::showInstance("preview_anim", LLSD(item_id), take_focus);
+ break;
+ case LLAssetType::AT_GESTURE:
+ LLFloaterReg::showInstance("preview_gesture", LLSD(item_id), take_focus);
+ break;
+ case LLAssetType::AT_SCRIPT:
+ LLFloaterReg::showInstance("preview_script", LLSD(item_id), take_focus);
+ break;
+ case LLAssetType::AT_SOUND:
+ LLFloaterReg::showInstance("preview_sound", LLSD(item_id), take_focus);
+ break;
default:
break;
}
@@ -1146,9 +1158,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
default:
LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
break;
- } // end switch (mIM)
-
- // Show falls through to accept.
+ }
+ break;
+ // end switch (mIM)
case IOR_ACCEPT:
msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
@@ -1837,7 +1849,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// This is a block, modeless dialog.
//*TODO: Translate
args["MESSAGE"] = message;
- LLNotificationsUtil::add("SystemMessage", args);
+ LLNotificationsUtil::add("SystemMessageTip", args);
}
break;
case IM_GROUP_NOTICE:
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 69d2458217..993853b9a6 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -446,6 +446,17 @@ void LLVoiceChannel::resume()
}
}
+boost::signals2::connection LLVoiceChannel::setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front)
+{
+ if (at_front)
+ {
+ return sCurrentVoiceChannelChangedSignal.connect(cb, boost::signals2::at_front);
+ }
+ else
+ {
+ return sCurrentVoiceChannelChangedSignal.connect(cb);
+ }
+}
//
// LLVoiceChannelGroup
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 77801142cb..cb86671305 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -64,7 +64,7 @@ public:
typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t;
typedef boost::signals2::signal<void(const LLUUID& session_id)> channel_changed_signal_t;
static channel_changed_signal_t sCurrentVoiceChannelChangedSignal;
- static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb) { return sCurrentVoiceChannelChangedSignal.connect(cb); }
+ static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front = false);
LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index cfa1f05ec0..c2d26a1971 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -4443,6 +4443,33 @@ void LLVoiceClient::participantUpdatedEvent(
participant->mPower = 0.0f;
}
participant->mVolume = volume;
+
+
+ // *HACH: mantipov: added while working on EXT-3544
+ /*
+ Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE
+ LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER.
+
+ participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted
+ Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug.
+ Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates.
+
+ But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post()
+ voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager
+ and event is not fired.
+
+ So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it
+ in LLCallFloater::draw()
+ */
+ LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice_cnl)
+ {
+ LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID());
+ if (speaker_manager)
+ {
+ speaker_manager->update(true);
+ }
+ }
}
else
{
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 706245a479..cb511c2f0b 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -102,6 +102,24 @@
name="AvatarNameColor"
reference="White" />
<color
+ name="AvatarListItemIconDefaultColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconOnlineColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconOfflineColor"
+ value="0.5 0.5 0.5 0.5" />
+ <color
+ name="AvatarListItemIconVoiceInvitedColor"
+ reference="AvatarListItemIconOfflineColor" />
+ <color
+ name="AvatarListItemIconVoiceJoinedColor"
+ reference="AvatarListItemIconOnlineColor" />
+ <color
+ name="AvatarListItemIconVoiceLeftColor"
+ reference="AvatarListItemIconOfflineColor" />
+ <color
name="BackgroundChatColor"
reference="DkGray_66" />
<color
diff --git a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg
new file mode 100644
index 0000000000..3bb7f7183c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 8a9126208a..95db84cb32 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -70,6 +70,8 @@ with the same filename but different name
<texture name="Audio_Over" file_name="icons/Audio_Over.png" preload="false" />
<texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" />
+ <texture name="Avaline_Icon" file_name="icons/avaline_default_icon.jpg" preload="true" />
+
<texture name="BackArrow_Disabled" file_name="icons/BackArrow_Disabled.png" preload="false" />
<texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" />
<texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 81c54ae55e..b9ce11600f 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -11,6 +11,10 @@
title="UNKNOWN PERSON IS CALLING"
width="410">
<floater.string
+ name="lifetime">
+ 5
+ </floater.string>
+ <floater.string
name="localchat">
Nearby Voice Chat
</floater.string>
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 58ba346e50..920f0c909a 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -16,6 +16,7 @@
can_dock="true"
bevel_style="in"
height="300"
+ min_width="150"
layout="topleft"
name="nearby_chat"
help_topic="nearby_chat"
diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
index c6bc093c6c..104ac2143f 100644
--- a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
@@ -11,6 +11,10 @@
title="CALLING"
width="410">
<floater.string
+ name="lifetime">
+ 5
+ </floater.string>
+ <floater.string
name="localchat">
Nearby Voice Chat
</floater.string>
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index ec54522d3e..a36a1b591b 100644
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -9,6 +9,7 @@
name="Snapshot"
help_topic="snapshot"
save_rect="true"
+ save_visibility="true"
title="SNAPSHOT PREVIEW"
width="215">
<floater.string
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index c849188699..9b3948b29b 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -104,6 +104,9 @@
<on_click
function="Places.LandmarksGear.Folding.Action"
parameter="expand_all" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="expand_all" />
</menu_item_call>
<menu_item_call
label="Collapse all folders"
@@ -112,6 +115,9 @@
<on_click
function="Places.LandmarksGear.Folding.Action"
parameter="collapse_all" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="collapse_all" />
</menu_item_call>
<menu_item_check
label="Sort by Date"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d4b712e048..9d3c31c4e6 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4498,14 +4498,14 @@ You don&apos;t have permission to copy this.
<notification
icon="notifytip.tga"
name="InventoryAccepted"
- type="offer">
+ type="notifytip">
[NAME] received your inventory offer.
</notification>
<notification
icon="notifytip.tga"
name="InventoryDeclined"
- type="offer">
+ type="notifytip">
[NAME] declined your inventory offer.
</notification>
@@ -5022,9 +5022,9 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O
[ITEM_SLURL]
<form name="form">
<button
- index="0"
- name="Keep"
- text="Keep"/>
+ index="4"
+ name="Show"
+ text="Show"/>
<button
index="1"
name="Discard"
@@ -5106,7 +5106,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you [O
<notification
icon="notify.tga"
name="OfferFriendship"
- type="offer">
+ type="alertmodal">
[NAME] is offering friendship.
[MESSAGE]
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 5ae808581d..00eba94f47 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -227,16 +227,20 @@
<button
follows="left|right"
height="23"
+ image_selected="PushButton_Selected_Press"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
left="0"
label=""
layout="topleft"
name="snapshots"
width="36"
top="4"
+ is_toggle="true"
image_overlay="Snapshot_Off"
tool_tip="Take snapshot">
- <button.commit_callback
- function="Floater.Toggle"
+ <button.init_callback
+ function="Button.SetFloaterToggle"
parameter="snapshot" />
</button>
</layout_panel>
@@ -248,7 +252,7 @@
top="0"
name="chiclet_list_panel"
width="189"
- min_width="180"
+ min_width="100"
user_resize="false"
auto_resize="true">
<!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same
@@ -259,7 +263,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
height="23"
layout="topleft"
left="1"
- min_width="180"
+ min_width="110"
name="chiclet_list"
top="6"
chiclet_padding="4"
diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml
index 859822dd81..39c4923f12 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_header.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -28,7 +28,7 @@
height="12"
layout="topleft"
left_pad="5"
- right="-60"
+ right="-120"
name="user_name"
text_color="white"
bg_readonly_color="black"
@@ -46,5 +46,5 @@
right="-5"
top="8"
value="23:30"
- width="50" />
+ width="110" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
index b5760e977f..1fbf7abda9 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -103,6 +103,7 @@
top_pad="2"
max_length="63"
name="classified_name"
+ prevalidate_callback="ascii"
text_color="black"
width="290" />
<text
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index 9f06e64560..744ee43f57 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -228,6 +228,16 @@
top_pad="10"
value="Title:"
width="290" />
+ <text
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="0"
+ name="title_value"
+ text_color="white"
+ top_pad="5"
+ use_ellipses="true"
+ width="290" />
<line_editor
background_image_disabled="task_panel_background.png"
follows="left|top|right"
@@ -238,7 +248,7 @@
name="title_editor"
prevalidate_callback="ascii"
text_readonly_color="white"
- top_pad="5"
+ top_delta="0"
width="290" />
<text
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index 1f211c0fed..c899dcb750 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -23,7 +23,7 @@
layout="topleft"
name="tab_favorites"
title="Favorites bar">
- <inventory_subtree_panel
+ <places_inventory_panel
allow_multi_select="true"
border="true"
bottom="0"
@@ -39,7 +39,7 @@
layout="topleft"
name="tab_landmarks"
title="Landmarks">
- <inventory_subtree_panel
+ <places_inventory_panel
allow_multi_select="true"
border="true"
bottom="0"
@@ -55,7 +55,7 @@
layout="topleft"
name="tab_inventory"
title="My Inventory">
- <inventory_subtree_panel
+ <places_inventory_panel
allow_multi_select="true"
border="true"
bottom="0"
@@ -71,7 +71,7 @@
layout="topleft"
name="tab_library"
title="Library">
- <inventory_subtree_panel
+ <places_inventory_panel
allow_multi_select="true"
border="true"
bottom="0"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 32eae9d11d..447901f984 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2907,7 +2907,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Joining voice call...
</string>
<string name="connected-im">
- Connected, click End Call to hang up
+ Connected, click Leave Call to hang up
</string>
<string name="hang_up-im">
Left voice call
@@ -2990,6 +2990,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="mute">
Error while moderating.
</string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name.
+ So, let add string with name="removed" with the same value as "removed_from_group" -->
+ <string name="removed">
+ You have been removed from the group.
+ </string>
<string name="removed_from_group">
You have been removed from the group.
</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml
new file mode 100644
index 0000000000..7cb973f4c8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_im_adhoc
+ font="SansSerif"
+ height="25"
+ name="im_adhoc_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_adhoc.speaker
+ auto_update="true"
+ draw_border="false"
+ height="25"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20"/>
+ <chiclet_im_adhoc.avatar_icon
+ follows="left|top|bottom"
+ height="22"
+ mouse_opaque="true"
+ name="adhoc_icon"
+ width="22"/>
+ <chiclet_im_adhoc.unread_notifications
+ font="SansSerif"
+ font_halign="center"
+ height="25"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="5"
+ visible="false"
+ width="20"/>
+ <chiclet_im_adhoc.new_message_icon
+ bottom="12"
+ height="13"
+ image_name="Unread_IM"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="13" />
+</chiclet_im_adhoc> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml
new file mode 100644
index 0000000000..a9b567225e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_im_group
+ font="SansSerif"
+ height="25"
+ name="im_group_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_group.speaker
+ auto_update="true"
+ draw_border="false"
+ height="25"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20"/>
+ <chiclet_im_group.group_icon
+ default_icon="Generic_Group"
+ follows="left|top|bottom"
+ height="22"
+ mouse_opaque="true"
+ name="group_icon"
+ width="22"/>
+ <chiclet_im_group.unread_notifications
+ height="25"
+ font="SansSerif"
+ font_halign="center"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="5"
+ visible="false"
+ width="20"/>
+ <chiclet_im_group.new_message_icon
+ bottom="12"
+ height="13"
+ image_name="Unread_IM"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="13" />
+</chiclet_im_group> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml
new file mode 100644
index 0000000000..9283594a4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_im_p2p
+ font="SansSerif"
+ height="25"
+ name="im_p2p_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_p2p.speaker
+ auto_update="true"
+ draw_border="false"
+ height="25"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20"/>
+ <chiclet_im_p2p.avatar_icon
+ follows="left|top|bottom"
+ height="22"
+ mouse_opaque="true"
+ name="avatar_icon"
+ width="22"/>
+ <chiclet_im_p2p.unread_notifications
+ height="25"
+ font="SansSerif"
+ font_halign="center"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="5"
+ visible="false"
+ width="20"/>
+ <chiclet_im_p2p.new_message_icon
+ bottom="12"
+ height="13"
+ image_name="Unread_IM"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="13" />
+</chiclet_im_p2p> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml
new file mode 100644
index 0000000000..5a22563758
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_offer
+ font="SansSerif"
+ height="25"
+ name="offer_chiclet"
+ width="25">
+ <chiclet_offer.icon
+ default_icon="Generic_Object_Small"
+ follows="all"
+ height="22"
+ mouse_opaque="false"
+ name="chiclet_icon"
+ width="22"/>
+ <chiclet_offer.new_message_icon
+ bottom="12"
+ height="13"
+ image_name="Unread_IM"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="13" />
+</chiclet_offer> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml
new file mode 100644
index 0000000000..f3207ddeae
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_panel
+ name="chiclet_panel"
+ chiclet_padding="3"
+ scrolling_offset="40"
+ scroll_button_hpad="5"
+ scroll_ratio="10"
+ min_width="180"
+ /> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
index e5af961a56..05a23b95f9 100644
--- a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
@@ -1,10 +1,22 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<chiclet_script
- name="script_chiclet"
- font="SansSerif">
- <icon
- name="chiclet_icon"
- follows="all"
- mouse_opaque="false"
- image_name="Generic_Object_Small" />
-</expandable_text> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_script
+ font="SansSerif"
+ height="25"
+ name="script_chiclet"
+ width="25">
+ <chiclet_script.icon
+ follows="all"
+ height="22"
+ image_name="Generic_Object_Small"
+ mouse_opaque="false"
+ name="chiclet_icon"
+ width="22"/>
+ <chiclet_script.new_message_icon
+ bottom="12"
+ height="13"
+ image_name="Unread_IM"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="13" />
+</chiclet_script> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
index 21b957d089..9d71ceca2f 100644
--- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<output_monitor
+ draw_border="true"
+ follows="top|left"
image_mute="Parcel_VoiceNo_Light"
image_off="VoicePTT_Off"
image_on="VoicePTT_On"
image_level_1="VoicePTT_Lvl1"
image_level_2="VoicePTT_Lvl2"
image_level_3="VoicePTT_Lvl3"
+ mouse_opaque="false"
+ name="output_monitor"
/>