00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llfolderview.h"
00035
00036 #include <algorithm>
00037
00038 #include "llviewercontrol.h"
00039 #include "lldbstrings.h"
00040 #include "llfocusmgr.h"
00041 #include "llfontgl.h"
00042 #include "llgl.h"
00043 #include "llinventory.h"
00044
00045 #include "llcallbacklist.h"
00046 #include "llinventoryclipboard.h"
00047 #include "llinventoryview.h"
00048 #include "llkeyboard.h"
00049 #include "lllineeditor.h"
00050 #include "llmenugl.h"
00051 #include "llresmgr.h"
00052 #include "llpreview.h"
00053 #include "llscrollcontainer.h"
00054 #include "lltooldraganddrop.h"
00055 #include "llui.h"
00056 #include "llviewerimage.h"
00057 #include "llviewerimagelist.h"
00058 #include "llviewerjointattachment.h"
00059 #include "llviewermenu.h"
00060 #include "llvieweruictrlfactory.h"
00061 #include "llviewerwindow.h"
00062 #include "llvoavatar.h"
00063 #include "llfloaterproperties.h"
00064
00065
00066
00067
00068 #include "llagent.h"
00069 #include "viewer.h"
00070
00074
00075 const S32 LEFT_PAD = 5;
00076 const S32 LEFT_INDENTATION = 13;
00077 const S32 ICON_PAD = 2;
00078 const S32 ICON_WIDTH = 16;
00079 const S32 TEXT_PAD = 1;
00080 const S32 ARROW_SIZE = 12;
00081 const S32 RENAME_WIDTH_PAD = 4;
00082 const S32 RENAME_HEIGHT_PAD = 6;
00083 const S32 AUTO_OPEN_STACK_DEPTH = 16;
00084 const S32 MIN_ITEM_WIDTH_VISIBLE = ICON_WIDTH + ICON_PAD + ARROW_SIZE + TEXT_PAD + 40;
00085 const S32 MINIMUM_RENAMER_WIDTH = 80;
00086 const F32 FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
00087 const F32 FOLDER_OPEN_TIME_CONSTANT = 0.03f;
00088 const S32 MAX_FOLDER_ITEM_OVERLAP = 2;
00089
00090 F32 LLFolderView::sAutoOpenTime = 1.f;
00091
00092 void delete_selected_item(void* user_data);
00093 void copy_selected_item(void* user_data);
00094 void open_selected_items(void* user_data);
00095 void properties_selected_items(void* user_data);
00096 void paste_items(void* user_data);
00097 void renamer_focus_lost( LLUICtrl* handler, void* user_data );
00098
00102
00103
00104 const LLFontGL* LLFolderViewItem::sFont = NULL;
00105 const LLFontGL* LLFolderViewItem::sSmallFont = NULL;
00106 LLColor4 LLFolderViewItem::sFgColor;
00107 LLColor4 LLFolderViewItem::sHighlightBgColor;
00108 LLColor4 LLFolderViewItem::sHighlightFgColor;
00109 LLColor4 LLFolderViewItem::sFilterBGColor;
00110 LLColor4 LLFolderViewItem::sFilterTextColor;
00111
00112
00113 LLFolderViewItem::LLFolderViewItem( const LLString& name, LLViewerImage* icon,
00114 S32 creation_date,
00115 LLFolderView* root,
00116 LLFolderViewEventListener* listener ) :
00117 LLUICtrl( name, LLRect(0, 0, 0, 0), TRUE, NULL, NULL, FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT),
00118 mLabel( name ),
00119 mLabelWidth(0),
00120 mCreationDate(creation_date),
00121 mParentFolder( NULL ),
00122 mListener( listener ),
00123 mIsSelected( FALSE ),
00124 mIsCurSelection( FALSE ),
00125 mSelectPending(FALSE),
00126 mLabelStyle( LLFontGL::NORMAL ),
00127 mHasVisibleChildren(FALSE),
00128 mIndentation(0),
00129 mNumDescendantsSelected(0),
00130 mFiltered(FALSE),
00131 mLastFilterGeneration(-1),
00132 mStringMatchOffset(LLString::npos),
00133 mControlLabelRotation(0.f),
00134 mRoot( root ),
00135 mDragAndDropTarget(FALSE)
00136 {
00137 setIcon(icon);
00138 if( !LLFolderViewItem::sFont )
00139 {
00140 LLFolderViewItem::sFont = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
00141 }
00142
00143 if (!LLFolderViewItem::sSmallFont)
00144 {
00145 LLFolderViewItem::sSmallFont = gResMgr->getRes( LLFONT_SMALL );
00146 }
00147
00148
00149 LLFolderViewItem::sFgColor = gColors.getColor( "MenuItemEnabledColor" );
00150 LLFolderViewItem::sHighlightBgColor = gColors.getColor( "MenuItemHighlightBgColor" );
00151 LLFolderViewItem::sHighlightFgColor = gColors.getColor( "MenuItemHighlightFgColor" );
00152 LLFolderViewItem::sFilterBGColor = gColors.getColor( "FilterBackgroundColor" );
00153 LLFolderViewItem::sFilterTextColor = gColors.getColor( "FilterTextColor" );
00154
00155 mArrowImage = gImageList.getImage(LLUUID(gViewerArt.getString("folder_arrow.tga")), MIPMAP_FALSE, TRUE);
00156 mBoxImage = gImageList.getImage(LLUUID(gViewerArt.getString("rounded_square.tga")), MIPMAP_FALSE, TRUE);
00157
00158 refresh();
00159 setTabStop(FALSE);
00160 }
00161
00162
00163 LLFolderViewItem::~LLFolderViewItem( void )
00164 {
00165 delete mListener;
00166 mListener = NULL;
00167 mArrowImage = NULL;
00168 mBoxImage = NULL;
00169 }
00170
00171 LLFolderView* LLFolderViewItem::getRoot()
00172 {
00173 return mRoot;
00174 }
00175
00176
00177 BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor )
00178 {
00179 LLFolderViewItem* root = this;
00180 while( root->mParentFolder )
00181 {
00182 if( root->mParentFolder == potential_ancestor )
00183 {
00184 return TRUE;
00185 }
00186 root = root->mParentFolder;
00187 }
00188 return FALSE;
00189 }
00190
00191 LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children)
00192 {
00193 if (!mParentFolder)
00194 {
00195 return NULL;
00196 }
00197
00198 LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children );
00199 while(itemp && !itemp->getVisible())
00200 {
00201 LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children );
00202 if (itemp == next_itemp)
00203 {
00204
00205 return itemp->getVisible() ? itemp : this;
00206 }
00207 itemp = next_itemp;
00208 }
00209
00210 return itemp;
00211 }
00212
00213 LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
00214 {
00215 if (!mParentFolder)
00216 {
00217 return NULL;
00218 }
00219
00220 LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
00221 while(itemp && !itemp->getVisible())
00222 {
00223 LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
00224 if (itemp == next_itemp)
00225 {
00226
00227 return itemp->getVisible() ? itemp : this;
00228 }
00229 itemp = next_itemp;
00230 }
00231
00232 return itemp;
00233 }
00234
00235
00236
00237
00238 BOOL LLFolderViewItem::potentiallyVisible()
00239 {
00240
00241
00242 return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered();
00243 }
00244
00245 BOOL LLFolderViewItem::getFiltered()
00246 {
00247 return mFiltered && mLastFilterGeneration >= mRoot->getFilter()->getMinRequiredGeneration();
00248 }
00249
00250 BOOL LLFolderViewItem::getFiltered(S32 filter_generation)
00251 {
00252 return mFiltered && mLastFilterGeneration >= filter_generation;
00253 }
00254
00255 void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation)
00256 {
00257 mFiltered = filtered;
00258 mLastFilterGeneration = filter_generation;
00259 }
00260
00261 void LLFolderViewItem::setIcon(LLViewerImage* icon)
00262 {
00263 mIcon = icon;
00264 if (mIcon)
00265 {
00266 mIcon->setBoostLevel(LLViewerImage::BOOST_UI);
00267 }
00268 }
00269
00270
00271 void LLFolderViewItem::refresh()
00272 {
00273 if(mListener)
00274 {
00275 const char* label = mListener->getDisplayName().c_str();
00276 mLabel = label ? label : "";
00277 setIcon(mListener->getIcon());
00278 U32 creation_date = mListener->getCreationDate();
00279 if (mCreationDate != creation_date)
00280 {
00281 mCreationDate = mListener->getCreationDate();
00282 dirtyFilter();
00283 }
00284 mLabelStyle = mListener->getLabelStyle();
00285 mLabelSuffix = mListener->getLabelSuffix();
00286
00287 LLString searchable_label(mLabel);
00288 searchable_label.append(mLabelSuffix);
00289 LLString::toUpper(searchable_label);
00290
00291 if (mSearchableLabel.compare(searchable_label))
00292 {
00293 mSearchableLabel.assign(searchable_label);
00294 dirtyFilter();
00295
00296 if (mParentFolder)
00297 {
00298 mParentFolder->requestArrange();
00299 }
00300 }
00301
00302 S32 label_width = sFont->getWidth(mLabel);
00303 if( mLabelSuffix.size() )
00304 {
00305 label_width += sFont->getWidth( mLabelSuffix );
00306 }
00307
00308 mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + label_width;
00309 }
00310 }
00311
00312 void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor)
00313 {
00314 functor(mListener);
00315 }
00316
00317
00318
00319
00320 void LLFolderViewItem::filterFromRoot( void )
00321 {
00322 LLFolderViewItem* root = getRoot();
00323
00324 root->filter(*((LLFolderView*)root)->getFilter());
00325 }
00326
00327
00328
00329
00330 void LLFolderViewItem::arrangeFromRoot()
00331 {
00332 LLFolderViewItem* root = getRoot();
00333
00334 S32 height = 0;
00335 S32 width = 0;
00336 root->arrange( &width, &height, 0 );
00337 }
00338
00339
00340
00341
00342
00343 void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection,
00344 BOOL open,
00345 BOOL take_keyboard_focus)
00346 {
00347 getRoot()->setSelection(selection, open, take_keyboard_focus);
00348 }
00349
00350
00351 void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected)
00352 {
00353 getRoot()->changeSelection(selection, selected);
00354 }
00355
00356 void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection)
00357 {
00358 LLDynamicArray<LLFolderViewItem*> selected_items;
00359
00360 getRoot()->extendSelection(selection, NULL, selected_items);
00361 }
00362
00363 EWidgetType LLFolderViewItem::getWidgetType() const
00364 {
00365 return WIDGET_TYPE_FOLDER_ITEM;
00366 }
00367
00368 LLString LLFolderViewItem::getWidgetTag() const
00369 {
00370 return LL_FOLDER_VIEW_ITEM_TAG;
00371 }
00372
00373 EInventorySortGroup LLFolderViewItem::getSortGroup()
00374 {
00375 return SG_ITEM;
00376 }
00377
00378
00379 BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
00380 {
00381 if (!folder)
00382 {
00383 return FALSE;
00384 }
00385 mParentFolder = folder;
00386 root->addItemID(getListener()->getUUID(), this);
00387 return folder->addItem(this);
00388 }
00389
00390
00391
00392
00393 S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
00394 {
00395 mIndentation = mParentFolder ? mParentFolder->getIndentation() + LEFT_INDENTATION : 0;
00396 *width = llmax(*width, mLabelWidth + mIndentation);
00397 *height = getItemHeight();
00398 return *height;
00399 }
00400
00401 S32 LLFolderViewItem::getItemHeight()
00402 {
00403 S32 icon_height = mIcon->getHeight();
00404 S32 label_height = llround(sFont->getLineHeight());
00405 return llmax( icon_height, label_height ) + ICON_PAD;
00406 }
00407
00408 void LLFolderViewItem::filter( LLInventoryFilter& filter)
00409 {
00410 BOOL filtered = mListener && filter.check(this);
00411
00412
00413
00414 if (getVisible() != filtered)
00415 {
00416 if (mParentFolder)
00417 {
00418 mParentFolder->requestArrange();
00419 }
00420 }
00421
00422 setFiltered(filtered, filter.getCurrentGeneration());
00423 mStringMatchOffset = filter.getStringMatchOffset();
00424 filter.decrementFilterCount();
00425
00426 if (getRoot()->getDebugFilters())
00427 {
00428 mStatusText = llformat("%d", mLastFilterGeneration);
00429 }
00430 }
00431
00432 void LLFolderViewItem::dirtyFilter()
00433 {
00434 mLastFilterGeneration = -1;
00435
00436 if (getParentFolder())
00437 {
00438 getParentFolder()->setCompletedFilterGeneration(-1, TRUE);
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447 BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, BOOL take_keyboard_focus)
00448 {
00449 if( selection == this )
00450 {
00451 mIsSelected = TRUE;
00452 if(mListener)
00453 {
00454 mListener->selectItem();
00455 }
00456 }
00457 else
00458 {
00459 mIsSelected = FALSE;
00460 }
00461 return mIsSelected;
00462 }
00463
00464 BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected)
00465 {
00466 if(selection == this && mIsSelected != selected)
00467 {
00468 mIsSelected = selected;
00469 if(mListener)
00470 {
00471 mListener->selectItem();
00472 }
00473 return TRUE;
00474 }
00475 return FALSE;
00476 }
00477
00478 void LLFolderViewItem::recursiveDeselect(BOOL deselect_self)
00479 {
00480 if (mIsSelected && deselect_self)
00481 {
00482 mIsSelected = FALSE;
00483
00484
00485 LLFolderViewFolder* parent_folder = getParentFolder();
00486 while(parent_folder)
00487 {
00488 parent_folder->mNumDescendantsSelected--;
00489 parent_folder = parent_folder->getParentFolder();
00490 }
00491 }
00492 }
00493
00494
00495 BOOL LLFolderViewItem::isMovable()
00496 {
00497 if( mListener )
00498 {
00499 return mListener->isItemMovable();
00500 }
00501 else
00502 {
00503 return TRUE;
00504 }
00505 }
00506
00507 BOOL LLFolderViewItem::isRemovable()
00508 {
00509 if( mListener )
00510 {
00511 return mListener->isItemRemovable();
00512 }
00513 else
00514 {
00515 return TRUE;
00516 }
00517 }
00518
00519 void LLFolderViewItem::destroyView()
00520 {
00521 if (mParentFolder)
00522 {
00523
00524 mParentFolder->removeView(this);
00525 }
00526 }
00527
00528
00529
00530
00531 BOOL LLFolderViewItem::remove()
00532 {
00533 if(!isRemovable())
00534 {
00535 return FALSE;
00536 }
00537 if(mListener)
00538 {
00539 return mListener->removeItem();
00540 }
00541 return TRUE;
00542 }
00543
00544
00545 void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)
00546 {
00547 if(mListener)
00548 {
00549 mListener->buildContextMenu(menu, flags);
00550 }
00551 }
00552
00553 void LLFolderViewItem::open( void )
00554 {
00555 if( mListener )
00556 {
00557 mListener->openItem();
00558 }
00559 }
00560
00561 void LLFolderViewItem::preview( void )
00562 {
00563 if (mListener)
00564 {
00565 mListener->previewItem();
00566 }
00567 }
00568
00569 void LLFolderViewItem::rename(const LLString& new_name)
00570 {
00571 if( !new_name.empty() )
00572 {
00573 mLabel = new_name.c_str();
00574 if( mListener )
00575 {
00576 mListener->renameItem(new_name);
00577
00578 if(mParentFolder)
00579 {
00580 mParentFolder->resort(this);
00581 }
00582 }
00583 }
00584 }
00585
00586 const LLString& LLFolderViewItem::getSearchableLabel() const
00587 {
00588 return mSearchableLabel;
00589 }
00590
00591 const LLString& LLFolderViewItem::getName( void ) const
00592 {
00593 if(mListener)
00594 {
00595 return mListener->getName();
00596 }
00597 return mLabel;
00598 }
00599
00600 LLFolderViewFolder* LLFolderViewItem::getParentFolder( void )
00601 {
00602 return mParentFolder;
00603 }
00604
00605 LLFolderViewEventListener* LLFolderViewItem::getListener( void )
00606 {
00607 return mListener;
00608 }
00609
00610
00611 BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask )
00612 {
00613 if(!mIsSelected)
00614 {
00615 setSelectionFromRoot(this, FALSE);
00616 }
00617 make_ui_sound("UISndClick");
00618 return TRUE;
00619 }
00620
00621 BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )
00622 {
00623
00624
00625 gViewerWindow->setMouseCapture( this );
00626
00627 if (!mIsSelected)
00628 {
00629 if(mask & MASK_CONTROL)
00630 {
00631 changeSelectionFromRoot(this, !mIsSelected);
00632 }
00633 else if (mask & MASK_SHIFT)
00634 {
00635 extendSelectionFromRoot(this);
00636 }
00637 else
00638 {
00639 setSelectionFromRoot(this, FALSE);
00640 }
00641 make_ui_sound("UISndClick");
00642 }
00643 else
00644 {
00645 mSelectPending = TRUE;
00646 }
00647
00648 if( isMovable() )
00649 {
00650 S32 screen_x;
00651 S32 screen_y;
00652 localPointToScreen(x, y, &screen_x, &screen_y );
00653 gToolDragAndDrop->setDragStart( screen_x, screen_y );
00654 }
00655 return TRUE;
00656 }
00657
00658 BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
00659 {
00660 if( hasMouseCapture() && isMovable() )
00661 {
00662 S32 screen_x;
00663 S32 screen_y;
00664 localPointToScreen(x, y, &screen_x, &screen_y );
00665 BOOL can_drag = TRUE;
00666 if( gToolDragAndDrop->isOverThreshold( screen_x, screen_y ) )
00667 {
00668 LLFolderView* root = getRoot();
00669
00670 if(root->getCurSelectedItem())
00671 {
00672 LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD;
00673
00674
00675
00676 if(mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gAgent.getInventoryRootID()))
00677 {
00678 src = LLToolDragAndDrop::SOURCE_AGENT;
00679 }
00680 else if (mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventoryLibraryRoot))
00681 {
00682 src = LLToolDragAndDrop::SOURCE_LIBRARY;
00683 }
00684
00685 can_drag = root->startDrag(src);
00686 if (can_drag)
00687 {
00688
00689
00690 root->autoOpenTest(NULL);
00691 root->setShowSelectionContext(TRUE);
00692
00693
00694
00695
00696 gViewerWindow->setKeyboardFocus(NULL, NULL);
00697
00698 return gToolDragAndDrop->handleHover( x, y, mask );
00699 }
00700 }
00701 }
00702
00703 if (can_drag)
00704 {
00705 gViewerWindow->setCursor(UI_CURSOR_ARROW);
00706 }
00707 else
00708 {
00709 gViewerWindow->setCursor(UI_CURSOR_NOLOCKED);
00710 }
00711 return TRUE;
00712 }
00713 else
00714 {
00715 getRoot()->setShowSelectionContext(FALSE);
00716 gViewerWindow->setCursor(UI_CURSOR_ARROW);
00717
00718 return FALSE;
00719 }
00720 }
00721
00722
00723 BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask )
00724 {
00725 preview();
00726 return TRUE;
00727 }
00728
00729 BOOL LLFolderViewItem::handleScrollWheel(S32 x, S32 y, S32 clicks)
00730 {
00731 if (getParent())
00732 {
00733 return getParent()->handleScrollWheel(x, y, clicks);
00734 }
00735 return FALSE;
00736 }
00737
00738 BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )
00739 {
00740
00741 if ( pointInView(x, y) && mSelectPending )
00742 {
00743
00744 if(mask & MASK_CONTROL)
00745 {
00746 changeSelectionFromRoot(this, !mIsSelected);
00747 }
00748 else if (mask & MASK_SHIFT)
00749 {
00750 extendSelectionFromRoot(this);
00751 }
00752 else
00753 {
00754 setSelectionFromRoot(this, FALSE);
00755 }
00756 }
00757
00758 mSelectPending = FALSE;
00759
00760 if( hasMouseCapture() )
00761 {
00762 getRoot()->setShowSelectionContext(FALSE);
00763 gViewerWindow->setMouseCapture( NULL );
00764 }
00765 return TRUE;
00766 }
00767
00768 BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
00769 EDragAndDropType cargo_type,
00770 void* cargo_data,
00771 EAcceptance* accept,
00772 LLString& tooltip_msg)
00773 {
00774 BOOL accepted = FALSE;
00775 BOOL handled = FALSE;
00776 if(mListener)
00777 {
00778 accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data);
00779 handled = accepted;
00780 if (accepted)
00781 {
00782 mDragAndDropTarget = TRUE;
00783 *accept = ACCEPT_YES_MULTI;
00784 }
00785 else
00786 {
00787 *accept = ACCEPT_NO;
00788 }
00789 }
00790 if(mParentFolder && !handled)
00791 {
00792 handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
00793 }
00794 if (handled)
00795 {
00796 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl;
00797 }
00798
00799 return handled;
00800 }
00801
00802
00803 void LLFolderViewItem::draw()
00804 {
00805 bool possibly_has_children = false;
00806 bool up_to_date = mListener && mListener->isUpToDate();
00807 if((up_to_date && hasVisibleChildren() ) ||
00808 (!up_to_date && mListener && mListener->hasChildren()))
00809 {
00810 possibly_has_children = true;
00811 }
00812 if(possibly_has_children)
00813 {
00814 LLGLSTexture gls_texture;
00815 if (mArrowImage)
00816 {
00817 gl_draw_scaled_rotated_image(mIndentation, mRect.getHeight() - ARROW_SIZE - TEXT_PAD,
00818 ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, mArrowImage, sFgColor);
00819 }
00820 }
00821
00822 F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation);
00823
00824
00825 BOOL show_context = getRoot()->getShowSelectionContext();
00826 BOOL filled = show_context || (gFocusMgr.getKeyboardFocus() == getRoot());
00827
00828
00829
00830 if( mIsSelected )
00831 {
00832 LLGLSNoTexture gls_no_texture;
00833 LLColor4 bg_color = sHighlightBgColor;
00834
00835 if (!mIsCurSelection)
00836 {
00837
00838 F32 fade_time = getRoot()->getSelectionFadeElapsedTime();
00839 if (getRoot()->getShowSingleSelection())
00840 {
00841
00842 bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f);
00843 }
00844 else
00845 {
00846
00847 bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]);
00848 }
00849 }
00850
00851 gl_rect_2d(
00852 0,
00853 mRect.getHeight(),
00854 mRect.getWidth() - 2,
00855 llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD),
00856 bg_color, filled);
00857 if (mIsCurSelection)
00858 {
00859 gl_rect_2d(
00860 0,
00861 mRect.getHeight(),
00862 mRect.getWidth() - 2,
00863 llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD),
00864 sHighlightFgColor, FALSE);
00865 }
00866 if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2)
00867 {
00868 gl_rect_2d(
00869 0,
00870 llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2,
00871 mRect.getWidth() - 2,
00872 2,
00873 sHighlightFgColor, FALSE);
00874 if (show_context)
00875 {
00876 gl_rect_2d(
00877 0,
00878 llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2,
00879 mRect.getWidth() - 2,
00880 2,
00881 sHighlightBgColor, TRUE);
00882 }
00883 }
00884 }
00885 if (mDragAndDropTarget)
00886 {
00887 LLGLSNoTexture gls_no_texture;
00888 gl_rect_2d(
00889 0,
00890 mRect.getHeight(),
00891 mRect.getWidth() - 2,
00892 llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD),
00893 sHighlightBgColor, FALSE);
00894
00895 if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2)
00896 {
00897 gl_rect_2d(
00898 0,
00899 llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2,
00900 mRect.getWidth() - 2,
00901 2,
00902 sHighlightBgColor, FALSE);
00903 }
00904 mDragAndDropTarget = FALSE;
00905 }
00906
00907
00908 if(mIcon)
00909 {
00910 gl_draw_image(mIndentation + ARROW_SIZE + TEXT_PAD, mRect.getHeight() - mIcon->getHeight(), mIcon);
00911 mIcon->addTextureStats( (F32)(mIcon->getWidth() * mIcon->getHeight()));
00912 }
00913
00914 if (!mLabel.empty())
00915 {
00916
00917 BOOL debug_filters = getRoot()->getDebugFilters();
00918 LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor );
00919 F32 right_x;
00920 F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD;
00921
00922 if (debug_filters)
00923 {
00924 if (!getFiltered() && !possibly_has_children)
00925 {
00926 color.mV[VALPHA] *= 0.5f;
00927 }
00928
00929 LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f);
00930 sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color,
00931 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL,
00932 S32_MAX, S32_MAX, &right_x, FALSE );
00933 text_left = right_x;
00934 }
00935
00936 sFont->renderUTF8( mLabel, 0, text_left, y, color,
00937 LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle,
00938 S32_MAX, S32_MAX, &right_x, FALSE );
00939 if (!mLabelSuffix.empty())
00940 {
00941 sFont->renderUTF8( mLabelSuffix, 0, right_x, y, LLColor4(0.75f, 0.85f, 0.85f, 1.f),
00942 LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle,
00943 S32_MAX, S32_MAX, &right_x, FALSE );
00944 }
00945
00946 if (mBoxImage.notNull() && mStringMatchOffset != LLString::npos)
00947 {
00948
00949 S32 filter_string_length = mRoot->getFilterSubString().size();
00950 if (filter_string_length > 0)
00951 {
00952 LLString combined_string = mLabel + mLabelSuffix;
00953 S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1;
00954 S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2;
00955 S32 bottom = llfloor(mRect.getHeight() - sFont->getLineHeight() - 3);
00956 S32 top = mRect.getHeight();
00957
00958 LLViewerImage::bindTexture(mBoxImage);
00959 glColor4fv(sFilterBGColor.mV);
00960 gl_segmented_rect_2d_tex(left, top, right, bottom, mBoxImage->getWidth(), mBoxImage->getHeight(), 16);
00961 F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset);
00962 F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD;
00963 sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y,
00964 sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle,
00965 filter_string_length, S32_MAX, &right_x, FALSE );
00966 }
00967 }
00968 }
00969
00970 if( sDebugRects )
00971 {
00972 drawDebugRect();
00973 }
00974 }
00975
00976
00980
00981
00982 LLFolderViewFolder::LLFolderViewFolder( const LLString& name, LLViewerImage* icon,
00983 LLFolderView* root,
00984 LLFolderViewEventListener* listener ):
00985 LLFolderViewItem( name, icon, 0, root, listener ),
00986 mIsOpen(FALSE),
00987 mExpanderHighlighted(FALSE),
00988 mCurHeight(0.f),
00989 mTargetHeight(0.f),
00990 mAutoOpenCountdown(0.f),
00991 mSubtreeCreationDate(0),
00992 mAmTrash(LLFolderViewFolder::UNKNOWN),
00993 mLastArrangeGeneration( -1 ),
00994 mLastCalculatedWidth(0),
00995 mCompletedFilterGeneration(-1),
00996 mMostFilteredDescendantGeneration(-1)
00997 {
00998 mType = "(folder)";
00999
01000
01001
01002 }
01003
01004
01005 LLFolderViewFolder::~LLFolderViewFolder( void )
01006 {
01007
01008
01009 gFocusMgr.releaseFocusIfNeeded( this );
01010
01011
01012
01013
01014 }
01015
01016 EWidgetType LLFolderViewFolder::getWidgetType() const
01017 {
01018 return WIDGET_TYPE_FOLDER;
01019 }
01020
01021 LLString LLFolderViewFolder::getWidgetTag() const
01022 {
01023 return LL_FOLDER_VIEW_FOLDER_TAG;
01024 }
01025
01026
01027 BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
01028 {
01029 if (!folder)
01030 {
01031 return FALSE;
01032 }
01033 mParentFolder = folder;
01034 root->addItemID(getListener()->getUUID(), this);
01035 return folder->addFolder(this);
01036 }
01037
01038
01039
01040 S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
01041 {
01042 mHasVisibleChildren = hasFilteredDescendants(filter_generation);
01043
01044 LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getShowFolderState();
01045
01046
01047 LLFolderViewItem::arrange( width, height, filter_generation );
01048
01049
01050 mCurHeight = llmax((F32)*height, mCurHeight);
01051
01052
01053 *height = getItemHeight();
01054 F32 running_height = (F32)*height;
01055 F32 target_height = (F32)*height;
01056
01057
01058 if (needsArrange())
01059 {
01060
01061
01062 mLastArrangeGeneration = mRoot->getArrangeGeneration();
01063 if (mIsOpen)
01064 {
01065
01066 S32 parent_item_height = mRect.getHeight();
01067
01068 folders_t::iterator fit = mFolders.begin();
01069 folders_t::iterator fend = mFolders.end();
01070 for(; fit < fend; ++fit)
01071 {
01072 LLFolderViewFolder* folderp = (*fit);
01073 if (getRoot()->getDebugFilters())
01074 {
01075 folderp->setVisible(TRUE);
01076 }
01077 else
01078 {
01079 folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS ||
01080 (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)));
01081 }
01082
01083 if (folderp->getVisible())
01084 {
01085 S32 child_width = *width;
01086 S32 child_height = 0;
01087 S32 child_top = parent_item_height - llround(running_height);
01088
01089 target_height += folderp->arrange( &child_width, &child_height, filter_generation );
01090
01091 running_height += (F32)child_height;
01092 *width = llmax(*width, child_width);
01093 folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() );
01094 }
01095 }
01096 items_t::iterator iit = mItems.begin();
01097 items_t::iterator iend = mItems.end();
01098 for(;iit < iend; ++iit)
01099 {
01100 LLFolderViewItem* itemp = (*iit);
01101 if (getRoot()->getDebugFilters())
01102 {
01103 itemp->setVisible(TRUE);
01104 }
01105 else
01106 {
01107 itemp->setVisible(itemp->getFiltered(filter_generation));
01108 }
01109
01110 if (itemp->getVisible())
01111 {
01112 S32 child_width = *width;
01113 S32 child_height = 0;
01114 S32 child_top = parent_item_height - llround(running_height);
01115
01116 target_height += itemp->arrange( &child_width, &child_height, filter_generation );
01117
01118 itemp->reshape( itemp->getRect().getWidth(), child_height);
01119
01120 running_height += (F32)child_height;
01121 *width = llmax(*width, child_width);
01122 itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() );
01123 }
01124 }
01125 }
01126
01127 mTargetHeight = target_height;
01128
01129 mLastCalculatedWidth = *width;
01130 }
01131 else
01132 {
01133
01134 *width = mLastCalculatedWidth;
01135 }
01136
01137
01138 if (llabs(mCurHeight - mTargetHeight) > 1.f)
01139 {
01140 mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT));
01141
01142 requestArrange();
01143
01144
01145 for (folders_t::iterator iter = mFolders.begin();
01146 iter != mFolders.end();)
01147 {
01148 folders_t::iterator fit = iter++;
01149
01150 if (mRect.getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight()
01151 > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP)
01152 {
01153
01154 (*fit)->setVisible(FALSE);
01155 }
01156 }
01157
01158 for (items_t::iterator iter = mItems.begin();
01159 iter != mItems.end();)
01160 {
01161 items_t::iterator iit = iter++;
01162
01163 if (mRect.getHeight() - (*iit)->getRect().mBottom
01164 > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP)
01165 {
01166 (*iit)->setVisible(FALSE);
01167 }
01168 }
01169 }
01170 else
01171 {
01172 mCurHeight = mTargetHeight;
01173 }
01174
01175
01176 reshape(mRect.getWidth(),llround(mCurHeight));
01177
01178
01179 *height = llround(mCurHeight);
01180
01181 return llround(mTargetHeight);
01182 }
01183
01184 BOOL LLFolderViewFolder::needsArrange()
01185 {
01186 return mLastArrangeGeneration < mRoot->getArrangeGeneration();
01187 }
01188
01189 void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up)
01190 {
01191 mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
01192 mCompletedFilterGeneration = generation;
01193
01194 if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration())
01195 {
01196 mParentFolder->setCompletedFilterGeneration(generation, TRUE);
01197 }
01198 }
01199
01200 void LLFolderViewFolder::filter( LLInventoryFilter& filter)
01201 {
01202 S32 filter_generation = filter.getCurrentGeneration();
01203
01204
01205
01206 S32 must_pass_generation = filter.getMustPassGeneration();
01207
01208
01209 if (getCompletedFilterGeneration() >= filter_generation)
01210 {
01211 return;
01212 }
01213
01214
01215 if (getLastFilterGeneration() < filter_generation)
01216 {
01217 if (getLastFilterGeneration() >= must_pass_generation &&
01218 !mFiltered)
01219 {
01220
01221 mLastFilterGeneration = filter_generation;
01222 }
01223 else
01224 {
01225
01226 LLFolderViewItem::filter( filter );
01227 }
01228 }
01229
01230 if (getRoot()->getDebugFilters())
01231 {
01232 mStatusText = llformat("%d", mLastFilterGeneration);
01233 mStatusText += llformat("(%d)", mCompletedFilterGeneration);
01234 mStatusText += llformat("+%d", mMostFilteredDescendantGeneration);
01235 }
01236
01237
01238
01239 if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation))
01240 {
01241
01242
01243 return;
01244 }
01245
01246
01247
01248 if (filter.getFilterCount() < 0)
01249 {
01250 return;
01251 }
01252
01253
01254 if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
01255 {
01256 gInventory.startBackgroundFetch(mListener->getUUID());
01257 }
01258
01259
01260 for (folders_t::iterator iter = mFolders.begin();
01261 iter != mFolders.end();)
01262 {
01263 folders_t::iterator fit = iter++;
01264
01265 if (filter.getFilterCount() < 0)
01266 {
01267 break;
01268 }
01269
01270
01271
01272
01273 if ((*fit)->getCompletedFilterGeneration() >= filter_generation)
01274 {
01275
01276 if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration()))
01277 {
01278 mMostFilteredDescendantGeneration = filter_generation;
01279 if (mRoot->needsAutoSelect())
01280 {
01281 (*fit)->setOpenArrangeRecursively(TRUE);
01282 }
01283 }
01284
01285 continue;
01286 }
01287
01288
01289 (*fit)->filter( filter );
01290
01291
01292 if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation))
01293 {
01294 mMostFilteredDescendantGeneration = filter_generation;
01295 if (mRoot->needsAutoSelect())
01296 {
01297 (*fit)->setOpenArrangeRecursively(TRUE);
01298 }
01299 }
01300 }
01301
01302 for (items_t::iterator iter = mItems.begin();
01303 iter != mItems.end();)
01304 {
01305 items_t::iterator iit = iter++;
01306 if (filter.getFilterCount() < 0)
01307 {
01308 break;
01309 }
01310 if ((*iit)->getLastFilterGeneration() >= filter_generation)
01311 {
01312 if ((*iit)->getFiltered())
01313 {
01314 mMostFilteredDescendantGeneration = filter_generation;
01315 }
01316 continue;
01317 }
01318
01319 if ((*iit)->getLastFilterGeneration() >= must_pass_generation &&
01320 !(*iit)->getFiltered(must_pass_generation))
01321 {
01322
01323
01324 (*iit)->setFiltered(FALSE, filter_generation);
01325 continue;
01326 }
01327
01328 (*iit)->filter( filter );
01329
01330 if ((*iit)->getFiltered(filter.getMinRequiredGeneration()))
01331 {
01332 mMostFilteredDescendantGeneration = filter_generation;
01333 }
01334 }
01335
01336
01337
01338
01339 if (filter.getFilterCount() > 0)
01340 {
01341
01342 setCompletedFilterGeneration(filter_generation, FALSE);
01343 }
01344 }
01345
01346 void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation)
01347 {
01348
01349
01350 if (filtered && !mFiltered)
01351 {
01352
01353
01354 mCurHeight = 0.f;
01355 }
01356
01357 LLFolderViewItem::setFiltered(filtered, filter_generation);
01358 }
01359
01360 void LLFolderViewFolder::dirtyFilter()
01361 {
01362
01363 setCompletedFilterGeneration(-1, FALSE);
01364 LLFolderViewItem::dirtyFilter();
01365 }
01366
01367 BOOL LLFolderViewFolder::hasFilteredDescendants()
01368 {
01369 return mMostFilteredDescendantGeneration >= mRoot->getFilter()->getCurrentGeneration();
01370 }
01371
01372
01373
01374 BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL open,
01375 BOOL take_keyboard_focus)
01376 {
01377 BOOL rv = FALSE;
01378 if( selection == this )
01379 {
01380 mIsSelected = TRUE;
01381 if(mListener)
01382 {
01383 mListener->selectItem();
01384 }
01385 rv = TRUE;
01386 }
01387 else
01388 {
01389 mIsSelected = FALSE;
01390 rv = FALSE;
01391 }
01392 BOOL child_selected = FALSE;
01393
01394 for (folders_t::iterator iter = mFolders.begin();
01395 iter != mFolders.end();)
01396 {
01397 folders_t::iterator fit = iter++;
01398 if((*fit)->setSelection(selection, open, take_keyboard_focus))
01399 {
01400 rv = TRUE;
01401 child_selected = TRUE;
01402 mNumDescendantsSelected++;
01403 }
01404 }
01405 for (items_t::iterator iter = mItems.begin();
01406 iter != mItems.end();)
01407 {
01408 items_t::iterator iit = iter++;
01409 if((*iit)->setSelection(selection, open, take_keyboard_focus))
01410 {
01411 rv = TRUE;
01412 child_selected = TRUE;
01413 mNumDescendantsSelected++;
01414 }
01415 }
01416 if(open && child_selected)
01417 {
01418 setOpenArrangeRecursively(TRUE);
01419 }
01420 return rv;
01421 }
01422
01423
01424
01425
01426 BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection,
01427 BOOL selected)
01428 {
01429 BOOL rv = FALSE;
01430 if(selection == this)
01431 {
01432 mIsSelected = selected;
01433 if(mListener && selected)
01434 {
01435 mListener->selectItem();
01436 }
01437 rv = TRUE;
01438 }
01439
01440 for (folders_t::iterator iter = mFolders.begin();
01441 iter != mFolders.end();)
01442 {
01443 folders_t::iterator fit = iter++;
01444 if((*fit)->changeSelection(selection, selected))
01445 {
01446 if (selected)
01447 {
01448 mNumDescendantsSelected++;
01449 }
01450 else
01451 {
01452 mNumDescendantsSelected--;
01453 }
01454 rv = TRUE;
01455 }
01456 }
01457 for (items_t::iterator iter = mItems.begin();
01458 iter != mItems.end();)
01459 {
01460 items_t::iterator iit = iter++;
01461 if((*iit)->changeSelection(selection, selected))
01462 {
01463 if (selected)
01464 {
01465 mNumDescendantsSelected++;
01466 }
01467 else
01468 {
01469 mNumDescendantsSelected--;
01470 }
01471 rv = TRUE;
01472 }
01473 }
01474 return rv;
01475 }
01476
01477 S32 LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items)
01478 {
01479 S32 num_selected = 0;
01480
01481
01482 for (folders_t::iterator iter = mFolders.begin();
01483 iter != mFolders.end();)
01484 {
01485 folders_t::iterator fit = iter++;
01486 num_selected += (*fit)->extendSelection(selection, last_selected, selected_items);
01487 mNumDescendantsSelected += num_selected;
01488 }
01489
01490
01491 BOOL reverse_select = FALSE;
01492 BOOL found_last_selected = FALSE;
01493 BOOL found_selection = FALSE;
01494 LLDynamicArray<LLFolderViewItem*> items_to_select;
01495 LLFolderViewItem* item;
01496
01497
01498 for (folders_t::iterator iter = mFolders.begin();
01499 iter != mFolders.end();)
01500 {
01501 folders_t::iterator fit = iter++;
01502 item = (*fit);
01503 if(item == selection)
01504 {
01505 found_selection = TRUE;
01506 }
01507 else if (item == last_selected)
01508 {
01509 found_last_selected = TRUE;
01510 if (found_selection)
01511 {
01512 reverse_select = TRUE;
01513 }
01514 }
01515
01516 if (found_selection || found_last_selected)
01517 {
01518
01519 if (item->isSelected())
01520 {
01521 item->changeSelection(item, FALSE);
01522 }
01523 items_to_select.put(item);
01524 }
01525
01526 if (found_selection && found_last_selected)
01527 {
01528 break;
01529 }
01530 }
01531
01532 if (!(found_selection && found_last_selected))
01533 {
01534
01535 for (items_t::iterator iter = mItems.begin();
01536 iter != mItems.end();)
01537 {
01538 items_t::iterator iit = iter++;
01539 item = (*iit);
01540 if(item == selection)
01541 {
01542 found_selection = TRUE;
01543 }
01544 else if (item == last_selected)
01545 {
01546 found_last_selected = TRUE;
01547 if (found_selection)
01548 {
01549 reverse_select = TRUE;
01550 }
01551 }
01552
01553 if (found_selection || found_last_selected)
01554 {
01555
01556 if (item->isSelected())
01557 {
01558 item->changeSelection(item, FALSE);
01559 }
01560 items_to_select.put(item);
01561 }
01562
01563 if (found_selection && found_last_selected)
01564 {
01565 break;
01566 }
01567 }
01568 }
01569
01570 if (found_last_selected && found_selection)
01571 {
01572
01573 for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0;
01574 reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++)
01575 {
01576 LLFolderViewItem* item = items_to_select[index];
01577 if (item->changeSelection(item, TRUE))
01578 {
01579 selected_items.put(item);
01580 mNumDescendantsSelected++;
01581 num_selected++;
01582 }
01583 }
01584 }
01585 else if (found_selection)
01586 {
01587
01588 if (selection->changeSelection(selection, TRUE))
01589 {
01590 selected_items.put(selection);
01591 mNumDescendantsSelected++;
01592 num_selected++;
01593 }
01594 }
01595
01596 return num_selected;
01597 }
01598
01599 void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self)
01600 {
01601
01602 llassert(mNumDescendantsSelected >= 0);
01603
01604 if (mIsSelected && deselect_self)
01605 {
01606 mIsSelected = FALSE;
01607
01608
01609 LLFolderViewFolder* parent_folder = getParentFolder();
01610 while(parent_folder)
01611 {
01612 parent_folder->mNumDescendantsSelected--;
01613 parent_folder = parent_folder->getParentFolder();
01614 }
01615 }
01616
01617 if (0 == mNumDescendantsSelected)
01618 {
01619 return;
01620 }
01621
01622 for (items_t::iterator iter = mItems.begin();
01623 iter != mItems.end();)
01624 {
01625 items_t::iterator iit = iter++;
01626 LLFolderViewItem* item = (*iit);
01627 item->recursiveDeselect(TRUE);
01628 }
01629
01630 for (folders_t::iterator iter = mFolders.begin();
01631 iter != mFolders.end();)
01632 {
01633 folders_t::iterator fit = iter++;
01634 LLFolderViewFolder* folder = (*fit);
01635 folder->recursiveDeselect(TRUE);
01636 }
01637
01638 }
01639
01640 void LLFolderViewFolder::destroyView()
01641 {
01642 for (items_t::iterator iter = mItems.begin();
01643 iter != mItems.end();)
01644 {
01645 items_t::iterator iit = iter++;
01646 LLFolderViewItem* item = (*iit);
01647 getRoot()->removeItemID(item->getListener()->getUUID());
01648 }
01649
01650 std::for_each(mItems.begin(), mItems.end(), DeletePointer());
01651 mItems.clear();
01652
01653 while (!mFolders.empty())
01654 {
01655 LLFolderViewFolder *folderp = mFolders.back();
01656 folderp->destroyView();
01657 }
01658
01659 mFolders.clear();
01660
01661 deleteAllChildren();
01662
01663 if (mParentFolder)
01664 {
01665 mParentFolder->removeView(this);
01666 }
01667 }
01668
01669
01670
01671 BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item)
01672 {
01673 if(item->remove())
01674 {
01675
01676
01677 return TRUE;
01678 }
01679 return FALSE;
01680 }
01681
01682
01683
01684 void LLFolderViewFolder::removeView(LLFolderViewItem* item)
01685 {
01686 if (!item || item->getParentFolder() != this)
01687 {
01688 return;
01689 }
01690
01691 item->recursiveDeselect(TRUE);
01692 getRoot()->removeFromSelectionList(item);
01693 extractItem(item);
01694 delete item;
01695 }
01696
01697
01698
01699 void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
01700 {
01701 items_t::iterator it = std::find(mItems.begin(), mItems.end(), item);
01702 if(it == mItems.end())
01703 {
01704
01705
01706
01707 LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item);
01708 folders_t::iterator ft;
01709 ft = std::find(mFolders.begin(), mFolders.end(), f);
01710 if(ft != mFolders.end())
01711 {
01712 mFolders.erase(ft);
01713 }
01714 }
01715 else
01716 {
01717 mItems.erase(it);
01718 }
01719
01720 dirtyFilter();
01721
01722 requestArrange();
01723 getRoot()->removeItemID(item->getListener()->getUUID());
01724 removeChild(item);
01725 }
01726
01727
01728
01729 void LLFolderViewFolder::resort(LLFolderViewItem* item)
01730 {
01731 std::sort(mItems.begin(), mItems.end(), mSortFunction);
01732 std::sort(mFolders.begin(), mFolders.end(), mSortFunction);
01733 }
01734
01735 bool LLFolderViewFolder::isTrash()
01736 {
01737 if (mAmTrash == LLFolderViewFolder::UNKNOWN)
01738 {
01739 mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH;
01740 }
01741 return mAmTrash == LLFolderViewFolder::TRASH;
01742 }
01743
01744 void LLFolderViewFolder::sortBy(U32 order)
01745 {
01746 if (!mSortFunction.updateSort(order))
01747 {
01748
01749 return;
01750 }
01751
01752
01753 for (folders_t::iterator iter = mFolders.begin();
01754 iter != mFolders.end();)
01755 {
01756 folders_t::iterator fit = iter++;
01757 (*fit)->sortBy(order);
01758 }
01759
01760 std::sort(mFolders.begin(), mFolders.end(), mSortFunction);
01761 std::sort(mItems.begin(), mItems.end(), mSortFunction);
01762
01763 if (order & LLInventoryFilter::SO_DATE)
01764 {
01765 U32 latest = 0;
01766
01767 if (!mItems.empty())
01768 {
01769 LLFolderViewItem* item = *(mItems.begin());
01770 latest = item->getCreationDate();
01771 }
01772
01773 if (!mFolders.empty())
01774 {
01775 LLFolderViewFolder* folder = *(mFolders.begin());
01776 if (folder->getCreationDate() > latest)
01777 {
01778 latest = folder->getCreationDate();
01779 }
01780 }
01781 mSubtreeCreationDate = latest;
01782 }
01783 }
01784
01785 void LLFolderViewFolder::setItemSortOrder(U32 ordering)
01786 {
01787 if (mSortFunction.updateSort(ordering))
01788 {
01789 for (folders_t::iterator iter = mFolders.begin();
01790 iter != mFolders.end();)
01791 {
01792 folders_t::iterator fit = iter++;
01793 (*fit)->setItemSortOrder(ordering);
01794 }
01795
01796 std::sort(mFolders.begin(), mFolders.end(), mSortFunction);
01797 std::sort(mItems.begin(), mItems.end(), mSortFunction);
01798 }
01799 }
01800
01801 EInventorySortGroup LLFolderViewFolder::getSortGroup()
01802 {
01803 if (isTrash())
01804 {
01805 return SG_TRASH_FOLDER;
01806 }
01807
01808
01809 if( mListener )
01810 {
01811 if( !(mListener->isItemMovable()) )
01812 {
01813 return SG_SYSTEM_FOLDER;
01814 }
01815 }
01816
01817 return SG_NORMAL_FOLDER;
01818 }
01819
01820 BOOL LLFolderViewFolder::isMovable()
01821 {
01822 if( mListener )
01823 {
01824 if( !(mListener->isItemMovable()) )
01825 {
01826 return FALSE;
01827 }
01828
01829 for (items_t::iterator iter = mItems.begin();
01830 iter != mItems.end();)
01831 {
01832 items_t::iterator iit = iter++;
01833 if(!(*iit)->isMovable())
01834 {
01835 return FALSE;
01836 }
01837 }
01838
01839 for (folders_t::iterator iter = mFolders.begin();
01840 iter != mFolders.end();)
01841 {
01842 folders_t::iterator fit = iter++;
01843 if(!(*fit)->isMovable())
01844 {
01845 return FALSE;
01846 }
01847 }
01848 }
01849 return TRUE;
01850 }
01851
01852
01853 BOOL LLFolderViewFolder::isRemovable()
01854 {
01855 if( mListener )
01856 {
01857 if( !(mListener->isItemRemovable()) )
01858 {
01859 return FALSE;
01860 }
01861
01862 for (items_t::iterator iter = mItems.begin();
01863 iter != mItems.end();)
01864 {
01865 items_t::iterator iit = iter++;
01866 if(!(*iit)->isRemovable())
01867 {
01868 return FALSE;
01869 }
01870 }
01871
01872 for (folders_t::iterator iter = mFolders.begin();
01873 iter != mFolders.end();)
01874 {
01875 folders_t::iterator fit = iter++;
01876 if(!(*fit)->isRemovable())
01877 {
01878 return FALSE;
01879 }
01880 }
01881 }
01882 return TRUE;
01883 }
01884
01885
01886 BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
01887 {
01888
01889 items_t::iterator it = std::lower_bound(
01890 mItems.begin(),
01891 mItems.end(),
01892 item,
01893 mSortFunction);
01894 mItems.insert(it,item);
01895 item->setRect(LLRect(0, 0, mRect.getWidth(), 0));
01896 item->setVisible(FALSE);
01897 addChild( item );
01898 item->dirtyFilter();
01899 requestArrange();
01900 return TRUE;
01901 }
01902
01903
01904 BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
01905 {
01906 folders_t::iterator it = std::lower_bound(
01907 mFolders.begin(),
01908 mFolders.end(),
01909 folder,
01910 mSortFunction);
01911 mFolders.insert(it,folder);
01912 folder->setOrigin(0, 0);
01913 folder->reshape(mRect.getWidth(), 0);
01914 folder->setVisible(FALSE);
01915 addChild( folder );
01916 folder->dirtyFilter();
01917
01918 folder->requestArrange(TRUE);
01919 return TRUE;
01920 }
01921
01922 void LLFolderViewFolder::requestArrange(BOOL include_descendants)
01923 {
01924 mLastArrangeGeneration = -1;
01925
01926 if (mParentFolder)
01927 {
01928 mParentFolder->requestArrange();
01929 }
01930
01931 if (include_descendants)
01932 {
01933 for (folders_t::iterator iter = mFolders.begin();
01934 iter != mFolders.end();
01935 ++iter)
01936 {
01937 (*iter)->requestArrange(TRUE);
01938 }
01939 }
01940 }
01941
01942 void LLFolderViewFolder::toggleOpen()
01943 {
01944 setOpen(!mIsOpen);
01945 }
01946
01947
01948 void LLFolderViewFolder::setOpen(BOOL open)
01949 {
01950 setOpenArrangeRecursively(open);
01951 }
01952
01953 void LLFolderViewFolder::setOpenArrangeRecursively(BOOL open, ERecurseType recurse)
01954 {
01955 BOOL was_open = mIsOpen;
01956 mIsOpen = open;
01957 if(!was_open && open)
01958 {
01959 if(mListener)
01960 {
01961 mListener->openItem();
01962 }
01963 }
01964 if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN)
01965 {
01966 for (folders_t::iterator iter = mFolders.begin();
01967 iter != mFolders.end();)
01968 {
01969 folders_t::iterator fit = iter++;
01970 (*fit)->setOpenArrangeRecursively(open, RECURSE_DOWN);
01971 }
01972 }
01973 if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN))
01974 {
01975 mParentFolder->setOpenArrangeRecursively(open, RECURSE_UP);
01976 }
01977
01978 if (was_open != mIsOpen)
01979 {
01980 requestArrange();
01981 }
01982 }
01983
01984 BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask,
01985 BOOL drop,
01986 EDragAndDropType c_type,
01987 void* cargo_data,
01988 EAcceptance* accept,
01989 LLString& tooltip_msg)
01990 {
01991 BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data);
01992 if (accepted)
01993 {
01994 mDragAndDropTarget = TRUE;
01995 *accept = ACCEPT_YES_MULTI;
01996 }
01997 else
01998 {
01999 *accept = ACCEPT_NO;
02000 }
02001
02002
02003 getRoot()->autoOpenTest(NULL);
02004
02005 return TRUE;
02006 }
02007
02008 void LLFolderViewFolder::open( void )
02009 {
02010 toggleOpen();
02011 }
02012
02013 void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor)
02014 {
02015 functor.doFolder(this);
02016
02017 for (folders_t::iterator iter = mFolders.begin();
02018 iter != mFolders.end();)
02019 {
02020 folders_t::iterator fit = iter++;
02021 (*fit)->applyFunctorRecursively(functor);
02022 }
02023 for (items_t::iterator iter = mItems.begin();
02024 iter != mItems.end();)
02025 {
02026 items_t::iterator iit = iter++;
02027 functor.doItem((*iit));
02028 }
02029 }
02030
02031 void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor)
02032 {
02033 functor(mListener);
02034 for (folders_t::iterator iter = mFolders.begin();
02035 iter != mFolders.end();)
02036 {
02037 folders_t::iterator fit = iter++;
02038 (*fit)->applyListenerFunctorRecursively(functor);
02039 }
02040 for (items_t::iterator iter = mItems.begin();
02041 iter != mItems.end();)
02042 {
02043 items_t::iterator iit = iter++;
02044 (*iit)->applyListenerFunctorRecursively(functor);
02045 }
02046 }
02047
02048
02049 BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
02050 BOOL drop,
02051 EDragAndDropType cargo_type,
02052 void* cargo_data,
02053 EAcceptance* accept,
02054 LLString& tooltip_msg)
02055 {
02056 LLFolderView* root_view = getRoot();
02057
02058 BOOL handled = FALSE;
02059 if(mIsOpen)
02060 {
02061 handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
02062 cargo_data, accept, tooltip_msg) != NULL;
02063 }
02064
02065 if (!handled)
02066 {
02067 BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data);
02068
02069 if (accepted)
02070 {
02071 mDragAndDropTarget = TRUE;
02072 *accept = ACCEPT_YES_MULTI;
02073 }
02074 else
02075 {
02076 *accept = ACCEPT_NO;
02077 }
02078
02079 if (!drop && accepted)
02080 {
02081 root_view->autoOpenTest(this);
02082 }
02083
02084 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl;
02085 }
02086
02087 return TRUE;
02088 }
02089
02090
02091 BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask )
02092 {
02093 BOOL handled = FALSE;
02094 if( getVisible() )
02095 {
02096
02097
02098 gInventory.fetchDescendentsOf(mListener->getUUID());
02099
02100 if( mIsOpen )
02101 {
02102 handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
02103 }
02104 if (!handled)
02105 {
02106 handled = LLFolderViewItem::handleRightMouseDown( x, y, mask );
02107 }
02108 }
02109 return handled;
02110 }
02111
02112
02113 BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask)
02114 {
02115 BOOL handled = LLView::handleHover(x, y, mask);
02116
02117 if (!handled)
02118 {
02119
02120 handled = LLFolderViewItem::handleHover(x, y, mask);
02121 }
02122
02123
02124
02125
02126
02127
02128
02129 return handled;
02130 }
02131
02132 BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
02133 {
02134 BOOL handled = FALSE;
02135 if( mIsOpen )
02136 {
02137 handled = childrenHandleMouseDown(x,y,mask) != NULL;
02138 }
02139 if( !handled )
02140 {
02141 if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD)
02142 {
02143 toggleOpen();
02144 handled = TRUE;
02145 }
02146 else
02147 {
02148
02149 handled = LLFolderViewItem::handleMouseDown(x, y, mask);
02150 }
02151 }
02152
02153 return handled;
02154 }
02155
02156 BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
02157 {
02158 if (!getVisible())
02159 {
02160 return FALSE;
02161 }
02162 BOOL rv = false;
02163 if( mIsOpen )
02164 {
02165 rv = childrenHandleDoubleClick( x, y, mask ) != NULL;
02166 }
02167 if( !rv )
02168 {
02169 if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD)
02170 {
02171
02172
02173 toggleOpen();
02174 }
02175 else
02176 {
02177 setSelectionFromRoot(this, FALSE);
02178 toggleOpen();
02179 }
02180 return TRUE;
02181 }
02182 return rv;
02183 }
02184
02185 void LLFolderViewFolder::draw()
02186 {
02187 if (mAutoOpenCountdown != 0.f)
02188 {
02189 mControlLabelRotation = mAutoOpenCountdown * -90.f;
02190 }
02191 else if (mIsOpen)
02192 {
02193 mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f));
02194 }
02195 else
02196 {
02197 mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f));
02198 }
02199
02200 LLFolderViewItem::draw();
02201
02202
02203 if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight ))
02204 {
02205 LLView::draw();
02206 }
02207
02208 mExpanderHighlighted = FALSE;
02209 }
02210
02211 U32 LLFolderViewFolder::getCreationDate() const
02212 {
02213 return llmax<U32>(mCreationDate, mSubtreeCreationDate);
02214 }
02215
02216
02217 BOOL LLFolderViewFolder::potentiallyVisible()
02218 {
02219
02220 return LLFolderViewItem::potentiallyVisible()
02221
02222 || hasFilteredDescendants(mRoot->getFilter()->getMinRequiredGeneration())
02223
02224 || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration();
02225 }
02226
02227
02228 LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children )
02229 {
02230 BOOL found_item = FALSE;
02231
02232 LLFolderViewItem* result = NULL;
02233
02234 if(item == NULL)
02235 {
02236 found_item = TRUE;
02237 }
02238
02239
02240 folders_t::iterator fit = mFolders.begin();
02241 folders_t::iterator fend = mFolders.end();
02242
02243 items_t::iterator iit = mItems.begin();
02244 items_t::iterator iend = mItems.end();
02245
02246
02247 if (!found_item)
02248 {
02249
02250 for(; fit != fend; ++fit)
02251 {
02252 if(item == (*fit))
02253 {
02254 found_item = TRUE;
02255
02256 if (include_children && (*fit)->isOpen())
02257 {
02258
02259 return (*fit)->getNextFromChild(NULL, TRUE);
02260 }
02261
02262 ++fit;
02263 include_children = TRUE;
02264 break;
02265 }
02266 }
02267
02268
02269 if (!found_item)
02270 {
02271 for(; iit != iend; ++iit)
02272 {
02273 if(item == (*iit))
02274 {
02275 found_item = TRUE;
02276
02277 ++iit;
02278 break;
02279 }
02280 }
02281 }
02282 }
02283
02284 if (!found_item)
02285 {
02286
02287
02288 llassert(FALSE);
02289 return NULL;
02290 }
02291
02292
02293
02294
02295
02296
02297 while(fit != fend && !(*fit)->getVisible())
02298 {
02299
02300 ++fit;
02301 }
02302
02303 if (fit != fend)
02304 {
02305 result = (*fit);
02306 }
02307 else
02308 {
02309
02310 while(iit != iend && !(*iit)->getVisible())
02311 {
02312 ++iit;
02313 }
02314
02315
02316 if (iit != iend)
02317 {
02318 result = (*iit);
02319 }
02320 }
02321
02322 if( !result && mParentFolder )
02323 {
02324
02325
02326 result = mParentFolder->getNextFromChild(this, FALSE);
02327 }
02328
02329 return result;
02330 }
02331
02332
02333 LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children )
02334 {
02335 BOOL found_item = FALSE;
02336
02337 LLFolderViewItem* result = NULL;
02338
02339 if(item == NULL)
02340 {
02341 found_item = TRUE;
02342 }
02343
02344
02345 folders_t::reverse_iterator fit = mFolders.rbegin();
02346 folders_t::reverse_iterator fend = mFolders.rend();
02347
02348 items_t::reverse_iterator iit = mItems.rbegin();
02349 items_t::reverse_iterator iend = mItems.rend();
02350
02351
02352 if (!found_item)
02353 {
02354
02355 for(; iit != iend; ++iit)
02356 {
02357 if(item == (*iit))
02358 {
02359 found_item = TRUE;
02360
02361 ++iit;
02362 break;
02363 }
02364 }
02365
02366
02367 if (!found_item)
02368 {
02369 for(; fit != fend; ++fit)
02370 {
02371 if(item == (*fit))
02372 {
02373 found_item = TRUE;
02374
02375 ++fit;
02376 break;
02377 }
02378 }
02379 }
02380 }
02381
02382 if (!found_item)
02383 {
02384
02385
02386 llassert(FALSE);
02387 return NULL;
02388 }
02389
02390
02391
02392
02393
02394
02395 while(iit != iend && !(*iit)->getVisible())
02396 {
02397 ++iit;
02398 }
02399
02400 if (iit != iend)
02401 {
02402
02403 result = (*iit);
02404 }
02405 else
02406 {
02407
02408 while(fit != fend && !(*fit)->getVisible())
02409 {
02410 ++fit;
02411 }
02412
02413
02414 if (fit != fend)
02415 {
02416
02417 if ((*fit)->isOpen())
02418 {
02419 result = (*fit)->getPreviousFromChild(NULL);
02420 }
02421 else
02422 {
02423 result = (*fit);
02424 }
02425 }
02426 }
02427
02428 if( !result )
02429 {
02430
02431
02432 result = this;
02433 }
02434
02435 return result;
02436 }
02437
02438
02439
02440
02441
02442
02443 class LLSetItemSortFunction : public LLFolderViewFunctor
02444 {
02445 public:
02446 LLSetItemSortFunction(U32 ordering)
02447 : mSortOrder(ordering) {}
02448 virtual ~LLSetItemSortFunction() {}
02449 virtual void doFolder(LLFolderViewFolder* folder);
02450 virtual void doItem(LLFolderViewItem* item);
02451
02452 U32 mSortOrder;
02453 };
02454
02455
02456
02457 void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder)
02458 {
02459 folder->setItemSortOrder(mSortOrder);
02460 }
02461
02462
02463 void LLSetItemSortFunction::doItem(LLFolderViewItem* item)
02464 {
02465 return;
02466 }
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480 class LLCloseAllFoldersFunctor : public LLFolderViewFunctor
02481 {
02482 public:
02483 LLCloseAllFoldersFunctor(BOOL close) { mOpen = !close; }
02484 virtual ~LLCloseAllFoldersFunctor() {}
02485 virtual void doFolder(LLFolderViewFolder* folder);
02486 virtual void doItem(LLFolderViewItem* item);
02487
02488 BOOL mOpen;
02489 };
02490
02491
02492
02493 void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder)
02494 {
02495 folder->setOpenArrangeRecursively(mOpen);
02496 }
02497
02498
02499 void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
02500 { }
02501
02505
02506
02507 LLFolderView::LLFolderView( const LLString& name, LLViewerImage* root_folder_icon,
02508 const LLRect& rect, const LLUUID& source_id, LLView *parent_view ) :
02509 #if LL_WINDOWS
02510 #pragma warning( push )
02511 #pragma warning( disable : 4355 )
02512 #endif
02513 LLFolderViewFolder( name, root_folder_icon, this, NULL ),
02514 #if LL_WINDOWS
02515 #pragma warning( pop )
02516 #endif
02517 mScrollContainer( NULL ),
02518 mPopupMenuHandle( LLViewHandle::sDeadHandle ),
02519 mAllowMultiSelect(TRUE),
02520 mShowFolderHierarchy(FALSE),
02521 mSourceID(source_id),
02522 mRenameItem( NULL ),
02523 mNeedsScroll( FALSE ),
02524 mLastScrollItem( NULL ),
02525 mNeedsAutoSelect( FALSE ),
02526 mAutoSelectOverride(FALSE),
02527 mNeedsAutoRename(FALSE),
02528 mDebugFilters(FALSE),
02529 mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME),
02530 mFilter(name),
02531 mShowSelectionContext(FALSE),
02532 mShowSingleSelection(FALSE),
02533 mArrangeGeneration(0),
02534 mUserData(NULL),
02535 mSelectCallback(NULL),
02536 mSelectionChanged(FALSE),
02537 mMinWidth(0),
02538 mDragAndDropThisFrame(FALSE)
02539 {
02540 LLRect new_rect(rect.mLeft, rect.mBottom + mRect.getHeight(), rect.mLeft + mRect.getWidth(), rect.mBottom);
02541 setRect( rect );
02542 reshape(rect.getWidth(), rect.getHeight());
02543 mIsOpen = TRUE;
02544 mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH);
02545 mAutoOpenCandidate = NULL;
02546 mAutoOpenTimer.stop();
02547 mKeyboardSelection = FALSE;
02548 mIndentation = -LEFT_INDENTATION;
02549 gIdleCallbacks.addFunction(idle, this);
02550
02551
02552
02553
02554 mLabel = LLString::null;
02555
02556 mRenamer = new LLLineEditor("ren", mRect, "", sFont,
02557 DB_INV_ITEM_NAME_STR_LEN,
02558 &LLFolderView::commitRename,
02559 NULL,
02560 NULL,
02561 this,
02562 &LLLineEditor::prevalidatePrintableNotPipe,
02563 LLViewBorder::BEVEL_NONE,
02564 LLViewBorder::STYLE_LINE,
02565 2);
02566 mRenamer->setWriteableBgColor(LLColor4::white);
02567
02568 mRenamer->setCommitOnFocusLost(TRUE);
02569 mRenamer->setVisible(FALSE);
02570 addChild(mRenamer);
02571
02572
02573 LLMenuGL* menu = gUICtrlFactory->buildMenu("menu_inventory.xml", parent_view);
02574 if (!menu)
02575 {
02576 menu = new LLMenuGL("");
02577 }
02578 menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
02579 menu->setVisible(FALSE);
02580 mPopupMenuHandle = menu->mViewHandle;
02581
02582 setTabStop(TRUE);
02583 }
02584
02585
02586 LLFolderView::~LLFolderView( void )
02587 {
02588
02589
02590
02591
02592
02593 mScrollContainer = NULL;
02594 mRenameItem = NULL;
02595 mRenamer = NULL;
02596 gFocusMgr.releaseFocusIfNeeded( this );
02597
02598 if( gEditMenuHandler == this )
02599 {
02600 gEditMenuHandler = NULL;
02601 }
02602
02603 mAutoOpenItems.removeAllNodes();
02604 gIdleCallbacks.deleteFunction(idle, this);
02605
02606 LLView::deleteViewByHandle(mPopupMenuHandle);
02607
02608 if(gViewerWindow->hasTopCtrl(mRenamer))
02609 {
02610 gViewerWindow->setTopCtrl(NULL);
02611 }
02612
02613 mAutoOpenItems.removeAllNodes();
02614 clearSelection();
02615 mItems.clear();
02616 mFolders.clear();
02617
02618 mItemMap.clear();
02619 }
02620
02621 EWidgetType LLFolderView::getWidgetType() const
02622 {
02623 return WIDGET_TYPE_FOLDER_VIEW;
02624 }
02625
02626 LLString LLFolderView::getWidgetTag() const
02627 {
02628 return LL_FOLDER_VIEW_TAG;
02629 }
02630
02631 BOOL LLFolderView::canFocusChildren() const
02632 {
02633 return FALSE;
02634 }
02635
02636 void LLFolderView::checkTreeResortForModelChanged()
02637 {
02638 if (mSortOrder & LLInventoryFilter::SO_DATE && !(mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME))
02639 {
02640
02641
02642
02643 mSortOrder = mSortOrder & ~LLInventoryFilter::SO_DATE;
02644 setSortOrder(mSortOrder | LLInventoryFilter::SO_DATE);
02645 }
02646 }
02647
02648 void LLFolderView::setSortOrder(U32 order)
02649 {
02650 if (order != mSortOrder)
02651 {
02652 LLFastTimer t(LLFastTimer::FTM_SORT);
02653 mSortOrder = order;
02654
02655 for (folders_t::iterator iter = mFolders.begin();
02656 iter != mFolders.end();)
02657 {
02658 folders_t::iterator fit = iter++;
02659 (*fit)->sortBy(order);
02660 }
02661
02662 arrangeAll();
02663 }
02664 }
02665
02666
02667 U32 LLFolderView::getSortOrder() const
02668 {
02669 return mSortOrder;
02670 }
02671
02672 BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
02673 {
02674
02675 if (folder->getListener()->getUUID() == gInventoryLibraryRoot)
02676 {
02677 mFolders.push_back(folder);
02678 }
02679 else
02680 {
02681 mFolders.insert(mFolders.begin(), folder);
02682 }
02683 folder->setOrigin(0, 0);
02684 folder->reshape(mRect.getWidth(), 0);
02685 folder->setVisible(FALSE);
02686 addChild( folder );
02687 folder->dirtyFilter();
02688 folder->requestArrange();
02689 return TRUE;
02690 }
02691
02692 void LLFolderView::closeAllFolders()
02693 {
02694
02695 setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
02696 }
02697
02698 void LLFolderView::openFolder(const LLString& foldername)
02699 {
02700 LLFolderViewFolder* inv = (LLFolderViewFolder*)getChildByName(foldername);
02701 if (inv)
02702 {
02703 setSelection(inv, FALSE, FALSE);
02704 inv->setOpen(TRUE);
02705 }
02706 }
02707
02708 void LLFolderView::setOpenArrangeRecursively(BOOL open, ERecurseType recurse)
02709 {
02710
02711 LLFolderViewFolder::setOpenArrangeRecursively(open, recurse);
02712
02713 mIsOpen = TRUE;
02714 }
02715
02716
02717 S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )
02718 {
02719 LLFastTimer t2(LLFastTimer::FTM_ARRANGE);
02720
02721 filter_generation = mFilter.getMinRequiredGeneration();
02722 mMinWidth = 0;
02723
02724 mHasVisibleChildren = hasFilteredDescendants(filter_generation);
02725
02726 mLastArrangeGeneration = mRoot->getArrangeGeneration();
02727
02728 LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getShowFolderState();
02729
02730 S32 total_width = LEFT_PAD;
02731 S32 running_height = mDebugFilters ? llceil(sSmallFont->getLineHeight()) : 0;
02732 S32 target_height = running_height;
02733 S32 parent_item_height = mRect.getHeight();
02734
02735 for (folders_t::iterator iter = mFolders.begin();
02736 iter != mFolders.end();)
02737 {
02738 folders_t::iterator fit = iter++;
02739 LLFolderViewFolder* folderp = (*fit);
02740 if (getDebugFilters())
02741 {
02742 folderp->setVisible(TRUE);
02743 }
02744 else
02745 {
02746 folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS ||
02747 (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)));
02748 }
02749 if (folderp->getVisible())
02750 {
02751 S32 child_height = 0;
02752 S32 child_width = 0;
02753 S32 child_top = parent_item_height - running_height;
02754
02755 target_height += folderp->arrange( &child_width, &child_height, filter_generation );
02756
02757 mMinWidth = llmax(mMinWidth, child_width);
02758 total_width = llmax( total_width, child_width );
02759 running_height += child_height;
02760 folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() );
02761 }
02762 }
02763
02764 for (items_t::iterator iter = mItems.begin();
02765 iter != mItems.end();)
02766 {
02767 items_t::iterator iit = iter++;
02768 LLFolderViewItem* itemp = (*iit);
02769 itemp->setVisible(itemp->getFiltered(filter_generation));
02770
02771 if (itemp->getVisible())
02772 {
02773 S32 child_width = 0;
02774 S32 child_height = 0;
02775 S32 child_top = parent_item_height - running_height;
02776
02777 target_height += itemp->arrange( &child_width, &child_height, filter_generation );
02778 itemp->reshape(itemp->getRect().getWidth(), child_height);
02779
02780 mMinWidth = llmax(mMinWidth, child_width);
02781 total_width = llmax( total_width, child_width );
02782 running_height += child_height;
02783 itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() );
02784 }
02785 }
02786
02787 S32 dummy_s32;
02788 BOOL dummy_bool;
02789 S32 min_width;
02790 mScrollContainer->calcVisibleSize( &min_width, &dummy_s32, &dummy_bool, &dummy_bool);
02791 reshape( llmax(min_width, total_width), running_height );
02792
02793 S32 new_min_width;
02794 mScrollContainer->calcVisibleSize( &new_min_width, &dummy_s32, &dummy_bool, &dummy_bool);
02795 if (new_min_width != min_width)
02796 {
02797 reshape( llmax(min_width, total_width), running_height );
02798 }
02799
02800 mTargetHeight = (F32)target_height;
02801 return llround(mTargetHeight);
02802 }
02803
02804 const LLString LLFolderView::getFilterSubString(BOOL trim)
02805 {
02806 return mFilter.getFilterSubString(trim);
02807 }
02808
02809 void LLFolderView::filter( LLInventoryFilter& filter )
02810 {
02811 LLFastTimer t2(LLFastTimer::FTM_FILTER);
02812 filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000));
02813
02814 if (getCompletedFilterGeneration() < filter.getCurrentGeneration())
02815 {
02816 mFiltered = FALSE;
02817 mMinWidth = 0;
02818 LLFolderViewFolder::filter(filter);
02819 }
02820 }
02821
02822 void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)
02823 {
02824 S32 min_width = 0;
02825 S32 dummy_height;
02826 BOOL dummy_bool;
02827 if (mScrollContainer)
02828 {
02829 mScrollContainer->calcVisibleSize( &min_width, &dummy_height, &dummy_bool, &dummy_bool);
02830 }
02831 width = llmax(mMinWidth, min_width);
02832 LLView::reshape(width, height, called_from_parent);
02833 }
02834
02835 void LLFolderView::addToSelectionList(LLFolderViewItem* item)
02836 {
02837 if (item->isSelected())
02838 {
02839 removeFromSelectionList(item);
02840 }
02841 if (mSelectedItems.size())
02842 {
02843 mSelectedItems.back()->setIsCurSelection(FALSE);
02844 }
02845 item->setIsCurSelection(TRUE);
02846 mSelectedItems.push_back(item);
02847 }
02848
02849 void LLFolderView::removeFromSelectionList(LLFolderViewItem* item)
02850 {
02851 if (mSelectedItems.size())
02852 {
02853 mSelectedItems.back()->setIsCurSelection(FALSE);
02854 }
02855
02856 selected_items_t::iterator item_iter;
02857 for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end();)
02858 {
02859 if (*item_iter == item)
02860 {
02861 item_iter = mSelectedItems.erase(item_iter);
02862 }
02863 else
02864 {
02865 ++item_iter;
02866 }
02867 }
02868 if (mSelectedItems.size())
02869 {
02870 mSelectedItems.back()->setIsCurSelection(TRUE);
02871 }
02872 }
02873
02874 LLFolderViewItem* LLFolderView::getCurSelectedItem( void )
02875 {
02876 if(mSelectedItems.size())
02877 {
02878 LLFolderViewItem* itemp = mSelectedItems.back();
02879 llassert(itemp->getIsCurSelection());
02880 return itemp;
02881 }
02882 return NULL;
02883 }
02884
02885
02886
02887 BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL open,
02888 BOOL take_keyboard_focus)
02889 {
02890 if( selection == this )
02891 {
02892 return FALSE;
02893 }
02894
02895 if( selection && take_keyboard_focus)
02896 {
02897 setFocus(TRUE);
02898 }
02899
02900
02901
02902 clearSelection();
02903
02904 if(selection)
02905 {
02906 addToSelectionList(selection);
02907 }
02908
02909 BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus);
02910 if(open && selection)
02911 {
02912 selection->getParentFolder()->requestArrange();
02913 }
02914
02915 llassert(mSelectedItems.size() <= 1);
02916
02917 mSelectionChanged = TRUE;
02918
02919 return rv;
02920 }
02921
02922 BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected)
02923 {
02924 BOOL rv = FALSE;
02925
02926
02927 if(!selection || selection == this)
02928 {
02929 return FALSE;
02930 }
02931
02932 if (!mAllowMultiSelect)
02933 {
02934 clearSelection();
02935 }
02936
02937 selected_items_t::iterator item_iter;
02938 for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter)
02939 {
02940 if (*item_iter == selection)
02941 {
02942 break;
02943 }
02944 }
02945
02946 BOOL on_list = (item_iter != mSelectedItems.end());
02947
02948 if(selected && !on_list)
02949 {
02950 addToSelectionList(selection);
02951 }
02952 if(!selected && on_list)
02953 {
02954 removeFromSelectionList(selection);
02955 }
02956
02957 rv = LLFolderViewFolder::changeSelection(selection, selected);
02958
02959 mSelectionChanged = TRUE;
02960
02961 return rv;
02962 }
02963
02964 S32 LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items)
02965 {
02966 S32 rv = 0;
02967
02968
02969 if (mAllowMultiSelect)
02970 {
02971 LLFolderViewItem *cur_selection = getCurSelectedItem();
02972 rv = LLFolderViewFolder::extendSelection(selection, cur_selection, items);
02973 for (S32 i = 0; i < items.count(); i++)
02974 {
02975 addToSelectionList(items[i]);
02976 rv++;
02977 }
02978 }
02979 else
02980 {
02981 setSelection(selection, FALSE, FALSE);
02982 rv++;
02983 }
02984
02985 mSelectionChanged = TRUE;
02986 return rv;
02987 }
02988
02989 void LLFolderView::sanitizeSelection()
02990 {
02991
02992
02993 LLFolderViewItem* original_selected_item = getCurSelectedItem();
02994
02995
02996 BOOL show_all_folders = (getRoot()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS);
02997
02998 std::vector<LLFolderViewItem*> items_to_remove;
02999 selected_items_t::iterator item_iter;
03000 for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter)
03001 {
03002 LLFolderViewItem* item = *item_iter;
03003
03004
03005 BOOL visible = item->potentiallyVisible();
03006
03007 LLFolderViewFolder* parent_folder = item->getParentFolder();
03008 if ( parent_folder )
03009 {
03010 if ( show_all_folders )
03011 {
03012 visible = TRUE;
03013 }
03014 else
03015 {
03016 while(parent_folder)
03017 {
03018 visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible();
03019 parent_folder = parent_folder->getParentFolder();
03020 }
03021 }
03022 }
03023
03024
03025 if (!visible)
03026 {
03027 items_to_remove.push_back(item);
03028 }
03029
03030
03031
03032
03033 selected_items_t::iterator other_item_iter;
03034 for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter)
03035 {
03036 LLFolderViewItem* other_item = *other_item_iter;
03037 for( parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder())
03038 {
03039 if (parent_folder == item)
03040 {
03041
03042 items_to_remove.push_back(other_item);
03043 break;
03044 }
03045 }
03046 }
03047 }
03048
03049 std::vector<LLFolderViewItem*>::iterator item_it;
03050 for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it )
03051 {
03052 changeSelection(*item_it, FALSE);
03053 }
03054
03055
03056 if (mSelectedItems.empty())
03057 {
03058
03059 LLFolderViewItem* new_selection = NULL;
03060 if (original_selected_item)
03061 {
03062 for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder();
03063 parent_folder;
03064 parent_folder = parent_folder->getParentFolder())
03065 {
03066 if (parent_folder->potentiallyVisible())
03067 {
03068
03069 if (!new_selection)
03070 {
03071 new_selection = parent_folder;
03072 }
03073
03074
03075
03076 if (!parent_folder->isOpen())
03077 {
03078 new_selection = parent_folder;
03079 }
03080 }
03081 }
03082 }
03083 else
03084 {
03085
03086 new_selection = getItemByID(gAgent.getInventoryRootID());
03087 }
03088
03089 if (new_selection)
03090 {
03091 setSelection(new_selection, FALSE, FALSE);
03092 }
03093 }
03094 }
03095
03096 void LLFolderView::clearSelection()
03097 {
03098 if (mSelectedItems.size() > 0)
03099 {
03100 recursiveDeselect(FALSE);
03101 mSelectedItems.clear();
03102 }
03103 }
03104
03105 BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection)
03106 {
03107 selected_items_t::iterator item_it;
03108 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03109 {
03110 selection.insert((*item_it)->getListener()->getUUID());
03111 }
03112
03113 return (selection.size() != 0);
03114 }
03115
03116 BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source)
03117 {
03118 std::vector<EDragAndDropType> types;
03119 std::vector<LLUUID> cargo_ids;
03120 selected_items_t::iterator item_it;
03121 BOOL can_drag = TRUE;
03122 if (!mSelectedItems.empty())
03123 {
03124 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03125 {
03126 EDragAndDropType type = DAD_NONE;
03127 LLUUID id = LLUUID::null;
03128 can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id);
03129
03130 types.push_back(type);
03131 cargo_ids.push_back(id);
03132 }
03133
03134 gToolDragAndDrop->beginMultiDrag(types, cargo_ids, source, mSourceID);
03135 }
03136 return can_drag;
03137 }
03138
03139 void LLFolderView::commitRename( LLUICtrl* renamer, void* user_data )
03140 {
03141 LLFolderView* root = reinterpret_cast<LLFolderView*>(user_data);
03142 if( root )
03143 {
03144 root->finishRenamingItem();
03145 }
03146 }
03147
03148 void LLFolderView::draw()
03149 {
03150 if (mDebugFilters)
03151 {
03152 LLString current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d",
03153 mFilter.getCurrentGeneration(), mFilter.getMinRequiredGeneration(), mFilter.getMustPassGeneration());
03154 sSmallFont->renderUTF8(current_filter_string, 0, 2,
03155 mRect.getHeight() - sSmallFont->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f),
03156 LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
03157 }
03158
03159
03160
03161 if (!mDragAndDropThisFrame)
03162 {
03163 closeAutoOpenedFolders();
03164 }
03165 if(gViewerWindow->hasKeyboardFocus(this) && !getVisible())
03166 {
03167 gViewerWindow->setKeyboardFocus( NULL, NULL );
03168 }
03169
03170
03171 if (gToolDragAndDrop && gToolDragAndDrop->hasMouseCapture())
03172 {
03173 EAcceptance last_accept = gToolDragAndDrop->getLastAccept();
03174 if (last_accept == ACCEPT_YES_SINGLE || last_accept == ACCEPT_YES_COPY_SINGLE)
03175 {
03176 setShowSingleSelection(TRUE);
03177 }
03178 else
03179 {
03180 setShowSingleSelection(FALSE);
03181 }
03182 }
03183 else
03184 {
03185 setShowSingleSelection(FALSE);
03186 }
03187
03188
03189 if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout") || !mSearchString.size())
03190 {
03191 mSearchString.clear();
03192 }
03193
03194 if (hasVisibleChildren() || getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS)
03195 {
03196 mStatusText.clear();
03197 }
03198 else
03199 {
03200 if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter.getMinRequiredGeneration())
03201 {
03202 mStatusText = "Searching...";
03203 sFont->renderUTF8(mStatusText, 0, 2, 1, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
03204 }
03205 else
03206 {
03207 mStatusText = "No matching items found in inventory.";
03208 sFont->renderUTF8(mStatusText, 0, 2, 1, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
03209 }
03210 }
03211
03212 LLFolderViewFolder::draw();
03213
03214 mDragAndDropThisFrame = FALSE;
03215 }
03216
03217 void LLFolderView::finishRenamingItem( void )
03218 {
03219 if(!mRenamer)
03220 {
03221 return;
03222 }
03223 if( mRenameItem )
03224 {
03225 mRenameItem->rename( mRenamer->getText().c_str() );
03226 }
03227
03228 mRenamer->setCommitOnFocusLost( FALSE );
03229 mRenamer->setFocus( FALSE );
03230 mRenamer->setVisible( FALSE );
03231 mRenamer->setCommitOnFocusLost( TRUE );
03232 gViewerWindow->setTopCtrl( NULL );
03233
03234 if( mRenameItem )
03235 {
03236 setSelectionFromRoot( mRenameItem, TRUE );
03237 mRenameItem = NULL;
03238 }
03239
03240
03241 scrollToShowSelection();
03242 }
03243
03244 void LLFolderView::revertRenamingItem( void )
03245 {
03246 mRenamer->setCommitOnFocusLost( FALSE );
03247 mRenamer->setFocus( FALSE );
03248 mRenamer->setVisible( FALSE );
03249 mRenamer->setCommitOnFocusLost( TRUE );
03250 gViewerWindow->setTopCtrl( NULL );
03251
03252 if( mRenameItem )
03253 {
03254 setSelectionFromRoot( mRenameItem, TRUE );
03255 mRenameItem = NULL;
03256 }
03257 }
03258
03259 void LLFolderView::removeSelectedItems( void )
03260 {
03261 if(getVisible() && mEnabled)
03262 {
03263
03264 mRenameItem = NULL;
03265
03266
03267
03268
03269 std::vector<LLFolderViewItem*> items;
03270 S32 count = mSelectedItems.size();
03271 if(count == 0) return;
03272 LLFolderViewItem* item = NULL;
03273 selected_items_t::iterator item_it;
03274 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03275 {
03276 item = *item_it;
03277 if(item->isRemovable())
03278 {
03279 items.push_back(item);
03280 }
03281 else
03282 {
03283 llinfos << "Cannot delete " << item->getName() << llendl;
03284 return;
03285 }
03286 }
03287
03288
03289 count = items.size();
03290 LLUUID new_selection_id;
03291 if(count == 1)
03292 {
03293 LLFolderViewItem* item_to_delete = items[0];
03294 LLFolderViewFolder* parent = item_to_delete->getParentFolder();
03295 LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE);
03296 if (!new_selection)
03297 {
03298 new_selection = item_to_delete->getPreviousOpenNode(FALSE);
03299 }
03300 if(parent)
03301 {
03302 if (parent->removeItem(item_to_delete))
03303 {
03304
03305 if (new_selection)
03306 {
03307 setSelectionFromRoot(new_selection, new_selection->isOpen(), gViewerWindow->childHasKeyboardFocus(this));
03308 }
03309 else
03310 {
03311 setSelectionFromRoot(NULL, gViewerWindow->childHasKeyboardFocus(this));
03312 }
03313 }
03314 }
03315 arrangeAll();
03316 }
03317 else if (count > 1)
03318 {
03319 LLDynamicArray<LLFolderViewEventListener*> listeners;
03320 LLFolderViewEventListener* listener;
03321 LLFolderViewItem* last_item = items[count - 1];
03322 LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE);
03323 while(new_selection && new_selection->isSelected())
03324 {
03325 new_selection = new_selection->getNextOpenNode(FALSE);
03326 }
03327 if (!new_selection)
03328 {
03329 new_selection = last_item->getPreviousOpenNode(FALSE);
03330 while (new_selection && new_selection->isSelected())
03331 {
03332 new_selection = new_selection->getPreviousOpenNode(FALSE);
03333 }
03334 }
03335 if (new_selection)
03336 {
03337 setSelectionFromRoot(new_selection, new_selection->isOpen(), gViewerWindow->childHasKeyboardFocus(this));
03338 }
03339 else
03340 {
03341 setSelectionFromRoot(NULL, gViewerWindow->childHasKeyboardFocus(this));
03342 }
03343
03344 for(S32 i = 0; i < count; ++i)
03345 {
03346 listener = items[i]->getListener();
03347 if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL))
03348 {
03349 listeners.put(listener);
03350 }
03351 }
03352 listener = listeners.get(0);
03353 if(listener)
03354 {
03355 listener->removeBatch(listeners);
03356 }
03357 }
03358 arrangeAll();
03359 scrollToShowSelection();
03360 }
03361 }
03362
03363
03364 void LLFolderView::openSelectedItems( void )
03365 {
03366 if(getVisible() && mEnabled)
03367 {
03368 if (mSelectedItems.size() == 1)
03369 {
03370 mSelectedItems.front()->open();
03371 }
03372 else
03373 {
03374 S32 left, top;
03375 gFloaterView->getNewFloaterPosition(&left, &top);
03376 LLMultiPreview* multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100));
03377 gFloaterView->getNewFloaterPosition(&left, &top);
03378 LLMultiProperties* multi_propertiesp = new LLMultiProperties(LLRect(left, top, left + 300, top - 100));
03379
03380 selected_items_t::iterator item_it;
03381 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03382 {
03383
03384
03385
03386 LLFolderViewEventListener* listener = (*item_it)->getListener();
03387 bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT);
03388 if (is_prop)
03389 LLFloater::setFloaterHost(multi_propertiesp);
03390 else
03391 LLFloater::setFloaterHost(multi_previewp);
03392 (*item_it)->open();
03393 }
03394
03395 LLFloater::setFloaterHost(NULL);
03396
03397
03398 multi_previewp->open();
03399 multi_propertiesp->open();
03400 }
03401 }
03402 }
03403
03404 void LLFolderView::propertiesSelectedItems( void )
03405 {
03406 if(getVisible() && mEnabled)
03407 {
03408 if (mSelectedItems.size() == 1)
03409 {
03410 LLFolderViewItem* folder_item = mSelectedItems.front();
03411 if(!folder_item) return;
03412 folder_item->getListener()->showProperties();
03413 }
03414 else
03415 {
03416 S32 left, top;
03417 gFloaterView->getNewFloaterPosition(&left, &top);
03418
03419 LLMultiProperties* multi_propertiesp = new LLMultiProperties(LLRect(left, top, left + 100, top - 100));
03420
03421 LLFloater::setFloaterHost(multi_propertiesp);
03422
03423 selected_items_t::iterator item_it;
03424 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03425 {
03426 (*item_it)->getListener()->showProperties();
03427 }
03428
03429 LLFloater::setFloaterHost(NULL);
03430 multi_propertiesp->open();
03431 }
03432 }
03433 }
03434
03435 void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
03436 {
03437 if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH)
03438 {
03439 return;
03440 }
03441
03442
03443 LLFolderViewFolder* close_item = mAutoOpenItems.check();
03444 while (close_item && close_item != item->getParentFolder())
03445 {
03446 mAutoOpenItems.pop();
03447 close_item->setOpenArrangeRecursively(FALSE);
03448 close_item = mAutoOpenItems.check();
03449 }
03450
03451 item->requestArrange();
03452
03453 mAutoOpenItems.push(item);
03454
03455 item->setOpen(TRUE);
03456 scrollToShowItem(item);
03457 }
03458
03459 void LLFolderView::closeAutoOpenedFolders()
03460 {
03461 while (mAutoOpenItems.check())
03462 {
03463 LLFolderViewFolder* close_item = mAutoOpenItems.pop();
03464 close_item->setOpen(FALSE);
03465 }
03466
03467 if (mAutoOpenCandidate)
03468 {
03469 mAutoOpenCandidate->setAutoOpenCountdown(0.f);
03470 }
03471 mAutoOpenCandidate = NULL;
03472 mAutoOpenTimer.stop();
03473 }
03474
03475 BOOL LLFolderView::autoOpenTest(LLFolderViewFolder* folder)
03476 {
03477 if (folder && mAutoOpenCandidate == folder)
03478 {
03479 if (mAutoOpenTimer.getStarted())
03480 {
03481 if (!mAutoOpenCandidate->isOpen())
03482 {
03483 mAutoOpenCandidate->setAutoOpenCountdown(clamp_rescale(mAutoOpenTimer.getElapsedTimeF32(), 0.f, sAutoOpenTime, 0.f, 1.f));
03484 }
03485 if (mAutoOpenTimer.getElapsedTimeF32() > sAutoOpenTime)
03486 {
03487 autoOpenItem(folder);
03488 mAutoOpenTimer.stop();
03489 return TRUE;
03490 }
03491 }
03492 return FALSE;
03493 }
03494
03495
03496 if (mAutoOpenCandidate)
03497 {
03498 mAutoOpenCandidate->setAutoOpenCountdown(0.f);
03499 }
03500 mAutoOpenCandidate = folder;
03501 mAutoOpenTimer.start();
03502 return FALSE;
03503 }
03504
03505 BOOL LLFolderView::canCopy()
03506 {
03507 if (!(getVisible() && mEnabled && (mSelectedItems.size() > 0)))
03508 {
03509 return FALSE;
03510 }
03511
03512 selected_items_t::iterator selected_it;
03513 for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)
03514 {
03515 LLFolderViewItem* item = *selected_it;
03516 if (!item->getListener()->isItemCopyable())
03517 {
03518 return FALSE;
03519 }
03520 }
03521 return TRUE;
03522 }
03523
03524
03525 void LLFolderView::copy()
03526 {
03527
03528 LLInventoryClipboard::instance().reset();
03529 S32 count = mSelectedItems.size();
03530 if(getVisible() && mEnabled && (count > 0))
03531 {
03532 LLFolderViewEventListener* listener = NULL;
03533 selected_items_t::iterator item_it;
03534 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03535 {
03536 listener = (*item_it)->getListener();
03537 if(listener)
03538 {
03539 listener->copyToClipboard();
03540 }
03541 }
03542 }
03543 mSearchString.clear();
03544 }
03545
03546 BOOL LLFolderView::canCut()
03547 {
03548 return FALSE;
03549 }
03550
03551 void LLFolderView::cut()
03552 {
03553
03554 }
03555
03556 BOOL LLFolderView::canPaste()
03557 {
03558 if (mSelectedItems.empty())
03559 {
03560 return FALSE;
03561 }
03562
03563 if(getVisible() && mEnabled)
03564 {
03565 selected_items_t::iterator item_it;
03566 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03567 {
03568
03569 LLFolderViewItem* item = (*item_it);
03570 LLFolderViewEventListener* listener = item->getListener();
03571 if(!listener || !listener->isClipboardPasteable())
03572 {
03573 LLFolderViewFolder* folderp = item->getParentFolder();
03574 listener = folderp->getListener();
03575 if (!listener || !listener->isClipboardPasteable())
03576 {
03577 return FALSE;
03578 }
03579 }
03580 }
03581 return TRUE;
03582 }
03583 return FALSE;
03584 }
03585
03586
03587 void LLFolderView::paste()
03588 {
03589 if(getVisible() && mEnabled)
03590 {
03591
03592 std::set<LLFolderViewItem*> folder_set;
03593
03594 selected_items_t::iterator selected_it;
03595 for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)
03596 {
03597 LLFolderViewItem* item = *selected_it;
03598 LLFolderViewEventListener* listener = item->getListener();
03599 if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)
03600 {
03601 item = item->getParentFolder();
03602 }
03603 folder_set.insert(item);
03604 }
03605
03606 std::set<LLFolderViewItem*>::iterator set_iter;
03607 for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter)
03608 {
03609 LLFolderViewEventListener* listener = (*set_iter)->getListener();
03610 if(listener && listener->isClipboardPasteable())
03611 {
03612 listener->pasteFromClipboard();
03613 }
03614 }
03615 }
03616 mSearchString.clear();
03617 }
03618
03619
03620 void LLFolderView::startRenamingSelectedItem( void )
03621 {
03622
03623 scrollToShowSelection();
03624
03625 S32 count = mSelectedItems.size();
03626 LLFolderViewItem* item = NULL;
03627 if(count > 0)
03628 {
03629 item = mSelectedItems.front();
03630 }
03631 if(getVisible() && mEnabled && (count == 1) && item && item->getListener() &&
03632 item->getListener()->isItemRenameable())
03633 {
03634 mRenameItem = item;
03635
03636 S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + item->getIndentation();
03637 S32 y = llfloor(item->getRect().getHeight()-sFont->getLineHeight()-2);
03638 item->localPointToScreen( x, y, &x, &y );
03639 screenPointToLocal( x, y, &x, &y );
03640 mRenamer->setOrigin( x, y );
03641
03642 S32 scroller_height = 0;
03643 S32 scroller_width = gViewerWindow->getWindowWidth();
03644 BOOL dummy_bool;
03645 if (mScrollContainer)
03646 {
03647 mScrollContainer->calcVisibleSize( &scroller_width, &scroller_height, &dummy_bool, &dummy_bool);
03648 }
03649
03650 S32 width = llmax(llmin(item->getRect().getWidth() - x, scroller_width - x - mRect.mLeft), MINIMUM_RENAMER_WIDTH);
03651 S32 height = llfloor(sFont->getLineHeight() + RENAME_HEIGHT_PAD);
03652 mRenamer->reshape( width, height, TRUE );
03653
03654 mRenamer->setText(item->getName());
03655 mRenamer->selectAll();
03656 mRenamer->setVisible( TRUE );
03657
03658 mRenamer->setFocus( TRUE );
03659 mRenamer->setFocusLostCallback(renamer_focus_lost);
03660 gViewerWindow->setTopCtrl( mRenamer );
03661 }
03662 }
03663
03664 void LLFolderView::setFocus(BOOL focus)
03665 {
03666 if (focus)
03667 {
03668 if(!hasFocus())
03669 {
03670 gEditMenuHandler = this;
03671 }
03672 }
03673
03674 LLFolderViewFolder::setFocus(focus);
03675 }
03676
03677 BOOL LLFolderView::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
03678 {
03679 BOOL handled = FALSE;
03680
03681
03682
03683 LLMenuGL* menu = (LLMenuGL*)LLView::getViewByHandle(mPopupMenuHandle);
03684 if (menu->isOpen())
03685 {
03686 LLMenuGL::sMenuContainer->hideMenus();
03687 }
03688
03689 LLView *item = NULL;
03690 if (getChildCount() > 0)
03691 {
03692 item = *(getChildList()->begin());
03693 }
03694
03695 if( getVisible() && mEnabled && !called_from_parent )
03696 {
03697 switch( key )
03698 {
03699 case KEY_F2:
03700 mSearchString.clear();
03701 startRenamingSelectedItem();
03702 handled = TRUE;
03703 break;
03704
03705 case KEY_RETURN:
03706 if (mask == MASK_NONE)
03707 {
03708 if( mRenameItem && mRenamer->getVisible() )
03709 {
03710 finishRenamingItem();
03711 mSearchString.clear();
03712 handled = TRUE;
03713 }
03714 else
03715 {
03716 LLFolderView::openSelectedItems();
03717 handled = TRUE;
03718 }
03719 }
03720 break;
03721
03722 case KEY_ESCAPE:
03723
03724 if( mRenameItem && mRenamer->getVisible() )
03725 {
03726 revertRenamingItem();
03727 handled = TRUE;
03728 }
03729 else
03730 {
03731 if( gViewerWindow->childHasKeyboardFocus( this ) )
03732 {
03733 gViewerWindow->setKeyboardFocus( NULL, NULL );
03734 }
03735 }
03736 mSearchString.clear();
03737 break;
03738
03739 case KEY_PAGE_UP:
03740 mSearchString.clear();
03741 mScrollContainer->pageUp(30);
03742 handled = TRUE;
03743 break;
03744
03745 case KEY_PAGE_DOWN:
03746 mSearchString.clear();
03747 mScrollContainer->pageDown(30);
03748 handled = TRUE;
03749 break;
03750
03751 case KEY_HOME:
03752 mSearchString.clear();
03753 mScrollContainer->goToTop();
03754 handled = TRUE;
03755 break;
03756
03757 case KEY_END:
03758 mSearchString.clear();
03759 mScrollContainer->goToBottom();
03760 break;
03761
03762 case KEY_DOWN:
03763 if((mSelectedItems.size() > 0) && mScrollContainer)
03764 {
03765 LLFolderViewItem* last_selected = getCurSelectedItem();
03766
03767 if (!mKeyboardSelection)
03768 {
03769 setSelection(last_selected, FALSE, TRUE);
03770 mKeyboardSelection = TRUE;
03771 }
03772
03773 LLFolderViewItem* next = NULL;
03774 if (mask & MASK_SHIFT)
03775 {
03776
03777 next = last_selected->getNextOpenNode(FALSE);
03778 if (next)
03779 {
03780 if (next->isSelected())
03781 {
03782
03783 changeSelectionFromRoot(last_selected, FALSE);
03784 }
03785 else if (last_selected->getParentFolder() == next->getParentFolder())
03786 {
03787
03788 changeSelectionFromRoot(next, TRUE);
03789 }
03790 }
03791 }
03792 else
03793 {
03794 next = last_selected->getNextOpenNode();
03795 if( next )
03796 {
03797 if (next == last_selected)
03798 {
03799 return FALSE;
03800 }
03801 setSelection( next, FALSE, TRUE );
03802 }
03803 }
03804 scrollToShowSelection();
03805 mSearchString.clear();
03806 handled = TRUE;
03807 }
03808 break;
03809
03810 case KEY_UP:
03811 if((mSelectedItems.size() > 0) && mScrollContainer)
03812 {
03813 LLFolderViewItem* last_selected = mSelectedItems.back();
03814
03815 if (!mKeyboardSelection)
03816 {
03817 setSelection(last_selected, FALSE, TRUE);
03818 mKeyboardSelection = TRUE;
03819 }
03820
03821 LLFolderViewItem* prev = NULL;
03822 if (mask & MASK_SHIFT)
03823 {
03824
03825 prev = last_selected->getPreviousOpenNode(FALSE);
03826 if (prev)
03827 {
03828 if (prev->isSelected())
03829 {
03830
03831 changeSelectionFromRoot(last_selected, FALSE);
03832 }
03833 else if (last_selected->getParentFolder() == prev->getParentFolder())
03834 {
03835
03836 changeSelectionFromRoot(prev, TRUE);
03837 }
03838 }
03839 }
03840 else
03841 {
03842 prev = last_selected->getPreviousOpenNode();
03843 if( prev )
03844 {
03845 if (prev == this)
03846 {
03847 return FALSE;
03848 }
03849 setSelection( prev, FALSE, TRUE );
03850 }
03851 }
03852 scrollToShowSelection();
03853 mSearchString.clear();
03854
03855 handled = TRUE;
03856 }
03857 break;
03858
03859 case KEY_RIGHT:
03860 if(mSelectedItems.size())
03861 {
03862 LLFolderViewItem* last_selected = getCurSelectedItem();
03863 last_selected->setOpen( TRUE );
03864 mSearchString.clear();
03865 handled = TRUE;
03866 }
03867 break;
03868
03869 case KEY_LEFT:
03870 if(mSelectedItems.size())
03871 {
03872 LLFolderViewItem* last_selected = getCurSelectedItem();
03873 LLFolderViewItem* parent_folder = last_selected->getParentFolder();
03874 if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder())
03875 {
03876 setSelection(parent_folder, FALSE, TRUE);
03877 }
03878 else
03879 {
03880 last_selected->setOpen( FALSE );
03881 }
03882 mSearchString.clear();
03883 scrollToShowSelection();
03884 handled = TRUE;
03885 }
03886 break;
03887 }
03888 }
03889
03890 if (!handled && gFocusMgr.childHasKeyboardFocus(getRoot()))
03891 {
03892 if (key == KEY_BACKSPACE)
03893 {
03894 mSearchTimer.reset();
03895 if (mSearchString.size())
03896 {
03897 mSearchString.erase(mSearchString.size() - 1, 1);
03898 }
03899 search(getCurSelectedItem(), mSearchString.c_str(), FALSE);
03900 handled = TRUE;
03901 }
03902 }
03903
03904 return handled;
03905 }
03906
03907
03908 BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
03909 {
03910 if ((uni_char < 0x20) || (uni_char == 0x7F))
03911 {
03912 return FALSE;
03913 }
03914
03915 if (uni_char > 0x7f)
03916 {
03917 llwarns << "LLFolderView::handleUnicodeCharHere - Don't handle non-ascii yet, aborting" << llendl;
03918 return FALSE;
03919 }
03920
03921 BOOL handled = FALSE;
03922 if (gFocusMgr.childHasKeyboardFocus(getRoot()))
03923 {
03924
03925 if (mSearchTimer.getElapsedTimeF32() > gSavedSettings.getF32("TypeAheadTimeout"))
03926 {
03927 mSearchString.clear();
03928 }
03929 mSearchTimer.reset();
03930 if (mSearchString.size() < 128)
03931 {
03932 mSearchString += uni_char;
03933 }
03934 search(getCurSelectedItem(), mSearchString.c_str(), FALSE);
03935
03936 handled = TRUE;
03937 }
03938
03939 return handled;
03940 }
03941
03942
03943 BOOL LLFolderView::canDoDelete()
03944 {
03945 if (mSelectedItems.size() == 0) return FALSE;
03946 selected_items_t::iterator item_it;
03947 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
03948 {
03949 if (!(*item_it)->getListener()->isItemRemovable())
03950 {
03951 return FALSE;
03952 }
03953 }
03954 return TRUE;
03955 }
03956
03957 void LLFolderView::doDelete()
03958 {
03959 if(mSelectedItems.size() > 0)
03960 {
03961 removeSelectedItems();
03962 }
03963 }
03964
03965
03966 BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask )
03967 {
03968 mKeyboardSelection = FALSE;
03969 mSearchString.clear();
03970
03971 setFocus(TRUE);
03972
03973 return LLView::handleMouseDown( x, y, mask );
03974 }
03975
03976 void LLFolderView::onFocusLost( )
03977 {
03978 if( gEditMenuHandler == this )
03979 {
03980 gEditMenuHandler = NULL;
03981 }
03982 LLUICtrl::onFocusLost();
03983 }
03984
03985 BOOL LLFolderView::search(LLFolderViewItem* first_item, const LLString &search_string, BOOL backward)
03986 {
03987
03988 LLFolderViewItem* search_item = first_item;
03989
03990
03991 LLString upper_case_string = search_string;
03992 LLString::toUpper(upper_case_string);
03993
03994
03995 if (!search_item)
03996 {
03997
03998 search_item = getNextFromChild(NULL);
03999 }
04000
04001
04002 BOOL found = FALSE;
04003 LLFolderViewItem* original_search_item = search_item;
04004 do
04005 {
04006
04007 if (!search_item)
04008 {
04009 if (backward)
04010 {
04011 search_item = getPreviousFromChild(NULL);
04012 }
04013 else
04014 {
04015 search_item = getNextFromChild(NULL);
04016 }
04017 if (!search_item || search_item == original_search_item)
04018 {
04019 break;
04020 }
04021 }
04022
04023 const LLString current_item_label(search_item->getSearchableLabel());
04024 S32 search_string_length = llmin(upper_case_string.size(), current_item_label.size());
04025 if (!current_item_label.compare(0, search_string_length, upper_case_string))
04026 {
04027 found = TRUE;
04028 break;
04029 }
04030 if (backward)
04031 {
04032 search_item = search_item->getPreviousOpenNode();
04033 }
04034 else
04035 {
04036 search_item = search_item->getNextOpenNode();
04037 }
04038
04039 } while(search_item != original_search_item);
04040
04041
04042 if (found)
04043 {
04044 setSelection(search_item, FALSE, TRUE);
04045 scrollToShowSelection();
04046 }
04047
04048 return found;
04049 }
04050
04051 BOOL LLFolderView::handleDoubleClick( S32 x, S32 y, MASK mask )
04052 {
04053 if (!getVisible())
04054 {
04055 return FALSE;
04056 }
04057
04058 return LLView::handleDoubleClick( x, y, mask );
04059 }
04060
04061 BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
04062 {
04063
04064
04065 setFocus(TRUE);
04066
04067 BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
04068 S32 count = mSelectedItems.size();
04069 LLMenuGL* menu = (LLMenuGL*)LLView::getViewByHandle(mPopupMenuHandle);
04070 if(handled && (count > 0) && menu)
04071 {
04072
04073 const LLView::child_list_t *list = menu->getChildList();
04074
04075 LLView::child_list_t::const_iterator menu_itor;
04076 for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
04077 {
04078 (*menu_itor)->setVisible(TRUE);
04079 (*menu_itor)->setEnabled(TRUE);
04080 }
04081
04082
04083 selected_items_t::iterator item_itor;
04084 U32 flags = FIRST_SELECTED_ITEM;
04085 for (item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor)
04086 {
04087 (*item_itor)->buildContextMenu(*menu, flags);
04088 flags = 0x0;
04089 }
04090
04091 menu->arrange();
04092 menu->updateParent(LLMenuGL::sMenuContainer);
04093 LLMenuGL::showPopup(this, menu, x, y);
04094 }
04095 else
04096 {
04097 if(menu && menu->getVisible())
04098 {
04099 menu->setVisible(FALSE);
04100 }
04101 setSelection(NULL, FALSE, TRUE);
04102 }
04103 return handled;
04104 }
04105
04106 BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask )
04107 {
04108 return LLView::handleHover( x, y, mask );
04109 }
04110
04111 BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
04112 EDragAndDropType cargo_type,
04113 void* cargo_data,
04114 EAcceptance* accept,
04115 LLString& tooltip_msg)
04116 {
04117 mDragAndDropThisFrame = TRUE;
04118 BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data,
04119 accept, tooltip_msg);
04120
04121 if (handled)
04122 {
04123 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl;
04124 }
04125
04126 return handled;
04127 }
04128
04129 BOOL LLFolderView::handleScrollWheel(S32 x, S32 y, S32 clicks)
04130 {
04131 if (mScrollContainer)
04132 {
04133 return mScrollContainer->handleScrollWheel(x, y, clicks);
04134 }
04135 return FALSE;
04136 }
04137
04138 void LLFolderView::deleteAllChildren()
04139 {
04140 if(gViewerWindow->hasTopCtrl(mRenamer))
04141 {
04142 gViewerWindow->setTopCtrl(NULL);
04143 }
04144 LLView::deleteViewByHandle(mPopupMenuHandle);
04145 mPopupMenuHandle = LLViewHandle::sDeadHandle;
04146 mRenamer = NULL;
04147 mRenameItem = NULL;
04148 clearSelection();
04149 LLView::deleteAllChildren();
04150 }
04151
04152 void LLFolderView::scrollToShowSelection()
04153 {
04154 if (mSelectedItems.size())
04155 {
04156 mNeedsScroll = TRUE;
04157 }
04158 }
04159
04160
04161
04162 void LLFolderView::scrollToShowItem(LLFolderViewItem* item)
04163 {
04164
04165 if (gFocusMgr.childHasMouseCapture(mScrollContainer))
04166 {
04167 mNeedsScroll = FALSE;
04168 return;
04169 }
04170 if(item && mScrollContainer)
04171 {
04172 LLRect local_rect = item->getRect();
04173 LLRect item_scrolled_rect;
04174
04175 S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();
04176 S32 label_height = llround(sFont->getLineHeight());
04177
04178 S32 max_height_to_show = gFocusMgr.childHasKeyboardFocus(this) ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight();
04179 item->localPointToOtherView(item->getIndentation(), llmax(0, local_rect.getHeight() - max_height_to_show), &item_scrolled_rect.mLeft, &item_scrolled_rect.mBottom, mScrollContainer);
04180 item->localPointToOtherView(local_rect.getWidth(), local_rect.getHeight(), &item_scrolled_rect.mRight, &item_scrolled_rect.mTop, mScrollContainer);
04181
04182 item_scrolled_rect.mRight = llmin(item_scrolled_rect.mLeft + MIN_ITEM_WIDTH_VISIBLE, item_scrolled_rect.mRight);
04183 LLCoordGL scroll_offset(-mScrollContainer->getBorderWidth() - item_scrolled_rect.mLeft,
04184 mScrollContainer->getRect().getHeight() - item_scrolled_rect.mTop - 1);
04185
04186 S32 max_scroll_offset = getVisibleRect().getHeight() - item_scrolled_rect.getHeight();
04187 if (item != mLastScrollItem ||
04188
04189 (scroll_offset.mY > 0 && scroll_offset.mY < max_scroll_offset &&
04190 (mLastScrollOffset.mY < 0 || mLastScrollOffset.mY > max_scroll_offset)))
04191 {
04192
04193
04194 mLastScrollOffset = scroll_offset;
04195 mLastScrollItem = item;
04196 }
04197
04198 mScrollContainer->scrollToShowRect( item_scrolled_rect, mLastScrollOffset );
04199
04200
04201
04202 LLCoordGL new_item_left_top;
04203 item->localPointToOtherView(item->getIndentation(), item->getRect().getHeight(), &new_item_left_top.mX, &new_item_left_top.mY, mScrollContainer);
04204 mLastScrollOffset.set(-mScrollContainer->getBorderWidth() - new_item_left_top.mX, mScrollContainer->getRect().getHeight() - new_item_left_top.mY - 1);
04205 }
04206 }
04207
04208 LLRect LLFolderView::getVisibleRect()
04209 {
04210 S32 visible_height = mScrollContainer->getRect().getHeight();
04211 S32 visible_width = mScrollContainer->getRect().getWidth();
04212 LLRect visible_rect;
04213 visible_rect.setLeftTopAndSize(-mRect.mLeft, visible_height - mRect.mBottom, visible_width, visible_height);
04214 return visible_rect;
04215 }
04216
04217 BOOL LLFolderView::getShowSelectionContext()
04218 {
04219 if (mShowSelectionContext)
04220 {
04221 return TRUE;
04222 }
04223 LLMenuGL* menu = (LLMenuGL*)LLView::getViewByHandle(mPopupMenuHandle);
04224 if (menu && menu->getVisible())
04225 {
04226 return TRUE;
04227 }
04228 return FALSE;
04229 }
04230
04231 void LLFolderView::setShowSingleSelection(BOOL show)
04232 {
04233 if (show != mShowSingleSelection)
04234 {
04235 mMultiSelectionFadeTimer.reset();
04236 mShowSingleSelection = show;
04237 }
04238 }
04239
04240 void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp)
04241 {
04242 mItemMap[id] = itemp;
04243 }
04244
04245 void LLFolderView::removeItemID(const LLUUID& id)
04246 {
04247 mItemMap.erase(id);
04248 }
04249
04250 LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
04251 {
04252 if (id.isNull())
04253 {
04254 return this;
04255 }
04256
04257 std::map<LLUUID, LLFolderViewItem*>::iterator map_it;
04258 map_it = mItemMap.find(id);
04259 if (map_it != mItemMap.end())
04260 {
04261 return map_it->second;
04262 }
04263
04264 return NULL;
04265 }
04266
04267
04268
04269 void LLFolderView::doIdle()
04270 {
04271 LLFastTimer t2(LLFastTimer::FTM_INVENTORY);
04272
04273 BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters");
04274 if (debug_filters != getDebugFilters())
04275 {
04276 mDebugFilters = debug_filters;
04277 arrangeAll();
04278 }
04279
04280 mFilter.clearModified();
04281 BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter.getCurrentGeneration() &&
04282 mFilter.isNotDefault();
04283 mNeedsAutoSelect = filter_modified_and_active &&
04284 !(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture());
04285
04286
04287 filterFromRoot();
04288
04289
04290
04291
04292
04293
04294 if (mNeedsAutoSelect)
04295 {
04296 LLFastTimer t3(LLFastTimer::FTM_AUTO_SELECT);
04297
04298 LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
04299 if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride)
04300 {
04301
04302 LLSelectFirstFilteredItem filter;
04303 applyFunctorRecursively(filter);
04304 }
04305 scrollToShowSelection();
04306 }
04307
04308 BOOL is_visible = isInVisibleChain();
04309
04310 if ( is_visible )
04311 {
04312 sanitizeSelection();
04313 if( needsArrange() )
04314 {
04315 arrangeFromRoot();
04316 }
04317 }
04318
04319 if (mSelectedItems.size() && mNeedsScroll)
04320 {
04321 scrollToShowItem(mSelectedItems.back());
04322
04323 if (getCompletedFilterGeneration() >= mFilter.getMinRequiredGeneration() &&
04324 (!needsArrange() || !is_visible))
04325 {
04326 mNeedsScroll = FALSE;
04327 }
04328 }
04329
04330 if (mSelectionChanged && mSelectCallback)
04331 {
04332
04333 mSelectCallback(mSelectedItems, gFocusMgr.childHasKeyboardFocus(this), mUserData);
04334 }
04335 mSelectionChanged = FALSE;
04336 }
04337
04338
04339
04340 void LLFolderView::idle(void* user_data)
04341 {
04342 LLFolderView* self = (LLFolderView*)user_data;
04343 if ( self )
04344 {
04345 self->doIdle();
04346 }
04347 }
04348
04349
04350 void LLFolderView::dumpSelectionInformation()
04351 {
04352 llinfos << "LLFolderView::dumpSelectionInformation()" << llendl;
04353 llinfos << "****************************************" << llendl;
04354 selected_items_t::iterator item_it;
04355 for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
04356 {
04357 llinfos << " " << (*item_it)->getName() << llendl;
04358 }
04359 llinfos << "****************************************" << llendl;
04360 }
04361
04365 bool LLInventorySort::updateSort(U32 order)
04366 {
04367 if (order != mSortOrder)
04368 {
04369 mSortOrder = order;
04370 mByDate = (order & LLInventoryFilter::SO_DATE);
04371 mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP);
04372 mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME);
04373 return true;
04374 }
04375 return false;
04376 }
04377
04378 bool LLInventorySort::operator()(LLFolderViewItem* a, LLFolderViewItem* b)
04379 {
04380 return mComparisonFunction(this, a, b);
04381 }
04382
04383 bool LLInventorySort::compare(LLInventorySort *self, LLFolderViewItem* a, LLFolderViewItem* b)
04384 {
04385
04386
04387 bool by_name = (!self->isByDate()
04388 || (self->isFoldersByName()
04389 && (a->getSortGroup() != SG_ITEM)));
04390
04391 if (a->getSortGroup() != b->getSortGroup())
04392 {
04393 if (self->isSystemToTop())
04394 {
04395
04396 return (a->getSortGroup() < b->getSortGroup());
04397 }
04398 else if (self->isByDate())
04399 {
04400
04401 if ( (a->getSortGroup() == SG_TRASH_FOLDER)
04402 || (b->getSortGroup() == SG_TRASH_FOLDER))
04403 {
04404 return (b->getSortGroup() == SG_TRASH_FOLDER);
04405 }
04406 }
04407 }
04408
04409 if (by_name)
04410 {
04411 S32 compare = LLString::compareDict(a->getLabel(), b->getLabel());
04412 if (0 == compare)
04413 {
04414 return (a->getCreationDate() > b->getCreationDate());
04415 }
04416 else
04417 {
04418 return (compare < 0);
04419 }
04420 }
04421 else
04422 {
04423
04424
04425 U32 first_create = a->getCreationDate();
04426 U32 second_create = b->getCreationDate();
04427 if (first_create == second_create)
04428 {
04429 return (LLString::compareDict(a->getLabel(), b->getLabel()) < 0);
04430 }
04431 else
04432 {
04433 return (first_create > second_create);
04434 }
04435 }
04436 }
04437
04438 void renamer_focus_lost( LLUICtrl* ctrl, void* userdata)
04439 {
04440 if( ctrl )
04441 {
04442 ctrl->setVisible( FALSE );
04443 }
04444 }
04445
04446 void delete_selected_item(void* user_data)
04447 {
04448 if(user_data)
04449 {
04450 LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
04451 fv->removeSelectedItems();
04452 }
04453 }
04454
04455 void copy_selected_item(void* user_data)
04456 {
04457 if(user_data)
04458 {
04459 LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
04460 fv->copy();
04461 }
04462 }
04463
04464 void paste_items(void* user_data)
04465 {
04466 if(user_data)
04467 {
04468 LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
04469 fv->paste();
04470 }
04471 }
04472
04473 void open_selected_items(void* user_data)
04474 {
04475 if(user_data)
04476 {
04477 LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
04478 fv->openSelectedItems();
04479 }
04480 }
04481
04482 void properties_selected_items(void* user_data)
04483 {
04484 if(user_data)
04485 {
04486 LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
04487 fv->propertiesSelectedItems();
04488 }
04489 }
04490
04494
04495 void LLFolderViewEventListener::arrangeAndSet(LLFolderViewItem* focus,
04496 BOOL set_selection,
04497 BOOL take_keyboard_focus)
04498 {
04499 if(!focus) return;
04500 LLFolderView* root = focus->getRoot();
04501 focus->getParentFolder()->requestArrange();
04502 if(set_selection)
04503 {
04504 focus->setSelectionFromRoot(focus, TRUE, take_keyboard_focus);
04505 if(root)
04506 {
04507 root->scrollToShowSelection();
04508 }
04509 }
04510 }
04511
04512
04516 LLInventoryFilter::LLInventoryFilter(const LLString& name) :
04517 mName(name),
04518 mModified(FALSE),
04519 mNeedTextRebuild(TRUE)
04520 {
04521 mFilterOps.mFilterTypes = 0xffffffff;
04522 mFilterOps.mMinDate = 0;
04523 mFilterOps.mMaxDate = U32_MAX;
04524 mFilterOps.mHoursAgo = 0;
04525 mFilterOps.mShowFolderState = SHOW_NON_EMPTY_FOLDERS;
04526 mFilterOps.mPermissions = PERM_NONE;
04527
04528 mOrder = SO_FOLDERS_BY_NAME;
04529
04530 mSubStringMatchOffset = 0;
04531 mFilterSubString = "";
04532 mFilterGeneration = 0;
04533 mMustPassGeneration = S32_MAX;
04534 mMinRequiredGeneration = 0;
04535 mFilterCount = 0;
04536 mNextFilterGeneration = mFilterGeneration + 1;
04537
04538 mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
04539 mFilterBehavior = FILTER_NONE;
04540 }
04541
04542 LLInventoryFilter::~LLInventoryFilter()
04543 {
04544 }
04545
04546 BOOL LLInventoryFilter::check(LLFolderViewItem* item)
04547 {
04548 U32 earliest;
04549
04550 earliest = time_corrected() - mFilterOps.mHoursAgo * 3600;
04551 if (mFilterOps.mMinDate && mFilterOps.mMinDate < earliest)
04552 {
04553 earliest = mFilterOps.mMinDate;
04554 }
04555 else if (!mFilterOps.mHoursAgo)
04556 {
04557 earliest = 0;
04558 }
04559 LLFolderViewEventListener* listener = item->getListener();
04560 mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : LLString::npos;
04561 BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE)
04562 && (mFilterSubString.size() == 0 || mSubStringMatchOffset != LLString::npos)
04563 && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions)
04564 && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate);
04565 return passed;
04566 }
04567
04568 const LLString LLInventoryFilter::getFilterSubString(BOOL trim)
04569 {
04570 return mFilterSubString;
04571 }
04572
04573 std::string::size_type LLInventoryFilter::getStringMatchOffset() const
04574 {
04575 return mSubStringMatchOffset;
04576 }
04577
04578
04579 BOOL LLInventoryFilter::isNotDefault()
04580 {
04581 return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes
04582 || mFilterSubString.size()
04583 || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions
04584 || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate
04585 || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate
04586 || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo;
04587 }
04588
04589 BOOL LLInventoryFilter::isActive()
04590 {
04591 return mFilterOps.mFilterTypes != 0xffffffff
04592 || mFilterSubString.size()
04593 || mFilterOps.mPermissions != PERM_NONE
04594 || mFilterOps.mMinDate != 0
04595 || mFilterOps.mMaxDate != U32_MAX
04596 || mFilterOps.mHoursAgo != 0;
04597 }
04598
04599 BOOL LLInventoryFilter::isModified()
04600 {
04601 return mModified;
04602 }
04603
04604 BOOL LLInventoryFilter::isModifiedAndClear()
04605 {
04606 BOOL ret = mModified;
04607 mModified = FALSE;
04608 return ret;
04609 }
04610
04611 void LLInventoryFilter::setFilterTypes(U32 types)
04612 {
04613 if (mFilterOps.mFilterTypes != types)
04614 {
04615
04616 BOOL fewer_bits_set = (mFilterOps.mFilterTypes & ~types);
04617 BOOL more_bits_set = (~mFilterOps.mFilterTypes & types);
04618
04619 mFilterOps.mFilterTypes = types;
04620 if (more_bits_set && fewer_bits_set)
04621 {
04622
04623
04624 setModified(FILTER_RESTART);
04625 }
04626 else if (more_bits_set)
04627 {
04628
04629 setModified(FILTER_LESS_RESTRICTIVE);
04630 }
04631 else if (fewer_bits_set)
04632 {
04633 setModified(FILTER_MORE_RESTRICTIVE);
04634 }
04635
04636 }
04637 }
04638
04639 void LLInventoryFilter::setFilterSubString(const LLString& string)
04640 {
04641 if (mFilterSubString != string)
04642 {
04643
04644 BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string);
04645
04646 BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString);
04647 mFilterSubString = string;
04648 LLString::toUpper(mFilterSubString);
04649 LLString::trimHead(mFilterSubString);
04650
04651 if (less_restrictive)
04652 {
04653 setModified(FILTER_LESS_RESTRICTIVE);
04654 }
04655 else if (more_restrictive)
04656 {
04657 setModified(FILTER_MORE_RESTRICTIVE);
04658 }
04659 else
04660 {
04661 setModified(FILTER_RESTART);
04662 }
04663 }
04664 }
04665
04666 void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
04667 {
04668 if (mFilterOps.mPermissions != perms)
04669 {
04670
04671 BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms);
04672 BOOL more_bits_set = (~mFilterOps.mPermissions & perms);
04673 mFilterOps.mPermissions = perms;
04674
04675 if (more_bits_set && fewer_bits_set)
04676 {
04677 setModified(FILTER_RESTART);
04678 }
04679 else if (more_bits_set)
04680 {
04681
04682 setModified(FILTER_MORE_RESTRICTIVE);
04683 }
04684 else if (fewer_bits_set)
04685 {
04686 setModified(FILTER_LESS_RESTRICTIVE);
04687 }
04688 }
04689 }
04690
04691 void LLInventoryFilter::setDateRange(U32 min_date, U32 max_date)
04692 {
04693 mFilterOps.mHoursAgo = 0;
04694 if (mFilterOps.mMinDate != min_date)
04695 {
04696 mFilterOps.mMinDate = min_date;
04697 setModified();
04698 }
04699 if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date))
04700 {
04701 mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
04702 setModified();
04703 }
04704 }
04705
04706 void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
04707 {
04708 if (sl && !isSinceLogoff())
04709 {
04710 setDateRange(mLastLogoff, U32_MAX);
04711 setModified();
04712 }
04713 if (!sl && isSinceLogoff())
04714 {
04715 setDateRange(0, U32_MAX);
04716 setModified();
04717 }
04718 }
04719
04720 BOOL LLInventoryFilter::isSinceLogoff()
04721 {
04722 return (mFilterOps.mMinDate == mLastLogoff) && (mFilterOps.mMaxDate == U32_MAX);
04723 }
04724
04725 void LLInventoryFilter::setHoursAgo(U32 hours)
04726 {
04727 if (mFilterOps.mHoursAgo != hours)
04728 {
04729
04730 BOOL less_restrictive = (mFilterOps.mMinDate == 0 && mFilterOps.mMaxDate == U32_MAX && hours > mFilterOps.mHoursAgo);
04731 BOOL more_restrictive = (mFilterOps.mMinDate == 0 && mFilterOps.mMaxDate == U32_MAX && hours <= mFilterOps.mHoursAgo);
04732 mFilterOps.mHoursAgo = hours;
04733 mFilterOps.mMinDate = 0;
04734 mFilterOps.mMaxDate = U32_MAX;
04735 if (less_restrictive)
04736 {
04737 setModified(FILTER_LESS_RESTRICTIVE);
04738 }
04739 else if (more_restrictive)
04740 {
04741 setModified(FILTER_MORE_RESTRICTIVE);
04742 }
04743 else
04744 {
04745 setModified(FILTER_RESTART);
04746 }
04747 }
04748 }
04749 void LLInventoryFilter::setShowFolderState(EFolderShow state)
04750 {
04751 if (mFilterOps.mShowFolderState != state)
04752 {
04753 mFilterOps.mShowFolderState = state;
04754 if (state == SHOW_NON_EMPTY_FOLDERS)
04755 {
04756
04757 setModified(FILTER_MORE_RESTRICTIVE);
04758 }
04759 else if (state == SHOW_ALL_FOLDERS)
04760 {
04761
04762 setModified(FILTER_LESS_RESTRICTIVE);
04763 }
04764 else
04765 {
04766 setModified();
04767 }
04768 }
04769 }
04770
04771 void LLInventoryFilter::setSortOrder(U32 order)
04772 {
04773 if (mOrder != order)
04774 {
04775 mOrder = order;
04776 setModified();
04777 }
04778 }
04779
04780 void LLInventoryFilter::markDefault()
04781 {
04782 mDefaultFilterOps = mFilterOps;
04783 }
04784
04785 void LLInventoryFilter::resetDefault()
04786 {
04787 mFilterOps = mDefaultFilterOps;
04788 setModified();
04789 }
04790
04791 void LLInventoryFilter::setModified(EFilterBehavior behavior)
04792 {
04793 mModified = TRUE;
04794 mNeedTextRebuild = TRUE;
04795 mFilterGeneration = mNextFilterGeneration++;
04796
04797 if (mFilterBehavior == FILTER_NONE)
04798 {
04799 mFilterBehavior = behavior;
04800 }
04801 else if (mFilterBehavior != behavior)
04802 {
04803
04804
04805 mFilterBehavior = FILTER_RESTART;
04806 }
04807
04808 if (isNotDefault())
04809 {
04810
04811 switch(mFilterBehavior)
04812 {
04813 case FILTER_RESTART:
04814 mMustPassGeneration = mFilterGeneration;
04815 mMinRequiredGeneration = mFilterGeneration;
04816 break;
04817 case FILTER_LESS_RESTRICTIVE:
04818 mMustPassGeneration = mFilterGeneration;
04819 break;
04820 case FILTER_MORE_RESTRICTIVE:
04821 mMinRequiredGeneration = mFilterGeneration;
04822
04823
04824 mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration);
04825 break;
04826 default:
04827 llerrs << "Bad filter behavior specified" << llendl;
04828 }
04829 }
04830 else
04831 {
04832
04833 mMinRequiredGeneration = 0;
04834 mMustPassGeneration = S32_MAX;
04835 }
04836 }
04837
04838 BOOL LLInventoryFilter::isFilterWith(LLInventoryType::EType t)
04839 {
04840 return mFilterOps.mFilterTypes & (0x01 << t);
04841 }
04842
04843 LLString LLInventoryFilter::getFilterText()
04844 {
04845 if (!mNeedTextRebuild)
04846 {
04847 return mFilterText;
04848 }
04849
04850 mNeedTextRebuild = FALSE;
04851 LLString filtered_types;
04852 LLString not_filtered_types;
04853 BOOL filtered_by_type = FALSE;
04854 BOOL filtered_by_all_types = TRUE;
04855 S32 num_filter_types = 0;
04856 mFilterText = "";
04857
04858 if (isFilterWith(LLInventoryType::IT_ANIMATION))
04859 {
04860 filtered_types += " Animations,";
04861 filtered_by_type = TRUE;
04862 num_filter_types++;
04863 }
04864 else
04865 {
04866 not_filtered_types += " Animations,";
04867 filtered_by_all_types = FALSE;
04868 }
04869
04870 if (isFilterWith(LLInventoryType::IT_CALLINGCARD))
04871 {
04872 filtered_types += " Calling Cards,";
04873 filtered_by_type = TRUE;
04874 num_filter_types++;
04875 }
04876 else
04877 {
04878 not_filtered_types += " Calling Cards,";
04879 filtered_by_all_types = FALSE;
04880 }
04881
04882 if (isFilterWith(LLInventoryType::IT_WEARABLE))
04883 {
04884 filtered_types += " Clothing,";
04885 filtered_by_type = TRUE;
04886 num_filter_types++;
04887 }
04888 else
04889 {
04890 not_filtered_types += " Clothing,";
04891 filtered_by_all_types = FALSE;
04892 }
04893
04894 if (isFilterWith(LLInventoryType::IT_GESTURE))
04895 {
04896 filtered_types += " Gestures,";
04897 filtered_by_type = TRUE;
04898 num_filter_types++;
04899 }
04900 else
04901 {
04902 not_filtered_types += " Gestures,";
04903 filtered_by_all_types = FALSE;
04904 }
04905
04906 if (isFilterWith(LLInventoryType::IT_LANDMARK))
04907 {
04908 filtered_types += " Landmarks,";
04909 filtered_by_type = TRUE;
04910 num_filter_types++;
04911 }
04912 else
04913 {
04914 not_filtered_types += " Landmarks,";
04915 filtered_by_all_types = FALSE;
04916 }
04917
04918 if (isFilterWith(LLInventoryType::IT_NOTECARD))
04919 {
04920 filtered_types += " Notecards,";
04921 filtered_by_type = TRUE;
04922 num_filter_types++;
04923 }
04924 else
04925 {
04926 not_filtered_types += " Notecards,";
04927 filtered_by_all_types = FALSE;
04928 }
04929
04930 if (isFilterWith(LLInventoryType::IT_OBJECT) && isFilterWith(LLInventoryType::IT_ATTACHMENT))
04931 {
04932 filtered_types += " Objects,";
04933 filtered_by_type = TRUE;
04934 num_filter_types++;
04935 }
04936 else
04937 {
04938 not_filtered_types += " Objects,";
04939 filtered_by_all_types = FALSE;
04940 }
04941
04942 if (isFilterWith(LLInventoryType::IT_LSL))
04943 {
04944 filtered_types += " Scripts,";
04945 filtered_by_type = TRUE;
04946 num_filter_types++;
04947 }
04948 else
04949 {
04950 not_filtered_types += " Scripts,";
04951 filtered_by_all_types = FALSE;
04952 }
04953
04954 if (isFilterWith(LLInventoryType::IT_SOUND))
04955 {
04956 filtered_types += " Sounds,";
04957 filtered_by_type = TRUE;
04958 num_filter_types++;
04959 }
04960 else
04961 {
04962 not_filtered_types += " Sounds,";
04963 filtered_by_all_types = FALSE;
04964 }
04965
04966 if (isFilterWith(LLInventoryType::IT_TEXTURE))
04967 {
04968 filtered_types += " Textures,";
04969 filtered_by_type = TRUE;
04970 num_filter_types++;
04971 }
04972 else
04973 {
04974 not_filtered_types += " Textures,";
04975 filtered_by_all_types = FALSE;
04976 }
04977
04978 if (isFilterWith(LLInventoryType::IT_SNAPSHOT))
04979 {
04980 filtered_types += " Snapshots,";
04981 filtered_by_type = TRUE;
04982 num_filter_types++;
04983 }
04984 else
04985 {
04986 not_filtered_types += " Snapshots,";
04987 filtered_by_all_types = FALSE;
04988 }
04989
04990 if (!gInventory.backgroundFetchActive() && filtered_by_type && !filtered_by_all_types)
04991 {
04992 mFilterText += " - ";
04993 if (num_filter_types < 5)
04994 {
04995 mFilterText += filtered_types;
04996 }
04997 else
04998 {
04999 mFilterText += "No ";
05000 mFilterText += not_filtered_types;
05001 }
05002
05003 mFilterText.erase(mFilterText.size() - 1, 1);
05004 }
05005
05006 if (isSinceLogoff())
05007 {
05008 mFilterText += " - Since Logoff";
05009 }
05010 return mFilterText;
05011 }
05012
05013 void LLInventoryFilter::toLLSD(LLSD& data)
05014 {
05015 data["filter_types"] = (LLSD::Integer)getFilterTypes();
05016 data["min_date"] = (LLSD::Integer)getMinDate();
05017 data["max_date"] = (LLSD::Integer)getMaxDate();
05018 data["hours_ago"] = (LLSD::Integer)getHoursAgo();
05019 data["show_folder_state"] = (LLSD::Integer)getShowFolderState();
05020 data["permissions"] = (LLSD::Integer)getFilterPermissions();
05021 data["substring"] = (LLSD::String)getFilterSubString();
05022 data["sort_order"] = (LLSD::Integer)getSortOrder();
05023 data["since_logoff"] = (LLSD::Boolean)isSinceLogoff();
05024 }
05025
05026 void LLInventoryFilter::fromLLSD(LLSD& data)
05027 {
05028 if(data.has("filter_types"))
05029 {
05030 setFilterTypes((U32)data["filter_types"].asInteger());
05031 }
05032
05033 if(data.has("min_date") && data.has("max_date"))
05034 {
05035 setDateRange((U32)data["min_date"].asInteger(), (U32)data["max_date"].asInteger());
05036 }
05037
05038 if(data.has("hours_ago"))
05039 {
05040 setHoursAgo((U32)data["hours_ago"].asInteger());
05041 }
05042
05043 if(data.has("show_folder_state"))
05044 {
05045 setShowFolderState((EFolderShow)data["show_folder_state"].asInteger());
05046 }
05047
05048 if(data.has("permissions"))
05049 {
05050 setFilterPermissions((PermissionMask)data["permissions"].asInteger());
05051 }
05052
05053 if(data.has("substring"))
05054 {
05055 setFilterSubString(LLString(data["substring"].asString()));
05056 }
05057
05058 if(data.has("sort_order"))
05059 {
05060 setSortOrder((U32)data["sort_order"].asInteger());
05061 }
05062
05063 if(data.has("since_logoff"))
05064 {
05065 setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean());
05066 }
05067 }