diff options
author | Merov Linden <merov@lindenlab.com> | 2014-03-06 18:15:51 -0800 |
---|---|---|
committer | Merov Linden <merov@lindenlab.com> | 2014-03-06 18:15:51 -0800 |
commit | a030b30d34ef3152791b123c4f52d4086f3eb549 (patch) | |
tree | 27e77628ed69c53b7eb3ff4c3205eaf10e79a0c0 /indra/newview/llfloateroutbox.cpp | |
parent | c7e2f81bbf299cf884d9e687fc4a7e7f7096c877 (diff) |
DD-4, DD-5, DD-6, DD-7, DD-8: WIP : Add Merchant Items panel and make it somewhat work, in a clunky sort of way
Diffstat (limited to 'indra/newview/llfloateroutbox.cpp')
-rwxr-xr-x | indra/newview/llfloateroutbox.cpp | 395 |
1 files changed, 394 insertions, 1 deletions
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index de96f75602..5ed72e4250 100755 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -1,6 +1,8 @@ /** * @file llfloateroutbox.cpp - * @brief Implementation of the merchant outbox window + * @brief Implementation of the merchant outbox window and of the merchant items window + * + * *TODO : Eventually, take out all the merchant outbox stuff and rename that file to llfloatermerchantitems * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -105,6 +107,39 @@ private: }; ///---------------------------------------------------------------------------- +/// LLMerchantItemsAddedObserver helper class +///---------------------------------------------------------------------------- + +class LLMerchantItemsAddedObserver : public LLInventoryCategoryAddedObserver +{ +public: + LLMerchantItemsAddedObserver(LLFloaterMerchantItems * merchant_items_floater) + : LLInventoryCategoryAddedObserver() + , mMerchantItemsFloater(merchant_items_floater) + { + } + + void done() + { + for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) + { + LLViewerInventoryCategory* added_category = *it; + + LLFolderType::EType added_category_type = added_category->getPreferredType(); + + if (added_category_type == LLFolderType::FT_MERCHANT_ITEMS) + { + mMerchantItemsFloater->initializeMarketPlace(); + } + } + } + +private: + LLFloaterMerchantItems * mMerchantItemsFloater; +}; + + +///---------------------------------------------------------------------------- /// LLFloaterOutbox ///---------------------------------------------------------------------------- @@ -617,3 +652,361 @@ void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) notification_handler->processNotification(notification); } +///---------------------------------------------------------------------------- +/// LLFloaterMerchantItems +///---------------------------------------------------------------------------- + +LLFloaterMerchantItems::LLFloaterMerchantItems(const LLSD& key) +: LLFloater(key) +, mCategoriesObserver(NULL) +, mCategoryAddedObserver(NULL) +, mRootFolderId(LLUUID::null) +, mInventoryPlaceholder(NULL) +, mInventoryText(NULL) +, mInventoryTitle(NULL) +, mTopLevelDropZone(NULL) +{ +} + +LLFloaterMerchantItems::~LLFloaterMerchantItems() +{ + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + } + delete mCategoryAddedObserver; +} + +BOOL LLFloaterMerchantItems::postBuild() +{ + mInventoryPlaceholder = getChild<LLView>("merchant_items_inventory_placeholder_panel"); + mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("merchant_items_inventory_placeholder_text"); + mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("merchant_items_inventory_placeholder_title"); + + mTopLevelDropZone = getChild<LLPanel>("merchant_items_generic_drag_target"); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterMerchantItems::onFocusReceived, this)); + + // Observe category creation to catch merchant items creation (moot if already existing) + mCategoryAddedObserver = new LLMerchantItemsAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + + return TRUE; +} + +void LLFloaterMerchantItems::clean() +{ + // Note: we cannot delete the mOutboxInventoryPanel as that point + // as this is called through callback observers of the panel itself. + // Doing so would crash rapidly. + + // Invalidate the outbox data + mRootFolderId.setNull(); +} + +void LLFloaterMerchantItems::onClose(bool app_quitting) +{ +} + +void LLFloaterMerchantItems::onOpen(const LLSD& key) +{ + // + // Initialize the Market Place or go update the outbox + // + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) + { + initializeMarketPlace(); + } + else + { + setup(); + } + + // + // Update the floater view + // + updateView(); + + // + // Trigger fetch of the contents + // + fetchContents(); +} + +void LLFloaterMerchantItems::onFocusReceived() +{ + fetchContents(); +} + +void LLFloaterMerchantItems::fetchContents() +{ + if (mRootFolderId.notNull()) + { + LLInventoryModelBackgroundFetch::instance().start(mRootFolderId); + } +} + +void LLFloaterMerchantItems::setup() +{ + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) + { + // If we are *not* a merchant or we have no market place connection established yet, do nothing + return; + } + + // We are a merchant. Get the Merchant items folder, create it if needs be. + LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MERCHANT_ITEMS, true); + if (outbox_id.isNull()) + { + // We should never get there unless the inventory fails badly + llinfos << "Merov : Inventory problem: failure to create the merchant items folder for a merchant!" << llendl; + llerrs << "Inventory problem: failure to create the merchant items folder for a merchant!" << llendl; + return; + } + + // Consolidate Merchant items + // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, things get messy and conventions get broken down eventually + gInventory.consolidateForType(outbox_id, LLFolderType::FT_MERCHANT_ITEMS); + + if (outbox_id == mRootFolderId) + { + llinfos << "Merov : Inventory warning: Merchant items folder already set" << llendl; + llwarns << "Inventory warning: Merchant items folder already set" << llendl; + return; + } + mRootFolderId = outbox_id; + + // No longer need to observe new category creation + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + delete mCategoryAddedObserver; + mCategoryAddedObserver = NULL; + } + llassert(!mCategoryAddedObserver); + + // Create observer for merchant items modifications : clear the old one and create a new one + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + delete mCategoriesObserver; + } + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + mCategoriesObserver->addCategory(mRootFolderId, boost::bind(&LLFloaterMerchantItems::onChanged, this)); + llassert(mCategoriesObserver); + + // Set up the merchant items inventory view + LLInventoryPanel* inventory_panel = mInventoryPanel.get(); + if (inventory_panel) + { + delete inventory_panel; + } + inventory_panel = LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_merchant_items_inventory.xml", mInventoryPlaceholder->getParent(), LLInventoryPanel::child_registry_t::instance()); + mInventoryPanel = inventory_panel->getInventoryPanelHandle(); + llassert(mInventoryPanel.get() != NULL); + + // Reshape the inventory to the proper size + LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); + inventory_panel->setShape(inventory_placeholder_rect); + + // Set the sort order newest to oldest + inventory_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + inventory_panel->getFilter().markDefault(); + + // Get the content of the merchant items folder + fetchContents(); +} + +void LLFloaterMerchantItems::initializeMarketPlace() +{ + // *TODO : What do we need to do really once the merchant items folder has been created? + // + // Initialize the marketplace import API + // + //LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance(); + + //if (!importer.isInitialized()) + //{ + //importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2)); + //importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1)); + //importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2)); + //importer.initialize(); + //} +} + +S32 LLFloaterMerchantItems::getFolderCount() +{ + if (mInventoryPanel.get() && mRootFolderId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mRootFolderId, cats, items); + + return (cats->count() + items->count()); + } + else + { + return 0; + } +} + +void LLFloaterMerchantItems::updateView() +{ + LLInventoryPanel* panel = mInventoryPanel.get(); + + if (getFolderCount() > 0) + { + panel->setVisible(TRUE); + mInventoryPlaceholder->setVisible(FALSE); + mTopLevelDropZone->setVisible(TRUE); + } + else + { + if (panel) + { + panel->setVisible(FALSE); + } + + // Show the drop zone if there is an outbox folder + mTopLevelDropZone->setVisible(mRootFolderId.notNull()); + + std::string text; + std::string title; + std::string tooltip; + + const LLSD& subs = getMarketplaceStringSubstitutions(); + U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus(); + + // *TODO : check those messages and create better appropriate ones in strings.xml + if (mRootFolderId.notNull()) + { + // Does the outbox needs recreation? + if ((panel == NULL) || !gInventory.getCategory(mRootFolderId)) + { + setup(); + } + // "Merchant items is empty!" message strings + text = LLTrans::getString("InventoryMerchantItemsNoItems", subs); + title = LLTrans::getString("InventoryMerchantItemsNoItemsTitle"); + tooltip = LLTrans::getString("InventoryMerchantItemsNoItemsTooltip"); + } + else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) + { + // "Initializing!" message strings + text = LLTrans::getString("InventoryOutboxInitializing", subs); + title = LLTrans::getString("InventoryOutboxInitializingTitle"); + tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); + } + else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) + { + // "Not a merchant!" message strings + text = LLTrans::getString("InventoryOutboxNotMerchant", subs); + title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + else + { + // "Errors!" message strings + text = LLTrans::getString("InventoryOutboxError", subs); + title = LLTrans::getString("InventoryOutboxErrorTitle"); + tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + } + + mInventoryText->setValue(text); + mInventoryTitle->setValue(title); + mInventoryPlaceholder->getParent()->setToolTip(tooltip); + } +} + +bool LLFloaterMerchantItems::isAccepted(EAcceptance accept) +{ + // *TODO : Need a bit more test on what we accept: depends of what and where... + return (accept >= ACCEPT_YES_COPY_SINGLE); +} + + +BOOL LLFloaterMerchantItems::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if ((mInventoryPanel.get() == NULL) || + mRootFolderId.isNull()) + { + return FALSE; + } + + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + + // Determine if the mouse is inside the inventory panel itself or just within the floater + bool pointInInventoryPanel = false; + bool pointInInventoryPanelChild = false; + LLInventoryPanel* panel = mInventoryPanel.get(); + LLFolderView* root_folder = panel->getRootFolder(); + if (panel->getVisible()) + { + S32 inv_x, inv_y; + localPointToOtherView(x, y, &inv_x, &inv_y, panel); + + pointInInventoryPanel = panel->getRect().pointInRect(inv_x, inv_y); + + LLView * inventory_panel_child_at_point = panel->childFromPoint(inv_x, inv_y, true); + pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder); + } + + // Pass all drag and drop for this floater to the outbox inventory control + if (!handled || !isAccepted(*accept)) + { + // Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel + // (otherwise the inventory panel itself will handle the drag and drop operation, without any override) + if (!pointInInventoryPanel) + { + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + mTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept)); + } + else + { + mTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild); + } + + return handled; +} + +BOOL LLFloaterMerchantItems::handleHover(S32 x, S32 y, MASK mask) +{ + mTopLevelDropZone->setBackgroundVisible(FALSE); + + return LLFloater::handleHover(x, y, mask); +} + +void LLFloaterMerchantItems::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mTopLevelDropZone->setBackgroundVisible(FALSE); + + LLFloater::onMouseLeave(x, y, mask); +} + +void LLFloaterMerchantItems::onChanged() +{ + LLViewerInventoryCategory* category = gInventory.getCategory(mRootFolderId); + if (mRootFolderId.notNull() && category) + { + fetchContents(); + updateView(); + } + else + { + clean(); + } +} |