From a4000c3744e42fcbb638e742f3b63fa31a0dee15 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Fri, 8 May 2009 07:43:08 +0000 Subject: merge trunk@116587 skinning-7@119389 -> viewer-2.0.0-skinning-7 --- indra/llui/llscrolllistctrl.cpp | 1884 ++++++++------------------------------- 1 file changed, 366 insertions(+), 1518 deletions(-) (limited to 'indra/llui/llscrolllistctrl.cpp') diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 5dd4e2d0ee..6f484b1875 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1,6 +1,7 @@ /** * @file llscrolllistctrl.cpp - * @brief LLScrollListCtrl base class + * @brief Scroll lists are composed of rows (items), each of which + * contains columns (cells). * * $LicenseInfo:firstyear=2001&license=viewergpl$ * @@ -30,32 +31,36 @@ * $/LicenseInfo$ */ -#include +#define INSTANTIATE_GETCHILD_SCROLLLIST #include "linden_common.h" -#include "llstl.h" -#include "llboost.h" #include "llscrolllistctrl.h" -#include "indra_constants.h" +#include + +#include "llstl.h" +#include "llboost.h" +//#include "indra_constants.h" #include "llcheckboxctrl.h" #include "llclipboard.h" #include "llfocusmgr.h" -#include "llrender.h" +//#include "llrender.h" #include "llresmgr.h" #include "llscrollbar.h" +#include "llscrolllistcell.h" #include "llstring.h" #include "llui.h" #include "lluictrlfactory.h" #include "llwindow.h" #include "llcontrol.h" #include "llkeyboard.h" -#include "llresizebar.h" +#include "llviewborder.h" +#include "lltextbox.h" +#include "llsdparam.h" -const S32 MIN_COLUMN_WIDTH = 20; -const S32 LIST_SNAP_PADDING = 5; +template LLScrollListCtrl* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; static LLRegisterWidget r("scroll_list"); @@ -96,510 +101,89 @@ struct SortScrollListItem const sort_order_t& mSortOrders; }; - -// -// LLScrollListIcon -// -LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width) - : LLScrollListCell(width), - mIcon(icon), - mColor(LLColor4::white) -{ -} - -LLScrollListIcon::LLScrollListIcon(const LLSD& value, S32 width) - : LLScrollListCell(width), - mColor(LLColor4::white) -{ - setValue(value); -} - - -LLScrollListIcon::~LLScrollListIcon() -{ -} - -void LLScrollListIcon::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::sImageProvider->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 LLScrollListIcon::setColor(const LLColor4& color) -{ - mColor = color; -} - -S32 LLScrollListIcon::getWidth() const -{ - // if no specified fix width, use width of icon - if (LLScrollListCell::getWidth() == 0 && mIcon.notNull()) - { - return mIcon->getWidth(); - } - return LLScrollListCell::getWidth(); -} - - -void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_color) const -{ - if (mIcon) - { - mIcon->draw(0, 0, mColor); - } -} - -// -// LLScrollListCheck -// -LLScrollListCheck::LLScrollListCheck(LLCheckBoxCtrl* check_box, S32 width) -{ - mCheckBox = check_box; - LLRect rect(mCheckBox->getRect()); - if (width) - { - - rect.mRight = rect.mLeft + width; - mCheckBox->setRect(rect); - setWidth(width); - } - else - { - setWidth(rect.getWidth()); //check_box->getWidth(); - } -} - -LLScrollListCheck::~LLScrollListCheck() -{ - delete mCheckBox; -} - -void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const -{ - mCheckBox->draw(); -} - -BOOL LLScrollListCheck::handleClick() -{ - if (mCheckBox->getEnabled()) - { - mCheckBox->toggle(); - } - // don't change selection when clicking on embedded checkbox - return TRUE; -} - -// -// LLScrollListSeparator -// -LLScrollListSeparator::LLScrollListSeparator(S32 width) : LLScrollListCell(width) -{ -} - -//virtual -S32 LLScrollListSeparator::getHeight() const -{ - return 5; -} - - -void LLScrollListSeparator::draw(const LLColor4& color, const LLColor4& highlight_color) const -{ - //*FIXME: use dynamic item heights and make separators narrow, and inactive - gl_line_2d(5, 8, llmax(5, getWidth() - 5), 8, color); -} - -// -// LLScrollListText -// -U32 LLScrollListText::sCount = 0; - -LLScrollListText::LLScrollListText( const std::string& text, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible) -: LLScrollListCell(width), - mText( text ), - mFont( font ), - mColor(color), - mUseColor(use_color), - mFontStyle( font_style ), - mFontAlignment( font_alignment ), - mVisible( visible ), - mHighlightCount( 0 ), - mHighlightOffset( 0 ) -{ - sCount++; - - // initialize rounded rect image - if (!mRoundedRectImage) - { - mRoundedRectImage = LLUI::sImageProvider->getUIImage("rounded_square.tga"); - } -} -//virtual -void LLScrollListText::highlightText(S32 offset, S32 num_chars) -{ - mHighlightOffset = offset; - mHighlightCount = num_chars; -} - -//virtual -BOOL LLScrollListText::isText() const -{ - return TRUE; -} - -//virtual -BOOL LLScrollListText::getVisible() const -{ - return mVisible; -} - -//virtual -S32 LLScrollListText::getHeight() const -{ - return llround(mFont->getLineHeight()); -} - - -LLScrollListText::~LLScrollListText() -{ - sCount--; -} - -S32 LLScrollListText::getContentWidth() const -{ - return mFont->getWidth(mText.getString()); -} - - -void LLScrollListText::setColor(const LLColor4& color) -{ - mColor = color; - mUseColor = TRUE; -} - -void LLScrollListText::setText(const LLStringExplicit& text) -{ - mText = text; -} - -//virtual -void LLScrollListText::setValue(const LLSD& text) -{ - setText(text.asString()); -} - -//virtual -const LLSD LLScrollListText::getValue() const -{ - return LLSD(mText.getString()); -} - - -void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_color) const -{ - LLColor4 display_color; - if (mUseColor) - { - display_color = mColor; - } - else - { - display_color = color; - } - - if (mHighlightCount > 0) - { - S32 left = 0; - switch(mFontAlignment) - { - case LLFontGL::LEFT: - left = mFont->getWidth(mText.getString(), 0, mHighlightOffset); - break; - case LLFontGL::RIGHT: - left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX); - break; - case LLFontGL::HCENTER: - left = (getWidth() - mFont->getWidth(mText.getString())) / 2; - break; - } - LLRect highlight_rect(left - 2, - llround(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_x = 0.f; - switch(mFontAlignment) - { - case LLFontGL::LEFT: - start_x = 0.f; - break; - case LLFontGL::RIGHT: - start_x = (F32)getWidth(); - break; - case LLFontGL::HCENTER: - start_x = (F32)getWidth() * 0.5f; - break; - } - mFont->render(mText.getWString(), 0, - start_x, 2.f, - display_color, - mFontAlignment, - LLFontGL::BOTTOM, - mFontStyle, - string_chars, - getWidth(), - &right_x, - FALSE, - TRUE); -} - -LLScrollListDate::LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible) -: LLScrollListText(date.asRFC1123(), font, width, font_style, font_alignment, color, use_color, visible), - mDate(date) -{ -} - -void LLScrollListDate::setValue(const LLSD& value) -{ - mDate = value.asDate(); - LLScrollListText::setValue(mDate.asRFC1123()); -} - -const LLSD LLScrollListDate::getValue() const -{ - return mDate; -} - -LLScrollListItem::~LLScrollListItem() -{ - std::for_each(mColumns.begin(), mColumns.end(), DeletePointer()); -} - -void LLScrollListItem::setNumColumns(S32 columns) -{ - S32 prev_columns = mColumns.size(); - if (columns < prev_columns) - { - std::for_each(mColumns.begin()+columns, mColumns.end(), DeletePointer()); - } - - mColumns.resize(columns); - - for (S32 col = prev_columns; col < columns; ++col) - { - mColumns[col] = NULL; - } -} - -void LLScrollListItem::setColumn( S32 column, LLScrollListCell *cell ) -{ - if (column < (S32)mColumns.size()) - { - delete mColumns[column]; - mColumns[column] = cell; - } - else - { - llerrs << "LLScrollListItem::setColumn: bad column: " << column << llendl; - } -} - -std::string LLScrollListItem::getContentsCSV() const -{ - std::string ret; - - S32 count = getNumColumns(); - for (S32 i=0; igetValue().asString(); - if (i < count-1) - { - ret += ", "; - } - } - - return ret; -} - -void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) -{ - // draw background rect - LLRect bg_rect = rect; - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv(bg_color.mV); - gl_rect_2d( bg_rect ); - } - - S32 cur_x = rect.mLeft; - S32 num_cols = getNumColumns(); - S32 cur_col = 0; - - for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col)) - { - // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) continue; - - LLUI::pushMatrix(); - { - LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f); - - cell->draw( fg_color, highlight_color ); - } - LLUI::popMatrix(); - - cur_x += cell->getWidth() + column_padding; - } -} - - -void LLScrollListItem::setEnabled(BOOL b) -{ - mEnabled = b; -} - -//--------------------------------------------------------------------------- -// LLScrollListItemComment -//--------------------------------------------------------------------------- -LLScrollListItemComment::LLScrollListItemComment(const std::string& comment_string, const LLColor4& color) -: LLScrollListItem(FALSE), - mColor(color) -{ - addColumn( comment_string, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ) ); -} - -void LLScrollListItemComment::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) -{ - LLScrollListCell* cell = getColumn(0); - if (cell) - { - // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) return; - - LLUI::pushMatrix(); - { - LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f); - - // force first cell to be width of entire item - cell->setWidth(rect.getWidth()); - cell->draw( mColor, highlight_color ); - } - LLUI::popMatrix(); - } -} - -//--------------------------------------------------------------------------- -// LLScrollListItemSeparator -//--------------------------------------------------------------------------- -LLScrollListItemSeparator::LLScrollListItemSeparator() -: LLScrollListItem(FALSE) -{ - LLScrollListSeparator* cell = new LLScrollListSeparator(0); - setNumColumns(1); - setColumn(0, cell); -} - -void LLScrollListItemSeparator::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) -{ - //TODO* move LLScrollListSeparator::draw into here and get rid of it - LLScrollListCell* cell = getColumn(0); - if (cell) - { - // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) return; - - LLUI::pushMatrix(); - { - LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f); - - // force first cell to be width of entire item - cell->setWidth(rect.getWidth()); - cell->draw( fg_color, highlight_color ); - } - LLUI::popMatrix(); - } -} - //--------------------------------------------------------------------------- // LLScrollListCtrl //--------------------------------------------------------------------------- -LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, - void (*commit_callback)(LLUICtrl* ctrl, void* userdata), - void* callback_user_data, - BOOL allow_multiple_selection, - BOOL show_border - ) - : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data), +LLScrollListCtrl::Contents::Contents() +: columns("columns"), + rows("rows") +{ + addSynonym(columns, "column"); + addSynonym(rows, "row"); +} + +LLScrollListCtrl::Params::Params() +: multi_select("multi_select", false), + has_border("draw_border"), + draw_heading("draw_heading"), + search_column("search_column", 0), + sort_column("sort_column", -1), + sort_ascending("sort_ascending", true), + commit_on_keyboard_movement("commit_on_keyboard_movement", true), + heading_height("heading_height"), + background_visible("background_visible"), + draw_stripes("draw_stripes"), + column_padding("column_padding"), + fg_unselected_color("fg_unselected_color"), + fg_selected_color("fg_selected_color"), + bg_selected_color("bg_selected_color"), + fg_disable_color("fg_disable_color"), + bg_writeable_color("bg_writeable_color"), + bg_read_only_color("bg_read_only_color"), + bg_stripe_color("bg_stripe_color"), + hovered_color("hovered_color"), + highlighted_color("highlighted_color") +{ + name = "scroll_list"; + mouse_opaque = true; +} + +LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) +: LLUICtrl(p), mLineHeight(0), mScrollLines(0), mPageLines(0), - mHeadingHeight(20), mMaxSelectable(0), - mAllowMultipleSelection( allow_multiple_selection ), mAllowKeyboardMovement(TRUE), - mCommitOnKeyboardMovement(TRUE), + mCommitOnKeyboardMovement(p.commit_on_keyboard_movement), mCommitOnSelectionChange(FALSE), mSelectionChanged(FALSE), mNeedsScroll(FALSE), mCanSelect(TRUE), - mDisplayColumnHeaders(FALSE), mColumnsDirty(FALSE), mMaxItemCount(INT_MAX), mMaxContentWidth(0), - mBackgroundVisible( TRUE ), - mDrawStripes(TRUE), - mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ), - mBgReadOnlyColor( LLUI::sColorsGroup->getColor( "ScrollBgReadOnlyColor" ) ), - mBgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedBGColor") ), - mBgStripeColor( LLUI::sColorsGroup->getColor("ScrollBGStripeColor") ), - mFgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedFGColor") ), - mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ), - mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ), - mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ), mBorderThickness( 2 ), mOnDoubleClickCallback( NULL ), mOnMaximumSelectCallback( NULL ), mOnSortChangedCallback( NULL ), mHighlightedItem(-1), mBorder(NULL), - mSearchColumn(0), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), mTotalColumnPadding(0), - mSorted(TRUE), + mSorted(FALSE), mDirty(FALSE), mOriginalSelection(-1), - mDrewSelected(FALSE) + mDrewSelected(FALSE), + mLastSelected(NULL), + mHeadingHeight(p.heading_height), + mAllowMultipleSelection(p.multi_select), + mDisplayColumnHeaders(p.draw_heading), + mBackgroundVisible(p.background_visible), + mDrawStripes(p.draw_stripes), + mBgWriteableColor(p.bg_writeable_color()), + mBgReadOnlyColor(p.bg_read_only_color()), + mBgSelectedColor(p.bg_selected_color()), + mBgStripeColor(p.bg_stripe_color()), + mFgSelectedColor(p.fg_selected_color()), + mFgUnselectedColor(p.fg_unselected_color()), + mFgDisabledColor(p.fg_disable_color()), + mHighlightedColor(p.highlighted_color()), + mHoveredColor(p.hovered_color()), + mSearchColumn(p.search_column), + mColumnPadding(p.column_padding) { mItemListRect.setOriginAndSize( mBorderThickness, @@ -612,37 +196,73 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, mPageLines = mLineHeight? (mItemListRect.getHeight()) / mLineHeight : 0; // Init the scrollbar + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + LLRect scroll_rect; scroll_rect.setOriginAndSize( - getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE, + getRect().getWidth() - mBorderThickness - scrollbar_size, mItemListRect.mBottom, - SCROLLBAR_SIZE, + scrollbar_size, mItemListRect.getHeight()); - mScrollbar = new LLScrollbar( std::string("Scrollbar"), scroll_rect, - LLScrollbar::VERTICAL, - getItemCount(), - mScrollLines, - mPageLines, - &LLScrollListCtrl::onScrollChange, this ); - mScrollbar->setFollowsRight(); - mScrollbar->setFollowsTop(); - mScrollbar->setFollowsBottom(); - mScrollbar->setEnabled( TRUE ); - // scrollbar is visible only when needed - mScrollbar->setVisible(FALSE); + + LLScrollbar::Params sbparams; + sbparams.name("Scrollbar"); + sbparams.rect(scroll_rect); + sbparams.orientation(LLScrollbar::VERTICAL); + sbparams.doc_size(getItemCount()); + sbparams.doc_pos(mScrollLines); + sbparams.page_size(mPageLines); + sbparams.change_callback(boost::bind(&LLScrollListCtrl::onScrollChange, this, _1, _2)); + sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + sbparams.visible(false); + mScrollbar = LLUICtrlFactory::create (sbparams); addChild(mScrollbar); // Border - if (show_border) - { - LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mBorder = new LLViewBorder( std::string("dlg border"), border_rect, LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, 1 ); + if (p.has_border) + { + LLRect border_rect = getLocalRect(); + LLViewBorder::Params params; + params.name("dig border"); + params.rect(border_rect); + params.bevel_type(LLViewBorder::BEVEL_IN); + mBorder = LLUICtrlFactory::create (params); addChild(mBorder); } - mColumnPadding = 5; + // set border *after* rect is fully initialized + if (mBorder) + { + mBorder->setRect(getLocalRect()); + mBorder->reshape(getRect().getWidth(), getRect().getHeight()); + } + + if (p.sort_column >= 0) + { + sortByColumnIndex(p.sort_column, p.sort_ascending); + } - mLastSelected = NULL; + + for (LLInitParam::ParamIterator::const_iterator row_it = p.contents.columns().begin(); + row_it != p.contents.columns().end(); + ++row_it) + { + addColumn(*row_it); + } + + for (LLInitParam::ParamIterator::const_iterator row_it = p.contents.rows().begin(); + row_it != p.contents.rows().end(); + ++row_it) + { + addRow(*row_it); + } + + LLTextBox::Params text_p; + text_p.name("comment_text"); + text_p.border_visible(false); + text_p.rect(mItemListRect); + text_p.follows.flags(FOLLOWS_ALL); + addChild(LLUICtrlFactory::create(text_p)); } S32 LLScrollListCtrl::getSearchColumn() @@ -666,6 +286,18 @@ S32 LLScrollListCtrl::getSearchColumn() } return llclamp(mSearchColumn, 0, getNumColumns()); } +/*virtual*/ +bool LLScrollListCtrl::preProcessChildNode(LLXMLNodePtr child) +{ + if (child->hasName("column") || child->hasName("row")) + { + return true; // skip + } + else + { + return false; + } +} LLScrollListCtrl::~LLScrollListCtrl() { @@ -818,6 +450,7 @@ void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) void LLScrollListCtrl::updateLayout() { + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); // reserve room for column headers, if needed S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0); mItemListRect.setOriginAndSize( @@ -826,22 +459,19 @@ void LLScrollListCtrl::updateLayout() getRect().getWidth() - 2 * mBorderThickness, getRect().getHeight() - (2 * mBorderThickness ) - heading_size ); + getChildView("comment_text")->setShape(mItemListRect); + // how many lines of content in a single "page" mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0; BOOL scrollbar_visible = getItemCount() > mPageLines; if (scrollbar_visible) { // provide space on the right for scrollbar - mItemListRect.mRight = getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE; + mItemListRect.mRight = getRect().getWidth() - mBorderThickness - scrollbar_size; } - // don't allow scrolling off bottom - if (mScrollLines + mPageLines > getItemCount()) - { - setScrollPos(llmax(0, getItemCount() - mPageLines)); - } - - mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); + mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - scrollbar_size, mItemListRect.mBottom); + mScrollbar->reshape(scrollbar_size, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); mScrollbar->setPageSize( mPageLines ); mScrollbar->setDocSize( getItemCount() ); mScrollbar->setVisible(scrollbar_visible); @@ -916,11 +546,11 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r // create new column on demand if (mColumns.empty() && requires_column) { - LLSD new_column; - new_column["name"] = "default_column"; - new_column["label"] = ""; - new_column["dynamicwidth"] = TRUE; - addColumn(new_column); + LLScrollListColumn::Params col_params; + col_params.name = "default_column"; + col_params.header.label = ""; + col_params.width.dynamic_width = true; + addColumn(col_params); } updateLineHeightInsert(item); @@ -1017,7 +647,7 @@ void LLScrollListCtrl::updateColumns() // update column headers std::vector::iterator column_ordered_it; S32 left = mItemListRect.mLeft; - LLColumnHeader* last_header = NULL; + LLScrollColumnHeader* last_header = NULL; for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it) { if ((*column_ordered_it)->getWidth() < 0) @@ -1052,7 +682,7 @@ void LLScrollListCtrl::updateColumns() } // expand last column header we encountered to full list width - if (last_header && last_header->canResize()) + if (last_header) { S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft); last_header->reshape(new_width, last_header->getRect().getHeight()); @@ -1077,13 +707,6 @@ void LLScrollListCtrl::updateColumns() } -void LLScrollListCtrl::setDisplayHeading(BOOL display) -{ - mDisplayColumnHeaders = display; - - updateLayout(); -} - void LLScrollListCtrl::setHeadingHeight(S32 heading_height) { mHeadingHeight = heading_height; @@ -1275,7 +898,15 @@ void LLScrollListCtrl::deleteSelectedItems() dirtyColumns(); } -void LLScrollListCtrl::highlightNthItem(S32 target_index) +void LLScrollListCtrl::clearHighlightedItems() +{ + for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); ++iter) + { + (*iter)->setHighlighted(false); + } +} + +void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index) { if (mHighlightedItem != target_index) { @@ -1283,14 +914,14 @@ void LLScrollListCtrl::highlightNthItem(S32 target_index) } } -S32 LLScrollListCtrl::selectMultiple( LLDynamicArray ids ) +S32 LLScrollListCtrl::selectMultiple( std::vector ids ) { item_list::iterator iter; S32 count = 0; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - LLDynamicArray::iterator iditr; + std::vector::iterator iditr; for(iditr = ids.begin(); iditr != ids.end(); ++iditr) { if (item->getEnabled() && (item->getUUID() == (*iditr))) @@ -1446,35 +1077,51 @@ void LLScrollListCtrl::deselectAllItems(BOOL no_commit_on_change) /////////////////////////////////////////////////////////////////////////////////////////////////// // Use this to add comment text such as "Searching", which ignores column settings of list -LLScrollListItem* LLScrollListCtrl::addCommentText(const std::string& comment_text, EAddPosition pos) +void LLScrollListCtrl::setCommentText(const std::string& comment_text) { - LLScrollListItem* item = NULL; - if (getItemCount() < mMaxItemCount) - { - // always draw comment text with "enabled" color - item = new LLScrollListItemComment( comment_text, mFgUnselectedColor ); - addItem( item, pos, FALSE ); - } - return item; + getChild("comment_text")->setValue(comment_text); } LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) { - LLScrollListItem* item = new LLScrollListItemSeparator(); - addItem(item, pos, FALSE); - return item; + LLScrollListItem::Params separator_params; + separator_params.enabled(false); + LLScrollListCell::Params cell_params; + cell_params.type = "icon"; + cell_params.value = "menu_separator"; + cell_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); + cell_params.font_halign = LLFontGL::HCENTER; + separator_params.cells.add(cell_params); + return addRow( separator_params, pos ); } // Selects first enabled item of the given name. // Returns false if item not found. +// Calls getItemByLabel in order to combine functionality BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive) { - // ensure that no stale items are selected, even if we don't find a match - deselectAllItems(TRUE); - //RN: assume no empty items - if (label.empty()) + deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match + LLScrollListItem* item = getItemByLabel(label, case_sensitive); + + bool found = NULL != item; + if(found) { - return FALSE; + selectItem(item); + } + + if (mCommitOnSelectionChange) + { + commitIfChanged(); + } + + return found; +} + +LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOOL case_sensitive, S32 column) +{ + if (label.empty()) //RN: assume no empty items + { + return NULL; } std::string target_text = label; @@ -1483,34 +1130,21 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen LLStringUtil::toLower(target_text); } - BOOL found = FALSE; - item_list::iterator iter; - S32 index = 0; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - // Only select enabled items with matching names - std::string item_text = item->getColumn(0)->getValue().asString(); + std::string item_text = item->getColumn(column)->getValue().asString(); // Only select enabled items with matching names if (!case_sensitive) { LLStringUtil::toLower(item_text); } - BOOL select = !found && item->getEnabled() && item_text == target_text; - if (select) + if(item_text == target_text) { - selectItem(item); + return item; } - found = found || select; - index++; } - - if (mCommitOnSelectionChange) - { - commitIfChanged(); - } - - return found; + return NULL; } @@ -1614,14 +1248,16 @@ const std::string LLScrollListCtrl::getSelectedItemLabel(S32 column) const LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos, BOOL enabled, S32 column_width) { - LLScrollListItem* item = NULL; if (getItemCount() < mMaxItemCount) { - item = new LLScrollListItem( enabled, NULL, id ); - item->addColumn(item_text, LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL), column_width); - addItem( item, pos ); + LLScrollListItem::Params item_p; + item_p.enabled(enabled); + item_p.value(id); + item_p.cells.add().value(item_text).width(column_width).type("text"); + + return addRow( item_p, pos ); } - return item; + return NULL; } // Select the line or lines that match this UUID @@ -1726,7 +1362,7 @@ void LLScrollListCtrl::drawItems() S32 max_columns = 0; LLColor4 highlight_color = LLColor4::white; - F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout"); + static LLUICachedControl 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); item_list::iterator iter; @@ -1754,27 +1390,46 @@ void LLScrollListCtrl::drawItems() if( mScrollLines <= line && line < mScrollLines + num_page_lines ) { - fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); + fg_color = (item->getEnabled() ? mFgUnselectedColor.get() : mFgDisabledColor.get()); if( item->getSelected() && mCanSelect) { - bg_color = mBgSelectedColor; - fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor); + if(item->getHighlighted()) // if it's highlighted, average the colors + { + bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f); + } + else // otherwise just select-highlight it + { + bg_color = mBgSelectedColor.get(); + } + + fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get()); } else if (mHighlightedItem == line && mCanSelect) { - bg_color = mHighlightedColor; + if(item->getHighlighted()) // if it's highlighted, average the colors + { + bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f); + } + else // otherwise just hover-highlight it + { + bg_color = mHoveredColor.get(); + } + } + else if (item->getHighlighted()) + { + bg_color = mHighlightedColor.get(); } else { if (mDrawStripes && (line % 2 == 0) && (max_columns > 1)) { - bg_color = mBgStripeColor; + bg_color = mBgStripeColor.get(); } } if (!item->getEnabled()) { - bg_color = mBgReadOnlyColor; + bg_color = mBgReadOnlyColor.get(); } item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding); @@ -1807,8 +1462,7 @@ void LLScrollListCtrl::draw() if (mBackgroundVisible) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv( getEnabled() ? mBgWriteableColor.mV : mBgReadOnlyColor.mV ); - gl_rect_2d(background); + gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() : mBgReadOnlyColor.get() ); } if (mColumnsDirty) @@ -1817,6 +1471,8 @@ void LLScrollListCtrl::draw() mColumnsDirty = FALSE; } + getChildView("comment_text")->setVisible(mItemList.empty()); + drawItems(); if (mBorder) @@ -1879,7 +1535,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti } // otherwise, look for a tooltip associated with this column - LLColumnHeader* headerp = columnp->mHeader; + LLScrollColumnHeader* headerp = columnp->mHeader; if (headerp && !handled) { headerp->handleToolTip(x, y, msg, sticky_rect_screen); @@ -1922,7 +1578,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if(mOnMaximumSelectCallback) { - mOnMaximumSelectCallback(mCallbackUserData); + mOnMaximumSelectCallback(); } break; } @@ -1960,7 +1616,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask) { if(mOnMaximumSelectCallback) { - mOnMaximumSelectCallback(mCallbackUserData); + mOnMaximumSelectCallback(); } } } @@ -2051,7 +1707,7 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask) { if( mCanSelect && mOnDoubleClickCallback ) { - mOnDoubleClickCallback( mCallbackUserData ); + mOnDoubleClickCallback(); } } } @@ -2221,11 +1877,11 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) LLScrollListItem* item = hitItem(x, y); if (item) { - highlightNthItem(getItemIndex(item)); + mouseOverHighlightNthItem(getItemIndex(item)); } else { - highlightNthItem(-1); + mouseOverHighlightNthItem(-1); } } @@ -2234,6 +1890,11 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) return handled; } +void LLScrollListCtrl::onMouseLeave(S32 x, S32 y, MASK mask) +{ + // clear mouse highlight + mouseOverHighlightNthItem(-1); +} BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { @@ -2378,7 +2039,8 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) } // perform incremental search based on keyboard input - if (mSearchTimer.getElapsedTimeF32() > LLUI::sConfigGroup->getF32("TypeAheadTimeout")) + static LLUICachedControl type_ahead_timeout ("TypeAheadTimeout", 0); + if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout) { mSearchString.clear(); } @@ -2554,7 +2216,7 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) LLScrollListColumn* sort_column = getColumn(column_idx); if (!sort_column) return FALSE; - sort_column->mSortAscending = ascending; + sort_column->mSortDirection = ascending ? LLScrollListColumn::ASCENDING : LLScrollListColumn::DESCENDING; sort_column_t new_sort_column(column_idx, ascending); @@ -2579,11 +2241,9 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending) } // Called by scrollbar -//static -void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata ) +void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar ) { - LLScrollListCtrl* self = (LLScrollListCtrl*) userdata; - self->mScrollLines = new_pos; + mScrollLines = new_pos; } @@ -2656,7 +2316,7 @@ void LLScrollListCtrl::setScrollPos( S32 pos ) { mScrollbar->setDocPos( pos ); - onScrollChange(mScrollbar->getDocPos(), mScrollbar, this); + onScrollChange(mScrollbar->getDocPos(), mScrollbar); } @@ -2706,293 +2366,6 @@ void LLScrollListCtrl::updateStaticColumnWidth(LLScrollListColumn* col, S32 new_ mTotalStaticColumnWidth += llmax(0, new_width) - llmax(0, col->getWidth()); } - -// virtual -LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - // Attributes - - node->createChild("multi_select", TRUE)->setBoolValue(mAllowMultipleSelection); - - node->createChild("draw_border", TRUE)->setBoolValue((mBorder != NULL)); - - node->createChild("draw_heading", TRUE)->setBoolValue(mDisplayColumnHeaders); - - node->createChild("background_visible", TRUE)->setBoolValue(mBackgroundVisible); - - node->createChild("draw_stripes", TRUE)->setBoolValue(mDrawStripes); - - node->createChild("column_padding", TRUE)->setIntValue(mColumnPadding); - - addColorXML(node, mBgWriteableColor, "bg_writeable_color", "ScrollBgWriteableColor"); - addColorXML(node, mBgReadOnlyColor, "bg_read_only_color", "ScrollBgReadOnlyColor"); - addColorXML(node, mBgSelectedColor, "bg_selected_color", "ScrollSelectedBGColor"); - addColorXML(node, mBgStripeColor, "bg_stripe_color", "ScrollBGStripeColor"); - addColorXML(node, mFgSelectedColor, "fg_selected_color", "ScrollSelectedFGColor"); - addColorXML(node, mFgUnselectedColor, "fg_unselected_color", "ScrollUnselectedColor"); - addColorXML(node, mFgDisabledColor, "fg_disable_color", "ScrollDisabledColor"); - addColorXML(node, mHighlightedColor, "highlighted_color", "ScrollHighlightedColor"); - - // Contents - - std::map::const_iterator itor; - std::vector sorted_list; - sorted_list.resize(mColumns.size()); - for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) - { - sorted_list[itor->second.mIndex] = &itor->second; - } - - std::vector::iterator itor2; - for (itor2 = sorted_list.begin(); itor2 != sorted_list.end(); ++itor2) - { - LLXMLNodePtr child_node = node->createChild("column", FALSE); - const LLScrollListColumn *column = *itor2; - - child_node->createChild("name", TRUE)->setStringValue(column->mName); - child_node->createChild("label", TRUE)->setStringValue(column->mLabel); - child_node->createChild("width", TRUE)->setIntValue(column->getWidth()); - } - - return node; -} - -void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node) -{ - // James: This is not a good way to do colors. We need a central "UI style" - // manager that sets the colors for ALL scroll lists, buttons, etc. - - LLColor4 color; - if(node->hasAttribute("fg_unselected_color")) - { - LLUICtrlFactory::getAttributeColor(node,"fg_unselected_color", color); - setFgUnselectedColor(color); - } - if(node->hasAttribute("fg_selected_color")) - { - LLUICtrlFactory::getAttributeColor(node,"fg_selected_color", color); - setFgSelectedColor(color); - } - if(node->hasAttribute("bg_selected_color")) - { - LLUICtrlFactory::getAttributeColor(node,"bg_selected_color", color); - setBgSelectedColor(color); - } - if(node->hasAttribute("fg_disable_color")) - { - LLUICtrlFactory::getAttributeColor(node,"fg_disable_color", color); - setFgDisableColor(color); - } - if(node->hasAttribute("bg_writeable_color")) - { - LLUICtrlFactory::getAttributeColor(node,"bg_writeable_color", color); - setBgWriteableColor(color); - } - if(node->hasAttribute("bg_read_only_color")) - { - LLUICtrlFactory::getAttributeColor(node,"bg_read_only_color", color); - setReadOnlyBgColor(color); - } - if (LLUICtrlFactory::getAttributeColor(node,"bg_stripe_color", color)) - { - setBgStripeColor(color); - } - if (LLUICtrlFactory::getAttributeColor(node,"highlighted_color", color)) - { - setHighlightedColor(color); - } - - if(node->hasAttribute("background_visible")) - { - BOOL background_visible; - node->getAttributeBOOL("background_visible", background_visible); - setBackgroundVisible(background_visible); - } - - if(node->hasAttribute("draw_stripes")) - { - BOOL draw_stripes; - node->getAttributeBOOL("draw_stripes", draw_stripes); - setDrawStripes(draw_stripes); - } - - if(node->hasAttribute("column_padding")) - { - S32 column_padding; - node->getAttributeS32("column_padding", column_padding); - setColumnPadding(column_padding); - } -} - -// static -LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name("scroll_list"); - node->getAttributeString("name", name); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - BOOL multi_select = FALSE; - node->getAttributeBOOL("multi_select", multi_select); - - BOOL draw_border = TRUE; - node->getAttributeBOOL("draw_border", draw_border); - - BOOL draw_heading = FALSE; - node->getAttributeBOOL("draw_heading", draw_heading); - - S32 search_column = 0; - node->getAttributeS32("search_column", search_column); - - S32 sort_column = -1; - node->getAttributeS32("sort_column", sort_column); - - BOOL sort_ascending = TRUE; - node->getAttributeBOOL("sort_ascending", sort_ascending); - - LLUICtrlCallback callback = NULL; - - LLScrollListCtrl* scroll_list = new LLScrollListCtrl( - name, - rect, - callback, - NULL, - multi_select, - draw_border); - - scroll_list->setDisplayHeading(draw_heading); - if (node->hasAttribute("heading_height")) - { - S32 heading_height; - node->getAttributeS32("heading_height", heading_height); - scroll_list->setHeadingHeight(heading_height); - } - - scroll_list->setScrollListParameters(node); - - scroll_list->initFromXML(node, parent); - - scroll_list->setSearchColumn(search_column); - - LLSD columns; - S32 index = 0; - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("column")) - { - std::string labelname(""); - child->getAttributeString("label", labelname); - - std::string columnname(labelname); - child->getAttributeString("name", columnname); - - std::string sortname(columnname); - child->getAttributeString("sort", sortname); - - BOOL sort_ascending = TRUE; - child->getAttributeBOOL("sort_ascending", sort_ascending); - - std::string imagename; - child->getAttributeString("image", imagename); - - BOOL columndynamicwidth = FALSE; - child->getAttributeBOOL("dynamicwidth", columndynamicwidth); - - S32 columnwidth = -1; - child->getAttributeS32("width", columnwidth); - - std::string tooltip; - child->getAttributeString("tool_tip", tooltip); - - F32 columnrelwidth = 0.f; - child->getAttributeF32("relwidth", columnrelwidth); - - LLFontGL::HAlign h_align = LLFontGL::LEFT; - h_align = LLView::selectFontHAlign(child); - - columns[index]["name"] = columnname; - columns[index]["sort"] = sortname; - columns[index]["sort_ascending"] = sort_ascending; - columns[index]["image"] = imagename; - columns[index]["label"] = labelname; - columns[index]["width"] = columnwidth; - columns[index]["relwidth"] = columnrelwidth; - columns[index]["dynamicwidth"] = columndynamicwidth; - columns[index]["halign"] = (S32)h_align; - columns[index]["tool_tip"] = tooltip; - - index++; - } - } - scroll_list->setColumnHeadings(columns); - - if (sort_column >= 0) - { - scroll_list->sortByColumnIndex(sort_column, sort_ascending); - } - - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("row")) - { - LLUUID id; - child->getAttributeUUID("id", id); - - LLSD row; - - row["id"] = id; - - S32 column_idx = 0; - LLXMLNodePtr row_child; - for (row_child = child->getFirstChild(); row_child.notNull(); row_child = row_child->getNextSibling()) - { - if (row_child->hasName("column")) - { - std::string value = row_child->getTextContents(); - - std::string columnname(""); - row_child->getAttributeString("name", columnname); - - std::string font(""); - row_child->getAttributeString("font", font); - - std::string font_style(""); - row_child->getAttributeString("font-style", font_style); - - row["columns"][column_idx]["column"] = columnname; - row["columns"][column_idx]["value"] = value; - row["columns"][column_idx]["font"] = font; - row["columns"][column_idx]["font-style"] = font_style; - column_idx++; - } - } - scroll_list->addElement(row); - } - } - - std::string contents = node->getTextContents(); - if (!contents.empty()) - { - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("\t\n"); - tokenizer tokens(contents, sep); - tokenizer::iterator token_iter = tokens.begin(); - - while(token_iter != tokens.end()) - { - const std::string& line = *token_iter; - scroll_list->addSimpleElement(line); - ++token_iter; - } - } - - return scroll_list; -} - // LLEditMenuHandler functions // virtual @@ -3068,20 +2441,27 @@ BOOL LLScrollListCtrl::canDeselect() const void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) { - std::string name = column["name"].asString(); + LLScrollListColumn::Params p; + LLParamSDParser::instance().readSD(column, p); + addColumn(p, pos); +} + +void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params, EAddPosition pos) +{ + if (!column_params.validateBlock()) return; + + std::string name = column_params.name; // if no column name provided, just use ordinal as name if (name.empty()) { - std::ostringstream new_name; - new_name << mColumnsIndexed.size(); - name = new_name.str(); + name = llformat("%d", mColumnsIndexed.size()); } + if (mColumns.find(name) == mColumns.end()) { // Add column - mColumns[name] = LLScrollListColumn(column, this); + mColumns[name] = LLScrollListColumn(column_params, this); LLScrollListColumn* new_column = &mColumns[name]; - new_column->mParentCtrl = this; new_column->mIndex = mColumns.size()-1; // Add button @@ -3101,44 +2481,47 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) new_column->setWidth((mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns); } S32 top = mItemListRect.mTop; + S32 left = mItemListRect.mLeft; + for (std::map::iterator itor = mColumns.begin(); + itor != mColumns.end(); + ++itor) { - std::map::iterator itor; - for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) + if (itor->second.mIndex < new_column->mIndex && + itor->second.getWidth() > 0) { - if (itor->second.mIndex < new_column->mIndex && - itor->second.getWidth() > 0) - { - left += itor->second.getWidth() + mColumnPadding; - } + left += itor->second.getWidth() + mColumnPadding; } } - std::string button_name = "btn_" + name; + S32 right = left+new_column->getWidth(); if (new_column->mIndex != (S32)mColumns.size()-1) { right += mColumnPadding; } + LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); - new_column->mHeader = new LLColumnHeader(button_name, temp_rect, new_column); - if(column["image"].asString() != "") + + LLScrollColumnHeader::Params params; + params.name = "btn_" + name; + params.rect = temp_rect; + params.column = new_column; + params.tool_tip = column_params.tool_tip; + params.tab_stop = false; + params.visible = mDisplayColumnHeaders; + + if(column_params.header.image.isProvided()) { - //new_column->mHeader->setScaleImage(false); - new_column->mHeader->setImage(column["image"].asString()); + params.image_selected = column_params.header.image; + params.image_unselected = column_params.header.image; } else { - new_column->mHeader->setLabel(new_column->mLabel); - //new_column->mHeader->setLabel(new_column->mLabel); + params.label = column_params.header.label; } - 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); + new_column->mHeader = LLUICtrlFactory::create(params); addChild(new_column->mHeader); - new_column->mHeader->setVisible(mDisplayColumnHeaders); sendChildToFront(mScrollbar); } @@ -3159,7 +2542,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata) S32 column_index = info->mIndex; LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex]; - bool ascending = column->mSortAscending; + bool ascending = column->mSortDirection == LLScrollListColumn::ASCENDING; if (column->mSortingColumn != column->mName && parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) { @@ -3178,7 +2561,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata) if (parent->mOnSortChangedCallback) { - parent->mOnSortChangedCallback(parent->getCallbackUserData()); + parent->mOnSortChangedCallback(); } } @@ -3200,7 +2583,7 @@ void LLScrollListCtrl::clearColumns() std::map::iterator itor; for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) { - LLColumnHeader *header = itor->second.mHeader; + LLScrollColumnHeader *header = itor->second.mHeader; if (header) { removeChild(header); @@ -3215,13 +2598,13 @@ void LLScrollListCtrl::clearColumns() void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label) { - std::map::iterator itor = mColumns.find(column); - if (itor != mColumns.end()) + LLScrollListColumn* columnp = getColumn(column); + if (columnp) { - itor->second.mLabel = label; - if (itor->second.mHeader) + columnp->mLabel = label; + if (columnp->mHeader) { - itor->second.mHeader->setLabel(label); + columnp->mHeader->setLabel(label); } } } @@ -3235,74 +2618,62 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(S32 index) return mColumnsIndexed[index]; } -void LLScrollListCtrl::setColumnHeadings(LLSD headings) +LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name) { - mColumns.clear(); - LLSD::array_const_iterator itor; - for (itor = headings.beginArray(); itor != headings.endArray(); ++itor) + column_map_t::iterator column_itor = mColumns.find(name); + if (column_itor != mColumns.end()) { - addColumn(*itor); + return &column_itor->second; } + return NULL; } -LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition pos, void* userdata) + +LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) { - // ID - LLSD id = value["id"]; + LLScrollListItem::Params item_params; + LLParamSDParser::instance().readSD(element, item_params); + item_params.userdata = userdata; + return addRow(item_params, pos); +} - LLScrollListItem *new_item = new LLScrollListItem(id, userdata); - if (value.has("enabled")) - { - new_item->setEnabled( value["enabled"].asBoolean() ); - } +LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos) +{ + if (!item_p.validateBlock()) return NULL; + LLScrollListItem *new_item = new LLScrollListItem(item_p); new_item->setNumColumns(mColumns.size()); // Add any columns we don't already have - LLSD columns = value["columns"]; - LLSD::array_const_iterator itor; - S32 col_index = 0 ; - for (itor = columns.beginArray(); itor != columns.endArray(); ++itor) - { - if (itor->isUndefined()) - { - // skip unused columns in item passed in - continue; - } - std::string column = (*itor)["column"].asString(); + S32 col_index = 0; - LLScrollListColumn* columnp = NULL; + for(LLInitParam::ParamIterator::const_iterator itor = item_p.cells().begin(); + itor != item_p.cells().end(); + ++itor) + { + LLScrollListCell::Params cell_p = *itor; + std::string column = cell_p.column; // empty columns strings index by ordinal if (column.empty()) { - std::ostringstream new_name; - new_name << col_index; - column = new_name.str(); + column = llformat("%d", col_index); } - std::map::iterator column_itor; - column_itor = mColumns.find(column); - if (column_itor != mColumns.end()) - { - columnp = &column_itor->second; - } + LLScrollListColumn* columnp = getColumn(column); // create new column on demand if (!columnp) { - LLSD new_column; - new_column["name"] = column; - new_column["label"] = column; + LLScrollListColumn::Params new_column; + new_column.name = column; + new_column.header.label = column; + // if width supplied for column, use it, otherwise // use adaptive width - if (itor->has("width")) - { - new_column["width"] = (*itor)["width"]; - } - else + if (cell_p.width.isProvided()) { - new_column["dynamicwidth"] = true; + new_column.width.pixel_width = cell_p.width; } addColumn(new_column); columnp = &mColumns[column]; @@ -3310,91 +2681,48 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p } S32 index = columnp->mIndex; - S32 width = columnp->getWidth(); - LLFontGL::HAlign font_alignment = columnp->mFontAlignment; - LLColor4 fcolor = LLColor4::black; - - LLSD value = (*itor)["value"]; - std::string fontname = (*itor)["font"].asString(); - std::string fontstyle = (*itor)["font-style"].asString(); - std::string type = (*itor)["type"].asString(); - - if ((*itor).has("font-color")) - { - LLSD sd_color = (*itor)["font-color"]; - fcolor.setValue(sd_color); - } - - BOOL has_color = (*itor).has("color"); - LLColor4 color = ((*itor)["color"]); - BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true; + cell_p.width.setIfNotProvided(columnp->getWidth()); - const LLFontGL *font = LLResMgr::getInstance()->getRes(fontname); - if (!font) - { - font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); - } - U8 font_style = LLFontGL::getStyleFromString(fontstyle); + LLScrollListCell* cell = LLScrollListCell::create(cell_p); - if (type == "icon") + if (cell) { - LLScrollListIcon* cell = new LLScrollListIcon(value, width); - if (has_color) - { - cell->setColor(color); - } new_item->setColumn(index, cell); - } - else if (type == "checkbox") - { - LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl(std::string("check"), - LLRect(0, width, width, 0), std::string(" ")); - ctrl->setEnabled(enabled); - ctrl->setValue(value); - LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width); - if (has_color) + if (columnp->mHeader + && cell->isText() + && !cell->getValue().asString().empty()) { - cell->setColor(color); - } - new_item->setColumn(index, cell); - } - else if (type == "separator") - { - LLScrollListSeparator* cell = new LLScrollListSeparator(width); - if (has_color) - { - cell->setColor(color); + columnp->mHeader->setHasResizableElement(TRUE); } - new_item->setColumn(index, cell); } - else if (type == "date") + + col_index++; + } + + if (item_p.cells().empty()) + { + if (mColumns.empty()) { - LLScrollListDate* cell = new LLScrollListDate(value.asDate(), font, width, font_style, font_alignment); - if (has_color) - { - cell->setColor(color); - } - new_item->setColumn(index, cell); - if (columnp->mHeader && !value.asString().empty()) - { - columnp->mHeader->setHasResizableElement(TRUE); - } + LLScrollListColumn::Params new_column; + new_column.name = "0"; + + addColumn(new_column); + new_item->setNumColumns(mColumns.size()); } - else + + LLScrollListCell* cell = LLScrollListCell::create(LLScrollListCell::Params().value(item_p.value)); + if (cell) { - LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE); - if (has_color) - { - cell->setColor(color); - } - new_item->setColumn(index, cell); - if (columnp->mHeader && !value.asString().empty()) + LLScrollListColumn* columnp = &(mColumns.begin()->second); + + new_item->setColumn(0, cell); + if (columnp->mHeader + && cell->isText() + && !cell->getValue().asString().empty()) { columnp->mHeader->setHasResizableElement(TRUE); } } - - col_index++; } // add dummy cells for missing columns @@ -3404,12 +2732,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p if (new_item->getColumn(column_idx) == NULL) { LLScrollListColumn* column_ptr = &column_it->second; - new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->getWidth(), LLFontGL::NORMAL)); + LLScrollListCell::Params cell_p; + cell_p.width = column_ptr->getWidth(); + + new_item->setColumn(column_idx, new LLScrollListSpacer(cell_p)); } } addItem(new_item, pos); - return new_item; } @@ -3422,14 +2752,13 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E entry_id = value; } - LLScrollListItem *new_item = new LLScrollListItem(entry_id); - - const LLFontGL *font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); - - new_item->addColumn(value, font, getRect().getWidth()); - - addItem(new_item, pos); - return new_item; + LLScrollListItem::Params item_params; + item_params.value(entry_id); + item_params.cells.add() + .value(value) + .font(LLFontGL::getFontSansSerifSmall()); + + return addRow(item_params, pos); } void LLScrollListCtrl::setValue(const LLSD& value ) @@ -3530,484 +2859,3 @@ void LLScrollListCtrl::onFocusLost() LLUICtrl::onFocusLost(); } -LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL* fontp) : - LLComboBox(label, rect, label, NULL, NULL), - mColumn(column), - mOrigLabel(label), - mShowSortOptions(FALSE), - mHasResizableElement(FALSE) -{ - mListPosition = LLComboBox::ABOVE; - setCommitCallback(onSelectSort); - setCallbackUserData(this); - mButton->setTabStop(FALSE); - // require at least two frames between mouse down and mouse up event to capture intentional "hold" not just bad framerate - mButton->setHeldDownDelay(LLUI::sConfigGroup->getF32("ColumnHeaderDropDownDelay"), 2); - mButton->setHeldDownCallback(onHeldDown); - mButton->setClickedCallback(onClick); - mButton->setMouseDownCallback(onMouseDown); - - mButton->setCallbackUserData(this); - mButton->setToolTip(label); - - mAscendingText = std::string("[LOW]...[HIGH](Ascending)"); // *TODO: Translate - mDescendingText = std::string("[HIGH]...[LOW](Descending)"); // *TODO: Translate - - mList->reshape(llmax(mList->getRect().getWidth(), 110, getRect().getWidth()), mList->getRect().getHeight()); - - // resize handles on left and right - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar = new LLResizeBar( - std::string("resizebar"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - MIN_COLUMN_WIDTH, S32_MAX, LLResizeBar::RIGHT ); - addChild(mResizeBar); - - mResizeBar->setEnabled(FALSE); -} - -LLColumnHeader::~LLColumnHeader() -{ -} - -void LLColumnHeader::draw() -{ - BOOL draw_arrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn; - - BOOL is_ascending = mColumn->mParentCtrl->getSortAscending(); - mButton->setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent); - mArrowImage = mButton->getImageOverlay(); - - //BOOL clip = getRect().mRight > mColumn->mParentCtrl->getItemListRect().getWidth(); - //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE); - - //LLRect column_header_local_rect(-getRect().mLeft, getRect().getHeight(), mColumn->mParentCtrl->getItemListRect().getWidth() - getRect().mLeft, 0); - //LLUI::setScissorRegionLocal(column_header_local_rect); - - // Draw children - LLComboBox::draw(); - - if (mList->getVisible()) - { - // sync sort order with list selection every frame - mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, getCurrentIndex() == 0); - } -} - -BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - if (canResize() && mResizeBar->getRect().pointInRect(x, y)) - { - // reshape column to max content width - LLRect column_rect = getRect(); - column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth; - userSetShape(column_rect); - } - else - { - onClick(this); - } - return TRUE; -} - -void LLColumnHeader::setImage(const std::string &image_name) -{ - if (mButton) - { - mButton->setImageSelected(image_name); - mButton->setImageUnselected(image_name); - } -} - -//static -void LLColumnHeader::onClick(void* user_data) -{ - LLColumnHeader* headerp = (LLColumnHeader*)user_data; - if (!headerp) return; - - LLScrollListColumn* column = headerp->mColumn; - if (!column) return; - - if (headerp->mList->getVisible()) - { - headerp->hideList(); - } - - LLScrollListCtrl::onClickColumn(column); - - // propagate new sort order to sort order list - headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1); -} - -//static -void LLColumnHeader::onMouseDown(void* user_data) -{ - // for now, do nothing but block the normal showList() behavior - return; -} - -//static -void LLColumnHeader::onHeldDown(void* user_data) -{ - LLColumnHeader* headerp = (LLColumnHeader*)user_data; - headerp->showList(); -} - -void LLColumnHeader::showList() -{ - if (mShowSortOptions) - { - //LLSD item_val = mColumn->mParentCtrl->getFirstData()->getValue(); - mOrigLabel = mButton->getLabelSelected(); - - // move sort column over to this column and do initial sort - mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, mColumn->mParentCtrl->getSortAscending()); - - std::string low_item_text; - std::string high_item_text; - - LLScrollListItem* itemp = mColumn->mParentCtrl->getFirstData(); - if (itemp) - { - LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex); - if (cell && cell->isText()) - { - if (mColumn->mParentCtrl->getSortAscending()) - { - low_item_text = cell->getValue().asString(); - } - else - { - high_item_text = cell->getValue().asString(); - } - } - } - - itemp = mColumn->mParentCtrl->getLastData(); - if (itemp) - { - LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex); - if (cell && cell->isText()) - { - if (mColumn->mParentCtrl->getSortAscending()) - { - high_item_text = cell->getValue().asString(); - } - else - { - low_item_text = cell->getValue().asString(); - } - } - } - - LLStringUtil::truncate(low_item_text, 3); - LLStringUtil::truncate(high_item_text, 3); - - std::string ascending_string; - std::string descending_string; - - if (low_item_text.empty() || high_item_text.empty()) - { - ascending_string = "Ascending"; - descending_string = "Descending"; - } - else - { - mAscendingText.setArg("[LOW]", low_item_text); - mAscendingText.setArg("[HIGH]", high_item_text); - mDescendingText.setArg("[LOW]", low_item_text); - mDescendingText.setArg("[HIGH]", high_item_text); - ascending_string = mAscendingText.getString(); - descending_string = mDescendingText.getString(); - } - - S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(ascending_string); - text_width = llmax(text_width, LLFontGL::getFontSansSerifSmall()->getWidth(descending_string)) + 10; - text_width = llmax(text_width, getRect().getWidth() - 30); - - mList->getColumn(0)->setWidth(text_width); - ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string); - ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string); - - mList->reshape(llmax(text_width + 30, 110, getRect().getWidth()), mList->getRect().getHeight()); - - LLComboBox::showList(); - } -} - -//static -void LLColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data) -{ - LLColumnHeader* headerp = (LLColumnHeader*)user_data; - if (!headerp) return; - - LLScrollListColumn* column = headerp->mColumn; - if (!column) return; - LLScrollListCtrl *parent = column->mParentCtrl; - if (!parent) return; - - if (headerp->getCurrentIndex() == 0) - { - // ascending - parent->sortByColumn(column->mSortingColumn, TRUE); - } - else - { - // descending - parent->sortByColumn(column->mSortingColumn, FALSE); - } - - // restore original column header - headerp->setLabel(headerp->mOrigLabel); -} - -LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding) -{ - // this logic assumes dragging on right - llassert(snap_edge == SNAP_RIGHT); - - // use higher snap threshold for column headers - threshold = llmin(threshold, 10); - - LLRect snap_rect = getSnapRect(); - - S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth(); - - // x coord growing means column growing, so same signs mean we're going in right direction - if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 ) - { - new_edge_val = snap_rect.mRight + snap_delta; - } - else - { - LLScrollListColumn* next_column = mColumn->mParentCtrl->getColumn(mColumn->mIndex + 1); - while (next_column) - { - if (next_column->mHeader) - { - snap_delta = (next_column->mHeader->getSnapRect().mRight - next_column->mMaxContentWidth) - snap_rect.mRight; - if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 ) - { - new_edge_val = snap_rect.mRight + snap_delta; - } - break; - } - next_column = mColumn->mParentCtrl->getColumn(next_column->mIndex + 1); - } - } - - return this; -} - -void LLColumnHeader::userSetShape(const LLRect& new_rect) -{ - S32 new_width = new_rect.getWidth(); - S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/); - - if (delta_width != 0) - { - S32 remaining_width = -delta_width; - S32 col; - for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++) - { - LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); - if (!columnp) continue; - - if (columnp->mHeader && columnp->mHeader->canResize()) - { - // how many pixels in width can this column afford to give up? - S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH); - - // user shrinking column, need to add width to other columns - if (delta_width < 0) - { - if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0) - { - // statically sized column, give all remaining width to this column - columnp->setWidth(columnp->getWidth() + remaining_width); - if (columnp->mRelWidth > 0.f) - { - columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); - } - // all padding went to this widget, we're done - break; - } - } - else - { - // user growing column, need to take width from other columns - remaining_width += resize_buffer_amt; - - if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0) - { - columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width)); - if (columnp->mRelWidth > 0.f) - { - columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); - } - } - - if (remaining_width >= 0) - { - // width sucked up from neighboring columns, done - break; - } - } - } - } - - // clamp resize amount to maximum that can be absorbed by other columns - if (delta_width > 0) - { - delta_width += llmin(remaining_width, 0); - } - - // propagate constrained delta_width to new width for this column - new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding(); - - // use requested width - mColumn->setWidth(new_width); - - // update proportional spacing - if (mColumn->mRelWidth > 0.f) - { - mColumn->mRelWidth = (F32)new_width / (F32)mColumn->mParentCtrl->getItemListRect().getWidth(); - } - - // tell scroll list to layout columns again - // do immediate update to get proper feedback to resize handle - // which needs to know how far the resize actually went - mColumn->mParentCtrl->updateColumns(); - } -} - -void LLColumnHeader::setHasResizableElement(BOOL resizable) -{ - // for now, dynamically spaced columns can't be resized -// if (mColumn->mDynamicWidth) return; - - if (mHasResizableElement != resizable) - { - mColumn->mParentCtrl->dirtyColumns(); - mHasResizableElement = resizable; - } -} - -void LLColumnHeader::updateResizeBars() -{ - S32 num_resizable_columns = 0; - S32 col; - for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) - { - LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); - if (columnp->mHeader && columnp->mHeader->canResize()) - { - num_resizable_columns++; - } - } - - S32 num_resizers_enabled = 0; - - // now enable/disable resize handles on resizable columns if we have at least two - for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++) - { - LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col); - if (!columnp->mHeader) continue; - BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize(); - columnp->mHeader->enableResizeBar(enable); - if (enable) - { - num_resizers_enabled++; - } - } -} - -void LLColumnHeader::enableResizeBar(BOOL enable) -{ - // for now, dynamically spaced columns can't be resized - //if (!mColumn->mDynamicWidth) - { - mResizeBar->setEnabled(enable); - } -} - -BOOL LLColumnHeader::canResize() -{ - return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); -} - -void LLScrollListColumn::setWidth(S32 width) -{ - if (!mDynamicWidth && mRelWidth <= 0.f) - { - mParentCtrl->updateStaticColumnWidth(this, width); - } - mWidth = width; -} - -// Default constructor -LLScrollListColumn::LLScrollListColumn() : - mName(), - mSortingColumn(), - mSortAscending(TRUE), - mLabel(), - mWidth(-1), - mRelWidth(-1.0), - mDynamicWidth(FALSE), - mMaxContentWidth(0), - mIndex(-1), - mParentCtrl(NULL), - mHeader(NULL), - mFontAlignment(LLFontGL::LEFT) -{ } - -LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) : - mWidth(0), - mIndex (-1), - mParentCtrl(parent), - mHeader(NULL), - mMaxContentWidth(0), - mDynamicWidth(FALSE), - mRelWidth(-1.f) -{ - mName = sd.get("name").asString(); - mSortingColumn = mName; - if (sd.has("sort")) - { - mSortingColumn = sd.get("sort").asString(); - } - mSortAscending = TRUE; - if (sd.has("sort_ascending")) - { - mSortAscending = sd.get("sort_ascending").asBoolean(); - } - mLabel = sd.get("label").asString(); - if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0) - { - mRelWidth = (F32)sd.get("relwidth").asReal(); - if (mRelWidth < 0) mRelWidth = 0; - if (mRelWidth > 1) mRelWidth = 1; - mDynamicWidth = FALSE; - } - else if(sd.has("dynamicwidth") && (BOOL)sd.get("dynamicwidth").asBoolean() == TRUE) - { - mDynamicWidth = TRUE; - mRelWidth = -1; - } - else - { - - setWidth(sd.get("width").asInteger()); - } - - if (sd.has("halign")) - { - mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER); - } - else - { - mFontAlignment = LLFontGL::LEFT; - } - -} -- cgit v1.2.3