diff options
Diffstat (limited to 'indra/llui/llscrolllistctrl.cpp')
-rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 787 |
1 files changed, 530 insertions, 257 deletions
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 96a739418f..0c81b2da08 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -61,43 +61,55 @@ const S32 LIST_SNAP_PADDING = 5; // local structures & classes. struct SortScrollListItem { - SortScrollListItem(const S32 sort_col, BOOL sort_ascending) - { - mSortCol = sort_col; - mSortAscending = sort_ascending; - } + SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders) + : mSortOrders(sort_orders) + {} bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2) { - const LLScrollListCell *cell1; - const LLScrollListCell *cell2; - - cell1 = i1->getColumn(mSortCol); - cell2 = i2->getColumn(mSortCol); + if ( mSortOrders.empty() ) return true; + + const LLScrollListCell *cell1 = NULL; + const LLScrollListCell *cell2 = NULL; - S32 order = 1; - if (!mSortAscending) + sort_order_t::const_reverse_iterator end_it = mSortOrders.rend(); + sort_order_t::const_reverse_iterator it; + + // sort over all columns in order specified by mSortOrders + S32 sort_result = 0; + for (it = mSortOrders.rbegin(); it != end_it; ++it) { - order = -1; - } + S32 col_idx = it->first; + BOOL sort_ascending = it->second; - BOOL retval = FALSE; + cell1 = i1->getColumn(col_idx); + cell2 = i2->getColumn(col_idx); + // ascending or descending sort for this column? + S32 order = 1; + if (!sort_ascending) + { + order = -1; + } - if (cell1 && cell2) - { - retval = ((order * LLString::compareDict(cell1->getText(), cell2->getText())) < 0); + if (cell1 && cell2) + { + sort_result = (order * LLString::compareDict(cell1->getValue().asString(), cell2->getValue().asString())); + if (sort_result != 0) + { + // we have a sort order! + break; + } + } } - return (retval ? TRUE : FALSE); + return sort_result < 0; } -protected: - S32 mSortCol; - S32 mSortAscending; + typedef std::vector<std::pair<S32, BOOL> > sort_order_t; + const sort_order_t& mSortOrders; }; - // // LLScrollListIcon // @@ -120,6 +132,14 @@ LLScrollListIcon::~LLScrollListIcon() { } +void LLScrollListIcon::setValue(LLSD value) +{ + mImageUUID = value.asUUID(); + // don't use default image specified by LLUUID::null, use no image in that case + mIcon = mImageUUID.isNull() ? NULL : LLUI::sImageProvider->getImageByID(value.asUUID()); +} + + void LLScrollListIcon::setColor(const LLColor4& color) { mColor = color; @@ -127,7 +147,10 @@ void LLScrollListIcon::setColor(const LLColor4& color) void LLScrollListIcon::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const { - gl_draw_image(0, 0, mIcon, mColor); + if (mIcon) + { + gl_draw_image(0, 0, mIcon, mColor); + } } // @@ -158,15 +181,15 @@ LLScrollListCheck::~LLScrollListCheck() void LLScrollListCheck::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const { mCheckBox->draw(); - } BOOL LLScrollListCheck::handleClick() { - if ( mCheckBox->getEnabled() ) + if (mCheckBox->getEnabled()) { - LLCheckBoxCtrl::onButtonPress(mCheckBox); + mCheckBox->toggle(); } + // don't change selection when clicking on embedded checkbox return TRUE; } @@ -213,7 +236,7 @@ LLScrollListText::LLScrollListText( const LLString& text, const LLFontGL* font, // initialize rounded rect image if (!mRoundedRectImage) { - mRoundedRectImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("rounded_square.tga"))); + mRoundedRectImage = LLUI::sImageProvider->getImageByID(LLUUID(LLUI::sAssetsGroup->getString("rounded_square.tga"))); } } @@ -223,6 +246,12 @@ LLScrollListText::~LLScrollListText() delete mColor; } +S32 LLScrollListText::getContentWidth() const +{ + return mFont->getWidth(mText.getString()); +} + + void LLScrollListText::setColor(const LLColor4& color) { if (!mColor) @@ -314,31 +343,6 @@ LLScrollListItem::~LLScrollListItem() std::for_each(mColumns.begin(), mColumns.end(), DeletePointer()); } -BOOL LLScrollListItem::handleClick(S32 x, S32 y, MASK mask) -{ - BOOL handled = FALSE; - - S32 left = 0; - S32 right = 0; - S32 width = 0; - - std::vector<LLScrollListCell *>::iterator iter = mColumns.begin(); - std::vector<LLScrollListCell *>::iterator end = mColumns.end(); - for ( ; iter != end; ++iter) - { - width = (*iter)->getWidth(); - right += width; - if (left <= x && x < right ) - { - handled = (*iter)->handleClick(); - break; - } - - left += width; - } - return handled; -} - void LLScrollListItem::setNumColumns(S32 columns) { S32 prev_columns = mColumns.size(); @@ -375,7 +379,7 @@ LLString LLScrollListItem::getContentsCSV() S32 count = getNumColumns(); for (S32 i=0; i<count; ++i) { - ret += getColumn(i)->getText(); + ret += getColumn(i)->getValue().asString(); if (i < count-1) { ret += ", "; @@ -387,16 +391,7 @@ LLString LLScrollListItem::getContentsCSV() void LLScrollListItem::setEnabled(BOOL b) { - if (b != mEnabled) - { - std::vector<LLScrollListCell *>::iterator iter = mColumns.begin(); - std::vector<LLScrollListCell *>::iterator end = mColumns.end(); - for ( ; iter != end; ++iter) - { - (*iter)->setEnabled(b); - } - mEnabled = b; - } + mEnabled = b; } //--------------------------------------------------------------------------- @@ -424,9 +419,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mCanSelect(TRUE), mDisplayColumnHeaders(FALSE), mCollapseEmptyColumns(FALSE), - mIsPopup(FALSE), mMaxItemCount(INT_MAX), - //mItemCount(0), + mMaxContentWidth(0), mBackgroundVisible( TRUE ), mDrawStripes(TRUE), mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ), @@ -443,12 +437,13 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mOnSortChangedCallback( NULL ), mHighlightedItem(-1), mBorder(NULL), - mDefaultColumn("SIMPLE"), + mDefaultColumnName("SIMPLE"), mSearchColumn(0), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), - mSortColumn(-1), mSortAscending(TRUE), + mSecondarySortColumn(-1), + mSecondarySortAscending(TRUE), mSorted(TRUE), mDirty(FALSE), mOriginalSelection(-1), @@ -457,7 +452,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mItemListRect.setOriginAndSize( mBorderThickness + LIST_BORDER_PAD, mBorderThickness + LIST_BORDER_PAD, - mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE, + mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ), mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) ); updateLineHeight(); @@ -481,7 +476,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect, mScrollbar->setFollowsTop(); mScrollbar->setFollowsBottom(); mScrollbar->setEnabled( TRUE ); - mScrollbar->setVisible( TRUE ); + // scrollbar is visible only when needed + mScrollbar->setVisible(FALSE); addChild(mScrollbar); // Border @@ -539,7 +535,8 @@ void LLScrollListCtrl::clearRows() mScrollLines = 0; mLastSelected = NULL; - updateMaxContentWidth(NULL); + calcMaxContentWidth(NULL); + updateLayout(); mDirty = FALSE; } @@ -620,38 +617,64 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const return ret; } +// returns first matching item +LLScrollListItem* LLScrollListCtrl::getItem(const LLSD& sd) const +{ + LLString string_val = sd.asString(); + + item_list::const_iterator iter; + for(iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListItem* item = *iter; + // assumes string representation is good enough for comparison + if (item->getValue().asString() == string_val) + { + return item; + } + } + return NULL; +} + void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { - S32 old_height = mRect.getHeight(); LLUICtrl::reshape( width, height, called_from_parent ); - S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0); + updateLayout(); +} +void LLScrollListCtrl::updateLayout() +{ + // reserve room for column headers, if needed + S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0); mItemListRect.setOriginAndSize( mBorderThickness + LIST_BORDER_PAD, mBorderThickness + LIST_BORDER_PAD, - mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE, + mRect.getWidth() - 2*( mBorderThickness + LIST_BORDER_PAD ), mRect.getHeight() - 2*( mBorderThickness + LIST_BORDER_PAD ) - heading_size ); + // how many lines of content in a single "page" mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0; - if(old_height < height && getScrollPos() == mScrollbar->getDocPosMax()) + BOOL scrollbar_visible = getItemCount() > mPageLines; + if (scrollbar_visible) { - setScrollPos(mScrollbar->getDocPosMax()); + // provide space on the right for scrollbar + mItemListRect.mRight = mRect.getWidth() - ( mBorderThickness + LIST_BORDER_PAD ) - SCROLLBAR_SIZE; } - mScrollbar->setVisible(mPageLines < getItemCount()); + + mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); mScrollbar->setPageSize( mPageLines ); - + mScrollbar->setDocSize( getItemCount() ); + mScrollbar->setVisible(scrollbar_visible); + updateColumns(); } // Attempt to size the control to show all items. // Do not make larger than width or height. -void LLScrollListCtrl::arrange(S32 max_width, S32 max_height) +void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height) { - S32 height = mLineHeight * (getItemCount() + 1); - height = llmin( height, max_height ); - + S32 height = llmin( getRequiredRect().getHeight(), max_height ); S32 width = mRect.getWidth(); reshape( width, height ); @@ -660,7 +683,10 @@ void LLScrollListCtrl::arrange(S32 max_width, S32 max_height) LLRect LLScrollListCtrl::getRequiredRect() { - S32 height = mLineHeight * (getItemCount() + 1); + S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0); + S32 height = (mLineHeight * getItemCount()) + + (2 * ( mBorderThickness + LIST_BORDER_PAD )) + + heading_size; S32 width = mRect.getWidth(); return LLRect(0, height, width, 0); @@ -680,15 +706,22 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos ) break; case ADD_SORTED: - if (mSortColumn == -1) { - mSortColumn = 0; - mSortAscending = TRUE; - } - mItemList.push_back(item); - std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); - break; - + // sort by column 0, in ascending order + std::vector<sort_column_t> single_sort_column; + single_sort_column.push_back(std::make_pair(0, TRUE)); + + mItemList.push_back(item); + std::stable_sort( + mItemList.begin(), + mItemList.end(), + SortScrollListItem(single_sort_column)); + + // ADD_SORTED just sorts by first column... + // this might not match user sort criteria, so flag list as being in unsorted state + setSorted(FALSE); + break; + } case ADD_BOTTOM: mItemList.push_back(item); setSorted(FALSE); @@ -702,33 +735,31 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos ) } updateLineHeightInsert(item); - mPageLines = mLineHeight ? mItemListRect.getHeight() / mLineHeight : 0; - BOOL scrollbar_visible = mPageLines < getItemCount(); - - if (scrollbar_visible != mScrollbar->getVisible()) - { - mScrollbar->setVisible(mPageLines < getItemCount()); - updateColumns(); - } - mScrollbar->setPageSize( mPageLines ); - - mScrollbar->setDocSize( getItemCount() ); + calcMaxContentWidth(item); - updateMaxContentWidth(item); + updateLayout(); } return not_too_big; } -void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item) +void LLScrollListCtrl::calcMaxContentWidth(LLScrollListItem* added_item) { const S32 HEADING_TEXT_PADDING = 30; const S32 COLUMN_TEXT_PADDING = 20; - std::map<LLString, LLScrollListColumn>::iterator column_itor; - for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) + if (added_item == NULL) + { + mMaxContentWidth = 0; + } + + S32 item_content_width = 0; + + ordered_columns_t::iterator column_itor; + for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor) { - LLScrollListColumn* column = &column_itor->second; + LLScrollListColumn* column = *column_itor; + if (!column) continue; if (!added_item) { @@ -740,7 +771,7 @@ void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item) LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); if (!cellp) continue; - column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); } } else @@ -748,9 +779,13 @@ void LLScrollListCtrl::updateMaxContentWidth(LLScrollListItem* added_item) LLScrollListCell* cellp = added_item->getColumn(column->mIndex); if (!cellp) continue; - column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getText()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + column->mMaxContentWidth = llmax(LLFontGL::sSansSerifSmall->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); } + + item_content_width += column->mMaxContentWidth; } + + mMaxContentWidth = llmax(mMaxContentWidth, item_content_width); } const S32 SCROLL_LIST_ROW_PAD = 2; @@ -789,7 +824,6 @@ void LLScrollListCtrl::updateColumns() mColumnsIndexed.resize(mColumns.size()); std::map<LLString, LLScrollListColumn>::iterator column_itor; - bool first_dynamic = true; for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) { LLScrollListColumn *column = &column_itor->second; @@ -801,11 +835,6 @@ void LLScrollListCtrl::updateColumns() else if (column->mDynamicWidth) { new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; - if(first_dynamic) - { - first_dynamic = false; - new_width += (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE); - } } if (new_width != column->mWidth) @@ -854,43 +883,38 @@ void LLScrollListCtrl::updateColumns() } right = llmax(left, llmin(mItemListRect.getWidth(), right)); S32 header_width = right - left; - + last_header->reshape(header_width, mHeadingHeight); - last_header->translate(left - last_header->getRect().mLeft, top - last_header->getRect().mBottom); + last_header->translate( + left - last_header->getRect().mLeft, + top - last_header->getRect().mBottom); last_header->setVisible(mDisplayColumnHeaders && header_width > 0); left = right; } } // expand last column header we encountered to full list width - if (last_header) { - S32 header_strip_width = mItemListRect.getWidth() + (mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE); - S32 new_width = llmax(0, mItemListRect.mLeft + header_strip_width - last_header->getRect().mLeft); + S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft); last_header->reshape(new_width, last_header->getRect().getHeight()); last_header->setVisible(mDisplayColumnHeaders && new_width > 0); } - } void LLScrollListCtrl::setDisplayHeading(BOOL display) { mDisplayColumnHeaders = display; - updateColumns(); - - setHeadingHeight(mHeadingHeight); + updateLayout(); } void LLScrollListCtrl::setHeadingHeight(S32 heading_height) { mHeadingHeight = heading_height; - reshape(mRect.getWidth(), mRect.getHeight()); + updateLayout(); - // Resize - mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); } void LLScrollListCtrl::setCollapseEmptyColumns(BOOL collapse) @@ -934,6 +958,8 @@ BOOL LLScrollListCtrl::selectFirstItem() BOOL LLScrollListCtrl::selectNthItem( S32 target_index ) { + if (mItemList.empty()) return FALSE; + // Deselects all other items BOOL success = FALSE; S32 index = 0; @@ -1012,7 +1038,32 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index) } delete itemp; mItemList.erase(mItemList.begin() + target_index); - updateMaxContentWidth(NULL); + calcMaxContentWidth(NULL); +} + +//FIXME: refactor item deletion +void LLScrollListCtrl::deleteItems(const LLSD& sd) +{ + item_list::iterator iter; + for (iter = mItemList.begin(); iter < mItemList.end(); ) + { + LLScrollListItem* itemp = *iter; + if (itemp->getValue().asString() == sd.asString()) + { + if (itemp == mLastSelected) + { + mLastSelected = NULL; + } + delete itemp; + mItemList.erase(iter++); + } + else + { + iter++; + } + } + + calcMaxContentWidth(NULL); } void LLScrollListCtrl::deleteSelectedItems() @@ -1032,7 +1083,7 @@ void LLScrollListCtrl::deleteSelectedItems() } } mLastSelected = NULL; - updateMaxContentWidth(NULL); + calcMaxContentWidth(NULL); } void LLScrollListCtrl::highlightNthItem(S32 target_index) @@ -1108,7 +1159,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) if (!getFirstSelected()) { - selectFirstItem(); + // select last item + selectNthItem(getItemCount() - 1); } else { @@ -1130,7 +1182,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) break; } - prev_item = cur_item; + // don't allow navigation to disabled elements + prev_item = cur_item->getEnabled() ? cur_item : prev_item; } } @@ -1145,32 +1198,34 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection) void LLScrollListCtrl::selectNextItem( BOOL extend_selection) { + LLScrollListItem* next_item = NULL; + if (!getFirstSelected()) { selectFirstItem(); } else { - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + item_list::reverse_iterator iter; + for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++) { - LLScrollListItem* item = *iter; - if (item->getSelected()) + LLScrollListItem* cur_item = *iter; + + if (cur_item->getSelected()) { - if (++iter != mItemList.end()) + if (next_item) { - LLScrollListItem *next_item = *iter; - if (next_item) - { - selectItem(next_item, !extend_selection); - } - else - { - reportInvalidInput(); - } + selectItem(next_item, !extend_selection); + } + else + { + reportInvalidInput(); } break; } + + // don't allow navigation to disabled items + next_item = cur_item->getEnabled() ? cur_item : next_item; } } @@ -1213,10 +1268,29 @@ LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, EAd item->setEnabled(enabled); item->addColumn( item_text, gResMgr->getRes( LLFONT_SANSSERIF_SMALL ) ); addItem( item, pos ); + + // create new column on demand for "simple" items + if (mColumns.empty()) + { + LLSD new_column; + new_column["name"] = mDefaultColumnName; + new_column["label"] = ""; + new_column["dynamicwidth"] = TRUE; + addColumn(new_column); + } } return item; } +LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) +{ + LLSD item; + item["enabled"] = FALSE; + item["columns"][0]["type"] = "separator"; + item["columns"][0]["column"] = mDefaultColumnName; + + return addElement(item, pos); +} // Selects first enabled item of the given name. // Returns false if item not found. @@ -1242,7 +1316,7 @@ BOOL LLScrollListCtrl::selectSimpleItem(const LLString& label, BOOL case_sensiti { LLScrollListItem* item = *iter; // Only select enabled items with matching names - LLString item_text = item->getColumn(0)->getText(); + LLString item_text = item->getColumn(0)->getValue().asString(); if (!case_sensitive) { LLString::toLower(item_text); @@ -1288,7 +1362,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca LLScrollListItem* item = *iter; // Only select enabled items with matching names LLScrollListCell* cellp = item->getColumn(mSearchColumn); - BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getText()[0]) : FALSE; + BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE; if (select) { selectItem(item); @@ -1315,7 +1389,7 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca { continue; } - LLWString item_label = utf8str_to_wstring(cellp->getText()); + LLWString item_label = utf8str_to_wstring(cellp->getValue().asString()); if (!case_sensitive) { LLWString::toLower(item_label); @@ -1346,14 +1420,14 @@ BOOL LLScrollListCtrl::selectSimpleItemByPrefix(const LLWString& target, BOOL ca return found; } -const LLString& LLScrollListCtrl::getSimpleSelectedItem(S32 column) const +const LLString LLScrollListCtrl::getSimpleSelectedItem(S32 column) const { LLScrollListItem* item; item = getFirstSelected(); if (item) { - return item->getColumn(column)->getText(); + return item->getColumn(column)->getValue().asString(); } return LLString::null; @@ -1384,6 +1458,16 @@ LLScrollListItem* LLScrollListCtrl::addSimpleItem(const LLString& item_text, LLS item->setEnabled(enabled); item->addColumn(item_text, gResMgr->getRes(LLFONT_SANSSERIF_SMALL), column_width); addItem( item, pos ); + + // create new column on demand + if (mColumns.empty()) + { + LLSD new_column; + new_column["name"] = "default_column"; + new_column["label"] = ""; + new_column["dynamicwidth"] = TRUE; + addColumn(new_column); + } } return item; } @@ -1481,9 +1565,7 @@ void LLScrollListCtrl::drawItems() LLGLSUIDefault gls_ui; { - LLRect clip_rect = mItemListRect; - if(!mScrollbar->getVisible()) clip_rect.mRight += SCROLLBAR_SIZE; - LLLocalClipRect clip(clip_rect); + LLLocalClipRect clip(mItemListRect); S32 cur_x = x; S32 cur_y = y; @@ -1491,7 +1573,6 @@ void LLScrollListCtrl::drawItems() mDrewSelected = FALSE; S32 line = 0; - LLColor4 color; S32 max_columns = 0; item_list::iterator iter; @@ -1502,7 +1583,7 @@ void LLScrollListCtrl::drawItems() item_rect.setOriginAndSize( cur_x, cur_y, - mScrollbar->getVisible() ? mItemListRect.getWidth() : mItemListRect.getWidth() + SCROLLBAR_SIZE, + mScrollbar->getVisible() ? mItemListRect.getWidth() : mItemListRect.getWidth() + mScrollbar->getRect().getWidth(), mLineHeight ); //llinfos << item_rect.getWidth() << llendl; @@ -1514,37 +1595,43 @@ void LLScrollListCtrl::drawItems() max_columns = llmax(max_columns, item->getNumColumns()); + LLColor4 fg_color; LLRect bg_rect = item_rect; // pad background rectangle to separate it from contents bg_rect.stretch(LIST_BORDER_PAD, 0); + LLColor4 bg_color(0.f, 0.f, 0.f, 0.f); if( mScrollLines <= line && line < mScrollLines + num_page_lines ) { if( item->getSelected() && mCanSelect) { // Draw background of selected item - LLGLSNoTexture no_texture; - glColor4fv(mBgSelectedColor.mV); - gl_rect_2d( bg_rect ); - - color = mFgSelectedColor; + bg_color = mBgSelectedColor; + fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor); } else if (mHighlightedItem == line && mCanSelect) { - LLGLSNoTexture no_texture; - glColor4fv(mHighlightedColor.mV); - gl_rect_2d( bg_rect ); - color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); + bg_color = mHighlightedColor; + fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); } else { - color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); if (mDrawStripes && (line%2 == 0) && (max_columns > 1)) { - LLGLSNoTexture no_texture; - glColor4fv(mBgStripeColor.mV); - gl_rect_2d( bg_rect ); + bg_color = mBgStripeColor; } + fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); + } + + if (!item->getEnabled()) + { + bg_color = mBgReadOnlyColor; + } + // draw background rect + { + LLGLSNoTexture no_texture; + glColor4fv(bg_color.mV); + gl_rect_2d( bg_rect ); } S32 line_x = cur_x; @@ -1553,7 +1640,6 @@ void LLScrollListCtrl::drawItems() S32 cur_col = 0; S32 dynamic_width = 0; S32 dynamic_remainder = 0; - bool first_dynamic = true; if(mNumDynamicWidthColumns > 0) { dynamic_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; @@ -1563,15 +1649,9 @@ void LLScrollListCtrl::drawItems() for (LLScrollListCell* cell = item->getColumn(0); cur_col < num_cols; cell = item->getColumn(++cur_col)) { S32 cell_width = cell->getWidth(); - if(mColumnsIndexed.size() > (U32)cur_col && mColumnsIndexed[cur_col] && mColumnsIndexed[cur_col]->mDynamicWidth) { cell_width = dynamic_width + (--dynamic_remainder ? 1 : 0); - if(first_dynamic) - { - cell_width += mScrollbar->getVisible() ? 0 : SCROLLBAR_SIZE; - first_dynamic = false; - } cell->setWidth(cell_width); } // Two ways a cell could be hidden @@ -1585,7 +1665,7 @@ void LLScrollListCtrl::drawItems() F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout"); highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f); - cell->drawToWidth( space_left, color, highlight_color ); + cell->drawToWidth( space_left, fg_color, highlight_color ); LLUI::popMatrix(); cur_x += cell_width + mColumnPadding; @@ -1605,6 +1685,12 @@ void LLScrollListCtrl::draw() { if( getVisible() ) { + // if user specifies sort, make sure it is maintained + if (needsSorting() && !isSorted()) + { + sortItems(); + } + if (mNeedsScroll) { scrollToShowSelected(); @@ -1645,6 +1731,54 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) return handled; } +BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen) +{ + S32 column_index = getColumnIndexFromOffset(x); + LLScrollListColumn* columnp = getColumn(column_index); + + if (columnp == NULL) return FALSE; + + BOOL handled = FALSE; + // show tooltip for full name of hovered item if it has been truncated + LLScrollListItem* hit_item = hitItem(x, y); + if (hit_item) + { + LLScrollListCell* hit_cell = hit_item->getColumn(column_index); + if (!hit_cell) return FALSE; + S32 cell_required_width = hit_cell->getContentWidth(); + if (hit_cell + && hit_cell->isText() + && cell_required_width > columnp->mWidth) + { + + S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft; + S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item)); + LLRect cell_rect; + cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->mWidth, mLineHeight); + // Convert rect local to screen coordinates + localPointToScreen( + cell_rect.mLeft, cell_rect.mBottom, + &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); + localPointToScreen( + cell_rect.mRight, cell_rect.mTop, + &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); + + msg = hit_cell->getValue().asString(); + handled = TRUE; + } + } + + // otherwise, look for a tooltip associated with this column + LLColumnHeader* headerp = columnp->mHeader; + if (headerp && !handled) + { + headerp->handleToolTip(x, y, msg, sticky_rect_screen); + handled = !msg.empty(); + } + + return handled; +} + BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if (!mCanSelect) return FALSE; @@ -1652,6 +1786,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) BOOL selection_changed = FALSE; LLScrollListItem* hit_item = hitItem(x, y); + if( hit_item ) { if( mAllowMultipleSelection ) @@ -1686,6 +1821,11 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { selectItem(item, FALSE); selecting = !selecting; + if (hit_item == lastSelected) + { + // stop selecting now, since we just clicked on our last selected item + selecting = FALSE; + } } if (selecting) { @@ -1726,9 +1866,6 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) selectItem(hit_item); } - hit_item->handleClick(x - mBorderThickness - LIST_BORDER_PAD, - 1, mask); - selection_changed = mSelectionChanged; if (mCommitOnSelectionChange) { @@ -1750,19 +1887,17 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL; + BOOL handled = childrenHandleMouseDown(x, y, mask) != NULL; if( !handled ) { // set keyboard focus first, in case click action wants to move focus elsewhere setFocus(TRUE); - // clear selection changed flag so because user is starting a selection operation + // clear selection changed flag because user is starting a selection operation mSelectionChanged = FALSE; - gFocusMgr.setMouseCapture(this); - selectItemAt(x, y, mask); - mNeedsScroll = TRUE; + handleClick(x, y, mask); } return TRUE; @@ -1798,19 +1933,74 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) //BOOL handled = FALSE; if(getVisible()) { - // Offer the click to the children, even if we aren't enabled - // so the scroll bars will work. - if (NULL == LLView::childrenHandleDoubleClick(x, y, mask)) + BOOL handled = handleClick(x, y, mask); + + if (!handled) { - if( mCanSelect && mOnDoubleClickCallback ) + // Offer the click to the children, even if we aren't enabled + // so the scroll bars will work. + if (NULL == LLView::childrenHandleDoubleClick(x, y, mask)) { - mOnDoubleClickCallback( mCallbackUserData ); + if( mCanSelect && mOnDoubleClickCallback ) + { + mOnDoubleClickCallback( mCallbackUserData ); + } } } } return TRUE; } +BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) +{ + // which row was clicked on? + LLScrollListItem* hit_item = hitItem(x, y); + if (!hit_item) return FALSE; + + // get appropriate cell from that row + S32 column_index = getColumnIndexFromOffset(x); + LLScrollListCell* hit_cell = hit_item->getColumn(column_index); + if (!hit_cell) return FALSE; + + // select item (thus deselecting any currently selected item) + // only if item is not already selected + if (!hit_item->getSelected()) + { + selectItemAt(x, y, mask); + gFocusMgr.setMouseCapture(this); + mNeedsScroll = TRUE; + } + + if (hit_cell->handleClick()) + { + // propagate value of this cell to other selected items + // and commit the respective widgets + LLSD item_value = hit_cell->getValue(); + for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListItem* item = *iter; + if (item->getSelected()) + { + LLScrollListCell* cellp = item->getColumn(column_index); + cellp->setValue(item_value); + cellp->onCommit(); + } + } + //FIXME: find a better way to signal cell changes + onCommit(); + return TRUE; + } + else + { + // treat this as a normal single item selection + selectItemAt(x, y, mask); + gFocusMgr.setMouseCapture(this); + mNeedsScroll = TRUE; + // do not stop click processing (click callback, etc) + return FALSE; + } +} + LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) { // Excludes disabled items. @@ -1847,6 +2037,59 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) return hit_item; } +S32 LLScrollListCtrl::getColumnIndexFromOffset(S32 x) +{ + // which column did we hit? + S32 left = 0; + S32 right = 0; + S32 width = 0; + S32 column_index = 0; + + ordered_columns_t::const_iterator iter = mColumnsIndexed.begin(); + ordered_columns_t::const_iterator end = mColumnsIndexed.end(); + for ( ; iter != end; ++iter) + { + width = (*iter)->mWidth + mColumnPadding; + right += width; + if (left <= x && x < right ) + { + break; + } + + // set left for next column as right of current column + left = right; + column_index++; + } + + return llclamp(column_index, 0, getNumColumns() - 1); +} + + +S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index) +{ + S32 column_offset = 0; + ordered_columns_t::const_iterator iter = mColumnsIndexed.begin(); + ordered_columns_t::const_iterator end = mColumnsIndexed.end(); + for ( ; iter != end; ++iter) + { + if (index-- <= 0) + { + return column_offset; + } + column_offset += (*iter)->mWidth + mColumnPadding; + } + + // when running off the end, return the rightmost pixel + return mItemListRect.mRight; +} + +S32 LLScrollListCtrl::getRowOffsetFromIndex(S32 index) +{ + S32 row_bottom = ((mItemListRect.mTop - (index - mScrollLines)) * mLineHeight) + - mLineHeight; + return row_bottom; +} + BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) { @@ -1860,7 +2103,8 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) mNeedsScroll = TRUE; } } - else if (mCanSelect) + else + if (mCanSelect) { LLScrollListItem* item = hitItem(x, y); if (item) @@ -1875,13 +2119,6 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) handled = LLUICtrl::handleHover( x, y, mask ); - //if( !handled ) - //{ - // // Opaque - // getWindow()->setCursor(UI_CURSOR_ARROW); - // lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; - // handled = TRUE; - //} return handled; } @@ -2082,7 +2319,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_ if (cellp) { // Only select enabled items with matching first characters - LLWString item_label = utf8str_to_wstring(cellp->getText()); + LLWString item_label = utf8str_to_wstring(cellp->getValue().asString()); if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char) { selectItem(item); @@ -2176,7 +2413,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp) LLScrollListCell* cellp = itemp->getColumn(mSearchColumn); if (cellp) { - cellp->highlightText(0, 0); + cellp->highlightText(0, 0); } mSelectionChanged = TRUE; } @@ -2202,38 +2439,52 @@ BOOL LLScrollListCtrl::isSorted() return mSorted; } -// Called by scrollbar -//static -void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata ) +struct SameSortColumn { - LLScrollListCtrl* self = (LLScrollListCtrl*) userdata; - self->mScrollLines = new_pos; -} + SameSortColumn(S32 column) : mColumn(column) {} + S32 mColumn; + bool operator()(std::pair<S32, BOOL> sort_column) { return sort_column.first == mColumn; } +}; -// First column is column 0 -void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending) +BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending) { - if (!mSorted || mSortColumn != column) + sort_column_t new_sort_column(column, ascending); + + if (mSortColumns.empty()) { - mSortColumn = column; - std::sort(mItemList.begin(), mItemList.end(), SortScrollListItem(mSortColumn, mSortAscending)); - setSorted(TRUE); + mSortColumns.push_back(new_sort_column); + return TRUE; } + else + { + // grab current sort column + sort_column_t cur_sort_column = mSortColumns.back(); + + // remove any existing sort criterion referencing this column + // and add the new one + remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column)); + mSortColumns.push_back(new_sort_column); - // just reverse the list if changing sort order - if(mSortAscending != ascending) - { - std::reverse(mItemList.begin(), mItemList.end()); - mSortAscending = ascending; + // did the sort criteria change? + return (cur_sort_column != new_sort_column); } } +// Called by scrollbar +//static +void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata ) +{ + LLScrollListCtrl* self = (LLScrollListCtrl*) userdata; + self->mScrollLines = new_pos; +} + + void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending) { if (name.empty()) { - sortByColumn(mSortColumn, mSortAscending); + sortItems(); return; } @@ -2244,6 +2495,26 @@ void LLScrollListCtrl::sortByColumn(LLString name, BOOL ascending) } } +// First column is column 0 +void LLScrollListCtrl::sortByColumn(U32 column, BOOL ascending) +{ + if (setSort(column, ascending)) + { + sortItems(); + } +} + +void LLScrollListCtrl::sortItems() +{ + // do stable sort to preserve any previous sorts + std::stable_sort( + mItemList.begin(), + mItemList.end(), + SortScrollListItem(mSortColumns)); + + setSorted(TRUE); +} + S32 LLScrollListCtrl::getScrollPos() { return mScrollbar->getDocPos(); @@ -2465,7 +2736,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac LLSD columns; S32 index = 0; LLXMLNodePtr child; - S32 total_static = 0, num_dynamic = 0; + S32 total_static = 0; for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) { if (child->hasName("column")) @@ -2491,8 +2762,10 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac S32 columnwidth = -1; child->getAttributeS32("width", columnwidth); + LLString tooltip; + child->getAttributeString("tool_tip", tooltip); + if(!columndynamicwidth) total_static += columnwidth; - else ++num_dynamic; F32 columnrelwidth = 0.f; child->getAttributeF32("relwidth", columnrelwidth); @@ -2509,10 +2782,11 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac columns[index]["relwidth"] = columnrelwidth; columns[index]["dynamicwidth"] = columndynamicwidth; columns[index]["halign"] = (S32)h_align; + columns[index]["tool_tip"] = tooltip; + index++; } } - scroll_list->setNumDynamicColumns(num_dynamic); scroll_list->setTotalStaticColumnWidth(total_static); scroll_list->setColumnHeadings(columns); @@ -2665,7 +2939,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) LLString name = column["name"].asString(); if (mColumns.empty()) { - mDefaultColumn = 0; + mDefaultColumnName = name; } // if no column name provided, just use ordinal as name if (name.empty()) @@ -2691,6 +2965,7 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) } else if(new_column->mDynamicWidth) { + mNumDynamicWidthColumns++; new_column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns; } S32 top = mItemListRect.mTop; @@ -2724,17 +2999,16 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) new_column->mHeader->setLabel(new_column->mLabel); //new_column->mHeader->setLabel(new_column->mLabel); } + + new_column->mHeader->setToolTip(column["tool_tip"].asString()); + //RN: although it might be useful to change sort order with the keyboard, // mixing tab stops on child items along with the parent item is not supported yet new_column->mHeader->setTabStop(FALSE); addChild(new_column->mHeader); new_column->mHeader->setVisible(mDisplayColumnHeaders); - - // Move scroll to front - removeChild(mScrollbar); - addChild(mScrollbar); - + sendChildToFront(mScrollbar); } } updateColumns(); @@ -2753,18 +3027,18 @@ void LLScrollListCtrl::onClickColumn(void *userdata) LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; bool ascending = column->mSortAscending; - if (column->mSortingColumn != column->mName) + if (column->mSortingColumn != column->mName + && parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) { - if (parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) - { - LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn]; - column_index = info_redir.mIndex; - } + LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn]; + column_index = info_redir.mIndex; } - if (column_index == parent->mSortColumn) + // if this column is the primary sort key, reverse the direction + sort_column_t cur_sort_column; + if (!parent->mSortColumns.empty() && parent->mSortColumns.back().first == column_index) { - ascending = !parent->mSortAscending; + ascending = !parent->mSortColumns.back().second; } parent->sortByColumn(column_index, ascending); @@ -2777,12 +3051,17 @@ void LLScrollListCtrl::onClickColumn(void *userdata) std::string LLScrollListCtrl::getSortColumnName() { - LLScrollListColumn* column = mSortColumn >= 0 ? mColumnsIndexed[mSortColumn] : NULL; + LLScrollListColumn* column = mSortColumns.empty() ? NULL : mColumnsIndexed[mSortColumns.back().first]; if (column) return column->mName; else return ""; } +BOOL LLScrollListCtrl::needsSorting() +{ + return !mSortColumns.empty(); +} + void LLScrollListCtrl::clearColumns() { std::map<LLString, LLScrollListColumn>::iterator itor; @@ -2796,6 +3075,7 @@ void LLScrollListCtrl::clearColumns() } } mColumns.clear(); + mSortColumns.clear(); } void LLScrollListCtrl::setColumnLabel(const LLString& column, const LLString& label) @@ -2851,11 +3131,6 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p { LLString column = (*itor)["column"].asString(); - if (mColumns.size() == 0) - { - mDefaultColumn = 0; - } - LLScrollListColumn* columnp = NULL; // empty columns strings index by ordinal @@ -2895,6 +3170,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p LLString type = (*itor)["type"].asString(); BOOL has_color = (*itor).has("color"); LLColor4 color = ((*itor)["color"]); + BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true; const LLFontGL *font = gResMgr->getRes(fontname); if (!font) @@ -2906,7 +3182,8 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p if (type == "icon") { LLUUID image_id = value.asUUID(); - LLImageGL* icon = LLUI::sImageProvider->getUIImageByID(image_id); + // don't use special image with UUID::null, just don't draw an image + LLImageGL* icon = image_id.isNull() ? NULL : LLUI::sImageProvider->getImageByID(image_id); LLScrollListIcon* cell = new LLScrollListIcon(icon, width, image_id); if (has_color) { @@ -2916,8 +3193,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p } else if (type == "checkbox") { - LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl(value.asString(), - LLRect(0, 0, width, width), "label"); + LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl("check", + LLRect(0, width, width, 0), " "); + ctrl->setEnabled(enabled); + ctrl->setValue(value); LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width); if (has_color) { @@ -3070,18 +3349,12 @@ void LLScrollListCtrl::onFocusReceived() { // forget latent selection changes when getting focus mSelectionChanged = FALSE; + LLUICtrl::onFocusReceived(); } //virtual void LLScrollListCtrl::onFocusLost() { - if (mIsPopup) - { - if (getParent()) - { - getParent()->onFocusLost(); - } - } if (hasMouseCapture()) { gFocusMgr.setMouseCapture(NULL); @@ -3133,11 +3406,11 @@ void LLColumnHeader::draw() { if( getVisible() ) { - mDrawArrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; + BOOL draw_arrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; BOOL is_ascending = mColumn->mParentCtrl->getSortAscending(); - mArrowImage = is_ascending ? LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("up_arrow.tga"))) - : LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("down_arrow.tga"))); + mButton->setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent); + mArrowImage = mButton->getImageOverlay()->getImage(); //BOOL clip = mRect.mRight > mColumn->mParentCtrl->getItemListRect().getWidth(); //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE); @@ -3237,11 +3510,11 @@ void LLColumnHeader::showList() { if (mColumn->mParentCtrl->getSortAscending()) { - low_item_text = cell->getText(); + low_item_text = cell->getValue().asString(); } else { - high_item_text = cell->getText(); + high_item_text = cell->getValue().asString(); } } } @@ -3254,11 +3527,11 @@ void LLColumnHeader::showList() { if (mColumn->mParentCtrl->getSortAscending()) { - high_item_text = cell->getText(); + high_item_text = cell->getValue().asString(); } else { - low_item_text = cell->getText(); + low_item_text = cell->getValue().asString(); } } } |