diff options
Diffstat (limited to 'indra/llui')
41 files changed, 415 insertions, 125 deletions
| diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index b5e870228a..d0c73fbfbc 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -63,6 +63,8 @@ static LLDefaultChildRegistry::Register<LLAccordionCtrl>	t2("accordion");  LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)   , mFitParent(params.fit_parent) + , mAutoScrolling( false ) + , mAutoScrollRate( 0.f )  {    mSingleExpansion = params.single_expansion;  	if(mFitParent && !mSingleExpansion) @@ -72,6 +74,8 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)  }  LLAccordionCtrl::LLAccordionCtrl() : LLPanel() + , mAutoScrolling( false ) + , mAutoScrollRate( 0.f )  {  	mSingleExpansion = false;  	mFitParent = false; @@ -81,6 +85,19 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel()  //---------------------------------------------------------------------------------  void LLAccordionCtrl::draw()  { +	if (mAutoScrolling) +	{ +		// add acceleration to autoscroll +		mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE); +	} +	else +	{ +		// reset to minimum for next time +		mAutoScrollRate = MIN_AUTO_SCROLL_RATE; +	} +	// clear this flag to be set on next call to autoScroll +	mAutoScrolling = false; +  	LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);  	LLLocalClipRect clip(local_rect); @@ -420,6 +437,64 @@ BOOL LLAccordionCtrl::handleKeyHere			(KEY key, MASK mask)  	return LLPanel::handleKeyHere(key,mask);  } +BOOL LLAccordionCtrl::handleDragAndDrop		(S32 x, S32 y, MASK mask, +											 BOOL drop, +											 EDragAndDropType cargo_type, +											 void* cargo_data, +											 EAcceptance* accept, +											 std::string& tooltip_msg) +{ +	// Scroll folder view if needed.  Never accepts a drag or drop. +	*accept = ACCEPT_NO; +	BOOL handled = autoScroll(x, y); + +	if( !handled ) +	{ +		handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, +											cargo_data, accept, tooltip_msg) != NULL; +	} +	return TRUE; +} + +BOOL LLAccordionCtrl::autoScroll		(S32 x, S32 y) +{ +	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + +	bool scrolling = false; +	if( mScrollbar->getVisible() ) +	{ +		LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 ); +		LLRect screen_local_extents; + +		// clip rect against root view +		screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); +		rect_local.intersectWith(screen_local_extents); + +		// autoscroll region should take up no more than one third of visible scroller area +		S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10); +		S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); + +		LLRect bottom_scroll_rect = screen_local_extents; +		bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height; +		if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()) ) +		{ +			mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed ); +			mAutoScrolling = true; +			scrolling = true; +		} + +		LLRect top_scroll_rect = screen_local_extents; +		top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height; +		if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() > 0) ) +		{ +			mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed ); +			mAutoScrolling = true; +			scrolling = true; +		} +	} +	return scrolling; +} +  void	LLAccordionCtrl::updateLayout	(S32 width, S32 height)  {  	S32 panel_top = height - BORDER_MARGIN ; diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index 4cb0f38281..d57a42df32 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -81,6 +81,11 @@ public:  	virtual BOOL handleRightMouseDown	( S32 x, S32 y, MASK mask);   	virtual BOOL handleScrollWheel		( S32 x, S32 y, S32 clicks );  	virtual BOOL handleKeyHere			(KEY key, MASK mask); +	virtual BOOL handleDragAndDrop		(S32 x, S32 y, MASK mask, BOOL drop, +										 EDragAndDropType cargo_type, +										 void* cargo_data, +										 EAcceptance* accept, +										 std::string& tooltip_msg);  	//  	// Call reshape after changing splitter's size @@ -112,11 +117,15 @@ private:  	void	showScrollbar			(S32 width, S32 height);  	void	hideScrollbar			(S32 width, S32 height); +	BOOL	autoScroll				(S32 x, S32 y); +  private:  	LLRect			mInnerRect;  	LLScrollbar*	mScrollbar;  	bool			mSingleExpansion;  	bool			mFitParent; +	bool			mAutoScrolling; +	F32				mAutoScrollRate;  }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 4bfe44135a..daa9e08f14 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -45,6 +45,7 @@ static const std::string DD_HEADER_NAME = "dd_header";  static const S32 HEADER_HEIGHT = 20;  static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;  static const S32 HEADER_TEXT_LEFT_OFFSET = 30; +static const F32 AUTO_OPEN_TIME = 1.f;  static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab"); @@ -73,6 +74,11 @@ public:  	virtual void onMouseEnter(S32 x, S32 y, MASK mask);  	virtual void onMouseLeave(S32 x, S32 y, MASK mask);  	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); +	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +								   EDragAndDropType cargo_type, +								   void* cargo_data, +								   EAcceptance* accept, +								   std::string& tooltip_msg);  private:  	LLTextBox* mHeaderTextbox; @@ -92,6 +98,8 @@ private:  	LLUIColor mHeaderBGColor;  	bool mNeedsHighlight; + +	LLFrameTimer mAutoOpenTimer;  };  LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() @@ -209,6 +217,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MA  {  	LLUICtrl::onMouseLeave(x, y, mask);  	mNeedsHighlight = false; +	mAutoOpenTimer.stop();  }  BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)  { @@ -218,8 +227,33 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask,  	}  	return LLUICtrl::handleKey(key, mask, called_from_parent);  } +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask, +																	 BOOL drop, +																	 EDragAndDropType cargo_type, +																	 void* cargo_data, +																	 EAcceptance* accept, +																	 std::string& tooltip_msg) +{ +	LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent()); +	if ( parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose() ) +	{ +		if (mAutoOpenTimer.getStarted()) +		{ +			if (mAutoOpenTimer.getElapsedTimeF32() > AUTO_OPEN_TIME) +			{ +				parent->changeOpenClose(false); +				mAutoOpenTimer.stop(); +				return TRUE; +			} +		} +		else +			mAutoOpenTimer.start(); +	} +	return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type, +									   cargo_data, accept, tooltip_msg); +}  LLAccordionCtrlTab::Params::Params()  	: title("title")  	,display_children("expanded", true) diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index b200d43438..2e0260ab16 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -115,6 +115,7 @@ public:  	void changeOpenClose(bool is_open);  	void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; +	bool canOpenClose() const { return mCanOpenClose; };  	virtual BOOL postBuild(); diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index e9f6288f44..4944ed4fe7 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -81,6 +81,10 @@ LLButton::Params::Params()  	image_pressed_selected("image_pressed_selected"),  	image_overlay("image_overlay"),  	image_overlay_alignment("image_overlay_alignment", std::string("center")), +	image_left_pad("image_left_pad"), +	image_right_pad("image_right_pad"), +	image_top_pad("image_top_pad"), +	image_bottom_pad("image_bottom_pad"),  	label_color("label_color"),  	label_color_selected("label_color_selected"),	// requires is_toggle true  	label_color_disabled("label_color_disabled"), @@ -140,6 +144,10 @@ LLButton::LLButton(const LLButton::Params& p)  	mImageOverlay(p.image_overlay()),  	mImageOverlayColor(p.image_overlay_color()),  	mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)), +	mImageOverlayLeftPad(p.image_left_pad), +	mImageOverlayRightPad(p.image_right_pad), +	mImageOverlayTopPad(p.image_top_pad), +	mImageOverlayBottomPad(p.image_bottom_pad),  	mIsToggle(p.is_toggle),  	mScaleImage(p.scale_image),  	mDropShadowedText(p.label_shadow), @@ -763,6 +771,12 @@ void LLButton::draw()  			center_x++;  		} +		S32 text_width_delta = overlay_width + 1; +		// if image paddings set, they should participate in scaling process +		S32 image_size_delta = mImageOverlayTopPad + mImageOverlayBottomPad; +		overlay_width = overlay_width - image_size_delta; +		overlay_height = overlay_height - image_size_delta; +  		// fade out overlay images on disabled buttons  		LLColor4 overlay_color = mImageOverlayColor.get();  		if (!enabled) @@ -774,8 +788,8 @@ void LLButton::draw()  		switch(mImageOverlayAlignment)  		{  		case LLFontGL::LEFT: -			text_left += overlay_width + 1; -			text_width -= overlay_width + 1; +			text_left += overlay_width + mImageOverlayRightPad + 1; +			text_width -= text_width_delta;  			mImageOverlay->draw(  				mLeftHPad,   				center_y - (overlay_height / 2),  @@ -792,8 +806,8 @@ void LLButton::draw()  				overlay_color);  			break;  		case LLFontGL::RIGHT: -			text_right -= overlay_width + 1;				 -			text_width -= overlay_width + 1; +			text_right -= overlay_width + mImageOverlayLeftPad+ 1; +			text_width -= text_width_delta;  			mImageOverlay->draw(  				getRect().getWidth() - mRightHPad - overlay_width,   				center_y - (overlay_height / 2),  @@ -1022,6 +1036,20 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a  	}  } +void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color) +{ +	if (image_id.isNull()) +	{ +		mImageOverlay = NULL; +	} +	else +	{ +		mImageOverlay = LLUI::getUIImageByID(image_id); +		mImageOverlayAlignment = alignment; +		mImageOverlayColor = color; +	} +} +  void LLButton::onMouseCaptureLost()  {  	resetMouseDownTimer(); diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 5e28b8cdff..8e5f19602f 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -106,6 +106,12 @@ public:  		Optional<S32>			pad_left;  		Optional<S32>			pad_bottom; // under text label +		//image overlay paddings +		Optional<S32>			image_left_pad; +		Optional<S32>			image_right_pad; +		Optional<S32>			image_top_pad; +		Optional<S32>			image_bottom_pad; +  		// callbacks  		Optional<CommitCallbackParam>	click_callback, // alias -> commit_callback  										mouse_down_callback, @@ -186,6 +192,15 @@ public:  	void			setLeftHPad( S32 pad )					{ mLeftHPad = pad; }  	void			setRightHPad( S32 pad )					{ mRightHPad = pad; } +	void 			setImageOverlayLeftPad( S32 pad )			{ mImageOverlayLeftPad = pad; } +	S32 			getImageOverlayLeftPad() const				{ return mImageOverlayLeftPad; } +	void 			setImageOverlayRightPad( S32 pad )			{ mImageOverlayRightPad = pad; } +	S32 			getImageOverlayRightPad() const				{ return mImageOverlayRightPad; } +	void 			setImageOverlayTopPad( S32 pad )			{ mImageOverlayTopPad = pad; } +	S32 			getImageOverlayTopPad() const				{ return mImageOverlayTopPad; } +	void 			setImageOverlayBottomPad( S32 pad )			{ mImageOverlayBottomPad = pad; } +	S32 			getImageOverlayBottomPad() const			{ return mImageOverlayBottomPad; } +  	const std::string	getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); }  	const std::string	getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); } @@ -200,6 +215,7 @@ public:  	void			setDisabledSelectedLabelColor( const LLColor4& c )	{ mDisabledSelectedLabelColor = c; }  	void			setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); +	void 			setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);  	LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }  	void            autoResize();	// resize with label of current btn state  @@ -312,6 +328,11 @@ private:  	S32							mRightHPad;  	S32							mBottomVPad;	// under text label +	S32							mImageOverlayLeftPad; +	S32							mImageOverlayRightPad; +	S32							mImageOverlayTopPad; +	S32							mImageOverlayBottomPad; +  	F32							mHoverGlowStrength;  	F32							mCurGlowStrength; diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index f29e8785eb..9d23daf56d 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -103,7 +103,8 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)  	mPrearrangeCallback(p.prearrange_callback()),  	mTextEntryCallback(p.text_entry_callback()),  	mListPosition(p.list_position), -	mLastSelectedIndex(-1) +	mLastSelectedIndex(-1), +	mLabel(p.label)  {  	// Text label button @@ -490,6 +491,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)  		params.handle_edit_keys_directly(true);  		params.commit_on_focus_lost(false);  		params.follows.flags(FOLLOWS_ALL); +		params.label(mLabel);  		mTextEntry = LLUICtrlFactory::create<LLLineEditor> (params);  		mTextEntry->setText(cur_label);  		mTextEntry->setIgnoreTab(TRUE); @@ -505,7 +507,8 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)  		mButton->setRect(rect);  		mButton->setTabStop(TRUE);  		mButton->setHAlign(LLFontGL::LEFT); - +		mButton->setLabel(mLabel.getString()); +		  		if (mTextEntry)  		{  			mTextEntry->setVisible(FALSE); @@ -633,7 +636,7 @@ void LLComboBox::hideList()  			if(mLastSelectedIndex >= 0)  				mList->selectNthItem(mLastSelectedIndex);  		} -		else +		else if(mLastSelectedIndex >= 0)  			mList->selectNthItem(mLastSelectedIndex);  		mButton->setToggleState(FALSE); diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index 59499f987b..0237c80efa 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -66,7 +66,9 @@ LLConsole::LLConsole(const LLConsole::Params& p)  :	LLUICtrl(p),  	LLFixedBuffer(p.max_lines),  	mLinePersistTime(p.persist_time), // seconds -	mFont(p.font) +	mFont(p.font), +	mConsoleWidth(0), +	mConsoleHeight(0)  {  	if (p.font_size_index.isProvided())  	{ diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index 5800a82922..4719950f28 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -150,8 +150,6 @@ private:  	F32			mLinePersistTime; // Age at which to stop drawing.  	F32			mFadeTime; // Age at which to start fading  	const LLFontGL*	mFont; -	S32			mLastBoxHeight; -	S32			mLastBoxWidth;  	S32			mConsoleWidth;  	S32			mConsoleHeight; diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 74438b184a..57baf28dab 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -146,7 +146,7 @@ void LLDockableFloater::setVisible(BOOL visible)  	if (visible)  	{ -		LLFloater::setFrontmost(TRUE); +		LLFloater::setFrontmost(getAutoFocus());  	}  	LLFloater::setVisible(visible);  } diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 0d8e54aa48..d836a5f4cd 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -37,7 +37,11 @@  LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,  		const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : -		mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue) +		mDockWidget(dockWidget), +		mDockableFloater(dockableFloater), +		mDockTongue(dockTongue), +		mDockTongueX(0), +		mDockTongueY(0)  {  	mDockAt = dockAt; diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index a93c666648..832f148902 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -113,6 +113,7 @@ void LLDragHandleTop::setTitle(const std::string& title)  		params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);  		params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);  		params.use_ellipses = true; +		params.allow_html = false; //cancel URL replacement in floater title  		mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);  		addChild( mTitleBox );  	} diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 3694ecd4f4..92993650a7 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -289,8 +289,8 @@ 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)); +	// Stretch selected item rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));  }  void LLFlatListView::setNoItemsCommentText(const std::string& comment_text) @@ -393,7 +393,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)  	LLViewBorder::Params params;  	params.name("scroll border"); -	params.rect(getSelectedItemsRect()); +	params.rect(getLastSelectedItemRect());  	params.visible(false);  	params.bevel_style(LLViewBorder::BEVEL_IN);  	mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params); @@ -480,8 +480,8 @@ void LLFlatListView::rearrangeItems()  		item_new_top -= (rc.getHeight() + mItemPad);  	} -	// Stretch selected items rect to ensure it won't be clipped -	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1)); +	// Stretch selected item rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));  }  void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) @@ -664,8 +664,8 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)  		onCommit();  	} -	// Stretch selected items rect to ensure it won't be clipped -	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1)); +	// Stretch selected item rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));  	return true;  } @@ -680,23 +680,6 @@ LLRect LLFlatListView::getLastSelectedItemRect()  	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; -} -  void LLFlatListView::selectFirstItem	()  {  	selectItemPair(mItemPairs.front(), true); @@ -819,8 +802,8 @@ bool LLFlatListView::selectAll()  		onCommit();  	} -	// Stretch selected items rect to ensure it won't be clipped -	mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1)); +	// Stretch selected item rect to ensure it won't be clipped +	mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));  	return true;  } diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 5999e79f61..949a731507 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -368,8 +368,6 @@ protected:  	LLRect getLastSelectedItemRect(); -	LLRect getSelectedItemsRect(); -  	void   ensureSelectedVisible();  private: diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 79d8f90fec..de46d89d6f 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1916,9 +1916,10 @@ static LLDefaultChildRegistry::Register<LLFloaterView> r("floater_view");  LLFloaterView::LLFloaterView (const Params& p)  :	LLUICtrl (p), +  	mFocusCycleMode(FALSE), -	mSnapOffsetBottom(0) -	,mSnapOffsetRight(0) +	mSnapOffsetBottom(0), +	mSnapOffsetRight(0)  {  } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index f70495c0f0..2166d8db8a 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -301,6 +301,7 @@ protected:  	const LLRect&	getExpandedRect() const { return mExpandedRect; }  	void			setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened +	BOOL			getAutoFocus() const { return mAutoFocus; }  	LLDragHandle*	getDragHandle() const { return mDragHandle; }  	void			destroy() { die(); } // Don't call this directly.  You probably want to call closeFloater() @@ -468,9 +469,6 @@ public:  	void setSnapOffsetRight(S32 offset) { mSnapOffsetRight = offset; }  private: -	S32				mColumn; -	S32				mNextLeft; -	S32				mNextTop;  	BOOL			mFocusCycleMode;  	S32				mSnapOffsetBottom;  	S32				mSnapOffsetRight; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 73e4d126f3..cb5aea272d 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -70,6 +70,8 @@ const S32   SCROLL_INCREMENT_DEL = 4;	// make space for baskspacing  const F32   AUTO_SCROLL_TIME = 0.05f;  const F32	TRIPLE_CLICK_INTERVAL = 0.3f;	// delay between double and triple click. *TODO: make this equal to the double click interval? +const std::string PASSWORD_ASTERISK( "\xE2\x97\x8F" ); // U+25CF BLACK CIRCLE +  static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor");  // Compiler optimization, generate extern template @@ -401,7 +403,7 @@ void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )  	{  		for (S32 i = 0; i < mText.length(); i++)  		{ -			asterix_text += '*'; +			asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);  		}  		wtext = asterix_text.c_str();  	} @@ -1599,7 +1601,7 @@ void LLLineEditor::draw()  		std::string text;  		for (S32 i = 0; i < mText.length(); i++)  		{ -			text += '*'; +			text += PASSWORD_ASTERISK;  		}  		mText = text;  	} diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index c172a2b714..7fa9a88059 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1651,6 +1651,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)  	mBackgroundColor( p.bg_color() ),  	mBgVisible( p.bg_visible ),  	mDropShadowed( p.drop_shadow ), +	mHasSelection(false),  	mHorizontalLayout( p.horizontal_layout ),  	mScrollable(mHorizontalLayout ? FALSE : p.scrollable), // Scrolling is supported only for vertical layout  	mMaxScrollableItems(p.max_scrollable_items), @@ -1875,17 +1876,21 @@ void LLMenuGL::scrollItemsDown()  	item_list_t::iterator next_item_iter; -	for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++) +	if (cur_item_iter != mItems.end())  	{ -		if( (*next_item_iter)->getVisible()) +		for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)  		{ -			break; +			if( (*next_item_iter)->getVisible()) +			{ +				break; +			} +		} +		 +		if (next_item_iter != mItems.end() && +		    (*next_item_iter)->getVisible()) +		{ +			mFirstVisibleItem = *next_item_iter;  		} -	} - -	if ((*next_item_iter)->getVisible()) -	{ -		mFirstVisibleItem = *next_item_iter;  	}  	mNeedsArrange = TRUE; @@ -2809,7 +2814,7 @@ BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask )  					((LLMenuItemGL*)viewp)->setHighlight(TRUE);  					LLMenuGL::setKeyboardMode(FALSE);  				} -				mHasSelection = TRUE; +				mHasSelection = true;  			}  		}  	} @@ -2888,7 +2893,7 @@ void LLMenuGL::setVisible(BOOL visible)  		}  		else  		{ -			mHasSelection = FALSE; +			mHasSelection = true;  			mFadeTimer.stop();  		} diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 61e06f9e5f..8441aaadd4 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -546,7 +546,7 @@ private:  	LLHandle<LLView> mParentMenuItem;  	LLUIString		mLabel;  	BOOL mDropShadowed; 	//  Whether to drop shadow  -	BOOL			mHasSelection; +	bool			mHasSelection;  	LLFrameTimer	mFadeTimer;  	LLTimer			mScrollItemsTimer;  	BOOL			mTornOff; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 86989012ee..5816cef6af 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -283,6 +283,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP  }  LLNotificationForm::LLNotificationForm(const LLSD& sd) +	: mIgnore(IGNORE_NO)  {  	if (sd.isArray())  	{ @@ -384,7 +385,8 @@ LLNotificationTemplate::LLNotificationTemplate() :  	mExpireSeconds(0),  	mExpireOption(-1),  	mURLOption(-1), -    mURLOpenExternally(-1), +	mURLOpenExternally(-1), +	mPersist(false),  	mUnique(false),  	mPriority(NOTIFICATION_PRIORITY_NORMAL)  { @@ -1058,6 +1060,7 @@ LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelN  	if(p == mChannels.end())  	{  		llerrs << "Did not find channel named " << channelName << llendl; +		return LLNotificationChannelPtr();  	}  	return p->second;  } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index aeb4cebf1b..d55e0f4043 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -371,7 +371,7 @@ private:  	// this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT  	// for anything real! -	LLNotification(LLUUID uuid) : mId(uuid) {} + LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mTemporaryResponder(false) {}  	void cancel(); @@ -621,7 +621,7 @@ namespace LLNotificationComparators  	struct orderBy  	{  		typedef boost::function<T (LLNotificationPtr)> field_t; -		orderBy(field_t field, EDirection = ORDER_INCREASING) : mField(field) {} +        	orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {}  		bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs)  		{  			if (mDirection == ORDER_DECREASING) diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp index f343d27cb4..54bdb4bd66 100644 --- a/indra/llui/llnotificationsutil.cpp +++ b/indra/llui/llnotificationsutil.cpp @@ -94,3 +94,8 @@ void LLNotificationsUtil::cancel(LLNotificationPtr pNotif)  {  	LLNotifications::instance().cancel(pNotif);  } + +LLNotificationPtr LLNotificationsUtil::find(LLUUID uuid) +{ +	return LLNotifications::instance().find(uuid); +} diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h index d552fa915b..338204924a 100644 --- a/indra/llui/llnotificationsutil.h +++ b/indra/llui/llnotificationsutil.h @@ -65,6 +65,8 @@ namespace LLNotificationsUtil  	S32 getSelectedOption(const LLSD& notification, const LLSD& response);  	void cancel(LLNotificationPtr pNotif); + +	LLNotificationPtr find(LLUUID uuid);  }  #endif diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 4e84013db0..478e270c98 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -498,7 +498,7 @@ void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)  {  	S32 height = llmin( getRequiredRect().getHeight(), max_height );  	if(mPageLines) -		height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height ); +		height = llmin( mPageLines * mLineHeight + 2*mBorderThickness + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );  	S32 width = getRect().getWidth(); @@ -1534,7 +1534,7 @@ LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index)  	S32 rect_bottom = getRowOffsetFromIndex(row_index);  	LLScrollListColumn* columnp = getColumn(column_index);  	cell_rect.setOriginAndSize(rect_left, rect_bottom, -		rect_left + columnp->getWidth(), mLineHeight); +		/*rect_left + */columnp->getWidth(), mLineHeight);  	return cell_rect;  } @@ -2760,9 +2760,13 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition  LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)  { -	if (!item_p.validateBlock()) return NULL; -  	LLScrollListItem *new_item = new LLScrollListItem(item_p); +	return addRow(new_item, item_p, pos); +} + +LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos) +{ +	if (!item_p.validateBlock() || !new_item) return NULL;  	new_item->setNumColumns(mColumns.size());  	// Add any columns we don't already have diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 907dc90bea..d2d2379328 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -148,6 +148,7 @@ public:  	// "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid  	// Creates missing columns automatically.  	virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); +	virtual LLScrollListItem* addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);  	virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);  	// Simple add element. Takes a single array of:  	// [ "value" => value, "font" => font, "font-style" => style ] diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 15b86cc945..25ce846d90 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -95,7 +95,7 @@ public:  	void	setUserdata( void* userdata )	{ mUserdata = userdata; }  	void*	getUserdata() const 			{ return mUserdata; } -	LLUUID	getUUID() const					{ return mItemValue.asUUID(); } +	virtual LLUUID	getUUID() const			{ return mItemValue.asUUID(); }  	LLSD	getValue() const				{ return mItemValue; }  	void	setRect(LLRect rect)			{ mRectangle = rect; } diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp index 71511f69a4..b8f93b6a0e 100644 --- a/indra/llui/llstyle.cpp +++ b/indra/llui/llstyle.cpp @@ -49,7 +49,10 @@ LLStyle::Params::Params()  LLStyle::LLStyle(const LLStyle::Params& p) -:	mVisible(p.visible), +:	mItalic(FALSE), +	mBold(FALSE), +	mUnderline(FALSE), +	mVisible(p.visible),  	mColor(p.color()),  	mReadOnlyColor(p.readonly_color()),  	mFont(p.font()), diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 327dd01612..6be76605fd 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1373,6 +1373,8 @@ BOOL LLTabContainer::setTab(S32 which)  		{  			LLTabTuple* tuple = *iter;  			BOOL is_selected = ( tuple == selected_tuple ); +			tuple->mButton->setUseEllipses(TRUE); +			tuple->mButton->setHAlign(LLFontGL::LEFT);  			tuple->mTabPanel->setVisible( is_selected );  // 			tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.  			tuple->mButton->setToggleState( is_selected ); @@ -1478,32 +1480,54 @@ void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state )  void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)  { -	static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);  	LLTabTuple* tuple = getTabByPanel(child);  	if( tuple )  	{ -		tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color); +		tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color); +		reshape_tuple(tuple); +	} +} -		if (!mIsVertical) -		{ -			// remove current width from total tab strip width -			mTotalTabWidth -= tuple->mButton->getRect().getWidth(); +void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color) +{ +	LLTabTuple* tuple = getTabByPanel(child); +	if( tuple ) +	{ +		tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color); +		reshape_tuple(tuple); +	} +} -			S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?  -				tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : -				0; +void LLTabContainer::reshape_tuple(LLTabTuple* tuple) +{ +	static LLUICachedControl<S32> tab_padding ("UITabPadding", 0); +	static LLUICachedControl<S32> image_left_padding ("UIButtonImageLeftPadding", 4); +	static LLUICachedControl<S32> image_right_padding ("UIButtonImageRightPadding", 4); +	static LLUICachedControl<S32> image_top_padding ("UIButtonImageTopPadding", 2); +	static LLUICachedControl<S32> image_bottom_padding ("UIButtonImageBottomPadding", 2); -			tuple->mPadding = image_overlay_width; +	if (!mIsVertical) +	{ +		tuple->mButton->setImageOverlayLeftPad(image_left_padding); +		tuple->mButton->setImageOverlayRightPad(image_right_padding); +		tuple->mButton->setImageOverlayTopPad(image_top_padding); +		tuple->mButton->setImageOverlayBottomPad(image_bottom_padding); -			tuple->mButton->setRightHPad(6); -			tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),  -									tuple->mButton->getRect().getHeight()); -			// add back in button width to total tab strip width -			mTotalTabWidth += tuple->mButton->getRect().getWidth(); +		// remove current width from total tab strip width +		mTotalTabWidth -= tuple->mButton->getRect().getWidth(); -			// tabs have changed size, might need to scroll to see current tab -			updateMaxScrollPos(); -		} +		S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ? +		tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0; + +		tuple->mPadding = image_overlay_width; + +		tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), +								tuple->mButton->getRect().getHeight()); +		// add back in button width to total tab strip width +		mTotalTabWidth += tuple->mButton->getRect().getWidth(); + +		// tabs have changed size, might need to scroll to see current tab +		updateMaxScrollPos();  	}  } @@ -1566,7 +1590,10 @@ void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel )  	LLTabTuple* tuple = getTabByPanel(panel);  	selectTabPanel( panel ); -	tuple->mTabPanel->setFocus(TRUE); +	if (tuple) +	{ +		tuple->mTabPanel->setFocus(TRUE); +	}  }  void LLTabContainer::onNextBtn( const LLSD& data ) diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 5d0f194bf9..2a55877d3c 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -172,6 +172,7 @@ public:  	BOOL        getTabPanelFlashing(LLPanel* child);  	void		setTabPanelFlashing(LLPanel* child, BOOL state);  	void 		setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white); +	void 		setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);  	void		setTitle( const std::string& title );  	const std::string getPanelTitle(S32 index); @@ -227,6 +228,7 @@ private:  	// updates tab button images given the tuple, tab position and the corresponding params  	void update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos); +	void reshape_tuple(LLTabTuple* tuple);  	// Variables diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 41ff462850..a12b7793f7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -244,7 +244,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  LLTextBase::~LLTextBase()  { -	delete mPopupMenu; +	// Menu, like any other LLUICtrl, is deleted by its parent - gMenuHolder +  	clearSegments();  } @@ -1567,20 +1568,28 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c  					prepend_newline = false;  				}  			} -			// output the styled Url -			appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params); -			prepend_newline = false; -			// set the tooltip for the Url label -			if (! match.getTooltip().empty()) +			// output the styled Url (unless we've been asked to suppress hyperlinking) +			if (match.isLinkDisabled()) +			{ +				appendAndHighlightText(match.getLabel(), prepend_newline, part, style_params); +			} +			else  			{ -				segment_set_t::iterator it = getSegIterContaining(getLength()-1); -				if (it != mSegments.end()) +				appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params); + +				// set the tooltip for the Url label +				if (! match.getTooltip().empty())  				{ -					LLTextSegmentPtr segment = *it; -					segment->setToolTip(match.getTooltip()); +					segment_set_t::iterator it = getSegIterContaining(getLength()-1); +					if (it != mSegments.end()) +						{ +							LLTextSegmentPtr segment = *it; +							segment->setToolTip(match.getTooltip()); +						}  				}  			} +			prepend_newline = false;  			// move on to the rest of the text after the Url  			if (end < (S32)text.length())  @@ -2487,7 +2496,7 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin  	LLUIImagePtr image = mStyle->getImage();  	if( image.notNull())  	{ -		num_pixels -= image->getWidth(); +		num_pixels = llmax(0, num_pixels - image->getWidth());  	}  	// search for newline and if found, truncate there diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 9fff910173..48d5478088 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -41,6 +41,7 @@  #include "llpanel.h"  #include <string> +#include <vector>  #include <set>  #include <boost/signals2.hpp> diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3ea33d5f6a..e76fee9f17 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2040,6 +2040,20 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)  																				LLMenuHolderGL::child_registry_t::instance());  	} +	// Route menu to this class +	// previously this was done in ::handleRightMoseDown: +	//if(hasTabStop()) +	// setFocus(TRUE)  - why? weird... +	// and then inside setFocus +	// .... +	//    gEditMenuHandler = this; +	// .... +	// but this didn't work in all cases and just weird... +    //why not here?  +	// (all this was done for EXT-4443) + +	gEditMenuHandler = this; +  	S32 screen_x, screen_y;  	localPointToScreen(x, y, &screen_x, &screen_y);  	mContextMenu->show(screen_x, screen_y); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 01c7a81309..173fde8e76 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -400,7 +400,8 @@ bool LLToolTip::hasClickCallback()  //  LLToolTipMgr::LLToolTipMgr() -:	mToolTip(NULL), +:       mToolTipsBlocked(false), +	mToolTip(NULL),  	mNeedsToolTip(false)  {} diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 7ec0fd603a..32cfc0d9cd 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -64,7 +64,7 @@ class LLUIString  public:  	// These methods all perform appropriate argument substitution  	// and modify mOrig where appropriate -	LLUIString() {} +        LLUIString() : mNeedsResult(false), mNeedsWResult(false) {}  	LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args);  	LLUIString(const std::string& instring) { assign(instring); } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 4927e57a52..58148ad2aa 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -39,8 +39,9 @@  #include "lltrans.h"  #include "lluicolortable.h" -LLUrlEntryBase::LLUrlEntryBase() -: mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")) +LLUrlEntryBase::LLUrlEntryBase() : +	mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")), +	mDisabledLink(false)  {  } @@ -204,7 +205,7 @@ LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()  	mPattern = boost::regex("("  				"\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR  				"|" // or -				"(?<!@)\\b[^[:space:]:@/]+\\.(?:com|net|edu|org)([/:]\\S*)?\\b" // i.e. FOO.net +				"(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net  				")",  				boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_http.xml"; @@ -641,3 +642,20 @@ std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const  	// return the part of the Url after secondlife:///app/worldmap/ part  	return ::getStringAfterToken(url, "app/worldmap/");  } + +// +// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags +// +LLUrlEntryNoLink::LLUrlEntryNoLink() +{ +	mPattern = boost::regex("<nolink>[^[:space:]<]+</nolink>", +							boost::regex::perl|boost::regex::icase); +	mDisabledLink = true; +} + +std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ +	// return the text between the <nolink> and </nolink> tags +	return url.substr(8, url.size()-8-9); +} + diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 4adffde99c..94455ac247 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -91,6 +91,9 @@ public:  	/// Return the name of a SL location described by this Url, if any  	virtual std::string getLocation(const std::string &url) const { return ""; } +	/// is this a match for a URL that should not be hyperlinked? +	bool isLinkDisabled() const { return mDisabledLink; } +  protected:  	std::string getIDStringFromUrl(const std::string &url) const;  	std::string escapeUrl(const std::string &url) const; @@ -111,6 +114,7 @@ protected:  	std::string                                    	mTooltip;  	LLUIColor										mColor;  	std::multimap<std::string, LLUrlEntryObserver>	mObservers; +	bool                                            mDisabledLink;  };  /// @@ -267,4 +271,14 @@ public:  	/*virtual*/ std::string getLocation(const std::string &url) const;  }; +/// +/// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags +/// +class LLUrlEntryNoLink : public LLUrlEntryBase +{ +public: +	LLUrlEntryNoLink(); +	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); +}; +  #endif diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp index 3b47145a22..72a199c220 100644 --- a/indra/llui/llurlmatch.cpp +++ b/indra/llui/llurlmatch.cpp @@ -41,14 +41,17 @@ LLUrlMatch::LLUrlMatch() :  	mLabel(""),  	mTooltip(""),  	mIcon(""), -	mMenuName("") +	mMenuName(""), +	mLocation(""), +	mDisabledLink(false)  {  }  void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,  						   const std::string &label, const std::string &tooltip,  						   const std::string &icon, const LLUIColor& color, -						   const std::string &menu, const std::string &location) +						   const std::string &menu, const std::string &location, +						   bool disabled_link)  {  	mStart = start;  	mEnd = end; @@ -59,4 +62,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,  	mColor = color;  	mMenuName = menu;  	mLocation = location; +	mDisabledLink = disabled_link;  } diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h index 7f5767923a..e86762548b 100644 --- a/indra/llui/llurlmatch.h +++ b/indra/llui/llurlmatch.h @@ -83,11 +83,14 @@ public:  	/// return the SL location that this Url describes, or "" if none.  	std::string getLocation() const { return mLocation; } +	/// is this a match for a URL that should not be hyperlinked? +	bool isLinkDisabled() const { return mDisabledLink; } +  	/// Change the contents of this match object (used by LLUrlRegistry)  	void setValues(U32 start, U32 end, const std::string &url, const std::string &label,  	               const std::string &tooltip, const std::string &icon,  				   const LLUIColor& color, const std::string &menu,  -				   const std::string &location); +				   const std::string &location, bool disabled_link);  private:  	U32         mStart; @@ -99,6 +102,7 @@ private:  	std::string mMenuName;  	std::string mLocation;  	LLUIColor	mColor; +	bool        mDisabledLink;  };  #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index ad5c0911f8..55eb8950e9 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -44,6 +44,7 @@ void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)  LLUrlRegistry::LLUrlRegistry()  {  	// Urls are matched in the order that they were registered +	registerUrl(new LLUrlEntryNoLink());  	registerUrl(new LLUrlEntrySLURL());  	registerUrl(new LLUrlEntryHTTP());  	registerUrl(new LLUrlEntryHTTPLabel()); @@ -176,7 +177,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL  						match_entry->getIcon(),  						match_entry->getColor(),  						match_entry->getMenuName(), -						match_entry->getLocation(url)); +						match_entry->getLocation(url), +						match_entry->isLinkDisabled());  		return true;  	} @@ -204,9 +206,13 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr  		S32 end = start + wurl.size() - 1;  		match.setValues(start, end, match.getUrl(),  -			match.getLabel(), match.getTooltip(), -			match.getIcon(), match.getColor(), -			match.getMenuName(), match.getLocation()); +						match.getLabel(), +						match.getTooltip(), +						match.getIcon(), +						match.getColor(), +						match.getMenuName(), +						match.getLocation(), +						match.isLinkDisabled());  		return true;  	}  	return false; diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 80be8fcbf7..bc97cf3df2 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -33,7 +33,7 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa  	return LLUIColor();  } -LLUIColor::LLUIColor() {} +LLUIColor::LLUIColor() : mColorPtr(NULL) {}  namespace tut  { @@ -610,5 +610,13 @@ namespace tut  		testRegex("invalid .net URL", r,  				  "foo.netty",  				  ""); + +		testRegex("XML tags around URL [1]", r, +				  "<foo>secondlife.com</foo>", +				  "secondlife.com"); + +		testRegex("XML tags around URL [2]", r, +				  "<foo>secondlife.com/status?bar=1</foo>", +				  "secondlife.com/status?bar=1");  	}  } diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index e8cf135346..24a32de268 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -25,6 +25,7 @@  // link seam  LLUIColor::LLUIColor() +	: mColorPtr(NULL)  {}  namespace tut @@ -53,7 +54,7 @@ namespace tut  		LLUrlMatch match;  		ensure("empty()", match.empty()); -		match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", ""); +		match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false);  		ensure("! empty()", ! match.empty());  	} @@ -66,7 +67,7 @@ namespace tut  		LLUrlMatch match;  		ensure_equals("getStart() == 0", match.getStart(), 0); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getStart() == 10", match.getStart(), 10);  	} @@ -79,7 +80,7 @@ namespace tut  		LLUrlMatch match;  		ensure_equals("getEnd() == 0", match.getEnd(), 0); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getEnd() == 20", match.getEnd(), 20);  	} @@ -92,10 +93,10 @@ namespace tut  		LLUrlMatch match;  		ensure_equals("getUrl() == ''", match.getUrl(), ""); -		match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/"); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getUrl() == '' (2)", match.getUrl(), "");  	} @@ -108,10 +109,10 @@ namespace tut  		LLUrlMatch match;  		ensure_equals("getLabel() == ''", match.getLabel(), ""); -		match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false);  		ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label"); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getLabel() == '' (2)", match.getLabel(), "");  	} @@ -124,10 +125,10 @@ namespace tut  		LLUrlMatch match;  		ensure_equals("getTooltip() == ''", match.getTooltip(), ""); -		match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false);  		ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info"); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");  	} @@ -140,10 +141,10 @@ namespace tut  		LLUrlMatch match;  		ensure_equals("getIcon() == ''", match.getIcon(), ""); -		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false);  		ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon"); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure_equals("getIcon() == '' (2)", match.getIcon(), "");  	} @@ -156,10 +157,10 @@ namespace tut  		LLUrlMatch match;  		ensure("getMenuName() empty", match.getMenuName().empty()); -		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", ""); +		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false);  		ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml"); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure("getMenuName() empty (2)", match.getMenuName().empty());  	} @@ -172,10 +173,10 @@ namespace tut  		LLUrlMatch match;  		ensure("getLocation() empty", match.getLocation().empty()); -		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris"); +		match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false);  		ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris"); -		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", ""); +		match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);  		ensure("getLocation() empty (2)", match.getLocation().empty());  	}  } | 
