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