diff options
-rwxr-xr-x | .hgtags | 3 | ||||
-rw-r--r-- | indra/llmessage/llavatarnamecache.cpp | 58 | ||||
-rw-r--r-- | indra/llmessage/llavatarnamecache.h | 4 | ||||
-rw-r--r-- | indra/llui/llcombobox.cpp | 3 | ||||
-rw-r--r-- | indra/llui/llscrolllistcolumn.cpp | 3 | ||||
-rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 166 | ||||
-rw-r--r-- | indra/llui/llscrolllistctrl.h | 28 | ||||
-rw-r--r-- | indra/llui/llview.cpp | 12 | ||||
-rw-r--r-- | indra/newview/llnamelistctrl.cpp | 27 | ||||
-rw-r--r-- | indra/newview/llnamelistctrl.h | 18 | ||||
-rw-r--r-- | indra/newview/llpanelgroup.h | 2 | ||||
-rw-r--r-- | indra/newview/llpanelgroupgeneral.cpp | 101 | ||||
-rw-r--r-- | indra/newview/llpanelgroupgeneral.h | 6 | ||||
-rw-r--r-- | indra/newview/llpanelgroupinvite.cpp | 11 | ||||
-rw-r--r-- | indra/newview/llpanelgroupinvite.h | 4 | ||||
-rw-r--r-- | indra/newview/llpanelgrouplandmoney.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanelgrouproles.cpp | 54 | ||||
-rw-r--r-- | indra/newview/llpanelgrouproles.h | 2 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml | 2 |
19 files changed, 269 insertions, 237 deletions
@@ -359,3 +359,6 @@ f7bedce18ad52283e6072814db23318907261487 DRTVWR-238 e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243 73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4 5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241 +f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232 +4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245 +94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1 diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 32d9d8bfc3..700525e1fa 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -334,8 +334,9 @@ void LLAvatarNameCache::requestNamesViaCapability() // http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0 // // Apache can handle URLs of 4096 chars, but let's be conservative - const U32 NAME_URL_MAX = 4096; - const U32 NAME_URL_SEND_THRESHOLD = 3000; + static const U32 NAME_URL_MAX = 4096; + static const U32 NAME_URL_SEND_THRESHOLD = 3500; + std::string url; url.reserve(NAME_URL_MAX); @@ -343,10 +344,12 @@ void LLAvatarNameCache::requestNamesViaCapability() agent_ids.reserve(128); U32 ids = 0; - ask_queue_t::const_iterator it = sAskQueue.begin(); - for ( ; it != sAskQueue.end(); ++it) + ask_queue_t::const_iterator it; + while(!sAskQueue.empty()) { + it = sAskQueue.begin(); const LLUUID& agent_id = *it; + sAskQueue.erase(it); if (url.empty()) { @@ -369,27 +372,17 @@ void LLAvatarNameCache::requestNamesViaCapability() if (url.size() > NAME_URL_SEND_THRESHOLD) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability first " - << ids << " ids" - << LL_ENDL; - LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); - url.clear(); - agent_ids.clear(); + break; } } if (!url.empty()) { - LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability all " + LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " << ids << " ids" << LL_ENDL; LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); - url.clear(); - agent_ids.clear(); } - - // We've moved all asks to the pending request queue - sAskQueue.clear(); } void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, @@ -416,12 +409,15 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, void LLAvatarNameCache::requestNamesViaLegacy() { + static const S32 MAX_REQUESTS = 100; F64 now = LLFrameTimer::getTotalSeconds(); std::string full_name; - ask_queue_t::const_iterator it = sAskQueue.begin(); - for (; it != sAskQueue.end(); ++it) + ask_queue_t::const_iterator it; + for (S32 requests = 0; !sAskQueue.empty() && requests < MAX_REQUESTS; ++requests) { + it = sAskQueue.begin(); const LLUUID& agent_id = *it; + sAskQueue.erase(it); // Mark as pending first, just in case the callback is immediately // invoked below. This should never happen in practice. @@ -433,10 +429,6 @@ void LLAvatarNameCache::requestNamesViaLegacy() boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3)); } - - // We've either answered immediately or moved all asks to the - // pending queue - sAskQueue.clear(); } void LLAvatarNameCache::initClass(bool running) @@ -513,11 +505,11 @@ void LLAvatarNameCache::idle() // *TODO: Possibly re-enabled this based on People API load measurements // 100 ms is the threshold for "user speed" operations, so we can // stall for about that long to batch up requests. - //const F32 SECS_BETWEEN_REQUESTS = 0.1f; - //if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) - //{ - // return; - //} + const F32 SECS_BETWEEN_REQUESTS = 0.1f; + if (!sRequestTimer.hasExpired()) + { + return; + } if (!sAskQueue.empty()) { @@ -532,6 +524,12 @@ void LLAvatarNameCache::idle() } } + if (sAskQueue.empty()) + { + // cleared the list, reset the request timer. + sRequestTimer.resetWithExpiry(SECS_BETWEEN_REQUESTS); + } + // erase anything that has not been refreshed for more than MAX_UNREFRESHED_TIME eraseUnrefreshed(); } @@ -743,12 +741,6 @@ void LLAvatarNameCache::erase(const LLUUID& agent_id) sCache.erase(agent_id); } -void LLAvatarNameCache::fetch(const LLUUID& agent_id) -{ - // re-request, even if request is already pending - sAskQueue.insert(agent_id); -} - void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name) { // *TODO: update timestamp if zero? diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 064942fe53..79f170f7c8 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -86,10 +86,6 @@ namespace LLAvatarNameCache /// Provide some fallback for agents that return errors void handleAgentError(const LLUUID& agent_id); - // Force a re-fetch of the most recent data, but keep the current - // data in cache - void fetch(const LLUUID& agent_id); - void insert(const LLUUID& agent_id, const LLAvatarName& av_name); // Compute name expiration time from HTTP Cache-Control header, diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 806d2ef3f6..41e5d74042 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -563,8 +563,7 @@ void LLComboBox::showList() S32 min_width = getRect().getWidth(); S32 max_width = llmax(min_width, MAX_COMBO_WIDTH); // make sure we have up to date content width metrics - mList->calcColumnWidths(); - S32 list_width = llclamp(mList->getMaxContentWidth(), min_width, max_width); + S32 list_width = llclamp(mList->calcMaxContentWidth(), min_width, max_width); if (mListPosition == BELOW) { diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 07a6dfaa10..af124d9826 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -98,6 +98,7 @@ BOOL LLScrollColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask) if (canResize() && mResizeBar->getRect().pointInRect(x, y)) { // reshape column to max content width + mColumn->mParentCtrl->calcMaxContentWidth(); LLRect column_rect = getRect(); column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth; setShape(column_rect, true); @@ -127,6 +128,8 @@ LLView* LLScrollColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& m LLRect snap_rect = getSnapRect(); + mColumn->mParentCtrl->calcMaxContentWidth(); + S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth(); // x coord growing means column growing, so same signs mean we're going in right direction diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index b3499693dd..3e0653e9a4 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -35,6 +35,7 @@ #include "llboost.h" //#include "indra_constants.h" +#include "llavatarnamecache.h" #include "llcheckboxctrl.h" #include "llclipboard.h" #include "llfocusmgr.h" @@ -158,15 +159,14 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) 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 ), @@ -180,7 +180,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mTotalStaticColumnWidth(0), mTotalColumnPadding(0), mSorted(false), - mDirty(FALSE), + mDirty(false), mOriginalSelection(-1), mLastSelected(NULL), mHeadingHeight(p.heading_height), @@ -356,7 +356,7 @@ void LLScrollListCtrl::clearRows() mScrollLines = 0; mLastSelected = NULL; updateLayout(); - mDirty = FALSE; + mDirty = false; } @@ -591,13 +591,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; @@ -606,6 +604,35 @@ void LLScrollListCtrl::calcColumnWidths() LLScrollListColumn* column = *column_itor; if (!column) continue; + if (mColumnWidthsDirty) + { + mColumnWidthsDirty = false; + // 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; + } + + 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(); if (column->mRelWidth >= 0) @@ -617,23 +644,13 @@ void LLScrollListCtrl::calcColumnWidths() 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++) + if (column->getWidth() != new_width) { - LLScrollListCell* cellp = (*iter)->getColumn(column->mIndex); - if (!cellp) continue; - - column->mMaxContentWidth = llmax(LLFontGL::getFontSansSerifSmall()->getWidth(cellp->getValue().asString()) + mColumnPadding + COLUMN_TEXT_PADDING, column->mMaxContentWidth); + column->setWidth(new_width); + width_changed = true; } - - max_item_width += column->mMaxContentWidth; } - - mMaxContentWidth = max_item_width; + return width_changed; } const S32 SCROLL_LIST_ROW_PAD = 2; @@ -669,7 +686,12 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp) void LLScrollListCtrl::updateColumns() { - calcColumnWidths(); + if (!mColumnsDirty) + return; + + mColumnsDirty = false; + + bool columns_changed_width = updateColumnWidths(); // update column headers std::vector<LLScrollListColumn*>::iterator column_ordered_it; @@ -718,20 +740,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) { - 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) @@ -772,7 +796,7 @@ BOOL LLScrollListCtrl::selectFirstItem() { deselectItem(itemp); } - first_item = FALSE; + first_item = false; } if (mCommitOnSelectionChange) { @@ -1406,17 +1430,23 @@ void LLScrollListCtrl::drawItems() 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); + 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, @@ -1480,7 +1510,6 @@ void LLScrollListCtrl::drawItems() cur_y -= mLineHeight; } - line++; } } } @@ -1496,7 +1525,7 @@ void LLScrollListCtrl::draw() if (mNeedsScroll) { scrollToShowSelected(); - mNeedsScroll = FALSE; + mNeedsScroll = false; } LLRect background(0, getRect().getHeight(), getRect().getWidth(), 0); // Draw background @@ -1507,11 +1536,7 @@ void LLScrollListCtrl::draw() gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() % alpha : mBgReadOnlyColor.get() % alpha ); } - if (mColumnsDirty) - { - updateColumns(); - mColumnsDirty = FALSE; - } + updateColumns(); getChildView("comment_text")->setVisible(mItemList.empty()); @@ -1719,7 +1744,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); } @@ -1737,15 +1762,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(); } @@ -1805,7 +1830,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.getLegacyName(); } LLUrlAction::copyURLToClipboard(name); } @@ -1859,7 +1886,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 @@ -1888,7 +1915,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; } @@ -1994,7 +2021,7 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask) if(mask == MASK_NONE) { selectItemAt(x, y, mask); - mNeedsScroll = TRUE; + mNeedsScroll = true; } } else @@ -2041,7 +2068,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectPrevItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2050,7 +2077,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) { // commit implicit in call selectNextItem(FALSE); - mNeedsScroll = TRUE; + mNeedsScroll = true; handled = TRUE; } break; @@ -2058,7 +2085,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getFirstSelectedIndex() - (mScrollbar->getPageSize() - 1)); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2071,7 +2098,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getFirstSelectedIndex() + (mScrollbar->getPageSize() - 1)); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2084,7 +2111,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectFirstItem(); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2097,7 +2124,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask ) if (mAllowKeyboardMovement || hasFocus()) { selectNthItem(getItemCount() - 1); - mNeedsScroll = TRUE; + mNeedsScroll = true; if (mCommitOnKeyboardMovement && !mCommitOnSelectionChange) { @@ -2136,7 +2163,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(); @@ -2177,7 +2204,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(); @@ -2223,7 +2250,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(); @@ -2294,7 +2321,7 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it } itemp->setSelected(TRUE); mLastSelected = itemp; - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2315,7 +2342,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp) { cellp->highlightText(0, 0); } - mSelectionChanged = TRUE; + mSelectionChanged = true; } } @@ -2323,7 +2350,7 @@ void LLScrollListCtrl::commitIfChanged() { if (mSelectionChanged) { - mDirty = TRUE; + mDirty = true; mSelectionChanged = FALSE; onCommit(); } @@ -2434,7 +2461,8 @@ void LLScrollListCtrl::sortOnce(S32 column, BOOL ascending) void LLScrollListCtrl::dirtyColumns() { - mColumnsDirty = TRUE; + mColumnsDirty = true; + mColumnWidthsDirty = true; // need to keep mColumnsIndexed up to date // just in case someone indexes into it immediately @@ -3003,7 +3031,7 @@ void LLScrollListCtrl::resetDirty() void LLScrollListCtrl::onFocusReceived() { // forget latent selection changes when getting focus - mSelectionChanged = FALSE; + mSelectionChanged = false; LLUICtrl::onFocusReceived(); } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index e83794e173..38450b6313 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -343,8 +343,8 @@ public: static void onClickColumn(void *userdata); virtual void updateColumns(); - void calcColumnWidths(); - S32 getMaxContentWidth() { return mMaxContentWidth; } + S32 calcMaxContentWidth(); + bool updateColumnWidths(); void setHeadingHeight(S32 heading_height); /** @@ -440,16 +440,17 @@ private: S32 mHeadingHeight; // the height of the column header buttons, if visible U32 mMaxSelectable; LLScrollbar* mScrollbar; - BOOL mAllowMultipleSelection; - BOOL mAllowKeyboardMovement; - BOOL mCommitOnKeyboardMovement; - BOOL mCommitOnSelectionChange; - BOOL mSelectionChanged; - BOOL mNeedsScroll; - BOOL mMouseWheelOpaque; - BOOL mCanSelect; - const BOOL mDisplayColumnHeaders; - BOOL mColumnsDirty; + bool mAllowMultipleSelection; + bool mAllowKeyboardMovement; + bool mCommitOnKeyboardMovement; + bool mCommitOnSelectionChange; + bool mSelectionChanged; + bool mNeedsScroll; + bool mMouseWheelOpaque; + bool mCanSelect; + bool mDisplayColumnHeaders; + bool mColumnsDirty; + bool mColumnWidthsDirty; mutable item_list mItemList; @@ -458,7 +459,6 @@ private: S32 mMaxItemCount; LLRect mItemListRect; - S32 mMaxContentWidth; S32 mColumnPadding; BOOL mBackgroundVisible; @@ -498,7 +498,7 @@ private: typedef std::map<std::string, LLScrollListColumn*> column_map_t; column_map_t mColumns; - BOOL mDirty; + bool mDirty; S32 mOriginalSelection; ContextMenuType mContextMenuType; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 54843227b7..ad9bec9f61 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1549,16 +1549,18 @@ void LLView::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* l void LLView::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const { - *screen_x = local_x + getRect().mLeft; - *screen_y = local_y + getRect().mBottom; + *screen_x = local_x; + *screen_y = local_y; const LLView* cur = this; - while( cur->mParentView ) + do { + LLRect cur_rect = cur->getRect(); + *screen_x += cur_rect.mLeft; + *screen_y += cur_rect.mBottom; cur = cur->mParentView; - *screen_x += cur->getRect().mLeft; - *screen_y += cur->getRect().mBottom; } + while( cur ); } void LLView::screenRectToLocal(const LLRect& screen, LLRect* local) const diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 472c26e22d..b0fbad33b0 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -68,7 +68,7 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) {} // public -void LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, +LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, BOOL enabled, const std::string& suffix) { //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; @@ -78,7 +78,7 @@ void LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, item.enabled = enabled; item.target = INDIVIDUAL; - addNameItemRow(item, pos, suffix); + return addNameItemRow(item, pos, suffix); } // virtual, public @@ -204,7 +204,7 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; S32 column_index = getColumnIndexFromOffset(x); - LLScrollListItem* hit_item = hitItem(x, y); + LLNameListItem* hit_item = dynamic_cast<LLNameListItem*>(hitItem(x, y)); if (hit_item && column_index == mNameColumnIndex) { @@ -228,7 +228,7 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask) LLCoordGL pos( sticky_rect.mRight - info_icon_size, sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight())/2 ); // Should we show a group or an avatar inspector? - bool is_group = hit_item->getValue()["is_group"].asBoolean(); + bool is_group = hit_item->isGroup(); LLToolTip::Params params; params.background_visible( false ); @@ -271,10 +271,10 @@ void LLNameListCtrl::addGroupNameItem(LLNameListCtrl::NameItem& item, EAddPositi addNameItemRow(item, pos); } -void LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos) +LLScrollListItem* LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos) { item.target = INDIVIDUAL; - addNameItemRow(item, pos); + return addNameItemRow(item, pos); } LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata) @@ -293,19 +293,12 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( const std::string& suffix) { LLUUID id = name_item.value().asUUID(); - LLNameListItem* item = NULL; - - // Store item type so that we can invoke the proper inspector. - // *TODO Vadim: Is there a more proper way of storing additional item data? - { - LLNameListCtrl::NameItem item_p(name_item); - item_p.value = LLSD().with("uuid", id).with("is_group", name_item.target() == GROUP); - item = new LLNameListItem(item_p); - LLScrollListCtrl::addRow(item, item_p, pos); - } + LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP); if (!item) return NULL; + LLScrollListCtrl::addRow(item, name_item, pos); + // use supplied name by default std::string fullname = name_item.name; switch(name_item.target) @@ -411,7 +404,7 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id, setNeedsSort(); } } - + dirtyColumns(); } diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index ba85e77c65..3ac0565761 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -42,14 +42,24 @@ class LLAvatarName; class LLNameListItem : public LLScrollListItem, public LLHandleProvider<LLNameListItem> { public: - LLUUID getUUID() const { return getValue()["uuid"].asUUID(); } + bool isGroup() const { return mIsGroup; } + void setIsGroup(bool is_group) { mIsGroup = is_group; } + protected: friend class LLNameListCtrl; LLNameListItem( const LLScrollListItem::Params& p ) - : LLScrollListItem(p) + : LLScrollListItem(p), mIsGroup(false) + { + } + + LLNameListItem( const LLScrollListItem::Params& p, bool is_group ) + : LLScrollListItem(p), mIsGroup(is_group) { } + +private: + bool mIsGroup; }; @@ -105,9 +115,9 @@ protected: public: // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. - void addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, + LLScrollListItem* addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null); - void addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); + LLScrollListItem* addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM); /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, const std::string& suffix = LLStringUtil::null); diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index b494c7d403..0e6f5b8924 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -33,7 +33,7 @@ class LLOfferInfo; -const S32 UPDATE_MEMBERS_PER_FRAME = 500; +const F32 UPDATE_MEMBERS_SECONDS_PER_FRAME = 0.005; // 5ms // Forward declares class LLPanelGroupTab; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index f6ce7de47e..51b4d2ea65 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -28,8 +28,10 @@ #include "llpanelgroupgeneral.h" -#include "lluictrlfactory.h" +#include "llavatarnamecache.h" #include "llagent.h" +#include "llsdparam.h" +#include "lluictrlfactory.h" #include "roles_constants.h" // UI elements @@ -668,6 +670,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) { mMemberProgress = gdatap->mMembers.begin(); mPendingMemberUpdate = TRUE; + mUdpateSessionID.generate(); sSDTime = 0.0f; sElementTime = 0.0f; @@ -696,76 +699,45 @@ void LLPanelGroupGeneral::updateMembers() LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); - if (!mListVisibleMembers || !gdatap + if (!mListVisibleMembers + || !gdatap || !gdatap->isMemberDataComplete() || gdatap->mMembers.empty()) { return; } - static LLTimer all_timer; - static LLTimer sd_timer; - static LLTimer element_timer; + LLTimer update_time; + update_time.setTimerExpirySec(UPDATE_MEMBERS_SECONDS_PER_FRAME); - all_timer.reset(); - S32 i = 0; + LLAvatarName av_name; - for( ; mMemberProgress != gdatap->mMembers.end() && i<UPDATE_MEMBERS_PER_FRAME; - ++mMemberProgress, ++i) + for( ; mMemberProgress != gdatap->mMembers.end() && !update_time.hasExpired(); + ++mMemberProgress) { - lldebugs << "Adding " << mMemberProgress->first << ", " << mMemberProgress->second->getTitle() << llendl; LLGroupMemberData* member = mMemberProgress->second; if (!member) { continue; } - // Owners show up in bold. - std::string style = "NORMAL"; - sd_timer.reset(); - LLSD row; - row["id"] = member->getID(); - - row["columns"][0]["column"] = "name"; - row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][0]["font"]["style"] = style; - // value is filled in by name list control - - row["columns"][1]["column"] = "title"; - row["columns"][1]["value"] = member->getTitle(); - row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][1]["font"]["style"] = style; - - std::string status = member->getOnlineStatus(); - - row["columns"][2]["column"] = "status"; - row["columns"][2]["value"] = status; - row["columns"][2]["font"]["name"] = "SANSSERIF_SMALL"; - row["columns"][2]["font"]["style"] = style; - sSDTime += sd_timer.getElapsedTimeF32(); - - element_timer.reset(); - LLScrollListItem* member_row = mListVisibleMembers->addElement(row); - - if ( member->isOwner() ) + if (LLAvatarNameCache::get(mMemberProgress->first, &av_name)) + { + addMember(mMemberProgress->second); + } + else { - LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(member_row->getColumn(0)); - if (name_textp) - name_textp->setFontStyle(LLFontGL::BOLD); + // If name is not cached, onNameCache() should be called when it is cached and add this member to list. + LLAvatarNameCache::get(mMemberProgress->first, + boost::bind(&LLPanelGroupGeneral::onNameCache, + this, mUdpateSessionID, member, _1, _2)); } - sElementTime += element_timer.getElapsedTimeF32(); } - sAllTime += all_timer.getElapsedTimeF32(); - lldebugs << "Updated " << i << " of " << UPDATE_MEMBERS_PER_FRAME << "members in the list." << llendl; if (mMemberProgress == gdatap->mMembers.end()) { lldebugs << " member list completed." << llendl; mListVisibleMembers->setEnabled(TRUE); - - lldebugs << "All Time: " << sAllTime << llendl; - lldebugs << "SD Time: " << sSDTime << llendl; - lldebugs << "Element Time: " << sElementTime << llendl; } else { @@ -774,6 +746,39 @@ void LLPanelGroupGeneral::updateMembers() } } +void LLPanelGroupGeneral::addMember(LLGroupMemberData* member) +{ + LLNameListCtrl::NameItem item_params; + item_params.value = member->getID(); + + LLScrollListCell::Params column; + item_params.columns.add().column("name").font.name("SANSSERIF_SMALL"); + + item_params.columns.add().column("title").value(member->getTitle()).font.name("SANSSERIF_SMALL"); + + item_params.columns.add().column("status").value(member->getOnlineStatus()).font.name("SANSSERIF_SMALL"); + + LLScrollListItem* member_row = mListVisibleMembers->addNameItemRow(item_params); + + if ( member->isOwner() ) + { + LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(member_row->getColumn(0)); + if (name_textp) + name_textp->setFontStyle(LLFontGL::BOLD); + } +} + +void LLPanelGroupGeneral::onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLUUID& id, const LLAvatarName& av_name) +{ + if (!member + || update_id != mUdpateSessionID) + { + return; + } + + addMember(member); +} + void LLPanelGroupGeneral::updateChanged() { // List all the controls we want to check for changes... diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index 88c092c461..b179f78c56 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -38,6 +38,7 @@ class LLNameListCtrl; class LLCheckBoxCtrl; class LLComboBox; class LLSpinCtrl; +class LLAvatarName; class LLPanelGroupGeneral : public LLPanelGroupTab { @@ -62,6 +63,7 @@ public: virtual void setupCtrls (LLPanel* parent); + void onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLUUID& id, const LLAvatarName& av_name); private: void reset(); @@ -75,7 +77,8 @@ private: static void onReceiveNotices(LLUICtrl* ctrl, void* data); static void openProfile(void* data); - S32 sortMembersList(S32,const LLScrollListItem*,const LLScrollListItem*); + S32 sortMembersList(S32,const LLScrollListItem*,const LLScrollListItem*); + void addMember(LLGroupMemberData* member); static bool joinDlgCB(const LLSD& notification, const LLSD& response); @@ -87,6 +90,7 @@ private: BOOL mChanged; BOOL mFirstUse; std::string mIncompleteMemberDataStr; + LLUUID mUdpateSessionID; // Group information (include any updates in updateChanged) LLLineEditor *mGroupNameEditor; diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index 1ed8d8cf03..b9b347d4be 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -467,10 +467,11 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) //so we need to do this additional search in avatar tracker, see EXT-4732 if (LLAvatarTracker::instance().isBuddy(agent_id)) { - if (!gCacheName->getFullName(agent_id, fullname)) + LLAvatarName av_name; + if (!LLAvatarNameCache::get(agent_id, &av_name)) { // actually it should happen, just in case - gCacheName->get(LLUUID(agent_id), false, boost::bind( + LLAvatarNameCache::get(LLUUID(agent_id), boost::bind( &LLPanelGroupInvite::addUserCallback, this, _1, _2)); // for this special case! //when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence @@ -479,7 +480,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) } else { - names.push_back(fullname); + names.push_back(av_name.getLegacyName()); } } } @@ -487,12 +488,12 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) mImplementation->addUsers(names, agent_ids); } -void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const std::string& full_name) +void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& av_name) { std::vector<std::string> names; uuid_vec_t agent_ids; agent_ids.push_back(id); - names.push_back(full_name); + names.push_back(av_name.getLegacyName()); mImplementation->addUsers(names, agent_ids); } diff --git a/indra/newview/llpanelgroupinvite.h b/indra/newview/llpanelgroupinvite.h index a7bfd2226e..9f7b5ae9be 100644 --- a/indra/newview/llpanelgroupinvite.h +++ b/indra/newview/llpanelgroupinvite.h @@ -29,6 +29,8 @@ #include "llpanel.h" #include "lluuid.h" +class LLAvatarName; + class LLPanelGroupInvite : public LLPanel { @@ -40,7 +42,7 @@ public: /** * this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers(). */ - void addUserCallback(const LLUUID& id, const std::string& full_name); + void addUserCallback(const LLUUID& id, const LLAvatarName& av_name); void clear(); void update(); diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 363443646d..37755fb851 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -517,7 +517,7 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) row["columns"][3]["column"] = "type"; row["columns"][3]["value"] = land_type; - row["columns"][3]["font"] = "SANSSERIFSMALL"; + row["columns"][3]["font"] = "SANSSERIF_SMALL"; // hidden is always last column row["columns"][4]["column"] = "hidden"; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index bbe47ae943..5720168f81 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -29,6 +29,7 @@ #include "llcheckboxctrl.h" #include "llagent.h" +#include "llavatarnamecache.h" #include "llbutton.h" #include "llfiltereditor.h" #include "llfloatergroupinvite.h" @@ -1584,25 +1585,22 @@ void LLPanelGroupMembersSubTab::addMemberToList(LLUUID id, LLGroupMemberData* da LLUIString donated = getString("donation_area"); donated.setArg("[AREA]", llformat("%d", data->getContribution())); - LLSD row; - row["id"] = id; + LLNameListCtrl::NameItem item_params; + item_params.value = id; - row["columns"][0]["column"] = "name"; - // value is filled in by name list control + item_params.columns.add().column("name").font.name("SANSSERIF_SMALL").style("NORMAL"); - row["columns"][1]["column"] = "donated"; - row["columns"][1]["value"] = donated.getString(); + item_params.columns.add().column("donated").value(donated.getString()) + .font.name("SANSSERIF_SMALL").style("NORMAL"); - row["columns"][2]["column"] = "online"; - row["columns"][2]["value"] = data->getOnlineStatus(); - row["columns"][2]["font"] = "SANSSERIF_SMALL"; - - mMembersList->addElement(row); + item_params.columns.add().column("online").value(data->getOnlineStatus()) + .font.name("SANSSERIF_SMALL").style("NORMAL"); + mMembersList->addNameItemRow(item_params); mHasMatch = TRUE; } -void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, const LLUUID& id) +void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLUUID& id, const LLAvatarName& av_name) { // Update ID is used to determine whether member whose id is passed // into onNameCache() was passed after current or previous user-initiated update. @@ -1612,21 +1610,15 @@ void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, const LLUUI // we do nothing. if (mUdpateSessionID != update_id) return; - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); - if (!gdatap) + if (!member) { - llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl; return; } - std::string fullname; - gCacheName->getFullName(id, fullname); - - LLGroupMemberData* data; // trying to avoid unnecessary hash lookups - if (matchesSearchFilter(fullname) && ((data = gdatap->mMembers[id]) != NULL)) + if (matchesSearchFilter(av_name.getLegacyName())) { - addMemberToList(id, data); + addMemberToList(id, member); if(!mMembersList->getEnabled()) { mMembersList->setEnabled(TRUE); @@ -1665,18 +1657,20 @@ void LLPanelGroupMembersSubTab::updateMembers() LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end(); - - S32 i = 0; - for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME; - ++mMemberProgress, ++i) + + LLTimer update_time; + update_time.setTimerExpirySec(UPDATE_MEMBERS_SECONDS_PER_FRAME); + + for( ; mMemberProgress != end && !update_time.hasExpired(); ++mMemberProgress) { if (!mMemberProgress->second) continue; + // Do filtering on name if it is already in the cache. - std::string fullname; - if (gCacheName->getFullName(mMemberProgress->first, fullname)) + LLAvatarName av_name; + if (LLAvatarNameCache::get(mMemberProgress->first, &av_name)) { - if (matchesSearchFilter(fullname)) + if (matchesSearchFilter(av_name.getLegacyName())) { addMemberToList(mMemberProgress->first, mMemberProgress->second); } @@ -1684,8 +1678,8 @@ void LLPanelGroupMembersSubTab::updateMembers() else { // If name is not cached, onNameCache() should be called when it is cached and add this member to list. - gCacheName->get(mMemberProgress->first, FALSE, boost::bind(&LLPanelGroupMembersSubTab::onNameCache, - this, mUdpateSessionID, _1)); + LLAvatarNameCache::get(mMemberProgress->first, boost::bind(&LLPanelGroupMembersSubTab::onNameCache, + this, mUdpateSessionID, mMemberProgress->second, _1, _2)); } } diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index a55e264150..8b454e020a 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -188,7 +188,7 @@ public: virtual void setGroupID(const LLUUID& id); void addMemberToList(LLUUID id, LLGroupMemberData* data); - void onNameCache(const LLUUID& update_id, const LLUUID& id); + void onNameCache(const LLUUID& update_id, LLGroupMemberData* member, const LLUUID& id, const LLAvatarName& av_name); protected: typedef std::map<LLUUID, LLRoleMemberChangeType> role_change_data_map_t; diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml index 63e154697b..2c420aa1e3 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml @@ -57,7 +57,7 @@ layout="topleft" name="take_copy"> <menu_item_call.on_click - function="InspectObject.TakeFreeCopy"/> + function="Tools.TakeCopy"/> <menu_item_call.on_visible function="Tools.EnableTakeCopy"/> </menu_item_call> |