diff options
| -rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 5 | ||||
| -rw-r--r-- | indra/newview/llinventorygallery.cpp | 480 | ||||
| -rw-r--r-- | indra/newview/llinventorygallery.h | 25 | ||||
| -rw-r--r-- | indra/newview/llinventorygallerymenu.cpp | 162 | ||||
| -rw-r--r-- | indra/newview/llinventorygallerymenu.h | 6 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_gallery_inventory.xml | 26 | 
6 files changed, 509 insertions, 195 deletions
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index f5f0d74f0f..4aeacae6ed 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -454,7 +454,10 @@ void copy_inventory_category(LLInventoryModel* model,      inventory_func_type func = [model, cat, root_copy_id, move_no_copy_items, callback](const LLUUID &new_id)      {          copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items); -        callback(new_id); +        if (callback) +        { +            callback(new_id); +        }      };  	gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID());  } diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8170c0c63b..eab15b79ad 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -107,7 +107,6 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p)        mIsInitialized(false),        mRootDirty(false),        mNeedsArrange(false), -      mNeedsSelection(false),        mSearchType(LLInventoryFilter::SEARCHTYPE_NAME),        mSortOrder(LLInventoryFilter::SO_DATE)  { @@ -219,10 +218,10 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id)      gIdleCallbacks.deleteFunction(onIdle, (void*)this);      mFolderID = cat_id; -    mItemToSelect.setNull(); +    mItemsToSelect.clear(); +    mSelectedItemIDs.clear();      mItemBuildQuery.clear();      mNeedsArrange = false; -    mNeedsSelection = false;      dirtyRootFolder();  } @@ -831,15 +830,17 @@ void LLInventoryGallery::onIdle(void* userdata)          self->updateMessageVisibility();      } -    if (self->mNeedsSelection) +    if (!self->mItemsToSelect.empty() && !self->mNeedsArrange)      { -        LLUUID item_to_select = self->mItemToSelect; -        self->mItemToSelect = LLUUID::null; -        self->mNeedsSelection = false; -        self->changeItemSelection(item_to_select, true); +        selection_deque selection_list(self->mItemsToSelect); +        self->mItemsToSelect.clear(); +        for (LLUUID & item_to_select : selection_list) +        { +            self->addItemSelection(item_to_select, true); +        }      } -    if (!self->mNeedsSelection && self->mItemBuildQuery.empty()) +    if (self->mItemsToSelect.empty() && self->mItemBuildQuery.empty())      {          gIdleCallbacks.deleteFunction(onIdle, (void*)self);      } @@ -911,7 +912,6 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id)      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->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false));      if (mGalleryCreated)      {          res = applyFilter(item, mFilterSubString); @@ -1074,8 +1074,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask)              mFilterSubString.clear();              if (mInventoryGalleryMenu && mSelectedItemIDs.size() == 1)              { -                selection_deque::iterator iter = mSelectedItemIDs.begin(); -                mInventoryGalleryMenu->doToSelected("rename", *iter); +                mInventoryGalleryMenu->rename(mSelectedItemIDs.front());              }              handled = TRUE;              break; @@ -1117,22 +1116,22 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask)              break;          case KEY_LEFT: -            moveLeft(); +            moveLeft(mask);              handled = TRUE;              break;          case KEY_RIGHT: -            moveRight(); +            moveRight(mask);              handled = TRUE;              break;          case KEY_UP: -            moveUp(); +            moveUp(mask);              handled = TRUE;              break;          case KEY_DOWN: -            moveDown(); +            moveDown(mask);              handled = TRUE;              break; @@ -1148,59 +1147,107 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask)      return handled;  } -void LLInventoryGallery::moveUp() +void LLInventoryGallery::moveUp(MASK mask)  {      mFilterSubString.clear();      if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1)      { -        LLInventoryGalleryItem* item = getFirstSelectedItem(); +        LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID];          if (item)          { -            S32 n = mItemIndexMap[item]; -            n -= mItemsInRow; -            if (n >= 0) +            if (mask == MASK_NONE || mask == MASK_CONTROL)              { -                item = mIndexToItemMap[n]; -                LLUUID item_id = item->getUUID(); -                changeItemSelection(item_id, true); -                item->setFocus(TRUE); -                claimEditHandler(); +                S32 n = mItemIndexMap[item]; +                n -= mItemsInRow; +                if (n >= 0) +                { +                    item = mIndexToItemMap[n]; +                    LLUUID item_id = item->getUUID(); +                    if (mask == MASK_CONTROL) +                    { +                        addItemSelection(item_id, true); +                    } +                    else +                    { +                        changeItemSelection(item_id, true); +                    } +                    item->setFocus(TRUE); +                    claimEditHandler(); +                } +            } +            else if (mask == MASK_SHIFT) +            { +                S32 n = mItemIndexMap[item]; +                S32 target  = llmax(0, n - mItemsInRow); +                toggleSelectionRange(target, n - 1); +                if (target != n) +                { +                    item = mIndexToItemMap[target]; +                    item->setFocus(TRUE); +                    claimEditHandler(); +                }              }          }      }  } -void LLInventoryGallery::moveDown() +void LLInventoryGallery::moveDown(MASK mask)  {      mFilterSubString.clear();      if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1)      { -        LLInventoryGalleryItem* item = getFirstSelectedItem(); +        LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID];          if (item)          { -            S32 n = mItemIndexMap[item]; -            n += mItemsInRow; -            if (n < mItemsAddedCount) +            if (mask == MASK_NONE || mask == MASK_CONTROL)              { -                item = mIndexToItemMap[n]; -                LLUUID item_id = item->getUUID(); -                changeItemSelection(item_id, true); -                item->setFocus(TRUE); -                claimEditHandler(); +                S32 n = mItemIndexMap[item]; +                n += mItemsInRow; +                if (n < mItemsAddedCount) +                { +                    item = mIndexToItemMap[n]; +                    LLUUID item_id = item->getUUID(); +                    if (mask == MASK_CONTROL) +                    { +                        addItemSelection(item_id, true); +                    } +                    else +                    { +                        changeItemSelection(item_id, true); +                    } +                    item->setFocus(TRUE); +                    claimEditHandler(); +                } +            } +            else if (mask == MASK_SHIFT) +            { +                S32 n = mItemIndexMap[item]; +                S32 target = llmin(mItemsAddedCount - 1, n + mItemsInRow); +                toggleSelectionRange(n + 1, target); +                if (target != n) +                { +                    item = mIndexToItemMap[target]; +                    item->setFocus(TRUE); +                    claimEditHandler(); +                }              }          }      }  } -void LLInventoryGallery::moveLeft() +void LLInventoryGallery::moveLeft(MASK mask)  {      mFilterSubString.clear();      if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1)      { -        LLInventoryGalleryItem* item = getFirstSelectedItem(); +        LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; +        if (mask == MASK_SHIFT) +        { +            item = mItemMap[mLastSelectedUUID]; +        }          if (item)          {              // Might be better to get item from panel @@ -1212,20 +1259,31 @@ void LLInventoryGallery::moveLeft()              }              item = mIndexToItemMap[n];              LLUUID item_id = item->getUUID(); -            changeItemSelection(item_id, true); +            if (mask == MASK_CONTROL) +            { +                addItemSelection(item_id, true); +            } +            else if (mask == MASK_SHIFT) +            { +                toggleItemSelection(item_id, true); +            } +            else +            { +                changeItemSelection(item_id, true); +            }              item->setFocus(TRUE);              claimEditHandler();          }      }  } -void LLInventoryGallery::moveRight() +void LLInventoryGallery::moveRight(MASK mask)  {      mFilterSubString.clear();      if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1)      { -        LLInventoryGalleryItem* item = getFirstSelectedItem(); +        LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID];          if (item)          {              S32 n = mItemIndexMap[item]; @@ -1236,13 +1294,58 @@ void LLInventoryGallery::moveRight()              }              item = mIndexToItemMap[n];              LLUUID item_id = item->getUUID(); -            changeItemSelection(item_id, true); +            if (mask == MASK_CONTROL) +            { +                addItemSelection(item_id, true); +            } +            else if (mask == MASK_SHIFT) +            { +                toggleItemSelection(item_id, true); +            } +            else +            { +                changeItemSelection(item_id, true); +            }              item->setFocus(TRUE);              claimEditHandler();          }      }  } +void LLInventoryGallery::toggleSelectionRange(S32 start_idx, S32 end_idx) +{ +    LLInventoryGalleryItem* item = NULL; +    for (S32 i = start_idx; i <= end_idx; i++) +    { +        item = mIndexToItemMap[i]; +        LLUUID item_id = item->getUUID(); +        toggleItemSelection(item_id, true); +    } +} + +void LLInventoryGallery::toggleSelectionRangeFromLast(const LLUUID target) +{ +    if (mLastSelectedUUID == target) +    { +        return; +    } +    LLInventoryGalleryItem* last_item = mItemMap[mLastSelectedUUID]; +    LLInventoryGalleryItem* next_item = mItemMap[target]; +    if (last_item && next_item) +    { +        S32 last_idx = mItemIndexMap[last_item]; +        S32 next_idx = mItemIndexMap[next_item]; +        if (last_idx < next_idx) +        { +            toggleSelectionRange(last_idx + 1, next_idx); +        } +        else +        { +            toggleSelectionRange(next_idx, last_idx - 1); +        } +    } +} +  void LLInventoryGallery::onFocusLost()  {      // inventory no longer handles cut/copy/paste/delete @@ -1270,17 +1373,21 @@ void LLInventoryGallery::onFocusReceived()      // Tab support, when tabbing into this view, select first item      if (mSelectedItemIDs.size() > 0)      { +        LLInventoryGalleryItem* focus_item = NULL;          for (const LLUUID& id : mSelectedItemIDs)          {              if (mItemMap[id])              { -                LLInventoryGalleryItem* focus_item = mItemMap[id]; +                focus_item = mItemMap[id];                  focus_item->setSelected(true); -                focus_item->setFocus(TRUE);              }          } +        if (focus_item) +        { +            focus_item->setFocus(TRUE); +        }      } -    else if (mIndexToItemMap.size() > 0 && !mNeedsSelection) +    else if (mIndexToItemMap.size() > 0 && mItemsToSelect.empty())      {          // choose any items from visible rect          S32 vert_offset = mScrollPanel->getDocPosVertical(); @@ -1304,18 +1411,26 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU              mSelectedItemIDs.clear();              changeItemSelection(item_id, false);          } -        uuid_vec_t selected_uuids; -        selected_uuids.push_back(item_id); +        uuid_vec_t selected_uuids(mSelectedItemIDs.begin(), mSelectedItemIDs.end());          mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y);      }  }  void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_to_selection)  { +    for (const LLUUID& id : mSelectedItemIDs) +    { +        if (mItemMap[id]) +        { +            mItemMap[id]->setSelected(FALSE); +        } +    } +    mSelectedItemIDs.clear(); +      if ((mItemMap.count(item_id) == 0) || mNeedsArrange)      { -        mItemToSelect = item_id; -        mNeedsSelection = true; +        mItemsToSelect.clear(); +        mItemsToSelect.push_back(item_id);          return;      }      if (mSelectedItemIDs.size() == 1 @@ -1325,14 +1440,32 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_          return;      } -    for (const LLUUID& id : mSelectedItemIDs) +    if (mItemMap[item_id])      { -        if (mItemMap[id]) -        { -            mItemMap[id]->setSelected(FALSE); -        } +        mItemMap[item_id]->setSelected(TRUE); +    } +    mSelectedItemIDs.push_back(item_id); +    signalSelectionItemID(item_id); +    mLastSelectedUUID = item_id; + +    if (scroll_to_selection) +    { +        scrollToShowItem(item_id); +    } +} + +void LLInventoryGallery::addItemSelection(const LLUUID& item_id, bool scroll_to_selection) +{ +    if ((mItemMap.count(item_id) == 0) || mNeedsArrange) +    { +        mItemsToSelect.push_back(item_id); +        return; +    } +    if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) +    { +        // Already selected +        return;      } -    mSelectedItemIDs.clear();      if (mItemMap[item_id])      { @@ -1340,6 +1473,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_      }      mSelectedItemIDs.push_back(item_id);      signalSelectionItemID(item_id); +    mLastSelectedUUID = item_id;      if (scroll_to_selection)      { @@ -1347,6 +1481,43 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_      }  } +bool LLInventoryGallery::toggleItemSelection(const LLUUID& item_id, bool scroll_to_selection) +{ +    bool result = false; +    if ((mItemMap.count(item_id) == 0) || mNeedsArrange) +    { +        mItemsToSelect.push_back(item_id); +        return result; +    } +    selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id); +    if (found != mSelectedItemIDs.end()) +    { +        if (mItemMap[item_id]) +        { +            mItemMap[item_id]->setSelected(FALSE); +        } +        mSelectedItemIDs.erase(found); +        result = false; +    } +    else +    { +        if (mItemMap[item_id]) +        { +            mItemMap[item_id]->setSelected(TRUE); +        } +        mSelectedItemIDs.push_back(item_id); +        signalSelectionItemID(item_id); +        mLastSelectedUUID = item_id; +        result = true; +    } + +    if (scroll_to_selection) +    { +        scrollToShowItem(item_id); +    } +    return result; +} +  void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id)  {      LLInventoryGalleryItem* item = mItemMap[item_id]; @@ -1476,32 +1647,63 @@ void LLInventoryGallery::paste()          return;      } -    LLUUID first_selected_id; -    if (mSelectedItemIDs.size() > 0) -    { -        first_selected_id = *mSelectedItemIDs.begin(); -    } - -    LLInventoryObject* obj = gInventory.getObject(first_selected_id); -    bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); -    LLUUID dest = is_folder ? first_selected_id : mFolderID;      bool is_cut_mode = LLClipboard::instance().isCutMode(); -      std::vector<LLUUID> objects;      LLClipboard::instance().pasteFromClipboard(objects); -    LLHandle<LLPanel> handle = getHandle(); -    std::function <void(const LLUUID)> on_copy_callback = [handle](const LLUUID& inv_item) +    bool paste_into_root = mSelectedItemIDs.empty(); +    for (LLUUID& dest : mSelectedItemIDs)      { -        LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); -        if (panel) +        LLInventoryObject* obj = gInventory.getObject(dest); +        if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY))          { -            // Scroll to pasted item and highlight it -            // Should it only highlight the last one? -            panel->changeItemSelection(inv_item, true); +            paste_into_root = true; +            continue;          } -    }; -    LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(on_copy_callback); + +        paste(dest, objects, is_cut_mode, marketplacelistings_id); +        is_cut_mode = false; +    } + +    if (paste_into_root) +    { +        for (const LLUUID& id : mSelectedItemIDs) +        { +            if (mItemMap[id]) +            { +                mItemMap[id]->setSelected(FALSE); +            } +        } +        mSelectedItemIDs.clear(); + +        paste(mFolderID, objects, is_cut_mode, marketplacelistings_id); +    } + +    LLClipboard::instance().setCutMode(false); +} + +void LLInventoryGallery::paste(const LLUUID& dest, +                               std::vector<LLUUID>& objects, +                               bool is_cut_mode, +                               const LLUUID& marketplacelistings_id) +{ +    LLHandle<LLPanel> handle = getHandle(); +    std::function <void(const LLUUID)> on_copy_callback = NULL; +    LLPointer<LLInventoryCallback> cb = NULL; +    if (dest == mFolderID) +    { +        on_copy_callback = [handle](const LLUUID& inv_item) +            { +                LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); +                if (panel) +                { +                    // Scroll to pasted item and highlight it +                    // Should it only highlight the last one? +                    panel->addItemSelection(inv_item, true); +                } +            }; +        cb = new LLBoostFuncInventoryCallback(on_copy_callback); +    }      for (std::vector<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter)      { @@ -1517,9 +1719,11 @@ void LLInventoryGallery::paste()              if (is_cut_mode)              {                  gInventory.changeCategoryParent(cat, dest, false); -                // Don't select immediately, wait for item to arrive -                mItemToSelect = item_id; -                mNeedsSelection = true; +                if (dest == mFolderID) +                { +                    // Don't select immediately, wait for item to arrive +                    mItemsToSelect.push_back(item_id); +                }              }              else              { @@ -1534,9 +1738,11 @@ void LLInventoryGallery::paste()                  if (is_cut_mode)                  {                      gInventory.changeItemParent(item, dest, false); -                    // Don't select immediately, wait for item to arrive -                    mItemToSelect = item_id; -                    mNeedsSelection = true; +                    if (dest == mFolderID) +                    { +                        // Don't select immediately, wait for item to arrive +                        mItemsToSelect.push_back(item_id); +                    }                  }                  else                  { @@ -1679,17 +1885,45 @@ void LLInventoryGallery::pasteAsLink()      const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);      const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); -    LLUUID dest; -    if (mSelectedItemIDs.size() > 0) +    std::vector<LLUUID> objects; +    LLClipboard::instance().pasteFromClipboard(objects); + +    bool paste_into_root = mSelectedItemIDs.empty(); +    for (LLUUID& dest : mSelectedItemIDs)      { -        dest = *mSelectedItemIDs.begin(); +        LLInventoryObject* obj = gInventory.getObject(dest); +        if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) +        { +            paste_into_root = true; +            continue; +        } + +        pasteAsLink(dest, objects, current_outfit_id, marketplacelistings_id, my_outifts_id);      } -    LLInventoryObject* obj = gInventory.getObject(dest); -    if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) + +    if (paste_into_root)      { -        dest = mFolderID; +        for (const LLUUID& id : mSelectedItemIDs) +        { +            if (mItemMap[id]) +            { +                mItemMap[id]->setSelected(FALSE); +            } +        } +        mSelectedItemIDs.clear(); + +        pasteAsLink(mFolderID, objects, current_outfit_id, marketplacelistings_id, my_outifts_id);      } +    LLClipboard::instance().setCutMode(false); +} + +void LLInventoryGallery::pasteAsLink(const LLUUID& dest, +                                     std::vector<LLUUID>& objects, +                                     const LLUUID& current_outfit_id, +                                     const LLUUID& marketplacelistings_id, +                                     const LLUUID& my_outifts_id) +{      const BOOL move_is_into_current_outfit = (dest == current_outfit_id);      const BOOL move_is_into_my_outfits = (dest == my_outifts_id) || gInventory.isObjectDescendentOf(dest, my_outifts_id);      const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(dest, marketplacelistings_id); @@ -1698,21 +1932,23 @@ void LLInventoryGallery::pasteAsLink()      {          return;      } -    std::vector<LLUUID> objects; -    LLClipboard::instance().pasteFromClipboard(objects); -    LLHandle<LLPanel> handle = getHandle(); -    std::function <void(const LLUUID)> on_link_callback = [handle](const LLUUID& inv_item) +    LLPointer<LLInventoryCallback> cb = NULL; +    if (dest == mFolderID)      { -        LLInventoryGallery *panel = (LLInventoryGallery*)handle.get(); -        if (panel) -        { -            // Scroll to pasted item and highlight it -            // Should it only highlight the last one? -            panel->changeItemSelection(inv_item, true); -        } -    }; -    LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(on_link_callback); +        LLHandle<LLPanel> handle = getHandle(); +        std::function <void(const LLUUID)> on_link_callback = [handle](const LLUUID& inv_item) +            { +                LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); +                if (panel) +                { +                    // Scroll to pasted item and highlight it +                    // Should it only highlight the last one? +                    panel->addItemSelection(inv_item, true); +                } +            }; +        cb = new LLBoostFuncInventoryCallback(on_link_callback); +    }      for (std::vector<LLUUID>::const_iterator iter = objects.begin();           iter != objects.end(); @@ -1724,8 +1960,6 @@ void LLInventoryGallery::pasteAsLink()              link_inventory_object(dest, link_obj, cb);          }      } - -    LLClipboard::instance().setCutMode(false);  }  void LLInventoryGallery::claimEditHandler() @@ -1852,7 +2086,7 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id)          mNeedsArrange = true;      } -    if(mNeedsArrange || mItemToSelect.notNull()) +    if(mNeedsArrange || !mItemsToSelect.empty())      {          // Don't scroll to target/arrange immediately          // since more updates might be pending @@ -1969,7 +2203,7 @@ void LLInventoryGallery::deselectItem(const LLUUID& category_id)          mItemMap[category_id]->setSelected(FALSE);          setFocus(true);          // Todo: support multiselect -        signalSelectionItemID(LLUUID::null); +        // signalSelectionItemID(LLUUID::null);      }      selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), category_id); @@ -1991,6 +2225,7 @@ void LLInventoryGallery::clearSelection()      if (!mSelectedItemIDs.empty())      {          mSelectedItemIDs.clear(); +        // BUG: wrong, item can be null          signalSelectionItemID(LLUUID::null);      }  } @@ -2350,8 +2585,6 @@ void LLInventoryGalleryItem::draw()          border.mTop = border.mTop + 1;          gl_rect_2d(border, border_color.get(), FALSE);      } - -  }  void LLInventoryGalleryItem::setItemName(std::string name) @@ -2379,7 +2612,18 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask)  {      // call changeItemSelection directly, before setFocus      // to avoid autoscroll from LLInventoryGallery::onFocusReceived() -    mGallery->changeItemSelection(mUUID, false); +    if (mask == MASK_CONTROL) +    { +        mGallery->addItemSelection(mUUID, false); +    } +    else if (mask == MASK_SHIFT) +    { +        mGallery->toggleSelectionRangeFromLast(mUUID); +    } +    else +    { +        mGallery->changeItemSelection(mUUID, false); +    }      setFocus(TRUE);      mGallery->claimEditHandler(); @@ -2496,22 +2740,22 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask)      switch (key)      {          case KEY_LEFT: -            mGallery->moveLeft(); +            mGallery->moveLeft(mask);              handled = true;              break;          case KEY_RIGHT: -            mGallery->moveRight(); +            mGallery->moveRight(mask);              handled = true;              break;          case KEY_UP: -            mGallery->moveUp(); +            mGallery->moveUp(mask);              handled = true;              break;          case KEY_DOWN: -            mGallery->moveDown(); +            mGallery->moveDown(mask);              handled = true;              break; @@ -2525,7 +2769,6 @@ void LLInventoryGalleryItem::onFocusLost()  {      // inventory no longer handles cut/copy/paste/delete      mGallery->resetEditHandler(); -    setSelected(false);      LLPanel::onFocusLost();  } @@ -2534,7 +2777,6 @@ void LLInventoryGalleryItem::onFocusReceived()  {      // inventory now handles cut/copy/paste/delete      mGallery->claimEditHandler(); -    setSelected(true);      LLPanel::onFocusReceived();  } @@ -2649,6 +2891,11 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop,  {      LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; +    if (drop && LLToolDragAndDrop::getInstance()->getCargoIndex() == 0) +    { +        clearSelection(); +    } +      BOOL accepted = FALSE;      switch(cargo_type)      { @@ -2669,8 +2916,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop,              if (accepted && drop)              {                  // Don't select immediately, wait for item to arrive -                mItemToSelect = inv_item->getUUID(); -                mNeedsSelection = true; +                mItemsToSelect.push_back(inv_item->getUUID());              }              break;          case DAD_LINK: @@ -2691,8 +2937,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop,              }              if (accepted && drop && inv_item)              { -                mItemToSelect = inv_item->getUUID(); -                mNeedsSelection = true; +                mItemsToSelect.push_back(inv_item->getUUID());              }              break;          case DAD_CATEGORY: @@ -2706,8 +2951,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop,                  accepted = dragCategoryIntoFolder(dest_id, cat_ptr, drop, tooltip_msg, FALSE);                  if (accepted && drop)                  { -                    mItemToSelect = cat_ptr->getUUID(); -                    mNeedsSelection = true; +                    mItemsToSelect.push_back(cat_ptr->getUUID());                  }              }              break; diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index f2e5e38940..44e0dcf960 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -82,10 +82,12 @@ public:                             void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override;      BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;      BOOL handleKeyHere(KEY key, MASK mask) override; -    void moveUp(); -    void moveDown(); -    void moveLeft(); -    void moveRight(); +    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; @@ -130,6 +132,8 @@ public:      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); @@ -174,6 +178,15 @@ public:      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); @@ -185,8 +198,8 @@ protected:      LLGalleryGestureObserver*          mGestureObserver;      LLInventoryObserver*               mInventoryObserver;      selection_deque                    mSelectedItemIDs; -    LLUUID                             mItemToSelect; -    bool                               mNeedsSelection; +    selection_deque                    mItemsToSelect; +    LLUUID                             mLastSelectedUUID;      bool                               mIsInitialized;      bool                               mRootDirty; diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index bca10b9c0e..5f4b816b99 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -51,16 +51,17 @@  LLContextMenu* LLInventoryGalleryContextMenu::createMenu()  {      LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -    //LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -    LLUUID selected_id = mUUIDs.front(); +    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -    registrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryGalleryContextMenu::doToSelected, this, _2, selected_id)); -    registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2, selected_id)); +    registrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryGalleryContextMenu::doToSelected, this, _2)); +    registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2));      registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));      registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); -    std::set<LLUUID> uuids{selected_id}; +    std::set<LLUUID> uuids(mUUIDs.begin(), mUUIDs.end());      registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery))); + +    enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2));      LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml"); @@ -69,49 +70,52 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu()      return menu;  } -void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLUUID& selected_id) +void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)  {      std::string action = userdata.asString(); -    LLInventoryObject* obj = gInventory.getObject(selected_id); +    LLInventoryObject* obj = gInventory.getObject(mUUIDs.front());      if(!obj) return;      if ("open_selected_folder" == action)      { -        mGallery->setRootFolder(selected_id); +        mGallery->setRootFolder(mUUIDs.front());      }      else if ("open_in_new_window" == action)      { -        new_folder_window(selected_id); +        new_folder_window(mUUIDs.front());      }      else if ("properties" == action)      { -        show_item_profile(selected_id); +        show_item_profile(mUUIDs.front());      }      else if ("restore" == action)      { -        LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); -        if(cat) +        for (LLUUID& selected_id : mUUIDs)          { -            const LLUUID new_parent = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); -            // do not restamp children on restore -            gInventory.changeCategoryParent(cat, new_parent, false); -        } -        else -        { -            LLViewerInventoryItem* item = gInventory.getItem(selected_id); -            if(item) +            LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); +            if (cat)              { -                bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); - -                const LLUUID new_parent = gInventory.findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType())); +                const LLUUID new_parent = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));                  // do not restamp children on restore -                gInventory.changeItemParent(item, new_parent, false); +                gInventory.changeCategoryParent(cat, new_parent, false); +            } +            else +            { +                LLViewerInventoryItem* item = gInventory.getItem(selected_id); +                if (item) +                { +                    bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); + +                    const LLUUID new_parent = gInventory.findCategoryUUIDForType(is_snapshot ? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType())); +                    // do not restamp children on restore +                    gInventory.changeItemParent(item, new_parent, false); +                }              }          }      }      else if ("copy_uuid" == action)      { -        LLViewerInventoryItem* item = gInventory.getItem(selected_id); +        LLViewerInventoryItem* item = gInventory.getItem(mUUIDs.front());          if(item)          {              LLUUID asset_id = item->getProtectedAssetUUID(); @@ -123,15 +127,18 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU      }      else if ("purge" == action)      { -        remove_inventory_object(selected_id, NULL); +        for (LLUUID& selected_id : mUUIDs) +        { +            remove_inventory_object(selected_id, NULL); +        }      }      else if ("goto" == action)      { -        show_item_original(selected_id); +        show_item_original(mUUIDs.front());      }      else if ("thumbnail" == action)      { -        LLSD data(selected_id); +        LLSD data(mUUIDs.front());          LLFloaterReg::showInstance("change_item_thumbnail", data);      }      else if ("cut" == action) @@ -165,61 +172,70 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU      }      else if ("rename" == action)      { -        LLSD args; -        args["NAME"] = obj->getName(); - -        LLSD payload; -        payload["id"] = selected_id; - -        LLNotificationsUtil::add("RenameItem", args, payload, boost::bind(onRename, _1, _2)); +        rename(mUUIDs.front());      }      else if ("open" == action || "open_original" == action)      { -        LLViewerInventoryItem* item = gInventory.getItem(selected_id); +        LLViewerInventoryItem* item = gInventory.getItem(mUUIDs.front());          if (item)          { -            LLInvFVBridgeAction::doAction(item->getType(), selected_id , &gInventory); +            LLInvFVBridgeAction::doAction(item->getType(), mUUIDs.front(), &gInventory);          }      }      else if ("ungroup_folder_items" == action)      { -        ungroup_folder_items(selected_id); +        ungroup_folder_items(mUUIDs.front());      }      else if ("take_off" == action || "detach" == action)      { -        LLAppearanceMgr::instance().removeItemFromAvatar(selected_id); +        for (LLUUID& selected_id : mUUIDs) +        { +            LLAppearanceMgr::instance().removeItemFromAvatar(selected_id); +        }      }      else if ("wear_add" == action)      { -        LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, false); // Don't replace if adding. +        for (LLUUID& selected_id : mUUIDs) +        { +            LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, false); // Don't replace if adding. +        }      }      else if ("wear" == action)      { -        LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, true); +        for (LLUUID& selected_id : mUUIDs) +        { +            LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, true); +        }      }      else if ("activate" == action)      { -        LLGestureMgr::instance().activateGesture(selected_id); +        for (LLUUID& selected_id : mUUIDs) +        { +            LLGestureMgr::instance().activateGesture(selected_id); -        LLViewerInventoryItem* item = gInventory.getItem(selected_id); -        if (!item) return; +            LLViewerInventoryItem* item = gInventory.getItem(selected_id); +            if (!item) return; -        gInventory.updateItem(item); +            gInventory.updateItem(item); +        }          gInventory.notifyObservers();      }      else if ("deactivate" == action)      { -        LLGestureMgr::instance().deactivateGesture(selected_id); +        for (LLUUID& selected_id : mUUIDs) +        { +            LLGestureMgr::instance().deactivateGesture(selected_id); -        LLViewerInventoryItem* item = gInventory.getItem(selected_id); -        if (!item) return; +            LLViewerInventoryItem* item = gInventory.getItem(selected_id); +            if (!item) return; -        gInventory.updateItem(item); +            gInventory.updateItem(item); +        }          gInventory.notifyObservers();      }      else if ("replace_links" == action)      { -        LLFloaterReg::showInstance("linkreplace", LLSD(selected_id)); +        LLFloaterReg::showInstance("linkreplace", LLSD(mUUIDs.front()));      }      else if ("copy_slurl" == action)      { @@ -236,7 +252,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU              };              LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true);          }; -        LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, copy_slurl_cb); +        LLLandmark* landmark = LLLandmarkActions::getLandmark(mUUIDs.front(), copy_slurl_cb);          if (landmark)          {              copy_slurl_cb(landmark); @@ -246,7 +262,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU      {          LLSD key;          key["type"] = "landmark"; -        key["id"] = selected_id; +        key["id"] = mUUIDs.front();          LLFloaterSidePanelContainer::showPanel("places", key);      }      else if ("show_on_map" == action) @@ -264,7 +280,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU                  }              }          }; -        LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, show_on_map_cb); +        LLLandmark* landmark = LLLandmarkActions::getLandmark(mUUIDs.front(), show_on_map_cb);          if(landmark)          {              show_on_map_cb(landmark); @@ -272,7 +288,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU      }      else if ("save_as" == action)      { -        LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", selected_id); +        LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", mUUIDs.front());          if (preview_texture)          {              preview_texture->openToSave(); @@ -281,6 +297,20 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU      }  } +void LLInventoryGalleryContextMenu::rename(const LLUUID& item_id) +{ +    LLInventoryObject* obj = gInventory.getObject(item_id); +    if (!obj) return; + +    LLSD args; +    args["NAME"] = obj->getName(); + +    LLSD payload; +    payload["id"] = mUUIDs.front(); + +    LLNotificationsUtil::add("RenameItem", args, payload, boost::bind(onRename, _1, _2)); +} +  void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response)  {      S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -311,25 +341,39 @@ void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLS      }  } -void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id) +void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata)  {      const std::string param = userdata.asString();      if (param == "model")      { -        gSavedPerAccountSettings.setString("ModelUploadFolder", selected_id.asString()); +        gSavedPerAccountSettings.setString("ModelUploadFolder", mUUIDs.front().asString());      }      else if (param == "texture")      { -        gSavedPerAccountSettings.setString("TextureUploadFolder", selected_id.asString()); +        gSavedPerAccountSettings.setString("TextureUploadFolder", mUUIDs.front().asString());      }      else if (param == "sound")      { -        gSavedPerAccountSettings.setString("SoundUploadFolder", selected_id.asString()); +        gSavedPerAccountSettings.setString("SoundUploadFolder", mUUIDs.front().asString());      }      else if (param == "animation")      { -        gSavedPerAccountSettings.setString("AnimationUploadFolder", selected_id.asString()); +        gSavedPerAccountSettings.setString("AnimationUploadFolder", mUUIDs.front().asString()); +    } +} + +bool LLInventoryGalleryContextMenu::canSetUploadLocation(const LLSD& userdata) +{ +    if (mUUIDs.size() != 1) +    { +        return false; +    } +    LLInventoryCategory* cat = gInventory.getCategory(mUUIDs.front()); +    if (!cat) +    { +        return false;      } +    return true;  }  bool is_inbox_folder(LLUUID item_id) diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h index 67cf9a569a..7c3545432b 100644 --- a/indra/newview/llinventorygallerymenu.h +++ b/indra/newview/llinventorygallerymenu.h @@ -39,13 +39,15 @@ public:      bool isRootFolder() { return mRootFolder; }      void setRootFolder(bool is_root) { mRootFolder = is_root; } -    void doToSelected(const LLSD& userdata, const LLUUID& selected_id); +    void doToSelected(const LLSD& userdata); +    void rename(const LLUUID& item_id);  protected:      //virtual void buildContextMenu(class LLMenuGL& menu, U32 flags);      void updateMenuItemsVisibility(LLContextMenu* menu); -    void fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id); +    void fileUploadLocation(const LLSD& userdata); +    bool canSetUploadLocation(const LLSD& userdata);      static void onRename(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml index 46afa3821b..d82c453e5f 100644 --- a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml @@ -453,30 +453,38 @@        <menu_item_call.on_click         function="Inventory.FileUploadLocation"          parameter="texture" /> +      <menu_item_call.on_visible +       function="Inventory.CanSetUploadLocation" />      </menu_item_call>      <menu_item_call       label="Sound uploads"       layout="topleft"       name="Sound uploads"> -    <menu_item_call.on_click -     function="Inventory.FileUploadLocation" -     parameter="sound" /> +      <menu_item_call.on_click +       function="Inventory.FileUploadLocation" +       parameter="sound" /> +      <menu_item_call.on_visible +       function="Inventory.CanSetUploadLocation" />      </menu_item_call>      <menu_item_call       label="Animation uploads"       layout="topleft"       name="Animation uploads"> -    <menu_item_call.on_click -     function="Inventory.FileUploadLocation" -     parameter="animation" /> +      <menu_item_call.on_click +       function="Inventory.FileUploadLocation" +       parameter="animation" /> +      <menu_item_call.on_visible +       function="Inventory.CanSetUploadLocation" />      </menu_item_call>      <menu_item_call       label="Model uploads"       layout="topleft"       name="Model uploads"> -    <menu_item_call.on_click -     function="Inventory.FileUploadLocation" -     parameter="model" /> +      <menu_item_call.on_click +       function="Inventory.FileUploadLocation" +       parameter="model" /> +      <menu_item_call.on_visible +       function="Inventory.CanSetUploadLocation" />      </menu_item_call>    </menu>  	<menu_item_separator  | 
