llgivemoney.cpp

Go to the documentation of this file.
00001 
00033 #include "llviewerprecompiledheaders.h"
00034 
00035 #include "llgivemoney.h"
00036 
00037 #include "message.h"
00038 
00039 #include "llagent.h"
00040 #include "llresmgr.h"
00041 #include "lltextbox.h"
00042 #include "lllineeditor.h"
00043 #include "llviewerobject.h"
00044 #include "llviewerobjectlist.h"
00045 #include "llviewerregion.h"
00046 #include "llviewerwindow.h"
00047 #include "llbutton.h"
00048 #include "llselectmgr.h"
00049 #include "lltransactiontypes.h"
00050 #include "llvieweruictrlfactory.h"
00051 
00055 
00056 const char* GIVE_MONEY_TITLE = "";      // Dialog contains text "Pay"
00057 
00058 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00059 // Class LLGiveMoneyInfo
00060 //
00061 // A small class used to track callback information
00062 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00063 
00064 struct LLGiveMoneyInfo
00065 {
00066         LLFloaterPay* mFloater;
00067         S32 mAmount;
00068         LLGiveMoneyInfo(LLFloaterPay* floater, S32 amount) :
00069                 mFloater(floater), mAmount(amount){}
00070 };
00071 
00075 
00076 S32 LLFloaterPay::sLastAmount = 0;
00077 const S32 MAX_AMOUNT_LENGTH = 10;
00078 const S32 FASTPAY_BUTTON_WIDTH = 80;
00079 
00080 // Default constructor
00081 LLFloaterPay::LLFloaterPay(const std::string& name, 
00082                                                    money_callback callback,
00083                                                    const LLUUID& uuid,
00084                                                    BOOL target_is_object) :
00085         LLFloater(name, "FloaterPayRectB", GIVE_MONEY_TITLE, RESIZE_NO,
00086                                 DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, DRAG_ON_TOP,
00087                                 MINIMIZE_NO, CLOSE_YES),
00088         mCallbackData(),
00089         mCallback(callback),
00090         mObjectNameText(NULL),
00091         mTargetUUID(uuid),
00092         mTargetIsObject(target_is_object),
00093         mTargetIsGroup(FALSE)
00094 {
00095         if (target_is_object)
00096         {
00097                 gUICtrlFactory->buildFloater(this,"floater_pay_object.xml");
00098                 mObjectSelection = gSelectMgr->getEditSelection();
00099         }
00100         else 
00101         {
00102                 gUICtrlFactory->buildFloater(this,"floater_pay.xml");
00103         }
00104 
00105         
00106         S32 i =0;
00107 
00108         LLGiveMoneyInfo* info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0);
00109         mCallbackData.push_back(info);
00110 
00111         childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
00112         childSetVisible("fastpay 1", FALSE);
00113 
00114         mQuickPayButton[i] = LLUICtrlFactory::getButtonByName(this, "fastpay 1");
00115         mQuickPayInfo[i] = info;
00116         ++i;
00117 
00118         info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1);
00119         mCallbackData.push_back(info);
00120 
00121         childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
00122         childSetVisible("fastpay 5", FALSE);
00123 
00124         mQuickPayButton[i] = LLUICtrlFactory::getButtonByName(this, "fastpay 5");
00125         mQuickPayInfo[i] = info;
00126         ++i;
00127 
00128         info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2);
00129         mCallbackData.push_back(info);
00130 
00131         childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
00132         childSetVisible("fastpay 10", FALSE);
00133 
00134         mQuickPayButton[i] = LLUICtrlFactory::getButtonByName(this, "fastpay 10");
00135         mQuickPayInfo[i] = info;
00136         ++i;
00137 
00138         info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3);
00139         mCallbackData.push_back(info);
00140 
00141         childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
00142         childSetVisible("fastpay 20", FALSE);
00143 
00144         mQuickPayButton[i] = LLUICtrlFactory::getButtonByName(this, "fastpay 20");
00145         mQuickPayInfo[i] = info;
00146         ++i;
00147 
00148         
00149     childSetVisible("amount text", FALSE);      
00150 
00151         LLString last_amount;
00152         if(sLastAmount > 0)
00153         {
00154                 last_amount = llformat("%d", sLastAmount);
00155         }
00156 
00157     childSetVisible("amount", FALSE);
00158         
00159         childSetKeystrokeCallback("amount", &LLFloaterPay::onKeystroke, this);
00160         childSetText("amount", last_amount);
00161         childSetPrevalidate("amount", LLLineEditor::prevalidateNonNegativeS32);
00162 
00163         info = new LLGiveMoneyInfo(this, 0);
00164         mCallbackData.push_back(info);
00165 
00166         childSetAction("pay btn",&LLFloaterPay::onGive,info);
00167         setDefaultBtn("pay btn");
00168         childSetVisible("pay btn", FALSE);
00169         childSetEnabled("pay btn", (sLastAmount > 0));
00170 
00171         childSetAction("cancel btn",&LLFloaterPay::onCancel,this);
00172 
00173         center();
00174         open();         /*Flawfinder: ignore*/
00175 }
00176 
00177 // Destroys the object
00178 LLFloaterPay::~LLFloaterPay()
00179 {
00180         std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer());
00181 
00182         // Clean up if we are still waiting for a name.
00183         gCacheName->cancelCallback(mTargetUUID,onCacheOwnerName,this);
00184 }
00185 
00186 // static
00187 void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata)
00188 {
00189         LLFloaterPay* self = (LLFloaterPay*)userdata;
00190         if (self)
00191         {
00192                 S32 price;
00193                 LLUUID target;
00194 
00195                 msg->getUUIDFast(_PREHASH_ObjectData,_PREHASH_ObjectID,target);
00196                 if (target != self->mTargetUUID)
00197                 {
00198                         // This is a message for a different object's pay info
00199                         return;
00200                 }
00201 
00202                 msg->getS32Fast(_PREHASH_ObjectData,_PREHASH_DefaultPayPrice,price);
00203                 
00204                 if (PAY_PRICE_HIDE == price)
00205                 {
00206                         self->childSetVisible("amount", FALSE);
00207                         self->childSetVisible("pay btn", FALSE);
00208                         self->childSetVisible("amount text", FALSE);
00209                 }
00210                 else if (PAY_PRICE_DEFAULT == price)
00211                 {                       
00212                         self->childSetVisible("amount", TRUE);
00213                         self->childSetVisible("pay btn", TRUE);
00214                         self->childSetVisible("amount text", TRUE);
00215                 }
00216                 else
00217                 {
00218                         // PAY_PRICE_HIDE and PAY_PRICE_DEFAULT are negative values
00219                         // So we take the absolute value here after we have checked for those cases
00220                         
00221                         self->childSetVisible("amount", TRUE);
00222                         self->childSetVisible("pay btn", TRUE);
00223                         self->childSetEnabled("pay btn", TRUE);
00224                         self->childSetVisible("amount text", TRUE);
00225 
00226                         self->childSetText("amount", llformat("%d", llabs(price)));
00227                 }
00228 
00229                 S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_ButtonData);
00230                 S32 i = 0;
00231                 if (num_blocks > MAX_PAY_BUTTONS) num_blocks = MAX_PAY_BUTTONS;
00232 
00233                 S32 max_pay_amount = 0;
00234                 S32 padding_required = 0;
00235 
00236                 for (i=0;i<num_blocks;++i)
00237                 {
00238                         S32 pay_button;
00239                         msg->getS32Fast(_PREHASH_ButtonData,_PREHASH_PayButton,pay_button,i);
00240                         if (pay_button > 0)
00241                         {
00242                                 LLString button_str = "L$";
00243                                 button_str += gResMgr->getMonetaryString( pay_button );
00244 
00245                                 self->mQuickPayButton[i]->setLabelSelected(button_str);
00246                                 self->mQuickPayButton[i]->setLabelUnselected(button_str);
00247                                 self->mQuickPayButton[i]->setVisible(TRUE);
00248                                 self->mQuickPayInfo[i]->mAmount = pay_button;
00249                                 self->childSetVisible("fastpay text",TRUE);
00250 
00251                                 if ( pay_button > max_pay_amount )
00252                                 {
00253                                         max_pay_amount = pay_button;
00254                                 }
00255                         }
00256                         else
00257                         {
00258                                 self->mQuickPayButton[i]->setVisible(FALSE);
00259                         }
00260                 }
00261 
00262                 // build a string containing the maximum value and calc nerw button width from it.
00263                 LLString balance_str = "L$";
00264                 balance_str += gResMgr->getMonetaryString( max_pay_amount );
00265                 const LLFontGL* font = gResMgr->getRes(LLFONT_SANSSERIF);
00266                 S32 new_button_width = font->getWidth( LLString(balance_str));
00267                 new_button_width += ( 12 + 12 );        // padding
00268 
00269                 // dialong is sized for 2 digit pay amounts - larger pay values need to be scaled
00270                 const S32 threshold = 100000;
00271                 if ( max_pay_amount >= threshold )
00272                 {
00273                         S32 num_digits_threshold = (S32)log10((double)threshold) + 1;
00274                         S32 num_digits_max = (S32)log10((double)max_pay_amount) + 1;
00275                                 
00276                         // calculate the extra width required by 2 buttons with max amount and some commas
00277                         padding_required = ( num_digits_max - num_digits_threshold + ( num_digits_max / 3 ) ) * font->getWidth( "0" );
00278                 };
00279 
00280                 // change in button width
00281                 S32 button_delta = new_button_width - FASTPAY_BUTTON_WIDTH;
00282                 if ( button_delta < 0 ) 
00283                         button_delta = 0;
00284 
00285                 // now we know the maximum amount, we can resize all the buttons to be 
00286                 for (i=0;i<num_blocks;++i)
00287                 {
00288                         LLRect r;
00289                         r = self->mQuickPayButton[i]->getRect();
00290 
00291                         // RHS button colum needs to move further because LHS changed too
00292                         if ( i % 2 )
00293                         {
00294                                 r.setCenterAndSize( r.getCenterX() + ( button_delta * 3 ) / 2 , 
00295                                         r.getCenterY(), 
00296                                                 r.getWidth() + button_delta, 
00297                                                         r.getHeight() ); 
00298                         }
00299                         else
00300                         {
00301                                 r.setCenterAndSize( r.getCenterX() + button_delta / 2, 
00302                                         r.getCenterY(), 
00303                                                 r.getWidth() + button_delta, 
00304                                                 r.getHeight() ); 
00305                         }
00306                         self->mQuickPayButton[i]->setRect( r );
00307                 }
00308 
00309                 for (i=num_blocks;i<MAX_PAY_BUTTONS;++i)
00310                 {
00311                         self->mQuickPayButton[i]->setVisible(FALSE);
00312                 }
00313 
00314                 self->reshape( self->mRect.getWidth() + padding_required, self->mRect.getHeight(), FALSE );
00315         }
00316         msg->setHandlerFunc("PayPriceReply",NULL,NULL);
00317 }
00318 
00319 // static
00320 void LLFloaterPay::payViaObject(money_callback callback, const LLUUID& object_id)
00321 {
00322         LLViewerObject* object = gObjectList.findObject(object_id);
00323         if (!object) return;
00324         
00325         LLFloaterPay *floater = new LLFloaterPay("Give L$", callback, object_id, TRUE);
00326         if (!floater) return;
00327 
00328         LLSelectNode* node = floater->mObjectSelection->getFirstRootNode();
00329         if (!node) 
00330         {
00331                 //FIXME: notify user object no longer exists
00332                 floater->close();
00333                 return;
00334         }
00335         
00336         LLHost target_region = object->getRegion()->getHost();
00337         
00338         LLMessageSystem* msg = gMessageSystem;
00339         msg->newMessageFast(_PREHASH_RequestPayPrice);
00340         msg->nextBlockFast(_PREHASH_ObjectData);
00341         msg->addUUIDFast(_PREHASH_ObjectID, object_id);
00342         msg->sendReliable(target_region);
00343         msg->setHandlerFuncFast(_PREHASH_PayPriceReply, processPayPriceReply,(void **)floater);
00344         
00345         LLUUID owner_id;
00346         BOOL is_group = FALSE;
00347         node->mPermissions->getOwnership(owner_id, is_group);
00348         
00349         floater->childSetText("object_name_text",node->mName);
00350 
00351         floater->finishPayUI(owner_id, is_group);
00352 }
00353 
00354 void LLFloaterPay::payDirectly(money_callback callback, 
00355                                                            const LLUUID& target_id,
00356                                                            BOOL is_group)
00357 {
00358         LLFloaterPay *floater = new LLFloaterPay("Give L$", callback, target_id, FALSE);
00359         if (!floater) return;
00360 
00361         floater->childSetVisible("amount", TRUE);
00362         floater->childSetVisible("pay btn", TRUE);
00363         floater->childSetVisible("amount text", TRUE);
00364 
00365         floater->childSetVisible("fastpay text",TRUE);
00366         for(S32 i=0;i<MAX_PAY_BUTTONS;++i)
00367         {
00368                 floater->mQuickPayButton[i]->setVisible(TRUE);
00369         }
00370         
00371         floater->finishPayUI(target_id, is_group);
00372 }
00373         
00374 void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group)
00375 {
00376         gCacheName->get(target_id, is_group, onCacheOwnerName, (void*)this);
00377 
00378         // Make sure the amount field has focus
00379 
00380         childSetFocus("amount", TRUE);
00381         
00382         LLLineEditor* amount = LLUICtrlFactory::getLineEditorByName(this, "amount");
00383         amount->selectAll();
00384         mTargetIsGroup = is_group;
00385 }
00386 
00387 // static
00388 void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id,
00389                                                                         const char* firstname,
00390                                                                         const char* lastname,
00391                                                                         BOOL is_group,
00392                                                                         void* userdata)
00393 {
00394         LLFloaterPay* self = (LLFloaterPay*)userdata;
00395         if (!self) return;
00396         
00397         if (is_group)
00398         {
00399                 self->childSetVisible("payee_group",true);
00400                 self->childSetVisible("payee_resident",false);
00401         }
00402         else
00403         {
00404                 self->childSetVisible("payee_group",false);
00405                 self->childSetVisible("payee_resident",true);
00406         }
00407         
00408         self->childSetTextArg("payee_name", "[FIRST]", LLString(firstname));
00409         self->childSetTextArg("payee_name", "[LAST]", LLString(lastname));
00410 }
00411 
00412 // static
00413 void LLFloaterPay::onCancel(void* data)
00414 {
00415         LLFloaterPay* self = reinterpret_cast<LLFloaterPay*>(data);
00416         if(self)
00417         {
00418                 self->close();
00419         }
00420 }
00421 
00422 // static
00423 void LLFloaterPay::onKeystroke(LLLineEditor*, void* data)
00424 {
00425         LLFloaterPay* self = reinterpret_cast<LLFloaterPay*>(data);
00426         if(self)
00427         {
00428                 // enable the Pay button when amount is non-empty and positive, disable otherwise
00429                 LLString amtstr = self->childGetText("amount");
00430                 self->childSetEnabled("pay btn", !amtstr.empty() && atoi(amtstr.c_str()) > 0);
00431         }
00432 }
00433 
00434 // static
00435 void LLFloaterPay::onGive(void* data)
00436 {
00437         LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data);
00438         if(info && info->mFloater)
00439         {
00440                 info->mFloater->give(info->mAmount);
00441                 info->mFloater->close();
00442         }
00443 }
00444 
00445 void LLFloaterPay::give(S32 amount)
00446 {
00447         if(mCallback)
00448         {
00449                 // if the amount is 0, that menas that we should use the
00450                 // text field.
00451                 if(amount == 0)
00452                 {
00453                         amount = atoi(childGetText("amount").c_str());
00454                 }
00455                 sLastAmount = amount;
00456 
00457                 // Try to pay an object.
00458                 if (mTargetIsObject)
00459                 {
00460                         LLViewerObject* dest_object = gObjectList.findObject(mTargetUUID);
00461                         if(dest_object)
00462                         {
00463                                 LLViewerRegion* region = dest_object->getRegion();
00464                                 if (region)
00465                                 {
00466                                         // Find the name of the root object
00467                                         LLSelectNode* node = mObjectSelection->getFirstRootNode();
00468                                         LLString object_name;
00469                                         if (node)
00470                                         {
00471                                                 object_name = node->mName;
00472                                         }
00473                                         S32 tx_type = TRANS_PAY_OBJECT;
00474                                         if(dest_object->isAvatar()) tx_type = TRANS_GIFT;
00475                                         mCallback(mTargetUUID, region, amount, FALSE, tx_type, object_name);
00476                                         mObjectSelection = NULL;
00477                                 }
00478                         }
00479                 }
00480                 else
00481                 {
00482                         // just transfer the L$
00483                         mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, LLString::null);
00484                 }
00485         }
00486 }
00487 
00491 
00492 

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