Files
SingularityViewer/indra/newview/llcurrencyuimanager.cpp
2012-07-17 19:27:14 +02:00

538 lines
12 KiB
C++

/**
* @file llcurrencyuimanager.cpp
* @brief LLCurrencyUIManager class implementation
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lluictrlfactory.h"
#include "lltextbox.h"
#include "lllineeditor.h"
#include "llcurrencyuimanager.h"
// viewer includes
#include "llagent.h"
#include "llconfirmationmanager.h"
#include "llframetimer.h"
#include "lllineeditor.h"
#include "llviewchildren.h"
#include "llxmlrpctransaction.h"
#include "llviewernetwork.h"
#include "hippogridmanager.h"
const F64 CURRENCY_ESTIMATE_FREQUENCY = 2.0;
// how long of a pause in typing a currency buy amount before an
// esimate is fetched from the server
class LLCurrencyUIManager::Impl
{
public:
Impl(LLPanel& dialog);
virtual ~Impl();
LLPanel& mPanel;
bool mHidden;
bool mError;
std::string mErrorMessage;
std::string mErrorURI;
std::string mZeroMessage;
// user's choices
S32 mUserCurrencyBuy;
bool mUserEnteredCurrencyBuy;
// from website
bool mSiteCurrencyEstimated;
S32 mSiteCurrencyEstimatedCost;
std::string mSiteConfirm;
bool mBought;
enum TransactionType
{
TransactionNone,
TransactionCurrency,
TransactionBuy
};
TransactionType mTransactionType;
LLXMLRPCTransaction* mTransaction;
bool mCurrencyChanged;
LLFrameTimer mCurrencyKeyTimer;
void updateCurrencyInfo();
void finishCurrencyInfo();
void startCurrencyBuy(const std::string& password);
void finishCurrencyBuy();
void startTransaction(TransactionType type,
const char* method, LLXMLRPCValue params);
bool checkTransaction();
// return true if update needed
void setError(const std::string& message, const std::string& uri);
void clearError();
bool considerUpdateCurrency();
// return true if update needed
void currencyKey(S32);
static void onCurrencyKey(LLLineEditor* caller, void* data);
void prepare();
void updateUI();
};
// is potentially not fully constructed.
LLCurrencyUIManager::Impl::Impl(LLPanel& dialog)
: mPanel(dialog),
mHidden(false),
mError(false),
mUserCurrencyBuy(2000), // note, this is a default, real value set in llfloaterbuycurrency.cpp
mUserEnteredCurrencyBuy(false),
mSiteCurrencyEstimated(false),
mSiteCurrencyEstimatedCost(0),
mBought(false),
mTransactionType(TransactionNone), mTransaction(0),
mCurrencyChanged(false)
{
}
LLCurrencyUIManager::Impl::~Impl()
{
delete mTransaction;
}
void LLCurrencyUIManager::Impl::updateCurrencyInfo()
{
mSiteCurrencyEstimated = false;
mSiteCurrencyEstimatedCost = 0;
mBought = false;
mCurrencyChanged = false;
if (mUserCurrencyBuy == 0)
{
mSiteCurrencyEstimated = true;
return;
}
LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
keywordArgs.appendString("agentId", gAgent.getID().asString());
keywordArgs.appendString(
"secureSessionId",
gAgent.getSecureSessionID().asString());
keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
LLXMLRPCValue params = LLXMLRPCValue::createArray();
params.append(keywordArgs);
startTransaction(TransactionCurrency, "getCurrencyQuote", params);
}
void LLCurrencyUIManager::Impl::finishCurrencyInfo()
{
LLXMLRPCValue result = mTransaction->responseValue();
bool success = result["success"].asBool();
if (!success)
{
setError(
result["errorMessage"].asString(),
result["errorURI"].asString()
);
return;
}
LLXMLRPCValue currency = result["currency"];
mSiteCurrencyEstimated = true;
mSiteCurrencyEstimatedCost = currency["estimatedCost"].asInt();
S32 newCurrencyBuy = currency["currencyBuy"].asInt();
if (newCurrencyBuy != mUserCurrencyBuy)
{
mUserCurrencyBuy = newCurrencyBuy;
mUserEnteredCurrencyBuy = false;
}
mSiteConfirm = result["confirm"].asString();
}
void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
{
mSiteCurrencyEstimated = false;
mSiteCurrencyEstimatedCost = 0;
mCurrencyChanged = false;
LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
keywordArgs.appendString("agentId", gAgent.getID().asString());
keywordArgs.appendString(
"secureSessionId",
gAgent.getSecureSessionID().asString());
keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
keywordArgs.appendInt("estimatedCost", mSiteCurrencyEstimatedCost);
keywordArgs.appendString("confirm", mSiteConfirm);
if (!password.empty())
{
keywordArgs.appendString("password", password);
}
LLXMLRPCValue params = LLXMLRPCValue::createArray();
params.append(keywordArgs);
startTransaction(TransactionBuy, "buyCurrency", params);
}
void LLCurrencyUIManager::Impl::finishCurrencyBuy()
{
LLXMLRPCValue result = mTransaction->responseValue();
bool success = result["success"].asBool();
if (!success)
{
setError(
result["errorMessage"].asString(),
result["errorURI"].asString()
);
}
else
{
mUserCurrencyBuy = 0;
mUserEnteredCurrencyBuy = false;
mBought = true;
}
}
void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
const char* method, LLXMLRPCValue params)
{
static std::string transactionURI;
if (transactionURI.empty())
{
transactionURI = LLViewerLogin::getInstance()->getHelperURI() + "currency.php";
}
delete mTransaction;
mTransactionType = type;
mTransaction = new LLXMLRPCTransaction(
transactionURI,
method,
params,
false /* don't use gzip */
);
clearError();
}
bool LLCurrencyUIManager::Impl::checkTransaction()
{
if (!mTransaction)
{
return false;
}
if (!mTransaction->is_finished())
{
return false;
}
if (mTransaction->status(NULL) != LLXMLRPCTransaction::StatusComplete)
{
setError(mTransaction->statusMessage(), mTransaction->statusURI());
}
else {
switch (mTransactionType)
{
case TransactionCurrency: finishCurrencyInfo(); break;
case TransactionBuy: finishCurrencyBuy(); break;
default: ;
}
}
delete mTransaction;
mTransaction = NULL;
mTransactionType = TransactionNone;
return true;
}
void LLCurrencyUIManager::Impl::setError(
const std::string& message, const std::string& uri)
{
mError = true;
mErrorMessage = message;
mErrorURI = uri;
}
void LLCurrencyUIManager::Impl::clearError()
{
mError = false;
mErrorMessage.clear();
mErrorURI.clear();
}
bool LLCurrencyUIManager::Impl::considerUpdateCurrency()
{
if (mCurrencyChanged
&& !mTransaction
&& mCurrencyKeyTimer.getElapsedTimeF32() >= CURRENCY_ESTIMATE_FREQUENCY)
{
updateCurrencyInfo();
return true;
}
return false;
}
void LLCurrencyUIManager::Impl::currencyKey(S32 value)
{
mUserEnteredCurrencyBuy = true;
mCurrencyKeyTimer.reset();
if (mUserCurrencyBuy == value)
{
return;
}
mUserCurrencyBuy = value;
if (mSiteCurrencyEstimated) {
mSiteCurrencyEstimated = false;
//cannot just simply refresh the whole UI, as the edit field will
// get reset and the cursor will change...
mPanel.childHide("currency_est");
mPanel.childSetVisible("getting_data",TRUE);
}
mCurrencyChanged = true;
}
// static
void LLCurrencyUIManager::Impl::onCurrencyKey(
LLLineEditor* caller, void* data)
{
S32 value = atoi(caller->getText().c_str());
LLCurrencyUIManager::Impl* self = (LLCurrencyUIManager::Impl*)data;
self->currencyKey(value);
}
void LLCurrencyUIManager::Impl::prepare()
{
LLLineEditor* lindenAmount = mPanel.getChild<LLLineEditor>("currency_amt");
if (lindenAmount)
{
lindenAmount->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
lindenAmount->setKeystrokeCallback(onCurrencyKey);
lindenAmount->setCallbackUserData(this);
}
}
void LLCurrencyUIManager::Impl::updateUI()
{
if (mHidden)
{
mPanel.childHide("currency_action");
mPanel.childHide("currency_amt");
mPanel.childHide("currency_est");
return;
}
mPanel.childShow("currency_action");
mPanel.childSetTextArg("currency_action", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol());
LLLineEditor* lindenAmount = mPanel.getChild<LLLineEditor>("currency_amt");
if (lindenAmount)
{
lindenAmount->setVisible(true);
lindenAmount->setLabel(mZeroMessage);
if (!mUserEnteredCurrencyBuy)
{
if (!mZeroMessage.empty() && mUserCurrencyBuy == 0)
{
lindenAmount->setText(LLStringUtil::null);
}
else
{
lindenAmount->setText(llformat("%d", mUserCurrencyBuy));
}
lindenAmount->selectAll();
}
}
mPanel.childSetTextArg("currency_est", "[USD]", llformat("%#.2f", mSiteCurrencyEstimatedCost / 100.0));
mPanel.childSetVisible("currency_est", mSiteCurrencyEstimated && mUserCurrencyBuy > 0);
if (mPanel.childIsEnabled("buy_btn")
||mPanel.childIsVisible("currency_est")
|| mPanel.childIsVisible("error_web"))
{
mPanel.childSetVisible("getting_data",FALSE);
}
}
LLCurrencyUIManager::LLCurrencyUIManager(LLPanel& dialog)
: impl(* new Impl(dialog))
{
}
LLCurrencyUIManager::~LLCurrencyUIManager()
{
delete &impl;
}
void LLCurrencyUIManager::setAmount(int amount, bool noEstimate)
{
impl.mUserCurrencyBuy = amount;
impl.mUserEnteredCurrencyBuy = false;
impl.updateUI();
impl.mCurrencyChanged = !noEstimate;
}
int LLCurrencyUIManager::getAmount()
{
return impl.mUserCurrencyBuy;
}
void LLCurrencyUIManager::setZeroMessage(const std::string& message)
{
impl.mZeroMessage = message;
}
void LLCurrencyUIManager::setEstimate(int amount)
{
impl.mSiteCurrencyEstimatedCost = amount;
impl.mSiteCurrencyEstimated = true;
impl.updateUI();
impl.mCurrencyChanged = false;
}
int LLCurrencyUIManager::getEstimate()
{
return impl.mSiteCurrencyEstimated ? impl.mSiteCurrencyEstimatedCost : 0;
}
void LLCurrencyUIManager::prepare()
{
impl.prepare();
}
void LLCurrencyUIManager::updateUI(bool show)
{
impl.mHidden = !show;
impl.updateUI();
}
bool LLCurrencyUIManager::process()
{
bool changed = false;
changed |= impl.checkTransaction();
changed |= impl.considerUpdateCurrency();
return changed;
}
void LLCurrencyUIManager::buy(const std::string& buy_msg)
{
if (!canBuy())
{
return;
}
LLUIString msg = buy_msg;
msg.setArg("[LINDENS]", llformat("%d", impl.mUserCurrencyBuy));
msg.setArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol());
msg.setArg("[USD]", llformat("%#.2f", impl.mSiteCurrencyEstimatedCost / 100.0));
msg.setArg("[REALCURRENCY]", gHippoGridManager->getConnectedGrid()->getRealCurrencySymbol());
LLConfirmationManager::confirm(impl.mSiteConfirm,
msg,
impl,
&LLCurrencyUIManager::Impl::startCurrencyBuy);
}
bool LLCurrencyUIManager::inProcess()
{
return impl.mTransactionType != Impl::TransactionNone;
}
bool LLCurrencyUIManager::canCancel()
{
return impl.mTransactionType != Impl::TransactionBuy;
}
bool LLCurrencyUIManager::canBuy()
{
return impl.mTransactionType == Impl::TransactionNone
&& impl.mSiteCurrencyEstimated
&& impl.mUserCurrencyBuy > 0;
}
bool LLCurrencyUIManager::buying()
{
return impl.mTransactionType == Impl::TransactionBuy;
}
bool LLCurrencyUIManager::bought()
{
return impl.mBought;
}
bool LLCurrencyUIManager::hasError()
{
return impl.mError;
}
std::string LLCurrencyUIManager::errorMessage()
{
return impl.mErrorMessage;
}
std::string LLCurrencyUIManager::errorURI()
{
return impl.mErrorURI;
}