llcurrencyuimanager.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "lluictrlfactory.h"
00035 #include "lltextbox.h"
00036 #include "lllineeditor.h"
00037 
00038 #include "llcurrencyuimanager.h"
00039 
00040 // viewer includes
00041 #include "llagent.h"
00042 #include "llconfirmationmanager.h"
00043 #include "llframetimer.h"
00044 #include "lllineeditor.h"
00045 #include "llviewchildren.h"
00046 #include "llxmlrpctransaction.h"
00047 #include "llappviewer.h"
00048 
00049 
00050 const F64 CURRENCY_ESTIMATE_FREQUENCY = 2.0;
00051         // how long of a pause in typing a currency buy amount before an
00052         // esimate is fetched from the server
00053 
00054 class LLCurrencyUIManager::Impl
00055 {
00056 public:
00057         Impl(LLPanel& dialog);
00058         virtual ~Impl();
00059 
00060         LLPanel&                mPanel;
00061 
00062         bool                    mHidden;
00063         
00064         bool                    mError;
00065         std::string             mErrorMessage;
00066         std::string             mErrorURI;
00067         
00068         std::string             mZeroMessage;
00069         
00070         // user's choices
00071         S32                             mUserCurrencyBuy;
00072         bool                    mUserEnteredCurrencyBuy;
00073         
00074         // from website
00075         bool                    mSiteCurrencyEstimated;
00076         S32                             mSiteCurrencyEstimatedCost;
00077         std::string             mSiteConfirm;
00078         
00079         bool                    mBought;
00080         
00081         enum TransactionType
00082         {
00083                 TransactionNone,
00084                 TransactionCurrency,
00085                 TransactionBuy
00086         };
00087 
00088         TransactionType          mTransactionType;
00089         LLXMLRPCTransaction* mTransaction;
00090         
00091         bool             mCurrencyChanged;
00092         LLFrameTimer mCurrencyKeyTimer;
00093 
00094 
00095         void updateCurrencyInfo();
00096         void finishCurrencyInfo();
00097         
00098         void startCurrencyBuy(const std::string& password);
00099         void finishCurrencyBuy();
00100         
00101         void startTransaction(TransactionType type,
00102                 const char* method, LLXMLRPCValue params);
00103         bool checkTransaction();
00104                 // return true if update needed
00105         
00106         void setError(const std::string& message, const std::string& uri);
00107         void clearError();
00108 
00109         bool considerUpdateCurrency();
00110                 // return true if update needed
00111         void currencyKey(S32);
00112         static void onCurrencyKey(LLLineEditor* caller, void* data);    
00113 
00114         void prepare();
00115         void updateUI();
00116 };
00117 
00118 // is potentially not fully constructed.
00119 LLCurrencyUIManager::Impl::Impl(LLPanel& dialog)
00120         : mPanel(dialog),
00121         mHidden(false),
00122         mError(false),
00123         mUserCurrencyBuy(1000), mUserEnteredCurrencyBuy(false),
00124         mSiteCurrencyEstimated(false),
00125         mBought(false),
00126         mTransactionType(TransactionNone), mTransaction(0),
00127         mCurrencyChanged(false)
00128 {
00129 }
00130 
00131 LLCurrencyUIManager::Impl::~Impl()
00132 {
00133         delete mTransaction;
00134 }
00135 
00136 void LLCurrencyUIManager::Impl::updateCurrencyInfo()
00137 {
00138         mSiteCurrencyEstimated = false;
00139         mSiteCurrencyEstimatedCost = 0;
00140         mBought = false;
00141         mCurrencyChanged = false;
00142 
00143         if (mUserCurrencyBuy == 0)
00144         {
00145                 mSiteCurrencyEstimated = true;
00146                 return;
00147         }
00148         
00149         LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
00150         keywordArgs.appendString("agentId", gAgent.getID().asString());
00151         keywordArgs.appendString(
00152                 "secureSessionId",
00153                 gAgent.getSecureSessionID().asString());
00154         keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
00155         
00156         LLXMLRPCValue params = LLXMLRPCValue::createArray();
00157         params.append(keywordArgs);
00158 
00159         startTransaction(TransactionCurrency, "getCurrencyQuote", params);
00160 }
00161 
00162 void LLCurrencyUIManager::Impl::finishCurrencyInfo()
00163 {
00164         LLXMLRPCValue result = mTransaction->responseValue();
00165 
00166         bool success = result["success"].asBool();
00167         if (!success)
00168         {
00169                 setError(
00170                         result["errorMessage"].asString(),
00171                         result["errorURI"].asString()
00172                 );
00173                 return;
00174         }
00175         
00176         LLXMLRPCValue currency = result["currency"];
00177         mSiteCurrencyEstimated = true;
00178         mSiteCurrencyEstimatedCost = currency["estimatedCost"].asInt();
00179         
00180         S32 newCurrencyBuy = currency["currencyBuy"].asInt();
00181         if (newCurrencyBuy != mUserCurrencyBuy)
00182         {
00183                 mUserCurrencyBuy = newCurrencyBuy;
00184                 mUserEnteredCurrencyBuy = false;
00185         }
00186 
00187         mSiteConfirm = result["confirm"].asString();
00188 }
00189 
00190 void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
00191 {
00192         mSiteCurrencyEstimated = false;
00193         mSiteCurrencyEstimatedCost = 0;
00194         mCurrencyChanged = false;
00195         
00196         LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
00197         keywordArgs.appendString("agentId", gAgent.getID().asString());
00198         keywordArgs.appendString(
00199                 "secureSessionId",
00200                 gAgent.getSecureSessionID().asString());
00201         keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
00202         keywordArgs.appendInt("estimatedCost", mSiteCurrencyEstimatedCost);
00203         keywordArgs.appendString("confirm", mSiteConfirm);
00204         if (!password.empty())
00205         {
00206                 keywordArgs.appendString("password", password);
00207         }
00208         
00209         LLXMLRPCValue params = LLXMLRPCValue::createArray();
00210         params.append(keywordArgs);
00211 
00212         startTransaction(TransactionBuy, "buyCurrency", params);
00213 }
00214 
00215 void LLCurrencyUIManager::Impl::finishCurrencyBuy()
00216 {
00217         LLXMLRPCValue result = mTransaction->responseValue();
00218 
00219         bool success = result["success"].asBool();
00220         if (!success)
00221         {
00222                 setError(
00223                         result["errorMessage"].asString(),
00224                         result["errorURI"].asString()
00225                 );
00226         }
00227         else
00228         {
00229                 mUserCurrencyBuy = 0;
00230                 mUserEnteredCurrencyBuy = false;
00231                 mBought = true;
00232         }
00233 }
00234 
00235 void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
00236                 const char* method, LLXMLRPCValue params)
00237 {
00238         static std::string transactionURI;
00239         if (transactionURI.empty())
00240         {
00241                 transactionURI = LLAppViewer::instance()->getHelperURI() + "currency.php";
00242         }
00243 
00244         delete mTransaction;
00245 
00246         mTransactionType = type;
00247         mTransaction = new LLXMLRPCTransaction(
00248                 transactionURI,
00249                 method,
00250                 params,
00251                 false /* don't use gzip */
00252                 );
00253 
00254         clearError();
00255 }
00256 
00257 bool LLCurrencyUIManager::Impl::checkTransaction()
00258 {
00259         if (!mTransaction)
00260         {
00261                 return false;
00262         }
00263         
00264         if (!mTransaction->process())
00265         {
00266                 return false;
00267         }
00268 
00269         if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete)
00270         {
00271                 setError(mTransaction->statusMessage(), mTransaction->statusURI());
00272         }
00273         else {
00274                 switch (mTransactionType)
00275                 {       
00276                         case TransactionCurrency:       finishCurrencyInfo();   break;
00277                         case TransactionBuy:            finishCurrencyBuy();    break;
00278                         default: ;
00279                 }
00280         }
00281         
00282         delete mTransaction;
00283         mTransaction = NULL;
00284         mTransactionType = TransactionNone;
00285         
00286         return true;
00287 }
00288 
00289 void LLCurrencyUIManager::Impl::setError(
00290         const std::string& message, const std::string& uri)
00291 {
00292         mError = true;
00293         mErrorMessage = message;
00294         mErrorURI = uri;
00295 }
00296 
00297 void LLCurrencyUIManager::Impl::clearError()
00298 {
00299         mError = false;
00300         mErrorMessage.clear();
00301         mErrorURI.clear();
00302 }
00303 
00304 bool LLCurrencyUIManager::Impl::considerUpdateCurrency()
00305 {
00306         if (mCurrencyChanged
00307         &&  !mTransaction 
00308         &&  mCurrencyKeyTimer.getElapsedTimeF32() >= CURRENCY_ESTIMATE_FREQUENCY)
00309         {
00310                 updateCurrencyInfo();
00311                 return true;
00312         }
00313 
00314         return false;
00315 }
00316 
00317 void LLCurrencyUIManager::Impl::currencyKey(S32 value)
00318 {
00319         mUserEnteredCurrencyBuy = true;
00320         mCurrencyKeyTimer.reset();
00321 
00322         if (mUserCurrencyBuy == value)
00323         {
00324                 return;
00325         }
00326 
00327         mUserCurrencyBuy = value;
00328         
00329         if (mSiteCurrencyEstimated) {
00330                 mSiteCurrencyEstimated = false;
00331                 //cannot just simply refresh the whole UI, as the edit field will
00332                 // get reset and the cursor will change...
00333                 
00334                 mPanel.childHide("currency_est");
00335                 mPanel.childSetVisible("getting_data",TRUE);
00336         }
00337         
00338         mCurrencyChanged = true;
00339 }
00340 
00341 // static
00342 void LLCurrencyUIManager::Impl::onCurrencyKey(
00343                 LLLineEditor* caller, void* data)
00344 {
00345         S32 value = atoi(caller->getText().c_str());
00346         LLCurrencyUIManager::Impl* self = (LLCurrencyUIManager::Impl*)data;
00347         self->currencyKey(value);
00348 }
00349 
00350 void LLCurrencyUIManager::Impl::prepare()
00351 {
00352         LLLineEditor* lindenAmount = mPanel.getChild<LLLineEditor>("currency_amt");
00353         if (lindenAmount)
00354         {
00355                 lindenAmount->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
00356                 lindenAmount->setKeystrokeCallback(onCurrencyKey);
00357                 lindenAmount->setCallbackUserData(this);
00358         }
00359 }
00360 
00361 void LLCurrencyUIManager::Impl::updateUI()
00362 {
00363         if (mHidden)
00364         {
00365                 mPanel.childHide("currency_action");
00366                 mPanel.childHide("currency_amt");
00367                 mPanel.childHide("currency_est");
00368                 return;
00369         }
00370 
00371         mPanel.childShow("currency_action");
00372 
00373         LLLineEditor* lindenAmount = mPanel.getChild<LLLineEditor>("currency_amt");
00374         if (lindenAmount) 
00375         {
00376                 lindenAmount->setVisible(true);
00377                 lindenAmount->setLabel(mZeroMessage);
00378                 
00379                 if (!mUserEnteredCurrencyBuy)
00380                 {
00381                         if (!mZeroMessage.empty() && mUserCurrencyBuy == 0)
00382                         {
00383                                 lindenAmount->setText(LLString::null);
00384                         }
00385                         else
00386                         {
00387                                 lindenAmount->setText(llformat("%d", mUserCurrencyBuy));
00388                         }
00389 
00390                         lindenAmount->selectAll();
00391                 }
00392         }
00393 
00394         mPanel.childSetTextArg("currency_est", "[USD]", llformat("%#.2f", mSiteCurrencyEstimatedCost / 100.0));
00395         mPanel.childSetVisible("currency_est", mSiteCurrencyEstimated && mUserCurrencyBuy > 0);
00396 
00397         if (mPanel.childIsEnabled("buy_btn")
00398                 ||mPanel.childIsVisible("currency_est")
00399                 || mPanel.childIsVisible("error_web"))
00400         {
00401                 mPanel.childSetVisible("getting_data",FALSE);
00402         }
00403 }
00404 
00405 
00406 
00407 LLCurrencyUIManager::LLCurrencyUIManager(LLPanel& dialog)
00408         : impl(* new Impl(dialog))
00409 {
00410 }
00411 
00412 LLCurrencyUIManager::~LLCurrencyUIManager()
00413 {
00414         delete &impl;
00415 }
00416 
00417 void LLCurrencyUIManager::setAmount(int amount, bool noEstimate)
00418 {
00419         impl.mUserCurrencyBuy = amount;
00420         impl.mUserEnteredCurrencyBuy = false;
00421         impl.updateUI();
00422         
00423         impl.mCurrencyChanged = !noEstimate;
00424 }
00425 
00426 int LLCurrencyUIManager::getAmount()
00427 {
00428         return impl.mUserCurrencyBuy;
00429 }
00430 
00431 void LLCurrencyUIManager::setZeroMessage(const std::string& message)
00432 {
00433         impl.mZeroMessage = message;
00434 }
00435 
00436 void LLCurrencyUIManager::setEstimate(int amount)
00437 {
00438         impl.mSiteCurrencyEstimatedCost = amount;
00439         impl.mSiteCurrencyEstimated = true;
00440         impl.updateUI();
00441         
00442         impl.mCurrencyChanged = false;
00443 }
00444 
00445 int LLCurrencyUIManager::getEstimate()
00446 {
00447         return impl.mSiteCurrencyEstimated ? impl.mSiteCurrencyEstimatedCost : 0;
00448 }
00449 
00450 void LLCurrencyUIManager::prepare()
00451 {
00452         impl.prepare();
00453 }
00454 
00455 void LLCurrencyUIManager::updateUI(bool show)
00456 {
00457         impl.mHidden = !show;
00458         impl.updateUI();
00459 }
00460 
00461 bool LLCurrencyUIManager::process()
00462 {
00463         bool changed = false;
00464         changed |= impl.checkTransaction();
00465         changed |= impl.considerUpdateCurrency();
00466         return changed;
00467 }
00468 
00469 void LLCurrencyUIManager::buy(const LLString& buy_msg)
00470 {
00471         if (!canBuy())
00472         {
00473                 return;
00474         }
00475 
00476         LLUIString msg = buy_msg;
00477         msg.setArg("[LINDENS]", llformat("%d", impl.mUserCurrencyBuy));
00478         msg.setArg("[USD]", llformat("%#.2f", impl.mSiteCurrencyEstimatedCost / 100.0));
00479         LLConfirmationManager::confirm(impl.mSiteConfirm,
00480                                                                    msg,
00481                                                                    impl,
00482                                                                    &LLCurrencyUIManager::Impl::startCurrencyBuy);
00483 }
00484 
00485 
00486 bool LLCurrencyUIManager::inProcess()
00487 {
00488         return impl.mTransactionType != Impl::TransactionNone;
00489 }
00490 
00491 bool LLCurrencyUIManager::canCancel()
00492 {
00493         return impl.mTransactionType != Impl::TransactionBuy;
00494 }
00495 
00496 bool LLCurrencyUIManager::canBuy()
00497 {
00498         return impl.mTransactionType == Impl::TransactionNone
00499                 && impl.mSiteCurrencyEstimated
00500                 && impl.mUserCurrencyBuy > 0;
00501 }
00502 
00503 bool LLCurrencyUIManager::buying()
00504 {
00505         return impl.mTransactionType == Impl::TransactionBuy;
00506 }
00507 
00508 bool LLCurrencyUIManager::bought()
00509 {
00510         return impl.mBought;
00511 }
00512 
00513 bool LLCurrencyUIManager::hasError()
00514 {
00515         return impl.mError;
00516 }
00517 
00518 std::string LLCurrencyUIManager::errorMessage()
00519 {
00520         return impl.mErrorMessage;
00521 }
00522 
00523 std::string LLCurrencyUIManager::errorURI()
00524 {
00525         return impl.mErrorURI;
00526 }
00527 
00528 

Generated on Fri May 16 08:33:16 2008 for SecondLife by  doxygen 1.5.5