00001
00031 #include "llviewerprecompiledheaders.h"
00032
00033 #include "llfloatersellland.h"
00034
00035 #include "llfloateravatarpicker.h"
00036 #include "llfloater.h"
00037 #include "llfloaterland.h"
00038 #include "lllineeditor.h"
00039 #include "llnotify.h"
00040 #include "llparcel.h"
00041 #include "llselectmgr.h"
00042 #include "lltexturectrl.h"
00043 #include "llviewercontrol.h"
00044 #include "llviewerparcelmgr.h"
00045 #include "lluictrlfactory.h"
00046 #include "llviewerwindow.h"
00047
00048
00049 void send_parcel_select_objects(S32 parcel_local_id, S32 return_type,
00050 uuid_list_t* return_ids = NULL);
00051
00052 enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR };
00053
00054 class LLFloaterSellLandUI
00055 : public LLFloater
00056 {
00057 private:
00058 LLFloaterSellLandUI();
00059 virtual ~LLFloaterSellLandUI();
00060
00061 LLViewerRegion* mRegion;
00062 LLParcelSelectionHandle mParcelSelection;
00063 bool mParcelIsForSale;
00064 bool mSellToBuyer;
00065 bool mChoseSellTo;
00066 S32 mParcelPrice;
00067 S32 mParcelActualArea;
00068 LLUUID mParcelSnapshot;
00069 LLUUID mAuthorizedBuyer;
00070 bool mParcelSoldWithObjects;
00071
00072 void updateParcelInfo();
00073 void refreshUI();
00074 void setBadge(const char* id, Badge badge);
00075
00076 static LLFloaterSellLandUI* sInstance;
00077
00078 static void onChangeValue(LLUICtrl *ctrl, void *userdata);
00079 static void doSelectAgent(void *userdata);
00080 static void doCancel(void *userdata);
00081 static void doSellLand(void *userdata);
00082 static void onConfirmSale(S32 option, void *userdata);
00083 static void doShowObjects(void *userdata);
00084 static void callbackHighlightTransferable(S32 option, void* userdata);
00085
00086 static void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
00087
00088 public:
00089 virtual BOOL postBuild();
00090 virtual void onClose(bool app_quitting);
00091
00092 static LLFloaterSellLandUI* soleInstance(bool createIfNeeded);
00093
00094 bool setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
00095
00096 private:
00097 class SelectionObserver : public LLParcelObserver
00098 {
00099 public:
00100 virtual void changed();
00101 };
00102 };
00103
00104
00105 void LLFloaterSellLand::sellLand(
00106 LLViewerRegion* region, LLParcelSelectionHandle parcel)
00107 {
00108 LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(true);
00109 if (ui->setParcel(region, parcel))
00110 {
00111 ui->open();
00112 }
00113 }
00114
00115
00116 LLFloaterSellLandUI* LLFloaterSellLandUI::sInstance = NULL;
00117
00118
00119 LLFloaterSellLandUI* LLFloaterSellLandUI::soleInstance(bool createIfNeeded)
00120 {
00121 if (!sInstance && createIfNeeded)
00122 {
00123 sInstance = new LLFloaterSellLandUI();
00124
00125 LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_sell_land.xml");
00126 sInstance->center();
00127 }
00128
00129
00130 static SelectionObserver* parcelSelectionObserver = NULL;
00131 if (!parcelSelectionObserver)
00132 {
00133 parcelSelectionObserver = new SelectionObserver;
00134 LLViewerParcelMgr::getInstance()->addObserver(parcelSelectionObserver);
00135 }
00136
00137 return sInstance;
00138 }
00139
00140 LLFloaterSellLandUI::LLFloaterSellLandUI()
00141 : LLFloater("Sell Land"),
00142 mRegion(0)
00143 {
00144 }
00145
00146 LLFloaterSellLandUI::~LLFloaterSellLandUI()
00147 {
00148 if (sInstance == this)
00149 {
00150 sInstance = NULL;
00151 }
00152 }
00153
00154 void LLFloaterSellLandUI::SelectionObserver::changed()
00155 {
00156 LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(false);
00157 if (ui)
00158 {
00159 if (LLViewerParcelMgr::getInstance()->selectionEmpty())
00160 {
00161 ui->close();
00162 }
00163 else {
00164 ui->setParcel(
00165 LLViewerParcelMgr::getInstance()->getSelectionRegion(),
00166 LLViewerParcelMgr::getInstance()->getParcelSelection());
00167 }
00168 }
00169 }
00170
00171 void LLFloaterSellLandUI::onClose(bool app_quitting)
00172 {
00173 LLFloater::onClose(app_quitting);
00174 destroy();
00175 }
00176
00177 BOOL LLFloaterSellLandUI::postBuild()
00178 {
00179 childSetCommitCallback("sell_to", onChangeValue, this);
00180 childSetCommitCallback("price", onChangeValue, this);
00181 childSetPrevalidate("price", LLLineEditor::prevalidateNonNegativeS32);
00182 childSetCommitCallback("sell_objects", onChangeValue, this);
00183 childSetAction("sell_to_select_agent", doSelectAgent, this);
00184 childSetAction("cancel_btn", doCancel, this);
00185 childSetAction("sell_btn", doSellLand, this);
00186 childSetAction("show_objects", doShowObjects, this);
00187 return TRUE;
00188 }
00189
00190 bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
00191 {
00192 if (!parcel->getParcel())
00193 {
00194 return false;
00195 }
00196
00197 mRegion = region;
00198 mParcelSelection = parcel;
00199 mChoseSellTo = false;
00200
00201
00202 updateParcelInfo();
00203 refreshUI();
00204
00205 return true;
00206 }
00207
00208 void LLFloaterSellLandUI::updateParcelInfo()
00209 {
00210 LLParcel* parcelp = mParcelSelection->getParcel();
00211 if (!parcelp) return;
00212
00213 mParcelActualArea = parcelp->getArea();
00214 mParcelIsForSale = parcelp->getForSale();
00215 if (mParcelIsForSale)
00216 {
00217 mChoseSellTo = true;
00218 }
00219 mParcelPrice = mParcelIsForSale ? parcelp->getSalePrice() : 0;
00220 mParcelSoldWithObjects = parcelp->getSellWithObjects();
00221 if (mParcelIsForSale)
00222 {
00223 childSetValue("price", mParcelPrice);
00224 if (mParcelSoldWithObjects)
00225 {
00226 childSetValue("sell_objects", "yes");
00227 }
00228 else
00229 {
00230 childSetValue("sell_objects", "no");
00231 }
00232 }
00233 else
00234 {
00235 childSetValue("price", "");
00236 childSetValue("sell_objects", "none");
00237 }
00238
00239 mParcelSnapshot = parcelp->getSnapshotID();
00240
00241 mAuthorizedBuyer = parcelp->getAuthorizedBuyerID();
00242 mSellToBuyer = mAuthorizedBuyer.notNull();
00243
00244 if(mSellToBuyer)
00245 {
00246 LLString name;
00247 gCacheName->getFullName(mAuthorizedBuyer, name);
00248 childSetText("sell_to_agent", name);
00249 }
00250 }
00251
00252 void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
00253 {
00254 static LLString badgeOK("badge_ok.j2c");
00255 static LLString badgeNote("badge_note.j2c");
00256 static LLString badgeWarn("badge_warn.j2c");
00257 static LLString badgeError("badge_error.j2c");
00258
00259 LLString badgeName;
00260 switch (badge)
00261 {
00262 default:
00263 case BADGE_OK: badgeName = badgeOK; break;
00264 case BADGE_NOTE: badgeName = badgeNote; break;
00265 case BADGE_WARN: badgeName = badgeWarn; break;
00266 case BADGE_ERROR: badgeName = badgeError; break;
00267 }
00268
00269 childSetValue(id, badgeName);
00270 }
00271
00272 void LLFloaterSellLandUI::refreshUI()
00273 {
00274 LLParcel* parcelp = mParcelSelection->getParcel();
00275 if (!parcelp) return;
00276
00277 LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("info_image");
00278 if (snapshot)
00279 {
00280 snapshot->setImageAssetID(mParcelSnapshot);
00281 }
00282
00283 childSetText("info_parcel", parcelp->getName());
00284 childSetTextArg("info_size", "[AREA]", llformat("%d", mParcelActualArea));
00285
00286 LLString price_str = childGetValue("price").asString();
00287 bool valid_price = false;
00288 valid_price = (price_str != "") && LLLineEditor::prevalidateNonNegativeS32(utf8str_to_wstring(price_str));
00289
00290 if (valid_price && mParcelActualArea > 0)
00291 {
00292 F32 per_meter_price = 0;
00293 per_meter_price = F32(mParcelPrice) / F32(mParcelActualArea);
00294 childSetTextArg("price_per_m", "[PER_METER]", llformat("%0.2f", per_meter_price));
00295 childShow("price_per_m");
00296
00297 setBadge("step_price", BADGE_OK);
00298 }
00299 else
00300 {
00301 childHide("price_per_m");
00302
00303 if ("" == price_str)
00304 {
00305 setBadge("step_price", BADGE_NOTE);
00306 }
00307 else
00308 {
00309 setBadge("step_price", BADGE_ERROR);
00310 }
00311 }
00312
00313 if (mSellToBuyer)
00314 {
00315 childSetValue("sell_to", "user");
00316 childShow("sell_to_agent");
00317 childShow("sell_to_select_agent");
00318 }
00319 else
00320 {
00321 if (mChoseSellTo)
00322 {
00323 childSetValue("sell_to", "anyone");
00324 }
00325 else
00326 {
00327 childSetValue("sell_to", "select");
00328 }
00329 childHide("sell_to_agent");
00330 childHide("sell_to_select_agent");
00331 }
00332
00333
00334 LLString sell_to = childGetValue("sell_to").asString();
00335 bool valid_sell_to = "select" != sell_to &&
00336 ("user" != sell_to || mAuthorizedBuyer.notNull());
00337
00338 if (!valid_sell_to)
00339 {
00340 setBadge("step_sell_to", BADGE_NOTE);
00341 }
00342 else
00343 {
00344 setBadge("step_sell_to", BADGE_OK);
00345 }
00346
00347 bool valid_sell_objects = ("none" != childGetValue("sell_objects").asString());
00348
00349 if (!valid_sell_objects)
00350 {
00351 setBadge("step_sell_objects", BADGE_NOTE);
00352 }
00353 else
00354 {
00355 setBadge("step_sell_objects", BADGE_OK);
00356 }
00357
00358 if (valid_sell_to && valid_price && valid_sell_objects)
00359 {
00360 childEnable("sell_btn");
00361 }
00362 else
00363 {
00364 childDisable("sell_btn");
00365 }
00366 }
00367
00368
00369 void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata)
00370 {
00371 LLFloaterSellLandUI *self = (LLFloaterSellLandUI *)userdata;
00372
00373 LLString sell_to = self->childGetValue("sell_to").asString();
00374
00375 if (sell_to == "user")
00376 {
00377 self->mChoseSellTo = true;
00378 self->mSellToBuyer = true;
00379 if (self->mAuthorizedBuyer.isNull())
00380 {
00381 doSelectAgent(self);
00382 }
00383 }
00384 else if (sell_to == "anyone")
00385 {
00386 self->mChoseSellTo = true;
00387 self->mSellToBuyer = false;
00388 }
00389
00390 self->mParcelPrice = self->childGetValue("price");
00391
00392 if ("yes" == self->childGetValue("sell_objects").asString())
00393 {
00394 self->mParcelSoldWithObjects = true;
00395 }
00396 else
00397 {
00398 self->mParcelSoldWithObjects = false;
00399 }
00400
00401 self->refreshUI();
00402 }
00403
00404
00405 void LLFloaterSellLandUI::doSelectAgent(void *userdata)
00406 {
00407 LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)userdata;
00408
00409 floaterp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarPick, floaterp, FALSE, TRUE));
00410 }
00411
00412
00413 void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
00414 {
00415 LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data;
00416 LLParcel* parcel = floaterp->mParcelSelection->getParcel();
00417
00418 if (names.empty() || ids.empty()) return;
00419
00420 LLUUID id = ids[0];
00421 parcel->setAuthorizedBuyerID(id);
00422
00423 floaterp->mAuthorizedBuyer = ids[0];
00424
00425 floaterp->childSetText("sell_to_agent", names[0]);
00426
00427 floaterp->refreshUI();
00428 }
00429
00430
00431 void LLFloaterSellLandUI::doCancel(void *userdata)
00432 {
00433 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00434 self->close();
00435 }
00436
00437
00438 void LLFloaterSellLandUI::doShowObjects(void *userdata)
00439 {
00440 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00441 LLParcel* parcel = self->mParcelSelection->getParcel();
00442 if (!parcel) return;
00443
00444 send_parcel_select_objects(parcel->getLocalID(), RT_SELL);
00445
00446 LLNotifyBox::showXml("TransferObjectsHighlighted",
00447 callbackHighlightTransferable,
00448 userdata);
00449 }
00450
00451
00452 void LLFloaterSellLandUI::callbackHighlightTransferable(S32 option, void* userdata)
00453 {
00454 LLSelectMgr::getInstance()->unhighlightAll();
00455 }
00456
00457
00458 void LLFloaterSellLandUI::doSellLand(void *userdata)
00459 {
00460 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00461
00462 LLParcel* parcel = self->mParcelSelection->getParcel();
00463
00464
00465 if (!parcel->getForSale())
00466 {
00467 S32 sale_price = self->childGetValue("price");
00468 S32 area = parcel->getArea();
00469 std::string authorizedBuyerName = "Anyone";
00470 bool sell_to_anyone = true;
00471 if ("user" == self->childGetValue("sell_to").asString())
00472 {
00473 authorizedBuyerName = self->childGetText("sell_to_agent");
00474 sell_to_anyone = false;
00475 }
00476
00477
00478 if ((sale_price == 0) && sell_to_anyone)
00479 {
00480 gViewerWindow->alertXml("SalePriceRestriction");
00481 return;
00482 }
00483
00484 LLStringBase<char>::format_map_t args;
00485 args["[LAND_SIZE]"] = llformat("%d",area);
00486 args["[SALE_PRICE]"] = llformat("%d",sale_price);
00487 args["[NAME]"] = authorizedBuyerName;
00488
00489 if (sell_to_anyone)
00490 {
00491 gViewerWindow->alertXml("ConfirmLandSaleToAnyoneChange", args, onConfirmSale, self);
00492 }
00493 else
00494 {
00495 gViewerWindow->alertXml("ConfirmLandSaleChange", args, onConfirmSale, self);
00496 }
00497 }
00498 else
00499 {
00500 onConfirmSale(-1, self);
00501 }
00502 }
00503
00504
00505 void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata)
00506 {
00507 if (option != 0)
00508 {
00509 return;
00510 }
00511 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00512 S32 sale_price = self->childGetValue("price");
00513
00514
00515 if (sale_price < 0)
00516 {
00517
00518 return;
00519 }
00520
00521 LLParcel* parcel = self->mParcelSelection->getParcel();
00522 if (!parcel) return;
00523
00524
00525
00526
00527
00528
00529
00530
00531 parcel->setParcelFlag(PF_FOR_SALE, TRUE);
00532 parcel->setSalePrice(sale_price);
00533 bool sell_with_objects = false;
00534 if ("yes" == self->childGetValue("sell_objects").asString())
00535 {
00536 sell_with_objects = true;
00537 }
00538 parcel->setSellWithObjects(sell_with_objects);
00539 if ("user" == self->childGetValue("sell_to").asString())
00540 {
00541 parcel->setAuthorizedBuyerID(self->mAuthorizedBuyer);
00542 }
00543 else
00544 {
00545 parcel->setAuthorizedBuyerID(LLUUID::null);
00546 }
00547
00548
00549 LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
00550
00551 self->close();
00552 }