diff options
35 files changed, 1354 insertions, 578 deletions
diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 2f8e8fdd23..b14e66b915 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -107,6 +107,7 @@ public:  	std::string			getLabel() const;  	void				setFont( const LLFontGL* font ) { mFont = font; } +	const LLFontGL*		getFont() { return mFont; }  	virtual void		setControlName(const std::string& control_name, LLView* context); diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 19f203b80c..8de3a8a96f 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -94,6 +94,9 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*  	item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));  	item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); +	// Children don't accept the focus +	item->setTabStop(false); +  	rearrangeItems();  	notifyParentItemsRectChanged();  	return true; @@ -282,6 +285,9 @@ void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/)  	{  		onCommit();  	} + +	// Stretch selected items rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));  }  void LLFlatListView::setNoItemsCommentText(const std::string& comment_text) @@ -381,8 +387,34 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)  	//we don't need to stretch in vertical direction on reshaping by a parent  	//no bottom following!  	mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + +	LLViewBorder::Params params; +	params.name("scroll border"); +	params.rect(getSelectedItemsRect()); +	params.visible(false); +	params.bevel_style(LLViewBorder::BEVEL_IN); +	mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params); +	mItemsPanel->addChild( mSelectedItemsBorder );  }; +// virtual +void LLFlatListView::draw() +{ +	// Highlight border if a child of this container has keyboard focus +	if( mSelectedItemsBorder->getVisible() ) +	{ +		mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() ); +	} +	LLScrollContainer::draw(); +} + +// virtual +BOOL LLFlatListView::postBuild() +{ +	setTabStop(true); +	return LLScrollContainer::postBuild(); +} +  void LLFlatListView::rearrangeItems()  {  	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); @@ -444,6 +476,9 @@ void LLFlatListView::rearrangeItems()  		// move top for next item in list  		item_new_top -= (rc.getHeight() + mItemPad);  	} + +	// Stretch selected items rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));  }  void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) @@ -473,6 +508,64 @@ void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask)  	onItemMouseClick(item_pair, mask);  } +BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask) +{ +	BOOL reset_selection = (mask != MASK_SHIFT); +	BOOL handled = FALSE; +	switch (key) +	{ +		case KEY_RETURN: +		{ +			if (mSelectedItemPairs.size() && mask == MASK_NONE) +			{ +				mOnReturnSignal(this, getValue()); +				handled = TRUE; +			} +			break; +		} +		case KEY_UP: +		{ +			if ( !selectNextItemPair(true, reset_selection) && reset_selection) +			{ +				// If case we are in accordion tab notify parent to go to the previous accordion +				notifyParent(LLSD().insert("action","select_prev")); +			} +			break; +		} +		case KEY_DOWN: +		{ +			if ( !selectNextItemPair(false, reset_selection) && reset_selection) +			{ +				// If case we are in accordion tab notify parent to go to the next accordion +				notifyParent(LLSD().insert("action","select_next")); +			} +			break; +		} +		case 'A': +		{ +			if(MASK_CONTROL & mask) +			{ +				selectAll(); +				handled = TRUE; +			} +			break; +		} +		default: +			break; +	} + +	if ( key == KEY_UP || key == KEY_DOWN ) +	{ +		LLRect selcted_rect = getLastSelectedItemRect().stretch(1); +		LLRect visible_rect = getVisibleContentRect(); +		if ( !visible_rect.contains (selcted_rect) ) +			scrollToShowRect(selcted_rect); +		handled = TRUE; +	} + +	return handled ? handled : LLScrollContainer::handleKeyHere(key, mask); +} +  LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const  {  	llassert(item); @@ -552,6 +645,143 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)  		onCommit();  	} +	setFocus(TRUE); + +	// Stretch selected items rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1)); + +	return true; +} + +LLRect LLFlatListView::getLastSelectedItemRect() +{ +	if (!mSelectedItemPairs.size()) +	{ +		return LLRect::null; +	} + +	return mSelectedItemPairs.back()->first->getRect(); +} + +LLRect LLFlatListView::getSelectedItemsRect() +{ +	if (!mSelectedItemPairs.size()) +	{ +		return LLRect::null; +	} +	LLRect rc = getLastSelectedItemRect(); +	for ( pairs_const_iterator_t +			  it = mSelectedItemPairs.begin(), +			  it_end = mSelectedItemPairs.end(); +		  it != it_end; ++it ) +	{ +		rc.unionWith((*it)->first->getRect()); +	} +	return rc; +} + +// virtual +bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selection) +{ +	// No items - no actions! +	if ( !mItemPairs.size() ) +		return false; + +	item_pair_t* cur_sel_pair = NULL; +	item_pair_t* to_sel_pair = NULL; + +	if ( mSelectedItemPairs.size() ) +	{ +		// Take the last selected pair +		cur_sel_pair = mSelectedItemPairs.back(); +	} +	else +	{ +		// If there weren't selected items then choose the first one bases on given direction +		cur_sel_pair = (is_up_direction) ? mItemPairs.back() : mItemPairs.front(); +		// Force selection to first item +		to_sel_pair = cur_sel_pair; +	} + +	// Bases on given direction choose next item to select +	if ( is_up_direction ) +	{ +		// Find current selected item position in mItemPairs list +		pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair); + +		for (;++sel_it != mItemPairs.rend();) +		{ +			// skip invisible items +			if ( (*sel_it)->first->getVisible() ) +			{ +				to_sel_pair = *sel_it; +				break; +			} +		} +	} +	else +	{ +		// Find current selected item position in mItemPairs list +		pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair); + +		for (;++sel_it != mItemPairs.end();) +		{ +			// skip invisible items +			if ( (*sel_it)->first->getVisible() ) +			{ +				to_sel_pair = *sel_it; +				break; +			} +		} +	} + +	if ( to_sel_pair ) +	{ +		bool select = true; + +		if ( reset_selection ) +		{ +			// Reset current selection if we were asked about it +			resetSelection(); +		} +		else +		{ +			// If item already selected and no reset request than we should deselect last selected item. +			select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair)); +		} + +		// Select/Deselect next item +		selectItemPair(select ? to_sel_pair : cur_sel_pair, select); + +		return true; +	} +	return false; +} + +bool LLFlatListView::selectAll() +{ +	if (!mAllowSelection) +		return false; + +	mSelectedItemPairs.clear(); + +	for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it) +	{ +		item_pair_t* item_pair = *it; +		mSelectedItemPairs.push_back(item_pair); +		//a way of notifying panel of selection state changes +		LLPanel* item = item_pair->first; +		item->setValue(SELECTED_EVENT); +	} + +	if (mCommitOnSelectionChange) +	{ +		onCommit(); +	} + +	// Stretch selected items rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1)); +  	return true;  } @@ -670,4 +900,15 @@ void LLFlatListView::getValues(std::vector<LLSD>& values) const  	}  } +// virtual +void LLFlatListView::onFocusReceived() +{ +	mSelectedItemsBorder->setVisible(TRUE); +} +// virtual +void LLFlatListView::onFocusLost() +{ +	mSelectedItemsBorder->setVisible(FALSE); +} +  //EOF diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 97772bc677..eac947a0d7 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -113,6 +113,10 @@ public:  	virtual ~LLFlatListView() { clear(); }; +	/** +	 * Connects callback to signal called when Return key is pressed. +	 */ +	boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); }  	/** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */  	virtual void reshape(S32 width, S32 height, BOOL called_from_parent  = TRUE); @@ -318,6 +322,10 @@ protected:  	virtual bool selectItemPair(item_pair_t* item_pair, bool select); +	virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection); + +	virtual bool selectAll(); +  	virtual bool isSelected(item_pair_t* item_pair) const;  	virtual bool removeItemPair(item_pair_t* item_pair); @@ -331,6 +339,19 @@ protected:  	 */  	void notifyParentItemsRectChanged(); +	virtual BOOL handleKeyHere(KEY key, MASK mask); + +	virtual BOOL postBuild(); + +	virtual void onFocusReceived(); + +	virtual void onFocusLost(); + +	virtual void draw(); + +	LLRect getLastSelectedItemRect(); + +	LLRect getSelectedItemsRect();  private: @@ -381,6 +402,10 @@ private:  	LLRect mPrevNotifyParentRect;  	LLTextBox* mNoItemsCommentTextbox; + +	LLViewBorder* mSelectedItemsBorder; + +	commit_signal_t	mOnReturnSignal;  };  #endif diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index 304ac64f31..a7cf9be277 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -143,6 +143,12 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)  		if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )  		{ +			// undock floater when user resize it +			if (((LLFloater*)getParent())->isDocked()) +			{ +				((LLFloater*)getParent())->setDocked(false, false); +			} +  			// Resize the parent  			LLRect orig_rect = mResizingView->getRect();  			LLRect scaled_rect = orig_rect; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 7985ccc2a1..c4f0fa53a7 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -48,6 +48,7 @@  LLBottomTray::LLBottomTray(const LLSD&)  :	mChicletPanel(NULL),  	mSysWell(NULL), +	mSpeakPanel(NULL),  	mSpeakBtn(NULL),  	mNearbyChatBar(NULL),  	mToolbarStack(NULL) @@ -304,6 +305,7 @@ BOOL LLBottomTray::postBuild()  	mSnapshotPanel = getChild<LLPanel>("snapshot_panel");  	setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4)); +	mSpeakPanel = getChild<LLPanel>("speak_panel");  	mSpeakBtn = getChild<LLSpeakButton>("talk");  	// Speak button should be initially disabled because @@ -320,6 +322,7 @@ BOOL LLBottomTray::postBuild()  	mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();  	mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();  	mObjectDefaultWidthMap[RS_BUTTON_CAMERA]   = mCamPanel->getRect().getWidth(); +	mObjectDefaultWidthMap[RS_BUTTON_SPEAK]	   = mSpeakPanel->getRect().getWidth();  	return TRUE;  } @@ -476,7 +479,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width)  	S32 buttons_freed_width = 0;  	if (still_should_be_processed)  	{ -		processShrinkButtons(&delta_width); +		processShrinkButtons(&delta_width, &buttons_freed_width);  		if (delta_width < 0)  		{ @@ -532,38 +535,43 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)  	const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;  	// how many room we have to show hidden buttons -	S32 available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet; -	S32 buttons_required_width = 0; //How many room will take shown buttons +	S32 total_available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet; +	lldebugs << "Processing extending, available width:" +		<< ", chatbar - " << chatbar_available_shrink_width +		<< ", chiclets - " << available_width_chiclet +		<< ", total - " << total_available_width +		<< llendl; + +	S32 available_width = total_available_width;  	if (available_width > 0)  	{ -		lldebugs << "Trying to process: RS_BUTTON_GESTURES" << llendl; -		processShowButton(RS_BUTTON_GESTURES, &available_width, &buttons_required_width); +		processShowButton(RS_BUTTON_GESTURES, &available_width);  	}  	if (available_width > 0)  	{ -		lldebugs << "Trying to process: RS_BUTTON_MOVEMENT" << llendl; -		processShowButton(RS_BUTTON_MOVEMENT, &available_width, &buttons_required_width); +		processShowButton(RS_BUTTON_MOVEMENT, &available_width);  	}  	if (available_width > 0)  	{ -		lldebugs << "Trying to process: RS_BUTTON_CAMERA" << llendl; -		processShowButton(RS_BUTTON_CAMERA, &available_width, &buttons_required_width); +		processShowButton(RS_BUTTON_CAMERA, &available_width);  	}  	if (available_width > 0)  	{ -		lldebugs << "Trying to process: RS_BUTTON_SNAPSHOT" << llendl; -		processShowButton(RS_BUTTON_SNAPSHOT, &available_width, &buttons_required_width); +		processShowButton(RS_BUTTON_SNAPSHOT, &available_width);  	} -	// if we have to show some buttons but width increasing is not enough... -	if (buttons_required_width > 0 && delta_width < buttons_required_width) +	processExtendButtons(&available_width); + +	// if we have to show/extend some buttons but resized delta width is not enough... +	S32 processed_width = total_available_width - available_width; +	if (processed_width > delta_width)  	{  		// ... let's shrink nearby chat & chiclet panels -		S32 required_to_process_width = buttons_required_width; +		S32 required_to_process_width = processed_width;  		// 1. use delta width of resizing  		required_to_process_width -= delta_width; @@ -593,9 +601,8 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)  	}  	// shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels -	delta_width -= buttons_required_width; +	delta_width -= processed_width; -	processExtendButtons(&delta_width);  	// how many space can nearby chatbar take?  	S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth(); @@ -603,13 +610,21 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)  	{  		S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_;  		S32 delta_panel = llmin(delta_width, delta_panel_max); +		lldebugs << "Unprocesed delta width: " << delta_width +			<< ", can be applied to chatbar: " << delta_panel_max +			<< ", will be applied: " << delta_panel +			<< llendl; +  		delta_width -= delta_panel_max;  		mNearbyChatBar->reshape(chatbar_panel_width_ + delta_panel, mNearbyChatBar->getRect().getHeight()); +		log(mNearbyChatBar, "applied unprocessed delta width");  	}  } -bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width) +bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width)  { +	lldebugs << "Trying to show object type: " << shown_object_type << llendl; +  	LLPanel* panel = mStateProcessedObjectMap[shown_object_type];  	if (NULL == panel)  	{ @@ -625,12 +640,11 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa  		if (can_be_shown)  		{  			*available_width -= required_width; -			*buttons_required_width += required_width;  			setTrayButtonVisible(shown_object_type, true); -			lldebugs << "processing object type: " << shown_object_type -				<< ", buttons_required_width: " << *buttons_required_width +			lldebugs << "processed object type: " << shown_object_type +				<< ", rest available width: " << *available_width  				<< llendl;  			mResizeState &= ~shown_object_type;  		} @@ -640,6 +654,8 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa  void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width)  { +	lldebugs << "Trying to hide object type: " << processed_object_type << llendl; +  	LLPanel* panel = mStateProcessedObjectMap[processed_object_type];  	if (NULL == panel)  	{ @@ -666,7 +682,7 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* re  	}  } -void LLBottomTray::processShrinkButtons(S32* required_width) +void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_width)  {  	processShrinkButton(RS_BUTTON_CAMERA, required_width); @@ -678,9 +694,44 @@ void LLBottomTray::processShrinkButtons(S32* required_width)  	{  		processShrinkButton(RS_BUTTON_GESTURES, required_width);  	} +	if (*required_width < 0) +	{ + +		S32 panel_min_width = 0; +		std::string panel_name = mSpeakPanel->getName(); +		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL); +		if (!success) +		{ +			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl; +		} +		else +		{ +			// +			mSpeakBtn->setLabelVisible(false); +			S32 panel_width = mSpeakPanel->getRect().getWidth(); +			S32 possible_shrink_width = panel_width - panel_min_width; + +			if (possible_shrink_width > 0) +			{ +				mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight()); + +				*required_width += possible_shrink_width; + +				if (*required_width > 0) +				{ +					*buttons_freed_width += *required_width; +				} + +				lldebugs << "Shrunk panel: " << panel_name +					<< ", shrunk width: " << possible_shrink_width +					<< ", rest width to process: " << *required_width +					<< llendl; +			} +		} +	}  } -void LLBottomTray::processShrinkButton(EResizeState processed_object_type, /*const std::string& panel_name, */S32* required_width) +void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32* required_width)  {  	LLPanel* panel = mStateProcessedObjectMap[processed_object_type];  	if (NULL == panel) @@ -729,6 +780,9 @@ void LLBottomTray::processShrinkButton(EResizeState processed_object_type, /*con  void LLBottomTray::processExtendButtons(S32* available_width)  { +	// do not allow extending any buttons if we have some buttons hidden +	if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return; +  	processExtendButton(RS_BUTTON_GESTURES, available_width);  	if (*available_width > 0) @@ -739,6 +793,25 @@ void LLBottomTray::processExtendButtons(S32* available_width)  	{  		processExtendButton(RS_BUTTON_MOVEMENT, available_width);  	} +	if (*available_width > 0) +	{ +		S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK]; +		S32 panel_width = mSpeakPanel->getRect().getWidth(); +		S32 possible_extend_width = panel_max_width - panel_width; +		if (possible_extend_width > 0 && possible_extend_width <= *available_width) +		{ +			mSpeakBtn->setLabelVisible(true); +			mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight()); +			log(mSpeakBtn, "speak button is extended"); + +			*available_width -= possible_extend_width; + +			lldebugs << "Extending panel: " << mSpeakPanel->getName() +				<< ", extended width: " << possible_extend_width +				<< ", rest width to process: " << *available_width +				<< llendl; +		} +	}  }  void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width) diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 97bcc23403..7640cdcf9d 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -98,12 +98,18 @@ private:  		, RS_BUTTON_MOVEMENT	= 0x0010  		, RS_BUTTON_GESTURES	= 0x0020  		, RS_BUTTON_SPEAK		= 0x0040 + +		/** +		 * Specifies buttons which can be hidden when bottom tray is shrunk. +		 * They are: Gestures, Movement (Move), Camera (View), Snapshot +		 */ +		, RS_BUTTONS_CAN_BE_HIDDEN = RS_BUTTON_SNAPSHOT | RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES  	}EResizeState;  	S32 processWidthDecreased(S32 delta_width);  	void processWidthIncreased(S32 delta_width);  	void log(LLView* panel, const std::string& descr); -	bool processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width); +	bool processShowButton(EResizeState shown_object_type, S32* available_width);  	void processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width);  	/** @@ -112,7 +118,7 @@ private:  	 * @param - required_width - width which buttons can use to be shrunk. It is a negative value.  	 * It is increased on the value processed by buttons.  	 */ -	void processShrinkButtons(S32* required_width); +	void processShrinkButtons(S32* required_width, S32* buttons_freed_width);  	void processShrinkButton(EResizeState processed_object_type, S32* required_width);  	/** @@ -175,6 +181,7 @@ protected:  	LLChicletPanel* 	mChicletPanel;  	LLNotificationChiclet* 	mSysWell; +	LLPanel*			mSpeakPanel;  	LLSpeakButton* 		mSpeakBtn;  	LLNearbyChatBar*	mNearbyChatBar;  	LLLayoutStack*		mToolbarStack; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 9845664c74..6a5877f673 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1,34 +1,34 @@  /**  -* @file llchiclet.cpp -* @brief LLChiclet class implementation -* -* $LicenseInfo:firstyear=2002&license=viewergpl$ -*  -* Copyright (c) 2002-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$ -*/ + * @file llchiclet.cpp + * @brief LLChiclet class implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-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" // must be first include  #include "llchiclet.h" @@ -922,34 +922,45 @@ void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id)  	s_previous_active_voice_session_id = session_id;  } -S32 LLChicletPanel::calcChickletPanleWidth() -{ -	S32 res = 0; - -	for (chiclet_list_t::iterator it = mChicletList.begin(); it -			!= mChicletList.end(); it++) -	{ -		res = (*it)->getRect().getWidth() + getChicletPadding(); -	} -	return res; -} -  bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)  {  	if(mScrollArea->addChild(chiclet))  	{ -		// chicklets should be aligned to right edge of scroll panel -		S32 offset = 0; +		// chiclets should be aligned to right edge of scroll panel +		S32 left_shift = 0;  		if (!canScrollLeft())  		{ -			offset = mScrollArea->getRect().getWidth() -					- chiclet->getRect().getWidth() - calcChickletPanleWidth(); +			// init left shift for the first chiclet in the list... +			if (mChicletList.empty()) +			{ +				// ...start from the right border of the scroll area for the first added chiclet  +				left_shift = mScrollArea->getRect().getWidth(); +			} +			else +			{ +				// ... start from the left border of the first chiclet minus padding +				left_shift = getChiclet(0)->getRect().mLeft - getChicletPadding(); +			} + +			// take into account width of the being added chiclet +			left_shift -= chiclet->getRequiredRect().getWidth(); + +			// if we overflow the scroll area we do not need to shift chiclets +			if (left_shift < 0) +			{ +				left_shift = 0; +			}  		}  		mChicletList.insert(mChicletList.begin() + index, chiclet); -		getChiclet(0)->translate(offset, 0); +		// shift first chiclet to place it in correct position.  +		// rest ones will be placed in arrange() +		if (!canScrollLeft()) +		{ +			getChiclet(0)->translate(left_shift - getChiclet(0)->getRect().mLeft, 0); +		}  		chiclet->setLeftButtonClickCallback(boost::bind(&LLChicletPanel::onChicletClick, this, _1, _2));  		chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index)); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index bb5dc1e550..03935d21a6 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -1,34 +1,34 @@  /**  -* @file llchiclet.h -* @brief LLChiclet class header file -* -* $LicenseInfo:firstyear=2002&license=viewergpl$ -*  -* Copyright (c) 2002-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$ -*/ + * @file llchiclet.h + * @brief LLChiclet class header file + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-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_LLCHICLET_H  #define LL_LLCHICLET_H @@ -44,9 +44,9 @@ class LLVoiceControlPanel;  class LLMenuGL;  class LLIMFloater; -/* +/**   * Class for displaying amount of messages/notifications(unread). -*/ + */  class LLChicletNotificationCounterCtrl : public LLTextBox  {  public: @@ -57,30 +57,30 @@ public:  		{};  	}; -	/* +	/**  	 * Sets number of notifications -	*/ +	 */  	virtual void setCounter(S32 counter); -	/* +	/**  	 * Returns number of notifications -	*/ +	 */  	virtual S32 getCounter() const { return mCounter; } -	/* +	/**  	 * Returns width, required to display amount of notifications in text form.  	 * Width is the only valid value. -	*/ +	 */  	/*virtual*/ LLRect getRequiredRect(); -	/* +	/**  	 * Sets number of notifications using LLSD -	*/ +	 */  	/*virtual*/ void setValue(const LLSD& value); -	/* +	/**  	 * Returns number of notifications wrapped in LLSD -	*/ +	 */  	/*virtual*/ LLSD getValue() const;  protected: @@ -94,9 +94,9 @@ private:  	S32 mInitialWidth;  }; -/* +/**   * Class for displaying avatar's icon in P2P chiclet. -*/ + */  class LLChicletAvatarIconCtrl : public LLAvatarIconCtrl  {  public: @@ -147,9 +147,9 @@ protected:  	std::string mDefaultIcon;  }; -/* +/**   * Class for displaying of speaker's voice indicator  -*/ + */  class LLChicletSpeakerCtrl : public LLOutputMonitorCtrl  {  public: @@ -164,7 +164,7 @@ protected:  	friend class LLUICtrlFactory;  }; -/* +/**   * Base class for all chiclets.   */  class LLChiclet : public LLUICtrl @@ -180,59 +180,59 @@ public:  	/*virtual*/ ~LLChiclet(); -	/* +	/**  	 * Associates chat session id with chiclet. -	*/ +	 */  	virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; } -	/* +	/**  	 * Returns associated chat session. -	*/ +	 */  	virtual const LLUUID& getSessionId() const { return mSessionId; } -	/* +	/**  	 * Sets number of unread notifications. -	*/ +	 */  	virtual void setCounter(S32 counter) = 0; -	/* +	/**  	 * Returns number of unread notifications. -	*/ +	 */  	virtual S32 getCounter() = 0; -	/* +	/**  	 * Sets show counter state. -	*/ +	 */  	virtual void setShowCounter(bool show) { mShowCounter = show; } -	/* +	/**  	 * Returns show counter state. -	*/ +	 */  	virtual bool getShowCounter() {return mShowCounter;}; -	/* +	/**  	 * Connects chiclet clicked event with callback. -	*/ +	 */  	/*virtual*/ boost::signals2::connection setLeftButtonClickCallback(  		const commit_callback_t& cb);  	typedef boost::function<void (LLChiclet* ctrl, const LLSD& param)>   		chiclet_size_changed_callback_t; -	/* +	/**  	 * Connects chiclets size changed event with callback. -	*/ +	 */  	virtual boost::signals2::connection setChicletSizeChangedCallback(  		const chiclet_size_changed_callback_t& cb); -	/* +	/**  	 * Sets IM Session id using LLSD -	*/ +	 */  	/*virtual*/ LLSD getValue() const; -	/* +	/**  	 * Returns IM Session id using LLSD -	*/ +	 */  	/*virtual*/ void setValue(const LLSD& value);  protected: @@ -240,14 +240,14 @@ protected:  	friend class LLUICtrlFactory;  	LLChiclet(const Params& p); -	/* +	/**  	 * Notifies subscribers about click on chiclet. -	*/ +	 */  	/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); -	/* +	/**  	 * Notifies subscribers about chiclet size changed event. -	*/ +	 */  	virtual void onChicletSizeChanged();  private: @@ -263,11 +263,11 @@ private:  }; -/* -* Base class for Instant Message chiclets. -* IMChiclet displays icon, number of unread messages(optional) -* and voice chat status(optional). -*/ +/** + * Base class for Instant Message chiclets. + * IMChiclet displays icon, number of unread messages(optional) + * and voice chat status(optional). + */  class LLIMChiclet : public LLChiclet  {  public: @@ -288,50 +288,50 @@ public:  	/*virtual*/ ~LLIMChiclet() {}; -	/* +	/**  	 * Sets IM session name. This name will be displayed in chiclet tooltip. -	*/ +	 */  	virtual void setIMSessionName(const std::string& name) { setToolTip(name); } -	/* +	/**  	 * Sets id of person/group user is chatting with.  	 * Session id should be set before calling this -	*/ +	 */  	virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; } -	/* +	/**  	 * Gets id of person/group user is chatting with.  	 */  	virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; } -	/* -	* Init Speaker Control with speaker's ID -	*/ +	/** +	 * Init Speaker Control with speaker's ID +	 */  	virtual void initSpeakerControl(); -	/* +	/**  	 * set status (Shows/Hide) for voice control. -	*/ +	 */  	virtual void setShowSpeaker(bool show); -	/* +	/**  	 * Returns voice chat status control visibility. -	*/ +	 */  	virtual bool getShowSpeaker() {return mShowSpeaker;}; -	/* -	* Shows/Hides for voice control for a chiclet. -	*/ +	/** +	 * Shows/Hides for voice control for a chiclet. +	 */  	virtual void toggleSpeakerControl(); -	/* -	* Shows/hides overlay icon concerning new unread messages. -	*/ +	/** +	 * Shows/hides overlay icon concerning new unread messages. +	 */  	virtual void setShowNewMessagesIcon(bool show); -	/* -	* Returns visibility of overlay icon concerning new unread messages. -	*/ +	/** +	 * Returns visibility of overlay icon concerning new unread messages. +	 */  	virtual bool getShowNewMessagesIcon();  	virtual void draw(); @@ -418,45 +418,45 @@ public:  	/* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id); -	/* -	* Sets number of unread messages. Will update chiclet's width if number text  -	* exceeds size of counter and notify it's parent about size change. -	*/ +	/** +	 * Sets number of unread messages. Will update chiclet's width if number text  +	 * exceeds size of counter and notify it's parent about size change. +	 */  	/*virtual*/ void setCounter(S32); -	/* -	* Init Speaker Control with speaker's ID -	*/ +	/** +	 * Init Speaker Control with speaker's ID +	 */  	/*virtual*/ void initSpeakerControl(); -	/* -	* Returns number of unread messages. -	*/ +	/** +	 * Returns number of unread messages. +	 */  	/*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }  protected:  	LLIMP2PChiclet(const Params& p);  	friend class LLUICtrlFactory; -	/* -	* Creates chiclet popup menu. Will create P2P or Group IM Chat menu  -	* based on other participant's id. -	*/ +	/** +	 * Creates chiclet popup menu. Will create P2P or Group IM Chat menu  +	 * based on other participant's id. +	 */  	virtual void createPopupMenu(); -	/* -	* Processes clicks on chiclet popup menu. -	*/ +	/** +	 * Processes clicks on chiclet popup menu. +	 */  	virtual void onMenuItemClicked(const LLSD& user_data); -	/* -	* Displays popup menu. -	*/ +	/** +	 * Displays popup menu. +	 */  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); -	/*  -	* Enables/disables menus based on relationship with other participant. -	*/ +	/**  +	 * Enables/disables menus based on relationship with other participant. +	 */  	virtual void updateMenuItems();  private: @@ -492,39 +492,39 @@ public:  	 */  	/*virtual*/ void setSessionId(const LLUUID& session_id); -	/* -	* Sets number of unread messages. Will update chiclet's width if number text  -	* exceeds size of counter and notify it's parent about size change. -	*/ +	/** +	 * Sets number of unread messages. Will update chiclet's width if number text  +	 * exceeds size of counter and notify it's parent about size change. +	 */  	/*virtual*/ void setCounter(S32); -	/* -	* Keep Speaker Control with actual speaker's ID -	*/ +	/** +	 * Keep Speaker Control with actual speaker's ID +	 */  	/*virtual*/ void draw(); -	/* -	* Init Speaker Control with speaker's ID -	*/ +	/** +	 * Init Speaker Control with speaker's ID +	 */  	/*virtual*/ void initSpeakerControl(); -	/* -	* Returns number of unread messages. -	*/ +	/** +	 * Returns number of unread messages. +	 */  	/*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }  protected:  	LLAdHocChiclet(const Params& p);  	friend class LLUICtrlFactory; -	/* -	* Displays popup menu. -	*/ +	/** +	 * Displays popup menu. +	 */  	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); -	/* -	* Finds a current speaker and resets the SpeakerControl with speaker's ID -	*/ +	/** +	 * Finds a current speaker and resets the SpeakerControl with speaker's ID +	 */  	/*virtual*/ void switchToCurrentSpeaker();  private: @@ -559,9 +559,9 @@ public:  	 */  	/*virtual*/ void setSessionId(const LLUUID& session_id); -	/* -	* Keep Speaker Control with actual speaker's ID -	*/ +	/** +	 * Keep Speaker Control with actual speaker's ID +	 */  	/*virtual*/ void draw();  	/** @@ -570,20 +570,20 @@ public:  	 */  	/*virtual*/ void changed(LLGroupChange gc); -	/* -	* Sets number of unread messages. Will update chiclet's width if number text  -	* exceeds size of counter and notify it's parent about size change. -	*/ +	/** +	 * Sets number of unread messages. Will update chiclet's width if number text  +	 * exceeds size of counter and notify it's parent about size change. +	 */  	/*virtual*/ void setCounter(S32); -	/* -	* Init Speaker Control with speaker's ID -	*/ +	/** +	 * Init Speaker Control with speaker's ID +	 */  	/*virtual*/ void initSpeakerControl(); -	/* -	* Returns number of unread messages. -	*/ +	/** +	 * Returns number of unread messages. +	 */  	/*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }  	~LLIMGroupChiclet(); @@ -592,25 +592,25 @@ protected:  	LLIMGroupChiclet(const Params& p);  	friend class LLUICtrlFactory; -	/* -	* Finds a current speaker and resets the SpeakerControl with speaker's ID -	*/ +	/** +	 * Finds a current speaker and resets the SpeakerControl with speaker's ID +	 */  	/*virtual*/ void switchToCurrentSpeaker(); -	/* -	* Creates chiclet popup menu. Will create P2P or Group IM Chat menu  -	* based on other participant's id. -	*/ +	/** +	 * Creates chiclet popup menu. Will create P2P or Group IM Chat menu  +	 * based on other participant's id. +	 */  	virtual void createPopupMenu(); -	/* -	* Processes clicks on chiclet popup menu. -	*/ +	/** +	 * Processes clicks on chiclet popup menu. +	 */  	virtual void onMenuItemClicked(const LLSD& user_data); -	/* -	* Displays popup menu. -	*/ +	/** +	 * Displays popup menu. +	 */  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);  private: @@ -619,10 +619,10 @@ private:  	LLMenuGL* mPopupMenu;  }; -/* +/**   * Implements notification chiclet. Used to display total amount of unread messages    * across all IM sessions, total amount of system notifications. -*/ + */  class LLNotificationChiclet : public LLChiclet  {  public: @@ -666,10 +666,10 @@ protected:  	S32 mCounter;  }; -/* +/**   * Storage class for all IM chiclets. Provides mechanism to display,    * scroll, create, remove chiclets. -*/ + */  class LLChicletPanel : public LLPanel  {  public: @@ -686,62 +686,62 @@ public:  	virtual ~LLChicletPanel(); -	/* +	/**  	 * Creates chiclet and adds it to chiclet list at specified index. -	*/ +	 */  	template<class T> T* createChiclet(const LLUUID& session_id, S32 index); -	/* +	/**  	 * Creates chiclet and adds it to chiclet list at right. -	*/ +	 */  	template<class T> T* createChiclet(const LLUUID& session_id); -	/* +	/**  	 * Returns pointer to chiclet of specified type at specified index. -	*/ +	 */  	template<class T> T* getChiclet(S32 index); -	/* +	/**  	 * Returns pointer to LLChiclet at specified index. -	*/ +	 */  	LLChiclet* getChiclet(S32 index) { return getChiclet<LLChiclet>(index); } -	/* +	/**  	 * Searches a chiclet using IM session id. -	*/ +	 */  	template<class T> T* findChiclet(const LLUUID& im_session_id); -	/* +	/**  	 * Returns number of hosted chiclets. -	*/ +	 */  	S32 getChicletCount() {return mChicletList.size();}; -	/* +	/**  	 * Returns index of chiclet in list. -	*/ +	 */  	S32 getChicletIndex(const LLChiclet* chiclet); -	/* +	/**  	 * Removes chiclet by index. -	*/ +	 */  	void removeChiclet(S32 index); -	/* +	/**  	 * Removes chiclet by pointer. -	*/ +	 */  	void removeChiclet(LLChiclet* chiclet); -	/* +	/**  	 * Removes chiclet by IM session id. -	*/ +	 */  	void removeChiclet(const LLUUID& im_session_id); -	/* +	/**  	 * Removes all chiclets. -	*/ +	 */  	void removeAll(); -	/* +	/**  	 * Scrolls the panel to the specified chiclet  	 */  	void scrollToChiclet(const LLChiclet* chiclet); @@ -751,14 +751,14 @@ public:  	/*virtual*/ BOOL postBuild(); -	/* -	* Handler for the Voice Client's signal. Finds a corresponding chiclet and toggles its SpeakerControl -	*/ +	/** +	 * Handler for the Voice Client's signal. Finds a corresponding chiclet and toggles its SpeakerControl +	 */  	void onCurrentVoiceChannelChanged(const LLUUID& session_id); -	/* +	/**  	 * Reshapes controls and rearranges chiclets if needed. -	*/ +	 */  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE );  	/*virtual*/ void draw(); @@ -769,100 +769,107 @@ protected:  	LLChicletPanel(const Params&p);  	friend class LLUICtrlFactory; -	S32 calcChickletPanleWidth(); - -	/* -	 * Adds chiclet to list and rearranges all chiclets. -	*/ +	/** +	 * Adds chiclet to list and rearranges all chiclets.  +	 * They should be right aligned, most recent right. See EXT-1293 +	 * +	 * It calculates position of the first chiclet in the list. Other chiclets are placed in arrange(). +	 * +	 * @see arrange() +	 */  	bool addChiclet(LLChiclet*, S32 index); -	/* -	 * Arranges chiclets. -	*/ +	/** +	 * Arranges chiclets to have them in correct positions. +	 * +	 * Method bases on assumption that first chiclet has correct rect and starts from the its position. +	 * +	 * @see addChiclet() +	 */  	void arrange(); -	/* +	/**  	 * Returns true if chiclets can be scrolled right. -	*/ +	 */  	bool canScrollRight(); -	/* -	* Returns true if chiclets can be scrolled left. -	*/ +	/** +	 * Returns true if chiclets can be scrolled left. +	 */  	bool canScrollLeft(); -	/* -	* Shows or hides chiclet scroll buttons if chiclets can or can not be scrolled. -	*/ +	/** +	 * Shows or hides chiclet scroll buttons if chiclets can or can not be scrolled. +	 */  	void showScrollButtonsIfNeeded(); -	/* +	/**  	 * Shifts chiclets left or right. -	*/ +	 */  	void shiftChiclets(S32 offset, S32 start_index = 0); -	/* +	/**  	 * Removes gaps between first chiclet and scroll area left side,  	 * last chiclet and scroll area right side. -	*/ +	 */  	void trimChiclets(); -	/* +	/**  	 * Scrolls chiclets to right or left. -	*/ +	 */  	void scroll(S32 offset); -	/* +	/**  	 * Verifies that chiclets can be scrolled left, then calls scroll() -	*/ +	 */  	void scrollLeft(); -	/* +	/**  	 * Verifies that chiclets can be scrolled right, then calls scroll() -	*/ +	 */  	void scrollRight(); -	/* +	/**  	 * Callback for left scroll button clicked -	*/ +	 */  	void onLeftScrollClick(); -	/* -	* Callback for right scroll button clicked -	*/ +	/** +	 * Callback for right scroll button clicked +	 */  	void onRightScrollClick(); -	/* -	* Callback for right scroll button held down event -	*/ +	/** +	 * Callback for right scroll button held down event +	 */  	void onLeftScrollHeldDown(); -	/* +	/**  	 * Callback for left scroll button held down event  	 */  	void onRightScrollHeldDown(); -	/* +	/**  	 * Callback for mouse wheel scrolled, calls scrollRight() or scrollLeft() -	*/ +	 */  	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); -	/* +	/**  	 * Notifies subscribers about click on chiclet.  	 * Do not place any code here, instead subscribe on event (see setChicletClickedCallback). -	*/ +	 */  	void onChicletClick(LLUICtrl*ctrl,const LLSD¶m); -	/* +	/**  	 * Callback for chiclet size changed event, rearranges chiclets. -	*/ +	 */  	void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param);  	typedef std::vector<LLChiclet*> chiclet_list_t; -	/* +	/**  	 * Removes chiclet from scroll area and chiclet list. -	*/ +	 */  	void removeChiclet(chiclet_list_t::iterator it);  	S32 getChicletPadding() { return mChicletPadding; } diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index af86274472..0f8e4c10d7 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -34,32 +34,24 @@  #include "llfloatergesture.h" -#include "lldir.h"  #include "llinventory.h" -#include "llmultigesture.h" +#include "llinventorybridge.h" +#include "llinventorymodel.h" +#include "llinventoryclipboard.h"  #include "llagent.h" -#include "llviewerwindow.h" -#include "llbutton.h" -#include "llcombobox.h" +#include "llappearancemgr.h" +#include "llclipboard.h"  #include "llgesturemgr.h" -#include "llinventorymodel.h" -#include "llinventorypanel.h" -#include "llfloaterinventory.h"  #include "llkeyboard.h" -#include "lllineeditor.h" +#include "llmenugl.h" +#include "llmultigesture.h"  #include "llpreviewgesture.h" -#include "llresizehandle.h" -#include "llscrollbar.h" -#include "llscrollcontainer.h"  #include "llscrolllistctrl.h" -#include "lltextbox.h"  #include "lltrans.h" -#include "lluictrlfactory.h"  #include "llviewergesture.h" -#include "llviewertexturelist.h" +#include "llviewermenu.h"   #include "llviewerinventory.h" -#include "llvoavatar.h"  #include "llviewercontrol.h"  BOOL item_name_precedes( LLInventoryItem* a, LLInventoryItem* b ) @@ -77,6 +69,35 @@ public:  private:  	LLFloaterGesture* mFloater;  }; +//----------------------------- +// GestureCallback +//----------------------------- + +class GestureShowCallback : public LLInventoryCallback +{ +public: +	void fire(const LLUUID &inv_item) +	{ +		LLPreviewGesture::show(inv_item, LLUUID::null); +	} +}; + +class GestureCopiedCallback : public LLInventoryCallback +{ +private: +	LLFloaterGesture* mFloater; +	 +public: +	GestureCopiedCallback(LLFloaterGesture* floater): mFloater(floater) +	{} +	void fire(const LLUUID &inv_item) +	{ +		if(mFloater) +		{ +			mFloater->addGesture(inv_item,NULL,mFloater->getChild<LLScrollListCtrl>("gesture_list")); +		} +	} +};  //---------------------------------------------------------------------------  // LLFloaterGesture @@ -86,7 +107,13 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key)  {  	mObserver = new LLFloaterGestureObserver(this);  	LLGestureManager::instance().addObserver(mObserver); -	//LLUICtrlFactory::getInstance()->buildFloater(this, "floater_gesture.xml"); + +	mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", boost::bind(&LLFloaterGesture::onActivateBtnClick, this)); +	mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this)); +	mCommitCallbackRegistrar.add("Gesture.Action.CopyPast", boost::bind(&LLFloaterGesture::onCopyPastAction, this, _2)); +	mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this)); + +	mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));  }  void LLFloaterGesture::done() @@ -151,19 +178,18 @@ BOOL LLFloaterGesture::postBuild()  	label = getTitle();  	setTitle(label); - -	getChild<LLUICtrl>("gesture_list")->setCommitCallback(boost::bind(&LLFloaterGesture::onCommitList, this)); -	getChild<LLScrollListCtrl>("gesture_list")->setDoubleClickCallback(boost::bind(&LLFloaterGesture::onClickPlay, this)); - -	getChild<LLUICtrl>("inventory_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickInventory, this)); +	mGestureList = getChild<LLScrollListCtrl>("gesture_list"); +	mGestureList->setCommitCallback(boost::bind(&LLFloaterGesture::onCommitList, this)); +	mGestureList->setDoubleClickCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));  	getChild<LLUICtrl>("edit_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickEdit, this));  	getChild<LLUICtrl>("play_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));  	getChild<LLUICtrl>("stop_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));  	getChild<LLButton>("activate_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onActivateBtnClick, this)); - +	  	getChild<LLUICtrl>("new_gesture_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickNew, this)); +	getChild<LLButton>("del_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onDeleteSelected, this));  	childSetVisible("play_btn", true);  	childSetVisible("stop_btn", false); @@ -178,14 +204,13 @@ BOOL LLFloaterGesture::postBuild()  	buildGestureList(); -	childSetFocus("gesture_list"); +	mGestureList->setFocus(TRUE); -	LLCtrlListInterface *list = getGestureList(); -	if (list) +	if (mGestureList)  	{  		const BOOL ascending = TRUE; -		list->sortByColumn(std::string("name"), ascending); -		list->selectFirstItem(); +		mGestureList->sortByColumn(std::string("name"), ascending); +		mGestureList->selectFirstItem();  	}  	// Update button labels @@ -199,18 +224,17 @@ void LLFloaterGesture::refreshAll()  {  	buildGestureList(); -	LLCtrlListInterface *list = getGestureList(); -	if (!list) return; +	if (!mGestureList) return;  	if (mSelectedID.isNull())  	{ -		list->selectFirstItem(); +		mGestureList->selectFirstItem();  	}  	else  	{ -		if (! list->setCurrentByID(mSelectedID)) +		if (! mGestureList->setCurrentByID(mSelectedID))  		{ -			list->selectFirstItem(); +			mGestureList->selectFirstItem();  		}  	} @@ -220,20 +244,16 @@ void LLFloaterGesture::refreshAll()  void LLFloaterGesture::buildGestureList()  { -	LLCtrlListInterface *list = getGestureList(); -	LLCtrlScrollInterface *scroll = childGetScrollInterface("gesture_list"); - -	if (! (list && scroll)) return; - -	LLUUID selected_item = list->getCurrentID(); +	std::vector<LLUUID> selected_items; +	getSelectedIds(selected_items);  	LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL; -	list->operateOnAll(LLCtrlListInterface::OP_DELETE); +	mGestureList->deleteAllItems();  	LLGestureManager::item_map_t::const_iterator it;  	const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();  	for (it = active_gestures.begin(); it != active_gestures.end(); ++it)  	{ -		addGesture(it->first,it->second, list); +		addGesture(it->first,it->second, mGestureList);  	}  	if (gInventory.isCategoryComplete(mGestureFolderID))  	{ @@ -249,16 +269,17 @@ void LLFloaterGesture::buildGestureList()  			if (active_gestures.find(item->getUUID()) == active_gestures.end())  			{  				// if gesture wasn't loaded yet, we can display only name -				addGesture(item->getUUID(), NULL, list); +				addGesture(item->getUUID(), NULL, mGestureList);  			}  		}  	}  	// attempt to preserve scroll position through re-builds  	// since we do re-build any time anything dirties -	if(list->selectByValue(LLSD(selected_item))) +	for(std::vector<LLUUID>::iterator it = selected_items.begin(); it != selected_items.end(); it++)  	{ -		scroll->scrollToShowSelected(); +		mGestureList->selectByID(*it);  	} +	mGestureList->scrollToShowSelected();  }  void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list ) @@ -346,33 +367,59 @@ void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gestur  	list->addElement(element, ADD_BOTTOM);  } -void LLFloaterGesture::onClickInventory() +void LLFloaterGesture::getSelectedIds(std::vector<LLUUID>& ids) +{ +	std::vector<LLScrollListItem*> items = mGestureList->getAllSelected(); +	for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++) +	{ +		ids.push_back((*it)->getUUID()); +	} +} + +bool LLFloaterGesture::isActionEnabled(const LLSD& command)  { -	LLCtrlListInterface *list = getGestureList(); -	if (!list) return; -	const LLUUID& item_id = list->getCurrentID(); +	// paste copy_uuid edit_gesture +	std::string command_name = command.asString(); +	if("paste" == command_name) +	{ +		if(!LLInventoryClipboard::instance().hasContents()) +			return false; -	LLFloaterInventory* inv = LLFloaterInventory::showAgentInventory(); -	if (!inv) return; -	inv->getPanel()->setSelection(item_id, TRUE); +		LLDynamicArray<LLUUID> ids; +		LLInventoryClipboard::instance().retrieve(ids); +		for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++) +		{ +			LLInventoryItem* item = gInventory.getItem(*it); +			 +			if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE) +			{ +				return true; +			} +		} +		return false; +	} +	else if("copy_uuid" == command_name || "edit_gesture" == command_name  +			|| "inspect" == command_name) +	{ +		return	mGestureList->getAllSelected().size() == 1; +	} +	return true;  }  void LLFloaterGesture::onClickPlay()  { -	LLCtrlListInterface *list = getGestureList(); -	if (!list) return; -	const LLUUID& item_id = list->getCurrentID(); +	const LLUUID& item_id = mGestureList->getCurrentID();  	if(item_id.isNull()) return;  	LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <<LL_ENDL;  	if(!LLGestureManager::instance().isGestureActive(item_id))  	{ -		// we need to inform server about gesture activating to be consistent with LLPreviewGesture. +		// we need to inform server about gesture activating to be consistent with LLPreviewGesture and  LLGestureComboBox.  		BOOL inform_server = TRUE;  		BOOL deactivate_similar = FALSE; +		LLGestureManager::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));  		LLGestureManager::instance().activateGestureWithAsset(item_id, gInventory.getItem(item_id)->getAssetUUID(), inform_server, deactivate_similar);  		LL_DEBUGS("Gesture")<< "Activating gesture with inventory ID: " << item_id <<LL_ENDL; -		LLGestureManager::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));  	}  	else  	{ @@ -380,15 +427,6 @@ void LLFloaterGesture::onClickPlay()  	}  } -class GestureShowCallback : public LLInventoryCallback -{ -public: -	void fire(const LLUUID &inv_item) -	{ -		LLPreviewGesture::show(inv_item, LLUUID::null); -	} -}; -  void LLFloaterGesture::onClickNew()  {  	LLPointer<LLInventoryCallback> cb = new GestureShowCallback(); @@ -399,27 +437,96 @@ void LLFloaterGesture::onClickNew()  void LLFloaterGesture::onActivateBtnClick()  { -	LLCtrlListInterface* list = getGestureList(); -	 -	LLUUID gesture_inv_id = list->getSelectedValue(); +	std::vector<LLUUID> ids; +	getSelectedIds(ids); +	if(ids.empty()) +		return; +  	LLGestureManager* gm = LLGestureManager::getInstance(); -	 -	if(gm->isGestureActive(gesture_inv_id)) +	std::vector<LLUUID>::const_iterator it = ids.begin(); +	BOOL first_gesture_state = gm->isGestureActive(*it); +	BOOL is_mixed = FALSE; +	while( ++it != ids.end() )  	{ -		gm->deactivateGesture(gesture_inv_id); +		if(first_gesture_state != gm->isGestureActive(*it)) +		{ +			is_mixed = TRUE; +			break; +		}  	} -	else +	for(std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); it++)  	{ -		gm->activateGesture(gesture_inv_id); +		if(is_mixed) +		{ +			gm->activateGesture(*it); +		} +		else +		{ +			if(first_gesture_state) +			{ +				gm->deactivateGesture(*it); +			} +			else +			{ +				gm->activateGesture(*it); +			} +		}  	}  } +void LLFloaterGesture::onCopyPastAction(const LLSD& command) +{ +	std::string command_name  = command.asString(); +	// since we select this comman inventory item had  already arrived . +	if("copy_gesture" == command_name) +	{ +		std::vector<LLUUID> ids; +		getSelectedIds(ids); +		// make sure that clopboard is empty +		LLInventoryClipboard::instance().reset(); +		for(std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++) +		{ +			LLInventoryItem* item = gInventory.getItem(*it); +			if(item  && item->getInventoryType() == LLInventoryType::IT_GESTURE) +			{ +				LLInventoryClipboard::instance().add(item->getUUID()); +			} +		} +	} +	else if ("paste" == command_name) +	{ +		LLInventoryClipboard& clipbord = LLInventoryClipboard::instance(); +		LLDynamicArray<LLUUID> ids; +		clipbord.retrieve(ids); +		if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID)) +			return; +		LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID); +		LLPointer<GestureCopiedCallback> cb = new GestureCopiedCallback(this); + +		for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++) +		{ +			LLInventoryItem* item = gInventory.getItem(*it); +			LLStringUtil::format_map_t string_args; +			string_args["[COPY_NAME]"] = item->getName(); +			if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE) +			{ +				LL_DEBUGS("Gesture")<< "Copying gesture " << item->getName() << "  "<< item->getUUID() << " into " +										<< gesture_dir->getName() << "  "<< gesture_dir->getUUID() << LL_ENDL; +				copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(),  +						gesture_dir->getUUID(), getString("copy_name", string_args), cb); +			} +		} +		clipbord.reset(); +	} +	else if ("copy_uuid" == command_name) +	{ +		gClipboard.copyFromString(utf8str_to_wstring(mGestureList->getCurrentID().asString()), mGestureList->getCurrentID()); +	} +}  void LLFloaterGesture::onClickEdit()  { -	LLCtrlListInterface *list = getGestureList(); -	if (!list) return; -	const LLUUID& item_id = list->getCurrentID(); +	const LLUUID& item_id = mGestureList->getCurrentID();  	LLInventoryItem* item = gInventory.getItem(item_id);  	if (!item) return; @@ -433,7 +540,7 @@ void LLFloaterGesture::onClickEdit()  void LLFloaterGesture::onCommitList()  { -	const LLUUID& item_id = childGetValue("gesture_list").asUUID(); +	const LLUUID& item_id = mGestureList->getCurrentID();  	mSelectedID = item_id;  	if (LLGestureManager::instance().isGesturePlaying(item_id)) @@ -447,8 +554,60 @@ void LLFloaterGesture::onCommitList()  		childSetVisible("stop_btn", false);  	}  } + +void LLFloaterGesture::onDeleteSelected() +{ +	std::vector<LLUUID> ids; +	getSelectedIds(ids); +	if(ids.empty()) +		return; + +	const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); +	LLGestureManager* gm = LLGestureManager::getInstance(); +	for(std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); it++) +	{ +		const LLUUID& selected_item = *it; +		LLInventoryItem* inv_item = gInventory.getItem(selected_item); +		if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_GESTURE) +		{ +			if(gm->isGestureActive(selected_item)) +			{ +				gm->deactivateGesture(selected_item); +			} +			LLInventoryModel::update_list_t update; +			LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1); +			update.push_back(old_folder); +			LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1); +			update.push_back(new_folder); +			gInventory.accountForUpdate(update); + +			LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item); +			new_item->setParent(trash_id); +			// no need to restamp it though it's a move into trash because +			// it's a brand new item already. +			new_item->updateParentOnServer(FALSE); +			gInventory.updateItem(new_item); +		} +	} +	gInventory.notifyObservers(); +	buildGestureList(); +} + +void LLFloaterGesture::addToCurrentOutFit() +{ +	std::vector<LLUUID> ids; +	getSelectedIds(ids); +	LLAppearanceManager* am = LLAppearanceManager::getInstance(); +	for(std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); it++) +	{ +		am->addCOFItemLink(*it); +	} +} +  void LLFloaterGesture::playGesture(LLUUID item_id)  { +	LL_DEBUGS("Gesture")<<"Playing gesture "<< item_id<<LL_ENDL; +  	if (LLGestureManager::instance().isGesturePlaying(item_id))  	{  		LLGestureManager::instance().stopGesture(item_id); diff --git a/indra/newview/llfloatergesture.h b/indra/newview/llfloatergesture.h index 50bef818da..14e132900d 100644 --- a/indra/newview/llfloatergesture.h +++ b/indra/newview/llfloatergesture.h @@ -36,11 +36,10 @@  #ifndef LL_LLFLOATERGESTURE_H  #define LL_LLFLOATERGESTURE_H +#include <vector>   #include "llfloater.h" -#include "llinventorymodel.h"  #include "llinventoryobserver.h" -#include "lldarray.h"  class LLScrollContainer;  class LLView; @@ -53,6 +52,7 @@ class LLScrollListCtrl;  class LLFloaterGestureObserver;  class LLFloaterGestureInventoryObserver;  class LLMultiGesture; +class LLMenuGL;  class LLFloaterGesture  :	public LLFloater, LLInventoryFetchDescendentsObserver @@ -65,26 +65,46 @@ public:  	virtual BOOL postBuild();  	virtual void done ();  	void refreshAll(); +	/** +	 * @brief Add new scrolllistitem into gesture_list. +	 * @param  item_id inventory id of gesture +	 * @param  gesture can be NULL , if item was not loaded yet +	 */ +	void addGesture(const LLUUID& item_id, LLMultiGesture* gesture, LLCtrlListInterface * list);  protected:  	// Reads from the gesture manager's list of active gestures  	// and puts them in this list.  	void buildGestureList(); -	void addGesture(const LLUUID& item_id, LLMultiGesture* gesture, LLCtrlListInterface * list); -	void onClickInventory(); +	void playGesture(LLUUID item_id); +private: +	void addToCurrentOutFit(); +	/** +	 * @brief  This method is using to collect selected items.  +	 * In some places gesture_list can be rebuilt by gestureObservers during  iterating data from LLScrollListCtrl::getAllSelected(). +	 * Therefore we have to copy these items to avoid viewer crash. +	 * @see LLFloaterGesture::onActivateBtnClick +	 */ +	void getSelectedIds(std::vector<LLUUID>& ids); +	bool isActionEnabled(const LLSD& command); +	/** +	 * @brief Activation rules: +	 *  According to Gesture Spec: +	 *  1. If all selected gestures are active: set to inactive +	 *  2. If all selected gestures are inactive: set to active +	 *  3. If selected gestures are in a mixed state: set all to active +	 */ +	void onActivateBtnClick();  	void onClickEdit();  	void onClickPlay();  	void onClickNew();  	void onCommitList(); -	void playGesture(LLUUID item_id); -	LLCtrlListInterface* getGestureList() const  -	{ -		return childGetListInterface("gesture_list"); -	} -	void onActivateBtnClick(); -protected: +	void onCopyPastAction(const LLSD& command); +	void onDeleteSelected(); +  	LLUUID mSelectedID;  	LLUUID mGestureFolderID; +	LLScrollListCtrl* mGestureList;  	LLFloaterGestureObserver* mObserver;  }; diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index 003afafa87..d50b68b624 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -374,22 +374,34 @@ void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_cal  bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)  { -	LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID); +	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID); +	if (NULL == item) +		return false; + +	const LLUUID& asset_id = item->getAssetUUID(); +	LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL);  	if (NULL == landmark)  		return false;  	return landmark->getGlobalPos(posGlobal);  } -LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID) +LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb)  {  	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);  	if (NULL == item)  		return NULL;  	const LLUUID& asset_id = item->getAssetUUID(); -	return gLandmarkList.getAsset(asset_id, NULL); + +	LLLandmark* landmark = gLandmarkList.getAsset(asset_id, cb); +	if (landmark) +	{ +		return landmark; +	} + +	return NULL;  }  void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID) diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h index c65b831f3e..987caf0936 100644 --- a/indra/newview/lllandmarkactions.h +++ b/indra/newview/lllandmarkactions.h @@ -35,7 +35,10 @@  #include "llinventorymodel.h" +#include "lllandmarklist.h" +  class LLLandmark; +  /**   * @brief Provides helper functions to manage landmarks   */ @@ -112,10 +115,11 @@ public:      /**       * @brief Retrieve a landmark from gLandmarkList by inventory item's id +     * If a landmark is not currently in the gLandmarkList a callback "cb" is called when it is loaded.       *        * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.       */ -    static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID); +    static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb = NULL);      /**       * @brief  Performs standard action of copying of SLURL from landmark to user's clipboard. diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 598d021703..0a595765a9 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -92,16 +92,26 @@ bool LLOfferHandler::processNotification(const LLSD& notify)  	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")  	{  		// add message to IM -		LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, notification->getPayload()["from_id"]); -		if (!LLIMMgr::instance().hasSession(session_id)) +		const std::string +				name = +						notification->getSubstitutions().has("NAME") ? notification->getSubstitutions()["NAME"] +								: notification->getSubstitutions()["[NAME]"]; + +		// don't create IM session with objects +		if (notification->getName() != "ObjectGiveItem" +				&& notification->getName() != "ObjectGiveItemUnknownUser")  		{ -			session_id = LLIMMgr::instance().addSession( -					notification->getSubstitutions()["OBJECTFROMNAME"], IM_NOTHING_SPECIAL, -					notification->getPayload()["from_id"]); +			LLUUID from_id = notification->getPayload()["from_id"]; +			LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, +					from_id); +			if (!LLIMMgr::instance().hasSession(session_id)) +			{ +				session_id = LLIMMgr::instance().addSession(name, +						IM_NOTHING_SPECIAL, from_id); +			} +			LLIMMgr::instance().addMessage(session_id, LLUUID(), name, +					notification->getMessage());  		} -		LLIMMgr::instance().addMessage(session_id, LLUUID(), -				notification->getSubstitutions()["OBJECTFROMNAME"], -				notification->getMessage());  		LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index f94a59ecef..5de7c3f851 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -352,6 +352,8 @@ void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)  	}  	LLStringUtil::replaceChar(desc, '\n', ' '); +	LLViewerInventoryItem::insertDefaultSortField(name); +  	// If no folder chosen use the "Landmarks" folder.  	LLLandmarkActions::createLandmarkHere(name, desc,  		folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index e199db37ab..10b419dfdb 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -148,20 +148,13 @@ void LLLandmarksPanel::onShowOnMap()  		llwarns << "There are no selected list. No actions are performed." << llendl;  		return;  	} -	LLLandmark* landmark = getCurSelectedLandmark(); -	if (!landmark) -		return; -	LLVector3d landmark_global_pos; -	if (!landmark->getGlobalPos(landmark_global_pos)) -		return; -	 -	LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); -	if (!landmark_global_pos.isExactlyZero() && worldmap_instance) -	{ -		worldmap_instance->trackLocation(landmark_global_pos); -		LLFloaterReg::showInstance("world_map", "center"); -	} +	// Disable the "Map" button because loading landmark can take some time. +	// During this time the button is useless. It will be enabled on callback finish +	// or upon switching to other item. +	mShowOnMapBtn->setEnabled(FALSE); + +	doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doShowOnMap, this, _1));  }  // virtual @@ -256,15 +249,18 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const  	return false;  } -LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const -{ +void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb) +{  	LLFolderViewItem* cur_item = getCurSelectedItem();  	if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)  	{  -		return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID()); +		LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb); +		if (landmark) +		{ +			cb(landmark); +		}  	} -	return NULL;  }  LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const  @@ -294,45 +290,11 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)  	// 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) -		{ -			LLPanelPickEdit* panel_pick = LLPanelPickEdit::create(); -			LLVector3d landmark_global_pos; -			landmark->getGlobalPos(landmark_global_pos); - -			// 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); -			panel_pick->onOpen(LLSD()); - -			LLPickData data; -			data.pos_global = landmark_global_pos; -			data.name = cur_item->getName(); -			data.desc = inv_item->getDescription(); -			data.snapshot_id = parcel_data.snapshot_id; -			data.parcel_id = parcel_data.parcel_id; -			panel_pick->setPickData(&data); - -			LLSD params; -			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)); -			panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, -				panel_pick, panel_places,params)); -			panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, -							panel_pick, panel_places,params)); -		} +		LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id); +		doActionOnCurSelectedLandmark(boost::bind( +				&LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data));  	}  } @@ -747,42 +709,7 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)  	}  	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;  -		} +		doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1));  	}  } @@ -931,6 +858,97 @@ void LLLandmarksPanel::updateFilteredAccordions()  	mDirtyFilter = false;  } +void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark) +{ +	LLVector3d landmark_global_pos; +	if (!landmark->getGlobalPos(landmark_global_pos)) +		return; + +	LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); +	if (!landmark_global_pos.isExactlyZero() && worldmap_instance) +	{ +		worldmap_instance->trackLocation(landmark_global_pos); +		LLFloaterReg::showInstance("world_map", "center"); +	} + +	mShowOnMapBtn->setEnabled(TRUE); +} + +void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark, +										   LLFolderViewItem* cur_item, +										   LLInventoryItem* inv_item, +										   const LLParcelData& parcel_data) +{ +	LLPanelPickEdit* panel_pick = LLPanelPickEdit::create(); +	LLVector3d landmark_global_pos; +	landmark->getGlobalPos(landmark_global_pos); + +	// 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); +	panel_pick->onOpen(LLSD()); + +	LLPickData data; +	data.pos_global = landmark_global_pos; +	data.name = cur_item->getName(); +	data.desc = inv_item->getDescription(); +	data.snapshot_id = parcel_data.snapshot_id; +	data.parcel_id = parcel_data.parcel_id; +	panel_pick->setPickData(&data); + +	LLSD params; +	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)); +	panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, +		panel_pick, panel_places,params)); +	panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this, +					panel_pick, panel_places,params)); +} + +void LLLandmarksPanel::doCreatePick(LLLandmark* landmark) +{ +	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; +	} +}  //////////////////////////////////////////////////////////////////////////  // HELPER FUNCTIONS diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index 097d79badf..777ee562d2 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -37,6 +37,7 @@  // newview  #include "llinventorymodel.h" +#include "lllandmarklist.h"  #include "llpanelplacestab.h"  #include "llpanelpick.h"  #include "llremoteparcelrequest.h" @@ -68,7 +69,7 @@ protected:  	 */  	bool isLandmarkSelected() const;  	bool isReceivedFolderSelected() const; -	LLLandmark* getCurSelectedLandmark() const; +	void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);  	LLFolderViewItem* getCurSelectedItem() const;  	void updateSortOrder(LLInventoryPanel* panel, bool byDate); @@ -127,6 +128,16 @@ private:  	 */  	void updateFilteredAccordions(); +	/** +	 * Landmark actions callbacks. Fire when a landmark is loaded from the list. +	 */ +	void doShowOnMap(LLLandmark* landmark); +	void doProcessParcelInfo(LLLandmark* landmark, +							 LLFolderViewItem* cur_item, +							 LLInventoryItem* inv_item, +							 const LLParcelData& parcel_data); +	void doCreatePick(LLLandmark* landmark); +  private:  	LLInventorySubTreePanel*	mFavoritesInventoryPanel;  	LLInventorySubTreePanel*	mLandmarksInventoryPanel; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 4dc8872557..29f7cc1851 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -536,8 +536,15 @@ BOOL LLPanelPeople::postBuild()  	mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));  	mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList)); +	// Set openning IM as default on return action for avatar lists +	mOnlineFriendList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this)); +	mAllFriendList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this)); +	mNearbyList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this)); +	mRecentList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this)); +  	mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));  	mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this)); +	mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));  	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");  	accordion_tab->setDropDownStateChangedCallback( diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 13bd059d45..4ee9cba69c 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -65,6 +65,8 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  	mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));  	mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));  	mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); +    // Set onAvatarListDoubleClicked as default on_return action. +	mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));  	mParticipantListMenu = new LLParticipantListMenu(*this);  	mAvatarList->setContextMenu(mParticipantListMenu); @@ -99,6 +101,7 @@ void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)  void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list)  { +	// NOTE(EM): Should we check if there is multiple selection and start conference if it is so?  	LLUUID clicked_id = list->getSelectedUUID();  	if (clicked_id.isNull() || clicked_id == gAgent.getID()) diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index d1cf4a0810..24505f6bd6 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -533,19 +533,7 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)  	LLTextBox* text_box = mStartUpToastPanel->getChild<LLTextBox>("toast_text"); -	std::string mStartUpFormatString; - -	if(notif_num == 1) -	{ -		mStartUpFormatString = LLTrans::getString("StartUpNotification"); -	} -	else -	{ -		mStartUpFormatString = LLTrans::getString("StartUpNotifications"); -	} -	 - -	std::string	text = llformat(mStartUpFormatString.c_str(), notif_num); +	std::string	text = LLTrans::getString("StartUpNotifications");  	toast_rect = mStartUpToastPanel->getRect();  	mStartUpToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true); diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index 51d53b2674..54f776ca6a 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -143,6 +143,27 @@ void LLSpeakButton::setShowToolTip(const std::string& msg)  	mShowBtn->setToolTip(msg);  } +void LLSpeakButton::setLabelVisible(bool visible) +{ +	static std::string label_selected = mSpeakBtn->getLabelSelected(); +	static std::string label_unselected = mSpeakBtn->getLabelUnselected(); + +	if (visible) +	{ +		mSpeakBtn->setLabelSelected(label_selected); +		mSpeakBtn->setLabelUnselected(label_unselected); +	} +	else +	{ +		static LLStringExplicit empty_string(""); +		mSpeakBtn->setLabelSelected(empty_string); +		mSpeakBtn->setLabelUnselected(empty_string); +	} +} + +////////////////////////////////////////////////////////////////////////// +/// PROTECTED SECTION +//////////////////////////////////////////////////////////////////////////  void LLSpeakButton::onMouseDown_SpeakBtn()  {  	bool down = true; diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h index 02c8ab3890..424ee5357a 100644 --- a/indra/newview/llspeakbutton.h +++ b/indra/newview/llspeakbutton.h @@ -67,6 +67,18 @@ public:  	void setSpeakToolTip(const std::string& msg);  	void setShowToolTip(const std::string& msg); +	/** +	 * Sets visibility of speak button's label according to passed parameter. +	 * +	 * It removes label/selected label if "visible" is false and restores otherwise. +	 * +	 * @param visible if true - show label and selected label. +	 *  +	 * @see mSpeakBtn +	 * @see LLBottomTray::processShrinkButtons() +	 */ +	void setLabelVisible(bool visible); +  protected:  	friend class LLUICtrlFactory;  	LLSpeakButton(const Params& p); diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index beb31bc833..a4f5164a8d 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -53,6 +53,7 @@  #include "lluictrlfactory.h"  #include "llnotifications.h"  #include "llfunctorregistry.h" +#include "llrootview.h"  const S32 MAX_ALLOWED_MSG_WIDTH = 400;  const F32 DEFAULT_BUTTON_DELAY = 0.5f; @@ -220,16 +221,13 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  	static LLUIColor alert_text_color = LLUIColorTable::instance().getColor("AlertTextColor");  	if (mCaution)  	{ -		LLIconCtrl::Params params; -		params.name("icon"); -		params.rect(LLRect(msg_x, msg_y, msg_x+32, msg_y-32)); -		params.mouse_opaque(false); -		params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); -		params.tab_stop(false); -		LLIconCtrl * icon = LLUICtrlFactory::create<LLIconCtrl> (params); -		icon->setValue ("notify_caution_icon.tga"); -		icon->setMouseOpaque(FALSE); -		LLToastPanel::addChild(icon); +		LLIconCtrl* icon = LLUICtrlFactory::getInstance()->createFromFile<LLIconCtrl>("alert_icon.xml", this, LLPanel::child_registry_t::instance()); +		if(icon) +		{ +			icon->setRect(LLRect(msg_x, msg_y, msg_x+32, msg_y-32)); +			LLToastPanel::addChild(icon); +		} +		  		msg_x += 32 + HPAD;  		msg_box->setColor( alert_caution_text_color );  	} @@ -245,29 +243,30 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  	// Buttons	  	S32 button_left = (LLToastPanel::getRect().getWidth() - btn_total_width) / 2; - +	  	for( S32 i = 0; i < num_options; i++ )  	{  		LLRect button_rect; -		button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ); - -		LLButton::Params p; -		p.name(options[i].first); -		p.rect(button_rect); -		p.click_callback.function(boost::bind(&LLToastAlertPanel::onButtonPressed, this, _2, i)); -		p.font(font); -		p.label(options[i].second); +		 +		LLButton* btn = LLUICtrlFactory::getInstance()->createFromFile<LLButton>("alert_button.xml", this, LLPanel::child_registry_t::instance()); +		if(btn) +		{ +			btn->setName(options[i].first); +			btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT )); +			btn->setLabel(options[i].second); +			btn->setFont(font); +			 +			btn->setClickedCallback(boost::bind(&LLToastAlertPanel::onButtonPressed, this, _2, i)); -		LLButton* btn = LLUICtrlFactory::create<LLButton>(p); -		mButtonData[i].mButton = btn; +			mButtonData[i].mButton = btn; -		LLToastPanel::addChild(btn); +			LLToastPanel::addChild(btn); -		if( i == mDefaultOption ) -		{ -			btn->setFocus(TRUE); +			if( i == mDefaultOption ) +			{ +				btn->setFocus(TRUE); +			}  		} -  		button_left += button_width + BTN_HPAD;  	} @@ -275,25 +274,26 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  	if (!edit_text_name.empty())  	{  		S32 y = VPAD + BTN_HEIGHT + VPAD/2; +		mLineEditor = LLUICtrlFactory::getInstance()->createFromFile<LLLineEditor>("alert_line_editor.xml", this, LLPanel::child_registry_t::instance()); +	 +		if (mLineEditor) +		{ +			LLRect leditor_rect = LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y); +			mLineEditor->setName(edit_text_name); +			mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight()); +			mLineEditor->setRect(leditor_rect); +			mLineEditor->setText(edit_text_contents); +			mLineEditor->setMaxTextLength(STD_STRING_STR_LEN); -		LLLineEditor::Params params; -		params.name(edit_text_name); -		params.rect(LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y)); -		params.default_text(edit_text_contents); -		params.max_length_bytes(STD_STRING_STR_LEN); -		mLineEditor = LLUICtrlFactory::create<LLLineEditor> (params); +			// make sure all edit keys get handled properly (DEV-22396) +			mLineEditor->setHandleEditKeysDirectly(TRUE); -		// make sure all edit keys get handled properly (DEV-22396) -		mLineEditor->setHandleEditKeysDirectly(TRUE); +			LLToastPanel::addChild(mLineEditor); -		LLToastPanel::addChild(mLineEditor); -	} -	 -	if (mLineEditor) -	{ -		mLineEditor->setDrawAsterixes(is_password); +			mLineEditor->setDrawAsterixes(is_password); -		setEditTextArgs(notification->getSubstitutions()); +			setEditTextArgs(notification->getSubstitutions()); +		}  	}  	std::string ignore_label; @@ -323,7 +323,14 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )  { -	const LLFontGL* font = LLFontGL::getFontSansSerif(); +	mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance()); + +	if(!mCheck) +	{ +		return false; +	} + +	const LLFontGL* font =  mCheck->getFont();  	const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);  	// Extend dialog for "check next time" @@ -339,14 +346,13 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::  	LLToastPanel::reshape( dialog_width, dialog_height, FALSE );  	S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2; + +	// set check_box's attributes +	LLRect check_rect; +	mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT)); +	mCheck->setLabel(check_title); +	mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1)); -	LLCheckBoxCtrl::Params p; -	p.name("check"); -	p.rect.left(msg_x).bottom(VPAD+BTN_HEIGHT+LINE_HEIGHT/2).width(max_msg_width).height(LINE_HEIGHT); -	p.label(check_title); -	p.font(font); -	p.commit_callback.function(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1)); -	mCheck = LLUICtrlFactory::create<LLCheckBoxCtrl>(p);  	LLToastPanel::addChild(mCheck);  	return true; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 089535dfab..87d256b60a 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1336,6 +1336,12 @@ BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& na  	return result;  } +void LLViewerInventoryItem::insertDefaultSortField(std::string& name) +{ +	name.insert(0, std::string("1") + getSeparator()); +} + +  // This returns true if the item that this item points to   // doesn't exist in memory (i.e. LLInventoryModel).  The baseitem  // might still be in the database but just not loaded yet. diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 529425aa25..d27faffdd9 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -81,6 +81,7 @@ public:  	virtual U32 getCRC32() const; // really more of a checksum.  	static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); +	static void insertDefaultSortField(std::string& name);  	// construct a complete viewer inventory item  	LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 11b2f07f1b..8db6d5917a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1372,7 +1372,8 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)  	payload["from_id"] = info->mFromID;  	args["OBJECTFROMNAME"] = info->mFromName; -	args["NAME"] = LLSLURL::buildCommand("agent", info->mFromID, "about"); +	args["NAME"] = info->mFromName; +	args["NAME_SLURL"] = LLSLURL::buildCommand("agent", info->mFromID, "about");  	std::string verb = "highlight?name=" + msg;  	args["ITEM_SLURL"] = LLSLURL::buildCommand("inventory", info->mObjectID, verb.c_str()); @@ -2115,7 +2116,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			send_generic_message("requestonlinenotification", strings);  			args["NAME"] = name; -			LLNotifications::instance().add("FriendshipAccepted", args); +			LLSD payload; +			payload["from_id"] = from_id; +			LLNotifications::instance().add("FriendshipAccepted", args, payload);  		}  		break; diff --git a/indra/newview/skins/default/xui/en/alert_button.xml b/indra/newview/skins/default/xui/en/alert_button.xml new file mode 100644 index 0000000000..48c67a3770 --- /dev/null +++ b/indra/newview/skins/default/xui/en/alert_button.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<button +  label_shadow="true" +  auto_resize="false" +  image_overlay_alignment="center" +  use_ellipses="flse" +  pad_right="10" +  pad_left="10" +  is_toggle="false" +  scale_image="true" +  commit_on_return="true" +  font="SansSerifSmall" +  follows="bottom"/> diff --git a/indra/newview/skins/default/xui/en/alert_check_box.xml b/indra/newview/skins/default/xui/en/alert_check_box.xml new file mode 100644 index 0000000000..9f1bdb5193 --- /dev/null +++ b/indra/newview/skins/default/xui/en/alert_check_box.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<check_box +  text_enabled_color="LabelTextColor" +  text_disabled_color="LabelDisabledColor" +  font="SansSerif" +  follows="left|top" +  name="check"/>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/alert_icon.xml b/indra/newview/skins/default/xui/en/alert_icon.xml new file mode 100644 index 0000000000..b0886fce06 --- /dev/null +++ b/indra/newview/skins/default/xui/en/alert_icon.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<icon color="1.0 1.0 1.0 1.0" +      tab_stop="false" +      mouse_opaque="false" +      name="icon" +      image_name="notify_caution_icon.tga"  +      follows="left|top"> +</icon> diff --git a/indra/newview/skins/default/xui/en/alert_line_editor.xml b/indra/newview/skins/default/xui/en/alert_line_editor.xml new file mode 100644 index 0000000000..ab708adb06 --- /dev/null +++ b/indra/newview/skins/default/xui/en/alert_line_editor.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<line_editor +  select_on_focus="false" +  handle_edit_keys_directly="false" +  revert_on_esc="true" +  commit_on_focus_lost="true" +  ignore_tab="true" +  max_length="254" +  text_pad_right="0" +  text_pad_left="0" +  mouse_opaque="true"/> diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml index 21d292847a..9f5e6828d2 100644 --- a/indra/newview/skins/default/xui/en/floater_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_gesture.xml @@ -21,12 +21,16 @@       name="playing">          (Playing)      </floater.string> +    <!-- It's used to build new name for gesture created by "Copy" menu item --> +    <floater.string +     name="copy_name">Copy of [COPY_NAME]</floater.string>      <scroll_list       bottom_delta="400"       draw_heading="true"       follows="all"       layout="topleft"       left="0" +     multi_select="true"       top="20"       name="gesture_list">          <scroll_list.columns @@ -57,18 +61,18 @@               left="0"               name="bottom_panel"               width="313"> -               <button +              <menu_button                 follows="bottom|left" -               font="SansSerifBigBold" -               tool_tip="Change sort and view of recent residents list"                 height="18"                 image_disabled="OptionsMenu_Disabled"                 image_selected="OptionsMenu_Press"                 image_unselected="OptionsMenu_Off"                 layout="topleft"                 left="10" -               name="recent_viewsort_btn" +               menu_filename="menu_gesture_gear.xml" +               name="gear_btn"                 top="5" +               tool_tip="More options"                 width="18" />                <button                   follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml new file mode 100644 index 0000000000..4642e82c0b --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + layout="topleft" + mouse_opaque="false" + name="menu_gesture_gear" + visible="false"> +    <menu_item_call +     font="SansSerifBold" +     label="Add/Remove from Favorites" +     layout="topleft" +     name="activate"> +        <on_click +         function="Gesture.Action.ToogleActiveState" /> +    </menu_item_call> +    <menu_item_call +     label="Copy" +     layout="topleft" +     name="copy_gesture"> +        <on_click +         function="Gesture.Action.CopyPast" +         parameter="copy_gesture" /> +        <on_enable +         function="Gesture.EnableAction" +         parameter="copy_gesture" /> +    </menu_item_call> +    <menu_item_call +     label="Paste" +     layout="topleft" +     name="paste"> +        <on_click +         function="Gesture.Action.CopyPast" +         parameter="paste" /> +        <on_enable +         function="Gesture.EnableAction" +         parameter="paste" /> +    </menu_item_call> +    <menu_item_call +     label="Copy UUID" +     layout="topleft" +     name="copy_uuid"> +        <on_click +         function="Gesture.Action.CopyPast" +         parameter="copy_uuid" /> +        <on_enable +         function="Gesture.EnableAction" +         parameter="copy_uuid" /> +    </menu_item_call> +    <menu_item_call +     label="Save to current outfit" +     layout="topleft" +     name="save_to_outfit"> +        <on_click +         function="Gesture.Action.SaveToCOF" /> +    </menu_item_call> +    <menu_item_call +     label="Edit" +     layout="topleft" +     name="edit_gesture"> +        <on_click +         function="Gesture.Action.ShowPreview" /> +        <on_enable +         function="Gesture.EnableAction" +         parameter="edit_gesture" /> +    </menu_item_call> +    <menu_item_call +     label="Inspect" +     layout="topleft" +     name="inspect"> +        <on_click +         function="Gesture.Action.ShowPreview" /> +        <on_enable +         function="Gesture.EnableAction" +         parameter="inspect" /> +    </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index eb40fd473c..90e32cdd9c 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4966,7 +4966,7 @@ No valid parcel could be found.     icon="notify.tga"     name="ObjectGiveItem"     type="offer"> -An object named [OBJECTFROMNAME] owned by [NAME] has offered you [OBJECTTYPE]: +An object named [OBJECTFROMNAME] owned by [NAME_SLURL] has offered you [OBJECTTYPE]:  [ITEM_SLURL]      <form name="form">        <button @@ -4987,8 +4987,9 @@ An object named [OBJECTFROMNAME] owned by [NAME] has offered you [OBJECTTYPE]:    <notification     icon="notify.tga"     name="ObjectGiveItemUnknownUser" -   type="notify"> -An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a [OBJECTTYPE] named [OBJECTNAME]. +   type="offer"> +An object named [OBJECTFROMNAME] owned by (an unknown Resident) has offered you [OBJECTTYPE]: +[ITEM_SLURL]      <form name="form">        <button         index="0" @@ -5009,7 +5010,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a     icon="notify.tga"     name="UserGiveItem"     type="offer"> -[NAME] has offered you [OBJECTTYPE]: +[NAME_SLURL] has offered you [OBJECTTYPE]:  [ITEM_SLURL]      <form name="form">        <button diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 00711a29e0..6480469f43 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -60,11 +60,11 @@           min_height="28"           width="104"           top_delta="0" -         min_width="104" +         min_width="54"           name="speak_panel"           user_resize="false">            <talk_button -           follows="right" +           follows="left|right"             height="23"             speak_button.tab_stop="true"             show_button.tab_stop="true" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9238b88d9b..90fb3a6bf9 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -1782,8 +1782,7 @@ Clears (deletes) the media and all params from the given face.  	<string name="GroupNotifySaveAttachment">Save Attachment</string>    <string name="TeleportOffer">Teleport offering</string>    <!-- start-up toast's string--> -  <string name="StartUpNotification">%d new notification arrived while you were away...</string> -  <string name="StartUpNotifications">%d new notifications arrived while you were away...</string> +  <string name="StartUpNotifications">New notifications arrived while you were away.</string>    <!-- overflow toast's string-->    <string name="OverflowInfoChannelString">You have %d more notification</string> diff --git a/indra/newview/skins/default/xui/en/widgets/talk_button.xml b/indra/newview/skins/default/xui/en/widgets/talk_button.xml index 1d8257fbc8..64c2e65a6e 100644 --- a/indra/newview/skins/default/xui/en/widgets/talk_button.xml +++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml @@ -6,6 +6,7 @@      image_unselected="SegmentedBtn_Left_Off"    -->    <speak_button +    follows="left|right"       name="left"      label="Speak"      label_selected="Speak" @@ -13,6 +14,7 @@      tab_stop="false"      />    <show_button +    follows="right"       name="right"      label=""      left="0" @@ -25,6 +27,7 @@      image_unselected="ComboButton_UpOff"      />    <monitor +    follows="right"       name="monitor"      left="0"      top="18"  | 
