llfloatersellland.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:14k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloatersellland.cpp
  3.  *
  4.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2006-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21.  * 
  22.  * By copying, modifying or distributing this software, you acknowledge
  23.  * that you have read and understood your obligations described above,
  24.  * and agree to abide by those obligations.
  25.  * 
  26.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28.  * COMPLETENESS OR PERFORMANCE.
  29.  * $/LicenseInfo$
  30.  */
  31. #include "llviewerprecompiledheaders.h"
  32. #include "llfloatersellland.h"
  33. #include "llfloateravatarpicker.h"
  34. #include "llfloaterreg.h"
  35. #include "llfloaterland.h"
  36. #include "lllineeditor.h"
  37. #include "llnotifications.h"
  38. #include "llnotificationsutil.h"
  39. #include "llparcel.h"
  40. #include "llselectmgr.h"
  41. #include "lltexturectrl.h"
  42. #include "llviewercontrol.h"
  43. #include "llviewerparcelmgr.h"
  44. #include "lluictrlfactory.h"
  45. #include "llviewerwindow.h"
  46. // defined in llfloaterland.cpp
  47. void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
  48. uuid_list_t* return_ids = NULL);
  49. enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR };
  50. class LLFloaterSellLandUI
  51. : public LLFloater
  52. {
  53. public:
  54. LLFloaterSellLandUI(const LLSD& key);
  55. virtual ~LLFloaterSellLandUI();
  56. /*virtual*/ void onClose(bool app_quitting);
  57. private:
  58. class SelectionObserver : public LLParcelObserver
  59. {
  60. public:
  61. SelectionObserver(LLFloaterSellLandUI* floater) : mFloater(floater) {}
  62. virtual void changed();
  63. private:
  64. LLFloaterSellLandUI* mFloater;
  65. };
  66. private:
  67. LLViewerRegion* mRegion;
  68. LLParcelSelectionHandle mParcelSelection;
  69. bool mParcelIsForSale;
  70. bool mSellToBuyer;
  71. bool mChoseSellTo;
  72. S32 mParcelPrice;
  73. S32 mParcelActualArea;
  74. LLUUID mParcelSnapshot;
  75. LLUUID mAuthorizedBuyer;
  76. bool mParcelSoldWithObjects;
  77. SelectionObserver  mParcelSelectionObserver;
  78. void updateParcelInfo();
  79. void refreshUI();
  80. void setBadge(const char* id, Badge badge);
  81. static void onChangeValue(LLUICtrl *ctrl, void *userdata);
  82. void doSelectAgent();
  83. static void doCancel(void *userdata);
  84. static void doSellLand(void *userdata);
  85. bool onConfirmSale(const LLSD& notification, const LLSD& response);
  86. static void doShowObjects(void *userdata);
  87. static bool callbackHighlightTransferable(const LLSD& notification, const LLSD& response);
  88. void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
  89. public:
  90. virtual BOOL postBuild();
  91. bool setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
  92. };
  93. // static
  94. void LLFloaterSellLand::sellLand(
  95. LLViewerRegion* region, LLParcelSelectionHandle parcel)
  96. {
  97. LLFloaterSellLandUI* ui = LLFloaterReg::showTypedInstance<LLFloaterSellLandUI>("sell_land");
  98. ui->setParcel(region, parcel);
  99. }
  100. // static
  101. LLFloater* LLFloaterSellLand::buildFloater(const LLSD& key)
  102. {
  103. LLFloaterSellLandUI* floater = new LLFloaterSellLandUI(key);
  104. return floater;
  105. }
  106. #if LL_WINDOWS
  107. // passing 'this' during construction generates a warning. The callee
  108. // only uses the pointer to hold a reference to 'this' which is
  109. // already valid, so this call does the correct thing. Disable the
  110. // warning so that we can compile without generating a warning.
  111. #pragma warning(disable : 4355)
  112. #endif 
  113. LLFloaterSellLandUI::LLFloaterSellLandUI(const LLSD& key)
  114. : LLFloater(key),
  115. mParcelSelectionObserver(this),
  116. mRegion(0)
  117. {
  118. LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
  119. }
  120. LLFloaterSellLandUI::~LLFloaterSellLandUI()
  121. {
  122. LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
  123. }
  124. // Because we are single_instance, we are not destroyed on close.
  125. void LLFloaterSellLandUI::onClose(bool app_quitting)
  126. {
  127. // Must release parcel selection to allow land to deselect, see EXT-803
  128. mParcelSelection = NULL;
  129. }
  130. void LLFloaterSellLandUI::SelectionObserver::changed()
  131. {
  132. if (LLViewerParcelMgr::getInstance()->selectionEmpty())
  133. {
  134. mFloater->closeFloater();
  135. }
  136. else if (mFloater->getVisible()) // only update selection if sell land ui in use
  137. {
  138. mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
  139. LLViewerParcelMgr::getInstance()->getParcelSelection());
  140. }
  141. }
  142. BOOL LLFloaterSellLandUI::postBuild()
  143. {
  144. childSetCommitCallback("sell_to", onChangeValue, this);
  145. childSetCommitCallback("price", onChangeValue, this);
  146. childSetPrevalidate("price", LLTextValidate::validateNonNegativeS32);
  147. childSetCommitCallback("sell_objects", onChangeValue, this);
  148. childSetAction("sell_to_select_agent", boost::bind( &LLFloaterSellLandUI::doSelectAgent, this));
  149. childSetAction("cancel_btn", doCancel, this);
  150. childSetAction("sell_btn", doSellLand, this);
  151. childSetAction("show_objects", doShowObjects, this);
  152. center();
  153. return TRUE;
  154. }
  155. bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
  156. {
  157. if (!parcel->getParcel())
  158. {
  159. return false;
  160. }
  161. mRegion = region;
  162. mParcelSelection = parcel;
  163. mChoseSellTo = false;
  164. updateParcelInfo();
  165. refreshUI();
  166. return true;
  167. }
  168. void LLFloaterSellLandUI::updateParcelInfo()
  169. {
  170. LLParcel* parcelp = mParcelSelection->getParcel();
  171. if (!parcelp) return;
  172. mParcelActualArea = parcelp->getArea();
  173. mParcelIsForSale = parcelp->getForSale();
  174. if (mParcelIsForSale)
  175. {
  176. mChoseSellTo = true;
  177. }
  178. mParcelPrice = mParcelIsForSale ? parcelp->getSalePrice() : 0;
  179. mParcelSoldWithObjects = parcelp->getSellWithObjects();
  180. if (mParcelIsForSale)
  181. {
  182. childSetValue("price", mParcelPrice);
  183. if (mParcelSoldWithObjects)
  184. {
  185. childSetValue("sell_objects", "yes");
  186. }
  187. else
  188. {
  189. childSetValue("sell_objects", "no");
  190. }
  191. }
  192. else
  193. {
  194. childSetValue("price", "");
  195. childSetValue("sell_objects", "none");
  196. }
  197. mParcelSnapshot = parcelp->getSnapshotID();
  198. mAuthorizedBuyer = parcelp->getAuthorizedBuyerID();
  199. mSellToBuyer = mAuthorizedBuyer.notNull();
  200. if(mSellToBuyer)
  201. {
  202. std::string name;
  203. gCacheName->getFullName(mAuthorizedBuyer, name);
  204. childSetText("sell_to_agent", name);
  205. }
  206. }
  207. void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
  208. {
  209. static std::string badgeOK("badge_ok.j2c");
  210. static std::string badgeNote("badge_note.j2c");
  211. static std::string badgeWarn("badge_warn.j2c");
  212. static std::string badgeError("badge_error.j2c");
  213. std::string badgeName;
  214. switch (badge)
  215. {
  216. default:
  217. case BADGE_OK: badgeName = badgeOK; break;
  218. case BADGE_NOTE: badgeName = badgeNote; break;
  219. case BADGE_WARN: badgeName = badgeWarn; break;
  220. case BADGE_ERROR: badgeName = badgeError; break;
  221. }
  222. childSetValue(id, badgeName);
  223. }
  224. void LLFloaterSellLandUI::refreshUI()
  225. {
  226. LLParcel* parcelp = mParcelSelection->getParcel();
  227. if (!parcelp) return;
  228. LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("info_image");
  229. snapshot->setImageAssetID(mParcelSnapshot);
  230. childSetText("info_parcel", parcelp->getName());
  231. childSetTextArg("info_size", "[AREA]", llformat("%d", mParcelActualArea));
  232. std::string price_str = childGetValue("price").asString();
  233. bool valid_price = false;
  234. valid_price = (price_str != "") && LLTextValidate::validateNonNegativeS32(utf8str_to_wstring(price_str));
  235. if (valid_price && mParcelActualArea > 0)
  236. {
  237. F32 per_meter_price = 0;
  238. per_meter_price = F32(mParcelPrice) / F32(mParcelActualArea);
  239. childSetTextArg("price_per_m", "[PER_METER]", llformat("%0.2f", per_meter_price));
  240. childShow("price_per_m");
  241. setBadge("step_price", BADGE_OK);
  242. }
  243. else
  244. {
  245. childHide("price_per_m");
  246. if ("" == price_str)
  247. {
  248. setBadge("step_price", BADGE_NOTE);
  249. }
  250. else
  251. {
  252. setBadge("step_price", BADGE_ERROR);
  253. }
  254. }
  255. if (mSellToBuyer)
  256. {
  257. childSetValue("sell_to", "user");
  258. childShow("sell_to_agent");
  259. childShow("sell_to_select_agent");
  260. }
  261. else
  262. {
  263. if (mChoseSellTo)
  264. {
  265. childSetValue("sell_to", "anyone");
  266. }
  267. else
  268. {
  269. childSetValue("sell_to", "select");
  270. }
  271. childHide("sell_to_agent");
  272. childHide("sell_to_select_agent");
  273. }
  274. // Must select Sell To: Anybody, or User (with a specified username)
  275. std::string sell_to = childGetValue("sell_to").asString();
  276. bool valid_sell_to = "select" != sell_to &&
  277. ("user" != sell_to || mAuthorizedBuyer.notNull());
  278. if (!valid_sell_to)
  279. {
  280. setBadge("step_sell_to", BADGE_NOTE);
  281. }
  282. else
  283. {
  284. setBadge("step_sell_to", BADGE_OK);
  285. }
  286. bool valid_sell_objects = ("none" != childGetValue("sell_objects").asString());
  287. if (!valid_sell_objects)
  288. {
  289. setBadge("step_sell_objects", BADGE_NOTE);
  290. }
  291. else
  292. {
  293. setBadge("step_sell_objects", BADGE_OK);
  294. }
  295. if (valid_sell_to && valid_price && valid_sell_objects)
  296. {
  297. childEnable("sell_btn");
  298. }
  299. else
  300. {
  301. childDisable("sell_btn");
  302. }
  303. }
  304. // static
  305. void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata)
  306. {
  307. LLFloaterSellLandUI *self = (LLFloaterSellLandUI *)userdata;
  308. std::string sell_to = self->childGetValue("sell_to").asString();
  309. if (sell_to == "user")
  310. {
  311. self->mChoseSellTo = true;
  312. self->mSellToBuyer = true;
  313. if (self->mAuthorizedBuyer.isNull())
  314. {
  315. self->doSelectAgent();
  316. }
  317. }
  318. else if (sell_to == "anyone")
  319. {
  320. self->mChoseSellTo = true;
  321. self->mSellToBuyer = false;
  322. }
  323. self->mParcelPrice = self->childGetValue("price");
  324. if ("yes" == self->childGetValue("sell_objects").asString())
  325. {
  326. self->mParcelSoldWithObjects = true;
  327. }
  328. else
  329. {
  330. self->mParcelSoldWithObjects = false;
  331. }
  332. self->refreshUI();
  333. }
  334. void LLFloaterSellLandUI::doSelectAgent()
  335. {
  336. // grandparent is a floater, in order to set up dependency
  337. addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE));
  338. }
  339. void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
  340. {
  341. LLParcel* parcel = mParcelSelection->getParcel();
  342. if (names.empty() || ids.empty()) return;
  343. LLUUID id = ids[0];
  344. parcel->setAuthorizedBuyerID(id);
  345. mAuthorizedBuyer = ids[0];
  346. childSetText("sell_to_agent", names[0]);
  347. refreshUI();
  348. }
  349. // static
  350. void LLFloaterSellLandUI::doCancel(void *userdata)
  351. {
  352. LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
  353. self->closeFloater();
  354. }
  355. // static
  356. void LLFloaterSellLandUI::doShowObjects(void *userdata)
  357. {
  358. LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
  359. LLParcel* parcel = self->mParcelSelection->getParcel();
  360. if (!parcel) return;
  361. send_parcel_select_objects(parcel->getLocalID(), RT_SELL);
  362. LLNotificationsUtil::add("TransferObjectsHighlighted",
  363. LLSD(), LLSD(),
  364. &LLFloaterSellLandUI::callbackHighlightTransferable);
  365. }
  366. // static
  367. bool LLFloaterSellLandUI::callbackHighlightTransferable(const LLSD& notification, const LLSD& data)
  368. {
  369. LLSelectMgr::getInstance()->unhighlightAll();
  370. return false;
  371. }
  372. // static
  373. void LLFloaterSellLandUI::doSellLand(void *userdata)
  374. {
  375. LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
  376. LLParcel* parcel = self->mParcelSelection->getParcel();
  377. // Do a confirmation
  378. S32 sale_price = self->childGetValue("price");
  379. S32 area = parcel->getArea();
  380. std::string authorizedBuyerName = "Anyone";
  381. bool sell_to_anyone = true;
  382. if ("user" == self->childGetValue("sell_to").asString())
  383. {
  384. authorizedBuyerName = self->childGetText("sell_to_agent");
  385. sell_to_anyone = false;
  386. }
  387. // must sell to someone if indicating sale to anyone
  388. if (!parcel->getForSale() 
  389. && (sale_price == 0) 
  390. && sell_to_anyone)
  391. {
  392. LLNotificationsUtil::add("SalePriceRestriction");
  393. return;
  394. }
  395. LLSD args;
  396. args["LAND_SIZE"] = llformat("%d",area);
  397. args["SALE_PRICE"] = llformat("%d",sale_price);
  398. args["NAME"] = authorizedBuyerName;
  399. LLNotification::Params params("ConfirmLandSaleChange");
  400. params.substitutions(args)
  401. .functor.function(boost::bind(&LLFloaterSellLandUI::onConfirmSale, self, _1, _2));
  402. if (sell_to_anyone)
  403. {
  404. params.name("ConfirmLandSaleToAnyoneChange");
  405. }
  406. if (parcel->getForSale())
  407. {
  408. // parcel already for sale, so ignore this question
  409. LLNotifications::instance().forceResponse(params, -1);
  410. }
  411. else
  412. {
  413. // ask away
  414. LLNotifications::instance().add(params);
  415. }
  416. }
  417. bool LLFloaterSellLandUI::onConfirmSale(const LLSD& notification, const LLSD& response)
  418. {
  419. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  420. if (option != 0)
  421. {
  422. return false;
  423. }
  424. S32  sale_price = childGetValue("price");
  425. // Valid extracted data
  426. if (sale_price < 0)
  427. {
  428. // TomY TODO: Throw an error
  429. return false;
  430. }
  431. LLParcel* parcel = mParcelSelection->getParcel();
  432. if (!parcel) return false;
  433. // can_agent_modify_parcel deprecated by GROUPS
  434. //  if (!can_agent_modify_parcel(parcel))
  435. //  {
  436. //  close();
  437. //  return;
  438. //  }
  439. parcel->setParcelFlag(PF_FOR_SALE, TRUE);
  440. parcel->setSalePrice(sale_price);
  441. bool sell_with_objects = false;
  442. if ("yes" == childGetValue("sell_objects").asString())
  443. {
  444. sell_with_objects = true;
  445. }
  446. parcel->setSellWithObjects(sell_with_objects);
  447. if ("user" == childGetValue("sell_to").asString())
  448. {
  449. parcel->setAuthorizedBuyerID(mAuthorizedBuyer);
  450. }
  451. else
  452. {
  453. parcel->setAuthorizedBuyerID(LLUUID::null);
  454. }
  455. // Send update to server
  456. LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
  457. closeFloater();
  458. return false;
  459. }