diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index dfc84fb4ac..bcd2d0b0c4 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -216,7 +216,8 @@ LLButton::LLButton(const LLButton::Params& p) } // Hack to make sure there is space for at least one character - if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) + if (getRect().mRight >= 0 && getRect().getWidth() > 0 && + getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) { // Use old defaults mLeftHPad = llbutton_orig_h_pad; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index bd40074d2a..34a54204d1 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -591,6 +591,15 @@ void LLLayoutStack::updateLayout() mNeedsLayout = continue_animating; } // end LLLayoutStack::updateLayout +void LLLayoutStack::setPanelSpacing(S32 val) +{ + if (mPanelSpacing != val) + { + mPanelSpacing = val; + mNeedsLayout = true; + } +} + LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const { if (!panelp) return NULL; diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 8e0fc67cb0..f56cf216eb 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -96,6 +96,7 @@ public: void updateLayout(); S32 getPanelSpacing() const { return mPanelSpacing; } + void setPanelSpacing(S32 val); static void updateClass(); diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index c4cb739f0a..ad32f7186c 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -105,8 +105,8 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) mBorder = LLUICtrlFactory::create (params); LLView::addChild( mBorder ); - mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mInnerRect.stretch( -getBorderWidth() ); + mInnerRect = getLocalRect(); + mInnerRect.stretch( -getBorderWidth() ); LLRect vertical_scroll_rect = mInnerRect; vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - scrollbar_size; @@ -124,9 +124,9 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) mScrollbar[VERTICAL] = LLUICtrlFactory::create (sbparams); LLView::addChild( mScrollbar[VERTICAL] ); - LLRect horizontal_scroll_rect = mInnerRect; - horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size; - horizontal_scroll_rect.mLeft += 3; + LLRect horizontal_scroll_rect; + horizontal_scroll_rect.mTop = scrollbar_size; + horizontal_scroll_rect.mRight = mInnerRect.getWidth(); sbparams.name("scrollable horizontal"); sbparams.rect(horizontal_scroll_rect); sbparams.orientation(LLScrollbar::HORIZONTAL); @@ -135,7 +135,7 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p) sbparams.page_size(mInnerRect.getWidth()); sbparams.step_size(VERTICAL_MULTIPLE); sbparams.visible(false); - sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT); + sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); sbparams.change_callback(p.scroll_callback); mScrollbar[HORIZONTAL] = LLUICtrlFactory::create (sbparams); LLView::addChild( mScrollbar[HORIZONTAL] ); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index ea965c83ee..a3d722c69b 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1132,7 +1132,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } else { - //Scip tab button space if they are invisible(EXT - 576) + // Skip tab button space if tabs are invisible (EXT-576) tab_panel_top = getRect().getHeight(); tab_panel_bottom = LLPANEL_BORDER_WIDTH; } @@ -1147,9 +1147,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } else { - tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH, + tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3, tab_panel_top, - getRect().getWidth()-LLPANEL_BORDER_WIDTH, + getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2, tab_panel_bottom ); } child->setFollowsAll(); @@ -1241,7 +1241,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) p.follows.flags = p.follows.flags() | FOLLOWS_TOP; } else - { + { p.name("htab_"+std::string(child->getName())); p.visible(false); p.image_unselected(tab_img); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b2f502ae40..bdadf07fe2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -108,24 +108,11 @@ void copy_slurl_to_clipboard_callback_inv(const std::string& slurl); -typedef std::pair two_uuids_t; -typedef std::list two_uuids_list_t; - const F32 SOUND_GAIN = 1.0f; -struct LLMoveInv -{ - LLUUID mObjectID; - LLUUID mCategoryID; - two_uuids_list_t mMoveList; - void (*mCallback)(S32, void*); - void* mUserData; -}; - using namespace LLOldEvents; // Function declarations -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, boost::shared_ptr); bool confirm_attachment_rez(const LLSD& notification, const LLSD& response); void teleport_via_landmark(const LLUUID& asset_id); // Function left unused from FIRE-7219 @@ -4941,37 +4928,33 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& // Patch: ReplaceWornItemsOnly items.push_back(std::string("Wear Items")); // + if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID)) + { + disabled_items.push_back(std::string("Add To Outfit")); + } } items.push_back(std::string("Replace Outfit")); + //if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) +// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.4) + if ( ((is_outfit) && (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))) || + ((!is_outfit) && (gAgentWearables.isCOFChangeInProgress())) ) +// [/SL:KB] + { + disabled_items.push_back(std::string("Replace Outfit")); + } } if (is_agent_inventory) { items.push_back(std::string("Folder Wearables Separator")); + // Note: If user tries to unwear "My Inventory", it's going to deactivate everything including gestures + // Might be safer to disable this for "My Inventory" items.push_back(std::string("Remove From Outfit")); - if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) - { - disabled_items.push_back(std::string("Remove From Outfit")); - } - } - //if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) -// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.4) - if ( ((is_outfit) && (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))) || - ((!is_outfit) && (gAgentWearables.isCOFChangeInProgress())) ) -// [/SL:KB] - { - disabled_items.push_back(std::string("Replace Outfit")); - } -// [RLVa:KB] - Checked: RLVa-2.0.3 - // Block "Replace Current Outfit" if the user can't wear the new folder - if ( (RlvActions::isRlvEnabled()) && (RlvFolderLocks::instance().isLockedFolder(mUUID, RLV_LOCK_ADD)) ) - { - disabled_items.push_back(std::string("Replace Outfit")); - } -// [/RLVa:KB] - if (!LLAppearanceMgr::instance().getCanAddToCOF(mUUID)) - { - disabled_items.push_back(std::string("Add To Outfit")); + if (type != LLFolderType::FT_ROOT_INVENTORY // Unless COF is empty, whih shouldn't be, warrantied to have worn items + && !LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) // expensive from root! + { + disabled_items.push_back(std::string("Remove From Outfit")); + } } items.push_back(std::string("Outfit Separator")); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index cc0e58b892..0ec82c13d3 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -48,7 +48,8 @@ class LLViewerJointAttachment; class LLFolderView; typedef std::vector menuentry_vec_t; - +typedef std::pair two_uuids_t; +typedef std::list two_uuids_list_t; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInvFVBridge // @@ -835,4 +836,16 @@ public: bool canWearSelected(const uuid_vec_t& item_ids) const; }; +struct LLMoveInv +{ + LLUUID mObjectID; + LLUUID mCategoryID; + two_uuids_list_t mMoveList; + void (*mCallback)(S32, void*); + void* mUserData; +}; + +void warn_move_inventory(LLViewerObject* object, boost::shared_ptr move_inv); +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, boost::shared_ptr); + #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 6b59437cb6..25a009c609 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -63,6 +63,25 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL d BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm); void dropToMyOutfits(LLInventoryCategory* inv_cat); +class LLGalleryPanel: public LLPanel +{ +public: + + BOOL canFocusChildren() const override + { + // Tell Tab to not focus children + return FALSE; + } + +protected: + + LLGalleryPanel(const LLPanel::Params& params): LLPanel(params) + { + }; + + friend class LLUICtrlFactory; +}; + //----------------------------- // LLInventoryGallery //----------------------------- @@ -87,7 +106,8 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false), mRootDirty(false), mNeedsArrange(false), - mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) + mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), + mSortOrder(LLInventoryFilter::SO_DATE) { updateGalleryWidth(); mFilter = new LLInventoryFilter(); @@ -337,9 +357,16 @@ void LLInventoryGallery::draw() void LLInventoryGallery::onVisibilityChange(BOOL new_visibility) { - if (new_visibility && mRootDirty) + if (new_visibility) { - updateRootFolder(); + if (mRootDirty) + { + updateRootFolder(); + } + else if (mNeedsArrange) + { + gIdleCallbacks.addFunction(onIdle, (void*)this); + } } LLPanel::onVisibilityChange(new_visibility); } @@ -362,19 +389,35 @@ bool LLInventoryGallery::updateRowsIfNeeded() return false; } -bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) +bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2, bool sort_by_date, bool sort_folders_by_name) { if (item1->getSortGroup() != item2->getSortGroup()) { return (item1->getSortGroup() < item2->getSortGroup()); } - if(((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + + if(sort_folders_by_name && (item1->getSortGroup() != LLInventoryGalleryItem::SG_ITEM)) { std::string name1 = item1->getItemName(); std::string name2 = item2->getItemName(); return (LLStringUtil::compareDict(name1, name2) < 0); } + + if(((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + { + if(sort_by_date) + { + return item1->getCreationDate() > item2->getCreationDate(); + } + else + { + std::string name1 = item1->getItemName(); + std::string name2 = item2->getItemName(); + + return (LLStringUtil::compareDict(name1, name2) < 0); + } + } else { return item2->isDefaultImage(); @@ -396,7 +439,13 @@ void LLInventoryGallery::reArrangeRows(S32 row_diff) mItemsInRow+= row_diff; updateGalleryWidth(); - std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); + + bool sort_by_date = (mSortOrder & LLInventoryFilter::SO_DATE); + bool sort_folders_by_name = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); + std::sort(buf_items.begin(), buf_items.end(), [sort_by_date, sort_folders_by_name](LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) + { + return compareGalleryItem(item1, item2, sort_by_date, sort_folders_by_name); + }); for (std::vector::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) { @@ -566,7 +615,7 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) mItemPanels.pop_back(); } -LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link, bool is_worn) +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn) { LLInventoryGalleryItem::Params giparams; giparams.visible = true; @@ -582,6 +631,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); gitem->setDescription(get_searchable_description(&gInventory, item_id)); gitem->setAssetIDStr(get_searchable_UUID(&gInventory, item_id)); + gitem->setCreationDate(creation_date); return gitem; } @@ -591,7 +641,7 @@ void LLInventoryGallery::buildGalleryPanel(int row_count) params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); params.visible = true; params.use_bounding_rect = false; - mGalleryPanel = LLUICtrlFactory::create(params); + mGalleryPanel = LLUICtrlFactory::create(params); reshapeGalleryPanel(row_count); } @@ -616,6 +666,8 @@ LLPanel* LLInventoryGallery::buildItemPanel(int left) lpparams.visible = true; lpparams.rect(LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top)); lpparams.use_bounding_rect = false; + lpparams.focus_root = false; + //lpparams.tab_stop = false; lpanel = LLUICtrlFactory::create(lpparams); } else @@ -638,6 +690,8 @@ LLPanel* LLInventoryGallery::buildRowPanel(int left, int bottom) sparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); sparams.use_bounding_rect = false; sparams.visible = true; + sparams.focus_root = false; + //sparams.tab_stop = false; stack = LLUICtrlFactory::create(sparams); } else @@ -751,9 +805,10 @@ void LLInventoryGallery::onIdle(void* userdata) return; } + bool visible = self->getVisible(); // In visible chain? const F64 MAX_TIME_VISIBLE = 0.020f; const F64 MAX_TIME_HIDDEN = 0.001f; // take it slow - const F64 max_time = self->getVisible() ? MAX_TIME_VISIBLE : MAX_TIME_HIDDEN; + const F64 max_time = visible ? MAX_TIME_VISIBLE : MAX_TIME_HIDDEN; F64 curent_time = LLTimer::getTotalSeconds(); const F64 end_time = curent_time + max_time; @@ -766,7 +821,7 @@ void LLInventoryGallery::onIdle(void* userdata) curent_time = LLTimer::getTotalSeconds(); } - if (self->mNeedsArrange) + if (self->mNeedsArrange && visible) { self->mNeedsArrange = false; self->reArrangeRows(); @@ -849,7 +904,8 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id) } bool res = false; - LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); + + LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); @@ -1174,6 +1230,35 @@ void LLInventoryGallery::moveRight() } } +void LLInventoryGallery::onFocusLost() +{ + // inventory no longer handles cut/copy/paste/delete + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } + + LLPanel::onFocusLost(); + + if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(false); + } +} + +void LLInventoryGallery::onFocusReceived() +{ + // inventory now handles cut/copy/paste/delete + gEditMenuHandler = this; + + LLPanel::onFocusReceived(); + + if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(true); + } +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) @@ -1568,6 +1653,14 @@ void LLInventoryGallery::claimEditHandler() gEditMenuHandler = this; } +void LLInventoryGallery::resetEditHandler() +{ + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } +} + bool LLInventoryGallery::isItemCopyable(const LLUUID & item_id) { const LLInventoryCategory* cat = gInventory.getCategory(item_id); @@ -2004,6 +2097,17 @@ void LLInventoryGallery::handleModifiedFilter() } } +void LLInventoryGallery::setSortOrder(U32 order, bool update) +{ + bool dirty = (mSortOrder != order); + + mSortOrder = order; + if(update && dirty) + { + mNeedsArrange = true; + gIdleCallbacks.addFunction(onIdle, (void*)this); + } +} //----------------------------- // LLInventoryGalleryItem //----------------------------- @@ -2272,6 +2376,24 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) return handled; } +void LLInventoryGalleryItem::onFocusLost() +{ + // inventory no longer handles cut/copy/paste/delete + mGallery->resetEditHandler(); + setSelected(false); + + LLPanel::onFocusLost(); +} + +void LLInventoryGalleryItem::onFocusReceived() +{ + // inventory now handles cut/copy/paste/delete + mGallery->claimEditHandler(); + setSelected(true); + + LLPanel::onFocusReceived(); +} + void LLInventoryGalleryItem::setWorn(bool value) { mWorn = value; @@ -2676,6 +2798,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, // coming from a task. Need to figure out if the person can // move/copy this item. LLPermissions perm(inv_item->getPermissions()); + bool is_move = false; if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) @@ -2687,6 +2810,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, // If the object cannot be copied, but the object the // inventory is owned by the agent, then the item can be // moved from the task to agent inventory. + is_move = true; accept = TRUE; } @@ -2711,9 +2835,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, if (accept && drop) { - //todo: dnd from SOURCE_WORLD - - /*boost::shared_ptr move_inv (new LLMoveInv()); + boost::shared_ptr move_inv (new LLMoveInv()); move_inv->mObjectID = inv_item->getParentUUID(); std::pair item_pair(folder_id, inv_item->getUUID()); move_inv->mMoveList.push_back(item_pair); @@ -2731,7 +2853,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, LLNotification::Params params("MoveInventoryFromObject"); params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); LLNotifications::instance().forceResponse(params, 0); - }*/ + } } } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) @@ -3147,9 +3269,7 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, } else { - //todo: dnd from SOURCE_WORLD - accept = FALSE; - //accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter); + accept = move_inv_category_world_to_agent(cat_id, dest_id, drop); } } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index cb95f61255..5f9c191fc5 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -86,6 +86,9 @@ public: void moveLeft(); void moveRight(); + void onFocusLost() override; + void onFocusReceived() override; + void setFilterSubString(const std::string& string); std::string getFilterSubString() { return mFilterSubString; } LLInventoryFilter& getFilter() const { return *mFilter; } @@ -157,7 +160,11 @@ public: bool canDeleteSelection(); void pasteAsLink(); + void setSortOrder(U32 order, bool update = false); + U32 getSortOrder() { return mSortOrder; }; + void claimEditHandler(); + void resetEditHandler(); static bool isItemCopyable(const LLUUID & item_id); BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, EDragAndDropType cargo_type, @@ -202,7 +209,7 @@ private: bool updateRowsIfNeeded(); void updateGalleryWidth(); - LLInventoryGalleryItem* buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link, bool is_worn); + LLInventoryGalleryItem* buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn); void buildGalleryPanel(int row_count); void reshapeGalleryPanel(int row_count); @@ -242,6 +249,7 @@ private: LLInventoryGalleryContextMenu* mRootGalleryMenu; std::string mFilterSubString; LLInventoryFilter* mFilter; + U32 mSortOrder; typedef std::map gallery_item_map_t; gallery_item_map_t mItemMap; @@ -286,6 +294,9 @@ public: std::string& tooltip_msg); BOOL handleKeyHere(KEY key, MASK mask); + void onFocusLost(); + void onFocusReceived(); + LLFontGL* getTextFont(); void setItemName(std::string name); @@ -300,6 +311,8 @@ public: std::string getDescription() { return mDesc;} void setCreatorName(std::string name) {mCreatorName = name;} std::string getCreatorName() { return mCreatorName;} + void setCreationDate(time_t date) {mCreationDate = date;} + time_t getCreationDate() { return mCreationDate;} std::string getItemName() {return mItemName;} std::string getItemNameSuffix() {return mPermSuffix + mWornSuffix;} @@ -332,6 +345,7 @@ private: std::string mAssetIDStr; std::string mDesc; std::string mCreatorName; + time_t mCreationDate; EInventorySortGroup mSortGroup; LLAssetType::EType mType; diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index e30883d564..bca10b9c0e 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -33,12 +33,16 @@ #include "llavataractions.h" #include "llclipboard.h" #include "llfloaterreg.h" +#include "llfloatersidepanelcontainer.h" +#include "llfloaterworldmap.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" +#include "lllandmarkactions.h" #include "llmarketplacefunctions.h" #include "llmenugl.h" #include "llnotificationsutil.h" +#include "llpreviewtexture.h" #include "lltrans.h" #include "llviewerfoldertype.h" #include "llviewerwindow.h" @@ -217,6 +221,64 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { LLFloaterReg::showInstance("linkreplace", LLSD(selected_id)); } + else if ("copy_slurl" == action) + { + boost::function copy_slurl_cb = [](LLLandmark* landmark) + { + LLVector3d global_pos; + landmark->getGlobalPos(global_pos); + boost::function copy_slurl_to_clipboard_cb = [](const std::string& slurl) + { + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); + LLSD args; + args["SLURL"] = slurl; + LLNotificationsUtil::add("CopySLURL", args); + }; + LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true); + }; + LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, copy_slurl_cb); + if (landmark) + { + copy_slurl_cb(landmark); + } + } + else if ("about" == action) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = selected_id; + LLFloaterSidePanelContainer::showPanel("places", key); + } + else if ("show_on_map" == action) + { + boost::function show_on_map_cb = [](LLLandmark* landmark) + { + LLVector3d landmark_global_pos; + if (landmark->getGlobalPos(landmark_global_pos)) + { + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if (!landmark_global_pos.isExactlyZero() && worldmap_instance) + { + worldmap_instance->trackLocation(landmark_global_pos); + LLFloaterReg::showInstance("world_map", "center"); + } + } + }; + LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, show_on_map_cb); + if(landmark) + { + show_on_map_cb(landmark); + } + } + else if ("save_as" == action) + { + LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance("preview_texture", selected_id); + if (preview_texture) + { + preview_texture->openToSave(); + preview_texture->saveAs(); + } + } } void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) @@ -357,6 +419,13 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { items.push_back(std::string("Replace Links")); } + if (obj->getType() == LLAssetType::AT_LANDMARK) + { + items.push_back(std::string("Landmark Separator")); + items.push_back(std::string("url_copy")); + items.push_back(std::string("About Landmark")); + items.push_back(std::string("show_on_map")); + } } if(is_trash) @@ -561,6 +630,15 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } } } + if(obj->getType() == LLAssetType::AT_TEXTURE) + { + items.push_back(std::string("Save As")); + bool can_copy = selected_item && selected_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + if (!can_copy) + { + disabled_items.push_back(std::string("Save As")); + } + } if (is_link) { items.push_back(std::string("Find Original")); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index d36ad02b3c..21f64db8b7 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -361,6 +361,8 @@ void LLInventoryModelBackgroundFetch::scheduleFolderFetch(const LLUUID& cat_id, { if (mFetchFolderQueue.empty() || mFetchFolderQueue.front().mUUID != cat_id) { + mBackgroundFetchActive = true; + // Specific folder requests go to front of queue. mFetchFolderQueue.push_front(FetchQueueInfo(cat_id, forced ? FT_FORCED : FT_DEFAULT)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 92c9cb0038..4e84c7c796 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -323,11 +323,6 @@ void LLInventoryPanel::initFolderRoot() // Scroller LLRect scroller_view_rect = getRect(); scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - // Pull this magic number here so inventory scroll panel - // doesn't get cut off on the left side! - scroller_view_rect.mLeft += 2; - // - scroller_view_rect.mTop -= 3; LLScrollContainer::Params scroller_params(mParams.scroll()); scroller_params.rect(scroller_view_rect); mScroller = LLUICtrlFactory::create(scroller_params); @@ -1314,6 +1309,7 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id, const S32 starting_item_count = mItemMap.size(); LLFolderViewFolder *parentp = dynamic_cast(folder_view_item); + bool done = true; if(categories) { @@ -1351,6 +1347,7 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id, if (mBuildViewsEndTime < curent_time) { mBuildViewsQueue.push_back(id); + done = false; break; } } @@ -1386,13 +1383,14 @@ LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id, if (mBuildViewsEndTime < curent_time) { mBuildViewsQueue.push_back(id); + done = false; break; } } } } - if (!mBuildChildrenViews) + if (!mBuildChildrenViews && done) { // flat list is done initializing folder folder_view_item->setChildrenInited(true); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 045f273523..f4c2fe10bd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -377,6 +377,7 @@ BOOL LLPanelMainInventory::postBuild() mCombinationViewPanel = getChild("combination_view_inventory"); mCombinationGalleryLayoutPanel = getChild("comb_gallery_layout"); mCombinationListLayoutPanel = getChild("comb_inventory_layout"); + mCombinationLayoutStack = getChild("combination_view_stack"); mCombinationInventoryPanel = getChild("comb_single_folder_inv"); LLInventoryFilter& comb_inv_filter = mCombinationInventoryPanel->getFilter(); @@ -386,6 +387,7 @@ BOOL LLPanelMainInventory::postBuild() mListViewRootUpdatedConnection = mCombinationInventoryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, false)); mCombinationGalleryPanel = getChild("comb_gallery_view_inv"); + mCombinationGalleryPanel->setSortOrder(mCombinationInventoryPanel->getSortOrder()); LLInventoryFilter& comb_gallery_filter = mCombinationGalleryPanel->getFilter(); comb_gallery_filter.setFilterThumbnails(LLInventoryFilter::FILTER_ONLY_THUMBNAILS); comb_gallery_filter.markDefault(); @@ -745,6 +747,59 @@ void LLPanelMainInventory::findLinks(const LLUUID& item_id, const std::string& i mFilterEditor->setFocus(TRUE); } +void LLPanelMainInventory::setSortBy(const LLSD& userdata) +{ + U32 sort_order_mask = getActivePanel()->getSortOrder(); + std::string sort_type = userdata.asString(); + if (sort_type == "name") + { + sort_order_mask &= ~LLInventoryFilter::SO_DATE; + } + else if (sort_type == "date") + { + sort_order_mask |= LLInventoryFilter::SO_DATE; + } + else if (sort_type == "foldersalwaysbyname") + { + if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME ) + { + sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; + } + else + { + sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME; + } + } + else if (sort_type == "systemfolderstotop") + { + if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) + { + sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + } + else + { + sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + } + } + if(mSingleFolderMode && !isListViewMode()) + { + mCombinationGalleryPanel->setSortOrder(sort_order_mask, true); + } + + getActivePanel()->setSortOrder(sort_order_mask); + // Recent items panel should save sort order + //if (isRecentItemsPanelSelected()) + //{ + // gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask); + //} + //else + //{ + // gSavedSettings.setU32("InventorySortOrder", sort_order_mask); + //} + gSavedSettings.setU32(getActivePanel()->mSortOrderSetting, sort_order_mask); + // +} + void LLPanelMainInventory::onSelectSearchType() { std::string new_type = mSearchTypeCombo->getValue(); @@ -825,56 +880,6 @@ void LLPanelMainInventory::updateSearchTypeCombo() } } -// Sort By menu handlers -void LLPanelMainInventory::setSortBy(const LLSD& userdata) -{ - U32 sort_order_mask = getActivePanel()->getSortOrder(); - std::string sort_type = userdata.asString(); - if (sort_type == "name") - { - sort_order_mask &= ~LLInventoryFilter::SO_DATE; - } - else if (sort_type == "date") - { - sort_order_mask |= LLInventoryFilter::SO_DATE; - } - else if (sort_type == "foldersalwaysbyname") - { - if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME ) - { - sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; - } - else - { - sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME; - } - } - else if (sort_type == "systemfolderstotop") - { - if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) - { - sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } - else - { - sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } - } - - getActivePanel()->setSortOrder(sort_order_mask); - // Recent items panel should save sort order - //if (isRecentItemsPanelSelected()) - //{ - // gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask); - //} - //else - //{ - // gSavedSettings.setU32("InventorySortOrder", sort_order_mask); - //} - gSavedSettings.setU32(getActivePanel()->mSortOrderSetting, sort_order_mask); - // -} - BOOL LLPanelMainInventory::isSortByChecked(const LLSD& userdata) { U32 sort_order_mask = getActivePanel()->getSortOrder(); @@ -2656,7 +2661,7 @@ bool LLPanelMainInventory::isActionVisible(const LLSD& userdata) BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata) { - U32 sort_order_mask = getActivePanel()->getSortOrder(); + U32 sort_order_mask = (mSingleFolderMode && isGalleryViewMode()) ? mCombinationGalleryPanel->getSortOrder() : getActivePanel()->getSortOrder(); const std::string command_name = userdata.asString(); if (command_name == "sort_by_name") { @@ -3069,6 +3074,7 @@ void LLPanelMainInventory::updatePanelVisibility() comb_gallery_filter.setFilterThumbnails(LLInventoryFilter::FILTER_INCLUDE_THUMBNAILS); comb_gallery_filter.markDefault(); + mCombinationLayoutStack->setPanelSpacing(0); mCombinationGalleryLayoutPanel->setVisible(mSingleFolderMode && isGalleryViewMode()); mCombinationGalleryPanel->setVisible(mSingleFolderMode && isGalleryViewMode()); // to prevent or process updates mCombinationListLayoutPanel->setVisible(mSingleFolderMode && isListViewMode()); @@ -3088,6 +3094,10 @@ void LLPanelMainInventory::updateCombinationVisibility() { bool is_gallery_empty = !mCombinationGalleryPanel->hasVisibleItems(); bool show_inv_pane = mCombinationInventoryPanel->hasVisibleItems() || is_gallery_empty || mForceShowInvLayout; + + const S32 DRAG_HANDLE_PADDING = 12; // for drag handle to not overlap gallery when both inventories are visible + mCombinationLayoutStack->setPanelSpacing(show_inv_pane ? DRAG_HANDLE_PADDING : 0); + mCombinationGalleryLayoutPanel->setVisible(!is_gallery_empty); mCombinationListLayoutPanel->setVisible(show_inv_pane); mCombinationInventoryPanel->getRootFolder()->setForceArrange(!show_inv_pane); @@ -3203,20 +3213,24 @@ void LLPanelMainInventory::setViewMode(EViewModeType mode) { std::list forward_history; std::list backward_history; + U32 sort_order = 0; switch(mViewMode) { case MODE_LIST: forward_history = mCombinationInventoryPanel->getNavForwardList(); backward_history = mCombinationInventoryPanel->getNavBackwardList(); + sort_order = mCombinationInventoryPanel->getSortOrder(); break; case MODE_GALLERY: forward_history = mCombinationGalleryPanel->getNavForwardList(); backward_history = mCombinationGalleryPanel->getNavBackwardList(); + sort_order = mCombinationGalleryPanel->getSortOrder(); break; case MODE_COMBINATION: forward_history = mCombinationInventoryPanel->getNavForwardList(); backward_history = mCombinationInventoryPanel->getNavBackwardList(); mCombinationInventoryPanel->getRootFolder()->setForceArrange(false); + sort_order = mCombinationInventoryPanel->getSortOrder(); break; } @@ -3230,12 +3244,14 @@ void LLPanelMainInventory::setViewMode(EViewModeType mode) mCombinationInventoryPanel->changeFolderRoot(cur_root); mCombinationInventoryPanel->setNavForwardList(forward_history); mCombinationInventoryPanel->setNavBackwardList(backward_history); + mCombinationInventoryPanel->setSortOrder(sort_order); } if(isGalleryViewMode()) { mCombinationGalleryPanel->setRootFolder(cur_root); mCombinationGalleryPanel->setNavForwardList(forward_history); mCombinationGalleryPanel->setNavBackwardList(backward_history); + mCombinationGalleryPanel->setSortOrder(sort_order, true); } if(isCombinationViewMode()) { @@ -3245,6 +3261,8 @@ void LLPanelMainInventory::setViewMode(EViewModeType mode) mCombinationInventoryPanel->setNavBackwardList(backward_history); mCombinationGalleryPanel->setNavForwardList(forward_history); mCombinationGalleryPanel->setNavBackwardList(backward_history); + mCombinationInventoryPanel->setSortOrder(sort_order); + mCombinationGalleryPanel->setSortOrder(sort_order, true); } updateNavButtons(); diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index b1c225a655..ecbb531888 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -236,7 +236,8 @@ private: LLInventorySingleFolderPanel* mCombinationInventoryPanel; LLInventoryGallery* mCombinationGalleryPanel; LLPanel* mCombinationGalleryLayoutPanel; - LLPanel* mCombinationListLayoutPanel; + LLLayoutPanel* mCombinationListLayoutPanel; + LLLayoutStack* mCombinationLayoutStack; // Filter dropdown LLComboBox* mFilterComboBox; diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index ae0977ec9e..b72561e1cf 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -366,7 +366,13 @@ void LLSidepanelInventory::enableInbox(bool enabled) void LLSidepanelInventory::hideInbox() { if (mInboxLayoutPanel) // Inbox panel randomly shown on secondary inventory window + { mInboxLayoutPanel->setVisible(false); + if (LLLayoutStack* inv_stack = findChild(INVENTORY_LAYOUT_STACK_NAME); inv_stack) + { + inv_stack->setPanelSpacing(0); + } + } } void LLSidepanelInventory::toggleInbox() @@ -374,12 +380,19 @@ void LLSidepanelInventory::toggleInbox() // Optional hiding of Received Items folder aka Inbox //mInboxLayoutPanel->setVisible(mInboxEnabled); if (mInboxLayoutPanel) + { mInboxLayoutPanel->setVisible(mInboxEnabled && (!gSavedSettings.getBOOL("FSShowInboxFolder") || gSavedSettings.getBOOL("FSAlwaysShowInboxButton")) -// Show Received Items panel only in Second Life + // Show Received Items panel only in Second Life #ifdef OPENSIM - && LLGridManager::getInstance()->isInSecondLife() + && LLGridManager::getInstance()->isInSecondLife() #endif // OPENSIM - ); + ); + + if (LLLayoutStack* inv_stack = findChild(INVENTORY_LAYOUT_STACK_NAME); inv_stack) + { + inv_stack->setPanelSpacing(mInboxLayoutPanel->getVisible() ? gSavedSettings.getS32("UIResizeBarHeight") : 0); + } + } } // Optional hiding of Received Items folder aka Inbox diff --git a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml index b3ace8139b..176888f6eb 100644 --- a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml @@ -7,8 +7,7 @@ layout="topleft" min_height="300" min_width="240" - name="main inventory panel" - width="330"> + name="main inventory panel"> @@ -777,9 +776,9 @@ height="314" layout="topleft" left="2" + right="-3" name="default_inventory_panel" - top_pad="4" - width="326"> + top_pad="4"> + top="0"> @@ -818,16 +812,13 @@ border="false" bevel_style="none" follows="all" - height="338" label="Recent" sort_order_setting="RecentItemsSortOrder" help_topic="recent_inventory_tab" layout="topleft" - left_delta="0" name="Recent Items" show_item_link_overlays="true" preinitialize_views="false" - width="288" scroll.reserve_scroll_corner="false"> @@ -835,15 +826,12 @@ border="false" bevel_style="none" follows="all" - height="338" label="Worn" help_topic="worn_inventory_tab" layout="topleft" - left_delta="0" name="Worn Items" show_item_link_overlays="true" preinitialize_views="false" - width="288" scroll.reserve_scroll_corner="false"> @@ -852,19 +840,18 @@ + visible="false"> + right="-4"> + name="objects panel"> + visible="true"> + height="570"> + height="330" /> + height="235"> Received items ([NUM]) Received items