diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index ce11ef2f2..83479888f 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -30,11 +30,44 @@ #include "llscrolllistcell.h" #include "llcheckboxctrl.h" +#include "llresmgr.h" + +//static +LLScrollListCell* LLScrollListCell::create(LLScrollListCell::Params cell_p) +{ + LLScrollListCell* cell = NULL; + + if (cell_p.type() == "icon") + { + cell = new LLScrollListIcon(cell_p); + } + else if (cell_p.type() == "checkbox") + { + cell = new LLScrollListCheck(cell_p); + } + else if (cell_p.type() == "date") + { + if (!cell_p.color.isProvided()) cell_p.color = LLUI::sColorsGroup->getColor("DefaultListText"); + cell = new LLScrollListDate(cell_p); + } + else // default is "text" + { + if (!cell_p.color.isProvided()) cell_p.color = LLUI::sColorsGroup->getColor("DefaultListText"); + cell = new LLScrollListText(cell_p); + } + + if (cell_p.value.isProvided()) + { + cell->setValue(cell_p.value); + } + + return cell; +} -LLScrollListCell::LLScrollListCell(S32 width) -: mWidth(width), - mToolTip() +LLScrollListCell::LLScrollListCell(const LLScrollListCell::Params& p) +: mWidth(p.width), + mToolTip(p.tool_tip) {} // virtual @@ -46,14 +79,15 @@ const LLSD LLScrollListCell::getValue() const // // LLScrollListIcon // -LLScrollListIcon::LLScrollListIcon(const LLSD& value, S32 width) -: LLScrollListCell(width), +LLScrollListIcon::LLScrollListIcon(const LLScrollListCell::Params& p) +: LLScrollListCell(p), // mCallback(NULL), // - mColor(LLColor4::white) + mColor(p.color), + mAlignment(p.font_halign) { - setValue(value); + setValue(p.value().asString()); } LLScrollListIcon::~LLScrollListIcon() @@ -115,7 +149,20 @@ void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_col { if (mIcon) { - mIcon->draw(0, 0, mColor); + switch(mAlignment) + { + case LLFontGL::LEFT: + mIcon->draw(0, 0, mColor); + break; + case LLFontGL::RIGHT: + mIcon->draw(getWidth() - mIcon->getWidth(), 0, mColor); + break; + case LLFontGL::HCENTER: + mIcon->draw((getWidth() - mIcon->getWidth()) / 2, 0, mColor); + break; + default: + break; + } } } @@ -124,15 +171,15 @@ void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_col // 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), +LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p) +: LLScrollListCell(p), + mText(p.value().asString()), + mFont(p.font.isProvided() ? LLResMgr::getInstance()->getRes(p.font) : LLFontGL::getFontSansSerifSmall()), + mColor(p.color), + mUseColor(p.color.isProvided()), + mFontStyle(LLFontGL::getStyleFromString(p.font_style)), + mFontAlignment(p.font_halign), + mVisible(p.visible), mHighlightCount( 0 ), mHighlightOffset( 0 ) { @@ -302,22 +349,25 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col // // LLScrollListCheck // -LLScrollListCheck::LLScrollListCheck(LLCheckBoxCtrl* check_box, S32 width) -: LLScrollListCell(width) +LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p) +: LLScrollListCell(p) { - mCheckBox = check_box; + mCheckBox = new LLCheckBoxCtrl("checkbox", LLRect(0, p.width, p.width, 0), "", NULL, NULL, p.value()); + mCheckBox->setEnabled(p.enabled); LLRect rect(mCheckBox->getRect()); - if (width) + if (p.width) { - rect.mRight = rect.mLeft + width; + rect.mRight = rect.mLeft + p.width; mCheckBox->setRect(rect); - setWidth(width); + setWidth(p.width); } else { setWidth(rect.getWidth()); //check_box->getWidth(); } + + mCheckBox->setColor(p.color); } @@ -370,9 +420,9 @@ void LLScrollListCheck::setEnabled(BOOL enable) // LLScrollListDate // -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) +LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p) +: LLScrollListText(p), + mDate(p.value().asDate()) {} void LLScrollListDate::setValue(const LLSD& value) diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 528166afd..3e4a9cd06 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -33,6 +33,7 @@ #include "lluistring.h" #include "v4color.h" #include "llui.h" +#include "llinitparam.h" class LLCheckBoxCtrl; class LLSD; @@ -48,7 +49,48 @@ class LLSD; class LLScrollListCell { public: - LLScrollListCell(S32 width = 0); + struct Params : public LLInitParam::Block + { + Optional type, + column; + + Optional width; + Optional enabled, + visible; + + Optional userdata; + Optional value; + Optional tool_tip; + + Optional font; + Optional font_color; + Optional font_halign; + Optional font_style; + + Optional color; + + Params() + : type("type", "text"), + column("column"), + width("width"), + enabled("enabled", true), + visible("visible", true), + value("value"), + tool_tip("tool_tip", ""), + font("font"/*, LLFontGL::getFontSansSerifSmall()*/), + font_color("font_color", LLColor4::black), + font_style("font-style"), + color("color", LLColor4::white), + font_halign("halign", LLFontGL::LEFT) + { + addSynonym(column, "name"); + addSynonym(font_color, "font-color"); + } + }; + + static LLScrollListCell* create(Params); + + LLScrollListCell(const LLScrollListCell::Params&); virtual ~LLScrollListCell() {}; virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const {}; // truncate to given width, if possible @@ -74,6 +116,13 @@ private: S32 mWidth; std::string mToolTip; }; + +class LLScrollListSpacer : public LLScrollListCell +{ +public: + LLScrollListSpacer(const LLScrollListCell::Params& p) : LLScrollListCell(p) {} + /*virtual*/ ~LLScrollListSpacer() {}; + /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const {} }; /* @@ -82,7 +131,7 @@ private: class LLScrollListText : public LLScrollListCell { public: - LLScrollListText(const std::string& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE); + LLScrollListText(const LLScrollListCell::Params&); /*virtual*/ ~LLScrollListText(); /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const; @@ -128,8 +177,7 @@ private: class LLScrollListIcon : public LLScrollListCell { public: - LLScrollListIcon( LLUIImagePtr icon, S32 width = 0); - LLScrollListIcon(const LLSD& value, S32 width = 0); + LLScrollListIcon(const LLScrollListCell::Params& p); /*virtual*/ ~LLScrollListIcon(); /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const; /*virtual*/ S32 getWidth() const; @@ -145,6 +193,7 @@ public: private: LLPointer mIcon; LLColor4 mColor; + LLFontGL::HAlign mAlignment; // boost::function mCallback; // @@ -156,7 +205,7 @@ private: class LLScrollListCheck : public LLScrollListCell { public: - LLScrollListCheck( LLCheckBoxCtrl* check_box, S32 width = 0); + LLScrollListCheck( const LLScrollListCell::Params&); /*virtual*/ ~LLScrollListCheck(); /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const; /*virtual*/ S32 getHeight() const { return 0; } @@ -176,7 +225,7 @@ private: class LLScrollListDate : public LLScrollListText { public: - LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width=0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE); + LLScrollListDate( const LLScrollListCell::Params& p ); virtual void setValue(const LLSD& value); virtual const LLSD getValue() const; diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 0cc0fe62a..8b00c86f0 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -294,52 +294,46 @@ BOOL LLScrollColumnHeader::canResize() return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth); } +void LLScrollListColumn::SortNames::declareValues() +{ + declare("ascending", LLScrollListColumn::ASCENDING); + declare("descending", LLScrollListColumn::DESCENDING); +} + // // LLScrollListColumn // -// Default constructor -LLScrollListColumn::LLScrollListColumn() : mName(), mSortingColumn(), mSortDirection(ASCENDING), mLabel(), mWidth(-1), mRelWidth(-1.0), mDynamicWidth(false), mMaxContentWidth(0), mIndex(-1), mParentCtrl(NULL), mHeader(NULL), mFontAlignment(LLFontGL::LEFT) +/* Singu TODO: LLUICtrlFactory::getDefaultParams +//static +const LLScrollListColumn::Params& LLScrollListColumn::getDefaultParams() { -} + return LLUICtrlFactory::getDefaultParams(); +}*/ -LLScrollListColumn::LLScrollListColumn(const LLSD& sd, LLScrollListCtrl* parent) +LLScrollListColumn::LLScrollListColumn(const Params& p, LLScrollListCtrl* parent) : mWidth(0), mIndex (-1), mParentCtrl(parent), - mName(sd.get("name").asString()), - mLabel(sd.get("label").asString()), + mName(p.name), + mLabel(p.header.label), mHeader(NULL), mMaxContentWidth(0), - mDynamicWidth(sd.has("dynamicwidth") && sd.get("dynamicwidth").asBoolean()), - mRelWidth(-1.f), - mFontAlignment(LLFontGL::LEFT), - mSortingColumn(sd.has("sort") ? sd.get("sort").asString() : mName) + mDynamicWidth(p.width.dynamic_width), + mRelWidth(p.width.relative_width), + mFontAlignment(p.halign), + mSortingColumn(p.sort_column) { - if (sd.has("sort_ascending")) + if (p.sort_ascending.isProvided()) { - mSortDirection = sd.get("sort_ascending").asBoolean() ? ASCENDING : DESCENDING; + mSortDirection = p.sort_ascending() ? ASCENDING : DESCENDING; } else { - mSortDirection = ASCENDING; + mSortDirection = p.sort_direction; } - if (sd.has("relwidth") && sd.get("relwidth").asFloat() > 0) - { - mRelWidth = sd.get("relwidth").asFloat(); - if (mRelWidth > 1) mRelWidth = 1; - mDynamicWidth = false; - } - else if (!mDynamicWidth) - { - setWidth(sd.get("width").asInteger()); - } - - if (sd.has("halign")) - { - mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER); - } + setWidth(p.width.pixel_width); } void LLScrollListColumn::setWidth(S32 width) diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index 3b47f4010..2026e075c 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -31,6 +31,7 @@ #include "llrect.h" #include "lluistring.h" #include "llbutton.h" +#include "llinitparam.h" class LLScrollListColumn; class LLResizeBar; @@ -75,9 +76,73 @@ public: ASCENDING } ESortDirection; + struct SortNames + : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; + + struct Params : public LLInitParam::Block + { + Optional name, + tool_tip; + Optional sort_column; + Optional sort_direction; + Optional sort_ascending; + + struct Width : public LLInitParam::ChoiceBlock + { + Alternative dynamic_width; + Alternative pixel_width; + Alternative relative_width; + + Width() + : dynamic_width("dynamic_width", false), + pixel_width("width"), + relative_width("relative_width", -1.f) + { + addSynonym(dynamic_width, "dynamicwidth"); // Singu TODO: deprecate and remove + addSynonym(relative_width, "relwidth"); + } + }; + Optional width; + + // either an image or label is used in column header + struct Header : public LLInitParam::ChoiceBlock
+ { + Alternative label; + Alternative image_overlay; + Alternative image; + + Header() + : label("label"), + image_overlay("image_overlay"), + image("image") + {} + }; + Optional
header; + + Optional halign; + + Params() + : name("name"), + tool_tip("tool_tip"), + sort_column("sort_column"), + sort_direction("sort_direction"), + sort_ascending("sort_ascending", true), + halign("halign", LLFontGL::LEFT) + { + // default choice to "dynamic_width" + changeDefault(width.dynamic_width, true); + + addSynonym(sort_column, "sort"); + } + }; + + //static const Params& getDefaultParams(); + //NOTE: this is default constructible so we can store it in a map. - LLScrollListColumn(); - LLScrollListColumn(const LLSD& sd, LLScrollListCtrl* parent = NULL); + LLScrollListColumn(const Params& p = Params(), LLScrollListCtrl* = NULL); void setWidth(S32 width); S32 getWidth() const { return mWidth; } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 0268596d4..504e7288e 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -51,6 +51,7 @@ #include "llwindow.h" #include "llcontrol.h" #include "llkeyboard.h" +#include "llsdparam.h" static LLRegisterWidget r("scroll_list"); @@ -103,65 +104,6 @@ struct SortScrollListItem const sort_order_t& mSortOrders; }; - -//Singu TODO: Get rid of these in favor of making separators out of normal LLScrollListItems like LL -// -// LLScrollListSeparator -// -/* - * Draws a horizontal line. - */ -class LLScrollListSeparator : public LLScrollListCell -{ -public: - LLScrollListSeparator(S32 width) : LLScrollListCell(width) {} - virtual ~LLScrollListSeparator() {}; - virtual void 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); - } - virtual S32 getHeight() const { return 5; }; - virtual BOOL isText() const { return FALSE; } -}; - -//--------------------------------------------------------------------------- -// LLScrollListItemSeparator -//--------------------------------------------------------------------------- - -class LLScrollListItemSeparator : public LLScrollListItem -{ -public: - LLScrollListItemSeparator() : LLScrollListItem(false) - { - LLScrollListSeparator* cell = new LLScrollListSeparator(0); - setNumColumns(1); - setColumn(0, cell); - } - - /*virtual*/ void 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 //--------------------------------------------------------------------------- @@ -182,7 +124,6 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect, mColumnsDirty(false), mMaxItemCount(INT_MAX), mMaxContentWidth(0), - mDefaultListTextColor(LLUI::sColorsGroup->getColor("DefaultListText")), mBorderThickness( 2 ), mOnDoubleClickCallback( NULL ), mOnMaximumSelectCallback( NULL ), @@ -583,11 +524,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); } S32 num_cols = item->getNumColumns(); @@ -1182,13 +1123,20 @@ void LLScrollListCtrl::setCommentText(const std::string& 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 column_params; + column_params.type = "icon"; + column_params.value = "menu_separator.png"; + column_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); + column_params.font_halign = LLFontGL::HCENTER; + separator_params.columns.add(column_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) { deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match @@ -1339,14 +1287,16 @@ const std::string LLScrollListCtrl::getSelectedItemLabel(S32 column) const LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos, BOOL enabled) { - LLScrollListItem* item = NULL; if (getItemCount() < mMaxItemCount) { - item = new LLScrollListItem(enabled, 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.columns.add().value(item_text).type("text"); + + return addRow( item_p, pos ); } - return item; + return NULL; } // Select the line or lines that match this UUID @@ -2608,38 +2558,44 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac 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); - std::string imageoverlay; - child->getAttributeString("image_overlay", imageoverlay); - 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 = LLView::selectFontHAlign(child); + if (child->getAttributeString("label", labelname)) + columns[index]["label"] = labelname; + else if (child->getAttributeString("image", labelname)) + columns[index]["image"] = labelname; + else if (child->getAttributeString("image_overlay", labelname)) + columns[index]["image_overlay"] = labelname; - columns[index]["name"] = columnname; - columns[index]["sort"] = sortname; - columns[index]["sort_ascending"] = sort_ascending; - columns[index]["image"] = imagename; - columns[index]["image_overlay"] = imageoverlay; - columns[index]["label"] = labelname; - columns[index]["width"] = columnwidth; - columns[index]["relwidth"] = columnrelwidth; - columns[index]["dynamicwidth"] = columndynamicwidth; + std::string columnname(labelname); + if (child->getAttributeString("name", columnname)) + columns[index]["name"] = columnname; + + std::string sortname(columnname); + if (child->getAttributeString("sort", sortname)) + columns[index]["sort"] = sortname; + + BOOL sort_ascending = true; + if (child->getAttributeBOOL("sort_ascending", sort_ascending)) + columns[index]["sort_ascending"] = sort_ascending; + + S32 columnwidth = -1; + if (child->getAttributeS32("width", columnwidth)) + columns[index]["width"] = columnwidth; + + F32 columnrelwidth = 0.f; + if (child->getAttributeF32("relwidth", columnrelwidth)) + columns[index]["relwidth"] = columnrelwidth; + + BOOL columndynamicwidth = false; + if (child->getAttributeBOOL("dynamic_width", columndynamicwidth) + || child->getAttributeBOOL("dynamicwidth", columndynamicwidth)) // Singu TODO: Deprecate "dynamicwidth" + columns[index]["dynamic_width"] = columndynamicwidth; + + LLFontGL::HAlign h_align = LLView::selectFontHAlign(child); columns[index]["halign"] = (S32)h_align; - columns[index]["tool_tip"] = tooltip; + + std::string tooltip; + if (child->getAttributeString("tool_tip", tooltip)) + columns[index]["tool_tip"] = tooltip; ++index; } } @@ -2671,18 +2627,20 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac if (row_child->hasName("column")) { std::string value = row_child->getTextContents(); + row["columns"][column_idx]["value"] = value; 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); + if (row_child->getAttributeString("name", columnname)) + row["columns"][column_idx]["column"] = columnname; + + std::string font(""); + if (row_child->getAttributeString("font", font)) + row["columns"][column_idx]["font"] = font; + + std::string font_style(""); + if (row_child->getAttributeString("font-style", font_style)) + row["columns"][column_idx]["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; explicit_column = true; } @@ -2778,7 +2736,17 @@ BOOL LLScrollListCtrl::canDeselect() const void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) { - std::string name = column["name"].asString(); + LLScrollListColumn::Params p; + LLParamSDParser parser; + parser.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()) { @@ -2788,9 +2756,8 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) if (mColumns.find(name) == mColumns.end()) { // Add column - mColumns[name] = new LLScrollListColumn(column, this); + mColumns[name] = new LLScrollListColumn(column_params, this); LLScrollListColumn* new_column = mColumns[name]; - new_column->mParentCtrl = this; new_column->mIndex = mColumns.size()-1; // Add button @@ -2832,21 +2799,21 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); new_column->mHeader = new LLScrollColumnHeader("btn_" + name, temp_rect, new_column); - new_column->mHeader->setToolTip(column["tool_tip"].asString()); + new_column->mHeader->setToolTip(column_params.tool_tip()); new_column->mHeader->setTabStop(false); new_column->mHeader->setVisible(mDisplayColumnHeaders); - if(!column["image"].asString().empty()) + if(column_params.header.image.isProvided()) { - new_column->mHeader->setImages(column["image"].asString(), column["image"].asString()); + new_column->mHeader->setImages(column_params.header.image, column_params.header.image); } - else if(!column["image_overlay"].asString().empty()) + else if(column_params.header.image_overlay.isProvided()) { - new_column->mHeader->setImageOverlay(column["image_overlay"].asString()); + new_column->mHeader->setImageOverlay(column_params.header.image_overlay); } else { - new_column->mHeader->setLabel(new_column->mLabel.getString()); + new_column->mHeader->setLabel(column_params.header.label()); } addChild(new_column->mHeader); @@ -2981,29 +2948,39 @@ void LLScrollListCtrl::setColumnHeadings(const LLSD& headings) "width" "dynamic_width" */ +LLFastTimer::DeclareTimer FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item"); LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) { - LLScrollListItem *new_item = new LLScrollListItem(!element.has("enabled") || element["enabled"].asBoolean(), element["id"], userdata); + LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT); + LLScrollListItem::Params item_params; + LLParamSDParser parser; + parser.readSD(element, item_params); + item_params.userdata = userdata; + return addRow(item_params, pos); +} - if (!new_item) return NULL; +LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos) +{ + LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT); + LLScrollListItem *new_item = new LLScrollListItem(item_p); + return addRow(new_item, item_p, pos); +} + +LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos) +{ + LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT); + if (!item_p.validateBlock() || !new_item) return NULL; new_item->setNumColumns(mColumns.size()); // Add any columns we don't already have S32 col_index = 0; - LLSD columns = element["columns"]; - for (LLSD::array_const_iterator itor = columns.beginArray(); - itor != columns.endArray(); + for(LLInitParam::ParamIterator::const_iterator itor = item_p.columns.begin(); + itor != item_p.columns.end(); ++itor) { - if (itor->isUndefined()) - { - // skip unused columns in item passed in - continue; - } - std::string column = (*itor)["column"].asString(); - - LLScrollListColumn* columnp = NULL; + LLScrollListCell::Params cell_p = *itor; + std::string column = cell_p.column; // empty columns strings index by ordinal if (column.empty()) @@ -3011,27 +2988,20 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition column = llformat("%d", col_index); } - column_map_t::iterator 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")) + if (cell_p.width.isProvided()) { - new_column["width"] = (*itor)["width"]; - } - else - { - new_column["dynamicwidth"] = true; + new_column.width.pixel_width = cell_p.width; } addColumn(new_column); columnp = mColumns[column]; @@ -3039,89 +3009,20 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition } S32 index = columnp->mIndex; - S32 width = columnp->getWidth(); - LLFontGL::HAlign font_alignment = columnp->mFontAlignment; - LLColor4 fcolor = LLColor4::black; + if (!cell_p.width.isProvided()) + { + cell_p.width = columnp->getWidth(); + } + cell_p.font_halign = columnp->mFontAlignment; - 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); - } + LLScrollListCell* cell = LLScrollListCell::create(cell_p); - BOOL has_color = (*itor).has("color"); - LLColor4 color = ((*itor)["color"]); - BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true; - - const LLFontGL *font = LLResMgr::getInstance()->getRes(fontname); - if (!font) + if (cell) { - font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); - } - U8 font_style = LLFontGL::getStyleFromString(fontstyle); - - if (type == "icon") - { - 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) - { - cell->setColor(color); - } - new_item->setColumn(index, cell); - } - else if (type == "separator") - { - LLScrollListSeparator* cell = new LLScrollListSeparator(width); - if (has_color) - { - cell->setColor(color); - } - new_item->setColumn(index, cell); - } - else if (type == "date") - { - 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); - } - } - else - { - LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE); - if (has_color) - { - cell->setColor(color); - } - else - { - cell->setColor(mDefaultListTextColor); - } - new_item->setColumn(index, cell); - if (columnp->mHeader && !value.asString().empty()) + if (columnp->mHeader + && cell->isText() + && !cell->getValue().asString().empty()) { columnp->mHeader->setHasResizableElement(TRUE); } @@ -3130,6 +3031,32 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition col_index++; } + if (item_p.columns.empty()) + { + if (mColumns.empty()) + { + LLScrollListColumn::Params new_column; + new_column.name = "0"; + + addColumn(new_column); + new_item->setNumColumns(mColumns.size()); + } + + LLScrollListCell* cell = LLScrollListCell::create(LLScrollListCell::Params().value(item_p.value)); + if (cell) + { + LLScrollListColumn* columnp = mColumns.begin()->second; + + new_item->setColumn(0, cell); + if (columnp->mHeader + && cell->isText() + && !cell->getValue().asString().empty()) + { + columnp->mHeader->setHasResizableElement(TRUE); + } + } + } + // add dummy cells for missing columns for (column_map_t::iterator column_it = mColumns.begin(); column_it != mColumns.end(); ++column_it) { @@ -3137,7 +3064,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition 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)); } } @@ -3147,14 +3077,20 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, EAddPosition pos, const LLSD& id) { - LLScrollListItem* new_item = new LLScrollListItem(true, id.isUndefined() ? LLSD(value) : id); + LLSD entry_id = id; - const LLFontGL *font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ); + if (id.isUndefined()) + { + entry_id = value; + } - new_item->addColumn(value, font, getRect().getWidth()); + LLScrollListItem::Params item_params; + item_params.value(entry_id); + item_params.columns.add() + .value(value) + /*.font(LLFontGL::getFontSansSerifSmall())*/; - addItem(new_item, pos); - return new_item; + return addRow(item_params, pos); } void LLScrollListCtrl::setValue(const LLSD& value ) diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index ba09e8986..5b5b91d2d 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -42,8 +42,8 @@ #include "llframetimer.h" #include "llscrollbar.h" - -class LLScrollListColumn; +#include "llscrolllistitem.h" +#include "llscrolllistcolumn.h" class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler, public LLCtrlListInterface, public LLCtrlScrollInterface @@ -95,6 +95,7 @@ public: // LLCtrlListInterface functions virtual S32 getItemCount() const; // Adds a single column descriptor: ["name" : string, "label" : string, "width" : integer, "relwidth" : integer ] + virtual void addColumn(const LLScrollListColumn::Params& column, EAddPosition pos = ADD_BOTTOM); virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM); virtual void clearColumns(); virtual void setColumnLabel(const std::string& column, const std::string& label); @@ -106,6 +107,8 @@ public: // "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid // Creates missing columns automatically. virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); + virtual LLScrollListItem* addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM); + virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM); // Simple add element. Takes a single array of: // [ "value" => value, "font" => font, "font-style" => style ] virtual void clearRows(); // clears all elements @@ -419,7 +422,6 @@ private: LLColor4 mFgUnselectedColor; LLColor4 mFgDisabledColor; LLColor4 mHighlightedColor; - LLColor4 mDefaultListTextColor; S32 mBorderThickness; callback_t mOnDoubleClickCallback; diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp index 936fb6691..fc48e2578 100644 --- a/indra/llui/llscrolllistitem.cpp +++ b/indra/llui/llscrolllistitem.cpp @@ -34,11 +34,11 @@ // LLScrollListItem //--------------------------------------------------------------------------- -LLScrollListItem::LLScrollListItem( bool enabled, const LLSD& value, void* userdata ) +LLScrollListItem::LLScrollListItem( const Params& p ) : mSelected(FALSE), - mEnabled(enabled), - mUserdata(userdata), - mItemValue(value), + mEnabled(p.enabled), + mUserdata(p.userdata), + mItemValue(p.value), mColumns() { } @@ -49,9 +49,9 @@ LLScrollListItem::~LLScrollListItem() std::for_each(mColumns.begin(), mColumns.end(), DeletePointer()); } -void LLScrollListItem::addColumn(const std::string& text, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, bool visible) +void LLScrollListItem::addColumn(const LLScrollListCell::Params& p) { - mColumns.push_back(new LLScrollListText(text, font, width, font_style, font_alignment, LLColor4::black, false, visible)); + mColumns.push_back(LLScrollListCell::create(p)); } void LLScrollListItem::setNumColumns(S32 columns) diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 05c1f246e..bdc292def 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -41,6 +41,30 @@ class LLScrollListItem { friend class LLScrollListCtrl; public: + struct Params : public LLInitParam::Block + { + Optional enabled; + Optional userdata; + Optional value; + + Ignored name; // use for localization tools + Ignored type; + Ignored length; + + Multiple columns; + + Params() + : enabled("enabled", true), + value("value"), + name("name"), + type("type"), + length("length"), + columns("columns") + { + addSynonym(columns, "column"); + addSynonym(value, "id"); + } + }; virtual ~LLScrollListItem(); @@ -59,7 +83,7 @@ public: void setRect(LLRect rect) { mRectangle = rect; } LLRect getRect() const { return mRectangle; } - void addColumn( const std::string& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, bool visible = true ); + void addColumn( const LLScrollListCell::Params& p ); void setNumColumns(S32 columns); @@ -74,7 +98,7 @@ public: virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); protected: - LLScrollListItem( bool enabled = true, const LLSD& value = LLSD(), void* userdata = NULL ); + LLScrollListItem( const Params& ); private: BOOL mSelected; diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 71db12ffc..de8075e4c 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -778,7 +778,7 @@ void LLFloaterAvatarList::refreshAvatarList() BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) { - LLSD element; + LLScrollListItem::Params element; LLUUID av_id; std::string av_name; @@ -825,33 +825,30 @@ void LLFloaterAvatarList::refreshAvatarList() continue; } + element.value = av_id; - element["id"] = av_id; - - element["columns"][LIST_MARK]["column"] = "marked"; - element["columns"][LIST_MARK]["type"] = "text"; + LLScrollListCell::Params mark; + mark.column = "marked"; + mark.type = "text"; if (entry->isMarked()) { - element["columns"][LIST_MARK]["value"] = "X"; - element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue(); - element["columns"][LIST_MARK]["font-style"] = "BOLD"; - } - else - { - element["columns"][LIST_MARK]["value"] = ""; + mark.value = "X"; + mark.color = LLColor4::blue; + mark.font_style = "BOLD"; } - element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name"; - element["columns"][LIST_AVATAR_NAME]["type"] = "text"; - element["columns"][LIST_AVATAR_NAME]["value"] = av_name; + LLScrollListCell::Params name; + name.column = "avatar_name"; + name.type = "text"; + name.value = av_name; if (entry->isFocused()) { - element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD"; + name.font_style = "BOLD"; } // custom colors for certain types of avatars! //Changed a bit so people can modify them in settings. And since they're colors, again it's possibly account-based. Starting to think I need a function just to determine that. - HgB - //element["columns"][LIST_AVATAR_NAME]["color"] = gColors.getColor( "MapAvatar" ).getValue(); + //name.color = gColors.getColor( "MapAvatar" ); LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry->getPosition()); LLUUID estate_owner = LLUUID::null; if(parent_estate && parent_estate->isAlive()) @@ -895,12 +892,13 @@ void LLFloaterAvatarList::refreshAvatarList() name_color = name_color*0.5f + unselected_color*0.5f; - element["columns"][LIST_AVATAR_NAME]["color"] = name_color.getValue(); + name.color = name_color; char temp[32]; LLColor4 color = sDefaultListText; - element["columns"][LIST_DISTANCE]["column"] = "distance"; - element["columns"][LIST_DISTANCE]["type"] = "text"; + LLScrollListCell::Params dist; + dist.column = "distance"; + dist.type = "text"; if (UnknownAltitude) { strcpy(temp, "?"); @@ -932,9 +930,10 @@ void LLFloaterAvatarList::refreshAvatarList() snprintf(temp, sizeof(temp), "%d", (S32)distance); } } - element["columns"][LIST_DISTANCE]["value"] = temp; - element["columns"][LIST_DISTANCE]["color"] = color.getValue(); + dist.value = temp; + dist.color = color; + LLScrollListCell::Params pos; position = position - simpos; S32 x = (S32)position.mdV[VX]; @@ -963,12 +962,13 @@ void LLFloaterAvatarList::refreshAvatarList() strcat(temp, "E"); } } - element["columns"][LIST_POSITION]["column"] = "position"; - element["columns"][LIST_POSITION]["type"] = "text"; - element["columns"][LIST_POSITION]["value"] = temp; + pos.column = "position"; + pos.type = "text"; + pos.value = temp; - element["columns"][LIST_ALTITUDE]["column"] = "altitude"; - element["columns"][LIST_ALTITUDE]["type"] = "text"; + LLScrollListCell::Params alt; + alt.column = "altitude"; + alt.type = "text"; if (UnknownAltitude) { strcpy(temp, "?"); @@ -977,10 +977,11 @@ void LLFloaterAvatarList::refreshAvatarList() { snprintf(temp, sizeof(temp), "%d", (S32)position.mdV[VZ]); } - element["columns"][LIST_ALTITUDE]["value"] = temp; + alt.value = temp; - element["columns"][LIST_ACTIVITY]["column"] = "activity"; - element["columns"][LIST_ACTIVITY]["type"] = "icon"; + LLScrollListCell::Params act; + act.column = "activity"; + act.type = "icon"; std::string activity_icon = ""; std::string activity_tip = ""; @@ -1032,12 +1033,13 @@ void LLFloaterAvatarList::refreshAvatarList() break; } - element["columns"][LIST_ACTIVITY]["value"] = activity_icon;//icon_image_id; //"icn_active-speakers-dot-lvl0.tga"; - //element["columns"][LIST_AVATAR_ACTIVITY]["color"] = icon_color.getValue(); - element["columns"][LIST_ACTIVITY]["tool_tip"] = activity_tip; + act.value = activity_icon;//icon_image_id; //"icn_active-speakers-dot-lvl0.tga"; + //act.color = icon_color; + act.tool_tip = activity_tip; - element["columns"][LIST_AGE]["column"] = "age"; - element["columns"][LIST_AGE]["type"] = "text"; + LLScrollListCell::Params agep; + agep.column = "age"; + agep.type = "text"; color = sDefaultListText; std::string age = boost::lexical_cast(entry->mAge); if (entry->mAge > -1) @@ -1057,21 +1059,22 @@ void LLFloaterAvatarList::refreshAvatarList() { age = "?"; } - element["columns"][LIST_AGE]["value"] = age; - element["columns"][LIST_AGE]["color"] = color.getValue(); + agep.value = age; + agep.color = color; int dur = difftime(time(NULL), entry->getTime()); int hours = dur / 3600; int mins = (dur % 3600) / 60; int secs = (dur % 3600) % 60; - element["columns"][LIST_TIME]["column"] = "time"; - element["columns"][LIST_TIME]["type"] = "text"; - element["columns"][LIST_TIME]["value"] = llformat("%d:%02d:%02d", hours, mins, secs); - - element["columns"][LIST_CLIENT]["column"] = "client"; - element["columns"][LIST_CLIENT]["type"] = "text"; + LLScrollListCell::Params time; + time.column = "time"; + time.type = "text"; + time.value = llformat("%d:%02d:%02d", hours, mins, secs); + LLScrollListCell::Params viewer; + viewer.column = "client"; + viewer.type = "text"; static const LLCachedControl avatar_name_color(gColors, "AvatarNameColor",LLColor4(0.98f, 0.69f, 0.36f, 1.f)); LLColor4 client_color(avatar_name_color); @@ -1085,18 +1088,30 @@ void LLFloaterAvatarList::refreshAvatarList() client_color = unselected_color; client = "?"; } + viewer.value = client.c_str(); } else { - element["columns"][LIST_CLIENT]["value"] = getString("Out Of Range"); + viewer.value = getString("Out Of Range"); } //Blend to make the color show up better client_color = client_color *.5f + unselected_color * .5f; - element["columns"][LIST_CLIENT]["color"] = client_color.getValue(); + viewer.color = client_color; + + // Add individual column cell params to the item param + element.columns.add(mark); + element.columns.add(name); + element.columns.add(dist); + element.columns.add(pos); + element.columns.add(alt); + element.columns.add(act); + element.columns.add(agep); + element.columns.add(time); + element.columns.add(viewer); // Add to list - mAvatarList->addElement(element, ADD_BOTTOM); + mAvatarList->addRow(element); } // finish diff --git a/indra/newview/skins/default/textures/menu_separator.png b/indra/newview/skins/default/textures/menu_separator.png new file mode 100644 index 000000000..89dcdcdff Binary files /dev/null and b/indra/newview/skins/default/textures/menu_separator.png differ