Commits

Steven Bennetts  committed 53fb5f3

Merging revisions 2046-2068 of https://svn.aws.productengine.com/secondlife/pe/stable-2 into P:\svn\viewer-2.0.0, respecting ancestry
* Bugs: EXT-1414 EXT-1213 EXT-1539 EXT-1253 EXT-1446 EXT-1438 EXT-1233 EXT-1466 EXT-1446 EXT-1512 EXT-1231
* Dev: EXT-719 (landmarks) EXT-747 EXT-1446 EXT-1378 EXT-397 EXT-1476
* IM changes

  • Participants
  • Parent commits e58b4b9

Comments (0)

Files changed (72)

File indra/llui/llflatlistview.cpp

 
 static const std::string COMMENT_TEXTBOX = "comment_text";
 
+//forward declaration
+bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2);
+
 LLFlatListView::Params::Params()
 :	item_pad("item_pad"),
 	allow_select("allow_select"),
 	rearrangeItems();
 }
 
+bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value)
+{
+	if (old_value.isUndefined() || new_value.isUndefined()) return false;
+	if (llsds_are_equal(old_value, new_value)) return false;
+
+	item_pair_t* item_pair = getItemPair(old_value);
+	if (!item_pair) return false;
+
+	item_pair->second = new_value;
+	return true;
+}
 
 //////////////////////////////////////////////////////////////////////////
 // PROTECTED STUFF

File indra/llui/llflatlistview.h

 	void setComparator(const ItemComparator* comp) { mItemComparator = comp; }
 	void sort();
 
+	bool updateValue(const LLSD& old_value, const LLSD& new_value);
+
 protected:
 
 	/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */

File indra/llui/llfloater.cpp

 	return FALSE;
 }
 
+BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+	LLPanel::handleScrollWheel(x,y,clicks);
+	return TRUE;//always
+}
+
 // virtual
 BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
 {

File indra/llui/llfloater.h

 	virtual BOOL	handleRightMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleDoubleClick(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+	
+	virtual BOOL	handleScrollWheel(S32 x, S32 y, S32 mask);
+	
 	virtual void	draw();
 	
 	virtual void	onOpen(const LLSD& key) {}

File indra/llui/llscrollbar.cpp

 
 BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
-	changeLine( clicks * mStepSize, TRUE );
-	return TRUE;
+	S32 pos = llclamp(mDocPos + clicks * mStepSize, 0, getDocPosMax());
+	if (pos != mDocPos)
+	{
+		setDocPos(pos, TRUE);
+		return TRUE;
+	}
+	return FALSE;
 }
 
 BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,

File indra/llui/llscrollcontainer.cpp

 
 BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
 {
+	if(LLUICtrl::handleScrollWheel(x,y,clicks))
+		return TRUE;
 	for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
 	{
 		// Note: tries vertical and then horizontal
 			return TRUE;
 		}
 	}
-
-	// Eat scroll wheel event (to avoid scrolling nested containers?)
-	return TRUE;
+	return FALSE;
 }
 
 BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,

File indra/llui/llview.cpp

 }
 
 
+LLView*	LLView::childFromPoint(S32 x, S32 y)
+{
+	if (!getVisible()  )
+		return false;
+	for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+	{
+		LLView* viewp = *child_it;
+		S32 local_x = x - viewp->getRect().mLeft;
+		S32 local_y = y - viewp->getRect().mBottom;
+		if (!viewp->pointInView(local_x, local_y) 
+			|| !viewp->getVisible() )
+		{
+			continue;
+		}
+		return viewp;
+
+	}
+	return 0;
+}
+
 BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
 {
 	BOOL handled = FALSE;
 				handled_view = viewp;
 				break;
 			}
-
-			if (viewp->blockMouseEvent(local_x, local_y))
-			{
-				handled_view = viewp;
-				break;
-			}
 		}
 	}
 	return handled_view;

File indra/llui/llview.h

 	/*virtual*/ void	screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
 	/*virtual*/ void	localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
 
+	virtual		LLView*	childFromPoint(S32 x, S32 y);
+
 	// view-specific handlers 
 	virtual void	onMouseEnter(S32 x, S32 y, MASK mask);
 	virtual void	onMouseLeave(S32 x, S32 y, MASK mask);

File indra/newview/CMakeLists.txt

     llchannelmanager.cpp
     llchatbar.cpp
     llchatitemscontainerctrl.cpp
+    llchathistory.cpp
     llchatmsgbox.cpp
     llchiclet.cpp
     llclassifiedinfo.cpp
     llinventoryclipboard.cpp
     llinventoryfilter.cpp
     llinventorymodel.cpp
+    llinventorysubtreepanel.cpp
     lljoystickbutton.cpp
     lllandmarkactions.cpp
     lllandmarklist.cpp
     llpanelvolume.cpp
     llparcelselection.cpp
     llpatchvertexarray.cpp
+    llplacesinventorybridge.cpp
     llpolymesh.cpp
     llpolymorph.cpp
     llpreviewanim.cpp
     llchannelmanager.h
     llchatbar.h
     llchatitemscontainerctrl.h
+    llchathistory.h
     llchatmsgbox.h
     llchiclet.h
     llclassifiedinfo.h
     llinventoryclipboard.h
     llinventoryfilter.h
     llinventorymodel.h
+    llinventorysubtreepanel.h
     lljoystickbutton.h
     lllandmarkactions.h
     lllandmarklist.h
     llpanelvolume.h
     llparcelselection.h
     llpatchvertexarray.h
+    llplacesinventorybridge.h
     llpolymesh.h
     llpolymorph.h
     llpreview.h

File indra/newview/llavatariconctrl.cpp

 
 	rect.setOriginAndSize(left, bottom, llavatariconctrl_symbol_size, llavatariconctrl_symbol_size);
 
-	LLIconCtrl::Params icparams;
-	icparams.name ("Status Symbol");
-	icparams.follows.flags (FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
-	icparams.rect (rect);
-	mStatusSymbol = LLUICtrlFactory::create<LLIconCtrl> (icparams);
-	mStatusSymbol->setValue("circle.tga");
-	mStatusSymbol->setColor(LLColor4::grey);
-
-	addChild(mStatusSymbol);
-	
 	if (p.avatar_id.isProvided())
 	{
 		LLSD value(p.avatar_id);
 			mAvatarId = value.asUUID();
 
 			// *BUG: This will return stale icons if a user changes their
-			// profile picture.  Also, the online/offline tooltips will be
-			// out of date.  However, otherwise we send too many upstream
+			// profile picture. However, otherwise we send too many upstream
 			// AvatarPropertiesRequest messages.
-			//
-			// *TODO: Implement a timeout on the icon cache, perhaps a day?,
-			// and make the cache update if a user views the full-profile for
-			// an avatar.
+
+			// to get fresh avatar icon use
+			// LLAvatarIconIDCache::getInstance()->remove(avatar_id);
 
 			// Check if cache already contains image_id for that avatar
-			
 			if (!updateFromCache())
 			{
 				app->addObserver(mAvatarId, this);
 		LLIconCtrl::setValue("default_profile_picture.j2c");
 	}
 
-	// Can only see online status of friends
-	if (LLAvatarTracker::instance().isBuddy(mAvatarId))
-	{
-		if (LLAvatarTracker::instance().isBuddyOnline(mAvatarId))
-		{
-			// Update color of status symbol and tool tip
-			mStatusSymbol->setColor(LLColor4::green);
-			if (mDrawTooltip)
-			{
-				setToolTip((LLStringExplicit)"Online");
-			}
-		}
-		else
-		{
-			mStatusSymbol->setColor(LLColor4::grey);
-			if (mDrawTooltip)
-			{
-				setToolTip((LLStringExplicit)"Offline");
-			}
-		}
-	}
-	else
-	{
-		// Not a buddy, no information
-		mStatusSymbol->setColor(LLColor4::grey);
-		if (mDrawTooltip)
-		{
-			setToolTip((LLStringExplicit)"");
-		}
-	}
 	return true;
 }
 
 	{
 		mFirstName = first;
 		mLastName = last;
+
+		if (mDrawTooltip)
+		{
+			setToolTip(mFirstName + " " + mLastName);
+		}
 	}
 }
 

File indra/newview/llavatariconctrl.h

 	const std::string&	getLastName() const { return mLastName; }
 
 protected:
-	LLIconCtrl*			mStatusSymbol;
 	LLUUID				mAvatarId;
 	std::string			mFirstName;
 	std::string			mLastName;

File indra/newview/llavatarlist.cpp

 	item->showSpeakingIndicator(true);
 	item->setName(name);
 	item->setAvatarId(id);
+	item->setOnline(is_bold);
 	item->setContextMenu(mContextMenu);
 
 	item->childSetVisible("info_btn", false);

File indra/newview/llavatarlistitem.cpp

 	mInfoBtn(NULL),
 	mProfileBtn(NULL),
 	mContextMenu(NULL),
-	mAvatarId(LLUUID::null)
+	mOnlineStatus(E_UNKNOWN)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
 }
 
+LLAvatarListItem::~LLAvatarListItem()
+{
+	if (mAvatarId.notNull())
+		LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
+}
+
 BOOL  LLAvatarListItem::postBuild()
 {
 	mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
 	mStatus->setValue(status);
 }
 
+// virtual, called by LLAvatarTracker
+void LLAvatarListItem::changed(U32 mask)
+{
+	// no need to check mAvatarId for null in this case
+	setOnline(LLAvatarTracker::instance().isBuddyOnline(mAvatarId));
+}
+
+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;
+
+	mOnlineStatus = (EOnlineStatus) online;
+
+	// Change avatar name font style depending on the new online status.
+	LLStyle::Params style_params;
+	style_params.color = online ? LLColor4::white : LLColor4::grey;
+
+	// Rebuild the text to change its style.
+	std::string text = mAvatarName->getText();
+	mAvatarName->setText(LLStringUtil::null);
+	mAvatarName->appendText(text, false, style_params);
+
+	// Make the icon fade if the avatar goes offline.
+	mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke);
+}
+
 void LLAvatarListItem::setName(const std::string& name)
 {
 	mAvatarName->setValue(name);
 
 void LLAvatarListItem::setAvatarId(const LLUUID& id)
 {
+	if (mAvatarId.notNull())
+		LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
+
 	mAvatarId = id;
 	mAvatarIcon->setValue(id);
 	mSpeakingIndicator->setSpeakerId(id);
 
+	// We'll be notified on avatar online status changes
+	if (mAvatarId.notNull())
+		LLAvatarTracker::instance().addParticularFriendObserver(mAvatarId, this);
+
 	// Set avatar name.
 	gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
 }

File indra/newview/llavatarlistitem.h

 #include "llbutton.h"
 #include "lltextbox.h"
 
+#include "llcallingcard.h" // for LLFriendObserver
+
 class LLAvatarIconCtrl;
 
-class LLAvatarListItem : public LLPanel
+class LLAvatarListItem : public LLPanel, public LLFriendObserver
 {
 public:
 	class ContextMenu
 	};
 
 	LLAvatarListItem();
-	virtual ~LLAvatarListItem() {};
+	virtual ~LLAvatarListItem();
 
 	virtual BOOL postBuild();
 	virtual void onMouseLeave(S32 x, S32 y, MASK mask);
 	virtual void onMouseEnter(S32 x, S32 y, MASK mask);
 	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
 	virtual void setValue(const LLSD& value);
+	virtual void changed(U32 mask); // from LLFriendObserver
 
 	void setStatus(const std::string& status);
+	void setOnline(bool online);
 	void setName(const std::string& name);
 	void setAvatarId(const LLUUID& id);
 	
 	void setContextMenu(ContextMenu* menu) { mContextMenu = menu; }
 
 private:
+
+	typedef enum e_online_status {
+		E_OFFLINE,
+		E_ONLINE,
+		E_UNKNOWN,
+	} EOnlineStatus;
+
 	void onNameCache(const std::string& first_name, const std::string& last_name);
 
 	LLAvatarIconCtrl*mAvatarIcon;
 	ContextMenu* mContextMenu;
 
 	LLUUID mAvatarId;
+	EOnlineStatus mOnlineStatus;
 };
 
 #endif //LL_LLAVATARLISTITEM_H

File indra/newview/llbottomtray.cpp

 	}
 }
 
+void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+	//this is only needed in case of outgoing ad-hoc/group chat sessions
+	LLChicletPanel* chiclet_panel = getChicletPanel();
+	if (chiclet_panel)
+	{
+		//it should be ad-hoc im chiclet or group im chiclet
+		LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id);
+		if (chiclet) chiclet->setSessionId(new_session_id);
+	}
+}
+
 //virtual
 void LLBottomTray::onFocusLost()
 {

File indra/newview/llbottomtray.h

 	// LLIMSessionObserver observe triggers
 	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
 	virtual void sessionRemoved(const LLUUID& session_id);
+	void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
 
 	virtual void onFocusLost();
 	virtual void setVisible(BOOL visible);

File indra/newview/llcallingcard.cpp

 			++new_buddy_count;
 			mBuddyInfo[agent_id] = (*itr).second;
 			gCacheName->getName(agent_id, first, last);
-			mModifyMask |= LLFriendObserver::ADD;
+			addChangedMask(LLFriendObserver::ADD, agent_id);
 			lldebugs << "Added buddy " << agent_id
 					<< ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
 					<< ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo()
 	if(info)
 	{
 		info->online(is_online);
-		mModifyMask |= LLFriendObserver::ONLINE;
+		addChangedMask(LLFriendObserver::ONLINE, id);
 		lldebugs << "Set buddy " << id << (is_online ? " Online" : " Offline") << llendl;
 	}
 	else
 	{
 		(*it)->changed(mModifyMask);
 	}
+
+	for (changed_buddy_t::iterator it = mChangedBuddyIDs.begin(); it != mChangedBuddyIDs.end(); it++)
+	{
+		notifyParticularFriendObservers(*it);
+	}
+
 	mModifyMask = LLFriendObserver::NONE;
 	mChangedBuddyIDs.clear();
 }
 
+void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+	if (buddy_id.notNull() && observer)
+		mParticularFriendObserverMap[buddy_id].insert(observer);
+}
+
+void LLAvatarTracker::removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+	if (buddy_id.isNull() || !observer)
+		return;
+
+    observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+    if(obs_it == mParticularFriendObserverMap.end())
+        return;
+
+    obs_it->second.erase(observer);
+
+    // purge empty sets from the map
+    if (obs_it->second.size() == 0)
+    	mParticularFriendObserverMap.erase(obs_it);
+}
+
+void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)
+{
+    observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+    if(obs_it == mParticularFriendObserverMap.end())
+        return;
+
+    // Notify observers interested in buddy_id.
+    observer_set_t& obs = obs_it->second;
+    for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ob_it++)
+    {
+        (*ob_it)->changed(mModifyMask);
+    }
+}
+
 // store flag for change
 // and id of object change applies to
 void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
 			}
 		}
 	}
-	mModifyMask |= LLFriendObserver::POWERS;
 
+	addChangedMask(LLFriendObserver::POWERS, agent_id);
 	notifyObservers();
 }
 

File indra/newview/llcallingcard.h

 	void removeObserver(LLFriendObserver* observer);
 	void notifyObservers();
 
+	// Observers interested in updates of a particular avatar.
+	// On destruction these observers are NOT deleted.
+	void addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer);
+	void removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer);
+	void notifyParticularFriendObservers(const LLUUID& buddy_id);
+
 	/**
 	 * Stores flag for change and id of object change applies to
 	 *
 	typedef std::vector<LLFriendObserver*> observer_list_t;
 	observer_list_t mObservers;
 
+    typedef std::set<LLFriendObserver*> observer_set_t;
+    typedef std::map<LLUUID, observer_set_t> observer_map_t;
+    observer_map_t mParticularFriendObserverMap;
+
 private:
 	// do not implement
 	LLAvatarTracker(const LLAvatarTracker&);

File indra/newview/llchathistory.cpp

+/** 
+ * @file llchathistory.cpp
+ * @brief LLTextEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llchathistory.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
+
+static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
+static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- ");
+
+LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
+: LLTextEditor(p),
+mMessageHeaderFilename(p.message_header),
+mMessageSeparatorFilename(p.message_separator),
+mLeftTextPad(p.left_text_pad),
+mRightTextPad(p.right_text_pad),
+mLeftWidgetPad(p.left_widget_pad),
+mRightWidgetPad(p.rigth_widget_pad)
+{
+}
+
+LLChatHistory::~LLChatHistory()
+{
+	this->clear();
+}
+
+/*void LLChatHistory::updateTextRect()
+{
+	static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0);
+
+	LLRect old_text_rect = mTextRect;
+	mTextRect = mScroller->getContentWindowRect();
+	mTextRect.stretch(-texteditor_border);
+	mTextRect.mLeft += mLeftTextPad;
+	mTextRect.mRight -= mRightTextPad;
+	if (mTextRect != old_text_rect)
+	{
+		needsReflow();
+	}
+}*/
+
+LLView* LLChatHistory::getSeparator()
+{
+	LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageSeparatorFilename, NULL, LLPanel::child_registry_t::instance());
+	return separator;
+}
+
+LLView* LLChatHistory::getHeader(const LLUUID& avatar_id, std::string& from, std::string& time)
+{
+	LLPanel* header = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageHeaderFilename, NULL, LLPanel::child_registry_t::instance());
+	LLTextBox* userName = header->getChild<LLTextBox>("user_name");
+	userName->setValue(from);
+	LLTextBox* timeBox = header->getChild<LLTextBox>("time_box");
+	timeBox->setValue(time);
+	if(!avatar_id.isNull())
+	{
+		LLAvatarIconCtrl* icon = header->getChild<LLAvatarIconCtrl>("avatar_icon");
+		icon->setValue(avatar_id);
+	}
+	return header;
+}
+
+void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params)
+{
+	LLView* view = NULL;
+	std::string view_text;
+
+	if (mLastFromName == from)
+	{
+		view = getSeparator();
+		view_text = "\n";
+	}
+	else
+	{
+		view = getHeader(avatar_id, from, time);
+		view_text = from + MESSAGE_USERNAME_DATE_SEPARATOR + time;
+	}
+	//Prepare the rect for the view
+	LLRect target_rect = mScroller->getContentWindowRect();
+	target_rect.mLeft += mLeftWidgetPad;
+	target_rect.mRight -= mRightWidgetPad;
+	view->reshape(target_rect.getWidth(), view->getRect().getHeight());
+	view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
+
+	this->appendWidget(view, view_text, FALSE, TRUE);
+
+	//Append the text message
+	this->appendText(message, TRUE, style_params);
+
+	mLastFromName = from;
+	this->blockUndo();
+	this->setCursorAndScrollToEnd();
+}

File indra/newview/llchathistory.h

+/** 
+ * @file llchathistory.h
+ * @brief LLTextEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLCHATHISTORY_H_
+#define LLCHATHISTORY_H_
+
+#include "lltexteditor.h"
+
+//Chat log widget allowing addition of a message as a widget 
+class LLChatHistory : public LLTextEditor
+{
+	public:
+		struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
+		{
+			//Message header filename
+			Optional<std::string>	message_header;
+			//Message separator filename
+			Optional<std::string>	message_separator;
+			//Text left padding from the scroll rect
+			Optional<S32>			left_text_pad;
+			//Text right padding from the scroll rect
+			Optional<S32>			right_text_pad;
+			//Widget left padding from the scroll rect
+			Optional<S32>			left_widget_pad;
+			//Widget right padding from the scroll rect
+			Optional<S32>			rigth_widget_pad;
+
+			Params()
+			:	message_header("message_header"),
+				message_separator("message_separator"),
+				left_text_pad("left_text_pad"),
+				right_text_pad("right_text_pad"),
+				left_widget_pad("left_widget_pad"),
+				rigth_widget_pad("rigth_widget_pad")
+				{
+				}
+
+		};
+	protected:
+		LLChatHistory(const Params&);
+		friend class LLUICtrlFactory;
+
+		/**
+		 * Redefinition of LLTextEditor::updateTextRect() to considerate text
+		 * left/right padding params.
+		 */
+		//virtual void	updateTextRect();
+		/**
+		 * Builds a message separator.
+		 * @return pointer to LLView separator object.
+		 */
+		LLView* getSeparator();
+		/**
+		 * Builds a message header.
+		 * @param from owner of a message.
+		 * @param time time of a message.
+		 * @return pointer to LLView header object.
+		 */
+		LLView* getHeader(const LLUUID& avatar_id, std::string& from, std::string& time);
+
+	public:
+		~LLChatHistory();
+
+		/**
+		 * Appends a widget message.
+		 * If last user appended message, concurs with current user,
+		 * separator is added before the message, otherwise header is added.
+		 * @param from owner of a message.
+		 * @param time time of a message.
+		 * @param message message itself.
+		 */
+		void appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params);
+
+	private:
+		std::string mLastFromName;
+		std::string mMessageHeaderFilename;
+		std::string mMessageSeparatorFilename;
+		S32 mLeftTextPad;
+		S32 mRightTextPad;
+		S32 mLeftWidgetPad;
+		S32 mRightWidgetPad;
+};
+#endif /* LLCHATHISTORY_H_ */

File indra/newview/llfloaterinventory.cpp

 const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
 const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
 const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
+static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
 
 LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p)
 :	LLPanel(p),
 	mAllowMultiSelect(p.allow_multi_select),
 	mHasInventoryConnection(false),
 	mStartFolderString(p.start_folder)
+,	mBuildDefaultHierarchy(true)
+,	mRootInventoryItemUUID(LLUUID::null)
+,	mInvFVBridgeBuilder(NULL)
 {
+	mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
+
 	// contex menu callbacks
 	mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
 	mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH));
 	const LLAssetType::EType preferred_type = LLAssetType::lookupHumanReadable(mStartFolderString);
 	mStartFolderID = (preferred_type != LLAssetType::AT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
 
-	// build view of inventory if inventory ready, otherwise wait for modelChanged() callback
-	if (mInventory->isInventoryUsable() && !mHasInventoryConnection)
+	// build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
+	if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
 	{
 		rebuildViewsFor(mStartFolderID);
 		mHasInventoryConnection = true;
 	}
 }
 
+void LLInventoryPanel::setInvFVBridgeBuilder(const LLInventoryFVBridgeBuilder* bridge_builder)
+{
+	if (NULL == bridge_builder)
+	{
+		llwarns << "NULL is passed as Inventory Bridge Builder. Default will be used." << llendl; 
+	}
+	else
+	{
+		mInvFVBridgeBuilder = bridge_builder;
+	}
+
+	if (mInventory->isInventoryUsable() && !mHasInventoryConnection)
+	{
+		rebuildViewsFor(mRootInventoryItemUUID);
+		mHasInventoryConnection = true;
+	}
+}
+
+
 void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
 {
 	LLFolderViewItem* old_view = NULL;
 			else if (objectp->getType() == LLAssetType::AT_CATEGORY &&
 					 objectp->getActualType() != LLAssetType::AT_LINK_FOLDER) 
 			{
-				LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
-																		  objectp->getType(),
-																		  LLInventoryType::IT_CATEGORY,
-																		  this,
-																		  objectp->getUUID());
+				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+																				objectp->getType(),
+																				LLInventoryType::IT_CATEGORY,
+																				this,
+																				objectp->getUUID());
 
 				if (new_listener)
 				{
 			{
 				// Build new view for item
 				LLInventoryItem* item = (LLInventoryItem*)objectp;
-				LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(item->getType(),
-																		  item->getActualType(),
-																		  item->getInventoryType(),
-																		  this,
-																		  item->getUUID(),
-																		  item->getFlags());
+				LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+																				item->getActualType(),
+																				item->getInventoryType(),
+																				this,
+																				item->getUUID(),
+																				item->getFlags());
 
 				if (new_listener)
 				{

File indra/newview/llfloaterinventory.h

 class LLInventoryFilter;
 class LLInventoryModel;
 class LLInvFVBridge;
+class LLInventoryFVBridgeBuilder;
 class LLMenuBarGL;
 class LLCheckBoxCtrl;
 class LLSpinCtrl;
 	friend class LLUICtrlFactory;
 
 public:
-	~LLInventoryPanel();
+	virtual ~LLInventoryPanel();
 
 	LLInventoryModel* getModel() { return mInventory; }
 
 protected:
 	// Given the id and the parent, build all of the folder views.
 	void rebuildViewsFor(const LLUUID& id);
-	void buildNewViews(const LLUUID& id);
+	virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719
+
+	// Be sure that passed pointer will be destroyed where it was created.
+	void setInvFVBridgeBuilder(const LLInventoryFVBridgeBuilder* bridge_builder);
 
 protected:
 	LLInventoryModel*			mInventory;
 	BOOL 						mAllowMultiSelect;
 	std::string					mSortOrderSetting;
 
-private:
+//private: // Can not make these private - needed by llinventorysubtreepanel
 	LLFolderView*				mFolders;
 	std::string                 mStartFolderString;
 	LLUUID						mStartFolderID;
 	LLScrollContainer*			mScroller;
 	bool						mHasInventoryConnection;
+
+	/**
+	 * Flag specified if default inventory hierarchy should be created in postBuild()
+	 */
+	bool						mBuildDefaultHierarchy;
+
+	/**
+	 * Contains UUID of Inventory item from which hierarchy should be built.
+	 * Should be set by derived class before modelChanged() is called.
+	 * Default is LLUUID::null that means total Inventory hierarchy.
+	 */
+	LLUUID						mRootInventoryItemUUID;
+
+	/**
+	 * Pointer to LLInventoryFVBridgeBuilder.
+	 *
+	 * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with 
+	 * another implementation.
+	 * Take into account it will not be deleted by LLInventoryPanel itself.
+	 */
+	const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder;
+
 };
 
 class LLFloaterInventory;

File indra/newview/llfolderview.cpp

 	mDragAndDropThisFrame(FALSE),
 	mCallbackRegistrar(NULL),
 	mParentPanel(p.parent_panel)
+,	mUseEllipses(false)
+,	mDraggingOverItem(NULL)
 {
 	LLRect rect = p.rect;
 	LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
 		scroll_rect = mScrollContainer->getContentWindowRect();
 	}
 	width = llmax(mMinWidth, scroll_rect.getWidth());
+
+	// restrict width with scroll container's width
+	if (mUseEllipses)
+		width = scroll_rect.getWidth();
+
 	LLView::reshape(width, height, called_from_parent);
 
 	mReshapeSignal(mSelectedItems, FALSE);
 
 BOOL LLFolderView::canCut() const
 {
-	return FALSE;
+	if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0)))
+	{
+		return FALSE;
+	}
+	
+	for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)
+	{
+		const LLFolderViewItem* item = *selected_it;
+		const LLFolderViewEventListener* listener = item->getListener();
+		if (!listener || !listener->isItemMovable())
+		{
+			return FALSE;
+		}
+	}
+	return TRUE;
 }
 
 void LLFolderView::cut()
 {
-	// implement Windows-style cut-and-leave
+	// clear the inventory clipboard
+	LLInventoryClipboard::instance().reset();
+	S32 count = mSelectedItems.size();
+	if(getVisible() && getEnabled() && (count > 0))
+	{
+		LLFolderViewEventListener* listener = NULL;
+		selected_items_t::iterator item_it;
+		for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
+		{
+			listener = (*item_it)->getListener();
+			if(listener)
+			{
+				listener->cutToClipboard();
+			}
+		}
+	}
+	mSearchString.clear();
 }
 
 BOOL LLFolderView::canPaste() const

File indra/newview/llfolderview.h

 
 	BOOL startDrag(LLToolDragAndDrop::ESource source);
 	void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; }
+	void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; }
+	LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; }
+
 
 	// deletion functionality
  	void removeSelectedItems();
 	void setShowSingleSelection(BOOL show);
 	BOOL getShowSingleSelection() { return mShowSingleSelection; }
 	F32  getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
+	void setUseEllipses(bool use_ellipses) { mUseEllipses = use_ellipses; }
+	bool getUseEllipses() { return mUseEllipses; }
 
 	void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
 	void removeItemID(const LLUUID& id);
 	
 	LLPanel*						mParentPanel;
 
+	/**
+	 * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
+	 * NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel.
+	 */
+	bool							mUseEllipses; // See EXT-719
+
+	/**
+	 * Contains item under mouse pointer while dragging
+	 */
+	LLFolderViewItem*				mDraggingOverItem; // See EXT-719
+
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
 	
 public:

File indra/newview/llfoldervieweventlistener.h

 	virtual void showProperties(void) = 0;
 	virtual BOOL isItemRenameable() const = 0;
 	virtual BOOL renameItem(const std::string& new_name) = 0;
-	virtual BOOL isItemMovable( void ) = 0;		// Can be moved to another folder
+	virtual BOOL isItemMovable( void ) const = 0;		// Can be moved to another folder
 	virtual BOOL isItemRemovable( void ) = 0;	// Can be destroyed
 	virtual BOOL removeItem() = 0;
 	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0;

File indra/newview/llfolderviewitem.cpp

 // viewer includes
 #include "llfolderview.h"		// Items depend extensively on LLFolderViews
 #include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h"	// for LLItemBridge in LLInventorySort::operator()
 #include "llinventoryfilter.h"
 #include "llinventorymodel.h"	// *TODO: make it take a pointer to an inventory-model interface
 #include "llviewercontrol.h"	// gSavedSettings
 	mListener(p.listener),
 	mArrowImage(p.folder_arrow_image),
 	mBoxImage(p.selection_image)
+,	mDontShowInHierarhy(false)
 {
 	refresh();
 }
 
 	S32 height = 0;
 	S32 width = 0;
-	root->arrange( &width, &height, 0 );
+	S32 total_height = root->arrange( &width, &height, 0 );
+
+	LLSD params;
+	params["action"] = "size_changes";
+	params["height"] = total_height;
+	getParent()->notifyParent(params);
 }
 
 // Utility function for LLFolderView
 	}
 
 	*width = llmax(*width, mLabelWidth + mIndentation); 
+
+	// determine if we need to use ellipses to avoid horizontal scroll. EXT-719
+	bool use_ellipses = getRoot()->getUseEllipses();
+	if (use_ellipses)
+	{
+		// limit to set rect to avoid horizontal scrollbar
+		*width = llmin(*width, getRoot()->getRect().getWidth());
+	}
 	*height = getItemHeight();
 	return *height;
 }
 
 S32 LLFolderViewItem::getItemHeight()
 {
+	if (mDontShowInHierarhy) return 0;
+
 	S32 icon_height = mIcon->getHeight();
 	S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
 	return llmax( icon_height, label_height ) + ICON_PAD;
 	}
 	if(mParentFolder && !handled)
 	{
+		// store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event.
+		mRoot->setDraggingOverItem(this);
 		handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+		mRoot->setDraggingOverItem(NULL);
 	}
 	if (handled)
 	{
 
 void LLFolderViewItem::draw()
 {
+	if (mDontShowInHierarhy) return;
+
 	static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
 	static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
 	static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
 
 		font->renderUTF8( mLabel, 0, text_left, y, color,
 				   LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
-			S32_MAX, S32_MAX, &right_x, FALSE );
+			S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);
+
 		if (!mLabelSuffix.empty())
 		{
 			font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor,
 
 bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b)
 {
+	// ignore sort order for landmarks in the Favorites folder.
+	// they should be always sorted as in Favorites bar. See EXT-719
+	if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM
+		&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK
+		&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+	{
+
+		static LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+
+		LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID();
+		LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID();
+
+		if (a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)
+		{
+			// *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem
+			// or to LLInvFVBridge
+			S32 a_sort = (static_cast<const LLItemBridge*>(a->getListener()))->getItem()->getSortField();
+			S32 b_sort = (static_cast<const LLItemBridge*>(b->getListener()))->getItem()->getSortField();
+			return a_sort < b_sort;
+		}
+	}
+
 	// We sort by name if we aren't sorting by date
 	// OR if these are folders and we are sorting folders by name.
 	bool by_name = (!mByDate 

File indra/newview/llfolderviewitem.h

 	LLUIImagePtr				mBoxImage;
 	BOOL                            mIsLoading;
 	LLTimer                         mTimeSinceRequestStart;
+	bool						mDontShowInHierarhy;
 
 	// helper function to change the selection from the root.
 	void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
 	// makes sure that this view and it's children are the right size.
 	virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
 	virtual S32 getItemHeight();
+	void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarhy = dont_show; }
 
 	// applies filters to control visibility of inventory items
 	virtual void filter( LLInventoryFilter& filter);

File indra/newview/llgrouplist.cpp

 	// rebuild the text.  This will cause problems if the text contains
 	// hyperlinks, as their styles will be wrong.
 	std::string text = mGroupNameBox->getText();
-	mGroupNameBox->setText(LLStringUtil::null);// *HACK: replace with clear() when it's fixed.
+	mGroupNameBox->setText(LLStringUtil::null);
 	mGroupNameBox->appendText(text, false, style_params);
 }
 

File indra/newview/llimfloater.cpp

 	mDialog(IM_NOTHING_SPECIAL),
 	mHistoryEditor(NULL),
 	mInputEditor(NULL), 
-	mPositioned(false)
+	mPositioned(false),
+	mSessionInitialized(false)
 {
-	EInstantMessage type = LLIMModel::getInstance()->getType(session_id);
-	if(IM_COUNT != type)
+	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID);
+	if (im_session)
 	{
-		mDialog = type;
-
+		mSessionInitialized = im_session->mSessionInitialized;
+		
+		mDialog = im_session->mType;
 		if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
 		{
 			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
 			std::string utf8_text = wstring_to_utf8str(text);
 			utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
 			
-			LLIMModel::sendMessage(utf8_text,
-								mSessionID,
-								mOtherParticipantUUID,
-								mDialog);
+			if (mSessionInitialized)
+			{
+				LLIMModel::sendMessage(utf8_text, mSessionID,
+					mOtherParticipantUUID,mDialog);
+			}
+			else
+			{
+				//queue up the message to send once the session is initialized
+				mQueuedMsgsForInit.append(utf8_text);
+			}
 
 			mInputEditor->setText(LLStringUtil::null);
 
 		LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
 	}
 
+	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
+	//see LLFloaterIMPanel for how it is done (IB)
 
 	return LLDockableFloater::postBuild();
 }
 	}
 }
 
+//static
+LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id)
+{
+	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+}
+
+void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
+{
+	mSessionInitialized = true;
+
+	if (mSessionID != im_session_id)
+	{
+		mSessionID = im_session_id;
+		setKey(im_session_id);
+	}
+	
+	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
+
+
+	//need to send delayed messaged collected while waiting for session initialization
+	if (!mQueuedMsgsForInit.size()) return;
+	LLSD::array_iterator iter;
+	for ( iter = mQueuedMsgsForInit.beginArray();
+		iter != mQueuedMsgsForInit.endArray();
+		++iter)
+	{
+		LLIMModel::sendMessage(iter->asString(), mSessionID,
+			mOtherParticipantUUID, mDialog);
+	}
+}
+
 void LLIMFloater::updateMessages()
 {
 	std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
 	self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
 	self->mHistoryEditor->blockUndo();
 }
+

File indra/newview/llimfloater.h

 	// Returns true iff panel became visible
 	static bool toggle(const LLUUID& session_id);
 
+	static LLIMFloater* findInstance(const LLUUID& session_id);
+
+	void sessionInitReplyReceived(const LLUUID& im_session_id);
+
 	// get new messages from LLIMModel
 	void updateMessages();
 	static void onSendMsg( LLUICtrl*, void*);
 	LLViewerTextEditor* mHistoryEditor;
 	LLLineEditor* mInputEditor;
 	bool mPositioned;
+
+	bool mSessionInitialized;
+	LLSD mQueuedMsgsForInit;
 };
 
 

File indra/newview/llimview.cpp

 	// All participants will be added to the list of people we've recently interacted with.
 	mSpeakers->addListener(&LLRecentPeople::instance(), "add");
 
+	//we need to wait for session initialization for outgoing ad-hoc and group chat session
+	//correct session id for initiated ad-hoc chat will be received from the server
 	if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, 
 		mInitialTargetIDs, mType))
 	{
 	mVoiceChannel = NULL;
 }
 
+void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_id)
+{
+	mSessionInitialized = true;
+
+	if (new_session_id != mSessionID)
+	{
+		mSessionID = new_session_id;
+		mVoiceChannel->updateSessionID(new_session_id);
+	}
+}
+
 LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
 {
 	return get_if_there(LLIMModel::instance().sSessionsMap, session_id,
 		(LLIMModel::LLIMSession*) NULL);
 }
 
+//*TODO change name to represent session initialization aspect (IB)
 void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id)
 {
-	if (new_session_id == old_session_id) return;
-
 	LLIMSession* session = findIMSession(old_session_id);
 	if (session)
 	{
-		session->mSessionID = new_session_id;
-		session->mVoiceChannel->updateSessionID(new_session_id);
+		session->sessionInitReplyReceived(new_session_id);
 
-		session->mSessionInitialized = true;
+		if (old_session_id != new_session_id)
+		{
+			sSessionsMap.erase(old_session_id);
+			sSessionsMap[new_session_id] = session;
 
-		sSessionsMap.erase(old_session_id);
-		sSessionsMap[new_session_id] = session;
+			gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);
+		}
+
+		LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id);
+		if (im_floater)
+		{
+			im_floater->sessionInitReplyReceived(new_session_id);
+		}
 	}
 
 	//*TODO remove this "floater" stuff when Communicate Floater is gone
 			temp_session_id,
 			other_participant_id,
 			dialog);
-
-		switch(dialog)
-		{
-		case IM_SESSION_GROUP_START:
-			gMessageSystem->addBinaryDataFast(
+		gMessageSystem->addBinaryDataFast(
 				_PREHASH_BinaryBucket,
 				EMPTY_BINARY_BUCKET,
 				EMPTY_BINARY_BUCKET_SIZE);
-			break;
-		default:
-			break;
-		}
 		gAgent.sendReliableMessage();
 
 		return true;
 				other_participant_id,
 				agents);
 		}
+
+		//we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id)
+		return true;
 	}
 
 	return false;
 		new_session_id = computeSessionID(dialog, other_participant_id);
 	}
 
+	//*NOTE session_name is empty in case of incoming P2P sessions
+	std::string fixed_session_name = from;
+	if(!session_name.empty() && session_name.size()>1)
+	{
+		fixed_session_name = session_name;
+	}
+
 	if (!LLIMModel::getInstance()->findIMSession(new_session_id))
 	{
-		LLIMModel::instance().newSession(session_id, session_name, dialog, other_participant_id);
+		LLIMModel::getInstance()->newSession(session_id, fixed_session_name, dialog, other_participant_id);
 	}
 
 	floater = findFloaterBySession(new_session_id);
 	// create IM window as necessary
 	if(!floater)
 	{
-		std::string name = from;
-		if(!session_name.empty() && session_name.size()>1)
-		{
-			name = session_name;
-		}
 
 		
 		floater = createFloater(
 			new_session_id,
 			other_participant_id,
-			name,
+			fixed_session_name,
 			dialog,
 			FALSE);
 
 	}
 }
 
+void LLIMMgr::notifyObserverSessionIDUpdated( const LLUUID& old_session_id, const LLUUID& new_session_id )
+{
+	for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+	{
+		(*it)->sessionIDUpdated(old_session_id, new_session_id);
+	}
+
+}
+
 void LLIMMgr::addSessionObserver(LLIMSessionObserver *observer)
 {
 	mSessionObservers.push_back(observer);

File indra/newview/llimview.h

 			const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids);
 		virtual ~LLIMSession();
 
+		void sessionInitReplyReceived(const LLUUID& new_session_id);
+
 		LLUUID mSessionID;
 		std::string mName;
 		EInstantMessage mType;
 	virtual ~LLIMSessionObserver() {}
 	virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0;
 	virtual void sessionRemoved(const LLUUID& session_id) = 0;
+	virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0;
 };
 
 
 
 	void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
 	void notifyObserverSessionRemoved(const LLUUID& session_id);
+	void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
 
 private:
 	std::set<LLHandle<LLFloater> > mFloaters;

File indra/newview/llinspectavatar.cpp

 #include "lltooltip.h"	// positionViewNearMouse()
 #include "lluictrl.h"
 
+#include "llavatariconctrl.h"
+
 class LLFetchAvatarData;
 
 
 	// and this may result in the image being visible sooner.
 	// *NOTE: This may generate a duplicate avatar properties request, but that
 	// will be suppressed internally in the avatar properties processor.
+	
+	//remove avatar id from cache to get fresh info
+	LLAvatarIconIDCache::getInstance()->remove(mAvatarID);
+
 	childSetValue("avatar_icon", LLSD(mAvatarID) );
 
 	gCacheName->get(mAvatarID, FALSE,

File indra/newview/llinventorybridge.cpp

 }
 
 // Can be moved to another folder
-BOOL LLInvFVBridge::isItemMovable()
+BOOL LLInvFVBridge::isItemMovable() const
 {
 	return TRUE;
 }
 
+/*virtual*/
+/**
+ * @brief Adds this item into clipboard storage
+ */
+void LLInvFVBridge::cutToClipboard()
+{
+	if(isItemMovable())
+	{
+		LLInventoryClipboard::instance().cut(mUUID);
+	}
+}
 // *TODO: make sure this does the right thing
 void LLInvFVBridge::showProperties()
 {
 }
 
 // +=================================================+
+// |        InventoryFVBridgeBuilder                 |
+// +=================================================+
+LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+														LLAssetType::EType actual_asset_type,
+														LLInventoryType::EType inv_type,
+														LLInventoryPanel* inventory,
+														const LLUUID& uuid,
+														U32 flags /* = 0x00 */) const
+{
+	return LLInvFVBridge::createBridge(asset_type,
+		actual_asset_type,
+		inv_type,
+		inventory,
+		uuid,
+		flags);
+}
+
+// +=================================================+
 // |        LLItemBridge                             |
 // +=================================================+
 
 LLFolderBridge* LLFolderBridge::sSelf=NULL;
 
 // Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable()
+BOOL LLFolderBridge::isItemMovable() const 
 {
 	LLInventoryObject* obj = getInventoryObject();
 	if(obj)
 		LLDynamicArray<LLUUID> objects;
 		LLInventoryClipboard::instance().retrieve(objects);
 		S32 count = objects.count();
-		LLUUID parent_id(mUUID);
+		const LLUUID parent_id(mUUID);
 		for(S32 i = 0; i < count; i++)
 		{
 			item = model->getItem(objects.get(i));
 			if (item)
 			{
-				copy_inventory_item(
-					gAgent.getID(),
-					item->getPermissions().getOwner(),
-					item->getUUID(),
-					parent_id,
-					std::string(),
-					LLPointer<LLInventoryCallback>(NULL));
+				if(LLInventoryClipboard::instance().isCutMode())
+				{
+					// move_inventory_item() is not enough, 
+					//we have to update inventory locally too
+					changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+				}
+				else
+				{
+					copy_inventory_item(
+						gAgent.getID(),
+						item->getPermissions().getOwner(),
+						item->getUUID(),
+						parent_id,
+						std::string(),
+						LLPointer<LLInventoryCallback>(NULL));
+				}
 			}
 		}
 	}
 	return false;
 }
 
+/*
+Next functions intended to reorder items in the inventory folder and save order on server
+Is now used for Favorites folder.
+
+*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
+*/
+void saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+	int sortField = 0;
+
+	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+	for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+	{
+		LLViewerInventoryItem* item = *i;
+
+		item->setSortField(++sortField);
+		item->setComplete(TRUE);
+		item->updateServer(FALSE);
+
+		gInventory.updateItem(item);
+	}
+
+	gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+	LLInventoryModel::item_array_t::iterator result = items.end();
+
+	for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+	{
+		if ((*i)->getUUID() == id)
+		{
+			result = i;
+			break;
+		}
+	}
+
+	return result;
+}
+
+void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+	LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+	LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+	items.erase(findItemByUUID(items, srcItem->getUUID()));
+	items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
 BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 										BOOL drop)
 {
 			}
 		}
  
-		accept = is_movable && (mUUID != inv_item->getParentUUID());
+		LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+
+		// we can move item inside a folder only if this folder is Favorites. See EXT-719
+		accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
 		if(accept && drop)
 		{
 			if (inv_item->getType() == LLAssetType::AT_GESTURE
 				}
 			}
 
-			LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
-			if (favorites_id == mUUID) // if target is the favorites folder we use copy
+			// if dragging from/into favorites folder only reorder items
+			if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
+			{
+				LLInventoryModel::cat_array_t cats;
+				LLInventoryModel::item_array_t items;
+				LLIsType is_type(LLAssetType::AT_LANDMARK);
+				model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+				LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+				LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+				if (itemp)
+				{
+					LLUUID srcItemId = inv_item->getUUID();
+					LLUUID destItemId = itemp->getListener()->getUUID();
+
+					// update order
+					updateItemsOrder(items, srcItemId, destItemId);
+
+					saveItemsOrder(items);
+				}
+			}
+			else if (favorites_id == mUUID) // if target is the favorites folder we use copy
 			{
 				copy_inventory_item(
 					gAgent.getID(),
 	}
 
 	items.push_back(std::string("Landmark Separator"));
-	items.push_back(std::string("Teleport To Landmark"));
+	items.push_back(std::string("About Landmark"));
 
 	// Disable "About Landmark" menu item for
 	// multiple landmarks selected. Only one landmark
 	// info panel can be shown at a time.
 	if ((flags & FIRST_SELECTED_ITEM) == 0)
 	{
-		disabled_items.push_back(std::string("Teleport To Landmark"));
+		disabled_items.push_back(std::string("About Landmark"));
 	}
 
 	hideContextEntries(menu, items, disabled_items);

File indra/newview/llinventorybridge.h

 	LLInventoryPanel* mIP;
 };
 
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type);
+void hideContextEntries(LLMenuGL& menu, 
+						const std::vector<std::string> &entries_to_show,
+						const std::vector<std::string> &disabled_entries);
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInvFVBridge (& it's derived classes)
 //
 	virtual BOOL isItemRenameable() const { return TRUE; }
 	//virtual BOOL renameItem(const std::string& new_name) {}
 	virtual BOOL isItemRemovable();
-	virtual BOOL isItemMovable();
+	virtual BOOL isItemMovable() const;
 	//virtual BOOL removeItem() = 0;
 	virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
 	virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
 	virtual BOOL isItemCopyable() const { return FALSE; }
 	virtual BOOL copyToClipboard() const { return FALSE; }
-	virtual void cutToClipboard() {}
+	virtual void cutToClipboard();
 	virtual BOOL isClipboardPasteable() const;
 	virtual BOOL isClipboardPasteableAsLink() const;
 	virtual void pasteFromClipboard() {}
 	void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
 };
 
+/**
+ * This class intended to build Folder View Bridge via LLInvFVBridge::createBridge.
+ * It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge.
+ */
+class LLInventoryFVBridgeBuilder
+{
+public:
+ 	virtual ~LLInventoryFVBridgeBuilder(){}
+	virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
+										LLAssetType::EType actual_asset_type,
+										LLInventoryType::EType inv_type,
+										LLInventoryPanel* inventory,
+										const LLUUID& uuid,
+										U32 flags = 0x00) const;
+};
+
 
 class LLItemBridge : public LLInvFVBridge
 {
 							void* cargo_data);
 
 	virtual BOOL isItemRemovable();
-	virtual BOOL isItemMovable();
+	virtual BOOL isItemMovable() const ;
 	virtual BOOL isUpToDate() const;
 	virtual BOOL isItemCopyable() const;
 	virtual BOOL isClipboardPasteableAsLink() const;

File indra/newview/llinventoryclipboard.cpp

 ///----------------------------------------------------------------------------
 
 LLInventoryClipboard::LLInventoryClipboard()
+: mCutMode(false)
 {
 }
 
 	}
 }
 
+void LLInventoryClipboard::cut(const LLUUID& object)
+{
+	if(!mCutMode && !mObjects.empty())
+	{
+		//looks like there are some stored items, reset clipboard state
+		reset();
+	}
+	mCutMode = true;
+	add(object);
+}
 void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const
 {
 	inv_objects.reset();
 void LLInventoryClipboard::reset()
 {
 	mObjects.reset();
+	mCutMode = false;
 }
 
 // returns true if the clipboard has something pasteable in it.

File indra/newview/llinventoryclipboard.h

 	// this method stores an array of objects
 	void store(const LLDynamicArray<LLUUID>& inventory_objects);
 
+	void cut(const LLUUID& object);
 	// this method gets the objects in the clipboard by copying them
 	// into the array provided.
 	void retrieve(LLDynamicArray<LLUUID>& inventory_objects) const;
 
 	// returns true if the clipboard has something pasteable in it.
 	BOOL hasContents() const;
+	bool isCutMode() const { return mCutMode; }