diff options
Diffstat (limited to 'indra/llui')
| -rw-r--r-- | indra/llui/llmenugl.cpp | 42 | ||||
| -rw-r--r-- | indra/llui/llmenugl.h | 18 | ||||
| -rw-r--r-- | indra/llui/llscrolllistcell.cpp | 149 | ||||
| -rw-r--r-- | indra/llui/llscrolllistcell.h | 31 | ||||
| -rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 177 | ||||
| -rw-r--r-- | indra/llui/llscrolllistctrl.h | 21 | ||||
| -rw-r--r-- | indra/llui/llscrolllistitem.cpp | 56 | ||||
| -rw-r--r-- | indra/llui/llscrolllistitem.h | 21 | ||||
| -rw-r--r-- | indra/llui/lluictrlfactory.h | 4 | 
9 files changed, 458 insertions, 61 deletions
| diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 5568a84494..b87819102b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -213,6 +213,12 @@ LLSD LLMenuItemGL::getValue() const  }  //virtual +bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const +{ +	return (mAcceleratorKey == key) && (mAcceleratorMask == mask); +} + +//virtual  BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)  {  	if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) ) @@ -263,13 +269,13 @@ BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)  // This function checks to see if the accelerator key is already in use;  // if not, it will be added to the list -BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp) +BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp)  { -	LLKeyBinding *accelerator = NULL; +	LLMenuKeyboardBinding *accelerator = NULL;  	if (mAcceleratorKey != KEY_NONE)  	{ -		std::list<LLKeyBinding*>::iterator list_it; +		std::list<LLMenuKeyboardBinding*>::iterator list_it;  		for (list_it = listp->begin(); list_it != listp->end(); ++list_it)  		{  			accelerator = *list_it; @@ -293,7 +299,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)  		}  		if (!accelerator)  		{				 -			accelerator = new LLKeyBinding; +			accelerator = new LLMenuKeyboardBinding;  			if (accelerator)  			{  				accelerator->mKey = mAcceleratorKey; @@ -1017,6 +1023,11 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask)  	return TRUE;  } +bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const +{ +	return getBranch() && getBranch()->hasAccelerator(key, mask); +} +  BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)  {  	return getBranch() && getBranch()->handleAcceleratorKey(key, mask); @@ -1024,7 +1035,7 @@ BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)  // This function checks to see if the accelerator key is already in use;  // if not, it will be added to the list -BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp) +BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp)  {  	LLMenuGL* branch = getBranch();  	if (!branch) @@ -3023,6 +3034,27 @@ void LLMenuGL::updateParent(LLView* parentp)  	}  } +bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const +{ +	if (key == KEY_NONE) +	{ +		return false; +	} +	// Note: checking this way because mAccelerators seems to be broken +	// mAccelerators probably needs to be cleaned up or fixed +	// It was used for dupplicate accelerator avoidance. +	item_list_t::const_iterator item_iter; +	for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter) +	{ +		LLMenuItemGL* itemp = *item_iter; +		if (itemp->hasAccelerator(key, mask)) +		{ +			return true; +		} +	} +	return false; +} +  BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)  {  	// don't handle if not enabled diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 1f11f26192..8cef9c6463 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -42,6 +42,13 @@  extern S32 MENU_BAR_HEIGHT;  extern S32 MENU_BAR_WIDTH; +class LLMenuKeyboardBinding +{ +public: +    KEY				mKey; +    MASK			mMask; +}; +  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLMenuItemGL  // @@ -91,6 +98,7 @@ public:  	/*virtual*/ void setValue(const LLSD& value);  	/*virtual*/ LLSD getValue() const; +	virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;  	virtual BOOL handleAcceleratorKey(KEY key, MASK mask);  	LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); } @@ -109,7 +117,7 @@ public:  	virtual void setBriefItem(BOOL brief);  	virtual BOOL isBriefItem() const; -	virtual BOOL addToAcceleratorList(std::list<LLKeyBinding*> *listp); +	virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);  	void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }  	BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; } @@ -436,7 +444,8 @@ public:  	/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);  	/*virtual*/ void removeChild( LLView* ctrl);  	/*virtual*/ BOOL postBuild(); - +	 +	virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;  	virtual BOOL handleAcceleratorKey(KEY key, MASK mask);  	LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const; @@ -628,10 +637,11 @@ public:  	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); +	virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;  	virtual BOOL handleAcceleratorKey(KEY key, MASK mask);  	// check if we've used these accelerators already -	virtual BOOL addToAcceleratorList(std::list <LLKeyBinding*> *listp); +	virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);  	// called to rebuild the draw label  	virtual void buildDrawLabel( void ); @@ -797,7 +807,7 @@ private:  	void checkMenuTrigger(); -	std::list <LLKeyBinding*>	mAccelerators; +	std::list <LLMenuKeyboardBinding*>	mAccelerators;  	BOOL						mAltKeyTrigger;  }; diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 8000efad0e..13839da400 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -50,6 +50,10 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_  	{  		cell = new LLScrollListDate(cell_p);  	} +	else if (cell_p.type() == "icontext") +	{ +		cell = new LLScrollListIconText(cell_p); +	}  	else	// default is "text"  	{  		cell = new LLScrollListText(cell_p); @@ -168,7 +172,7 @@ U32 LLScrollListText::sCount = 0;  LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)  :	LLScrollListCell(p), -	mText(p.value().asString()), +	mText(p.label.isProvided() ? p.label() : p.value().asString()),  	mFont(p.font),  	mColor(p.color),  	mUseColor(p.color.isProvided()), @@ -192,7 +196,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)  void LLScrollListText::highlightText(S32 offset, S32 num_chars)  {  	mHighlightOffset = offset; -	mHighlightCount = num_chars; +	mHighlightCount = llmax(0, num_chars);  }  //virtual  @@ -292,11 +296,12 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col  	if (mHighlightCount > 0)  	{ +		// Highlight text  		S32 left = 0;  		switch(mFontAlignment)  		{  		case LLFontGL::LEFT: -			left = mFont->getWidth(mText.getString(), 0, mHighlightOffset); +			left = mFont->getWidth(mText.getString(), 1, mHighlightOffset);  			break;  		case LLFontGL::RIGHT:  			left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX); @@ -319,7 +324,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col  	switch(mFontAlignment)  	{  	case LLFontGL::LEFT: -		start_x = 0.f; +		start_x = 1.f;  		break;  	case LLFontGL::RIGHT:  		start_x = (F32)getWidth(); @@ -435,3 +440,139 @@ const LLSD LLScrollListDate::getValue() const  {  	return mDate;  } + +// +// LLScrollListIconText +// +LLScrollListIconText::LLScrollListIconText(const LLScrollListCell::Params& p) +    : LLScrollListText(p), +    mIcon(p.value().isUUID() ? LLUI::getUIImageByID(p.value().asUUID()) : LLUI::getUIImage(p.value().asString())), +    mPad(4) +{ +    mTextWidth = getWidth() - mPad /*padding*/ - mFont->getLineHeight(); +} + +LLScrollListIconText::~LLScrollListIconText() +{ +} + +const LLSD LLScrollListIconText::getValue() const +{ +    if (mIcon.isNull()) +    { +        return LLStringUtil::null; +    } +    return mIcon->getName(); +} + +void LLScrollListIconText::setValue(const LLSD& value) +{ +    if (value.isUUID()) +    { +        // don't use default image specified by LLUUID::null, use no image in that case +        LLUUID image_id = value.asUUID(); +        mIcon = image_id.notNull() ? LLUI::getUIImageByID(image_id) : LLUIImagePtr(NULL); +    } +    else +    { +        std::string value_string = value.asString(); +        if (LLUUID::validate(value_string)) +        { +            setValue(LLUUID(value_string)); +        } +        else if (!value_string.empty()) +        { +            mIcon = LLUI::getUIImage(value.asString()); +        } +        else +        { +            mIcon = NULL; +        } +    } +} + +void LLScrollListIconText::setWidth(S32 width) +{ +    LLScrollListCell::setWidth(width); +    // Assume that iamge height and width is identical to font height and width +    mTextWidth = width - mPad /*padding*/ - mFont->getLineHeight(); +} + + +void LLScrollListIconText::draw(const LLColor4& color, const LLColor4& highlight_color)	 const +{ +    LLColor4 display_color; +    if (mUseColor) +    { +        display_color = mColor; +    } +    else +    { +        display_color = color; +    } + +    S32 icon_height = mFont->getLineHeight(); +    S32 icon_space = mIcon ? (icon_height + mPad) : 0; + +    if (mHighlightCount > 0) +    { +        S32 left = 0; +        switch (mFontAlignment) +        { +        case LLFontGL::LEFT: +            left = mFont->getWidth(mText.getString(), icon_space + 1, mHighlightOffset); +            break; +        case LLFontGL::RIGHT: +            left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX) - icon_space; +            break; +        case LLFontGL::HCENTER: +            left = (getWidth() - mFont->getWidth(mText.getString()) - icon_space) / 2; +            break; +        } +        LLRect highlight_rect(left - 2, +            mFont->getLineHeight() + 1, +            left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1, +            1); +        mRoundedRectImage->draw(highlight_rect, highlight_color); +    } + +    // Try to draw the entire string +    F32 right_x; +    U32 string_chars = mText.length(); +    F32 start_text_x = 0.f; +    S32 start_icon_x = 0; +    switch (mFontAlignment) +    { +    case LLFontGL::LEFT: +        start_text_x = icon_space + 1; +        start_icon_x = 1; +        break; +    case LLFontGL::RIGHT: +        start_text_x = (F32)getWidth(); +        start_icon_x = getWidth() - mFont->getWidth(mText.getString()) - icon_space; +        break; +    case LLFontGL::HCENTER: +        F32 center = (F32)getWidth()* 0.5f; +        start_text_x = center + ((F32)icon_space * 0.5f); +        start_icon_x = center - (((F32)icon_space + mFont->getWidth(mText.getString())) * 0.5f); +        break; +    } +    mFont->render(mText.getWString(), 0, +        start_text_x, 0.f, +        display_color, +        mFontAlignment, +        LLFontGL::BOTTOM, +        0, +        LLFontGL::NO_SHADOW, +        string_chars, +        getTextWidth(), +        &right_x, +        TRUE); + +    if (mIcon) +    { +        mIcon->draw(start_icon_x, 0, icon_height, icon_height, mColor); +    } +} + + diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index d625ebddcc..19576fb247 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -59,7 +59,8 @@ public:  									visible;  		Optional<void*>				userdata; -		Optional<LLSD>				value; +		Optional<LLSD>				value; // state of checkbox, icon id/name, date +		Optional<std::string>		label; // description or text  		Optional<std::string>		tool_tip;  		Optional<const LLFontGL*>	font; @@ -75,6 +76,7 @@ public:  			enabled("enabled", true),  			visible("visible", true),  			value("value"), +			label("label"),  			tool_tip("tool_tip", ""),  			font("font", LLFontGL::getFontSansSerifSmall()),  			font_color("font_color", LLColor4::black), @@ -152,11 +154,12 @@ public:  	void			setText(const LLStringExplicit& text);  	void			setFontStyle(const U8 font_style); -private: +protected:  	LLUIString		mText;  	S32				mTextWidth;  	const LLFontGL*	mFont;  	LLColor4		mColor; +	LLColor4		mHighlightColor;  	U8				mUseColor;  	LLFontGL::HAlign mFontAlignment;  	BOOL			mVisible; @@ -169,7 +172,7 @@ private:  };  /* - * Cell displaying an image. + * Cell displaying an image. AT the moment, this is specifically UI image   */  class LLScrollListIcon : public LLScrollListCell  { @@ -223,4 +226,26 @@ private:  	LLDate		mDate;  }; +/* +* Cell displaying icon and text. +*/ + +class LLScrollListIconText : public LLScrollListText +{ +public: +    LLScrollListIconText(const LLScrollListCell::Params& p); +    /*virtual*/ ~LLScrollListIconText(); +    /*virtual*/ void	draw(const LLColor4& color, const LLColor4& highlight_color) const; +    /*virtual*/ const LLSD		getValue() const; +    /*virtual*/ void	setValue(const LLSD& value); + + +    S32					getIconWidth() const; +    /*virtual*/ void	setWidth(S32 width);/* { LLScrollListCell::setWidth(width); mTextWidth = width - ; }*/ + +private: +    LLPointer<LLUIImage>	mIcon; +    S32						mPad; +}; +  #endif diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 763c3aeb81..83f80cfb9e 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -115,6 +115,13 @@ struct SortScrollListItem  // LLScrollListCtrl  //--------------------------------------------------------------------------- +void LLScrollListCtrl::SelectionTypeNames::declareValues() +{ +    declare("row", LLScrollListCtrl::ROW); +    declare("cell", LLScrollListCtrl::CELL); +    declare("header", LLScrollListCtrl::HEADER); +} +  LLScrollListCtrl::Contents::Contents()  :	columns("column"),  	rows("row") @@ -128,8 +135,10 @@ LLScrollListCtrl::Params::Params()  	has_border("draw_border"),  	draw_heading("draw_heading"),  	search_column("search_column", 0), +	selection_type("selection_type", ROW),  	sort_column("sort_column", -1),  	sort_ascending("sort_ascending", true), +	can_sort("can_sort", true),  	mouse_wheel_opaque("mouse_wheel_opaque", false),  	commit_on_keyboard_movement("commit_on_keyboard_movement", true),  	heading_height("heading_height"), @@ -164,8 +173,10 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)  	mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),  	mCommitOnSelectionChange(false),  	mSelectionChanged(false), +	mSelectionType(p.selection_type),  	mNeedsScroll(false),  	mCanSelect(true), +	mCanSort(p.can_sort),  	mColumnsDirty(false),  	mMaxItemCount(INT_MAX),   	mBorderThickness( 2 ), @@ -819,7 +830,15 @@ BOOL LLScrollListCtrl::selectFirstItem()  		{  			if (!itemp->getSelected())  			{ -				selectItem(itemp); +                switch (mSelectionType) +                { +                case CELL: +                    selectItem(itemp, 0); +                    break; +                case HEADER: +                case ROW: +                    selectItem(itemp, -1); +                }  			}  			success = TRUE;  			mOriginalSelection = 0; @@ -878,7 +897,8 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )  		{  			if( itemp->getEnabled() )  			{ -				selectItem(itemp, FALSE); +				// TODO: support range selection for cells +				selectItem(itemp, -1, FALSE);  				success = TRUE;				  			}  		} @@ -1004,10 +1024,14 @@ void LLScrollListCtrl::clearHighlightedItems()  void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index)  { -	if (mHighlightedItem != target_index) -	{ -		mHighlightedItem = target_index; -	} +    if (mHighlightedItem != target_index) +    { +        if (mHighlightedItem >= 0 && mHighlightedItem < mItemList.size()) +        { +            mItemList[mHighlightedItem]->setHoverCell(-1); +        } +        mHighlightedItem = target_index; +    }  }  S32	LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) @@ -1022,7 +1046,8 @@ S32	LLScrollListCtrl::selectMultiple( uuid_vec_t ids )  		{  			if (item->getEnabled() && (item->getUUID() == (*iditr)))  			{ -				selectItem(item,FALSE); +				// TODO: support multiple selection for cells +				selectItem(item, -1, FALSE);  				++count;  				break;  			} @@ -1095,7 +1120,7 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)  			{  				if (prev_item)  				{ -					selectItem(prev_item, !extend_selection); +					selectItem(prev_item, cur_item->getSelectedCell(), !extend_selection);  				}  				else  				{ @@ -1139,7 +1164,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)  			{  				if (next_item)  				{ -					selectItem(next_item, !extend_selection); +					selectItem(next_item, cur_item->getSelectedCell(), !extend_selection);  				}  				else  				{ @@ -1210,7 +1235,7 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen  	bool found = NULL != item;  	if(found)  	{ -		selectItem(item); +		selectItem(item, -1);  	}  	if (mCommitOnSelectionChange) @@ -1278,7 +1303,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen  			BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;  			if (select)  			{ -				selectItem(item); +				selectItem(item, -1);  				found = TRUE;  				break;  			} @@ -1318,7 +1343,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen  				// find offset of matching text (might have leading whitespace)  				S32 offset = item_label.find(target_trimmed);  				cellp->highlightText(offset, target_trimmed.size()); -				selectItem(item); +				selectItem(item, -1);  				found = TRUE;  				break;  			} @@ -1384,7 +1409,7 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)  		{  			if (selected)  			{ -				selectItem(item); +				selectItem(item, -1);  			}  			else  			{ @@ -1464,7 +1489,7 @@ void LLScrollListCtrl::drawItems()  		S32 max_columns = 0; -		LLColor4 highlight_color = LLColor4::white; +		LLColor4 highlight_color = LLColor4::white; // ex: text inside cells  		static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);  		highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout(), 0.4f, 0.f); @@ -1490,7 +1515,8 @@ void LLScrollListCtrl::drawItems()  			max_columns = llmax(max_columns, item->getNumColumns());  			LLColor4 fg_color; -			LLColor4 bg_color(LLColor4::transparent); +			LLColor4 hover_color(LLColor4::transparent); +			LLColor4 select_color(LLColor4::transparent);  			if( mScrollLines <= line && line < mScrollLines + num_page_lines )  			{ @@ -1499,44 +1525,44 @@ void LLScrollListCtrl::drawItems()  				{  					if(item->getHighlighted())	// if it's highlighted, average the colors  					{ -						bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f); +						select_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);  					}  					else						// otherwise just select-highlight it  					{ -						bg_color = mBgSelectedColor.get(); +						select_color = mBgSelectedColor.get();  					}  					fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get());  				} -				else if (mHighlightedItem == line && mCanSelect) +				if (mHighlightedItem == line && mCanSelect)  				{  					if(item->getHighlighted())	// if it's highlighted, average the colors  					{ -						bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f); +						hover_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);  					}  					else						// otherwise just hover-highlight it  					{ -						bg_color = mHoveredColor.get(); +						hover_color = mHoveredColor.get();  					}  				}  				else if (item->getHighlighted())  				{ -					bg_color = mHighlightedColor.get(); +					hover_color = mHighlightedColor.get();  				}  				else   				{  					if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))  					{ -						bg_color = mBgStripeColor.get(); +						hover_color = mBgStripeColor.get();  					}  				}  				if (!item->getEnabled())  				{ -					bg_color = mBgReadOnlyColor.get(); +					hover_color = mBgReadOnlyColor.get();  				} -				item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding); +				item->draw(item_rect, fg_color % alpha, hover_color% alpha, select_color% alpha, highlight_color % alpha, mColumnPadding);  				cur_y -= mLineHeight;  			} @@ -1688,7 +1714,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)  			{  				if (mLastSelected == NULL)  				{ -					selectItem(hit_item); +					selectItem(hit_item, getColumnIndexFromOffset(x));  				}  				else  				{ @@ -1712,7 +1738,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)  						LLScrollListItem *item = *itor;                          if (item == hit_item || item == lastSelected)  						{ -							selectItem(item, FALSE); +							selectItem(item, getColumnIndexFromOffset(x), FALSE);  							selecting = !selecting;  							if (hit_item == lastSelected)  							{ @@ -1722,7 +1748,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)  						}  						if (selecting)  						{ -							selectItem(item, FALSE); +							selectItem(item, getColumnIndexFromOffset(x), FALSE);  						}  					}  				} @@ -1737,7 +1763,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)  				{  					if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable))  					{ -						selectItem(hit_item, FALSE); +						selectItem(hit_item, getColumnIndexFromOffset(x), FALSE);  					}  					else  					{ @@ -1751,12 +1777,12 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)  			else  			{  				deselectAllItems(TRUE); -				selectItem(hit_item); +				selectItem(hit_item, getColumnIndexFromOffset(x));  			}  		}  		else  		{ -			selectItem(hit_item); +			selectItem(hit_item, getColumnIndexFromOffset(x));  		}  		selection_changed = mSelectionChanged; @@ -2124,8 +2150,29 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)  	{  		LLScrollListItem* item = hitItem(x, y);  		if (item) -		{ -			mouseOverHighlightNthItem(getItemIndex(item)); +        { +            mouseOverHighlightNthItem(getItemIndex(item)); +            switch (mSelectionType) +            { +            case CELL: +                item->setHoverCell(getColumnIndexFromOffset(x)); +                break; +            case HEADER: +                { +                    S32 cell = getColumnIndexFromOffset(x); +                    if (cell > 0) +                    { +                        item->setHoverCell(cell); +                    } +                    else +                    { +                        item->setHoverCell(-1); +                    } +                    break; +                } +            case ROW: +                break; +            }  		}  		else  		{ @@ -2173,6 +2220,52 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )  					handled = TRUE;  				}  				break; +            case KEY_LEFT: +                if (mAllowKeyboardMovement || hasFocus()) +                { +                    // TODO: support multi-select +                    LLScrollListItem *item = getFirstSelected(); +                    S32 cell = item->getSelectedCell(); +                    switch (mSelectionType) +                    { +                    case CELL: +                        if (cell < mColumns.size()) cell++; +                        break; +                    case HEADER: +                        if (cell == -1) cell = 1; +                        else if (cell > 1 && cell < mColumns.size()) cell++; // skip header +                        break; +                    case ROW: +                        cell = -1; +                        break; +                    } +                    item->setSelectedCell(cell); +                    handled = TRUE; +                } +                break; +            case KEY_RIGHT: +                if (mAllowKeyboardMovement || hasFocus()) +                { +                    // TODO: support multi-select +                    LLScrollListItem *item = getFirstSelected(); +                    S32 cell = item->getSelectedCell(); +                    switch (mSelectionType) +                    { +                    case CELL: +                        if (cell >= 0) cell--; +                        break; +                    case HEADER: +                        if (cell > 1) cell--; +                        else if (cell == 1) cell = -1; // skip header +                        break; +                    case ROW: +                        cell = -1; +                        break; +                    } +                    item->setSelectedCell(cell); +                    handled = TRUE; +                } +                break;  			case KEY_PAGE_UP:  				if (mAllowKeyboardMovement || hasFocus())  				{ @@ -2341,7 +2434,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)  				LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());  				if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)  				{ -					selectItem(item); +					selectItem(item, -1);  					mNeedsScroll = true;  					cellp->highlightText(0, 1);  					mSearchTimer.reset(); @@ -2393,7 +2486,7 @@ BOOL LLScrollListCtrl::isRepeatedChars(const LLWString& string) const  	return TRUE;  } -void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_item) +void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, BOOL select_single_item)  {  	if (!itemp) return; @@ -2412,6 +2505,18 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it  			deselectAllItems(TRUE);  		}  		itemp->setSelected(TRUE); +        switch (mSelectionType) +        { +        case CELL: +            itemp->setSelectedCell(cell); +            break; +        case HEADER: +            itemp->setSelectedCell(cell <= 0 ? -1 : cell); +            break; +        case ROW: +            itemp->setSelectedCell(-1); +            break; +        }  		mLastSelected = itemp;  		mSelectionChanged = true;  	} @@ -2672,7 +2777,7 @@ void	LLScrollListCtrl::selectAll()  		LLScrollListItem *itemp = *iter;  		if( itemp->getEnabled() )  		{ -			selectItem(itemp, FALSE); +			selectItem(itemp, -1, FALSE);  		}  	} @@ -2801,6 +2906,8 @@ void LLScrollListCtrl::onClickColumn(void *userdata)  	LLScrollListCtrl *parent = info->mParentCtrl;  	if (!parent) return; +	if (!parent->mCanSort) return; +  	S32 column_index = info->mIndex;  	LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 43e1c0d707..45ce67349a 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -54,6 +54,18 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,  	public LLCtrlListInterface, public LLCtrlScrollInterface  {  public: +    typedef enum e_selection_type +    { +        ROW, // default +        CELL, // does not support multi-selection +        HEADER, // when pointing to cells in column 0 will highlight whole row, otherwise cell, no multi-select +    } ESelectionType; + +    struct SelectionTypeNames : public LLInitParam::TypeValuesHelper<LLScrollListCtrl::ESelectionType, SelectionTypeNames> +    { +        static void declareValues(); +    }; +  	struct Contents : public LLInitParam::Block<Contents>  	{  		Multiple<LLScrollListColumn::Params>	columns; @@ -99,6 +111,8 @@ public:  						commit_on_keyboard_movement,  						mouse_wheel_opaque; +		Optional<ESelectionType, SelectionTypeNames> selection_type; +  		// display flags  		Optional<bool>	has_border,  						draw_heading, @@ -115,7 +129,8 @@ public:  		// sort and search behavior  		Optional<S32>	search_column,  						sort_column; -		Optional<bool>	sort_ascending; +		Optional<bool>	sort_ascending, +						can_sort; // whether user is allowed to sort  		// colors  		Optional<LLUIColor>	fg_unselected_color, @@ -432,7 +447,7 @@ private:  	void            updateLineHeightInsert(LLScrollListItem* item);  	void			reportInvalidInput();  	BOOL			isRepeatedChars(const LLWString& string) const; -	void			selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE); +	void			selectItem(LLScrollListItem* itemp, S32 cell, BOOL single_select = TRUE);  	void			deselectItem(LLScrollListItem* itemp);  	void			commitIfChanged();  	BOOL			setSort(S32 column, BOOL ascending); @@ -457,9 +472,11 @@ private:  	bool			mCommitOnKeyboardMovement;  	bool			mCommitOnSelectionChange;  	bool			mSelectionChanged; +	ESelectionType	mSelectionType;  	bool			mNeedsScroll;  	bool			mMouseWheelOpaque;  	bool			mCanSelect; +    bool			mCanSort;		// Whether user is allowed to sort  	bool			mDisplayColumnHeaders;  	bool			mColumnsDirty;  	bool			mColumnWidthsDirty; diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp index df22c88afb..51c615dd00 100644 --- a/indra/llui/llscrolllistitem.cpp +++ b/indra/llui/llscrolllistitem.cpp @@ -40,6 +40,8 @@  LLScrollListItem::LLScrollListItem( const Params& p )  :	mSelected(FALSE),  	mHighlighted(FALSE), +	mHoverIndex(-1), +	mSelectedIndex(-1),  	mEnabled(p.enabled),  	mUserdata(p.userdata),  	mItemValue(p.value) @@ -53,6 +55,28 @@ LLScrollListItem::~LLScrollListItem()  	mColumns.clear();  } +void LLScrollListItem::setSelected(BOOL b) +{ +    mSelected = b; +    mSelectedIndex = -1; +} + +void LLScrollListItem::setHighlighted(BOOL b) +{ +    mHighlighted = b; +    mHoverIndex = -1; +} + +void LLScrollListItem::setHoverCell(S32 cell) +{ +    mHoverIndex = cell; +} + +void LLScrollListItem::setSelectedCell(S32 cell) +{ +    mSelectedIndex = cell; +} +  void LLScrollListItem::addColumn(const LLScrollListCell::Params& p)  {  	mColumns.push_back(LLScrollListCell::create(p)); @@ -120,12 +144,21 @@ std::string LLScrollListItem::getContentsCSV() const  } -void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) +void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& hover_color, const LLColor4& select_color, const LLColor4& highlight_color, S32 column_padding)  {  	// draw background rect  	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  	LLRect bg_rect = rect; -	gl_rect_2d( bg_rect, bg_color ); +    if (mSelectedIndex < 0 && getSelected()) +    { +        // Whole item is highlighted/selected +        gl_rect_2d(bg_rect, select_color); +    } +    else if (mHoverIndex < 0) +    { +        // Whole item is highlighted/selected +        gl_rect_2d(bg_rect, hover_color); +    }  	S32 cur_x = rect.mLeft;  	S32 num_cols = getNumColumns(); @@ -141,6 +174,25 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const  		{  			LLUI::translate((F32) cur_x, (F32) rect.mBottom); +            if (mSelectedIndex == cur_col) +            { +                // select specific cell +                LLRect highlight_rect(0, +                    cell->getHeight(), +                    cell->getWidth(), +                    0); +                gl_rect_2d(highlight_rect, select_color); +            } +            else if (mHoverIndex == cur_col) +            { +                // highlight specific cell +                LLRect highlight_rect(0, +                    cell->getHeight(), +                    cell->getWidth() , +                    0); +                gl_rect_2d(highlight_rect, hover_color); +            } +  			cell->draw( fg_color, highlight_color );  		}  		LLUI::popMatrix(); diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 13655b5873..d2c3dd7721 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -77,15 +77,21 @@ public:  	virtual ~LLScrollListItem(); -	void	setSelected( BOOL b )			{ mSelected = b; } +	void	setSelected( BOOL b );  	BOOL	getSelected() const				{ return mSelected; }  	void	setEnabled( BOOL b )			{ mEnabled = b; }  	BOOL	getEnabled() const 				{ return mEnabled; } -	void	setHighlighted( BOOL b )		{ mHighlighted = b; } +	void	setHighlighted( BOOL b );  	BOOL	getHighlighted() const			{ return mHighlighted; } +	void	setSelectedCell( S32 cell ); +	S32		getSelectedCell() const			{ return mSelectedIndex; } + +	void	setHoverCell( S32 cell ); +	S32		getHoverCell() const			{ return mHoverIndex; } +  	void	setUserdata( void* userdata )	{ mUserdata = userdata; }  	void*	getUserdata() const 			{ return mUserdata; } @@ -107,14 +113,21 @@ public:  	std::string getContentsCSV() const; -	virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); +	virtual void draw(const LLRect& rect, +					  const LLColor4& fg_color, +					  const LLColor4& hover_color, // highlight/hover selection of whole item or cell +					  const LLColor4& select_color, // highlight/hover selection of whole item or cell +					  const LLColor4& highlight_color, // highlights contents of cells (ex: text) +					  S32 column_padding);  protected:  	LLScrollListItem( const Params& );  private:  	BOOL	mSelected; -	BOOL	mHighlighted; +    BOOL	mHighlighted; +    S32		mHoverIndex; +	S32		mSelectedIndex;  	BOOL	mEnabled;  	void*	mUserdata;  	LLSD	mItemValue; diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 03d946f1b7..f740f14e4d 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -160,8 +160,8 @@ public:  			LLXMLNodePtr root_node;  			if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) -				{							 -				LL_WARNS() << "Couldn't parse XUI file: " << instance().getCurFileName() << LL_ENDL; +			{ +                LL_WARNS() << "Couldn't parse XUI from path: " << instance().getCurFileName() << ", from filename: " << filename << LL_ENDL;  				goto fail;  			} | 
