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/llfolderviewitem.cpp | 70 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'indra/llui/llfolderviewitem.cpp') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 0dc66bf37a..9069a95c9f 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -550,21 +550,21 @@ const std::string& LLFolderViewItem::getName( void ) const } // LLView functionality -BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) +bool LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) { if(!mIsSelected) { - getRoot()->setSelection(this, FALSE); + getRoot()->setSelection(this, false); } make_ui_sound("UISndClick"); - return TRUE; + return true; } -BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) +bool LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) { if (LLView::childrenHandleMouseDown(x, y, mask)) { - return TRUE; + return true; } // No handler needed for focus lost since this class has no @@ -583,7 +583,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) } else { - getRoot()->setSelection(this, FALSE); + getRoot()->setSelection(this, false); } make_ui_sound("UISndClick"); } @@ -591,15 +591,15 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) { // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. // This is necessary so we maintain selection consistent when starting a drag. - mSelectPending = TRUE; + mSelectPending = true; } mDragStartX = x; mDragStartY = y; - return TRUE; + return true; } -BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) +bool LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { static LLCachedControl drag_and_drop_threshold(*LLUI::getInstance()->mSettingGroups["config"],"DragAndDropDistanceThreshold", 3); @@ -616,7 +616,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { // RN: when starting drag and drop, clear out last auto-open root->autoOpenTest(NULL); - root->setShowSelectionContext(TRUE); + root->setShowSelectionContext(true); // Release keyboard focus, so that if stuff is dropped into the // world, pressing the delete key won't blow away the inventory @@ -631,31 +631,31 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) } root->clearHoveredItem(); - return TRUE; + return true; } else { LLFolderView* pRoot = getRoot(); pRoot->setHoveredItem(this); - pRoot->setShowSelectionContext(FALSE); + pRoot->setShowSelectionContext(false); getWindow()->setCursor(UI_CURSOR_ARROW); // let parent handle this then... - return FALSE; + return false; } } -BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) +bool LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { openItem(); - return TRUE; + return true; } -BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) +bool LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) { if (LLView::childrenHandleMouseUp(x, y, mask)) { - return TRUE; + return true; } // if mouse hasn't moved since mouse down... @@ -672,21 +672,21 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) } else { - getRoot()->setSelection(this, FALSE); + getRoot()->setSelection(this, false); } } - mSelectPending = FALSE; + mSelectPending = false; if( hasMouseCapture() ) { if (getRoot()) { - getRoot()->setShowSelectionContext(FALSE); + getRoot()->setShowSelectionContext(false); } gFocusMgr.setMouseCapture( NULL ); } - return TRUE; + return true; } void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) @@ -2019,9 +2019,9 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, } -BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) +bool LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; + bool handled = false; if( isOpen() ) { @@ -2035,11 +2035,11 @@ BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) } -BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) +bool LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) { mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - BOOL handled = LLView::handleHover(x, y, mask); + bool handled = LLView::handleHover(x, y, mask); if (!handled) { @@ -2050,9 +2050,9 @@ BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) return handled; } -BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) +bool LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; + bool handled = false; if( isOpen() ) { handled = childrenHandleMouseDown(x,y,mask) != NULL; @@ -2063,7 +2063,7 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) && !mSingleFolderMode) { toggleOpen(); - handled = TRUE; + handled = true; } else { @@ -2075,9 +2075,9 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) return handled; } -BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) +bool LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; + bool handled = false; if(mSingleFolderMode) { static LLUICachedControl double_click_new_window("SingleModeDoubleClickOpenWindow", false); @@ -2094,7 +2094,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) getViewModelItem()->navigateToFolder(false); }); } - return TRUE; + return true; } if( isOpen() ) @@ -2109,12 +2109,12 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) if (double_click_action == 1) { getViewModelItem()->navigateToFolder(true); - return TRUE; + return true; } if (double_click_action == 2) { getViewModelItem()->navigateToFolder(false, true); - return TRUE; + return true; } } if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) @@ -2125,10 +2125,10 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) } else { - getRoot()->setSelection(this, FALSE); + getRoot()->setSelection(this, false); toggleOpen(); } - handled = TRUE; + handled = true; } return handled; } -- 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/llfolderviewitem.cpp | 252 ++++++++++++++++++++-------------------- 1 file changed, 126 insertions(+), 126 deletions(-) (limited to 'indra/llui/llfolderviewitem.cpp') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9069a95c9f..5956ae8b36 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -128,18 +128,18 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mSuffixNeedsRefresh(false), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mParentFolder( NULL ), - mIsSelected( FALSE ), - mIsCurSelection( FALSE ), - mSelectPending(FALSE), + mIsSelected( false ), + mIsCurSelection( false ), + mSelectPending(false), mIsItemCut(false), mCutGeneration(0), mLabelStyle( LLFontGL::NORMAL ), - mHasVisibleChildren(FALSE), + mHasVisibleChildren(false), mLocalIndentation(p.folder_indentation), mIndentation(0), mItemHeight(p.item_height), mControlLabelRotation(0.f), - mDragAndDropTarget(FALSE), + mDragAndDropTarget(false), mLabel(p.name), mRoot(p.root), mViewModelItem(p.listener), @@ -185,7 +185,7 @@ LLFolderViewItem::~LLFolderViewItem() gFocusMgr.removeKeyboardFocusWithoutCallback(this); } -BOOL LLFolderViewItem::postBuild() +bool LLFolderViewItem::postBuild() { LLFolderViewModelItem& vmi = *getViewModelItem(); // getDisplayName() is expensive (due to internal getLabelSuffix() and name building) @@ -203,7 +203,7 @@ BOOL LLFolderViewItem::postBuild() // while LLFolderViewItem::arrange() updates visual part mSuffixNeedsRefresh = true; mLabelWidthDirty = true; - return TRUE; + return true; } LLFolderView* LLFolderViewItem::getRoot() @@ -216,21 +216,21 @@ const LLFolderView* LLFolderViewItem::getRoot() const return mRoot; } // Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. -BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) +bool LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) { LLFolderViewItem* root = this; while( root->mParentFolder ) { if( root->mParentFolder == potential_ancestor ) { - return TRUE; + return true; } root = root->mParentFolder; } - return FALSE; + return false; } -LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) +LLFolderViewItem* LLFolderViewItem::getNextOpenNode(bool include_children) { if (!mParentFolder) { @@ -252,7 +252,7 @@ LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children) return itemp; } -LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) +LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(bool include_children) { if (!mParentFolder) { @@ -276,19 +276,19 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) return itemp; } -BOOL LLFolderViewItem::passedFilter(S32 filter_generation) +bool LLFolderViewItem::passedFilter(S32 filter_generation) { return getViewModelItem()->passedFilter(filter_generation); } -BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) +bool LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) { if (filter_generation < 0) { filter_generation = getFolderViewModel()->getFilter().getFirstSuccessGeneration(); } LLFolderViewModelItem* model = getViewModelItem(); - BOOL visible = model->passedFilter(filter_generation); + bool visible = model->passedFilter(filter_generation); if (model->getMarkedDirtyGeneration() >= filter_generation) { // unsure visibility state @@ -348,8 +348,8 @@ void LLFolderViewItem::refreshSuffix() } // Utility function for LLFolderView -void LLFolderViewItem::arrangeAndSet(BOOL set_selection, - BOOL take_keyboard_focus) +void LLFolderViewItem::arrangeAndSet(bool set_selection, + bool take_keyboard_focus) { LLFolderView* root = getRoot(); if (getParentFolder()) @@ -358,7 +358,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection, } if(set_selection) { - getRoot()->setSelection(this, TRUE, take_keyboard_focus); + getRoot()->setSelection(this, true, take_keyboard_focus); if(root) { root->scrollToShowSelection(); @@ -373,7 +373,7 @@ std::set LLFolderViewItem::getSelectionList() const return selection; } -// addToFolder() returns TRUE if it succeeds. FALSE otherwise +// addToFolder() returns true if it succeeds. false otherwise void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { folder->addItem(this); @@ -443,7 +443,7 @@ S32 LLFolderViewItem::getTextPad() // means 'deselect' for a leaf item. Do this optimization after // multiple selection is implemented to make sure it all plays nice // together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) +bool LLFolderViewItem::setSelection(LLFolderViewItem* selection, bool openitem, bool take_keyboard_focus) { if (selection == this && !mIsSelected) { @@ -456,7 +456,7 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, return mIsSelected; } -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) +bool LLFolderViewItem::changeSelection(LLFolderViewItem* selection, bool selected) { if (selection == this) { @@ -468,31 +468,31 @@ BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selecte { selectItem(); } - return TRUE; + return true; } - return FALSE; + return false; } void LLFolderViewItem::deselectItem(void) { - mIsSelected = FALSE; + mIsSelected = false; } void LLFolderViewItem::selectItem(void) { - if (mIsSelected == FALSE) + if (mIsSelected == false) { - mIsSelected = TRUE; + mIsSelected = true; getViewModelItem()->selectItem(); } } -BOOL LLFolderViewItem::isMovable() +bool LLFolderViewItem::isMovable() { return getViewModelItem()->isItemMovable(); } -BOOL LLFolderViewItem::isRemovable() +bool LLFolderViewItem::isRemovable() { return getViewModelItem()->isItemRemovable(); } @@ -511,12 +511,12 @@ void LLFolderViewItem::destroyView() // Call through to the viewed object and return true if it can be // removed. -//BOOL LLFolderViewItem::removeRecursively(BOOL single_item) -BOOL LLFolderViewItem::remove() +//bool LLFolderViewItem::removeRecursively(bool single_item) +bool LLFolderViewItem::remove() { if(!isRemovable()) { - return FALSE; + return false; } return getViewModelItem()->removeItem(); } @@ -701,18 +701,18 @@ void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) } } -BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +bool LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { - BOOL handled = FALSE; - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + bool handled = false; + bool accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); handled = accepted; if (accepted) { - mDragAndDropTarget = TRUE; + mDragAndDropTarget = true; *accept = ACCEPT_YES_MULTI; } else @@ -773,7 +773,7 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L return mIsItemCut; } -void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, +void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { const S32 focus_top = getRect().getHeight(); @@ -787,7 +787,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo //--------------------------------------------------------------------------------// // Draw highlight for selected items // Note: Always render "current" item or flashing item, only render other selected - // items if mShowSingleSelection is FALSE. + // items if mShowSingleSelection is false. // if (isHighlightAllowed()) @@ -831,7 +831,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo focus_top, getRect().getWidth() - 2, focus_bottom, - focusOutlineColor, FALSE); + focusOutlineColor, false); } if (folder_open) @@ -840,14 +840,14 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo focus_bottom + 1, // overlap with bottom edge of above rect getRect().getWidth() - 2, 0, - focusOutlineColor, FALSE); + focusOutlineColor, false); if (showContent && !isFlashing()) { gl_rect_2d(FOCUS_LEFT, focus_bottom + 1, getRect().getWidth() - 2, 0, - bgColor, TRUE); + bgColor, true); } } } @@ -857,7 +857,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo focus_top, getRect().getWidth() - 2, focus_bottom, - mouseOverColor, FALSE); + mouseOverColor, false); } //--------------------------------------------------------------------------------// @@ -870,16 +870,16 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo focus_top, getRect().getWidth() - 2, focus_bottom, - bgColor, FALSE); + bgColor, false); if (folder_open) { gl_rect_2d(FOCUS_LEFT, focus_bottom + 1, // overlap with bottom edge of above rect getRect().getWidth() - 2, 0, - bgColor, FALSE); + bgColor, false); } - mDragAndDropTarget = FALSE; + mDragAndDropTarget = false; } } @@ -890,13 +890,13 @@ void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y // font->renderUTF8(mLabel, 0, x, y, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, TRUE); + S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, true); } void LLFolderViewItem::draw() { - const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - const BOOL filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : FALSE); // If we have keyboard focus, draw selection filled + const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); + const bool filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : false); // If we have keyboard focus, draw selection filled const Params& default_params = LLUICtrlFactory::getDefaultParams(); const S32 TOP_PAD = default_params.item_top_pad; @@ -999,7 +999,7 @@ void LLFolderViewItem::draw() { suffix_font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE ); + S32_MAX, S32_MAX, &right_x, false ); } //--------------------------------------------------------------------------------// @@ -1013,7 +1013,7 @@ void LLFolderViewItem::draw() F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; font->renderUTF8( combined_string, filter_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); + filter_string_length, S32_MAX, &right_x, false ); } else { @@ -1023,7 +1023,7 @@ void LLFolderViewItem::draw() F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel, filter_offset, label_filter_length); F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; font->renderUTF8( mLabel, filter_offset, match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, label_filter_length, S32_MAX, &right_x, FALSE ); + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, label_filter_length, S32_MAX, &right_x, false ); } S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; @@ -1032,7 +1032,7 @@ void LLFolderViewItem::draw() S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length); F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - suffix_font->renderUTF8( mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, suffix_filter_length, S32_MAX, &right_x, FALSE ); + suffix_font->renderUTF8( mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, suffix_filter_length, S32_MAX, &right_x, false ); } } @@ -1066,8 +1066,8 @@ bool LLFolderViewItem::isInSelection() const LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): LLFolderViewItem( p ), - mIsOpen(FALSE), - mExpanderHighlighted(FALSE), + mIsOpen(false), + mExpanderHighlighted(false), mCurHeight(0.f), mTargetHeight(0.f), mAutoOpenCountdown(0.f), @@ -1102,7 +1102,7 @@ LLFolderViewFolder::~LLFolderViewFolder( void ) gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() } -// addToFolder() returns TRUE if it succeeds. FALSE otherwise +// addToFolder() returns true if it succeeds. false otherwise void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { folder->addFolder(this); @@ -1262,7 +1262,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) > ll_round(mCurHeight) + mMaxFolderItemOverlap) { // hide if beyond current folder height - (*fit)->setVisible(FALSE); + (*fit)->setVisible(false); } } @@ -1274,7 +1274,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) if (getRect().getHeight() - (*iit)->getRect().mBottom > ll_round(mCurHeight) + mMaxFolderItemOverlap) { - (*iit)->setVisible(FALSE); + (*iit)->setVisible(false); } } } @@ -1292,7 +1292,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) return ll_round(mTargetHeight); } -BOOL LLFolderViewFolder::needsArrange() +bool LLFolderViewFolder::needsArrange() { return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); } @@ -1304,17 +1304,17 @@ bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation) // Passes selection information on to children and record selection // information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, - BOOL take_keyboard_focus) +bool LLFolderViewFolder::setSelection(LLFolderViewItem* selection, bool openitem, + bool take_keyboard_focus) { - BOOL rv = FALSE; + bool rv = false; if (selection == this) { if (!isSelected()) { selectItem(); } - rv = TRUE; + rv = true; } else { @@ -1322,9 +1322,9 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem { deselectItem(); } - rv = FALSE; + rv = false; } - BOOL child_selected = FALSE; + bool child_selected = false; for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) @@ -1332,8 +1332,8 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem folders_t::iterator fit = iter++; if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) { - rv = TRUE; - child_selected = TRUE; + rv = true; + child_selected = true; } } for (items_t::iterator iter = mItems.begin(); @@ -1342,13 +1342,13 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem items_t::iterator iit = iter++; if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) { - rv = TRUE; - child_selected = TRUE; + rv = true; + child_selected = true; } } if(openitem && child_selected && !mSingleFolderMode) { - setOpenArrangeRecursively(TRUE); + setOpenArrangeRecursively(true); } return rv; } @@ -1356,15 +1356,15 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem // This method is used to change the selection of an item. // Recursively traverse all children; if 'selection' is 'this' then change // the select status if necessary. -// Returns TRUE if the selection state of this folder, or of a child, was changed. -BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selected) +// Returns true if the selection state of this folder, or of a child, was changed. +bool LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, bool selected) { - BOOL rv = FALSE; + bool rv = false; if(selection == this) { if (isSelected() != selected) { - rv = TRUE; + rv = true; if (selected) { selectItem(); @@ -1382,7 +1382,7 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec folders_t::iterator fit = iter++; if((*fit)->changeSelection(selection, selected)) { - rv = TRUE; + rv = true; } } for (items_t::iterator iter = mItems.begin(); @@ -1391,7 +1391,7 @@ BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, BOOL selec items_t::iterator iit = iter++; if((*iit)->changeSelection(selection, selected)) { - rv = TRUE; + rv = true; } } return rv; @@ -1575,7 +1575,7 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) { - if (getRoot()->getAllowMultiSelect() == FALSE) return; + if (getRoot()->getAllowMultiSelect() == false) return; LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); if (cur_selected_item == NULL) @@ -1624,7 +1624,7 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) LLFolderView* root = getRoot(); - BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected + bool selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected // array always go from 'will be selected' to ' will be unselected', iterate // in opposite direction to simplify identification of 'point of origin' in @@ -1634,12 +1634,12 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) ++it) { LLFolderViewItem* item = *it; - BOOL selected = item->isSelected(); + bool selected = item->isSelected(); if (!selection_reverse && selected) { // it is our 'point of origin' where we shift/expand from // don't deselect it - selection_reverse = TRUE; + selection_reverse = true; } else { @@ -1650,11 +1650,11 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) if (selection_reverse) { // at some point we reversed selection, first element should be deselected - root->changeSelection(last_selected_item_from_cur, FALSE); + root->changeSelection(last_selected_item_from_cur, false); } // element we expand to should always be selected - root->changeSelection(new_selection, TRUE); + root->changeSelection(new_selection, true); } @@ -1712,11 +1712,11 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_mode removeChild(item); } -BOOL LLFolderViewFolder::isMovable() +bool LLFolderViewFolder::isMovable() { if( !(getViewModelItem()->isItemMovable()) ) { - return FALSE; + return false; } for (items_t::iterator iter = mItems.begin(); @@ -1725,7 +1725,7 @@ BOOL LLFolderViewFolder::isMovable() items_t::iterator iit = iter++; if(!(*iit)->isMovable()) { - return FALSE; + return false; } } @@ -1735,18 +1735,18 @@ BOOL LLFolderViewFolder::isMovable() folders_t::iterator fit = iter++; if(!(*fit)->isMovable()) { - return FALSE; + return false; } } - return TRUE; + return true; } -BOOL LLFolderViewFolder::isRemovable() +bool LLFolderViewFolder::isRemovable() { if( !(getViewModelItem()->isItemRemovable()) ) { - return FALSE; + return false; } for (items_t::iterator iter = mItems.begin(); @@ -1755,7 +1755,7 @@ BOOL LLFolderViewFolder::isRemovable() items_t::iterator iit = iter++; if(!(*iit)->isRemovable()) { - return FALSE; + return false; } } @@ -1765,10 +1765,10 @@ BOOL LLFolderViewFolder::isRemovable() folders_t::iterator fit = iter++; if(!(*fit)->isRemovable()) { - return FALSE; + return false; } } - return TRUE; + return true; } void LLFolderViewFolder::destroyRoot() @@ -1788,7 +1788,7 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) mItems.push_back(item); item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); - item->setVisible(FALSE); + item->setVisible(false); addChild(item); @@ -1811,7 +1811,7 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) mFolders.push_back(folder); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); - folder->setVisible(FALSE); + folder->setVisible(false); // rearrange all descendants too, as our indentation level might have changed //folder->requestArrange(); //requestSort(); @@ -1842,7 +1842,7 @@ void LLFolderViewFolder::toggleOpen() } // Force a folder open or closed -void LLFolderViewFolder::setOpen(BOOL openitem) +void LLFolderViewFolder::setOpen(bool openitem) { if(mSingleFolderMode) { @@ -1859,9 +1859,9 @@ void LLFolderViewFolder::setOpen(BOOL openitem) } } -void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) +void LLFolderViewFolder::setOpenArrangeRecursively(bool openitem, ERecurseType recurse) { - BOOL was_open = isOpen(); + bool was_open = isOpen(); mIsOpen = openitem; if(!was_open && openitem) { @@ -1896,17 +1896,17 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r } } -BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, +bool LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, + bool drop, EDragAndDropType c_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + bool accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { - mDragAndDropTarget = TRUE; + mDragAndDropTarget = true; *accept = ACCEPT_YES_MULTI; } else @@ -1917,7 +1917,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, // drag and drop to child item, so clear pending auto-opens getRoot()->autoOpenTest(NULL); - return TRUE; + return true; } void LLFolderViewFolder::openItem( void ) @@ -1960,14 +1960,14 @@ void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) } // LLView functionality -BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, +bool LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, + bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { - BOOL handled = FALSE; + bool handled = false; if (isOpen()) { @@ -1981,11 +1981,11 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewFolder" << LL_ENDL; } - return TRUE; + return true; } -BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, - BOOL drop, +bool LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, + bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, @@ -1995,14 +1995,14 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, { *accept = ACCEPT_NO; tooltip_msg = LLTrans::getString("TooltipOutboxCannotDropOnRoot"); - return TRUE; + return true; } - BOOL accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + bool accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { - mDragAndDropTarget = TRUE; + mDragAndDropTarget = true; *accept = ACCEPT_YES_MULTI; } else @@ -2015,7 +2015,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, getRoot()->autoOpenTest(this); } - return TRUE; + return true; } @@ -2145,19 +2145,19 @@ void LLFolderViewFolder::draw() LLView::draw(); } - mExpanderHighlighted = FALSE; + mExpanderHighlighted = false; } // this does prefix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) +LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, bool include_children ) { - BOOL found_item = FALSE; + bool found_item = false; LLFolderViewItem* result = NULL; // when not starting from a given item, start at beginning if(item == NULL) { - found_item = TRUE; + found_item = true; } // find current item among children @@ -2175,16 +2175,16 @@ LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, { if(item == (*fit)) { - found_item = TRUE; + found_item = true; // if we are on downwards traversal if (include_children && (*fit)->isOpen()) { // look for first descendant - return (*fit)->getNextFromChild(NULL, TRUE); + return (*fit)->getNextFromChild(NULL, true); } // otherwise advance to next folder ++fit; - include_children = TRUE; + include_children = true; break; } } @@ -2196,7 +2196,7 @@ LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, { if(item == (*iit)) { - found_item = TRUE; + found_item = true; // point to next item ++iit; break; @@ -2209,7 +2209,7 @@ LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, { // you should never call this method with an item that isn't a child // so we should always find something - llassert(FALSE); + llassert(false); return NULL; } @@ -2247,22 +2247,22 @@ LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, { // If there are no siblings or children to go to, recurse up one level in the tree // and skip children for this folder, as we've already discounted them - result = mParentFolder->getNextFromChild(this, FALSE); + result = mParentFolder->getNextFromChild(this, false); } return result; } // this does postfix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children ) +LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, bool include_children ) { - BOOL found_item = FALSE; + bool found_item = false; LLFolderViewItem* result = NULL; // when not starting from a given item, start at end if(item == NULL) { - found_item = TRUE; + found_item = true; } // find current item among children @@ -2280,7 +2280,7 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it { if(item == (*iit)) { - found_item = TRUE; + found_item = true; // point to next item ++iit; break; @@ -2294,7 +2294,7 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it { if(item == (*fit)) { - found_item = TRUE; + found_item = true; // point to next folder ++fit; break; @@ -2307,7 +2307,7 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it { // you should never call this method with an item that isn't a child // so we should always find something - llassert(FALSE); + llassert(false); return NULL; } -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/llui/llfolderviewitem.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'indra/llui/llfolderviewitem.cpp') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index bcbc0f9970..311056f541 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -484,7 +484,7 @@ void LLFolderViewItem::deselectItem(void) void LLFolderViewItem::selectItem(void) { - if (mIsSelected == false) + if (!mIsSelected) { mIsSelected = true; getViewModelItem()->selectItem(); @@ -1582,7 +1582,8 @@ void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFo void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) { - if (getRoot()->getAllowMultiSelect() == false) return; + if (!getRoot()->getAllowMultiSelect()) + return; LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); if (cur_selected_item == NULL) @@ -1593,14 +1594,15 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) bool reverse = false; LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); - if (!common_ancestor) return; + if (!common_ancestor) + return; LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); std::vector items_to_select_forward; - while(cur_folder != common_ancestor) + while (cur_folder != common_ancestor) { cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); @@ -1612,7 +1614,7 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) LLFolderViewItem* last_selected_item_from_new = new_selection; cur_folder = new_selection->getParentFolder(); - while(cur_folder != common_ancestor) + while (cur_folder != common_ancestor) { cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); -- 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/llfolderviewitem.cpp | 4736 +++++++++++++++++++-------------------- 1 file changed, 2368 insertions(+), 2368 deletions(-) (limited to 'indra/llui/llfolderviewitem.cpp') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 2bbf23c4bf..a0c7407b06 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1,2368 +1,2368 @@ -/** -* @file llfolderviewitem.cpp -* @brief Items and folders that can appear in a hierarchical folder view -* -* $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 "../newview/llviewerprecompiledheaders.h" - -#include "llflashtimer.h" - -#include "linden_common.h" -#include "llfolderviewitem.h" -#include "llfolderview.h" -#include "llfolderviewmodel.h" -#include "llpanel.h" -#include "llcallbacklist.h" -#include "llcriticaldamp.h" -#include "llclipboard.h" -#include "llfocusmgr.h" // gFocusMgr -#include "lltrans.h" -#include "llwindow.h" - -///---------------------------------------------------------------------------- -/// Class LLFolderViewItem -///---------------------------------------------------------------------------- - -static LLDefaultChildRegistry::Register r("folder_view_item"); - -// statics -std::map LLFolderViewItem::sFonts; // map of styles to fonts - -bool LLFolderViewItem::sColorSetInitialized = false; -LLUIColor LLFolderViewItem::sFgColor; -LLUIColor LLFolderViewItem::sHighlightBgColor; -LLUIColor LLFolderViewItem::sFlashBgColor; -LLUIColor LLFolderViewItem::sFocusOutlineColor; -LLUIColor LLFolderViewItem::sMouseOverColor; -LLUIColor LLFolderViewItem::sFilterBGColor; -LLUIColor LLFolderViewItem::sFilterTextColor; -LLUIColor LLFolderViewItem::sSuffixColor; -LLUIColor LLFolderViewItem::sSearchStatusColor; - -// only integers can be initialized in header -const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; -const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; - -const LLColor4U DEFAULT_WHITE(255, 255, 255); - - -//static -LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) -{ - LLFontGL* rtn = sFonts[style]; - if (!rtn) // grab label font with this style, lazily - { - LLFontDescriptor labelfontdesc("SansSerif", "Small", style); - rtn = LLFontGL::getFont(labelfontdesc); - if (!rtn) - { - rtn = LLFontGL::getFontDefault(); - } - sFonts[style] = rtn; - } - return rtn; -} - -//static -void LLFolderViewItem::initClass() -{ -} - -//static -void LLFolderViewItem::cleanupClass() -{ - sFonts.clear(); -} - - -// NOTE: Optimize this, we call it a *lot* when opening a large inventory -LLFolderViewItem::Params::Params() -: root(), - listener(), - folder_arrow_image("folder_arrow_image"), - folder_indentation("folder_indentation"), - selection_image("selection_image"), - item_height("item_height"), - item_top_pad("item_top_pad"), - creation_date(), - allow_wear("allow_wear", true), - allow_drop("allow_drop", true), - font_color("font_color"), - font_highlight_color("font_highlight_color"), - left_pad("left_pad", 0), - icon_pad("icon_pad", 0), - icon_width("icon_width", 0), - text_pad("text_pad", 0), - text_pad_right("text_pad_right", 0), - single_folder_mode("single_folder_mode", false), - double_click_override("double_click_override", false), - arrow_size("arrow_size", 0), - max_folder_item_overlap("max_folder_item_overlap", 0) -{ } - -// Default constructor -LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) -: LLView(p), - mLabelWidth(0), - mLabelWidthDirty(false), - mSuffixNeedsRefresh(false), - mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), - mParentFolder( NULL ), - mIsSelected( false ), - mIsCurSelection( false ), - mSelectPending(false), - mIsItemCut(false), - mCutGeneration(0), - mLabelStyle( LLFontGL::NORMAL ), - mHasVisibleChildren(false), - mLocalIndentation(p.folder_indentation), - mIndentation(0), - mItemHeight(p.item_height), - mControlLabelRotation(0.f), - mDragAndDropTarget(false), - mLabel(p.name), - mRoot(p.root), - mViewModelItem(p.listener), - mIsMouseOverTitle(false), - mAllowWear(p.allow_wear), - mAllowDrop(p.allow_drop), - mFontColor(p.font_color), - mFontHighlightColor(p.font_highlight_color), - mLeftPad(p.left_pad), - mIconPad(p.icon_pad), - mIconWidth(p.icon_width), - mTextPad(p.text_pad), - mTextPadRight(p.text_pad_right), - mArrowSize(p.arrow_size), - mSingleFolderMode(p.single_folder_mode), - mMaxFolderItemOverlap(p.max_folder_item_overlap), - mDoubleClickOverride(p.double_click_override) -{ - if (!sColorSetInitialized) - { - sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); - sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); - sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); - sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); - sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); - sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); - sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); - sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); - sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); - sColorSetInitialized = true; - } - - if (mViewModelItem) - { - mViewModelItem->setFolderViewItem(this); - } -} - -// Destroys the object -LLFolderViewItem::~LLFolderViewItem() -{ - mViewModelItem = NULL; - gFocusMgr.removeKeyboardFocusWithoutCallback(this); -} - -bool LLFolderViewItem::postBuild() -{ - LLFolderViewModelItem* vmi = getViewModelItem(); - llassert(vmi); // not supposed to happen, if happens, find out why and fix - if (vmi) - { - // getDisplayName() is expensive (due to internal getLabelSuffix() and name building) - // it also sets search strings so it requires a filter reset - mLabel = vmi->getDisplayName(); - setToolTip(vmi->getName()); - - // Dirty the filter flag of the model from the view (CHUI-849) - vmi->dirtyFilter(); - } - - // Don't do full refresh on constructor if it is possible to avoid - // it significantly slows down bulk view creation. - // Todo: Ideally we need to move getDisplayName() out of constructor as well. - // Like: make a logic that will let filter update search string, - // while LLFolderViewItem::arrange() updates visual part - mSuffixNeedsRefresh = true; - mLabelWidthDirty = true; - return true; -} - -LLFolderView* LLFolderViewItem::getRoot() -{ - return mRoot; -} - -const LLFolderView* LLFolderViewItem::getRoot() const -{ - return mRoot; -} -// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. -bool LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) -{ - LLFolderViewItem* root = this; - while( root->mParentFolder ) - { - if( root->mParentFolder == potential_ancestor ) - { - return true; - } - root = root->mParentFolder; - } - return false; -} - -LLFolderViewItem* LLFolderViewItem::getNextOpenNode(bool include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit last item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} - -LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(bool include_children) -{ - if (!mParentFolder) - { - return NULL; - } - - LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); - - // Skip over items that are invisible or are hidden from the UI. - while(itemp && !itemp->getVisible()) - { - LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); - if (itemp == next_itemp) - { - // hit first item - return itemp->getVisible() ? itemp : this; - } - itemp = next_itemp; - } - - return itemp; -} - -bool LLFolderViewItem::passedFilter(S32 filter_generation) -{ - return getViewModelItem()->passedFilter(filter_generation); -} - -bool LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) -{ - if (filter_generation < 0) - { - filter_generation = getFolderViewModel()->getFilter().getFirstSuccessGeneration(); - } - LLFolderViewModelItem* model = getViewModelItem(); - bool visible = model->passedFilter(filter_generation); - if (model->getMarkedDirtyGeneration() >= filter_generation) - { - // unsure visibility state - // retaining previous visibility until item is updated or filter generation changes - visible |= getVisible(); - } - return visible; -} - -void LLFolderViewItem::refresh() -{ - LLFolderViewModelItem& vmi = *getViewModelItem(); - - mLabel = vmi.getDisplayName(); - setToolTip(vmi.getName()); - // icons are slightly expensive to get, can be optimized - // see LLInventoryIcon::getIcon() - mIcon = vmi.getIcon(); - mIconOpen = vmi.getIconOpen(); - mIconOverlay = vmi.getIconOverlay(); - - if (mRoot->useLabelSuffix()) - { - // Very Expensive! - // Can do a number of expensive checks, like checking active motions, wearables or friend list - mLabelStyle = vmi.getLabelStyle(); - mLabelSuffix = vmi.getLabelSuffix(); - } - - // Dirty the filter flag of the model from the view (CHUI-849) - vmi.dirtyFilter(); - - mLabelWidthDirty = true; - mSuffixNeedsRefresh = false; -} - -void LLFolderViewItem::refreshSuffix() -{ - LLFolderViewModelItem const* vmi = getViewModelItem(); - - // icons are slightly expensive to get, can be optimized - // see LLInventoryIcon::getIcon() - mIcon = vmi->getIcon(); - mIconOpen = vmi->getIconOpen(); - mIconOverlay = vmi->getIconOverlay(); - - if (mRoot->useLabelSuffix()) - { - // Very Expensive! - // Can do a number of expensive checks, like checking active motions, wearables or friend list - mLabelStyle = vmi->getLabelStyle(); - mLabelSuffix = vmi->getLabelSuffix(); - } - - mLabelWidthDirty = true; - mSuffixNeedsRefresh = false; -} - -// Utility function for LLFolderView -void LLFolderViewItem::arrangeAndSet(bool set_selection, - bool take_keyboard_focus) -{ - LLFolderView* root = getRoot(); - if (getParentFolder()) - { - getParentFolder()->requestArrange(); - } - if(set_selection) - { - getRoot()->setSelection(this, true, take_keyboard_focus); - if(root) - { - root->scrollToShowSelection(); - } - } -} - - -std::set LLFolderViewItem::getSelectionList() const -{ - std::set selection; - return selection; -} - -// addToFolder() returns true if it succeeds. false otherwise -void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) -{ - folder->addItem(this); - - // Compute indentation since parent folder changed - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + mLocalIndentation - : 0; -} - - -// Finds width and height of this object and its children. Also -// makes sure that this view and its children are the right size. -S32 LLFolderViewItem::arrange( S32* width, S32* height ) -{ - // Only indent deeper items in hierarchy - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + mLocalIndentation - : 0; - if (mLabelWidthDirty) - { - if (mSuffixNeedsRefresh) - { - // Expensive. But despite refreshing label, - // it is purely visual, so it is fine to do at our laisure - refreshSuffix(); - } - mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix) + mLabelPaddingRight; - mLabelWidthDirty = false; - } - - *width = llmax(*width, mLabelWidth); - - // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 - bool use_ellipses = getRoot()->getUseEllipses(); - if (use_ellipses) - { - // limit to set rect to avoid horizontal scrollbar - *width = llmin(*width, getRoot()->getRect().getWidth()); - } - *height = getItemHeight(); - return *height; -} - -S32 LLFolderViewItem::getItemHeight() const -{ - return mItemHeight; -} - -S32 LLFolderViewItem::getLabelXPos() -{ - return getIndentation() + mArrowSize + mTextPad + mIconWidth + mIconPad; -} - -S32 LLFolderViewItem::getIconPad() -{ - return mIconPad; -} - -S32 LLFolderViewItem::getTextPad() -{ - return mTextPad; -} - -// *TODO: This can be optimized a lot by simply recording that it is -// selected in the appropriate places, and assuming that set selection -// means 'deselect' for a leaf item. Do this optimization after -// multiple selection is implemented to make sure it all plays nice -// together. -bool LLFolderViewItem::setSelection(LLFolderViewItem* selection, bool openitem, bool take_keyboard_focus) -{ - if (selection == this && !mIsSelected) - { - selectItem(); - } - else if (mIsSelected) // Deselect everything else. - { - deselectItem(); - } - return mIsSelected; -} - -bool LLFolderViewItem::changeSelection(LLFolderViewItem* selection, bool selected) -{ - if (selection == this) - { - if (mIsSelected) - { - deselectItem(); - } - else - { - selectItem(); - } - return true; - } - return false; -} - -void LLFolderViewItem::deselectItem(void) -{ - mIsSelected = false; -} - -void LLFolderViewItem::selectItem(void) -{ - if (!mIsSelected) - { - mIsSelected = true; - getViewModelItem()->selectItem(); - } -} - -bool LLFolderViewItem::isMovable() -{ - return getViewModelItem()->isItemMovable(); -} - -bool LLFolderViewItem::isRemovable() -{ - return getViewModelItem()->isItemRemovable(); -} - -void LLFolderViewItem::destroyView() -{ - getRoot()->removeFromSelectionList(this); - - if (mParentFolder) - { - // removeView deletes me - mParentFolder->extractItem(this); - } - delete this; -} - -// Call through to the viewed object and return true if it can be -// removed. -//bool LLFolderViewItem::removeRecursively(bool single_item) -bool LLFolderViewItem::remove() -{ - if(!isRemovable()) - { - return false; - } - return getViewModelItem()->removeItem(); -} - -// Build an appropriate context menu for the item. -void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - getViewModelItem()->buildContextMenu(menu, flags); -} - -void LLFolderViewItem::openItem( void ) -{ - if (mAllowWear || !getViewModelItem()->isItemWearable()) - { - getViewModelItem()->openItem(); - } -} - -void LLFolderViewItem::rename(const std::string& new_name) -{ - if( !new_name.empty() ) - { - getViewModelItem()->renameItem(new_name); - } -} - -const std::string& LLFolderViewItem::getName( void ) const -{ - static const std::string noName(""); - return getViewModelItem() ? getViewModelItem()->getName() : noName; -} - -// LLView functionality -bool LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - if(!mIsSelected) - { - getRoot()->setSelection(this, false); - } - make_ui_sound("UISndClick"); - return true; -} - -bool LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - if (LLView::childrenHandleMouseDown(x, y, mask)) - { - return true; - } - - // No handler needed for focus lost since this class has no - // state that depends on it. - gFocusMgr.setMouseCapture( this ); - - if (!mIsSelected) - { - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, false); - } - make_ui_sound("UISndClick"); - } - else - { - // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. - // This is necessary so we maintain selection consistent when starting a drag. - mSelectPending = true; - } - - mDragStartX = x; - mDragStartY = y; - return true; -} - -bool LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) -{ - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - if( hasMouseCapture() && isMovable() ) - { - LLFolderView* root = getRoot(); - - if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD - && root->getAllowDrag() - && root->getCurSelectedItem() - && root->startDrag()) - { - // RN: when starting drag and drop, clear out last auto-open - root->autoOpenTest(NULL); - root->setShowSelectionContext(true); - - // Release keyboard focus, so that if stuff is dropped into the - // world, pressing the delete key won't blow away the inventory - // item. - gFocusMgr.setKeyboardFocus(NULL); - - getWindow()->setCursor(UI_CURSOR_ARROW); - } - else if (x != mDragStartX || y != mDragStartY) - { - getWindow()->setCursor(UI_CURSOR_NOLOCKED); - } - - root->clearHoveredItem(); - return true; - } - else - { - LLFolderView* pRoot = getRoot(); - pRoot->setHoveredItem(this); - pRoot->setShowSelectionContext(false); - getWindow()->setCursor(UI_CURSOR_ARROW); - // let parent handle this then... - return false; - } -} - - -bool LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - openItem(); - return true; -} - -bool LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - if (LLView::childrenHandleMouseUp(x, y, mask)) - { - return true; - } - - // if mouse hasn't moved since mouse down... - if ( pointInView(x, y) && mSelectPending ) - { - //...then select - if(mask & MASK_CONTROL) - { - getRoot()->changeSelection(this, !mIsSelected); - } - else if (mask & MASK_SHIFT) - { - getParentFolder()->extendSelectionTo(this); - } - else - { - getRoot()->setSelection(this, false); - } - } - - mSelectPending = false; - - if( hasMouseCapture() ) - { - if (getRoot()) - { - getRoot()->setShowSelectionContext(false); - } - gFocusMgr.setMouseCapture( NULL ); - } - return true; -} - -void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mIsMouseOverTitle = false; - - // NOTE: LLViewerWindow::updateUI() calls "enter" before "leave"; if the mouse moved to another item, we can't just outright clear it - LLFolderView* pRoot = getRoot(); - if (this == pRoot->getHoveredItem()) - { - pRoot->clearHoveredItem(); - } -} - -bool LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - bool handled = false; - bool accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - handled = accepted; - if (accepted) - { - mDragAndDropTarget = true; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - if(mParentFolder && !handled) - { - // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. - mRoot->setDraggingOverItem(this); - handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - mRoot->setDraggingOverItem(NULL); - } - if (handled) - { - LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewItem" << LL_ENDL; - } - - return handled; -} - -void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color) -{ - //--------------------------------------------------------------------------------// - // Draw open folder arrow - // - const S32 TOP_PAD = default_params.item_top_pad; - - if (hasVisibleChildren() || !isFolderComplete()) - { - LLUIImage* arrow_image = default_params.folder_arrow_image; - gl_draw_scaled_rotated_image( - mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, - mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), fg_color); - } -} - -/*virtual*/ bool LLFolderViewItem::isHighlightAllowed() -{ - return mIsSelected; -} - -/*virtual*/ bool LLFolderViewItem::isHighlightActive() -{ - return mIsCurSelection; -} - -/*virtual*/ bool LLFolderViewItem::isFadeItem() -{ - LLClipboard& clipboard = LLClipboard::instance(); - if (mCutGeneration != clipboard.getGeneration()) - { - mCutGeneration = clipboard.getGeneration(); - mIsItemCut = clipboard.isCutMode() - && ((getParentFolder() && getParentFolder()->isFadeItem()) - || getViewModelItem()->isCutToClipboard()); - } - return mIsItemCut; -} - -void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, - const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) -{ - const S32 focus_top = getRect().getHeight(); - const S32 focus_bottom = getRect().getHeight() - mItemHeight; - const bool folder_open = (getRect().getHeight() > mItemHeight + 4); - const S32 FOCUS_LEFT = 1; - - // Determine which background color to use for highlighting - LLUIColor bgColor = (isFlashing() ? flashColor : selectColor); - - //--------------------------------------------------------------------------------// - // Draw highlight for selected items - // Note: Always render "current" item or flashing item, only render other selected - // items if mShowSingleSelection is false. - // - if (isHighlightAllowed()) - - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Highlight for selected but not current items - if (!isHighlightActive() && !isFlashing()) - { - LLColor4 bg_color = bgColor; - // do time-based fade of extra objects - F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); - if (getRoot() && getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bg_color, hasKeyboardFocus); - } - - // Highlight for currently selected or flashing item - if (isHighlightActive()) - { - // Background - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bgColor, hasKeyboardFocus); - // Outline - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - focusOutlineColor, false); - } - - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - focusOutlineColor, false); - if (showContent && !isFlashing()) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, - getRect().getWidth() - 2, - 0, - bgColor, true); - } - } - } - else if (mIsMouseOverTitle) - { - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - mouseOverColor, false); - } - - //--------------------------------------------------------------------------------// - // Draw DragNDrop highlight - // - if (mDragAndDropTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(FOCUS_LEFT, - focus_top, - getRect().getWidth() - 2, - focus_bottom, - bgColor, false); - if (folder_open) - { - gl_rect_2d(FOCUS_LEFT, - focus_bottom + 1, // overlap with bottom edge of above rect - getRect().getWidth() - 2, - 0, - bgColor, false); - } - mDragAndDropTarget = false; - } -} - -void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x) -{ - //--------------------------------------------------------------------------------// - // Draw the actual label text - // - font->renderUTF8(mLabel, 0, x, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, /*use_ellipses*/true); -} - -void LLFolderViewItem::draw() -{ - const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); - const bool filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : false); // If we have keyboard focus, draw selection filled - - const Params& default_params = LLUICtrlFactory::getDefaultParams(); - const S32 TOP_PAD = default_params.item_top_pad; - - const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - getViewModelItem()->update(); - - if(!mSingleFolderMode) - { - drawOpenFolderArrow(default_params, sFgColor); - } - - drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); - - //--------------------------------------------------------------------------------// - // Draw open icon - // - const S32 icon_x = mIndentation + mArrowSize + mTextPad; - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - { - mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - } - else if (mIcon) - { - mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - if (mIconOverlay && getRoot()->showItemLinkOverlays()) - { - mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - //--------------------------------------------------------------------------------// - // Exit if no label to draw - // - if (mLabel.empty()) - { - return; - } - - std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; - F32 right_x = 0; - F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - F32 text_left = (F32)getLabelXPos(); - std::string combined_string = mLabel + mLabelSuffix; - - const LLFontGL* suffix_font = getLabelFontForStyle(LLFontGL::NORMAL); - S32 filter_offset = mViewModelItem->getFilterStringOffset(); - if (filter_string_length > 0) - { - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - S32 top = getRect().getHeight() - TOP_PAD; - if(mLabelSuffix.empty() || (font == suffix_font)) - { - S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; - S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; - - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - } - else - { - S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length); - if(label_filter_length > 0) - { - S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, llmin(filter_offset, (S32)mLabel.size())) - 2; - S32 right = left + font->getWidthF32(mLabel, filter_offset, label_filter_length) + 2; - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - } - S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; - if(suffix_filter_length > 0) - { - S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); - S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset) - 2; - S32 right = left + suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length) + 2; - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - } - } - } - - LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; - - if (isFadeItem()) - { - // Fade out item color to indicate it's being cut - color.mV[VALPHA] *= 0.5f; - } - drawLabel(font, text_left, y, color, right_x); - - //--------------------------------------------------------------------------------// - // Draw label suffix - // - if (!mLabelSuffix.empty()) - { - suffix_font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x); - } - - //--------------------------------------------------------------------------------// - // Highlight string match - // - if (filter_string_length > 0) - { - if(mLabelSuffix.empty() || (font == suffix_font)) - { - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - font->renderUTF8(combined_string, filter_offset, match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x); - } - else - { - S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length); - if(label_filter_length > 0) - { - F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel, filter_offset, label_filter_length); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - font->renderUTF8(mLabel, filter_offset, match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - label_filter_length, S32_MAX, &right_x); - } - - S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; - if(suffix_filter_length > 0) - { - S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); - F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length); - F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; - suffix_font->renderUTF8(mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - suffix_filter_length, S32_MAX, &right_x); - } - } - - } - - //Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to - //be distorted...oddly. I initially added this in but didn't need it after all. So removing to prevent unnecessary bug. - //LLView::draw(); -} - -const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const -{ - return getRoot()->getFolderViewModel(); -} - -LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) -{ - return getRoot()->getFolderViewModel(); -} - -bool LLFolderViewItem::isInSelection() const -{ - return mIsSelected || (mParentFolder && mParentFolder->isInSelection()); -} - - - -///---------------------------------------------------------------------------- -/// Class LLFolderViewFolder -///---------------------------------------------------------------------------- - -LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), - mIsOpen(false), - mExpanderHighlighted(false), - mCurHeight(0.f), - mTargetHeight(0.f), - mAutoOpenCountdown(0.f), - mIsFolderComplete(false), // folder might have children that are not loaded yet. - mAreChildrenInited(false), // folder might have children that are not built yet. - mLastArrangeGeneration( -1 ), - mLastCalculatedWidth(0) -{ -} - -void LLFolderViewFolder::updateLabelRotation() -{ - if (mAutoOpenCountdown != 0.f) - { - mControlLabelRotation = mAutoOpenCountdown * -90.f; - } - else if (isOpen()) - { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLSmoothInterpolation::getInterpolant(0.04f)); - } - else - { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLSmoothInterpolation::getInterpolant(0.025f)); - } -} - -// Destroys the object -LLFolderViewFolder::~LLFolderViewFolder( void ) -{ - // The LLView base class takes care of object destruction. make sure that we - // don't have mouse or keyboard focus - gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() -} - -// addToFolder() returns true if it succeeds. false otherwise -void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) -{ - folder->addFolder(this); - - // Compute indentation since parent folder changed - mIndentation = (getParentFolder()) - ? getParentFolder()->getIndentation() + mLocalIndentation - : 0; - - if(isOpen() && folder->isOpen()) - { - requestArrange(); - } -} - -static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange"); - -// Make everything right and in the right place ready for drawing (CHUI-849) -// * Sort everything correctly if necessary -// * Turn widgets visible/invisible according to their model filtering state -// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible) -// * Reposition visible widgets so that they line up correctly with no gap -// * Compute the width and height of the current folder and its children -// * Makes sure that this view and its children are the right size -S32 LLFolderViewFolder::arrange( S32* width, S32* height ) -{ - // Sort before laying out contents - // Note that we sort from the root (CHUI-849) - if (mAreChildrenInited) - { - getRoot()->getFolderViewModel()->sort(this); - } - - LL_RECORD_BLOCK_TIME(FTM_ARRANGE); - - // evaluate mHasVisibleChildren - mHasVisibleChildren = false; - if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter()) - { - // We have to verify that there's at least one child that's not filtered out - bool found = false; - // Try the items first - for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - found = itemp->isPotentiallyVisible(); - if (found) - break; - } - if (!found) - { - // If no item found, try the folders - for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - found = folderp->isPotentiallyVisible(); - if (found) - break; - } - } - - mHasVisibleChildren = found; - } - if (!mIsFolderComplete && mAreChildrenInited) - { - mIsFolderComplete = getFolderViewModel()->isFolderComplete(this); - } - - - - // calculate height as a single item (without any children), and reshapes rectangle to match - LLFolderViewItem::arrange( width, height ); - - // clamp existing animated height so as to never get smaller than a single item - mCurHeight = llmax((F32)*height, mCurHeight); - - // initialize running height value as height of single item in case we have no children - F32 running_height = (F32)*height; - F32 target_height = (F32)*height; - - // are my children visible? - if (needsArrange()) - { - // set last arrange generation first, in case children are animating - // and need to be arranged again - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (isOpen()) - { - // Add sizes of children - S32 parent_item_height = getRect().getHeight(); - - for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) - { - LLFolderViewFolder* folderp = (*fit); - folderp->setVisible(folderp->isPotentiallyVisible()); - - if (folderp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - ll_round(running_height); - - target_height += folderp->arrange( &child_width, &child_height ); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); - } - } - for(items_t::iterator iit = mItems.begin(); - iit != mItems.end(); ++iit) - { - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->isPotentiallyVisible()); - - if (itemp->getVisible()) - { - S32 child_width = *width; - S32 child_height = 0; - S32 child_top = parent_item_height - ll_round(running_height); - - target_height += itemp->arrange( &child_width, &child_height ); - // don't change width, as this item is as wide as its parent folder by construction - itemp->reshape( itemp->getRect().getWidth(), child_height); - - running_height += (F32)child_height; - *width = llmax(*width, child_width); - itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); - } - } - } - - mTargetHeight = target_height; - // cache this width so next time we can just return it - mLastCalculatedWidth = *width; - } - else - { - // just use existing width - *width = mLastCalculatedWidth; - } - - // animate current height towards target height - if (llabs(mCurHeight - mTargetHeight) > 1.f) - { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLSmoothInterpolation::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); - - requestArrange(); - - // hide child elements that fall out of current animated height - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - // number of pixels that bottom of folder label is from top of parent folder - if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() - > ll_round(mCurHeight) + mMaxFolderItemOverlap) - { - // hide if beyond current folder height - (*fit)->setVisible(false); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - // number of pixels that bottom of item label is from top of parent folder - if (getRect().getHeight() - (*iit)->getRect().mBottom - > ll_round(mCurHeight) + mMaxFolderItemOverlap) - { - (*iit)->setVisible(false); - } - } - } - else - { - mCurHeight = mTargetHeight; - } - - // don't change width as this item is already as wide as its parent folder - reshape(getRect().getWidth(),ll_round(mCurHeight)); - - // pass current height value back to parent - *height = ll_round(mCurHeight); - - return ll_round(mTargetHeight); -} - -bool LLFolderViewFolder::needsArrange() -{ - return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); -} - -bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation) -{ - return getViewModelItem()->descendantsPassedFilter(filter_generation); -} - -// Passes selection information on to children and record selection -// information if necessary. -bool LLFolderViewFolder::setSelection(LLFolderViewItem* selection, bool openitem, - bool take_keyboard_focus) -{ - bool rv = false; - if (selection == this) - { - if (!isSelected()) - { - selectItem(); - } - rv = true; - } - else - { - if (isSelected()) - { - deselectItem(); - } - rv = false; - } - bool child_selected = false; - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = true; - child_selected = true; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) - { - rv = true; - child_selected = true; - } - } - if(openitem && child_selected && !mSingleFolderMode) - { - setOpenArrangeRecursively(true); - } - return rv; -} - -// This method is used to change the selection of an item. -// Recursively traverse all children; if 'selection' is 'this' then change -// the select status if necessary. -// Returns true if the selection state of this folder, or of a child, was changed. -bool LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, bool selected) -{ - bool rv = false; - if(selection == this) - { - if (isSelected() != selected) - { - rv = true; - if (selected) - { - selectItem(); - } - else - { - deselectItem(); - } - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if((*fit)->changeSelection(selection, selected)) - { - rv = true; - } - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if((*iit)->changeSelection(selection, selected)) - { - rv = true; - } - } - return rv; -} - -LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) -{ - if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; - - std::deque item_a_ancestors; - - LLFolderViewFolder* parent = item_a->getParentFolder(); - while(parent) - { - item_a_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - std::deque item_b_ancestors; - - parent = item_b->getParentFolder(); - while(parent) - { - item_b_ancestors.push_back(parent); - parent = parent->getParentFolder(); - } - - LLFolderViewFolder* common_ancestor = item_a->getRoot(); - - while(item_a_ancestors.size() > item_b_ancestors.size()) - { - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - } - - while(item_b_ancestors.size() > item_a_ancestors.size()) - { - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - while(item_a_ancestors.size()) - { - common_ancestor = item_a_ancestors.front(); - - if (item_a_ancestors.front() == item_b_ancestors.front()) - { - // which came first, sibling a or sibling b? - for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - - for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - - if (item == item_a) - { - reverse = false; - return common_ancestor; - } - if (item == item_b) - { - reverse = true; - return common_ancestor; - } - } - break; - } - - item_a = item_a_ancestors.front(); - item_a_ancestors.pop_front(); - item_b = item_b_ancestors.front(); - item_b_ancestors.pop_front(); - } - - return NULL; -} - -void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items) -{ - bool selecting = start == NULL; - if (reverse) - { - for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } - else - { - for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); - it != end_it; - ++it) - { - if (*it == end) - { - return; - } - - if (selecting && (*it)->getVisible()) - { - items.push_back(*it); - } - - if (*it == start) - { - selecting = true; - } - } - } -} - -void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) -{ - if (!getRoot()->getAllowMultiSelect()) - return; - - LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); - if (cur_selected_item == NULL) - { - cur_selected_item = new_selection; - } - - - bool reverse = false; - LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); - if (!common_ancestor) - return; - - LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; - LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); - - std::vector items_to_select_forward; - - while (cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); - - last_selected_item_from_cur = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - std::vector items_to_select_reverse; - - LLFolderViewItem* last_selected_item_from_new = new_selection; - cur_folder = new_selection->getParentFolder(); - while (cur_folder != common_ancestor) - { - cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); - - last_selected_item_from_new = cur_folder; - cur_folder = cur_folder->getParentFolder(); - } - - common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); - - for (std::vector::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); - it != end_it; - ++it) - { - items_to_select_forward.push_back(*it); - } - - LLFolderView* root = getRoot(); - - bool selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected - - // array always go from 'will be selected' to ' will be unselected', iterate - // in opposite direction to simplify identification of 'point of origin' in - // case it is in the list we are working with - for (std::vector::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend(); - it != end_it; - ++it) - { - LLFolderViewItem* item = *it; - bool selected = item->isSelected(); - if (!selection_reverse && selected) - { - // it is our 'point of origin' where we shift/expand from - // don't deselect it - selection_reverse = true; - } - else - { - root->changeSelection(item, !selected); - } - } - - if (selection_reverse) - { - // at some point we reversed selection, first element should be deselected - root->changeSelection(last_selected_item_from_cur, false); - } - - // element we expand to should always be selected - root->changeSelection(new_selection, true); -} - - -void LLFolderViewFolder::destroyView() -{ - while (!mItems.empty()) - { - LLFolderViewItem *itemp = mItems.back(); - mItems.pop_back(); - itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems - } - - while (!mFolders.empty()) - { - LLFolderViewFolder *folderp = mFolders.back(); - mFolders.pop_back(); - folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders - } - - LLFolderViewItem::destroyView(); -} - -// extractItem() removes the specified item from the folder, but -// doesn't delete it. -void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model ) -{ - if (item->isSelected()) - getRoot()->clearSelection(); - items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); - if(it == mItems.end()) - { - // This is an evil downcast. However, it's only doing - // pointer comparison to find if (which it should be ) the - // item is in the container, so it's pretty safe. - LLFolderViewFolder* f = static_cast(item); - folders_t::iterator ft; - ft = std::find(mFolders.begin(), mFolders.end(), f); - if (ft != mFolders.end()) - { - mFolders.erase(ft); - } - } - else - { - mItems.erase(it); - } - //item has been removed, need to update filter - if (deparent_model) - { - // in some cases model does not belong to parent view, is shared between views - getViewModelItem()->removeChild(item->getViewModelItem()); - } - //because an item is going away regardless of filter status, force rearrange - requestArrange(); - removeChild(item); -} - -bool LLFolderViewFolder::isMovable() -{ - if( !(getViewModelItem()->isItemMovable()) ) - { - return false; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isMovable()) - { - return false; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isMovable()) - { - return false; - } - } - return true; -} - - -bool LLFolderViewFolder::isRemovable() -{ - if( !(getViewModelItem()->isItemRemovable()) ) - { - return false; - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - if(!(*iit)->isRemovable()) - { - return false; - } - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - if(!(*fit)->isRemovable()) - { - return false; - } - } - return true; -} - -void LLFolderViewFolder::destroyRoot() -{ - delete this; -} - -// this is an internal method used for adding items to folders. -void LLFolderViewFolder::addItem(LLFolderViewItem* item) -{ - if (item->getParentFolder()) - { - item->getParentFolder()->extractItem(item); - } - item->setParentFolder(this); - - mItems.push_back(item); - - item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); - item->setVisible(false); - - addChild(item); - - // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it - // Note: this happens when models are created before views or shared between views - if (!item->getViewModelItem()->hasParent()) - { - getViewModelItem()->addChild(item->getViewModelItem()); - } -} - -// this is an internal method used for adding items to folders. -void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) -{ - if (folder->mParentFolder) - { - folder->mParentFolder->extractItem(folder); - } - folder->mParentFolder = this; - mFolders.push_back(folder); - folder->setOrigin(0, 0); - folder->reshape(getRect().getWidth(), 0); - folder->setVisible(false); - // rearrange all descendants too, as our indentation level might have changed - //folder->requestArrange(); - //requestSort(); - - addChild(folder); - - // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it - // Note: this happens when models are created before views or shared between views - if (!folder->getViewModelItem()->hasParent()) - { - getViewModelItem()->addChild(folder->getViewModelItem()); - } -} - -void LLFolderViewFolder::requestArrange() -{ - mLastArrangeGeneration = -1; - // flag all items up to root - if (mParentFolder) - { - mParentFolder->requestArrange(); - } -} - -void LLFolderViewFolder::toggleOpen() -{ - setOpen(!isOpen()); -} - -// Force a folder open or closed -void LLFolderViewFolder::setOpen(bool openitem) -{ - if(mSingleFolderMode) - { - // navigateToFolder can destroy this view - // delay it in case setOpen was called from click or key processing - doOnIdleOneTime([this]() - { - getViewModelItem()->navigateToFolder(); - }); - } - else - { - setOpenArrangeRecursively(openitem); - } -} - -void LLFolderViewFolder::setOpenArrangeRecursively(bool openitem, ERecurseType recurse) -{ - bool was_open = isOpen(); - mIsOpen = openitem; - if(!was_open && openitem) - { - getViewModelItem()->openItem(); - // openItem() will request content, it won't be incomplete - mIsFolderComplete = true; - } - else if(was_open && !openitem) - { - getViewModelItem()->closeItem(); - } - - if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ - } - } - if (mParentFolder - && (recurse == RECURSE_UP - || recurse == RECURSE_UP_DOWN)) - { - mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); - } - - if (was_open != isOpen()) - { - requestArrange(); - } -} - -bool LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - bool drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - bool accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); - if (accepted) - { - mDragAndDropTarget = true; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - // drag and drop to child item, so clear pending auto-opens - getRoot()->autoOpenTest(NULL); - - return true; -} - -void LLFolderViewFolder::openItem( void ) -{ - toggleOpen(); -} - -void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) -{ - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - functor.doItem((*fit)); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) -{ - functor.doFolder(this); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - functor.doItem((*iit)); - } -} - -// LLView functionality -bool LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, - bool drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - bool handled = false; - - if (isOpen()) - { - handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); - } - - if (!handled) - { - handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewFolder" << LL_ENDL; - } - - return true; -} - -bool LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, - bool drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - if (!mAllowDrop) - { - *accept = ACCEPT_NO; - tooltip_msg = LLTrans::getString("TooltipOutboxCannotDropOnRoot"); - return true; - } - - bool accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); - - if (accepted) - { - mDragAndDropTarget = true; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - getRoot()->autoOpenTest(this); - } - - return true; -} - - -bool LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) -{ - bool handled = false; - - if( isOpen() ) - { - handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; - } - if (!handled) - { - handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); - } - return handled; -} - - -bool LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) -{ - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); - - bool handled = LLView::handleHover(x, y, mask); - - if (!handled) - { - // this doesn't do child processing - handled = LLFolderViewItem::handleHover(x, y, mask); - } - - return handled; -} - -bool LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - bool handled = false; - if( isOpen() ) - { - handled = childrenHandleMouseDown(x,y,mask) != NULL; - } - if( !handled ) - { - if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) - && !mSingleFolderMode) - { - toggleOpen(); - handled = true; - } - else - { - // do normal selection logic - handled = LLFolderViewItem::handleMouseDown(x, y, mask); - } - } - - return handled; -} - -bool LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - bool handled = false; - if(mSingleFolderMode) - { - static LLUICachedControl double_click_new_window("SingleModeDoubleClickOpenWindow", false); - if (double_click_new_window) - { - getViewModelItem()->navigateToFolder(true); - } - else - { - // navigating is going to destroy views and change children - // delay it untill handleDoubleClick processing is complete - doOnIdleOneTime([this]() - { - getViewModelItem()->navigateToFolder(false); - }); - } - return true; - } - - if( isOpen() ) - { - handled = childrenHandleDoubleClick( x, y, mask ) != NULL; - } - if( !handled ) - { - if(mDoubleClickOverride) - { - static LLUICachedControl double_click_action("MultiModeDoubleClickFolder", false); - if (double_click_action == 1) - { - getViewModelItem()->navigateToFolder(true); - return true; - } - if (double_click_action == 2) - { - getViewModelItem()->navigateToFolder(false, true); - return true; - } - } - if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) - { - // don't select when user double-clicks plus sign - // so as not to contradict single-click behavior - toggleOpen(); - } - else - { - getRoot()->setSelection(this, false); - toggleOpen(); - } - handled = true; - } - return handled; -} - -void LLFolderViewFolder::draw() -{ - updateLabelRotation(); - - LLFolderViewItem::draw(); - - // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) - { - LLView::draw(); - } - - mExpanderHighlighted = false; -} - -// this does prefix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, bool include_children ) -{ - bool found_item = false; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at beginning - if(item == NULL) - { - found_item = true; - } - - // find current item among children - folders_t::iterator fit = mFolders.begin(); - folders_t::iterator fend = mFolders.end(); - - items_t::iterator iit = mItems.begin(); - items_t::iterator iend = mItems.end(); - - // if not trivially starting at the beginning, we have to find the current item - if (!found_item) - { - // first, look among folders, since they are always above items - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = true; - // if we are on downwards traversal - if (include_children && (*fit)->isOpen()) - { - // look for first descendant - return (*fit)->getNextFromChild(NULL, true); - } - // otherwise advance to next folder - ++fit; - include_children = true; - break; - } - } - - // didn't find in folders? Check items... - if (!found_item) - { - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = true; - // point to next item - ++iit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(false); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found folder, continue through folders - // searching for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - // turn on downwards traversal for next folder - ++fit; - } - - if (fit != fend) - { - result = (*fit); - } - else - { - // otherwise, scan for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - // check to see if we have a valid item - if (iit != iend) - { - result = (*iit); - } - } - - if( !result && mParentFolder ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // and skip children for this folder, as we've already discounted them - result = mParentFolder->getNextFromChild(this, false); - } - - return result; -} - -// this does postfix traversal, as folders are listed above their contents -LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, bool include_children ) -{ - bool found_item = false; - - LLFolderViewItem* result = NULL; - // when not starting from a given item, start at end - if(item == NULL) - { - found_item = true; - } - - // find current item among children - folders_t::reverse_iterator fit = mFolders.rbegin(); - folders_t::reverse_iterator fend = mFolders.rend(); - - items_t::reverse_iterator iit = mItems.rbegin(); - items_t::reverse_iterator iend = mItems.rend(); - - // if not trivially starting at the end, we have to find the current item - if (!found_item) - { - // first, look among items, since they are always below the folders - for(; iit != iend; ++iit) - { - if(item == (*iit)) - { - found_item = true; - // point to next item - ++iit; - break; - } - } - - // didn't find in items? Check folders... - if (!found_item) - { - for(; fit != fend; ++fit) - { - if(item == (*fit)) - { - found_item = true; - // point to next folder - ++fit; - break; - } - } - } - } - - if (!found_item) - { - // you should never call this method with an item that isn't a child - // so we should always find something - llassert(false); - return NULL; - } - - // at this point, either iit or fit point to a candidate "next" item - // if both are out of range, we need to punt up to our parent - - // now, starting from found item, continue through items - // searching for next visible item - while(iit != iend && !(*iit)->getVisible()) - { - ++iit; - } - - if (iit != iend) - { - // we found an appropriate item - result = (*iit); - } - else - { - // otherwise, scan for next visible folder - while(fit != fend && !(*fit)->getVisible()) - { - ++fit; - } - - // check to see if we have a valid folder - if (fit != fend) - { - // try selecting child element of this folder - if ((*fit)->isOpen() && include_children) - { - result = (*fit)->getPreviousFromChild(NULL); - } - else - { - result = (*fit); - } - } - } - - if( !result ) - { - // If there are no siblings or children to go to, recurse up one level in the tree - // which gets back to this folder, which will only be visited if it is a valid, visible item - result = this; - } - - return result; -} - +/** +* @file llfolderviewitem.cpp +* @brief Items and folders that can appear in a hierarchical folder view +* +* $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 "../newview/llviewerprecompiledheaders.h" + +#include "llflashtimer.h" + +#include "linden_common.h" +#include "llfolderviewitem.h" +#include "llfolderview.h" +#include "llfolderviewmodel.h" +#include "llpanel.h" +#include "llcallbacklist.h" +#include "llcriticaldamp.h" +#include "llclipboard.h" +#include "llfocusmgr.h" // gFocusMgr +#include "lltrans.h" +#include "llwindow.h" + +///---------------------------------------------------------------------------- +/// Class LLFolderViewItem +///---------------------------------------------------------------------------- + +static LLDefaultChildRegistry::Register r("folder_view_item"); + +// statics +std::map LLFolderViewItem::sFonts; // map of styles to fonts + +bool LLFolderViewItem::sColorSetInitialized = false; +LLUIColor LLFolderViewItem::sFgColor; +LLUIColor LLFolderViewItem::sHighlightBgColor; +LLUIColor LLFolderViewItem::sFlashBgColor; +LLUIColor LLFolderViewItem::sFocusOutlineColor; +LLUIColor LLFolderViewItem::sMouseOverColor; +LLUIColor LLFolderViewItem::sFilterBGColor; +LLUIColor LLFolderViewItem::sFilterTextColor; +LLUIColor LLFolderViewItem::sSuffixColor; +LLUIColor LLFolderViewItem::sSearchStatusColor; + +// only integers can be initialized in header +const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; +const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f; + +const LLColor4U DEFAULT_WHITE(255, 255, 255); + + +//static +LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) +{ + LLFontGL* rtn = sFonts[style]; + if (!rtn) // grab label font with this style, lazily + { + LLFontDescriptor labelfontdesc("SansSerif", "Small", style); + rtn = LLFontGL::getFont(labelfontdesc); + if (!rtn) + { + rtn = LLFontGL::getFontDefault(); + } + sFonts[style] = rtn; + } + return rtn; +} + +//static +void LLFolderViewItem::initClass() +{ +} + +//static +void LLFolderViewItem::cleanupClass() +{ + sFonts.clear(); +} + + +// NOTE: Optimize this, we call it a *lot* when opening a large inventory +LLFolderViewItem::Params::Params() +: root(), + listener(), + folder_arrow_image("folder_arrow_image"), + folder_indentation("folder_indentation"), + selection_image("selection_image"), + item_height("item_height"), + item_top_pad("item_top_pad"), + creation_date(), + allow_wear("allow_wear", true), + allow_drop("allow_drop", true), + font_color("font_color"), + font_highlight_color("font_highlight_color"), + left_pad("left_pad", 0), + icon_pad("icon_pad", 0), + icon_width("icon_width", 0), + text_pad("text_pad", 0), + text_pad_right("text_pad_right", 0), + single_folder_mode("single_folder_mode", false), + double_click_override("double_click_override", false), + arrow_size("arrow_size", 0), + max_folder_item_overlap("max_folder_item_overlap", 0) +{ } + +// Default constructor +LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) +: LLView(p), + mLabelWidth(0), + mLabelWidthDirty(false), + mSuffixNeedsRefresh(false), + mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), + mParentFolder( NULL ), + mIsSelected( false ), + mIsCurSelection( false ), + mSelectPending(false), + mIsItemCut(false), + mCutGeneration(0), + mLabelStyle( LLFontGL::NORMAL ), + mHasVisibleChildren(false), + mLocalIndentation(p.folder_indentation), + mIndentation(0), + mItemHeight(p.item_height), + mControlLabelRotation(0.f), + mDragAndDropTarget(false), + mLabel(p.name), + mRoot(p.root), + mViewModelItem(p.listener), + mIsMouseOverTitle(false), + mAllowWear(p.allow_wear), + mAllowDrop(p.allow_drop), + mFontColor(p.font_color), + mFontHighlightColor(p.font_highlight_color), + mLeftPad(p.left_pad), + mIconPad(p.icon_pad), + mIconWidth(p.icon_width), + mTextPad(p.text_pad), + mTextPadRight(p.text_pad_right), + mArrowSize(p.arrow_size), + mSingleFolderMode(p.single_folder_mode), + mMaxFolderItemOverlap(p.max_folder_item_overlap), + mDoubleClickOverride(p.double_click_override) +{ + if (!sColorSetInitialized) + { + sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); + sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); + sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); + sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); + sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); + sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); + sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); + sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); + sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); + sColorSetInitialized = true; + } + + if (mViewModelItem) + { + mViewModelItem->setFolderViewItem(this); + } +} + +// Destroys the object +LLFolderViewItem::~LLFolderViewItem() +{ + mViewModelItem = NULL; + gFocusMgr.removeKeyboardFocusWithoutCallback(this); +} + +bool LLFolderViewItem::postBuild() +{ + LLFolderViewModelItem* vmi = getViewModelItem(); + llassert(vmi); // not supposed to happen, if happens, find out why and fix + if (vmi) + { + // getDisplayName() is expensive (due to internal getLabelSuffix() and name building) + // it also sets search strings so it requires a filter reset + mLabel = vmi->getDisplayName(); + setToolTip(vmi->getName()); + + // Dirty the filter flag of the model from the view (CHUI-849) + vmi->dirtyFilter(); + } + + // Don't do full refresh on constructor if it is possible to avoid + // it significantly slows down bulk view creation. + // Todo: Ideally we need to move getDisplayName() out of constructor as well. + // Like: make a logic that will let filter update search string, + // while LLFolderViewItem::arrange() updates visual part + mSuffixNeedsRefresh = true; + mLabelWidthDirty = true; + return true; +} + +LLFolderView* LLFolderViewItem::getRoot() +{ + return mRoot; +} + +const LLFolderView* LLFolderViewItem::getRoot() const +{ + return mRoot; +} +// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor. +bool LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor ) +{ + LLFolderViewItem* root = this; + while( root->mParentFolder ) + { + if( root->mParentFolder == potential_ancestor ) + { + return true; + } + root = root->mParentFolder; + } + return false; +} + +LLFolderViewItem* LLFolderViewItem::getNextOpenNode(bool include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children ); + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit last item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(bool include_children) +{ + if (!mParentFolder) + { + return NULL; + } + + LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children ); + + // Skip over items that are invisible or are hidden from the UI. + while(itemp && !itemp->getVisible()) + { + LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children ); + if (itemp == next_itemp) + { + // hit first item + return itemp->getVisible() ? itemp : this; + } + itemp = next_itemp; + } + + return itemp; +} + +bool LLFolderViewItem::passedFilter(S32 filter_generation) +{ + return getViewModelItem()->passedFilter(filter_generation); +} + +bool LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) +{ + if (filter_generation < 0) + { + filter_generation = getFolderViewModel()->getFilter().getFirstSuccessGeneration(); + } + LLFolderViewModelItem* model = getViewModelItem(); + bool visible = model->passedFilter(filter_generation); + if (model->getMarkedDirtyGeneration() >= filter_generation) + { + // unsure visibility state + // retaining previous visibility until item is updated or filter generation changes + visible |= getVisible(); + } + return visible; +} + +void LLFolderViewItem::refresh() +{ + LLFolderViewModelItem& vmi = *getViewModelItem(); + + mLabel = vmi.getDisplayName(); + setToolTip(vmi.getName()); + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); + + if (mRoot->useLabelSuffix()) + { + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); + } + + // Dirty the filter flag of the model from the view (CHUI-849) + vmi.dirtyFilter(); + + mLabelWidthDirty = true; + mSuffixNeedsRefresh = false; +} + +void LLFolderViewItem::refreshSuffix() +{ + LLFolderViewModelItem const* vmi = getViewModelItem(); + + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() + mIcon = vmi->getIcon(); + mIconOpen = vmi->getIconOpen(); + mIconOverlay = vmi->getIconOverlay(); + + if (mRoot->useLabelSuffix()) + { + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list + mLabelStyle = vmi->getLabelStyle(); + mLabelSuffix = vmi->getLabelSuffix(); + } + + mLabelWidthDirty = true; + mSuffixNeedsRefresh = false; +} + +// Utility function for LLFolderView +void LLFolderViewItem::arrangeAndSet(bool set_selection, + bool take_keyboard_focus) +{ + LLFolderView* root = getRoot(); + if (getParentFolder()) + { + getParentFolder()->requestArrange(); + } + if(set_selection) + { + getRoot()->setSelection(this, true, take_keyboard_focus); + if(root) + { + root->scrollToShowSelection(); + } + } +} + + +std::set LLFolderViewItem::getSelectionList() const +{ + std::set selection; + return selection; +} + +// addToFolder() returns true if it succeeds. false otherwise +void LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) +{ + folder->addItem(this); + + // Compute indentation since parent folder changed + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + mLocalIndentation + : 0; +} + + +// Finds width and height of this object and its children. Also +// makes sure that this view and its children are the right size. +S32 LLFolderViewItem::arrange( S32* width, S32* height ) +{ + // Only indent deeper items in hierarchy + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + mLocalIndentation + : 0; + if (mLabelWidthDirty) + { + if (mSuffixNeedsRefresh) + { + // Expensive. But despite refreshing label, + // it is purely visual, so it is fine to do at our laisure + refreshSuffix(); + } + mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix) + mLabelPaddingRight; + mLabelWidthDirty = false; + } + + *width = llmax(*width, mLabelWidth); + + // determine if we need to use ellipses to avoid horizontal scroll. EXT-719 + bool use_ellipses = getRoot()->getUseEllipses(); + if (use_ellipses) + { + // limit to set rect to avoid horizontal scrollbar + *width = llmin(*width, getRoot()->getRect().getWidth()); + } + *height = getItemHeight(); + return *height; +} + +S32 LLFolderViewItem::getItemHeight() const +{ + return mItemHeight; +} + +S32 LLFolderViewItem::getLabelXPos() +{ + return getIndentation() + mArrowSize + mTextPad + mIconWidth + mIconPad; +} + +S32 LLFolderViewItem::getIconPad() +{ + return mIconPad; +} + +S32 LLFolderViewItem::getTextPad() +{ + return mTextPad; +} + +// *TODO: This can be optimized a lot by simply recording that it is +// selected in the appropriate places, and assuming that set selection +// means 'deselect' for a leaf item. Do this optimization after +// multiple selection is implemented to make sure it all plays nice +// together. +bool LLFolderViewItem::setSelection(LLFolderViewItem* selection, bool openitem, bool take_keyboard_focus) +{ + if (selection == this && !mIsSelected) + { + selectItem(); + } + else if (mIsSelected) // Deselect everything else. + { + deselectItem(); + } + return mIsSelected; +} + +bool LLFolderViewItem::changeSelection(LLFolderViewItem* selection, bool selected) +{ + if (selection == this) + { + if (mIsSelected) + { + deselectItem(); + } + else + { + selectItem(); + } + return true; + } + return false; +} + +void LLFolderViewItem::deselectItem(void) +{ + mIsSelected = false; +} + +void LLFolderViewItem::selectItem(void) +{ + if (!mIsSelected) + { + mIsSelected = true; + getViewModelItem()->selectItem(); + } +} + +bool LLFolderViewItem::isMovable() +{ + return getViewModelItem()->isItemMovable(); +} + +bool LLFolderViewItem::isRemovable() +{ + return getViewModelItem()->isItemRemovable(); +} + +void LLFolderViewItem::destroyView() +{ + getRoot()->removeFromSelectionList(this); + + if (mParentFolder) + { + // removeView deletes me + mParentFolder->extractItem(this); + } + delete this; +} + +// Call through to the viewed object and return true if it can be +// removed. +//bool LLFolderViewItem::removeRecursively(bool single_item) +bool LLFolderViewItem::remove() +{ + if(!isRemovable()) + { + return false; + } + return getViewModelItem()->removeItem(); +} + +// Build an appropriate context menu for the item. +void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + getViewModelItem()->buildContextMenu(menu, flags); +} + +void LLFolderViewItem::openItem( void ) +{ + if (mAllowWear || !getViewModelItem()->isItemWearable()) + { + getViewModelItem()->openItem(); + } +} + +void LLFolderViewItem::rename(const std::string& new_name) +{ + if( !new_name.empty() ) + { + getViewModelItem()->renameItem(new_name); + } +} + +const std::string& LLFolderViewItem::getName( void ) const +{ + static const std::string noName(""); + return getViewModelItem() ? getViewModelItem()->getName() : noName; +} + +// LLView functionality +bool LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + if(!mIsSelected) + { + getRoot()->setSelection(this, false); + } + make_ui_sound("UISndClick"); + return true; +} + +bool LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + if (LLView::childrenHandleMouseDown(x, y, mask)) + { + return true; + } + + // No handler needed for focus lost since this class has no + // state that depends on it. + gFocusMgr.setMouseCapture( this ); + + if (!mIsSelected) + { + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, false); + } + make_ui_sound("UISndClick"); + } + else + { + // If selected, we reserve the decision of deselecting/reselecting to the mouse up moment. + // This is necessary so we maintain selection consistent when starting a drag. + mSelectPending = true; + } + + mDragStartX = x; + mDragStartY = y; + return true; +} + +bool LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) +{ + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + if( hasMouseCapture() && isMovable() ) + { + LLFolderView* root = getRoot(); + + if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD + && root->getAllowDrag() + && root->getCurSelectedItem() + && root->startDrag()) + { + // RN: when starting drag and drop, clear out last auto-open + root->autoOpenTest(NULL); + root->setShowSelectionContext(true); + + // Release keyboard focus, so that if stuff is dropped into the + // world, pressing the delete key won't blow away the inventory + // item. + gFocusMgr.setKeyboardFocus(NULL); + + getWindow()->setCursor(UI_CURSOR_ARROW); + } + else if (x != mDragStartX || y != mDragStartY) + { + getWindow()->setCursor(UI_CURSOR_NOLOCKED); + } + + root->clearHoveredItem(); + return true; + } + else + { + LLFolderView* pRoot = getRoot(); + pRoot->setHoveredItem(this); + pRoot->setShowSelectionContext(false); + getWindow()->setCursor(UI_CURSOR_ARROW); + // let parent handle this then... + return false; + } +} + + +bool LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + openItem(); + return true; +} + +bool LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + if (LLView::childrenHandleMouseUp(x, y, mask)) + { + return true; + } + + // if mouse hasn't moved since mouse down... + if ( pointInView(x, y) && mSelectPending ) + { + //...then select + if(mask & MASK_CONTROL) + { + getRoot()->changeSelection(this, !mIsSelected); + } + else if (mask & MASK_SHIFT) + { + getParentFolder()->extendSelectionTo(this); + } + else + { + getRoot()->setSelection(this, false); + } + } + + mSelectPending = false; + + if( hasMouseCapture() ) + { + if (getRoot()) + { + getRoot()->setShowSelectionContext(false); + } + gFocusMgr.setMouseCapture( NULL ); + } + return true; +} + +void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = false; + + // NOTE: LLViewerWindow::updateUI() calls "enter" before "leave"; if the mouse moved to another item, we can't just outright clear it + LLFolderView* pRoot = getRoot(); + if (this == pRoot->getHoveredItem()) + { + pRoot->clearHoveredItem(); + } +} + +bool LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + bool handled = false; + bool accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + handled = accepted; + if (accepted) + { + mDragAndDropTarget = true; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + if(mParentFolder && !handled) + { + // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event. + mRoot->setDraggingOverItem(this); + handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + mRoot->setDraggingOverItem(NULL); + } + if (handled) + { + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewItem" << LL_ENDL; + } + + return handled; +} + +void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color) +{ + //--------------------------------------------------------------------------------// + // Draw open folder arrow + // + const S32 TOP_PAD = default_params.item_top_pad; + + if (hasVisibleChildren() || !isFolderComplete()) + { + LLUIImage* arrow_image = default_params.folder_arrow_image; + gl_draw_scaled_rotated_image( + mIndentation, getRect().getHeight() - mArrowSize - mTextPad - TOP_PAD, + mArrowSize, mArrowSize, mControlLabelRotation, arrow_image->getImage(), fg_color); + } +} + +/*virtual*/ bool LLFolderViewItem::isHighlightAllowed() +{ + return mIsSelected; +} + +/*virtual*/ bool LLFolderViewItem::isHighlightActive() +{ + return mIsCurSelection; +} + +/*virtual*/ bool LLFolderViewItem::isFadeItem() +{ + LLClipboard& clipboard = LLClipboard::instance(); + if (mCutGeneration != clipboard.getGeneration()) + { + mCutGeneration = clipboard.getGeneration(); + mIsItemCut = clipboard.isCutMode() + && ((getParentFolder() && getParentFolder()->isFadeItem()) + || getViewModelItem()->isCutToClipboard()); + } + return mIsItemCut; +} + +void LLFolderViewItem::drawHighlight(const bool showContent, const bool hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, + const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) +{ + const S32 focus_top = getRect().getHeight(); + const S32 focus_bottom = getRect().getHeight() - mItemHeight; + const bool folder_open = (getRect().getHeight() > mItemHeight + 4); + const S32 FOCUS_LEFT = 1; + + // Determine which background color to use for highlighting + LLUIColor bgColor = (isFlashing() ? flashColor : selectColor); + + //--------------------------------------------------------------------------------// + // Draw highlight for selected items + // Note: Always render "current" item or flashing item, only render other selected + // items if mShowSingleSelection is false. + // + if (isHighlightAllowed()) + + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Highlight for selected but not current items + if (!isHighlightActive() && !isFlashing()) + { + LLColor4 bg_color = bgColor; + // do time-based fade of extra objects + F32 fade_time = (getRoot() ? getRoot()->getSelectionFadeElapsedTime() : 0.0f); + if (getRoot() && getRoot()->getShowSingleSelection()) + { + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); + } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bg_color, hasKeyboardFocus); + } + + // Highlight for currently selected or flashing item + if (isHighlightActive()) + { + // Background + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bgColor, hasKeyboardFocus); + // Outline + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + focusOutlineColor, false); + } + + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + focusOutlineColor, false); + if (showContent && !isFlashing()) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, + getRect().getWidth() - 2, + 0, + bgColor, true); + } + } + } + else if (mIsMouseOverTitle) + { + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + mouseOverColor, false); + } + + //--------------------------------------------------------------------------------// + // Draw DragNDrop highlight + // + if (mDragAndDropTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(FOCUS_LEFT, + focus_top, + getRect().getWidth() - 2, + focus_bottom, + bgColor, false); + if (folder_open) + { + gl_rect_2d(FOCUS_LEFT, + focus_bottom + 1, // overlap with bottom edge of above rect + getRect().getWidth() - 2, + 0, + bgColor, false); + } + mDragAndDropTarget = false; + } +} + +void LLFolderViewItem::drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x) +{ + //--------------------------------------------------------------------------------// + // Draw the actual label text + // + font->renderUTF8(mLabel, 0, x, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, getRect().getWidth() - (S32) x - mLabelPaddingRight, &right_x, /*use_ellipses*/true); +} + +void LLFolderViewItem::draw() +{ + const bool show_context = (getRoot() ? getRoot()->getShowSelectionContext() : false); + const bool filled = show_context || (getRoot() ? getRoot()->getParentPanel()->hasFocus() : false); // If we have keyboard focus, draw selection filled + + const Params& default_params = LLUICtrlFactory::getDefaultParams(); + const S32 TOP_PAD = default_params.item_top_pad; + + const LLFontGL* font = getLabelFontForStyle(mLabelStyle); + + getViewModelItem()->update(); + + if(!mSingleFolderMode) + { + drawOpenFolderArrow(default_params, sFgColor); + } + + drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); + + //--------------------------------------------------------------------------------// + // Draw open icon + // + const S32 icon_x = mIndentation + mArrowSize + mTextPad; + if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + { + mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + } + else if (mIcon) + { + mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + if (mIconOverlay && getRoot()->showItemLinkOverlays()) + { + mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + } + + //--------------------------------------------------------------------------------// + // Exit if no label to draw + // + if (mLabel.empty()) + { + return; + } + + std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; + F32 right_x = 0; + F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + F32 text_left = (F32)getLabelXPos(); + std::string combined_string = mLabel + mLabelSuffix; + + const LLFontGL* suffix_font = getLabelFontForStyle(LLFontGL::NORMAL); + S32 filter_offset = mViewModelItem->getFilterStringOffset(); + if (filter_string_length > 0) + { + S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + S32 top = getRect().getHeight() - TOP_PAD; + if(mLabelSuffix.empty() || (font == suffix_font)) + { + S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; + S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; + + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + } + else + { + S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length); + if(label_filter_length > 0) + { + S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, llmin(filter_offset, (S32)mLabel.size())) - 2; + S32 right = left + font->getWidthF32(mLabel, filter_offset, label_filter_length) + 2; + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + } + S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; + if(suffix_filter_length > 0) + { + S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); + S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset) - 2; + S32 right = left + suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length) + 2; + LLUIImage* box_image = default_params.selection_image; + LLRect box_rect(left, top, right, bottom); + box_image->draw(box_rect, sFilterBGColor); + } + } + } + + LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; + + if (isFadeItem()) + { + // Fade out item color to indicate it's being cut + color.mV[VALPHA] *= 0.5f; + } + drawLabel(font, text_left, y, color, right_x); + + //--------------------------------------------------------------------------------// + // Draw label suffix + // + if (!mLabelSuffix.empty()) + { + suffix_font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + S32_MAX, S32_MAX, &right_x); + } + + //--------------------------------------------------------------------------------// + // Highlight string match + // + if (filter_string_length > 0) + { + if(mLabelSuffix.empty() || (font == suffix_font)) + { + F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + font->renderUTF8(combined_string, filter_offset, match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + filter_string_length, S32_MAX, &right_x); + } + else + { + S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length); + if(label_filter_length > 0) + { + F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel, filter_offset, label_filter_length); + F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + font->renderUTF8(mLabel, filter_offset, match_string_left, yy, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + label_filter_length, S32_MAX, &right_x); + } + + S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length; + if(suffix_filter_length > 0) + { + S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); + F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length); + F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; + suffix_font->renderUTF8(mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + suffix_filter_length, S32_MAX, &right_x); + } + } + + } + + //Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to + //be distorted...oddly. I initially added this in but didn't need it after all. So removing to prevent unnecessary bug. + //LLView::draw(); +} + +const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) const +{ + return getRoot()->getFolderViewModel(); +} + +LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) +{ + return getRoot()->getFolderViewModel(); +} + +bool LLFolderViewItem::isInSelection() const +{ + return mIsSelected || (mParentFolder && mParentFolder->isInSelection()); +} + + + +///---------------------------------------------------------------------------- +/// Class LLFolderViewFolder +///---------------------------------------------------------------------------- + +LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): + LLFolderViewItem( p ), + mIsOpen(false), + mExpanderHighlighted(false), + mCurHeight(0.f), + mTargetHeight(0.f), + mAutoOpenCountdown(0.f), + mIsFolderComplete(false), // folder might have children that are not loaded yet. + mAreChildrenInited(false), // folder might have children that are not built yet. + mLastArrangeGeneration( -1 ), + mLastCalculatedWidth(0) +{ +} + +void LLFolderViewFolder::updateLabelRotation() +{ + if (mAutoOpenCountdown != 0.f) + { + mControlLabelRotation = mAutoOpenCountdown * -90.f; + } + else if (isOpen()) + { + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLSmoothInterpolation::getInterpolant(0.04f)); + } + else + { + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLSmoothInterpolation::getInterpolant(0.025f)); + } +} + +// Destroys the object +LLFolderViewFolder::~LLFolderViewFolder( void ) +{ + // The LLView base class takes care of object destruction. make sure that we + // don't have mouse or keyboard focus + gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() +} + +// addToFolder() returns true if it succeeds. false otherwise +void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) +{ + folder->addFolder(this); + + // Compute indentation since parent folder changed + mIndentation = (getParentFolder()) + ? getParentFolder()->getIndentation() + mLocalIndentation + : 0; + + if(isOpen() && folder->isOpen()) + { + requestArrange(); + } +} + +static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange"); + +// Make everything right and in the right place ready for drawing (CHUI-849) +// * Sort everything correctly if necessary +// * Turn widgets visible/invisible according to their model filtering state +// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible) +// * Reposition visible widgets so that they line up correctly with no gap +// * Compute the width and height of the current folder and its children +// * Makes sure that this view and its children are the right size +S32 LLFolderViewFolder::arrange( S32* width, S32* height ) +{ + // Sort before laying out contents + // Note that we sort from the root (CHUI-849) + if (mAreChildrenInited) + { + getRoot()->getFolderViewModel()->sort(this); + } + + LL_RECORD_BLOCK_TIME(FTM_ARRANGE); + + // evaluate mHasVisibleChildren + mHasVisibleChildren = false; + if (mAreChildrenInited && getViewModelItem()->descendantsPassedFilter()) + { + // We have to verify that there's at least one child that's not filtered out + bool found = false; + // Try the items first + for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + found = itemp->isPotentiallyVisible(); + if (found) + break; + } + if (!found) + { + // If no item found, try the folders + for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + found = folderp->isPotentiallyVisible(); + if (found) + break; + } + } + + mHasVisibleChildren = found; + } + if (!mIsFolderComplete && mAreChildrenInited) + { + mIsFolderComplete = getFolderViewModel()->isFolderComplete(this); + } + + + + // calculate height as a single item (without any children), and reshapes rectangle to match + LLFolderViewItem::arrange( width, height ); + + // clamp existing animated height so as to never get smaller than a single item + mCurHeight = llmax((F32)*height, mCurHeight); + + // initialize running height value as height of single item in case we have no children + F32 running_height = (F32)*height; + F32 target_height = (F32)*height; + + // are my children visible? + if (needsArrange()) + { + // set last arrange generation first, in case children are animating + // and need to be arranged again + mLastArrangeGeneration = getRoot()->getArrangeGeneration(); + if (isOpen()) + { + // Add sizes of children + S32 parent_item_height = getRect().getHeight(); + + for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) + { + LLFolderViewFolder* folderp = (*fit); + folderp->setVisible(folderp->isPotentiallyVisible()); + + if (folderp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - ll_round(running_height); + + target_height += folderp->arrange( &child_width, &child_height ); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() ); + } + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + itemp->setVisible(itemp->isPotentiallyVisible()); + + if (itemp->getVisible()) + { + S32 child_width = *width; + S32 child_height = 0; + S32 child_top = parent_item_height - ll_round(running_height); + + target_height += itemp->arrange( &child_width, &child_height ); + // don't change width, as this item is as wide as its parent folder by construction + itemp->reshape( itemp->getRect().getWidth(), child_height); + + running_height += (F32)child_height; + *width = llmax(*width, child_width); + itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() ); + } + } + } + + mTargetHeight = target_height; + // cache this width so next time we can just return it + mLastCalculatedWidth = *width; + } + else + { + // just use existing width + *width = mLastCalculatedWidth; + } + + // animate current height towards target height + if (llabs(mCurHeight - mTargetHeight) > 1.f) + { + mCurHeight = lerp(mCurHeight, mTargetHeight, LLSmoothInterpolation::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + + requestArrange(); + + // hide child elements that fall out of current animated height + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + // number of pixels that bottom of folder label is from top of parent folder + if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight() + > ll_round(mCurHeight) + mMaxFolderItemOverlap) + { + // hide if beyond current folder height + (*fit)->setVisible(false); + } + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + // number of pixels that bottom of item label is from top of parent folder + if (getRect().getHeight() - (*iit)->getRect().mBottom + > ll_round(mCurHeight) + mMaxFolderItemOverlap) + { + (*iit)->setVisible(false); + } + } + } + else + { + mCurHeight = mTargetHeight; + } + + // don't change width as this item is already as wide as its parent folder + reshape(getRect().getWidth(),ll_round(mCurHeight)); + + // pass current height value back to parent + *height = ll_round(mCurHeight); + + return ll_round(mTargetHeight); +} + +bool LLFolderViewFolder::needsArrange() +{ + return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); +} + +bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation) +{ + return getViewModelItem()->descendantsPassedFilter(filter_generation); +} + +// Passes selection information on to children and record selection +// information if necessary. +bool LLFolderViewFolder::setSelection(LLFolderViewItem* selection, bool openitem, + bool take_keyboard_focus) +{ + bool rv = false; + if (selection == this) + { + if (!isSelected()) + { + selectItem(); + } + rv = true; + } + else + { + if (isSelected()) + { + deselectItem(); + } + rv = false; + } + bool child_selected = false; + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = true; + child_selected = true; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->setSelection(selection, openitem, take_keyboard_focus)) + { + rv = true; + child_selected = true; + } + } + if(openitem && child_selected && !mSingleFolderMode) + { + setOpenArrangeRecursively(true); + } + return rv; +} + +// This method is used to change the selection of an item. +// Recursively traverse all children; if 'selection' is 'this' then change +// the select status if necessary. +// Returns true if the selection state of this folder, or of a child, was changed. +bool LLFolderViewFolder::changeSelection(LLFolderViewItem* selection, bool selected) +{ + bool rv = false; + if(selection == this) + { + if (isSelected() != selected) + { + rv = true; + if (selected) + { + selectItem(); + } + else + { + deselectItem(); + } + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if((*fit)->changeSelection(selection, selected)) + { + rv = true; + } + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if((*iit)->changeSelection(selection, selected)) + { + rv = true; + } + } + return rv; +} + +LLFolderViewFolder* LLFolderViewFolder::getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse) +{ + if (!item_a->getParentFolder() || !item_b->getParentFolder()) return NULL; + + std::deque item_a_ancestors; + + LLFolderViewFolder* parent = item_a->getParentFolder(); + while(parent) + { + item_a_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + std::deque item_b_ancestors; + + parent = item_b->getParentFolder(); + while(parent) + { + item_b_ancestors.push_back(parent); + parent = parent->getParentFolder(); + } + + LLFolderViewFolder* common_ancestor = item_a->getRoot(); + + while(item_a_ancestors.size() > item_b_ancestors.size()) + { + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + } + + while(item_b_ancestors.size() > item_a_ancestors.size()) + { + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + while(item_a_ancestors.size()) + { + common_ancestor = item_a_ancestors.front(); + + if (item_a_ancestors.front() == item_b_ancestors.front()) + { + // which came first, sibling a or sibling b? + for (folders_t::iterator it = common_ancestor->mFolders.begin(), end_it = common_ancestor->mFolders.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + + for (items_t::iterator it = common_ancestor->mItems.begin(), end_it = common_ancestor->mItems.end(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + + if (item == item_a) + { + reverse = false; + return common_ancestor; + } + if (item == item_b) + { + reverse = true; + return common_ancestor; + } + } + break; + } + + item_a = item_a_ancestors.front(); + item_a_ancestors.pop_front(); + item_b = item_b_ancestors.front(); + item_b_ancestors.pop_front(); + } + + return NULL; +} + +void LLFolderViewFolder::gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector& items) +{ + bool selecting = start == NULL; + if (reverse) + { + for (items_t::reverse_iterator it = mItems.rbegin(), end_it = mItems.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (folders_t::reverse_iterator it = mFolders.rbegin(), end_it = mFolders.rend(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } + else + { + for (folders_t::iterator it = mFolders.begin(), end_it = mFolders.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + for (items_t::iterator it = mItems.begin(), end_it = mItems.end(); + it != end_it; + ++it) + { + if (*it == end) + { + return; + } + + if (selecting && (*it)->getVisible()) + { + items.push_back(*it); + } + + if (*it == start) + { + selecting = true; + } + } + } +} + +void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) +{ + if (!getRoot()->getAllowMultiSelect()) + return; + + LLFolderViewItem* cur_selected_item = getRoot()->getCurSelectedItem(); + if (cur_selected_item == NULL) + { + cur_selected_item = new_selection; + } + + + bool reverse = false; + LLFolderViewFolder* common_ancestor = getCommonAncestor(cur_selected_item, new_selection, reverse); + if (!common_ancestor) + return; + + LLFolderViewItem* last_selected_item_from_cur = cur_selected_item; + LLFolderViewFolder* cur_folder = cur_selected_item->getParentFolder(); + + std::vector items_to_select_forward; + + while (cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_cur, NULL, reverse, items_to_select_forward); + + last_selected_item_from_cur = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + std::vector items_to_select_reverse; + + LLFolderViewItem* last_selected_item_from_new = new_selection; + cur_folder = new_selection->getParentFolder(); + while (cur_folder != common_ancestor) + { + cur_folder->gatherChildRangeExclusive(last_selected_item_from_new, NULL, !reverse, items_to_select_reverse); + + last_selected_item_from_new = cur_folder; + cur_folder = cur_folder->getParentFolder(); + } + + common_ancestor->gatherChildRangeExclusive(last_selected_item_from_cur, last_selected_item_from_new, reverse, items_to_select_forward); + + for (std::vector::reverse_iterator it = items_to_select_reverse.rbegin(), end_it = items_to_select_reverse.rend(); + it != end_it; + ++it) + { + items_to_select_forward.push_back(*it); + } + + LLFolderView* root = getRoot(); + + bool selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected + + // array always go from 'will be selected' to ' will be unselected', iterate + // in opposite direction to simplify identification of 'point of origin' in + // case it is in the list we are working with + for (std::vector::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend(); + it != end_it; + ++it) + { + LLFolderViewItem* item = *it; + bool selected = item->isSelected(); + if (!selection_reverse && selected) + { + // it is our 'point of origin' where we shift/expand from + // don't deselect it + selection_reverse = true; + } + else + { + root->changeSelection(item, !selected); + } + } + + if (selection_reverse) + { + // at some point we reversed selection, first element should be deselected + root->changeSelection(last_selected_item_from_cur, false); + } + + // element we expand to should always be selected + root->changeSelection(new_selection, true); +} + + +void LLFolderViewFolder::destroyView() +{ + while (!mItems.empty()) + { + LLFolderViewItem *itemp = mItems.back(); + mItems.pop_back(); + itemp->destroyView(); // LLFolderViewItem::destroyView() removes entry from mItems + } + + while (!mFolders.empty()) + { + LLFolderViewFolder *folderp = mFolders.back(); + mFolders.pop_back(); + folderp->destroyView(); // LLFolderVievFolder::destroyView() removes entry from mFolders + } + + LLFolderViewItem::destroyView(); +} + +// extractItem() removes the specified item from the folder, but +// doesn't delete it. +void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model ) +{ + if (item->isSelected()) + getRoot()->clearSelection(); + items_t::iterator it = std::find(mItems.begin(), mItems.end(), item); + if(it == mItems.end()) + { + // This is an evil downcast. However, it's only doing + // pointer comparison to find if (which it should be ) the + // item is in the container, so it's pretty safe. + LLFolderViewFolder* f = static_cast(item); + folders_t::iterator ft; + ft = std::find(mFolders.begin(), mFolders.end(), f); + if (ft != mFolders.end()) + { + mFolders.erase(ft); + } + } + else + { + mItems.erase(it); + } + //item has been removed, need to update filter + if (deparent_model) + { + // in some cases model does not belong to parent view, is shared between views + getViewModelItem()->removeChild(item->getViewModelItem()); + } + //because an item is going away regardless of filter status, force rearrange + requestArrange(); + removeChild(item); +} + +bool LLFolderViewFolder::isMovable() +{ + if( !(getViewModelItem()->isItemMovable()) ) + { + return false; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isMovable()) + { + return false; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isMovable()) + { + return false; + } + } + return true; +} + + +bool LLFolderViewFolder::isRemovable() +{ + if( !(getViewModelItem()->isItemRemovable()) ) + { + return false; + } + + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + if(!(*iit)->isRemovable()) + { + return false; + } + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + if(!(*fit)->isRemovable()) + { + return false; + } + } + return true; +} + +void LLFolderViewFolder::destroyRoot() +{ + delete this; +} + +// this is an internal method used for adding items to folders. +void LLFolderViewFolder::addItem(LLFolderViewItem* item) +{ + if (item->getParentFolder()) + { + item->getParentFolder()->extractItem(item); + } + item->setParentFolder(this); + + mItems.push_back(item); + + item->setRect(LLRect(0, 0, getRect().getWidth(), 0)); + item->setVisible(false); + + addChild(item); + + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it + // Note: this happens when models are created before views or shared between views + if (!item->getViewModelItem()->hasParent()) + { + getViewModelItem()->addChild(item->getViewModelItem()); + } +} + +// this is an internal method used for adding items to folders. +void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) +{ + if (folder->mParentFolder) + { + folder->mParentFolder->extractItem(folder); + } + folder->mParentFolder = this; + mFolders.push_back(folder); + folder->setOrigin(0, 0); + folder->reshape(getRect().getWidth(), 0); + folder->setVisible(false); + // rearrange all descendants too, as our indentation level might have changed + //folder->requestArrange(); + //requestSort(); + + addChild(folder); + + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it + // Note: this happens when models are created before views or shared between views + if (!folder->getViewModelItem()->hasParent()) + { + getViewModelItem()->addChild(folder->getViewModelItem()); + } +} + +void LLFolderViewFolder::requestArrange() +{ + mLastArrangeGeneration = -1; + // flag all items up to root + if (mParentFolder) + { + mParentFolder->requestArrange(); + } +} + +void LLFolderViewFolder::toggleOpen() +{ + setOpen(!isOpen()); +} + +// Force a folder open or closed +void LLFolderViewFolder::setOpen(bool openitem) +{ + if(mSingleFolderMode) + { + // navigateToFolder can destroy this view + // delay it in case setOpen was called from click or key processing + doOnIdleOneTime([this]() + { + getViewModelItem()->navigateToFolder(); + }); + } + else + { + setOpenArrangeRecursively(openitem); + } +} + +void LLFolderViewFolder::setOpenArrangeRecursively(bool openitem, ERecurseType recurse) +{ + bool was_open = isOpen(); + mIsOpen = openitem; + if(!was_open && openitem) + { + getViewModelItem()->openItem(); + // openItem() will request content, it won't be incomplete + mIsFolderComplete = true; + } + else if(was_open && !openitem) + { + getViewModelItem()->closeItem(); + } + + if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */ + } + } + if (mParentFolder + && (recurse == RECURSE_UP + || recurse == RECURSE_UP_DOWN)) + { + mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); + } + + if (was_open != isOpen()) + { + requestArrange(); + } +} + +bool LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, + bool drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + bool accepted = mViewModelItem->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); + if (accepted) + { + mDragAndDropTarget = true; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + // drag and drop to child item, so clear pending auto-opens + getRoot()->autoOpenTest(NULL); + + return true; +} + +void LLFolderViewFolder::openItem( void ) +{ + toggleOpen(); +} + +void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + functor.doItem((*fit)); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) +{ + functor.doFolder(this); + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->applyFunctorRecursively(functor); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + +// LLView functionality +bool LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, + bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + bool handled = false; + + if (isOpen()) + { + handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); + } + + if (!handled) + { + handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFolderViewFolder" << LL_ENDL; + } + + return true; +} + +bool LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, + bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if (!mAllowDrop) + { + *accept = ACCEPT_NO; + tooltip_msg = LLTrans::getString("TooltipOutboxCannotDropOnRoot"); + return true; + } + + bool accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + + if (accepted) + { + mDragAndDropTarget = true; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + getRoot()->autoOpenTest(this); + } + + return true; +} + + +bool LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + bool handled = false; + + if( isOpen() ) + { + handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; + } + if (!handled) + { + handled = LLFolderViewItem::handleRightMouseDown( x, y, mask ); + } + return handled; +} + + +bool LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) +{ + mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); + + bool handled = LLView::handleHover(x, y, mask); + + if (!handled) + { + // this doesn't do child processing + handled = LLFolderViewItem::handleHover(x, y, mask); + } + + return handled; +} + +bool LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + bool handled = false; + if( isOpen() ) + { + handled = childrenHandleMouseDown(x,y,mask) != NULL; + } + if( !handled ) + { + if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) + && !mSingleFolderMode) + { + toggleOpen(); + handled = true; + } + else + { + // do normal selection logic + handled = LLFolderViewItem::handleMouseDown(x, y, mask); + } + } + + return handled; +} + +bool LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + bool handled = false; + if(mSingleFolderMode) + { + static LLUICachedControl double_click_new_window("SingleModeDoubleClickOpenWindow", false); + if (double_click_new_window) + { + getViewModelItem()->navigateToFolder(true); + } + else + { + // navigating is going to destroy views and change children + // delay it untill handleDoubleClick processing is complete + doOnIdleOneTime([this]() + { + getViewModelItem()->navigateToFolder(false); + }); + } + return true; + } + + if( isOpen() ) + { + handled = childrenHandleDoubleClick( x, y, mask ) != NULL; + } + if( !handled ) + { + if(mDoubleClickOverride) + { + static LLUICachedControl double_click_action("MultiModeDoubleClickFolder", false); + if (double_click_action == 1) + { + getViewModelItem()->navigateToFolder(true); + return true; + } + if (double_click_action == 2) + { + getViewModelItem()->navigateToFolder(false, true); + return true; + } + } + if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad) + { + // don't select when user double-clicks plus sign + // so as not to contradict single-click behavior + toggleOpen(); + } + else + { + getRoot()->setSelection(this, false); + toggleOpen(); + } + handled = true; + } + return handled; +} + +void LLFolderViewFolder::draw() +{ + updateLabelRotation(); + + LLFolderViewItem::draw(); + + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) + { + LLView::draw(); + } + + mExpanderHighlighted = false; +} + +// this does prefix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, bool include_children ) +{ + bool found_item = false; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at beginning + if(item == NULL) + { + found_item = true; + } + + // find current item among children + folders_t::iterator fit = mFolders.begin(); + folders_t::iterator fend = mFolders.end(); + + items_t::iterator iit = mItems.begin(); + items_t::iterator iend = mItems.end(); + + // if not trivially starting at the beginning, we have to find the current item + if (!found_item) + { + // first, look among folders, since they are always above items + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = true; + // if we are on downwards traversal + if (include_children && (*fit)->isOpen()) + { + // look for first descendant + return (*fit)->getNextFromChild(NULL, true); + } + // otherwise advance to next folder + ++fit; + include_children = true; + break; + } + } + + // didn't find in folders? Check items... + if (!found_item) + { + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = true; + // point to next item + ++iit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(false); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found folder, continue through folders + // searching for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + // turn on downwards traversal for next folder + ++fit; + } + + if (fit != fend) + { + result = (*fit); + } + else + { + // otherwise, scan for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + // check to see if we have a valid item + if (iit != iend) + { + result = (*iit); + } + } + + if( !result && mParentFolder ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // and skip children for this folder, as we've already discounted them + result = mParentFolder->getNextFromChild(this, false); + } + + return result; +} + +// this does postfix traversal, as folders are listed above their contents +LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, bool include_children ) +{ + bool found_item = false; + + LLFolderViewItem* result = NULL; + // when not starting from a given item, start at end + if(item == NULL) + { + found_item = true; + } + + // find current item among children + folders_t::reverse_iterator fit = mFolders.rbegin(); + folders_t::reverse_iterator fend = mFolders.rend(); + + items_t::reverse_iterator iit = mItems.rbegin(); + items_t::reverse_iterator iend = mItems.rend(); + + // if not trivially starting at the end, we have to find the current item + if (!found_item) + { + // first, look among items, since they are always below the folders + for(; iit != iend; ++iit) + { + if(item == (*iit)) + { + found_item = true; + // point to next item + ++iit; + break; + } + } + + // didn't find in items? Check folders... + if (!found_item) + { + for(; fit != fend; ++fit) + { + if(item == (*fit)) + { + found_item = true; + // point to next folder + ++fit; + break; + } + } + } + } + + if (!found_item) + { + // you should never call this method with an item that isn't a child + // so we should always find something + llassert(false); + return NULL; + } + + // at this point, either iit or fit point to a candidate "next" item + // if both are out of range, we need to punt up to our parent + + // now, starting from found item, continue through items + // searching for next visible item + while(iit != iend && !(*iit)->getVisible()) + { + ++iit; + } + + if (iit != iend) + { + // we found an appropriate item + result = (*iit); + } + else + { + // otherwise, scan for next visible folder + while(fit != fend && !(*fit)->getVisible()) + { + ++fit; + } + + // check to see if we have a valid folder + if (fit != fend) + { + // try selecting child element of this folder + if ((*fit)->isOpen() && include_children) + { + result = (*fit)->getPreviousFromChild(NULL); + } + else + { + result = (*fit); + } + } + } + + if( !result ) + { + // If there are no siblings or children to go to, recurse up one level in the tree + // which gets back to this folder, which will only be visited if it is a valid, visible item + result = this; + } + + return result; +} + -- 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/llfolderviewitem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/llui/llfolderviewitem.cpp') diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index a0c7407b06..82cd2483e8 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -940,22 +940,22 @@ void LLFolderViewItem::draw() return; } - std::string::size_type filter_string_length = mViewModelItem->hasFilterStringMatch() ? mViewModelItem->getFilterStringSize() : 0; + auto filter_string_length = mViewModelItem->hasFilterStringMatch() ? static_cast(mViewModelItem->getFilterStringSize()) : 0; F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; F32 text_left = (F32)getLabelXPos(); std::string combined_string = mLabel + mLabelSuffix; const LLFontGL* suffix_font = getLabelFontForStyle(LLFontGL::NORMAL); - S32 filter_offset = mViewModelItem->getFilterStringOffset(); + S32 filter_offset = static_cast(mViewModelItem->getFilterStringOffset()); if (filter_string_length > 0) { S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); S32 top = getRect().getHeight() - TOP_PAD; if(mLabelSuffix.empty() || (font == suffix_font)) { - S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2; - S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2; + S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, static_cast(mViewModelItem->getFilterStringOffset())) - 2; + S32 right = left + font->getWidth(combined_string, static_cast(mViewModelItem->getFilterStringOffset()), filter_string_length) + 2; LLUIImage* box_image = default_params.selection_image; LLRect box_rect(left, top, right, bottom); @@ -976,7 +976,7 @@ void LLFolderViewItem::draw() if(suffix_filter_length > 0) { S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); - S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset) - 2; + S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, static_cast(mLabel.size())) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset) - 2; S32 right = left + suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length) + 2; LLUIImage* box_image = default_params.selection_image; LLRect box_rect(left, top, right, bottom); @@ -1033,7 +1033,7 @@ void LLFolderViewItem::draw() if(suffix_filter_length > 0) { S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size()); - F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length); + F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, static_cast(mLabel.size())) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length); F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD; suffix_font->renderUTF8(mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -- cgit v1.2.3