From 4ad7d4b7504b491d5d7f30e7901cee5171fdbfe0 Mon Sep 17 00:00:00 2001 From: Christopher Colosi Date: Wed, 20 Sep 2017 16:00:25 -0700 Subject: [PATCH] Support for multiple currency solutions on a grid and across the hypergrid. --- indra/llcommon/tea.cpp | 29 ++++++++++-- indra/llcommon/tea.h | 22 +++++++-- indra/llui/llbutton.h | 5 +++ indra/llui/llfloater.h | 5 +++ indra/llui/lltextbox.h | 5 +++ indra/llui/lluistring.h | 7 +++ indra/newview/fsgridhandler.cpp | 7 +++ indra/newview/lfsimfeaturehandler.cpp | 62 +++++++++++++++++++++++++- indra/newview/lfsimfeaturehandler.h | 22 +++++++++ indra/newview/llbuycurrencyhtml.cpp | 11 ++++- indra/newview/llcurrencyuimanager.cpp | 14 +++--- indra/newview/llfloaterbuycurrency.cpp | 31 +++++++++++++ indra/newview/llfloaterbuycurrency.h | 6 +++ indra/newview/llfloaterbuyland.cpp | 14 +++--- indra/newview/llstartup.cpp | 14 ++++++ indra/newview/llstatusbar.cpp | 24 ++++++++++ indra/newview/llstatusbar.h | 5 +++ 17 files changed, 264 insertions(+), 19 deletions(-) diff --git a/indra/llcommon/tea.cpp b/indra/llcommon/tea.cpp index 0bb68c9d43..3d9828b9a2 100644 --- a/indra/llcommon/tea.cpp +++ b/indra/llcommon/tea.cpp @@ -34,7 +34,9 @@ #include -std::string Tea::sCurrency="L$"; +std::string Tea::sGridCurrency="L$"; +std::string Tea::sRegionCurrency=""; +std::string Tea::sActiveCurrency="L$"; Tea::Tea() { @@ -45,12 +47,33 @@ Tea::~Tea() { } +void Tea::setCurrency(const std::string& currency) +{ + sGridCurrency = currency; + updateActiveCurrencySymbol(); +} + +void Tea::setRegionCurrency(const std::string& currency) +{ + sRegionCurrency = currency; + updateActiveCurrencySymbol(); +} + +void Tea::updateActiveCurrencySymbol() +{ + if(!sRegionCurrency.empty()) { + sActiveCurrency = sRegionCurrency; + } else { + sActiveCurrency = sGridCurrency; + } +} + std::string Tea::wrapCurrency(const std::string& to_substitute) { - return boost::algorithm::replace_all_copy(to_substitute, "L$", sCurrency); + return boost::algorithm::replace_all_copy(to_substitute, "L$", sActiveCurrency); } void Tea::wrapCurrency(std::string& to_substitute) { - boost::algorithm::replace_all(to_substitute, "L$", sCurrency); + boost::algorithm::replace_all(to_substitute, "L$", sActiveCurrency); } diff --git a/indra/llcommon/tea.h b/indra/llcommon/tea.h index 1e02eb914a..eaed2d1936 100644 --- a/indra/llcommon/tea.h +++ b/indra/llcommon/tea.h @@ -41,12 +41,28 @@ public: Tea(); ~Tea(); - static void setCurrency(const std::string& currency) { sCurrency = currency; } - static std::string getCurrency() { return sCurrency; } + static void setCurrency(const std::string& currency); + static void setRegionCurrency(const std::string& currency); + static std::string getCurrency() { return sActiveCurrency; } static std::string wrapCurrency(const std::string& to_substitute); static void wrapCurrency(std::string& to_substitute); private: - static std::string sCurrency; + static std::string sGridCurrency; // Grid wide default currency symbol eg: L$, G$, D$ + static std::string sRegionCurrency; // Region currency symbol override; empty string means use grid symbol + static std::string sActiveCurrency; // Active currency symbol (Grid if region is empty string) + + static void updateActiveCurrencySymbol(); // Updated on... + // Startup to L$ (default set at top of cpp) + // Login to Grid Currency (see llstartup) + // HG teleport to new Grid Currency (hopefully also llstartup) + // Entering region with currency module override to Region Currency (see lfsimfeaturehandler) + // Ideally, this would trigger an update to mark any LLUIStrings with L$ + // symbols but without params to dirty to force re-execution and do any + // necessary reloads of UI widgets, but llcommon really should include + // systems from newview, so we've placed this function in lfsimfeaturehandler + // and call it manually. Aternatively, we could consider registering + // that func with Tea to let Tea call it, but for the timebeing, I did + // not want to complicate Tea which is rather simple. }; #endif //TEA_H diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 54439d93d1..fde59f5d9f 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -286,6 +286,11 @@ public: void setAutoResize(bool auto_resize) { mAutoResize = auto_resize; } + // + // Set all LLUIStrings to dirty after currency symbol change to force them to be updated. + void updateCurrencySymbols() { mUnselectedLabel.updateCurrencySymbols(); mSelectedLabel.updateCurrencySymbols(); mDisabledSelectedLabel.updateCurrencySymbols(); } + // + protected: LLPointer getImageUnselected() const { return mImageUnselected; } LLPointer getImageSelected() const { return mImageSelected; } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index ab09aa965b..5b7fc16a2d 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -373,6 +373,11 @@ public: void enableResizeCtrls(bool enable, bool width = true, bool height = true); bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } + + // + // update currency symbols in titles (if there) and force update of display + void updateCurrencySymbols() { mTitle.updateCurrencySymbols(); mShortTitle.updateCurrencySymbols(); applyTitle(); } + // protected: void applyControlsAndPosition(LLFloater* other); diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 062727fda6..14927756a8 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -68,6 +68,11 @@ public: /*virtual*/ LLSD getValue() const; /*virtual*/ BOOL setTextArg( const std::string& key, const LLStringExplicit& text ); + // + // Set all LLUIStrings to dirty after currency symbol change to force them to be updated. + void updateCurrencySymbols() { mText.updateCurrencySymbols(); LLTextBase::setText(mText.getString()); mLabel.updateCurrencySymbols(); } + // + protected: void onUrlLabelUpdated(const std::string &url, const std::string &label); diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index 07e02de6d8..55a202bef6 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -90,6 +90,13 @@ public: void insert(S32 charidx, const LLWString& wchars); void replace(S32 charidx, llwchar wc); + // + // Need a public method for setting an lluistring to dirty when we change + // currency symbols. This will force the text to be re-wrapped on the next + // get call with Tea::wrapCurrency() + void updateCurrencySymbols() { dirty(); } + // + private: // something changed, requiring reformatting of strings void dirty(); diff --git a/indra/newview/fsgridhandler.cpp b/indra/newview/fsgridhandler.cpp index f487bd83f0..50c2314ee3 100644 --- a/indra/newview/fsgridhandler.cpp +++ b/indra/newview/fsgridhandler.cpp @@ -48,6 +48,7 @@ #include "llstartup.h" #include "fscorehttputil.h" +#include "lfsimfeaturehandler.h" // void downloadError( LLSD const &aData, LLGridManager* mOwner, GridEntry* mData, LLGridManager::AddState mState ) { @@ -1137,6 +1138,12 @@ std::string LLGridManager::getHelperURI() { return cmd_line_helper_uri; } + // + std::string helperUriOverride = LFSimFeatureHandler::getInstance()->helperUriOverride(); + if(!helperUriOverride.empty()) { + return helperUriOverride; + } + // > return mGridList[mGrid][GRID_HELPER_URI_VALUE]; } diff --git a/indra/newview/lfsimfeaturehandler.cpp b/indra/newview/lfsimfeaturehandler.cpp index daa9b68a34..1c743f9fad 100644 --- a/indra/newview/lfsimfeaturehandler.cpp +++ b/indra/newview/lfsimfeaturehandler.cpp @@ -25,6 +25,12 @@ #include "llviewernetwork.h" #include "llviewerregion.h" +// +#include "tea.h" +#include "llstatusbar.h" +#include "llfloaterbuycurrency.h" +// + LFSimFeatureHandler::LFSimFeatureHandler() : mSupportsExport(false), mSayRange(20), @@ -56,17 +62,26 @@ void LFSimFeatureHandler::handleRegionChange() { if (LLViewerRegion* region = gAgent.getRegion()) { - if (region->capabilitiesReceived()) + if (region->simulatorFeaturesReceived()) { setSupportedFeatures(); } else { - region->setCapabilitiesReceivedCallback(boost::bind(&LFSimFeatureHandler::setSupportedFeatures, this)); + region->setSimulatorFeaturesReceivedCallback(boost::bind(&LFSimFeatureHandler::onSimulatorFeaturesReceived,this,_1)); } } } +void LFSimFeatureHandler::onSimulatorFeaturesReceived(const LLUUID ®ion_id) +{ + LLViewerRegion *region = gAgent.getRegion(); + if (region && (region->getRegionID()==region_id)) + { + setSupportedFeatures(); + } +} + void LFSimFeatureHandler::setSupportedFeatures() { if (LLViewerRegion* region = gAgent.getRegion()) @@ -150,6 +165,20 @@ void LFSimFeatureHandler::setSupportedFeatures() { mAvatarPickerURL = LLStringUtil::null; } + + // + if (extras.has("currency-base-uri")) { + mHelperUriOverride = extras["currency-base-uri"].asString(); + } else { + mHelperUriOverride = LLStringUtil::null; + } + + if (extras.has("currency")) { + mCurrencySymbolOverride = extras["currency"].asString(); + } else { + mCurrencySymbolOverride = LLStringUtil::null; + } + // } else // OpenSim specifics are unsupported reset all to default { @@ -198,13 +227,42 @@ void LFSimFeatureHandler::setSupportedFeatures() { mAvatarPickerURL = LLStringUtil::null; } + + // + mHelperUriOverride = LLStringUtil::null; + mCurrencySymbolOverride = LLStringUtil::null; + // > } mHasAvatarPicker = !avatarPickerURL().empty(); mHasDestinationGuide = !destinationGuideURL().empty(); + + // + std::string prevCurrencySymbol = Tea::getCurrency(); + Tea::setRegionCurrency(mCurrencySymbolOverride); + std::string newCurrencySymbol = Tea::getCurrency(); + // If currency symbol has changed, then update things + if (newCurrencySymbol != prevCurrencySymbol) { + LFSimFeatureHandler::updateCurrencySymbols(); + } + // } } +// +//static +void LFSimFeatureHandler::updateCurrencySymbols() +{ + // Update the static ui for the buy_currency_floater xml version; html version may require additional work. + LLFloaterBuyCurrency::updateCurrencySymbols(); + // Update the necessary compontents of the status bar panel + if (gStatusBar != NULL) { + gStatusBar->updateCurrencySymbols(); + } + // TODO: What else needs to be updated? +} +// + boost::signals2::connection LFSimFeatureHandler::setSupportsExportCallback(const boost::signals2::signal::slot_type& slot) { return mSupportsExport.connect(slot); diff --git a/indra/newview/lfsimfeaturehandler.h b/indra/newview/lfsimfeaturehandler.h index e2caf0c99c..6a2d600bb9 100644 --- a/indra/newview/lfsimfeaturehandler.h +++ b/indra/newview/lfsimfeaturehandler.h @@ -61,7 +61,19 @@ class LFSimFeatureHandler : public LLSingleton public: void handleRegionChange(); + void onSimulatorFeaturesReceived(const LLUUID ®ion_id); void setSupportedFeatures(); + // + // public helper to manage all the manual updates in one place callable from other systems like llstartup. + // Should be called whenever the sActiveCurrency in Tea is changed, but can't simply be called from Tea + // because that is an llcommon include and really shouldn't call out to newview system. + // updating the currency in Tea updates any dynamic LLUIStrings automatically when a param is replaced on the next get call, + // but static LLUIStrings for floaters/panels/etc pre-loaded are only evaluated once, so these need to be manually updated + // after we update the currency symbol in Tea. This function handles that. As we discover more UI components which we've + // missed, they can be added to this function. For now, it primaily handles the status panel (top bar) and the buy currency floater. + // If there is a better location for this function, we could move it. + static void updateCurrencySymbols(); + // // Connection setters boost::signals2::connection setSupportsExportCallback(const boost::signals2::signal::slot_type& slot); @@ -91,6 +103,11 @@ public: bool hasAvatarPicker() const { return mHasAvatarPicker; } bool hasDestinationGuide() const { return mHasDestinationGuide; } + // + std::string helperUriOverride() const { return mHelperUriOverride; } + std::string currencySymbolOverride() const { return mCurrencySymbolOverride; } + // + private: // SignaledTypes SignaledType mSupportsExport; @@ -109,6 +126,11 @@ private: bool mHasAvatarPicker; bool mHasDestinationGuide; + + // + std::string mHelperUriOverride; + std::string mCurrencySymbolOverride; + // > }; #endif //LFSIMFEATUREHANDLER_H diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index 1c69dadb12..a4f549b83c 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -35,6 +35,8 @@ #include "llviewercontrol.h" #include "llstatusbar.h" +#include "tea.h" > + // support for secondlife:///app/buycurrencyhtml/{ACTION}/{NEXT_ACTION}/{RETURN_CODE} SLapps class LLBuyCurrencyHTMLHandler : public LLCommandHandler @@ -132,7 +134,14 @@ void LLBuyCurrencyHTML::showDialog( bool specific_sum_requested, const std::stri if ( buy_currency_floater ) { // pass on flag indicating if we want to buy specific amount and if so, how much - buy_currency_floater->setParams( specific_sum_requested, message, sum ); + // + // Unclear if html version is used or if message will ever include "L$".. + // Message is stored as a std::string, not an LLUIString, in indra/newview/llfloaterbuycurrencyhtml.cpp + // As long as this is set every time it is displayed, we can just wrap it as below, but if not, + // then we should convert this to an LLUIString, unwrap it here so it stores with "L$" and + // update it on retrieval. + // + buy_currency_floater->setParams( specific_sum_requested, Tea::wrapCurrency(message), sum ); // force navigate to new URL buy_currency_floater->navigateToFinalURL(); diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index b4a1457f47..f8fc2a40ea 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -279,11 +279,15 @@ void LLCurrencyUIManager::Impl::finishCurrencyBuy() void LLCurrencyUIManager::Impl::startTransaction(TransactionType type, const char* method, LLXMLRPCValue params) { - static std::string transactionURI; - if (transactionURI.empty()) - { - transactionURI = LLGridManager::getInstance()->getHelperURI() + "currency.php"; - } + // + // Previously, transactionURI was a static local var only set once. This needs + // to update on HG teleport or crossing regions to a new currency module. + // Set every time as this action should be infrequent and efficient. + // However, we can alternatively make this a static member variable and + // update it when the currency system changes + std::string transactionURI; + transactionURI = LLGridManager::getInstance()->getHelperURI() + "currency.php"; + // delete mTransaction; diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 91436e52fe..5ebd6ad861 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -265,6 +265,11 @@ void LLFloaterBuyCurrencyUI::updateUI() void LLFloaterBuyCurrencyUI::onClickBuy() { + // + // Do not wrap the "buy_currency" string because it is the mOrig later stored + // in an LLUIString with params and will be wrapped when params are inserted. + // wrapping here would break multi-currency support as it would remove the L$ + //> mManager.buy(getString("buy_currency")); updateUI(); // Update L$ balance @@ -298,8 +303,34 @@ void LLFloaterBuyCurrency::buyCurrency() void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price) { LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance("buy_currency"); + // + // Not wrapping name here because according to llfloaterbuycurrency.h + // name should not include currency symbols as the price will be appended to the string. + // If an "L$" is ever included in a name, then we should call Tea::wrapCurrency on it here. + // > ui->target(name, price); ui->updateUI(); } +// +// static +void LLFloaterBuyCurrency::updateCurrencySymbols() +{ + LLFloater* fbc = LLFloaterReg::findInstance("buy_currency"); + if (fbc != NULL) { + // Call update on the floater to update the title + fbc->updateCurrencySymbols(); + // update all text boxes with currency symbols. + LLTextBox* tb; + static const std::list sctb = { "info_need_more", "info_buying", "currency_label", "purchase_warning_repurchase", "purchase_warning_notenough" }; + // Do not include balance_amount and total_amount because they are updated on every display when amounts are replaced. + for (std::list::const_iterator iter = sctb.begin(); iter != sctb.end(); ++iter) { + tb = fbc->getChild(*iter); + if (tb != NULL) { + tb->updateCurrencySymbols(); + } + } + } +} +// diff --git a/indra/newview/llfloaterbuycurrency.h b/indra/newview/llfloaterbuycurrency.h index 7ff6c42384..3fdacea4de 100644 --- a/indra/newview/llfloaterbuycurrency.h +++ b/indra/newview/llfloaterbuycurrency.h @@ -44,6 +44,12 @@ public: */ static LLFloater* buildFloater(const LLSD& key); + + // + // Necessary because floater was designed to build only on first display. + // Forces refresh of all currency symbols in floater when called. + static void updateCurrencySymbols(); + // }; diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 0a0e5ffc06..b373ba0f12 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -858,11 +858,15 @@ void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCVa mTransactionType = type; // Select a URI and method appropriate for the transaction type. - static std::string transaction_uri; - if (transaction_uri.empty()) - { - transaction_uri = LLGridManager::getInstance()->getHelperURI() + "landtool.php"; - } + // + // Previously, transaction_uri was a static local var only set once. This needs + // to update on HG teleport or crossing regions to a new currency module. + // Set every time as this action should be infrequent and efficient. + // However, we can alternatively make this a static member variable and + // update it when the currency system changes + std::string transaction_uri; + transaction_uri = LLGridManager::getInstance()->getHelperURI() + "landtool.php"; + // const char* method; switch (mTransactionType) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1a76f505ae..50c378f401 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -4518,6 +4518,10 @@ bool process_login_success_response(U32 &first_sim_size_x, U32 &first_sim_size_y } // + // + std::string prev_currency_symbol = Tea::getCurrency(); + // + // std::string currency = "L$"; #ifdef OPENSIM // @@ -4534,6 +4538,16 @@ bool process_login_success_response(U32 &first_sim_size_x, U32 &first_sim_size_y Tea::setCurrency(currency); // + // + // Blank out the region currency which is set in in lfsimfeatureshandler + Tea::setRegionCurrency(LLStringUtil::null); + std::string new_currency_symbol = Tea::getCurrency(); + // If currency symbol has changed, update currency symbols where manually necessary. + if (new_currency_symbol != prev_currency_symbol) { + LFSimFeatureHandler::updateCurrencySymbols(); + } + // + // if(response.has("avatar_picker_url")) { diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 0a9b976892..7cc902a66f 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -718,6 +718,16 @@ void LLStatusBar::setBalance(S32 balance) std::string label_str = getString("buycurrencylabel", string_args); mBoxBalance->setValue(label_str); + // + // Unclear if call to getTextBoundingRect updates text but assuming it calls length() + // when getting the bounding box which will update the text and get the length of the + // wrapped (Tea::wrapCurrency) text (see lluistring). If not, and currency symbols + // that are not two characters have the wrong size bounding rect, then the correct + // place to fix this is in the getTextBoundingRect() function, not here. + // buy_rect below should be properly set to dirty() when we modify the currency and + // should also be updated and wrapped before width is determined. + // + // Resize the L$ balance background to be wide enough for your balance plus the buy button { const S32 HPAD = 24; @@ -1054,6 +1064,20 @@ void LLStatusBar::showBalance(bool show) mBoxBalance->setVisible(show); } +// +void LLStatusBar::updateCurrencySymbols() +{ + // Update "Buy L$" button because it is only evaluated once when panel is loaded + LLButton* buyButton = getChild("buyL"); + if (buyButton != NULL) { + buyButton->updateCurrencySymbols(); + } + // Should not need to update the balance display because it is updated frequently. + // If it does require an update, do so via a balance update request so we don't + // switch the symbol without updating the balance. +} +// + void LLStatusBar::onBandwidthGraphButtonClicked() { if (gSavedSettings.getBOOL("FSUseStatsInsteadOfLagMeter")) diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 1a8c8a0788..a8f389dc63 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -152,6 +152,11 @@ public: void showBalance(bool show); // Hide currency balance in snapshots + // + // force update of the "BUY L$" button when currency symbol is changed. + void updateCurrencySymbols(); + // + private: void onClickBuyCurrency();