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

Generated on Fri May 16 08:33:37 2008 for SecondLife by  doxygen 1.5.5