/** * @file llfloaterbuycurrency.cpp * @brief LLFloaterBuyCurrency class implementation * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llfloaterbuycurrency.h" // viewer includes #include "llcurrencyuimanager.h" #include "llfloater.h" #include "llfloaterreg.h" #include "lllayoutstack.h" #include "lliconctrl.h" #include "llnotificationsutil.h" #include "llstatusbar.h" #include "lltextbox.h" #include "llviewchildren.h" #include "llviewerwindow.h" #include "lluictrlfactory.h" #include "llweb.h" #include "llwindow.h" #include "llappviewer.h" static const S32 MINIMUM_BALANCE_AMOUNT = 0; class LLFloaterBuyCurrencyUI : public LLFloater { public: LLFloaterBuyCurrencyUI(const LLSD& key); virtual ~LLFloaterBuyCurrencyUI(); public: LLViewChildren mChildren; LLCurrencyUIManager mManager; bool mHasTarget; S32 mTargetPrice; S32 mRequiredAmount; public: void noTarget(); void target(const std::string& name, S32 price); virtual BOOL postBuild(); void updateUI(); void collapsePanels(bool collapse); virtual void draw(); virtual BOOL canClose(); void onClickBuy(); void onClickCancel(); }; LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key) { LLFloaterBuyCurrencyUI* floater = new LLFloaterBuyCurrencyUI(key); return floater; } #if LL_WINDOWS // passing 'this' during construction generates a warning. The callee // only uses the pointer to hold a reference to 'this' which is // already valid, so this call does the correct thing. Disable the // warning so that we can compile without generating a warning. #pragma warning(disable : 4355) #endif LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI(const LLSD& key) : LLFloater(key), mChildren(*this), mManager(*this), mHasTarget(false), mTargetPrice(0) { } LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI() { } void LLFloaterBuyCurrencyUI::noTarget() { mHasTarget = false; mTargetPrice = 0; mManager.setAmount(0); } void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price) { mHasTarget = true; mTargetPrice = price; if (!name.empty()) { getChild<LLUICtrl>("target_price_label")->setValue(name); } S32 balance = gStatusBar->getBalance(); S32 need = price - balance; if (need < 0) { need = 0; } mRequiredAmount = need + MINIMUM_BALANCE_AMOUNT; mManager.setAmount(0); } // virtual BOOL LLFloaterBuyCurrencyUI::postBuild() { mManager.prepare(); getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this)); getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this)); center(); updateUI(); return TRUE; } void LLFloaterBuyCurrencyUI::draw() { if (mManager.process()) { if (mManager.bought()) { LLNotificationsUtil::add("BuyLindenDollarSuccess"); closeFloater(); return; } updateUI(); } // disable the Buy button when we are not able to buy getChildView("buy_btn")->setEnabled(mManager.canBuy()); LLFloater::draw(); } BOOL LLFloaterBuyCurrencyUI::canClose() { return mManager.canCancel(); } void LLFloaterBuyCurrencyUI::updateUI() { bool hasError = mManager.hasError(); mManager.updateUI(!hasError && !mManager.buying()); // hide most widgets - we'll turn them on as needed next getChildView("info_buying")->setVisible(FALSE); getChildView("info_need_more")->setVisible(FALSE); getChildView("purchase_warning_repurchase")->setVisible(FALSE); getChildView("purchase_warning_notenough")->setVisible(FALSE); getChildView("contacting")->setVisible(FALSE); if (hasError) { // display an error from the server LLSD args; args["TITLE"] = getString("info_cannot_buy"); args["MESSAGE"] = mManager.errorMessage(); LLNotificationsUtil::add("CouldNotBuyCurrency", args); mManager.clearError(); closeFloater(); } else { // display the main Buy L$ interface getChildView("normal_background")->setVisible(TRUE); if (mHasTarget) { getChildView("info_need_more")->setVisible(TRUE); } else { getChildView("info_buying")->setVisible(TRUE); } if (mManager.buying()) { getChildView("contacting")->setVisible( true); } else { if (mHasTarget) { getChild<LLUICtrl>("target_price")->setTextArg("[AMT]", llformat("%d", mTargetPrice)); getChild<LLUICtrl>("required_amount")->setTextArg("[AMT]", llformat("%d", mRequiredAmount)); } } S32 balance = gStatusBar->getBalance(); getChildView("balance_label")->setVisible(TRUE); getChildView("balance_amount")->setVisible(TRUE); getChild<LLUICtrl>("balance_amount")->setTextArg("[AMT]", llformat("%d", balance)); S32 buying = mManager.getAmount(); getChildView("buying_label")->setVisible(TRUE); getChildView("buying_amount")->setVisible(TRUE); getChild<LLUICtrl>("buying_amount")->setTextArg("[AMT]", llformat("%d", buying)); S32 total = balance + buying; getChildView("total_label")->setVisible(TRUE); getChildView("total_amount")->setVisible(TRUE); getChild<LLUICtrl>("total_amount")->setTextArg("[AMT]", llformat("%d", total)); if (mHasTarget) { getChildView("purchase_warning_repurchase")->setVisible( !getChildView("currency_links")->getVisible()); } } getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError && !getChildView("currency_est")->getVisible()); } void LLFloaterBuyCurrencyUI::collapsePanels(bool collapse) { LLLayoutPanel* price_panel = getChild<LLLayoutPanel>("layout_panel_price"); if (price_panel->isCollapsed() == collapse) return; LLLayoutStack* outer_stack = getChild<LLLayoutStack>("outer_stack"); LLLayoutPanel* required_panel = getChild<LLLayoutPanel>("layout_panel_required"); LLLayoutPanel* msg_panel = getChild<LLLayoutPanel>("layout_panel_msg"); S32 delta_height = price_panel->getRect().getHeight() + required_panel->getRect().getHeight() + msg_panel->getRect().getHeight(); delta_height *= (collapse ? -1 : 1); LLIconCtrl* icon = getChild<LLIconCtrl>("normal_background"); LLRect rect = icon->getRect(); icon->setRect(rect.setOriginAndSize(rect.mLeft, rect.mBottom - delta_height, rect.getWidth(), rect.getHeight() + delta_height)); outer_stack->collapsePanel(price_panel, collapse); outer_stack->collapsePanel(required_panel, collapse); outer_stack->collapsePanel(msg_panel, collapse); outer_stack->updateLayout(); LLRect floater_rect = getRect(); floater_rect.mBottom -= delta_height; setShape(floater_rect, false); } void LLFloaterBuyCurrencyUI::onClickBuy() { mManager.buy(getString("buy_currency")); updateUI(); // Update L$ balance LLStatusBar::sendMoneyBalanceRequest(); } void LLFloaterBuyCurrencyUI::onClickCancel() { closeFloater(); // Update L$ balance LLStatusBar::sendMoneyBalanceRequest(); } LLFetchAvatarPaymentInfo* LLFloaterBuyCurrency::sPropertiesRequest = NULL; // static void LLFloaterBuyCurrency::buyCurrency() { delete sPropertiesRequest; sPropertiesRequest = new LLFetchAvatarPaymentInfo(false); } // static void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price) { delete sPropertiesRequest; sPropertiesRequest = new LLFetchAvatarPaymentInfo(true, name, price); } // static void LLFloaterBuyCurrency::handleBuyCurrency(bool has_piof, bool has_target, const std::string name, S32 price) { delete sPropertiesRequest; sPropertiesRequest = NULL; if (has_piof) { LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency"); if (has_target) { ui->target(name, price); } else { ui->noTarget(); } ui->updateUI(); ui->collapsePanels(!has_target); } else { LLFloaterReg::showInstance("add_payment_method"); } } LLFetchAvatarPaymentInfo::LLFetchAvatarPaymentInfo(bool has_target, const std::string& name, S32 price) : mAvatarID(gAgent.getID()), mHasTarget(has_target), mPrice(price), mName(name) { LLAvatarPropertiesProcessor* processor = LLAvatarPropertiesProcessor::getInstance(); // register ourselves as an observer processor->addObserver(mAvatarID, this); // send a request (duplicates will be suppressed inside the avatar // properties processor) processor->sendAvatarPropertiesRequest(mAvatarID); } LLFetchAvatarPaymentInfo::~LLFetchAvatarPaymentInfo() { LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarID, this); } void LLFetchAvatarPaymentInfo::processProperties(void* data, EAvatarProcessorType type) { if (data && type == APT_PROPERTIES) { LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); LLFloaterBuyCurrency::handleBuyCurrency(LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(avatar_data), mHasTarget, mName, mPrice); } }