SL-6109 Cell selection support

meow-7.2.2
andreykproductengine 2019-10-01 22:21:37 +03:00 committed by Andrey Kleshchev
parent 0147a8c989
commit af7cefe031
6 changed files with 230 additions and 63 deletions

View File

@ -172,7 +172,7 @@ U32 LLScrollListText::sCount = 0;
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
mText(p.text.isProvided() ? p.text() : p.value().asString()),
mText(p.label.isProvided() ? p.label() : p.value().asString()),
mFont(p.font),
mColor(p.color),
mUseColor(p.color.isProvided()),
@ -199,13 +199,6 @@ void LLScrollListText::highlightText(S32 offset, S32 num_chars)
mHighlightCount = llmax(0, num_chars);
}
//virtual
void LLScrollListText::setHighlighted(bool highlighted)
{
mHighlightOffset = 0;
mHighlightCount = highlighted ? -1 : 0;
}
//virtual
BOOL LLScrollListText::isText() const
{
@ -323,15 +316,6 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
1);
mRoundedRectImage->draw(highlight_rect, highlight_color);
}
else if (mHighlightCount < 0)
{
// Highlight whole cell
LLRect highlight_rect(0,
getHeight(),
getWidth() - 1,
-1);
gl_rect_2d(highlight_rect, LLColor4(0.38f, 0.694f, 0.573f, 0.35f));
}
// Try to draw the entire string
F32 right_x;

View File

@ -60,7 +60,7 @@ public:
Optional<void*> userdata;
Optional<LLSD> value; // state of checkbox, icon id/name, date
Optional<std::string> text; // description or text
Optional<std::string> label; // description or text
Optional<std::string> tool_tip;
Optional<const LLFontGL*> font;
@ -70,12 +70,13 @@ public:
Optional<LLColor4> color;
Params()
: type("type", "text"),
: type("cell_type", "text"), // Don't use "type", it overlaps with xml's parameter
column("column"),
width("width"),
enabled("enabled", true),
visible("visible", true),
value("value"),
label("label"),
tool_tip("tool_tip", ""),
font("font", LLFontGL::getFontSansSerifSmall()),
font_color("font_color", LLColor4::black),
@ -103,7 +104,6 @@ public:
virtual BOOL getVisible() const { return TRUE; }
virtual void setWidth(S32 width) { mWidth = width; }
virtual void highlightText(S32 offset, S32 num_chars) {}
virtual void setHighlighted(bool highlighted) {}
virtual BOOL isText() const { return FALSE; }
virtual BOOL needsToolTip() const { return ! mToolTip.empty(); }
virtual void setColor(const LLColor4&) {}
@ -141,7 +141,6 @@ public:
/*virtual*/ const LLSD getValue() const;
/*virtual*/ BOOL getVisible() const;
/*virtual*/ void highlightText(S32 offset, S32 num_chars);
/*virtual*/ void setHighlighted(bool highlighted);
/*virtual*/ void setColor(const LLColor4&);
/*virtual*/ BOOL isText() const;
@ -160,6 +159,7 @@ protected:
S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;
LLColor4 mHighlightColor;
U8 mUseColor;
LLFontGL::HAlign mFontAlignment;
BOOL mVisible;

View File

@ -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,6 +135,7 @@ 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),
@ -165,6 +173,7 @@ 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),
@ -821,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;
@ -880,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;
}
}
@ -1006,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 )
@ -1024,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;
}
@ -1097,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
{
@ -1141,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
{
@ -1212,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)
@ -1280,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;
}
@ -1320,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;
}
@ -1386,7 +1409,7 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
{
if (selected)
{
selectItem(item);
selectItem(item, -1);
}
else
{
@ -1466,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);
@ -1492,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 )
{
@ -1501,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;
}
@ -1690,7 +1714,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if (mLastSelected == NULL)
{
selectItem(hit_item);
selectItem(hit_item, getColumnIndexFromOffset(x));
}
else
{
@ -1714,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)
{
@ -1724,7 +1748,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
}
if (selecting)
{
selectItem(item, FALSE);
selectItem(item, getColumnIndexFromOffset(x), FALSE);
}
}
}
@ -1739,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
{
@ -1753,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;
@ -2126,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
{
@ -2175,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())
{
@ -2343,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();
@ -2395,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;
@ -2414,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;
}
@ -2674,7 +2777,7 @@ void LLScrollListCtrl::selectAll()
LLScrollListItem *itemp = *iter;
if( itemp->getEnabled() )
{
selectItem(itemp, FALSE);
selectItem(itemp, -1, FALSE);
}
}

View File

@ -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,
@ -433,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);
@ -458,6 +472,7 @@ private:
bool mCommitOnKeyboardMovement;
bool mCommitOnSelectionChange;
bool mSelectionChanged;
ESelectionType mSelectionType;
bool mNeedsScroll;
bool mMouseWheelOpaque;
bool mCanSelect;

View File

@ -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();

View File

@ -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;