summaryrefslogtreecommitdiff
path: root/src/gui/inventorywindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/inventorywindow.cpp')
-rw-r--r--src/gui/inventorywindow.cpp503
1 files changed, 503 insertions, 0 deletions
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
new file mode 100644
index 000000000..abb702005
--- /dev/null
+++ b/src/gui/inventorywindow.cpp
@@ -0,0 +1,503 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/inventorywindow.h"
+
+#include "inventory.h"
+#include "item.h"
+#include "units.h"
+#include "keyboardconfig.h"
+#include "playerinfo.h"
+
+#include "gui/itemamount.h"
+#include "gui/setup.h"
+#include "gui/sdlinput.h"
+#include "gui/shopwindow.h"
+#include "gui/theme.h"
+#include "gui/viewport.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/itemcontainer.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layout.h"
+#include "gui/widgets/progressbar.h"
+#include "gui/widgets/scrollarea.h"
+
+#include "net/inventoryhandler.h"
+#include "net/net.h"
+
+#include "resources/iteminfo.h"
+
+#include "utils/dtor.h"
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <guichan/font.hpp>
+#include <guichan/mouseinput.hpp>
+
+#include <string>
+
+InventoryWindow::WindowList InventoryWindow::instances;
+
+InventoryWindow::InventoryWindow(Inventory *inventory):
+ Window(inventory ? (inventory->isMainInventory()
+ ? _("Inventory") : _("Storage")) : _("Inventory")),
+ mInventory(inventory),
+ mDropButton(0),
+ mSplit(false)
+{
+ listen(CHANNEL_ATTRIBUTES);
+
+ setWindowName(isMainInventory() ? "Inventory" : "Storage");
+
+ if (setupWindow)
+ setupWindow->registerWindowForReset(this);
+
+ setResizable(true);
+ setCloseButton(true);
+ setSaveVisible(true);
+
+ setDefaultSize(387, 307, ImageRect::CENTER);
+ setMinWidth(316);
+ setMinHeight(179);
+ addKeyListener(this);
+
+ mItems = new ItemContainer(mInventory);
+ mItems->addSelectionListener(this);
+
+ gcn::ScrollArea *invenScroll = new ScrollArea(mItems);
+ invenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ mSlotsLabel = new Label(_("Slots:"));
+ mSlotsBar = new ProgressBar(0.0f, 100, 20, Theme::PROG_INVY_SLOTS);
+
+ if (isMainInventory())
+ {
+ std::string equip = _("Equip");
+ std::string use = _("Use");
+ std::string unequip = _("Unequip");
+
+ std::string longestUseString = getFont()->getWidth(equip) >
+ getFont()->getWidth(use) ? equip : use;
+
+ if (getFont()->getWidth(longestUseString) <
+ getFont()->getWidth(unequip))
+ {
+ longestUseString = unequip;
+ }
+
+ mUseButton = new Button(longestUseString, "use", this);
+ mUseButton2 = new Button(longestUseString, "equip", this);
+ mDropButton = new Button(_("Drop..."), "drop", this);
+ mSplitButton = new Button(_("Split"), "split", this);
+ mOutfitButton = new Button(_("Outfits"), "outfit", this);
+ mShopButton = new Button(_("Shop"), "shop", this);
+
+ mWeightLabel = new Label(_("Weight:"));
+ mWeightBar = new ProgressBar(0.0f, 100, 20, Theme::PROG_WEIGHT);
+
+ place(0, 0, mWeightLabel).setPadding(3);
+ place(1, 0, mWeightBar, 3);
+ place(4, 0, mSlotsLabel).setPadding(3);
+ place(5, 0, mSlotsBar, 2);
+ place(0, 1, invenScroll, 7).setPadding(3);
+ place(0, 2, mUseButton);
+ place(1, 2, mUseButton2);
+ place(2, 2, mDropButton);
+ place(4, 2, mSplitButton);
+ place(5, 2, mShopButton);
+ place(6, 2, mOutfitButton);
+
+ updateWeight();
+ }
+ else
+ {
+ mStoreButton = new Button(_("Store"), "store", this);
+ mRetrieveButton = new Button(_("Retrieve"), "retrieve", this);
+ mCloseButton = new Button(_("Close"), "close", this);
+
+ place(0, 0, mSlotsLabel).setPadding(3);
+ place(1, 0, mSlotsBar, 3);
+ place(0, 1, invenScroll, 4, 4);
+ place(0, 5, mStoreButton);
+ place(1, 5, mRetrieveButton);
+ place(3, 5, mCloseButton);
+ }
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(1, Layout::AUTO_SET);
+
+ mInventory->addInventoyListener(this);
+
+ instances.push_back(this);
+
+ if (inventory->isMainInventory())
+ {
+ updateDropButton();
+ }
+ else
+ {
+ if (!instances.empty())
+ instances.front()->updateDropButton();
+ }
+
+ loadWindowState();
+ slotsChanged(mInventory);
+
+ if (!isMainInventory())
+ setVisible(true);
+}
+
+InventoryWindow::~InventoryWindow()
+{
+ instances.remove(this);
+ mInventory->removeInventoyListener(this);
+ if (!instances.empty())
+ instances.front()->updateDropButton();
+}
+
+void InventoryWindow::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "outfit")
+ {
+ extern Window *outfitWindow;
+ if (outfitWindow)
+ {
+ outfitWindow->setVisible(!outfitWindow->isVisible());
+ if (outfitWindow->isVisible())
+ outfitWindow->requestMoveToTop();
+ }
+ }
+
+ if (event.getId() == "shop")
+ {
+ if (shopWindow)
+ {
+ shopWindow->setVisible(!shopWindow->isVisible());
+ if (shopWindow->isVisible())
+ shopWindow->requestMoveToTop();
+ }
+ }
+ else if (event.getId() == "close")
+ {
+ close();
+ }
+ else if (event.getId() == "store")
+ {
+ if (!inventoryWindow || !inventoryWindow->isVisible())
+ return;
+
+ Item *item = inventoryWindow->getSelectedItem();
+
+ if (!item)
+ return;
+
+ ItemAmountWindow::showWindow(ItemAmountWindow::StoreAdd, this, item);
+ }
+
+ Item *item = mItems->getSelectedItem();
+
+ if (!item)
+ return;
+
+ if (event.getId() == "use")
+ {
+ if (item->isEquipment())
+ {
+ if (item->isEquipped())
+ Net::getInventoryHandler()->unequipItem(item);
+ else
+ Net::getInventoryHandler()->equipItem(item);
+ }
+ else
+ Net::getInventoryHandler()->useItem(item);
+ }
+ if (event.getId() == "equip")
+ {
+ if (!item->isEquipment())
+ {
+ if (item->isEquipped())
+ Net::getInventoryHandler()->unequipItem(item);
+ else
+ Net::getInventoryHandler()->equipItem(item);
+ }
+ else
+ Net::getInventoryHandler()->useItem(item);
+ }
+ else if (event.getId() == "drop")
+ {
+ if (isStorageActive())
+ {
+ Item *item = mItems->getSelectedItem();
+
+ if (!item)
+ return;
+
+ Net::getInventoryHandler()->moveItem(Inventory::INVENTORY,
+ item->getInvIndex(), item->getQuantity(),
+ Inventory::STORAGE);
+ }
+ else
+ {
+ ItemAmountWindow::showWindow(ItemAmountWindow::ItemDrop,
+ this, item);
+ }
+ }
+ else if (event.getId() == "split")
+ {
+ ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, this, item,
+ (item->getQuantity() - 1));
+ }
+ else if (event.getId() == "retrieve")
+ {
+ Item *item = mItems->getSelectedItem();
+
+ if (!item)
+ return;
+
+ ItemAmountWindow::showWindow(ItemAmountWindow::StoreRemove, this,
+ item);
+ }
+}
+
+Item *InventoryWindow::getSelectedItem() const
+{
+ return mItems->getSelectedItem();
+}
+
+void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
+{
+ Window::mouseClicked(event);
+
+ if (event.getButton() == gcn::MouseEvent::RIGHT)
+ {
+ Item *item = mItems->getSelectedItem();
+
+ if (!item)
+ return;
+
+ /* Convert relative to the window coordinates to absolute screen
+ * coordinates.
+ */
+ const int mx = event.getX() + getX();
+ const int my = event.getY() + getY();
+
+ if (viewport)
+ viewport->showPopup(this, mx, my, item, isMainInventory());
+ }
+
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (isStorageActive() && keyboard.isKeyActive(keyboard.KEY_EMOTE))
+ {
+ Item *item = mItems->getSelectedItem();
+
+ if (!item || !mInventory)
+ return;
+
+ if (mInventory->isMainInventory())
+ {
+ Net::getInventoryHandler()->moveItem(Inventory::INVENTORY,
+ item->getInvIndex(), item->getQuantity(),
+ Inventory::STORAGE);
+ }
+ else
+ {
+ Net::getInventoryHandler()->moveItem(Inventory::STORAGE,
+ item->getInvIndex(), item->getQuantity(),
+ Inventory::INVENTORY);
+ }
+ }
+ }
+}
+
+void InventoryWindow::keyPressed(gcn::KeyEvent &event)
+{
+ switch (event.getKey().getValue())
+ {
+ case Key::LEFT_SHIFT:
+ case Key::RIGHT_SHIFT:
+ mSplit = true;
+ break;
+ default:
+ break;
+ }
+}
+
+void InventoryWindow::keyReleased(gcn::KeyEvent &event)
+{
+ switch (event.getKey().getValue())
+ {
+ case Key::LEFT_SHIFT:
+ case Key::RIGHT_SHIFT:
+ mSplit = false;
+ break;
+ default:
+ break;
+ }
+}
+
+void InventoryWindow::valueChanged(const gcn::SelectionEvent &event _UNUSED_)
+{
+ if (!mInventory || !mInventory->isMainInventory())
+ return;
+
+ Item *item = mItems->getSelectedItem();
+
+ if (mSplit && item && Net::getInventoryHandler()->
+ canSplit(mItems->getSelectedItem()))
+ {
+ ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, this, item,
+ (item->getQuantity() - 1));
+ }
+
+ if (!item || item->getQuantity() == 0)
+ {
+ if (mUseButton)
+ mUseButton->setEnabled(true);
+ if (mUseButton2)
+ mUseButton2->setEnabled(true);
+ if (mDropButton)
+ mDropButton->setEnabled(true);
+ return;
+ }
+
+ if (mUseButton)
+ mUseButton->setEnabled(true);
+ if (mUseButton2)
+ mUseButton2->setEnabled(true);
+ if (mDropButton)
+ mDropButton->setEnabled(true);
+
+ if (mUseButton && item && item->isEquipment())
+ {
+ if (item->isEquipped())
+ mUseButton->setCaption(_("Unequip"));
+ else
+ mUseButton->setCaption(_("Equip"));
+ mUseButton2->setCaption(_("Use"));
+ }
+ else if (mUseButton2)
+ {
+ mUseButton->setCaption(_("Use"));
+ if (item->isEquipped())
+ mUseButton2->setCaption(_("Unequip"));
+ else
+ mUseButton2->setCaption(_("Equip"));
+ }
+
+ updateDropButton();
+
+ if (mSplitButton)
+ {
+ if (Net::getInventoryHandler()->canSplit(item))
+ mSplitButton->setEnabled(true);
+ else
+ mSplitButton->setEnabled(false);
+ }
+}
+
+
+void InventoryWindow::setSplitAllowed(bool allowed)
+{
+ mSplitButton->setVisible(allowed);
+}
+
+void InventoryWindow::close()
+{
+ if (this == inventoryWindow)
+ {
+ setVisible(false);
+ }
+ else
+ {
+ Net::getInventoryHandler()->closeStorage(Inventory::STORAGE);
+ scheduleDelete();
+ }
+}
+
+void InventoryWindow::event(Channels channel _UNUSED_,
+ const Mana::Event &event)
+{
+ if (event.getName() == EVENT_UPDATEATTRIBUTE)
+ {
+ int id = event.getInt("id");
+ if (id == TOTAL_WEIGHT || id == MAX_WEIGHT)
+ updateWeight();
+ }
+}
+
+void InventoryWindow::updateWeight()
+{
+ if (!isMainInventory())
+ return;
+
+ int total = PlayerInfo::getAttribute(TOTAL_WEIGHT);
+ int max = PlayerInfo::getAttribute(MAX_WEIGHT);
+
+ if (max <= 0)
+ return;
+
+ // Adjust progress bar
+ mWeightBar->setProgress(static_cast<float>(total)
+ / static_cast<float>(max));
+ mWeightBar->setText(strprintf("%s/%s", Units::formatWeight(total).c_str(),
+ Units::formatWeight(max).c_str()));
+}
+
+void InventoryWindow::slotsChanged(Inventory* inventory)
+{
+ if (inventory == mInventory)
+ {
+ const int usedSlots = mInventory->getNumberOfSlotsUsed();
+ const int maxSlots = mInventory->getSize();
+
+ if (maxSlots)
+ {
+ mSlotsBar->setProgress(static_cast<float>(usedSlots)
+ / static_cast<float>(maxSlots));
+ }
+
+ mSlotsBar->setText(strprintf("%d/%d", usedSlots, maxSlots));
+ }
+}
+
+void InventoryWindow::updateDropButton()
+{
+ if (!mDropButton)
+ return;
+
+ if (isStorageActive())
+ {
+ mDropButton->setCaption(_("Store"));
+ }
+ else
+ {
+ Item *item = 0;
+ if (mItems)
+ item = mItems->getSelectedItem();
+
+ if (item && item->getQuantity() > 1)
+ mDropButton->setCaption(_("Drop..."));
+ else
+ mDropButton->setCaption(_("Drop"));
+ }
+}