diff options
Diffstat (limited to 'indra/newview/llfolderview.cpp')
-rw-r--r-- | indra/newview/llfolderview.cpp | 289 |
1 files changed, 239 insertions, 50 deletions
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index de18e74752..7d527fa98a 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -38,11 +38,14 @@ #include "llinventorybridge.h" #include "llinventoryclipboard.h" // *TODO: remove this once hack below gone. #include "llinventoryfilter.h" +#include "llinventoryfunctions.h" +#include "llinventorypanel.h" #include "llfoldertype.h" #include "llfloaterinventory.h"// hacked in for the bonus context menu items. #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" +#include "llpanel.h" #include "llpreview.h" #include "llscrollcontainer.h" // hack to allow scrolling #include "lltooldraganddrop.h" @@ -54,6 +57,7 @@ #include "llviewermenu.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" +#include "llviewerfoldertype.h" #include "llviewerwindow.h" #include "llvoavatar.h" #include "llfloaterproperties.h" @@ -74,7 +78,7 @@ ///---------------------------------------------------------------------------- const S32 RENAME_WIDTH_PAD = 4; -const S32 RENAME_HEIGHT_PAD = 2; +const S32 RENAME_HEIGHT_PAD = 1; const S32 AUTO_OPEN_STACK_DEPTH = 16; const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + LLFolderViewItem::ICON_PAD @@ -191,7 +195,8 @@ LLFolderView::LLFolderView(const Params& p) mCallbackRegistrar(NULL), mParentPanel(p.parent_panel), mUseEllipses(false), - mDraggingOverItem(NULL) + mDraggingOverItem(NULL), + mStatusTextBox(NULL) { LLRect rect = p.rect; LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); @@ -202,7 +207,10 @@ LLFolderView::LLFolderView(const Params& p) mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); mKeyboardSelection = FALSE; - mIndentation = -LEFT_INDENTATION; // children start at indentation 0 + const LLFolderViewItem::Params& item_params = + LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); + S32 indentation = item_params.folder_indentation(); + mIndentation = -indentation; // children start at indentation 0 gIdleCallbacks.addFunction(idle, this); //clear label @@ -214,16 +222,34 @@ LLFolderView::LLFolderView(const Params& p) // Escape is handled by reverting the rename, not commiting it (default behavior) LLLineEditor::Params params; params.name("ren"); - params.rect(getRect()); + params.rect(rect); params.font(getLabelFontForStyle(LLFontGL::NORMAL)); params.max_length_bytes(DB_INV_ITEM_NAME_STR_LEN); params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidate_callback(&LLLineEditor::prevalidatePrintableNotPipe); + params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); params.commit_on_focus_lost(true); params.visible(false); mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); addChild(mRenamer); + // Textbox + LLTextBox::Params text_p; + LLFontGL* font = getLabelFontForStyle(mLabelStyle); + LLRect new_r = LLRect(rect.mLeft + ICON_PAD, + rect.mTop - TEXT_PAD, + rect.mRight, + rect.mTop - TEXT_PAD - llfloor(font->getLineHeight())); + text_p.rect(new_r); + text_p.name(std::string(p.name)); + text_p.font(font); + text_p.visible(false); + text_p.allow_html(true); + mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p); + mStatusTextBox->setFollowsLeft(); + mStatusTextBox->setFollowsTop(); + //addChild(mStatusTextBox); + + // make the popup menu available LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if (!menu) @@ -246,6 +272,7 @@ LLFolderView::~LLFolderView( void ) mScrollContainer = NULL; mRenameItem = NULL; mRenamer = NULL; + mStatusTextBox = NULL; if( gEditMenuHandler == this ) { @@ -327,6 +354,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { mFolders.insert(mFolders.begin(), folder); } + folder->setShowLoadStatus(true); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); @@ -353,6 +381,16 @@ void LLFolderView::openFolder(const std::string& foldername) } } +void LLFolderView::openTopLevelFolders() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setOpen(TRUE); + } +} + void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) { // call base class to do proper recursion @@ -379,8 +417,13 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen getRoot()->getFilter()->getShowFolderState(); S32 total_width = LEFT_PAD; - S32 running_height = mDebugFilters ? llceil(sSmallFont->getLineHeight()) : 0; + S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0; S32 target_height = running_height; + if(!mHasVisibleChildren)// is there any filtered items ? + { + //Nope. We need to display status textbox, let's reserve some place for it + target_height += mStatusTextBox->getTextPixelHeight(); + } S32 parent_item_height = getRect().getHeight(); for (folders_t::iterator iter = mFolders.begin(); @@ -397,7 +440,12 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter } - if (folderp->getVisible()) + + // Need to call arrange regardless of visibility, since children's visibility + // might need to be changed too (e.g. even though a folder is invisible, its + // children also need to be set invisible for state-tracking purposes, e.g. + // llfolderviewitem::filter). + // if (folderp->getVisible()) { S32 child_height = 0; S32 child_width = 0; @@ -465,13 +513,13 @@ void LLFolderView::filter( LLInventoryFilter& filter ) if (getCompletedFilterGeneration() < filter.getCurrentGeneration()) { - mFiltered = FALSE; + mPassedFilter = FALSE; mMinWidth = 0; LLFolderViewFolder::filter(filter); } else { - mFiltered = TRUE; + mPassedFilter = TRUE; } } @@ -548,6 +596,8 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus) { + mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; + if( selection == this ) { return FALSE; @@ -575,8 +625,6 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, llassert(mSelectedItems.size() <= 1); - mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS; - return rv; } @@ -729,6 +777,12 @@ void LLFolderView::sanitizeSelection() } } } + + // Don't allow invisible items (such as root folders) to be selected. + if (item->getHidden()) + { + items_to_remove.push_back(item); + } } std::vector<LLFolderViewItem*>::iterator item_it; @@ -748,7 +802,7 @@ void LLFolderView::sanitizeSelection() parent_folder; parent_folder = parent_folder->getParentFolder()) { - if (parent_folder->potentiallyVisible()) + if (parent_folder->potentiallyVisible() && !parent_folder->getHidden()) { // give initial selection to first ancestor folder that potentially passes the filter if (!new_selection) @@ -769,6 +823,11 @@ void LLFolderView::sanitizeSelection() { // nothing selected to start with, so pick "My Inventory" as best guess new_selection = getItemByID(gInventory.getRootFolderID()); + // ... except if it's hidden from the UI. + if (new_selection && new_selection->getHidden()) + { + new_selection = NULL; + } } if (new_selection) @@ -788,10 +847,11 @@ void LLFolderView::clearSelection() mSelectThisID.setNull(); } -BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) +BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) const { - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); + item_it != mSelectedItems.end(); + ++item_it) { selection.insert((*item_it)->getListener()->getUUID()); } @@ -834,12 +894,12 @@ void LLFolderView::draw() { std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); - sSmallFont->renderUTF8(current_filter_string, 0, 2, - getRect().getHeight() - sSmallFont->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), + LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, + getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } - LLFontGL* font = getLabelFontForStyle(mLabelStyle); + //LLFontGL* font = getLabelFontForStyle(mLabelStyle); // if cursor has moved off of me during drag and drop // close all auto opened folders @@ -876,19 +936,23 @@ void LLFolderView::draw() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) { mStatusText.clear(); + mStatusTextBox->setVisible( FALSE ); } else { if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) { mStatusText = LLTrans::getString("Searching"); - font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } else { - mStatusText = LLTrans::getString("InventoryNoMatchingItems"); - font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); + mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage()); + //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } + mStatusTextBox->setValue(mStatusText); + mStatusTextBox->setVisible( TRUE ); + } LLFolderViewFolder::draw(); @@ -907,11 +971,7 @@ void LLFolderView::finishRenamingItem( void ) mRenameItem->rename( mRenamer->getText() ); } - mRenamer->setCommitOnFocusLost( FALSE ); - mRenamer->setFocus( FALSE ); - mRenamer->setVisible( FALSE ); - mRenamer->setCommitOnFocusLost( TRUE ); - gFocusMgr.setTopCtrl( NULL ); + gFocusMgr.setTopCtrl( NULL ); if( mRenameItem ) { @@ -1107,7 +1167,7 @@ void LLFolderView::propertiesSelectedItems( void ) } } -void LLFolderView::changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type) +void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type) { LLFolderBridge *folder_bridge = LLFolderBridge::sSelf; @@ -1241,8 +1301,7 @@ BOOL LLFolderView::canCut() const const LLFolderViewItem* item = *selected_it; const LLFolderViewEventListener* listener = item->getListener(); - // *WARKAROUND: it is too many places where the "isItemRemovable" method should be changed with "const" modifier - if (!listener || !(const_cast<LLFolderViewEventListener*>(listener))->isItemRemovable()) + if (!listener || !listener->isItemRemovable()) { return FALSE; } @@ -1360,6 +1419,7 @@ void LLFolderView::startRenamingSelectedItem( void ) // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); mRenamer->setTopLostCallback(boost::bind(onRenamerLost, _1)); + mRenamer->setFocusLostCallback(boost::bind(onRenamerLost, _1)); gFocusMgr.setTopCtrl( mRenamer ); } } @@ -1476,10 +1536,26 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { if (next == last_selected) { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } return FALSE; } setSelection( next, FALSE, TRUE ); } + else + { + //special case for LLAccordionCtrl + if(notifyParent(LLSD().with("action","select_next")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; + } } scrollToShowSelection(); mSearchString.clear(); @@ -1524,6 +1600,13 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) { if (prev == this) { + // If case we are in accordion tab notify parent to go to the previous accordion + if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed + { + clearSelection(); + return TRUE; + } + return FALSE; } setSelection( prev, FALSE, TRUE ); @@ -1553,7 +1636,11 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) LLFolderViewItem* parent_folder = last_selected->getParentFolder(); if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder()) { - setSelection(parent_folder, FALSE, TRUE); + // Don't change selectin to hidden folder. See EXT-5328. + if (!parent_folder->getHidden()) + { + setSelection(parent_folder, FALSE, TRUE); + } } else { @@ -1795,6 +1882,13 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + // When there are no visible children drag and drop is handled + // by the folder which is the hierarchy root. + if (!handled && !hasVisibleChildren()) + { + handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); + } + if (handled) { lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; @@ -1803,15 +1897,6 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } -BOOL LLFolderView::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - if (mScrollContainer) - { - return mScrollContainer->handleScrollWheel(x, y, clicks); - } - return FALSE; -} - void LLFolderView::deleteAllChildren() { if(mRenamer == gFocusMgr.getTopCtrl()) @@ -1856,8 +1941,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); - // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder - S32 max_height_to_show = mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); // get portion of item that we want to see... LLRect item_local_rect = LLRect(item->getIndentation(), @@ -1933,6 +2018,26 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) return NULL; } +LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) +{ + if (id.isNull()) + { + return this; + } + + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end(); + ++iter) + { + LLFolderViewFolder *folder = (*iter); + if (folder->getListener()->getUUID() == id) + { + return folder; + } + } + return NULL; +} + bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) { std::string action = userdata.asString(); @@ -1957,7 +2062,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) if (action.length() > change_folder_string.length() && (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0)) { - LLAssetType::EType new_folder_type = LLFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); + LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length())); changeType(model, new_folder_type); return true; } @@ -2016,6 +2121,14 @@ static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory"); // Main idle routine void LLFolderView::doIdle() { + // If this is associated with the user's inventory, don't do anything + // until that inventory is loaded up. + const LLInventoryPanel *inventory_panel = dynamic_cast<LLInventoryPanel*>(mParentPanel); + if (inventory_panel && !inventory_panel->getIsViewsInitialized()) + { + return; + } + LLFastTimer t2(FTM_INVENTORY); BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters"); @@ -2164,26 +2277,102 @@ void LLFolderView::updateRenamerPosition() { if(mRenameItem) { - LLFontGL* font = getLabelFontForStyle(mLabelStyle); - - S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + mRenameItem->getIndentation(); - S32 y = llfloor(mRenameItem->getRect().getHeight() - font->getLineHeight()-2); + // See also LLFolderViewItem::draw() + S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation(); + S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; mRenameItem->localPointToScreen( x, y, &x, &y ); screenPointToLocal( x, y, &x, &y ); mRenamer->setOrigin( x, y ); - LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidth(), 0); + LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0); if (mScrollContainer) { scroller_rect = mScrollContainer->getContentWindowRect(); } S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH); - S32 height = llfloor(font->getLineHeight() + RENAME_HEIGHT_PAD); + S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD; mRenamer->reshape( width, height, TRUE ); } } +bool LLFolderView::selectFirstItem() +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + LLFolderViewFolder* folder = (*iter ); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getNextFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + + } + for(items_t::iterator iit = mItems.begin(); + iit != mItems.end(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} +bool LLFolderView::selectLastItem() +{ + for(items_t::reverse_iterator iit = mItems.rbegin(); + iit != mItems.rend(); ++iit) + { + LLFolderViewItem* itemp = (*iit); + if (itemp->getVisible()) + { + setSelection(itemp,FALSE,TRUE); + return true; + } + } + for (folders_t::reverse_iterator iter = mFolders.rbegin(); + iter != mFolders.rend();) + { + LLFolderViewFolder* folder = (*iter); + if (folder->getVisible()) + { + LLFolderViewItem* itemp = folder->getPreviousFromChild(0,true); + if(itemp) + setSelection(itemp,FALSE,TRUE); + return true; + } + } + return false; +} + + +S32 LLFolderView::notify(const LLSD& info) +{ + if(info.has("action")) + { + std::string str_action = info["action"]; + if(str_action == "select_first") + { + setFocus(true); + selectFirstItem(); + return 1; + + } + else if(str_action == "select_last") + { + setFocus(true); + selectLastItem(); + return 1; + } + } + return 0; +} + ///---------------------------------------------------------------------------- /// Local function definitions @@ -2209,9 +2398,9 @@ void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) mFilter->setFilterPermissions(filter_perm_mask); } -U32 LLFolderView::getFilterTypes() const +U32 LLFolderView::getFilterObjectTypes() const { - return mFilter->getFilterTypes(); + return mFilter->getFilterObjectTypes(); } PermissionMask LLFolderView::getFilterPermissions() const |