summaryrefslogtreecommitdiff
path: root/indra/newview/llviewermessage.cpp
diff options
context:
space:
mode:
authorMike Antipov <mantipov@productengine.com>2010-04-08 12:07:58 +0300
committerMike Antipov <mantipov@productengine.com>2010-04-08 12:07:58 +0300
commit00462c243116e2720acf51ee1f777e69e8189f33 (patch)
tree3181ab28309b7e488fb41b948b2cd575ae5a41e5 /indra/newview/llviewermessage.cpp
parent8ce661ae5d2a49bf120534769741932785cffb37 (diff)
Fixed normal bug EXT-4347 (Moving object contents to inventory opens files, changes menu)
Implementation details: * Added new LLViewerInventoryMoveFromWorldObserver to watch moved items via their Asses UUIDs. It is instantiated only once due to drop events are sent separately for each item while multi-dragging. * Existent LLOpenTaskOffer observer uses it to exclude watched by LLViewerInventoryMoveFromWorldObserver items from own processing. * Removed dependancy on LLPanelPlaces in open_inventory_offer(). Openning of offered LM via group notice moved into an appropriate section (processed by LLOpenTaskGroupOffer) Known Issues: * If Script item is among the dragged items from object to inventory it will be the only selected item in the inventory panel. Reason: it does not have its own Asset UUID and processed via LLOpenTaskOffer when should not. Reviewed by Leyla and Richard at https://codereview.productengine.com/secondlife/r/116/ --HG-- branch : product-engine
Diffstat (limited to 'indra/newview/llviewermessage.cpp')
-rw-r--r--indra/newview/llviewermessage.cpp212
1 files changed, 187 insertions, 25 deletions
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index c542459cdb..2b41a83ba5 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -71,7 +71,6 @@
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llpanelgrouplandmoney.h"
-#include "llpanelplaces.h"
#include "llrecentpeople.h"
#include "llscriptfloater.h"
#include "llselectmgr.h"
@@ -692,6 +691,52 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
return false;
}
+
+static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
+{
+ if (NULL == inventory_panel) return;
+
+ for (std::vector<LLUUID>::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
+ {
+ const LLUUID& item_id = (*item_iter);
+ if(!highlight_offered_item(item_id))
+ {
+ continue;
+ }
+
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ llassert(item);
+ if (!item) {
+ continue;
+ }
+
+ LL_DEBUGS("Inventory_Move") << "Highlighting inventory item: " << item->getName() << ", " << item_id << LL_ENDL;
+ LLFolderView* fv = inventory_panel->getRootFolder();
+ if (fv)
+ {
+ LLFolderViewItem* fv_item = fv->getItemByID(item_id);
+ if (fv_item)
+ {
+ LLFolderViewItem* fv_folder = fv_item->getParentFolder();
+ if (fv_folder)
+ {
+ // Parent folders can be different in case of 2 consecutive drag and drop
+ // operations when the second one is started before the first one completes.
+ LL_DEBUGS("Inventory_Move") << "Open folder: " << fv_folder->getName() << LL_ENDL;
+ fv_folder->setOpen(TRUE);
+ if (fv_folder->isSelected())
+ {
+ fv->changeSelection(fv_folder, FALSE);
+ }
+ }
+ fv->changeSelection(fv_item, TRUE);
+ }
+ }
+ }
+}
+
static LLNotificationFunctorRegistration jgr_1("JoinGroup", join_group_response);
static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember", join_group_response);
static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_response);
@@ -714,6 +759,108 @@ private:
std::string mFromName;
};
+/**
+ * Class to observe adding of new items moved from the world to user's inventory to select them in inventory.
+ *
+ * We can't create it each time items are moved because "drop" event is sent separately for each
+ * element even while multi-dragging. We have to have the only instance of the observer. See EXT-4347.
+ */
+class LLViewerInventoryMoveFromWorldObserver : public LLInventoryMoveFromWorldObserver
+{
+public:
+ LLViewerInventoryMoveFromWorldObserver()
+ : LLInventoryMoveFromWorldObserver()
+ , mActivePanel(NULL)
+ {
+
+ }
+
+ void setMoveIntoFolderID(const LLUUID& into_folder_uuid) {mMoveIntoFolderID = into_folder_uuid; }
+
+private:
+ /*virtual */void onAssetAdded(const LLUUID& asset_id)
+ {
+ // Store active Inventory panel.
+ mActivePanel = LLInventoryPanel::getActiveInventoryPanel();
+
+ // Store selected items (without destination folder)
+ mSelectedItems.clear();
+ mActivePanel->getRootFolder()->getSelectionList(mSelectedItems);
+ mSelectedItems.erase(mMoveIntoFolderID);
+ }
+
+ /**
+ * Selects added inventory items watched by their Asset UUIDs if selection was not changed since
+ * all items were started to watch (dropped into a folder).
+ */
+ void done()
+ {
+ // if selection is not changed since watch started lets hightlight new items.
+ if (mActivePanel && !isSelectionChanged())
+ {
+ LL_DEBUGS("Inventory_Move") << "Selecting new items..." << LL_ENDL;
+ mActivePanel->clearSelection();
+ highlight_inventory_items_in_panel(mAddedItems, mActivePanel);
+ }
+ }
+
+ /**
+ * Returns true if selected inventory items were changed since moved inventory items were started to watch.
+ */
+ bool isSelectionChanged()
+ {
+ const LLInventoryPanel * const current_active_panel = LLInventoryPanel::getActiveInventoryPanel();
+
+ if (NULL == mActivePanel || current_active_panel != mActivePanel)
+ {
+ return true;
+ }
+
+ // get selected items (without destination folder)
+ selected_items_t selected_items;
+ mActivePanel->getRootFolder()->getSelectionList(selected_items);
+ selected_items.erase(mMoveIntoFolderID);
+
+ // compare stored & current sets of selected items
+ selected_items_t different_items;
+ std::set_symmetric_difference(mSelectedItems.begin(), mSelectedItems.end(),
+ selected_items.begin(), selected_items.end(), std::inserter(different_items, different_items.begin()));
+
+ LL_DEBUGS("Inventory_Move") << "Selected firstly: " << mSelectedItems.size()
+ << ", now: " << selected_items.size() << ", difference: " << different_items.size() << LL_ENDL;
+
+ return different_items.size() > 0;
+ }
+
+ LLInventoryPanel *mActivePanel;
+ typedef std::set<LLUUID> selected_items_t;
+ selected_items_t mSelectedItems;
+
+ /**
+ * UUID of FolderViewFolder into which watched items are moved.
+ *
+ * Destination FolderViewFolder becomes selected while mouse hovering (when dragged items are dropped).
+ *
+ * If mouse is moved out it set unselected and number of selected items is changed
+ * even if selected items in Inventory stay the same.
+ * So, it is used to update stored selection list.
+ *
+ * @see onAssetAdded()
+ * @see isSelectionChanged()
+ */
+ LLUUID mMoveIntoFolderID;
+};
+
+LLViewerInventoryMoveFromWorldObserver* gInventoryMoveObserver = NULL;
+
+void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid)
+{
+ start_new_inventory_observer();
+
+ gInventoryMoveObserver->setMoveIntoFolderID(into_folder_uuid);
+ gInventoryMoveObserver->watchAsset(inv_item->getAssetUUID());
+}
+
//unlike the FetchObserver for AgentOffer, we only make one
//instance of the AddedObserver for TaskOffers
//and it never dies. We do this because we don't know the UUID of
@@ -724,6 +871,33 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
protected:
/*virtual*/ void done()
{
+ for (uuid_vec_t::iterator it = mAdded.begin(); it != mAdded.end();)
+ {
+ const LLUUID& item_uuid = *it;
+ bool was_moved = false;
+ LLInventoryObject* added_object = gInventory.getObject(item_uuid);
+ if (added_object)
+ {
+ // cast to item to get Asset UUID
+ LLInventoryItem* added_item = dynamic_cast<LLInventoryItem*>(added_object);
+ if (added_item)
+ {
+ const LLUUID& asset_uuid = added_item->getAssetUUID();
+ if (gInventoryMoveObserver->isAssetWatched(asset_uuid))
+ {
+ LL_DEBUGS("Inventory_Move") << "Found asset UUID: " << asset_uuid << LL_ENDL;
+ was_moved = true;
+ }
+ }
+ }
+
+ if (was_moved)
+ {
+ it = mAdded.erase(it);
+ }
+ else ++it;
+ }
+
open_inventory_offer(mAdded, "");
mAdded.clear();
}
@@ -752,6 +926,13 @@ void start_new_inventory_observer()
gNewInventoryObserver = new LLOpenTaskOffer;
gInventory.addObserver(gNewInventoryObserver);
}
+
+ if (!gInventoryMoveObserver) //inventory move from the world observer
+ {
+ // Observer is deleted by gInventory
+ gInventoryMoveObserver = new LLViewerInventoryMoveFromWorldObserver;
+ gInventory.addObserver(gInventoryMoveObserver);
+ }
}
class LLDiscardAgentOffer : public LLInventoryFetchComboObserver
@@ -916,9 +1097,12 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name)
}
else if("group_offer" == from_name)
{
- // do not open inventory when we open group notice attachment because
- // we already opened landmark info panel
// "group_offer" is passed by LLOpenTaskGroupOffer
+ // Notification about added landmark will be generated under the "from_name.empty()" called from LLOpenTaskOffer::done().
+ LLSD args;
+ args["type"] = "landmark";
+ args["id"] = item_id;
+ LLSideTray::getInstance()->showPanel("panel_places", args);
continue;
}
@@ -929,28 +1113,6 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name)
args["LANDMARK_NAME"] = item->getName();
args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown");
LLNotificationsUtil::add("LandmarkCreated", args);
- // Created landmark is passed to Places panel to allow its editing. In fact panel should be already displayed.
- // If the panel is closed we don't reopen it until created landmark is loaded.
- //TODO*:: dserduk(7/12/09) remove LLPanelPlaces dependency from here
- LLPanelPlaces *places_panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->getPanel("panel_places"));
- if (places_panel)
- {
- // Landmark creation handling is moved to LLPanelPlaces::showAddedLandmarkInfo()
- // TODO* LLPanelPlaces dependency is going to be removed. See EXT-4347.
- //if("create_landmark" == places_panel->getPlaceInfoType() && !places_panel->getItem())
- //{
- // places_panel->setItem(item);
- //}
- //else
- // we are opening a group notice attachment
- if("create_landmark" != places_panel->getPlaceInfoType())
- {
- LLSD args;
- args["type"] = "landmark";
- args["id"] = item_id;
- LLSideTray::getInstance()->showPanel("panel_places", args);
- }
- }
}
}
break;