Inv menus appear now. Still need to update llmenugl and its variants, since our current version is buggy. Also need to look into why inventory postfixes aren't appearing.
This commit is contained in:
@@ -2485,8 +2485,12 @@ void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list)
|
||||
|
||||
void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
|
||||
{
|
||||
for (child_list_const_iter_t child_iter = getChildList()->begin();
|
||||
child_iter != getChildList()->end(); ++child_iter)
|
||||
// make a copy of the list since some floaters change their
|
||||
// order in the childList when changing visibility.
|
||||
child_list_t child_list_copy = *getChildList();
|
||||
|
||||
for (child_list_const_iter_t child_iter = child_list_copy.begin();
|
||||
child_iter != child_list_copy.end(); ++child_iter)
|
||||
{
|
||||
LLView *view = *child_iter;
|
||||
if (skip_list.find(view) == skip_list.end())
|
||||
|
||||
@@ -522,31 +522,15 @@ BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit&
|
||||
// This class represents a separator.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLMenuItemSeparatorGL : public LLMenuItemGL
|
||||
{
|
||||
public:
|
||||
LLMenuItemSeparatorGL( const std::string &name = SEPARATOR_NAME );
|
||||
|
||||
virtual LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
|
||||
virtual std::string getType() const { return "separator"; }
|
||||
|
||||
// doIt() - do the primary funcationality of the menu item.
|
||||
virtual void doIt( void ) {}
|
||||
|
||||
virtual void draw( void );
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||
|
||||
virtual U32 getNominalHeight( void ) const { return SEPARATOR_HEIGHT_PIXELS; }
|
||||
};
|
||||
|
||||
LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const std::string &name ) :
|
||||
LLMenuItemGL( name, SEPARATOR_LABEL )
|
||||
LLMenuItemGL( name.empty() ? SEPARATOR_NAME : name, SEPARATOR_LABEL )
|
||||
{
|
||||
}
|
||||
|
||||
U32 LLMenuItemSeparatorGL::getNominalHeight( void ) const
|
||||
{
|
||||
return SEPARATOR_HEIGHT_PIXELS;
|
||||
}
|
||||
|
||||
LLXMLNodePtr LLMenuItemSeparatorGL::getXML(bool save_children) const
|
||||
{
|
||||
@@ -1694,7 +1678,6 @@ LLMenuGL::LLMenuGL( const std::string& name, const std::string& label, LLHandle<
|
||||
: LLUICtrl( name, LLRect(), FALSE, NULL, NULL ),
|
||||
mBackgroundColor( sDefaultBackgroundColor ),
|
||||
mBgVisible( TRUE ),
|
||||
mParentMenuItem( NULL ),
|
||||
mLabel( label ),
|
||||
mDropShadowed( TRUE ),
|
||||
mHorizontalLayout( FALSE ),
|
||||
@@ -1720,7 +1703,6 @@ LLMenuGL::LLMenuGL( const std::string& label, LLHandle<LLFloater> parent_floater
|
||||
: LLUICtrl( label, LLRect(), FALSE, NULL, NULL ),
|
||||
mBackgroundColor( sDefaultBackgroundColor ),
|
||||
mBgVisible( TRUE ),
|
||||
mParentMenuItem( NULL ),
|
||||
mLabel( label ),
|
||||
mDropShadowed( TRUE ),
|
||||
mHorizontalLayout( FALSE ),
|
||||
@@ -2342,6 +2324,16 @@ void LLMenuGL::arrange( void )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLMenuGL::arrangeAndClear( void )
|
||||
{
|
||||
if (mNeedsArrange)
|
||||
{
|
||||
arrange();
|
||||
mNeedsArrange = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void LLMenuGL::createSpilloverBranch()
|
||||
{
|
||||
if (!mSpilloverBranch)
|
||||
|
||||
@@ -216,6 +216,30 @@ private:
|
||||
KEY mJumpKey;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLMenuItemSeparatorGL
|
||||
//
|
||||
// This class represents a separator.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLMenuItemSeparatorGL : public LLMenuItemGL
|
||||
{
|
||||
public:
|
||||
LLMenuItemSeparatorGL( const std::string &name = std::string() );
|
||||
|
||||
virtual LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
|
||||
virtual std::string getType() const { return "separator"; }
|
||||
|
||||
// doIt() - do the primary funcationality of the menu item.
|
||||
virtual void doIt( void ) {}
|
||||
|
||||
virtual void draw( void );
|
||||
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
|
||||
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||
|
||||
virtual U32 getNominalHeight( void ) const;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLMenuItemCallGL
|
||||
@@ -483,6 +507,7 @@ public:
|
||||
// when you add items. *FIX: We may need to deal with visibility
|
||||
// arrangement.
|
||||
virtual void arrange( void );
|
||||
void arrangeAndClear( void );
|
||||
|
||||
// remove all items on the menu
|
||||
void empty( void );
|
||||
@@ -511,8 +536,8 @@ public:
|
||||
// Whether to drop shadow menu bar
|
||||
void setDropShadowed( const BOOL shadowed );
|
||||
|
||||
void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item; }
|
||||
LLMenuItemGL* getParentMenuItem() const { return mParentMenuItem; }
|
||||
void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); }
|
||||
LLMenuItemGL* getParentMenuItem() const { return dynamic_cast<LLMenuItemGL*>(mParentMenuItem.get()); }
|
||||
|
||||
void setTornOff(BOOL torn_off);
|
||||
BOOL getTornOff() { return mTornOff; }
|
||||
@@ -550,7 +575,7 @@ private:
|
||||
|
||||
LLColor4 mBackgroundColor;
|
||||
BOOL mBgVisible;
|
||||
LLMenuItemGL* mParentMenuItem;
|
||||
LLHandle<LLView> mParentMenuItem;
|
||||
LLUIString mLabel;
|
||||
BOOL mDropShadowed; // Whether to drop shadow
|
||||
BOOL mHasSelection;
|
||||
|
||||
@@ -493,6 +493,7 @@ void LLScrollableContainerView::draw()
|
||||
|
||||
void LLScrollableContainerView::updateScroll()
|
||||
{
|
||||
if(!mScrolledView)return;
|
||||
LLRect doc_rect = mScrolledView->getRect();
|
||||
S32 doc_width = doc_rect.getWidth();
|
||||
S32 doc_height = doc_rect.getHeight();
|
||||
|
||||
@@ -346,8 +346,9 @@ public:
|
||||
virtual void handleVisibilityChange ( BOOL curVisibilityIn );
|
||||
|
||||
void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); }
|
||||
void popVisible() { setVisible(mLastVisible); mLastVisible = TRUE; }
|
||||
|
||||
void popVisible() { setVisible(mLastVisible); }
|
||||
BOOL getLastVisible() const { return mLastVisible; }
|
||||
|
||||
LLHandle<LLView> getHandle() { mHandle.bind(this); return mHandle; }
|
||||
|
||||
U32 getFollows() const { return mReshapeFlags; }
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "llinventoryfilter.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventorymodelbackgroundfetch.h"
|
||||
#include "llinventorypanel.h"
|
||||
#include "llfoldertype.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "lllineeditor.h"
|
||||
@@ -196,7 +197,7 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
|
||||
|
||||
// Default constructor
|
||||
LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_icon,
|
||||
const LLRect& rect, const LLUUID& source_id, LLView *parent_view, LLFolderViewEventListener* listener ) :
|
||||
const LLRect& rect, const LLUUID& source_id, LLPanel *parent_view, LLFolderViewEventListener* listener ) :
|
||||
#if LL_WINDOWS
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
|
||||
@@ -205,6 +206,7 @@ LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_ic
|
||||
#if LL_WINDOWS
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
mRunningHeight(0),
|
||||
mScrollContainer( NULL ),
|
||||
mPopupMenuHandle(),
|
||||
mAllowMultiSelect(TRUE),
|
||||
@@ -225,8 +227,10 @@ LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_ic
|
||||
mArrangeGeneration(0),
|
||||
mSignalSelectCallback(0),
|
||||
mMinWidth(0),
|
||||
mDragAndDropThisFrame(FALSE)
|
||||
mDragAndDropThisFrame(FALSE),
|
||||
mParentPanel(parent_view)
|
||||
{
|
||||
mRoot = this;
|
||||
LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
|
||||
setRect( rect );
|
||||
reshape(rect.getWidth(), rect.getHeight());
|
||||
@@ -267,6 +271,8 @@ LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_ic
|
||||
mPopupMenuHandle = menu->getHandle();
|
||||
|
||||
setTabStop(TRUE);
|
||||
|
||||
mListener->openItem();
|
||||
}
|
||||
|
||||
// Destroys the object
|
||||
@@ -282,23 +288,12 @@ LLFolderView::~LLFolderView( void )
|
||||
mScrollContainer = NULL;
|
||||
mRenameItem = NULL;
|
||||
mRenamer = NULL;
|
||||
gFocusMgr.releaseFocusIfNeeded( this );
|
||||
|
||||
if( gEditMenuHandler == this )
|
||||
{
|
||||
gEditMenuHandler = NULL;
|
||||
}
|
||||
|
||||
mAutoOpenItems.removeAllNodes();
|
||||
gIdleCallbacks.deleteFunction(idle, this);
|
||||
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
|
||||
if(mRenamer == gFocusMgr.getTopCtrl())
|
||||
{
|
||||
gFocusMgr.setTopCtrl(NULL);
|
||||
}
|
||||
|
||||
mAutoOpenItems.removeAllNodes();
|
||||
clearSelection();
|
||||
mItems.clear();
|
||||
@@ -447,6 +442,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
|
||||
@@ -460,6 +465,18 @@ static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
|
||||
// This view grows and shinks to enclose all of its children items and folders.
|
||||
S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )
|
||||
{
|
||||
if(!mScrollContainer)
|
||||
return 1;
|
||||
if (getListener()->getUUID().notNull())
|
||||
{
|
||||
if (mNeedsSort)
|
||||
{
|
||||
mFolders.sort(mSortFunction);
|
||||
mItems.sort(mSortFunction);
|
||||
mNeedsSort = false;
|
||||
}
|
||||
}
|
||||
|
||||
LLFastTimer t2(FTM_ARRANGE);
|
||||
|
||||
filter_generation = mFilter->getMinRequiredGeneration();
|
||||
@@ -529,17 +546,21 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
|
||||
}
|
||||
}
|
||||
|
||||
S32 dummy_s32;
|
||||
BOOL dummy_bool;
|
||||
S32 min_width;
|
||||
mScrollContainer->calcVisibleSize( &min_width, &dummy_s32, &dummy_bool, &dummy_bool);
|
||||
reshape( llmax(min_width, total_width), running_height );
|
||||
|
||||
S32 new_min_width;
|
||||
mScrollContainer->calcVisibleSize( &new_min_width, &dummy_s32, &dummy_bool, &dummy_bool);
|
||||
if (new_min_width != min_width)
|
||||
/*if(!mHasVisibleChildren)// is there any filtered items ?
|
||||
{
|
||||
reshape( llmax(min_width, total_width), running_height );
|
||||
//Nope. We need to display status textbox, let's reserve some place for it
|
||||
running_height = mStatusTextBox->getTextPixelHeight();
|
||||
target_height = running_height;
|
||||
}*/
|
||||
|
||||
mRunningHeight = running_height;
|
||||
LLRect scroll_rect = mScrollContainer->getContentWindowRect();
|
||||
reshape( llmax(scroll_rect.getWidth(), total_width), running_height );
|
||||
|
||||
LLRect new_scroll_rect = mScrollContainer->getContentWindowRect();
|
||||
if (new_scroll_rect.getWidth() != scroll_rect.getWidth())
|
||||
{
|
||||
reshape( llmax(scroll_rect.getWidth(), total_width), running_height );
|
||||
}
|
||||
|
||||
// move item renamer text field to item's new position
|
||||
@@ -575,14 +596,14 @@ void LLFolderView::filter( LLInventoryFilter& filter )
|
||||
|
||||
void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)
|
||||
{
|
||||
S32 min_width = 0;
|
||||
S32 dummy_height;
|
||||
BOOL dummy_bool;
|
||||
LLRect scroll_rect;
|
||||
if (mScrollContainer)
|
||||
{
|
||||
mScrollContainer->calcVisibleSize( &min_width, &dummy_height, &dummy_bool, &dummy_bool);
|
||||
LLView::reshape(width, height, called_from_parent);
|
||||
scroll_rect = mScrollContainer->getContentWindowRect();
|
||||
}
|
||||
width = llmax(mMinWidth, min_width);
|
||||
width = llmax(mMinWidth, scroll_rect.getWidth());
|
||||
height = llmax(mRunningHeight, scroll_rect.getHeight());
|
||||
LLView::reshape(width, height, called_from_parent);
|
||||
|
||||
mReshapeSignal(mSelectedItems, FALSE);
|
||||
@@ -643,6 +664,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;
|
||||
@@ -650,7 +673,7 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,
|
||||
|
||||
if( selection && take_keyboard_focus)
|
||||
{
|
||||
setFocus(TRUE);
|
||||
mParentPanel->setFocus(TRUE);
|
||||
}
|
||||
|
||||
// clear selection down here because change of keyboard focus can potentially
|
||||
@@ -670,8 +693,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;
|
||||
}
|
||||
|
||||
@@ -921,10 +942,6 @@ void LLFolderView::draw()
|
||||
{
|
||||
closeAutoOpenedFolders();
|
||||
}
|
||||
if(this == gFocusMgr.getKeyboardFocus() && !getVisible())
|
||||
{
|
||||
gFocusMgr.setKeyboardFocus( NULL );
|
||||
}
|
||||
|
||||
// while dragging, update selection rendering to reflect single/multi drag status
|
||||
if (LLToolDragAndDrop::getInstance()->hasMouseCapture())
|
||||
@@ -996,11 +1013,40 @@ void LLFolderView::closeRenamer( void )
|
||||
{
|
||||
if (mRenamer && mRenamer->getVisible())
|
||||
{
|
||||
if(mRenamer == gFocusMgr.getTopCtrl())
|
||||
gFocusMgr.setTopCtrl( NULL );
|
||||
// Triggers onRenamerLost() that actually closes the renamer.
|
||||
gFocusMgr.setTopCtrl( NULL );
|
||||
//gFocusMgr.setTopCtrl( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFolderViewItem*>& selectedItems)
|
||||
{
|
||||
LLFolderViewItem* item_parent = dynamic_cast<LLFolderViewItem*>(item->getParent());
|
||||
|
||||
if (item_parent)
|
||||
{
|
||||
for(std::vector<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
|
||||
{
|
||||
const LLFolderViewItem* const selected_item = (*it);
|
||||
|
||||
LLFolderViewItem* parent = item_parent;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
if (selected_item == parent)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
parent = dynamic_cast<LLFolderViewItem*>(parent->getParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFolderView::removeSelectedItems( void )
|
||||
{
|
||||
if(getVisible() && getEnabled())
|
||||
@@ -1049,11 +1095,11 @@ void LLFolderView::removeSelectedItems( void )
|
||||
// change selection on successful delete
|
||||
if (new_selection)
|
||||
{
|
||||
setSelectionFromRoot(new_selection, new_selection->isOpen(), hasFocus());
|
||||
setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus());
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectionFromRoot(NULL, hasFocus());
|
||||
setSelectionFromRoot(NULL, mParentPanel->hasFocus());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1072,18 +1118,18 @@ void LLFolderView::removeSelectedItems( void )
|
||||
if (!new_selection)
|
||||
{
|
||||
new_selection = last_item->getPreviousOpenNode(FALSE);
|
||||
while (new_selection && (new_selection->isSelected()/* || isDescendantOfASelectedItem(new_selection, items)*/))
|
||||
while (new_selection && (new_selection->isSelected() || isDescendantOfASelectedItem(new_selection, items)))
|
||||
{
|
||||
new_selection = new_selection->getPreviousOpenNode(FALSE);
|
||||
}
|
||||
}
|
||||
if (new_selection)
|
||||
{
|
||||
setSelectionFromRoot(new_selection, new_selection->isOpen(), hasFocus());
|
||||
setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus());
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectionFromRoot(NULL, hasFocus());
|
||||
setSelectionFromRoot(NULL, mParentPanel->hasFocus());
|
||||
}
|
||||
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
@@ -1432,19 +1478,6 @@ void LLFolderView::startRenamingSelectedItem( void )
|
||||
}
|
||||
}
|
||||
|
||||
void LLFolderView::setFocus(BOOL focus)
|
||||
{
|
||||
if (focus)
|
||||
{
|
||||
if(!hasFocus())
|
||||
{
|
||||
gEditMenuHandler = this;
|
||||
}
|
||||
}
|
||||
|
||||
LLFolderViewFolder::setFocus(focus);
|
||||
}
|
||||
|
||||
BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
@@ -1647,7 +1680,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
|
||||
break;
|
||||
}
|
||||
|
||||
if (!handled && hasFocus())
|
||||
if (!handled && mParentPanel->hasFocus())
|
||||
{
|
||||
if (key == KEY_BACKSPACE)
|
||||
{
|
||||
@@ -1679,7 +1712,7 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char)
|
||||
}
|
||||
|
||||
BOOL handled = FALSE;
|
||||
if (hasFocus())
|
||||
if (mParentPanel->hasFocus())
|
||||
{
|
||||
// SL-51858: Key presses are not being passed to the Popup menu.
|
||||
// A proper fix is non-trivial so instead just close the menu.
|
||||
@@ -1736,20 +1769,13 @@ BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask )
|
||||
mKeyboardSelection = FALSE;
|
||||
mSearchString.clear();
|
||||
|
||||
setFocus(TRUE);
|
||||
mParentPanel->setFocus(TRUE);
|
||||
|
||||
LLEditMenuHandler::gEditMenuHandler = this;
|
||||
|
||||
return LLView::handleMouseDown( x, y, mask );
|
||||
}
|
||||
|
||||
void LLFolderView::onFocusLost( )
|
||||
{
|
||||
if( gEditMenuHandler == this )
|
||||
{
|
||||
gEditMenuHandler = NULL;
|
||||
}
|
||||
LLUICtrl::onFocusLost();
|
||||
}
|
||||
|
||||
BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward)
|
||||
{
|
||||
// get first selected item
|
||||
@@ -1826,35 +1852,21 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
// all user operations move keyboard focus to inventory
|
||||
// this way, we know when to stop auto-updating a search
|
||||
setFocus(TRUE);
|
||||
mParentPanel->setFocus(TRUE);
|
||||
|
||||
BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
|
||||
S32 count = mSelectedItems.size();
|
||||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if(handled && (count > 0) && menu)
|
||||
if ( handled
|
||||
&& ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible
|
||||
&& menu )
|
||||
{
|
||||
//menu->empty();
|
||||
const LLView::child_list_t *list = menu->getChildList();
|
||||
|
||||
LLView::child_list_t::const_iterator menu_itor;
|
||||
for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
|
||||
{
|
||||
(*menu_itor)->setVisible(TRUE);
|
||||
(*menu_itor)->setEnabled(TRUE);
|
||||
}
|
||||
|
||||
// Successively filter out invalid options
|
||||
selected_items_t::iterator item_itor;
|
||||
U32 flags = FIRST_SELECTED_ITEM;
|
||||
for (item_itor = mSelectedItems.begin(); item_itor != mSelectedItems.end(); ++item_itor)
|
||||
{
|
||||
(*item_itor)->buildContextMenu(*menu, flags);
|
||||
flags = 0x0;
|
||||
}
|
||||
|
||||
menu->arrange();
|
||||
updateMenuOptions(menu);
|
||||
|
||||
menu->updateParent(LLMenuGL::sMenuContainer);
|
||||
LLMenuGL::showPopup(this, menu, x, y);
|
||||
|
||||
menu->needsArrange(); // update menu height if needed
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1867,6 +1879,37 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
|
||||
return handled;
|
||||
}
|
||||
|
||||
// Add "--no options--" if the menu is completely blank.
|
||||
BOOL LLFolderView::addNoOptions(LLMenuGL* menu) const
|
||||
{
|
||||
const std::string nooptions_str = "--no options--";
|
||||
LLView *nooptions_item = NULL;
|
||||
|
||||
const LLView::child_list_t *list = menu->getChildList();
|
||||
for (LLView::child_list_t::const_iterator itor = list->begin();
|
||||
itor != list->end();
|
||||
++itor)
|
||||
{
|
||||
LLView *menu_item = (*itor);
|
||||
if (menu_item->getVisible())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
std::string name = menu_item->getName();
|
||||
if (menu_item->getName() == nooptions_str)
|
||||
{
|
||||
nooptions_item = menu_item;
|
||||
}
|
||||
}
|
||||
if (nooptions_item)
|
||||
{
|
||||
nooptions_item->setVisible(TRUE);
|
||||
nooptions_item->setEnabled(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
return LLView::handleHover( x, y, mask );
|
||||
@@ -1901,21 +1944,25 @@ BOOL LLFolderView::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
||||
|
||||
void LLFolderView::deleteAllChildren()
|
||||
{
|
||||
if(mRenamer == gFocusMgr.getTopCtrl())
|
||||
{
|
||||
gFocusMgr.setTopCtrl(NULL);
|
||||
}
|
||||
LLView::deleteViewByHandle(mPopupMenuHandle);
|
||||
closeRenamer();
|
||||
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
|
||||
mPopupMenuHandle = LLHandle<LLView>();
|
||||
mRenamer = NULL;
|
||||
mScrollContainer = NULL;
|
||||
mRenameItem = NULL;
|
||||
mRenamer = NULL;
|
||||
clearSelection();
|
||||
LLView::deleteAllChildren();
|
||||
}
|
||||
|
||||
void LLFolderView::scrollToShowSelection()
|
||||
{
|
||||
if (mSelectedItems.size())
|
||||
// If items are filtered while background fetch is in progress
|
||||
// scrollbar resets to the first filtered item. See EXT-3981.
|
||||
// However we allow scrolling for folder views with mAutoSelectOverride
|
||||
// (used in Places SP) as an exception because the selection in them
|
||||
// is not reset during items filtering. See STORM-133.
|
||||
if ( (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mAutoSelectOverride)
|
||||
&& mSelectedItems.size() )
|
||||
{
|
||||
mNeedsScroll = TRUE;
|
||||
}
|
||||
@@ -1925,6 +1972,7 @@ void LLFolderView::scrollToShowSelection()
|
||||
// is maximally visible.
|
||||
void LLFolderView::scrollToShowItem(LLFolderViewItem* item)
|
||||
{
|
||||
if (!mScrollContainer) return;
|
||||
// don't scroll to items when mouse is being used to scroll/drag and drop
|
||||
if (gFocusMgr.childHasMouseCapture(mScrollContainer))
|
||||
{
|
||||
@@ -2015,7 +2063,7 @@ LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID");
|
||||
LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
|
||||
{
|
||||
LLFastTimer _(FTM_GET_ITEM_BY_ID);
|
||||
if (id.isNull())
|
||||
if (id == getListener()->getUUID())
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@@ -2030,6 +2078,25 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id)
|
||||
{
|
||||
if (id == getListener()->getUUID())
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select");
|
||||
@@ -2038,6 +2105,14 @@ extern std::set<LLFolderViewItem*> sFolderViewItems; //dumb hack
|
||||
// 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");
|
||||
@@ -2078,12 +2153,21 @@ void LLFolderView::doIdle()
|
||||
clearSelection();
|
||||
requestArrange();
|
||||
}
|
||||
else if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getFiltered()))
|
||||
else if ((selected_itemp && !selected_itemp->getFiltered()) && !mAutoSelectOverride)
|
||||
{
|
||||
// select first filtered item
|
||||
LLSelectFirstFilteredItem filter;
|
||||
applyFunctorRecursively(filter);
|
||||
}
|
||||
|
||||
// Open filtered folders for folder views with mAutoSelectOverride=TRUE.
|
||||
// Used by LLPlacesFolderView.
|
||||
if (mAutoSelectOverride && !mFilter->getFilterSubString().empty())
|
||||
{
|
||||
LLOpenFilteredFolders filter;
|
||||
applyFunctorRecursively(filter);
|
||||
}
|
||||
|
||||
scrollToShowSelection();
|
||||
}
|
||||
|
||||
@@ -2155,8 +2239,7 @@ void LLFolderView::updateRenamerPosition()
|
||||
LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0);
|
||||
if (mScrollContainer)
|
||||
{
|
||||
BOOL dummy_bool;
|
||||
mScrollContainer->calcVisibleSize( &scroller_rect.mRight, &scroller_rect.mTop, &dummy_bool, &dummy_bool);
|
||||
scroller_rect = mScrollContainer->getContentWindowRect();
|
||||
}
|
||||
|
||||
S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH);
|
||||
@@ -2164,13 +2247,64 @@ void LLFolderView::updateRenamerPosition()
|
||||
mRenamer->reshape( width, height, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
// Update visibility and availability (i.e. enabled/disabled) of context menu items.
|
||||
void LLFolderView::updateMenuOptions(LLMenuGL* menu)
|
||||
{
|
||||
const LLView::child_list_t *list = menu->getChildList();
|
||||
|
||||
LLView::child_list_t::const_iterator menu_itor;
|
||||
for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
|
||||
{
|
||||
(*menu_itor)->setVisible(FALSE);
|
||||
(*menu_itor)->pushVisible(TRUE);
|
||||
(*menu_itor)->setEnabled(TRUE);
|
||||
}
|
||||
|
||||
// Successively filter out invalid options
|
||||
|
||||
U32 flags = FIRST_SELECTED_ITEM;
|
||||
for (selected_items_t::iterator item_itor = mSelectedItems.begin();
|
||||
item_itor != mSelectedItems.end();
|
||||
++item_itor)
|
||||
{
|
||||
LLFolderViewItem* selected_item = (*item_itor);
|
||||
selected_item->buildContextMenu(*menu, flags);
|
||||
flags = 0x0;
|
||||
}
|
||||
|
||||
addNoOptions(menu);
|
||||
}
|
||||
|
||||
// Refresh the context menu (that is already shown).
|
||||
void LLFolderView::updateMenu()
|
||||
{
|
||||
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
|
||||
if (menu && menu->getVisible())
|
||||
{
|
||||
updateMenuOptions(menu);
|
||||
menu->needsArrange(); // update menu height if needed
|
||||
}
|
||||
}
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function definitions
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
void LLFolderView::onRenamerLost()
|
||||
{
|
||||
if (mRenamer && mRenamer->getVisible())
|
||||
{
|
||||
mRenamer->setVisible(FALSE);
|
||||
|
||||
// will commit current name (which could be same as original name)
|
||||
mRenamer->setFocus(FALSE);
|
||||
}
|
||||
|
||||
if( mRenameItem )
|
||||
{
|
||||
setSelectionFromRoot( mRenameItem, TRUE );
|
||||
mRenameItem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LLInventoryFilter* LLFolderView::getFilter()
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
|
||||
LLFolderView( const std::string& name, LLUIImagePtr root_folder_icon, const LLRect& rect,
|
||||
const LLUUID& source_id, LLView *parent_view, LLFolderViewEventListener* listener );
|
||||
const LLUUID& source_id, LLPanel *parent_view, LLFolderViewEventListener* listener );
|
||||
virtual ~LLFolderView( void );
|
||||
|
||||
virtual BOOL canFocusChildren() const;
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
U32 getSortOrder() const;
|
||||
BOOL isFilterModified();
|
||||
|
||||
BOOL getAllowMultiSelect() { return mAllowMultiSelect; }
|
||||
bool getAllowMultiSelect() { return mAllowMultiSelect; }
|
||||
|
||||
U32 toggleSearchType(std::string toggle);
|
||||
U32 getSearchType() const;
|
||||
@@ -117,6 +117,7 @@ public:
|
||||
// Close all folders in the view
|
||||
void closeAllFolders();
|
||||
void openFolder(const std::string& foldername);
|
||||
void openTopLevelFolders();
|
||||
|
||||
virtual void toggleOpen() {};
|
||||
virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse);
|
||||
@@ -196,9 +197,6 @@ public:
|
||||
//void dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept );
|
||||
//void dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept );
|
||||
|
||||
// LLUICtrl Functionality
|
||||
/*virtual*/ void setFocus(BOOL focus);
|
||||
|
||||
// LLView functionality
|
||||
///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent );
|
||||
/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask );
|
||||
@@ -213,7 +211,6 @@ public:
|
||||
EAcceptance* accept,
|
||||
std::string& tooltip_msg);
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
|
||||
/*virtual*/ void onFocusLost();
|
||||
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
|
||||
virtual void draw();
|
||||
virtual void deleteAllChildren();
|
||||
@@ -233,6 +230,7 @@ public:
|
||||
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
|
||||
void removeItemID(const LLUUID& id);
|
||||
LLFolderViewItem* getItemByID(const LLUUID& id);
|
||||
LLFolderViewFolder* getFolderByID(const LLUUID& id);
|
||||
|
||||
void doIdle(); // Real idle routine
|
||||
static void idle(void* user_data); // static glue to doIdle()
|
||||
@@ -243,10 +241,16 @@ public:
|
||||
|
||||
BOOL getDebugFilters() { return mDebugFilters; }
|
||||
|
||||
LLPanel* getParentPanel() { return mParentPanel; }
|
||||
// DEBUG only
|
||||
void dumpSelectionInformation();
|
||||
|
||||
void updateMenu();
|
||||
|
||||
private:
|
||||
void updateMenuOptions(LLMenuGL* menu);
|
||||
void updateRenamerPosition();
|
||||
|
||||
protected:
|
||||
LLScrollableContainerView* mScrollContainer; // NULL if this is not a child of a scroll container.
|
||||
|
||||
@@ -256,6 +260,8 @@ protected:
|
||||
void finishRenamingItem( void );
|
||||
void closeRenamer( void );
|
||||
|
||||
|
||||
BOOL addNoOptions(LLMenuGL* menu) const;
|
||||
protected:
|
||||
LLHandle<LLView> mPopupMenuHandle;
|
||||
|
||||
@@ -295,8 +301,11 @@ protected:
|
||||
signal_t mReshapeSignal;
|
||||
S32 mSignalSelectCallback;
|
||||
S32 mMinWidth;
|
||||
S32 mRunningHeight;
|
||||
std::map<LLUUID, LLFolderViewItem*> mItemMap;
|
||||
BOOL mDragAndDropThisFrame;
|
||||
|
||||
LLPanel* mParentPanel;
|
||||
|
||||
/**
|
||||
* Contains item under mouse pointer while dragging
|
||||
|
||||
@@ -1046,7 +1046,8 @@ LLFolderViewFolder::LLFolderViewFolder( const std::string& name, LLUIImagePtr ic
|
||||
mLastArrangeGeneration( -1 ),
|
||||
mLastCalculatedWidth(0),
|
||||
mCompletedFilterGeneration(-1),
|
||||
mMostFilteredDescendantGeneration(-1)
|
||||
mMostFilteredDescendantGeneration(-1),
|
||||
mNeedsSort(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1075,6 +1076,14 @@ BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* r
|
||||
// makes sure that this view and it's children are the right size.
|
||||
S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
|
||||
{
|
||||
// sort before laying out contents
|
||||
if (mNeedsSort)
|
||||
{
|
||||
mFolders.sort(mSortFunction);
|
||||
mItems.sort(mSortFunction);
|
||||
mNeedsSort = false;
|
||||
}
|
||||
|
||||
mHasVisibleChildren = hasFilteredDescendants(filter_generation);
|
||||
|
||||
LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getFilter()->getShowFolderState();
|
||||
@@ -1219,6 +1228,12 @@ BOOL LLFolderViewFolder::needsArrange()
|
||||
return mLastArrangeGeneration < getRoot()->getArrangeGeneration();
|
||||
}
|
||||
|
||||
void LLFolderViewFolder::requestSort()
|
||||
{
|
||||
mNeedsSort = true;
|
||||
// whenever item order changes, we need to lay things out again
|
||||
requestArrange();
|
||||
}
|
||||
void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up)
|
||||
{
|
||||
mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
|
||||
@@ -1404,6 +1419,11 @@ void LLFolderViewFolder::dirtyFilter()
|
||||
LLFolderViewItem::dirtyFilter();
|
||||
}
|
||||
|
||||
BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation)
|
||||
{
|
||||
return mMostFilteredDescendantGeneration >= filter_generation;
|
||||
}
|
||||
|
||||
BOOL LLFolderViewFolder::hasFilteredDescendants()
|
||||
{
|
||||
return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration();
|
||||
@@ -1871,7 +1891,7 @@ void LLFolderViewFolder::destroyView()
|
||||
folderp->destroyView(); // removes entry from mFolders
|
||||
}
|
||||
|
||||
deleteAllChildren();
|
||||
//deleteAllChildren();
|
||||
|
||||
if (mParentFolder)
|
||||
{
|
||||
@@ -2190,12 +2210,16 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r
|
||||
{
|
||||
BOOL was_open = mIsOpen;
|
||||
mIsOpen = openitem;
|
||||
if(!was_open && openitem)
|
||||
if (mListener)
|
||||
{
|
||||
if(mListener)
|
||||
if(!was_open && openitem)
|
||||
{
|
||||
mListener->openItem();
|
||||
}
|
||||
else if(was_open && !openitem)
|
||||
{
|
||||
mListener->closeItem();
|
||||
}
|
||||
}
|
||||
|
||||
if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN)
|
||||
|
||||
@@ -364,6 +364,7 @@ protected:
|
||||
S32 mLastCalculatedWidth;
|
||||
S32 mCompletedFilterGeneration;
|
||||
S32 mMostFilteredDescendantGeneration;
|
||||
bool mNeedsSort;
|
||||
public:
|
||||
typedef enum e_recurse_type
|
||||
{
|
||||
@@ -389,6 +390,7 @@ public:
|
||||
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
|
||||
|
||||
BOOL needsArrange();
|
||||
void requestSort();
|
||||
|
||||
// Returns the sort group (system, trash, folder) for this folder.
|
||||
virtual EInventorySortGroup getSortGroup() const;
|
||||
@@ -396,7 +398,7 @@ public:
|
||||
virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
|
||||
virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
|
||||
|
||||
BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; }
|
||||
BOOL hasFilteredDescendants(S32 filter_generation);
|
||||
BOOL hasFilteredDescendants();
|
||||
|
||||
// applies filters to control visibility of inventory items
|
||||
|
||||
@@ -213,7 +213,7 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,
|
||||
mInvType(LLInventoryType::IT_NONE),
|
||||
mIsLink(FALSE)
|
||||
{
|
||||
mInventoryPanel = inventory;
|
||||
mInventoryPanel = inventory->getHandle();
|
||||
const LLInventoryObject* obj = getInventoryObject();
|
||||
mIsLink = obj && obj->getIsLinkType();
|
||||
}
|
||||
@@ -592,6 +592,22 @@ void hide_context_entries(LLMenuGL& menu,
|
||||
{
|
||||
const LLView::child_list_t *list = menu.getChildList();
|
||||
|
||||
// For removing double separators or leading separator. Start at true so that
|
||||
// if the first element is a separator, it will not be shown.
|
||||
bool is_previous_entry_separator = true;
|
||||
|
||||
for (menuentry_vec_t::const_iterator itor = entries_to_show.begin(); itor != entries_to_show.end(); ++itor)
|
||||
{
|
||||
bool found = false;
|
||||
for (LLView::child_list_t::const_iterator itor2 = list->begin(); itor2 != list->end(); ++itor2)
|
||||
{
|
||||
if(*itor == (*itor2)->getName())
|
||||
found = true;
|
||||
}
|
||||
if(!found)
|
||||
llinfos << "Failed to find entry '" << *itor << "'" << llendl;
|
||||
}
|
||||
|
||||
for (LLView::child_list_t::const_iterator itor = list->begin();
|
||||
itor != list->end();
|
||||
++itor)
|
||||
@@ -605,8 +621,7 @@ void hide_context_entries(LLMenuGL& menu,
|
||||
{
|
||||
hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool found = false;
|
||||
menuentry_vec_t::const_iterator itor2;
|
||||
for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
|
||||
@@ -614,21 +629,42 @@ void hide_context_entries(LLMenuGL& menu,
|
||||
if (*itor2 == name)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't allow multiple separators in a row (e.g. such as if there are no items
|
||||
// between two separators).
|
||||
if (found)
|
||||
{
|
||||
const bool is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL);
|
||||
found = !(is_entry_separator && is_previous_entry_separator);
|
||||
is_previous_entry_separator = is_entry_separator;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
menu_item->setVisible(FALSE);
|
||||
if (!menu_item->getLastVisible())
|
||||
{
|
||||
menu_item->setVisible(FALSE);
|
||||
}
|
||||
|
||||
menu_item->setEnabled(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
|
||||
menu_item->setVisible(TRUE);
|
||||
// A bit of a hack so we can remember that some UI element explicitly set this to be visible
|
||||
// so that some other UI element from multi-select doesn't later set this invisible.
|
||||
menu_item->pushVisible(TRUE);
|
||||
|
||||
bool enabled = (menu_item->getEnabled() == TRUE);
|
||||
for (itor2 = disabled_entries.begin(); enabled && (itor2 != disabled_entries.end()); ++itor2)
|
||||
{
|
||||
if (*itor2 == name)
|
||||
{
|
||||
menu_item->setEnabled(FALSE);
|
||||
}
|
||||
enabled &= (*itor2 != name);
|
||||
}
|
||||
llinfos << (enabled ? "Showing" : "hiding") << " " << menu_item->getName() << llendl;
|
||||
menu_item->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,7 +774,8 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
// [RLVa:KB] - Checked: 2009-11-11 (RLVa-1.1.0a) | Modified: RLVa-1.1.0a
|
||||
if (rlv_handler_t::isEnabled())
|
||||
{
|
||||
LLInventoryObject* pItem = (mInventoryPanel->getModel()) ? mInventoryPanel->getModel()->getObject(mUUID) : NULL;
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||
LLInventoryObject* pItem = (panel && panel->getModel()) ? panel->getModel()->getObject(mUUID) : NULL;
|
||||
if ( (pItem) &&
|
||||
( ((LLAssetType::AT_NOTECARD == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE))) ||
|
||||
((LLAssetType::AT_LSL_TEXT == pItem->getType()) && (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWSCRIPT))) ||
|
||||
@@ -855,7 +892,7 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const
|
||||
|
||||
LLInventoryModel* LLInvFVBridge::getInventoryModel() const
|
||||
{
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel);
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||
return panel ? panel->getModel() : NULL;
|
||||
}
|
||||
|
||||
@@ -1089,6 +1126,27 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
|
||||
model->notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
// +=================================================+
|
||||
// | InventoryFVBridgeBuilder |
|
||||
// +=================================================+
|
||||
LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
|
||||
LLAssetType::EType actual_asset_type,
|
||||
LLInventoryType::EType inv_type,
|
||||
LLInventoryPanel* inventory,
|
||||
LLFolderView* root,
|
||||
const LLUUID& uuid,
|
||||
U32 flags /* = 0x00 */) const
|
||||
{
|
||||
return LLInvFVBridge::createBridge(asset_type,
|
||||
actual_asset_type,
|
||||
inv_type,
|
||||
inventory,
|
||||
root,
|
||||
uuid,
|
||||
flags);
|
||||
}
|
||||
|
||||
// +=================================================+
|
||||
// | LLItemBridge |
|
||||
// +=================================================+
|
||||
@@ -1627,7 +1685,7 @@ BOOL LLFolderBridge::isItemRemovable() const
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel);
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||
LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL);
|
||||
if (folderp)
|
||||
{
|
||||
@@ -1661,16 +1719,58 @@ BOOL LLFolderBridge::isItemCopyable() const
|
||||
return InventoryLinksEnabled();
|
||||
}
|
||||
|
||||
|
||||
BOOL LLFolderBridge::isClipboardPasteable() const
|
||||
BOOL LLFolderBridge::copyToClipboard() const
|
||||
{
|
||||
if(LLInventoryClipboard::instance().hasContents() && isAgentInventory())
|
||||
if(isItemCopyable())
|
||||
{
|
||||
LLInventoryClipboard::instance().add(mUUID);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLFolderBridge::isClipboardPasteable() const
|
||||
{
|
||||
if ( ! LLInvFVBridge::isClipboardPasteable() )
|
||||
return FALSE;
|
||||
|
||||
/* TODO
|
||||
// Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
|
||||
if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if ( !model )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLDynamicArray<LLUUID> objects;
|
||||
LLInventoryClipboard::instance().retrieve(objects);
|
||||
const LLViewerInventoryCategory *current_cat = getCategory();
|
||||
|
||||
// Search for the direct descendent of current Friends subfolder among all pasted items,
|
||||
// and return false if is found.
|
||||
for(S32 i = objects.count() - 1; i >= 0; --i)
|
||||
{
|
||||
const LLUUID &obj_id = objects.get(i);
|
||||
if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return TRUE;
|
||||
|
||||
//Old, less restrictive behavior
|
||||
/*if(LLInventoryClipboard::instance().hasContents() && isAgentInventory())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOL LLFolderBridge::isClipboardPasteableAsLink() const
|
||||
{
|
||||
@@ -2312,6 +2412,11 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
modifyOutfit(TRUE);
|
||||
return;
|
||||
}
|
||||
else if ("copy" == action)
|
||||
{
|
||||
copyToClipboard();
|
||||
return;
|
||||
}
|
||||
else if ("wearitems" == action)
|
||||
{
|
||||
modifyOutfit(TRUE);
|
||||
@@ -2604,8 +2709,7 @@ void LLFolderBridge::staticFolderOptionsMenu()
|
||||
|
||||
if (selfp && selfp->mRoot)
|
||||
{
|
||||
//selfp->mRoot->updateMenu();
|
||||
selfp->buildContextMenuFolderOptions(0);
|
||||
selfp->mRoot->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2623,7 +2727,6 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
|
||||
|
||||
void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
|
||||
{
|
||||
LLUUID cof_id = LLAppearanceMgr::instance().getCOF();
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
llassert(model != NULL);
|
||||
|
||||
@@ -2649,13 +2752,7 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
|
||||
mDisabledItems.push_back(std::string("New Body Parts"));
|
||||
}
|
||||
|
||||
// clear out old menu and folder pointers
|
||||
mMenu.markDead();
|
||||
if (cof_id == mUUID)
|
||||
{
|
||||
mItems.push_back(std::string("Take Off Items"));
|
||||
}
|
||||
else if(trash_id == mUUID)
|
||||
if(trash_id == mUUID)
|
||||
{
|
||||
// This is the trash.
|
||||
mItems.push_back(std::string("Empty Trash"));
|
||||
@@ -2792,15 +2889,20 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)
|
||||
{
|
||||
mItems.push_back(std::string("Add To Outfit"));
|
||||
}
|
||||
mItems.push_back(std::string("Wear Items"));
|
||||
else if(!InventoryLinksEnabled())
|
||||
mItems.push_back(std::string("Wear Items"));
|
||||
mItems.push_back(std::string("Replace Outfit"));
|
||||
}
|
||||
mItems.push_back(std::string("Take Off Items"));
|
||||
}
|
||||
LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
|
||||
if (menup)
|
||||
{
|
||||
hide_context_entries(*menup, mItems, mDisabledItems);
|
||||
mItems.push_back(std::string("Remove From Outfit"));
|
||||
if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Remove From Outfit"));
|
||||
}
|
||||
if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Replace Outfit"));
|
||||
}
|
||||
mItems.push_back(std::string("Outfit Separator"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2827,31 +2929,26 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
uuid_vec_t folders;
|
||||
folders.push_back(category->getUUID());
|
||||
|
||||
mMenu = menu.getHandle();
|
||||
sSelf = getHandle();
|
||||
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
|
||||
fetch->startFetch();
|
||||
inc_busy_count();
|
||||
if(fetch->isFinished())
|
||||
if (fetch->isFinished())
|
||||
{
|
||||
//buildContextMenuFolderOptions(flags);
|
||||
// everything is already here - call done.
|
||||
fetch->done();
|
||||
buildContextMenuFolderOptions(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on it's way - add an observer, and the inventory
|
||||
// will call done for us when everything is here.
|
||||
// it's all on its way - add an observer, and the inventory will call done for us when everything is here.
|
||||
gInventory.addObserver(fetch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mItems.push_back(std::string("--no options--"));
|
||||
mDisabledItems.push_back(std::string("--no options--"));
|
||||
|
||||
}
|
||||
hide_context_entries(menu, mItems, mDisabledItems);
|
||||
|
||||
// Reposition the menu, in case we're adding items to an existing menu.
|
||||
menu.needsArrange();
|
||||
menu.arrangeAndClear();
|
||||
}
|
||||
|
||||
BOOL LLFolderBridge::hasChildren() const
|
||||
@@ -2939,7 +3036,7 @@ void LLFolderBridge::createNewCategory(void* user_data)
|
||||
{
|
||||
LLFolderBridge* bridge = (LLFolderBridge*)user_data;
|
||||
if(!bridge) return;
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel);
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
|
||||
if (!panel) return;
|
||||
LLInventoryModel* model = panel->getModel();
|
||||
if(!model) return;
|
||||
@@ -3133,7 +3230,7 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
|
||||
// use callback to rearrange favorite landmarks after adding
|
||||
// to have new one placed before target (on which it was dropped). See EXT-4312.
|
||||
LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel);
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||
LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
|
||||
if (drag_over_item && drag_over_item->getListener())
|
||||
{
|
||||
@@ -3228,6 +3325,20 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
||||
{
|
||||
is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID());
|
||||
}
|
||||
/* TODO
|
||||
if (is_movable)
|
||||
{
|
||||
// Don't allow creating duplicates in the Calling Card/Friends
|
||||
// subfolders, see bug EXT-1599. Check is item direct descendent
|
||||
// of target folder and forbid item's movement if it so.
|
||||
// Note: isItemDirectDescendentOfCategory checks if
|
||||
// passed category is in the Calling Card/Friends folder
|
||||
is_movable &= !LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(inv_item, getCategory());
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Determine if item can be moved & dropped
|
||||
@@ -3264,7 +3375,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
||||
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
|
||||
if (active_panel)
|
||||
{
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel);
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||
if (active_panel && (panel != active_panel))
|
||||
{
|
||||
active_panel->unSelectAll();
|
||||
@@ -3297,7 +3408,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
||||
|
||||
//
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
}
|
||||
else if(LLToolDragAndDrop::SOURCE_WORLD == source)
|
||||
@@ -3490,6 +3600,50 @@ void LLTextureBridge::openItem()
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLTextureBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
{
|
||||
// TODO
|
||||
/*if ("save_as" == action)
|
||||
{
|
||||
LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
|
||||
LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
|
||||
if (preview_texture)
|
||||
{
|
||||
preview_texture->openToSave();
|
||||
}
|
||||
}
|
||||
else*/
|
||||
LLItemBridge::performAction(model, action);
|
||||
}
|
||||
|
||||
void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
|
||||
menuentry_vec_t items;
|
||||
menuentry_vec_t disabled_items;
|
||||
if(isItemInTrash())
|
||||
{
|
||||
addTrashContextMenuOptions(items, disabled_items);
|
||||
}
|
||||
else
|
||||
{
|
||||
addOpenRightClickMenuOption(items);
|
||||
items.push_back(std::string("Properties"));
|
||||
|
||||
getClipboardEntries(true, items, disabled_items, flags);
|
||||
//TODO
|
||||
/*items.push_back(std::string("Texture Separator"));
|
||||
items.push_back(std::string("Save As"));
|
||||
if (!canSaveTexture())
|
||||
{
|
||||
disabled_items.push_back(std::string("Save As"));
|
||||
}*/
|
||||
}
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
|
||||
// +=================================================+
|
||||
// | LLSoundBridge |
|
||||
// +=================================================+
|
||||
@@ -3747,7 +3901,7 @@ LLCallingCardBridge::~LLCallingCardBridge()
|
||||
|
||||
void LLCallingCardBridge::refreshFolderViewItem()
|
||||
{
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel);
|
||||
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
|
||||
LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
|
||||
if (itemp)
|
||||
{
|
||||
@@ -4216,13 +4370,12 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio
|
||||
// See if we can bring an existing preview to the front
|
||||
if(LLPreview::show( mUUID ))
|
||||
return;
|
||||
|
||||
LLViewerInventoryItem *item = getItem();
|
||||
if( item )
|
||||
|
||||
if( getItem() )
|
||||
{
|
||||
S32 activate = 0;
|
||||
if ("playworld" == action) activate = 1;
|
||||
if ("playlocal" == action) activate = 2;
|
||||
LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
|
||||
if ("playworld" == action) activate = LLPreviewAnim::PLAY;
|
||||
if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
|
||||
|
||||
S32 left, top;
|
||||
gFloaterView->getNewFloaterPosition(&left, &top);
|
||||
@@ -4230,7 +4383,7 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio
|
||||
rect.translate( left - rect.mLeft, top - rect.mTop );
|
||||
LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
|
||||
rect,
|
||||
getPrefix() + item->getName(),
|
||||
getPrefix() + getItem()->getName(),
|
||||
mUUID,
|
||||
activate);
|
||||
// Force to be entirely onscreen.
|
||||
@@ -4260,7 +4413,7 @@ void LLAnimationBridge::openItem()
|
||||
rect,
|
||||
getPrefix() + item->getName(),
|
||||
mUUID,
|
||||
0);
|
||||
LLPreviewAnim::NONE);
|
||||
preview->setFocus(TRUE);
|
||||
// Force to be entirely onscreen.
|
||||
gFloaterView->adjustToFitScreen(preview, FALSE);
|
||||
@@ -4629,7 +4782,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
// [/RLVa:KB]
|
||||
}
|
||||
|
||||
LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject");
|
||||
LLSimpleListener* callback = mInventoryPanel.get()->getListenerByName("Inventory.AttachObject");
|
||||
|
||||
if (callback)
|
||||
{
|
||||
@@ -4638,7 +4791,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
}
|
||||
LLMenuItemCallGL *new_item = new LLMenuItemCallGL("Custom...", NULL, NULL);
|
||||
attach_menu->append(new_item);
|
||||
LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachCustom");
|
||||
LLSimpleListener* callback = mInventoryPanel.get()->getListenerByName("Inventory.AttachCustom");
|
||||
new_item->addListener(callback, "on_click", LLSD());
|
||||
}
|
||||
}
|
||||
@@ -4984,12 +5137,11 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
|
||||
items.push_back(std::string("Wearable And Object Separator"));
|
||||
|
||||
items.push_back(std::string("Wearable Wear"));
|
||||
items.push_back(std::string("Wearable Edit"));
|
||||
// [RLVa:KB] - Checked: 2011-09-16 (RLVa-1.1.4a) | Added: RLVa-1.1.4a
|
||||
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) )
|
||||
{
|
||||
disabled_items.push_back(std::string("Wearable Wear"));
|
||||
disabled_items.push_back(std::string("Wearable And Object Wear"));
|
||||
disabled_items.push_back(std::string("Wearable Edit"));
|
||||
}
|
||||
// [/RLVa:KB]
|
||||
@@ -5294,6 +5446,7 @@ void LLWearableBridge::removeFromAvatar()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// +=================================================+
|
||||
// | LLLinkItemBridge |
|
||||
// +=================================================+
|
||||
@@ -5400,6 +5553,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
std::string LLLinkFolderBridge::sPrefix("Link: ");
|
||||
LLUIImagePtr LLLinkFolderBridge::getIcon() const
|
||||
{
|
||||
//For now, all inv links share this icon. There is no 'overlay' mechanism yet.
|
||||
return LLUI::getUIImage("inv_link_folder.tga");
|
||||
}
|
||||
|
||||
|
||||
@@ -154,9 +154,8 @@ protected:
|
||||
const LLUUID& new_parent,
|
||||
BOOL restamp);
|
||||
void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch);
|
||||
|
||||
protected:
|
||||
LLInventoryPanel* mInventoryPanel;
|
||||
LLHandle<LLPanel> mInventoryPanel;
|
||||
LLFolderView* mRoot;
|
||||
LLUUID mUUID; // item id
|
||||
LLInventoryType::EType mInvType;
|
||||
@@ -165,6 +164,24 @@ protected:
|
||||
};
|
||||
|
||||
class AIFilePicker;
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInvFVBridgeBuilder
|
||||
//
|
||||
// This class intended to build Folder View Bridge via LLInvFVBridge::createBridge.
|
||||
// It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLInventoryFVBridgeBuilder
|
||||
{
|
||||
public:
|
||||
virtual ~LLInventoryFVBridgeBuilder() {}
|
||||
virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
|
||||
LLAssetType::EType actual_asset_type,
|
||||
LLInventoryType::EType inv_type,
|
||||
LLInventoryPanel* inventory,
|
||||
LLFolderView* root,
|
||||
const LLUUID& uuid,
|
||||
U32 flags = 0x00) const;
|
||||
};
|
||||
|
||||
class LLItemBridge : public LLInvFVBridge
|
||||
{
|
||||
@@ -251,9 +268,9 @@ public:
|
||||
virtual BOOL isItemCopyable() const;
|
||||
virtual BOOL isClipboardPasteable() const;
|
||||
virtual BOOL isClipboardPasteableAsLink() const;
|
||||
|
||||
virtual BOOL copyToClipboard() const;
|
||||
|
||||
static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);
|
||||
//static void createWearable(LLUUID parent_folder_id, LLWearableType::EType type);
|
||||
|
||||
LLViewerInventoryCategory* getCategory() const;
|
||||
LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
|
||||
@@ -302,13 +319,11 @@ public:
|
||||
private:
|
||||
BOOL mCallingCards;
|
||||
BOOL mWearables;
|
||||
LLHandle<LLView> mMenu;
|
||||
menuentry_vec_t mItems;
|
||||
menuentry_vec_t mDisabledItems;
|
||||
LLRootHandle<LLFolderBridge> mHandle;
|
||||
};
|
||||
|
||||
|
||||
class LLTextureBridge : public LLItemBridge
|
||||
{
|
||||
public:
|
||||
@@ -323,8 +338,8 @@ public:
|
||||
}
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual void openItem();
|
||||
//virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
//virtual void performAction(LLInventoryModel* model, std::string action);
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
virtual void performAction(LLInventoryModel* model, std::string action);
|
||||
bool canSaveTexture(void);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,32 +1,26 @@
|
||||
/**
|
||||
* @file llinventoryview.cpp
|
||||
* @brief Implementation of the inventory view and associated stuff.
|
||||
/*
|
||||
* @file llinventorypanel.cpp
|
||||
* @brief Implementation of the inventory panel and associated stuff.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -37,6 +31,7 @@
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "llappearancemgr.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llfloatercustomize.h"
|
||||
#include "llfolderview.h"
|
||||
@@ -58,12 +53,11 @@
|
||||
|
||||
static LLRegisterWidget<LLInventoryPanel> r("inventory_panel");
|
||||
|
||||
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Local function declarations, constants, enums, and typedefs
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
|
||||
const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
|
||||
const std::string LLInventoryPanel::WORNITEMS_SORT_ORDER = std::string("WornItemsSortOrder");
|
||||
const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
|
||||
static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -89,10 +83,50 @@ protected:
|
||||
|
||||
|
||||
|
||||
const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
|
||||
const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
|
||||
const std::string LLInventoryPanel::WORNITEMS_SORT_ORDER = std::string("WornItemsSortOrder");
|
||||
const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInvPanelComplObserver
|
||||
//
|
||||
// Calls specified callback when all specified items become complete.
|
||||
//
|
||||
// Usage:
|
||||
// observer = new LLInvPanelComplObserver(boost::bind(onComplete));
|
||||
// inventory->addObserver(observer);
|
||||
// observer->reset(); // (optional)
|
||||
// observer->watchItem(incomplete_item1_id);
|
||||
// observer->watchItem(incomplete_item2_id);
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLInvPanelComplObserver : public LLInventoryCompletionObserver
|
||||
{
|
||||
public:
|
||||
typedef boost::function<void()> callback_t;
|
||||
|
||||
LLInvPanelComplObserver(callback_t cb)
|
||||
: mCallback(cb)
|
||||
{
|
||||
}
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
/*virtual*/ void done();
|
||||
|
||||
/// Called when all the items are complete.
|
||||
callback_t mCallback;
|
||||
};
|
||||
|
||||
void LLInvPanelComplObserver::reset()
|
||||
{
|
||||
mIncomplete.clear();
|
||||
mComplete.clear();
|
||||
}
|
||||
|
||||
void LLInvPanelComplObserver::done()
|
||||
{
|
||||
mCallback();
|
||||
}
|
||||
|
||||
LLInventoryPanel::LLInventoryPanel(const std::string& name,
|
||||
const std::string& sort_order_setting,
|
||||
@@ -101,56 +135,66 @@ LLInventoryPanel::LLInventoryPanel(const std::string& name,
|
||||
BOOL allow_multi_select,
|
||||
LLView *parent_view) :
|
||||
LLPanel(name, rect, TRUE),
|
||||
mInventory(inventory),
|
||||
mInventoryObserver(NULL),
|
||||
mCompletionObserver(NULL),
|
||||
mFolderRoot(NULL),
|
||||
mScroller(NULL),
|
||||
mSortOrderSetting(sort_order_setting),
|
||||
mInventory(inventory),
|
||||
mAllowMultiSelect(allow_multi_select),
|
||||
mSortOrderSetting(sort_order_setting)
|
||||
mViewsInitialized(false),
|
||||
mInvFVBridgeBuilder(NULL)
|
||||
{
|
||||
mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
|
||||
|
||||
setBackgroundColor(gColors.getColor("InventoryBackgroundColor"));
|
||||
setBackgroundVisible(TRUE);
|
||||
setBackgroundOpaque(TRUE);
|
||||
}
|
||||
|
||||
BOOL LLInventoryPanel::postBuild()
|
||||
void LLInventoryPanel::buildFolderView()
|
||||
{
|
||||
init_inventory_panel_actions(this);
|
||||
|
||||
LLRect folder_rect(0,
|
||||
0,
|
||||
getRect().getWidth(),
|
||||
0);
|
||||
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(LLAssetType::AT_CATEGORY,
|
||||
LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
|
||||
LLAssetType::AT_CATEGORY,
|
||||
LLInventoryType::IT_CATEGORY,
|
||||
this,
|
||||
NULL,
|
||||
LLUUID::null);
|
||||
|
||||
mFolderRoot = new LLFolderView(getName(), NULL, folder_rect, LLUUID::null, this, new_listener);
|
||||
mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
|
||||
mFolderRoot = createFolderView(new_listener, true/*params.use_label_suffix()*/);
|
||||
}
|
||||
BOOL LLInventoryPanel::postBuild()
|
||||
{
|
||||
init_inventory_panel_actions(this);
|
||||
|
||||
// scroller
|
||||
LLRect scroller_view_rect = getRect();
|
||||
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
|
||||
mScroller = new LLScrollableContainerView(std::string("Inventory Scroller"),
|
||||
scroller_view_rect,
|
||||
mFolderRoot);
|
||||
mScroller->setFollowsAll();
|
||||
mScroller->setReserveScrollCorner(TRUE);
|
||||
addChild(mScroller);
|
||||
mFolderRoot->setScrollContainer(mScroller);
|
||||
buildFolderView();
|
||||
{
|
||||
// scroller
|
||||
LLRect scroller_view_rect = getRect();
|
||||
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
|
||||
mScroller = new LLScrollableContainerView(std::string("Inventory Scroller"),
|
||||
scroller_view_rect,
|
||||
mFolderRoot);
|
||||
mScroller->setFollowsAll();
|
||||
mScroller->setReserveScrollCorner(TRUE);
|
||||
addChild(mScroller);
|
||||
mFolderRoot->setScrollContainer(mScroller);
|
||||
}
|
||||
|
||||
// set up the callbacks from the inventory we're viewing, and then
|
||||
// build everything.
|
||||
// Set up the callbacks from the inventory we're viewing, and then build everything.
|
||||
mInventoryObserver = new LLInventoryPanelObserver(this);
|
||||
mInventory->addObserver(mInventoryObserver);
|
||||
rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
|
||||
|
||||
// bit of a hack to make sure the inventory is open.
|
||||
mFolderRoot->openFolder(std::string("My Inventory"));
|
||||
mCompletionObserver = new LLInvPanelComplObserver(boost::bind(&LLInventoryPanel::onItemsCompletion, this));
|
||||
mInventory->addObserver(mCompletionObserver);
|
||||
|
||||
// Build view of inventory if we need default full hierarchy and inventory ready,
|
||||
// otherwise wait for idle callback.
|
||||
if (mInventory->isInventoryUsable() && !mViewsInitialized)
|
||||
{
|
||||
initializeViews();
|
||||
}
|
||||
gIdleCallbacks.addFunction(onIdle, (void*)this);
|
||||
|
||||
if (mSortOrderSetting != INHERIT_SORT_ORDER)
|
||||
{
|
||||
@@ -177,9 +221,14 @@ LLInventoryPanel::~LLInventoryPanel()
|
||||
}
|
||||
}
|
||||
|
||||
gIdleCallbacks.deleteFunction(onIdle, this);
|
||||
|
||||
// LLView destructor will take care of the sub-views.
|
||||
mInventory->removeObserver(mInventoryObserver);
|
||||
mInventory->removeObserver(mCompletionObserver);
|
||||
delete mInventoryObserver;
|
||||
delete mCompletionObserver;
|
||||
|
||||
mScroller = NULL;
|
||||
}
|
||||
|
||||
@@ -301,11 +350,9 @@ U32 LLInventoryPanel::getSortOrder() const
|
||||
return mFolderRoot->getSortOrder();
|
||||
}
|
||||
|
||||
// static
|
||||
LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel()
|
||||
void LLInventoryPanel::requestSort()
|
||||
{
|
||||
LLInventoryView *view = LLInventoryView::getActiveInventory();
|
||||
return view ? view->getPanel() : NULL;
|
||||
mFolderRoot->requestSort();
|
||||
}
|
||||
|
||||
void LLInventoryPanel::setSinceLogoff(BOOL sl)
|
||||
@@ -335,8 +382,8 @@ void LLInventoryPanel::modelChanged(U32 mask)
|
||||
|
||||
bool handled = false;
|
||||
|
||||
//if (!mViewsInitialized) return;
|
||||
|
||||
if (!mViewsInitialized) return;
|
||||
|
||||
const LLInventoryModel* model = getModel();
|
||||
if (!model) return;
|
||||
|
||||
@@ -353,7 +400,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
|
||||
|
||||
// LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item
|
||||
// to folder is the fast way to get a folder without searching through folders tree.
|
||||
//LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item);
|
||||
LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item);
|
||||
|
||||
//////////////////////////////
|
||||
// LABEL Operation
|
||||
@@ -377,7 +424,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
|
||||
//////////////////////////////
|
||||
// REBUILD Operation
|
||||
// Destroy and regenerate the UI.
|
||||
/*if (mask & LLInventoryObserver::REBUILD)
|
||||
if (mask & LLInventoryObserver::REBUILD)
|
||||
{
|
||||
handled = true;
|
||||
if (model_item && view_item)
|
||||
@@ -386,7 +433,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
|
||||
}
|
||||
view_item = buildNewViews(item_id);
|
||||
view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
|
||||
}*/
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// INTERNAL Operation
|
||||
@@ -402,13 +449,13 @@ void LLInventoryPanel::modelChanged(U32 mask)
|
||||
//////////////////////////////
|
||||
// SORT Operation
|
||||
// Sort the folder.
|
||||
/*if (mask & LLInventoryObserver::SORT)
|
||||
if (mask & LLInventoryObserver::SORT)
|
||||
{
|
||||
if (view_folder)
|
||||
{
|
||||
view_folder->requestSort();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// We don't typically care which of these masks the item is actually flagged with, since the masks
|
||||
// may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into
|
||||
@@ -479,11 +526,60 @@ LLFolderView* LLInventoryPanel::getRootFolder()
|
||||
{
|
||||
return mFolderRoot;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void LLInventoryPanel::onIdle(void *userdata)
|
||||
{
|
||||
if (!gInventory.isInventoryUsable())
|
||||
return;
|
||||
|
||||
LLInventoryPanel *self = (LLInventoryPanel*)userdata;
|
||||
// Inventory just initialized, do complete build
|
||||
if (!self->mViewsInitialized)
|
||||
{
|
||||
self->initializeViews();
|
||||
}
|
||||
if (self->mViewsInitialized)
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdle, (void*)self);
|
||||
}
|
||||
}
|
||||
|
||||
const LLUUID& LLInventoryPanel::getRootFolderID() const
|
||||
{
|
||||
return mFolderRoot->getListener()->getUUID();
|
||||
}
|
||||
LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id, U32 mask)
|
||||
|
||||
void LLInventoryPanel::initializeViews()
|
||||
{
|
||||
if (!gInventory.isInventoryUsable()) return;
|
||||
|
||||
rebuildViewsFor(getRootFolderID());
|
||||
|
||||
mViewsInitialized = true;
|
||||
|
||||
openStartFolderOrMyInventory();
|
||||
|
||||
// Special case for new user login
|
||||
if (gAgent.isFirstLogin())
|
||||
{
|
||||
// Auto open the user's library
|
||||
LLFolderViewFolder* lib_folder = mFolderRoot->getFolderByID(gInventory.getLibraryRootFolderID());
|
||||
if (lib_folder)
|
||||
{
|
||||
lib_folder->setOpen(TRUE);
|
||||
}
|
||||
|
||||
// Auto close the user's my inventory folder
|
||||
LLFolderViewFolder* my_inv_folder = mFolderRoot->getFolderByID(gInventory.getRootFolderID());
|
||||
if (my_inv_folder)
|
||||
{
|
||||
my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
|
||||
{
|
||||
// Destroy the old view for this ID so we can rebuild it.
|
||||
LLFolderViewItem* old_view = mFolderRoot->getItemByID(id);
|
||||
@@ -495,6 +591,18 @@ LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id, U32 mask)
|
||||
return buildNewViews(id);
|
||||
}
|
||||
|
||||
LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix)
|
||||
{
|
||||
LLRect folder_rect(0,
|
||||
0,
|
||||
getRect().getWidth(),
|
||||
0);
|
||||
|
||||
LLFolderView* ret = new LLFolderView(getName(), NULL, folder_rect, LLUUID::null, this, bridge);
|
||||
ret->setAllowMultiSelect(mAllowMultiSelect);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
|
||||
{
|
||||
return new LLFolderViewFolder(
|
||||
@@ -544,7 +652,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
|
||||
if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
|
||||
(objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
|
||||
{
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
|
||||
LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
|
||||
objectp->getType(),
|
||||
LLInventoryType::IT_CATEGORY,
|
||||
this,
|
||||
@@ -564,7 +672,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
|
||||
{
|
||||
// Build new view for item.
|
||||
LLInventoryItem* item = (LLInventoryItem*)objectp;
|
||||
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(item->getType(),
|
||||
LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
|
||||
item->getActualType(),
|
||||
item->getInventoryType(),
|
||||
this,
|
||||
@@ -622,6 +730,23 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
|
||||
return itemp;
|
||||
}
|
||||
|
||||
// bit of a hack to make sure the inventory is open.
|
||||
void LLInventoryPanel::openStartFolderOrMyInventory()
|
||||
{
|
||||
// Find My Inventory folder and open it up by name
|
||||
for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
|
||||
{
|
||||
LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
|
||||
if (fchild
|
||||
&& fchild->getListener()
|
||||
&& fchild->getListener()->getUUID() == gInventory.getRootFolderID())
|
||||
{
|
||||
fchild->setOpen(TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LLConfirmPurgeData
|
||||
{
|
||||
LLUUID mID;
|
||||
@@ -654,6 +779,10 @@ protected:
|
||||
const LLUUID& mID;
|
||||
};
|
||||
|
||||
void LLInventoryPanel::onItemsCompletion()
|
||||
{
|
||||
if (mFolderRoot) mFolderRoot->updateMenu();
|
||||
}
|
||||
|
||||
void LLInventoryPanel::openSelected()
|
||||
{
|
||||
@@ -707,6 +836,26 @@ BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLInventoryPanel::onFocusLost()
|
||||
{
|
||||
// inventory no longer handles cut/copy/paste/delete
|
||||
if (LLEditMenuHandler::gEditMenuHandler == mFolderRoot)
|
||||
{
|
||||
LLEditMenuHandler::gEditMenuHandler = NULL;
|
||||
}
|
||||
|
||||
LLPanel::onFocusLost();
|
||||
}
|
||||
|
||||
void LLInventoryPanel::onFocusReceived()
|
||||
{
|
||||
// inventory now handles cut/copy/paste/delete
|
||||
LLEditMenuHandler::gEditMenuHandler = mFolderRoot;
|
||||
|
||||
LLPanel::onFocusReceived();
|
||||
}
|
||||
|
||||
void LLInventoryPanel::openAllFolders()
|
||||
{
|
||||
mFolderRoot->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
|
||||
@@ -757,6 +906,19 @@ void LLInventoryPanel::clearSelection()
|
||||
|
||||
void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
|
||||
{
|
||||
// Schedule updating the folder view context menu when all selected items become complete (STORM-373).
|
||||
mCompletionObserver->reset();
|
||||
for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
LLUUID id = (*it)->getListener()->getUUID();
|
||||
LLViewerInventoryItem* inv_item = mInventory->getItem(id);
|
||||
|
||||
if (inv_item && !inv_item->isFinished())
|
||||
{
|
||||
mCompletionObserver->watchItem(id);
|
||||
}
|
||||
}
|
||||
|
||||
LLFolderView* fv = getRootFolder();
|
||||
if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
|
||||
{
|
||||
@@ -808,3 +970,30 @@ void LLInventoryPanel::dumpSelectionInformation(void* user_data)
|
||||
LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
|
||||
iv->mFolderRoot->dumpSelectionInformation();
|
||||
}
|
||||
// static
|
||||
LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
|
||||
{
|
||||
LLInventoryPanel* res = NULL;
|
||||
LLInventoryView* floater_inventory = LLInventoryView::getActiveInventory();
|
||||
if (!floater_inventory)
|
||||
{
|
||||
llwarns << "Could not find My Inventory floater" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
res = floater_inventory ? floater_inventory->getActivePanel() : NULL;
|
||||
if (res)
|
||||
{
|
||||
// Make sure the floater is not minimized (STORM-438).
|
||||
if (floater_inventory && floater_inventory->isMinimized())
|
||||
{
|
||||
floater_inventory->setMinimized(FALSE);
|
||||
}
|
||||
}
|
||||
else if (auto_open)
|
||||
{
|
||||
floater_inventory->open();
|
||||
|
||||
res = floater_inventory->getActivePanel();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -47,16 +47,13 @@
|
||||
#include "lluictrlfactory.h"
|
||||
#include <set>
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInventoryView
|
||||
//
|
||||
// This is the controller class specific for handling agent
|
||||
// inventory. It deals with the buttons and views used to navigate as
|
||||
// well as controls the behavior of the overall object.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLFolderView;
|
||||
class LLFolderViewFolder;
|
||||
class LLFolderViewItem;
|
||||
class LLInventoryFilter;
|
||||
class LLInventoryModel;
|
||||
class LLInvFVBridge;
|
||||
class LLInventoryFVBridgeBuilder;
|
||||
class LLMenuBarGL;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSpinCtrl;
|
||||
@@ -65,19 +62,21 @@ class LLTextBox;
|
||||
class LLIconCtrl;
|
||||
class LLSaveFolderState;
|
||||
class LLSearchEditor;
|
||||
|
||||
class LLInvPanelComplObserver;
|
||||
|
||||
class LLInventoryPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
protected:
|
||||
LLInventoryPanel(const std::string& name,
|
||||
const std::string& sort_order_setting,
|
||||
const LLRect& rect,
|
||||
LLInventoryModel* inventory,
|
||||
BOOL allow_multi_select,
|
||||
LLView *parent_view = NULL);
|
||||
~LLInventoryPanel();
|
||||
public:
|
||||
virtual ~LLInventoryPanel();
|
||||
|
||||
public:
|
||||
LLInventoryModel* getModel() { return mInventory; }
|
||||
|
||||
BOOL postBuild();
|
||||
@@ -93,6 +92,9 @@ public:
|
||||
void* cargo_data,
|
||||
EAcceptance* accept,
|
||||
std::string& tooltip_msg);
|
||||
// LLUICtrl methods
|
||||
/*virtual*/ void onFocusLost();
|
||||
/*virtual*/ void onFocusReceived();
|
||||
|
||||
// Call this method to set the selection.
|
||||
void openAllFolders();
|
||||
@@ -130,7 +132,12 @@ public:
|
||||
|
||||
void openSelected();
|
||||
void unSelectAll();
|
||||
|
||||
static void onIdle(void* user_data);
|
||||
|
||||
// Find whichever inventory panel is active / on top.
|
||||
// "Auto_open" determines if we open an inventory panel if none are open.
|
||||
static LLInventoryPanel *getActiveInventoryPanel(BOOL auto_open = TRUE);
|
||||
|
||||
public:
|
||||
// TomY TODO: Move this elsewhere?
|
||||
@@ -144,13 +151,27 @@ public:
|
||||
U32 next_owner_perm = 0);
|
||||
|
||||
protected:
|
||||
void openStartFolderOrMyInventory(); // open the first level of inventory
|
||||
void onItemsCompletion(); // called when selected items are complete
|
||||
|
||||
LLInventoryModel* mInventory;
|
||||
LLInventoryObserver* mInventoryObserver;
|
||||
|
||||
LLInvPanelComplObserver* mCompletionObserver;
|
||||
|
||||
BOOL mAllowMultiSelect;
|
||||
LLFolderView* mFolderRoot;
|
||||
LLScrollableContainerView* mScroller;
|
||||
|
||||
/**
|
||||
* Pointer to LLInventoryFVBridgeBuilder.
|
||||
*
|
||||
* It is set in LLInventoryPanel's constructor and can be overridden in derived classes with
|
||||
* another implementation.
|
||||
* Take into account it will not be deleted by LLInventoryPanel itself.
|
||||
*/
|
||||
const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Sorting
|
||||
//--------------------------------------------------------------------
|
||||
@@ -159,24 +180,30 @@ public:
|
||||
static const std::string RECENTITEMS_SORT_ORDER;
|
||||
static const std::string WORNITEMS_SORT_ORDER;
|
||||
static const std::string INHERIT_SORT_ORDER;
|
||||
|
||||
|
||||
void setSortOrder(U32 order);
|
||||
U32 getSortOrder() const;
|
||||
void requestSort();
|
||||
|
||||
static LLInventoryPanel *getActiveInventoryPanel();
|
||||
private:
|
||||
const std::string mSortOrderSetting;
|
||||
LLUUID mSelectThisID; // if non null, select this item
|
||||
|
||||
public:
|
||||
BOOL getIsViewsInitialized() const { return mViewsInitialized; }
|
||||
const LLUUID& getRootFolderID() const;
|
||||
protected:
|
||||
// Given the id and the parent, build all of the folder views.
|
||||
LLFolderViewItem* rebuildViewsFor(const LLUUID& id, U32 mask);
|
||||
// Builds the UI. Call this once the inventory is usable.
|
||||
void initializeViews();
|
||||
LLFolderViewItem* rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
|
||||
|
||||
virtual void buildFolderView();
|
||||
LLFolderViewItem* buildNewViews(const LLUUID& id);
|
||||
|
||||
LLFolderViewItem* buildNewViews(const LLUUID& id);
|
||||
virtual LLFolderView* createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix);
|
||||
virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge);
|
||||
virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge);
|
||||
BOOL mViewsInitialized; // Views have been generated
|
||||
};
|
||||
|
||||
class LLInventoryView;
|
||||
|
||||
@@ -105,7 +105,7 @@ void LLLocalInventory::open(LLUUID item_id)
|
||||
rect,
|
||||
"",
|
||||
item_id,
|
||||
0);
|
||||
LLPreviewAnim::NONE);
|
||||
floaterp->setFocus(TRUE);
|
||||
gFloaterView->adjustToFitScreen(floaterp, FALSE);
|
||||
}
|
||||
|
||||
@@ -1434,7 +1434,7 @@ void LLTaskAnimationBridge::openItem()
|
||||
rect,
|
||||
getName(),
|
||||
mUUID,
|
||||
0,
|
||||
LLPreviewAnim::NONE,
|
||||
mPanel->getTaskUUID());
|
||||
preview->setFocus(TRUE); // take focus if you're looking at one of these
|
||||
|
||||
|
||||
@@ -51,55 +51,18 @@
|
||||
|
||||
extern LLAgent gAgent;
|
||||
|
||||
LLPreviewAnim::LLPreviewAnim(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const S32& activate, const LLUUID& object_uuid ) :
|
||||
LLPreviewAnim::LLPreviewAnim(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const e_activation_type& _activate, const LLUUID& object_uuid ) :
|
||||
LLPreview( name, rect, title, item_uuid, object_uuid)
|
||||
{
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_animation.xml");
|
||||
|
||||
childSetAction("Anim play btn",playAnim,this);
|
||||
childSetAction("Anim audition btn",auditionAnim,this);
|
||||
|
||||
const LLInventoryItem* item = getItem();
|
||||
|
||||
childSetCommitCallback("desc", LLPreview::onText, this);
|
||||
childSetText("desc", item->getDescription());
|
||||
childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
|
||||
|
||||
mIsCopyable = false;
|
||||
setTitle(title);
|
||||
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_animation.xml");
|
||||
if (!getHost())
|
||||
{
|
||||
LLRect curRect = getRect();
|
||||
translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
|
||||
}
|
||||
|
||||
mIsCopyable = false;
|
||||
// preload the animation
|
||||
if(item)
|
||||
{
|
||||
gAgentAvatarp->createMotion(item->getAssetUUID());
|
||||
|
||||
const LLPermissions& perm = item->getPermissions();
|
||||
mIsCopyable = (perm.getCreator() == gAgent.getID());
|
||||
}
|
||||
|
||||
switch ( activate )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
playAnim( (void *) this );
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
auditionAnim( (void *) this );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
activate(_activate);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -115,6 +78,50 @@ void LLPreviewAnim::endAnimCallback( void *userdata )
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLPreviewAnim::postBuild()
|
||||
{
|
||||
const LLInventoryItem* item = getItem();
|
||||
|
||||
// preload the animation
|
||||
if(item)
|
||||
{
|
||||
gAgentAvatarp->createMotion(item->getAssetUUID());
|
||||
childSetText("desc", item->getDescription());
|
||||
|
||||
const LLPermissions& perm = item->getPermissions();
|
||||
mIsCopyable = (perm.getCreator() == gAgent.getID());
|
||||
}
|
||||
|
||||
childSetAction("Anim play btn",playAnim,this);
|
||||
childSetAction("Anim audition btn",auditionAnim,this);
|
||||
|
||||
childSetCommitCallback("desc", LLPreview::onText, this);
|
||||
childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
|
||||
|
||||
return LLPreview::postBuild();
|
||||
}
|
||||
void LLPreviewAnim::activate(e_activation_type type)
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case PLAY:
|
||||
{
|
||||
playAnim( (void *) this );
|
||||
break;
|
||||
}
|
||||
case AUDITION:
|
||||
{
|
||||
auditionAnim( (void *) this );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPreviewAnim::playAnim( void *userdata )
|
||||
{
|
||||
@@ -135,10 +142,7 @@ void LLPreviewAnim::playAnim( void *userdata )
|
||||
{
|
||||
self->mPauseRequest = NULL;
|
||||
gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START);
|
||||
|
||||
LLVOAvatar* avatar = gAgentAvatarp;
|
||||
LLMotion* motion = avatar->findMotion(itemID);
|
||||
|
||||
LLMotion* motion = gAgentAvatarp->findMotion(itemID);
|
||||
if (motion)
|
||||
{
|
||||
motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle())));
|
||||
@@ -172,9 +176,7 @@ void LLPreviewAnim::auditionAnim( void *userdata )
|
||||
{
|
||||
self->mPauseRequest = NULL;
|
||||
gAgentAvatarp->startMotion(item->getAssetUUID());
|
||||
|
||||
LLVOAvatar* avatar = gAgentAvatarp;
|
||||
LLMotion* motion = avatar->findMotion(itemID);
|
||||
LLMotion* motion = gAgentAvatarp->findMotion(itemID);
|
||||
|
||||
if (motion)
|
||||
{
|
||||
@@ -434,9 +436,7 @@ void LLPreviewAnim::onClose(bool app_quitting)
|
||||
{
|
||||
gAgentAvatarp->stopMotion(item->getAssetUUID());
|
||||
gAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP);
|
||||
|
||||
LLVOAvatar* avatar = gAgentAvatarp;
|
||||
LLMotion* motion = avatar->findMotion(item->getAssetUUID());
|
||||
LLMotion* motion = gAgentAvatarp->findMotion(item->getAssetUUID());
|
||||
|
||||
if (motion)
|
||||
{
|
||||
|
||||
@@ -41,9 +41,10 @@ class AIFilePicker;
|
||||
class LLPreviewAnim : public LLPreview
|
||||
{
|
||||
public:
|
||||
enum e_activation_type { NONE = 0, PLAY = 1, AUDITION = 2 };
|
||||
LLPreviewAnim(const std::string& name, const LLRect& rect, const std::string& title,
|
||||
const LLUUID& item_uuid,
|
||||
const S32& activate,
|
||||
const e_activation_type& activate,
|
||||
const LLUUID& object_uuid = LLUUID::null);
|
||||
|
||||
static void playAnim( void* userdata );
|
||||
@@ -65,6 +66,8 @@ public:
|
||||
static void copyAnimID(void* userdata);
|
||||
// </edit>
|
||||
static void endAnimCallback( void *userdata );
|
||||
/*virtual*/ BOOL postBuild();
|
||||
void activate(e_activation_type type);
|
||||
|
||||
protected:
|
||||
virtual void onClose(bool app_quitting);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<menu bottom="100" color="MenuDefaultBgColor" drop_shadow="true" height="101" left="100"
|
||||
mouse_opaque="false" name="Popup" opaque="true" width="128">
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Buy" left="0" mouse_opaque="true"
|
||||
@@ -224,10 +224,11 @@
|
||||
mouse_opaque="true" name="Replace Outfit" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="replaceoutfit" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Take Off Items" left="0"
|
||||
mouse_opaque="true" name="Take Off Items" width="128">
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Remove From Outfit" left="0"
|
||||
mouse_opaque="true" name="Remove From Outfit" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="removefromoutfit" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator name="Outfit Separator"></menu_item_separator>
|
||||
<menu_item_separator name="Calling Card Separator" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Start Conference Chat" left="0"
|
||||
mouse_opaque="true" name="Conference Chat Folder" width="128">
|
||||
@@ -276,11 +277,11 @@
|
||||
</menu_item_call>
|
||||
<menu_item_separator name="Wearable And Object Separator" />
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Wear" left="0" mouse_opaque="true"
|
||||
name="Wearable And Object Wear" width="128">
|
||||
name="Object Wear" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="attach" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Add to Worn" left="0" mouse_opaque="true"
|
||||
name="Wearable Add" width="128">
|
||||
name="Object Add" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="wear_add" />
|
||||
</menu_item_call>
|
||||
<menu bottom_delta="-18" height="18" label="Attach To" left="0" mouse_opaque="true"
|
||||
@@ -297,7 +298,7 @@
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="edit" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Wear" left="0" mouse_opaque="true"
|
||||
name="Wearable Wear" width="128">
|
||||
name="Wearable And Object Wear" width="128">
|
||||
<on_click filter="" function="Inventory.DoToSelected" userdata="wear" />
|
||||
</menu_item_call>
|
||||
<menu_item_call bottom_delta="-18" height="18" label="Take Off" left="0" mouse_opaque="true"
|
||||
|
||||
Reference in New Issue
Block a user