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

Generated on Thu Jul 1 06:08:23 2010 for Second Life Viewer by  doxygen 1.4.7