diff options
Diffstat (limited to 'indra/llui')
42 files changed, 624 insertions, 405 deletions
| diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index e2de4b9d3b..1fe64c472e 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -133,7 +133,7 @@ public:  	 */  	const LLAccordionCtrlTab* getExpandedTab() const; -	const LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; } +	LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; }  	bool getFitParent() const {return mFitParent;} diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 4e0537f592..b7da5f4a1b 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -353,6 +353,7 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)  	,mPaddingBottom(p.padding_bottom)  	,mCanOpenClose(true)  	,mFitPanel(p.fit_panel) +	,mSelectionEnabled(p.selection_enabled)  	,mContainerPanel(NULL)  	,mScrollbar(NULL)  { @@ -824,7 +825,7 @@ void LLAccordionCtrlTab::showAndFocusHeader()  {  	LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);	  	header->setFocus(true); -	header->setSelected(true); +	header->setSelected(mSelectionEnabled);  	LLRect screen_rc;  	LLRect selected_rc = header->getRect(); diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 8ae91ad651..d6ac8cbc8f 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -236,6 +236,8 @@ private:  	bool mStoredOpenCloseState;  	bool mWasStateStored; +	bool mSelectionEnabled; +  	LLScrollbar*	mScrollbar;  	LLView*			mContainerPanel; diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index ac5651e4b6..f0f34ebd4f 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -114,6 +114,7 @@ LLButton::LLButton(const LLButton::Params& p)  	mFlashing( FALSE ),  	mCurGlowStrength(0.f),  	mNeedsHighlight(FALSE), +	mMouseOver(false),  	mUnselectedLabel(p.label()),  	mSelectedLabel(p.label_selected()),  	mGLFont(p.font), @@ -498,7 +499,11 @@ void LLButton::onMouseEnter(S32 x, S32 y, MASK mask)  	LLUICtrl::onMouseEnter(x, y, mask);  	if (isInEnabledChain()) +	{  		mNeedsHighlight = TRUE; +	} + +	mMouseOver = true;  }  void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) @@ -506,6 +511,7 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)  	LLUICtrl::onMouseLeave(x, y, mask);  	mNeedsHighlight = FALSE; +	mMouseOver = true;  }  void LLButton::setHighlight(bool b) @@ -559,14 +565,10 @@ void LLButton::draw()  	}  	// Unselected image assignments -	S32 local_mouse_x; -	S32 local_mouse_y; -	LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); -  	bool enabled = isInEnabledChain();  	bool pressed = pressed_by_keyboard  -					|| (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) +					|| (hasMouseCapture() && mMouseOver)  					|| mForcePressedState;  	bool selected = getToggleState(); diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 2d5fefa78c..d87ceb7c42 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -350,6 +350,7 @@ private:  	BOOL						mCommitOnReturn;  	BOOL						mFadeWhenDisabled;  	bool						mForcePressedState; +	bool						mMouseOver;  	LLFrameTimer				mFlashingTimer;  }; diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index eb8b423b29..0a10877c09 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -29,12 +29,13 @@  #include <map>  #include <string> +#include <boost/function.hpp>  class LLCallbackMap  {  public:  	// callback definition. -	typedef void* (*callback_t)(void* data); +	typedef boost::function<void* (void* data)> callback_t;  	typedef std::map<std::string, LLCallbackMap> map_t;  	typedef map_t::iterator map_iter_t; diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index bf55239f1b..ca2dc644a4 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -43,12 +43,13 @@ void LLDockableFloater::init(LLDockableFloater* thiz)  	thiz->setCanClose(TRUE);  	thiz->setCanDock(true);  	thiz->setCanMinimize(TRUE); +	thiz->setOverlapsScreenChannel(false); +	thiz->mForceDocking = false;  }  LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,  		const LLSD& key, const Params& params) :  	LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true) -	, mOverlapsScreenChannel(false)  {  	init(this);  	mUseTongue = true; @@ -75,6 +76,12 @@ LLDockableFloater::~LLDockableFloater()  BOOL LLDockableFloater::postBuild()  { +	// Remember we should force docking when the floater is opened for the first time +	if (mIsDockedStateForcedCallback != NULL && mIsDockedStateForcedCallback()) +	{ +		mForceDocking = true; +	} +  	mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");  	LLFloater::setDocked(true);  	return LLView::postBuild(); @@ -128,6 +135,14 @@ void LLDockableFloater::resetInstance()  void LLDockableFloater::setVisible(BOOL visible)  { +	// Force docking if requested +	if (visible && mForceDocking) +	{ +		setCanDock(true); +		setDocked(true); +		mForceDocking = false; +	} +  	if(visible && isDocked())  	{  		resetInstance(); diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 86dcf670b1..8deb6c1159 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -124,6 +124,10 @@ protected:  	void setDockControl(LLDockControl* dockControl);  	const LLUIImagePtr& getDockTongue(); +	// Checks if docking should be forced. +	// It may be useful e.g. if floater created in mouselook mode (see EXT-5609) +	boost::function<BOOL ()> mIsDockedStateForcedCallback; +  private:  	std::auto_ptr<LLDockControl> mDockControl;  	LLUIImagePtr mDockTongue; @@ -137,6 +141,9 @@ private:  	bool mUseTongue;  	bool mOverlapsScreenChannel; + +	// Force docking when the floater is being shown for the first time. +	bool mForceDocking;  };  #endif /* LL_DOCKABLEFLOATER_H */ diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 9ad7c01bd5..42e6c3c786 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -107,7 +107,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 +		params.parse_urls = 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 b28399a36b..c57c02f4b1 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -607,8 +607,14 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)  		return;  	} -	if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(); +	//no need to do additional commit on selection reset +	if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(true); + +	//only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it +	if (mask & MASK_CONTROL)  	selectItemPair(item_pair, select_item); +	else +		selectItemPair(item_pair, true);  }  void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask) @@ -660,6 +666,14 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)  			}  			break;  		} +		case KEY_ESCAPE: +		{ +			if (mask == MASK_NONE) +			{ +				setFocus(FALSE); // pass focus to the game area (EXT-8357) +			} +			break; +		}  		default:  			break;  	} @@ -775,6 +789,18 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)  	return true;  } +void LLFlatListView::scrollToShowFirstSelectedItem() +{ +	if (!mSelectedItemPairs.size())	return; + +	LLRect selected_rc = mSelectedItemPairs.front()->first->getRect(); + +	if (selected_rc.isValid()) +	{ +		scrollToShowRect(selected_rc); +	} +} +  LLRect LLFlatListView::getLastSelectedItemRect()  {  	if (!mSelectedItemPairs.size()) diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index afd0176d98..0515853698 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -292,6 +292,7 @@ public:  	bool updateValue(const LLSD& old_value, const LLSD& new_value); +	void scrollToShowFirstSelectedItem();  	void selectFirstItem	();  	void selectLastItem		(); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 3cfb2c5d4a..e1203971ea 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2279,6 +2279,7 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)  	S32 floater_header_size = default_params.header_height;  	static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);  	LLRect snap_rect_local = getLocalSnapRect(); +	snap_rect_local.mTop += mMinimizePositionVOffset;  	for(S32 col = snap_rect_local.mLeft;  		col < snap_rect_local.getWidth() - minimized_width;  		col += minimized_width) @@ -2376,6 +2377,19 @@ BOOL LLFloaterView::allChildrenClosed()  	return true;  } +void LLFloaterView::shiftFloaters(S32 x_offset, S32 y_offset) +{ +	for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) +	{ +		LLFloater* floaterp = dynamic_cast<LLFloater*>(*it); + +		if (floaterp && floaterp->isMinimized()) +		{ +			floaterp->translate(x_offset, y_offset); +		} +	} +} +  void LLFloaterView::refresh()  {  	// Constrain children to be entirely on the screen diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 2deae29607..5e482cbac3 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -449,6 +449,7 @@ public:  	// Given a child of gFloaterView, make sure this view can fit entirely onscreen.  	void			adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside); +	void			setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; }  	void			getMinimizePosition( S32 *left, S32 *bottom);  	void			restoreAll();		// un-minimize all floaters  	typedef std::set<LLView*> skip_list_t; @@ -465,6 +466,7 @@ public:  	// attempt to close all floaters  	void			closeAllChildren(bool app_quitting);  	BOOL			allChildrenClosed(); +	void			shiftFloaters(S32 x_offset, S32 y_offset);  	LLFloater* getFrontmost() const;  	LLFloater* getBackmost() const; @@ -484,6 +486,7 @@ private:  	BOOL			mFocusCycleMode;  	S32				mSnapOffsetBottom;  	S32				mSnapOffsetRight; +	S32				mMinimizePositionVOffset;  };  // diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp index 1a311bb13a..6841301219 100644 --- a/indra/llui/lllocalcliprect.cpp +++ b/indra/llui/lllocalcliprect.cpp @@ -27,33 +27,8 @@  #include "lllocalcliprect.h"  #include "llfontgl.h" -#include "llgl.h"  #include "llui.h" -#include <stack> - -//--------------------------------------------------------------------------- -// LLScreenClipRect -// implementation class in screen space -//--------------------------------------------------------------------------- -class LLScreenClipRect -{ -public: -	LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE); -	virtual ~LLScreenClipRect(); - -private: -	static void pushClipRect(const LLRect& rect); -	static void popClipRect(); -	static void updateScissorRegion(); - -private: -	LLGLState		mScissorState; -	BOOL			mEnabled; - -	static std::stack<LLRect> sClipRectStack; -}; -  /*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack; @@ -64,9 +39,9 @@ LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled)  	if (mEnabled)  	{  		pushClipRect(rect); +		mScissorState.setEnabled(!sClipRectStack.empty()); +		updateScissorRegion();  	} -	mScissorState.setEnabled(!sClipRectStack.empty()); -	updateScissorRegion();  }  LLScreenClipRect::~LLScreenClipRect() @@ -74,8 +49,8 @@ LLScreenClipRect::~LLScreenClipRect()  	if (mEnabled)  	{  		popClipRect(); +		updateScissorRegion();  	} -	updateScissorRegion();  }  //static  @@ -125,16 +100,11 @@ void LLScreenClipRect::updateScissorRegion()  // LLLocalClipRect  //---------------------------------------------------------------------------  LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */) -{ -	LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX,  -		rect.mTop + LLFontGL::sCurOrigin.mY,  -		rect.mRight + LLFontGL::sCurOrigin.mX,  -		rect.mBottom + LLFontGL::sCurOrigin.mY); -	mScreenClipRect = new LLScreenClipRect(screen, enabled); -} +:	LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,  +					rect.mTop + LLFontGL::sCurOrigin.mY,  +					rect.mRight + LLFontGL::sCurOrigin.mX,  +					rect.mBottom + LLFontGL::sCurOrigin.mY), enabled) +{}  LLLocalClipRect::~LLLocalClipRect() -{ -	delete mScreenClipRect; -	mScreenClipRect = NULL; -} +{} diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h index 0097958916..eeeaf2adb6 100644 --- a/indra/llui/lllocalcliprect.h +++ b/indra/llui/lllocalcliprect.h @@ -25,7 +25,9 @@  #ifndef LLLOCALCLIPRECT_H  #define LLLOCALCLIPRECT_H +#include "llgl.h"  #include "llrect.h"		// can't forward declare, it's templated +#include <stack>  // Clip rendering to a specific rectangle using GL scissor  // Just create one of these on the stack: @@ -33,15 +35,29 @@  //     LLLocalClipRect(rect);  //     draw();  // } -class LLLocalClipRect +class LLScreenClipRect  {  public: -	LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); -	~LLLocalClipRect(); +	LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE); +	virtual ~LLScreenClipRect(); + +private: +	static void pushClipRect(const LLRect& rect); +	static void popClipRect(); +	static void updateScissorRegion();  private: -	// implementation class -	class LLScreenClipRect* mScreenClipRect; +	LLGLState		mScissorState; +	BOOL			mEnabled; + +	static std::stack<LLRect> sClipRectStack; +}; + +class LLLocalClipRect : public LLScreenClipRect +{ +public: +	LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE); +	~LLLocalClipRect();  };  #endif diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index c533610381..3e652ea960 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -52,6 +52,7 @@  #include "llbutton.h"  #include "llfontgl.h"  #include "llresmgr.h" +#include "lltrans.h"  #include "llui.h"  #include "llstl.h" @@ -2266,8 +2267,9 @@ void LLMenuGL::createSpilloverBranch()  		// technically, you can't tear off spillover menus, but we're passing the handle  		// along just to be safe  		LLMenuGL::Params p; +		std::string label = LLTrans::getString("More");  		p.name("More"); -		p.label("More"); // *TODO: Translate +		p.label(label);  		p.bg_color(mBackgroundColor);  		p.bg_visible(true);  		p.can_tear_off(false); @@ -2276,7 +2278,7 @@ void LLMenuGL::createSpilloverBranch()  		LLMenuItemBranchGL::Params branch_params;  		branch_params.name = "More"; -		branch_params.label = "More"; // *TODO: Translate +		branch_params.label = label;  		branch_params.branch = mSpilloverMenu;  		branch_params.font.style = "italic"; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 6fe36bbc0c..b2e08c48c5 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -655,7 +655,7 @@ void LLPanel::childSetEnabled(const std::string& id, bool enabled)  void LLPanel::childSetTentative(const std::string& id, bool tentative)  { -	LLView* child = findChild<LLView>(id); +	LLUICtrl* child = findChild<LLUICtrl>(id);  	if (child)  	{  		child->setTentative(tentative); @@ -854,13 +854,16 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const  	return NULL;  } -static LLPanel *childGetVisibleTabWithHelp(LLView *parent) +LLPanel* LLPanel::childGetVisibleTabWithHelp()  {  	LLView *child; -	// look through immediate children first for an active tab with help -	for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child)) +	bfs_tree_iterator_t it = beginTreeBFS(); +	// skip ourselves +	++it; +	for (; it != endTreeBFS(); ++it)  	{ +		child = *it;  		LLPanel *curTabPanel = NULL;  		// do we have a tab container? @@ -884,36 +887,21 @@ static LLPanel *childGetVisibleTabWithHelp(LLView *parent)  		}  	} -	// then try a bit harder and recurse through all children -	for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child)) -	{ -		if (child->getVisible()) -		{ -			LLPanel* tab = ::childGetVisibleTabWithHelp(child); -			if (tab) -			{ -				return tab; -			} -		} -	} -  	// couldn't find any active tabs with a help topic string  	return NULL;  } -LLPanel *LLPanel::childGetVisibleTabWithHelp() -{ -	// find a visible tab with a help topic (to determine help context) -	return ::childGetVisibleTabWithHelp(this); -} -static LLPanel *childGetVisiblePanelWithHelp(LLView *parent) +LLPanel *LLPanel::childGetVisiblePanelWithHelp()  {  	LLView *child; -	// look through immediate children first for an active panel with help -	for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child)) +	bfs_tree_iterator_t it = beginTreeBFS(); +	// skip ourselves +	++it; +	for (; it != endTreeBFS(); ++it)  	{ +		child = *it;  		// do we have a panel with a help topic?  		LLPanel *panel = dynamic_cast<LLPanel *>(child);  		if (panel && panel->getVisible() && !panel->getHelpTopic().empty()) @@ -922,39 +910,19 @@ static LLPanel *childGetVisiblePanelWithHelp(LLView *parent)  		}  	} -	// then try a bit harder and recurse through all children -	for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child)) -	{ -		if (child->getVisible()) -		{ -			LLPanel* panel = ::childGetVisiblePanelWithHelp(child); -			if (panel) -			{ -				return panel; -			} -		} -	} -  	// couldn't find any active panels with a help topic string  	return NULL;  } -LLPanel *LLPanel::childGetVisiblePanelWithHelp() +void LLPanel::childSetAction(const std::string& id, const commit_signal_t::slot_type& function)  { -	// find a visible tab with a help topic (to determine help context) -	return ::childGetVisiblePanelWithHelp(this); -} - -void LLPanel::childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) ) -{ -	LLLineEditor* child = findChild<LLLineEditor>(id); -	if (child) +	LLButton* button = findChild<LLButton>(id); +	if (button)  	{ -		child->setPrevalidate(func); +		button->setClickedCallback(function);  	}  } -  void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value)  {  	LLButton* button = findChild<LLButton>(id); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index ca8bb77b77..a7224648c1 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -164,6 +164,7 @@ public:  	std::string getString(const std::string& name) const;  	// ** Wrappers for setting child properties by name ** -TomY +	// WARNING: These are deprecated, please use getChild<T>("name")->doStuff() idiom instead  	// LLView  	void childSetVisible(const std::string& name, bool visible); @@ -227,7 +228,8 @@ public:  	void childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) );  	// LLButton -	void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value = NULL); +	void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value); +	void childSetAction(const std::string& id, const commit_signal_t::slot_type& function);  	// LLTextBox  	void childSetActionTextbox(const std::string& id, boost::function<void(void*)> function, void* value = NULL); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 3f4ab0fbc8..84e438cfb7 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -129,6 +129,7 @@ LLScrollListCtrl::Params::Params()  	search_column("search_column", 0),  	sort_column("sort_column", -1),  	sort_ascending("sort_ascending", true), +	mouse_wheel_opaque("mouse_wheel_opaque", false),  	commit_on_keyboard_movement("commit_on_keyboard_movement", true),  	heading_height("heading_height"),  	page_lines("page_lines", 0), @@ -157,6 +158,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)  :	LLUICtrl(p),  	mLineHeight(0),  	mScrollLines(0), +	mMouseWheelOpaque(p.mouse_wheel_opaque),  	mPageLines(p.page_lines),  	mMaxSelectable(0),  	mAllowKeyboardMovement(TRUE), @@ -1530,6 +1532,12 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)  	BOOL handled = FALSE;  	// Pretend the mouse is over the scrollbar  	handled = mScrollbar->handleScrollWheel( 0, 0, clicks ); + +	if (mMouseWheelOpaque) +	{ +		return TRUE; +	} +  	return handled;  } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 30618866af..8a2f893ba2 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -96,7 +96,8 @@ public:  	{  		// behavioral flags  		Optional<bool>	multi_select, -						commit_on_keyboard_movement; +						commit_on_keyboard_movement, +						mouse_wheel_opaque;  		// display flags  		Optional<bool>	has_border, @@ -443,6 +444,7 @@ private:  	BOOL			mCommitOnSelectionChange;  	BOOL			mSelectionChanged;  	BOOL			mNeedsScroll; +	BOOL			mMouseWheelOpaque;  	BOOL			mCanSelect;  	const BOOL		mDisplayColumnHeaders;  	BOOL			mColumnsDirty; diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 904c458e85..d760178e35 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -229,6 +229,10 @@ void LLSliderCtrl::updateText()  		std::string text = llformat(format.c_str(), displayed_value);  		if( mEditor )  		{ +			// Setting editor text here to "" before using actual text is here because if text which +			// is set is the same as the one which is actually typed into lineeditor, LLLineEditor::setText() +			// will exit at it's beginning, so text for revert on escape won't be saved. (EXT-8536) +			mEditor->setText( LLStringUtil::null );  			mEditor->setText( text );  		}  		else diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp index 93314d7bc0..5e09cee78b 100644 --- a/indra/llui/llstyle.cpp +++ b/indra/llui/llstyle.cpp @@ -36,6 +36,8 @@ LLStyle::Params::Params()  :	visible("visible", true),  	drop_shadow("drop_shadow", LLFontGL::NO_SHADOW),  	color("color", LLColor4::black), +	readonly_color("readonly_color", LLColor4::black), +	selected_color("selected_color", LLColor4::black),  	font("font", LLFontGL::getFontMonospace()),  	image("image"),  	link_href("href") @@ -43,12 +45,10 @@ LLStyle::Params::Params()  LLStyle::LLStyle(const LLStyle::Params& p) -:	mItalic(FALSE), -	mBold(FALSE), -	mUnderline(FALSE), -	mVisible(p.visible), -	mColor(p.color()), -	mReadOnlyColor(p.readonly_color()), +:	mVisible(p.visible), +	mColor(p.color), +	mReadOnlyColor(p.readonly_color), +	mSelectedColor(p.selected_color),  	mFont(p.font()),  	mLink(p.link_href),  	mDropShadow(p.drop_shadow), diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h index bfd0d72e85..66cd639936 100644 --- a/indra/llui/llstyle.h +++ b/indra/llui/llstyle.h @@ -41,7 +41,8 @@ public:  		Optional<bool>					visible;  		Optional<LLFontGL::ShadowType>	drop_shadow;  		Optional<LLUIColor>				color, -										readonly_color; +										readonly_color, +										selected_color;  		Optional<const LLFontGL*>		font;  		Optional<LLUIImage*>			image;  		Optional<std::string>			link_href; @@ -49,11 +50,14 @@ public:  	};  	LLStyle(const Params& p = Params());  public: -	const LLColor4& getColor() const { return mColor; } -	void setColor(const LLColor4 &color) { mColor = color; } +	const LLUIColor& getColor() const { return mColor; } +	void setColor(const LLUIColor &color) { mColor = color; } -	const LLColor4& getReadOnlyColor() const { return mReadOnlyColor; } -	void setReadOnlyColor(const LLColor4& color) { mReadOnlyColor = color; } +	const LLUIColor& getReadOnlyColor() const { return mReadOnlyColor; } +	void setReadOnlyColor(const LLUIColor& color) { mReadOnlyColor = color; } + +	const LLUIColor& getSelectedColor() const { return mSelectedColor; } +	void setSelectedColor(const LLUIColor& color) { mSelectedColor = color; }  	BOOL isVisible() const;  	void setVisible(BOOL is_visible); @@ -73,41 +77,36 @@ public:  	BOOL isImage() const { return mImagep.notNull(); } -	// inlined here to make it easier to compare to member data below. -MG  	bool operator==(const LLStyle &rhs) const  	{  		return   			mVisible == rhs.mVisible  			&& mColor == rhs.mColor  			&& mReadOnlyColor == rhs.mReadOnlyColor +			&& mSelectedColor == rhs.mSelectedColor  			&& mFont == rhs.mFont  			&& mLink == rhs.mLink  			&& mImagep == rhs.mImagep -			&& mItalic == rhs.mItalic -			&& mBold == rhs.mBold -			&& mUnderline == rhs.mUnderline  			&& mDropShadow == rhs.mDropShadow;  	}  	bool operator!=(const LLStyle& rhs) const { return !(*this == rhs); }  public:	 -	BOOL        mItalic; -	BOOL        mBold; -	BOOL        mUnderline;  	LLFontGL::ShadowType		mDropShadow;  protected:  	~LLStyle() { }  private: -	BOOL		mVisible; -	LLUIColor	mColor; -	LLUIColor   mReadOnlyColor; -	std::string	mFontName; -	const LLFontGL*   mFont;		// cached for performance -	std::string	mLink; -	LLUIImagePtr mImagep; +	BOOL				mVisible; +	LLUIColor			mColor; +	LLUIColor   		mReadOnlyColor; +	LLUIColor			mSelectedColor; +	std::string			mFontName; +	const LLFontGL*		mFont; +	std::string			mLink; +	LLUIImagePtr		mImagep;  };  typedef LLPointer<LLStyle> LLStyleSP; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 60c313b6ce..574b24cf13 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -149,6 +149,8 @@ LLTextBase::Params::Params()  	bg_readonly_color("bg_readonly_color"),  	bg_writeable_color("bg_writeable_color"),  	bg_focus_color("bg_focus_color"), +	text_selected_color("text_selected_color"), +	bg_selected_color("bg_selected_color"),  	allow_scroll("allow_scroll", true),  	plain_text("plain_text",false),  	track_end("track_end", false), @@ -161,11 +163,12 @@ LLTextBase::Params::Params()  	font_shadow("font_shadow"),  	wrap("wrap"),  	use_ellipses("use_ellipses", false), -	allow_html("allow_html", false), +	parse_urls("parse_urls", false),  	parse_highlights("parse_highlights", false)  {  	addSynonym(track_end, "track_bottom");  	addSynonym(wrap, "word_wrap"); +	addSynonym(parse_urls, "allow_html");  } @@ -184,6 +187,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  	mWriteableBgColor(p.bg_writeable_color),  	mReadOnlyBgColor(p.bg_readonly_color),  	mFocusBgColor(p.bg_focus_color), +	mTextSelectedColor(p.text_selected_color), +	mSelectedBGColor(p.bg_selected_color),  	mReflowIndex(S32_MAX),  	mCursorPos( 0 ),  	mScrollNeeded(FALSE), @@ -203,7 +208,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  	mPlainText ( p.plain_text ),  	mWordWrap(p.wrap),  	mUseEllipses( p.use_ellipses ), -	mParseHTML(p.allow_html), +	mParseHTML(p.parse_urls),  	mParseHighlights(p.parse_highlights),  	mBGVisible(p.bg_visible),  	mScroller(NULL), @@ -263,9 +268,6 @@ void LLTextBase::initFromParams(const LLTextBase::Params& p)  	{  		mReadOnly = p.read_only;  	} - -	// HACK:  text editors always need to be enabled so that we can scroll -	LLView::setEnabled(true);  }  bool LLTextBase::truncate() @@ -295,11 +297,14 @@ bool LLTextBase::truncate()  const LLStyle::Params& LLTextBase::getDefaultStyleParams()  { +	//FIXME: convert mDefaultStyle to a flyweight http://www.boost.org/doc/libs/1_40_0/libs/flyweight/doc/index.html +	//and eliminate color member values  	if (mStyleDirty)  	{  		  mDefaultStyle -				  .color(LLUIColor(&mFgColor)) +				  .color(LLUIColor(&mFgColor))						// pass linked color instead of copy of mFGColor  				  .readonly_color(LLUIColor(&mReadOnlyFgColor)) +				  .selected_color(LLUIColor(&mTextSelectedColor))  				  .font(mDefaultFont)  				  .drop_shadow(mFontShadow);  		  mStyleDirty = false; @@ -397,7 +402,7 @@ void LLTextBase::drawSelectionBackground()  		// Draw the selection box (we're using a box instead of reversing the colors on the selected text).  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		const LLColor4& color = mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get(); +		const LLColor4& color = mSelectedBGColor;  		F32 alpha = hasFocus() ? 0.7f : 0.3f;  		alpha *= getDrawContext().mAlpha;  		LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha); @@ -437,7 +442,6 @@ void LLTextBase::drawCursor()  		}  		else  		{ -			//segmentp = mSegments.back();  			return;  		} @@ -471,21 +475,8 @@ void LLTextBase::drawCursor()  			{  				LLColor4 text_color;  				const LLFontGL* fontp; -				if (segmentp) -				{  					text_color = segmentp->getColor();  					fontp = segmentp->getStyle()->getFont(); -				} -				else if (mReadOnly) -				{ -					text_color = mReadOnlyFgColor.get(); -					fontp = mDefaultFont; -				} -				else -				{ -					text_color = mFgColor.get(); -					fontp = mDefaultFont; -				}  				fontp->render(text, mCursorPos, cursor_rect,   					LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),  					LLFontGL::LEFT, mVAlign, @@ -1015,21 +1006,26 @@ void LLTextBase::draw()  	if (mBGVisible)  	{  		// clip background rect against extents, if we support scrolling -		LLLocalClipRect clip(doc_rect, mScroller != NULL); - +		LLRect bg_rect = mVisibleTextRect; +		if (mScroller) +		{ +			bg_rect.intersectWith(doc_rect); +		}  		LLColor4 bg_color = mReadOnly   							? mReadOnlyBgColor.get()  							: hasFocus()   								? mFocusBgColor.get()   								: mWriteableBgColor.get(); -		gl_rect_2d(mVisibleTextRect, bg_color, TRUE); +		gl_rect_2d(doc_rect, bg_color, TRUE);  	}  	// draw document view  	LLUICtrl::draw();  	{ -		// only clip if we support scrolling (mScroller != NULL) +		// only clip if we support scrolling... +		// since convention is that text boxes never vertically truncate their contents +		// regardless of rect bounds  		LLLocalClipRect clip(doc_rect, mScroller != NULL);  		drawSelectionBackground();  		drawText(); @@ -1493,23 +1489,32 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg  LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)  { +	static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); +  	if (index > getLength()) { return mSegments.end(); }  	// when there are no segments, we return the end iterator, which must be checked by caller  	if (mSegments.size() <= 1) { return mSegments.begin(); } -	segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index)); +	//FIXME: avoid operator new somehow (without running into refcount problems) +	index_segment->setStart(index); +	index_segment->setEnd(index); +	segment_set_t::iterator it = mSegments.upper_bound(index_segment);  	return it;  }  LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 index) const  { +	static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); +  	if (index > getLength()) { return mSegments.end(); }  	// when there are no segments, we return the end iterator, which must be checked by caller  	if (mSegments.size() <= 1) { return mSegments.begin(); } -	LLTextBase::segment_set_t::const_iterator it =  mSegments.upper_bound(new LLIndexSegment(index)); +	index_segment->setStart(index); +	index_segment->setEnd(index); +	LLTextBase::segment_set_t::const_iterator it =  mSegments.upper_bound(index_segment);  	return it;  } @@ -1611,9 +1616,6 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  		while ( LLUrlRegistry::instance().findUrl(text, match,  		        boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )  		{ -			 -			LLTextUtil::processUrlMatch(&match,this); -  			start = match.getStart();  			end = match.getEnd()+1; @@ -1638,6 +1640,10 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  				std::string subtext=text.substr(0,start);  				appendAndHighlightText(subtext, part, style_params);   			} + +			// inserts an avatar icon preceding the Url if appropriate +			LLTextUtil::processUrlMatch(&match,this); +  			// output the styled Url (unless we've been asked to suppress hyperlinking)  			if (match.isLinkDisabled())  			{ @@ -1645,7 +1651,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  			}  			else  			{ -				appendAndHighlightText(match.getLabel(), part, link_params); +				appendAndHighlightText(match.getLabel(), part, link_params, match.underlineOnHoverOnly());  				// set the tooltip for the Url label  				if (! match.getTooltip().empty()) @@ -1728,7 +1734,7 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s  	insertStringNoUndo(getLength(), widget_wide_text, &segments);  } -void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params) +void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)  {  	// Save old state  	S32 selection_start = mSelectionStart; @@ -1759,7 +1765,17 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig  			S32 cur_length = getLength();  			LLStyleConstSP sp(new LLStyle(highlight_params)); -			LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); +			LLTextSegmentPtr segmentp; +			if(underline_on_hover_only) +			{ +				highlight_params.font.style("NORMAL"); +				LLStyleConstSP normal_sp(new LLStyle(highlight_params)); +				segmentp = new LLOnHoverChangeableTextSegment(sp, normal_sp, cur_length, cur_length + wide_text.size(), *this); +			} +			else +			{ +				segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this); +			}  			segment_vec_t segments;  			segments.push_back(segmentp);  			insertStringNoUndo(cur_length, wide_text, &segments); @@ -1774,7 +1790,17 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig  		S32 segment_start = old_length;  		S32 segment_end = old_length + wide_text.size();  		LLStyleConstSP sp(new LLStyle(style_params)); +		if (underline_on_hover_only) +		{ +			LLStyle::Params normal_style_params(style_params); +			normal_style_params.font.style("NORMAL"); +			LLStyleConstSP normal_sp(new LLStyle(normal_style_params)); +			segments.push_back(new LLOnHoverChangeableTextSegment(sp, normal_sp, segment_start, segment_end, *this )); +		} +		else +		{  		segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this )); +		}  		insertStringNoUndo(getLength(), wide_text, &segments);  	} @@ -1798,7 +1824,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig  	}  } -void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params) +void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)  {  	if (new_text.empty()) return;  @@ -1810,7 +1836,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig  		if(pos!=start)  		{  			std::string str = std::string(new_text,start,pos-start); -			appendAndHighlightTextImpl(str,highlight_part, style_params); +			appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);  		}  		appendLineBreakSegment(style_params);  		start = pos+1; @@ -1818,7 +1844,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig  	}  	std::string str = std::string(new_text,start,new_text.length()-start); -	appendAndHighlightTextImpl(str,highlight_part, style_params); +	appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);  } @@ -2272,6 +2298,7 @@ void LLTextBase::updateRects()  	// allow horizontal scrolling?  	// if so, use entire width of text contents  	// otherwise, stop at width of mVisibleTextRect +	//FIXME: consider use of getWordWrap() instead  	doc_rect.mRight = mScroller   		? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)  		: mVisibleTextRect.getWidth(); @@ -2481,7 +2508,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele  		font->render(text, start,   			     rect, -			     LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), +			     mStyle->getSelectedColor().get(),  			     LLFontGL::LEFT, mEditor.mVAlign,   			     LLFontGL::NORMAL,   			     LLFontGL::NO_SHADOW,  @@ -2678,6 +2705,33 @@ void LLNormalTextSegment::dump() const  		llendl;  } +// +// LLOnHoverChangeableTextSegment +// + +LLOnHoverChangeableTextSegment::LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor ): +	  LLNormalTextSegment(normal_style, start, end, editor), +	  mHoveredStyle(style), +	  mNormalStyle(normal_style){} + +/*virtual*/  +F32 LLOnHoverChangeableTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) +{ +	F32 result = LLNormalTextSegment::draw(start, end, selection_start, selection_end, draw_rect); +	if (end == mEnd - mStart) +	{ +		mStyle = mNormalStyle; +	} +	return result; +} + +/*virtual*/ +BOOL LLOnHoverChangeableTextSegment::handleHover(S32 x, S32 y, MASK mask) +{ +	mStyle = mHoveredStyle; +	return LLNormalTextSegment::handleHover(x, y, mask); +} +  //  // LLInlineViewSegment diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 86ab8f357d..e5dfecad54 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -139,10 +139,25 @@ protected:  	boost::signals2::connection mImageLoadedConnection;  }; +// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment) +class LLOnHoverChangeableTextSegment : public LLNormalTextSegment +{ +public: +	LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor ); +	/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); +	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); +protected: +	// Style used for text when mouse pointer is over segment +	LLStyleConstSP		mHoveredStyle; +	// Style used for text when mouse pointer is outside segment +	LLStyleConstSP		mNormalStyle; + +}; +  class LLIndexSegment : public LLTextSegment  {  public: -	LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {} +	LLIndexSegment() : LLTextSegment(0, 0) {}  };  class LLInlineViewSegment : public LLTextSegment @@ -235,7 +250,9 @@ public:  								text_readonly_color,  								bg_readonly_color,  								bg_writeable_color, -								bg_focus_color; +								bg_focus_color, +								text_selected_color, +								bg_selected_color;  		Optional<bool>			bg_visible,  								border_visible, @@ -245,7 +262,7 @@ public:  								plain_text,  								wrap,  								use_ellipses, -								allow_html, +								parse_urls,  								parse_highlights,  								clip_partial; @@ -435,7 +452,7 @@ protected:  	S32								insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted  	S32 							removeStringNoUndo(S32 pos, S32 length);  	S32								overwriteCharNoUndo(S32 pos, llwchar wc); -	void							appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep); +	void							appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false);  	// manage segments  @@ -478,7 +495,7 @@ protected:  	void							replaceUrlLabel(const std::string &url, const std::string &label);  	void							appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); -	void							appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params); +	void							appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);  protected: @@ -501,6 +518,8 @@ protected:  	LLUIColor					mWriteableBgColor;  	LLUIColor					mReadOnlyBgColor;  	LLUIColor					mFocusBgColor; +	LLUIColor					mTextSelectedColor; +	LLUIColor					mSelectedBGColor;  	// cursor  	S32							mCursorPos;			// I-beam is just after the mCursorPos-th character. diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 3e2422c88b..6a905b7ec0 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -113,6 +113,17 @@ BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)  	return handled;  } +void LLTextBox::setEnabled(BOOL enabled) +{ +	// just treat enabled as read-only flag +	bool read_only = !enabled; +	if (read_only != mReadOnly) +	{ +		LLTextBase::setReadOnly(read_only); +		updateSegments(); +	} +} +  void LLTextBox::setText(const LLStringExplicit& text , const LLStyle::Params& input_params )  {  	// does string argument insertion diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 4634dd0ff2..071e18c638 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -52,6 +52,8 @@ public:  	/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); +	/*virtual*/ void setEnabled(BOOL enabled); +  	/*virtual*/ void setText( const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params() );  	void			setRightAlign()							{ mHAlign = LLFontGL::RIGHT; } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index e09df60704..94bf716e7d 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -283,6 +283,9 @@ void LLTextEditor::initFromParams( const LLTextEditor::Params& p)  {  	LLTextBase::initFromParams(p); +	// HACK:  text editors always need to be enabled so that we can scroll +	LLView::setEnabled(true); +  	if (p.commit_on_focus_lost.isProvided())  	{  		mCommitOnFocusLost = p.commit_on_focus_lost; @@ -452,8 +455,13 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const  const LLTextSegmentPtr	LLTextEditor::getPreviousSegment() const  { +	static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment; + +	index_segment->setStart(mCursorPos); +	index_segment->setEnd(mCursorPos); +  	// find segment index at character to left of cursor (or rightmost edge of selection) -	segment_set_t::const_iterator it = mSegments.lower_bound(new LLIndexSegment(mCursorPos)); +	segment_set_t::const_iterator it = mSegments.lower_bound(index_segment);  	if (it != mSegments.end())  	{ diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp index d7260369ec..4b9faa0560 100644 --- a/indra/llui/lltextvalidate.cpp +++ b/indra/llui/lltextvalidate.cpp @@ -44,6 +44,7 @@ namespace LLTextValidate  		declare("alpha_num_space", validateAlphaNumSpace);  		declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);  		declare("ascii_printable_no_space", validateASCIIPrintableNoSpace); +		declare("ascii_with_newline", validateASCIIWithNewLine);  	}  	// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. @@ -293,4 +294,21 @@ namespace LLTextValidate  		}  		return rv;  	} + +	// Used for multiline text stored on the server. +	// Example is landmark description in Places SP. +	bool validateASCIIWithNewLine(const LLWString &str) +	{ +		bool rv = TRUE; +		S32 len = str.length(); +		while(len--) +		{ +			if (str[len] < 0x20 && str[len] != 0xA || str[len] > 0x7f) +			{ +				rv = FALSE; +				break; +			} +		} +		return rv; +	}  } diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h index 1b61eca051..84644be30c 100644 --- a/indra/llui/lltextvalidate.h +++ b/indra/llui/lltextvalidate.h @@ -51,6 +51,7 @@ namespace LLTextValidate  	bool	validateASCIIPrintableNoPipe(const LLWString &str);   	bool	validateASCIIPrintableNoSpace(const LLWString &str);  	bool	validateASCII(const LLWString &str); +	bool	validateASCIIWithNewLine(const LLWString &str);  } diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 8ab4a119e5..b02d3122fe 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -180,7 +180,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)  	params.font = p.font;  	params.use_ellipses = true;  	params.wrap = p.wrap; -	params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips +	params.parse_urls = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips  	mTextBox = LLUICtrlFactory::create<LLTextBox> (params);  	addChild(mTextBox); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 03223b45f7..d33d8e3178 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -460,7 +460,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border  	gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);  } -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect) +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect)  {  	stop_glerror(); @@ -470,36 +470,53 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex  		return;  	} +	// add in offset of current image to current ui translation +	const LLVector3 ui_scale = gGL.getUIScale(); +	const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); + +	F32 uv_width = uv_outer_rect.getWidth(); +	F32 uv_height = uv_outer_rect.getHeight(); +  	// shrink scaling region to be proportional to clipped image region -	LLRectf scale_rect_uv( -		uv_rect.mLeft + (scale_rect.mLeft * uv_rect.getWidth()), -		uv_rect.mBottom + (scale_rect.mTop * uv_rect.getHeight()), -		uv_rect.mLeft + (scale_rect.mRight * uv_rect.getWidth()), -		uv_rect.mBottom + (scale_rect.mBottom * uv_rect.getHeight())); - -	S32 image_natural_width = llround((F32)image->getWidth(0) * uv_rect.getWidth()); -	S32 image_natural_height = llround((F32)image->getHeight(0) * uv_rect.getHeight()); - -	LLRect draw_rect(0, height, width, 0); -	LLRect draw_scale_rect(llround(scale_rect_uv.mLeft * (F32)image->getWidth(0)), -						llround(scale_rect_uv.mTop * (F32)image->getHeight(0)), -						llround(scale_rect_uv.mRight * (F32)image->getWidth(0)), -						llround(scale_rect_uv.mBottom * (F32)image->getHeight(0))); -	// scale fixed region of image to drawn region -	draw_scale_rect.mRight += width - image_natural_width; -	draw_scale_rect.mTop += height - image_natural_height; - -	S32 border_shrink_width = llmax(0, draw_scale_rect.mLeft - draw_scale_rect.mRight); -	S32 border_shrink_height = llmax(0, draw_scale_rect.mBottom - draw_scale_rect.mTop); - -	F32 shrink_width_ratio = scale_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - scale_rect.getWidth())); -	F32 shrink_height_ratio = scale_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - scale_rect.getHeight())); - -	F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); -	draw_scale_rect.mLeft = llround((F32)draw_scale_rect.mLeft * shrink_scale); -	draw_scale_rect.mTop = llround(lerp((F32)height, (F32)draw_scale_rect.mTop, shrink_scale)); -	draw_scale_rect.mRight = llround(lerp((F32)width, (F32)draw_scale_rect.mRight, shrink_scale)); -	draw_scale_rect.mBottom = llround((F32)draw_scale_rect.mBottom * shrink_scale); +	LLRectf uv_center_rect( +		uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), +		uv_outer_rect.mBottom + (center_rect.mTop * uv_height), +		uv_outer_rect.mLeft + (center_rect.mRight * uv_width), +		uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); + +	F32 image_width = image->getWidth(0); +	F32 image_height = image->getHeight(0); + +	S32 image_natural_width = llround(image_width * uv_width); +	S32 image_natural_height = llround(image_height * uv_height); + +	LLRectf draw_center_rect(	uv_center_rect.mLeft * image_width, +								uv_center_rect.mTop * image_height, +								uv_center_rect.mRight * image_width, +								uv_center_rect.mBottom * image_height); + +	{	// scale fixed region of image to drawn region +		draw_center_rect.mRight += width - image_natural_width; +		draw_center_rect.mTop += height - image_natural_height; + +		F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); +		F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); + +		F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); +		F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); + +		F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); + +		draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); +		draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); +		draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); +		draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); +	} + +	LLRectf draw_outer_rect(ui_translation.mV[VX],  +							ui_translation.mV[VY] + height * ui_scale.mV[VY],  +							ui_translation.mV[VX] + width * ui_scale.mV[VX],  +							ui_translation.mV[VY]);  	LLGLSUIDefault gls_ui; @@ -509,136 +526,174 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex  		gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);  	} -	gGL.pushUIMatrix(); -	{ -		gGL.translateUI((F32)x, (F32)y, 0.f); +	gGL.getTexUnit(0)->bind(image); -		gGL.getTexUnit(0)->bind(image); +	gGL.color4fv(color.mV); +	 +	const S32 NUM_VERTICES = 9 * 4; // 9 quads +	LLVector2 uv[NUM_VERTICES]; +	LLVector3 pos[NUM_VERTICES]; -		gGL.color4fv(color.mV); -		 -		gGL.begin(LLRender::QUADS); -		{ -			// draw bottom left -			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); -			gGL.vertex2i(0, 0); +	S32 index = 0; -			gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom); -			gGL.vertex2i(draw_scale_rect.mLeft, 0); +	gGL.begin(LLRender::QUADS); +	{ +		// draw bottom left +		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); +		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom); -			gGL.vertex2i(0, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); +		index++; -			// draw bottom middle -			gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom); -			gGL.vertex2i(draw_scale_rect.mLeft, 0); +		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom); -			gGL.vertex2i(draw_scale_rect.mRight, 0); +		// draw bottom middle +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); +		index++; -			// draw bottom right -			gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom); -			gGL.vertex2i(draw_scale_rect.mRight, 0); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); -			gGL.vertex2i(width, 0); +		// draw bottom right +		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom); -			gGL.vertex2i(width, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); +		pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); +		index++; -			// draw left  -			gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom); -			gGL.vertex2i(0, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom); +		// draw left  +		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop); -			gGL.vertex2i(0, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); +		index++; -			// draw middle -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom); +		// draw middle +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); +		index++; -			// draw right  -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom); -			gGL.vertex2i(width, draw_scale_rect.mBottom); +		// draw right  +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop); -			gGL.vertex2i(width, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); +		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); +		index++; -			// draw top left -			gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop); -			gGL.vertex2i(0, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop); +		// draw top left +		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop); -			gGL.vertex2i(draw_scale_rect.mLeft, height); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); -			gGL.vertex2i(0, height); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); +		index++; -			// draw top middle -			gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); +		pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop); +		// draw top middle +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop); -			gGL.vertex2i(draw_scale_rect.mRight, height); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop); -			gGL.vertex2i(draw_scale_rect.mLeft, height); +		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); +		index++; -			// draw top right -			gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop); -			gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop); +		uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop); -			gGL.vertex2i(width, draw_scale_rect.mTop); +		// draw top right +		uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); -			gGL.vertex2i(width, height); +		uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); +		pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); +		index++; -			gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop); -			gGL.vertex2i(draw_scale_rect.mRight, height); -		} -		gGL.end(); +		uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); +		pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); +		index++; + +		uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); +		pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); +		index++; + +		gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);  	} -	gGL.popUIMatrix(); +	gGL.end();  	if (solid_color)  	{ @@ -668,25 +723,40 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre  	if (degrees == 0.f)  	{ -		gGL.pushUIMatrix(); -		gGL.translateUI((F32)x, (F32)y, 0.f); -			 +		const S32 NUM_VERTICES = 4; // 9 quads +		LLVector2 uv[NUM_VERTICES]; +		LLVector3 pos[NUM_VERTICES]; +  		gGL.begin(LLRender::QUADS);  		{ -			gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); -			gGL.vertex2i(width, height ); - -			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); -			gGL.vertex2i(0, height ); - -			gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); -			gGL.vertex2i(0, 0); - -			gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); -			gGL.vertex2i(width, 0); +			LLVector3 ui_scale = gGL.getUIScale(); +			LLVector3 ui_translation = gGL.getUITranslation(); +			ui_translation.mV[VX] += x; +			ui_translation.mV[VY] += y; +			ui_translation.scaleVec(ui_scale); +			S32 index = 0; +			S32 scaled_width = llround(width * ui_scale.mV[VX]); +			S32 scaled_height = llround(height * ui_scale.mV[VY]); + +			uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); +			pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); +			index++; + +			uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); +			pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); +			index++; + +			uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); +			pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); +			index++; + +			uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); +			pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); +			index++; + +			gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);  		}  		gGL.end(); -		gGL.popUIMatrix();  	}  	else  	{ @@ -755,25 +825,6 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL  	LLUI::setLineWidth(1.f);  } - -void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom) -{ -	gGL.color4fv( LLColor4::white.mV ); -	glLogicOp( GL_XOR ); -	stop_glerror(); - -	gGL.begin(LLRender::QUADS); -		gGL.vertex2i(left, top); -		gGL.vertex2i(left, bottom); -		gGL.vertex2i(right, bottom); -		gGL.vertex2i(right, top); -	gGL.end(); - -	glLogicOp( GL_COPY ); -	stop_glerror(); -} - -  void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)  {  	if (end_angle < start_angle) @@ -1007,42 +1058,6 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians,  	gGL.end();  } -// Draws spokes around a circle. -void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color) -{ -	const F32 DELTA = F_TWO_PI / count; -	const F32 HALF_DELTA = DELTA * 0.5f; -	const F32 SIN_DELTA = sin( DELTA ); -	const F32 COS_DELTA = cos( DELTA ); - -	F32 x1 = outer_radius * cos( HALF_DELTA ); -	F32 y1 = outer_radius * sin( HALF_DELTA ); -	F32 x2 = inner_radius * cos( HALF_DELTA ); -	F32 y2 = inner_radius * sin( HALF_DELTA ); - -	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - -	gGL.begin( LLRender::LINES  ); -	{ -		while( count-- ) -		{ -			gGL.color4fv(outer_color.mV); -			gGL.vertex2f( x1, y1 ); -			gGL.color4fv(inner_color.mV); -			gGL.vertex2f( x2, y2 ); - -			F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA; -			y1 = x1 * SIN_DELTA +  y1 * COS_DELTA; -			x1 = x1_new; - -			F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA; -			y2 = x2 * SIN_DELTA +  y2 * COS_DELTA; -			x2 = x2_new; -		} -	} -	gGL.end(); -} -  void gl_rect_2d_simple_tex( S32 width, S32 height )  {  	gGL.begin( LLRender::QUADS ); @@ -1230,6 +1245,7 @@ void gl_segmented_rect_2d_tex(const S32 left,  	gGL.popUIMatrix();  } +//FIXME: rewrite to use scissor?  void gl_segmented_rect_2d_fragment_tex(const S32 left,   									   const S32 top,   									   const S32 right,  diff --git a/indra/llui/llui.h b/indra/llui/llui.h index afec2e9c26..fc545c85d5 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -90,7 +90,6 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor  void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);  void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);  void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); -void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color);  void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));  void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); @@ -99,7 +98,6 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre  void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));  void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom);  void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );   void gl_rect_2d_simple_tex( S32 width, S32 height ); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 294c96f8f4..3ac3bf8c41 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -95,6 +95,7 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)  :	LLView(p),  	mTentative(FALSE),  	mIsChrome(FALSE), +	mTabStop(FALSE),      mViewModel(viewmodel),  	mControlVariable(NULL),  	mEnabledControlVariable(NULL), diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 71fd5034df..76dfdf754c 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -141,8 +141,6 @@ public:  	// LLView interface  	/*virtual*/ BOOL	setLabelArg( const std::string& key, const LLStringExplicit& text );  	/*virtual*/ BOOL	isCtrl() const; -	/*virtual*/ void	setTentative(BOOL b); -	/*virtual*/ BOOL	getTentative() const;  	/*virtual*/ void	onMouseEnter(S32 x, S32 y, MASK mask);  	/*virtual*/ void	onMouseLeave(S32 x, S32 y, MASK mask);  	/*virtual*/ BOOL	canFocusChildren() const; @@ -174,6 +172,8 @@ public:  	void setMakeVisibleControlVariable(LLControlVariable* control);  	void setMakeInvisibleControlVariable(LLControlVariable* control); +	virtual void	setTentative(BOOL b); +	virtual BOOL	getTentative() const;  	virtual void	setValue(const LLSD& value);  	virtual LLSD	getValue() const;      /// When two widgets are displaying the same data (e.g. during a skin diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index a34ede439a..5680ab8bd4 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -357,6 +357,12 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const  	return LLTrans::getString("TooltipAgentUrl");  } +bool LLUrlEntryAgent::underlineOnHoverOnly(const std::string &string) const +{ +	std::string url = getUrl(string); +	return LLStringUtil::endsWith(url, "/about") || LLStringUtil::endsWith(url, "/inspect"); +} +  std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)  {  	if (!gCacheName) @@ -724,6 +730,19 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const  	return LLUrlEntryBase::getTooltip(string);  } +bool LLUrlEntrySLLabel::underlineOnHoverOnly(const std::string &string) const +{ +	std::string url = getUrl(string); +	LLUrlMatch match; +	if (LLUrlRegistry::instance().findUrl(url, match)) +	{ +		return match.underlineOnHoverOnly(); +	} + +	// unrecognized URL? should not happen +	return LLUrlEntryBase::underlineOnHoverOnly(string); +} +  //  // LLUrlEntryWorldMap Describes secondlife:///<location> URLs  // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index d868e01aa6..e25eaa7555 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -88,6 +88,9 @@ public:  	/// is this a match for a URL that should not be hyperlinked?  	bool isLinkDisabled() const { return mDisabledLink; } +	/// Should this link text be underlined only when mouse is hovered over it? +	virtual bool underlineOnHoverOnly(const std::string &string) const { return false; } +  	virtual LLUUID	getID(const std::string &string) const { return LLUUID::null; }  protected: @@ -167,6 +170,7 @@ public:  	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);  	/*virtual*/ std::string getTooltip(const std::string &string) const;  	/*virtual*/ LLUUID	getID(const std::string &string) const; +	/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;  private:  	void onAgentNameReceived(const LLUUID& id, const std::string& first,  							 const std::string& last, BOOL is_group); @@ -269,6 +273,7 @@ public:  	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);  	/*virtual*/ std::string getUrl(const std::string &string) const;  	/*virtual*/ std::string getTooltip(const std::string &string) const; +	/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;  };  /// diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp index 4ec97091a3..e53b0c4370 100644 --- a/indra/llui/llurlmatch.cpp +++ b/indra/llui/llurlmatch.cpp @@ -37,7 +37,8 @@ LLUrlMatch::LLUrlMatch() :  	mIcon(""),  	mMenuName(""),  	mLocation(""), -	mDisabledLink(false) +	mDisabledLink(false), +	mUnderlineOnHoverOnly(false)  {  } @@ -45,7 +46,7 @@ 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, -						   bool disabled_link, const LLUUID& id) +						   bool disabled_link, const LLUUID& id, bool underline_on_hover_only)  {  	mStart = start;  	mEnd = end; @@ -58,4 +59,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,  	mLocation = location;  	mDisabledLink = disabled_link;  	mID = id; +	mUnderlineOnHoverOnly = underline_on_hover_only;  } diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h index 7a4f0bc10e..d1b2112ee7 100644 --- a/indra/llui/llurlmatch.h +++ b/indra/llui/llurlmatch.h @@ -80,12 +80,15 @@ public:  	/// is this a match for a URL that should not be hyperlinked?  	bool isLinkDisabled() const { return mDisabledLink; } +	/// Should this link text be underlined only when mouse is hovered over it? +	bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; } +  	/// 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, bool disabled_link -				   , const LLUUID& id ); +				   , const LLUUID& id, bool underline_on_hover_only  = false );  	const LLUUID& getID() const { return mID;} @@ -102,6 +105,7 @@ private:  	LLUUID		mID;  	LLUIColor	mColor;  	bool        mDisabledLink; +	bool		mUnderlineOnHoverOnly;  };  #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 1c103a628b..9d215cf7ef 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -178,7 +178,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL  						match_entry->getMenuName(),  						match_entry->getLocation(url),  						match_entry->isLinkDisabled(), -						match_entry->getID(url)); +						match_entry->getID(url), +						match_entry->underlineOnHoverOnly(url));  		return true;  	} @@ -213,7 +214,8 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr  						match.getMenuName(),  						match.getLocation(),  						match.isLinkDisabled(), -						match.getID()); +						match.getID(), +						match.underlineOnHoverOnly());  		return true;  	}  	return false; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 42ce7b84fe..fe5ef269a9 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -397,28 +397,40 @@ bool LLCompareByTabOrder::operator() (const LLView* const a, const LLView* const  	return (a_score == b_score) ? a < b : a_score < b_score;  } -bool LLView::trueToRoot(const boost::function<bool (const LLView*)>& predicate) const +BOOL LLView::isInVisibleChain() const  { -	const LLView* cur_view = this; -	while(cur_view) +	BOOL visible = TRUE; + +	const LLView* viewp = this; +	while(viewp)  	{ -		if(!predicate(cur_view)) +		if (!viewp->getVisible())  		{ -			return false; +			visible = FALSE; +			break;  		} -		cur_view = cur_view->getParent(); +		viewp = viewp->getParent();  	} -	return true; -} - -BOOL LLView::isInVisibleChain() const -{ -	return trueToRoot(&LLView::getVisible); +	 +	return visible;  }  BOOL LLView::isInEnabledChain() const  { -	return trueToRoot(&LLView::getEnabled); +	BOOL enabled = TRUE; + +	const LLView* viewp = this; +	while(viewp) +	{ +		if (!viewp->getEnabled()) +		{ +			enabled = FALSE; +			break; +		} +		viewp = viewp->getParent(); +	} +	 +	return enabled;  }  // virtual @@ -428,17 +440,6 @@ BOOL LLView::canFocusChildren() const  }  //virtual -void LLView::setTentative(BOOL b) -{ -} - -//virtual -BOOL LLView::getTentative() const -{ -	return FALSE; -} - -//virtual  void LLView::setEnabled(BOOL enabled)  {  	mEnabled = enabled; @@ -2778,6 +2779,19 @@ LLView::tree_post_iterator_t LLView::endTreeDFSPost()  	return tree_post_iterator_t();  } +LLView::bfs_tree_iterator_t LLView::beginTreeBFS()  +{  +	return bfs_tree_iterator_t(this,  +							boost::bind(boost::mem_fn(&LLView::beginChild), _1),  +							boost::bind(boost::mem_fn(&LLView::endChild), _1));  +} + +LLView::bfs_tree_iterator_t LLView::endTreeBFS()  +{  +	// an empty iterator is an "end" iterator +	return bfs_tree_iterator_t(); +} +  LLView::root_to_view_iterator_t LLView::beginRootToView()  { diff --git a/indra/llui/llview.h b/indra/llui/llview.h index b9cecb0f84..f7175112bf 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -267,7 +267,6 @@ public:  	S32 getDefaultTabGroup() const				{ return mDefaultTabGroup; }  	S32 getLastTabGroup()						{ return mLastTabGroup; } -	bool        trueToRoot(const boost::function<bool (const LLView*)>& predicate) const;  	BOOL		isInVisibleChain() const;  	BOOL		isInEnabledChain() const; @@ -283,8 +282,6 @@ public:  	// children, etc.  	virtual void deleteAllChildren(); -	virtual void	setTentative(BOOL b); -	virtual BOOL	getTentative() const;  	void 	setAllChildrenEnabled(BOOL b);  	virtual void	setVisible(BOOL visible); @@ -351,6 +348,10 @@ public:  	tree_post_iterator_t beginTreeDFSPost();  	tree_post_iterator_t endTreeDFSPost(); +	typedef LLTreeBFSIter<LLView, child_list_const_iter_t> bfs_tree_iterator_t; +	bfs_tree_iterator_t beginTreeBFS(); +	bfs_tree_iterator_t endTreeBFS(); +  	typedef LLTreeDownIter<LLView> root_to_view_iterator_t;  	root_to_view_iterator_t beginRootToView(); | 
