00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "gui/trade.h"
00023
00024 #include "inventory.h"
00025 #include "item.h"
00026 #include "localplayer.h"
00027 #include "units.h"
00028
00029 #include "gui/inventorywindow.h"
00030 #include "gui/item_amount.h"
00031 #include "gui/itemcontainer.h"
00032
00033 #include "gui/widgets/button.h"
00034 #include "gui/widgets/chattab.h"
00035 #include "gui/widgets/label.h"
00036 #include "gui/widgets/scrollarea.h"
00037 #include "gui/widgets/textfield.h"
00038 #include "gui/widgets/layout.h"
00039
00040 #include "net/net.h"
00041 #include "net/tradehandler.h"
00042
00043 #include "utils/gettext.h"
00044 #include "utils/stringutils.h"
00045 #include "utils/strprintf.h"
00046
00047
00048 #include <sstream>
00049
00050 #include <guichan/font.hpp>
00051
00052 #define CAPTION_PROPOSE _("Propose trade")
00053 #define CAPTION_CONFIRMED _("Confirmed. Waiting...")
00054 #define CAPTION_ACCEPT _("Agree trade")
00055 #define CAPTION_ACCEPTED _("Agreed. Waiting...")
00056
00057 TradeWindow::TradeWindow():
00058 Window(_("Trade: You")),
00059 mMyInventory(new Inventory(INVENTORY_SIZE)),
00060 mPartnerInventory(new Inventory(INVENTORY_SIZE)),
00061 mStatus(PROPOSING)
00062 {
00063 setWindowName("Trade");
00064 setResizable(true);
00065 setCloseButton(true);
00066 setDefaultSize(386, 180, ImageRect::CENTER);
00067 setMinWidth(386);
00068 setMinHeight(180);
00069
00070 std::string longestName = getFont()->getWidth(_("OK")) >
00071 getFont()->getWidth(_("Trade")) ?
00072 _("OK") : _("Trade");
00073
00074 mAddButton = new Button(_("Add"), "add", this);
00075 mOkButton = new Button("", "", this);
00076
00077 int width = std::max(mOkButton->getFont()->getWidth(CAPTION_PROPOSE),
00078 mOkButton->getFont()->getWidth(CAPTION_CONFIRMED));
00079 width = std::max(width, mOkButton->getFont()->getWidth(CAPTION_ACCEPT));
00080 width = std::max(width, mOkButton->getFont()->getWidth(CAPTION_ACCEPTED));
00081
00082 mOkButton->setWidth(8 + width);
00083
00084 mMyItemContainer = new ItemContainer(mMyInventory.get());
00085 mMyItemContainer->addSelectionListener(this);
00086
00087 ScrollArea *myScroll = new ScrollArea(mMyItemContainer);
00088 myScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
00089
00090 mPartnerItemContainer = new ItemContainer(mPartnerInventory.get());
00091 mPartnerItemContainer->addSelectionListener(this);
00092
00093 ScrollArea *partnerScroll = new ScrollArea(mPartnerItemContainer);
00094 partnerScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
00095
00096 mMoneyLabel = new Label(strprintf(_("You get %s."), ""));
00097 gcn::Label *mMoneyLabel2 = new Label(_("You give:"));
00098
00099 mMoneyField = new TextField;
00100 mMoneyField->setWidth(40);
00101 mMoneyChangeButton = new Button(_("Change"), "money", this);
00102
00103 place(1, 0, mMoneyLabel);
00104 place(0, 1, myScroll).setPadding(3);
00105 place(1, 1, partnerScroll).setPadding(3);
00106 ContainerPlacer place;
00107 place = getPlacer(0, 0);
00108 place(0, 0, mMoneyLabel2);
00109 place(1, 0, mMoneyField);
00110 place(2, 0, mMoneyChangeButton).setHAlign(LayoutCell::LEFT);
00111 place = getPlacer(0, 2);
00112 place(0, 0, mAddButton);
00113 place(1, 0, mOkButton);
00114 Layout &layout = getLayout();
00115 layout.extend(0, 2, 2, 1);
00116 layout.setRowHeight(1, Layout::AUTO_SET);
00117 layout.setRowHeight(2, 0);
00118 layout.setColWidth(0, Layout::AUTO_SET);
00119 layout.setColWidth(1, Layout::AUTO_SET);
00120
00121 loadWindowState();
00122
00123 reset();
00124 }
00125
00126 TradeWindow::~TradeWindow()
00127 {
00128 }
00129
00130 void TradeWindow::setMoney(int amount)
00131 {
00132 mMoneyLabel->setCaption(strprintf(_("You get %s."),
00133 Units::formatCurrency(amount).c_str()));
00134 mMoneyLabel->adjustSize();
00135 }
00136
00137 void TradeWindow::addItem(int id, bool own, int quantity)
00138 {
00139 (own ? mMyInventory : mPartnerInventory)->addItem(id, quantity);
00140 }
00141
00142 void TradeWindow::addItem(int id, bool own, int quantity, bool equipment)
00143 {
00144 if (own)
00145 {
00146 mMyInventory->addItem(id, quantity, equipment);
00147 }
00148 else
00149 {
00150 mPartnerInventory->addItem(id, quantity, equipment);
00151 }
00152 }
00153
00154 void TradeWindow::changeQuantity(int index, bool own, int quantity)
00155 {
00156 if (own)
00157 mMyInventory->getItem(index)->setQuantity(quantity);
00158 else
00159 mPartnerInventory->getItem(index)->setQuantity(quantity);
00160 }
00161
00162 void TradeWindow::increaseQuantity(int index, bool own, int quantity)
00163 {
00164 if (own)
00165 mMyInventory->getItem(index)->increaseQuantity(quantity);
00166 else
00167 mPartnerInventory->getItem(index)->increaseQuantity(quantity);
00168 }
00169
00170 void TradeWindow::reset()
00171 {
00172 mMyInventory->clear();
00173 mPartnerInventory->clear();
00174 mOkOther = false;
00175 mOkMe = false;
00176 setMoney(0);
00177 mMoneyField->setEnabled(true);
00178 mMoneyField->setText("");
00179 mAddButton->setEnabled(true);
00180 mMoneyChangeButton->setEnabled(true);
00181 setStatus(PREPARING);
00182 }
00183
00184 void TradeWindow::receivedOk(bool own)
00185 {
00186 if (own)
00187 mOkMe = true;
00188 else
00189 mOkOther = true;
00190
00191 if (mOkMe && mOkOther)
00192 {
00193
00194
00195 setStatus(ACCEPTING);
00196 }
00197 }
00198
00199 void TradeWindow::tradeItem(Item *item, int quantity)
00200 {
00201 Net::getTradeHandler()->addItem(item, quantity);
00202 }
00203
00204 void TradeWindow::valueChanged(const gcn::SelectionEvent &event)
00205 {
00206 const Item *item;
00207
00208
00209
00210
00211 if (event.getSource() == mMyItemContainer &&
00212 (item = mMyItemContainer->getSelectedItem()))
00213 mPartnerItemContainer->selectNone();
00214 else if ((item = mPartnerItemContainer->getSelectedItem()))
00215 mMyItemContainer->selectNone();
00216 }
00217
00218 void TradeWindow::setStatus(Status s)
00219 {
00220 if (s == mStatus)
00221 return;
00222 mStatus = s;
00223
00224 switch (s)
00225 {
00226 case PREPARING:
00227 mOkButton->setCaption(CAPTION_PROPOSE);
00228 mOkButton->setActionEventId("ok");
00229 break;
00230 case PROPOSING:
00231 mOkButton->setCaption(CAPTION_CONFIRMED);
00232 mOkButton->setActionEventId("");
00233 break;
00234 case ACCEPTING:
00235 mOkButton->setCaption(CAPTION_ACCEPT);
00236 mOkButton->setActionEventId("trade");
00237 break;
00238 case ACCEPTED:
00239 mOkButton->setCaption(CAPTION_ACCEPTED);
00240 mOkButton->setActionEventId("");
00241 break;
00242 default:
00243 break;
00244 }
00245
00246 mOkButton->setEnabled((s != PROPOSING && s != ACCEPTED));
00247 }
00248
00249 void TradeWindow::action(const gcn::ActionEvent &event)
00250 {
00251 Item *item = inventoryWindow->getSelectedItem();
00252
00253 if (event.getId() == "add")
00254 {
00255 if(mStatus != PREPARING)
00256 return;
00257
00258 if (!inventoryWindow->isVisible())
00259 return;
00260
00261 if (!item)
00262 return;
00263
00264 if (mMyInventory->getFreeSlot() == -1)
00265 return;
00266
00267 if (mMyInventory->contains(item))
00268 {
00269 localChatTab->chatLog(_("Failed adding item. You can not "
00270 "overlap one kind of item on the window."),
00271 BY_SERVER);
00272 return;
00273 }
00274
00275 if (item->getQuantity() == 1)
00276 {
00277 tradeItem(item, 1);
00278 }
00279 else
00280 {
00281
00282 new ItemAmountWindow(ItemAmountWindow::TradeAdd, this, item);
00283 }
00284
00285 setStatus(PREPARING);
00286 }
00287 else if (event.getId() == "cancel")
00288 {
00289 setVisible(false);
00290 reset();
00291 player_node->setTrading(false);
00292
00293 Net::getTradeHandler()->cancel();
00294 }
00295 else if (event.getId() == "ok")
00296 {
00297 mMoneyField->setEnabled(false);
00298 mAddButton->setEnabled(false);
00299 mMoneyChangeButton->setEnabled(false);
00300 receivedOk(true);
00301 setStatus(PROPOSING);
00302 Net::getTradeHandler()->confirm();
00303 }
00304 else if (event.getId() == "trade")
00305 {
00306 receivedOk(true);
00307 setStatus(ACCEPTED);
00308 Net::getTradeHandler()->finish();
00309 }
00310 else if (event.getId() == "money")
00311 {
00312 if(mStatus != PREPARING)
00313 return;
00314
00315 int v = atoi(mMoneyField->getText().c_str());
00316 int curMoney = player_node->getMoney();
00317 if(v > curMoney)
00318 {
00319 localChatTab->chatLog(_("You don't have enough money"), BY_SERVER);
00320 v = curMoney;
00321 }
00322 Net::getTradeHandler()->setMoney(v);
00323 mMoneyField->setText(strprintf("%d", v));
00324 }
00325 }
00326
00327 void TradeWindow::close()
00328 {
00329 Net::getTradeHandler()->cancel();
00330 }