diff options
Diffstat (limited to 'indra/llui')
| -rw-r--r-- | indra/llui/llaccordionctrltab.h | 2 | ||||
| -rw-r--r-- | indra/llui/llflatlistview.cpp | 13 | ||||
| -rw-r--r-- | indra/llui/llflatlistview.h | 6 | ||||
| -rw-r--r-- | indra/llui/llfolderview.h | 1 | ||||
| -rw-r--r-- | indra/llui/llfolderviewitem.cpp | 249 | ||||
| -rw-r--r-- | indra/llui/llfolderviewitem.h | 30 | ||||
| -rw-r--r-- | indra/llui/llfolderviewmodel.h | 74 | ||||
| -rw-r--r-- | indra/llui/llmenugl.cpp | 2 | ||||
| -rw-r--r-- | indra/llui/llmodaldialog.cpp | 12 | ||||
| -rw-r--r-- | indra/llui/lltextbase.cpp | 9 | ||||
| -rw-r--r-- | indra/llui/lltexteditor.cpp | 30 | ||||
| -rw-r--r-- | indra/llui/lltexteditor.h | 4 | ||||
| -rw-r--r-- | indra/llui/llurlaction.cpp | 28 | ||||
| -rw-r--r-- | indra/llui/llurlaction.h | 4 | ||||
| -rw-r--r-- | indra/llui/llurlentry.cpp | 18 | ||||
| -rw-r--r-- | indra/llui/llurlentry.h | 6 | 
16 files changed, 436 insertions, 52 deletions
| diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 3fdcf9f7f2..bb0b8ce04f 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -140,7 +140,7 @@ public:      S32 notify(const LLSD& info);      bool notifyChildren(const LLSD& info); -    void draw(); +    virtual void draw();      void storeOpenCloseState();      void restoreOpenCloseState(); diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 8178bada42..dfe0a71b74 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -69,7 +69,7 @@ const LLRect& LLFlatListView::getItemsRect() const  bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/)  {      if (!item) return false; -    if (value.isUndefined()) return false; +    if (value.isUndefined()) return false; // item stays an orphan?!!!      //force uniqueness of items, easiest check but unreliable      if (item->getParent() == mItemsPanel) return false; @@ -1346,9 +1346,17 @@ bool LLFlatListViewEx::getForceShowingUnmatchedItems() const      return mForceShowingUnmatchedItems;  } -void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) +void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show, bool notify_parent) +{ +    if (mForceShowingUnmatchedItems != show)  {      mForceShowingUnmatchedItems = show; +        if (!mFilterSubString.empty()) +        { +            updateNoItemsMessage(mFilterSubString); +            filterItems(false, true); +        } +    }  }  void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) @@ -1416,6 +1424,7 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)      if (visibility_changed && notify_parent)      { +        rearrangeItems();          notifyParentItemsRectChanged();      }  } diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 6271231183..1f22360a8a 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -484,7 +484,11 @@ public:      bool getForceShowingUnmatchedItems() const; -    void setForceShowingUnmatchedItems(bool show); +    /** +     * Sets filtered out items to stay visible. Can result in rect changes, +     * so can notify_parent if rect changes +     */ +    void setForceShowingUnmatchedItems(bool show, bool notify_parent);      /**       * Sets up new filter string and filters the list. diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index bdce9dec54..368a86ea84 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -221,6 +221,7 @@ public:      void scrollToShowSelection();      void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);      void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } +    LLScrollContainer* getScrollContainer() { return mScrollContainer; }      LLRect getVisibleRect();      bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 6d0cfcba95..9ca77dbe46 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -31,11 +31,12 @@  #include "llfolderviewitem.h"  #include "llfolderview.h"  #include "llfolderviewmodel.h" -#include "llpanel.h"  #include "llcallbacklist.h"  #include "llcriticaldamp.h"  #include "llclipboard.h"  #include "llfocusmgr.h"     // gFocusMgr +#include "llnotificationsutil.h" +#include "llpanel.h"  #include "lltrans.h"  #include "llwindow.h" @@ -60,7 +61,11 @@ LLUIColor LLFolderViewItem::sSearchStatusColor;  S32 LLFolderViewItem::sTopPad = 0;  LLUIImagePtr LLFolderViewItem::sFolderArrowImg;  LLUIImagePtr LLFolderViewItem::sSelectionImg; +LLUIImagePtr LLFolderViewItem::sFavoriteImg; +LLUIImagePtr LLFolderViewItem::sFavoriteContentImg;  LLFontGL* LLFolderViewItem::sSuffixFont = nullptr; +LLUIColor LLFolderViewItem::sFavoriteColor; +bool LLFolderViewItem::sColorSetInitialized = false;  // only integers can be initialized in header  const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; @@ -68,6 +73,9 @@ const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f;  const LLColor4U DEFAULT_WHITE(255, 255, 255); +constexpr S32 FAVORITE_IMAGE_SIZE = 14; +constexpr S32 FAVORITE_IMAGE_PAD = 3; +  //static  LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) @@ -102,6 +110,8 @@ void LLFolderViewItem::initClass()      sTopPad = default_params.item_top_pad;      sFolderArrowImg = default_params.folder_arrow_image;      sSelectionImg = default_params.selection_image; +    sFavoriteImg = default_params.favorite_image; +    sFavoriteContentImg = default_params.favorite_content_image;      sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL);      sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); @@ -121,6 +131,8 @@ void LLFolderViewItem::cleanupClass()      sFonts.clear();      sFolderArrowImg = nullptr;      sSelectionImg = nullptr; +    sFavoriteImg = nullptr; +    sFavoriteContentImg = nullptr;      sSuffixFont = nullptr;  } @@ -129,13 +141,15 @@ void LLFolderViewItem::cleanupClass()  LLFolderViewItem::Params::Params()  :   root(),      listener(), +    favorite_image("favorite_image"), +    favorite_content_image("favorite_content_image"),      folder_arrow_image("folder_arrow_image"),      folder_indentation("folder_indentation"),      selection_image("selection_image"),      item_height("item_height"),      item_top_pad("item_top_pad"),      creation_date(), -    allow_wear("allow_wear", true), +    marketplace_item("marketplace_item", false),      allow_drop("allow_drop", true),      font_color("font_color"),      font_highlight_color("font_highlight_color"), @@ -155,6 +169,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)  :   LLView(p),      mLabelWidth(0),      mLabelWidthDirty(false), +    mIsFavorite(false), +    mHasFavorites(false),      mSuffixNeedsRefresh(false),      mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT),      mParentFolder( NULL ), @@ -175,7 +191,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)      mRoot(p.root),      mViewModelItem(p.listener),      mIsMouseOverTitle(false), -    mAllowWear(p.allow_wear), +    mMarketplaceItem(p.marketplace_item),      mAllowDrop(p.allow_drop),      mFontColor(p.font_color),      mFontHighlightColor(p.font_highlight_color), @@ -189,6 +205,21 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)      mMaxFolderItemOverlap(p.max_folder_item_overlap),      mDoubleClickOverride(p.double_click_override)  { +    if (!sColorSetInitialized) +    { +        sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); +        sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE); +        sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE); +        sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE); +        sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE); +        sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE); +        sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE); +        sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE); +        sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE); +        sFavoriteColor = LLUIColorTable::instance().getColor("InventoryFavoriteColor", DEFAULT_WHITE); +        sColorSetInitialized = true; +    } +      if (mViewModelItem)      {          mViewModelItem->setFolderViewItem(this); @@ -211,6 +242,7 @@ bool LLFolderViewItem::postBuild()          // getDisplayName() is expensive (due to internal getLabelSuffix() and name building)          // it also sets search strings so it requires a filter reset          mLabel = utf8str_to_wstring(vmi->getDisplayName()); +        mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();          setToolTip(vmi->getName());          // Dirty the filter flag of the model from the view (CHUI-849) @@ -325,6 +357,7 @@ void LLFolderViewItem::refresh()      mLabel = utf8str_to_wstring(vmi.getDisplayName());      mLabelFontBuffer.reset(); +    mIsFavorite = vmi.isFavorite() && !vmi.isItemInTrash();      setToolTip(vmi.getName());      // icons are slightly expensive to get, can be optimized      // see LLInventoryIcon::getIcon() @@ -359,6 +392,8 @@ void LLFolderViewItem::refreshSuffix()      mIconOpen = vmi->getIconOpen();      mIconOverlay = vmi->getIconOverlay(); +    mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash(); +      if (mRoot->useLabelSuffix())      {          // Very Expensive! @@ -428,6 +463,10 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )          }          mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel.c_str()) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix.c_str()) + mLabelPaddingRight;          mLabelWidthDirty = false; +        if (mIsFavorite) +        { +            mLabelWidth += FAVORITE_IMAGE_SIZE + FAVORITE_IMAGE_PAD; +        }      }      *width = llmax(*width, mLabelWidth); @@ -554,10 +593,15 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)  void LLFolderViewItem::openItem( void )  { -    if (mAllowWear || !getViewModelItem()->isItemWearable()) +    if (!mMarketplaceItem || !getViewModelItem()->isItemWearable())      {          getViewModelItem()->openItem();      } +    else if (mMarketplaceItem) +    { +        // Wearing an object from any listing, active or not, is verbotten +        LLNotificationsUtil::add("AlertMerchantListingCannotWear"); +    }  }  void LLFolderViewItem::rename(const std::string& new_name) @@ -771,6 +815,45 @@ void LLFolderViewItem::drawOpenFolderArrow()      }  } +void LLFolderViewItem::drawFavoriteIcon() +{ +    static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true); +    static LLUICachedControl<bool> draw_hollow_star("InventoryFavoritesUseHollowStar", true); + +    LLUIImage* favorite_image = nullptr; +    if (draw_star && mIsFavorite) +    { +        favorite_image = sFavoriteImg; +    } +    else if (draw_hollow_star && mHasFavorites && !isOpen()) +    { +        favorite_image = sFavoriteContentImg; +    } + +    if (favorite_image) +    { +        S32 x_offset = 0; +        LLScrollContainer* scroll = mRoot->getScrollContainer(); +        if (scroll) +        { +            S32 width = scroll->getVisibleContentRect().getWidth(); +            S32 offset = scroll->getDocPosHorizontal(); +            x_offset = width + offset; +        } +        else +        { +            x_offset = getRect().getWidth(); +        } +        gl_draw_scaled_image( +            x_offset - FAVORITE_IMAGE_SIZE - FAVORITE_IMAGE_PAD, +            getRect().getHeight() - mItemHeight + FAVORITE_IMAGE_PAD, +            FAVORITE_IMAGE_SIZE, +            FAVORITE_IMAGE_SIZE, +            favorite_image->getImage(), +            sFgColor); +    } +} +  /*virtual*/ bool LLFolderViewItem::isHighlightAllowed()  {      return mIsSelected; @@ -928,6 +1011,7 @@ void LLFolderViewItem::draw()      {          drawOpenFolderArrow();      } +    drawFavoriteIcon();      drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); @@ -999,7 +1083,20 @@ void LLFolderViewItem::draw()          }      } -    LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; +    static LLUICachedControl<bool> highlight_color("InventoryFavoritesColorText", true); +    LLColor4 color; +    if (mIsSelected && filled) +    { +        color = mFontHighlightColor; +    } +    else if (mIsFavorite && highlight_color) +    { +        color = sFavoriteColor; +    } +    else +    { +        color = mFontColor; +    }      if (isFadeItem())      { @@ -1093,7 +1190,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):      mIsFolderComplete(false), // folder might have children that are not loaded yet.      mAreChildrenInited(false), // folder might have children that are not built yet.      mLastArrangeGeneration( -1 ), -    mLastCalculatedWidth(0) +    mLastCalculatedWidth(0), +    mFavoritesDirtyFlags(0)  {  } @@ -1119,6 +1217,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void )      // The LLView base class takes care of object destruction. make sure that we      // don't have mouse or keyboard focus      gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() + +    if (mFavoritesDirtyFlags) +    { +        gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this); +    }  }  // addToFolder() returns true if it succeeds. false otherwise @@ -1762,6 +1865,140 @@ bool LLFolderViewFolder::isMovable()      return true;  } +void LLFolderViewFolder::updateHasFavorites(bool new_childs_value) +{ +    if (mFavoritesDirtyFlags == 0) +    { +        gIdleCallbacks.addFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this); +    } +    if (new_childs_value) +    { +        mFavoritesDirtyFlags |= FAVORITE_ADDED; +    } +    else +    { +        mFavoritesDirtyFlags |= FAVORITE_REMOVED; +    } +} + +void LLFolderViewFolder::onIdleUpdateFavorites(void* data) +{ +    LLFolderViewFolder* self = reinterpret_cast<LLFolderViewFolder*>(data); +    if (self->mFavoritesDirtyFlags == 0) +    { +        // already processed either on previous run or by a different callback +        gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self); +        return; +    } + +    if (self->getViewModelItem()->isItemInTrash()) +    { +        // do not display favorite-stars in trash +        self->mFavoritesDirtyFlags = 0; +        gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self); +        return; +    } + +    if (self->mFavoritesDirtyFlags == FAVORITE_ADDED) +    { +        if (!self->mHasFavorites) +        { +            // propagate up, exclude root +            LLFolderViewFolder* parent = self; +            while (parent +                && (!parent->hasFavorites() || parent->mFavoritesDirtyFlags) +                && !parent->getViewModelItem()->isAgentInventoryRoot()) +            { +                parent->setHasFavorites(true); +                if (parent->mFavoritesDirtyFlags) +                { +                    // Parent will remove onIdleUpdateFavorites later, don't remove now, +                    // We are inside gIdleCallbacks. Removing 'self' callback is safe, +                    // but removing 'parent' can invalidate following iterator +                    parent->mFavoritesDirtyFlags = 0; +                } +                parent = parent->getParentFolder(); +            } +        } +        else +        { +            // already up to date +            self->mFavoritesDirtyFlags = 0; +            gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self); +        } +    } +    else if (self->mFavoritesDirtyFlags > FAVORITE_ADDED) +    { +        // full check +        LLFolderViewFolder* parent = self; +        while (parent && !parent->getViewModelItem()->isAgentInventoryRoot()) +        { +            bool has_favorites = false; +            for (items_t::iterator iter = parent->mItems.begin(); +                iter != parent->mItems.end();) +            { +                items_t::iterator iit = iter++; +                if ((*iit)->isFavorite()) +                { +                    has_favorites = true; +                    break; +                } +            } + +            for (folders_t::iterator iter = parent->mFolders.begin(); +                iter != parent->mFolders.end() && !has_favorites;) +            { +                folders_t::iterator fit = iter++; +                if ((*fit)->isFavorite() || (*fit)->hasFavorites()) +                { +                    has_favorites = true; +                    break; +                } +            } + +            if (!has_favorites) +            { +                if (parent->hasFavorites()) +                { +                    parent->setHasFavorites(false); +                } +                else +                { +                    // Nothing changed +                    break; +                } +            } +            else +            { +                // propagate up, exclude root +                while (parent +                    && (!parent->hasFavorites() || parent->mFavoritesDirtyFlags) +                    && !parent->getViewModelItem()->isAgentInventoryRoot()) +                { +                    parent->setHasFavorites(true); +                    if (parent->mFavoritesDirtyFlags) +                    { +                        // Parent will remove onIdleUpdateFavorites later, don't remove now, +                        // We are inside gIdleCallbacks. Removing 'self' callback is safe, +                        // but removing 'parent' can invalidate following iterator +                        parent->mFavoritesDirtyFlags = 0; +                    } +                    parent = parent->getParentFolder(); +                } +                break; +            } +            if (parent->mFavoritesDirtyFlags) +            { +                // Parent will remove onIdleUpdateFavorites later, don't remove now. +                // We are inside gIdleCallbacks. Removing 'self' callback is safe, +                // but removing 'parent' can invalidate following iterator +                parent->mFavoritesDirtyFlags = 0; +            } +            parent = parent->getParentFolder(); +        } +    } +} +  bool LLFolderViewFolder::isRemovable()  { diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 2ee018a90a..c9b003b892 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -50,7 +50,9 @@ class LLFolderViewItem : public LLView  public:      struct Params : public LLInitParam::Block<Params, LLView::Params>      { -        Optional<LLUIImage*>                        folder_arrow_image, +        Optional<LLUIImage*>                        favorite_image, +                                                    favorite_content_image, +                                                    folder_arrow_image,                                                      selection_image;          Mandatory<LLFolderView*>                    root;          Mandatory<LLFolderViewModelItem*>           listener; @@ -60,7 +62,7 @@ public:                                                      item_top_pad;          Optional<time_t>                            creation_date; -        Optional<bool>                              allow_wear; +        Optional<bool>                              marketplace_item;          Optional<bool>                              allow_drop;          Optional<LLUIColor>                         font_color; @@ -93,6 +95,8 @@ protected:      LLWString                   mLabel;      S32                         mLabelWidth;      bool                        mLabelWidthDirty; +    bool                        mIsFavorite; +    bool                        mHasFavorites;      S32                         mLabelPaddingRight;      LLFolderViewFolder*         mParentFolder;      LLPointer<LLFolderViewModelItem> mViewModelItem; @@ -122,7 +126,7 @@ protected:                                  mIsCurSelection,                                  mDragAndDropTarget,                                  mIsMouseOverTitle, -                                mAllowWear, +                                mMarketplaceItem,                                  mAllowDrop,                                  mSingleFolderMode,                                  mDoubleClickOverride, @@ -133,6 +137,7 @@ protected:      LLUIColor                   mFontColor;      LLUIColor                   mFontHighlightColor; +    static bool                 sColorSetInitialized;      // For now assuming all colors are the same in derived classes.      static LLUIColor            sFgColor; @@ -145,6 +150,8 @@ protected:      static LLUIColor            sFilterTextColor;      static LLUIColor            sSuffixColor;      static LLUIColor            sSearchStatusColor; +    static LLUIColor            sFavoriteColor; +      // this is an internal method used for adding items to folders. A      // no-op at this level, but reimplemented in derived classes. @@ -208,6 +215,8 @@ public:      // Returns true is this object and all of its children can be moved      virtual bool isMovable(); +    bool isFavorite() const { return mIsFavorite; } +      // destroys this item recursively      virtual void destroyView(); @@ -298,6 +307,7 @@ public:      //  virtual void handleDropped();      virtual void draw();      void drawOpenFolderArrow(); +    void drawFavoriteIcon();      void drawHighlight(bool showContent, bool hasKeyboardFocus, const LLUIColor& selectColor, const LLUIColor& flashColor, const LLUIColor& outlineColor, const LLUIColor& mouseOverColor);      void drawLabel(const LLFontGL* font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);      virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, @@ -311,6 +321,8 @@ private:      static S32 sTopPad;      static LLUIImagePtr sFolderArrowImg;      static LLUIImagePtr sSelectionImg; +    static LLUIImagePtr sFavoriteImg; +    static LLUIImagePtr sFavoriteContentImg;      static LLFontGL* sSuffixFont;      LLFontVertexBuffer mLabelFontBuffer; @@ -400,6 +412,18 @@ public:      // Returns true is this object and all of its children can be moved      virtual bool isMovable(); +    bool isFavorite() const { return mIsFavorite; } +    bool hasFavorites() const { return mHasFavorites; } +    void setHasFavorites(bool val) { mHasFavorites = val; } +    void updateHasFavorites(bool new_childs_value); +private: +    static void onIdleUpdateFavorites(void* data); + +    constexpr static S32 FAVORITE_ADDED = 1; +    constexpr static S32 FAVORITE_REMOVED = 2; +    S32 mFavoritesDirtyFlags { 0 }; +public: +      // destroys this folder, and all children      virtual void destroyView();      void destroyRoot(); diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 9372818ca5..2865b789b9 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -162,6 +162,7 @@ public:      virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0; +    virtual bool isFavorite() const = 0;      virtual bool isItemWearable() const { return false; }      virtual bool isItemRenameable() const = 0; @@ -170,7 +171,8 @@ public:      virtual bool isItemMovable( void ) const = 0;       // Can be moved to another folder      virtual void move( LLFolderViewModelItem* parent_listener ) = 0; -    virtual bool isItemRemovable( bool check_worn = true ) const = 0;       // Can be destroyed +    virtual bool isItemRemovable( bool check_worn = true) const = 0;     // Can be destroyed +    virtual bool isItemInTrash(void) const = 0;      virtual bool removeItem() = 0;      virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; @@ -183,6 +185,9 @@ public:      virtual void pasteFromClipboard() = 0;      virtual void pasteLinkFromClipboard() = 0; +    virtual bool isAgentInventory() const = 0; +    virtual bool isAgentInventoryRoot() const = 0; +      virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;      virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? @@ -219,6 +224,7 @@ public:      virtual S32 getSortVersion() = 0;      virtual void setSortVersion(S32 version) = 0;      virtual void setParent(LLFolderViewModelItem* parent) = 0; +    virtual const LLFolderViewModelItem* getParent() = 0;      virtual bool hasParent() = 0;  protected: @@ -249,14 +255,14 @@ public:          mChildren.clear();      } -    void requestSort() { mSortVersion = -1; } -    S32 getSortVersion() { return mSortVersion; } -    void setSortVersion(S32 version) { mSortVersion = version;} +    void requestSort() override { mSortVersion = -1; } +    S32 getSortVersion() override { return mSortVersion; } +    void setSortVersion(S32 version) override { mSortVersion = version;} -    S32 getLastFilterGeneration() const { return mLastFilterGeneration; } +    S32 getLastFilterGeneration() const override { return mLastFilterGeneration; }      S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } -    S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; } -    void dirtyFilter() +    S32 getMarkedDirtyGeneration() const override { return mMarkedDirtyGeneration; } +    void dirtyFilter() override      {          if(mMarkedDirtyGeneration < 0)          { @@ -271,7 +277,7 @@ public:              mParent->dirtyFilter();          }      } -    void dirtyDescendantsFilter() +    void dirtyDescendantsFilter() override      {          mMostFilteredDescendantGeneration = -1;          if (mParent) @@ -279,13 +285,13 @@ public:              mParent->dirtyDescendantsFilter();          }      } -    bool hasFilterStringMatch(); -    std::string::size_type getFilterStringOffset(); -    std::string::size_type getFilterStringSize(); +    bool hasFilterStringMatch() override; +    std::string::size_type getFilterStringOffset() override; +    std::string::size_type getFilterStringSize() override; -    typedef std::list<LLFolderViewModelItem*> child_list_t; +    typedef std::list<LLPointer<LLFolderViewModelItem> > child_list_t; -    virtual void addChild(LLFolderViewModelItem* child) +    virtual void addChild(LLFolderViewModelItem* child) override      {          mChildren.push_back(child);          child->setParent(this); @@ -293,15 +299,15 @@ public:          requestSort();      } -    virtual void removeChild(LLFolderViewModelItem* child) +    virtual void removeChild(LLFolderViewModelItem* child) override final      { -        mChildren.remove(child);          child->setParent(NULL); +        mChildren.remove(child);          dirtyDescendantsFilter();          dirtyFilter();      } -    virtual void clearChildren() +    virtual void clearChildren() override      {          // We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest          std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); }); @@ -314,7 +320,7 @@ public:      child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); }      child_list_t::size_type getChildrenCount() const { return mChildren.size(); } -    void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) +    void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) override      {          mPassedFilter = passed;          mLastFilterGeneration = filter_generation; @@ -323,20 +329,20 @@ public:          mMarkedDirtyGeneration = -1;      } -    void setPassedFolderFilter(bool passed, S32 filter_generation) +    void setPassedFolderFilter(bool passed, S32 filter_generation) override      {          mPassedFolderFilter = passed;          mLastFolderFilterGeneration = filter_generation;      } -    virtual bool potentiallyVisible() +    virtual bool potentiallyVisible() override      {          return passedFilter() // we've passed the filter              || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet              || descendantsPassedFilter();      } -    virtual bool passedFilter(S32 filter_generation = -1) +    virtual bool passedFilter(S32 filter_generation = -1) override      {          if (filter_generation < 0)          { @@ -347,7 +353,7 @@ public:          return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));      } -    virtual bool descendantsPassedFilter(S32 filter_generation = -1) +    virtual bool descendantsPassedFilter(S32 filter_generation = -1) override      {          if (filter_generation < 0)          { @@ -356,10 +362,10 @@ public:          return mMostFilteredDescendantGeneration >= filter_generation;      } -  protected: -    virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } -    virtual bool hasParent() { return mParent != NULL; } +    virtual void setParent(LLFolderViewModelItem* parent) override final { mParent = parent; } +    virtual const LLFolderViewModelItem* getParent() override { return mParent; }; +    virtual bool hasParent() override { return mParent != NULL; }      S32                         mSortVersion;      bool                        mPassedFilter; @@ -376,7 +382,7 @@ protected:      LLFolderViewModelItem*      mParent;      LLFolderViewModelInterface& mRootViewModel; -    void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} +    void setFolderViewItem(LLFolderViewItem* folder_view_item) override { mFolderViewItem = folder_view_item;}      LLFolderViewItem*       mFolderViewItem;  }; @@ -390,15 +396,15 @@ public:          mFolderView(NULL)      {} -    virtual void requestSortAll() +    virtual void requestSortAll() override      {          // sort everything          mTargetSortVersion++;      } -    virtual std::string getStatusText(bool is_empty_folder = false); -    virtual void filter(); +    virtual std::string getStatusText(bool is_empty_folder = false) override; +    virtual void filter() override; -    void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} +    void setFolderView(LLFolderView* folder_view) override { mFolderView = folder_view;}  protected:      bool needsSort(class LLFolderViewModelItem* item); @@ -428,14 +434,14 @@ public:      virtual const SortType& getSorter() const        { return *mSorter; }      virtual void setSorter(const SortType& sorter)   { mSorter.reset(new SortType(sorter)); requestSortAll(); } -    virtual FilterType& getFilter()                  { return *mFilter; } -    virtual const FilterType& getFilter() const      { return *mFilter; } +    virtual FilterType& getFilter() override                  { return *mFilter; } +    virtual const FilterType& getFilter() const override      { return *mFilter; }      virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); }      // By default, we assume the content is available. If a network fetch mechanism is implemented for the model,      // this method needs to be overloaded and return the relevant fetch status. -    virtual bool contentsReady()                    { return true; } -    virtual bool isFolderComplete(LLFolderViewFolder* folder)                   { return true; } +    virtual bool contentsReady() override                     { return true; } +    virtual bool isFolderComplete(LLFolderViewFolder* folder) override { return true; }      struct ViewModelCompare      { @@ -456,7 +462,7 @@ public:          const SortType& mSorter;      }; -    void sort(LLFolderViewFolder* folder) +    void sort(LLFolderViewFolder* folder) override      {          if (needsSort(folder->getViewModelItem()))          { diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index c11b42a348..2ca2454040 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -46,6 +46,7 @@  #include "llfocusmgr.h"  #include "llcoord.h"  #include "llwindow.h" +#include "llemojihelper.h"  #include "llcriticaldamp.h"  #include "lluictrlfactory.h" @@ -1411,6 +1412,7 @@ void LLMenuItemBranchDownGL::openMenu( void )      }      else      { +        LLEmojiHelper::instance().hideHelper(nullptr, true);          if (branch->getTornOff())          {              LLFloater * branch_parent = dynamic_cast<LLFloater *>(branch->getParent()); diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index c5c31f7252..225ff607ad 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -28,6 +28,7 @@  #include "llmodaldialog.h" +#include "llemojihelper.h"  #include "llfocusmgr.h"  #include "v4color.h"  #include "v2math.h" @@ -35,6 +36,7 @@  #include "llwindow.h"  #include "llkeyboard.h"  #include "llmenugl.h" +  // static  std::list<LLModalDialog*> LLModalDialog::sModalStack; @@ -98,7 +100,7 @@ void LLModalDialog::onOpen(const LLSD& key)  {      if (mModal)      { -        // If Modal, Hide the active modal dialog +        // If Modal, hide the active modal dialog          if (!sModalStack.empty())          {              LLModalDialog* front = sModalStack.front(); @@ -155,6 +157,12 @@ void LLModalDialog::setVisible( bool visible )      {          if( visible )          { +            // Hide all menus currently shown +            LLMenuGL::sMenuContainer->hideMenus(); + +            // Hide EmojiPicker if it is shown +            LLEmojiHelper::instance().hideHelper(nullptr, true); +              // This is a modal dialog.  It sucks up all mouse and keyboard operations.              gFocusMgr.setMouseCapture( this ); @@ -301,7 +309,6 @@ void LLModalDialog::centerOnScreen()      centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY])));  } -  // static  void LLModalDialog::onAppFocusLost()  { @@ -333,6 +340,7 @@ void LLModalDialog::onAppFocusGained()      }  } +// static  void LLModalDialog::shutdownModals()  {      // This method is only for use during app shutdown. ~LLModalDialog() diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 778b253c3c..382847d68f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1069,6 +1069,14 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s  S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)  { +    S32 text_length = (S32)getLength(); +    if (pos >= text_length || pos < 0) +    { +        return 0; // nothing to remove +    } +    // Clamp length to not go past the end of the text +    length = std::min(length, text_length - pos); +      beforeValueChange();      segment_set_t::iterator seg_iter = getSegIterContaining(pos);      while(seg_iter != mSegments.end()) @@ -2228,6 +2236,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)      registrar.add("Url.ReportAbuse", boost::bind(&LLUrlAction::reportAbuse, url));      registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url));      registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); +    registrar.add("Url.ShowParcelOnMap", boost::bind(&LLUrlAction::showParcelOnMap, url));      registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));      registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index cfe729be06..58b785fcdd 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -274,7 +274,9 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :      mShowChatMentionPicker(false),      mEnableTooltipPaste(p.enable_tooltip_paste),      mPassDelete(false), -    mKeepSelectionOnReturn(false) +    mKeepSelectionOnReturn(false), +    mSelectAllOnFocusReceived(false), +    mSelectedOnFocusReceived(false)  {      mSourceID.generate(); @@ -398,6 +400,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen      setCursorPos(loc);      mIsSelecting = true; +    mSelectedOnFocusReceived = false;      mSelectionEnd = mCursorPos;      mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));  } @@ -677,6 +680,13 @@ bool LLTextEditor::canSelectAll() const      return true;  } +//virtual +void LLTextEditor::deselect() +{ +    LLTextBase::deselect(); +    mSelectedOnFocusReceived = false; +} +  // virtual  void LLTextEditor::selectAll()  { @@ -694,6 +704,11 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p      endSelection();  } +void LLTextEditor::setSelectAllOnFocusReceived(bool b) +{ +    mSelectAllOnFocusReceived = b; +} +  void LLTextEditor::insertEmoji(llwchar emoji)  {      LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; @@ -795,8 +810,16 @@ bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)      // Delay cursor flashing      resetCursorBlink(); +    mSelectedOnFocusReceived = false;      if (handled && !gFocusMgr.getMouseCapture())      { +        if (!mask && mSelectAllOnFocusReceived) +        { +            mIsSelecting = false; +            mSelectionStart = getLength(); +            mSelectionEnd = 0; +            mSelectedOnFocusReceived = true; +        }          gFocusMgr.setMouseCapture( this );      }      return handled; @@ -2200,6 +2223,11 @@ void LLTextEditor::focusLostHelper()          gEditMenuHandler = NULL;      } +    if (mSelectedOnFocusReceived) +    { +        deselect(); +    } +      if (mCommitOnFocusLost)      {          onCommit(); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 882bb145df..cdfcbcdd63 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -144,8 +144,10 @@ public:      virtual bool    canDoDelete() const;      virtual void    selectAll();      virtual bool    canSelectAll()  const; +    virtual void    deselect();      void            selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos); +    void            setSelectAllOnFocusReceived(bool b);      virtual bool    canLoadOrSaveToFile(); @@ -336,6 +338,8 @@ private:      bool            mEnableTooltipPaste;      bool            mPassDelete;      bool            mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter +    bool            mSelectAllOnFocusReceived; +    bool            mSelectedOnFocusReceived;      LLUUID          mSourceID; diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index b6b450c2a1..fdae22cfa1 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -30,6 +30,7 @@  #include "llview.h"  #include "llwindow.h"  #include "llurlregistry.h" +#include "v3dmath.h"  // global state for the callback functions @@ -128,6 +129,23 @@ void LLUrlAction::showLocationOnMap(std::string url)      }  } +void LLUrlAction::showParcelOnMap(std::string url) +{ +    LLSD path_array = LLURI(url).pathArray(); +    auto path_parts = path_array.size(); + +    if (path_parts < 3) // no parcel id +    { +        LL_WARNS() << "Global coordinates are missing in url: [" << url << "]" << LL_ENDL; +        return; +    } + +    LLVector3d parcel_pos = LLUrlEntryParcel::getParcelPos(LLUUID(LLURI::unescape(path_array[2]))); +    std::ostringstream pos; +    pos << parcel_pos.mdV[VX] << '/' << parcel_pos.mdV[VY] << '/' << parcel_pos.mdV[VZ]; +    executeSLURL("secondlife:///app/worldmap_global/" + pos.str()); +} +  void LLUrlAction::copyURLToClipboard(std::string url)  {      LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url)); @@ -142,6 +160,16 @@ void LLUrlAction::copyLabelToClipboard(std::string url)      }  } +std::string LLUrlAction::getURLLabel(std::string url) +{ +    LLUrlMatch match; +    if (LLUrlRegistry::instance().findUrl(url, match)) +    { +       return match.getLabel(); +    } +    return ""; +} +  void LLUrlAction::showProfile(std::string url)  {      // Get id from 'secondlife:///app/{cmd}/{id}/{action}' diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index ac9741a7ad..8b7ab0e7c5 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -63,6 +63,8 @@ public:      /// if the Url specifies an SL location, show it on a map      static void showLocationOnMap(std::string url); +    static void showParcelOnMap(std::string url); +      /// perform the appropriate action for left-clicking on a Url      static void clickAction(std::string url, bool trusted_content); @@ -72,6 +74,8 @@ public:      /// copy a Url to the clipboard      static void copyURLToClipboard(std::string url); +    static std::string getURLLabel(std::string url); +      /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile      static void showProfile(std::string url);      static std::string getUserID(std::string url); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index bcd13b7f0b..95603d7ed5 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -41,8 +41,7 @@  #include "lluicolortable.h"  #include "message.h"  #include "llexperiencecache.h" - -#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" +#include "v3dmath.h"  // Utility functions  std::string localize_slapp_label(const std::string& url, const std::string& full_name); @@ -1084,6 +1083,7 @@ LLUUID  LLUrlEntryParcel::sSessionID(LLUUID::null);  LLHost  LLUrlEntryParcel::sRegionHost;  bool    LLUrlEntryParcel::sDisconnected(false);  std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers; +std::map<LLUUID, LLVector3d> LLUrlEntryParcel::sParcelPos;  ///  /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g., @@ -1176,6 +1176,20 @@ void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data)              url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label);          }      } +    if (sParcelPos.find(parcel_data.parcel_id) == sParcelPos.end()) +    { +        sParcelPos[parcel_data.parcel_id] = LLVector3d(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z); +    } +} + +// static +LLVector3d LLUrlEntryParcel::getParcelPos(const LLUUID& parcel_id) +{ +    if (sParcelPos.find(parcel_id) != sParcelPos.end()) +    { +        return sParcelPos[parcel_id]; +    } +    return LLVector3d();  }  // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 6e7d2fc80f..efb5081103 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -41,6 +41,9 @@  #include <map>  class LLAvatarName; +class LLVector3d; + +#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"  typedef boost::signals2::signal<void (const std::string& url,                                        const std::string& label, @@ -434,6 +437,8 @@ public:      // Processes parcel label and triggers notifying observers.      static void processParcelInfo(const LLParcelData& parcel_data); +    static LLVector3d getParcelPos(const LLUUID& parcel_id); +      // Next setters are used to update agent and viewer connection information      // upon events like user login, viewer disconnect and user changing region host.      // These setters are made public to be accessible from newview and should not be @@ -447,6 +452,7 @@ private:      static LLHost                       sRegionHost;      static bool                         sDisconnected;      static std::set<LLUrlEntryParcel*>  sParcelInfoObservers; +    static std::map<LLUUID, LLVector3d> sParcelPos;  };  /// | 
