From 9480a98cffaafa5826b8daad20020cf399bbbefc Mon Sep 17 00:00:00 2001 From: Ansariel Date: Fri, 16 Feb 2024 00:07:58 +0100 Subject: Replace most of BOOL with bool in llmath --- indra/llui/llfolderview.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui/llfolderview.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 650ae9ae75..8033eaa00f 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1476,10 +1476,10 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) } } - BOOL item_clicked = FALSE; - for (selected_items_t::iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + bool item_clicked{ false }; + for (const auto item : mSelectedItems) { - item_clicked |= (*item_it)->getRect().pointInRect(x, y); + item_clicked |= item->getRect().pointInRect(x, y); } if(!item_clicked && mSingleFolderMode) { -- cgit v1.2.3 From c285f59ce2a05703e3a1232fcaf3ee3aea714b3f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 18 Feb 2024 12:52:19 +0100 Subject: Replace BOOL with bool in llwindow and dependent classes --- indra/llui/llfolderview.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'indra/llui/llfolderview.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 8033eaa00f..c9f74c63f8 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1310,20 +1310,20 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) } -BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) +bool LLFolderView::handleUnicodeCharHere(llwchar uni_char) { if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL { - return FALSE; + return false; } if (uni_char > 0x7f) { LL_WARNS() << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << LL_ENDL; - return FALSE; + return false; } - BOOL handled = FALSE; + bool handled = false; if (mParentPanel.get()->hasFocus()) { // SL-51858: Key presses are not being passed to the Popup menu. @@ -1344,21 +1344,21 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char) { mSearchString += uni_char; } - search(getCurSelectedItem(), mSearchString, FALSE); + search(getCurSelectedItem(), mSearchString, false); - handled = TRUE; + handled = true; } return handled; } -BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) +bool LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) { - mKeyboardSelection = FALSE; + mKeyboardSelection = false; mSearchString.clear(); - mParentPanel.get()->setFocus(TRUE); + mParentPanel.get()->setFocus(true); LLEditMenuHandler::gEditMenuHandler = this; @@ -1432,19 +1432,19 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc return found; } -BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) +bool LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) { // skip LLFolderViewFolder::handleDoubleClick() return LLView::handleDoubleClick( x, y, mask ); } -BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) +bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) { // all user operations move keyboard focus to inventory // this way, we know when to stop auto-updating a search - mParentPanel.get()->setFocus(TRUE); + mParentPanel.get()->setFocus(true); - BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; + bool handled = childrenHandleRightMouseDown(x, y, mask) != NULL; S32 count = mSelectedItems.size(); LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); @@ -1516,9 +1516,9 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) { if (menu && menu->getVisible()) { - menu->setVisible(FALSE); + menu->setVisible(false); } - setSelection(NULL, FALSE, TRUE); + setSelection(NULL, false, true); } return handled; } @@ -1554,7 +1554,7 @@ BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const return FALSE; } -BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask ) +bool LLFolderView::handleHover( S32 x, S32 y, MASK mask ) { return LLView::handleHover( x, y, mask ); } -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/llui/llfolderview.cpp | 276 ++++++++++++++++++++++---------------------- 1 file changed, 138 insertions(+), 138 deletions(-) (limited to 'indra/llui/llfolderview.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c9f74c63f8..0ac04e374d 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -84,12 +84,12 @@ F32 LLFolderView::sAutoOpenTime = 1.f; class LLCloseAllFoldersFunctor : public LLFolderViewFunctor { public: - LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; } + LLCloseAllFoldersFunctor(bool close) { mOpen = !close; } virtual ~LLCloseAllFoldersFunctor() {} virtual void doFolder(LLFolderViewFolder* folder); virtual void doItem(LLFolderViewItem* item); - BOOL mOpen; + bool mOpen; }; @@ -167,21 +167,21 @@ LLFolderView::LLFolderView(const Params& p) mAllowMultiSelect(p.allow_multiselect), mAllowDrag(p.allow_drag), mShowEmptyMessage(p.show_empty_message), - mShowFolderHierarchy(FALSE), + mShowFolderHierarchy(false), mRenameItem( NULL ), - mNeedsScroll( FALSE ), + mNeedsScroll( false ), mUseLabelSuffix(p.use_label_suffix), mSuppressFolderMenu(p.suppress_folder_menu), - mPinningSelectedItem(FALSE), - mNeedsAutoSelect( FALSE ), - mAutoSelectOverride(FALSE), - mNeedsAutoRename(FALSE), - mShowSelectionContext(FALSE), - mShowSingleSelection(FALSE), + mPinningSelectedItem(false), + mNeedsAutoSelect( false ), + mAutoSelectOverride(false), + mNeedsAutoRename(false), + mShowSelectionContext(false), + mShowSingleSelection(false), mArrangeGeneration(0), mSignalSelectCallback(0), mMinWidth(0), - mDragAndDropThisFrame(FALSE), + mDragAndDropThisFrame(false), mCallbackRegistrar(NULL), mEnableRegistrar(NULL), mUseEllipses(p.use_ellipses), @@ -205,7 +205,7 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); - mKeyboardSelection = FALSE; + mKeyboardSelection = false; mIndentation = getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0; //clear label @@ -280,9 +280,9 @@ LLFolderView::~LLFolderView( void ) mViewModel = NULL; } -BOOL LLFolderView::canFocusChildren() const +bool LLFolderView::canFocusChildren() const { - return FALSE; + return false; } void LLFolderView::addFolder( LLFolderViewFolder* folder) @@ -293,7 +293,7 @@ void LLFolderView::addFolder( LLFolderViewFolder* folder) void LLFolderView::closeAllFolders() { // Close all the folders - setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); + setOpenArrangeRecursively(false, LLFolderViewFolder::RECURSE_DOWN); arrangeAll(); } @@ -303,7 +303,7 @@ void LLFolderView::openTopLevelFolders() iter != mFolders.end();) { folders_t::iterator fit = iter++; - (*fit)->setOpen(TRUE); + (*fit)->setOpen(true); } } @@ -343,7 +343,7 @@ void LLFolderView::filter( LLFolderViewFilter& filter ) getViewModelItem()->filter(filter); } -void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) +void LLFolderView::reshape(S32 width, S32 height, bool called_from_parent) { LLRect scroll_rect; if (mScrollContainer) @@ -360,7 +360,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) width = scroll_rect.getWidth(); } LLView::reshape(width, height, called_from_parent); - mReshapeSignal(mSelectedItems, FALSE); + mReshapeSignal(mSelectedItems, false); } void LLFolderView::addToSelectionList(LLFolderViewItem* item) @@ -371,9 +371,9 @@ void LLFolderView::addToSelectionList(LLFolderViewItem* item) } if (mSelectedItems.size()) { - mSelectedItems.back()->setIsCurSelection(FALSE); + mSelectedItems.back()->setIsCurSelection(false); } - item->setIsCurSelection(TRUE); + item->setIsCurSelection(true); mSelectedItems.push_back(item); } @@ -381,7 +381,7 @@ void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) { if (mSelectedItems.size()) { - mSelectedItems.back()->setIsCurSelection(FALSE); + mSelectedItems.back()->setIsCurSelection(false); } selected_items_t::iterator item_iter; @@ -398,7 +398,7 @@ void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) } if (mSelectedItems.size()) { - mSelectedItems.back()->setIsCurSelection(TRUE); + mSelectedItems.back()->setIsCurSelection(true); } } @@ -419,19 +419,19 @@ LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) } // Record the selected item and pass it down the hierachy. -BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) +bool LLFolderView::setSelection(LLFolderViewItem* selection, bool openitem, + bool take_keyboard_focus) { mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; if( selection == this ) { - return FALSE; + return false; } if( selection && take_keyboard_focus) { - mParentPanel.get()->setFocus(TRUE); + mParentPanel.get()->setFocus(true); } // clear selection down here because change of keyboard focus can potentially @@ -443,7 +443,7 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, addToSelectionList(selection); } - BOOL rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); + bool rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); if(openitem && selection) { selection->getParentFolder()->requestArrange(); @@ -454,14 +454,14 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, return rv; } -BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) +bool LLFolderView::changeSelection(LLFolderViewItem* selection, bool selected) { - BOOL rv = FALSE; + bool rv = false; // can't select root folder if(!selection || selection == this) { - return FALSE; + return false; } if (!mAllowMultiSelect) @@ -478,7 +478,7 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) } } - BOOL on_list = (item_iter != mSelectedItems.end()); + bool on_list = (item_iter != mSelectedItems.end()); if(selected && !on_list) { @@ -510,7 +510,7 @@ void LLFolderView::sanitizeSelection() LLFolderViewItem* item = *item_iter; // ensure that each ancestor is open and potentially passes filtering - BOOL visible = false; + bool visible = false; if(item->getViewModelItem() != NULL) { visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item @@ -558,7 +558,7 @@ void LLFolderView::sanitizeSelection() std::vector::iterator item_it; for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) { - changeSelection(*item_it, FALSE); // toggle selection (also removes from list) + changeSelection(*item_it, false); // toggle selection (also removes from list) } // if nothing selected after prior constraints... @@ -596,7 +596,7 @@ void LLFolderView::sanitizeSelection() if (new_selection) { - setSelection(new_selection, FALSE, FALSE); + setSelection(new_selection, false, false); } } } @@ -664,12 +664,12 @@ void LLFolderView::draw() if (hasVisibleChildren()) { - mStatusTextBox->setVisible( FALSE ); + mStatusTextBox->setVisible( false ); } else if (mShowEmptyMessage) { mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty())); - mStatusTextBox->setVisible( TRUE ); + mStatusTextBox->setVisible( true ); // firstly reshape message textbox with current size. This is necessary to // LLTextBox::getTextPixelHeight works properly @@ -711,7 +711,7 @@ void LLFolderView::draw() // and arrow for the root folder LLView::draw(); - mDragAndDropThisFrame = FALSE; + mDragAndDropThisFrame = false; } void LLFolderView::finishRenamingItem( void ) @@ -830,7 +830,7 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) while (close_item && close_item != item->getParentFolder()) { mAutoOpenItems.pop(); - close_item->setOpenArrangeRecursively(FALSE); + close_item->setOpenArrangeRecursively(false); close_item = mAutoOpenItems.check(); } @@ -838,7 +838,7 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) mAutoOpenItems.push(item); - item->setOpen(TRUE); + item->setOpen(true); if(!item->isSingleFolderMode()) { LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); @@ -852,7 +852,7 @@ void LLFolderView::closeAutoOpenedFolders() while (mAutoOpenItems.check()) { LLFolderViewFolder* close_item = mAutoOpenItems.pop(); - close_item->setOpen(FALSE); + close_item->setOpen(false); } if (mAutoOpenCandidate) @@ -863,7 +863,7 @@ void LLFolderView::closeAutoOpenedFolders() mAutoOpenTimer.stop(); } -BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) +bool LLFolderView::autoOpenTest(LLFolderViewFolder* folder) { if (folder && mAutoOpenCandidate == folder) { @@ -877,10 +877,10 @@ BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) { autoOpenItem(folder); mAutoOpenTimer.stop(); - return TRUE; + return true; } } - return FALSE; + return false; } // otherwise new candidate, restart timer @@ -890,14 +890,14 @@ BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder) } mAutoOpenCandidate = folder; mAutoOpenTimer.start(); - return FALSE; + return false; } -BOOL LLFolderView::canCopy() const +bool LLFolderView::canCopy() const { if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) { - return FALSE; + return false; } for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) @@ -905,10 +905,10 @@ BOOL LLFolderView::canCopy() const const LLFolderViewItem* item = *selected_it; if (!item->getViewModelItem()->isItemCopyable()) { - return FALSE; + return false; } } - return TRUE; + return true; } // copy selected item @@ -933,11 +933,11 @@ void LLFolderView::copy() mSearchString.clear(); } -BOOL LLFolderView::canCut() const +bool LLFolderView::canCut() const { if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) { - return FALSE; + return false; } for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) @@ -947,10 +947,10 @@ BOOL LLFolderView::canCut() const if (!listener || !listener->isItemRemovable()) { - return FALSE; + return false; } } - return TRUE; + return true; } void LLFolderView::cut() @@ -982,11 +982,11 @@ void LLFolderView::cut() mSearchString.clear(); } -BOOL LLFolderView::canPaste() const +bool LLFolderView::canPaste() const { if (mSelectedItems.empty()) { - return FALSE; + return false; } if(getVisible() && getEnabled()) @@ -1003,13 +1003,13 @@ BOOL LLFolderView::canPaste() const listener = folderp->getViewModelItem(); if (!listener || !listener->isClipboardPasteable()) { - return FALSE; + return false; } } } - return TRUE; + return true; } - return FALSE; + return false; } // paste selected item @@ -1069,17 +1069,17 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setText(item->getName()); mRenamer->selectAll(); - mRenamer->setVisible( TRUE ); + mRenamer->setVisible( true ); // set focus will fail unless item is visible - mRenamer->setFocus( TRUE ); + mRenamer->setFocus( true ); mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); LLUI::getInstance()->addPopup(mRenamer); } } -BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) +bool LLFolderView::handleKeyHere( KEY key, MASK mask ) { - BOOL handled = FALSE; + bool handled = false; // SL-51858: Key presses are not being passed to the Popup menu. // A proper fix is non-trivial so instead just close the menu. @@ -1094,7 +1094,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) case KEY_F2: mSearchString.clear(); startRenamingSelectedItem(); - handled = TRUE; + handled = true; break; case KEY_RETURN: @@ -1104,7 +1104,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { finishRenamingItem(); mSearchString.clear(); - handled = TRUE; + handled = true; } } break; @@ -1113,7 +1113,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if( mRenameItem && mRenamer->getVisible() ) { closeRenamer(); - handled = TRUE; + handled = true; } mSearchString.clear(); break; @@ -1124,7 +1124,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { mScrollContainer->pageUp(30); } - handled = TRUE; + handled = true; break; case KEY_PAGE_DOWN: @@ -1133,7 +1133,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { mScrollContainer->pageDown(30); } - handled = TRUE; + handled = true; break; case KEY_HOME: @@ -1142,7 +1142,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { mScrollContainer->goToTop(); } - handled = TRUE; + handled = true; break; case KEY_END: @@ -1157,14 +1157,14 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if((mSelectedItems.size() > 0) && mScrollContainer) { LLFolderViewItem* last_selected = getCurSelectedItem(); - BOOL shift_select = mask & MASK_SHIFT; + bool shift_select = mask & MASK_SHIFT; // don't shift select down to children of folders (they are implicitly selected through parent) LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; + setSelection(last_selected, false, true); + mKeyboardSelection = true; } if (shift_select) @@ -1174,12 +1174,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (next->isSelected()) { // shrink selection - changeSelection(last_selected, FALSE); + changeSelection(last_selected, false); } else if (last_selected->getParentFolder() == next->getParentFolder()) { // grow selection - changeSelection(next, TRUE); + changeSelection(next, true); } } } @@ -1193,11 +1193,11 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed { clearSelection(); - return TRUE; + return true; } - return FALSE; + return false; } - setSelection( next, FALSE, TRUE ); + setSelection( next, false, true ); } else { @@ -1205,14 +1205,14 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed { clearSelection(); - return TRUE; + return true; } - return FALSE; + return false; } } scrollToShowSelection(); mSearchString.clear(); - handled = TRUE; + handled = true; } break; @@ -1220,14 +1220,14 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if((mSelectedItems.size() > 0) && mScrollContainer) { LLFolderViewItem* last_selected = mSelectedItems.back(); - BOOL shift_select = mask & MASK_SHIFT; + bool shift_select = mask & MASK_SHIFT; // don't shift select down to children of folders (they are implicitly selected through parent) LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select); if (!mKeyboardSelection || (!shift_select && prev == this)) { - setSelection(last_selected, FALSE, TRUE); - mKeyboardSelection = TRUE; + setSelection(last_selected, false, true); + mKeyboardSelection = true; } if (shift_select) @@ -1237,12 +1237,12 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if (prev->isSelected()) { // shrink selection - changeSelection(last_selected, FALSE); + changeSelection(last_selected, false); } else if (last_selected->getParentFolder() == prev->getParentFolder()) { // grow selection - changeSelection(prev, TRUE); + changeSelection(prev, true); } } } @@ -1256,18 +1256,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed { clearSelection(); - return TRUE; + return true; } - return FALSE; + return false; } - setSelection( prev, FALSE, TRUE ); + setSelection( prev, false, true ); } } scrollToShowSelection(); mSearchString.clear(); - handled = TRUE; + handled = true; } break; @@ -1275,9 +1275,9 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if(mSelectedItems.size()) { LLFolderViewItem* last_selected = getCurSelectedItem(); - last_selected->setOpen( TRUE ); + last_selected->setOpen( true ); mSearchString.clear(); - handled = TRUE; + handled = true; } break; @@ -1287,21 +1287,21 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) LLFolderViewItem* last_selected = getCurSelectedItem(); if(last_selected && last_selected->isSingleFolderMode()) { - handled = FALSE; + handled = false; break; } LLFolderViewItem* parent_folder = last_selected->getParentFolder(); if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) { - setSelection(parent_folder, FALSE, TRUE); + setSelection(parent_folder, false, true); } else { - last_selected->setOpen( FALSE ); + last_selected->setOpen( false ); } mSearchString.clear(); scrollToShowSelection(); - handled = TRUE; + handled = true; } break; } @@ -1365,7 +1365,7 @@ bool LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) return LLView::handleMouseDown( x, y, mask ); } -BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward) +bool LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, bool backward) { // get first selected item LLFolderViewItem* search_item = first_item; @@ -1382,7 +1382,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc } // search over all open nodes for first substring match (with wrapping) - BOOL found = FALSE; + bool found = false; LLFolderViewItem* original_search_item = search_item; do { @@ -1408,7 +1408,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); if (!current_item_label.compare(0, search_string_length, upper_case_string)) { - found = TRUE; + found = true; break; } if (backward) @@ -1425,7 +1425,7 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc if (found) { - setSelection(search_item, FALSE, TRUE); + setSelection(search_item, false, true); scrollToShowSelection(); } @@ -1524,7 +1524,7 @@ bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) } // Add "--no options--" if the menu is completely blank. -BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const +bool LLFolderView::addNoOptions(LLMenuGL* menu) const { const std::string nooptions_str = "--no options--"; LLView *nooptions_item = NULL; @@ -1537,7 +1537,7 @@ BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const LLView *menu_item = (*itor); if (menu_item->getVisible()) { - return FALSE; + return false; } std::string name = menu_item->getName(); if (menu_item->getName() == nooptions_str) @@ -1547,11 +1547,11 @@ BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const } if (nooptions_item) { - nooptions_item->setVisible(TRUE); - nooptions_item->setEnabled(FALSE); - return TRUE; + nooptions_item->setVisible(true); + nooptions_item->setEnabled(false); + return true; } - return FALSE; + return false; } bool LLFolderView::handleHover( S32 x, S32 y, MASK mask ) @@ -1575,15 +1575,15 @@ void LLFolderView::setHoveredItem(LLFolderViewItem* itemp) } } -BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +bool LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { - mDragAndDropThisFrame = TRUE; + mDragAndDropThisFrame = true; // have children handle it first - BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + bool handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); // when drop is not handled by child, it should be handled @@ -1614,7 +1614,7 @@ void LLFolderView::scrollToShowSelection() { if ( mSelectedItems.size() ) { - mNeedsScroll = TRUE; + mNeedsScroll = true; } } @@ -1627,7 +1627,7 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr // don't scroll to items when mouse is being used to scroll/drag and drop if (gFocusMgr.childHasMouseCapture(mScrollContainer)) { - mNeedsScroll = FALSE; + mNeedsScroll = false; return; } @@ -1665,18 +1665,18 @@ LLRect LLFolderView::getVisibleRect() return visible_rect; } -BOOL LLFolderView::getShowSelectionContext() +bool LLFolderView::getShowSelectionContext() { if (mShowSelectionContext) { - return TRUE; + return true; } LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if (menu && menu->getVisible()) { - return TRUE; + return true; } - return FALSE; + return false; } void LLFolderView::setShowSingleSelection(bool show) @@ -1707,7 +1707,7 @@ void LLFolderView::update() if (filter_object.isModified() && filter_object.isNotDefault() && mParentPanel.get()->getVisible()) { - mNeedsAutoSelect = TRUE; + mNeedsAutoSelect = true; } // Filter to determine visibility before arranging @@ -1734,7 +1734,7 @@ void LLFolderView::update() applyFunctorRecursively(functor); } - // Open filtered folders for folder views with mAutoSelectOverride=TRUE. + // Open filtered folders for folder views with mAutoSelectOverride=true. // Used by LLPlacesFolderView. if (filter_object.showAllResults()) { @@ -1747,7 +1747,7 @@ void LLFolderView::update() scrollToShowSelection(); } - BOOL filter_finished = mViewModel->contentsReady() + bool filter_finished = mViewModel->contentsReady() && (getViewModelItem()->passedFilter() || ( getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration() && !filter_modified)); @@ -1756,10 +1756,10 @@ void LLFolderView::update() || gFocusMgr.childHasMouseCapture(mParentPanel.get())) { // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process - mNeedsAutoSelect = FALSE; + mNeedsAutoSelect = false; } - BOOL is_visible = isInVisibleChain() || mForceArrange; + bool is_visible = isInVisibleChain() || mForceArrange; //Puts folders/items in proper positions // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) @@ -1784,7 +1784,7 @@ void LLFolderView::update() if (!mPinningSelectedItem && !mSelectedItems.empty()) { // lets pin it! - mPinningSelectedItem = TRUE; + mPinningSelectedItem = true; //Computes visible area const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); @@ -1819,7 +1819,7 @@ void LLFolderView::update() // stop pinning selected item after folders stop rearranging if (!needsArrange()) { - mPinningSelectedItem = FALSE; + mPinningSelectedItem = false; } } @@ -1855,7 +1855,7 @@ void LLFolderView::update() } if (!needs_arrange || !is_visible) { - mNeedsScroll = FALSE; + mNeedsScroll = false; } } } @@ -1872,15 +1872,15 @@ void LLFolderView::update() if (mSignalSelectCallback) { //RN: we use keyboard focus as a proxy for user-explicit actions - BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); + bool take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); mSelectSignal(mSelectedItems, take_keyboard_focus); } - mSignalSelectCallback = FALSE; + mSignalSelectCallback = false; } } else { - mSignalSelectCallback = FALSE; + mSignalSelectCallback = false; } } @@ -1915,7 +1915,7 @@ void LLFolderView::updateRenamerPosition() S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenamer->reshape( width, height, TRUE ); + mRenamer->reshape( width, height, true ); } } @@ -1927,9 +1927,9 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) LLView::child_list_t::const_iterator menu_itor; for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) { - (*menu_itor)->setVisible(FALSE); - (*menu_itor)->pushVisible(TRUE); - (*menu_itor)->setEnabled(TRUE); + (*menu_itor)->setVisible(false); + (*menu_itor)->pushVisible(true); + (*menu_itor)->setEnabled(true); } // Successively filter out invalid options @@ -1995,7 +1995,7 @@ bool LLFolderView::selectFirstItem() { LLFolderViewItem* itemp = folder->getNextFromChild(0,true); if(itemp) - setSelection(itemp,FALSE,TRUE); + setSelection(itemp,false,true); return true; } @@ -2006,7 +2006,7 @@ bool LLFolderView::selectFirstItem() LLFolderViewItem* itemp = (*iit); if (itemp->getVisible()) { - setSelection(itemp,FALSE,TRUE); + setSelection(itemp,false,true); return true; } } @@ -2020,7 +2020,7 @@ bool LLFolderView::selectLastItem() LLFolderViewItem* itemp = (*iit); if (itemp->getVisible()) { - setSelection(itemp,FALSE,TRUE); + setSelection(itemp,false,true); return true; } } @@ -2032,7 +2032,7 @@ bool LLFolderView::selectLastItem() { LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); if(itemp) - setSelection(itemp,FALSE,TRUE); + setSelection(itemp,false,true); return true; } } @@ -2073,15 +2073,15 @@ void LLFolderView::onRenamerLost() { if (mRenamer && mRenamer->getVisible()) { - mRenamer->setVisible(FALSE); + mRenamer->setVisible(false); // will commit current name (which could be same as original name) - mRenamer->setFocus(FALSE); + mRenamer->setFocus(false); } if( mRenameItem ) { - setSelection( mRenameItem, TRUE ); + setSelection( mRenameItem, true ); mRenameItem = NULL; } } @@ -2089,17 +2089,17 @@ void LLFolderView::onRenamerLost() LLFolderViewItem* LLFolderView::getNextUnselectedItem() { LLFolderViewItem* last_item = *mSelectedItems.rbegin(); - LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); + LLFolderViewItem* new_selection = last_item->getNextOpenNode(false); while(new_selection && new_selection->isSelected()) { - new_selection = new_selection->getNextOpenNode(FALSE); + new_selection = new_selection->getNextOpenNode(false); } if (!new_selection) { - new_selection = last_item->getPreviousOpenNode(FALSE); + new_selection = last_item->getPreviousOpenNode(false); while (new_selection && (new_selection->isInSelection())) { - new_selection = new_selection->getPreviousOpenNode(FALSE); + new_selection = new_selection->getPreviousOpenNode(false); } } return new_selection; -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llui/llfolderview.cpp | 4258 +++++++++++++++++++++---------------------- 1 file changed, 2129 insertions(+), 2129 deletions(-) (limited to 'indra/llui/llfolderview.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index c01e811477..47821e38ca 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1,2129 +1,2129 @@ -/** - * @file llfolderview.cpp - * @brief Implementation of the folder view collection of classes. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * 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. - * - * 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. - * - * 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 - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llfolderview.h" -#include "llfolderviewmodel.h" -#include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpanel.h" -#include "llscrollcontainer.h" // hack to allow scrolling -#include "lltextbox.h" -#include "lltrans.h" -#include "llui.h" -#include "lluictrlfactory.h" - -// Linden library includes -#include "lldbstrings.h" -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llgl.h" -#include "llrender.h" - -// Third-party library includes -#include - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -const S32 RENAME_HEIGHT_PAD = 1; -const S32 AUTO_OPEN_STACK_DEPTH = 16; - -const S32 MINIMUM_RENAMER_WIDTH = 80; - -// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. -const S32 STATUS_TEXT_HPAD = 6; -const S32 STATUS_TEXT_VPAD = 8; - -enum { - SIGNAL_NO_KEYBOARD_FOCUS = 1, - SIGNAL_KEYBOARD_FOCUS = 2 -}; - -F32 LLFolderView::sAutoOpenTime = 1.f; - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to close themselves -// For efficiency, calls setOpenArrangeRecursively(). -// The calling function must then call: -// LLFolderView* root = getRoot(); -// if( root ) -// { -// root->arrange( NULL, NULL ); -// root->scrollToShowSelection(); -// } -// to patch things up. -class LLCloseAllFoldersFunctor : public LLFolderViewFunctor -{ -public: - LLCloseAllFoldersFunctor(bool close) { mOpen = !close; } - virtual ~LLCloseAllFoldersFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - bool mOpen; -}; - - -void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) -{ - folder->setOpenArrangeRecursively(mOpen); -} - -// Do nothing. -void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) -{ } - -//--------------------------------------------------------------------------- - -void LLAllDescendentsPassedFilter::doFolder(LLFolderViewFolder* folder) -{ - mAllDescendentsPassedFilter &= (folder) && (folder->passedFilter()) && (folder->descendantsPassedFilter()); -} - -void LLAllDescendentsPassedFilter::doItem(LLFolderViewItem* item) -{ - mAllDescendentsPassedFilter &= (item) && (item->passedFilter()); -} - -///---------------------------------------------------------------------------- -/// Class LLFolderViewScrollContainer -///---------------------------------------------------------------------------- - -// virtual -const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const -{ - LLRect rect = LLRect::null; - if (mScrolledView) - { - LLFolderView* folder_view = dynamic_cast(mScrolledView); - if (folder_view) - { - S32 height = folder_view->getRect().getHeight(); - - rect = mScrolledView->getRect(); - rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); - } - } - - return rect; -} - -LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) -: LLScrollContainer(p) -{} - -///---------------------------------------------------------------------------- -/// Class LLFolderView -///---------------------------------------------------------------------------- -LLFolderView::Params::Params() -: title("title"), - use_label_suffix("use_label_suffix"), - allow_multiselect("allow_multiselect", true), - allow_drag("allow_drag", true), - show_empty_message("show_empty_message", true), - suppress_folder_menu("suppress_folder_menu", false), - use_ellipses("use_ellipses", false), - options_menu("options_menu", "") -{ - folder_indentation = -4; -} - - -// Default constructor -LLFolderView::LLFolderView(const Params& p) -: LLFolderViewFolder(p), - mScrollContainer( NULL ), - mPopupMenuHandle(), - mMenuFileName(p.options_menu), - mAllowMultiSelect(p.allow_multiselect), - mAllowDrag(p.allow_drag), - mShowEmptyMessage(p.show_empty_message), - mShowFolderHierarchy(false), - mRenameItem( NULL ), - mNeedsScroll( false ), - mUseLabelSuffix(p.use_label_suffix), - mSuppressFolderMenu(p.suppress_folder_menu), - mPinningSelectedItem(false), - mNeedsAutoSelect( false ), - mAutoSelectOverride(false), - mNeedsAutoRename(false), - mShowSelectionContext(false), - mShowSingleSelection(false), - mArrangeGeneration(0), - mSignalSelectCallback(0), - mMinWidth(0), - mDragAndDropThisFrame(false), - mCallbackRegistrar(NULL), - mEnableRegistrar(NULL), - mUseEllipses(p.use_ellipses), - mDraggingOverItem(NULL), - mStatusTextBox(NULL), - mShowItemLinkOverlays(p.show_item_link_overlays), - mViewModel(p.view_model), - mGroupedItemModel(p.grouped_item_model), - mForceArrange(false), - mSingleFolderMode(false) -{ - LLPanel* panel = p.parent_panel; - mParentPanel = panel->getHandle(); - mViewModel->setFolderView(this); - mRoot = this; - - LLRect rect = p.rect; - LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); - setRect( rect ); - reshape(rect.getWidth(), rect.getHeight()); - mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); - mKeyboardSelection = false; - mIndentation = getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0; - - //clear label - // go ahead and render root folder as usual - // just make sure the label ("Inventory Folder") never shows up - mLabel = LLStringUtil::null; - - // Escape is handled by reverting the rename, not commiting it (default behavior) - LLLineEditor::Params params; - params.name("ren"); - params.rect(rect); - params.font(getLabelFontForStyle(LLFontGL::NORMAL)); - params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); - params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidator(&LLTextValidate::validateASCIIPrintableNoPipe); - params.commit_on_focus_lost(true); - params.visible(false); - mRenamer = LLUICtrlFactory::create (params); - addChild(mRenamer); - - // Textbox - LLTextBox::Params text_p; - LLFontGL* font = getLabelFontForStyle(mLabelStyle); - //mIconPad, mTextPad are set in folder_view_item.xml - LLRect new_r = LLRect(rect.mLeft + mIconPad, - rect.mTop - mTextPad, - rect.mRight, - rect.mTop - mTextPad - font->getLineHeight()); - text_p.rect(new_r); - text_p.name(std::string(p.name)); - text_p.font(font); - text_p.visible(false); - text_p.parse_urls(true); - text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 - // set text padding the same as in People panel. EXT-7047, EXT-4837 - text_p.h_pad(STATUS_TEXT_HPAD); - text_p.v_pad(STATUS_TEXT_VPAD); - mStatusTextBox = LLUICtrlFactory::create (text_p); - mStatusTextBox->setFollowsLeft(); - mStatusTextBox->setFollowsTop(); - addChild(mStatusTextBox); - - mViewModelItem->openItem(); - - mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited. -} - -// Destroys the object -LLFolderView::~LLFolderView( void ) -{ - mRenamerTopLostSignalConnection.disconnect(); - if (mRenamer) - { - // instead of using closeRenamer remove it directly, - // since it might already be hidden - LLUI::getInstance()->removePopup(mRenamer); - } - - // The release focus call can potentially call the - // scrollcontainer, which can potentially be called with a partly - // destroyed scollcontainer. Just null it out here, and no worries - // about calling into the invalid scroll container. - // Same with the renamer. - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle.markDead(); - - mAutoOpenItems.removeAllNodes(); - clearSelection(); - mItems.clear(); - mFolders.clear(); - - //mViewModel->setFolderView(NULL); - mViewModel = NULL; -} - -bool LLFolderView::canFocusChildren() const -{ - return false; -} - -void LLFolderView::addFolder( LLFolderViewFolder* folder) -{ - LLFolderViewFolder::addFolder(folder); -} - -void LLFolderView::closeAllFolders() -{ - // Close all the folders - setOpenArrangeRecursively(false, LLFolderViewFolder::RECURSE_DOWN); - arrangeAll(); -} - -void LLFolderView::openTopLevelFolders() -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpen(true); - } -} - -// This view grows and shrinks to enclose all of its children items and folders. -// *width should be 0 -// conform show folder state works -S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) - { - mMinWidth = 0; - S32 target_height; - - LLFolderViewFolder::arrange(&mMinWidth, &target_height); - - LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); - - LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) - { - reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); - } - - // move item renamer text field to item's new position - updateRenamerPosition(); - - return ll_round(mTargetHeight); -} - -void LLFolderView::filter( LLFolderViewFilter& filter ) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - const S32 TIME_VISIBLE = 10; // in milliseconds - const S32 TIME_INVISIBLE = 1; - filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? TIME_VISIBLE : TIME_INVISIBLE), 1, 100)); - - // Note: we filter the model, not the view - getViewModelItem()->filter(filter); -} - -void LLFolderView::reshape(S32 width, S32 height, bool called_from_parent) -{ - LLRect scroll_rect; - if (mScrollContainer) - { - LLView::reshape(width, height, called_from_parent); - scroll_rect = mScrollContainer->getContentWindowRect(); - } - width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(ll_round(mCurHeight), scroll_rect.getHeight()); - - // Restrict width within scroll container's width - if (mUseEllipses && mScrollContainer) - { - width = scroll_rect.getWidth(); - } - LLView::reshape(width, height, called_from_parent); - mReshapeSignal(mSelectedItems, false); -} - -void LLFolderView::addToSelectionList(LLFolderViewItem* item) -{ - if (item->isSelected()) - { - removeFromSelectionList(item); - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(false); - } - item->setIsCurSelection(true); - mSelectedItems.push_back(item); -} - -void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) -{ - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(false); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) - { - if (*item_iter == item) - { - item_iter = mSelectedItems.erase(item_iter); - } - else - { - ++item_iter; - } - } - if (mSelectedItems.size()) - { - mSelectedItems.back()->setIsCurSelection(true); - } -} - -LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) -{ - if(mSelectedItems.size()) - { - LLFolderViewItem* itemp = mSelectedItems.back(); - llassert(itemp->getIsCurSelection()); - return itemp; - } - return NULL; -} - -LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) -{ - return mSelectedItems; -} - -// Record the selected item and pass it down the hierachy. -bool LLFolderView::setSelection(LLFolderViewItem* selection, bool openitem, - bool take_keyboard_focus) -{ - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - - if( selection == this ) - { - return false; - } - - if( selection && take_keyboard_focus) - { - mParentPanel.get()->setFocus(true); - } - - // clear selection down here because change of keyboard focus can potentially - // affect selection - clearSelection(); - - if(selection) - { - addToSelectionList(selection); - } - - bool rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); - if(openitem && selection) - { - selection->getParentFolder()->requestArrange(); - } - - llassert(mSelectedItems.size() <= 1); - - return rv; -} - -bool LLFolderView::changeSelection(LLFolderViewItem* selection, bool selected) -{ - bool rv = false; - - // can't select root folder - if(!selection || selection == this) - { - return false; - } - - if (!mAllowMultiSelect) - { - clearSelection(); - } - - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - if (*item_iter == selection) - { - break; - } - } - - bool on_list = (item_iter != mSelectedItems.end()); - - if(selected && !on_list) - { - addToSelectionList(selection); - } - if(!selected && on_list) - { - removeFromSelectionList(selection); - } - - rv = LLFolderViewFolder::changeSelection(selection, selected); - - mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; - - return rv; -} - -void LLFolderView::sanitizeSelection() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - // store off current item in case it is automatically deselected - // and we want to preserve context - LLFolderViewItem* original_selected_item = getCurSelectedItem(); - - std::vector items_to_remove; - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewItem* item = *item_iter; - - // ensure that each ancestor is open and potentially passes filtering - bool visible = false; - if(item->getViewModelItem() != NULL) - { - visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item - } - // modify with parent open and filters states - LLFolderViewFolder* parent_folder = item->getParentFolder(); - // Move up through parent folders and see what's visible - while(parent_folder) - { - visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); - parent_folder = parent_folder->getParentFolder(); - } - - // deselect item if any ancestor is closed or didn't pass filter requirements. - if (!visible) - { - items_to_remove.push_back(item); - } - - // disallow nested selections (i.e. folder items plus one or more ancestors) - // could check cached mum selections count and only iterate if there are any - // but that may be a premature optimization. - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) - { - LLFolderViewItem* other_item = *other_item_iter; - for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - } - } - - // Don't allow invisible items (such as root folders) to be selected. - if (item == getRoot()) - { - items_to_remove.push_back(item); - } - } - - std::vector::iterator item_it; - for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) - { - changeSelection(*item_it, false); // toggle selection (also removes from list) - } - - // if nothing selected after prior constraints... - if (mSelectedItems.empty()) - { - // ...select first available parent of original selection - LLFolderViewItem* new_selection = NULL; - if (original_selected_item) - { - for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); - parent_folder; - parent_folder = parent_folder->getParentFolder()) - { - if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible()) - { - // give initial selection to first ancestor folder that potentially passes the filter - if (!new_selection) - { - new_selection = parent_folder; - } - - // if any ancestor folder of original item is closed, move the selection up - // to the highest closed - if (!parent_folder->isOpen()) - { - new_selection = parent_folder; - } - } - } - } - else - { - new_selection = NULL; - } - - if (new_selection) - { - setSelection(new_selection, false, false); - } - } -} - -void LLFolderView::clearSelection() -{ - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) - { - (*item_it)->setUnselected(); - } - - mSelectedItems.clear(); - mNeedsScroll = false; -} - -std::set LLFolderView::getSelectionList() const -{ - std::set selection; - std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); - return selection; -} - -bool LLFolderView::startDrag() -{ - std::vector selected_items; - selected_items_t::iterator item_it; - - if (!mSelectedItems.empty()) - { - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - selected_items.push_back((*item_it)->getViewModelItem()); - } - - return getFolderViewModel()->startDrag(selected_items); - } - return false; -} - -void LLFolderView::commitRename( const LLSD& data ) -{ - finishRenamingItem(); - arrange( NULL, NULL ); - -} - -void LLFolderView::draw() -{ - //LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - // if cursor has moved off of me during drag and drop - // close all auto opened folders - if (!mDragAndDropThisFrame) - { - closeAutoOpenedFolders(); - } - - static LLCachedControl type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f); - if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size()) - { - mSearchString.clear(); - } - - if (hasVisibleChildren()) - { - mStatusTextBox->setVisible( false ); - } - else if (mShowEmptyMessage) - { - mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty())); - mStatusTextBox->setVisible( true ); - - // firstly reshape message textbox with current size. This is necessary to - // LLTextBox::getTextPixelHeight works properly - const LLRect local_rect = getLocalRect(); - mStatusTextBox->setShape(local_rect); - - // get preferable text height... - S32 pixel_height = mStatusTextBox->getTextPixelHeight(); - bool height_changed = (local_rect.getHeight() < pixel_height); - if (height_changed) - { - // ... if it does not match current height, lets rearrange current view. - // This will indirectly call ::arrange and reshape of the status textbox. - // We should call this method to also notify parent about required rect. - // See EXT-7564, EXT-7047. - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - - LLUI::popMatrix(); - LLUI::pushMatrix(); - LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); - } - } - - if (mRenameItem - && mRenamer - && mRenamer->getVisible() - && !getVisibleRect().overlaps(mRenamer->getRect())) - { - // renamer is not connected to the item we are renaming in any form so manage it manually - // TODO: consider stopping on any scroll action instead of when out of visible area - LL_DEBUGS("Inventory") << "Renamer out of bounds, hiding" << LL_ENDL; - finishRenamingItem(); - } - - // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, - // and arrow for the root folder - LLView::draw(); - - mDragAndDropThisFrame = false; -} - -void LLFolderView::finishRenamingItem( void ) -{ - if(!mRenamer) - { - return; - } - if( mRenameItem ) - { - mRenameItem->rename( mRenamer->getText() ); - } - - closeRenamer(); - - // This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611). - // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. - //scrollToShowSelection(); -} - -void LLFolderView::closeRenamer( void ) -{ - if (mRenamer && mRenamer->getVisible()) - { - // Triggers onRenamerLost() that actually closes the renamer. - LLUI::getInstance()->removePopup(mRenamer); - } -} - -void LLFolderView::removeSelectedItems() -{ - if(getVisible() && getEnabled()) - { - // just in case we're removing the renaming item. - mRenameItem = NULL; - - // create a temporary structure which we will use to remove - // items, since the removal will futz with internal data - // structures. - std::vector items; - S32 count = mSelectedItems.size(); - if(count <= 0) return; - LLFolderViewItem* item = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - item = *item_it; - if (item && item->isRemovable()) - { - items.push_back(item); - } - else - { - LL_DEBUGS() << "Cannot delete " << item->getName() << LL_ENDL; - return; - } - } - - // iterate through the new container. - count = items.size(); - LLUUID new_selection_id; - LLFolderViewItem* item_to_select = getNextUnselectedItem(); - - if(count == 1) - { - LLFolderViewItem* item_to_delete = items[0]; - LLFolderViewFolder* parent = item_to_delete->getParentFolder(); - if(parent) - { - if (item_to_delete->remove()) - { - // change selection on successful delete - setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); - } - } - arrangeAll(); - } - else if (count > 1) - { - std::vector listeners; - LLFolderViewModelItem* listener; - - setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); - - listeners.reserve(count); - for(S32 i = 0; i < count; ++i) - { - listener = items[i]->getViewModelItem(); - if(listener && (std::find(listeners.begin(), listeners.end(), listener) == listeners.end())) - { - listeners.push_back(listener); - } - } - listener = static_cast(listeners.at(0)); - if(listener) - { - listener->removeBatch(listeners); - } - } - arrangeAll(); - scrollToShowSelection(); - } -} - -void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) -{ - if ((mAutoOpenItems.check() == item) || - (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || - item->isOpen()) - { - return; - } - - // close auto-opened folders - LLFolderViewFolder* close_item = mAutoOpenItems.check(); - while (close_item && close_item != item->getParentFolder()) - { - mAutoOpenItems.pop(); - close_item->setOpenArrangeRecursively(false); - close_item = mAutoOpenItems.check(); - } - - item->requestArrange(); - - mAutoOpenItems.push(item); - - item->setOpen(true); - if(!item->isSingleFolderMode()) - { - LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); - scrollToShowItem(item, constraint_rect); - } -} - -void LLFolderView::closeAutoOpenedFolders() -{ - while (mAutoOpenItems.check()) - { - LLFolderViewFolder* close_item = mAutoOpenItems.pop(); - close_item->setOpen(false); - } - - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = NULL; - mAutoOpenTimer.stop(); -} - -bool LLFolderView::autoOpenTest(LLFolderViewFolder* folder) -{ - if (folder && mAutoOpenCandidate == folder) - { - if (mAutoOpenTimer.getStarted()) - { - if (!mAutoOpenCandidate->isOpen()) - { - mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); - } - if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) - { - autoOpenItem(folder); - mAutoOpenTimer.stop(); - return true; - } - } - return false; - } - - // otherwise new candidate, restart timer - if (mAutoOpenCandidate) - { - mAutoOpenCandidate->setAutoOpenCountdown(0.f); - } - mAutoOpenCandidate = folder; - mAutoOpenTimer.start(); - return false; -} - -bool LLFolderView::canCopy() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return false; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - if (!item->getViewModelItem()->isItemCopyable()) - { - return false; - } - } - return true; -} - -// copy selected item -void LLFolderView::copy() -{ - // *NOTE: total hack to clear the inventory clipboard - LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); - if(getVisible() && getEnabled() && (count > 0)) - { - LLFolderViewModelItem* listener = NULL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - listener = (*item_it)->getViewModelItem(); - if(listener) - { - listener->copyToClipboard(); - } - } - } - mSearchString.clear(); -} - -bool LLFolderView::canCut() const -{ - if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) - { - return false; - } - - for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - const LLFolderViewItem* item = *selected_it; - const LLFolderViewModelItem* listener = item->getViewModelItem(); - - if (!listener || !listener->isItemRemovable()) - { - return false; - } - } - return true; -} - -void LLFolderView::cut() -{ - // clear the inventory clipboard - LLClipboard::instance().reset(); - if(getVisible() && getEnabled() && (mSelectedItems.size() > 0)) - { - // Find out which item will be selected once the selection will be cut - LLFolderViewItem* item_to_select = getNextUnselectedItem(); - - // Get the selection: removeItem() modified mSelectedItems and makes iterating on it unwise - std::set inventory_selected = getSelectionList(); - - // Move each item to the clipboard and out of their folder - for (std::set::iterator item_it = inventory_selected.begin(); item_it != inventory_selected.end(); ++item_it) - { - LLFolderViewItem* item_to_cut = *item_it; - LLFolderViewModelItem* listener = item_to_cut->getViewModelItem(); - if (listener) - { - listener->cutToClipboard(); - } - } - - // Update the selection - setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); - } - mSearchString.clear(); -} - -bool LLFolderView::canPaste() const -{ - if (mSelectedItems.empty()) - { - return false; - } - - if(getVisible() && getEnabled()) - { - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); ++item_it) - { - // *TODO: only check folders and parent folders of items - const LLFolderViewItem* item = (*item_it); - const LLFolderViewModelItem* listener = item->getViewModelItem(); - if(!listener || !listener->isClipboardPasteable()) - { - const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getViewModelItem(); - if (!listener || !listener->isClipboardPasteable()) - { - return false; - } - } - } - return true; - } - return false; -} - -// paste selected item -void LLFolderView::paste() -{ - if(getVisible() && getEnabled()) - { - // find set of unique folders to paste into - std::set folder_set; - - selected_items_t::iterator selected_it; - for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) - { - LLFolderViewItem* item = *selected_it; - LLFolderViewFolder* folder = dynamic_cast(item); - if (folder == NULL) - { - folder = item->getParentFolder(); - } - folder_set.insert(folder); - } - - std::set::iterator set_iter; - for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) - { - LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); - if(listener && listener->isClipboardPasteable()) - { - listener->pasteFromClipboard(); - } - } - } - mSearchString.clear(); -} - -// public rename functionality - can only start the process -void LLFolderView::startRenamingSelectedItem( void ) -{ - LL_DEBUGS("Inventory") << "Starting inventory renamer" << LL_ENDL; - - // make sure selection is visible - scrollToShowSelection(); - - S32 count = mSelectedItems.size(); - LLFolderViewItem* item = NULL; - if(count > 0) - { - item = mSelectedItems.front(); - } - if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && - item->getViewModelItem()->isItemRenameable()) - { - mRenameItem = item; - - updateRenamerPosition(); - - - mRenamer->setText(item->getName()); - mRenamer->selectAll(); - mRenamer->setVisible( true ); - // set focus will fail unless item is visible - mRenamer->setFocus( true ); - if (!mRenamerTopLostSignalConnection.connected()) - { - mRenamerTopLostSignalConnection = mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); - } - LLUI::getInstance()->addPopup(mRenamer); - } -} - -bool LLFolderView::handleKeyHere( KEY key, MASK mask ) -{ - bool handled = false; - - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - switch( key ) - { - case KEY_F2: - mSearchString.clear(); - startRenamingSelectedItem(); - handled = true; - break; - - case KEY_RETURN: - if (mask == MASK_NONE) - { - if( mRenameItem && mRenamer->getVisible() ) - { - finishRenamingItem(); - mSearchString.clear(); - handled = true; - } - } - break; - - case KEY_ESCAPE: - if( mRenameItem && mRenamer->getVisible() ) - { - closeRenamer(); - handled = true; - } - mSearchString.clear(); - break; - - case KEY_PAGE_UP: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->pageUp(30); - } - handled = true; - break; - - case KEY_PAGE_DOWN: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->pageDown(30); - } - handled = true; - break; - - case KEY_HOME: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->goToTop(); - } - handled = true; - break; - - case KEY_END: - mSearchString.clear(); - if (mScrollContainer) - { - mScrollContainer->goToBottom(); - } - break; - - case KEY_DOWN: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - bool shift_select = mask & MASK_SHIFT; - // don't shift select down to children of folders (they are implicitly selected through parent) - LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); - - if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) - { - setSelection(last_selected, false, true); - mKeyboardSelection = true; - } - - if (shift_select) - { - if (next) - { - if (next->isSelected()) - { - // shrink selection - changeSelection(last_selected, false); - } - else if (last_selected->getParentFolder() == next->getParentFolder()) - { - // grow selection - changeSelection(next, true); - } - } - } - else - { - if( next ) - { - if (next == last_selected) - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return true; - } - return false; - } - setSelection( next, false, true ); - } - else - { - //special case for LLAccordionCtrl - if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed - { - clearSelection(); - return true; - } - return false; - } - } - scrollToShowSelection(); - mSearchString.clear(); - handled = true; - } - break; - - case KEY_UP: - if((mSelectedItems.size() > 0) && mScrollContainer) - { - LLFolderViewItem* last_selected = mSelectedItems.back(); - bool shift_select = mask & MASK_SHIFT; - // don't shift select down to children of folders (they are implicitly selected through parent) - LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select); - - if (!mKeyboardSelection || (!shift_select && prev == this)) - { - setSelection(last_selected, false, true); - mKeyboardSelection = true; - } - - if (shift_select) - { - if (prev) - { - if (prev->isSelected()) - { - // shrink selection - changeSelection(last_selected, false); - } - else if (last_selected->getParentFolder() == prev->getParentFolder()) - { - // grow selection - changeSelection(prev, true); - } - } - } - else - { - if( prev ) - { - if (prev == this) - { - // If case we are in accordion tab notify parent to go to the previous accordion - if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed - { - clearSelection(); - return true; - } - - return false; - } - setSelection( prev, false, true ); - } - } - scrollToShowSelection(); - mSearchString.clear(); - - handled = true; - } - break; - - case KEY_RIGHT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - last_selected->setOpen( true ); - mSearchString.clear(); - handled = true; - } - break; - - case KEY_LEFT: - if(mSelectedItems.size()) - { - LLFolderViewItem* last_selected = getCurSelectedItem(); - if(last_selected && last_selected->isSingleFolderMode()) - { - handled = false; - break; - } - LLFolderViewItem* parent_folder = last_selected->getParentFolder(); - if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) - { - setSelection(parent_folder, false, true); - } - else - { - last_selected->setOpen( false ); - } - mSearchString.clear(); - scrollToShowSelection(); - handled = true; - } - break; - } - - return handled; -} - - -bool LLFolderView::handleUnicodeCharHere(llwchar uni_char) -{ - if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL - { - return false; - } - - if (uni_char > 0x7f) - { - LL_WARNS() << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << LL_ENDL; - return false; - } - - bool handled = false; - if (mParentPanel.get()->hasFocus()) - { - // SL-51858: Key presses are not being passed to the Popup menu. - // A proper fix is non-trivial so instead just close the menu. - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->isOpen()) - { - LLMenuGL::sMenuContainer->hideMenus(); - } - - //do text search - if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout")) - { - mSearchString.clear(); - } - mSearchTimer.reset(); - if (mSearchString.size() < 128) - { - mSearchString += uni_char; - } - search(getCurSelectedItem(), mSearchString, false); - - handled = true; - } - - return handled; -} - - -bool LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - mKeyboardSelection = false; - mSearchString.clear(); - - mParentPanel.get()->setFocus(true); - - LLEditMenuHandler::gEditMenuHandler = this; - - return LLView::handleMouseDown( x, y, mask ); -} - -bool LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, bool backward) -{ - // get first selected item - LLFolderViewItem* search_item = first_item; - - // make sure search string is upper case - std::string upper_case_string = search_string; - LLStringUtil::toUpper(upper_case_string); - - // if nothing selected, select first item in folder - if (!search_item) - { - // start from first item - search_item = getNextFromChild(NULL); - } - - // search over all open nodes for first substring match (with wrapping) - bool found = false; - LLFolderViewItem* original_search_item = search_item; - do - { - // wrap at end - if (!search_item) - { - if (backward) - { - search_item = getPreviousFromChild(NULL); - } - else - { - search_item = getNextFromChild(NULL); - } - if (!search_item || search_item == original_search_item) - { - break; - } - } - - std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); - LLStringUtil::toUpper(current_item_label); - S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); - if (!current_item_label.compare(0, search_string_length, upper_case_string)) - { - found = true; - break; - } - if (backward) - { - search_item = search_item->getPreviousOpenNode(); - } - else - { - search_item = search_item->getNextOpenNode(); - } - - } while(search_item != original_search_item); - - - if (found) - { - setSelection(search_item, false, true); - scrollToShowSelection(); - } - - return found; -} - -bool LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - // skip LLFolderViewFolder::handleDoubleClick() - return LLView::handleDoubleClick( x, y, mask ); -} - -bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - // all user operations move keyboard focus to inventory - // this way, we know when to stop auto-updating a search - mParentPanel.get()->setFocus(true); - - bool handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - S32 count = mSelectedItems.size(); - - LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); - if (!menu) - { - if (mCallbackRegistrar) - { - mCallbackRegistrar->pushScope(); - } - if (mEnableRegistrar) - { - mEnableRegistrar->pushScope(); - } - llassert(LLMenuGL::sMenuContainer != NULL); - menu = LLUICtrlFactory::getInstance()->createFromFile(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - if (mEnableRegistrar) - { - mEnableRegistrar->popScope(); - } - if (mCallbackRegistrar) - { - mCallbackRegistrar->popScope(); - } - } - - bool item_clicked{ false }; - for (const auto item : mSelectedItems) - { - item_clicked |= item->getRect().pointInRect(x, y); - } - if(!item_clicked && mSingleFolderMode) - { - clearSelection(); - } - bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if (menu && (mSingleFolderMode || (handled - && ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible - !hide_folder_menu) - { - if (mCallbackRegistrar) - { - mCallbackRegistrar->pushScope(); - } - if (mEnableRegistrar) - { - mEnableRegistrar->pushScope(); - } - - updateMenuOptions(menu); - - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - if (mEnableRegistrar) - { - mEnableRegistrar->popScope(); - } - if (mCallbackRegistrar) - { - mCallbackRegistrar->popScope(); - } - } - else - { - if (menu && menu->getVisible()) - { - menu->setVisible(false); - } - setSelection(NULL, false, true); - } - return handled; -} - -// Add "--no options--" if the menu is completely blank. -bool LLFolderView::addNoOptions(LLMenuGL* menu) const -{ - const std::string nooptions_str = "--no options--"; - LLView *nooptions_item = NULL; - - const LLView::child_list_t *list = menu->getChildList(); - for (LLView::child_list_t::const_iterator itor = list->begin(); - itor != list->end(); - ++itor) - { - LLView *menu_item = (*itor); - if (menu_item->getVisible()) - { - return false; - } - std::string name = menu_item->getName(); - if (menu_item->getName() == nooptions_str) - { - nooptions_item = menu_item; - } - } - if (nooptions_item) - { - nooptions_item->setVisible(true); - nooptions_item->setEnabled(false); - return true; - } - return false; -} - -bool LLFolderView::handleHover( S32 x, S32 y, MASK mask ) -{ - return LLView::handleHover( x, y, mask ); -} - -LLFolderViewItem* LLFolderView::getHoveredItem() const -{ - return dynamic_cast(mHoveredItem.get()); -} - -void LLFolderView::setHoveredItem(LLFolderViewItem* itemp) -{ - if (mHoveredItem.get() != itemp) - { - if (itemp) - mHoveredItem = itemp->getHandle(); - else - mHoveredItem.markDead(); - } -} - -bool LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - mDragAndDropThisFrame = true; - // have children handle it first - bool handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, - accept, tooltip_msg); - - // when drop is not handled by child, it should be handled - // by the folder which is the hierarchy root. - if (!handled) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - - return handled; -} - -void LLFolderView::deleteAllChildren() -{ - mRenamerTopLostSignalConnection.disconnect(); - if (mRenamer) - { - LLUI::getInstance()->removePopup(mRenamer); - } - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle.markDead(); - mScrollContainer = NULL; - mRenameItem = NULL; - mRenamer = NULL; - mStatusTextBox = NULL; - - clearSelection(); - LLView::deleteAllChildren(); -} - -void LLFolderView::scrollToShowSelection() -{ - if ( mSelectedItems.size() ) - { - mNeedsScroll = true; - } -} - -// If the parent is scroll container, scroll it to make the selection -// is maximally visible. -void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) -{ - if (!mScrollContainer) return; - - // don't scroll to items when mouse is being used to scroll/drag and drop - if (gFocusMgr.childHasMouseCapture(mScrollContainer)) - { - mNeedsScroll = false; - return; - } - - // if item exists and is in visible portion of parent folder... - if(item) - { - LLRect local_rect = item->getLocalRect(); - S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); - S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); - // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder - S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + item->getIconPad()) : local_rect.getHeight(); - - // get portion of item that we want to see... - LLRect item_local_rect = LLRect(item->getIndentation(), - local_rect.getHeight(), - //+40 is supposed to include few first characters - llmin(item->getLabelXPos() - item->getIndentation() + 40, local_rect.getWidth()), - llmax(0, local_rect.getHeight() - max_height_to_show)); - - LLRect item_doc_rect; - - item->localRectToOtherView(item_local_rect, &item_doc_rect, this); - - mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); - - } -} - -LLRect LLFolderView::getVisibleRect() -{ - S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); - S32 visible_width = (mScrollContainer ? mScrollContainer->getRect().getWidth() : 0); - LLRect visible_rect; - visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); - return visible_rect; -} - -bool LLFolderView::getShowSelectionContext() -{ - if (mShowSelectionContext) - { - return true; - } - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - return true; - } - return false; -} - -void LLFolderView::setShowSingleSelection(bool show) -{ - if (show != mShowSingleSelection) - { - mMultiSelectionFadeTimer.reset(); - mShowSingleSelection = show; - } -} - -static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory"); - -// Main idle routine -void LLFolderView::update() -{ - // If this is associated with the user's inventory, don't do anything - // until that inventory is loaded up. - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_INVENTORY); - - // If there's no model, the view is in suspended state (being deleted) and shouldn't be updated - if (getFolderViewModel() == NULL) - { - return; - } - - LLFolderViewFilter& filter_object = getFolderViewModel()->getFilter(); - - if (filter_object.isModified() && filter_object.isNotDefault() && mParentPanel.get()->getVisible()) - { - mNeedsAutoSelect = true; - } - - // Filter to determine visibility before arranging - filter(filter_object); - - // Clear the modified setting on the filter only if the filter finished after running the filter process - // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items - bool filter_modified = filter_object.isModified(); - if (filter_modified && (!filter_object.isTimedOut())) - { - filter_object.clearModified(); - } - - // automatically show matching items, and select first one if we had a selection - if (mNeedsAutoSelect) - { - // select new item only if a filtered item not currently selected and there was a selection - LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible()) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLSelectFirstFilteredItem functor; - applyFunctorRecursively(functor); - } - - // Open filtered folders for folder views with mAutoSelectOverride=true. - // Used by LLPlacesFolderView. - if (filter_object.showAllResults()) - { - // these are named variables to get around gcc not binding non-const references to rvalues - // and functor application is inherently non-const to allow for stateful functors - LLOpenFilteredFolders functor; - applyFunctorRecursively(functor); - } - - scrollToShowSelection(); - } - - bool filter_finished = mViewModel->contentsReady() - && (getViewModelItem()->passedFilter() - || ( getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration() - && !filter_modified)); - if (filter_finished - || gFocusMgr.childHasKeyboardFocus(mParentPanel.get()) - || gFocusMgr.childHasMouseCapture(mParentPanel.get())) - { - // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process - mNeedsAutoSelect = false; - } - - bool is_visible = isInVisibleChain() || mForceArrange; - - //Puts folders/items in proper positions - // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) - // It also handles the open/close folder animation - if ( is_visible ) - { - sanitizeSelection(); - if( needsArrange() ) - { - S32 height = 0; - S32 width = 0; - S32 total_height = arrange( &width, &height ); - notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); - } - } - - // during filtering process, try to pin selected item's location on screen - // this will happen when searching your inventory and when new items arrive - if (!filter_finished) - { - // calculate rectangle to pin item to at start of animated rearrange - if (!mPinningSelectedItem && !mSelectedItems.empty()) - { - // lets pin it! - mPinningSelectedItem = true; - - //Computes visible area - const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); - LLFolderViewItem* selected_item = mSelectedItems.back(); - - //Computes location of selected content, content outside visible area will be scrolled to using below code - LLRect item_rect; - selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); - - //Computes intersected region of the selected content and visible area - LLRect overlap_rect(item_rect); - overlap_rect.intersectWith(visible_content_rect); - - //Don't scroll when the selected content exists within the visible area - if (overlap_rect.getHeight() >= selected_item->getItemHeight()) - { - // then attempt to keep it in same place on screen - mScrollConstraintRect = item_rect; - mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); - } - //Scroll because the selected content is outside the visible area - else - { - // otherwise we just want it onscreen somewhere - LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - } - } - else - { - // stop pinning selected item after folders stop rearranging - if (!needsArrange()) - { - mPinningSelectedItem = false; - } - } - - LLRect constraint_rect; - if (mPinningSelectedItem) - { - // use last known constraint rect for pinned item - constraint_rect = mScrollConstraintRect; - } - else - { - // during normal use (page up/page down, etc), just try to fit item on screen - LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); - constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); - } - - if (mSelectedItems.size() && mNeedsScroll) - { - LLFolderViewItem* scroll_to_item = mSelectedItems.back(); - scrollToShowItem(scroll_to_item, constraint_rect); - // continue scrolling until animated layout change is done - bool selected_filter_finished = getRoot()->getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration(); - if (selected_filter_finished && scroll_to_item && scroll_to_item->getViewModelItem()) - { - selected_filter_finished = scroll_to_item->getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration(); - } - if (filter_finished && selected_filter_finished) - { - bool needs_arrange = needsArrange() || getRoot()->needsArrange(); - if (mParentFolder) - { - needs_arrange |= (bool)mParentFolder->needsArrange(); - } - if (!needs_arrange || !is_visible) - { - mNeedsScroll = false; - } - } - } - - if (mSelectedItems.size()) - { - LLFolderViewItem* item = mSelectedItems.back(); - // If the goal is to show renamer, don't callback untill - // item is visible or is no longer being scrolled to. - // Otherwise renamer will be instantly closed - // Todo: consider moving renamer out of selection callback - if (!mNeedsAutoRename || !mNeedsScroll || item->getVisible()) - { - if (mSignalSelectCallback) - { - //RN: we use keyboard focus as a proxy for user-explicit actions - bool take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); - mSelectSignal(mSelectedItems, take_keyboard_focus); - } - mSignalSelectCallback = false; - } - } - else - { - mSignalSelectCallback = false; - } -} - -void LLFolderView::dumpSelectionInformation() -{ - LL_INFOS() << "LLFolderView::dumpSelectionInformation()" << LL_NEWLINE - << "****************************************" << LL_ENDL; - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - LL_INFOS() << " " << (*item_it)->getName() << LL_ENDL; - } - LL_INFOS() << "****************************************" << LL_ENDL; -} - -void LLFolderView::updateRenamerPosition() -{ - if(mRenameItem) - { - // See also LLFolderViewItem::draw() - S32 x = mRenameItem->getLabelXPos(); - S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenameItem->localPointToScreen( x, y, &x, &y ); - screenPointToLocal( x, y, &x, &y ); - mRenamer->setOrigin( x, y ); - - LLRect scroller_rect(0, 0, (S32)LLUI::getInstance()->getWindowSize().mV[VX], 0); - if (mScrollContainer) - { - scroller_rect = mScrollContainer->getContentWindowRect(); - } - - S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; - mRenamer->reshape( width, height, true ); - } -} - -// Update visibility and availability (i.e. enabled/disabled) of context menu items. -void LLFolderView::updateMenuOptions(LLMenuGL* menu) -{ - const LLView::child_list_t *list = menu->getChildList(); - - LLView::child_list_t::const_iterator menu_itor; - for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) - { - (*menu_itor)->setVisible(false); - (*menu_itor)->pushVisible(true); - (*menu_itor)->setEnabled(true); - } - - // Successively filter out invalid options - U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); - U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; - for (selected_items_t::iterator item_itor = mSelectedItems.begin(); - item_itor != mSelectedItems.end(); - ++item_itor) - { - LLFolderViewItem* selected_item = (*item_itor); - selected_item->buildContextMenu(*menu, flags); - flags = multi_select_flag; - } - - if(mSingleFolderMode && (mSelectedItems.size() == 0)) - { - buildContextMenu(*menu, flags); - } - - // This adds a check for restrictions based on the entire - // selection set - for example, any one wearable may not push you - // over the limit, but all wearables together still might. - if (getFolderViewGroupedItemModel()) - { - getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); - } - - addNoOptions(menu); -} - -// Refresh the context menu (that is already shown). -void LLFolderView::updateMenu() -{ - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - if (menu && menu->getVisible()) - { - updateMenuOptions(menu); - menu->needsArrange(); // update menu height if needed - } -} - -bool LLFolderView::isFolderSelected() -{ - selected_items_t::iterator item_iter; - for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) - { - LLFolderViewFolder* folder = dynamic_cast(*item_iter); - if (folder != NULL) - { - return true; - } - } - return false; -} - -bool LLFolderView::selectFirstItem() -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();++iter) - { - LLFolderViewFolder* folder = (*iter ); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getNextFromChild(0,true); - if(itemp) - setSelection(itemp,false,true); - return true; - } - - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,false,true); - return true; - } - } - return false; -} -bool LLFolderView::selectLastItem() -{ - for(items_t::reverse_iterator iit = mItems.rbegin(); - iit != mItems.rend(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - if (itemp->getVisible()) - { - setSelection(itemp,false,true); - return true; - } - } - for (folders_t::reverse_iterator iter = mFolders.rbegin(); - iter != mFolders.rend();++iter) - { - LLFolderViewFolder* folder = (*iter); - if (folder->getVisible()) - { - LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); - if(itemp) - setSelection(itemp,false,true); - return true; - } - } - return false; -} - - -S32 LLFolderView::notify(const LLSD& info) -{ - if(info.has("action")) - { - std::string str_action = info["action"]; - if(str_action == "select_first") - { - setFocus(true); - selectFirstItem(); - scrollToShowSelection(); - return 1; - - } - else if(str_action == "select_last") - { - setFocus(true); - selectLastItem(); - scrollToShowSelection(); - return 1; - } - } - return 0; -} - - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- - -void LLFolderView::onRenamerLost() -{ - if (mRenamer && mRenamer->getVisible()) - { - mRenamer->setVisible(false); - - // will commit current name (which could be same as original name) - mRenamer->setFocus(false); - } - - if( mRenameItem ) - { - setSelection( mRenameItem, true ); - mRenameItem = NULL; - } -} - -LLFolderViewItem* LLFolderView::getNextUnselectedItem() -{ - LLFolderViewItem* last_item = *mSelectedItems.rbegin(); - LLFolderViewItem* new_selection = last_item->getNextOpenNode(false); - while(new_selection && new_selection->isSelected()) - { - new_selection = new_selection->getNextOpenNode(false); - } - if (!new_selection) - { - new_selection = last_item->getPreviousOpenNode(false); - while (new_selection && (new_selection->isInSelection())) - { - new_selection = new_selection->getPreviousOpenNode(false); - } - } - return new_selection; -} - -S32 LLFolderView::getItemHeight() const -{ - if(!hasVisibleChildren()) -{ - //We need to display status textbox, let's reserve some place for it - return llmax(0, mStatusTextBox->getTextPixelHeight()); -} - return 0; -} +/** + * @file llfolderview.cpp + * @brief Implementation of the folder view collection of classes. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * 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. + * + * 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. + * + * 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 + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfolderview.h" +#include "llfolderviewmodel.h" +#include "llclipboard.h" // *TODO: remove this once hack below gone. +#include "llkeyboard.h" +#include "lllineeditor.h" +#include "llmenugl.h" +#include "llpanel.h" +#include "llscrollcontainer.h" // hack to allow scrolling +#include "lltextbox.h" +#include "lltrans.h" +#include "llui.h" +#include "lluictrlfactory.h" + +// Linden library includes +#include "lldbstrings.h" +#include "llfocusmgr.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llrender.h" + +// Third-party library includes +#include + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +const S32 RENAME_HEIGHT_PAD = 1; +const S32 AUTO_OPEN_STACK_DEPTH = 16; + +const S32 MINIMUM_RENAMER_WIDTH = 80; + +// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. +const S32 STATUS_TEXT_HPAD = 6; +const S32 STATUS_TEXT_VPAD = 8; + +enum { + SIGNAL_NO_KEYBOARD_FOCUS = 1, + SIGNAL_KEYBOARD_FOCUS = 2 +}; + +F32 LLFolderView::sAutoOpenTime = 1.f; + +//--------------------------------------------------------------------------- + +// Tells all folders in a folderview to close themselves +// For efficiency, calls setOpenArrangeRecursively(). +// The calling function must then call: +// LLFolderView* root = getRoot(); +// if( root ) +// { +// root->arrange( NULL, NULL ); +// root->scrollToShowSelection(); +// } +// to patch things up. +class LLCloseAllFoldersFunctor : public LLFolderViewFunctor +{ +public: + LLCloseAllFoldersFunctor(bool close) { mOpen = !close; } + virtual ~LLCloseAllFoldersFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + + bool mOpen; +}; + + +void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) +{ + folder->setOpenArrangeRecursively(mOpen); +} + +// Do nothing. +void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) +{ } + +//--------------------------------------------------------------------------- + +void LLAllDescendentsPassedFilter::doFolder(LLFolderViewFolder* folder) +{ + mAllDescendentsPassedFilter &= (folder) && (folder->passedFilter()) && (folder->descendantsPassedFilter()); +} + +void LLAllDescendentsPassedFilter::doItem(LLFolderViewItem* item) +{ + mAllDescendentsPassedFilter &= (item) && (item->passedFilter()); +} + +///---------------------------------------------------------------------------- +/// Class LLFolderViewScrollContainer +///---------------------------------------------------------------------------- + +// virtual +const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const +{ + LLRect rect = LLRect::null; + if (mScrolledView) + { + LLFolderView* folder_view = dynamic_cast(mScrolledView); + if (folder_view) + { + S32 height = folder_view->getRect().getHeight(); + + rect = mScrolledView->getRect(); + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); + } + } + + return rect; +} + +LLFolderViewScrollContainer::LLFolderViewScrollContainer(const LLScrollContainer::Params& p) +: LLScrollContainer(p) +{} + +///---------------------------------------------------------------------------- +/// Class LLFolderView +///---------------------------------------------------------------------------- +LLFolderView::Params::Params() +: title("title"), + use_label_suffix("use_label_suffix"), + allow_multiselect("allow_multiselect", true), + allow_drag("allow_drag", true), + show_empty_message("show_empty_message", true), + suppress_folder_menu("suppress_folder_menu", false), + use_ellipses("use_ellipses", false), + options_menu("options_menu", "") +{ + folder_indentation = -4; +} + + +// Default constructor +LLFolderView::LLFolderView(const Params& p) +: LLFolderViewFolder(p), + mScrollContainer( NULL ), + mPopupMenuHandle(), + mMenuFileName(p.options_menu), + mAllowMultiSelect(p.allow_multiselect), + mAllowDrag(p.allow_drag), + mShowEmptyMessage(p.show_empty_message), + mShowFolderHierarchy(false), + mRenameItem( NULL ), + mNeedsScroll( false ), + mUseLabelSuffix(p.use_label_suffix), + mSuppressFolderMenu(p.suppress_folder_menu), + mPinningSelectedItem(false), + mNeedsAutoSelect( false ), + mAutoSelectOverride(false), + mNeedsAutoRename(false), + mShowSelectionContext(false), + mShowSingleSelection(false), + mArrangeGeneration(0), + mSignalSelectCallback(0), + mMinWidth(0), + mDragAndDropThisFrame(false), + mCallbackRegistrar(NULL), + mEnableRegistrar(NULL), + mUseEllipses(p.use_ellipses), + mDraggingOverItem(NULL), + mStatusTextBox(NULL), + mShowItemLinkOverlays(p.show_item_link_overlays), + mViewModel(p.view_model), + mGroupedItemModel(p.grouped_item_model), + mForceArrange(false), + mSingleFolderMode(false) +{ + LLPanel* panel = p.parent_panel; + mParentPanel = panel->getHandle(); + mViewModel->setFolderView(this); + mRoot = this; + + LLRect rect = p.rect; + LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); + setRect( rect ); + reshape(rect.getWidth(), rect.getHeight()); + mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); + mKeyboardSelection = false; + mIndentation = getParentFolder() ? getParentFolder()->getIndentation() + mLocalIndentation : 0; + + //clear label + // go ahead and render root folder as usual + // just make sure the label ("Inventory Folder") never shows up + mLabel = LLStringUtil::null; + + // Escape is handled by reverting the rename, not commiting it (default behavior) + LLLineEditor::Params params; + params.name("ren"); + params.rect(rect); + params.font(getLabelFontForStyle(LLFontGL::NORMAL)); + params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); + params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); + params.prevalidator(&LLTextValidate::validateASCIIPrintableNoPipe); + params.commit_on_focus_lost(true); + params.visible(false); + mRenamer = LLUICtrlFactory::create (params); + addChild(mRenamer); + + // Textbox + LLTextBox::Params text_p; + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + //mIconPad, mTextPad are set in folder_view_item.xml + LLRect new_r = LLRect(rect.mLeft + mIconPad, + rect.mTop - mTextPad, + rect.mRight, + rect.mTop - mTextPad - font->getLineHeight()); + text_p.rect(new_r); + text_p.name(std::string(p.name)); + text_p.font(font); + text_p.visible(false); + text_p.parse_urls(true); + text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 + // set text padding the same as in People panel. EXT-7047, EXT-4837 + text_p.h_pad(STATUS_TEXT_HPAD); + text_p.v_pad(STATUS_TEXT_VPAD); + mStatusTextBox = LLUICtrlFactory::create (text_p); + mStatusTextBox->setFollowsLeft(); + mStatusTextBox->setFollowsTop(); + addChild(mStatusTextBox); + + mViewModelItem->openItem(); + + mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited. +} + +// Destroys the object +LLFolderView::~LLFolderView( void ) +{ + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + // instead of using closeRenamer remove it directly, + // since it might already be hidden + LLUI::getInstance()->removePopup(mRenamer); + } + + // The release focus call can potentially call the + // scrollcontainer, which can potentially be called with a partly + // destroyed scollcontainer. Just null it out here, and no worries + // about calling into the invalid scroll container. + // Same with the renamer. + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle.markDead(); + + mAutoOpenItems.removeAllNodes(); + clearSelection(); + mItems.clear(); + mFolders.clear(); + + //mViewModel->setFolderView(NULL); + mViewModel = NULL; +} + +bool LLFolderView::canFocusChildren() const +{ + return false; +} + +void LLFolderView::addFolder( LLFolderViewFolder* folder) +{ + LLFolderViewFolder::addFolder(folder); +} + +void LLFolderView::closeAllFolders() +{ + // Close all the folders + setOpenArrangeRecursively(false, LLFolderViewFolder::RECURSE_DOWN); + arrangeAll(); +} + +void LLFolderView::openTopLevelFolders() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpen(true); + } +} + +// This view grows and shrinks to enclose all of its children items and folders. +// *width should be 0 +// conform show folder state works +S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) + { + mMinWidth = 0; + S32 target_height; + + LLFolderViewFolder::arrange(&mMinWidth, &target_height); + + LLRect scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); + + LLRect new_scroll_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) + { + reshape( llmax(scroll_rect.getWidth(), mMinWidth), ll_round(mCurHeight) ); + } + + // move item renamer text field to item's new position + updateRenamerPosition(); + + return ll_round(mTargetHeight); +} + +void LLFolderView::filter( LLFolderViewFilter& filter ) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + const S32 TIME_VISIBLE = 10; // in milliseconds + const S32 TIME_INVISIBLE = 1; + filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? TIME_VISIBLE : TIME_INVISIBLE), 1, 100)); + + // Note: we filter the model, not the view + getViewModelItem()->filter(filter); +} + +void LLFolderView::reshape(S32 width, S32 height, bool called_from_parent) +{ + LLRect scroll_rect; + if (mScrollContainer) + { + LLView::reshape(width, height, called_from_parent); + scroll_rect = mScrollContainer->getContentWindowRect(); + } + width = llmax(mMinWidth, scroll_rect.getWidth()); + height = llmax(ll_round(mCurHeight), scroll_rect.getHeight()); + + // Restrict width within scroll container's width + if (mUseEllipses && mScrollContainer) + { + width = scroll_rect.getWidth(); + } + LLView::reshape(width, height, called_from_parent); + mReshapeSignal(mSelectedItems, false); +} + +void LLFolderView::addToSelectionList(LLFolderViewItem* item) +{ + if (item->isSelected()) + { + removeFromSelectionList(item); + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(false); + } + item->setIsCurSelection(true); + mSelectedItems.push_back(item); +} + +void LLFolderView::removeFromSelectionList(LLFolderViewItem* item) +{ + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(false); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();) + { + if (*item_iter == item) + { + item_iter = mSelectedItems.erase(item_iter); + } + else + { + ++item_iter; + } + } + if (mSelectedItems.size()) + { + mSelectedItems.back()->setIsCurSelection(true); + } +} + +LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) +{ + if(mSelectedItems.size()) + { + LLFolderViewItem* itemp = mSelectedItems.back(); + llassert(itemp->getIsCurSelection()); + return itemp; + } + return NULL; +} + +LLFolderView::selected_items_t& LLFolderView::getSelectedItems( void ) +{ + return mSelectedItems; +} + +// Record the selected item and pass it down the hierachy. +bool LLFolderView::setSelection(LLFolderViewItem* selection, bool openitem, + bool take_keyboard_focus) +{ + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + + if( selection == this ) + { + return false; + } + + if( selection && take_keyboard_focus) + { + mParentPanel.get()->setFocus(true); + } + + // clear selection down here because change of keyboard focus can potentially + // affect selection + clearSelection(); + + if(selection) + { + addToSelectionList(selection); + } + + bool rv = LLFolderViewFolder::setSelection(selection, openitem, take_keyboard_focus); + if(openitem && selection) + { + selection->getParentFolder()->requestArrange(); + } + + llassert(mSelectedItems.size() <= 1); + + return rv; +} + +bool LLFolderView::changeSelection(LLFolderViewItem* selection, bool selected) +{ + bool rv = false; + + // can't select root folder + if(!selection || selection == this) + { + return false; + } + + if (!mAllowMultiSelect) + { + clearSelection(); + } + + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + if (*item_iter == selection) + { + break; + } + } + + bool on_list = (item_iter != mSelectedItems.end()); + + if(selected && !on_list) + { + addToSelectionList(selection); + } + if(!selected && on_list) + { + removeFromSelectionList(selection); + } + + rv = LLFolderViewFolder::changeSelection(selection, selected); + + mSignalSelectCallback = SIGNAL_KEYBOARD_FOCUS; + + return rv; +} + +void LLFolderView::sanitizeSelection() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); + + std::vector items_to_remove; + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + LLFolderViewItem* item = *item_iter; + + // ensure that each ancestor is open and potentially passes filtering + bool visible = false; + if(item->getViewModelItem() != NULL) + { + visible = item->getViewModelItem()->potentiallyVisible(); // initialize from filter state for this item + } + // modify with parent open and filters states + LLFolderViewFolder* parent_folder = item->getParentFolder(); + // Move up through parent folders and see what's visible + while(parent_folder) + { + visible = visible && parent_folder->isOpen() && parent_folder->getViewModelItem()->potentiallyVisible(); + parent_folder = parent_folder->getParentFolder(); + } + + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) + { + items_to_remove.push_back(item); + } + + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + { + LLFolderViewItem* other_item = *other_item_iter; + for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder == item) + { + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; + } + } + } + + // Don't allow invisible items (such as root folders) to be selected. + if (item == getRoot()) + { + items_to_remove.push_back(item); + } + } + + std::vector::iterator item_it; + for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) + { + changeSelection(*item_it, false); // toggle selection (also removes from list) + } + + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) + { + // ...select first available parent of original selection + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) + { + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder->getViewModelItem() && parent_folder->getViewModelItem()->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } + } + } + else + { + new_selection = NULL; + } + + if (new_selection) + { + setSelection(new_selection, false, false); + } + } +} + +void LLFolderView::clearSelection() +{ + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) + { + (*item_it)->setUnselected(); + } + + mSelectedItems.clear(); + mNeedsScroll = false; +} + +std::set LLFolderView::getSelectionList() const +{ + std::set selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); + return selection; +} + +bool LLFolderView::startDrag() +{ + std::vector selected_items; + selected_items_t::iterator item_it; + + if (!mSelectedItems.empty()) + { + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + selected_items.push_back((*item_it)->getViewModelItem()); + } + + return getFolderViewModel()->startDrag(selected_items); + } + return false; +} + +void LLFolderView::commitRename( const LLSD& data ) +{ + finishRenamingItem(); + arrange( NULL, NULL ); + +} + +void LLFolderView::draw() +{ + //LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + // if cursor has moved off of me during drag and drop + // close all auto opened folders + if (!mDragAndDropThisFrame) + { + closeAutoOpenedFolders(); + } + + static LLCachedControl type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f); + if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size()) + { + mSearchString.clear(); + } + + if (hasVisibleChildren()) + { + mStatusTextBox->setVisible( false ); + } + else if (mShowEmptyMessage) + { + mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty())); + mStatusTextBox->setVisible( true ); + + // firstly reshape message textbox with current size. This is necessary to + // LLTextBox::getTextPixelHeight works properly + const LLRect local_rect = getLocalRect(); + mStatusTextBox->setShape(local_rect); + + // get preferable text height... + S32 pixel_height = mStatusTextBox->getTextPixelHeight(); + bool height_changed = (local_rect.getHeight() < pixel_height); + if (height_changed) + { + // ... if it does not match current height, lets rearrange current view. + // This will indirectly call ::arrange and reshape of the status textbox. + // We should call this method to also notify parent about required rect. + // See EXT-7564, EXT-7047. + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + + LLUI::popMatrix(); + LLUI::pushMatrix(); + LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom); + } + } + + if (mRenameItem + && mRenamer + && mRenamer->getVisible() + && !getVisibleRect().overlaps(mRenamer->getRect())) + { + // renamer is not connected to the item we are renaming in any form so manage it manually + // TODO: consider stopping on any scroll action instead of when out of visible area + LL_DEBUGS("Inventory") << "Renamer out of bounds, hiding" << LL_ENDL; + finishRenamingItem(); + } + + // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, + // and arrow for the root folder + LLView::draw(); + + mDragAndDropThisFrame = false; +} + +void LLFolderView::finishRenamingItem( void ) +{ + if(!mRenamer) + { + return; + } + if( mRenameItem ) + { + mRenameItem->rename( mRenamer->getText() ); + } + + closeRenamer(); + + // This is moved to an inventory observer in llinventorybridge.cpp, to handle updating after operation completed in AISv3 (SH-4611). + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. + //scrollToShowSelection(); +} + +void LLFolderView::closeRenamer( void ) +{ + if (mRenamer && mRenamer->getVisible()) + { + // Triggers onRenamerLost() that actually closes the renamer. + LLUI::getInstance()->removePopup(mRenamer); + } +} + +void LLFolderView::removeSelectedItems() +{ + if(getVisible() && getEnabled()) + { + // just in case we're removing the renaming item. + mRenameItem = NULL; + + // create a temporary structure which we will use to remove + // items, since the removal will futz with internal data + // structures. + std::vector items; + S32 count = mSelectedItems.size(); + if(count <= 0) return; + LLFolderViewItem* item = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + item = *item_it; + if (item && item->isRemovable()) + { + items.push_back(item); + } + else + { + LL_DEBUGS() << "Cannot delete " << item->getName() << LL_ENDL; + return; + } + } + + // iterate through the new container. + count = items.size(); + LLUUID new_selection_id; + LLFolderViewItem* item_to_select = getNextUnselectedItem(); + + if(count == 1) + { + LLFolderViewItem* item_to_delete = items[0]; + LLFolderViewFolder* parent = item_to_delete->getParentFolder(); + if(parent) + { + if (item_to_delete->remove()) + { + // change selection on successful delete + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); + } + } + arrangeAll(); + } + else if (count > 1) + { + std::vector listeners; + LLFolderViewModelItem* listener; + + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); + + listeners.reserve(count); + for(S32 i = 0; i < count; ++i) + { + listener = items[i]->getViewModelItem(); + if(listener && (std::find(listeners.begin(), listeners.end(), listener) == listeners.end())) + { + listeners.push_back(listener); + } + } + listener = static_cast(listeners.at(0)); + if(listener) + { + listener->removeBatch(listeners); + } + } + arrangeAll(); + scrollToShowSelection(); + } +} + +void LLFolderView::autoOpenItem( LLFolderViewFolder* item ) +{ + if ((mAutoOpenItems.check() == item) || + (mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH) || + item->isOpen()) + { + return; + } + + // close auto-opened folders + LLFolderViewFolder* close_item = mAutoOpenItems.check(); + while (close_item && close_item != item->getParentFolder()) + { + mAutoOpenItems.pop(); + close_item->setOpenArrangeRecursively(false); + close_item = mAutoOpenItems.check(); + } + + item->requestArrange(); + + mAutoOpenItems.push(item); + + item->setOpen(true); + if(!item->isSingleFolderMode()) + { + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0); + scrollToShowItem(item, constraint_rect); + } +} + +void LLFolderView::closeAutoOpenedFolders() +{ + while (mAutoOpenItems.check()) + { + LLFolderViewFolder* close_item = mAutoOpenItems.pop(); + close_item->setOpen(false); + } + + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = NULL; + mAutoOpenTimer.stop(); +} + +bool LLFolderView::autoOpenTest(LLFolderViewFolder* folder) +{ + if (folder && mAutoOpenCandidate == folder) + { + if (mAutoOpenTimer.getStarted()) + { + if (!mAutoOpenCandidate->isOpen()) + { + mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f)); + } + if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime) + { + autoOpenItem(folder); + mAutoOpenTimer.stop(); + return true; + } + } + return false; + } + + // otherwise new candidate, restart timer + if (mAutoOpenCandidate) + { + mAutoOpenCandidate->setAutoOpenCountdown(0.f); + } + mAutoOpenCandidate = folder; + mAutoOpenTimer.start(); + return false; +} + +bool LLFolderView::canCopy() const +{ + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return false; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + if (!item->getViewModelItem()->isItemCopyable()) + { + return false; + } + } + return true; +} + +// copy selected item +void LLFolderView::copy() +{ + // *NOTE: total hack to clear the inventory clipboard + LLClipboard::instance().reset(); + S32 count = mSelectedItems.size(); + if(getVisible() && getEnabled() && (count > 0)) + { + LLFolderViewModelItem* listener = NULL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + listener = (*item_it)->getViewModelItem(); + if(listener) + { + listener->copyToClipboard(); + } + } + } + mSearchString.clear(); +} + +bool LLFolderView::canCut() const +{ + if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0))) + { + return false; + } + + for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + const LLFolderViewItem* item = *selected_it; + const LLFolderViewModelItem* listener = item->getViewModelItem(); + + if (!listener || !listener->isItemRemovable()) + { + return false; + } + } + return true; +} + +void LLFolderView::cut() +{ + // clear the inventory clipboard + LLClipboard::instance().reset(); + if(getVisible() && getEnabled() && (mSelectedItems.size() > 0)) + { + // Find out which item will be selected once the selection will be cut + LLFolderViewItem* item_to_select = getNextUnselectedItem(); + + // Get the selection: removeItem() modified mSelectedItems and makes iterating on it unwise + std::set inventory_selected = getSelectionList(); + + // Move each item to the clipboard and out of their folder + for (std::set::iterator item_it = inventory_selected.begin(); item_it != inventory_selected.end(); ++item_it) + { + LLFolderViewItem* item_to_cut = *item_it; + LLFolderViewModelItem* listener = item_to_cut->getViewModelItem(); + if (listener) + { + listener->cutToClipboard(); + } + } + + // Update the selection + setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); + } + mSearchString.clear(); +} + +bool LLFolderView::canPaste() const +{ + if (mSelectedItems.empty()) + { + return false; + } + + if(getVisible() && getEnabled()) + { + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); ++item_it) + { + // *TODO: only check folders and parent folders of items + const LLFolderViewItem* item = (*item_it); + const LLFolderViewModelItem* listener = item->getViewModelItem(); + if(!listener || !listener->isClipboardPasteable()) + { + const LLFolderViewFolder* folderp = item->getParentFolder(); + listener = folderp->getViewModelItem(); + if (!listener || !listener->isClipboardPasteable()) + { + return false; + } + } + } + return true; + } + return false; +} + +// paste selected item +void LLFolderView::paste() +{ + if(getVisible() && getEnabled()) + { + // find set of unique folders to paste into + std::set folder_set; + + selected_items_t::iterator selected_it; + for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) + { + LLFolderViewItem* item = *selected_it; + LLFolderViewFolder* folder = dynamic_cast(item); + if (folder == NULL) + { + folder = item->getParentFolder(); + } + folder_set.insert(folder); + } + + std::set::iterator set_iter; + for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) + { + LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); + if(listener && listener->isClipboardPasteable()) + { + listener->pasteFromClipboard(); + } + } + } + mSearchString.clear(); +} + +// public rename functionality - can only start the process +void LLFolderView::startRenamingSelectedItem( void ) +{ + LL_DEBUGS("Inventory") << "Starting inventory renamer" << LL_ENDL; + + // make sure selection is visible + scrollToShowSelection(); + + S32 count = mSelectedItems.size(); + LLFolderViewItem* item = NULL; + if(count > 0) + { + item = mSelectedItems.front(); + } + if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && + item->getViewModelItem()->isItemRenameable()) + { + mRenameItem = item; + + updateRenamerPosition(); + + + mRenamer->setText(item->getName()); + mRenamer->selectAll(); + mRenamer->setVisible( true ); + // set focus will fail unless item is visible + mRenamer->setFocus( true ); + if (!mRenamerTopLostSignalConnection.connected()) + { + mRenamerTopLostSignalConnection = mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + } + LLUI::getInstance()->addPopup(mRenamer); + } +} + +bool LLFolderView::handleKeyHere( KEY key, MASK mask ) +{ + bool handled = false; + + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + switch( key ) + { + case KEY_F2: + mSearchString.clear(); + startRenamingSelectedItem(); + handled = true; + break; + + case KEY_RETURN: + if (mask == MASK_NONE) + { + if( mRenameItem && mRenamer->getVisible() ) + { + finishRenamingItem(); + mSearchString.clear(); + handled = true; + } + } + break; + + case KEY_ESCAPE: + if( mRenameItem && mRenamer->getVisible() ) + { + closeRenamer(); + handled = true; + } + mSearchString.clear(); + break; + + case KEY_PAGE_UP: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->pageUp(30); + } + handled = true; + break; + + case KEY_PAGE_DOWN: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->pageDown(30); + } + handled = true; + break; + + case KEY_HOME: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->goToTop(); + } + handled = true; + break; + + case KEY_END: + mSearchString.clear(); + if (mScrollContainer) + { + mScrollContainer->goToBottom(); + } + break; + + case KEY_DOWN: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + bool shift_select = mask & MASK_SHIFT; + // don't shift select down to children of folders (they are implicitly selected through parent) + LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); + + if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) + { + setSelection(last_selected, false, true); + mKeyboardSelection = true; + } + + if (shift_select) + { + if (next) + { + if (next->isSelected()) + { + // shrink selection + changeSelection(last_selected, false); + } + else if (last_selected->getParentFolder() == next->getParentFolder()) + { + // grow selection + changeSelection(next, true); + } + } + } + else + { + if( next ) + { + if (next == last_selected) + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return true; + } + return false; + } + setSelection( next, false, true ); + } + else + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return true; + } + return false; + } + } + scrollToShowSelection(); + mSearchString.clear(); + handled = true; + } + break; + + case KEY_UP: + if((mSelectedItems.size() > 0) && mScrollContainer) + { + LLFolderViewItem* last_selected = mSelectedItems.back(); + bool shift_select = mask & MASK_SHIFT; + // don't shift select down to children of folders (they are implicitly selected through parent) + LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select); + + if (!mKeyboardSelection || (!shift_select && prev == this)) + { + setSelection(last_selected, false, true); + mKeyboardSelection = true; + } + + if (shift_select) + { + if (prev) + { + if (prev->isSelected()) + { + // shrink selection + changeSelection(last_selected, false); + } + else if (last_selected->getParentFolder() == prev->getParentFolder()) + { + // grow selection + changeSelection(prev, true); + } + } + } + else + { + if( prev ) + { + if (prev == this) + { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + { + clearSelection(); + return true; + } + + return false; + } + setSelection( prev, false, true ); + } + } + scrollToShowSelection(); + mSearchString.clear(); + + handled = true; + } + break; + + case KEY_RIGHT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + last_selected->setOpen( true ); + mSearchString.clear(); + handled = true; + } + break; + + case KEY_LEFT: + if(mSelectedItems.size()) + { + LLFolderViewItem* last_selected = getCurSelectedItem(); + if(last_selected && last_selected->isSingleFolderMode()) + { + handled = false; + break; + } + LLFolderViewItem* parent_folder = last_selected->getParentFolder(); + if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) + { + setSelection(parent_folder, false, true); + } + else + { + last_selected->setOpen( false ); + } + mSearchString.clear(); + scrollToShowSelection(); + handled = true; + } + break; + } + + return handled; +} + + +bool LLFolderView::handleUnicodeCharHere(llwchar uni_char) +{ + if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL + { + return false; + } + + if (uni_char > 0x7f) + { + LL_WARNS() << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << LL_ENDL; + return false; + } + + bool handled = false; + if (mParentPanel.get()->hasFocus()) + { + // SL-51858: Key presses are not being passed to the Popup menu. + // A proper fix is non-trivial so instead just close the menu. + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->isOpen()) + { + LLMenuGL::sMenuContainer->hideMenus(); + } + + //do text search + if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout")) + { + mSearchString.clear(); + } + mSearchTimer.reset(); + if (mSearchString.size() < 128) + { + mSearchString += uni_char; + } + search(getCurSelectedItem(), mSearchString, false); + + handled = true; + } + + return handled; +} + + +bool LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + mKeyboardSelection = false; + mSearchString.clear(); + + mParentPanel.get()->setFocus(true); + + LLEditMenuHandler::gEditMenuHandler = this; + + return LLView::handleMouseDown( x, y, mask ); +} + +bool LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, bool backward) +{ + // get first selected item + LLFolderViewItem* search_item = first_item; + + // make sure search string is upper case + std::string upper_case_string = search_string; + LLStringUtil::toUpper(upper_case_string); + + // if nothing selected, select first item in folder + if (!search_item) + { + // start from first item + search_item = getNextFromChild(NULL); + } + + // search over all open nodes for first substring match (with wrapping) + bool found = false; + LLFolderViewItem* original_search_item = search_item; + do + { + // wrap at end + if (!search_item) + { + if (backward) + { + search_item = getPreviousFromChild(NULL); + } + else + { + search_item = getNextFromChild(NULL); + } + if (!search_item || search_item == original_search_item) + { + break; + } + } + + std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); + LLStringUtil::toUpper(current_item_label); + S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); + if (!current_item_label.compare(0, search_string_length, upper_case_string)) + { + found = true; + break; + } + if (backward) + { + search_item = search_item->getPreviousOpenNode(); + } + else + { + search_item = search_item->getNextOpenNode(); + } + + } while(search_item != original_search_item); + + + if (found) + { + setSelection(search_item, false, true); + scrollToShowSelection(); + } + + return found; +} + +bool LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + // skip LLFolderViewFolder::handleDoubleClick() + return LLView::handleDoubleClick( x, y, mask ); +} + +bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + // all user operations move keyboard focus to inventory + // this way, we know when to stop auto-updating a search + mParentPanel.get()->setFocus(true); + + bool handled = childrenHandleRightMouseDown(x, y, mask) != NULL; + S32 count = mSelectedItems.size(); + + LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); + if (!menu) + { + if (mCallbackRegistrar) + { + mCallbackRegistrar->pushScope(); + } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); + } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } + if (mCallbackRegistrar) + { + mCallbackRegistrar->popScope(); + } + } + + bool item_clicked{ false }; + for (const auto item : mSelectedItems) + { + item_clicked |= item->getRect().pointInRect(x, y); + } + if(!item_clicked && mSingleFolderMode) + { + clearSelection(); + } + bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); + if (menu && (mSingleFolderMode || (handled + && ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible + !hide_folder_menu) + { + if (mCallbackRegistrar) + { + mCallbackRegistrar->pushScope(); + } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } + + updateMenuOptions(menu); + + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } + if (mCallbackRegistrar) + { + mCallbackRegistrar->popScope(); + } + } + else + { + if (menu && menu->getVisible()) + { + menu->setVisible(false); + } + setSelection(NULL, false, true); + } + return handled; +} + +// Add "--no options--" if the menu is completely blank. +bool LLFolderView::addNoOptions(LLMenuGL* menu) const +{ + const std::string nooptions_str = "--no options--"; + LLView *nooptions_item = NULL; + + const LLView::child_list_t *list = menu->getChildList(); + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + if (menu_item->getVisible()) + { + return false; + } + std::string name = menu_item->getName(); + if (menu_item->getName() == nooptions_str) + { + nooptions_item = menu_item; + } + } + if (nooptions_item) + { + nooptions_item->setVisible(true); + nooptions_item->setEnabled(false); + return true; + } + return false; +} + +bool LLFolderView::handleHover( S32 x, S32 y, MASK mask ) +{ + return LLView::handleHover( x, y, mask ); +} + +LLFolderViewItem* LLFolderView::getHoveredItem() const +{ + return dynamic_cast(mHoveredItem.get()); +} + +void LLFolderView::setHoveredItem(LLFolderViewItem* itemp) +{ + if (mHoveredItem.get() != itemp) + { + if (itemp) + mHoveredItem = itemp->getHandle(); + else + mHoveredItem.markDead(); + } +} + +bool LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + mDragAndDropThisFrame = true; + // have children handle it first + bool handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + accept, tooltip_msg); + + // when drop is not handled by child, it should be handled + // by the folder which is the hierarchy root. + if (!handled) + { + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + return handled; +} + +void LLFolderView::deleteAllChildren() +{ + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + LLUI::getInstance()->removePopup(mRenamer); + } + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle.markDead(); + mScrollContainer = NULL; + mRenameItem = NULL; + mRenamer = NULL; + mStatusTextBox = NULL; + + clearSelection(); + LLView::deleteAllChildren(); +} + +void LLFolderView::scrollToShowSelection() +{ + if ( mSelectedItems.size() ) + { + mNeedsScroll = true; + } +} + +// If the parent is scroll container, scroll it to make the selection +// is maximally visible. +void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect) +{ + if (!mScrollContainer) return; + + // don't scroll to items when mouse is being used to scroll/drag and drop + if (gFocusMgr.childHasMouseCapture(mScrollContainer)) + { + mNeedsScroll = false; + return; + } + + // if item exists and is in visible portion of parent folder... + if(item) + { + LLRect local_rect = item->getLocalRect(); + S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); + S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + item->getIconPad()) : local_rect.getHeight(); + + // get portion of item that we want to see... + LLRect item_local_rect = LLRect(item->getIndentation(), + local_rect.getHeight(), + //+40 is supposed to include few first characters + llmin(item->getLabelXPos() - item->getIndentation() + 40, local_rect.getWidth()), + llmax(0, local_rect.getHeight() - max_height_to_show)); + + LLRect item_doc_rect; + + item->localRectToOtherView(item_local_rect, &item_doc_rect, this); + + mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect ); + + } +} + +LLRect LLFolderView::getVisibleRect() +{ + S32 visible_height = (mScrollContainer ? mScrollContainer->getRect().getHeight() : 0); + S32 visible_width = (mScrollContainer ? mScrollContainer->getRect().getWidth() : 0); + LLRect visible_rect; + visible_rect.setLeftTopAndSize(-getRect().mLeft, visible_height - getRect().mBottom, visible_width, visible_height); + return visible_rect; +} + +bool LLFolderView::getShowSelectionContext() +{ + if (mShowSelectionContext) + { + return true; + } + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + return true; + } + return false; +} + +void LLFolderView::setShowSingleSelection(bool show) +{ + if (show != mShowSingleSelection) + { + mMultiSelectionFadeTimer.reset(); + mShowSingleSelection = show; + } +} + +static LLTrace::BlockTimerStatHandle FTM_INVENTORY("Inventory"); + +// Main idle routine +void LLFolderView::update() +{ + // If this is associated with the user's inventory, don't do anything + // until that inventory is loaded up. + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_INVENTORY); + + // If there's no model, the view is in suspended state (being deleted) and shouldn't be updated + if (getFolderViewModel() == NULL) + { + return; + } + + LLFolderViewFilter& filter_object = getFolderViewModel()->getFilter(); + + if (filter_object.isModified() && filter_object.isNotDefault() && mParentPanel.get()->getVisible()) + { + mNeedsAutoSelect = true; + } + + // Filter to determine visibility before arranging + filter(filter_object); + + // Clear the modified setting on the filter only if the filter finished after running the filter process + // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items + bool filter_modified = filter_object.isModified(); + if (filter_modified && (!filter_object.isTimedOut())) + { + filter_object.clearModified(); + } + + // automatically show matching items, and select first one if we had a selection + if (mNeedsAutoSelect) + { + // select new item only if a filtered item not currently selected and there was a selection + LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); + if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible()) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLSelectFirstFilteredItem functor; + applyFunctorRecursively(functor); + } + + // Open filtered folders for folder views with mAutoSelectOverride=true. + // Used by LLPlacesFolderView. + if (filter_object.showAllResults()) + { + // these are named variables to get around gcc not binding non-const references to rvalues + // and functor application is inherently non-const to allow for stateful functors + LLOpenFilteredFolders functor; + applyFunctorRecursively(functor); + } + + scrollToShowSelection(); + } + + bool filter_finished = mViewModel->contentsReady() + && (getViewModelItem()->passedFilter() + || ( getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration() + && !filter_modified)); + if (filter_finished + || gFocusMgr.childHasKeyboardFocus(mParentPanel.get()) + || gFocusMgr.childHasMouseCapture(mParentPanel.get())) + { + // finishing the filter process, giving focus to the folder view, or dragging the scrollbar all stop the auto select process + mNeedsAutoSelect = false; + } + + bool is_visible = isInVisibleChain() || mForceArrange; + + //Puts folders/items in proper positions + // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) + // It also handles the open/close folder animation + if ( is_visible ) + { + sanitizeSelection(); + if( needsArrange() ) + { + S32 height = 0; + S32 width = 0; + S32 total_height = arrange( &width, &height ); + notifyParent(LLSD().with("action", "size_changes").with("height", total_height)); + } + } + + // during filtering process, try to pin selected item's location on screen + // this will happen when searching your inventory and when new items arrive + if (!filter_finished) + { + // calculate rectangle to pin item to at start of animated rearrange + if (!mPinningSelectedItem && !mSelectedItems.empty()) + { + // lets pin it! + mPinningSelectedItem = true; + + //Computes visible area + const LLRect visible_content_rect = (mScrollContainer ? mScrollContainer->getVisibleContentRect() : LLRect()); + LLFolderViewItem* selected_item = mSelectedItems.back(); + + //Computes location of selected content, content outside visible area will be scrolled to using below code + LLRect item_rect; + selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this); + + //Computes intersected region of the selected content and visible area + LLRect overlap_rect(item_rect); + overlap_rect.intersectWith(visible_content_rect); + + //Don't scroll when the selected content exists within the visible area + if (overlap_rect.getHeight() >= selected_item->getItemHeight()) + { + // then attempt to keep it in same place on screen + mScrollConstraintRect = item_rect; + mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom); + } + //Scroll because the selected content is outside the visible area + else + { + // otherwise we just want it onscreen somewhere + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + } + } + else + { + // stop pinning selected item after folders stop rearranging + if (!needsArrange()) + { + mPinningSelectedItem = false; + } + } + + LLRect constraint_rect; + if (mPinningSelectedItem) + { + // use last known constraint rect for pinned item + constraint_rect = mScrollConstraintRect; + } + else + { + // during normal use (page up/page down, etc), just try to fit item on screen + LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect()); + constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + } + + if (mSelectedItems.size() && mNeedsScroll) + { + LLFolderViewItem* scroll_to_item = mSelectedItems.back(); + scrollToShowItem(scroll_to_item, constraint_rect); + // continue scrolling until animated layout change is done + bool selected_filter_finished = getRoot()->getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration(); + if (selected_filter_finished && scroll_to_item && scroll_to_item->getViewModelItem()) + { + selected_filter_finished = scroll_to_item->getViewModelItem()->getLastFilterGeneration() >= filter_object.getFirstSuccessGeneration(); + } + if (filter_finished && selected_filter_finished) + { + bool needs_arrange = needsArrange() || getRoot()->needsArrange(); + if (mParentFolder) + { + needs_arrange |= (bool)mParentFolder->needsArrange(); + } + if (!needs_arrange || !is_visible) + { + mNeedsScroll = false; + } + } + } + + if (mSelectedItems.size()) + { + LLFolderViewItem* item = mSelectedItems.back(); + // If the goal is to show renamer, don't callback untill + // item is visible or is no longer being scrolled to. + // Otherwise renamer will be instantly closed + // Todo: consider moving renamer out of selection callback + if (!mNeedsAutoRename || !mNeedsScroll || item->getVisible()) + { + if (mSignalSelectCallback) + { + //RN: we use keyboard focus as a proxy for user-explicit actions + bool take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS); + mSelectSignal(mSelectedItems, take_keyboard_focus); + } + mSignalSelectCallback = false; + } + } + else + { + mSignalSelectCallback = false; + } +} + +void LLFolderView::dumpSelectionInformation() +{ + LL_INFOS() << "LLFolderView::dumpSelectionInformation()" << LL_NEWLINE + << "****************************************" << LL_ENDL; + selected_items_t::iterator item_it; + for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + { + LL_INFOS() << " " << (*item_it)->getName() << LL_ENDL; + } + LL_INFOS() << "****************************************" << LL_ENDL; +} + +void LLFolderView::updateRenamerPosition() +{ + if(mRenameItem) + { + // See also LLFolderViewItem::draw() + S32 x = mRenameItem->getLabelXPos(); + S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenameItem->localPointToScreen( x, y, &x, &y ); + screenPointToLocal( x, y, &x, &y ); + mRenamer->setOrigin( x, y ); + + LLRect scroller_rect(0, 0, (S32)LLUI::getInstance()->getWindowSize().mV[VX], 0); + if (mScrollContainer) + { + scroller_rect = mScrollContainer->getContentWindowRect(); + } + + S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); + S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; + mRenamer->reshape( width, height, true ); + } +} + +// Update visibility and availability (i.e. enabled/disabled) of context menu items. +void LLFolderView::updateMenuOptions(LLMenuGL* menu) +{ + const LLView::child_list_t *list = menu->getChildList(); + + LLView::child_list_t::const_iterator menu_itor; + for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor) + { + (*menu_itor)->setVisible(false); + (*menu_itor)->pushVisible(true); + (*menu_itor)->setEnabled(true); + } + + // Successively filter out invalid options + U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); + U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; + for (selected_items_t::iterator item_itor = mSelectedItems.begin(); + item_itor != mSelectedItems.end(); + ++item_itor) + { + LLFolderViewItem* selected_item = (*item_itor); + selected_item->buildContextMenu(*menu, flags); + flags = multi_select_flag; + } + + if(mSingleFolderMode && (mSelectedItems.size() == 0)) + { + buildContextMenu(*menu, flags); + } + + // This adds a check for restrictions based on the entire + // selection set - for example, any one wearable may not push you + // over the limit, but all wearables together still might. + if (getFolderViewGroupedItemModel()) + { + getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); + } + + addNoOptions(menu); +} + +// Refresh the context menu (that is already shown). +void LLFolderView::updateMenu() +{ + LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + if (menu && menu->getVisible()) + { + updateMenuOptions(menu); + menu->needsArrange(); // update menu height if needed + } +} + +bool LLFolderView::isFolderSelected() +{ + selected_items_t::iterator item_iter; + for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) + { + LLFolderViewFolder* folder = dynamic_cast(*item_iter); + if (folder != NULL) + { + return true; + } + } + return false; +} + +bool LLFolderView::selectFirstItem() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();++iter) + { + LLFolderViewFolder* folder = (*iter ); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getNextFromChild(0,true); + if(itemp) + setSelection(itemp,false,true); + return true; + } + + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,false,true); + return true; + } + } + return false; +} +bool LLFolderView::selectLastItem() +{ + for(items_t::reverse_iterator iit = mItems.rbegin(); + iit != mItems.rend(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,false,true); + return true; + } + } + for (folders_t::reverse_iterator iter = mFolders.rbegin(); + iter != mFolders.rend();++iter) + { + LLFolderViewFolder* folder = (*iter); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); + if(itemp) + setSelection(itemp,false,true); + return true; + } + } + return false; +} + + +S32 LLFolderView::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + scrollToShowSelection(); + return 1; + + } + else if(str_action == "select_last") + { + setFocus(true); + selectLastItem(); + scrollToShowSelection(); + return 1; + } + } + return 0; +} + + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +void LLFolderView::onRenamerLost() +{ + if (mRenamer && mRenamer->getVisible()) + { + mRenamer->setVisible(false); + + // will commit current name (which could be same as original name) + mRenamer->setFocus(false); + } + + if( mRenameItem ) + { + setSelection( mRenameItem, true ); + mRenameItem = NULL; + } +} + +LLFolderViewItem* LLFolderView::getNextUnselectedItem() +{ + LLFolderViewItem* last_item = *mSelectedItems.rbegin(); + LLFolderViewItem* new_selection = last_item->getNextOpenNode(false); + while(new_selection && new_selection->isSelected()) + { + new_selection = new_selection->getNextOpenNode(false); + } + if (!new_selection) + { + new_selection = last_item->getPreviousOpenNode(false); + while (new_selection && (new_selection->isInSelection())) + { + new_selection = new_selection->getPreviousOpenNode(false); + } + } + return new_selection; +} + +S32 LLFolderView::getItemHeight() const +{ + if(!hasVisibleChildren()) +{ + //We need to display status textbox, let's reserve some place for it + return llmax(0, mStatusTextBox->getTextPixelHeight()); +} + return 0; +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/llui/llfolderview.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/llui/llfolderview.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 47821e38ca..1d4ecbe9c9 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -758,7 +758,7 @@ void LLFolderView::removeSelectedItems() // items, since the removal will futz with internal data // structures. std::vector items; - S32 count = mSelectedItems.size(); + auto count = mSelectedItems.size(); if(count <= 0) return; LLFolderViewItem* item = NULL; selected_items_t::iterator item_it; @@ -803,7 +803,7 @@ void LLFolderView::removeSelectedItems() setSelection(item_to_select, item_to_select ? item_to_select->isOpen() : false, mParentPanel.get()->hasFocus()); listeners.reserve(count); - for(S32 i = 0; i < count; ++i) + for(size_t i = 0; i < count; ++i) { listener = items[i]->getViewModelItem(); if(listener && (std::find(listeners.begin(), listeners.end(), listener) == listeners.end())) @@ -922,7 +922,7 @@ void LLFolderView::copy() { // *NOTE: total hack to clear the inventory clipboard LLClipboard::instance().reset(); - S32 count = mSelectedItems.size(); + auto count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { LLFolderViewModelItem* listener = NULL; @@ -1059,7 +1059,7 @@ void LLFolderView::startRenamingSelectedItem( void ) // make sure selection is visible scrollToShowSelection(); - S32 count = mSelectedItems.size(); + auto count = mSelectedItems.size(); LLFolderViewItem* item = NULL; if(count > 0) { @@ -1414,7 +1414,7 @@ bool LLFolderView::search(LLFolderViewItem* first_item, const std::string &searc std::string current_item_label(search_item->getViewModelItem()->getSearchableName()); LLStringUtil::toUpper(current_item_label); - S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size()); + auto search_string_length = llmin(upper_case_string.size(), current_item_label.size()); if (!current_item_label.compare(0, search_string_length, upper_case_string)) { found = true; @@ -1454,7 +1454,7 @@ bool LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) mParentPanel.get()->setFocus(true); bool handled = childrenHandleRightMouseDown(x, y, mask) != NULL; - S32 count = mSelectedItems.size(); + auto count = mSelectedItems.size(); LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); if (!menu) -- cgit v1.2.3 From 604cb4cb4dd71c0f90633e50d5b0108e3901c4ad Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Fri, 26 Jul 2024 06:19:34 -0400 Subject: Reduce utf8 to wstring conversion and llwstring temporaries during text draw (#2115) --- indra/llui/llfolderview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui/llfolderview.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 1d4ecbe9c9..388dc5b1ac 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -211,7 +211,7 @@ LLFolderView::LLFolderView(const Params& p) //clear label // go ahead and render root folder as usual // just make sure the label ("Inventory Folder") never shows up - mLabel = LLStringUtil::null; + mLabel.clear(); // Escape is handled by reverting the rename, not commiting it (default behavior) LLLineEditor::Params params; -- cgit v1.2.3