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 "llvieweruictrlfactory.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 gUICtrlFactory->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 gParcelMgr->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 (gParcelMgr->selectionEmpty())
00160 {
00161 ui->close();
00162 }
00163 else {
00164 ui->setParcel(
00165 gParcelMgr->getSelectionRegion(),
00166 gParcelMgr->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 char firstname[MAX_STRING];
00248 char lastname[MAX_STRING];
00249 gCacheName->getName(mAuthorizedBuyer, firstname, lastname);
00250 name.assign(firstname);
00251 name.append(" ");
00252 name.append(lastname);
00253
00254 childSetText("sell_to_agent", name);
00255 }
00256 }
00257
00258 void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
00259 {
00260 static LLUUID badgeOK(gViewerArt.getString("badge_ok.tga"));
00261 static LLUUID badgeNote(gViewerArt.getString("badge_note.tga"));
00262 static LLUUID badgeWarn(gViewerArt.getString("badge_warn.tga"));
00263 static LLUUID badgeError(gViewerArt.getString("badge_error.tga"));
00264
00265 LLUUID badgeUUID;
00266 switch (badge)
00267 {
00268 default:
00269 case BADGE_OK: badgeUUID = badgeOK; break;
00270 case BADGE_NOTE: badgeUUID = badgeNote; break;
00271 case BADGE_WARN: badgeUUID = badgeWarn; break;
00272 case BADGE_ERROR: badgeUUID = badgeError; break;
00273 }
00274
00275 childSetValue(id, badgeUUID);
00276 }
00277
00278 void LLFloaterSellLandUI::refreshUI()
00279 {
00280 LLParcel* parcelp = mParcelSelection->getParcel();
00281 if (!parcelp) return;
00282
00283 LLTextureCtrl* snapshot = LLViewerUICtrlFactory::getTexturePickerByName(this, "info_image");
00284 if (snapshot)
00285 {
00286 snapshot->setImageAssetID(mParcelSnapshot);
00287 }
00288
00289 childSetText("info_parcel", parcelp->getName());
00290 childSetTextArg("info_size", "[AREA]", llformat("%d", mParcelActualArea));
00291
00292 LLString price_str = childGetValue("price").asString();
00293 bool valid_price = false;
00294 valid_price = (price_str != "") && LLLineEditor::prevalidateNonNegativeS32(utf8str_to_wstring(price_str));
00295
00296 if (valid_price && mParcelActualArea > 0)
00297 {
00298 F32 per_meter_price = 0;
00299 per_meter_price = F32(mParcelPrice) / F32(mParcelActualArea);
00300 childSetTextArg("price_per_m", "[PER_METER]", llformat("%0.2f", per_meter_price));
00301 childShow("price_per_m");
00302
00303 setBadge("step_price", BADGE_OK);
00304 }
00305 else
00306 {
00307 childHide("price_per_m");
00308
00309 if ("" == price_str)
00310 {
00311 setBadge("step_price", BADGE_NOTE);
00312 }
00313 else
00314 {
00315 setBadge("step_price", BADGE_ERROR);
00316 }
00317 }
00318
00319 if (mSellToBuyer)
00320 {
00321 childSetValue("sell_to", "user");
00322 childShow("sell_to_agent");
00323 childShow("sell_to_select_agent");
00324 }
00325 else
00326 {
00327 if (mChoseSellTo)
00328 {
00329 childSetValue("sell_to", "anyone");
00330 }
00331 else
00332 {
00333 childSetValue("sell_to", "select");
00334 }
00335 childHide("sell_to_agent");
00336 childHide("sell_to_select_agent");
00337 }
00338
00339
00340 LLString sell_to = childGetValue("sell_to").asString();
00341 bool valid_sell_to = "select" != sell_to &&
00342 ("user" != sell_to || mAuthorizedBuyer.notNull());
00343
00344 if (!valid_sell_to)
00345 {
00346 setBadge("step_sell_to", BADGE_NOTE);
00347 }
00348 else
00349 {
00350 setBadge("step_sell_to", BADGE_OK);
00351 }
00352
00353 bool valid_sell_objects = ("none" != childGetValue("sell_objects").asString());
00354
00355 if (!valid_sell_objects)
00356 {
00357 setBadge("step_sell_objects", BADGE_NOTE);
00358 }
00359 else
00360 {
00361 setBadge("step_sell_objects", BADGE_OK);
00362 }
00363
00364 if (valid_sell_to && valid_price && valid_sell_objects)
00365 {
00366 childEnable("sell_btn");
00367 }
00368 else
00369 {
00370 childDisable("sell_btn");
00371 }
00372 }
00373
00374
00375 void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata)
00376 {
00377 LLFloaterSellLandUI *self = (LLFloaterSellLandUI *)userdata;
00378
00379 LLString sell_to = self->childGetValue("sell_to").asString();
00380
00381 if (sell_to == "user")
00382 {
00383 self->mChoseSellTo = true;
00384 self->mSellToBuyer = true;
00385 if (self->mAuthorizedBuyer.isNull())
00386 {
00387 doSelectAgent(self);
00388 }
00389 }
00390 else if (sell_to == "anyone")
00391 {
00392 self->mChoseSellTo = true;
00393 self->mSellToBuyer = false;
00394 }
00395
00396 self->mParcelPrice = self->childGetValue("price");
00397
00398 if ("yes" == self->childGetValue("sell_objects").asString())
00399 {
00400 self->mParcelSoldWithObjects = true;
00401 }
00402 else
00403 {
00404 self->mParcelSoldWithObjects = false;
00405 }
00406
00407 self->refreshUI();
00408 }
00409
00410
00411 void LLFloaterSellLandUI::doSelectAgent(void *userdata)
00412 {
00413 LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)userdata;
00414
00415 floaterp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarPick, floaterp, FALSE, TRUE));
00416 }
00417
00418
00419 void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
00420 {
00421 LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data;
00422 LLParcel* parcel = floaterp->mParcelSelection->getParcel();
00423
00424 if (names.empty() || ids.empty()) return;
00425
00426 LLUUID id = ids[0];
00427 parcel->setAuthorizedBuyerID(id);
00428
00429 floaterp->mAuthorizedBuyer = ids[0];
00430
00431 floaterp->childSetText("sell_to_agent", names[0]);
00432
00433 floaterp->refreshUI();
00434 }
00435
00436
00437 void LLFloaterSellLandUI::doCancel(void *userdata)
00438 {
00439 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00440 self->close();
00441 }
00442
00443
00444 void LLFloaterSellLandUI::doShowObjects(void *userdata)
00445 {
00446 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00447 LLParcel* parcel = self->mParcelSelection->getParcel();
00448 if (!parcel) return;
00449
00450 send_parcel_select_objects(parcel->getLocalID(), RT_SELL);
00451
00452 LLNotifyBox::showXml("TransferObjectsHighlighted",
00453 callbackHighlightTransferable,
00454 userdata);
00455 }
00456
00457
00458 void LLFloaterSellLandUI::callbackHighlightTransferable(S32 option, void* userdata)
00459 {
00460 gSelectMgr->unhighlightAll();
00461 }
00462
00463
00464 void LLFloaterSellLandUI::doSellLand(void *userdata)
00465 {
00466 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00467
00468 LLParcel* parcel = self->mParcelSelection->getParcel();
00469
00470
00471 if (!parcel->getForSale())
00472 {
00473 S32 sale_price = self->childGetValue("price");
00474 S32 area = parcel->getArea();
00475 std::string authorizedBuyerName = "Anyone";
00476 bool sell_to_anyone = true;
00477 if ("user" == self->childGetValue("sell_to").asString())
00478 {
00479 authorizedBuyerName = self->childGetText("sell_to_agent");
00480 sell_to_anyone = false;
00481 }
00482
00483
00484 if ((sale_price == 0) && sell_to_anyone)
00485 {
00486 gViewerWindow->alertXml("SalePriceRestriction");
00487 return;
00488 }
00489
00490 LLStringBase<char>::format_map_t args;
00491 args["[LAND_SIZE]"] = llformat("%d",area);
00492 args["[SALE_PRICE]"] = llformat("%d",sale_price);
00493 args["[NAME]"] = authorizedBuyerName;
00494
00495 gViewerWindow->alertXml("ConfirmLandSaleChange", args, onConfirmSale, self);
00496 }
00497 else
00498 {
00499 onConfirmSale(-1, self);
00500 }
00501 }
00502
00503
00504 void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata)
00505 {
00506 if (option != 0)
00507 {
00508 return;
00509 }
00510 LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
00511 S32 sale_price = self->childGetValue("price");
00512
00513
00514 if (sale_price < 0)
00515 {
00516
00517 return;
00518 }
00519
00520 LLParcel* parcel = self->mParcelSelection->getParcel();
00521 if (!parcel) return;
00522
00523
00524
00525
00526
00527
00528
00529
00530 parcel->setParcelFlag(PF_FOR_SALE, TRUE);
00531 parcel->setSalePrice(sale_price);
00532 bool sell_with_objects = false;
00533 if ("yes" == self->childGetValue("sell_objects").asString())
00534 {
00535 sell_with_objects = true;
00536 }
00537 parcel->setSellWithObjects(sell_with_objects);
00538 if ("user" == self->childGetValue("sell_to").asString())
00539 {
00540 parcel->setAuthorizedBuyerID(self->mAuthorizedBuyer);
00541 }
00542 else
00543 {
00544 parcel->setAuthorizedBuyerID(LLUUID::null);
00545 }
00546
00547
00548 gParcelMgr->sendParcelPropertiesUpdate( parcel );
00549
00550 self->close();
00551 }