/** * @file llinventorygallery.h * @brief LLInventoryGallery class definition * * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2023, Linden Research, Inc. * * 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. * * 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. * * 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$ */ #ifndef LL_LLINVENTORYGALLERY_H #define LL_LLINVENTORYGALLERY_H #include "llgesturemgr.h" #include "lllistcontextmenu.h" #include "llpanel.h" #include "llinventoryfilter.h" #include "llinventoryobserver.h" #include "llinventorymodel.h" class LLInventoryCategoriesObserver; class LLInventoryGalleryItem; class LLScrollContainer; class LLTextBox; class LLThumbnailsObserver; class LLThumbnailCtrl; class LLGalleryGestureObserver; class LLInventoryGalleryContextMenu; typedef boost::function<void()> callback_t; class LLInventoryGallery : public LLPanel, public LLEditMenuHandler { public: typedef boost::signals2::signal<void(const LLUUID&)> selection_change_signal_t; typedef boost::function<void(const LLUUID&)> selection_change_callback_t; typedef std::deque<LLUUID> selection_deque; struct Params : public LLInitParam::Block<Params, LLPanel::Params> { Optional<S32> row_panel_height; Optional<S32> row_panel_width_factor; Optional<S32> gallery_width_factor; Optional<S32> vertical_gap; Optional<S32> horizontal_gap; Optional<S32> item_width; Optional<S32> item_height; Optional<S32> item_horizontal_gap; Optional<S32> items_in_row; Params(); }; static const LLInventoryGallery::Params& getDefaultParams(); LLInventoryGallery(const LLInventoryGallery::Params& params = getDefaultParams()); ~LLInventoryGallery(); BOOL postBuild() override; void initGallery(); void draw() override; void onVisibilityChange(BOOL new_visibility) override; BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override; void startDrag(); BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; BOOL handleKeyHere(KEY key, MASK mask) override; void moveUp(MASK mask); void moveDown(MASK mask); void moveLeft(MASK mask); void moveRight(MASK mask); void toggleSelectionRange(S32 start_idx, S32 end_idx); void toggleSelectionRangeFromLast(const LLUUID target); void onFocusLost() override; void onFocusReceived() override; void setFilterSubString(const std::string& string); std::string getFilterSubString() { return mFilterSubString; } LLInventoryFilter& getFilter() const { return *mFilter; } bool checkAgainstFilterType(const LLUUID& object_id); void getCurrentCategories(uuid_vec_t& vcur); bool updateAddedItem(LLUUID item_id); // returns true if added item is visible void updateRemovedItem(LLUUID item_id); void updateChangedItemName(LLUUID item_id, std::string name); void updateItemThumbnail(LLUUID item_id); void updateWornItem(LLUUID item_id, bool is_worn); void updateMessageVisibility(); void setRootFolder(const LLUUID cat_id); void updateRootFolder(); LLUUID getRootFolder() { return mFolderID; } bool isRootDirty() { return mRootDirty; } boost::signals2::connection setRootChangedCallback(callback_t cb); void onForwardFolder(); void onBackwardFolder(); void clearNavigationHistory(); bool isBackwardAvailable(); bool isForwardAvailable(); void setNavBackwardList(std::list<LLUUID> backward_list) { mBackwardFolders = backward_list; } void setNavForwardList(std::list<LLUUID> forward_list) { mForwardFolders = forward_list; } std::list<LLUUID> getNavBackwardList() { return mBackwardFolders; } std::list<LLUUID> getNavForwardList() { return mForwardFolders; } LLUUID getOutfitImageID(LLUUID outfit_id); void refreshList(const LLUUID& category_id); void onCOFChanged(); void onGesturesChanged(); void computeDifference(const LLInventoryModel::cat_array_t vcats, const LLInventoryModel::item_array_t vitems, uuid_vec_t& vadded, uuid_vec_t& vremoved); void deselectItem(const LLUUID& category_id); void clearSelection(); void changeItemSelection(const LLUUID& item_id, bool scroll_to_selection = false); void addItemSelection(const LLUUID& item_id, bool scroll_to_selection = false); bool toggleItemSelection(const LLUUID& item_id, bool scroll_to_selection = false); void scrollToShowItem(const LLUUID& item_id); void signalSelectionItemID(const LLUUID& category_id); boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); LLUUID getFirstSelectedItemID(); void setSearchType(LLInventoryFilter::ESearchType type); LLInventoryFilter::ESearchType getSearchType() { return mSearchType; } bool areViewsInitialized(); bool hasDescendents(const LLUUID& cat_id); bool hasVisibleItems(); void handleModifiedFilter(); LLScrollContainer* getScrollableContainer() { return mScrollPanel; } LLInventoryGalleryItem* getFirstSelectedItem(); // Copy & paste (LLEditMenuHandler) void copy() override; BOOL canCopy() const override; void cut() override; BOOL canCut() const override; void paste() override; BOOL canPaste() const override; // Copy & paste & delete static void onDelete(const LLSD& notification, const LLSD& response, const selection_deque selected_ids); void deleteSelection(); 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, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); void showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id); protected: void paste(const LLUUID& dest, std::vector<LLUUID>& objects, bool is_cut_mode, const LLUUID& marketplacelistings_id); void pasteAsLink(const LLUUID& dest, std::vector<LLUUID>& objects, const LLUUID& current_outfit_id, const LLUUID& marketplacelistings_id, const LLUUID& my_outifts_id); bool applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring); bool checkAgainstFilters(LLInventoryGalleryItem* item, const std::string& filter_substring); static void onIdle(void* userdata); void dirtyRootFolder(); LLInventoryCategoriesObserver* mCategoriesObserver; LLThumbnailsObserver* mThumbnailsObserver; LLGalleryGestureObserver* mGestureObserver; LLInventoryObserver* mInventoryObserver; selection_deque mSelectedItemIDs; selection_deque mItemsToSelect; LLUUID mLastInteractedUUID; bool mIsInitialized; bool mRootDirty; selection_change_signal_t mSelectionChangeSignal; boost::signals2::signal<void()> mRootChangedSignal; LLUUID mFolderID; std::list<LLUUID> mBackwardFolders; std::list<LLUUID> mForwardFolders; private: void addToGallery(LLInventoryGalleryItem* item); void removeFromGalleryLast(LLInventoryGalleryItem* item, bool needs_reshape = true); void removeFromGalleryMiddle(LLInventoryGalleryItem* item); LLPanel* addLastRow(); void removeLastRow(); void moveRowUp(int row); void moveRowDown(int row); void moveRow(int row, int pos); LLPanel* addToRow(LLPanel* row_stack, LLInventoryGalleryItem* item, int pos, int hgap); void removeFromLastRow(LLInventoryGalleryItem* item); void reArrangeRows(S32 row_diff = 0); bool updateRowsIfNeeded(); void updateGalleryWidth(); 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); LLPanel* buildItemPanel(int left); LLPanel* buildRowPanel(int left, int bottom); void moveRowPanel(LLPanel* stack, int left, int bottom); std::vector<LLPanel*> mRowPanels; std::vector<LLPanel*> mItemPanels; std::vector<LLPanel*> mUnusedRowPanels; std::vector<LLPanel*> mUnusedItemPanels; std::vector<LLInventoryGalleryItem*> mItems; std::vector<LLInventoryGalleryItem*> mHiddenItems; LLScrollContainer* mScrollPanel; LLPanel* mGalleryPanel; LLPanel* mLastRowPanel; LLTextBox* mMessageTextBox; int mRowCount; int mItemsAddedCount; bool mGalleryCreated; bool mLoadThumbnailsImmediately; bool mNeedsArrange; /* Params */ int mRowPanelHeight; int mVerticalGap; int mHorizontalGap; int mItemWidth; int mItemHeight; int mItemHorizontalGap; int mItemsInRow; int mRowPanelWidth; int mGalleryWidth; int mRowPanWidthFactor; int mGalleryWidthFactor; LLInventoryGalleryContextMenu* mInventoryGalleryMenu; LLInventoryGalleryContextMenu* mRootGalleryMenu; std::string mFilterSubString; LLInventoryFilter* mFilter; U32 mSortOrder; typedef std::map<LLUUID, LLInventoryGalleryItem*> gallery_item_map_t; gallery_item_map_t mItemMap; uuid_vec_t mCOFLinkedItems; uuid_vec_t mActiveGestures; uuid_set_t mItemBuildQuery; std::map<LLInventoryGalleryItem*, S32> mItemIndexMap; std::map<S32, LLInventoryGalleryItem*> mIndexToItemMap; LLInventoryFilter::ESearchType mSearchType; std::string mUsername; }; class LLInventoryGalleryItem : public LLPanel { public: struct Params : public LLInitParam::Block<Params, LLPanel::Params> {}; enum EInventorySortGroup { SG_SYSTEM_FOLDER, SG_TRASH_FOLDER, SG_NORMAL_FOLDER, SG_ITEM }; LLInventoryGalleryItem(const Params& p); virtual ~LLInventoryGalleryItem(); BOOL postBuild(); void draw(); BOOL handleMouseDown(S32 x, S32 y, MASK mask); BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); BOOL handleDoubleClick(S32 x, S32 y, MASK mask); BOOL handleMouseUp(S32 x, S32 y, MASK mask); BOOL handleHover(S32 x, S32 y, MASK mask); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); BOOL handleKeyHere(KEY key, MASK mask); void onFocusLost(); void onFocusReceived(); LLFontGL* getTextFont(); void setItemName(std::string name); bool isSelected() { return mSelected; } void setSelected(bool value); void setWorn(bool value); void setUUID(LLUUID id) {mUUID = id;} LLUUID getUUID() { return mUUID;} void setAssetIDStr(std::string asset_id) {mAssetIDStr = asset_id;} std::string getAssetIDStr() { return mAssetIDStr;} void setDescription(std::string desc) {mDesc = desc;} 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;} bool isDefaultImage() {return mDefaultImage;} bool isHidden() {return mHidden;} void setHidden(bool hidden) {mHidden = hidden;} void setType(LLAssetType::EType type, LLInventoryType::EType inventory_type, U32 flags, bool is_link); LLAssetType::EType getAssetType() { return mType; } void setThumbnail(LLUUID id); void setGallery(LLInventoryGallery* gallery) { mGallery = gallery; } void setLoadImmediately(bool val); bool isFolder() { return mIsFolder; } bool isLink() { return mIsLink; } EInventorySortGroup getSortGroup() { return mSortGroup; } void updateNameText(); private: bool isFadeItem(); LLUUID mUUID; LLTextBox* mNameText; LLPanel* mTextBgPanel; LLThumbnailCtrl* mThumbnailCtrl; bool mSelected; bool mWorn; bool mDefaultImage; bool mHidden; bool mIsFolder; bool mIsLink; S32 mCutGeneration; bool mSelectedForCut; std::string mAssetIDStr; std::string mDesc; std::string mCreatorName; time_t mCreationDate; EInventorySortGroup mSortGroup; LLAssetType::EType mType; std::string mItemName; std::string mWornSuffix; std::string mPermSuffix; LLInventoryGallery* mGallery; }; class LLThumbnailsObserver : public LLInventoryObserver { public: LLThumbnailsObserver(){}; virtual void changed(U32 mask); bool addItem(const LLUUID& obj_id, callback_t cb); void removeItem(const LLUUID& obj_id); protected: struct LLItemData { LLItemData(const LLUUID& obj_id, const LLUUID& thumbnail_id, callback_t cb) : mItemID(obj_id) , mCallback(cb) , mThumbnailID(thumbnail_id) {} callback_t mCallback; LLUUID mItemID; LLUUID mThumbnailID; }; typedef std::map<LLUUID, LLItemData> item_map_t; typedef item_map_t::value_type item_map_value_t; item_map_t mItemMap; }; class LLGalleryGestureObserver : public LLGestureManagerObserver { public: LLGalleryGestureObserver(LLInventoryGallery* gallery) : mGallery(gallery) {} virtual ~LLGalleryGestureObserver() {} virtual void changed() { mGallery->onGesturesChanged(); } private: LLInventoryGallery* mGallery; }; #endif