From 77efbb50066a030d1f44f8de8d06ace9f284e3a2 Mon Sep 17 00:00:00 2001
From: Bjørn Lindeijer <bjorn@lindeijer.nl>
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*>(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*>(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 <guichan/actionlistener.hpp>
 
 #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 <guichan/mouseinput.hpp>
 
+#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*>(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 <guichan/mouselistener.hpp>
 #include <guichan/widget.hpp>
 
+#include <list>
+
 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<SelectionListener*> 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 <guichan/widget.hpp>
+
+/**
+ * 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<SelectionListener*> 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 <string>
 
-#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 <map>
+#include "iteminfo.h"
 
-class ItemInfo;
+#include <map>
 
 /**
  * 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<int, ItemInfo*> ItemInfos;
         typedef ItemInfos::iterator ItemInfoIterator;
         ItemInfos mItemInfos;
-        ItemInfo *mUnknown;
+        ItemInfo mUnknown;
 };
 
 extern ItemManager *itemDb;
-- 
cgit v1.2.3-70-g09d2