diff options
Diffstat (limited to 'indra/llui/llscrolllistctrl.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/llui/llscrolllistctrl.cpp | 470 |
1 files changed, 287 insertions, 183 deletions
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index a6cd6412e5..db8fdc46b7 100644..100755 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3,31 +3,25 @@ * @brief Scroll lists are composed of rows (items), each of which * contains columns (cells). * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -41,6 +35,7 @@ #include "llboost.h" //#include "indra_constants.h" +#include "llavatarnamecache.h" #include "llcheckboxctrl.h" #include "llclipboard.h" #include "llfocusmgr.h" @@ -71,8 +66,9 @@ static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list"); // local structures & classes. struct SortScrollListItem { - SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders) + SortScrollListItem(const std::vector<std::pair<S32, BOOL> >& sort_orders,const LLScrollListCtrl::sort_signal_t* sort_signal) : mSortOrders(sort_orders) + , mSortSignal(sort_signal) {} bool operator()(const LLScrollListItem* i1, const LLScrollListItem* i2) @@ -85,12 +81,20 @@ struct SortScrollListItem S32 col_idx = it->first; BOOL sort_ascending = it->second; + S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column? + const LLScrollListCell *cell1 = i1->getColumn(col_idx); const LLScrollListCell *cell2 = i2->getColumn(col_idx); - S32 order = sort_ascending ? 1 : -1; // ascending or descending sort for this column? if (cell1 && cell2) { - sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString()); + if(mSortSignal) + { + sort_result = order * (*mSortSignal)(col_idx,i1, i2); + } + else + { + sort_result = order * LLStringUtil::compareDict(cell1->getValue().asString(), cell2->getValue().asString()); + } if (sort_result != 0) { break; // we have a sort order! @@ -100,8 +104,10 @@ struct SortScrollListItem return sort_result < 0; } + typedef std::vector<std::pair<S32, BOOL> > sort_order_t; + const LLScrollListCtrl::sort_signal_t* mSortSignal; const sort_order_t& mSortOrders; }; @@ -124,6 +130,7 @@ LLScrollListCtrl::Params::Params() search_column("search_column", 0), sort_column("sort_column", -1), sort_ascending("sort_ascending", true), + mouse_wheel_opaque("mouse_wheel_opaque", false), commit_on_keyboard_movement("commit_on_keyboard_movement", true), heading_height("heading_height"), page_lines("page_lines", 0), @@ -141,39 +148,39 @@ LLScrollListCtrl::Params::Params() highlighted_color("highlighted_color"), contents(""), scroll_bar_bg_visible("scroll_bar_bg_visible"), - scroll_bar_bg_color("scroll_bar_bg_color") -{ - name = "scroll_list"; - mouse_opaque = true; -} + scroll_bar_bg_color("scroll_bar_bg_color"), + border("border") +{} LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) : LLUICtrl(p), mLineHeight(0), mScrollLines(0), + mMouseWheelOpaque(p.mouse_wheel_opaque), mPageLines(p.page_lines), mMaxSelectable(0), - mAllowKeyboardMovement(TRUE), + mAllowKeyboardMovement(true), mCommitOnKeyboardMovement(p.commit_on_keyboard_movement), - mCommitOnSelectionChange(FALSE), - mSelectionChanged(FALSE), - mNeedsScroll(FALSE), - mCanSelect(TRUE), - mColumnsDirty(FALSE), + mCommitOnSelectionChange(false), + mSelectionChanged(false), + mNeedsScroll(false), + mCanSelect(true), + mColumnsDirty(false), mMaxItemCount(INT_MAX), - mMaxContentWidth(0), mBorderThickness( 2 ), mOnDoubleClickCallback( NULL ), mOnMaximumSelectCallback( NULL ), mOnSortChangedCallback( NULL ), mHighlightedItem(-1), mBorder(NULL), + mSortCallback(NULL), mPopupMenu(NULL), + mCommentTextView(NULL), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), mTotalColumnPadding(0), mSorted(false), - mDirty(FALSE), + mDirty(false), mOriginalSelection(-1), mLastSelected(NULL), mHeadingHeight(p.heading_height), @@ -231,10 +238,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) if (p.has_border) { LLRect border_rect = getLocalRect(); - LLViewBorder::Params params; - params.name("dig border"); + LLViewBorder::Params params = p.border; params.rect(border_rect); - params.bevel_style(LLViewBorder::BEVEL_IN); mBorder = LLUICtrlFactory::create<LLViewBorder> (params); addChild(mBorder); } @@ -252,15 +257,15 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) } - for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator row_it = p.contents.columns().begin(); - row_it != p.contents.columns().end(); + for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator row_it = p.contents.columns.begin(); + row_it != p.contents.columns.end(); ++row_it) { addColumn(*row_it); } - for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = p.contents.rows().begin(); - row_it != p.contents.rows().end(); + for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = p.contents.rows.begin(); + row_it != p.contents.rows.end(); ++row_it) { addRow(*row_it); @@ -271,6 +276,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) text_p.border_visible(false); text_p.rect(mItemListRect); text_p.follows.flags(FOLLOWS_ALL); + // word wrap was added accroding to the EXT-6841 + text_p.wrap(true); addChild(LLUICtrlFactory::create<LLTextBox>(text_p)); } @@ -310,12 +317,12 @@ bool LLScrollListCtrl::preProcessChildNode(LLXMLNodePtr child) LLScrollListCtrl::~LLScrollListCtrl() { - std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); + delete mSortCallback; - if( gEditMenuHandler == this ) - { - gEditMenuHandler = NULL; - } + std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); + mItemList.clear(); + std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer()); + mColumns.clear(); } @@ -351,7 +358,7 @@ void LLScrollListCtrl::clearRows() mScrollLines = 0; mLastSelected = NULL; updateLayout(); - mDirty = FALSE; + mDirty = false; } @@ -384,6 +391,22 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllSelected() const return ret; } +S32 LLScrollListCtrl::getNumSelected() const +{ + S32 numSelected = 0; + + for(item_list::const_iterator iter = mItemList.begin(); iter != mItemList.end(); ++iter) + { + LLScrollListItem* item = *iter; + if (item->getSelected()) + { + ++numSelected; + } + } + + return numSelected; +} + S32 LLScrollListCtrl::getFirstSelectedIndex() const { S32 CurSelectedIndex = 0; @@ -472,7 +495,12 @@ void LLScrollListCtrl::updateLayout() getRect().getWidth() - 2 * mBorderThickness, getRect().getHeight() - (2 * mBorderThickness ) - heading_size ); - getChildView("comment_text")->setShape(mItemListRect); + if (mCommentTextView == NULL) + { + mCommentTextView = getChildView("comment_text"); + } + + mCommentTextView->setShape(mItemListRect); // how many lines of content in a single "page" S32 page_lines = getLinesPerPage(); @@ -499,7 +527,7 @@ void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height) { S32 height = llmin( getRequiredRect().getHeight(), max_height ); if(mPageLines) - height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height ); + height = llmin( mPageLines * mLineHeight + 2*mBorderThickness + (mDisplayColumnHeaders ? mHeadingHeight : 0), height ); S32 width = getRect().getWidth(); @@ -531,23 +559,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r setNeedsSort(); break; - case ADD_SORTED: - { - // sort by column 0, in ascending order - std::vector<sort_column_t> single_sort_column; - single_sort_column.push_back(std::make_pair(0, TRUE)); - - mItemList.push_back(item); - std::stable_sort( - mItemList.begin(), - mItemList.end(), - SortScrollListItem(single_sort_column)); - - // ADD_SORTED just sorts by first column... - // this might not match user sort criteria, so flag list as being in unsorted state - setNeedsSort(); - break; - } + case ADD_DEFAULT: case ADD_BOTTOM: mItemList.push_back(item); setNeedsSort(); @@ -570,6 +582,15 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r addColumn(col_params); } + S32 num_cols = item->getNumColumns(); + S32 i = 0; + for (LLScrollListCell* cell = item->getColumn(i); i < num_cols; cell = item->getColumn(++i)) + { + if (i >= (S32)mColumnsIndexed.size()) break; + + cell->setWidth(mColumnsIndexed[i]->getWidth()); + } + updateLineHeightInsert(item); updateLayout(); @@ -581,13 +602,11 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r // NOTE: This is *very* expensive for large lists, especially when we are dirtying the list every frame // while receiving a long list of names. // *TODO: Use bookkeeping to make this an incramental cost with item additions -void LLScrollListCtrl::calcColumnWidths() +S32 LLScrollListCtrl::calcMaxContentWidth() { const S32 HEADING_TEXT_PADDING = 25; const S32 COLUMN_TEXT_PADDING = 10; - mMaxContentWidth = 0; - S32 max_item_width = 0; ordered_columns_t::iterator column_itor; @@ -596,34 +615,57 @@ void LLScrollListCtrl::calcColumnWidths() LLScrollListColumn* column = *column_itor; if (!column) continue; + if (mColumnWidthsDirty) + { + // update max content width for this column, by looking at all items + column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + { + LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); + if (!cellp) continue; + + column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + } + } + max_item_width += column->mMaxContentWidth; + } + mColumnWidthsDirty = false; + + return max_item_width; +} + +bool LLScrollListCtrl::updateColumnWidths() +{ + bool width_changed = false; + ordered_columns_t::iterator column_itor; + for (column_itor = mColumnsIndexed.begin(); column_itor != mColumnsIndexed.end(); ++column_itor) + { + LLScrollListColumn* column = *column_itor; + if (!column) continue; + // update column width - S32 new_width = column->getWidth(); + S32 new_width = 0; if (column->mRelWidth >= 0) { - new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth()); + new_width = (S32)ll_round(column->mRelWidth*mItemListRect.getWidth()); } else if (column->mDynamicWidth) { new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns; } - - column->setWidth(new_width); - - // update max content width for this column, by looking at all items - column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0; - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + else { - LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); - if (!cellp) continue; - - column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + new_width = column->getWidth(); } - max_item_width += column->mMaxContentWidth; + if (column->getWidth() != new_width) + { + column->setWidth(new_width); + width_changed = true; + } } - - mMaxContentWidth = max_item_width; + return width_changed; } const S32 SCROLL_LIST_ROW_PAD = 2; @@ -657,9 +699,14 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp) } -void LLScrollListCtrl::updateColumns() +void LLScrollListCtrl::updateColumns(bool force_update) { - calcColumnWidths(); + if (!mColumnsDirty && !force_update) + return; + + mColumnsDirty = false; + + bool columns_changed_width = updateColumnWidths(); // update column headers std::vector<LLScrollListColumn*>::iterator column_ordered_it; @@ -708,20 +755,22 @@ void LLScrollListCtrl::updateColumns() } // propagate column widths to individual cells - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + if (columns_changed_width || force_update) { - LLScrollListItem *itemp = *iter; - S32 num_cols = itemp->getNumColumns(); - S32 i = 0; - for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) + item_list::iterator iter; + for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { - if (i >= (S32)mColumnsIndexed.size()) break; + LLScrollListItem *itemp = *iter; + S32 num_cols = itemp->getNumColumns(); + S32 i = 0; + for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i)) + { + if (i >= (S32)mColumnsIndexed.size()) break; - cell->setWidth(mColumnsIndexed[i]->getWidth()); + cell->setWidth(mColumnsIndexed[i]->getWidth()); + } } } - } void LLScrollListCtrl::setHeadingHeight(S32 heading_height) @@ -762,7 +811,7 @@ BOOL LLScrollListCtrl::selectFirstItem() { deselectItem(itemp); } - first_item = FALSE; + first_item = false; } if (mCommitOnSelectionChange) { @@ -944,14 +993,14 @@ void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index) } } -S32 LLScrollListCtrl::selectMultiple( std::vector<LLUUID> ids ) +S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) { item_list::iterator iter; S32 count = 0; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) { LLScrollListItem* item = *iter; - std::vector<LLUUID>::iterator iditr; + uuid_vec_t::iterator iditr; for(iditr = ids.begin(); iditr != ids.end(); ++iditr) { if (item->getEnabled() && (item->getUUID() == (*iditr))) @@ -1136,10 +1185,10 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition 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) +BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive, S32 column/* = 0*/) { deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match - LLScrollListItem* item = getItemByLabel(label, case_sensitive); + LLScrollListItem* item = getItemByLabel(label, case_sensitive, column); bool found = NULL != item; if(found) @@ -1389,22 +1438,30 @@ void LLScrollListCtrl::drawItems() LLGLSUIDefault gls_ui; + F32 alpha = getDrawContext().mAlpha; + { LLLocalClipRect clip(mItemListRect); S32 cur_y = y; - S32 line = 0; S32 max_columns = 0; LLColor4 highlight_color = LLColor4::white; static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0); - highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f); + highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout(), 0.4f, 0.f); + S32 first_line = mScrollLines; + S32 last_line = llmin((S32)mItemList.size() - 1, mScrollLines + getLinesPerPage()); + + if (first_line >= mItemList.size()) + { + return; + } item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (S32 line = first_line; line <= last_line; line++) { - LLScrollListItem* item = *iter; + LLScrollListItem* item = mItemList[line]; item_rect.setOriginAndSize( x, @@ -1413,8 +1470,6 @@ void LLScrollListCtrl::drawItems() mLineHeight ); item->setRect(item_rect); - //llinfos << item_rect.getWidth() << llendl; - max_columns = llmax(max_columns, item->getNumColumns()); LLColor4 fg_color; @@ -1464,11 +1519,10 @@ void LLScrollListCtrl::drawItems() bg_color = mBgReadOnlyColor.get(); } - item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding); + item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding); cur_y -= mLineHeight; } - line++; } } } @@ -1484,21 +1538,18 @@ void LLScrollListCtrl::draw() if (mNeedsScroll) { scrollToShowSelected(); - mNeedsScroll = FALSE; + mNeedsScroll = false; } LLRect background(0, getRect().getHeight(), getRect().getWidth(), 0); // Draw background if (mBackgroundVisible) { + F32 alpha = getCurrentTransparency(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() : mBgReadOnlyColor.get() ); + gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() % alpha : mBgReadOnlyColor.get() % alpha ); } - if (mColumnsDirty) - { - updateColumns(); - mColumnsDirty = FALSE; - } + updateColumns(); getChildView("comment_text")->setVisible(mItemList.empty()); @@ -1524,6 +1575,12 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) BOOL handled = FALSE; // Pretend the mouse is over the scrollbar handled = mScrollbar->handleScrollWheel( 0, 0, clicks ); + + if (mMouseWheelOpaque) + { + return TRUE; + } + return handled; } @@ -1535,7 +1592,7 @@ LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index) S32 rect_bottom = getRowOffsetFromIndex(row_index); LLScrollListColumn* columnp = getColumn(column_index); cell_rect.setOriginAndSize(rect_left, rect_bottom, - rect_left + columnp->getWidth(), mLineHeight); + /*rect_left + */columnp->getWidth(), mLineHeight); return cell_rect; } @@ -1565,7 +1622,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask) // display tooltip exactly over original cell, in same font LLToolTipMgr::instance().show(LLToolTip::Params() - .message(hit_cell->getValue().asString()) + .message(hit_cell->getToolTip()) .font(LLFontGL::getFontSansSerifSmall()) .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6)) .delay_time(0.2f) @@ -1700,7 +1757,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); // clear selection changed flag because user is starting a selection operation - mSelectionChanged = FALSE; + mSelectionChanged = false; handleClick(x, y, mask); } @@ -1718,15 +1775,15 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask) if(mask == MASK_NONE) { selectItemAt(x, y, mask); - mNeedsScroll = TRUE; + mNeedsScroll = true; } } // always commit when mouse operation is completed inside list if (mItemListRect.pointInRect(x,y)) { - mDirty |= mSelectionChanged; - mSelectionChanged = FALSE; + mDirty = mDirty || mSelectionChanged; + mSelectionChanged = false; onCommit(); } @@ -1748,6 +1805,9 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) // (N.B. callbacks don't take const refs as id is local scope) bool is_group = (mContextMenuType == MENU_GROUP); LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Url.ShowProfile", boost::bind(&LLScrollListCtrl::showProfile, id, is_group)); + registrar.add("Url.SendIM", boost::bind(&LLScrollListCtrl::sendIM, id)); + registrar.add("Url.AddFriend", boost::bind(&LLScrollListCtrl::addFriend, id)); registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group)); registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group)); registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group)); @@ -1755,6 +1815,7 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) // create the context menu from the XUI file and display it std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml"; delete mPopupMenu; + llassert(LLMenuGL::sMenuContainer != NULL); mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); if (mPopupMenu) @@ -1764,16 +1825,39 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) return TRUE; } } + return LLUICtrl::handleRightMouseDown(x, y, mask); } return FALSE; } -void LLScrollListCtrl::showNameDetails(std::string id, bool is_group) +void LLScrollListCtrl::showProfile(std::string id, bool is_group) { // show the resident's profile or the group profile std::string sltype = is_group ? "group" : "agent"; std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about"; - LLUrlAction::clickAction(slurl); + LLUrlAction::showProfile(slurl); +} + +void LLScrollListCtrl::sendIM(std::string id) +{ + // send im to the resident + std::string slurl = "secondlife:///app/agent/" + id + "/about"; + LLUrlAction::sendIM(slurl); +} + +void LLScrollListCtrl::addFriend(std::string id) +{ + // add resident to friends list + std::string slurl = "secondlife:///app/agent/" + id + "/about"; + LLUrlAction::addFriend(slurl); +} + +void LLScrollListCtrl::showNameDetails(std::string id, bool is_group) +{ + // open the resident's details or the group details + std::string sltype = is_group ? "group" : "agent"; + std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about"; + LLUrlAction::clickAction(slurl, true); } void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group) @@ -1786,7 +1870,9 @@ void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group) } else { - gCacheName->getFullName(LLUUID(id), name); + LLAvatarName av_name; + LLAvatarNameCache::get(LLUUID(id), &av_name); + name = av_name.getAccountName(); } LLUrlAction::copyURLToClipboard(name); } @@ -1840,7 +1926,7 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) { selectItemAt(x, y, mask); gFocusMgr.setMouseCapture(this); - mNeedsScroll = TRUE; + mNeedsScroll = true; } // propagate state of cell to rest of selected column @@ -1869,7 +1955,7 @@ BOOL LLScrollListCtrl::handleClick(S32 x, S32 y, MASK mask) // treat this as a normal single item selection selectItemAt(x, y, mask); gFocusMgr.setMouseCapture(this); - mNeedsScroll = TRUE; + mNeedsScroll = true; // do not eat click (allow double click callback) return FALSE; } @@ -1975,7 +2061,7 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) if(mask == MASK_NONE) { selectItemAt(x, y, mask); - mNeedsScroll = TRUE; + mNeedsScroll = true; } } else @@ -2010,9 +2096,6 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) // not called from parent means we have keyboard focus or a child does if (mCanSelect) { - // Ignore capslock - mask = mask; - if (mask == MASK_NONE) { switch(key) @@ -2022,7 +2105,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectPrevItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2031,7 +2114,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectNextItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2039,7 +2122,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getFirstSelectedIndex() - (mScrollbar->getPageSize() - 1)); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2052,7 +2135,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getFirstSelectedIndex() + (mScrollbar->getPageSize() - 1)); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2065,7 +2148,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectFirstItem(); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2078,7 +2161,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getItemCount() - 1); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2117,7 +2200,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) } else if (selectItemByPrefix(wstring_to_utf8str(mSearchString), FALSE)) { - mNeedsScroll = TRUE; + mNeedsScroll = true; // update search string only on successful match mSearchTimer.reset(); @@ -2158,7 +2241,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) if (selectItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE)) { // update search string only on successful match - mNeedsScroll = TRUE; + mNeedsScroll = true; mSearchString += uni_char; mSearchTimer.reset(); @@ -2204,7 +2287,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char) if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char) { selectItem(item); - mNeedsScroll = TRUE; + mNeedsScroll = true; cellp->highlightText(0, 1); mSearchTimer.reset(); @@ -2275,7 +2358,7 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it } itemp->setSelected(TRUE); mLastSelected = itemp; - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2296,7 +2379,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp) { cellp->highlightText(0, 0); } - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2304,7 +2387,7 @@ void LLScrollListCtrl::commitIfChanged() { if (mSelectionChanged) { - mDirty = TRUE; + mDirty = true; mSelectionChanged = FALSE; onCommit(); } @@ -2372,10 +2455,10 @@ void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar ) void LLScrollListCtrl::sortByColumn(const std::string& name, BOOL ascending) { - std::map<std::string, LLScrollListColumn>::iterator itor = mColumns.find(name); + column_map_t::iterator itor = mColumns.find(name); if (itor != mColumns.end()) { - sortByColumnIndex((*itor).second.mIndex, ascending); + sortByColumnIndex((*itor).second->mIndex, ascending); } } @@ -2394,7 +2477,7 @@ void LLScrollListCtrl::updateSort() const std::stable_sort( mItemList.begin(), mItemList.end(), - SortScrollListItem(mSortColumns)); + SortScrollListItem(mSortColumns,mSortCallback)); mSorted = true; } @@ -2410,22 +2493,23 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending) std::stable_sort( mItemList.begin(), mItemList.end(), - SortScrollListItem(sort_column)); + SortScrollListItem(sort_column,mSortCallback)); } void LLScrollListCtrl::dirtyColumns() { - mColumnsDirty = TRUE; + mColumnsDirty = true; + mColumnWidthsDirty = true; // need to keep mColumnsIndexed up to date // just in case someone indexes into it immediately mColumnsIndexed.resize(mColumns.size()); - std::map<std::string, LLScrollListColumn>::iterator column_itor; + column_map_t::iterator column_itor; for (column_itor = mColumns.begin(); column_itor != mColumns.end(); ++column_itor) { - LLScrollListColumn *column = &column_itor->second; - mColumnsIndexed[column_itor->second.mIndex] = column; + LLScrollListColumn *column = column_itor->second; + mColumnsIndexed[column_itor->second->mIndex] = column; } } @@ -2501,7 +2585,7 @@ void LLScrollListCtrl::copy() { buffer += (*itor)->getContentsCSV() + "\n"; } - gClipboard.copyFromSubstring(utf8str_to_wstring(buffer), 0, buffer.length()); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(buffer), 0, buffer.length()); } // virtual @@ -2564,7 +2648,8 @@ BOOL LLScrollListCtrl::canDeselect() const void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) { LLScrollListColumn::Params p; - LLParamSDParser::instance().readSD(column, p); + LLParamSDParser parser; + parser.readSD(column, p); addColumn(p, pos); } @@ -2582,8 +2667,8 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params if (mColumns.find(name) == mColumns.end()) { // Add column - mColumns[name] = LLScrollListColumn(column_params, this); - LLScrollListColumn* new_column = &mColumns[name]; + mColumns[name] = new LLScrollListColumn(column_params, this); + LLScrollListColumn* new_column = mColumns[name]; new_column->mIndex = mColumns.size()-1; // Add button @@ -2595,7 +2680,7 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params } if (new_column->mRelWidth >= 0) { - new_column->setWidth((S32)llround(new_column->mRelWidth*mItemListRect.getWidth())); + new_column->setWidth((S32)ll_round(new_column->mRelWidth*mItemListRect.getWidth())); } else if(new_column->mDynamicWidth) { @@ -2605,14 +2690,14 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params S32 top = mItemListRect.mTop; S32 left = mItemListRect.mLeft; - for (std::map<std::string, LLScrollListColumn>::iterator itor = mColumns.begin(); + for (column_map_t::iterator 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; } } @@ -2624,7 +2709,7 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top); - LLScrollColumnHeader::Params params; + LLScrollColumnHeader::Params params(LLUICtrlFactory::getDefaultParams<LLScrollColumnHeader>()); params.name = "btn_" + name; params.rect = temp_rect; params.column = new_column; @@ -2668,8 +2753,8 @@ void LLScrollListCtrl::onClickColumn(void *userdata) if (column->mSortingColumn != column->mName && parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end()) { - LLScrollListColumn& info_redir = parent->mColumns[column->mSortingColumn]; - column_index = info_redir.mIndex; + LLScrollListColumn* info_redir = parent->mColumns[column->mSortingColumn]; + column_index = info_redir->mIndex; } // if this column is the primary sort key, reverse the direction @@ -2700,18 +2785,24 @@ BOOL LLScrollListCtrl::hasSortOrder() const return !mSortColumns.empty(); } +void LLScrollListCtrl::clearSortOrder() +{ + mSortColumns.clear(); +} + void LLScrollListCtrl::clearColumns() { - std::map<std::string, LLScrollListColumn>::iterator itor; + column_map_t::iterator itor; for (itor = mColumns.begin(); itor != mColumns.end(); ++itor) { - LLScrollColumnHeader *header = itor->second.mHeader; + LLScrollColumnHeader *header = itor->second->mHeader; if (header) { removeChild(header); delete header; } } + std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer()); mColumns.clear(); mSortColumns.clear(); mTotalStaticColumnWidth = 0; @@ -2745,32 +2836,40 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name) column_map_t::iterator column_itor = mColumns.find(name); if (column_itor != mColumns.end()) { - return &column_itor->second; + return column_itor->second; } return NULL; } - +LLTrace::BlockTimerStatHandle FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item"); LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) { + LL_RECORD_BLOCK_TIME(FTM_ADD_SCROLLLIST_ELEMENT); LLScrollListItem::Params item_params; - LLParamSDParser::instance().readSD(element, item_params); + LLParamSDParser parser; + parser.readSD(element, item_params); item_params.userdata = userdata; return addRow(item_params, pos); } LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos) { - if (!item_p.validateBlock()) return NULL; - + LL_RECORD_BLOCK_TIME(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) +{ + LL_RECORD_BLOCK_TIME(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; - for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns().begin(); - itor != item_p.columns().end(); + for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns.begin(); + itor != item_p.columns.end(); ++itor) { LLScrollListCell::Params cell_p = *itor; @@ -2798,12 +2897,15 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ new_column.width.pixel_width = cell_p.width; } addColumn(new_column); - columnp = &mColumns[column]; + columnp = mColumns[column]; new_item->setNumColumns(mColumns.size()); } S32 index = columnp->mIndex; - cell_p.width.setIfNotProvided(columnp->getWidth()); + if (!cell_p.width.isProvided()) + { + cell_p.width = columnp->getWidth(); + } LLScrollListCell* cell = LLScrollListCell::create(cell_p); @@ -2821,7 +2923,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ col_index++; } - if (item_p.columns().empty()) + if (item_p.columns.empty()) { if (mColumns.empty()) { @@ -2835,7 +2937,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ LLScrollListCell* cell = LLScrollListCell::create(LLScrollListCell::Params().value(item_p.value)); if (cell) { - LLScrollListColumn* columnp = &(mColumns.begin()->second); + LLScrollListColumn* columnp = mColumns.begin()->second; new_item->setColumn(0, cell); if (columnp->mHeader @@ -2850,10 +2952,10 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ // add dummy cells for missing columns for (column_map_t::iterator column_it = mColumns.begin(); column_it != mColumns.end(); ++column_it) { - S32 column_idx = column_it->second.mIndex; + S32 column_idx = column_it->second->mIndex; if (new_item->getColumn(column_idx) == NULL) { - LLScrollListColumn* column_ptr = &column_it->second; + LLScrollListColumn* column_ptr = column_it->second; LLScrollListCell::Params cell_p; cell_p.width = column_ptr->getWidth(); @@ -2933,7 +3035,6 @@ BOOL LLScrollListCtrl::operateOnAll(EOperation op) //virtual void LLScrollListCtrl::setFocus(BOOL b) { - mSearchString.clear(); // for tabbing into pristine scroll lists (Finder) if (!getFirstSelected()) { @@ -2967,7 +3068,7 @@ void LLScrollListCtrl::resetDirty() void LLScrollListCtrl::onFocusReceived() { // forget latent selection changes when getting focus - mSelectionChanged = FALSE; + mSelectionChanged = false; LLUICtrl::onFocusReceived(); } @@ -2978,6 +3079,9 @@ void LLScrollListCtrl::onFocusLost() { gFocusMgr.setMouseCapture(NULL); } + + mSearchString.clear(); + LLUICtrl::onFocusLost(); } |