summaryrefslogtreecommitdiff
path: root/src/gui/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/widgets')
-rw-r--r--src/gui/widgets/avatar.cpp1
-rw-r--r--src/gui/widgets/browserbox.cpp3
-rw-r--r--src/gui/widgets/button.cpp6
-rw-r--r--src/gui/widgets/chattab.cpp6
-rw-r--r--src/gui/widgets/checkbox.cpp6
-rw-r--r--src/gui/widgets/desktop.cpp1
-rw-r--r--src/gui/widgets/dropdown.cpp10
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp197
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.h77
-rw-r--r--src/gui/widgets/guildlistbox.cpp131
-rw-r--r--src/gui/widgets/guildlistbox.h65
-rw-r--r--src/gui/widgets/itemcontainer.cpp436
-rw-r--r--src/gui/widgets/itemcontainer.h192
-rw-r--r--src/gui/widgets/itemlinkhandler.cpp60
-rw-r--r--src/gui/widgets/itemlinkhandler.h40
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp254
-rw-r--r--src/gui/widgets/itemshortcutcontainer.h81
-rw-r--r--src/gui/widgets/linkhandler.h41
-rw-r--r--src/gui/widgets/listbox.cpp4
-rw-r--r--src/gui/widgets/playerbox.cpp109
-rw-r--r--src/gui/widgets/playerbox.h74
-rw-r--r--src/gui/widgets/popup.cpp8
-rw-r--r--src/gui/widgets/progressbar.cpp10
-rw-r--r--src/gui/widgets/scrollarea.cpp3
-rw-r--r--src/gui/widgets/setuptab.cpp27
-rw-r--r--src/gui/widgets/setuptab.h62
-rw-r--r--src/gui/widgets/shopitems.cpp103
-rw-r--r--src/gui/widgets/shopitems.h115
-rw-r--r--src/gui/widgets/shoplistbox.cpp157
-rw-r--r--src/gui/widgets/shoplistbox.h96
-rw-r--r--src/gui/widgets/shortcutcontainer.cpp64
-rw-r--r--src/gui/widgets/shortcutcontainer.h107
-rw-r--r--src/gui/widgets/slider.cpp3
-rw-r--r--src/gui/widgets/tab.cpp6
-rw-r--r--src/gui/widgets/tabbedarea.cpp1
-rw-r--r--src/gui/widgets/table.cpp549
-rw-r--r--src/gui/widgets/table.h185
-rw-r--r--src/gui/widgets/tablemodel.cpp161
-rw-r--r--src/gui/widgets/tablemodel.h146
-rw-r--r--src/gui/widgets/textfield.cpp8
-rw-r--r--src/gui/widgets/textpreview.cpp6
-rw-r--r--src/gui/widgets/window.cpp10
42 files changed, 3578 insertions, 43 deletions
diff --git a/src/gui/widgets/avatar.cpp b/src/gui/widgets/avatar.cpp
index 5d8aea01..7bec47a2 100644
--- a/src/gui/widgets/avatar.cpp
+++ b/src/gui/widgets/avatar.cpp
@@ -24,6 +24,7 @@
#include "localplayer.h"
#include "gui/gui.h"
+
#include "gui/widgets/icon.h"
#include "gui/widgets/label.h"
diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp
index d189947d..610bc153 100644
--- a/src/gui/widgets/browserbox.cpp
+++ b/src/gui/widgets/browserbox.cpp
@@ -21,9 +21,10 @@
#include "gui/widgets/browserbox.h"
-#include "gui/linkhandler.h"
#include "gui/palette.h"
+#include "gui/widgets/linkhandler.h"
+
#include <guichan/graphics.hpp>
#include <guichan/font.hpp>
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 9f44cdfc..3fd5fdf6 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -21,14 +21,14 @@
#include "gui/widgets/button.h"
-#include "gui/palette.h"
-
#include "configuration.h"
#include "graphics.h"
+#include "gui/palette.h"
+#include "gui/skin.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
#include "utils/dtor.h"
diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp
index 443fab3d..6a915e5b 100644
--- a/src/gui/widgets/chattab.cpp
+++ b/src/gui/widgets/chattab.cpp
@@ -25,11 +25,11 @@
#include "configuration.h"
#include "localplayer.h"
+#include "gui/recorder.h"
+
#include "gui/widgets/browserbox.h"
#include "gui/widgets/scrollarea.h"
-
-#include "gui/itemlinkhandler.h"
-#include "gui/recorder.h"
+#include "gui/widgets/itemlinkhandler.h"
#include "net/chathandler.h"
#include "net/net.h"
diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp
index 9b4ab2f4..bff8d4d8 100644
--- a/src/gui/widgets/checkbox.cpp
+++ b/src/gui/widgets/checkbox.cpp
@@ -21,14 +21,14 @@
#include "gui/widgets/checkbox.h"
-#include "gui/palette.h"
-
#include "configuration.h"
#include "graphics.h"
+#include "gui/palette.h"
+#include "gui/skin.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
int CheckBox::instances = 0;
float CheckBox::mAlpha = 1.0;
diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp
index 13ac866a..fb807f38 100644
--- a/src/gui/widgets/desktop.cpp
+++ b/src/gui/widgets/desktop.cpp
@@ -22,6 +22,7 @@
#include "gui/widgets/desktop.h"
#include "gui/palette.h"
+
#include "gui/widgets/label.h"
#include "resources/image.h"
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
index d5b324a6..9088bad9 100644
--- a/src/gui/widgets/dropdown.cpp
+++ b/src/gui/widgets/dropdown.cpp
@@ -21,18 +21,18 @@
#include "gui/widgets/dropdown.h"
-#include "gui/widgets/listbox.h"
-#include "gui/widgets/scrollarea.h"
+#include "configuration.h"
+#include "graphics.h"
#include "gui/palette.h"
#include "gui/sdlinput.h"
+#include "gui/skin.h"
-#include "configuration.h"
-#include "graphics.h"
+#include "gui/widgets/listbox.h"
+#include "gui/widgets/scrollarea.h"
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
#include "utils/dtor.h"
diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp
new file mode 100644
index 00000000..5327caab
--- /dev/null
+++ b/src/gui/widgets/emoteshortcutcontainer.cpp
@@ -0,0 +1,197 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/emoteshortcutcontainer.h"
+
+#include "animatedsprite.h"
+#include "configuration.h"
+#include "emoteshortcut.h"
+#include "graphics.h"
+#include "inventory.h"
+#include "item.h"
+#include "itemshortcut.h"
+#include "keyboardconfig.h"
+#include "localplayer.h"
+#include "log.h"
+
+#include "gui/palette.h"
+
+#include "resources/emotedb.h"
+#include "resources/image.h"
+#include "resources/resourcemanager.h"
+
+#include "utils/dtor.h"
+
+static const int MAX_ITEMS = 12;
+
+EmoteShortcutContainer::EmoteShortcutContainer():
+ ShortcutContainer(),
+ mEmoteClicked(false),
+ mEmoteMoved(0)
+{
+ addMouseListener(this);
+ addWidgetListener(this);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
+
+ mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); i++)
+ {
+ mEmoteImg.push_back(EmoteDB::getAnimation(i));
+ }
+
+ mMaxItems = EmoteDB::getLast() < MAX_ITEMS ? EmoteDB::getLast() : MAX_ITEMS;
+
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
+}
+
+EmoteShortcutContainer::~EmoteShortcutContainer()
+{
+ mBackgroundImg->decRef();
+}
+
+void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
+{
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ mBackgroundImg->setAlpha(mAlpha);
+ }
+
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ graphics->setFont(getFont());
+
+ for (int i = 0; i < mMaxItems; i++)
+ {
+ const int emoteX = (i % mGridWidth) * mBoxWidth;
+ const int emoteY = (i / mGridWidth) * mBoxHeight;
+
+ g->drawImage(mBackgroundImg, emoteX, emoteY);
+
+ // Draw emote keyboard shortcut.
+ const char *key = SDL_GetKeyName(
+ (SDLKey) keyboard.getKeyValue(keyboard.KEY_EMOTE_1 + i));
+ graphics->setColor(guiPalette->getColor(Palette::TEXT));
+ g->drawText(key, emoteX + 2, emoteY + 2, gcn::Graphics::LEFT);
+
+ if (emoteShortcut->getEmote(i))
+ {
+ mEmoteImg[emoteShortcut->getEmote(i) - 1]->draw(g, emoteX + 2,
+ emoteY + 10);
+ }
+
+ }
+
+ if (mEmoteMoved)
+ {
+ // Draw the emote image being dragged by the cursor.
+ const AnimatedSprite* sprite = mEmoteImg[mEmoteMoved - 1];
+ if (sprite)
+ {
+ const int tPosX = mCursorPosX - (sprite->getWidth() / 2);
+ const int tPosY = mCursorPosY - (sprite->getHeight() / 2);
+
+ sprite->draw(g, tPosX, tPosY);
+ }
+ }
+}
+
+void EmoteShortcutContainer::mouseDragged(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (!mEmoteMoved && mEmoteClicked)
+ {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ const int emoteId = emoteShortcut->getEmote(index);
+
+ if (index == -1)
+ return;
+
+ if (emoteId)
+ {
+ mEmoteMoved = emoteId;
+ emoteShortcut->removeEmote(index);
+ }
+ }
+ if (mEmoteMoved)
+ {
+ mCursorPosX = event.getX();
+ mCursorPosY = event.getY();
+ }
+ }
+}
+
+void EmoteShortcutContainer::mousePressed(gcn::MouseEvent &event)
+{
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+
+ if (index == -1)
+ return;
+
+ // Stores the selected emote if there is one.
+ if (emoteShortcut->isEmoteSelected())
+ {
+ emoteShortcut->setEmote(index);
+ emoteShortcut->setEmoteSelected(0);
+ }
+ else if (emoteShortcut->getEmote(index))
+ {
+ mEmoteClicked = true;
+ }
+}
+
+void EmoteShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+
+ if (emoteShortcut->isEmoteSelected())
+ emoteShortcut->setEmoteSelected(0);
+
+ if (index == -1)
+ {
+ mEmoteMoved = 0;
+ return;
+ }
+
+ if (mEmoteMoved)
+ {
+ emoteShortcut->setEmotes(index, mEmoteMoved);
+ mEmoteMoved = 0;
+ }
+ else if (emoteShortcut->getEmote(index) && mEmoteClicked)
+ {
+ emoteShortcut->useEmote(index + 1);
+ }
+
+ if (mEmoteClicked)
+ mEmoteClicked = false;
+ }
+}
+
diff --git a/src/gui/widgets/emoteshortcutcontainer.h b/src/gui/widgets/emoteshortcutcontainer.h
new file mode 100644
index 00000000..8860927e
--- /dev/null
+++ b/src/gui/widgets/emoteshortcutcontainer.h
@@ -0,0 +1,77 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTESHORTCUTCONTAINER_H
+#define EMOTESHORTCUTCONTAINER_H
+
+#include <vector>
+
+#include "gui/widgets/shortcutcontainer.h"
+
+class AnimatedSprite;
+class Image;
+
+/**
+ * An emote shortcut container. Used to quickly use emoticons.
+ *
+ * \ingroup GUI
+ */
+class EmoteShortcutContainer : public ShortcutContainer
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ EmoteShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~EmoteShortcutContainer();
+
+ /**
+ * Draws the items.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Handles mouse when dragged.
+ */
+ void mouseDragged(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse when pressed.
+ */
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse release.
+ */
+ void mouseReleased(gcn::MouseEvent &event);
+
+ private:
+ std::vector<const AnimatedSprite*> mEmoteImg;
+
+ bool mEmoteClicked;
+ int mEmoteMoved;
+};
+
+#endif
diff --git a/src/gui/widgets/guildlistbox.cpp b/src/gui/widgets/guildlistbox.cpp
new file mode 100644
index 00000000..14a8f77f
--- /dev/null
+++ b/src/gui/widgets/guildlistbox.cpp
@@ -0,0 +1,131 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/guildlistbox.h"
+
+#include "graphics.h"
+
+#include "resources/image.h"
+#include "resources/resourcemanager.h"
+
+#include <guichan/font.hpp>
+
+GuildListBox::GuildListBox():
+ ListBox(NULL)
+{
+ onlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-green.png");
+ offlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-gray.png");
+}
+
+void GuildListBox::draw(gcn::Graphics *gcnGraphics)
+{
+ if (!mListModel)
+ return;
+
+ Graphics *graphics = static_cast<Graphics*>(gcnGraphics);
+
+ graphics->setColor(gcn::Color(110, 160, 255));
+ graphics->setFont(getFont());
+
+ int fontHeight = getFont()->getHeight();
+
+ // Draw rectangle below the selected list element
+ if (mSelected >= 0)
+ {
+ graphics->fillRectangle(gcn::Rectangle(0, fontHeight * mSelected,
+ getWidth(), fontHeight));
+ }
+
+ // Draw the list elements
+ for (int i = 0, y = 0;
+ i < mListModel->getNumberOfElements();
+ ++i, y += fontHeight)
+ {
+ // Draw online status
+ bool online = false;
+ UserMap::iterator itr = mUsers.find(mListModel->getElementAt(i));
+ if (itr != mUsers.end())
+ {
+ online = itr->second;
+ }
+ Image *icon = online ? onlineIcon : offlineIcon;
+ if (icon)
+ graphics->drawImage(icon, 1, y);
+ // Draw Name
+ graphics->setColor(gcn::Color(0, 0, 0));
+ graphics->drawText(mListModel->getElementAt(i), 33, y);
+ }
+}
+/*
+void GuildListBox::setSelected(int selected)
+{
+ if (!mListModel)
+ {
+ mSelected = -1;
+ }
+ else
+ {
+ // Update mSelected with bounds checking
+ mSelected = std::min(mListModel->getNumberOfElements() - 1,
+ std::max(-1, selected));
+
+ gcn::Widget *parent;
+ parent = (gcn::Widget*)getParent();
+ if (parent)
+ {
+ gcn::Rectangle scroll;
+ scroll.y = (mSelected < 0) ? 0 : getFont()->getHeight() * mSelected;
+ scroll.height = getFont()->getHeight();
+ parent->showWidgetPart(this, scroll);
+ }
+ }
+
+ distributeValueChangedEvent();
+}
+*/
+void GuildListBox::mousePressed(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ int y = event.getY();
+ setSelected(y / getFont()->getHeight());
+ distributeActionEvent();
+ }
+ // TODO: Add guild functions, ie private messaging
+ if (event.getButton() == gcn::MouseEvent::RIGHT)
+ {
+ // Show context menu
+ }
+}
+
+void GuildListBox::setOnlineStatus(const std::string &user, bool online)
+{
+ UserMap::iterator itr = mUsers.find(user);
+ if (itr == mUsers.end())
+ {
+ mUsers.insert(std::pair<std::string, bool>(user, online));
+ }
+ else
+ {
+ itr->second = online;
+ }
+ adjustSize();
+}
diff --git a/src/gui/widgets/guildlistbox.h b/src/gui/widgets/guildlistbox.h
new file mode 100644
index 00000000..d266fe46
--- /dev/null
+++ b/src/gui/widgets/guildlistbox.h
@@ -0,0 +1,65 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GUI_GUILDLISTBOX_H
+#define GUI_GUILDLISTBOX_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "gui/widgets/listbox.h"
+
+class Image;
+
+class GuildListBox : public ListBox
+{
+public:
+ /**
+ * Constructor
+ */
+ GuildListBox();
+
+ /**
+ * Draws the list box.
+ */
+ void draw(gcn::Graphics *gcnGraphics);
+
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Sets the index of the selected element.
+ */
+// void setSelected(int selected);
+
+ /**
+ * Set whether a member is online or offline
+ */
+ void setOnlineStatus(const std::string &user, bool online);
+
+private:
+ Image *onlineIcon;
+ Image *offlineIcon;
+ typedef std::map<std::string, bool> UserMap;
+ UserMap mUsers;
+};
+
+#endif
diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp
new file mode 100644
index 00000000..67561e89
--- /dev/null
+++ b/src/gui/widgets/itemcontainer.cpp
@@ -0,0 +1,436 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/itemcontainer.h"
+
+#include "graphics.h"
+#include "inventory.h"
+#include "item.h"
+#include "itemshortcut.h"
+#include "log.h"
+
+#include "gui/chat.h"
+#include "gui/itempopup.h"
+#include "gui/outfitwindow.h"
+#include "gui/palette.h"
+#include "gui/sdlinput.h"
+#include "gui/viewport.h"
+
+#include "net/net.h"
+#include "net/inventoryhandler.h"
+
+#include "resources/image.h"
+#include "resources/iteminfo.h"
+#include "resources/resourcemanager.h"
+
+#include "utils/stringutils.h"
+
+#include <guichan/mouseinput.hpp>
+#include <guichan/selectionlistener.hpp>
+
+// TODO: Add support for adding items to the item shortcut window (global
+// itemShortcut).
+
+static const int BOX_WIDTH = 35;
+static const int BOX_HEIGHT = 43;
+
+ItemContainer::ItemContainer(Inventory *inventory, bool forceQuantity):
+ mInventory(inventory),
+ mGridColumns(1),
+ mGridRows(1),
+ mSelectedIndex(-1),
+ mHighlightedIndex(-1),
+ mLastUsedSlot(-1),
+ mSelectionStatus(SEL_NONE),
+ mForceQuantity(forceQuantity),
+ mSwapItems(false),
+ mDescItems(false)
+{
+ mItemPopup = new ItemPopup;
+ setFocusable(true);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mSelImg = resman->getImage("graphics/gui/selection.png");
+ if (!mSelImg)
+ logger->error("Unable to load selection.png");
+
+ addKeyListener(this);
+ addMouseListener(this);
+ addWidgetListener(this);
+}
+
+ItemContainer::~ItemContainer()
+{
+ mSelImg->decRef();
+ delete mItemPopup;
+}
+
+void ItemContainer::logic()
+{
+ gcn::Widget::logic();
+
+ const int lastUsedSlot = mInventory->getLastUsedSlot();
+
+ if (lastUsedSlot != mLastUsedSlot)
+ {
+ mLastUsedSlot = lastUsedSlot;
+ adjustHeight();
+ }
+}
+
+void ItemContainer::draw(gcn::Graphics *graphics)
+{
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ g->setFont(getFont());
+
+ for (int i = 0; i < mGridColumns; i++)
+ {
+ for (int j = 0; j < mGridRows; j++)
+ {
+ int itemX = i * BOX_WIDTH;
+ int itemY = j * BOX_HEIGHT;
+ int itemIndex = (j * mGridColumns) + i;
+ Item *item = mInventory->getItem(itemIndex);
+
+ if (!item || item->getId() == 0)
+ continue;
+
+ Image *image = item->getImage();
+ if (image)
+ {
+ if (itemIndex == mSelectedIndex)
+ {
+ if (mSelectionStatus == SEL_DRAGGING)
+ {
+ // Reposition the coords to that of the cursor.
+ itemX = mDragPosX - (BOX_WIDTH / 2);
+ itemY = mDragPosY - (BOX_HEIGHT / 2);
+ }
+ else
+ {
+ // Draw selection border image.
+ g->drawImage(mSelImg, itemX, itemY);
+ }
+ }
+ image->setAlpha(1.0f); // ensure the image if fully drawn...
+ g->drawImage(image, itemX, itemY);
+ }
+ // Draw item caption
+ std::string caption;
+ if (item->getQuantity() > 1 || mForceQuantity)
+ caption = toString(item->getQuantity());
+ else if (item->isEquipped())
+ caption = "Eq.";
+
+ if (item->isEquipped())
+ g->setColor(guiPalette->getColor(Palette::ITEM_EQUIPPED));
+ else
+ g->setColor(gcn::Color(0, 0, 0));
+
+ g->drawText(caption, itemX + BOX_WIDTH / 2,
+ itemY + BOX_HEIGHT - 14, gcn::Graphics::CENTER);
+ }
+ }
+
+ // Draw an orange box around the selected item
+ if (isFocused() && mHighlightedIndex != -1)
+ {
+ const int itemX = (mHighlightedIndex % mGridColumns) * BOX_WIDTH;
+ const int itemY = (mHighlightedIndex / mGridColumns) * BOX_HEIGHT;
+ g->setColor(gcn::Color(255, 128, 0));
+ g->drawRectangle(gcn::Rectangle(itemX, itemY, BOX_WIDTH, BOX_HEIGHT));
+ }
+}
+
+void ItemContainer::selectNone()
+{
+ setSelectedIndex(-1);
+ mSelectionStatus = SEL_NONE;
+ outfitWindow->setItemSelected(-1);
+}
+
+void ItemContainer::setSelectedIndex(int newIndex)
+{
+ if (mSelectedIndex != newIndex)
+ {
+ mSelectedIndex = newIndex;
+ distributeValueChangedEvent();
+ }
+}
+
+Item *ItemContainer::getSelectedItem() const
+{
+ return mInventory->getItem(mSelectedIndex);
+}
+
+void ItemContainer::distributeValueChangedEvent()
+{
+ SelectionListenerIterator i, i_end;
+
+ for (i = mSelectionListeners.begin(), i_end = mSelectionListeners.end();
+ i != i_end; ++i)
+ {
+ gcn::SelectionEvent event(this);
+ (*i)->valueChanged(event);
+ }
+}
+
+void ItemContainer::keyPressed(gcn::KeyEvent &event)
+{
+ /*switch (event.getKey().getValue())
+ {
+ case Key::LEFT:
+ moveHighlight(Left);
+ break;
+ case Key::RIGHT:
+ moveHighlight(Right);
+ break;
+ case Key::UP:
+ moveHighlight(Up);
+ break;
+ case Key::DOWN:
+ moveHighlight(Down);
+ break;
+ case Key::SPACE:
+ keyAction();
+ break;
+ case Key::LEFT_ALT:
+ case Key::RIGHT_ALT:
+ mSwapItems = true;
+ break;
+ case Key::RIGHT_CONTROL:
+ mDescItems = true;
+ break;
+ }*/
+}
+
+void ItemContainer::keyReleased(gcn::KeyEvent &event)
+{
+ /*switch (event.getKey().getValue())
+ {
+ case Key::LEFT_ALT:
+ case Key::RIGHT_ALT:
+ mSwapItems = false;
+ break;
+ case Key::RIGHT_CONTROL:
+ mDescItems = false;
+ break;
+ }*/
+}
+
+void ItemContainer::mousePressed(gcn::MouseEvent &event)
+{
+ const int button = event.getButton();
+ if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
+ {
+ const int index = getSlotIndex(event.getX(), event.getY());
+ if (index == Inventory::NO_SLOT_INDEX)
+ return;
+
+ Item *item = mInventory->getItem(index);
+
+ // put item name into chat window
+ if (mDescItems)
+ {
+ chatWindow->addItemText(item->getInfo().getName());
+ }
+
+ if (mSelectedIndex == index)
+ {
+ mSelectionStatus = SEL_DESELECTING;
+ }
+ else if (item && item->getId())
+ {
+ setSelectedIndex(index);
+ mSelectionStatus = SEL_SELECTING;
+
+ itemShortcut->setItemSelected(item->getId());
+ if (item->isEquipment())
+ outfitWindow->setItemSelected(item->getId());
+ }
+ else
+ {
+ selectNone();
+ }
+ }
+}
+
+void ItemContainer::mouseDragged(gcn::MouseEvent &event)
+{
+ if (mSelectionStatus != SEL_NONE)
+ {
+ mSelectionStatus = SEL_DRAGGING;
+ mDragPosX = event.getX();
+ mDragPosY = event.getY();
+ }
+}
+
+void ItemContainer::mouseReleased(gcn::MouseEvent &event)
+{
+ switch (mSelectionStatus)
+ {
+ case SEL_SELECTING:
+ mSelectionStatus = SEL_SELECTED;
+ return;
+ case SEL_DESELECTING:
+ selectNone();
+ return;
+ case SEL_DRAGGING:
+ mSelectionStatus = SEL_SELECTED;
+ break;
+ default:
+ return;
+ };
+
+ int index = getSlotIndex(event.getX(), event.getY());
+ if (index == Inventory::NO_SLOT_INDEX)
+ return;
+ if (index == mSelectedIndex || mSelectedIndex == -1)
+ return;
+ Net::getInventoryHandler()->moveItem(mSelectedIndex, index);
+ selectNone();
+}
+
+
+// Show ItemTooltip
+void ItemContainer::mouseMoved(gcn::MouseEvent &event)
+{
+ Item *item = mInventory->getItem(getSlotIndex(event.getX(), event.getY()));
+
+ if (item)
+ {
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->view(viewport->getMouseX(), viewport->getMouseY());
+ }
+ else
+ {
+ mItemPopup->setVisible(false);
+ }
+}
+
+// Hide ItemTooltip
+void ItemContainer::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
+}
+
+void ItemContainer::widgetResized(const gcn::Event &event)
+{
+ mGridColumns = std::max(1, getWidth() / BOX_WIDTH);
+ adjustHeight();
+}
+
+void ItemContainer::adjustHeight()
+{
+ mGridRows = (mLastUsedSlot + 1) / mGridColumns;
+ if (mGridRows == 0 || (mLastUsedSlot + 1) % mGridColumns > 0)
+ ++mGridRows;
+
+ setHeight(mGridRows * BOX_HEIGHT);
+}
+
+int ItemContainer::getSlotIndex(int x, int y) const
+{
+ if (x < getWidth() && y < getHeight())
+ {
+ return (y / BOX_HEIGHT) * mGridColumns + (x / BOX_WIDTH);
+ }
+ return Inventory::NO_SLOT_INDEX;
+}
+
+void ItemContainer::keyAction()
+{
+ // If there is no highlight then return.
+ if (mHighlightedIndex == -1)
+ return;
+
+ // If the highlight is on the selected item, then deselect it.
+ if (mHighlightedIndex == mSelectedIndex)
+ {
+ selectNone();
+ }
+ // Check and swap items if necessary.
+ else if (mSwapItems &&
+ mSelectedIndex != -1 &&
+ mHighlightedIndex != -1)
+ {
+ Net::getInventoryHandler()->moveItem(
+ mSelectedIndex, mHighlightedIndex);
+ setSelectedIndex(mHighlightedIndex);
+ }
+ // If the highlight is on an item then select it.
+ else if (mHighlightedIndex != -1)
+ {
+ setSelectedIndex(mHighlightedIndex);
+ mSelectionStatus = SEL_SELECTED;
+ }
+ // If the highlight is on a blank space then move it.
+ else if (mSelectedIndex != -1)
+ {
+ Net::getInventoryHandler()->moveItem(
+ mSelectedIndex, mHighlightedIndex);
+ selectNone();
+ }
+}
+
+void ItemContainer::moveHighlight(Direction direction)
+{
+ if (mHighlightedIndex == -1)
+ {
+ if (mSelectedIndex != -1)
+ mHighlightedIndex = mSelectedIndex;
+ else
+ mHighlightedIndex = 0;
+ return;
+ }
+
+ switch (direction)
+ {
+ case Left:
+ if (mHighlightedIndex % mGridColumns == 0)
+ mHighlightedIndex += mGridColumns;
+ mHighlightedIndex--;
+ break;
+ case Right:
+ if ((mHighlightedIndex % mGridColumns) ==
+ (mGridColumns - 1))
+ {
+ mHighlightedIndex -= mGridColumns;
+ }
+ mHighlightedIndex++;
+ break;
+ case Up:
+ if (mHighlightedIndex / mGridColumns == 0)
+ mHighlightedIndex += (mGridColumns * mGridRows);
+ mHighlightedIndex -= mGridColumns;
+ break;
+ case Down:
+ if ((mHighlightedIndex / mGridColumns) ==
+ (mGridRows - 1))
+ {
+ mHighlightedIndex -= (mGridColumns * mGridRows);
+ }
+ mHighlightedIndex += mGridColumns;
+ break;
+ }
+}
diff --git a/src/gui/widgets/itemcontainer.h b/src/gui/widgets/itemcontainer.h
new file mode 100644
index 00000000..2cfd06b2
--- /dev/null
+++ b/src/gui/widgets/itemcontainer.h
@@ -0,0 +1,192 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ITEMCONTAINER_H
+#define ITEMCONTAINER_H
+
+#include <guichan/keylistener.hpp>
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+#include <guichan/widgetlistener.hpp>
+
+#include <list>
+
+class Image;
+class Inventory;
+class Item;
+class ItemPopup;
+
+namespace gcn {
+ class SelectionListener;
+}
+
+/**
+ * An item container. Used to show items in inventory and trade dialog.
+ *
+ * \ingroup GUI
+ */
+class ItemContainer : public gcn::Widget,
+ public gcn::KeyListener,
+ public gcn::MouseListener,
+ public gcn::WidgetListener
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ *
+ * @param inventory
+ * @param gridColumns Amount of columns in grid.
+ * @param gridRows Amount of rows in grid.
+ * @param offset Index offset
+ */
+ ItemContainer(Inventory *inventory, bool forceQuantity = false);
+
+ /**
+ * Destructor.
+ */
+ virtual ~ItemContainer();
+
+ /**
+ * Necessary for checking how full the inventory is.
+ */
+ void logic();
+
+ /**
+ * Draws the items.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ // KeyListener
+ void keyPressed(gcn::KeyEvent &event);
+ void keyReleased(gcn::KeyEvent &event);
+
+ // MouseListener
+ void mousePressed(gcn::MouseEvent &event);
+ void mouseDragged(gcn::MouseEvent &event);
+ void mouseReleased(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
+ void mouseExited(gcn::MouseEvent &event);
+
+ // WidgetListener
+ void widgetResized(const gcn::Event &event);
+
+ /**
+ * Returns the selected item.
+ */
+ Item *getSelectedItem() const;
+
+ /**
+ * 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(gcn::SelectionListener *listener)
+ {
+ mSelectionListeners.push_back(listener);
+ }
+
+ /**
+ * Removes a listener from the list that's notified each time a change
+ * to the selection occurs.
+ */
+ void removeSelectionListener(gcn::SelectionListener *listener)
+ {
+ mSelectionListeners.remove(listener);
+ }
+
+ private:
+ enum Direction
+ {
+ Left,
+ Right,
+ Up,
+ Down
+ };
+
+ enum SelectionState
+ {
+ SEL_NONE = 0,
+ SEL_SELECTED,
+ SEL_SELECTING,
+ SEL_DESELECTING,
+ SEL_DRAGGING
+ };
+
+ /**
+ * Execute all the functionality associated with the action key.
+ */
+ void keyAction();
+
+ /**
+ * Moves the highlight in the direction specified.
+ *
+ * @param direction The move direction of the highlighter.
+ */
+ void moveHighlight(Direction direction);
+
+ /**
+ * Sets the currently selected item.
+ */
+ void setSelectedIndex(int index);
+
+ /**
+ * Determine and set the height of the container.
+ */
+ void adjustHeight();
+
+ /**
+ * Sends out selection events to the list of selection listeners.
+ */
+ void distributeValueChangedEvent();
+
+ /**
+ * Gets the slot index based on the cursor position.
+ *
+ * @param x The X coordinate position.
+ * @param y The Y coordinate position.
+ * @return The slot index on success, -1 on failure.
+ */
+ int getSlotIndex(int x, int y) const;
+
+ Inventory *mInventory;
+ int mGridColumns, mGridRows;
+ Image *mSelImg;
+ int mSelectedIndex, mHighlightedIndex;
+ int mLastUsedSlot;
+ SelectionState mSelectionStatus;
+ bool mForceQuantity;
+ bool mSwapItems;
+ bool mDescItems;
+ int mDragPosX, mDragPosY;
+
+ ItemPopup *mItemPopup;
+
+ typedef std::list<gcn::SelectionListener*> SelectionListenerList;
+ typedef SelectionListenerList::iterator SelectionListenerIterator;
+
+ SelectionListenerList mSelectionListeners;
+};
+
+#endif
diff --git a/src/gui/widgets/itemlinkhandler.cpp b/src/gui/widgets/itemlinkhandler.cpp
new file mode 100644
index 00000000..1a7011ab
--- /dev/null
+++ b/src/gui/widgets/itemlinkhandler.cpp
@@ -0,0 +1,60 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sstream>
+#include <string>
+
+#include "gui/widgets/itemlinkhandler.h"
+#include "gui/itempopup.h"
+#include "gui/viewport.h"
+
+#include "resources/iteminfo.h"
+#include "resources/itemdb.h"
+
+ItemLinkHandler::ItemLinkHandler()
+{
+ mItemPopup = new ItemPopup;
+}
+
+ItemLinkHandler::~ItemLinkHandler()
+{
+ delete mItemPopup;
+}
+
+void ItemLinkHandler::handleLink(const std::string &link)
+{
+ int id = 0;
+ std::stringstream stream;
+ stream << link;
+ stream >> id;
+
+ if (id > 0)
+ {
+ const ItemInfo &iteminfo = ItemDB::get(id);
+
+ mItemPopup->setItem(iteminfo);
+
+ if (mItemPopup->isVisible())
+ mItemPopup->setVisible(false);
+ else
+ mItemPopup->view(viewport->getMouseX(), viewport->getMouseY());
+ }
+}
diff --git a/src/gui/widgets/itemlinkhandler.h b/src/gui/widgets/itemlinkhandler.h
new file mode 100644
index 00000000..af20b9ce
--- /dev/null
+++ b/src/gui/widgets/itemlinkhandler.h
@@ -0,0 +1,40 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ITEM_LINK_HANDLER_H
+#define ITEM_LINK_HANDLER_H
+
+#include "gui/widgets/linkhandler.h"
+
+class ItemPopup;
+
+class ItemLinkHandler : public LinkHandler
+{
+ public:
+ ItemLinkHandler();
+ ~ItemLinkHandler();
+ void handleLink(const std::string &link);
+
+ private:
+ ItemPopup *mItemPopup;
+};
+
+#endif
diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp
new file mode 100644
index 00000000..489a85be
--- /dev/null
+++ b/src/gui/widgets/itemshortcutcontainer.cpp
@@ -0,0 +1,254 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/itemshortcutcontainer.h"
+
+#include "configuration.h"
+#include "graphics.h"
+#include "inventory.h"
+#include "item.h"
+#include "itemshortcut.h"
+#include "keyboardconfig.h"
+#include "localplayer.h"
+
+#include "gui/inventorywindow.h"
+#include "gui/itempopup.h"
+#include "gui/palette.h"
+#include "gui/viewport.h"
+
+#include "resources/image.h"
+#include "resources/iteminfo.h"
+#include "resources/resourcemanager.h"
+
+#include "utils/stringutils.h"
+
+ItemShortcutContainer::ItemShortcutContainer():
+ ShortcutContainer(),
+ mItemClicked(false),
+ mItemMoved(NULL)
+{
+ addMouseListener(this);
+ addWidgetListener(this);
+
+ mItemPopup = new ItemPopup;
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
+ mMaxItems = itemShortcut->getItemCount();
+
+ mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
+}
+
+ItemShortcutContainer::~ItemShortcutContainer()
+{
+ mBackgroundImg->decRef();
+ delete mItemPopup;
+}
+
+void ItemShortcutContainer::draw(gcn::Graphics *graphics)
+{
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ mAlpha = config.getValue("guialpha", 0.8);
+ mBackgroundImg->setAlpha(mAlpha);
+ }
+
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ graphics->setFont(getFont());
+
+ for (int i = 0; i < mMaxItems; i++)
+ {
+ const int itemX = (i % mGridWidth) * mBoxWidth;
+ const int itemY = (i / mGridWidth) * mBoxHeight;
+
+ g->drawImage(mBackgroundImg, itemX, itemY);
+
+ // Draw item keyboard shortcut.
+ const char *key = SDL_GetKeyName(
+ (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i));
+ graphics->setColor(guiPalette->getColor(Palette::TEXT));
+ g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT);
+
+ if (itemShortcut->getItem(i) < 0)
+ continue;
+
+ Item *item =
+ player_node->getInventory()->findItem(itemShortcut->getItem(i));
+
+ if (item)
+ {
+ // Draw item icon.
+ Image* image = item->getImage();
+
+ if (image)
+ {
+ std::string caption;
+ if (item->getQuantity() > 1)
+ caption = toString(item->getQuantity());
+ else if (item->isEquipped())
+ caption = "Eq.";
+
+ g->drawImage(image, itemX, itemY);
+ if (item->isEquipped())
+ g->setColor(guiPalette->getColor(Palette::ITEM_EQUIPPED));
+ g->drawText(caption, itemX + mBoxWidth / 2,
+ itemY + mBoxHeight - 14, gcn::Graphics::CENTER);
+ }
+ }
+ }
+
+ if (mItemMoved)
+ {
+ // Draw the item image being dragged by the cursor.
+ Image* image = mItemMoved->getImage();
+ if (image)
+ {
+ const int tPosX = mCursorPosX - (image->getWidth() / 2);
+ const int tPosY = mCursorPosY - (image->getHeight() / 2);
+
+ g->drawImage(image, tPosX, tPosY);
+ g->drawText(toString(mItemMoved->getQuantity()),
+ tPosX + mBoxWidth / 2, tPosY + mBoxHeight - 14,
+ gcn::Graphics::CENTER);
+ }
+ }
+}
+
+void ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (!mItemMoved && mItemClicked)
+ {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1 || itemId < 0)
+ return;
+
+ Item *item = player_node->getInventory()->findItem(itemId);
+
+ if (item)
+ {
+ mItemMoved = item;
+ itemShortcut->removeItem(index);
+ }
+ }
+ if (mItemMoved)
+ {
+ mCursorPosX = event.getX();
+ mCursorPosY = event.getY();
+ }
+ }
+}
+
+void ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
+{
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+
+ if (index == -1)
+ return;
+
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ // Stores the selected item if theirs one.
+ if (itemShortcut->isItemSelected() && inventoryWindow->isVisible())
+ {
+ itemShortcut->setItem(index);
+ itemShortcut->setItemSelected(-1);
+ }
+ else if (itemShortcut->getItem(index))
+ mItemClicked = true;
+ }
+ else if (event.getButton() == gcn::MouseEvent::RIGHT)
+ {
+ Item *item = player_node->getInventory()->
+ findItem(itemShortcut->getItem(index));
+
+ if (!item)
+ return;
+
+ // Convert relative to the window coordinates to absolute screen
+ // coordinates.
+ viewport->showPopup(viewport->getMouseX(), viewport->getMouseY(), item);
+ }
+}
+
+void ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (itemShortcut->isItemSelected())
+ itemShortcut->setItemSelected(-1);
+
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1)
+ {
+ mItemMoved = NULL;
+ return;
+ }
+ if (mItemMoved)
+ {
+ itemShortcut->setItems(index, mItemMoved->getId());
+ mItemMoved = NULL;
+ }
+ else if (itemShortcut->getItem(index) && mItemClicked)
+ {
+ itemShortcut->useItem(index);
+ }
+
+ if (mItemClicked)
+ mItemClicked = false;
+ }
+}
+
+// Show ItemTooltip
+void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event)
+{
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1 || itemId < 0)
+ return;
+
+ Item *item = player_node->getInventory()->findItem(itemId);
+
+ if (item)
+ {
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->view(viewport->getMouseX(), viewport->getMouseY());
+ }
+ else
+ {
+ mItemPopup->setVisible(false);
+ }
+}
+
+// Hide ItemTooltip
+void ItemShortcutContainer::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
+}
diff --git a/src/gui/widgets/itemshortcutcontainer.h b/src/gui/widgets/itemshortcutcontainer.h
new file mode 100644
index 00000000..03d57b8d
--- /dev/null
+++ b/src/gui/widgets/itemshortcutcontainer.h
@@ -0,0 +1,81 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef ITEMSHORTCUTCONTAINER_H
+#define ITEMSHORTCUTCONTAINER_H
+
+#include <guichan/mouselistener.hpp>
+
+#include "gui/widgets/shortcutcontainer.h"
+
+class Image;
+class Item;
+class ItemPopup;
+
+/**
+ * An item shortcut container. Used to quickly use items.
+ *
+ * \ingroup GUI
+ */
+class ItemShortcutContainer : public ShortcutContainer
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ ItemShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~ItemShortcutContainer();
+
+ /**
+ * Draws the items.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Handles mouse when dragged.
+ */
+ void mouseDragged(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse when pressed.
+ */
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Handles mouse release.
+ */
+ void mouseReleased(gcn::MouseEvent &event);
+
+ private:
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
+
+ bool mItemClicked;
+ Item *mItemMoved;
+
+ ItemPopup *mItemPopup;
+};
+
+#endif
diff --git a/src/gui/widgets/linkhandler.h b/src/gui/widgets/linkhandler.h
new file mode 100644
index 00000000..30267f87
--- /dev/null
+++ b/src/gui/widgets/linkhandler.h
@@ -0,0 +1,41 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LINK_HANDLER_H
+#define LINK_HANDLER_H
+
+#include <string>
+
+#include <string>
+
+/**
+ * A simple interface to windows that need to handle links from BrowserBox
+ * widget.
+ */
+class LinkHandler
+{
+ public:
+ virtual ~LinkHandler() { }
+
+ virtual void handleLink(const std::string &link) = 0;
+};
+
+#endif
diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp
index aee0f8d3..baedf8e4 100644
--- a/src/gui/widgets/listbox.cpp
+++ b/src/gui/widgets/listbox.cpp
@@ -21,10 +21,10 @@
#include "gui/widgets/listbox.h"
+#include "configuration.h"
+
#include "gui/palette.h"
#include "gui/sdlinput.h"
-
-#include "configuration.h"
#include "gui/skin.h"
#include <guichan/font.hpp>
diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp
new file mode 100644
index 00000000..4c499c36
--- /dev/null
+++ b/src/gui/widgets/playerbox.cpp
@@ -0,0 +1,109 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/playerbox.h"
+
+#include "animatedsprite.h"
+#include "configuration.h"
+#include "graphics.h"
+#include "player.h"
+
+#include "resources/image.h"
+#include "resources/resourcemanager.h"
+
+#include "utils/dtor.h"
+
+int PlayerBox::instances = 0;
+float PlayerBox::mAlpha = 1.0;
+ImageRect PlayerBox::background;
+
+PlayerBox::PlayerBox(const Player *player):
+ mPlayer(player)
+{
+ setFrameSize(2);
+
+ if (instances == 0)
+ {
+ // Load the background skin
+ ResourceManager *resman = ResourceManager::getInstance();
+ Image *textbox = resman->getImage("graphics/gui/deepbox.png");
+ int bggridx[4] = {0, 3, 28, 31};
+ int bggridy[4] = {0, 3, 28, 31};
+ int a = 0, x, y;
+
+ for (y = 0; y < 3; y++)
+ {
+ for (x = 0; x < 3; x++)
+ {
+ background.grid[a] = textbox->getSubImage(
+ bggridx[x], bggridy[y],
+ bggridx[x + 1] - bggridx[x] + 1,
+ bggridy[y + 1] - bggridy[y] + 1);
+ background.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
+ a++;
+ }
+ }
+
+ textbox->decRef();
+ }
+
+ instances++;
+}
+
+PlayerBox::~PlayerBox()
+{
+ instances--;
+
+ if (instances == 0)
+ {
+ for_each(background.grid, background.grid + 9, dtor<Image*>());
+ }
+}
+
+void PlayerBox::draw(gcn::Graphics *graphics)
+{
+ if (mPlayer)
+ {
+ // Draw character
+ const int bs = getFrameSize();
+ const int x = getWidth() / 2 + bs;
+ const int y = getHeight() - bs;
+ mPlayer->draw(static_cast<Graphics*>(graphics), x, y);
+ }
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ {
+ for (int a = 0; a < 9; a++)
+ {
+ background.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
+ }
+ }
+}
+
+void PlayerBox::drawFrame(gcn::Graphics *graphics)
+{
+ int w, h, bs;
+ bs = getFrameSize();
+ w = getWidth() + bs * 2;
+ h = getHeight() + bs * 2;
+
+ static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, background);
+}
diff --git a/src/gui/widgets/playerbox.h b/src/gui/widgets/playerbox.h
new file mode 100644
index 00000000..7c08defd
--- /dev/null
+++ b/src/gui/widgets/playerbox.h
@@ -0,0 +1,74 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PLAYERBOX_H
+#define PLAYERBOX_H
+
+#include <guichan/widgets/scrollarea.hpp>
+
+class ImageRect;
+class Player;
+
+/**
+ * A box showing a player character.
+ *
+ * \ingroup GUI
+ */
+class PlayerBox : public gcn::ScrollArea
+{
+ public:
+ /**
+ * Constructor. Takes the initial player character that this box should
+ * display, which defaults to <code>NULL</code>.
+ */
+ PlayerBox(const Player *player = NULL);
+
+ /**
+ * Destructor.
+ */
+ ~PlayerBox();
+
+ /**
+ * Sets a new player character to be displayed by this box. Setting the
+ * player to <code>NULL</code> causes the box not to draw any
+ * character.
+ */
+ void setPlayer(const Player *player) { mPlayer = player; }
+
+ /**
+ * Draws the scroll area.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Draws the background and border of the scroll area.
+ */
+ void drawFrame(gcn::Graphics *graphics);
+
+ private:
+ const Player *mPlayer; /**< The character used for display */
+
+ static float mAlpha;
+ static int instances;
+ static ImageRect background;
+};
+
+#endif
diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp
index 41d60ab6..d801bf32 100644
--- a/src/gui/widgets/popup.cpp
+++ b/src/gui/widgets/popup.cpp
@@ -22,14 +22,14 @@
#include "gui/widgets/popup.h"
-#include "gui/widgets/windowcontainer.h"
-
-#include "gui/skin.h"
-
#include "configuration.h"
#include "graphics.h"
#include "log.h"
+#include "gui/skin.h"
+
+#include "gui/widgets/windowcontainer.h"
+
#include "resources/image.h"
#include <guichan/exception.hpp>
diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp
index 0eda50a1..1b19ed7c 100644
--- a/src/gui/widgets/progressbar.cpp
+++ b/src/gui/widgets/progressbar.cpp
@@ -21,16 +21,16 @@
#include "gui/widgets/progressbar.h"
-#include "gui/gui.h"
-#include "gui/palette.h"
-#include "gui/textrenderer.h"
-
#include "configuration.h"
#include "graphics.h"
+#include "textrenderer.h"
+
+#include "gui/gui.h"
+#include "gui/palette.h"
+#include "gui/skin.h"
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
#include "utils/dtor.h"
diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp
index eed0ff33..5a2b5d61 100644
--- a/src/gui/widgets/scrollarea.cpp
+++ b/src/gui/widgets/scrollarea.cpp
@@ -24,9 +24,10 @@
#include "configuration.h"
#include "graphics.h"
+#include "gui/skin.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
#include "utils/dtor.h"
diff --git a/src/gui/widgets/setuptab.cpp b/src/gui/widgets/setuptab.cpp
new file mode 100644
index 00000000..e585fa5d
--- /dev/null
+++ b/src/gui/widgets/setuptab.cpp
@@ -0,0 +1,27 @@
+/*
+ * The Mana World
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/setuptab.h"
+
+SetupTab::SetupTab()
+{
+ setOpaque(false);
+}
diff --git a/src/gui/widgets/setuptab.h b/src/gui/widgets/setuptab.h
new file mode 100644
index 00000000..f0af1ea9
--- /dev/null
+++ b/src/gui/widgets/setuptab.h
@@ -0,0 +1,62 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GUI_SETUPTAB_H
+#define GUI_SETUPTAB_H
+
+#include "gui/widgets/container.h"
+
+#include <string>
+
+/**
+ * A container for the contents of a tab in the setup window.
+ */
+class SetupTab : public Container
+{
+public:
+ SetupTab();
+
+ const std::string &getName() const
+ { return mName; }
+
+ /**
+ * Called when the Apply button is pressed in the setup window.
+ */
+ virtual void apply() = 0;
+
+ /**
+ * Called when the Cancel button is pressed in the setup window.
+ */
+ virtual void cancel() = 0;
+
+protected:
+ /**
+ * Sets the name displayed on the tab. Should be set in the
+ * constructor of a subclass.
+ */
+ void setName(const std::string &name)
+ { mName = name; }
+
+private:
+ std::string mName;
+};
+
+#endif
diff --git a/src/gui/widgets/shopitems.cpp b/src/gui/widgets/shopitems.cpp
new file mode 100644
index 00000000..f59df591
--- /dev/null
+++ b/src/gui/widgets/shopitems.cpp
@@ -0,0 +1,103 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/shopitems.h"
+
+#include "shopitem.h"
+
+#include "utils/dtor.h"
+
+ShopItems::ShopItems(bool mergeDuplicates) :
+ mMergeDuplicates(mergeDuplicates)
+{
+}
+
+ShopItems::~ShopItems()
+{
+ clear();
+}
+
+int ShopItems::getNumberOfElements()
+{
+ return mShopItems.size();
+}
+
+std::string ShopItems::getElementAt(int i)
+{
+ return mShopItems.at(i)->getDisplayName();
+}
+
+void ShopItems::addItem(int id, int amount, int price)
+{
+ mShopItems.push_back(new ShopItem(-1, id, amount, price));
+}
+
+void ShopItems::addItem(int inventoryIndex, int id, int quantity, int price)
+{
+ ShopItem *item = 0;
+ if (mMergeDuplicates)
+ {
+ item = findItem(id);
+ }
+
+ if (item)
+ {
+ item->addDuplicate (inventoryIndex, quantity);
+ }
+ else
+ {
+ item = new ShopItem(inventoryIndex, id, quantity, price);
+ mShopItems.push_back(item);
+ }
+}
+
+ShopItem *ShopItems::at(int i) const
+{
+ return mShopItems.at(i);
+}
+
+void ShopItems::erase(int i)
+{
+ mShopItems.erase(mShopItems.begin() + i);
+}
+
+void ShopItems::clear()
+{
+ delete_all(mShopItems);
+ mShopItems.clear();
+}
+
+ShopItem *ShopItems::findItem(int id)
+{
+ ShopItem *item;
+
+ std::vector<ShopItem*>::iterator it;
+ for (it = mShopItems.begin(); it != mShopItems.end(); it++)
+ {
+ item = *(it);
+ if (item->getId() == id)
+ {
+ return item;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/gui/widgets/shopitems.h b/src/gui/widgets/shopitems.h
new file mode 100644
index 00000000..28f5d4b3
--- /dev/null
+++ b/src/gui/widgets/shopitems.h
@@ -0,0 +1,115 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SHOP_H
+#define SHOP_H
+
+#include <guichan/listmodel.hpp>
+
+#include <string>
+#include <vector>
+
+class ShopItem;
+
+/**
+ * This class handles the list of items available in a shop.
+ *
+ * The addItem routine can automatically check, if an item already exists and
+ * only adds duplicates to the old item, if one is found. The original
+ * distribution of the duplicates can be retrieved from the item.
+ *
+ * This functionality can be enabled in the constructor.
+ */
+class ShopItems : public gcn::ListModel
+{
+ public:
+ /**
+ * Constructor.
+ *
+ * @param mergeDuplicates lets the Shop look for duplicate entries and
+ * merges them to one item.
+ */
+ ShopItems(bool mergeDuplicates = false);
+
+ ~ShopItems();
+
+ /**
+ * Adds an item to the list.
+ */
+ void addItem(int id, int amount, int price);
+
+ /**
+ * Adds an item to the list (used by sell dialog). Looks for
+ * duplicate entries, if mergeDuplicates was turned on.
+ *
+ * @param inventoryIndex the inventory index of the item
+ * @param id the id of the item
+ * @param quantity number of available copies of the item
+ * @param price price of the item
+ */
+ void addItem(int inventoryIndex, int id, int amount, int price);
+
+ /**
+ * Returns the number of items in the shop.
+ */
+ int getNumberOfElements();
+
+ /**
+ * Returns the name of item number i in the shop.
+ *
+ * @param i the index to retrieve
+ */
+ std::string getElementAt(int i);
+
+ /**
+ * Returns the item number i in the shop.
+ */
+ ShopItem *at(int i) const;
+
+ /**
+ * Removes an element from the shop.
+ *
+ * @param i index to remove
+ */
+ void erase(int i);
+
+ /**
+ * Clears the list of items in the shop.
+ */
+ void clear();
+
+ private:
+ /**
+ * Searches the current items in the shop for the specified
+ * id and returns the item if found, or 0 else.
+ *
+ * @return the item found or 0
+ */
+ ShopItem *findItem(int id);
+
+ /** The list of items in the shop. */
+ std::vector<ShopItem*> mShopItems;
+
+ /** Look for duplicate entries on addition. */
+ bool mMergeDuplicates;
+};
+
+#endif // SHOP_H
diff --git a/src/gui/widgets/shoplistbox.cpp b/src/gui/widgets/shoplistbox.cpp
new file mode 100644
index 00000000..4779b8c2
--- /dev/null
+++ b/src/gui/widgets/shoplistbox.cpp
@@ -0,0 +1,157 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/shoplistbox.h"
+
+#include "configuration.h"
+#include "graphics.h"
+#include "shopitem.h"
+
+#include "gui/itempopup.h"
+#include "gui/palette.h"
+#include "gui/viewport.h"
+
+#include "gui/widgets/shopitems.h"
+
+#include "resources/image.h"
+
+#include <guichan/font.hpp>
+#include <guichan/listmodel.hpp>
+
+const int ITEM_ICON_SIZE = 32;
+
+float ShopListBox::mAlpha = 1.0;
+
+ShopListBox::ShopListBox(gcn::ListModel *listModel):
+ ListBox(listModel),
+ mPlayerMoney(0)
+{
+ mRowHeight = getFont()->getHeight();
+ mPriceCheck = true;
+
+ mItemPopup = new ItemPopup;
+}
+
+ShopListBox::ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel):
+ ListBox(listModel),
+ mPlayerMoney(0),
+ mShopItems(shopListModel)
+{
+ mRowHeight = std::max(getFont()->getHeight(), ITEM_ICON_SIZE);
+ mPriceCheck = true;
+
+ mItemPopup = new ItemPopup;
+}
+
+void ShopListBox::setPlayersMoney(int money)
+{
+ mPlayerMoney = money;
+}
+
+void ShopListBox::draw(gcn::Graphics *gcnGraphics)
+{
+ if (!mListModel)
+ return;
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ mAlpha = config.getValue("guialpha", 0.8);
+
+ int alpha = (int)(mAlpha * 255.0f);
+ const gcn::Color* highlightColor =
+ &guiPalette->getColor(Palette::HIGHLIGHT, alpha);
+
+ Graphics *graphics = static_cast<Graphics*>(gcnGraphics);
+
+ graphics->setFont(getFont());
+
+ // Draw the list elements
+ for (int i = 0, y = 0;
+ i < mListModel->getNumberOfElements();
+ ++i, y += mRowHeight)
+ {
+ gcn::Color temp;
+ const gcn::Color* backgroundColor =
+ &guiPalette->getColor(Palette::BACKGROUND, alpha);
+
+ if (mShopItems &&
+ mPlayerMoney < mShopItems->at(i)->getPrice() && mPriceCheck)
+ if (i != mSelected)
+ backgroundColor = &guiPalette->getColor(Palette::SHOP_WARNING,
+ alpha);
+ else
+ {
+ temp = guiPalette->getColor(Palette::SHOP_WARNING, alpha);
+ temp.r = (temp.r + highlightColor->r) / 2;
+ temp.g = (temp.g + highlightColor->g) / 2;
+ temp.b = (temp.g + highlightColor->b) / 2;
+ backgroundColor = &temp;
+ }
+ else if (i == mSelected)
+ backgroundColor = highlightColor;
+
+ graphics->setColor(*backgroundColor);
+ graphics->fillRectangle(gcn::Rectangle(0, y, getWidth(), mRowHeight));
+
+ if (mShopItems)
+ {
+ Image *icon = mShopItems->at(i)->getImage();
+ if (icon)
+ {
+ icon->setAlpha(1.0f);
+ graphics->drawImage(icon, 1, y);
+ }
+ }
+ graphics->setColor(guiPalette->getColor(Palette::TEXT));
+ graphics->drawText(mListModel->getElementAt(i), ITEM_ICON_SIZE + 5,
+ y + (ITEM_ICON_SIZE - getFont()->getHeight()) / 2);
+ }
+}
+
+void ShopListBox::adjustSize()
+{
+ if (mListModel)
+ {
+ setHeight(mRowHeight * mListModel->getNumberOfElements());
+ }
+}
+
+void ShopListBox::setPriceCheck(bool check)
+{
+ mPriceCheck = check;
+}
+
+void ShopListBox::mouseMoved(gcn::MouseEvent &event)
+{
+ if (!mShopItems)
+ return;
+
+ Item *item = mShopItems->at(event.getY() / mRowHeight);
+
+ if (item)
+ {
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->view(viewport->getMouseX(), viewport->getMouseY());
+ }
+ else
+ {
+ mItemPopup->setVisible(false);
+ }
+}
diff --git a/src/gui/widgets/shoplistbox.h b/src/gui/widgets/shoplistbox.h
new file mode 100644
index 00000000..99d3b9bd
--- /dev/null
+++ b/src/gui/widgets/shoplistbox.h
@@ -0,0 +1,96 @@
+/*
+ * The Mana World
+ * Copyright (C) 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SHOPLISTBOX_H
+#define SHOPLISTBOX_H
+
+#include "gui/widgets/listbox.h"
+
+class ShopItems;
+class ItemPopup;
+
+/**
+ * A list box, meant to be used inside a scroll area. Same as the Guichan list
+ * box except this one doesn't have a background, instead completely relying
+ * on the scroll area. It also adds selection listener functionality.
+ *
+ * \ingroup GUI
+ */
+class ShopListBox : public ListBox
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ShopListBox(gcn::ListModel *listModel);
+
+ /**
+ * Constructor with shopitems
+ */
+ ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel);
+
+ /**
+ * Draws the list box.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Returns the height of a row.
+ */
+ unsigned int getRowHeight() const { return mRowHeight; }
+
+ /**
+ * gives information about the current player's money
+ */
+ void setPlayersMoney(int money);
+
+ /**
+ * Adjust List draw size
+ */
+ void adjustSize();
+
+ /**
+ * Set on/off the disabling of too expensive items.
+ * (Good for selling mode.)
+ */
+ void setPriceCheck(bool check);
+
+ void mouseMoved(gcn::MouseEvent &event);
+
+ private:
+ int mPlayerMoney;
+
+ /**
+ * Keeps another pointer to the same listModel, permitting to
+ * use the ShopItems specific functions.
+ */
+ ShopItems *mShopItems;
+
+ ItemPopup *mItemPopup;
+
+ unsigned int mRowHeight; /**< Row Height */
+
+ static float mAlpha;
+
+ bool mPriceCheck;
+};
+
+#endif // SHOPLISTBOX_H
diff --git a/src/gui/widgets/shortcutcontainer.cpp b/src/gui/widgets/shortcutcontainer.cpp
new file mode 100644
index 00000000..61524acc
--- /dev/null
+++ b/src/gui/widgets/shortcutcontainer.cpp
@@ -0,0 +1,64 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/shortcutcontainer.h"
+
+#include "configuration.h"
+
+#include "resources/image.h"
+
+#include "utils/stringutils.h"
+
+float ShortcutContainer::mAlpha = 1.0;
+
+ShortcutContainer::ShortcutContainer():
+ mGridWidth(1),
+ mGridHeight(1)
+{
+}
+
+void ShortcutContainer::widgetResized(const gcn::Event &event)
+{
+ mGridWidth = getWidth() / mBoxWidth;
+
+ if (mGridWidth < 1)
+ mGridWidth = 1;
+
+ mGridHeight = mMaxItems / mGridWidth;
+
+ if (mMaxItems % mGridWidth != 0 || mGridHeight < 1)
+ ++mGridHeight;
+
+ setHeight(mGridHeight * mBoxHeight);
+}
+
+int ShortcutContainer::getIndexFromGrid(int pointX, int pointY) const
+{
+ const gcn::Rectangle tRect = gcn::Rectangle(0, 0, mGridWidth * mBoxWidth,
+ mGridHeight * mBoxHeight);
+
+ int index = ((pointY / mBoxHeight) * mGridWidth) + pointX / mBoxWidth;
+
+ if (!tRect.isPointInRect(pointX, pointY) || index >= mMaxItems)
+ index = -1;
+
+ return index;
+}
diff --git a/src/gui/widgets/shortcutcontainer.h b/src/gui/widgets/shortcutcontainer.h
new file mode 100644
index 00000000..906201be
--- /dev/null
+++ b/src/gui/widgets/shortcutcontainer.h
@@ -0,0 +1,107 @@
+/*
+ * The Mana World
+ * Copyright (C) 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SHORTCUTCONTAINER_H
+#define SHORTCUTCONTAINER_H
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+#include <guichan/widgetlistener.hpp>
+
+class Image;
+
+/**
+ * A generic shortcut container.
+ *
+ * \ingroup GUI
+ */
+class ShortcutContainer : public gcn::Widget,
+ public gcn::WidgetListener,
+ public gcn::MouseListener
+{
+ public:
+ /**
+ * Constructor. Initializes the shortcut container.
+ */
+ ShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ ~ShortcutContainer() {}
+
+ /**
+ * Draws the shortcuts
+ */
+ virtual void draw(gcn::Graphics *graphics) = 0;
+
+ /**
+ * Invoked when a widget changes its size. This is used to determine
+ * the new height of the container.
+ */
+ virtual void widgetResized(const gcn::Event &event);
+
+ /**
+ * Handles mouse when dragged.
+ */
+ virtual void mouseDragged(gcn::MouseEvent &event) = 0;
+
+ /**
+ * Handles mouse when pressed.
+ */
+ virtual void mousePressed(gcn::MouseEvent &event) = 0;
+
+ /**
+ * Handles mouse release.
+ */
+ virtual void mouseReleased(gcn::MouseEvent &event) = 0;
+
+ int getMaxItems() const
+ { return mMaxItems; }
+
+ int getBoxWidth() const
+ { return mBoxWidth; }
+
+ int getBoxHeight() const
+ { return mBoxHeight; }
+
+ protected:
+ /**
+ * Gets the index from the grid provided the point is in an item box.
+ *
+ * @param pointX X coordinate of the point.
+ * @param pointY Y coordinate of the point.
+ * @return index on success, -1 on failure.
+ */
+ int getIndexFromGrid(int pointX, int pointY) const;
+
+ Image *mBackgroundImg;
+
+ static float mAlpha;
+
+ int mMaxItems;
+ int mBoxWidth;
+ int mBoxHeight;
+ int mCursorPosX, mCursorPosY;
+ int mGridWidth, mGridHeight;
+};
+
+#endif
diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp
index 66fe780d..693ac0f7 100644
--- a/src/gui/widgets/slider.cpp
+++ b/src/gui/widgets/slider.cpp
@@ -24,9 +24,10 @@
#include "configuration.h"
#include "graphics.h"
+#include "gui/skin.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip;
Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip;
diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp
index a49c4f12..9abe1f58 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -21,12 +21,12 @@
#include "gui/widgets/tab.h"
-#include "gui/widgets/tabbedarea.h"
+#include "configuration.h"
+#include "graphics.h"
#include "gui/palette.h"
-#include "configuration.h"
-#include "graphics.h"
+#include "gui/widgets/tabbedarea.h"
#include "resources/image.h"
#include "resources/resourcemanager.h"
diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp
index dd2e62dd..563d995f 100644
--- a/src/gui/widgets/tabbedarea.cpp
+++ b/src/gui/widgets/tabbedarea.cpp
@@ -20,6 +20,7 @@
*/
#include "gui/widgets/tabbedarea.h"
+
#include "gui/widgets/tab.h"
#include <guichan/widgets/container.hpp>
diff --git a/src/gui/widgets/table.cpp b/src/gui/widgets/table.cpp
new file mode 100644
index 00000000..f33d0abe
--- /dev/null
+++ b/src/gui/widgets/table.cpp
@@ -0,0 +1,549 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/table.h"
+
+#include "configuration.h"
+
+#include "gui/palette.h"
+#include "gui/sdlinput.h"
+
+#include "utils/dtor.h"
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/graphics.hpp>
+#include <guichan/key.hpp>
+
+float GuiTable::mAlpha = 1.0;
+
+class GuiTableActionListener : public gcn::ActionListener
+{
+public:
+ GuiTableActionListener(GuiTable *_table, gcn::Widget *_widget, int _row, int _column);
+
+ virtual ~GuiTableActionListener();
+
+ virtual void action(const gcn::ActionEvent& actionEvent);
+
+protected:
+ GuiTable *mTable;
+ int mRow;
+ int mColumn;
+ gcn::Widget *mWidget;
+};
+
+
+GuiTableActionListener::GuiTableActionListener(GuiTable *table, gcn::Widget *widget, int row, int column) :
+ mTable(table),
+ mRow(row),
+ mColumn(column),
+ mWidget(widget)
+{
+ if (widget)
+ {
+ widget->addActionListener(this);
+ widget->_setParent(table);
+ }
+}
+
+GuiTableActionListener::~GuiTableActionListener()
+{
+ if (mWidget)
+ {
+ mWidget->removeActionListener(this);
+ mWidget->_setParent(NULL);
+ }
+}
+
+void GuiTableActionListener::action(const gcn::ActionEvent& actionEvent)
+{
+ mTable->setSelected(mRow, mColumn);
+ mTable->distributeActionEvent();
+}
+
+
+GuiTable::GuiTable(TableModel *initial_model, gcn::Color background,
+ bool opacity) :
+ mLinewiseMode(false),
+ mWrappingEnabled(false),
+ mOpaque(opacity),
+ mBackgroundColor(background),
+ mModel(NULL),
+ mSelectedRow(0),
+ mSelectedColumn(0),
+ mTopWidget(NULL)
+{
+ setModel(initial_model);
+ setFocusable(true);
+
+ addMouseListener(this);
+ addKeyListener(this);
+}
+
+GuiTable::~GuiTable()
+{
+ uninstallActionListeners();
+ delete mModel;
+}
+
+TableModel *GuiTable::getModel() const
+{
+ return mModel;
+}
+
+void GuiTable::setModel(TableModel *new_model)
+{
+ if (mModel)
+ {
+ uninstallActionListeners();
+ mModel->removeListener(this);
+ }
+
+ mModel = new_model;
+ installActionListeners();
+
+ if (new_model)
+ {
+ new_model->installListener(this);
+ recomputeDimensions();
+ }
+}
+
+void GuiTable::recomputeDimensions()
+{
+ int rows_nr = mModel->getRows();
+ int columns_nr = mModel->getColumns();
+ int width = 0;
+ int height = 0;
+
+ if (mSelectedRow >= rows_nr)
+ mSelectedRow = rows_nr - 1;
+
+ if (mSelectedColumn >= columns_nr)
+ mSelectedColumn = columns_nr - 1;
+
+ for (int i = 0; i < columns_nr; i++)
+ width += getColumnWidth(i);
+
+ height = getRowHeight() * rows_nr;
+
+ setWidth(width);
+ setHeight(height);
+}
+
+void GuiTable::setSelected(int row, int column)
+{
+ mSelectedColumn = column;
+ mSelectedRow = row;
+}
+
+int GuiTable::getSelectedRow() const
+{
+ return mSelectedRow;
+}
+
+int GuiTable::getSelectedColumn() const
+{
+ return mSelectedColumn;
+}
+
+void GuiTable::setLinewiseSelection(bool linewise)
+{
+ mLinewiseMode = linewise;
+}
+
+int GuiTable::getRowHeight() const
+{
+ if (mModel)
+ return mModel->getRowHeight() + 1; // border
+ else
+ return 0;
+}
+
+int GuiTable::getColumnWidth(int i) const
+{
+ if (mModel)
+ return mModel->getColumnWidth(i) + 1; // border
+ else
+ return 0;
+}
+
+void GuiTable::setSelectedRow(int selected)
+{
+ if (!mModel)
+ {
+ mSelectedRow = -1;
+ }
+ else
+ {
+ if (selected < 0 && !mWrappingEnabled)
+ {
+ mSelectedRow = -1;
+ }
+ else if (selected >= mModel->getRows() && mWrappingEnabled)
+ {
+ mSelectedRow = 0;
+ }
+ else if ((selected >= mModel->getRows() && !mWrappingEnabled) ||
+ (selected < 0 && mWrappingEnabled))
+ {
+ mSelectedRow = mModel->getRows() - 1;
+ }
+ else
+ {
+ mSelectedRow = selected;
+ }
+ }
+}
+
+void GuiTable::setSelectedColumn(int selected)
+{
+ if (!mModel)
+ {
+ mSelectedColumn = -1;
+ }
+ else
+ {
+ if ((selected >= mModel->getColumns() && mWrappingEnabled) ||
+ (selected < 0 && !mWrappingEnabled))
+ {
+ mSelectedColumn = 0;
+ }
+ else if ((selected >= mModel->getColumns() && !mWrappingEnabled) ||
+ (selected < 0 && mWrappingEnabled))
+ {
+ mSelectedColumn = mModel->getColumns() - 1;
+ }
+ else
+ {
+ mSelectedColumn = selected;
+ }
+ }
+}
+
+void GuiTable::uninstallActionListeners()
+{
+ delete_all(mActionListeners);
+ mActionListeners.clear();
+}
+
+void GuiTable::installActionListeners()
+{
+ if (!mModel)
+ return;
+
+ int rows = mModel->getRows();
+ int columns = mModel->getColumns();
+
+ for (int row = 0; row < rows; ++row)
+ for (int column = 0; column < columns; ++column)
+ {
+ gcn::Widget *widget = mModel->getElementAt(row, column);
+ mActionListeners.push_back(new GuiTableActionListener(this, widget,
+ row, column));
+ }
+
+ _setFocusHandler(_getFocusHandler()); // propagate focus handler to widgets
+}
+
+// -- widget ops
+void GuiTable::draw(gcn::Graphics* graphics)
+{
+ if (!mModel)
+ return;
+
+ if (config.getValue("guialpha", 0.8) != mAlpha)
+ mAlpha = config.getValue("guialpha", 0.8);
+
+ if (mOpaque)
+ {
+ graphics->setColor(guiPalette->getColor(Palette::BACKGROUND,
+ (int)(mAlpha * 255.0f)));
+ graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
+ }
+
+ // First, determine how many rows we need to draw, and where we should start.
+ int first_row = -(getY() / getRowHeight());
+
+ if (first_row < 0)
+ first_row = 0;
+
+ int rows_nr = 1 + (getHeight() / getRowHeight()); // May overestimate by one.
+
+ int max_rows_nr = mModel->getRows() - first_row; // clip if neccessary:
+ if (max_rows_nr < rows_nr)
+ rows_nr = max_rows_nr;
+
+ // Now determine the first and last column
+ // Take the easy way out; these are usually bounded and all visible.
+ int first_column = 0;
+ int last_column = mModel->getColumns() - 1;
+
+ // Set up everything for drawing
+ int height = getRowHeight();
+ int y_offset = first_row * height;
+
+ for (int r = first_row; r < first_row + rows_nr; ++r)
+ {
+ int x_offset = 0;
+
+ for (int c = first_column; c <= last_column; ++c)
+ {
+ gcn::Widget *widget = mModel->getElementAt(r, c);
+ int width = getColumnWidth(c);
+ if (widget)
+ {
+ gcn::Rectangle bounds(x_offset, y_offset, width, height);
+
+ if (widget == mTopWidget)
+ {
+ bounds.height = widget->getHeight();
+ bounds.width = widget->getWidth();
+ }
+
+ widget->setDimension(bounds);
+
+ graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT,
+ (int)(mAlpha * 255.0f)));
+
+ if (mLinewiseMode && r == mSelectedRow && c == 0)
+ {
+ graphics->fillRectangle(gcn::Rectangle(0, y_offset,
+ getWidth(), height));
+ }
+ else if (!mLinewiseMode &&
+ c == mSelectedColumn && r == mSelectedRow)
+ {
+ graphics->fillRectangle(gcn::Rectangle(x_offset, y_offset,
+ width, height));
+ }
+
+ graphics->pushClipArea(bounds);
+ widget->draw(graphics);
+ graphics->popClipArea();
+ }
+
+ x_offset += width;
+ }
+
+ y_offset += height;
+ }
+
+ if (mTopWidget)
+ {
+ gcn::Rectangle bounds = mTopWidget->getDimension();
+ graphics->pushClipArea(bounds);
+ mTopWidget->draw(graphics);
+ graphics->popClipArea();
+ }
+}
+
+void GuiTable::moveToTop(gcn::Widget *widget)
+{
+ gcn::Widget::moveToTop(widget);
+ mTopWidget = widget;
+}
+
+void GuiTable::moveToBottom(gcn::Widget *widget)
+{
+ gcn::Widget::moveToBottom(widget);
+ if (widget == mTopWidget)
+ mTopWidget = NULL;
+}
+
+gcn::Rectangle GuiTable::getChildrenArea() const
+{
+ return gcn::Rectangle(0, 0, getWidth(), getHeight());
+}
+
+// -- KeyListener notifications
+void GuiTable::keyPressed(gcn::KeyEvent& keyEvent)
+{
+ gcn::Key key = keyEvent.getKey();
+
+ if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
+ {
+ distributeActionEvent();
+ keyEvent.consume();
+ }
+ else if (key.getValue() == Key::UP)
+ {
+ setSelectedRow(mSelectedRow - 1);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == Key::DOWN)
+ {
+ setSelectedRow(mSelectedRow + 1);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == Key::LEFT)
+ {
+ setSelectedColumn(mSelectedColumn - 1);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == Key::RIGHT)
+ {
+ setSelectedColumn(mSelectedColumn + 1);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == Key::HOME)
+ {
+ setSelectedRow(0);
+ setSelectedColumn(0);
+ keyEvent.consume();
+ }
+ else if (key.getValue() == Key::END)
+ {
+ setSelectedRow(mModel->getRows() - 1);
+ setSelectedColumn(mModel->getColumns() - 1);
+ keyEvent.consume();
+ }
+}
+
+// -- MouseListener notifications
+void GuiTable::mousePressed(gcn::MouseEvent& mouseEvent)
+{
+ if (mouseEvent.getButton() == gcn::MouseEvent::LEFT)
+ {
+ int row = getRowForY(mouseEvent.getY());
+ int column = getColumnForX(mouseEvent.getX());
+
+ if (row > -1 && column > -1 &&
+ row < mModel->getRows() && column < mModel->getColumns())
+ {
+ mSelectedColumn = column;
+ mSelectedRow = row;
+ }
+
+ distributeActionEvent();
+ }
+}
+
+void GuiTable::mouseWheelMovedUp(gcn::MouseEvent& mouseEvent)
+{
+ if (isFocused())
+ {
+ if (getSelectedRow() > 0 || (getSelectedRow() == 0 && mWrappingEnabled))
+ {
+ setSelectedRow(getSelectedRow() - 1);
+ }
+
+ mouseEvent.consume();
+ }
+}
+
+void GuiTable::mouseWheelMovedDown(gcn::MouseEvent& mouseEvent)
+{
+ if (isFocused())
+ {
+ setSelectedRow(getSelectedRow() + 1);
+
+ mouseEvent.consume();
+ }
+}
+
+void GuiTable::mouseDragged(gcn::MouseEvent& mouseEvent)
+{
+}
+
+// -- TableModelListener notifications
+void GuiTable::modelUpdated(bool completed)
+{
+ if (completed)
+ {
+ recomputeDimensions();
+ installActionListeners();
+ }
+ else
+ { // before the update?
+ mTopWidget = NULL; // No longer valid in general
+ uninstallActionListeners();
+ }
+}
+
+gcn::Widget *GuiTable::getWidgetAt(int x, int y) const
+{
+ int row = getRowForY(y);
+ int column = getColumnForX(x);
+
+ if (mTopWidget && mTopWidget->getDimension().isPointInRect(x, y))
+ return mTopWidget;
+
+ if (row > -1 && column > -1)
+ {
+ gcn::Widget *w = mModel->getElementAt(row, column);
+ if (w && w->isFocusable())
+ return w;
+ else
+ return NULL; // Grab the event locally
+ }
+ else
+ return NULL;
+}
+
+int GuiTable::getRowForY(int y) const
+{
+ int row = -1;
+
+ if (getRowHeight() > 0)
+ row = y / getRowHeight();
+
+ if (row < 0 || row >= mModel->getRows())
+ return -1;
+ else
+ return row;
+}
+
+int GuiTable::getColumnForX(int x) const
+{
+ int column;
+ int delta = 0;
+
+ for (column = 0; column < mModel->getColumns(); column++)
+ {
+ delta += getColumnWidth(column);
+ if (x <= delta)
+ break;
+ }
+
+ if (column < 0 || column >= mModel->getColumns())
+ return -1;
+ else
+ return column;
+}
+
+void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler)
+{
+ gcn::Widget::_setFocusHandler(focusHandler);
+
+ if (mModel)
+ {
+ for (int r = 0; r < mModel->getRows(); ++r)
+ {
+ for (int c = 0; c < mModel->getColumns(); ++c)
+ {
+ gcn::Widget *w = mModel->getElementAt(r, c);
+ if (w)
+ w->_setFocusHandler(focusHandler);
+ }
+ }
+ }
+}
diff --git a/src/gui/widgets/table.h b/src/gui/widgets/table.h
new file mode 100644
index 00000000..d1f445b3
--- /dev/null
+++ b/src/gui/widgets/table.h
@@ -0,0 +1,185 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TABLE_H
+#define TABLE_H
+
+#include "tablemodel.h"
+
+#include <guichan/keylistener.hpp>
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+
+#include <vector>
+
+class GuiTableActionListener;
+
+/**
+ * A table, with rows and columns made out of sub-widgets. Largely inspired by
+ * (and can be thought of as a generalisation of) the guichan listbox
+ * implementation.
+ *
+ * Normally you want this within a ScrollArea.
+ *
+ * \ingroup GUI
+ */
+class GuiTable : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::KeyListener,
+ public TableModelListener
+{
+ // so that the action listener can call distributeActionEvent
+ friend class GuiTableActionListener;
+
+public:
+ GuiTable(TableModel * initial_model = NULL, gcn::Color background = 0xffffff,
+ bool opacity = true);
+
+ virtual ~GuiTable();
+
+ /**
+ * Retrieves the active table model
+ */
+ TableModel *getModel() const;
+
+ /**
+ * Sets the table model
+ *
+ * Note that actions issued by widgets returned from the model will update
+ * the table selection, but only AFTER any event handlers installed within
+ * the widget have been triggered. To be notified after such an update, add
+ * an action listener to the table instead.
+ */
+ void setModel(TableModel *m);
+
+ void setSelected(int row, int column);
+
+ int getSelectedRow() const;
+
+ int getSelectedColumn() const;
+
+ void setSelectedRow(int selected);
+
+ void setSelectedColumn(int selected);
+
+ bool isWrappingEnabled() const {return mWrappingEnabled;}
+
+ void setWrappingEnabled(bool wrappingEnabled)
+ {mWrappingEnabled = wrappingEnabled;}
+
+ gcn::Rectangle getChildrenArea() const;
+
+ /**
+ * Toggle whether to use linewise selection mode, in which the table selects
+ * an entire line at a time, rather than a single cell.
+ *
+ * Note that column information is tracked even in linewise selection mode;
+ * this mode therefore only affects visualisation.
+ *
+ * Disabled by default.
+ *
+ * \param linewise: Whether to enable linewise selection mode
+ */
+ void setLinewiseSelection(bool linewise);
+
+ // Inherited from Widget
+ virtual void draw(gcn::Graphics* graphics);
+
+ virtual gcn::Widget *getWidgetAt(int x, int y) const;
+
+ virtual void moveToTop(gcn::Widget *child);
+
+ virtual void moveToBottom(gcn::Widget *child);
+
+ virtual void _setFocusHandler(gcn::FocusHandler* focusHandler);
+
+ // Inherited from KeyListener
+ virtual void keyPressed(gcn::KeyEvent& keyEvent);
+
+ /**
+ * Sets the table to be opaque, that is sets the table
+ * to display its background.
+ *
+ * @param opaque True if the table should be opaque, false otherwise.
+ */
+ virtual void setOpaque(bool opaque) {mOpaque = opaque;}
+
+ /**
+ * Checks if the table is opaque, that is if the table area displays its
+ * background.
+ *
+ * @return True if the table is opaque, false otherwise.
+ */
+ virtual bool isOpaque() const {return mOpaque;}
+
+ // Inherited from MouseListener
+ virtual void mousePressed(gcn::MouseEvent& mouseEvent);
+
+ virtual void mouseWheelMovedUp(gcn::MouseEvent& mouseEvent);
+
+ virtual void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent);
+
+ virtual void mouseDragged(gcn::MouseEvent& mouseEvent);
+
+ // Constraints inherited from TableModelListener
+ virtual void modelUpdated(bool);
+
+protected:
+ /** Frees all action listeners on inner widgets. */
+ virtual void uninstallActionListeners();
+ /** Installs all action listeners on inner widgets. */
+ virtual void installActionListeners();
+
+ virtual int getRowHeight() const;
+ virtual int getColumnWidth(int i) const;
+
+private:
+ int getRowForY(int y) const; // -1 on error
+ int getColumnForX(int x) const; // -1 on error
+ void recomputeDimensions();
+ bool mLinewiseMode;
+ bool mWrappingEnabled;
+ bool mOpaque;
+
+ static float mAlpha;
+
+ /**
+ * Holds the background color of the table.
+ */
+ gcn::Color mBackgroundColor;
+
+ TableModel *mModel;
+
+ int mSelectedRow;
+ int mSelectedColumn;
+
+ /** Number of frames to skip upwards when drawing the selected widget. */
+ int mPopFramesNr;
+
+ /** If someone moves a fresh widget to the top, we must display it. */
+ gcn::Widget *mTopWidget;
+
+ /** Vector for compactness; used as a list in practice. */
+ std::vector<GuiTableActionListener *> mActionListeners;
+};
+
+
+#endif // TABLE_H
diff --git a/src/gui/widgets/tablemodel.cpp b/src/gui/widgets/tablemodel.cpp
new file mode 100644
index 00000000..db06edec
--- /dev/null
+++ b/src/gui/widgets/tablemodel.cpp
@@ -0,0 +1,161 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "gui/widgets/tablemodel.h"
+
+#include "utils/dtor.h"
+
+#include <guichan/widget.hpp>
+
+void TableModel::installListener(TableModelListener *listener)
+{
+ listeners.insert(listener);
+}
+
+void TableModel::removeListener(TableModelListener *listener)
+{
+ listeners.erase(listener);
+}
+
+void TableModel::signalBeforeUpdate()
+{
+ for (std::set<TableModelListener *>::const_iterator it = listeners.begin(); it != listeners.end(); it++)
+ (*it)->modelUpdated(false);
+}
+
+void TableModel::signalAfterUpdate()
+{
+ for (std::set<TableModelListener *>::const_iterator it = listeners.begin(); it != listeners.end(); it++)
+ (*it)->modelUpdated(true);
+}
+
+
+#define WIDGET_AT(row, column) (((row) * mColumns) + (column))
+#define DYN_SIZE(h) ((h) >= 0) // determines whether this size is tagged for auto-detection
+
+StaticTableModel::StaticTableModel(int row, int column) :
+ mRows(row),
+ mColumns(column),
+ mHeight(1)
+{
+ mTableModel.resize(row * column, NULL);
+ mWidths.resize(column, 1);
+}
+
+StaticTableModel::~StaticTableModel()
+{
+ delete_all(mTableModel);
+}
+
+void StaticTableModel::resize()
+{
+ mRows = getRows();
+ mColumns = getColumns();
+ mTableModel.resize(mRows * mColumns, NULL);
+}
+
+void StaticTableModel::set(int row, int column, gcn::Widget *widget)
+{
+ if (row >= mRows || row < 0
+ || column >= mColumns || column < 0)
+ // raise exn?
+ return;
+
+ if (DYN_SIZE(mHeight)
+ && widget->getHeight() > mHeight)
+ mHeight = widget->getHeight();
+
+ if (DYN_SIZE(mWidths[column])
+ && widget->getWidth() > mWidths[column])
+ mWidths[column] = widget->getWidth();
+
+ signalBeforeUpdate();
+
+ if (mTableModel[WIDGET_AT(row, column)])
+ delete mTableModel[WIDGET_AT(row, column)];
+
+ mTableModel[WIDGET_AT(row, column)] = widget;
+
+ signalAfterUpdate();
+}
+
+gcn::Widget *StaticTableModel::getElementAt(int row, int column) const
+{
+ return mTableModel[WIDGET_AT(row, column)];
+}
+
+void StaticTableModel::fixColumnWidth(int column, int width)
+{
+ if (width < 0
+ || column < 0 || column >= mColumns)
+ return;
+
+ mWidths[column] = -width; // Negate to tag as fixed
+}
+
+void StaticTableModel::fixRowHeight(int height)
+{
+ if (height < 0)
+ return;
+
+ mHeight = -height;
+}
+
+int StaticTableModel::getRowHeight() const
+{
+ return abs(mHeight);
+}
+
+int StaticTableModel::getColumnWidth(int column) const
+{
+ if (column < 0 || column >= mColumns)
+ return 0;
+
+ return abs(mWidths[column]);
+}
+
+int StaticTableModel::getRows() const
+{
+ return mRows;
+}
+
+int StaticTableModel::getColumns() const
+{
+ return mColumns;
+}
+
+int StaticTableModel::getWidth() const
+{
+ int width = 0;
+
+ for (unsigned int i = 0; i < mWidths.size(); i++)
+ {
+ width += mWidths[i];
+ }
+
+ return width;
+}
+
+int StaticTableModel::getHeight() const
+{
+ return mColumns * mHeight;
+}
+
diff --git a/src/gui/widgets/tablemodel.h b/src/gui/widgets/tablemodel.h
new file mode 100644
index 00000000..129d2089
--- /dev/null
+++ b/src/gui/widgets/tablemodel.h
@@ -0,0 +1,146 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TABLE_MODEL_H
+#define TABLE_MODEL_H
+
+#include <guichanfwd.h>
+
+#include <set>
+#include <vector>
+
+class TableModelListener
+{
+public:
+ /**
+ * Must be invoked by the TableModel whenever a global change is about to
+ * occur or has occurred (e.g., when a row or column is being removed or
+ * added).
+ *
+ * This method is triggered twice, once before and once after the update.
+ *
+ * \param completed whether we are signalling the end of the update
+ */
+ virtual void modelUpdated(bool completed) = 0;
+};
+
+/**
+ * A model for a regular table of widgets.
+ */
+class TableModel
+{
+public:
+ virtual ~TableModel() { }
+
+ /**
+ * Determines the number of rows (lines) in the table
+ */
+ virtual int getRows() const = 0;
+
+ /**
+ * Determines the number of columns in each row
+ */
+ virtual int getColumns() const = 0;
+
+ /**
+ * Determines the height for each row
+ */
+ virtual int getRowHeight() const = 0;
+
+ /**
+ * Determines the width of each individual column
+ */
+ virtual int getColumnWidth(int index) const = 0;
+
+ /**
+ * Retrieves the widget stored at the specified location within the table.
+ */
+ virtual gcn::Widget *getElementAt(int row, int column) const = 0;
+
+ virtual void installListener(TableModelListener *listener);
+
+ virtual void removeListener(TableModelListener *listener);
+
+protected:
+ /**
+ * Tells all listeners that the table is about to see an update
+ */
+ virtual void signalBeforeUpdate();
+
+ /**
+ * Tells all listeners that the table has seen an update
+ */
+ virtual void signalAfterUpdate();
+
+private:
+ std::set<TableModelListener *> listeners;
+};
+
+
+class StaticTableModel : public TableModel
+{
+public:
+ StaticTableModel(int width, int height);
+ virtual ~StaticTableModel();
+
+ /**
+ * Inserts a widget into the table model.
+ * The model is resized to accomodate the widget's width and height,
+ * unless column width / row height have been fixed.
+ */
+ virtual void set(int row, int column, gcn::Widget *widget);
+
+ /**
+ * Fixes the column width for a given column; this overrides dynamic width
+ * inference.
+ *
+ * Semantics are undefined for width 0.
+ */
+ virtual void fixColumnWidth(int column, int width);
+
+ /**
+ * Fixes the row height; this overrides dynamic height inference.
+ *
+ * Semantics are undefined for width 0.
+ */
+ virtual void fixRowHeight(int height);
+
+ /**
+ * Resizes the table model
+ */
+ virtual void resize();
+
+ virtual int getRows() const;
+ virtual int getColumns() const;
+ virtual int getRowHeight() const;
+ virtual int getWidth() const;
+ virtual int getHeight() const;
+ virtual int getColumnWidth(int index) const;
+ virtual gcn::Widget *getElementAt(int row, int column) const;
+
+protected:
+ int mRows, mColumns;
+ int mHeight;
+ std::vector<gcn::Widget *> mTableModel;
+ std::vector<int> mWidths;
+};
+
+#endif // TABLE_MODEL_H
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index 0f0caa00..c0c42718 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -21,15 +21,15 @@
#include "gui/widgets/textfield.h"
-#include "gui/palette.h"
-#include "gui/sdlinput.h"
-
#include "configuration.h"
#include "graphics.h"
+#include "gui/palette.h"
+#include "gui/sdlinput.h"
+#include "gui/skin.h"
+
#include "resources/image.h"
#include "resources/resourcemanager.h"
-#include "gui/skin.h"
#include "utils/dtor.h"
diff --git a/src/gui/widgets/textpreview.cpp b/src/gui/widgets/textpreview.cpp
index 0113c09f..ba2b557b 100644
--- a/src/gui/widgets/textpreview.cpp
+++ b/src/gui/widgets/textpreview.cpp
@@ -21,13 +21,13 @@
#include "gui/widgets/textpreview.h"
+#include "configuration.h"
+#include "textrenderer.h"
+
#include "gui/gui.h"
#include "gui/palette.h"
-#include "gui/textrenderer.h"
#include "gui/truetypefont.h"
-#include "configuration.h"
-
#include <typeinfo>
float TextPreview::mAlpha = 1.0;
diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp
index 8d7b442b..ada1e957 100644
--- a/src/gui/widgets/window.cpp
+++ b/src/gui/widgets/window.cpp
@@ -21,16 +21,16 @@
#include "gui/widgets/window.h"
-#include "gui/widgets/layout.h"
-#include "gui/widgets/resizegrip.h"
-#include "gui/widgets/windowcontainer.h"
+#include "configuration.h"
+#include "log.h"
#include "gui/gui.h"
#include "gui/palette.h"
#include "gui/skin.h"
-#include "configuration.h"
-#include "log.h"
+#include "gui/widgets/layout.h"
+#include "gui/widgets/resizegrip.h"
+#include "gui/widgets/windowcontainer.h"
#include "resources/image.h"