diff options
| author | Steven Bennetts <steve@lindenlab.com> | 2009-10-19 01:45:44 +0000 | 
|---|---|---|
| committer | Steven Bennetts <steve@lindenlab.com> | 2009-10-19 01:45:44 +0000 | 
| commit | 8103710c054ec6ea4a46f9732e569e543691184b (patch) | |
| tree | ac03dd6d385e3345c57eff0e1064a011597fe5d6 | |
| parent | 4ee757b45d527699b094bf9422244171fdd7d693 (diff) | |
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
72 files changed, 2594 insertions, 817 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index e9df361472..bba5464b00 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -44,6 +44,9 @@ const LLSD UNSELECTED_EVENT	= LLSD().insert("selected", false);  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"), @@ -333,6 +336,17 @@ void LLFlatListView::sort()  	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 diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index af5a9cfa9b..888258efdc 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -273,6 +273,8 @@ public:  	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 */ diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 47ca4899df..44c5f8c0de 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1262,6 +1262,12 @@ BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons inde  	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)  { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 7a6c3f6863..123de12398 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -206,6 +206,9 @@ public:  	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) {} diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index a75a0c6979..0d674528dc 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -409,8 +409,13 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)  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, diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 5597d494fe..d8606c6889 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -235,6 +235,8 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask)  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 @@ -246,9 +248,7 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )  			return TRUE;  		}  	} - -	// Eat scroll wheel event (to avoid scrolling nested containers?) -	return TRUE; +	return FALSE;  }  BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index ff6fe5a7ea..31f12fe312 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -672,6 +672,26 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)  } +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; @@ -901,12 +921,6 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)  				handled_view = viewp;  				break;  			} - -			if (viewp->blockMouseEvent(local_x, local_y)) -			{ -				handled_view = viewp; -				break; -			}  		}  	}  	return handled_view; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 5e35068733..73146b2c1f 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -445,6 +445,8 @@ public:  	/*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); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c630a56c8d..51840bf696 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -94,6 +94,7 @@ set(viewer_SOURCE_FILES      llchannelmanager.cpp      llchatbar.cpp      llchatitemscontainerctrl.cpp +    llchathistory.cpp      llchatmsgbox.cpp      llchiclet.cpp      llclassifiedinfo.cpp @@ -246,6 +247,7 @@ set(viewer_SOURCE_FILES      llinventoryclipboard.cpp      llinventoryfilter.cpp      llinventorymodel.cpp +    llinventorysubtreepanel.cpp      lljoystickbutton.cpp      lllandmarkactions.cpp      lllandmarklist.cpp @@ -344,6 +346,7 @@ set(viewer_SOURCE_FILES      llpanelvolume.cpp      llparcelselection.cpp      llpatchvertexarray.cpp +    llplacesinventorybridge.cpp      llpolymesh.cpp      llpolymorph.cpp      llpreviewanim.cpp @@ -564,6 +567,7 @@ set(viewer_HEADER_FILES      llchannelmanager.h      llchatbar.h      llchatitemscontainerctrl.h +    llchathistory.h      llchatmsgbox.h      llchiclet.h      llclassifiedinfo.h @@ -716,6 +720,7 @@ set(viewer_HEADER_FILES      llinventoryclipboard.h      llinventoryfilter.h      llinventorymodel.h +    llinventorysubtreepanel.h      lljoystickbutton.h      lllandmarkactions.h      lllandmarklist.h @@ -811,6 +816,7 @@ set(viewer_HEADER_FILES      llpanelvolume.h      llparcelselection.h      llpatchvertexarray.h +    llplacesinventorybridge.h      llpolymesh.h      llpolymorph.h      llpreview.h diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 3e411583ac..7ae1b5cd4a 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -181,16 +181,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)  	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); @@ -239,16 +229,13 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)  			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); @@ -282,36 +269,6 @@ bool LLAvatarIconCtrl::updateFromCache()  		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;  } @@ -370,6 +327,11 @@ void LLAvatarIconCtrl::nameUpdatedCallback(  	{  		mFirstName = first;  		mLastName = last; + +		if (mDrawTooltip) +		{ +			setToolTip(mFirstName + " " + mLastName); +		}  	}  } diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index 77390eb233..426fcec514 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -104,7 +104,6 @@ public:  	const std::string&	getLastName() const { return mLastName; }  protected: -	LLIconCtrl*			mStatusSymbol;  	LLUUID				mAvatarId;  	std::string			mFirstName;  	std::string			mLastName; diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 36f9780ad0..ef48420490 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -202,6 +202,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is  	item->showSpeakingIndicator(true);  	item->setName(name);  	item->setAvatarId(id); +	item->setOnline(is_bold);  	item->setContextMenu(mContextMenu);  	item->childSetVisible("info_btn", false); diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 4179d7a58d..90408beca0 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -52,11 +52,17 @@ LLAvatarListItem::LLAvatarListItem()  	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"); @@ -138,6 +144,36 @@ void LLAvatarListItem::setStatus(const std::string& status)  	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); @@ -146,10 +182,17 @@ void LLAvatarListItem::setName(const std::string& 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));  } diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 871441b2d3..2330db5249 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -38,9 +38,11 @@  #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 @@ -50,15 +52,17 @@ public:  	};  	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); @@ -75,6 +79,13 @@ public:  	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; @@ -87,6 +98,7 @@ private:  	ContextMenu* mContextMenu;  	LLUUID mAvatarId; +	EOnlineStatus mOnlineStatus;  };  #endif //LL_LLAVATARLISTITEM_H diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 0ff8ca7d26..8987f14e97 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -185,6 +185,18 @@ void LLBottomTray::sessionRemoved(const LLUUID& session_id)  	}  } +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()  { diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 4724c5ecef..cc35e63524 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -67,6 +67,7 @@ public:  	// 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); diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 2b7bd83ca3..359bb23f05 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -260,7 +260,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)  			++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() @@ -333,7 +333,7 @@ void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)  	if(info)  	{  		info->online(is_online); -		mModifyMask |= LLFriendObserver::ONLINE; +		addChangedMask(LLFriendObserver::ONLINE, id);  		lldebugs << "Set buddy " << id << (is_online ? " Online" : " Offline") << llendl;  	}  	else @@ -488,10 +488,52 @@ void LLAvatarTracker::notifyObservers()  	{  		(*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) @@ -610,8 +652,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)  			}  		}  	} -	mModifyMask |= LLFriendObserver::POWERS; +	addChangedMask(LLFriendObserver::POWERS, agent_id);  	notifyObservers();  } diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h index 228239b5ba..bd58b2fbe6 100644 --- a/indra/newview/llcallingcard.h +++ b/indra/newview/llcallingcard.h @@ -150,6 +150,12 @@ public:  	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  	 * @@ -199,6 +205,10 @@ protected:  	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&); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp new file mode 100644 index 0000000000..80f3867a80 --- /dev/null +++ b/indra/newview/llchathistory.cpp @@ -0,0 +1,126 @@ +/**  + * @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(); +} diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h new file mode 100644 index 0000000000..d6eccf896a --- /dev/null +++ b/indra/newview/llchathistory.h @@ -0,0 +1,112 @@ +/**  + * @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_ */ diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index a8ab4303ba..a33a605f50 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -1161,6 +1161,7 @@ LLUIImagePtr get_item_icon(LLAssetType::EType asset_type,  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), @@ -1172,7 +1173,12 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& 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)); @@ -1237,8 +1243,8 @@ BOOL LLInventoryPanel::postBuild()  	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; @@ -1456,6 +1462,25 @@ void LLInventoryPanel::modelChanged(U32 mask)  	}  } +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; @@ -1493,11 +1518,11 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)  			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)  				{ @@ -1516,12 +1541,12 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)  			{  				// 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)  				{ diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h index 33b1a3b6c9..1666f18c05 100644 --- a/indra/newview/llfloaterinventory.h +++ b/indra/newview/llfloaterinventory.h @@ -57,6 +57,7 @@ class LLFolderViewItem;  class LLInventoryFilter;  class LLInventoryModel;  class LLInvFVBridge; +class LLInventoryFVBridgeBuilder;  class LLMenuBarGL;  class LLCheckBoxCtrl;  class LLSpinCtrl; @@ -110,7 +111,7 @@ protected:  	friend class LLUICtrlFactory;  public: -	~LLInventoryPanel(); +	virtual ~LLInventoryPanel();  	LLInventoryModel* getModel() { return mInventory; } @@ -172,7 +173,10 @@ public:  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; @@ -180,12 +184,34 @@ protected:  	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; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 3fd0875709..155262ee13 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -190,6 +190,8 @@ LLFolderView::LLFolderView(const Params& p)  	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); @@ -481,6 +483,11 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)  		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); @@ -1224,12 +1231,42 @@ void LLFolderView::copy()  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 diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index c95dc6e5bd..ebfb4efde2 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -180,6 +180,9 @@ public:  	BOOL startDrag(LLToolDragAndDrop::ESource source);  	void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; } +	void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } +	LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } +  	// deletion functionality   	void removeSelectedItems(); @@ -248,6 +251,8 @@ public:  	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); @@ -327,6 +332,17 @@ protected:  	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: diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index 254ce4062a..ff38da279a 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -68,7 +68,7 @@ public:  	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; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 2b1dd83d72..0d74641c5f 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -36,6 +36,7 @@  // 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 @@ -130,6 +131,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p)  	mListener(p.listener),  	mArrowImage(p.folder_arrow_image),  	mBoxImage(p.selection_image) +,	mDontShowInHierarhy(false)  {  	refresh();  } @@ -312,7 +314,12 @@ void LLFolderViewItem::arrangeFromRoot()  	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 @@ -385,12 +392,22 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)  	}  	*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; @@ -781,7 +798,10 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	}  	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)  	{ @@ -794,6 +814,8 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  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); @@ -948,7 +970,8 @@ void LLFolderViewItem::draw()  		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, @@ -2456,6 +2479,28 @@ bool LLInventorySort::updateSort(U32 order)  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  diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 09c97662d9..90c346b381 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -158,6 +158,7 @@ protected:  	LLUIImagePtr				mBoxImage;  	BOOL                            mIsLoading;  	LLTimer                         mTimeSinceRequestStart; +	bool						mDontShowInHierarhy;  	// helper function to change the selection from the root.  	void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected); @@ -200,6 +201,7 @@ public:  	// 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); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index ae869d9ac4..27e31d4edd 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -315,7 +315,7 @@ void LLGroupListItem::setActive(bool active)  	// 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);  } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 680106c7bb..a35c04440b 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -63,13 +63,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  	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); @@ -139,10 +141,16 @@ void LLIMFloater::sendMsg()  			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); @@ -200,6 +208,8 @@ BOOL LLIMFloater::postBuild()  		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();  } @@ -337,6 +347,37 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  	}  } +//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); @@ -457,3 +498,4 @@ void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line  	self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));  	self->mHistoryEditor->blockUndo();  } + diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 5276013568..9b519ee7e3 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -68,6 +68,10 @@ public:  	// 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*); @@ -108,6 +112,9 @@ private:  	LLViewerTextEditor* mHistoryEditor;  	LLLineEditor* mInputEditor;  	bool mPositioned; + +	bool mSessionInitialized; +	LLSD mQueuedMsgsForInit;  }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2ecd3eb448..6aa6c3f461 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -144,6 +144,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&  	// 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))  	{ @@ -181,26 +183,44 @@ LLIMModel::LLIMSession::~LLIMSession()  	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 @@ -736,18 +756,10 @@ bool LLIMModel::sendStartSession(  			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; @@ -789,6 +801,9 @@ bool LLIMModel::sendStartSession(  				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; @@ -1291,9 +1306,16 @@ void LLIMMgr::addMessage(  		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); @@ -1310,17 +1332,12 @@ void LLIMMgr::addMessage(  	// 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); @@ -1869,6 +1886,15 @@ void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)  	}  } +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); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index df28c16bb1..84646a9a6f 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -56,6 +56,8 @@ public:  			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; @@ -153,6 +155,7 @@ public:  	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;  }; @@ -304,6 +307,7 @@ private:  	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; diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 44dd11dd86..14dd0cdbce 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -54,6 +54,8 @@  #include "lltooltip.h"	// positionViewNearMouse()  #include "lluictrl.h" +#include "llavatariconctrl.h" +  class LLFetchAvatarData; @@ -347,6 +349,10 @@ void LLInspectAvatar::requestUpdate()  	// 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, diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e807240e4e..db7d4f4c8f 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -257,11 +257,22 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&  }  // 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()  { @@ -912,6 +923,24 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)  }  // +=================================================+ +// |        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                             |  // +=================================================+ @@ -1321,7 +1350,7 @@ BOOL LLItemBridge::isItemPermissive() const  LLFolderBridge* LLFolderBridge::sSelf=NULL;  // Can be moved to another folder -BOOL LLFolderBridge::isItemMovable() +BOOL LLFolderBridge::isItemMovable() const   {  	LLInventoryObject* obj = getInventoryObject();  	if(obj) @@ -2184,19 +2213,28 @@ void LLFolderBridge::pasteFromClipboard()  		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)); +				}  			}  		}  	} @@ -2668,6 +2706,56 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response  	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)  { @@ -2726,7 +2814,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			}  		} -		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 @@ -2748,8 +2839,28 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  				}  			} -			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(), @@ -3023,14 +3134,14 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	}  	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); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index bc950520aa..d1d2c57f07 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -120,6 +120,11 @@ protected:  	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)  // @@ -168,13 +173,13 @@ public:  	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() {} @@ -221,6 +226,22 @@ protected:  	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  { @@ -291,7 +312,7 @@ public:  							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; diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp index 94ffcbd457..71a5e12332 100644 --- a/indra/newview/llinventoryclipboard.cpp +++ b/indra/newview/llinventoryclipboard.cpp @@ -47,6 +47,7 @@ LLInventoryClipboard LLInventoryClipboard::sInstance;  ///----------------------------------------------------------------------------  LLInventoryClipboard::LLInventoryClipboard() +: mCutMode(false)  {  } @@ -77,6 +78,16 @@ void LLInventoryClipboard::store(const LLDynamicArray<LLUUID>& inv_objects)  	}  } +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(); @@ -90,6 +101,7 @@ void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const  void LLInventoryClipboard::reset()  {  	mObjects.reset(); +	mCutMode = false;  }  // returns true if the clipboard has something pasteable in it. diff --git a/indra/newview/llinventoryclipboard.h b/indra/newview/llinventoryclipboard.h index 7a2cf15d62..7e221d650c 100644 --- a/indra/newview/llinventoryclipboard.h +++ b/indra/newview/llinventoryclipboard.h @@ -60,6 +60,7 @@ public:  	// 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; @@ -69,11 +70,13 @@ public:  	// returns true if the clipboard has something pasteable in it.  	BOOL hasContents() const; +	bool isCutMode() const { return mCutMode; }  protected:  	static LLInventoryClipboard sInstance;  	LLDynamicArray<LLUUID> mObjects; +	bool mCutMode;  public:  	// please don't actually call these diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index 7c759e22a8..2e6615dd91 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -42,16 +42,18 @@  #include "llnotifications.h"  #include "llagent.h" +#include "llagentui.h"  #include "llinventorymodel.h"  #include "lllandmarklist.h"  #include "llslurl.h" +#include "llstring.h"  #include "llviewerinventory.h"  #include "llviewerparcelmgr.h" +#include "llviewerwindow.h" +#include "llwindow.h"  #include "llworldmap.h" -#include "lllandmark.h" -#include "llinventorymodel.h" -#include "llagentui.h" +void copy_slurl_to_clipboard_callback(const std::string& slurl);  class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor  { @@ -303,15 +305,39 @@ void LLLandmarkActions::onRegionResponse(slurl_callback_t cb,  bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)  { +	LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID); + +	if (NULL == landmark) +		return false; + +	return landmark->getGlobalPos(posGlobal); +} + +LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID) +{  	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);  	if (NULL == item)  		return false;  	const LLUUID& asset_id = item->getAssetUUID(); -	LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL); +	return gLandmarkList.getAsset(asset_id, NULL); +} -	if (NULL == landmark) -		return false; +void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID) +{ +	LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID); +	if(landmark) +	{ +		LLVector3d global_pos; +		landmark->getGlobalPos(global_pos); +		LLLandmarkActions::getSLURLfromPosGlobal(global_pos,©_slurl_to_clipboard_callback,true); +	} +} -	return landmark->getGlobalPos(posGlobal); +void copy_slurl_to_clipboard_callback(const std::string& slurl) +{ +	gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(slurl)); +	LLSD args; +	args["SLURL"] = slurl; +	LLNotifications::instance().add("CopySLURL", args);  } diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h index ab8cc4d6a5..e882db0a92 100644 --- a/indra/newview/lllandmarkactions.h +++ b/indra/newview/lllandmarkactions.h @@ -35,6 +35,7 @@  #include "llinventorymodel.h" +class LLLandmark;  /**   * @brief Provides helper functions to manage landmarks   */ @@ -101,6 +102,20 @@ public:      // *TODO: mantipov: profide callback for cases, when Landmark is not loaded yet.      static bool getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal); +    /** +     * @brief Retrieve a landmark from gLandmarkList by inventory item's id +     *  +     * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist. +     */ +    static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID); + +    /** +     * @brief  Performs standard action of copying of SLURL from landmark to user's clipboard. +     * 	This action requires additional server request. The user will be notified  by info message,  +     *  when URL is copied . +     */ +    static void copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID); +  private:      LLLandmarkActions();      LLLandmarkActions(const LLLandmarkActions&); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 91862112a0..7160cce5cb 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -48,11 +48,9 @@  #include "llnearbychathandler.h"  #include "llchannelmanager.h" -//for LLViewerTextEditor support  #include "llagent.h" 			// gAgent  #include "llfloaterscriptdebug.h" -#include "llslurl.h" -#include "llviewertexteditor.h" +#include "llchathistory.h"  #include "llstylemap.h"  #include "lldraghandle.h" @@ -64,7 +62,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) :  	LLFloater(key),  	mEChatTearofState(CHAT_PINNED),  	mChatCaptionPanel(NULL), -	mChatHistoryEditor(NULL) +	mChatHistory(NULL)  {  	m_isDirty = false;  } @@ -110,7 +108,7 @@ BOOL LLNearbyChat::postBuild()  	gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true);  	mChatCaptionPanel = getChild<LLPanel>("chat_caption", false); -	mChatHistoryEditor = getChild<LLViewerTextEditor>("Chat History Editor"); +	mChatHistory = getChild<LLChatHistory>("chat_history");  	reshape(getRect().getWidth(), getRect().getHeight(), FALSE); @@ -185,44 +183,6 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)  void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)  { -	std::string line = chat.mText; - -	//chat.mText starts with Avatar Name if entered message was "/me <action>".  -	// In this case output chat message should be "<Avatar Name> <action>". See EXT-656 -	// See also process_chat_from_simulator() in the llviewermessage.cpp where ircstyle = TRUE; -	if (CHAT_STYLE_IRC != chat.mChatStyle) -		line = chat.mFromName + ": " + line; - -	bool prepend_newline = true; -	if (gSavedSettings.getBOOL("ChatShowTimestamps")) -	{ -		mChatHistoryEditor->appendTime(prepend_newline); -		prepend_newline = false; -	} - -	// If the msg is from an agent (not yourself though), -	// extract out the sender name and replace it with the hotlinked name. -	 -	std::string		str_URL = chat.mURL; - -	if (chat.mSourceType == CHAT_SOURCE_AGENT && -		chat.mFromID != LLUUID::null) -	{ -		str_URL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect"); -	} - -	// If the chat line has an associated url, link it up to the name. -	if (!str_URL.empty() -		&& (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) -	{ -		std::string start_line = line.substr(0, chat.mFromName.length() + 1); -		line = line.substr(chat.mFromName.length() + 1); -		mChatHistoryEditor->appendText(start_line, prepend_newline,  -			LLStyleMap::instance().lookup(chat.mFromID,str_URL)); -		mChatHistoryEditor->blockUndo(); -		prepend_newline = false; -	} -  	S32 font_size = gSavedSettings.getS32("ChatFontSize");  	const LLFontGL* fontp = NULL; @@ -240,8 +200,14 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo  		break;  	} -	mChatHistoryEditor->appendText(line, prepend_newline, LLStyle::Params().color(color).font(fontp)); -	mChatHistoryEditor->blockUndo(); +	LLStyle::Params style_params; +	style_params.color(color); +	style_params.font(fontp); +	LLUUID uuid = chat.mFromID; +	std::string from = chat.mFromName; +	std::string time = ""; +	std::string message = chat.mText; +	mChatHistory->appendWidgetMessage(uuid, from, time, message, style_params);  }  void	LLNearbyChat::addMessage(const LLChat& chat) @@ -315,7 +281,7 @@ void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent)  		mResizeBar[LLResizeBar::RIGHT]->setRect(resize_rect);  	} -	// *NOTE: we must check mChatCaptionPanel and mChatHistoryEditor against NULL because reshape is called from the  +	// *NOTE: we must check mChatCaptionPanel and mChatHistory against NULL because reshape is called from the   	// LLView::initFromParams BEFORE postBuild is called and child controls are not exist yet  	LLRect caption_rect;  	if (NULL != mChatCaptionPanel) @@ -326,12 +292,12 @@ void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent)  		mChatCaptionPanel->setRect(caption_rect);  	} -	if (NULL != mChatHistoryEditor) +	if (NULL != mChatHistory)  	{ -		LLRect scroll_rect = mChatHistoryEditor->getRect(); +		LLRect scroll_rect = mChatHistory->getRect();  		scroll_rect.setLeftTopAndSize( 2, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS, width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2); -		mChatHistoryEditor->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1); -		mChatHistoryEditor->setRect(scroll_rect); +		mChatHistory->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1); +		mChatHistory->setRect(scroll_rect);  	}  	// diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7c8ffa3b94..47cae8ed0d 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -38,7 +38,7 @@  #include "llchat.h"  class LLResizeBar; -class LLViewerTextEditor; +class LLChatHistory;  class LLNearbyChat: public LLFloater  { @@ -89,7 +89,7 @@ private:  	LLHandle<LLView>	mPopupMenuHandle;  	LLPanel*			mChatCaptionPanel; -	LLViewerTextEditor*	mChatHistoryEditor; +	LLChatHistory*		mChatHistory;  	bool				m_isDirty;  }; diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 5186a93569..c08f92b983 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -33,6 +33,8 @@  #include "llviewerprecompiledheaders.h" // must be first include +#include "llfloaterreg.h" +#include "llnearbychat.h"  #include "llnotificationhandler.h"  #include "lltoastnotifypanel.h"  #include "llviewercontrol.h" @@ -96,6 +98,14 @@ bool LLTipHandler::processNotification(const LLSD& notify)  		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);  		if(channel)  			channel->addToast(p); + +		// archive message in nearby chat +		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); +		if(nearby_chat) +		{ +			LLChat chat_msg(notification->getMessage()); +			nearby_chat->addMessage(chat_msg); +		}  	}  	else if (notify["sigtype"].asString() == "delete")  	{ diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 3a3ea1fc3c..7670a5120c 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -43,6 +43,7 @@  #include "lltexturectrl.h"  #include "lltooldraganddrop.h"  #include "llscrollcontainer.h" +#include "llavatariconctrl.h"  #include "llweb.h"  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -447,6 +448,10 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g  void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)  { +	//remove avatar id from cache to get fresh info +	LLAvatarIconIDCache::getInstance()->remove(avatar_data->avatar_id); + +  	childSetValue("register_date", avatar_data->born_on );  	childSetValue("sl_description_edit", avatar_data->about_text);  	childSetValue("fl_description_edit",avatar_data->fl_about_text); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 1d79ea4a21..5f96407d7d 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -35,32 +35,50 @@  #include "llbutton.h"  #include "llfloaterreg.h" -#include "lllandmark.h" +#include "llsdutil.h" +#include "llaccordionctrltab.h" +#include "llagent.h" +#include "llagentui.h"  #include "llfloaterworldmap.h" -#include "llfloaterinventory.h" -#include "llfoldervieweventlistener.h" -#include "lllandmarklist.h" +#include "llfolderviewitem.h" +#include "llinventorysubtreepanel.h" +#include "lllandmarkactions.h" +#include "llplacesinventorybridge.h"  #include "llsidetray.h" -#include "lltabcontainer.h" -#include "llworldmap.h" +#include "llviewermenu.h" +#include "llviewerregion.h"  // Not yet implemented; need to remove buildPanel() from constructor when we switch  //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks"); +static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn"; +static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn"; +static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn"; +static const std::string TRASH_BUTTON_NAME = "trash_btn"; + +static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER; + +// helper functions +static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string); + +  LLLandmarksPanel::LLLandmarksPanel() -	:	LLPanelPlacesTab(), -		mInventoryPanel(NULL) +	:	LLPanelPlacesTab() +	,	mFavoritesInventoryPanel(NULL) +	,	mLandmarksInventoryPanel(NULL) +	,	mMyInventoryPanel(NULL) +	,	mLibraryInventoryPanel(NULL) +	,	mCurrentSelectedList(NULL) +	,	mListCommands(NULL) +	,	mGearFolderMenu(NULL) +	,	mGearLandmarkMenu(NULL)  { -	mSavedFolderState = new LLSaveFolderState(); -	mSavedFolderState->setApply(FALSE); -  	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");  }  LLLandmarksPanel::~LLLandmarksPanel()  { -	delete mSavedFolderState;  }  BOOL LLLandmarksPanel::postBuild() @@ -68,19 +86,13 @@ BOOL LLLandmarksPanel::postBuild()  	if (!gInventory.isInventoryUsable())  		return FALSE; -	mInventoryPanel = getChild<LLInventoryPanel>("landmarks_list"); -	mInventoryPanel->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); -	mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); -	mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_LANDMARK); -	mInventoryPanel->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, _1, _2)); +	// mast be called before any other initXXX methods to init Gear menu +	initListCommandsHandlers(); -	LLFolderView* root_folder = mInventoryPanel->getRootFolder(); -	root_folder->setReshapeCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, _1, _2)); - -	mActionBtn = getChild<LLButton>("selector"); -	root_folder->addChild(mActionBtn); -	mActionBtn->setEnabled(TRUE); -	childSetAction("selector", boost::bind(&LLLandmarksPanel::onSelectorButtonClicked, this), this); +	initFavoritesInventroyPanel(); +	initLandmarksInventroyPanel(); +	initMyInventroyPanel(); +	initLibraryInventroyPanel();  	return TRUE;  } @@ -88,53 +100,21 @@ BOOL LLLandmarksPanel::postBuild()  // virtual  void LLLandmarksPanel::onSearchEdit(const std::string& string)  { -	if (string == "") -	{ -		mInventoryPanel->setFilterSubString(LLStringUtil::null); - -		// re-open folders that were initially open -		mSavedFolderState->setApply(TRUE); -		mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); -		LLOpenFoldersWithSelection opener; -		mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); -		mInventoryPanel->getRootFolder()->scrollToShowSelection(); -	} - -	gInventory.startBackgroundFetch(); - -	if (mInventoryPanel->getFilterSubString().empty() && string.empty()) -	{ -		// current filter and new filter empty, do nothing -		return; -	} - -	// save current folder open state if no filter currently applied -	if (mInventoryPanel->getRootFolder()->getFilterSubString().empty()) -	{ -		mSavedFolderState->setApply(FALSE); -		mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); -	} - -	// set new filter string -	mInventoryPanel->setFilterSubString(string); +	filter_list(mFavoritesInventoryPanel, string); +	filter_list(mLandmarksInventoryPanel, string); +	filter_list(mMyInventoryPanel, string); +	filter_list(mLibraryInventoryPanel, string);  }  // virtual  void LLLandmarksPanel::onShowOnMap()  { -	LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem(); -	if (!current_item) -		return; - -	LLFolderViewEventListener* listenerp = current_item->getListener(); -	if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK) -		return; - -	LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID()); -	if (!inventory_item) +	if (NULL == mCurrentSelectedList) +	{ +		llwarns << "There are no selected list. No actions are performed." << llendl;  		return; - -	LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID()); +	} +	LLLandmark* landmark = getCurSelectedLandmark();  	if (!landmark)  		return; @@ -153,9 +133,12 @@ void LLLandmarksPanel::onShowOnMap()  // virtual  void LLLandmarksPanel::onTeleport()  { -	LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem(); +	LLFolderViewItem* current_item = getCurSelectedItem();  	if (!current_item) +	{ +		llwarns << "There are no selected list. No actions are performed." << llendl;  		return; +	}  	LLFolderViewEventListener* listenerp = current_item->getListener();  	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) @@ -164,117 +147,546 @@ void LLLandmarksPanel::onTeleport()  	}  } -/*  // virtual -void LLLandmarksPanel::onCopySLURL() +void LLLandmarksPanel::updateVerbs()  { -	LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem(); -	if (!current_item) +	if (!isTabVisible())   		return; -	LLFolderViewEventListener* listenerp = current_item->getListener(); -	if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK) -		return; +	BOOL enabled = isLandmarkSelected(); +	mTeleportBtn->setEnabled(enabled); +	mShowOnMapBtn->setEnabled(enabled); -	LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID()); -	if (!inventory_item) -		return; +	// TODO: mantipov: Uncomment when mShareBtn is supported +	// Share button should be enabled when neither a folder nor a landmark is selected +	//mShareBtn->setEnabled(NULL != current_item); -	LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID()); -	if (!landmark) -		return; +	updateListCommands(); +} -	LLVector3d landmark_global_pos; -	if (!landmark->getGlobalPos(landmark_global_pos)) +void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action) +{ +	if (user_action && (items.size() > 0)) +	{ +		deselectOtherThan(inventory_list); +		mCurrentSelectedList = inventory_list; +	} + +	LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem(); +	if (!current_item)  		return; -	U64 new_region_handle = to_region_handle(landmark_global_pos); +	updateVerbs(); +} + +void LLLandmarksPanel::onSelectorButtonClicked() +{ +	// TODO: mantipov: update getting of selected item +	// TODO: bind to "i" button +	LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); -	LLWorldMap::url_callback_t cb = boost::bind( -			&LLPanelPlacesTab::onRegionResponse, this, -			landmark_global_pos, _1, _2, _3, _4); +	LLFolderViewEventListener* listenerp = cur_item->getListener(); +	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) +	{ +		LLSD key; +		key["type"] = "landmark"; +		key["id"] = listenerp->getUUID(); -	LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false); +		LLSideTray::getInstance()->showPanel("panel_places", key); +	} +} + +////////////////////////////////////////////////////////////////////////// +// PROTECTED METHODS +////////////////////////////////////////////////////////////////////////// + +bool LLLandmarksPanel::isLandmarkSelected() const  +{ +	LLFolderViewItem* current_item = getCurSelectedItem(); +	if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	{ +		return true; +	} + +	return false; +} + +LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const +{ + +	LLFolderViewItem* cur_item = getCurSelectedItem(); +	if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +	{  +		return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID()); +	} +	return NULL; +} + +LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const  +{ +	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;  } -*/  // virtual -void LLLandmarksPanel::updateVerbs() +void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)  { -	if (!isTabVisible())  -		return; +	//this function will be called after user will try to create a pick for selected landmark. +	// We have to make request to sever to get parcel_id and snaption_id.  +	if(isLandmarkSelected()) +	{ +		LLLandmark* landmark  =  getCurSelectedLandmark(); +		LLFolderViewItem* cur_item = getCurSelectedItem(); +		LLUUID id = cur_item->getListener()->getUUID(); +		LLInventoryItem* inv_item =  mCurrentSelectedList->getModel()->getItem(id); +		if(landmark) +		{ +			LLPanelPick* panel_pick = new LLPanelPick(TRUE); +			LLSD params; +			LLVector3d landmark_global_pos; +			landmark->getGlobalPos(landmark_global_pos); +			panel_pick->prepareNewPick(landmark_global_pos,cur_item->getName(),inv_item->getDescription(), +			parcel_data.snapshot_id,parcel_data.parcel_id); +			// by default save button should be enabled +			panel_pick->childSetEnabled("save_changes_btn", TRUE); +			// let's toggle pick panel into  panel places +			LLPanel* panel_places =  LLSideTray::getInstance()->getChild<LLPanel>("panel_places");//-> sidebar_places +			panel_places->addChild(panel_pick); +			LLRect paren_rect(panel_places->getRect()); +			panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE); +			panel_pick->setRect(paren_rect); +			params["parcel_id"] =parcel_data.parcel_id; +			/* set exit callback to get back onto panel places   +			 in callback we will make cleaning up( delete pick_panel instance,  +			 remove landmark panel from observer list +			*/  +			panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, +					panel_pick, panel_places,params)); +		} +	} +} + +// virtual +void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id) +{ +	if (!parcel_id.isNull()) +	{ +		LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this); +		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); +	} +} + +// virtual +void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason) +{ +	llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl; +} + + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +////////////////////////////////////////////////////////////////////////// + +void LLLandmarksPanel::initFavoritesInventroyPanel() +{ +	mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list"); + +	LLUUID start_folder_id = mFavoritesInventoryPanel->getModel()->findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + +	initLandmarksPanel(mFavoritesInventoryPanel, start_folder_id); + +	initAccordion("tab_favorites", mFavoritesInventoryPanel); +} + +void LLLandmarksPanel::initLandmarksInventroyPanel() +{ +	mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list"); + +	LLUUID start_folder_id = mLandmarksInventoryPanel->getModel()->findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + +	initLandmarksPanel(mLandmarksInventoryPanel, start_folder_id); +	mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + +	// subscribe to have auto-rename functionality while creating New Folder +	mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2)); + +	initAccordion("tab_landmarks", mLandmarksInventoryPanel); +} + +void LLLandmarksPanel::initMyInventroyPanel() +{ +	mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list"); + +	LLUUID start_folder_id = mMyInventoryPanel->getModel()->getRootFolderID(); + +	initLandmarksPanel(mMyInventoryPanel, start_folder_id); + +	initAccordion("tab_inventory", mMyInventoryPanel); +} + +void LLLandmarksPanel::initLibraryInventroyPanel() +{ +	mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list"); + +	LLUUID start_folder_id = mLibraryInventoryPanel->getModel()->getLibraryRootFolderID(); + +	initLandmarksPanel(mLibraryInventoryPanel, start_folder_id); + +	initAccordion("tab_library", mLibraryInventoryPanel); +} + + +void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list, const LLUUID& start_folder_id) +{ +	inventory_list->buildSubtreeViewsFor(start_folder_id, &PLACES_INVENTORY_BUILDER); + +	inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); +	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); + +	inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + +	LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder()); +	if (root_folder) +	{ +		root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle()); +		root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle()); +	} +} + +void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list) +{ +	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name); +	accordion_tab->setDropDownStateChangedCallback( +		boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list)); +} + +void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list) +{ +	bool expanded = param.asBoolean(); + +	if(!expanded && (mCurrentSelectedList == inventory_list)) +	{ +		inventory_list->getRootFolder()->clearSelection(); + +		mCurrentSelectedList = NULL; +		updateVerbs(); +	} +} + +void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list) +{ +	if (inventory_list != mFavoritesInventoryPanel) +	{ +		mFavoritesInventoryPanel->getRootFolder()->clearSelection(); +	} + +	if (inventory_list != mLandmarksInventoryPanel) +	{ +		mLandmarksInventoryPanel->getRootFolder()->clearSelection(); +	} +	if (inventory_list != mMyInventoryPanel) +	{ +		mMyInventoryPanel->getRootFolder()->clearSelection(); +	} +	if (inventory_list != mLibraryInventoryPanel) +	{ +		mLibraryInventoryPanel->getRootFolder()->clearSelection(); +	} +} + +// List Commands Handlers +void LLLandmarksPanel::initListCommandsHandlers() +{ +	mListCommands = getChild<LLPanel>("bottom_panel"); -	BOOL enabled = FALSE; +	mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this)); +	mListCommands->childSetAction(ADD_LANDMARK_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddLandmarkButtonClick, this)); +	mListCommands->childSetAction(ADD_FOLDER_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddFolderButtonClick, this)); +	mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this)); + +	 +	mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2)); +	mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onCopyPasteAction, this, _2)); +	mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2)); +	mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2)); +	mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2)); +	mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +} + + +void LLLandmarksPanel::updateListCommands() +{ +	// TODO: should be false when "Received" folder is selected +	bool add_folder_enabled = mCurrentSelectedList == mLandmarksInventoryPanel; +	bool trash_enabled = false; // TODO: should be false when "Received" folder is selected + +	LLFolderViewItem* current_item = getCurSelectedItem(); -	LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();  	if (current_item)  	{  		LLFolderViewEventListener* listenerp = current_item->getListener();  		if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)  		{ -			enabled = TRUE; +			trash_enabled = mCurrentSelectedList != mLibraryInventoryPanel;  		}  	} -	mTeleportBtn->setEnabled(enabled); -	mShowOnMapBtn->setEnabled(enabled); +	// keep Options & Add Landmark buttons always enabled +	mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled); +	mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled);  } -void LLLandmarksPanel::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) +void LLLandmarksPanel::onActionsButtonClick()  { -	LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem(); -	if (!current_item) +	LLFolderViewItem* cur_item = NULL; +	if(mCurrentSelectedList) +		cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem(); +	 +	if(!cur_item)  		return; - -	LLFolderViewEventListener* listenerp = current_item->getListener(); +	 +	LLFolderViewEventListener* listenerp = cur_item->getListener(); +	 +	LLMenuGL* menu  =NULL;  	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{ -		S32 bottom = 0; -		LLFolderViewItem* folder = current_item->getParentFolder(); +		menu = mGearLandmarkMenu; +	} +	else if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY) +	{ +		mGearFolderMenu->getChild<LLMenuItemCallGL>("expand")->setVisible(!cur_item->isOpen()); +		mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen()); +		menu = mGearFolderMenu; +	} +	if(menu) +	{ +		menu->buildDrawLabels(); +		menu->updateParent(LLMenuGL::sMenuContainer); +		LLView* actions_btn  = getChild<LLView>(OPTIONS_BUTTON_NAME); +		S32 menu_x, menu_y; +		actions_btn->localPointToOtherView(0,actions_btn->getRect().getHeight(),&menu_x,&menu_y, this); +		menu_y += menu->getRect().getHeight(); +		LLMenuGL::showPopup(this, menu, menu_x,menu_y); +	} +} -		while ( folder->getParentFolder() != NULL ) +void LLLandmarksPanel::onAddLandmarkButtonClick() const +{ +	if(LLLandmarkActions::landmarkAlreadyExists()) +	{ +		std::string location; +		LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL); +		llwarns<<" Landmark already exists at location:  "<< location<<llendl; +		return; +	} +	LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); +} + +void LLLandmarksPanel::onAddFolderButtonClick() const +{ +	LLFolderViewItem*  item = getCurSelectedItem(); +	if(item &&  mCurrentSelectedList == mLandmarksInventoryPanel) +	{ +		LLFolderBridge *parentBridge = NULL; +		if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) +		{ +			parentBridge = dynamic_cast<LLFolderBridge*>(item->getParentFolder()->getListener()); +			/*WORKAROUND:*  +			 LLFolderView::doIdle() is calling in each frame, +			 it changes selected items before LLFolderView::startRenamingSelectedItem. +			 To avoid it we have to change keyboardFocus.  +			*/ +			gFocusMgr.setKeyboardFocus(item->getParentFolder()); +		} +		else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY)   		{ -			bottom += folder->getRect().mBottom; -			folder = folder->getParentFolder(); +			parentBridge = dynamic_cast<LLFolderBridge*>(item->getListener()); +			gFocusMgr.setKeyboardFocus(item);  		} +		menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),parentBridge, LLSD("category")); +	} +} -		LLRect rect = current_item->getRect(); -		LLRect btn_rect( -			rect.mRight - mActionBtn->getRect().getWidth(), -			bottom + rect.mTop, -			rect.mRight, -			bottom + rect.mBottom); +void LLLandmarksPanel::onTrashButtonClick() const +{ +	if(!mCurrentSelectedList) return; -		mActionBtn->setRect(btn_rect); +	mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(), "delete"); +} -		if (!mActionBtn->getVisible()) -			mActionBtn->setVisible(TRUE); +void LLLandmarksPanel::onAddAction(const LLSD& userdata) const +{ +	std::string command_name = userdata.asString(); +	if("add_landmark" == command_name) +	{ +		onAddLandmarkButtonClick(); +	}  +	else if ("category" == command_name) +	{ +		onAddFolderButtonClick(); +	} +} + +void LLLandmarksPanel::onCopyPasteAction(const LLSD& userdata) const +{ +	if(!mCurrentSelectedList)  +		return; +	std::string command_name = userdata.asString(); +    if("copy_slurl" == command_name) +	{ +    	LLFolderViewItem* cur_item = getCurSelectedItem(); +		if(cur_item) +			LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); +	} +	else if ( "paste" == command_name) +	{ +		mCurrentSelectedList->getRootFolder()->paste(); +	}  +	else if ( "cut" == command_name) +	{ +		mCurrentSelectedList->getRootFolder()->cut();  	}  	else  	{ -		if (mActionBtn->getVisible()) -			mActionBtn->setVisible(FALSE); +		mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);  	} - -	updateVerbs();  } -void LLLandmarksPanel::onSelectorButtonClicked() +void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) const  { -	LLFolderViewItem* cur_item = mInventoryPanel->getRootFolder()->getCurSelectedItem(); +	if(!mCurrentSelectedList) return; -	LLFolderViewEventListener* listenerp = cur_item->getListener(); -	if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) +	LLFolderView* root_folder = mCurrentSelectedList->getRootFolder(); +	std::string command_name = userdata.asString(); + +	if ("expand_all" == command_name)  	{ -		LLSD key; -		key["type"] = "landmark"; -		key["id"] = listenerp->getUUID(); +		root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); +		root_folder->arrangeAll(); +	} +	else if ("collapse_all" == command_name) +	{ +		root_folder->closeAllFolders(); +	} +	else +	{ +		root_folder->doToSelected(&gInventory, userdata); +	} +} -		LLSideTray::getInstance()->showPanel("panel_places", key); +bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const +{ +	std::string command_name = userdata.asString(); +	if("category" == command_name) +	{ +		return mCurrentSelectedList == mLandmarksInventoryPanel;  +	} +	else if("paste" == command_name) +	{ +		return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->canPaste() : false; +	} +	return true; +} + +void LLLandmarksPanel::onCustomAction(const LLSD& userdata) +{ +	LLFolderViewItem* cur_item = getCurSelectedItem(); +	if(!cur_item) +		return ; +	std::string command_name = userdata.asString(); +	if("more_info" == command_name) +	{ +		cur_item->getListener()->performAction(mCurrentSelectedList->getRootFolder(),mCurrentSelectedList->getModel(),"about");  	} +	else if ("teleport" == command_name) +	{ +		onTeleport(); +	} +	else if ("show_on_map" == command_name) +	{ +		onShowOnMap(); +	} +	else if ("create_pick" == command_name) +	{ +		LLLandmark* landmark = getCurSelectedLandmark(); +		if(!landmark) return; +		 +		LLViewerRegion* region = gAgent.getRegion(); +		if (!region) return; + +		LLGlobalVec pos_global; +		LLUUID region_id; +		landmark->getGlobalPos(pos_global); +		landmark->getRegionID(region_id); +		LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS), +						  (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS), +						  (F32)pos_global.mdV[VZ]); + +		LLSD body; +		std::string url = region->getCapability("RemoteParcelRequest"); +		if (!url.empty()) +		{ +			body["location"] = ll_sd_from_vector3(region_pos); +			if (!region_id.isNull()) +			{ +				body["region_id"] = region_id; +			} +			if (!pos_global.isExactlyZero()) +			{ +				U64 region_handle = to_region_handle(pos_global); +				body["region_handle"] = ll_sd_from_U64(region_handle); +			} +			LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle())); +		} +		else  +		{ +			llwarns << "Can't create pick for landmark for region" << region_id  +					<< ". Region: "	<< region->getName()  +					<< " does not support RemoteParcelRequest" << llendl;  +		} +	} +} + +void LLLandmarksPanel::onPickPanelExit( LLPanelPick* pick_panel, LLView* owner, const LLSD& params) +{ +	pick_panel->setVisible(FALSE); +	owner->removeChild(pick_panel); +	//we need remove  observer to  avoid  processParcelInfo in the future. +	LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this); + +	delete pick_panel; +	pick_panel = NULL;  } -void LLLandmarksPanel::setSelectedItem(const LLUUID& obj_id) + +////////////////////////////////////////////////////////////////////////// +// HELPER FUNCTIONS +////////////////////////////////////////////////////////////////////////// +static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)  { -	mInventoryPanel->setSelection(obj_id, FALSE); +	if (string == "") +	{ +		inventory_list->setFilterSubString(LLStringUtil::null); + +		// re-open folders that were initially open +		inventory_list->restoreFolderState(); +	} + +	gInventory.startBackgroundFetch(); + +	if (inventory_list->getFilterSubString().empty() && string.empty()) +	{ +		// current filter and new filter empty, do nothing +		return; +	} + +	// save current folder open state if no filter currently applied +	if (inventory_list->getRootFolder()->getFilterSubString().empty()) +	{ +		inventory_list->saveFolderState(); +	} + +	// set new filter string +	inventory_list->setFilterSubString(string);  } +// EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 14cbbd6123..e74a7fdc88 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -33,14 +33,20 @@  #ifndef LL_LLPANELLANDMARKS_H  #define LL_LLPANELLANDMARKS_H +#include "lllandmark.h" + +// newview  #include "llinventorymodel.h"  #include "llpanelplacestab.h" +#include "llpanelpick.h" +#include "llremoteparcelrequest.h"  class LLFolderViewItem; +class LLMenuGL;  class LLInventoryPanel; -class LLSaveFolderState; +class LLInventorySubTreePanel; -class LLLandmarksPanel : public LLPanelPlacesTab +class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver  {  public:  	LLLandmarksPanel(); @@ -50,17 +56,58 @@ public:  	/*virtual*/ void onSearchEdit(const std::string& string);  	/*virtual*/ void onShowOnMap();  	/*virtual*/ void onTeleport(); -	///*virtual*/ void onCopySLURL();  	/*virtual*/ void updateVerbs(); -	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);  	void onSelectorButtonClicked(); -	void setSelectedItem(const LLUUID& obj_id); +	 +protected: +	/** +	 * @return true - if current selected panel is not null and selected item is a landmark +	 */ +	bool isLandmarkSelected() const; +	LLLandmark* getCurSelectedLandmark() const; +	LLFolderViewItem* getCurSelectedItem () const; +	//LLRemoteParcelInfoObserver interface +	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); +	/*virtual*/ void setParcelID(const LLUUID& parcel_id); +	/*virtual*/ void setErrorStatus(U32 status, const std::string& reason); +	  private: -	LLInventoryPanel*			mInventoryPanel; -	LLSaveFolderState*			mSavedFolderState; -	LLButton*					mActionBtn; +	void initFavoritesInventroyPanel(); +	void initLandmarksInventroyPanel(); +	void initMyInventroyPanel(); +	void initLibraryInventroyPanel(); +	void initLandmarksPanel(LLInventorySubTreePanel* inventory_list, const LLUUID& start_folder_id); +	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); + +	// List Commands Handlers +	void initListCommandsHandlers(); +	void updateListCommands(); +	void onActionsButtonClick(); +	void onAddLandmarkButtonClick() const; +	void onAddFolderButtonClick() const; +	void onTrashButtonClick() const; +	void onAddAction(const LLSD& command_name) const; +	void onCopyPasteAction(const LLSD& command_name) const; +	void onFoldingAction(const LLSD& command_name) const; +	bool isActionEnabled(const LLSD& command_name) const; +	void onCustomAction(const LLSD& command_name); +	void onPickPanelExit( LLPanelPick* pick_panel, LLView* owner, const LLSD& params); + +private: +	LLInventorySubTreePanel*	mFavoritesInventoryPanel; +	LLInventorySubTreePanel*	mLandmarksInventoryPanel; +	LLInventorySubTreePanel*	mMyInventoryPanel; +	LLInventorySubTreePanel*	mLibraryInventoryPanel; +	LLMenuGL*					mGearLandmarkMenu; +	LLMenuGL*					mGearFolderMenu; +	LLInventorySubTreePanel*	mCurrentSelectedList; + +	LLPanel*					mListCommands;  };  #endif //LL_LLPANELLANDMARKS_H diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 82cba72bc4..7cc2a04c53 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -39,6 +39,7 @@  #include "llpanel.h"  #include "llremoteparcelrequest.h" +#include "llavatarpropertiesprocessor.h"  class LLTextureCtrl;  class LLMessageSystem; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index d415b17538..b2541ac1b0 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -650,6 +650,23 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)  		mPlaceInfo->createPick(mPosGlobal, mPickPanel);  	} +    else if (item == "add_to_favbar") +    { +        if ( mItem.notNull() )  +        { +            LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); +            if ( favorites_id.notNull() ) +            { +                copy_inventory_item(gAgent.getID(), +                                    mItem->getPermissions().getOwner(), +                                    mItem->getUUID(), +                                    favorites_id, +                                    std::string(), +                                    LLPointer<LLInventoryCallback>(NULL)); +                llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl; +            } +        } +    }  }  void LLPanelPlaces::onBackButtonClicked() diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index e1e3fe4677..96efb885dd 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -47,6 +47,10 @@  #include "lllandmarkactions.h"  #include "llclipboard.h" +// Maximum number of items that can be added to a list in one pass. +// Used to limit time spent for items list update per frame. +static const U32 ADD_LIMIT = 50; +  class LLTeleportHistoryFlatItem : public LLPanel  {  public: @@ -56,6 +60,7 @@ public:  	virtual BOOL postBuild();  	S32 getIndex() { return mIndex; } +	const std::string& getRegionName() { return mRegionName;}  	/*virtual*/ void setValue(const LLSD& value); @@ -211,9 +216,10 @@ void LLTeleportHistoryPanel::ContextMenu::onCopy()  LLTeleportHistoryPanel::LLTeleportHistoryPanel()  	:	LLPanelPlacesTab(),  		mFilterSubString(LLStringUtil::null), +		mDirty(true), +		mCurrentItem(0),  		mTeleportHistory(NULL),  		mHistoryAccordion(NULL), -		mStarButton(NULL),  		mAccordionTabMenu(NULL),  		mLastSelectedScrollList(NULL)  { @@ -277,13 +283,19 @@ BOOL LLTeleportHistoryPanel::postBuild()  	if(gear_menu)  		mGearMenuHandle  = gear_menu->getHandle(); -	mStarButton = getChild<LLButton>("star_btn"); -	mStarButton->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::onStarButtonCommit, this)); -  	return TRUE;  }  // virtual +void LLTeleportHistoryPanel::draw() +{ +	if (mDirty) +		refresh(); + +	LLPanelPlacesTab::draw(); +} + +// virtual  void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)  {  	if (mFilterSubString != string) @@ -361,8 +373,6 @@ void LLTeleportHistoryPanel::updateVerbs()  	{  		mTeleportBtn->setEnabled(false);  		mShowOnMapBtn->setEnabled(false); -		mStarButton->setEnabled(false); -		mStarButton->setToolTip(LLStringExplicit(""));  		return;  	} @@ -370,141 +380,138 @@ void LLTeleportHistoryPanel::updateVerbs()  	mTeleportBtn->setEnabled(NULL != itemp && itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1);  	mShowOnMapBtn->setEnabled(NULL != itemp); +} + +void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date) +{ +	const U32 seconds_in_day = 24 * 60 * 60; + +	S32 tabs_cnt = mItemContainers.size(); +	S32 curr_year = 0, curr_month = 0, curr_day = 0; + +	tab_date = LLDate::now(); +	tab_date.split(&curr_year, &curr_month, &curr_day); +	tab_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0 +	tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() + seconds_in_day); -	if (NULL != itemp) +	tab_idx = -1; + +	while (tab_idx < tabs_cnt - 1 && item_date < tab_date)  	{ -		LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos( -			mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos); +		tab_idx++; -		mStarButton->setEnabled(true); -		if (!landmark || landmark->getUUID().isNull()) +		if (tab_idx <= tabs_cnt - 4)  		{ -			mStarButton->setToggleState(true); -			// Landmark can be created only for current agent positon, which is most recent (last) item in teleport history. -			// mTeleportBtn is disabled only for that item. -			mStarButton->setToolTip(mTeleportBtn->getEnabled() ? getString("cant_create_lm_here") : getString("create_landmark")); +			tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);  		} -		else +		else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month  		{ -			mStarButton->setToggleState(false); -			mStarButton->setToolTip(getString("open_landmark")); +			tab_date =  LLDate::now(); +			tab_date.split(&curr_year, &curr_month, &curr_day); +			curr_month--; +			if (0 == curr_month) +			{ +				curr_month = 12; +				curr_year--; +			} +			tab_date.fromYMDHMS(curr_year, curr_month, curr_day); +		} +		else if (tab_idx == tabs_cnt - 2) // 1 month and older, low boundary is 6 months +		{ +			tab_date =  LLDate::now(); +			tab_date.split(&curr_year, &curr_month, &curr_day); +			if (curr_month > 6) +			{ +				curr_month -= 6; +			} +			else +			{ +				curr_month += 6; +				curr_year--; +			} +			tab_date.fromYMDHMS(curr_year, curr_month, curr_day); +		} +		else // 6 months and older +		{ +			tab_date.secondsSinceEpoch(0);  		} -	} -	else -	{ -		mStarButton->setEnabled(false); -		mStarButton->setToolTip(LLStringExplicit(""));  	}  } -void LLTeleportHistoryPanel::showTeleportHistory() +void LLTeleportHistoryPanel::refresh()  {  	if (!mHistoryAccordion) +	{ +		mDirty = false;  		return; +	} -	const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems(); - -	const U32 seconds_in_day = 24 * 60 * 60; -	LLDate curr_date =  LLDate::now(); - -	S32 curr_tab = -1; -	S32 tabs_cnt = mItemContainers.size(); -	S32 curr_year = 0, curr_month = 0, curr_day = 0; - -	curr_date.split(&curr_year, &curr_month, &curr_day); -	curr_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0 -	curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() + seconds_in_day); +	const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems(); +	LLDate tab_boundary_date =  LLDate::now();  	LLFlatListView* curr_flat_view = NULL; -	S32 index = hist_items.size() - 1; - -	for (LLTeleportHistoryStorage::slurl_list_t::const_reverse_iterator iter = hist_items.rbegin(); -	      iter != hist_items.rend(); ++iter, --index) +	U32 added_items = 0; +	while (mCurrentItem >= 0)  	{ -		std::string landmark_title = (*iter).mTitle; +		std::string landmark_title = items[mCurrentItem].mTitle;  		LLStringUtil::toUpper(landmark_title);  		std::string::size_type match_offset = mFilterSubString.size() ? landmark_title.find(mFilterSubString) : std::string::npos;  		bool passed = mFilterSubString.size() == 0 || match_offset != std::string::npos;  		if (!passed) +		{ +			mCurrentItem--;  			continue; +		} -		if (curr_tab < tabs_cnt - 1) -		{ -			const LLDate &date = (*iter).mDate; +		const LLDate &date = items[mCurrentItem].mDate; -			if (date < curr_date) -			{ -				LLAccordionCtrlTab* tab = NULL; -				while (curr_tab < tabs_cnt - 1 && date < curr_date) -				{ -					curr_tab++; - -					tab = mItemContainers.get(mItemContainers.size() - 1 - curr_tab); -					tab->setVisible(false); - -					if (curr_tab <= tabs_cnt - 4) -					{ -						curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day); -					} -					else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month -					{ -						curr_date =  LLDate::now(); -						curr_date.split(&curr_year, &curr_month, &curr_day); -						curr_month--; -						if (0 == curr_month) -						{ -							curr_month = 12; -							curr_year--; -						} -						curr_date.fromYMDHMS(curr_year, curr_month, curr_day); -					} -					else if (curr_tab == tabs_cnt - 2) // 1 month and older, low boundary is 6 months -					{ -						curr_date =  LLDate::now(); -						curr_date.split(&curr_year, &curr_month, &curr_day); -						if (curr_month > 6) -						{ -							curr_month -= 6; -						} -						else -						{ -							curr_month += 6; -							curr_year--; -						} -						curr_date.fromYMDHMS(curr_year, curr_month, curr_day); -					} -					else // 6 months and older -					{ -						curr_date.secondsSinceEpoch(0); -					} -				} +		if (date < tab_boundary_date) +		{ +			S32 tab_idx = 0; +			getNextTab(date, tab_idx, tab_boundary_date); -				tab->setVisible(true); +			LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1 - tab_idx); +			tab->setVisible(true); -				curr_flat_view = getFlatListViewFromTab(tab); -				if (curr_flat_view) -				{ -					curr_flat_view->clear(); -				} -			} +			curr_flat_view = getFlatListViewFromTab(tab);  		}  		if (curr_flat_view) -		{ -			curr_flat_view->addItem(new LLTeleportHistoryFlatItem(index, &mContextMenu, (*iter).mTitle)); -		} -	} +			curr_flat_view->addItem(new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle)); + +		mCurrentItem--; -	// Hide empty tabs from current to bottom -	for (curr_tab++; curr_tab < tabs_cnt; curr_tab++) -		mItemContainers.get(mItemContainers.size() - 1 - curr_tab)->setVisible(false); +		if (++added_items >= ADD_LIMIT) +			break; +	}  	mHistoryAccordion->arrange();  	updateVerbs(); + +	if (mCurrentItem < 0) +		mDirty = false; +} + +void LLTeleportHistoryPanel::showTeleportHistory() +{ +	mDirty = true; +	mCurrentItem = mTeleportHistory->getItems().size() - 1; + +	for (S32 n = mItemContainers.size() - 1; n >= 0; --n) +	{ +		LLAccordionCtrlTab* tab = mItemContainers.get(n); +		tab->setVisible(false); + +		LLFlatListView* fv = getFlatListViewFromTab(tab); +		if (fv) +			fv->clear(); +	} + +	refresh();  }  void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) @@ -667,28 +674,3 @@ void LLTeleportHistoryPanel::onGearButtonClicked()  	LLMenuGL::showPopup(this, menu, menu_x, menu_y);  } -void LLTeleportHistoryPanel::onStarButtonCommit() -{ -	if (!mLastSelectedScrollList) -		return; - -	LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedScrollList->getSelectedItem()); -	if(!itemp) -		return; - -	if (itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1) -	{ -		LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex()); -	} -	else -	{ -		LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos( -			mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos); - -		if (!landmark || landmark->getUUID().isNull()) -			LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); -		else -			LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex()); -	} -} - diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index f487c92836..bc3595e66d 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -69,6 +69,8 @@ public:  	virtual ~LLTeleportHistoryPanel();  	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void draw(); +  	/*virtual*/ void onSearchEdit(const std::string& string);  	/*virtual*/ void onShowOnMap();  	/*virtual*/ void onTeleport(); @@ -86,17 +88,19 @@ private:  	void onClearTeleportHistory();  	bool onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response); +	void refresh(); +	void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date);  	void showTeleportHistory();  	void handleItemSelect(LLFlatListView* );  	LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);  	void onGearButtonClicked(); -	void onStarButtonCommit();  	LLTeleportHistoryStorage*	mTeleportHistory;  	LLAccordionCtrl*		mHistoryAccordion; -	LLButton *			mStarButton;  	LLFlatListView*			mLastSelectedScrollList; +	bool				mDirty; +	S32				mCurrentItem;  	std::string				mFilterSubString;  	typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t; diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp new file mode 100644 index 0000000000..ef02882c0d --- /dev/null +++ b/indra/newview/llplacesinventorybridge.cpp @@ -0,0 +1,212 @@ +/**  + * @file llplacesinventorybridge.cpp + * @brief Implementation of the Inventory-Folder-View-Bridge classes for Places Panel. + * + * $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 "llmenugl.h" + +#include "llplacesinventorybridge.h" + +#include "llfloaterinventory.h" // for LLInventoryPanel +#include "llfolderview.h" // for FIRST_SELECTED_ITEM + + +static const std::string LANDMARKS_INVENTORY_LIST_NAME("landmarks_list"); + +bool is_landmarks_panel(const LLInventoryPanel* inv_panel) +{ +	if (NULL == inv_panel) +		return false; +	return inv_panel->getName() == LANDMARKS_INVENTORY_LIST_NAME; +} + +void fill_items_with_menu_items(std::vector<std::string>& items, LLMenuGL& menu) +{ +	LLView::child_list_const_iter_t itor; +	for (itor = menu.beginChild(); itor != menu.endChild(); ++itor) +	{ +		std::string name = (*itor)->getName(); +		items.push_back(name); +	} +} + +// virtual +void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ +	std::vector<std::string> items; +	std::vector<std::string> disabled_items; + +	if(isInTrash()) +	{ +		items.push_back(std::string("Purge Item")); +		if (!isItemRemovable()) +		{ +			disabled_items.push_back(std::string("Purge Item")); +		} + +		items.push_back(std::string("Restore Item")); +	} +	else +	{ +		fill_items_with_menu_items(items, menu); + +		// Disable "Landmark More Information" 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("more_info")); +		} +	} + +	hideContextEntries(menu, items, disabled_items); +} + + + +void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ +	{ +		std::vector<std::string> items; +		std::vector<std::string> disabled_items; + +		LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +		bool is_open = false; +		bool disable_changing = true; +		if (inv_panel) +		{ +			LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); +			is_open = (NULL != folder) && folder->isOpen(); + +			disable_changing = !is_landmarks_panel(inv_panel); +		} + +		// collect all items' names +		fill_items_with_menu_items(items, menu); + +		// remove expand or collapse menu item depend on folder state +		std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); +		std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); +		if (it != items.end())	items.erase(it); + +		if (disable_changing) +		{ +			disabled_items.push_back(std::string("add_folder")); +			disabled_items.push_back(std::string("rename")); +			disabled_items.push_back(std::string("delete")); +		} + +		// repeat parent functionality + 		sSelf = this; // necessary for "New Folder" functionality + +		hideContextEntries(menu, items, disabled_items); +	} +} + +//virtual +void LLPlacesFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ +	if ("expand" == action) +	{ +		LLFolderViewFolder* act_folder = getFolder(); +		act_folder->toggleOpen(); +	} +	else if ("collapse" == action) +	{ +		LLFolderViewFolder* act_folder = getFolder(); +		act_folder->toggleOpen(); +	} +	else +	{ +		LLFolderBridge::performAction(folder, model, action); +	} +} + +LLFolderViewFolder* LLPlacesFolderBridge::getFolder() +{ +	LLFolderViewFolder* folder = NULL; +	LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +	if (inv_panel) +	{ +		folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); +	} + +	return folder; +} + +// virtual +LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge( +	LLAssetType::EType asset_type, +	LLAssetType::EType actual_asset_type, +	LLInventoryType::EType inv_type, +	LLInventoryPanel* inventory, +	const LLUUID& uuid, +	U32 flags/* = 0x00*/) const +{ +	LLInvFVBridge* new_listener = NULL; +	switch(asset_type) +	{ +	case LLAssetType::AT_LANDMARK: +		if(!(inv_type == LLInventoryType::IT_LANDMARK)) +		{ +			llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; +		} +		new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, uuid, flags); +		break; +	case LLAssetType::AT_CATEGORY: +		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) +		{ +			// *TODO: Create a link folder handler instead if it is necessary +			new_listener = LLInventoryFVBridgeBuilder::createBridge( +				asset_type, +				actual_asset_type, +				inv_type, +				inventory, +				uuid, +				flags); +			break; +		} +		new_listener = new LLPlacesFolderBridge(inv_type, inventory, uuid); +		break; +	default: +		new_listener = LLInventoryFVBridgeBuilder::createBridge( +			asset_type, +			actual_asset_type, +			inv_type, +			inventory, +			uuid, +			flags); +	} +	return new_listener; +} + +// EOF diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h new file mode 100644 index 0000000000..66a8e8e54d --- /dev/null +++ b/indra/newview/llplacesinventorybridge.h @@ -0,0 +1,91 @@ +/**  + * @file llplacesinventorybridge.h + * @brief Declaration of the Inventory-Folder-View-Bridge classes for Places Panel. + * + * $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_LLPLACESINVENTORYBRIDGE_H +#define LL_LLPLACESINVENTORYBRIDGE_H + +#include "llinventorybridge.h" + +class LLFolderViewFolder; + +/** + * Overridden version of the Inventory-Folder-View-Bridge for Places Panel (Landmarks Tab) + */ +class LLPlacesLandmarkBridge : public LLLandmarkBridge +{ +	friend class LLPlacesInventoryBridgeBuilder; + +public: +	/*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags); + +protected: +	LLPlacesLandmarkBridge(LLInventoryType::EType type, LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00) +		: LLLandmarkBridge(inventory, uuid, flags) {mInvType = type;} +}; + +/** + * Overridden version of the Inventory-Folder-View-Bridge for Folders + */ +class LLPlacesFolderBridge : public LLFolderBridge +{ +	friend class LLPlacesInventoryBridgeBuilder; + +public: +	/*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags); +	/*virtual*/ void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action); + +protected: +	LLPlacesFolderBridge(LLInventoryType::EType type, LLInventoryPanel* inventory, const LLUUID& uuid) +		: LLFolderBridge(inventory, uuid) {mInvType = type;} + +	LLFolderViewFolder* getFolder(); +}; + + +/** + * This class intended to override default InventoryBridgeBuilder for Inventory Panel. + * + * It builds Bridges for Landmarks and Folders in Places Landmarks Panel + */ +class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +{ +public: +	/*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; +}; + +#endif // LL_LLPLACESINVENTORYBRIDGE_H diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 4db849c159..ff95f8adce 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -559,6 +559,15 @@ void LLSideTray::highlightFocused()  } +BOOL	LLSideTray::handleScrollWheel(S32 x, S32 y, S32 mask) +{ +	BOOL ret = LLPanel::handleScrollWheel(x,y,mask); + +	if(!ret && childFromPoint(x,y) != 0 ) +		return TRUE;//mouse wheel over sidetray buttons, eat mouse wheel +	return ret; +} +  //virtual  BOOL		LLSideTray::handleMouseDown	(S32 x, S32 y, MASK mask)  { @@ -641,7 +650,9 @@ LLPanel*	LLSideTray::showPanel		(const std::string& panel_name, const LLSD& para  		LLView* view = (*child_it)->findChildView(panel_name,true);  		if(view)  		{ -			onTabButtonClick((*child_it)->getName()); +			selectTabByName	((*child_it)->getName()); +			if(mCollapsed) +				expandSideBar();  			LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());  			if(container) diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 13acbbb659..6ea6bafac9 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -203,6 +203,7 @@ public:  	bool		addChild		(LLView* view, S32 tab_group);  	BOOL		handleMouseDown	(S32 x, S32 y, MASK mask); +	BOOL		handleScrollWheel(S32 x, S32 y, S32 mask);  	void		reshape			(S32 width, S32 height, BOOL called_from_parent = TRUE);  	S32			getTrayWidth(); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 67a0528a06..6714fe908f 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -45,29 +45,6 @@  #include "llnotificationmanager.h" -// IM session ID can be the same as Avatar UUID. (See LLIMMgr::computeSessionID) -// Probably notification ID also can be the same as Avatar UUID. -// In case when session ID & notification ID are the same it will be impossible to add both  -// appropriate Items into Flat List. -// Functions below are intended to wrap passed LLUUID into LLSD value with different "type". -// Use them anywhere you need to add, get, remove items via the list -inline -LLSD get_notification_value(const LLUUID& notification_id) -{ -	return LLSD() -		.insert("type", "notification") -		.insert("uuid", notification_id); -} - -inline -LLSD get_session_value(const LLUUID& session_id) -{ -	return LLSD() -		.insert("type", "im_chiclet") -		.insert("uuid", session_id); -} - -  //---------------------------------------------------------------------------------  LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),  													mChannel(NULL), @@ -157,7 +134,7 @@ LLSysWellWindow::~LLSysWellWindow()  //---------------------------------------------------------------------------------  void LLSysWellWindow::addItem(LLSysWellItem::Params p)  { -	LLSD value = get_notification_value(p.notification_id); +	LLSD value = p.notification_id;  	// do not add clones  	if( mMessageList->getItemByValue(value))  		return; @@ -191,7 +168,7 @@ void LLSysWellWindow::clear()  //---------------------------------------------------------------------------------  void LLSysWellWindow::removeItemByID(const LLUUID& id)  { -	if(mMessageList->removeItemByValue(get_notification_value(id))) +	if(mMessageList->removeItemByValue(id))  	{  		handleItemRemoved(IT_NOTIFICATION);  		reshapeWindow(); @@ -357,7 +334,7 @@ void LLSysWellWindow::reshapeWindow()  LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId)  {  	LLChiclet* res = NULL; -	RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(get_session_value(sessionId)); +	RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId);  	if (panel != NULL)  	{  		res = panel->mChiclet; @@ -371,7 +348,7 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,  		const std::string& name, const LLUUID& otherParticipantId)  {  	RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); -	if (mMessageList->insertItemAfter(mSeparator, item, get_session_value(sessionId))) +	if (mMessageList->insertItemAfter(mSeparator, item, sessionId))  	{  		handleItemAdded(IT_INSTANT_MESSAGE);  	} @@ -389,7 +366,7 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,  //---------------------------------------------------------------------------------  void LLSysWellWindow::delIMRow(const LLUUID& sessionId)  { -	if (mMessageList->removeItemByValue(get_session_value(sessionId))) +	if (mMessageList->removeItemByValue(sessionId))  	{  		handleItemRemoved(IT_INSTANT_MESSAGE);  	} @@ -423,7 +400,7 @@ void LLSysWellWindow::sessionAdded(const LLUUID& session_id,  		const std::string& name, const LLUUID& other_participant_id)  {  	//*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB) -	if (mMessageList->getItemByValue(get_session_value(session_id)) == NULL) +	if (mMessageList->getItemByValue(session_id) == NULL)  	{  		S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id);  		if (chicletCounter > -1) @@ -443,6 +420,17 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId)  	LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();  } +void LLSysWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ +	//for outgoing ad-hoc and group im sessions only +	LLChiclet* chiclet = findIMChiclet(old_session_id); +	if (chiclet) +	{ +		chiclet->setSessionId(new_session_id); +		mMessageList->updateValue(old_session_id, new_session_id); +	} +} +  void LLSysWellWindow::handleItemAdded(EItemType added_item_type)  {  	bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type); diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 0c3f4d0587..fa6a1abea4 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -108,6 +108,7 @@ private:  	// 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);  	// pointer to a corresponding channel's instance  	LLNotificationsUI::LLScreenChannel*	mChannel; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 86b162247a..0c23947a8c 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -36,178 +36,106 @@  #include "llviewercontrol.h"  #include "lluiconstants.h"  #include "llrect.h" -#include "lliconctrl.h" -#include "lltexteditor.h" -#include "lltextbox.h" -#include "lldbstrings.h" -#include "llchat.h" -#include "llfloaterchat.h"  #include "lltrans.h" -#include "lloverlaybar.h" -  const S32 BOTTOM_PAD = VPAD * 3; +const S32 BUTTON_WIDTH = 90;  //static  const LLFontGL* LLToastNotifyPanel::sFont = NULL;  const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; -LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToastPanel(notification) { -	mIsTip = notification->getType() == "notifytip"; -	mNumOptions = 0; -	mNumButtons = 0; -	mIsScriptDialog = (notification->getName() == "ScriptDialog" -			|| notification->getName() == "ScriptDialogGroup"); -	mAddedDefaultBtn = false; +LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) :  +LLToastPanel(notification), +mTextBox(NULL), +mIcon(NULL), +mInfoPanel(NULL), +mControlPanel(NULL), +mNumOptions(0), +mNumButtons(0), +mAddedDefaultBtn(false) +{ +	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml"); +	mInfoPanel = getChild<LLPanel>("info_panel"); +	mControlPanel = getChild<LLPanel>("control_panel"); +	mIcon = getChild<LLIconCtrl>("info_icon"); -	// clicking on a button does not steal current focus -	setIsChrome(TRUE); +	// customize panel's attributes +	// is it intended for displaying a tip +	mIsTip = notification->getType() == "notifytip"; +	// is it a script dialog +	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); +	// is it a caution +	// +	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the +	// notify xml template specifies that it is a caution +	// tip-style notification handle 'caution' differently -they display the tip in a different color +	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; -	// class init +	// setup parameters +	// get a notification message +	mMessage = notification->getMessage(); +	// init font variables  	if (!sFont)  	{  		sFont = LLFontGL::getFontSansSerif();  		sFontSmall = LLFontGL::getFontSansSerifSmall();  	} - -	// setup paramaters -	mMessage = notification->getMessage(); - +	// clicking on a button does not steal current focus +	setIsChrome(TRUE);  	// initialize  	setFocusRoot(!mIsTip); - -	// caution flag can be set explicitly by specifying it in the -	// notification payload, or it can be set implicitly if the -	// notify xml template specifies that it is a caution -	// -	// tip-style notification handle 'caution' differently - -	// they display the tip in a different color -	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - +	// get a form for the notification  	LLNotificationFormPtr form(notification->getForm()); - +	// get number of elements  	mNumOptions = form->getNumElements(); -	LLRect rect = mIsTip ? getNotifyTipRect(mMessage) -		   		  		 : getNotifyRect(mNumOptions, mIsScriptDialog, mIsCaution); -	setRect(rect); -	setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT)); -	setBackgroundVisible(FALSE); -	setBackgroundOpaque(TRUE); - -	LLIconCtrl* icon; -	LLTextEditor* text; - -	const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32); -	const S32 BOTTOM = (S32)sFont->getLineHeight(); -	S32 x = HPAD + HPAD; -	S32 y = TOP; - -	LLIconCtrl::Params common_params; -	common_params.rect(LLRect(x, y, x+32, TOP-32)); -	common_params.mouse_opaque(false); -	common_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); +	// customize panel's outfit +	// preliminary adjust panel's layout +	mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); +	// choose a right icon  	if (mIsTip)  	{  		// use the tip notification icon -		common_params.image(LLUI::getUIImage("notify_tip_icon.tga")); -		icon = LLUICtrlFactory::create<LLIconCtrl> (common_params); +		mIcon->setValue("notify_tip_icon.tga"); +		LLRect icon_rect = mIcon->getRect(); +		icon_rect.setLeftTopAndSize(icon_rect.mLeft, getRect().getHeight() - VPAD, icon_rect.getWidth(), icon_rect.getHeight()); +		mIcon->setRect(icon_rect);  	}  	else if (mIsCaution)  	{  		// use the caution notification icon -		common_params.image(LLUI::getUIImage("notify_caution_icon.tga")); -		icon = LLUICtrlFactory::create<LLIconCtrl> (common_params); +		mIcon->setValue("notify_caution_icon.tga");  	}  	else  	{  		// use the default notification icon -		common_params.image(LLUI::getUIImage("notify_box_icon.tga")); -		icon = LLUICtrlFactory::create<LLIconCtrl> (common_params); +		mIcon->setValue("notify_box_icon.tga");  	} -	icon->setMouseOpaque(FALSE); -	addChild(icon); - -	x += HPAD + HPAD + 32; - +	// adjust text options according to the notification type  	// add a caution textbox at the top of a caution notification -	LLTextBox* caution_box = NULL;  	if (mIsCaution && !mIsTip)  	{ -		S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD; -		LLTextBox::Params params; -		params.name("caution_box"); -		params.rect(LLRect(x, y, getRect().getWidth() - 2, caution_height)); -		params.font(sFont); -		params.mouse_opaque(false); -		params.font.style("BOLD"); -		params.text_color(LLUIColorTable::instance().getColor("NotifyCautionWarnColor")); -		params.bg_readonly_color(LLUIColorTable::instance().getColor("NotifyCautionBoxColor")); -		params.border_visible(false); -		params.wrap(true); -		caution_box = LLUICtrlFactory::create<LLTextBox> (params); -		caution_box->setValue(notification->getMessage()); - -		addChild(caution_box); - -		// adjust the vertical position of the next control so that -		// it appears below the caution textbox -		y = y - caution_height; +		mTextBox = getChild<LLTextBox>("caution_text_box");  	}  	else  	{ - -		const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD); - -		// Tokenization on \n is handled by LLTextBox - -		const S32 MAX_LENGTH = 512 + 20 + -			DB_FIRST_NAME_BUF_SIZE + -			DB_LAST_NAME_BUF_SIZE + -			DB_INV_ITEM_NAME_BUF_SIZE;  // For script dialogs: add space for title. - -		LLTextEditor::Params params; -		params.name("box"); -		params.rect(LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16)); -		params.max_text_length(MAX_LENGTH); -		params.read_only(true); -		params.default_text(mMessage); -		params.font(sFont); -		params.embedded_items(false); -		params.wrap(true); -		params.tab_stop(false); -		params.mouse_opaque(false); -		params.bg_readonly_color(LLColor4::transparent); -		params.text_readonly_color(LLUIColorTable::instance().getColor("NotifyTextColor")); -		params.enabled(false); -		params.border_visible(false); -		text = LLUICtrlFactory::create<LLTextEditor> (params); -		addChild(text); +		mTextBox = getChild<LLTextEditor>("text_editor_box");   	} -	if (mIsTip) -	{ -		// TODO: Make a separate archive for these. -		LLChat chat(mMessage); -		chat.mSourceType = CHAT_SOURCE_SYSTEM; -		LLFloaterChat::addChatHistory(chat); -	} -	else -	{ -		LLButton::Params p; -		p.name(std::string("next")); -		p.rect(LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD)); -		p.image_selected.name("notify_next.png"); -		p.image_unselected.name("notify_next.png"); -		p.font(sFont); -		p.scale_image(true); -		p.tool_tip(LLTrans::getString("next").c_str()); +	// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +	const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  + +	mTextBox->setVisible(TRUE); +	mTextBox->setValue(notification->getMessage()); +	// add buttons for a script notification +	if (!mIsTip) +	{  		for (S32 i = 0; i < mNumOptions; i++)  		{ -  			LLSD form_element = form->getElement(i);  			if (form_element["type"].asString() != "button")  			{ @@ -222,137 +150,63 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas  			addButton("OK", LLTrans::getString("ok"), FALSE, TRUE);  			mAddedDefaultBtn = true;  		} - -  	} + +	// adjust panel's height to the text size +	mInfoPanel->setFollowsAll(); +	snapToMessageHeight(mTextBox, MAX_LENGTH);  } -LLToastNotifyPanel::~LLToastNotifyPanel() { +LLToastNotifyPanel::~LLToastNotifyPanel()  +{  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());  } -LLRect LLToastNotifyPanel::getNotifyRect(S32 num_options, BOOL mIsScriptDialog, BOOL is_caution) +void LLToastNotifyPanel::adjustPanelForScriptNotice(const LLNotificationFormPtr form)  { -	S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight"); -	if (is_caution) +	F32 buttons_num = 0; +	S32 button_rows = 0; + +	// calculate number of buttons +	for (S32 i = 0; i < mNumOptions; i++)  	{ -		// make caution-style dialog taller to accomodate extra text, -		// as well as causing the accept/decline buttons to be drawn -		// in a different position, to help prevent "quick-click-through" -		// of many permissions prompts -		notify_height = gSavedSettings.getS32("PermissionsCautionNotifyBoxHeight"); +		if (form->getElement(i)["type"].asString() == "button") +		{ +			buttons_num++; +		}  	} -	const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth"); -	const S32 TOP = getRect().getHeight(); -	const S32 RIGHT =getRect().getWidth(); -	const S32 LEFT = RIGHT - NOTIFY_WIDTH; - -	if (num_options < 1) +	// calculate necessary height for the button panel +	// if notification form contains no buttons - reserve a place for OK button +	// script notifications have extra line for an IGNORE button +	if(mIsScriptDialog)  	{ -		num_options = 1; +		button_rows = llceil((buttons_num - 1) / 3.0f) + 1;  	} - -	// Add two "blank" option spaces. -	if (mIsScriptDialog) +	else  	{ -		num_options += 2; +		button_rows = llmax( 1, llceil(buttons_num / 3.0f));  	} -	S32 additional_lines = (num_options-1) / 3; - -	notify_height += additional_lines * (BTN_HEIGHT + VPAD); +	S32 button_panel_height = button_rows * BTN_HEIGHT + (button_rows + 1) * VPAD + BOTTOM_PAD; -	return LLRect(LEFT, TOP, RIGHT, TOP-notify_height); +	//adjust layout +	LLRect button_rect = mControlPanel->getRect(); +	reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height); +	mControlPanel->reshape(button_rect.getWidth(), button_panel_height);  }  // static -LLRect LLToastNotifyPanel::getNotifyTipRect(const std::string &utf8message) +void LLToastNotifyPanel::adjustPanelForTipNotice()  { -	S32 line_count = 1; -	LLWString message = utf8str_to_wstring(utf8message); -	S32 message_len = message.length(); - -	const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth"); -	// Make room for the icon area. -	const S32 text_area_width = NOTIFY_WIDTH - HPAD * 4 - 32; - -	const llwchar* wchars = message.c_str(); -	const llwchar* start = wchars; -	const llwchar* end; -	S32 total_drawn = 0; -	BOOL done = FALSE; - -	do -	{ -		line_count++; - -		for (end=start; *end != 0 && *end != '\n'; end++) -			; - -		if( *end == 0 ) -		{ -			end = wchars + message_len; -			done = TRUE; -		} - -		S32 remaining = end - start; -		while( remaining ) -		{ -			S32 drawn = sFont->maxDrawableChars( start, (F32)text_area_width, remaining, TRUE ); - -			if( 0 == drawn ) -			{ -				drawn = 1;  // Draw at least one character, even if it doesn't all fit. (avoids an infinite loop) -			} - -			total_drawn += drawn; -			start += drawn; -			remaining -= drawn; - -			if( total_drawn < message_len ) -			{ -				if( (wchars[ total_drawn ] != '\n') ) -				{ -					// wrap because line was too long -					line_count++; -				} -			} -			else -			{ -				done = TRUE; -			} -		} - -		total_drawn++;	// for '\n' -		end++; -		start = end; -	} while( !done ); +	LLRect info_rect = mInfoPanel->getRect(); +	LLRect this_rect = getRect(); -	const S32 MIN_NOTIFY_HEIGHT = 72; -	const S32 MAX_NOTIFY_HEIGHT = 600; -	S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight()); -	if(gOverlayBar) -	{ -		notify_height += gOverlayBar->getBoundingRect().mTop; -	} -	else -	{ -		// *FIX: this is derived from the padding caused by the -		// rounded rects, shouldn't be a const here. -		notify_height += 10; -	} -	notify_height += VPAD; -	notify_height = llclamp(notify_height, MIN_NOTIFY_HEIGHT, MAX_NOTIFY_HEIGHT); - -	const S32 RIGHT = getRect().getWidth(); -	const S32 LEFT = RIGHT - NOTIFY_WIDTH; - -	return LLRect(LEFT, notify_height, RIGHT, 0); +	mControlPanel->setVisible(FALSE); +	reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight());  } -  // static  void LLToastNotifyPanel::onClickButton(void* data)  { @@ -371,10 +225,6 @@ void LLToastNotifyPanel::onClickButton(void* data)  // virtual  LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default)  { -	// make caution notification buttons slightly narrower -	// so that 3 of them can fit without overlapping the "next" button -	S32 btn_width = mIsCaution? 84 : 90; -  	LLRect btn_rect;  	LLButton* btn;  	S32 btn_height= BTN_HEIGHT; @@ -397,9 +247,9 @@ LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::stri  		}  	} -	btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad, +	btn_rect.setOriginAndSize(x + (index % 3) * (BUTTON_WIDTH+HPAD+HPAD) + ignore_pad,  		BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD), -		btn_width - 2*ignore_pad, +		BUTTON_WIDTH - 2*ignore_pad,  		btn_height);  	InstanceAndS32* userdata = new InstanceAndS32; @@ -422,7 +272,7 @@ LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::stri  	btn = LLUICtrlFactory::create<LLButton>(p); -	addChild(btn, -1); +	mControlPanel->addChild(btn, -1);  	if (is_default)  	{ diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index df58c06f25..66534edcdf 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -38,6 +38,9 @@  #include "llnotifications.h"  #include "llbutton.h"  #include "lltoastpanel.h" +#include "lliconctrl.h" +#include "lltexteditor.h" +#include "lltextbox.h"  /** @@ -46,15 +49,15 @@   *   * Replaces class LLNotifyBox.   */ -class LLToastNotifyPanel: public LLToastPanel { +class LLToastNotifyPanel: public LLToastPanel  +{  public:  	LLToastNotifyPanel(LLNotificationPtr&);  	virtual ~LLToastNotifyPanel(); -	bool isTip() {return mIsTip;} -	static LLToastNotifyPanel * buildNotifyPanel(LLNotificationPtr notification);  protected:  	LLButton* addButton(std::string const &name, const std::string& label, BOOL is_option, BOOL is_default); +  	// Used for callbacks  	struct InstanceAndS32  	{ @@ -65,16 +68,23 @@ protected:  private: -	// Returns the rect, relative to gNotifyView, where this -	// notify box should be placed. -	LLRect getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution); -	LLRect getNotifyTipRect(const std::string &message); +	void adjustPanelForScriptNotice(const LLNotificationFormPtr form); +	void adjustPanelForTipNotice(); + +	// panel elements +	LLTextBase*		mTextBox; +	LLIconCtrl*		mIcon; +	LLPanel*		mInfoPanel;		// a panel, that contains an information +	LLPanel*		mControlPanel;	// a panel, that contains buttons (if present) +  	// internal handler for button being clicked  	static void onClickButton(void* data); +  	bool mIsTip;  	bool mAddedDefaultBtn;  	bool mIsScriptDialog; -	bool mIsCaution; // is this a caution notification? +	bool mIsCaution;  +  	std::string mMessage;  	S32 mNumOptions;  	S32 mNumButtons; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 7b477470aa..ef75e06047 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -34,6 +34,9 @@  #include "lltoastpanel.h" +//static +const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32) +  LLToastPanel::LLToastPanel(LLNotificationPtr& notification)   {  	mNotification = notification; @@ -50,8 +53,13 @@ std::string LLToastPanel::getTitle()  }  //snap to the message height if it is visible -void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount) +void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  { +	if(!message) +	{ +		return; +	} +  	//Add message height if it is visible  	if (message->getVisible())  	{ @@ -61,22 +69,16 @@ void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)  		LLRect messageRect = message->getRect();  		S32 oldTextHeight = messageRect.getHeight(); -		//Reshape the toast to give the message max height. -		//This needed to calculate lines count according to specified text -		heightDelta = maxTextHeight - oldTextHeight; -		reshape( getRect().getWidth(), getRect().getHeight() + heightDelta); -  		//Knowing the height is set to max allowed, getTextPixelHeight returns needed text height  		//Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape. -		S32 requiredTextHeight = message->getTextPixelHeight(); +		S32 requiredTextHeight = message->getContentsRect().getHeight();  		S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);  		//Calculate last delta height deducting previous heightDelta   		heightDelta = newTextHeight - oldTextHeight - heightDelta;  		//reshape the panel with new height -		reshape( getRect().getWidth(), getRect().getHeight() + heightDelta); +		reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT));  	} -  } diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 418373e8c6..a88127b008 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -58,9 +58,11 @@ public:  	virtual std::string getTitle();  	virtual const LLUUID& getID() { return mNotification->id();} + +	static const S32 MIN_PANEL_HEIGHT;  protected:  	LLNotificationPtr mNotification; -	void snapToMessageHeight(LLTextBox* message, S32 maxLineCount); +	void snapToMessageHeight(LLTextBase* message, S32 maxLineCount);  };  #endif /* LL_TOASTPANEL_H */ diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 273ca8bd1a..5f95e9ccf1 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2293,7 +2293,9 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)  	}  	// Zoom the camera in and out behavior -	gAgent.handleScrollWheel(clicks); + +	if(top_ctrl == 0 && mWorldViewRect.pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) ) +		gAgent.handleScrollWheel(clicks);  	return;  } @@ -4168,8 +4170,9 @@ void LLViewerWindow::drawMouselookInstructions()  		instructions, 0,  		getVirtualWorldViewRect().getCenterX(),  		getVirtualWorldViewRect().mBottom + INSTRUCTIONS_PAD, -		LLColor4( 0.0f, 0.0f, 0.0f, 0.6f ), -		LLFontGL::HCENTER, LLFontGL::TOP); +		LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ), +		LLFontGL::HCENTER, LLFontGL::TOP, +		LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);  }  S32	LLViewerWindow::getWindowHeight()	const 	 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 f1976afb4a..6fbfed5f60 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -30,23 +30,18 @@        		color="1 1 1 1" enabled="true" image_name="closebox.tga"        		name="close_btn"/>  	</panel> -            <text_editor +            <chat_history               allow_html="true"                bg_readonly_color="ChatHistoryBgColor"               bg_writeable_color="ChatHistoryBgColor" -             follows="left|top|right|bottom" +             follows="left|top|right"               font="SansSerif"               layout="topleft" -			       height="320" -             max_length="2147483647" -             name="Chat History Editor" +			 height="320" +             name="chat_history"               parse_highlights="true"  -             read_only="true"               text_color="ChatHistoryTextColor"               text_readonly_color="ChatHistoryTextColor" -             bottom="0" -             track_bottom="true" -             width="250" -             word_wrap="true" /> +             width="250"/>  </floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 6dc08ad3ef..7785492651 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -478,11 +478,12 @@           parameter="open" />      </menu_item_call>      <menu_item_separator -     layout="topleft" /> +     layout="topleft" +     name="Landmark Separator" />      <menu_item_call       label="About Landmark"       layout="topleft" -     name="Teleport To Landmark"> +     name="About Landmark">          <menu_item_call.on_click           function="Inventory.DoToSelected"           parameter="about" /> diff --git a/indra/newview/skins/default/xui/en/menu_landmark.xml b/indra/newview/skins/default/xui/en/menu_landmark.xml index 64fec3ab40..54a4095967 100644 --- a/indra/newview/skins/default/xui/en/menu_landmark.xml +++ b/indra/newview/skins/default/xui/en/menu_landmark.xml @@ -29,4 +29,12 @@           function="Places.OverflowMenu.Action"           parameter="pick" />      </menu_item_call> +    <menu_item_call +     label="Add to Favorites Bar" +     layout="topleft" +     name="add_to_favbar"> +        <menu_item_call.on_click +         function="Places.OverflowMenu.Action" +         parameter="add_to_favbar" /> +    </menu_item_call>  </toggleable_menu> 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 new file mode 100644 index 0000000000..b31a0d88a4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml @@ -0,0 +1,45 @@ +<menu name="menu_folder_gear" +     left="0" bottom="0" visible="false" +     mouse_opaque="false" opaque="true"  +     color="MenuDefaultBgColor" drop_shadow="true"> +     <menu_item_call name="add_landmark" label="Add Landmark"> +     <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="add_landmark" /> +     </menu_item_call> +     <menu_item_call name="add_folder" label="Add Folder"> +     <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="category" /> +     <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="category" /> +     </menu_item_call> +     <menu_item_separator layout="topleft" /> +     <menu_item_call name="cut" label="Cut"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="cut" /> +     </menu_item_call> +     <menu_item_call name="copy_folder" label="Copy"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="copy" /> +     </menu_item_call> +     <menu_item_call name="paste" label="Paste"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="paste" /> +     <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="paste" /> +     </menu_item_call> +     <menu_item_call name="rename" label="Rename"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="rename" /> +     </menu_item_call> +     <menu_item_call name="delete" label="Delete"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="delete" /> +     </menu_item_call> +     <menu_item_separator layout="topleft" /> +     <menu_item_call name="expand" label="Expand"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="expand" /> +     </menu_item_call> +     <menu_item_call name="collapse" label="Collapse"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="collapse" /> +     </menu_item_call> +     <menu_item_call name="expand_all" label="Expand all folders"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="expand_all" /> +     </menu_item_call> +     <menu_item_call name="collapse_all" label="Collapse all folders"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="collapse_all" /> +     </menu_item_call> +     <menu_item_call name="sort_by_date" label="Sort by Date"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="sort_by_date" /> +     </menu_item_call> +</menu>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml new file mode 100644 index 0000000000..2d8bb0dcb9 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml @@ -0,0 +1,56 @@ +<menu name="menu_ladmark_gear" +     left="0" bottom="0" visible="false" +     mouse_opaque="false" opaque="true"  +     color="MenuDefaultBgColor" drop_shadow="true"> +     <menu_item_call name="teleport" label="Teleport"> +     <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="teleport" /> +     </menu_item_call> +     <menu_item_call name="more_info" label="More Information"> +     <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="more_info" /> +     </menu_item_call> +     <menu_item_call name="show_on_map" label="Show on Map"> +     <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="show_on_map" /> +     </menu_item_call> +     <menu_item_separator layout="topleft" /> +     <menu_item_call name="add_landmark" label="Add Landmark"> +     <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="add_landmark" /> +     </menu_item_call> +     <menu_item_call name="add_folder" label="Add Folder"> +     <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="category" /> +     <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="category" /> +     </menu_item_call> +     <menu_item_separator layout="topleft" /> +     <menu_item_call name="cut" label="Cut"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="cut" /> +     </menu_item_call> +     <menu_item_call name="copy_landmark" label="Copy Landmark"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="copy" /> +     </menu_item_call> +     <menu_item_call name="copy_slurl" label="Copy SLURL"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="copy_slurl" /> +     </menu_item_call> +     <menu_item_call name="paste" label="Paste"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="paste" /> +     <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="paste" /> +     </menu_item_call> +     <menu_item_call name="rename" label="Rename"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="rename" /> +     </menu_item_call> +     <menu_item_call name="delete" label="Delete"> +     <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="delete" /> +     </menu_item_call> +     <menu_item_separator layout="topleft" /> +     <menu_item_call name="expand_all" label="Expand all folders"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="expand_all" /> +     </menu_item_call> +     <menu_item_call name="collapse_all" label="Collapse all folders"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="collapse_all" /> +     </menu_item_call> +     <menu_item_call name="sort_by_date" label="Sort by Date"> +     <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="sort_by_date" /> +     </menu_item_call> +     <menu_item_separator layout="topleft" /> +     <menu_item_call name="create_pick" label="Create Pick"> +     <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="create_pick" /> +     </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index f7f08b9b6a..69d90e4c7d 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -38,12 +38,13 @@       width="20" />      <text       follows="left|right" -     font="SansSerifSmallBold" +     font="SansSerifSmall" +     font.style="BOLD"       height="20"       layout="topleft"       left_pad="5"       name="avatar_name" -     text_color="white" +     text_color="grey"       top="4"       use_ellipses="true"        value="Unknown" diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml new file mode 100644 index 0000000000..a9f622e018 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="left|top|right" + height="57" + label="im_header_container" + layout="topleft" + left="8" + name="im_header_container"> +    <panel +     background_visible="true" +     bevel_style="in" +     bg_alpha_color="black" +     follows="left|top|right" +     height="30" +     label="im_header" +     layout="topleft" +     name="im_header" +     top_pad="17"> +        <avatar_icon +         follows="left" +         height="20" +         image_name="icon_avatar_online.tga" +         layout="topleft" +         left="5" +         mouse_opaque="true" +         name="avatar_icon" +         top="5" +         width="20" /> +        <text +         follows="left|right" +         font="SansSerifBigBold" +         height="20" +         layout="topleft" +         left_pad="10" +         right="-50" +         name="user_name" +         text_color="white" +         top="5" +         value="Darth Vader" +         use_ellipses="true" /> +        <text +         follows="right" +         font="SansSerifBig" +         height="20" +         layout="topleft" +         name="time_box" +         right="0" +         text_color="white" +         top="5" +         value="23:30" +         width="50" /> +    </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_chat_separator.xml b/indra/newview/skins/default/xui/en/panel_chat_separator.xml new file mode 100644 index 0000000000..dd27595cdb --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_chat_separator.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="left|right|top" + height="10" + layout="topleft" + left="8" + name="chat_separator_container"> +    <panel +     background_visible="true" +     bg_alpha_color="black" +     follows="left|right|top" +     height="1" +     layout="topleft" +     name="chat_separator_panel" +     top_pad="5" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index ae33d6da3e..7c7561f922 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -1,35 +1,143 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel     name="Landmarks" -   bottom="0" -   height="326" +   top="0" +   height="400" +   layout="topleft"      left="0"     width="380"     border="true"     background_visible="true"     bg_alpha_color="DkGray2"     follows="left|top|right|bottom"> -      <inventory_panel -	 allow_multi_select="true" -	 border="true" -	 bottom="0" -	 follows="left|top|right|bottom" -	 height="326" -	 left="0" -	 mouse_opaque="true" -	 name="landmarks_list" - 	 start_folder="landmark" -	 width="380"/> -      <button -	 bottom="0" -	 halign="center" -	 height="16" -	 label=">" -	 enabled="false" -	 mouse_opaque="false" -	 name="selector" -	 width="20" -	 left="0" -	 follows="right|bottom" -	 tool_tip="View landmark properties"/> +    <accordion +     follows="left|top|right|bottom" +     height="368" +     layout="topleft" +     left="0" +     name="landmarks_accordion" +     top="2" +     width="380"> +        <accordion_tab +         layout="topleft" +         name="tab_favorites" +         title="Favorites bar"> +            <inventory_subtree_panel +             allow_multi_select="true" +             border="true" +             bottom="0" +             follows="left|top|right|bottom" +             height="126" +             left="0" +             mouse_opaque="true" +             name="favorites_list" +             width="380"/> +        </accordion_tab> +        <accordion_tab +         layout="topleft" +         name="tab_landmarks" +         title="Landmarks"> +            <inventory_subtree_panel +             allow_multi_select="true" +             border="true" +             bottom="0" +             follows="left|top|right|bottom" +             height="126" +             left="0" +             mouse_opaque="true" +             name="landmarks_list" +             start_folder="landmark" +             width="380"/> +        </accordion_tab> +        <accordion_tab +         layout="topleft" +         name="tab_inventory" +         title="My Inventory"> +            <inventory_subtree_panel +             allow_multi_select="true" +             border="true" +             bottom="0" +             follows="left|top|right|bottom" +             height="126" +             left="0" +             mouse_opaque="true" +             name="my_inventory_list" +             width="380"/> +        </accordion_tab> +        <accordion_tab +         layout="topleft" +         name="tab_library" +         title="Library"> +            <inventory_subtree_panel +             allow_multi_select="true" +             border="true" +             bottom="0" +             follows="left|top|right|bottom" +             height="120" +             left="0" +             mouse_opaque="true" +             name="library_list" +             width="380"/> +        </accordion_tab> +    </accordion> +    <panel +     background_visible="true" +     bevel_style="none" +     bottom="0" +     follows="left|right|bottom" +     height="30" +     layout="bottomleft" +     left="0" +     name="bottom_panel" +     width="380"> +        <button +         follows="bottom|left" +         tool_tip="Show additional options" +         height="18" +         image_disabled="OptionsMenu_Disabled" +         image_selected="OptionsMenu_Press" +         image_unselected="OptionsMenu_Off" +         layout="topleft" +         left="10" +         name="options_gear_btn" +         picture_style="true" +         top="6" +         width="18" /> +        <button +         follows="bottom|left" +         height="18" +         image_selected="AddItem_Press" +         image_unselected="AddItem_Off" +         image_disabled="AddItem_Disabled" +         layout="topleft" +         left_pad="5" +         name="add_landmark_btn" +         picture_style="true" +         tool_tip="Add New Landmark" +         width="18" /> +        <button +         follows="bottom|left" +         height="18" +         image_selected="AddItem_Press" +         image_unselected="AddItem_Off" +         image_disabled="AddItem_Disabled" +         layout="topleft" +         left_pad="5" +         name="add_folder_btn" +         picture_style="true" +         tool_tip="Add New Folder" +         width="18" /> +        <button +         follows="bottom|right" +         height="18" +         image_selected="TrashItem_Press" +         image_unselected="TrashItem_Off" +         layout="topleft" +         right="-5" +         name="trash_btn" +         picture_style="true" +         tool_tip="Remove selected Landmark" +         top="6" +         width="18" /> +    </panel>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml new file mode 100644 index 0000000000..4d890b1d46 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel +  background_opaque="true" +  background_visible="false" +  bg_alpha_color="0.3 0.3 0.3 0" +  height="140" +  label="notification_panel" +  layout="topleft" +  left="0" +  name="notification_panel" +  top="0" +  width="350"> +  <panel +    background_visible="true" +    follows="left|right|top" +    height="100" +    label="info_panel" +    layout="topleft" +    left="0" +    name="info_panel" +    top="0" +    width="350"> +    <text +      border_visible="false" +      follows="left|right|top|bottom" +      font="SansSerif" +      height="90" +      layout="topleft" +      left="45" +      name="text_box" +      read_only="true" +      text_color="white" +      top="5" +      visible="false"  +      width="300" +      wrap="true"/> +    <text +      border_visible="false" +      follows="left|right|top|bottom" +      font="SansSerifBold" +      height="90" +      layout="topleft" +      left="45" +      name="caution_text_box" +      text_color="1 0.82 0.46 1" +      top="5" +      visible="false" +      width="300" +      wrap="true"/> +    <text_editor +      bg_readonly_color="0.0 0.0 0.0 0" +      border_visible="false" +      embedded_items="false" +      enabled="false" +      follows="left|right|top|bottom" +      font="SansSerif" +      height="90" +      layout="topleft" +      left="45" +      mouse_opaque="false" +      name="text_editor_box" +      read_only="true" +      tab_stop="false" +      text_color="white" +      text_readonly_color="white" +      top="5" +      visible="false" +      width="300" +      wrap="true"/> +  </panel> +  <panel +    background_visible="true" +    follows="left|right|bottom" +    height="40" +    label="control_panel" +    layout="topleft" +    left="0" +    name="control_panel" +    top_pad="0" +    width="350"> +  </panel> +  <icon +    follows="left|top" +    height="32" +    image_name="notify_tip_icon.tga" +    layout="topleft" +    left="8" +    mouse_opaque="false" +    name="info_icon" +    top="20" +    width="32" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index b0cd75117f..4169c6245b 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -1,15 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel name="Teleport History" bottom="0" height="326" left="0" width="380"       border="true" follows="left|top|right|bottom">      -    <string -     name="cant_create_lm_here" -     value="Please teleport to selected location before creating Landmark. " /> -    <string -     name="create_landmark" -     value="Create Landmark" /> -    <string -     name="open_landmark" -     value="Open Landmark panel" />      <accordion       follows="left|top|right|bottom"       height="300" @@ -188,19 +179,5 @@           picture_style="true"           top="5"           width="18" /> -        <button -         follows="bottom|left" -         font="SansSerifBigBold" -         height="18" -         image_selected="Favorite_Star_Active" -         image_disabled="Favorite_Star_Off" -         image_unselected="Favorite_Star_Press" -         layout="topleft" -         left_pad="5" -         name="star_btn" -         picture_style="true" -         tool_tip="" -         top_delta="0" -         width="18" />      </panel>  </panel> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml new file mode 100644 index 0000000000..b72d59524e --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<chat_history +	message_header="panel_chat_header.xml" +    message_separator="panel_chat_separator.xml" +    left_text_pad="10" +	right_text_pad="15" +    left_widget_pad="5" +	rigth_widget_pad="10" +	max_length="2147483647" +	enabled="false" +	track_bottom="true" +	name="chat_history" +	type="string" +	word_wrap="true" />
\ No newline at end of file  | 
