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
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
00052
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
00071 S32 mUserCurrencyBuy;
00072 bool mUserEnteredCurrencyBuy;
00073
00074
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
00105
00106 void setError(const std::string& message, const std::string& uri);
00107 void clearError();
00108
00109 bool considerUpdateCurrency();
00110
00111 void currencyKey(S32);
00112 static void onCurrencyKey(LLLineEditor* caller, void* data);
00113
00114 void prepare();
00115 void updateUI();
00116 };
00117
00118
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
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
00332
00333
00334 mPanel.childHide("currency_est");
00335 mPanel.childSetVisible("getting_data",TRUE);
00336 }
00337
00338 mCurrencyChanged = true;
00339 }
00340
00341
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