summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2007-09-19 17:28:33 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2007-09-19 17:28:33 +0000
commit1a9320fafb23940d0463e6f384713d0f99fc0c61 (patch)
treed152680dbdc8febf0b5a445ba760255068d72f04 /src/gui
parent2f027ebcf8f0ad78f7edf58af7dda94d89034c85 (diff)
downloadmana-1a9320fafb23940d0463e6f384713d0f99fc0c61.tar.gz
mana-1a9320fafb23940d0463e6f384713d0f99fc0c61.tar.bz2
mana-1a9320fafb23940d0463e6f384713d0f99fc0c61.tar.xz
mana-1a9320fafb23940d0463e6f384713d0f99fc0c61.zip
Merged 0.0 changes from revision 3362 to 3580 to trunk.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/button.cpp20
-rw-r--r--src/gui/button.h10
-rw-r--r--src/gui/buy.cpp125
-rw-r--r--src/gui/buy.h10
-rw-r--r--src/gui/char_select.cpp12
-rw-r--r--src/gui/char_select.h31
-rw-r--r--src/gui/chat.cpp10
-rw-r--r--src/gui/debugwindow.cpp14
-rw-r--r--src/gui/debugwindow.h9
-rw-r--r--src/gui/equipmentwindow.cpp1
-rw-r--r--src/gui/gui.cpp45
-rw-r--r--src/gui/gui.h43
-rw-r--r--src/gui/inventorywindow.cpp13
-rw-r--r--src/gui/inventorywindow.h11
-rw-r--r--src/gui/itemcontainer.cpp4
-rw-r--r--src/gui/itemshortcutcontainer.cpp224
-rw-r--r--src/gui/itemshortcutcontainer.h115
-rw-r--r--src/gui/itemshortcutwindow.cpp74
-rw-r--r--src/gui/itemshortcutwindow.h69
-rw-r--r--src/gui/menuwindow.cpp12
-rw-r--r--src/gui/popupmenu.cpp6
-rw-r--r--src/gui/selectionlistener.h16
-rw-r--r--src/gui/sell.cpp127
-rw-r--r--src/gui/sell.h16
-rw-r--r--src/gui/setup.cpp10
-rw-r--r--src/gui/setup_keyboard.cpp187
-rw-r--r--src/gui/setup_keyboard.h84
-rw-r--r--src/gui/shoplistbox.cpp20
-rw-r--r--src/gui/skill.cpp6
-rw-r--r--src/gui/skill.h1
-rw-r--r--src/gui/status.cpp6
-rw-r--r--src/gui/status.h3
-rw-r--r--src/gui/updatewindow.cpp4
-rw-r--r--src/gui/viewport.cpp25
-rw-r--r--src/gui/viewport.h13
-rw-r--r--src/gui/window.cpp198
-rw-r--r--src/gui/window.h99
-rw-r--r--src/gui/windowlistener.h86
38 files changed, 1426 insertions, 333 deletions
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
index 4e236c33..0379ebc0 100644
--- a/src/gui/button.cpp
+++ b/src/gui/button.cpp
@@ -60,11 +60,26 @@ static ButtonData const data[BUTTON_COUNT] = {
ImageRect Button::button[BUTTON_COUNT];
+Button::Button():
+ mIsLogged(false)
+{
+ init();
+}
+
Button::Button(const std::string& caption, const std::string &actionEventId,
gcn::ActionListener *listener):
gcn::Button(caption),
mIsLogged(false)
{
+ init();
+ setActionEventId(actionEventId);
+ if (listener) {
+ addActionListener(listener);
+ }
+}
+
+void Button::init()
+{
setBorderSize(0);
if (mInstances == 0)
@@ -91,12 +106,7 @@ Button::Button(const std::string& caption, const std::string &actionEventId,
btn[mode]->decRef();
}
}
-
mInstances++;
- setActionEventId(actionEventId);
- if (listener) {
- addActionListener(listener);
- }
}
Button::~Button()
diff --git a/src/gui/button.h b/src/gui/button.h
index eb73e311..d12173b2 100644
--- a/src/gui/button.h
+++ b/src/gui/button.h
@@ -38,7 +38,13 @@ class ImageRect;
class Button : public gcn::Button {
public:
/**
- * Constructor, sets the caption of the button to the given string.
+ * Default constructor.
+ */
+ Button();
+
+ /**
+ * Constructor, sets the caption of the button to the given string and
+ * adds the given action listener.
*/
Button(const std::string& caption, const std::string &actionEventId,
gcn::ActionListener *listener);
@@ -60,6 +66,8 @@ class Button : public gcn::Button {
{ mIsLogged = enable; }
private:
+ void init();
+
static ImageRect button[4]; /**< Button state graphics */
static int mInstances; /**< Number of button instances */
bool mIsLogged; /**< Makes the button appear pressed all the time */
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 6cfe5e18..bbf2102e 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -28,6 +28,7 @@
#include "button.h"
#include "scrollarea.h"
#include "shop.h"
+#include "shoplistbox.h"
#include "slider.h"
#include "../npc.h"
@@ -35,11 +36,15 @@
#include "../resources/itemdb.h"
#include "../utils/tostring.h"
-
BuyDialog::BuyDialog():
Window("Buy"),
mMoney(0), mAmountItems(0), mMaxItems(0)
{
+ setResizable(true);
+ setMinWidth(260);
+ setMinHeight(230);
+ setDefaultSize(0, 0, 260, 230);
+
mShopItems = new ShopItems;
mShopItemList = new ShopListBox(mShopItems, mShopItems);
@@ -54,32 +59,15 @@ BuyDialog::BuyDialog():
mItemDescLabel = new gcn::Label("Description:");
mItemEffectLabel = new gcn::Label("Effect:");
- setContentSize(260, 210);
- mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mScrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110));
- mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
-
- mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10));
- mSlider->setEnabled(false);
-
- mQuantityLabel->setPosition(215, 120);
- mMoneyLabel->setPosition(5, 130);
-
- mIncreaseButton->setPosition(40, 186);
mIncreaseButton->setSize(20, 20);
- mIncreaseButton->setEnabled(false);
-
- mDecreaseButton->setPosition(10, 186);
mDecreaseButton->setSize(20, 20);
- mDecreaseButton->setEnabled(false);
+ mQuantityLabel->setWidth(60);
- mBuyButton->setPosition(180, 186);
+ mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mIncreaseButton->setEnabled(false);
+ mDecreaseButton->setEnabled(false);
mBuyButton->setEnabled(false);
-
- mQuitButton->setPosition(212, 186);
-
- mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14));
- mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14));
+ mSlider->setEnabled(false);
mShopItemList->setActionEventId("item");
mSlider->setActionEventId("slider");
@@ -98,6 +86,8 @@ BuyDialog::BuyDialog():
add(mItemDescLabel);
add(mItemEffectLabel);
+ addWindowListener(this);
+ loadWindowState("Buy");
setLocationRelativeTo(getParent());
}
@@ -118,13 +108,12 @@ void BuyDialog::reset()
{
mShopItems->clear();
mShopItemList->adjustSize();
- mMoney = 0;
- mSlider->setValue(0.0);
- // Reset Previous Selected Items to prevent failing asserts
+ // Reset previous selected items to prevent failing asserts
mShopItemList->setSelected(-1);
+ mSlider->setValue(0);
- updateButtonsAndLabels();
+ setMoney(0);
}
void BuyDialog::addItem(int id, int amount, int price)
@@ -141,6 +130,7 @@ void BuyDialog::action(const gcn::ActionEvent &event)
{
setVisible(false);
current_npc = 0;
+ return;
}
// The following actions require a valid selection
@@ -152,21 +142,19 @@ void BuyDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "slider")
{
- mAmountItems = (int)(mSlider->getValue() * mMaxItems);
+ mAmountItems = (int) mSlider->getValue();
updateButtonsAndLabels();
}
else if (event.getId() == "+" && mAmountItems < mMaxItems)
{
mAmountItems++;
-
- mSlider->setValue((double) mAmountItems / (double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
- else if (event.getId() == "-" && mAmountItems > 0)
+ else if (event.getId() == "-" && mAmountItems > 1)
{
mAmountItems--;
-
- mSlider->setValue((double) mAmountItems / (double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
// TODO: Actually we'd have a bug elsewhere if this check for the number
@@ -178,25 +166,69 @@ void BuyDialog::action(const gcn::ActionEvent &event)
Net::GameServer::Player::tradeWithNPC
(mShopItems->at(selectedItem).id, mAmountItems);
- // Update money and adjust the max number of items that can be bought
- mMoney -= mAmountItems * mShopItems->at(selectedItem).price;
- mMaxItems -= mAmountItems;
-
// Reset selection
- mAmountItems = 0;
- mSlider->setValue(0.0);
+ mAmountItems = 1;
+ mSlider->setValue(1);
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
- updateButtonsAndLabels();
+ // Update money and adjust the max number of items that can be bought
+ mMaxItems -= mAmountItems;
+ setMoney(mMoney - mAmountItems * mShopItems->at(selectedItem).price);
}
}
void BuyDialog::selectionChanged(const SelectionEvent &event)
{
+
// Reset amount of items and update labels
- mAmountItems = 0;
- mSlider->setValue(0.0);
+ mAmountItems = 1;
+ mSlider->setValue(1);
updateButtonsAndLabels();
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
+}
+
+void BuyDialog::windowResized(const WindowEvent &event)
+{
+ gcn::Rectangle area = getChildrenArea();
+ int width = area.width;
+ int height = area.height;
+
+ mDecreaseButton->setPosition(8, height - 8 - mDecreaseButton->getHeight());
+ mIncreaseButton->setPosition(
+ mDecreaseButton->getX() + mDecreaseButton->getWidth() + 5,
+ mDecreaseButton->getY());
+
+ mQuitButton->setPosition(
+ width - 8 - mQuitButton->getWidth(),
+ height - 8 - mQuitButton->getHeight());
+ mBuyButton->setPosition(
+ mQuitButton->getX() - 5 - mBuyButton->getWidth(),
+ mQuitButton->getY());
+
+ mItemDescLabel->setDimension(gcn::Rectangle(8,
+ mBuyButton->getY() - 5 - mItemDescLabel->getHeight(),
+ width - 16,
+ mItemDescLabel->getHeight()));
+ mItemEffectLabel->setDimension(gcn::Rectangle(8,
+ mItemDescLabel->getY() - 5 - mItemEffectLabel->getHeight(),
+ width - 16,
+ mItemEffectLabel->getHeight()));
+ mMoneyLabel->setDimension(gcn::Rectangle(8,
+ mItemEffectLabel->getY() - 5 - mMoneyLabel->getHeight(),
+ width - 16,
+ mMoneyLabel->getHeight()));
+
+ mQuantityLabel->setPosition(
+ width - mQuantityLabel->getWidth() - 8,
+ mMoneyLabel->getY() - 5 - mQuantityLabel->getHeight());
+ mSlider->setDimension(gcn::Rectangle(8,
+ mQuantityLabel->getY(),
+ mQuantityLabel->getX() - 8 - 8,
+ 10));
+
+ mScrollArea->setDimension(gcn::Rectangle(8, 8, width - 16,
+ mSlider->getY() - 5 - 8));
}
void
@@ -232,14 +264,13 @@ BuyDialog::updateButtonsAndLabels()
// Enable or disable buttons and slider
mIncreaseButton->setEnabled(mAmountItems < mMaxItems);
- mDecreaseButton->setEnabled(mAmountItems > 0);
+ mDecreaseButton->setEnabled(mAmountItems > 1);
mBuyButton->setEnabled(mAmountItems > 0);
- mSlider->setEnabled(mMaxItems > 0);
+ mSlider->setEnabled(mMaxItems > 1);
// Update quantity and money labels
- mQuantityLabel->setCaption(toString(mAmountItems));
- mQuantityLabel->adjustSize();
+ mQuantityLabel->setCaption(
+ toString(mAmountItems) + " / " + toString(mMaxItems));
mMoneyLabel->setCaption("Price: " + toString(price) + " GP / "
+ toString(mMoney - price) + " GP" );
- mMoneyLabel->adjustSize();
}
diff --git a/src/gui/buy.h b/src/gui/buy.h
index 875deef9..63d25583 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -28,11 +28,11 @@
#include "window.h"
#include "selectionlistener.h"
-#include "shoplistbox.h"
#include "../guichanfwd.h"
class ShopItems;
+class ShopListBox;
class ListBox;
/**
@@ -40,7 +40,8 @@ class ListBox;
*
* \ingroup Interface
*/
-class BuyDialog : public Window, public gcn::ActionListener, SelectionListener
+class BuyDialog : public Window, public gcn::ActionListener, SelectionListener,
+ WindowListener
{
public:
/**
@@ -98,6 +99,11 @@ class BuyDialog : public Window, public gcn::ActionListener, SelectionListener
void
updateButtonsAndLabels();
+ /**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
+
private:
gcn::Button *mBuyButton;
gcn::Button *mQuitButton;
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index d752cdb3..e8381bef 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -48,6 +48,7 @@
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
#include "../utils/tostring.h"
+#include "../utils/trim.h"
// Defined in main.cpp, used here for setting the char create dialog
extern CharServerHandler charServerHandler;
@@ -255,11 +256,6 @@ bool CharSelectDialog::selectByName(const std::string &name)
return false;
}
-std::string CharSelectDialog::getName()
-{
- return mNameLabel->getCaption();
-}
-
CharCreateDialog::CharCreateDialog(Window *parent, int slot):
Window(_("Create Character"), true, parent), mSlot(slot)
{
@@ -410,10 +406,12 @@ CharCreateDialog::action(const gcn::ActionEvent &event)
}
}
-const std::string&
+std::string
CharCreateDialog::getName()
{
- return mNameField->getText();
+ std::string name = mNameField->getText();
+ trim(name);
+ return name;
}
void CharCreateDialog::UpdateSliders()
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 9d9184ea..5d0b42fa 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -60,11 +60,6 @@ class CharSelectDialog : public Window, public gcn::ActionListener
bool selectByName(const std::string &name);
- /**
- * Returns name of selected player
- */
- std::string getName();
-
private:
LockedArray<LocalPlayer*> *mCharInfo;
@@ -114,22 +109,28 @@ class CharCreateDialog : public Window, public gcn::ActionListener
*/
~CharCreateDialog();
- void
- action(const gcn::ActionEvent &event);
-
- const std::string&
- getName();
+ void action(const gcn::ActionEvent &event);
/**
* Unlocks the dialog, enabling the create character button again.
*/
- void
- unlock();
+ void unlock();
private:
int getDistributedPoints();
+
void UpdateSliders();
+ /**
+ * Returns the name of the character to create.
+ */
+ std::string getName();
+
+ /**
+ * Communicate character creation to the server.
+ */
+ void attemptCharCreate();
+
gcn::TextField *mNameField;
gcn::Label *mNameLabel;
gcn::Button *mNextHairColorButton;
@@ -154,12 +155,6 @@ class CharCreateDialog : public Window, public gcn::ActionListener
static const int mMaxPoints = 70;
int mUsedPoints;
-
-
- /**
- * Communicate character creation to the server.
- */
- void attemptCharCreate();
};
#endif
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index ba7c7f02..4ed8bb97 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -44,6 +44,7 @@
#include "../net/gameserver/player.h"
#include "../utils/dtor.h"
+#include "../utils/trim.h"
ChatWindow::ChatWindow():
Window(),
@@ -125,7 +126,7 @@ void
ChatWindow::chatLog(std::string line, int own, std::string channelName)
{
// Delete overhead from the end of the list
- while ((int)mChatlog.size() > mItemsKeep) {
+ while ((int) mChatlog.size() > mItemsKeep) {
mChatlog.pop_back();
}
@@ -142,12 +143,15 @@ ChatWindow::chatLog(std::string line, int own, std::string channelName)
own = BY_SERVER;
}
- int pos = line.find(" : ");
- if (pos > 0) {
+ std::string::size_type pos = line.find(" : ");
+ if (pos != std::string::npos) {
tmp.nick = line.substr(0, pos);
line.erase(0, pos + 3);
}
+ // Trim whitespace
+ trim(line);
+
std::string lineColor = "##0"; // Equiv. to BrowserBox::BLACK
switch (own) {
case BY_GM:
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 11ad37c2..884cdf7e 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -42,6 +42,7 @@ DebugWindow::DebugWindow():
Window("Debug")
{
setResizable(true);
+ setCloseButton(true);
setDefaultSize(0, 0, 400, 100);
loadWindowState("Debug");
@@ -60,15 +61,11 @@ DebugWindow::DebugWindow():
mParticleCountLabel = new gcn::Label("[Particle count: 0]");
mParticleCountLabel->setPosition(100, 60);
- Button *closeButton = new Button("Close", "close", this);
- closeButton->setPosition(5, 60);
-
add(mFPSLabel);
add(mMusicFileLabel);
add(mMapFileLabel);
add(mTileMouseLabel);
add(mParticleCountLabel);
- add(closeButton);
}
void
@@ -106,12 +103,3 @@ DebugWindow::logic()
+"]");
mParticleCountLabel->adjustSize();
}
-
-void
-DebugWindow::action(const gcn::ActionEvent &event)
-{
- if (event.getId() == "close")
- {
- setVisible(false);
- }
-}
diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h
index d082b2ca..9b6f2017 100644
--- a/src/gui/debugwindow.h
+++ b/src/gui/debugwindow.h
@@ -33,11 +33,11 @@
#include "../guichanfwd.h"
/**
- * The chat window.
+ * The debug window.
*
* \ingroup Interface
*/
-class DebugWindow : public Window, public gcn::ActionListener
+class DebugWindow : public Window
{
public:
/**
@@ -50,11 +50,6 @@ class DebugWindow : public Window, public gcn::ActionListener
*/
void logic();
- /**
- * Performs action.
- */
- void action(const gcn::ActionEvent &event);
-
private:
gcn::Label *mMusicFileLabel, *mMapFileLabel;
gcn::Label *mTileMouseLabel, *mFPSLabel;
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 5e835985..c86a27fc 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -59,6 +59,7 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
mBackground(NULL),
mSelected(-1)
{
+ setCloseButton(true);
setDefaultSize(5, 195, 216, 260);
loadWindowState("Equipment");
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index dc51054c..97dd4d44 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -42,7 +42,7 @@
#include "../graphics.h"
#include "../log.h"
-#include "../resources/image.h"
+#include "../resources/imageset.h"
#include "../resources/resourcemanager.h"
#include "../resources/imageloader.h"
@@ -77,8 +77,9 @@ class GuiConfigListener : public ConfigListener
};
Gui::Gui(Graphics *graphics):
- mMouseCursor(NULL),
- mCustomCursor(false)
+ mCustomCursor(false),
+ mMouseCursors(NULL),
+ mCursorType(CURSOR_POINTER)
{
logger->log("Initializing GUI...");
// Set graphics
@@ -106,7 +107,7 @@ Gui::Gui(Graphics *graphics):
// Set global font
try {
- mGuiFont = new TrueTypeFont("data/fonts/dejavusans.ttf", 12);
+ mGuiFont = new TrueTypeFont("data/fonts/dejavusans.ttf", 11);
}
catch (gcn::Exception e)
{
@@ -139,7 +140,7 @@ Gui::Gui(Graphics *graphics):
hitBlueFont = new gcn::ImageFont("graphics/gui/hits_blue.png",
"0123456789");
hitYellowFont = new gcn::ImageFont("graphics/gui/hits_yellow.png",
- "mis");
+ "0123456789misxp ");
}
catch (gcn::Exception e)
{
@@ -169,8 +170,8 @@ Gui::~Gui()
delete hitBlueFont;
delete hitYellowFont;
- if (mMouseCursor) {
- mMouseCursor->decRef();
+ if (mMouseCursors) {
+ mMouseCursors->decRef();
}
delete mGuiFont;
@@ -182,12 +183,6 @@ Gui::~Gui()
}
void
-Gui::logic()
-{
- gcn::Gui::logic();
-}
-
-void
Gui::draw()
{
mGraphics->pushClipArea(mTop->getDimension());
@@ -196,11 +191,13 @@ Gui::draw()
int mouseX, mouseY;
Uint8 button = SDL_GetMouseState(&mouseX, &mouseY);
- if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1))
- && mCustomCursor)
+ if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1)) &&
+ mCustomCursor)
{
- static_cast<Graphics*>(mGraphics)->
- drawImage(mMouseCursor, mouseX - 5, mouseY - 2);
+ static_cast<Graphics*>(mGraphics)->drawImage(
+ mMouseCursors->get(mCursorType),
+ mouseX - 15,
+ mouseY - 17);
}
mGraphics->popClipArea();
@@ -220,9 +217,11 @@ Gui::setUseCustomCursor(bool customCursor)
// Load the mouse cursor
ResourceManager *resman = ResourceManager::getInstance();
- mMouseCursor = resman->getImage("graphics/gui/mouse.png");
- if (!mMouseCursor) {
- logger->error("Unable to load mouse cursor.");
+ mMouseCursors =
+ resman->getImageSet("graphics/gui/mouse.png", 40, 40);
+
+ if (!mMouseCursors) {
+ logger->error("Unable to load mouse cursors.");
}
}
else
@@ -231,9 +230,9 @@ Gui::setUseCustomCursor(bool customCursor)
SDL_ShowCursor(SDL_ENABLE);
// Unload the mouse cursor
- if (mMouseCursor) {
- mMouseCursor->decRef();
- mMouseCursor = NULL;
+ if (mMouseCursors) {
+ mMouseCursors->decRef();
+ mMouseCursors = NULL;
}
}
}
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 5f2cc810..1e4b9348 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -30,7 +30,7 @@
class GuiConfigListener;
class Graphics;
-class Image;
+class ImageSet;
class Viewport;
/**
@@ -60,35 +60,48 @@ class Gui : public gcn::Gui
~Gui();
/**
- * Works around Guichan bug
- */
- void
- logic();
-
- /**
* Draws the whole Gui by calling draw functions down in the
* Gui hierarchy. It also draws the mouse pointer.
*/
- void
- draw();
+ void draw();
/**
- * Return game font
+ * Return game font.
*/
- gcn::Font*
- getFont() { return mGuiFont; }
+ gcn::Font* getFont() const
+ { return mGuiFont; }
/**
* Sets whether a custom cursor should be rendered.
*/
- void
- setUseCustomCursor(bool customCursor);
+ void setUseCustomCursor(bool customCursor);
+
+ /**
+ * Sets which cursor should be used.
+ */
+ void setCursorType(int index)
+ { mCursorType = index; }
+
+ /**
+ * Cursors are in graphic order from left to right.
+ * CURSOR_POINTER should be left untouched.
+ * CURSOR_TOTAL should always be last.
+ */
+ enum {
+ CURSOR_POINTER = 0,
+ CURSOR_RESIZE_ACROSS,
+ CURSOR_RESIZE_DOWN,
+ CURSOR_RESIZE_DOWN_LEFT,
+ CURSOR_RESIZE_DOWN_RIGHT,
+ CURSOR_TOTAL
+ };
private:
GuiConfigListener *mConfigListener;
gcn::Font *mGuiFont; /**< The global GUI font */
- Image *mMouseCursor; /**< Mouse cursor image */
bool mCustomCursor; /**< Show custom cursor */
+ ImageSet *mMouseCursors; /**< Mouse cursor images */
+ int mCursorType;
};
extern Gui *gui; /**< The GUI system */
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 085ab188..1e62b130 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -51,6 +51,7 @@ InventoryWindow::InventoryWindow():
mSplit(false)
{
setResizable(true);
+ setCloseButton(true);
setMinWidth(240);
setMinHeight(172);
// If you adjust these defaults, don't forget to adjust the trade window's.
@@ -69,7 +70,6 @@ InventoryWindow::InventoryWindow():
mItems->addSelectionListener(this);
mInvenScroll = new ScrollArea(mItems);
- mInvenScroll->setPosition(8, 8);
mItemNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
mItemDescriptionLabel = new gcn::Label(
@@ -100,8 +100,8 @@ InventoryWindow::InventoryWindow():
mSplitButton->setWidth(48);
}
+ addWindowListener(this);
loadWindowState("Inventory");
- updateContentSize();
}
InventoryWindow::~InventoryWindow()
@@ -130,7 +130,6 @@ void InventoryWindow::logic()
mWeightLabel->setCaption(
strprintf(_("Total Weight: %d - Maximum Weight: %d"),
player_node->getTotalWeight(), player_node->getMaxWeight()));
- mWeightLabel->adjustSize();
}
void InventoryWindow::action(const gcn::ActionEvent &event)
@@ -215,7 +214,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
}
}
-void InventoryWindow::updateContentSize()
+void InventoryWindow::windowResized(const WindowEvent &event)
{
const gcn::Rectangle area = getChildrenArea();
@@ -260,8 +259,7 @@ Item* InventoryWindow::getItem()
return mItems->getItem();
}
-void
-InventoryWindow::keyPressed(gcn::KeyEvent &event)
+void InventoryWindow::keyPressed(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
{
@@ -271,8 +269,7 @@ InventoryWindow::keyPressed(gcn::KeyEvent &event)
}
}
-void
-InventoryWindow::keyReleased(gcn::KeyEvent &event)
+void InventoryWindow::keyReleased(gcn::KeyEvent &event)
{
switch (event.getKey().getValue())
{
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 37ef0406..a9fdadf2 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -29,8 +29,9 @@
#include <guichan/widgets/checkbox.hpp>
-#include "window.h"
#include "selectionlistener.h"
+#include "window.h"
+#include "windowlistener.h"
#include "../guichanfwd.h"
@@ -45,7 +46,8 @@ class ItemContainer;
class InventoryWindow : public Window,
public gcn::ActionListener,
public gcn::KeyListener,
- public SelectionListener
+ public SelectionListener,
+ public WindowListener
{
public:
/**
@@ -92,7 +94,10 @@ class InventoryWindow : public Window,
*/
void selectionChanged(const SelectionEvent &event);
- void updateContentSize(); /**< Updates widgets size/position. */
+ /**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
private:
void updateButtons(); /**< Updates button states. */
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index b032bd49..bddf7cee 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -30,6 +30,7 @@
#include "../graphics.h"
#include "../inventory.h"
#include "../item.h"
+#include "../itemshortcut.h"
#include "../localplayer.h"
#include "../resources/image.h"
@@ -38,6 +39,9 @@
#include "../utils/tostring.h"
+// TODO: Add support for adding items to the item shortcut window (global
+// itemShortcut).
+
static const int BOX_WIDTH = 36;
static const int BOX_HEIGHT = 44;
diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp
new file mode 100644
index 00000000..1943ef93
--- /dev/null
+++ b/src/gui/itemshortcutcontainer.cpp
@@ -0,0 +1,224 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "itemshortcutcontainer.h"
+
+#include "../graphics.h"
+#include "../item.h"
+#include "../itemshortcut.h"
+#include "../keyboardconfig.h"
+
+#include "../resources/image.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/tostring.h"
+
+ItemShortcutContainer::ItemShortcutContainer():
+ mGridWidth(1),
+ mGridHeight(1),
+ mItemClicked(false),
+ mItemMoved(NULL)
+{
+ addMouseListener(this);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
+ mMaxItems = itemShortcut->getItemCount();
+
+ mBoxHeight = 42;
+ mBoxWidth = 36;
+}
+
+ItemShortcutContainer::~ItemShortcutContainer()
+{
+ mBackgroundImg->decRef();
+}
+
+void
+ItemShortcutContainer::logic()
+{
+ gcn::Widget::logic();
+
+ int i = itemShortcut->getItemCount();
+
+ if (i != mMaxItems)
+ {
+ mMaxItems = i;
+ setWidth(getWidth());
+ }
+}
+
+void
+ItemShortcutContainer::draw(gcn::Graphics *graphics)
+{
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ 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_0+i));
+ g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT);
+
+ Item *item = itemShortcut->getItem(i);
+ if (item) {
+ // Draw item icon.
+ Image* image = item->getInfo().getImage();
+ if (image) {
+ g->drawImage(image, itemX, itemY);
+ g->drawText(
+ toString(item->getQuantity()),
+ itemX + mBoxWidth / 2,
+ itemY + mBoxHeight - 14,
+ gcn::Graphics::CENTER);
+ }
+ }
+ }
+ if (mItemMoved)
+ {
+ // Draw the item image being dragged by the cursor.
+ Image* image = mItemMoved->getInfo().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::setWidth(int width)
+{
+ gcn::Widget::setWidth(width);
+
+ mGridWidth = getWidth() / mBoxWidth;
+ if (mGridWidth < 1) {
+ mGridWidth = 1;
+ }
+
+ setHeight((mMaxItems / mGridWidth +
+ (mMaxItems % mGridWidth > 0 ? 1 : 0)) * mBoxHeight);
+
+ mGridHeight = getHeight() / mBoxHeight;
+ if (mGridHeight < 1) {
+ mGridHeight = 1;
+ }
+}
+
+void
+ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT) {
+ if (!mItemMoved && mItemClicked) {
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ return;
+ }
+ Item *item = itemShortcut->getItem(index);
+ 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;
+ }
+
+ // Stores the selected item if theirs one.
+ if (itemShortcut->isItemSelected()) {
+ itemShortcut->setItem(index);
+ itemShortcut->setItemSelected(NULL);
+ }
+ else if (itemShortcut->getItem(index)) {
+ mItemClicked = true;
+ }
+}
+
+void
+ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+{
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (itemShortcut->isItemSelected())
+ {
+ itemShortcut->setItemSelected(NULL);
+ }
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ if (index == -1) {
+ mItemMoved = NULL;
+ return;
+ }
+ if (mItemMoved) {
+ itemShortcut->setItems(index, mItemMoved);
+ mItemMoved = NULL;
+ }
+ else if (itemShortcut->getItem(index) && mItemClicked)
+ {
+ itemShortcut->useItem(index);
+ }
+ if (mItemClicked) {
+ mItemClicked = false;
+ }
+ }
+}
+
+int
+ItemShortcutContainer::getIndexFromGrid(int pointX, int pointY) const
+{
+ const gcn::Rectangle tRect = gcn::Rectangle(
+ 0, 0, mGridWidth * mBoxWidth, mGridHeight * mBoxHeight);
+ if (!tRect.isPointInRect(pointX, pointY)) {
+ return -1;
+ }
+ const int index = ((pointY / mBoxHeight) * mGridWidth) +
+ pointX / mBoxWidth;
+ if (index >= mMaxItems)
+ {
+ return -1;
+ }
+ return index;
+}
diff --git a/src/gui/itemshortcutcontainer.h b/src/gui/itemshortcutcontainer.h
new file mode 100644
index 00000000..4b154cbb
--- /dev/null
+++ b/src/gui/itemshortcutcontainer.h
@@ -0,0 +1,115 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _TMW_ITEMSHORTCUTCONTAINER_H__
+#define _TMW_ITEMSHORTCUTCONTAINER_H__
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+
+#include <list>
+
+class Image;
+class Item;
+
+/**
+ * An item shortcut container. Used to quickly use items.
+ *
+ * \ingroup GUI
+ */
+class ItemShortcutContainer : public gcn::Widget, public gcn::MouseListener
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ ItemShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~ItemShortcutContainer();
+
+ /**
+ * Handles the logic of the ItemContainer
+ */
+ void logic();
+
+ /**
+ * Draws the items.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Sets the width of the container. This is used to determine the new
+ * height of the container.
+ */
+ void setWidth(int width);
+
+ /**
+ * 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);
+
+
+ int getMaxItems()
+ { return mMaxItems; }
+
+ int getBoxWidth()
+ { return mBoxWidth; }
+
+ int getBoxHeight()
+ { return mBoxHeight; }
+
+ private:
+ /**
+ * 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;
+
+ int mMaxItems;
+ int mBoxWidth;
+ int mBoxHeight;
+ int mCursorPosX, mCursorPosY;
+ int mGridWidth, mGridHeight;
+ bool mItemClicked;
+ Item *mItemMoved;
+
+};
+
+#endif
diff --git a/src/gui/itemshortcutwindow.cpp b/src/gui/itemshortcutwindow.cpp
new file mode 100644
index 00000000..dd97a7db
--- /dev/null
+++ b/src/gui/itemshortcutwindow.cpp
@@ -0,0 +1,74 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "itemshortcutwindow.h"
+
+#include "itemshortcutcontainer.h"
+#include "scrollarea.h"
+
+static const int SCROLL_PADDING = 0;
+
+ItemShortcutWindow::ItemShortcutWindow()
+{
+ // no title presented, title bar is padding so window can be moved.
+ gcn::Window::setTitleBarHeight(gcn::Window::getPadding());
+ setShowTitle(false);
+ setResizable(true);
+ setDefaultSize(758, 174, 42, 426);
+
+ mItems = new ItemShortcutContainer();
+
+ int border = SCROLL_PADDING * 2 + getPadding() * 2;
+ setMinWidth(mItems->getBoxWidth() + border);
+ setMinHeight(mItems->getBoxHeight() + border);
+ setMaxWidth(mItems->getBoxWidth() * mItems->getMaxItems() + border);
+ setMaxHeight(mItems->getBoxHeight() * mItems->getMaxItems() + border);
+
+ mInvenScroll = new ScrollArea(mItems);
+ mInvenScroll->setPosition(SCROLL_PADDING, SCROLL_PADDING);
+ mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ add(mInvenScroll);
+
+ addWindowListener(this);
+ loadWindowState("ItemShortcut");
+}
+
+ItemShortcutWindow::~ItemShortcutWindow()
+{
+ delete mItems;
+ delete mInvenScroll;
+}
+
+void ItemShortcutWindow::logic()
+{
+ Window::logic();
+}
+
+void ItemShortcutWindow::windowResized(const WindowEvent &event)
+{
+ const gcn::Rectangle area = getChildrenArea();
+
+ mInvenScroll->setSize(
+ area.width - SCROLL_PADDING,
+ area.height - SCROLL_PADDING);
+}
diff --git a/src/gui/itemshortcutwindow.h b/src/gui/itemshortcutwindow.h
new file mode 100644
index 00000000..83bc348d
--- /dev/null
+++ b/src/gui/itemshortcutwindow.h
@@ -0,0 +1,69 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _TMW_ITEMSHORTCUTWINDOW_H
+#define _TMW_ITEMSHORTCUTWINDOW_H
+
+#include "window.h"
+#include "windowlistener.h"
+
+#include "../guichanfwd.h"
+
+class ItemShortcutContainer;
+
+/**
+ * Inventory dialog.
+ *
+ * \ingroup Interface
+ */
+class ItemShortcutWindow : public Window, WindowListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ItemShortcutWindow();
+
+ /**
+ * Destructor.
+ */
+ ~ItemShortcutWindow();
+
+ /**
+ * Logic (updates buttons and weight information).
+ */
+ void logic();
+
+ /**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
+
+ private:
+ ItemShortcutContainer *mItems;
+
+ gcn::ScrollArea *mInvenScroll;
+};
+
+extern ItemShortcutWindow *itemShortcutWindow;
+
+#endif
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index bfa2f1f2..8d4d184d 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -37,6 +37,7 @@ extern Window *inventoryWindow;
extern Window *equipmentWindow;
extern Window *skillDialog;
extern Window *statusWindow;
+extern Window *itemShortcutWindow;
namespace {
struct MenuWindowListener : public gcn::ActionListener
@@ -62,6 +63,7 @@ MenuWindow::MenuWindow():
N_("Equipment"),
N_("Inventory"),
N_("Skills"),
+ N_("Shortcut"),
N_("Setup"),
0
};
@@ -109,14 +111,20 @@ void MenuWindowListener::action(const gcn::ActionEvent &event)
{
window = skillDialog;
}
+ else if (event.getId() == "Shortcut")
+ {
+ window = itemShortcutWindow;
+ }
else if (event.getId() == "Setup")
{
window = setupWindow;
}
- if (window) {
+ if (window)
+ {
window->setVisible(!window->isVisible());
- if (window->isVisible()) {
+ if (window->isVisible())
+ {
window->requestMoveToTop();
}
}
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index 48bbd3d0..aeb6637d 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -200,12 +200,6 @@ void PopupMenu::handleLink(const std::string& link)
setVisible(false);
- /*
- * This is need cause of a bug in guichan that leave
- * the focus on the popup menu even if is not visible.
- */
- _getFocusHandler()->focusNone();
-
mBeing = NULL;
mFloorItem = NULL;
mItem = NULL;
diff --git a/src/gui/selectionlistener.h b/src/gui/selectionlistener.h
index b39672b5..917a4871 100644
--- a/src/gui/selectionlistener.h
+++ b/src/gui/selectionlistener.h
@@ -25,33 +25,23 @@
#define _TMW_SELECTIONLISTENER_H__
#include <guichan/widget.hpp>
+#include <guichan/event.hpp>
/**
* An event that characterizes a change in the current selection.
*
* \ingroup GUI
*/
-class SelectionEvent
+class SelectionEvent : public gcn::Event
{
public:
/**
* Constructor.
*/
SelectionEvent(gcn::Widget *source):
- mSource(source)
+ gcn::Event(source)
{
}
-
- /**
- * The widget from which the event originated.
- */
- gcn::Widget* getSource() const
- {
- return mSource;
- }
-
- private:
- gcn::Widget *mSource;
};
/**
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index b601d70c..5f1011c1 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -44,58 +44,44 @@ SellDialog::SellDialog():
Window("Sell"),
mMaxItems(0), mAmountItems(0)
{
+ setResizable(true);
+ setMinWidth(260);
+ setMinHeight(230);
+ setDefaultSize(0, 0, 260, 230);
+
mShopItems = new ShopItems();
mShopItemList = new ShopListBox(mShopItems, mShopItems);
- ScrollArea *scrollArea = new ScrollArea(mShopItemList);
+ mScrollArea = new ScrollArea(mShopItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
mMoneyLabel = new gcn::Label("Money: 0 GP / Total: 0 GP");
- mItemDescLabel = new gcn::Label("Description:");
- mItemEffectLabel = new gcn::Label("Effect:");
mIncreaseButton = new Button("+", "+", this);
mDecreaseButton = new Button("-", "-", this);
mSellButton = new Button("Sell", "sell", this);
- Button *quitButton = new Button("Quit", "quit", this);
- mSellButton->setEnabled(false);
-
- setContentSize(260, 210);
- scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setDimension(gcn::Rectangle(5, 5, 250, 110));
- mShopItemList->setDimension(gcn::Rectangle(5, 5, 238, 110));
-
- mSlider->setDimension(gcn::Rectangle(5, 120, 200, 10));
- mSlider->setEnabled(false);
-
- mQuantityLabel->setPosition(215, 120);
+ mQuitButton = new Button("Quit", "quit", this);
+ mItemDescLabel = new gcn::Label("Description:");
+ mItemEffectLabel = new gcn::Label("Effect:");
- mIncreaseButton->setPosition(40, 186);
mIncreaseButton->setSize(20, 20);
- mIncreaseButton->setEnabled(false);
-
- mDecreaseButton->setPosition(10, 186);
mDecreaseButton->setSize(20, 20);
- mDecreaseButton->setEnabled(false);
+ mQuantityLabel->setWidth(60);
- mMoneyLabel->setPosition(5, 130);
- mItemEffectLabel->setDimension(gcn::Rectangle(5, 150, 240, 14));
- mItemDescLabel->setDimension(gcn::Rectangle(5, 169, 240, 14));
-
- mSellButton->setPosition(175, 186);
+ mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mIncreaseButton->setEnabled(false);
+ mDecreaseButton->setEnabled(false);
mSellButton->setEnabled(false);
+ mSlider->setEnabled(false);
- quitButton->setPosition(208, 186);
-
+ mShopItemList->setPriceCheck(false);
mShopItemList->setActionEventId("item");
mSlider->setActionEventId("slider");
- mShopItemList->setPriceCheck(false);
-
mShopItemList->addActionListener(this);
mShopItemList->addSelectionListener(this);
mSlider->addActionListener(this);
- add(scrollArea);
+ add(mScrollArea);
add(mSlider);
add(mQuantityLabel);
add(mMoneyLabel);
@@ -104,8 +90,10 @@ SellDialog::SellDialog():
add(mIncreaseButton);
add(mDecreaseButton);
add(mSellButton);
- add(quitButton);
+ add(mQuitButton);
+ addWindowListener(this);
+ loadWindowState("Sell");
setLocationRelativeTo(getParent());
}
@@ -117,7 +105,7 @@ SellDialog::~SellDialog()
void SellDialog::reset()
{
mShopItems->clear();
- mSlider->setValue(0.0);
+ mSlider->setValue(0);
// Reset previous selected item to prevent failing asserts
mShopItemList->setSelected(-1);
@@ -135,16 +123,11 @@ void SellDialog::action(const gcn::ActionEvent &event)
{
int selectedItem = mShopItemList->getSelected();
- if (event.getId() == "item")
- {
- mAmountItems = 0;
- mSlider->setValue(0);
- updateButtonsAndLabels();
- }
- else if (event.getId() == "quit")
+ if (event.getId() == "quit")
{
setVisible(false);
current_npc = 0;
+ return;
}
// The following actions require a valid item selection
@@ -156,21 +139,19 @@ void SellDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "slider")
{
- mAmountItems = (int) (mSlider->getValue() * mMaxItems);
+ mAmountItems = (int) mSlider->getValue();
updateButtonsAndLabels();
}
else if (event.getId() == "+" && mAmountItems < mMaxItems)
{
mAmountItems++;
-
- mSlider->setValue((double) mAmountItems /(double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
- else if (event.getId() == "-" && mAmountItems > 0)
+ else if (event.getId() == "-" && mAmountItems > 1)
{
mAmountItems--;
-
- mSlider->setValue((double) mAmountItems / (double) mMaxItems);
+ mSlider->setValue(mAmountItems);
updateButtonsAndLabels();
}
else if (event.getId() == "sell" && mAmountItems > 0
@@ -182,8 +163,7 @@ void SellDialog::action(const gcn::ActionEvent &event)
mMaxItems -= mAmountItems;
mShopItems->getShop()->at(selectedItem).quantity = mMaxItems;
mPlayerMoney += (mAmountItems * mShopItems->at(selectedItem).price);
- mAmountItems = 0;
- mSlider->setValue(0);
+ mAmountItems = 1;
if (!mMaxItems)
{
@@ -194,6 +174,7 @@ void SellDialog::action(const gcn::ActionEvent &event)
}
else
{
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
// Update only when there are items left, the entry doesn't exist
// otherwise and can't be updated
updateButtonsAndLabels();
@@ -204,10 +185,54 @@ void SellDialog::action(const gcn::ActionEvent &event)
void SellDialog::selectionChanged(const SelectionEvent &event)
{
// Reset amount of items and update labels
- mAmountItems = 0;
+ mAmountItems = 1;
mSlider->setValue(0);
updateButtonsAndLabels();
+ mSlider->gcn::Slider::setScale(1, mMaxItems);
+}
+
+void SellDialog::windowResized(const WindowEvent &event)
+{
+ gcn::Rectangle area = getChildrenArea();
+ int width = area.width;
+ int height = area.height;
+
+ mDecreaseButton->setPosition(8, height - 8 - mDecreaseButton->getHeight());
+ mIncreaseButton->setPosition(
+ mDecreaseButton->getX() + mDecreaseButton->getWidth() + 5,
+ mDecreaseButton->getY());
+
+ mQuitButton->setPosition(
+ width - 8 - mQuitButton->getWidth(),
+ height - 8 - mQuitButton->getHeight());
+ mSellButton->setPosition(
+ mQuitButton->getX() - 5 - mSellButton->getWidth(),
+ mQuitButton->getY());
+
+ mItemDescLabel->setDimension(gcn::Rectangle(8,
+ mSellButton->getY() - 5 - mItemDescLabel->getHeight(),
+ width - 16,
+ mItemDescLabel->getHeight()));
+ mItemEffectLabel->setDimension(gcn::Rectangle(8,
+ mItemDescLabel->getY() - 5 - mItemEffectLabel->getHeight(),
+ width - 16,
+ mItemEffectLabel->getHeight()));
+ mMoneyLabel->setDimension(gcn::Rectangle(8,
+ mItemEffectLabel->getY() - 5 - mMoneyLabel->getHeight(),
+ width - 16,
+ mMoneyLabel->getHeight()));
+
+ mQuantityLabel->setPosition(
+ width - mQuantityLabel->getWidth() - 8,
+ mMoneyLabel->getY() - 5 - mQuantityLabel->getHeight());
+ mSlider->setDimension(gcn::Rectangle(8,
+ mQuantityLabel->getY(),
+ mQuantityLabel->getX() - 8 - 8,
+ 10));
+
+ mScrollArea->setDimension(gcn::Rectangle(8, 8, width - 16,
+ mSlider->getY() - 5 - 8));
}
void SellDialog::setMoney(int amount)
@@ -246,15 +271,13 @@ SellDialog::updateButtonsAndLabels()
// Update Buttons and slider
mSellButton->setEnabled(mAmountItems > 0);
- mDecreaseButton->setEnabled(mAmountItems > 0);
+ mDecreaseButton->setEnabled(mAmountItems > 1);
mIncreaseButton->setEnabled(mAmountItems < mMaxItems);
- mSlider->setEnabled(selectedItem > -1);
+ mSlider->setEnabled(mMaxItems > 1);
// Update the quantity and money labels
mQuantityLabel->setCaption(
toString(mAmountItems) + " / " + toString(mMaxItems));
- mQuantityLabel->adjustSize();
mMoneyLabel->setCaption("Money: " + toString(income) + " GP / Total: "
+ toString(mPlayerMoney + income) + " GP");
- mMoneyLabel->adjustSize();
}
diff --git a/src/gui/sell.h b/src/gui/sell.h
index fc42fd1c..d1e2ddd2 100644
--- a/src/gui/sell.h
+++ b/src/gui/sell.h
@@ -28,6 +28,7 @@
#include "window.h"
#include "selectionlistener.h"
+#include "windowlistener.h"
#include "../guichanfwd.h"
@@ -40,7 +41,8 @@ class ShopListBox;
*
* \ingroup Interface
*/
-class SellDialog : public Window, gcn::ActionListener, SelectionListener
+class SellDialog : public Window, gcn::ActionListener, SelectionListener,
+ WindowListener
{
public:
/**
@@ -78,21 +80,27 @@ class SellDialog : public Window, gcn::ActionListener, SelectionListener
void selectionChanged(const SelectionEvent &event);
/**
+ * Called whenever the window is resized.
+ */
+ void windowResized(const WindowEvent &event);
+
+ /**
* Gives Player's Money amount
*/
void setMoney(int amount);
+ private:
/**
* Updates the state of buttons and labels.
*/
- void
- updateButtonsAndLabels();
+ void updateButtonsAndLabels();
- private:
gcn::Button *mSellButton;
+ gcn::Button *mQuitButton;
gcn::Button *mIncreaseButton;
gcn::Button *mDecreaseButton;
ShopListBox *mShopItemList;
+ gcn::ScrollArea *mScrollArea;
gcn::Label *mMoneyLabel;
gcn::Label *mItemDescLabel;
gcn::Label *mItemEffectLabel;
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index 3ea19059..6a13232a 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -27,6 +27,7 @@
#include "setup_audio.h"
#include "setup_joystick.h"
#include "setup_video.h"
+#include "setup_keyboard.h"
#include "tabbedcontainer.h"
#include "../utils/dtor.h"
@@ -43,7 +44,8 @@ extern Window *skillDialog;
Setup::Setup():
Window(_("Setup"))
{
- int width = 230;
+ setCloseButton(true);
+ int width = 250;
int height = 245;
setContentSize(width, height);
@@ -59,7 +61,7 @@ Setup::Setup():
}
TabbedContainer *panel = new TabbedContainer();
- panel->setDimension(gcn::Rectangle(5, 5, 220, 205));
+ panel->setDimension(gcn::Rectangle(5, 5, 250, 205));
panel->setOpaque(false);
SetupTab *tab;
@@ -76,6 +78,10 @@ Setup::Setup():
panel->addTab(tab, _("Joystick"));
mTabs.push_back(tab);
+ tab = new Setup_Keyboard();
+ panel->addTab(tab, "Keyboard");
+ mTabs.push_back(tab);
+
add(panel);
setLocationRelativeTo(getParent());
diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp
new file mode 100644
index 00000000..e88080b5
--- /dev/null
+++ b/src/gui/setup_keyboard.cpp
@@ -0,0 +1,187 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "setup_keyboard.h"
+
+#include <guichan/widgets/label.hpp>
+#include <guichan/listmodel.hpp>
+
+#include "button.h"
+#include "listbox.h"
+#include "ok_dialog.h"
+#include "scrollarea.h"
+
+#include "../configuration.h"
+#include "../keyboardconfig.h"
+
+#include "../utils/tostring.h"
+
+#include <SDL_keyboard.h>
+
+/**
+ * The list model for key function list.
+ *
+ * \ingroup Interface
+ */
+class KeyListModel : public gcn::ListModel
+{
+ public:
+ /**
+ * Returns the number of elements in container.
+ */
+ int getNumberOfElements() { return keyboard.KEY_TOTAL; }
+
+ /**
+ * Returns element from container.
+ */
+ std::string getElementAt(int i) { return mKeyFunctions[i]; }
+
+ /**
+ * Sets element from container.
+ */
+ void setElementAt(int i, std::string caption)
+ {
+ mKeyFunctions[i] = caption;
+ }
+
+ private:
+ std::string mKeyFunctions[KeyboardConfig::KEY_TOTAL];
+};
+
+Setup_Keyboard::Setup_Keyboard():
+ mKeyListModel(new KeyListModel()),
+ mKeyList(new ListBox(mKeyListModel)),
+ mKeySetting(false)
+{
+ keyboard.setSetupKeyboard(this);
+ setOpaque(false);
+
+ refreshKeys();
+
+ mKeyList->setDimension(gcn::Rectangle(0, 0, 185, 140));
+ mKeyList->addActionListener(this);
+ mKeyList->setSelected(-1);
+
+ ScrollArea *scrollArea = new ScrollArea(mKeyList);
+ scrollArea->setDimension(gcn::Rectangle(10, 10, 200, 140));
+ add(scrollArea);
+
+ mAssignKeyButton = new Button("Assign", "assign", this);
+ mAssignKeyButton->setPosition(165, 155);
+ mAssignKeyButton->addActionListener(this);
+ mAssignKeyButton->setEnabled(false);
+ add(mAssignKeyButton);
+
+ mMakeDefaultButton = new Button("Default", "makeDefault", this);
+ mMakeDefaultButton->setPosition(10, 155);
+ mMakeDefaultButton->addActionListener(this);
+ add(mMakeDefaultButton);
+}
+
+Setup_Keyboard::~Setup_Keyboard()
+{
+ delete mKeyList;
+ delete mKeyListModel;
+
+ delete mAssignKeyButton;
+ delete mMakeDefaultButton;
+}
+
+void Setup_Keyboard::apply()
+{
+ keyUnresolved();
+
+ if (keyboard.hasConflicts())
+ {
+ new OkDialog("Key Conflict(s) Detected.",
+ "Resolve them, or gameplay may result in strange behaviour.");
+ }
+ keyboard.setEnabled(true);
+ keyboard.store();
+}
+
+void Setup_Keyboard::cancel()
+{
+ keyUnresolved();
+
+ keyboard.retrieve();
+ keyboard.setEnabled(true);
+
+ refreshKeys();
+}
+
+void Setup_Keyboard::action(const gcn::ActionEvent &event)
+{
+ if (event.getSource() == mKeyList)
+ {
+ if (!mKeySetting) {
+ mAssignKeyButton->setEnabled(true);
+ }
+ }
+ else if (event.getId() == "assign")
+ {
+ mKeySetting = true;
+ mAssignKeyButton->setEnabled(false);
+ keyboard.setEnabled(false);
+ int i(mKeyList->getSelected());
+ keyboard.setNewKeyIndex(i);
+ mKeyListModel->setElementAt(i, keyboard.getKeyCaption(i) + ": ?");
+ }
+ else if (event.getId() == "makeDefault")
+ {
+ keyboard.makeDefault();
+ refreshKeys();
+ }
+}
+
+void Setup_Keyboard::refreshAssignedKey(int index)
+{
+ std::string caption;
+ char *temp = SDL_GetKeyName(
+ (SDLKey) keyboard.getKeyValue(index));
+ caption = keyboard.getKeyCaption(index) + ": " + toString(temp);
+ mKeyListModel->setElementAt(index, caption);
+}
+
+void Setup_Keyboard::newKeyCallback(int index)
+{
+ mKeySetting = false;
+ refreshAssignedKey(index);
+ mAssignKeyButton->setEnabled(true);
+}
+
+void Setup_Keyboard::refreshKeys()
+{
+ for(int i = 0; i < keyboard.KEY_TOTAL; i++)
+ {
+ refreshAssignedKey(i);
+ }
+}
+
+void Setup_Keyboard::keyUnresolved()
+{
+ if (mKeySetting) {
+ newKeyCallback(keyboard.getNewKeyIndex());
+ keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
+ }
+}
diff --git a/src/gui/setup_keyboard.h b/src/gui/setup_keyboard.h
new file mode 100644
index 00000000..b72e8746
--- /dev/null
+++ b/src/gui/setup_keyboard.h
@@ -0,0 +1,84 @@
+/*
+ * The Mana World
+ * Copyright 2007 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_GUI_SETUP_KEYBOARD_H
+#define _TMW_GUI_SETUP_KEYBOARD_H
+
+#include "setuptab.h"
+#include "button.h"
+#include "../guichanfwd.h"
+
+#include <guichan/actionlistener.hpp>
+
+
+#include <string>
+
+class Setup_Keyboard : public SetupTab, public gcn::ActionListener
+{
+ public:
+ /**
+ * Constructor
+ */
+ Setup_Keyboard();
+
+ /**
+ * Destructor
+ */
+ ~Setup_Keyboard();
+
+ void apply();
+ void cancel();
+
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Get an update on the assigned key.
+ */
+ void refreshAssignedKey(int index);
+
+ /**
+ * The callback function when a new key has been pressed.
+ */
+ void newKeyCallback(int index);
+
+ /**
+ * Shorthand method to update all the keys.
+ */
+ void refreshKeys();
+
+ /**
+ * If a key function is unresolved, then this reverts it.
+ */
+ void keyUnresolved();
+
+ private:
+ class KeyListModel *mKeyListModel;
+ gcn::ListBox *mKeyList;
+
+ gcn::Button *mAssignKeyButton;
+ gcn::Button *mMakeDefaultButton;
+
+ bool mKeySetting; /**< flag to check if key being set. */
+};
+
+#endif
diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp
index 0e2ea6d3..ae787ab7 100644
--- a/src/gui/shoplistbox.cpp
+++ b/src/gui/shoplistbox.cpp
@@ -129,24 +129,8 @@ void ShopListBox::mousePressed(gcn::MouseEvent &event)
{
if (event.getButton() == gcn::MouseEvent::LEFT)
{
- bool enoughMoney = false;
- int y = event.getY();
-
- if (mShopItems && mPriceCheck)
- {
- if (mPlayerMoney >= mShopItems->at(y / mRowHeight).price)
- enoughMoney = true;
- }
- else // Old Behaviour
- {
- enoughMoney = true;
- }
-
- if (enoughMoney)
- {
- setSelected(y / mRowHeight);
- generateAction();
- }
+ setSelected(event.getY() / mRowHeight);
+ generateAction();
}
}
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index 884b3744..d5cfe76a 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -63,22 +63,18 @@ const char *skill_db[] = {
SkillDialog::SkillDialog():
Window("Skills")
{
+ setCloseButton(true);
setDefaultSize(windowContainer->getWidth() - 255, 25, 240, 240);
mSkillListBox = new ListBox(this);
ScrollArea *skillScrollArea = new ScrollArea(mSkillListBox);
- mCloseButton = new Button("Close", "close", this);
mSkillListBox->setActionEventId("skill");
skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180));
- mCloseButton->setPosition(
- skillScrollArea->getX() + skillScrollArea->getWidth() - mCloseButton->getWidth(),
- 210);
add(skillScrollArea);
- add(mCloseButton);
mSkillListBox->addActionListener(this);
diff --git a/src/gui/skill.h b/src/gui/skill.h
index b8794e35..f1a14d50 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -71,7 +71,6 @@ class SkillDialog : public Window, public gcn::ActionListener,
private:
gcn::ListBox *mSkillListBox;
- gcn::Button *mCloseButton;
std::vector<SKILL*> mSkillList;
};
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index 7da3b905..323a6b16 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -39,6 +39,7 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mPlayer(player)
{
setResizable(true);
+ setCloseButton(true);
setDefaultSize((windowContainer->getWidth() - 365) / 2,
(windowContainer->getHeight() - 255) / 2, 365, 280);
loadWindowState("Status");
@@ -219,7 +220,7 @@ void StatusWindow::update()
mHpBar->setColor(0, 171, 34); // Green
}
- mHpBar->setProgress((float)hp / maxHp);
+ mHpBar->setProgress((float) hp / maxHp);
// Stats Part
// ----------
@@ -235,7 +236,8 @@ void StatusWindow::update()
int statusPoints = mPlayer->getAttributeIncreasePoints();
// Update labels
- for (int i = 0; i < 7; i++) {
+ for (int i = 0; i < 7; i++)
+ {
mStatsLabel[i]->setCaption(attrNames[i]);
mStatsDisplayLabel[i]->setCaption(
strprintf("%d / %d",
diff --git a/src/gui/status.h b/src/gui/status.h
index 40d25a2a..62cd8805 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -41,7 +41,8 @@ class ProgressBar;
*
* \ingroup Interface
*/
-class StatusWindow : public Window, public gcn::ActionListener {
+class StatusWindow : public Window, public gcn::ActionListener
+{
public:
/**
* Constructor.
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index ed75e5b3..5d81bb9c 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -46,6 +46,8 @@
#include "../resources/resourcemanager.h"
+extern std::string homeDir;
+
/**
* Calculates the Alder-32 checksum for the given file.
*/
@@ -119,7 +121,7 @@ UpdaterWindow::UpdaterWindow():
mUpdateHost =
config.getValue("updatehost", "http://updates.themanaworld.org");
- mBasePath = config.getValue("homeDir", ".");
+ mBasePath = homeDir;
// Try to download the updates list
download();
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 2af1d960..4c6b04a2 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -55,8 +55,7 @@ Viewport::Viewport():
mCameraX(0),
mCameraY(0),
mShowDebugPath(false),
- mPlayerFollowMouse(false),
- mPopupActive(false)
+ mPlayerFollowMouse(false)
{
setOpaque(false);
addMouseListener(this);
@@ -372,21 +371,20 @@ Viewport::mousePressed(gcn::MouseEvent &event)
if ((being = beingManager->findBeing(tilex, tiley)) &&
being->getType() != Being::LOCALPLAYER)
{
- showPopup(event.getX(), event.getY(), being);
+ mPopupMenu->showPopup(event.getX(), event.getY(), being);
return;
}
else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley)))
{
- showPopup(event.getX(), event.getY(), floorItem);
+ mPopupMenu->showPopup(event.getX(), event.getY(), floorItem);
return;
}
}
// If a popup is active, just remove it
- if (mPopupActive)
+ if (mPopupMenu->isVisible())
{
mPopupMenu->setVisible(false);
- mPopupActive = false;
return;
}
@@ -450,21 +448,6 @@ void
Viewport::showPopup(int x, int y, Item *item)
{
mPopupMenu->showPopup(x, y, item);
- mPopupActive = true;
-}
-
-void
-Viewport::showPopup(int x, int y, FloorItem *floorItem)
-{
- mPopupMenu->showPopup(x, y, floorItem);
- mPopupActive = true;
-}
-
-void
-Viewport::showPopup(int x, int y, Being *being)
-{
- mPopupMenu->showPopup(x, y, being);
- mPopupActive = true;
}
void
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index 22d0f249..eeb31bae 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -130,18 +130,6 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
private:
/**
- * Shows a popup for a floor item.
- * TODO Find some way to get rid of FloorItem here
- */
- void showPopup(int x, int y, FloorItem *floorItem);
-
- /**
- * Shows a popup for a being.
- * TODO Find some way to get rid of Being here
- */
- void showPopup(int x, int y, Being *being);
-
- /**
* Helper function for loading target cursors
*/
void
@@ -187,7 +175,6 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
int mWalkTime;
PopupMenu *mPopupMenu; /**< Popup menu. */
- bool mPopupActive;
};
#endif
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 84f4466c..17447009 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -26,6 +26,7 @@
#include <guichan/exception.hpp>
#include <guichan/widgets/icon.hpp>
+#include "gui.h"
#include "gccontainer.h"
#include "windowcontainer.h"
@@ -42,7 +43,9 @@
ConfigListener *Window::windowConfigListener = 0;
WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
+int Window::mouseResize = 0;
ImageRect Window::border;
+Image *Window::closeImage = NULL;
class WindowConfigListener : public ConfigListener
{
@@ -60,7 +63,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
mParent(parent),
mModal(modal),
mResizable(false),
- mMouseResize(0),
+ mCloseButton(false),
mSticky(false),
mMinWinWidth(100),
mMinWinHeight(40),
@@ -88,6 +91,8 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
border.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
border.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
dBorders->decRef();
+ closeImage = resman->getImage("graphics/gui/close_button.png");
+
windowConfigListener = new WindowConfigListener();
// Send GUI alpha changed for initialization
windowConfigListener->optionChanged("guialpha");
@@ -110,6 +115,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
if (mModal)
{
+ gui->setCursorType(Gui::CURSOR_POINTER);
requestModalFocus();
}
@@ -153,6 +159,7 @@ Window::~Window()
delete border.grid[6];
delete border.grid[7];
delete border.grid[8];
+ closeImage->decRef();
}
delete mChrome;
@@ -173,11 +180,19 @@ void Window::draw(gcn::Graphics *graphics)
// Draw title
if (getTitleBarHeight())
{
- graphics->setColor(gcn::Color(0, 0, 0));
- graphics->setFont(getFont());
- graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
+ g->setColor(gcn::Color(0, 0, 0));
+ g->setFont(getFont());
+ g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
}
+ // Draw Close Button
+ if (mCloseButton)
+ {
+ g->drawImage(closeImage,
+ getWidth() - closeImage->getWidth() - getPadding(),
+ getPadding()
+ );
+ }
drawChildren(graphics);
}
@@ -207,6 +222,8 @@ void Window::setWidth(int width)
{
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
}
void Window::setHeight(int height)
@@ -217,6 +234,8 @@ void Window::setHeight(int height)
{
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
}
void Window::setDimension(const gcn::Rectangle &dimension)
@@ -228,6 +247,27 @@ void Window::setDimension(const gcn::Rectangle &dimension)
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setPosition(int x, int y)
+{
+ gcn::Window::setPosition(x, y);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setX(int x)
+{
+ gcn::Window::setX(x);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setY(int y)
+{
+ gcn::Window::setY(y);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
}
void Window::setLocationRelativeTo(gcn::Widget *widget)
@@ -280,6 +320,11 @@ void Window::setResizable(bool r)
}
}
+void Window::setCloseButton(bool flag)
+{
+ mCloseButton = flag;
+}
+
bool Window::isResizable()
{
return mResizable;
@@ -327,27 +372,73 @@ void Window::mousePressed(gcn::MouseEvent &event)
// Let Guichan move window to top and figure out title bar drag
gcn::Window::mousePressed(event);
- const int x = event.getX();
- const int y = event.getY();
- mMouseResize = 0;
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ const int x = event.getX();
+ const int y = event.getY();
+
+ // Handle close button
+ if (mCloseButton)
+ {
+ gcn::Rectangle closeButtonRect(
+ getWidth() - closeImage->getWidth() - getPadding(),
+ getPadding(),
+ closeImage->getWidth(),
+ closeImage->getHeight());
+
+ if (closeButtonRect.isPointInRect(x, y))
+ {
+ setVisible(false);
+ }
+ }
+
+ // Handle window resizing
+ mouseResize = getResizeHandles(event);
+ }
+}
+
+void Window::mouseReleased(gcn::MouseEvent &event)
+{
+ if (mResizable && mouseResize)
+ {
+ mouseResize = 0;
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ }
+
+ // This should be the responsibility of Guichan (and is from 0.8.0 on)
+ mIsMoving = false;
+}
- // Activate resizing handles as appropriate
- if (event.getSource() == this && isResizable() &&
- event.getButton() == gcn::MouseEvent::LEFT &&
- !getChildrenArea().isPointInRect(x, y))
+void Window::mouseExited(gcn::MouseEvent &event)
+{
+ if (mResizable && !mouseResize)
{
- mMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
- (x < resizeBorderWidth) ? LEFT : 0;
- mMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
- (y < resizeBorderWidth) ? TOP : 0;
+ gui->setCursorType(Gui::CURSOR_POINTER);
}
- else if (event.getSource() == mGrip &&
- event.getButton() == gcn::MouseEvent::LEFT)
+}
+
+void Window::mouseMoved(gcn::MouseEvent &event)
+{
+ int resizeHandles = getResizeHandles(event);
+
+ // Changes the custom mouse cursor based on it's current position.
+ switch (resizeHandles)
{
- mDragOffsetX = x;
- mDragOffsetY = y;
- mMouseResize |= BOTTOM | RIGHT;
- mIsMoving = false;
+ case BOTTOM | RIGHT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_RIGHT);
+ break;
+ case BOTTOM | LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_LEFT);
+ break;
+ case BOTTOM:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN);
+ break;
+ case RIGHT:
+ case LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_ACROSS);
+ break;
+ default:
+ gui->setCursorType(Gui::CURSOR_POINTER);
}
}
@@ -366,31 +457,31 @@ void Window::mouseDragged(gcn::MouseEvent &event)
setPosition(newX, newY);
}
- if (mMouseResize && !mIsMoving)
+ if (mouseResize && !mIsMoving)
{
const int dx = event.getX() - mDragOffsetX;
const int dy = event.getY() - mDragOffsetY;
gcn::Rectangle newDim = getDimension();
- if (mMouseResize & (TOP | BOTTOM))
+ if (mouseResize & (TOP | BOTTOM))
{
- int newHeight = newDim.height + ((mMouseResize & TOP) ? -dy : dy);
+ int newHeight = newDim.height + ((mouseResize & TOP) ? -dy : dy);
newDim.height = std::min(mMaxWinHeight,
std::max(mMinWinHeight, newHeight));
- if (mMouseResize & TOP)
+ if (mouseResize & TOP)
{
newDim.y -= newDim.height - getHeight();
}
}
- if (mMouseResize & (LEFT | RIGHT))
+ if (mouseResize & (LEFT | RIGHT))
{
- int newWidth = newDim.width + ((mMouseResize & LEFT) ? -dx : dx);
+ int newWidth = newDim.width + ((mouseResize & LEFT) ? -dx : dx);
newDim.width = std::min(mMaxWinWidth,
std::max(mMinWinWidth, newWidth));
- if (mMouseResize & LEFT)
+ if (mouseResize & LEFT)
{
newDim.x -= newDim.width - getWidth();
}
@@ -417,11 +508,11 @@ void Window::mouseDragged(gcn::MouseEvent &event)
}
// Update mouse offset when dragging bottom or right border
- if (mMouseResize & BOTTOM)
+ if (mouseResize & BOTTOM)
{
mDragOffsetY += newDim.height - getHeight();
}
- if (mMouseResize & RIGHT)
+ if (mouseResize & RIGHT)
{
mDragOffsetX += newDim.width - getWidth();
}
@@ -469,3 +560,50 @@ void Window::resetToDefaultSize()
setContentSize(mDefaultWidth, mDefaultHeight);
updateContentSize();
}
+
+int Window::getResizeHandles(gcn::MouseEvent &event)
+{
+ int resizeHandles = 0;
+ const int y = event.getY();
+
+ if (mResizable && y > (int) mTitleBarHeight)
+ {
+ const int x = event.getX();
+
+ if (!getChildrenArea().isPointInRect(x, y) &&
+ event.getSource() == this)
+ {
+ resizeHandles |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
+ (x < resizeBorderWidth) ? LEFT : 0;
+ resizeHandles |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
+ (y < resizeBorderWidth) ? TOP : 0;
+ }
+
+ if (event.getSource() == mGrip)
+ {
+ mDragOffsetX = x;
+ mDragOffsetY = y;
+ resizeHandles |= BOTTOM | RIGHT;
+ }
+ }
+
+ return resizeHandles;
+}
+
+void Window::fireWindowEvent(const WindowEvent &event)
+{
+ WindowListeners::iterator i_end = mListeners.end();
+ WindowListeners::iterator i = mListeners.begin();
+
+ switch (event.getType())
+ {
+ case WindowEvent::WINDOW_MOVED:
+ for (; i != i_end; ++i)
+ { (*i)->windowMoved(event); }
+ break;
+ case WindowEvent::WINDOW_RESIZED:
+ for (; i != i_end; ++i)
+ { (*i)->windowResized(event); }
+ break;
+ }
+}
diff --git a/src/gui/window.h b/src/gui/window.h
index 1ba23fb2..ab266422 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -28,11 +28,14 @@
#include "../guichanfwd.h"
+#include "windowlistener.h"
+
class ConfigListener;
class GCContainer;
class ImageRect;
class ResizeGrip;
class WindowContainer;
+class Image;
/**
* A window. This window can be dragged around and has a title bar. Windows are
@@ -120,16 +123,36 @@ class Window : public gcn::Window
void setDimension(const gcn::Rectangle &dimension);
/**
+ * Sets the position of this window.
+ */
+ void setPosition(int x, int y);
+
+ /**
+ * Sets the window x coordinate.
+ */
+ void setX(int x);
+
+ /**
+ * Sets the window y coordinate.
+ */
+ void setY(int y);
+
+ /**
* Sets the location relative to the given widget.
*/
void setLocationRelativeTo(gcn::Widget *widget);
/**
- * Sets whether of not the window can be resized.
+ * Sets whether or not the window can be resized.
*/
void setResizable(bool resize);
/**
+ * Sets whether or not the window has a close button.
+ */
+ void setCloseButton(bool flag);
+
+ /**
* Returns whether the window can be resized.
*/
bool isResizable();
@@ -155,9 +178,14 @@ class Window : public gcn::Window
void setMaxHeight(unsigned int height);
/**
- * Sets whether the window is sticky.
- * A sticky window will not have its visibility set to false
- * on a general setVisible(false) call.
+ * Sets flag to show a title or not.
+ */
+ void setShowTitle(bool flag)
+ { mShowTitle = flag; }
+
+ /**
+ * Sets whether the window is sticky. A sticky window will not have
+ * its visibility set to false on a general setVisible(false) call.
*/
void setSticky(bool sticky);
@@ -167,10 +195,9 @@ class Window : public gcn::Window
bool isSticky();
/**
- * Overloads window setVisible by guichan to allow sticky window
- * Handling
+ * Overloads window setVisible by Guichan to allow sticky window
+ * handling.
*/
-
void setVisible(bool visible);
/**
@@ -199,6 +226,24 @@ class Window : public gcn::Window
void mouseDragged(gcn::MouseEvent &event);
/**
+ * Implements custom cursor image changing context, based on mouse
+ * relative position.
+ */
+ void mouseMoved(gcn::MouseEvent &event);
+
+ /**
+ * When the mouse button has been let go, this ensures that the mouse
+ * custom cursor is restored back to it's standard image.
+ */
+ void mouseReleased(gcn::MouseEvent &event);
+
+ /**
+ * When the mouse leaves the window this ensures that the custom cursor
+ * is restored back to it's standard image.
+ */
+ void mouseExited(gcn::MouseEvent &event);
+
+ /**
* Read the x, y, and width and height for resizables in the config
* based on the given string.
* That function let the values set with set{X, Y, Height, width}()
@@ -216,11 +261,25 @@ class Window : public gcn::Window
int defaultWidth, int defaultHeight);
/**
- * Reset the win pos and size to default.
- * Don't forget to set defaults first.
+ * Reset the win pos and size to default. Don't forget to set defaults
+ * first.
*/
void resetToDefaultSize();
+ /**
+ * Adds a listener to the list that's notified when the window is
+ * moved or resized.
+ */
+ void addWindowListener(WindowListener *listener)
+ { mListeners.push_back(listener); }
+
+ /**
+ * Removes a listener from the list that's notified when the window is
+ * moved or resized.
+ */
+ void removeWindowListener(WindowListener *listener)
+ { mListeners.remove(listener); }
+
enum ResizeHandles
{
TOP = 0x01,
@@ -233,13 +292,23 @@ class Window : public gcn::Window
static WindowContainer *windowContainer;
private:
+ /**
+ * Determines if the mouse is in a resize area and returns appropriate
+ * resize handles. Also initializes drag offset in case the resize
+ * grip is used.
+ *
+ * @see ResizeHandles
+ */
+ int getResizeHandles(gcn::MouseEvent &event);
+
GCContainer *mChrome; /**< Contained container */
ResizeGrip *mGrip; /**< Resize grip */
Window *mParent; /**< The parent window */
std::string mConfigName; /**< Name used for saving window-related data */
+ bool mShowTitle; /**< Window has a title bar */
bool mModal; /**< Window is modal */
bool mResizable; /**< Window can be resized */
- int mMouseResize; /**< Window is being resized */
+ bool mCloseButton; /**< Window has a close button */
bool mSticky; /**< Window resists minimization */
int mMinWinWidth; /**< Minimum window width */
int mMinWinHeight; /**< Minimum window height */
@@ -255,8 +324,10 @@ class Window : public gcn::Window
*/
static ConfigListener *windowConfigListener;
+ static int mouseResize; /**< Active resize handles */
static int instances; /**< Number of Window instances */
static ImageRect border; /**< The window border and background */
+ static Image *closeImage; /**< Close Button Image */
/**
* The width of the resize border. Is independent of the actual window
@@ -264,6 +335,14 @@ class Window : public gcn::Window
* where two borders are moved at the same time.
*/
static const int resizeBorderWidth = 10;
+
+ private:
+ /**
+ * Sends out a window event to the list of selection listeners.
+ */
+ void fireWindowEvent(const WindowEvent &event);
+
+ WindowListeners mListeners;
};
#endif
diff --git a/src/gui/windowlistener.h b/src/gui/windowlistener.h
new file mode 100644
index 00000000..08aab71d
--- /dev/null
+++ b/src/gui/windowlistener.h
@@ -0,0 +1,86 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_WINDOW_LISTENER_H_
+#define _TMW_WINDOW_LISTENER_H_
+
+#include <guichan/widgets/window.hpp>
+#include <guichan/event.hpp>
+
+/**
+ * An event that characterizes a window move or resize.
+ *
+ * \ingroup GUI
+ */
+class WindowEvent : public gcn::Event
+{
+ public:
+ /**
+ * Constructor.
+ */
+ WindowEvent(gcn::Window *source, int type):
+ gcn::Event(source)
+ {
+ mType = type;
+ }
+
+ /**
+ * Returns the event type.
+ */
+ int getType() const
+ { return mType; }
+
+ enum WindowEventType
+ {
+ WINDOW_MOVED,
+ WINDOW_RESIZED
+ };
+};
+
+/**
+ * The listener that's notified when a window is moved or resized.
+ *
+ * \ingroup GUI
+ */
+class WindowListener
+{
+ public:
+ /**
+ * Virtual destructor.
+ */
+ virtual ~WindowListener() {}
+
+ /**
+ * Called whenever the window is moved.
+ */
+ virtual void windowMoved(const WindowEvent &event) {}
+
+ /**
+ * Called whenever the window is resized.
+ */
+ virtual void windowResized(const WindowEvent &event) {}
+};
+
+typedef std::list<WindowListener*> WindowListeners;
+
+#endif