From 77efbb50066a030d1f44f8de8d06ace9f284e3a2 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Sun, 3 Sep 2006 15:00:47 +0000 Subject: Introduced SelectionListener to fix updating problem in inventory window (should also be used to fix similar problem in trade, buy and sell dialogs). Made the ItemInfo be passed around as a reference instead of a pointer, since it is never NULL. --- src/Makefile.am | 1 + src/floor_item.cpp | 4 +-- src/gui/buy.cpp | 12 ++++--- src/gui/equipmentwindow.cpp | 4 +-- src/gui/inventorywindow.cpp | 58 +++++++++++++++++++------------- src/gui/inventorywindow.h | 16 ++++++--- src/gui/itemcontainer.cpp | 35 +++++++++++++++---- src/gui/itemcontainer.h | 35 ++++++++++++++++++- src/gui/popupmenu.cpp | 2 +- src/gui/selectionlistener.h | 78 +++++++++++++++++++++++++++++++++++++++++++ src/gui/sell.cpp | 11 +++--- src/gui/trade.cpp | 4 +-- src/item.h | 2 +- src/net/inventoryhandler.cpp | 11 ++---- src/resources/iteminfo.cpp | 31 +++++++++++------ src/resources/iteminfo.h | 34 +++++++++++-------- src/resources/itemmanager.cpp | 9 ++--- src/resources/itemmanager.h | 8 ++--- 18 files changed, 259 insertions(+), 96 deletions(-) create mode 100644 src/gui/selectionlistener.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index fb67496f..d523422c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,7 @@ tmw_SOURCES = graphic/imagerect.h \ gui/register.h \ gui/scrollarea.cpp \ gui/scrollarea.h \ + gui/selectionlistener.h \ gui/sell.cpp \ gui/sell.h \ gui/setup_audio.cpp \ diff --git a/src/floor_item.cpp b/src/floor_item.cpp index edd5d4a7..9a179a21 100644 --- a/src/floor_item.cpp +++ b/src/floor_item.cpp @@ -42,7 +42,7 @@ FloorItem::FloorItem(unsigned int id, mMap(map) { // Retrieve item image from item info - mImage = itemDb->getItemInfo(itemId)->getImage(); + mImage = itemDb->getItemInfo(itemId).getImage(); // Add ourselves to the map mSpriteIterator = mMap->addSprite(this); @@ -50,6 +50,6 @@ FloorItem::FloorItem(unsigned int id, FloorItem::~FloorItem() { - // Remove and delete the representative sprite + // Remove ourselves from the map mMap->removeSprite(mSpriteIterator); } diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 7b9eb29c..20ceca92 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -140,7 +140,8 @@ void BuyDialog::addItem(short id, int price) { ITEM_SHOP item_shop; - item_shop.name = itemDb->getItemInfo(id)->getName() + " " + toString(price) + " GP"; + item_shop.name = itemDb->getItemInfo(id).getName() + " " + + toString(price) + " GP"; item_shop.price = price; item_shop.id = id; @@ -262,9 +263,10 @@ void BuyDialog::mouseClick(int x, int y, int button, int count) int selectedItem = mItemList->getSelected(); if (selectedItem > -1) { - mItemDescLabel->setCaption("Description: " + - itemDb->getItemInfo(mShopItems->at(selectedItem).id)->getDescription()); - mItemEffectLabel->setCaption("Effect: " + - itemDb->getItemInfo(mShopItems->at(selectedItem).id)->getEffect()); + const ItemInfo &info = + itemDb->getItemInfo(mShopItems->at(selectedItem).id); + + mItemDescLabel->setCaption("Description: " + info.getDescription()); + mItemEffectLabel->setCaption("Effect: " + info.getEffect()); } } diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index 2cbffde4..ec525c47 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -65,7 +65,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) continue; } - image = item->getInfo()->getImage(); + image = item->getInfo().getImage(); dynamic_cast(graphics)->drawImage( image, 36 * (i % 4) + 10, 36 * (i / 4) + 25); } @@ -76,7 +76,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) return; } - image = item->getInfo()->getImage(); + image = item->getInfo().getImage(); dynamic_cast(graphics)->drawImage(image, 160, 25); graphics->drawText(toString(item->getQuantity()), 170, 62, diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 04f07479..5812a71a 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -55,6 +55,8 @@ InventoryWindow::InventoryWindow(): mDropButton = new Button("Drop", "drop", this); mItems = new ItemContainer(player_node->mInventory.get()); + mItems->addSelectionListener(this); + mInvenScroll = new ScrollArea(mItems); mInvenScroll->setPosition(8, 8); mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); @@ -123,33 +125,46 @@ void InventoryWindow::action(const std::string& eventId, gcn::Widget* widget) } } -void InventoryWindow::mouseClick(int x, int y, int button, int count) +void InventoryWindow::selectionChanged(const SelectionEvent &event) { - Window::mouseClick(x, y, button, count); - Item *item = mItems->getItem(); - if (!item) { - return; + // Update name, effect and description + if (!item) + { + mItemNameLabel->setCaption("Name:"); + mItemEffectLabel->setCaption("Effect:"); + mItemDescriptionLabel->setCaption("Description:"); + } + else + { + const ItemInfo& itemInfo = item->getInfo(); + std::string SomeText; + SomeText = "Name: " + itemInfo.getName(); + mItemNameLabel->setCaption(SomeText); + SomeText = "Effect: " + itemInfo.getEffect(); + mItemEffectLabel->setCaption(SomeText); + SomeText = "Description: " + itemInfo.getDescription(); + mItemDescriptionLabel->setCaption(SomeText); + + mItemNameLabel->adjustSize(); + mItemEffectLabel->adjustSize(); + mItemDescriptionLabel->adjustSize(); } +} - // Show Name and Description - std::string SomeText; - SomeText = "Name: " + item->getInfo()->getName(); - mItemNameLabel->setCaption(SomeText); - mItemNameLabel->adjustSize(); - SomeText = "Effect: " + item->getInfo()->getEffect(); - mItemEffectLabel->setCaption(SomeText); - mItemEffectLabel->adjustSize(); - SomeText = "Description: " + item->getInfo()->getDescription(); - mItemDescriptionLabel->setCaption(SomeText); - mItemDescriptionLabel->adjustSize(); +void InventoryWindow::mouseClick(int x, int y, int button, int count) +{ + Window::mouseClick(x, y, button, count); if (button == gcn::MouseInput::RIGHT) { - /* - * convert relative to the window coordinates to - * absolute screen coordinates + Item *item = mItems->getItem(); + + if (!item) return; + + /* Convert relative to the window coordinates to + * absolute screen coordinates. */ int mx = x + getX(); int my = y + getY(); @@ -223,11 +238,6 @@ void InventoryWindow::loadWindowState() updateWidgets(); } -void InventoryWindow::setDefaultSize(int defaultX, int defaultY, int defaultWidth, int defaultHeight) -{ - Window::setDefaultSize(defaultX, defaultY, defaultWidth, defaultHeight); -} - void InventoryWindow::resetToDefaultSize() { Window::resetToDefaultSize(); diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h index da7a7ef2..a2c7535b 100644 --- a/src/gui/inventorywindow.h +++ b/src/gui/inventorywindow.h @@ -27,6 +27,7 @@ #include #include "window.h" +#include "selectionlistener.h" #include "../guichanfwd.h" @@ -38,7 +39,7 @@ class ItemContainer; * * \ingroup Interface */ -class InventoryWindow : public Window, gcn::ActionListener +class InventoryWindow : public Window, gcn::ActionListener, SelectionListener { public: /** @@ -47,14 +48,14 @@ class InventoryWindow : public Window, gcn::ActionListener InventoryWindow(); /** - * Logic (updates buttons and weight information) + * Logic (updates buttons and weight information). */ void logic(); /** * Called when receiving actions from the widgets. */ - void action(const std::string& eventId, gcn::Widget* widget); + void action(const std::string &eventId, gcn::Widget *widget); void mouseClick(int x, int y, int button, int count); @@ -64,10 +65,15 @@ class InventoryWindow : public Window, gcn::ActionListener void loadWindowState(); - void setDefaultSize(int defaultX, int defaultY, int defaultWidth, int defaultHeight); - void resetToDefaultSize(); + /** + * Updates labels to currently selected item. + * + * @see SelectionListener::selectionChanged. + */ + void selectionChanged(const SelectionEvent &event); + private: void updateButtons(); /** Updates button states */ diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index c7c55fd9..5bcd000d 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -25,6 +25,8 @@ #include +#include "selectionlistener.h" + #include "../graphics.h" #include "../inventory.h" #include "../item.h" @@ -38,14 +40,14 @@ #include "../utils/tostring.h" ItemContainer::ItemContainer(Inventory *inventory): - mInventory(inventory) + mInventory(inventory), + mSelectedItem(NULL) { ResourceManager *resman = ResourceManager::getInstance(); mSelImg = resman->getImage("graphics/gui/selection.png"); if (!mSelImg) logger->error("Unable to load selection.png"); - mSelectedItem = 0; // No item selected mMaxItems = mInventory->getLastUsedSlot() - 1; // Count from 0, usage from 2 addMouseListener(this); @@ -84,7 +86,7 @@ void ItemContainer::draw(gcn::Graphics* graphics) // sure somewhere else) if (mSelectedItem && mSelectedItem->getQuantity() <= 0) { - mSelectedItem = 0; + selectNone(); } /* @@ -111,7 +113,7 @@ void ItemContainer::draw(gcn::Graphics* graphics) // Draw item icon Image* image; - if ((image = item->getInfo()->getImage()) != NULL) + if ((image = item->getInfo().getImage()) != NULL) { dynamic_cast(graphics)->drawImage( image, itemX, itemY); @@ -150,7 +152,28 @@ Item* ItemContainer::getItem() void ItemContainer::selectNone() { - mSelectedItem = 0; + setSelectedItem(NULL); +} + +void ItemContainer::setSelectedItem(Item *item) +{ + if (mSelectedItem != item) + { + mSelectedItem = item; + fireSelectionChangedEvent(); + } +} + +void ItemContainer::fireSelectionChangedEvent() +{ + SelectionEvent event(this); + SelectionListeners::iterator i_end = mListeners.end(); + SelectionListeners::iterator i; + + for (i = mListeners.begin(); i != i_end; ++i) + { + (*i)->selectionChanged(event); + } } void ItemContainer::mousePress(int mx, int my, int button) @@ -166,6 +189,6 @@ void ItemContainer::mousePress(int mx, int my, int button) if (index > INVENTORY_SIZE) { index = INVENTORY_SIZE - 1; } - mSelectedItem = mInventory->getItem(index); + setSelectedItem(mInventory->getItem(index)); } } diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h index f52f37ec..a2d5f0f7 100644 --- a/src/gui/itemcontainer.h +++ b/src/gui/itemcontainer.h @@ -27,9 +27,12 @@ #include #include +#include + class Image; class Inventory; class Item; +class SelectionListener; /** * An item container. Used to show items in inventory and trade dialog. @@ -76,16 +79,46 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener Item* getItem(); /** - * Set selected item to -1. + * Sets selected item to NULL. */ void selectNone(); + /** + * Adds a listener to the list that's notified each time a change to + * the selection occurs. + */ + void addSelectionListener(SelectionListener *listener) + { + mListeners.push_back(listener); + } + + /** + * Removes a listener from the list that's notified each time a change + * to the selection occurs. + */ + void removeSelectionListener(SelectionListener *listener) + { + mListeners.remove(listener); + } + private: + /** + * Sets the currently selected item. + */ + void setSelectedItem(Item *item); + + /** + * Sends out selection events to the list of selection listeners. + */ + void fireSelectionChangedEvent(); + Inventory *mInventory; Image *mSelImg; Item *mSelectedItem; int mMaxItems; + + std::list mListeners; }; #endif diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 59316de1..ab81f7d0 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -106,7 +106,7 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem) mBrowserBox->clearRows(); // Floor item can be picked up (single option, candidate for removal) - std::string name = itemDb->getItemInfo(mFloorItem->getItemId())->getName(); + std::string name = itemDb->getItemInfo(mFloorItem->getItemId()).getName(); mBrowserBox->addRow("@@pickup|Pick Up " + name + "@@"); //browserBox->addRow("@@look|Look To@@"); diff --git a/src/gui/selectionlistener.h b/src/gui/selectionlistener.h new file mode 100644 index 00000000..e01b0c2f --- /dev/null +++ b/src/gui/selectionlistener.h @@ -0,0 +1,78 @@ +/* + * The Mana World + * Copyright 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: itemcontainer.h 2545 2006-08-17 19:11:28Z crush_tmw $ + */ + +#ifndef _TMW_SELECTIONLISTENER_H__ +#define _TMW_SELECTIONLISTENER_H__ + +#include + +/** + * An event that characterizes a change in the current selection. + * + * \ingroup GUI + */ +class SelectionEvent +{ + public: + /** + * Constructor. + */ + SelectionEvent(gcn::Widget *source): + mSource(source) + { + } + + /** + * The widget from which the event originated. + */ + gcn::Widget* getSource() const + { + return mSource; + } + + private: + gcn::Widget *mSource; +}; + +/** + * The listener that's notified when a selection value changes. + * + * \ingroup GUI + */ +class SelectionListener +{ + public: + /** + * Virtual destructor. + */ + virtual ~SelectionListener() {} + + /** + * Called whenever the value of the selection changes. + */ + virtual void selectionChanged(const SelectionEvent &event) = 0; +}; + +typedef std::list SelectionListeners; + +#endif diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 17185d71..44fa8e41 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -142,7 +142,7 @@ void SellDialog::addItem(Item *item, int price) ITEM_SHOP item_shop; - item_shop.name = item->getInfo()->getName() + " " + toString(price) + " GP"; + item_shop.name = item->getInfo().getName() + " " + toString(price) + " GP"; item_shop.price = price; item_shop.index = item->getInvIndex(); item_shop.id = item->getId(); @@ -259,9 +259,10 @@ void SellDialog::mouseClick(int x, int y, int button, int count) int selectedItem = mItemList->getSelected(); if (selectedItem > -1) { - mItemDescLabel->setCaption("Description: " + - itemDb->getItemInfo(mShopItems->at(selectedItem).id)->getDescription()); - mItemEffectLabel->setCaption("Effect: " + - itemDb->getItemInfo(mShopItems->at(selectedItem).id)->getEffect()); + const ItemInfo &info = + itemDb->getItemInfo(mShopItems->at(selectedItem).id); + + mItemDescLabel->setCaption("Description: " + info.getDescription()); + mItemEffectLabel->setCaption("Effect: " + info.getEffect()); } } diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 0086879e..babb5a87 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -250,10 +250,10 @@ void TradeWindow::mouseClick(int x, int y, int button, int count) // Show Name and Description std::string SomeText; - SomeText = "Name: " + item->getInfo()->getName(); + SomeText = "Name: " + item->getInfo().getName(); mItemNameLabel->setCaption(SomeText); mItemNameLabel->adjustSize(); - SomeText = "Description: " + item->getInfo()->getDescription(); + SomeText = "Description: " + item->getInfo().getDescription(); mItemDescriptionLabel->setCaption(SomeText); mItemDescriptionLabel->adjustSize(); } diff --git a/src/item.h b/src/item.h index c21f5ddf..1375886e 100644 --- a/src/item.h +++ b/src/item.h @@ -118,7 +118,7 @@ class Item /** * Returns information about this item type. */ - ItemInfo* + const ItemInfo& getInfo() const { return itemDb->getItemInfo(mId); } protected: diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp index a48ed51c..afe653eb 100644 --- a/src/net/inventoryhandler.cpp +++ b/src/net/inventoryhandler.cpp @@ -95,14 +95,9 @@ void InventoryHandler::handleMessage(MessageIn *msg) if (msg->readInt8()> 0) { chatWindow->chatLog("Unable to pick up item", BY_SERVER); } else { - ItemInfo *itemInfo = itemDb->getItemInfo(itemId); - if (itemInfo) { - chatWindow->chatLog("You picked up a " + - itemInfo->getName(), BY_SERVER); - } else { - chatWindow->chatLog("You picked up an unknown item", - BY_SERVER); - } + const ItemInfo &itemInfo = itemDb->getItemInfo(itemId); + chatWindow->chatLog("You picked up a " + + itemInfo.getName(), BY_SERVER); player_node->addInvItem(index, itemId, amount, equipType != 0); } break; diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index 5d39d832..b09d1cc0 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -23,22 +23,33 @@ #include "iteminfo.h" #include "resourcemanager.h" +#include "image.h" -Image* -ItemInfo::getImage() { - if (mImage == NULL && mImageName != "") { - mImage = ResourceManager::getInstance()->getImage(mImageName); + +ItemInfo::~ItemInfo() +{ + if (mImage != NULL) + { + mImage->decRef(); } - return mImage; } void -ItemInfo::setImage(const std::string &image) { +ItemInfo::setImage(const std::string &image) +{ mImageName = "graphics/items/" + image; -} -ItemInfo::~ItemInfo() { - if (mImage != NULL){ - mImage->decRef(); + if (mImageName != "") + { + if (mImage != NULL) + { + mImage->decRef(); + } + + mImage = ResourceManager::getInstance()->getImage(mImageName); + } + else + { + mImage = NULL; } } diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index afa2e857..9a04bb2e 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -26,7 +26,7 @@ #include -#include "image.h" +class Image; /** * Defines a class for storing item infos. @@ -40,8 +40,8 @@ class ItemInfo * Constructor. */ ItemInfo(): - mImage(NULL), mImageName(""), + mImage(NULL), mArt(0), mType(0), mWeight(0), @@ -53,19 +53,19 @@ class ItemInfo setArt(short art) { mArt = art; } short - getArt() { return mArt; } + getArt() const { return mArt; } void setName(const std::string &name) { mName = name; } - std::string - getName() { return mName; } + const std::string& + getName() const { return mName; } void setImage(const std::string &image); Image* - getImage(); + getImage() const { return mImage; } void setDescription(const std::string &description) @@ -73,32 +73,32 @@ class ItemInfo mDescription = description; } - std::string - getDescription() { return mDescription; } + const std::string& + getDescription() const { return mDescription; } void setEffect(const std::string &effect) { mEffect = effect; } - std::string - getEffect() { return mEffect; } + const std::string& + getEffect() const { return mEffect; } void setType(short type) { mType = type; } short - getType() { return mType; } + getType() const { return mType; } void setWeight(short weight) { mWeight = weight; } short - getWeight() { return mWeight; } + getWeight() const { return mWeight; } void setSlot(char slot) { mSlot = slot; } char - getSlot() { return mSlot; } + getSlot() const { return mSlot; } protected: /** @@ -106,8 +106,14 @@ class ItemInfo */ ~ItemInfo(); - Image* mImage; std::string mImageName; + + /* TODO (BL): I do not think the item info should keep a reference to + * the item icon. It would probably be better if this was kept in the + * Item class, so that the images can be lazily instantiated and also + * unloaded when no longer used. + */ + Image *mImage; short mArt; std::string mName; std::string mDescription; diff --git a/src/resources/itemmanager.cpp b/src/resources/itemmanager.cpp index a497b3c8..7d0b13f2 100644 --- a/src/resources/itemmanager.cpp +++ b/src/resources/itemmanager.cpp @@ -41,8 +41,7 @@ ItemManager::ItemManager() { - mUnknown = new ItemInfo(); - mUnknown->setName("Unknown item"); + mUnknown.setName("Unknown item"); ResourceManager *resman = ResourceManager::getInstance(); int size; @@ -163,14 +162,12 @@ ItemManager::~ItemManager() delete i->second; } mItemInfos.clear(); - - delete mUnknown; } -ItemInfo* +const ItemInfo& ItemManager::getItemInfo(int id) { ItemInfoIterator i = mItemInfos.find(id); - return (i != mItemInfos.end()) ? i->second : mUnknown; + return (i != mItemInfos.end()) ? *(i->second) : mUnknown; } diff --git a/src/resources/itemmanager.h b/src/resources/itemmanager.h index 06eee507..b1f2b95c 100644 --- a/src/resources/itemmanager.h +++ b/src/resources/itemmanager.h @@ -24,9 +24,9 @@ #ifndef _TMW_ITEM_MANAGER_H #define _TMW_ITEM_MANAGER_H -#include +#include "iteminfo.h" -class ItemInfo; +#include /** * Defines a class to load items database. @@ -44,14 +44,14 @@ class ItemManager */ ~ItemManager(); - ItemInfo *getItemInfo(int id); + const ItemInfo& getItemInfo(int id); protected: // Items database typedef std::map ItemInfos; typedef ItemInfos::iterator ItemInfoIterator; ItemInfos mItemInfos; - ItemInfo *mUnknown; + ItemInfo mUnknown; }; extern ItemManager *itemDb; -- cgit v1.2.3-70-g09d2