00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "gui/itemcontainer.h"
00023
00024 #include "gui/chat.h"
00025 #include "gui/itempopup.h"
00026 #include "gui/palette.h"
00027 #include "gui/sdlinput.h"
00028 #include "gui/viewport.h"
00029
00030 #include "graphics.h"
00031 #include "inventory.h"
00032 #include "item.h"
00033 #include "itemshortcut.h"
00034 #include "localplayer.h"
00035 #include "log.h"
00036
00037 #include "resources/image.h"
00038 #include "resources/iteminfo.h"
00039 #include "resources/resourcemanager.h"
00040
00041 #include "utils/stringutils.h"
00042
00043 #include <guichan/mouseinput.hpp>
00044 #include <guichan/selectionlistener.hpp>
00045
00046
00047
00048
00049 static const int BOX_WIDTH = 35;
00050 static const int BOX_HEIGHT = 43;
00051
00052 ItemContainer::ItemContainer(Inventory *inventory, bool forceQuantity):
00053 mInventory(inventory),
00054 mGridColumns(1),
00055 mGridRows(1),
00056 mSelectedItem(NULL),
00057 mHighlightedItem(NULL),
00058 mSelectionStatus(SEL_NONE),
00059 mForceQuantity(forceQuantity),
00060 mSwapItems(false),
00061 mDescItems(false)
00062 {
00063 mItemPopup = new ItemPopup;
00064 setFocusable(true);
00065
00066 ResourceManager *resman = ResourceManager::getInstance();
00067
00068 mSelImg = resman->getImage("graphics/gui/selection.png");
00069 if (!mSelImg)
00070 logger->error("Unable to load selection.png");
00071
00072 addKeyListener(this);
00073 addMouseListener(this);
00074 addWidgetListener(this);
00075 }
00076
00077 ItemContainer::~ItemContainer()
00078 {
00079 mSelImg->decRef();
00080 delete mItemPopup;
00081 }
00082
00083 void ItemContainer::draw(gcn::Graphics *graphics)
00084 {
00085 Graphics *g = static_cast<Graphics*>(graphics);
00086
00087 g->setFont(getFont());
00088
00089 for (int i = 0; i < mGridColumns; i++)
00090 {
00091 for (int j = 0; j < mGridRows; j++)
00092 {
00093 int itemX = i * BOX_WIDTH;
00094 int itemY = j * BOX_HEIGHT;
00095
00096 Item *item = mInventory->getItem((j * mGridColumns) + i);
00097
00098 if (!item || item->getId() == 0)
00099 continue;
00100
00101 Image *image = item->getImage();
00102 if (image)
00103 {
00104 if (item == mSelectedItem)
00105 {
00106 if (mSelectionStatus == SEL_DRAGGING) {
00107
00108 itemX = mDragPosX - (BOX_WIDTH / 2);
00109 itemY = mDragPosY - (BOX_HEIGHT / 2);
00110 }
00111 else {
00112
00113 g->drawImage(mSelImg, itemX, itemY);
00114 }
00115 }
00116 g->drawImage(image, itemX, itemY);
00117 }
00118
00119 std::string caption;
00120 if (item->getQuantity() > 1 || mForceQuantity)
00121 caption = toString(item->getQuantity());
00122 else if (item->isEquipped())
00123 caption = "Eq.";
00124
00125 if (item->isEquipped())
00126 g->setColor(guiPalette->getColor(Palette::ITEM_EQUIPPED));
00127 else
00128 g->setColor(gcn::Color(0, 0, 0));
00129
00130 g->drawText(caption, itemX + BOX_WIDTH / 2,
00131 itemY + BOX_HEIGHT - 14, gcn::Graphics::CENTER);
00132 }
00133 }
00134
00135
00136 if (isFocused() && mHighlightedItem)
00137 {
00138 const int i = mHighlightedItem->getInvIndex();
00139 const int itemX = (i % mGridColumns) * BOX_WIDTH;
00140 const int itemY = (i / mGridColumns) * BOX_HEIGHT;
00141 g->setColor(gcn::Color(255, 128, 0));
00142 g->drawRectangle(gcn::Rectangle(itemX, itemY, BOX_WIDTH, BOX_HEIGHT));
00143 }
00144 }
00145
00146 void ItemContainer::selectNone()
00147 {
00148 setSelectedItem(NULL);
00149 }
00150
00151 void ItemContainer::setSelectedItem(Item *item)
00152 {
00153 if (mSelectedItem != item)
00154 {
00155 mSelectedItem = item;
00156 distributeValueChangedEvent();
00157 }
00158 }
00159
00160 void ItemContainer::distributeValueChangedEvent()
00161 {
00162 SelectionListenerIterator i, i_end;
00163
00164 for (i = mSelectionListeners.begin(), i_end = mSelectionListeners.end();
00165 i != i_end; ++i)
00166 {
00167 gcn::SelectionEvent event(this);
00168 (*i)->valueChanged(event);
00169 }
00170 }
00171
00172 void ItemContainer::keyPressed(gcn::KeyEvent &event)
00173 {
00174 switch (event.getKey().getValue())
00175 {
00176 case Key::LEFT:
00177 moveHighlight(Left);
00178 break;
00179 case Key::RIGHT:
00180 moveHighlight(Right);
00181 break;
00182 case Key::UP:
00183 moveHighlight(Up);
00184 break;
00185 case Key::DOWN:
00186 moveHighlight(Down);
00187 break;
00188 case Key::SPACE:
00189 keyAction();
00190 break;
00191 case Key::LEFT_ALT:
00192 case Key::RIGHT_ALT:
00193 mSwapItems = true;
00194 break;
00195 case Key::RIGHT_CONTROL:
00196 mDescItems = true;
00197 break;
00198 }
00199 }
00200
00201 void ItemContainer::keyReleased(gcn::KeyEvent &event)
00202 {
00203 switch (event.getKey().getValue())
00204 {
00205 case Key::LEFT_ALT:
00206 case Key::RIGHT_ALT:
00207 mSwapItems = false;
00208 break;
00209 case Key::RIGHT_CONTROL:
00210 mDescItems = false;
00211 break;
00212 }
00213 }
00214
00215 void ItemContainer::mousePressed(gcn::MouseEvent &event)
00216 {
00217 const int button = event.getButton();
00218 if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
00219 {
00220 const int index = getSlotIndex(event.getX(), event.getY());
00221 if (index == Inventory::NO_SLOT_INDEX)
00222 return;
00223
00224 Item *item = mInventory->getItem(index);
00225
00226
00227 if (mDescItems)
00228 {
00229 chatWindow->addItemText(item->getInfo().getName());
00230 }
00231
00232 if (mSelectedItem && mSelectedItem == item)
00233 {
00234 mSelectionStatus = SEL_DESELECTING;
00235 }
00236 else if (item && item->getId())
00237 {
00238 setSelectedItem(item);
00239 mSelectionStatus = SEL_SELECTING;
00240
00241 itemShortcut->setItemSelected(item->getId());
00242 }
00243 else
00244 {
00245 setSelectedItem(NULL);
00246 mSelectionStatus = SEL_NONE;
00247 }
00248 }
00249 }
00250
00251 void ItemContainer::mouseDragged(gcn::MouseEvent &event)
00252 {
00253 if (mSelectionStatus != SEL_NONE)
00254 {
00255 mSelectionStatus = SEL_DRAGGING;
00256 mDragPosX = event.getX();
00257 mDragPosY = event.getY();
00258 }
00259 }
00260
00261 void ItemContainer::mouseReleased(gcn::MouseEvent &event)
00262 {
00263 switch (mSelectionStatus)
00264 {
00265 case SEL_SELECTING:
00266 mSelectionStatus = SEL_SELECTED;
00267 return;
00268 case SEL_DESELECTING:
00269 setSelectedItem(NULL);
00270 mSelectionStatus = SEL_NONE;
00271 return;
00272 case SEL_DRAGGING:
00273 mSelectionStatus = SEL_SELECTED;
00274 break;
00275 default:
00276 return;
00277 };
00278
00279 int index = getSlotIndex(event.getX(), event.getY());
00280 if (index == Inventory::NO_SLOT_INDEX)
00281 return;
00282 Item *item = mInventory->getItem(index);
00283 if (item == mSelectedItem)
00284 return;
00285 player_node->moveInvItem(mSelectedItem, index);
00286 setSelectedItem(NULL);
00287 mSelectionStatus = SEL_NONE;
00288 }
00289
00290
00291
00292 void ItemContainer::mouseMoved(gcn::MouseEvent &event)
00293 {
00294 Item *item = mInventory->getItem(getSlotIndex(event.getX(), event.getY()));
00295
00296 if (item)
00297 {
00298 mItemPopup->setItem(item->getInfo());
00299 mItemPopup->view(viewport->getMouseX(), viewport->getMouseY());
00300 }
00301 else
00302 {
00303 mItemPopup->setVisible(false);
00304 }
00305 }
00306
00307
00308 void ItemContainer::mouseExited(gcn::MouseEvent &event)
00309 {
00310 mItemPopup->setVisible(false);
00311 }
00312
00313 void ItemContainer::widgetResized(const gcn::Event &event)
00314 {
00315 mGridColumns = std::max(1, getWidth() / BOX_WIDTH);
00316 mGridRows = mInventory->getSize() / mGridColumns;
00317 if (mGridRows == 0 || mInventory->getSize() % mGridColumns > 0)
00318 ++mGridRows;
00319
00320 setHeight(mGridRows * BOX_HEIGHT);
00321 }
00322
00323 int ItemContainer::getSlotIndex(int x, int y) const
00324 {
00325 if (x < getWidth() && y < getHeight())
00326 {
00327 return (y / BOX_HEIGHT) * mGridColumns + (x / BOX_WIDTH);
00328 }
00329 return Inventory::NO_SLOT_INDEX;
00330 }
00331
00332 void ItemContainer::keyAction()
00333 {
00334
00335 if (!mHighlightedItem)
00336 return;
00337
00338
00339 if (mHighlightedItem == mSelectedItem)
00340 {
00341 setSelectedItem(NULL);
00342 mSelectionStatus = SEL_NONE;
00343 }
00344
00345 else if (mSwapItems &&
00346 mSelectedItem &&
00347 mHighlightedItem->getId())
00348 {
00349 player_node->moveInvItem(
00350 mSelectedItem, mHighlightedItem->getInvIndex());
00351 setSelectedItem(mHighlightedItem);
00352 }
00353
00354 else if (mHighlightedItem->getId())
00355 {
00356 setSelectedItem(mHighlightedItem);
00357 mSelectionStatus = SEL_SELECTED;
00358 }
00359
00360 else if (mSelectedItem)
00361 {
00362 player_node->moveInvItem(
00363 mSelectedItem, mHighlightedItem->getInvIndex());
00364 setSelectedItem(NULL);
00365 mSelectionStatus = SEL_NONE;
00366 }
00367 }
00368
00369 void ItemContainer::moveHighlight(Direction direction)
00370 {
00371 if (!mHighlightedItem)
00372 {
00373 if (mSelectedItem) {
00374 mHighlightedItem = mSelectedItem;
00375 }
00376 else {
00377 mHighlightedItem = mInventory->getItem(0);
00378 }
00379 return;
00380 }
00381
00382 switch (direction)
00383 {
00384 case Left:
00385 if (mHighlightedItem->getInvIndex() % mGridColumns == 0)
00386 {
00387 mHighlightedItem += mGridColumns;
00388 }
00389 mHighlightedItem--;
00390 break;
00391 case Right:
00392 if ((mHighlightedItem->getInvIndex() % mGridColumns) ==
00393 (mGridColumns - 1))
00394 {
00395 mHighlightedItem -= mGridColumns;
00396 }
00397 mHighlightedItem++;
00398 break;
00399 case Up:
00400 if (mHighlightedItem->getInvIndex() / mGridColumns == 0)
00401 {
00402 mHighlightedItem += (mGridColumns * mGridRows);
00403 }
00404 mHighlightedItem -= mGridColumns;
00405 break;
00406 case Down:
00407 if ((mHighlightedItem->getInvIndex() / mGridColumns) ==
00408 (mGridRows - 1))
00409 {
00410 mHighlightedItem -= (mGridColumns * mGridRows);
00411 }
00412 mHighlightedItem += mGridColumns;
00413 break;
00414 }
00415 }