summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2009-01-30 01:34:16 +0100
committerBjørn Lindeijer <bjorn@lindeijer.nl>2009-02-09 20:00:07 +0100
commit1b1050da1c7b84cc72b7efbb2229294975be9e10 (patch)
tree68d15ccb015d58aeb5797ffd06efca3e55997c24 /src/gui
parent0d4142a891cd228da24ee3aa3bbd7dc622da5b75 (diff)
parent955a7613d1fe116fe5e1da07a222b6849b3c885c (diff)
downloadmana-client-1b1050da1c7b84cc72b7efbb2229294975be9e10.tar.gz
mana-client-1b1050da1c7b84cc72b7efbb2229294975be9e10.tar.bz2
mana-client-1b1050da1c7b84cc72b7efbb2229294975be9e10.tar.xz
mana-client-1b1050da1c7b84cc72b7efbb2229294975be9e10.zip
Merged with Aethyra master as of 2009-01-27
Conflicts: Almost everywhere.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/browserbox.cpp86
-rw-r--r--src/gui/browserbox.h1
-rw-r--r--src/gui/buddywindow.cpp83
-rw-r--r--src/gui/button.cpp3
-rw-r--r--src/gui/button.h2
-rw-r--r--src/gui/buttonbox.cpp43
-rw-r--r--src/gui/buttonbox.h69
-rw-r--r--src/gui/buy.cpp5
-rw-r--r--src/gui/buy.h6
-rw-r--r--src/gui/buysell.cpp3
-rw-r--r--src/gui/buysell.h2
-rw-r--r--src/gui/char_select.cpp195
-rw-r--r--src/gui/char_select.h9
-rw-r--r--src/gui/char_server.cpp13
-rw-r--r--src/gui/chat.cpp533
-rw-r--r--src/gui/chat.h61
-rw-r--r--src/gui/chatinput.h4
-rw-r--r--src/gui/checkbox.h2
-rw-r--r--src/gui/colour.cpp139
-rw-r--r--src/gui/colour.h133
-rw-r--r--src/gui/confirm_dialog.cpp56
-rw-r--r--src/gui/confirm_dialog.h11
-rw-r--r--src/gui/connection.cpp3
-rw-r--r--src/gui/debugwindow.cpp3
-rw-r--r--src/gui/emotecontainer.cpp172
-rw-r--r--src/gui/emotecontainer.h138
-rw-r--r--src/gui/emoteshortcutcontainer.cpp195
-rw-r--r--src/gui/emoteshortcutcontainer.h81
-rw-r--r--src/gui/emotewindow.cpp82
-rw-r--r--src/gui/emotewindow.h68
-rw-r--r--src/gui/equipmentwindow.cpp144
-rw-r--r--src/gui/equipmentwindow.h43
-rw-r--r--src/gui/focushandler.cpp1
-rw-r--r--src/gui/gccontainer.h2
-rw-r--r--src/gui/gui.cpp27
-rw-r--r--src/gui/gui.h7
-rw-r--r--src/gui/help.cpp15
-rw-r--r--src/gui/help.h2
-rw-r--r--src/gui/inttextfield.cpp1
-rw-r--r--src/gui/inttextfield.h5
-rw-r--r--src/gui/inventorywindow.cpp210
-rw-r--r--src/gui/inventorywindow.h35
-rw-r--r--src/gui/item_amount.cpp3
-rw-r--r--src/gui/itemcontainer.cpp76
-rw-r--r--src/gui/itemcontainer.h32
-rw-r--r--src/gui/itemlinkhandler.cpp63
-rw-r--r--src/gui/itemlinkhandler.h40
-rw-r--r--src/gui/itempopup.cpp176
-rw-r--r--src/gui/itempopup.h (renamed from src/gui/buddywindow.h)45
-rw-r--r--src/gui/itemshortcutcontainer.cpp157
-rw-r--r--src/gui/itemshortcutcontainer.h45
-rw-r--r--src/gui/listbox.cpp9
-rw-r--r--src/gui/listbox.h2
-rw-r--r--src/gui/login.cpp216
-rw-r--r--src/gui/login.h59
-rw-r--r--src/gui/menuwindow.cpp45
-rw-r--r--src/gui/minimap.cpp71
-rw-r--r--src/gui/minimap.h14
-rw-r--r--src/gui/ministatus.cpp23
-rw-r--r--src/gui/npc_text.cpp38
-rw-r--r--src/gui/npc_text.h9
-rw-r--r--src/gui/npcintegerdialog.cpp1
-rw-r--r--src/gui/npclistdialog.cpp47
-rw-r--r--src/gui/npclistdialog.h9
-rw-r--r--src/gui/npcstringdialog.cpp5
-rw-r--r--src/gui/ok_dialog.cpp58
-rw-r--r--src/gui/ok_dialog.h12
-rw-r--r--src/gui/passwordfield.h5
-rw-r--r--src/gui/playerbox.cpp13
-rw-r--r--src/gui/playerbox.h5
-rw-r--r--src/gui/popupmenu.cpp194
-rw-r--r--src/gui/popupmenu.h3
-rw-r--r--src/gui/progressbar.cpp3
-rw-r--r--src/gui/progressbar.h7
-rw-r--r--src/gui/radiobutton.h3
-rw-r--r--src/gui/register.cpp54
-rw-r--r--src/gui/register.h21
-rw-r--r--src/gui/scrollarea.cpp21
-rw-r--r--src/gui/scrollarea.h2
-rw-r--r--src/gui/sell.cpp8
-rw-r--r--src/gui/setup.cpp27
-rw-r--r--src/gui/setup.h5
-rw-r--r--src/gui/setup_audio.cpp3
-rw-r--r--src/gui/setup_audio.h4
-rw-r--r--src/gui/setup_colours.cpp226
-rw-r--r--src/gui/setup_colours.h73
-rw-r--r--src/gui/setup_joystick.cpp13
-rw-r--r--src/gui/setup_joystick.h4
-rw-r--r--src/gui/setup_keyboard.cpp7
-rw-r--r--src/gui/setup_keyboard.h8
-rw-r--r--src/gui/setup_players.cpp13
-rw-r--r--src/gui/setup_players.h7
-rw-r--r--src/gui/setup_video.cpp142
-rw-r--r--src/gui/setup_video.h10
-rw-r--r--src/gui/shop.h5
-rw-r--r--src/gui/shoplistbox.cpp10
-rw-r--r--src/gui/shoplistbox.h2
-rw-r--r--src/gui/shortcutcontainer.cpp76
-rw-r--r--src/gui/shortcutcontainer.h107
-rw-r--r--src/gui/shortcutwindow.cpp (renamed from src/gui/itemshortcutwindow.cpp)26
-rw-r--r--src/gui/shortcutwindow.h (renamed from src/gui/itemshortcutwindow.h)20
-rw-r--r--src/gui/skill.cpp77
-rw-r--r--src/gui/skill.h5
-rw-r--r--src/gui/slider.h3
-rw-r--r--src/gui/speechbubble.cpp111
-rw-r--r--src/gui/speechbubble.h48
-rw-r--r--src/gui/status.cpp16
-rw-r--r--src/gui/status.h1
-rw-r--r--src/gui/table.cpp9
-rw-r--r--src/gui/table.h1
-rw-r--r--src/gui/table_model.cpp53
-rw-r--r--src/gui/table_model.h42
-rw-r--r--src/gui/textbox.cpp41
-rw-r--r--src/gui/textbox.h15
-rw-r--r--src/gui/textfield.cpp45
-rw-r--r--src/gui/textfield.h43
-rw-r--r--src/gui/trade.cpp180
-rw-r--r--src/gui/trade.h2
-rw-r--r--src/gui/truetypefont.cpp5
-rw-r--r--src/gui/updatewindow.cpp64
-rw-r--r--src/gui/updatewindow.h1
-rw-r--r--src/gui/viewport.cpp235
-rw-r--r--src/gui/viewport.h76
-rw-r--r--src/gui/widgets/dropdown.cpp167
-rw-r--r--src/gui/widgets/dropdown.h86
-rw-r--r--src/gui/widgets/resizegrip.cpp11
-rw-r--r--src/gui/widgets/resizegrip.h4
-rw-r--r--src/gui/window.cpp249
-rw-r--r--src/gui/window.h38
-rw-r--r--src/gui/windowcontainer.h2
130 files changed, 5116 insertions, 1589 deletions
diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp
index 2d805b9c..6fd0482a 100644
--- a/src/gui/browserbox.cpp
+++ b/src/gui/browserbox.cpp
@@ -22,7 +22,7 @@
#include <algorithm>
#include "browserbox.h"
-
+#include "colour.h"
#include "linkhandler.h"
#include "truetypefont.h"
@@ -98,12 +98,12 @@ void BrowserBox::addRow(const std::string &row)
mLinks.push_back(bLink);
- newRow += "##L" + bLink.caption;
+ newRow += "##<" + bLink.caption;
tmp.erase(0, idx3 + 2);
if(tmp != "")
{
- newRow += "##P";
+ newRow += "##>";
}
idx1 = tmp.find("@@");
}
@@ -210,8 +210,7 @@ struct MouseOverLink
int mX, mY;
};
-void
-BrowserBox::mousePressed(gcn::MouseEvent &event)
+void BrowserBox::mousePressed(gcn::MouseEvent &event)
{
LinkIterator i = find_if(mLinks.begin(), mLinks.end(),
MouseOverLink(event.getX(), event.getY()));
@@ -221,8 +220,7 @@ BrowserBox::mousePressed(gcn::MouseEvent &event)
}
}
-void
-BrowserBox::mouseMoved(gcn::MouseEvent &event)
+void BrowserBox::mouseMoved(gcn::MouseEvent &event)
{
LinkIterator i = find_if(mLinks.begin(), mLinks.end(),
MouseOverLink(event.getX(), event.getY()));
@@ -230,8 +228,7 @@ BrowserBox::mouseMoved(gcn::MouseEvent &event)
mSelectedLink = (i != mLinks.end()) ? (i - mLinks.begin()) : -1;
}
-void
-BrowserBox::draw(gcn::Graphics *graphics)
+void BrowserBox::draw(gcn::Graphics *graphics)
{
if (mOpaque)
{
@@ -254,7 +251,8 @@ BrowserBox::draw(gcn::Graphics *graphics)
if ((mHighMode & UNDERLINE))
{
- graphics->setColor(gcn::Color(LINK));
+ bool valid;
+ graphics->setColor(gcn::Color(textColour->getColour('<', valid)));
graphics->drawLine(
mLinks[mSelectedLink].x1,
mLinks[mSelectedLink].y2,
@@ -311,57 +309,30 @@ BrowserBox::draw(gcn::Graphics *graphics)
// Check for color change in format "##x", x = [L,P,0..9]
if (row.find("##", start) == start && row.size() > start + 2)
{
- switch (row.at(start + 2))
+ char c = row.at(start + 2);
+ if (c == '>')
{
- case 'L': // Link color
- prevColor = selColor;
- selColor = LINK;
- break;
- case 'P': // Previous color
- selColor = prevColor;
- break;
- case '1':
- prevColor = selColor;
- selColor = RED;
- break;
- case '2':
- prevColor = selColor;
- selColor = GREEN;
- break;
- case '3':
- prevColor = selColor;
- selColor = BLUE;
- break;
- case '4':
- prevColor = selColor;
- selColor = ORANGE;
- break;
- case '5':
- prevColor = selColor;
- selColor = YELLOW;
- break;
- case '6':
- prevColor = selColor;
- selColor = PINK;
- break;
- case '7':
- prevColor = selColor;
- selColor = PURPLE;
- break;
- case '8':
- prevColor = selColor;
- selColor = GRAY;
- break;
- case '9':
- prevColor = selColor;
- selColor = BROWN;
- break;
- case '0':
- default:
+ selColor = prevColor;
+ }
+ else
+ {
+ bool valid;
+ int rgb = textColour->getColour(c, valid);
+ if (c == '<')
+ {
prevColor = selColor;
- selColor = BLACK;
+ }
+ if (valid)
+ {
+ selColor = rgb;
+ }
}
start += 3;
+
+ if (start == row.size())
+ {
+ break;
+ }
}
graphics->setColor(gcn::Color(selColor));
}
@@ -424,3 +395,4 @@ BrowserBox::draw(gcn::Graphics *graphics)
setHeight((mTextRows.size() + wrappedLines) * font->getHeight());
}
}
+
diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h
index 4dc41e3d..4bdf224b 100644
--- a/src/gui/browserbox.h
+++ b/src/gui/browserbox.h
@@ -165,3 +165,4 @@ class BrowserBox : public gcn::Widget, public gcn::MouseListener
};
#endif
+
diff --git a/src/gui/buddywindow.cpp b/src/gui/buddywindow.cpp
deleted file mode 100644
index 0927ddf8..00000000
--- a/src/gui/buddywindow.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 "buddywindow.h"
-
-#include <guichan/widgets/listbox.hpp>
-
-#include "button.h"
-#include "chat.h"
-#include "scrollarea.h"
-
-#include "../resources/buddylist.h"
-
-extern ChatWindow *chatWindow;
-
-BuddyWindow::BuddyWindow():
- Window("Buddy")
-{
- setContentSize(124, 202);
-
- mBuddyList = new BuddyList();
-
- mListbox = new gcn::ListBox();
- mListbox->setListModel(mBuddyList);
-
- ScrollArea *scrollArea = new ScrollArea(mListbox);
- scrollArea->setDimension(gcn::Rectangle(
- 7, 5, 110, 170));
- add(scrollArea);
-
- Button *talk = new Button("Talk", "Talk", this);
- Button *remove = new Button("Remove", "Remove", this);
- Button *cancel = new Button("Cancel", "Cancel", this);
-
- talk->setPosition(2,180);
- remove->setPosition(talk->getWidth()+2,180);
- cancel->setPosition(talk->getWidth()+remove->getWidth()+2,180);
-
- add(talk);
- add(remove);
- add(cancel);
-}
-
-void BuddyWindow::action(const gcn::ActionEvent &event)
-{
- if (event.getId() == "Talk") {
- int selected = mListbox->getSelected();
- if ( selected > -1 )
- {
- std::string who = mBuddyList->getElementAt(selected);
- chatWindow->setInputText(who +": ");
- }
- }
- else if (event.getId() == "Remove") {
- int selected = mListbox->getSelected();
- if ( selected > -1 )
- {
- std::string who = mBuddyList->getElementAt(selected);
- mBuddyList->removeBuddy(who);
- }
- }
- else if (event.getId() == "Cancel") {
- setVisible(false);
- }
-}
diff --git a/src/gui/button.cpp b/src/gui/button.cpp
index caf93b94..9b624015 100644
--- a/src/gui/button.cpp
+++ b/src/gui/button.cpp
@@ -122,8 +122,7 @@ Button::~Button()
}
}
-void
-Button::draw(gcn::Graphics *graphics)
+void Button::draw(gcn::Graphics *graphics)
{
int mode;
diff --git a/src/gui/button.h b/src/gui/button.h
index 0ec99245..d8ed9fa7 100644
--- a/src/gui/button.h
+++ b/src/gui/button.h
@@ -26,6 +26,8 @@
#include <guichan/widgets/button.hpp>
+#include "../guichanfwd.h"
+
class ImageRect;
/**
diff --git a/src/gui/buttonbox.cpp b/src/gui/buttonbox.cpp
new file mode 100644
index 00000000..d29f3c58
--- /dev/null
+++ b/src/gui/buttonbox.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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
+ */
+
+#include "button.h"
+#include "buttonbox.h"
+
+ButtonBox::ButtonBox(const std::string &title, const std::string &buttonTxt,
+ ButtonBoxListener *listener) :
+ Window(title),
+ mListener(listener)
+{
+ Button *button = new Button(buttonTxt, "activate", this);
+ setContentSize(button->getWidth() + 10,
+ button->getHeight() + 10);
+ button->setPosition(5, 5);
+ add(button);
+}
+
+void ButtonBox::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "activate")
+ {
+ mListener->buttonBoxRespond();
+ }
+}
diff --git a/src/gui/buttonbox.h b/src/gui/buttonbox.h
new file mode 100644
index 00000000..6d0e46b6
--- /dev/null
+++ b/src/gui/buttonbox.h
@@ -0,0 +1,69 @@
+/*
+ * 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
+ */
+
+#ifndef BUTTONBOX_H
+#define BUTTONBOX_H
+
+#include <string>
+
+#include <guichan/actionlistener.hpp>
+
+#include "window.h"
+
+#include "../guichanfwd.h"
+
+class ButtonBoxListener
+{
+ public:
+
+ /*
+ * function that ButtonBox calls when the button has been pressed
+ */
+ virtual void buttonBoxRespond() = 0;
+};
+
+class ButtonBox : public Window, public gcn::ActionListener
+{
+ public:
+
+ /*
+ * Constructor
+ *
+ * @param title is the text that appears at the top of the box
+ * @param buttonTxt is the text that appears on the button
+ * @param listener points to the class that should respond to the
+ * button press
+ */
+ ButtonBox(const std::string &title, const std::string &buttonTxt,
+ ButtonBoxListener *listener);
+
+ /*
+ * called when the button is pressed
+ *
+ * @param event is the event that is generated
+ */
+ void action(const gcn::ActionEvent &event);
+
+ private:
+
+ ButtonBoxListener *mListener;
+};
+#endif
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 49dd52af..0c8c4d9d 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buy.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "buy.h"
#include "scrollarea.h"
#include "shop.h"
#include "shoplistbox.h"
@@ -43,7 +42,7 @@ BuyDialog::BuyDialog(Network *network):
Window(_("Buy")), mNetwork(network),
mMoney(0), mAmountItems(0), mMaxItems(0)
{
- setWindowName("Buy");
+ setWindowName(_("Buy"));
setResizable(true);
setMinWidth(260);
setMinHeight(230);
diff --git a/src/gui/buy.h b/src/gui/buy.h
index 37a39890..423918ce 100644
--- a/src/gui/buy.h
+++ b/src/gui/buy.h
@@ -111,9 +111,9 @@ class BuyDialog : public Window, public gcn::ActionListener,
ShopItems *mShopItems;
- int mMoney;
- int mAmountItems;
- int mMaxItems;
+ Uint32 mMoney;
+ Uint32 mAmountItems;
+ Uint32 mMaxItems;
};
#endif
diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp
index cdab0855..d060db85 100644
--- a/src/gui/buysell.cpp
+++ b/src/gui/buysell.cpp
@@ -19,9 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "buysell.h"
-
#include "button.h"
+#include "buysell.h"
#include "../npc.h"
diff --git a/src/gui/buysell.h b/src/gui/buysell.h
index e3cdc52a..60a6398d 100644
--- a/src/gui/buysell.h
+++ b/src/gui/buysell.h
@@ -26,6 +26,8 @@
#include "window.h"
+#include "../guichanfwd.h"
+
/**
* A dialog to choose between buying or selling at a shop.
*
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index df57f969..e556dfa0 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -19,13 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "char_select.h"
-
#include <string>
+#include <guichan/font.hpp>
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "char_select.h"
#include "confirm_dialog.h"
#include "ok_dialog.h"
#include "playerbox.h"
@@ -69,7 +69,8 @@ CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m):
void CharDeleteConfirm::action(const gcn::ActionEvent &event)
{
//ConfirmDialog::action(event);
- if (event.getId() == "yes") {
+ if (event.getId() == "yes")
+ {
master->attemptCharDelete();
}
ConfirmDialog::action(event);
@@ -81,38 +82,42 @@ CharSelectDialog::CharSelectDialog(Network *network,
Window(_("Select Character")), mNetwork(network),
mCharInfo(charInfo), mGender(gender), mCharSelected(false)
{
- mSelectButton = new Button(_("Ok"), "ok", this);
- mCancelButton = new Button(_("Cancel"), "cancel", this);
- mNewCharButton = new Button(_("New"), "new", this);
- mDelCharButton = new Button(_("Delete"), "delete", this);
- mPreviousButton = new Button(_("Previous"), "previous", this);
- mNextButton = new Button(_("Next"), "next", this);
+ // Control that shows the Player
+ mPlayerBox = new PlayerBox;
+ mPlayerBox->setWidth(74);
mNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
mLevelLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
mJobLevelLabel = new gcn::Label(strprintf(_("Job Level: %d"), 0));
mMoneyLabel = new gcn::Label(strprintf(_("Money: %d"), 0));
- // Control that shows the Player
- mPlayerBox = new PlayerBox;
- mPlayerBox->setWidth(74);
+ const std::string tempString = getFont()->getWidth(_("New")) <
+ getFont()->getWidth(_("Delete")) ?
+ _("Delete") : _("New");
+
+ mPreviousButton = new Button(_("Previous"), "previous", this);
+ mNextButton = new Button(_("Next"), "next", this);
+ mNewDelCharButton = new Button(tempString, "newdel", this);
+ mSelectButton = new Button(_("Ok"), "ok", this);
+ mCancelButton = new Button(_("Cancel"), "cancel", this);
ContainerPlacer place;
place = getPlacer(0, 0);
+
place(0, 0, mPlayerBox, 1, 6).setPadding(3);
- place(1, 0, mNameLabel, 3);
- place(1, 1, mLevelLabel, 3);
- place(1, 2, mJobLevelLabel, 3);
- place(1, 3, mMoneyLabel, 3);
- place(1, 4, mPreviousButton);
- place(2, 4, mNextButton);
- place(1, 5, mNewCharButton);
- place(2, 5, mDelCharButton);
- place.getCell().matchColWidth(1, 2);
+ place(1, 0, mNewDelCharButton);
+ place(1, 1, mNameLabel, 5);
+ place(1, 2, mLevelLabel, 5);
+ place(1, 3, mJobLevelLabel, 5);
+ place(1, 4, mMoneyLabel, 5);
+ place.getCell().matchColWidth(1, 4);
place = getPlacer(0, 2);
- place(0, 0, mSelectButton);
- place(1, 0, mCancelButton);
- reflowLayout(265, 0);
+ place(0, 0, mPreviousButton);
+ place(1, 0, mNextButton);
+ place(4, 0, mCancelButton);
+ place(5, 0, mSelectButton);
+
+ reflowLayout(250, 0);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -125,8 +130,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "ok" && n_character > 0)
{
// Start game
- mNewCharButton->setEnabled(false);
- mDelCharButton->setEnabled(false);
+ mNewDelCharButton->setEnabled(false);
mSelectButton->setEnabled(false);
mPreviousButton->setEnabled(false);
mNextButton->setEnabled(false);
@@ -137,20 +141,21 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
{
state = EXIT_STATE;
}
- else if (event.getId() == "new" && n_character <= MAX_SLOT)
- {
- // Start new character dialog
- CharCreateDialog *charCreateDialog =
- new CharCreateDialog(this, mCharInfo->getPos(), mNetwork, mGender);
- charServerHandler.setCharCreateDialog(charCreateDialog);
- }
- else if (event.getId() == "delete")
+ else if (event.getId() == "newdel")
{
- // Delete character
- if (mCharInfo->getEntry())
+ // Check for a character
+ if (mCharInfo->getEntry() && n_character <= MAX_SLOT )
{
new CharDeleteConfirm(this);
}
+ else
+ {
+ // Start new character dialog
+ CharCreateDialog *charCreateDialog =
+ new CharCreateDialog(this, mCharInfo->getPos(),
+ mNetwork, mGender);
+ charServerHandler.setCharCreateDialog(charCreateDialog);
+ }
}
else if (event.getId() == "previous")
{
@@ -174,18 +179,17 @@ void CharSelectDialog::updatePlayerInfo()
mMoneyLabel->setCaption(strprintf(_("Gold: %d"), pi->mGp));
if (!mCharSelected)
{
- mNewCharButton->setEnabled(false);
- mDelCharButton->setEnabled(true);
+ mNewDelCharButton->setCaption(_("Delete"));
mSelectButton->setEnabled(true);
}
}
- else {
+ else
+ {
mNameLabel->setCaption(strprintf(_("Name: %s"), ""));
mLevelLabel->setCaption(strprintf(_("Level: %d"), 0));
mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), 0));
mMoneyLabel->setCaption(strprintf(_("Money: %d"), 0));
- mNewCharButton->setEnabled(true);
- mDelCharButton->setEnabled(false);
+ mNewDelCharButton->setCaption(_("New"));
mSelectButton->setEnabled(false);
}
@@ -224,7 +228,8 @@ bool CharSelectDialog::selectByName(const std::string &name)
unsigned int oldPos = mCharInfo->getPos();
mCharInfo->select(0);
- do {
+ do
+ {
LocalPlayer *player = mCharInfo->getEntry();
if (player && player->getName() == name)
@@ -244,7 +249,10 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
{
mPlayer = new Player(0, 0, NULL);
mPlayer->setGender(gender);
- mPlayer->setHairStyle(rand() % Being::getHairStylesNr(), rand() % Being::getHairColorsNr());
+
+ int numberOfHairColors = ColorDB::size();
+
+ mPlayer->setHairStyle(rand() % mPlayer->getNumOfHairstyles(), rand() % numberOfHairColors);
mNameField = new TextField("");
mNameLabel = new gcn::Label(_("Name:"));
@@ -258,41 +266,29 @@ CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network,
mCancelButton = new Button(_("Cancel"), "cancel", this);
mPlayerBox = new PlayerBox(mPlayer);
+ mPlayerBox->setWidth(74);
+
mNameField->setActionEventId("create");
+ mNameField->addActionListener(this);
- int w = 200;
- int h = 150;
- setContentSize(w, h);
- mPlayerBox->setDimension(gcn::Rectangle(80, 30, 110, 85));
- mNameLabel->setPosition(5, 5);
- mNameField->setDimension(
- gcn::Rectangle(45, 5, w - 45 - 7, mNameField->getHeight()));
- mPrevHairColorButton->setPosition(90, 35);
- mNextHairColorButton->setPosition(165, 35);
- mHairColorLabel->setPosition(5, 40);
- mPrevHairStyleButton->setPosition(90, 64);
- mNextHairStyleButton->setPosition(165, 64);
- mHairStyleLabel->setPosition(5, 70);
- mCancelButton->setPosition(
- w - 5 - mCancelButton->getWidth(),
- h - 5 - mCancelButton->getHeight());
- mCreateButton->setPosition(
- mCancelButton->getX() - 5 - mCreateButton->getWidth(),
- h - 5 - mCancelButton->getHeight());
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
- mNameField->addActionListener(this);
+ place(0, 0, mNameLabel, 1);
+ place(1, 0, mNameField, 6);
+ place(0, 1, mHairStyleLabel, 1);
+ place(1, 1, mPrevHairStyleButton);
+ place(2, 1, mPlayerBox, 1, 8).setPadding(3);
+ place(3, 1, mNextHairStyleButton);
+ place(0, 2, mHairColorLabel, 1);
+ place(1, 2, mPrevHairColorButton);
+ place(3, 2, mNextHairColorButton);
+ place.getCell().matchColWidth(0, 2);
+ place = getPlacer(0, 2);
+ place(4, 0, mCancelButton);
+ place(5, 0, mCreateButton);
- add(mPlayerBox);
- add(mNameField);
- add(mNameLabel);
- add(mNextHairColorButton);
- add(mPrevHairColorButton);
- add(mHairColorLabel);
- add(mNextHairStyleButton);
- add(mPrevHairStyleButton);
- add(mHairStyleLabel);
- add(mCreateButton);
- add(mCancelButton);
+ reflowLayout(225, 0);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -307,53 +303,54 @@ CharCreateDialog::~CharCreateDialog()
charServerHandler.setCharCreateDialog(0);
}
-void
-CharCreateDialog::action(const gcn::ActionEvent &event)
+void CharCreateDialog::action(const gcn::ActionEvent &event)
{
- if (event.getId() == "create") {
- if (getName().length() >= 4) {
+ int numberOfColors = ColorDB::size();
+ if (event.getId() == "create")
+ {
+ if (getName().length() >= 4)
+ {
// Attempt to create the character
mCreateButton->setEnabled(false);
attemptCharCreate();
}
- else {
+ else
+ {
new OkDialog("Error",
"Your name needs to be at least 4 characters.", this);
}
}
- else if (event.getId() == "cancel") {
+ else if (event.getId() == "cancel")
scheduleDelete();
- }
- else if (event.getId() == "nextcolor") {
- mPlayer->setHairStyle(-1, mPlayer->getHairColor() + 1);
- }
- else if (event.getId() == "prevcolor") {
- mPlayer->setHairStyle(-1, mPlayer->getHairColor() + Being::getHairColorsNr() - 1);
- }
- else if (event.getId() == "nextstyle") {
- mPlayer->setHairStyle(mPlayer->getHairStyle() + 1, -1);
- }
- else if (event.getId() == "prevstyle") {
- mPlayer->setHairStyle(mPlayer->getHairStyle() + Being::getHairStylesNr() - 1, -1);
- }
+ else if (event.getId() == "nextcolor")
+ mPlayer->setHairStyle(mPlayer->getHairStyle(),
+ (mPlayer->getHairColor() + 1) % numberOfColors);
+ else if (event.getId() == "prevcolor")
+ mPlayer->setHairStyle(mPlayer->getHairStyle(),
+ (mPlayer->getHairColor() + numberOfColors - 1) %
+ numberOfColors);
+ else if (event.getId() == "nextstyle")
+ mPlayer->setHairStyle(mPlayer->getHairStyle() + 1,
+ mPlayer->getHairColor());
+ else if (event.getId() == "prevstyle")
+ mPlayer->setHairStyle(mPlayer->getHairStyle() +
+ mPlayer->getNumOfHairstyles() - 1,
+ mPlayer->getHairColor());
}
-std::string
-CharCreateDialog::getName()
+std::string CharCreateDialog::getName()
{
std::string name = mNameField->getText();
trim(name);
return name;
}
-void
-CharCreateDialog::unlock()
+void CharCreateDialog::unlock()
{
mCreateButton->setEnabled(true);
}
-void
-CharCreateDialog::attemptCharCreate()
+void CharCreateDialog::attemptCharCreate()
{
// Send character infos
MessageOut outMsg(mNetwork);
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 74745788..5d4ecfa8 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -22,17 +22,17 @@
#ifndef _CHAR_SELECT_H
#define _CHAR_SELECT_H
+#include <guichan/actionlistener.hpp>
+
#include "window.h"
#include "../guichanfwd.h"
#include "../lockedarray.h"
#include "../being.h"
-#include <guichan/actionlistener.hpp>
-
-class Player;
class LocalPlayer;
class Network;
+class Player;
class PlayerBox;
/**
@@ -65,8 +65,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener
gcn::Button *mSelectButton;
gcn::Button *mCancelButton;
- gcn::Button *mNewCharButton;
- gcn::Button *mDelCharButton;
+ gcn::Button *mNewDelCharButton;
gcn::Button *mPreviousButton;
gcn::Button *mNextButton;
diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp
index 7be2441d..2e823b60 100644
--- a/src/gui/char_server.cpp
+++ b/src/gui/char_server.cpp
@@ -19,9 +19,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "char_server.h"
-
#include "button.h"
+#include "char_server.h"
#include "listbox.h"
#include "scrollarea.h"
@@ -99,8 +98,7 @@ ServerSelectDialog::~ServerSelectDialog()
delete mServerListModel;
}
-void
-ServerSelectDialog::action(const gcn::ActionEvent &event)
+void ServerSelectDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "ok") {
mOkButton->setEnabled(false);
@@ -108,7 +106,6 @@ ServerSelectDialog::action(const gcn::ActionEvent &event)
mLoginData->hostname = iptostring(si->address);
mLoginData->port = si->port;
mLoginData->updateHost = si->updateHost;
-
state = mNextState;
}
else if (event.getId() == "cancel") {
@@ -116,14 +113,12 @@ ServerSelectDialog::action(const gcn::ActionEvent &event)
}
}
-int
-ServerListModel::getNumberOfElements()
+int ServerListModel::getNumberOfElements()
{
return n_server;
}
-std::string
-ServerListModel::getElementAt(int i)
+std::string ServerListModel::getElementAt(int i)
{
const SERVER_INFO *si = server_info[i];
return si->name + " (" + toString(si->online_users) + ")";
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index 87d843a0..c9c3e9bc 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -20,56 +20,66 @@
*/
#include <algorithm>
-#include <sstream>
+#include <fstream>
#include <guichan/focushandler.hpp>
-#include "chat.h"
-
#include "browserbox.h"
+#include "chat.h"
#include "chatinput.h"
+#include "itemlinkhandler.h"
#include "scrollarea.h"
#include "sdlinput.h"
#include "windowcontainer.h"
#include "widgets/layout.h"
+#include "../beingmanager.h"
#include "../configuration.h"
+#include "../extensions.h"
#include "../game.h"
#include "../localplayer.h"
+#include "../party.h"
+#include "../recorder.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
+#include "../resources/iteminfo.h"
+#include "../resources/itemdb.h"
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
#include "../utils/trim.h"
-ChatWindow::ChatWindow(Network *network):
- Window(""),
- mNetwork(network),
- mTmpVisible(false)
+ChatWindow::ChatWindow(Network * network):
+Window(""), mNetwork(network), mTmpVisible(false)
{
- setWindowName("Chat");
+ setWindowName(_("Chat"));
setResizable(true);
setDefaultSize(0, windowContainer->getHeight() - 123, 600, 123);
setMinWidth(150);
setMinHeight(90);
+ mItemLinkHandler = new ItemLinkHandler();
+
mChatInput = new ChatInput;
mChatInput->setActionEventId("chatinput");
mChatInput->addActionListener(this);
mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP);
mTextOutput->setOpaque(false);
- mTextOutput->disableLinksAndUserColors();
mTextOutput->setMaxRow((int) config.getValue("ChatLogLength", 0));
+ mTextOutput->setLinkHandler(mItemLinkHandler);
+
mScrollArea = new ScrollArea(mTextOutput);
- mScrollArea->setPosition(
- mScrollArea->getFrameSize(), mScrollArea->getFrameSize());
- mScrollArea->setScrollPolicy(
- gcn::ScrollArea::SHOW_NEVER, gcn::ScrollArea::SHOW_ALWAYS);
+ mScrollArea->setPosition(mScrollArea->getFrameSize(),
+ mScrollArea->getFrameSize());
+ mScrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER,
+ gcn::ScrollArea::SHOW_ALWAYS);
+ mScrollArea->setScrollAmount(0, 1);
mScrollArea->setOpaque(false);
place(0, 0, mScrollArea, 5, 5).setPadding(0);
@@ -84,23 +94,48 @@ ChatWindow::ChatWindow(Network *network):
// Add key listener to chat input to be able to respond to up/down
mChatInput->addKeyListener(this);
mCurHist = mHistory.end();
+
+ // Read the party prefix
+ std::string partyPrefix = config.getValue("PartyPrefix", "$");
+ mPartyPrefix = (partyPrefix == "" ? '$' : partyPrefix.at(0));
+ mReturnToggles = config.getValue("ReturnToggles", "0") == "1";
+ mRecorder = new Recorder(this);
+ mParty = new Party(this, mNetwork);
+
+ // If the player had @assert on in the last session, ask the server to
+ // run the @assert command for the player again. Convenience for GMs.
+ if (config.getValue(player_node->getName() + "GMassert", 0))
+ chatSend(player_node->getName(), "@assert");
}
-void ChatWindow::chatLog(std::string line, int own)
+ChatWindow::~ChatWindow()
+{
+ char partyPrefix[2] = ".";
+ *partyPrefix = mPartyPrefix;
+ config.setValue("PartyPrefix", partyPrefix);
+ config.setValue("ReturnToggles", mReturnToggles ? "1" : "0");
+ delete mRecorder;
+}
+
+void ChatWindow::chatLog(std::string line, int own, bool ignoreRecord)
{
// Trim whitespace
trim(line);
CHATLOG tmp;
- tmp.own = own;
+ tmp.own = own;
tmp.nick = "";
tmp.text = line;
+
std::string::size_type pos = line.find(" : ");
- if (pos != std::string::npos) {
+ if (pos != std::string::npos)
+ {
tmp.nick = line.substr(0, pos);
tmp.text = line.substr(pos + 3);
- } else {
+ }
+ else
+ {
// Fix the owner of welcome message.
if (line.substr(0, 7) == "Welcome")
{
@@ -108,77 +143,99 @@ void ChatWindow::chatLog(std::string line, int own)
}
}
- std::string lineColor = "##0"; // Equiv. to BrowserBox::BLACK
- switch (own) {
+ std::string lineColor = "##C";
+ switch (own)
+ {
case BY_GM:
- if (tmp.nick.empty()) {
- tmp.nick = _("Global announcement:");
+ if (tmp.nick.empty())
+ {
+ tmp.nick = std::string(_("Global announcement:"));
tmp.nick += " ";
- } else {
+ lineColor = "##G";
+ }
+ else
+ {
tmp.nick = strprintf(_("Global announcement from %s:"),
tmp.nick.c_str());
tmp.nick += " ";
+ lineColor = "##1"; // Equiv. to BrowserBox::RED
}
- lineColor = "##1"; // Equiv. to BrowserBox::RED
break;
case BY_PLAYER:
tmp.nick += CAT_NORMAL;
- lineColor = "##2"; // Equiv. to BrowserBox::GREEN
+ lineColor = "##Y";
break;
case BY_OTHER:
tmp.nick += CAT_NORMAL;
- lineColor = "##0"; // Equiv. to BrowserBox::BLACK
+ lineColor = "##C";
break;
case BY_SERVER:
tmp.nick = _("Server:");
tmp.nick += " ";
tmp.text = line;
- lineColor = "##7"; // Equiv. to BrowserBox::PINK
+ lineColor = "##S";
+ break;
+ case BY_PARTY:
+ tmp.nick += CAT_NORMAL;
+ lineColor = "##P";
break;
case ACT_WHISPER:
tmp.nick = strprintf(_("%s whispers:"), tmp.nick.c_str());
tmp.nick += " ";
- lineColor = "##3"; // Equiv. to BrowserBox::BLUE
+ lineColor = "##W";
break;
case ACT_IS:
tmp.nick += CAT_IS;
- lineColor = "##5"; // Equiv. to BrowserBox::YELLOW
+ lineColor = "##I";
break;
case BY_LOGGER:
tmp.nick = "";
tmp.text = line;
- lineColor = "##8"; // Equiv. to BrowserBox::GREY
+ lineColor = "##L";
break;
}
+ if (tmp.nick == ": ")
+ {
+ tmp.nick = "";
+ lineColor = "##S";
+ }
+
+ if (tmp.nick == "" && tmp.text.substr(0, 17) == "Visible GM status")
+ {
+ player_node->setGM();
+ }
+
// Get the current system time
time_t t;
time(&t);
// Format the time string properly
std::stringstream timeStr;
- timeStr << "["
- << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
- << (int)(((t / 60) / 60) % 24)
- << ":"
- << (((t / 60) % 60 < 10) ? "0" : "")
- << (int)((t / 60) % 60)
- << "] ";
+ timeStr << "[" << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
+ << (int) (((t / 60) / 60) % 24)
+ << ":" << (((t / 60) % 60 < 10) ? "0" : "")
+ << (int) ((t / 60) % 60)
+ << "] ";
line = lineColor + timeStr.str() + tmp.nick + tmp.text;
// We look if the Vertical Scroll Bar is set at the max before
// adding a row, otherwise the max will always be a row higher
// at comparison.
- if (mScrollArea->getVerticalScrollAmount() == mScrollArea->getVerticalMaxScroll())
+ if (mScrollArea->getVerticalScrollAmount() ==
+ mScrollArea->getVerticalMaxScroll())
{
mTextOutput->addRow(line);
- mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll());
+ mScrollArea->setVerticalScrollAmount(mScrollArea->
+ getVerticalMaxScroll());
}
else
{
mTextOutput->addRow(line);
}
+
+ mRecorder->record(line.substr(3));
}
void ChatWindow::chatLog(CHATSKILL act)
@@ -192,12 +249,13 @@ void ChatWindow::action(const gcn::ActionEvent &event)
{
std::string message = mChatInput->getText();
- if (!message.empty()) {
+ if (!message.empty())
+ {
// If message different from previous, put it in the history
- if (mHistory.empty() || message != mHistory.back()) {
+ if (mHistory.empty() || message != mHistory.back())
+ {
mHistory.push_back(message);
}
-
// Reset history iterator
mCurHist = mHistory.end();
@@ -208,13 +266,15 @@ void ChatWindow::action(const gcn::ActionEvent &event)
mChatInput->setText("");
}
- // Remove focus and hide input
- mFocusHandler->focusNone();
+ if (message.empty() || !mReturnToggles)
+ {
+ // Remove focus and hide input
+ mFocusHandler->focusNone();
- // If the chatWindow is shown up because you want to send a message
- // It should hide now
- if (mTmpVisible) {
- setVisible(false);
+ // If the chatWindow is shown up because you want to send a message
+ // It should hide now
+ if (mTmpVisible)
+ setVisible(false);
}
}
}
@@ -244,16 +304,15 @@ bool ChatWindow::isInputFocused()
return mChatInput->isFocused();
}
-void ChatWindow::whisper(const std::string &nick, std::string msg,
- int prefixlen)
+void ChatWindow::whisper(const std::string &nick, std::string msg)
{
std::string recvnick = "";
- msg.erase(0, prefixlen + 1);
if (msg.substr(0, 1) == "\"")
{
const std::string::size_type pos = msg.find('"', 1);
- if (pos != std::string::npos) {
+ if (pos != std::string::npos)
+ {
recvnick = msg.substr(1, pos - 1);
msg.erase(0, pos + 2);
}
@@ -261,7 +320,8 @@ void ChatWindow::whisper(const std::string &nick, std::string msg,
else
{
const std::string::size_type pos = msg.find(" ");
- if (pos != std::string::npos) {
+ if (pos != std::string::npos)
+ {
recvnick = msg.substr(0, pos);
msg.erase(0, pos + 1);
}
@@ -274,8 +334,8 @@ void ChatWindow::whisper(const std::string &nick, std::string msg,
outMsg.writeString(msg, msg.length());
chatLog(strprintf(_("Whispering to %s: %s"),
- recvnick.c_str(), msg.c_str()),
- BY_PLAYER);
+ recvnick.c_str(), msg.c_str()),
+ BY_PLAYER);
}
void ChatWindow::chatSend(const std::string &nick, std::string msg)
@@ -284,8 +344,67 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
* require server handling by proper packet. Probably
* those if elses should be replaced by protocol calls */
+ // Send party message
+ if (msg.at(0) == mPartyPrefix)
+ {
+ msg.erase(0, 1);
+ std::size_t length = msg.length() + 1;
+
+ if (length == 0)
+ {
+ chatLog(_("Trying to send a blank party message."), BY_SERVER);
+ return;
+ }
+ MessageOut outMsg(mNetwork);
+
+ outMsg.writeInt16(CMSG_PARTY_MESSAGE);
+ outMsg.writeInt16(length + 4);
+ outMsg.writeString(msg, length);
+ return;
+ }
+
+ // check for item link
+ std::string::size_type start = msg.find('[');
+ while (start != std::string::npos && msg[start+1] != '@')
+ {
+ std::string::size_type end = msg.find(']', start);
+ if (end != std::string::npos)
+ {
+ // Catch multiple embeds and ignore them so it doesn't crash the client.
+ while ((msg.find('[', start + 1) != std::string::npos) &&
+ (msg.find('[', start + 1) < end))
+ {
+ start = msg.find('[', start + 1);
+ }
+
+ std::string temp = msg.substr(start+1, end - start - 1);
+
+ while (temp[0] == ' ')
+ {
+ temp = temp.substr(1, temp.size());
+ }
+ while (temp[temp.size()] == ' ')
+ {
+ temp = temp.substr(0, temp.size() - 1);
+ }
+
+ for (unsigned int i = 0; i < temp.size(); i++)
+ {
+ temp[i] = (char) tolower(temp[i]);
+ }
+
+ const ItemInfo itemInfo = ItemDB::get(temp);
+ msg.insert(end, "@@");
+ msg.insert(start+1, "|");
+ msg.insert(start+1, toString(itemInfo.getId()));
+ msg.insert(start+1, "@@");
+ }
+ start = msg.find('[', start + 1);
+ }
+
// Prepare ordinary message
- if (msg.substr(0, 1) != "/") {
+ if (msg.substr(0, 1) != "/")
+ {
msg = nick + " : " + msg;
MessageOut outMsg(mNetwork);
@@ -293,21 +412,39 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
// Added + 1 in order to let eAthena parse admin commands correctly
outMsg.writeInt16(msg.length() + 4 + 1);
outMsg.writeString(msg, msg.length() + 1);
+ return;
+ }
+
+ msg.erase(0, 1);
+ trim(msg);
+
+ std::size_t space = msg.find(" ");
+ std::string command = msg.substr(0, space);
+
+ if (space == std::string::npos)
+ {
+ msg = "";
}
- else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE)
+ else
+ {
+ msg = msg.substr(space);
+ trim(msg);
+ }
+
+ if (command == "announce")
{
- msg.erase(0, IS_ANNOUNCE_LENGTH);
MessageOut outMsg(mNetwork);
outMsg.writeInt16(0x0099);
outMsg.writeInt16(msg.length() + 4);
outMsg.writeString(msg, msg.length());
}
- else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP)
+ else if (command == "help")
{
- msg.erase(0, IS_HELP_LENGTH + 1);
+ msg.erase(0, 6);
trim(msg);
std::size_t space = msg.find(" ");
std::string msg1;
+
if (space == std::string::npos)
{
msg1 = "";
@@ -317,33 +454,160 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
msg1 = msg.substr(space + 1, msg.length());
msg = msg.substr(0, space);
}
+
if (msg != "" && msg.at(0) == '/')
{
msg.erase(0, 1);
}
+
trim(msg1);
help(msg, msg1);
}
- else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE)
+ else if (command == "where")
{
// Display the current map, X, and Y
std::ostringstream where;
where << map_path << " " << player_node->mX << "," << player_node->mY;
chatLog(where.str(), BY_SERVER);
}
- else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO)
+ else if (command == "who")
{
MessageOut outMsg(mNetwork);
outMsg.writeInt16(0x00c1);
}
- else if (msg.substr(0, IS_CLEAR_LENGTH) == IS_CLEAR)
- {
+ else if (command == "clear")
mTextOutput->clearRows();
+ else if (command == "whisper" || command == "msg" || command == "w")
+ whisper(nick, msg);
+ else if (command == "record")
+ mRecorder->respond(msg);
+ else if (command == "toggle")
+ {
+ if (msg == "")
+ {
+ chatLog(mReturnToggles ? _("Return toggles chat.")
+ : _("Message closes chat."), BY_SERVER);
+ return;
+ }
+
+ msg = msg.substr(0, 1);
+
+ if (msg == "1" ||
+ msg == "y" || msg == "Y" ||
+ msg == "t" || msg == "T")
+ {
+ chatLog(_("Return now toggles chat."), BY_SERVER);
+ mReturnToggles = true;
+ return;
+ }
+ else if (msg == "0" ||
+ msg == "n" || msg == "N" ||
+ msg == "f" || msg == "F")
+ {
+ chatLog(_("Message now closes chat."), BY_SERVER);
+ mReturnToggles = false;
+ return;
+ }
+ else
+ chatLog(_("Options to /toggle are \"yes\", \"no\", \"true\", "
+ "\"false\", \"1\", \"0\"."), BY_SERVER);
+ }
+ else if (command == "party")
+ {
+ if (msg == "")
+ {
+ chatLog(_("Unknown party command... Type \"/help\" party for more "
+ "information."), BY_SERVER);
+ return;
+ }
+
+ const std::string::size_type space = msg.find(" ");
+ std::string rest = (space == std::string::npos ? ""
+ : msg.substr(space + 1, msg.length()));
+
+ if (rest != "")
+ {
+ msg = msg.substr(0, space);
+ trim(msg);
+ }
+
+ party(msg, rest);
+ return;
+ }
+ else if (command == "cast")
+ {
+ /*
+ * This will eventually be replaced by a GUI, so
+ * we don't need to get too sophisticated
+ */
+ if (extensions.aethyra_spells)
+ {
+ MessageOut outMsg(mNetwork);
+ if (msg == "heal")
+ {
+ outMsg.writeInt16(0x03f3);
+ outMsg.writeInt16(0x01);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(0);
+ outMsg.writeInt8(0);
+ outMsg.writeString("", 24);
+ }
+ else if (msg == "gather")
+ {
+ outMsg.writeInt16(0x03f3);
+ outMsg.writeInt16(0x02);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(0);
+ outMsg.writeInt8(0);
+ outMsg.writeString("", 24);
+ }
+ else
+ chatLog(_("No such spell!"), BY_SERVER);
+ }
+ else
+ chatLog(_("The current server doesn't support spells"), BY_SERVER);
+ }
+ else if (command == "present")
+ {
+ Beings & beings = beingManager->getAll();
+ std::string response = "";
+
+ for (BeingIterator bi = beings.begin(), be = beings.end();
+ bi != be; ++bi)
+ {
+ if ((*bi)->getType() == Being::PLAYER)
+ {
+ if (response != "")
+ {
+ response += ", ";
+ }
+ response += (*bi)->getName();
+ }
+ }
+
+ if (mRecorder->isRecording())
+ {
+ // Get the current system time
+ time_t t;
+ time(&t);
+
+ // Format the time string properly
+ std::stringstream timeStr;
+ timeStr << "[" << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
+ << (int) (((t / 60) / 60) % 24)
+ << ":" << (((t / 60) % 60 < 10) ? "0" : "")
+ << (int) ((t / 60) % 60)
+ << "] ";
+
+
+ mRecorder->record(timeStr.str() + _("Present: ") + response + ".");
+ chatLog(_("Attendance written to record log."), BY_SERVER, true);
+ }
+ else
+ {
+ chatLog(_("Present: ") + response, BY_SERVER);
+ }
}
- else if (msg.substr(0, IS_WHISPER_LENGTH) == IS_WHISPER)
- whisper(nick, msg, IS_WHISPER_LENGTH);
- else if (msg.substr(0, IS_SHORT_WHISPER_LENGTH) == IS_SHORT_WHISPER)
- whisper(nick, msg, IS_SHORT_WHISPER_LENGTH);
else
{
chatLog(_("Unknown command"), BY_SERVER);
@@ -353,8 +617,10 @@ void ChatWindow::chatSend(const std::string &nick, std::string msg)
std::string ChatWindow::const_msg(CHATSKILL act)
{
std::string msg;
- if (act.success == SKILL_FAILED && act.skill == SKILL_BASIC) {
- switch (act.bskill) {
+ if (act.success == SKILL_FAILED && act.skill == SKILL_BASIC)
+ {
+ switch (act.bskill)
+ {
case BSKILL_TRADE:
msg = _("Trade failed!");
break;
@@ -377,7 +643,8 @@ std::string ChatWindow::const_msg(CHATSKILL act)
msg += " ";
- switch (act.reason) {
+ switch (act.reason)
+ {
case RFAIL_SKILLDEP:
msg += _("You have not yet reached a high enough lvl!");
break;
@@ -412,8 +679,11 @@ std::string ChatWindow::const_msg(CHATSKILL act)
msg += _("Huh? What's that?");
break;
}
- } else {
- switch (act.skill) {
+ }
+ else
+ {
+ switch (act.skill)
+ {
case SKILL_WARP :
msg = _("Warp failed...");
break;
@@ -448,11 +718,14 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event)
{
// Move forward through the history
HistoryIterator prevHist = mCurHist++;
- if (mCurHist != mHistory.end()) {
+
+ if (mCurHist != mHistory.end())
+ {
mChatInput->setText(*mCurHist);
mChatInput->setCaretPosition(mChatInput->getText().length());
}
- else {
+ else
+ {
mCurHist = prevHist;
}
}
@@ -468,10 +741,18 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event)
void ChatWindow::setInputText(std::string input_str)
{
- mChatInput->setText(input_str + " ");
+ mChatInput->setText(mChatInput->getText() + input_str + " ");
requestChatFocus();
}
+void ChatWindow::addItemText(int itemId, const std::string &item)
+{
+ std::ostringstream text;
+ text << "[@@" << itemId << "|" << item << "@@] ";
+ mChatInput->setText(mChatInput->getText() + text.str());
+ requestChatFocus();
+}
+
void ChatWindow::setVisible(bool isVisible)
{
Window::setVisible(isVisible);
@@ -484,70 +765,132 @@ void ChatWindow::setVisible(bool isVisible)
mTmpVisible = false;
}
-void ChatWindow::help(const std::string &msg1, const std::string &msg2)
+void ChatWindow::party(const std::string & command, const std::string & rest)
+{
+ if (command == "prefix")
+ {
+ if (rest == "")
+ {
+ char temp[2] = ".";
+ *temp = mPartyPrefix;
+ chatLog(_("The current party prefix is ") + std::string(temp),
+ BY_SERVER);
+ }
+ else if (rest.length() != 1)
+ {
+ chatLog(_("Party prefix must be one character long."), BY_SERVER);
+ }
+ else
+ {
+ if (rest == "/")
+ {
+ chatLog(_("Cannot use a '/' as the prefix."), BY_SERVER);
+ }
+ else
+ {
+ mPartyPrefix = rest.at(0);
+ chatLog(_("Changing prefix to ") + rest, BY_SERVER);
+ }
+ }
+ }
+ else
+ mParty->respond(command, rest);
+}
+
+void ChatWindow::help(const std::string & msg1, const std::string & msg2)
{
chatLog(_("-- Help --"), BY_SERVER);
- if (msg1 == "")
+ if (msg1 == "")
{
chatLog(_("/announce: Global announcement (GM only)"), BY_SERVER);
chatLog(_("/clear: Clears this window"), BY_SERVER);
chatLog(_("/help: Display this help"), BY_SERVER);
+ mParty->help();
+ chatLog(_("/msg <nick> <message>: Alternate form for /whisper"), BY_SERVER);
+ chatLog(_("/present: Get list of players present"), BY_SERVER);
+ mRecorder->help();
+ chatLog(_("/toggle: Determine whether <return> toggles the chat log."),
+ BY_SERVER);
chatLog(_("/where: Display map name"), BY_SERVER);
+ chatLog(_("/w <nick> <message>: Short form for /whisper"), BY_SERVER);
chatLog(_("/whisper <nick> <message>: Sends a private <message>"
" to <nick>"), BY_SERVER);
- chatLog(_("/w <nick> <message>: Short form for /whisper"), BY_SERVER);
chatLog(_("/who: Display number of online users"), BY_SERVER);
chatLog(_("For more information, type /help <command>"), BY_SERVER);
- return;
}
- if (msg1 == "announce")
+ else if (msg1 == "announce")
{
chatLog(_("Command: /announce <msg>"), BY_SERVER);
chatLog(_("*** only available to a GM ***"), BY_SERVER);
chatLog(_("This command sends the message <msg> to "
"all players currently online."), BY_SERVER);
- return;
}
- if (msg1 == "clear")
+ else if (msg1 == "clear")
{
chatLog(_("Command: /clear"), BY_SERVER);
chatLog(_("This command clears the chat log of previous chat."),
BY_SERVER);
- return;
}
- if (msg1 == "help")
+ else if (msg1 == "help")
{
chatLog(_("Command: /help"), BY_SERVER);
chatLog(_("This command displays a list of all commands available."),
BY_SERVER);
chatLog(_("Command: /help <command>"), BY_SERVER);
chatLog(_("This command displays help on <command>."), BY_SERVER);
- return;
}
- if (msg1 == "where")
+ else if (msg1 == "party")
+ {
+ mParty->help(msg2);
+ }
+ else if (msg1 == "present")
+ {
+ chatLog(_("Command: /present"), BY_SERVER);
+ chatLog(_("This command gets a list of players within hearing and "
+ "sends it to either the record log if recording, or the chat "
+ "log otherwise."), BY_SERVER);
+ }
+ else if (msg1 == "record")
+ {
+ mRecorder->help(msg2);
+ }
+ else if (msg1 == "toggle")
+ {
+ chatLog(_("Command: /toggle <state>"), BY_SERVER);
+ chatLog(_("This command sets whether the return key should toggle the"
+ "chat log, or whether the chat log turns off automatically."),
+ BY_SERVER);
+ chatLog(_("<state> can be one of \"1\", \"yes\", \"true\" to "
+ "turn the toggle on, or \"0\", \"no\", \"false\" to turn the "
+ "toggle off."), BY_SERVER);
+ chatLog(_("Command: /toggle"), BY_SERVER);
+ chatLog(_("This command displays the return toggle status."), BY_SERVER);
+ }
+ else if (msg1 == "where")
{
chatLog(_("Command: /where"), BY_SERVER);
chatLog(_("This command displays the name of the current map."),
BY_SERVER);
- return;
}
- if (msg1 == "whisper" || msg1 == "w")
+ else if (msg1 == "whisper" || msg1 == "msg" || msg1 == "w")
{
+ chatLog(_("Command: /msg <nick> <msg>"), BY_SERVER);
chatLog(_("Command: /whisper <nick> <msg>"), BY_SERVER);
chatLog(_("Command: /w <nick> <msg>"), BY_SERVER);
chatLog(_("This command sends the message <msg> to <nick>."),
BY_SERVER);
chatLog(_("If the <nick> has spaces in it, enclose it in "
- "double quotes (\")."), BY_SERVER);
- return;
+ "double quotes (\")."), BY_SERVER);
}
- if (msg1 == "who")
+ else if (msg1 == "who")
{
chatLog(_("Command: /who"), BY_SERVER);
chatLog(_("This command displays the number of players currently "
- "online."), BY_SERVER);
- return;
+ "online."), BY_SERVER);
+ }
+ else
+ {
+ chatLog(_("Unknown command."), BY_SERVER);
+ chatLog(_("Type /help for a list of commands."), BY_SERVER);
}
- chatLog(_("Unknown command."), BY_SERVER);
- chatLog(_("Type /help for a list of commands."), BY_SERVER);
}
diff --git a/src/gui/chat.h b/src/gui/chat.h
index ad89c8dc..176fccb7 100644
--- a/src/gui/chat.h
+++ b/src/gui/chat.h
@@ -22,6 +22,7 @@
#ifndef CHAT_H
#define CHAT_H
+#include <fstream>
#include <list>
#include <string>
@@ -34,32 +35,21 @@
class BrowserBox;
class Network;
+class Recorder;
+class Party;
class ScrollArea;
+class ItemLinkHandler;
#define BY_GM 0 // those should be self-explanatory =)
#define BY_PLAYER 1
#define BY_OTHER 2
#define BY_SERVER 3
+#define BY_PARTY 4
-#define ACT_WHISPER 4 // getting whispered at
-#define ACT_IS 5 // equivalent to "/me" on IRC
-
-#define BY_LOGGER 6
-
-#define IS_ANNOUNCE "/announce "
-#define IS_ANNOUNCE_LENGTH 10
-#define IS_HELP "/help"
-#define IS_HELP_LENGTH 5
-#define IS_WHERE "/where"
-#define IS_WHERE_LENGTH 6
-#define IS_WHO "/who"
-#define IS_WHO_LENGTH 4
-#define IS_CLEAR "/clear"
-#define IS_CLEAR_LENGTH 6
-#define IS_WHISPER "/whisper"
-#define IS_WHISPER_LENGTH 8
-#define IS_SHORT_WHISPER "/w"
-#define IS_SHORT_WHISPER_LENGTH 2
+#define ACT_WHISPER 5 // getting whispered at
+#define ACT_IS 6 // equivalent to "/me" on IRC
+
+#define BY_LOGGER 7
/**
* gets in between usernick and message text depending on
@@ -127,14 +117,19 @@ class ChatWindow : public Window, public gcn::ActionListener,
ChatWindow(Network *network);
/**
+ * Destructor: used to write back values to the config file
+ */
+ ~ChatWindow();
+
+ /**
* Adds a line of text to our message list. Parameters:
*
* @param line Text message.
* @parem own Type of message (usually the owner-type).
*/
- void chatLog(std::string line, int own);
+ void chatLog(std::string line, int own, bool ignoreRecord = false);
- /*
+ /**
* Calls original chat_log() after processing the packet.
*/
void chatLog(CHATSKILL);
@@ -186,6 +181,9 @@ class ChatWindow : public Window, public gcn::ActionListener,
/** Called to set current text */
void setInputText(std::string input_str);
+ /** Called to add item to chat */
+ void addItemText(int itemid, const std::string &item);
+
/** Override to reset mTmpVisible */
void setVisible(bool visible);
@@ -199,6 +197,14 @@ class ChatWindow : public Window, public gcn::ActionListener,
void scroll(int amount);
/**
+ * party implements the partying chat commands
+ *
+ * @param command is the party command to perform
+ * @param msg is the remainder of the message
+ */
+ void party(const std::string &command, const std::string &msg);
+
+ /**
* help implements the /help command
*
* @param msg1 is the command that the player needs help on
@@ -207,10 +213,11 @@ class ChatWindow : public Window, public gcn::ActionListener,
void help(const std::string &msg1, const std::string &msg2);
private:
+
Network *mNetwork;
bool mTmpVisible;
- void whisper(const std::string &nick, std::string msg, int prefixlen);
+ void whisper(const std::string &nick, std::string msg);
/** One item in the chat log */
struct CHATLOG
@@ -226,13 +233,19 @@ class ChatWindow : public Window, public gcn::ActionListener,
gcn::TextField *mChatInput; /**< Input box for typing chat messages */
BrowserBox *mTextOutput; /**< Text box for displaying chat history */
ScrollArea *mScrollArea; /**< Scroll area around text output */
-
+ ItemLinkHandler *mItemLinkHandler; /** Used for showing item popup on
+ clicking links **/
typedef std::list<std::string> History;
typedef History::iterator HistoryIterator;
History mHistory; /**< Command history */
HistoryIterator mCurHist; /**< History iterator */
+ Recorder *mRecorder; /**< Recording class */
+ char mPartyPrefix; /**< Messages beginning with the prefix are sent to
+ the party */
+ bool mReturnToggles; /**< Marks whether <Return> toggles the chat log
+ or not */
+ Party *mParty;
};
-
extern ChatWindow *chatWindow;
#endif
diff --git a/src/gui/chatinput.h b/src/gui/chatinput.h
index 07144c5b..d98e120b 100644
--- a/src/gui/chatinput.h
+++ b/src/gui/chatinput.h
@@ -22,9 +22,11 @@
#ifndef CHATINPUT_H
#define CHATINPUT_H
+#include <guichan/focuslistener.hpp>
+
#include "textfield.h"
-#include <guichan/focuslistener.hpp>
+#include "../guichanfwd.h"
/**
* The chat input hides when it loses focus. It is also invisible by default.
diff --git a/src/gui/checkbox.h b/src/gui/checkbox.h
index 4b312d22..d92fc822 100644
--- a/src/gui/checkbox.h
+++ b/src/gui/checkbox.h
@@ -26,6 +26,8 @@
#include <guichan/widgets/checkbox.hpp>
+#include "../guichanfwd.h"
+
class Image;
/**
diff --git a/src/gui/colour.cpp b/src/gui/colour.cpp
new file mode 100644
index 00000000..816420ed
--- /dev/null
+++ b/src/gui/colour.cpp
@@ -0,0 +1,139 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Douglas Boffey *
+ * *
+ * DougABoffey@netscape.net *
+ * 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 *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed with The Mana Experiment *
+ * 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 <cstdio>
+
+#include "colour.h"
+
+#include "../configuration.h"
+
+#include "../utils/gettext.h"
+
+Colour::Colour()
+{
+ addColour('C', 0x000000, _("Chat"));
+ addColour('G', 0xff0000, _("GM"));
+ addColour('Y', 0x1fa052, _("Player"));
+ addColour('W', 0x0000ff, _("Whisper"));
+ addColour('I', 0xf1dc27, _("Is"));
+ addColour('P', 0xff00d8, _("Party"));
+ addColour('S', 0x8415e2, _("Server"));
+ addColour('L', 0x919191, _("Logger"));
+ addColour('<', 0xe50d0d, _("Hyperlink"));
+ commit();
+}
+
+Colour::~Colour()
+{
+ for (ColVector::iterator col = mColVector.begin(),
+ colEnd = mColVector.end();
+ col != colEnd;
+ ++col)
+ {
+ char buffer[20];
+ std::sprintf(buffer, "0x%06x", col->rgb);
+ config.setValue("Colour" + col->text, buffer);
+ }
+}
+
+void Colour::setColour(const char c, const int rgb)
+{
+ for (ColVector::iterator col = mColVector.begin(),
+ colEnd = mColVector.end();
+ col != colEnd;
+ ++col)
+ {
+ if (col->ch == c)
+ {
+ col->rgb = rgb;
+ return;
+ }
+ }
+}
+
+int Colour::getColour(const char c, bool &valid) const
+{
+ for (ColVector::const_iterator col = mColVector.begin(),
+ colEnd = mColVector.end();
+ col != colEnd;
+ ++col)
+ {
+ if (col->ch == c)
+ {
+ valid = true;
+ return col->rgb;
+ }
+ }
+ valid = false;
+ return 0x000000;
+}
+
+std::string Colour::getElementAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return mColVector[i].text;
+}
+
+void Colour::addColour(const char c, const int rgb, const std::string &text)
+{
+ int trueRgb = config.getValue("Colour" + text, rgb);
+ mColVector.push_back(ColourElem(c, trueRgb, text));
+}
+
+int Colour::getColourAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return 0;
+ }
+ return mColVector[i].rgb;
+}
+
+void Colour::setColourAt(int i, int rgb)
+{
+ if (i >= 0 && i < getNumberOfElements())
+ {
+ mColVector[i].rgb = rgb;
+ }
+}
+
+void Colour::commit()
+{
+ for (ColVector::iterator i = mColVector.begin(), iEnd = mColVector.end();
+ i != iEnd;
+ ++i)
+ {
+ i->committedRgb = i->rgb;
+ }
+}
+
+void Colour::rollback()
+{
+ for (ColVector::iterator i = mColVector.begin(), iEnd = mColVector.end();
+ i != iEnd;
+ ++i)
+ {
+ i->rgb = i->committedRgb;
+ }
+}
diff --git a/src/gui/colour.h b/src/gui/colour.h
new file mode 100644
index 00000000..1e8ba3db
--- /dev/null
+++ b/src/gui/colour.h
@@ -0,0 +1,133 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Douglas Boffey *
+ * *
+ * DougABoffey@netscape.net *
+ * 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 *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed with The Mana Experiment *
+ * 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 _COLOUR_H
+#define _COLOUR_H
+
+#include <cstdio>
+#include <string>
+#include <vector>
+
+#include <guichan/listmodel.hpp>
+
+#include "../guichanfwd.h"
+
+class Colour : public gcn::ListModel
+{
+ public:
+ /**
+ * Constructor
+ */
+ Colour();
+
+ /**
+ * Destructor
+ */
+ ~Colour();
+
+ /**
+ * Define the colour replacement for a character
+ *
+ * @param c charater to be replaced
+ * @param rgb colour to replace character
+ */
+ void setColour(const char c, const int rgb);
+
+ /**
+ * Define the colour replacement for a character
+ *
+ * @param c character to be replaced
+ * @param r red component
+ * @param g green component
+ * @param b blue component
+ */
+ void setColour(const char c, const int r, const int g, const int b)
+ {
+ setColour(c, (r << 16) | (g << 8) | b);
+ }
+
+ /**
+ * Return the colour associated with a character, if exists
+ *
+ * @param c character requested
+ * @param valid indicate whether character is known
+ */
+ int getColour(const char c, bool &valid) const;
+
+ /**
+ * Return the number of colours known
+ */
+ int getNumberOfElements() {return mColVector.size(); }
+
+ /**
+ * Return the name of the ith colour
+ *
+ * @param i index of colour interested in
+ */
+ std::string getElementAt(int i);
+
+ /**
+ * Get the colour for the element at index i in the current colour
+ * model
+ */
+ int getColourAt(int i);
+
+ /**
+ * Set the colour for the element at index i
+ */
+ void setColourAt(int i, int rgb);
+
+ /**
+ * Commit the colours
+ */
+ void commit();
+
+ /**
+ * Rollback the colours
+ */
+ void rollback();
+
+ private:
+ struct ColourElem
+ {
+ ColourElem(const char c, const int rgb, const std::string &text) :
+ ch(c), rgb(rgb), text(text) {}
+ char ch;
+ int rgb;
+ int committedRgb;
+ std::string text;
+ };
+ typedef std::vector<ColourElem> ColVector;
+ ColVector mColVector;
+
+ /**
+ * Initialise colour
+ *
+ * @param c character that needs initialising
+ * @param rgb default colour if not found in config
+ * @param text identifier of colour
+ */
+ void addColour(const char c, const int rgb, const std::string &text);
+};
+
+extern Colour *textColour;
+
+#endif
diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp
index 46b7c971..569fd93f 100644
--- a/src/gui/confirm_dialog.cpp
+++ b/src/gui/confirm_dialog.cpp
@@ -19,11 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "confirm_dialog.h"
-
-#include <guichan/widgets/label.hpp>
+#include <guichan/font.hpp>
-#include "button.h"
+#include "confirm_dialog.h"
#include "../utils/gettext.h"
@@ -31,28 +29,51 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg,
Window *parent):
Window(title, true, parent)
{
- gcn::Label *textLabel = new gcn::Label(msg);
+ mTextBox = new TextBox();
+ mTextBox->setEditable(false);
+ mTextBox->setOpaque(false);
+
+ mTextArea = new ScrollArea(mTextBox);
gcn::Button *yesButton = new Button(_("Yes"), "yes", this);
gcn::Button *noButton = new Button(_("No"), "no", this);
- int w = textLabel->getWidth() + 20;
+ mTextArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setOpaque(false);
+
+ mTextBox->setMinWidth(260);
+ mTextBox->setTextWrapped(msg);
+
+ int numRows = mTextBox->getNumberOfRows();
+ int width = getFont()->getWidth(title);
int inWidth = yesButton->getWidth() + noButton->getWidth() + 5;
- int h = textLabel->getHeight() + 25 + yesButton->getHeight();
- if (w < inWidth + 10) {
- w = inWidth + 10;
+ if (numRows > 1)
+ {
+ // 15 == height of each line of text (based on font heights)
+ // 14 == row top + bottom graphic pixel heights
+ setContentSize(mTextBox->getMinWidth() + 15, 15 + (numRows * 15) + noButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, mTextBox->getMinWidth() + 5,
+ 3 + (numRows * 14)));
+ }
+ else
+ {
+ if (width < getFont()->getWidth(msg))
+ width = getFont()->getWidth(msg);
+ if (width < inWidth)
+ width = inWidth;
+ setContentSize(width + 15, 30 + noButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, width + 5, 17));
}
- setContentSize(w, h);
- textLabel->setPosition(10, 10);
yesButton->setPosition(
- (w - inWidth) / 2,
- h - 5 - noButton->getHeight());
+ (mTextBox->getMinWidth() - inWidth) / 2,
+ (numRows * 14) + noButton->getHeight() - 8);
noButton->setPosition(
yesButton->getX() + yesButton->getWidth() + 5,
- h - 5 - noButton->getHeight());
+ (numRows * 14) + noButton->getHeight() - 8);
- add(textLabel);
+ add(mTextArea);
add(yesButton);
add(noButton);
@@ -64,6 +85,11 @@ ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg,
yesButton->requestFocus();
}
+unsigned int ConfirmDialog::getNumRows()
+{
+ return mTextBox->getNumberOfRows();
+}
+
void ConfirmDialog::action(const gcn::ActionEvent &event)
{
// Proxy button events to our listeners
diff --git a/src/gui/confirm_dialog.h b/src/gui/confirm_dialog.h
index 69b3e9e4..fb8290c8 100644
--- a/src/gui/confirm_dialog.h
+++ b/src/gui/confirm_dialog.h
@@ -24,8 +24,12 @@
#include <guichan/actionlistener.hpp>
+#include "button.h"
+#include "scrollarea.h"
+#include "textbox.h"
#include "window.h"
+#include "../guichanfwd.h"
/**
* An option dialog.
@@ -42,10 +46,17 @@ class ConfirmDialog : public Window, public gcn::ActionListener {
ConfirmDialog(const std::string &title, const std::string &msg,
Window *parent = NULL);
+ unsigned int getNumRows();
+
/**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
+
+ private:
+ TextBox *mTextBox;
+ ScrollArea *mTextArea;
+ gcn::Button *okButton;
};
#endif
diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp
index f73bb74d..15d85bbc 100644
--- a/src/gui/connection.cpp
+++ b/src/gui/connection.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "connection.h"
-
#include <guichan/actionlistener.hpp>
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "connection.h"
#include "progressbar.h"
#include "../main.h"
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 669aabd2..223b7fbd 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "debugwindow.h"
-
#include <SDL_mouse.h>
#include <guichan/widgets/label.hpp>
#include "button.h"
+#include "debugwindow.h"
#include "gui.h"
#include "viewport.h"
diff --git a/src/gui/emotecontainer.cpp b/src/gui/emotecontainer.cpp
new file mode 100644
index 00000000..fa63d4bb
--- /dev/null
+++ b/src/gui/emotecontainer.cpp
@@ -0,0 +1,172 @@
+/*
+ * Aethyra
+ * Copyright 2009 Aethyra Development Team
+ *
+ * This file is part of Aethyra.
+ *
+ * Aethyra 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.
+ *
+ * Aethyra 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 Aethyra; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/mouseinput.hpp>
+#include <guichan/selectionlistener.hpp>
+
+#include "emotecontainer.h"
+
+#include "../animatedsprite.h"
+#include "../configuration.h"
+#include "../emoteshortcut.h"
+#include "../graphics.h"
+#include "../localplayer.h"
+#include "../log.h"
+
+#include "../resources/emotedb.h"
+#include "../resources/image.h"
+#include "../resources/iteminfo.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/dtor.h"
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+const int EmoteContainer::gridWidth = 34; // emote icon width + 4
+const int EmoteContainer::gridHeight = 36; // emote icon height + 4
+
+static const int NO_EMOTE = -1;
+
+EmoteContainer::EmoteContainer():
+ mSelectedEmoteIndex(NO_EMOTE)
+{
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); i++)
+ {
+ mEmoteImg.push_back(player_node->getEmote(i));
+ }
+
+ mSelImg = resman->getImage("graphics/gui/selection.png");
+ if (!mSelImg) logger->error(_("Unable to load selection.png"));
+
+ mSelImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ mMaxEmote = EmoteDB::getLast() + 1;
+
+ addMouseListener(this);
+ addWidgetListener(this);
+}
+
+EmoteContainer::~EmoteContainer()
+{
+ if (!mSelImg)
+ {
+ mSelImg->decRef();
+ mSelImg = NULL;
+ }
+}
+
+void EmoteContainer::draw(gcn::Graphics *graphics)
+{
+ int columns = getWidth() / gridWidth;
+
+ // Have at least 1 column
+ if (columns < 1)
+ {
+ columns = 1;
+ }
+
+ for (int i = 0; i < mMaxEmote ; i++)
+ {
+ int emoteX = ((i) % columns) * gridWidth;
+ int emoteY = ((i) / columns) * gridHeight;
+
+ // Draw emote icon
+ mEmoteImg[i]->draw(static_cast<Graphics*>(graphics), emoteX, emoteY);
+
+ // Draw selection image below selected item
+ if (mSelectedEmoteIndex == i)
+ {
+ static_cast<Graphics*>(graphics)->drawImage(
+ mSelImg, emoteX, emoteY);
+ }
+ }
+}
+
+void EmoteContainer::widgetResized(const gcn::Event &event)
+{
+ recalculateHeight();
+}
+
+void EmoteContainer::recalculateHeight()
+{
+ int cols = getWidth() / gridWidth;
+
+ if (cols < 1)
+ cols = 1;
+
+ const int rows = (mMaxEmote / cols) + (mMaxEmote % cols > 0 ? 1 : 0);
+ const int height = rows * gridHeight + 8;
+ if (height != getHeight())
+ setHeight(height);
+}
+
+int EmoteContainer::getSelectedEmote()
+{
+ if (mSelectedEmoteIndex == NO_EMOTE)
+ return 0;
+
+ return 1 + mSelectedEmoteIndex;
+}
+
+void EmoteContainer::selectNone()
+{
+ setSelectedEmoteIndex(NO_EMOTE);
+}
+
+void EmoteContainer::setSelectedEmoteIndex(int index)
+{
+ if (index < 0 || index >= mMaxEmote )
+ mSelectedEmoteIndex = NO_EMOTE;
+ else
+ mSelectedEmoteIndex = index;
+}
+
+void EmoteContainer::distributeValueChangedEvent()
+{
+ gcn::SelectionEvent event(this);
+ std::list<gcn::SelectionListener*>::iterator i_end = mListeners.end();
+ std::list<gcn::SelectionListener*>::iterator i;
+
+ for (i = mListeners.begin(); i != i_end; ++i)
+ {
+ (*i)->valueChanged(event);
+ }
+}
+
+void EmoteContainer::mousePressed(gcn::MouseEvent &event)
+{
+ int button = event.getButton();
+ if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
+ {
+ int columns = getWidth() / gridWidth;
+ int mx = event.getX();
+ int my = event.getY();
+ int index = mx / gridWidth + ((my / gridHeight) * columns);
+ if (index < mMaxEmote)
+ {
+ setSelectedEmoteIndex(index);
+ emoteShortcut->setEmoteSelected(index + 1);
+ }
+ }
+}
diff --git a/src/gui/emotecontainer.h b/src/gui/emotecontainer.h
new file mode 100644
index 00000000..8e52a206
--- /dev/null
+++ b/src/gui/emotecontainer.h
@@ -0,0 +1,138 @@
+/*
+ * Aethyra
+ * Copyright 2009 Aethyra Development Team
+ *
+ * This file is part of Aethyra.
+ *
+ * Aethyra 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.
+ *
+ * Aethyra 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 Aethyra; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTECONTAINER_H__
+#define EMOTECONTAINER_H__
+
+#include <list>
+#include <vector>
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+#include <guichan/widgetlistener.hpp>
+
+#include "../guichanfwd.h"
+
+class AnimatedSprite;
+class Image;
+
+namespace gcn {
+ class SelectionListener;
+}
+
+/**
+ * An emote container. Used to show emotes in inventory and trade dialog.
+ *
+ * \ingroup GUI
+ */
+class EmoteContainer : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::WidgetListener
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ EmoteContainer();
+
+ /**
+ * Destructor.
+ */
+ virtual ~EmoteContainer();
+
+ /**
+ * Draws the emotes.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ /**
+ * Called whenever the widget changes size.
+ */
+ void widgetResized(const gcn::Event &event);
+
+ /**
+ * Handles mouse click.
+ */
+ void mousePressed(gcn::MouseEvent &event);
+
+ /**
+ * Returns the selected emote.
+ */
+ int getSelectedEmote();
+
+ /**
+ * Sets selected emote 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)
+ {
+ mListeners.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)
+ {
+ mListeners.remove(listener);
+ }
+
+ private:
+ /**
+
+ * Sets the currently selected emote. Invalid (e.g., negative) indices set `no emotr'.
+ */
+ void setSelectedEmoteIndex(int index);
+
+ /**
+ * Find the current emote index by the most recently used emote ID
+ */
+ void refindSelectedEmote(void);
+
+ /**
+ * Determine and set the height of the container.
+ */
+ void recalculateHeight(void);
+
+ /**
+ * Sends out selection events to the list of selection listeners.
+ */
+ void distributeValueChangedEvent(void);
+
+ std::vector<AnimatedSprite*> mEmoteImg;
+ Image *mSelImg;
+ int mSelectedEmoteIndex;
+
+ int mMaxEmote;
+
+ std::list<gcn::SelectionListener*> mListeners;
+
+ static const int gridWidth;
+ static const int gridHeight;
+};
+
+#endif
diff --git a/src/gui/emoteshortcutcontainer.cpp b/src/gui/emoteshortcutcontainer.cpp
new file mode 100644
index 00000000..f5ee9843
--- /dev/null
+++ b/src/gui/emoteshortcutcontainer.cpp
@@ -0,0 +1,195 @@
+/*
+ * Aethyra
+ * Copyright 2009 Aethyra Development Team
+ *
+ * This file is part of Aethyra.
+ *
+ * Aethyra 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.
+ *
+ * Aethyra 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 Aethyra; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "emoteshortcutcontainer.h"
+
+#include "../animatedsprite.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 "../resources/emotedb.h"
+#include "../resources/image.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/dtor.h"
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+static const int MAX_ITEMS = 12;
+
+EmoteShortcutContainer::EmoteShortcutContainer():
+ mEmoteClicked(false),
+ mEmoteMoved(0)
+{
+ mGridWidth = 1,
+ mGridHeight = 1,
+ addMouseListener(this);
+ addWidgetListener(this);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
+
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); i++)
+ {
+ mEmoteImg.push_back(player_node->getEmote(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)
+{
+ 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(0x000000);
+ 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.
+ 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/emoteshortcutcontainer.h b/src/gui/emoteshortcutcontainer.h
new file mode 100644
index 00000000..cffaee6f
--- /dev/null
+++ b/src/gui/emoteshortcutcontainer.h
@@ -0,0 +1,81 @@
+/*
+ * Aethyra
+ * Copyright 2009 Aethyra Development Team
+ *
+ * This file is part of Aethyra.
+ *
+ * Aethyra 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.
+ *
+ * Aethyra 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 Aethyra; 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 <guichan/mouselistener.hpp>
+
+#include "shortcutcontainer.h"
+
+#include "../guichanfwd.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<AnimatedSprite*> mEmoteImg;
+
+ bool mEmoteClicked;
+ int mEmoteMoved;
+};
+
+#endif
diff --git a/src/gui/emotewindow.cpp b/src/gui/emotewindow.cpp
new file mode 100644
index 00000000..b4e9c735
--- /dev/null
+++ b/src/gui/emotewindow.cpp
@@ -0,0 +1,82 @@
+/*
+ * Aethyra
+ * Copyright 2009 Aethyra Development Team
+ *
+ * This file is part of Aethyra.
+ *
+ * Aethyra 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.
+ *
+ * Aethyra 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 Aethyra; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+
+#include <guichan/mouseinput.hpp>
+
+#include "button.h"
+#include "gui.h"
+#include "emotewindow.h"
+#include "emotecontainer.h"
+#include "scrollarea.h"
+#include "textbox.h"
+
+#include "widgets/layout.h"
+
+#include "../localplayer.h"
+
+#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+EmoteWindow::EmoteWindow():
+ Window(_("Emote"))
+{
+ setWindowName(_("Emote"));
+ setResizable(true);
+ setCloseButton(true);
+ setMinWidth(80);
+ setMinHeight(130);
+ setDefaultSize(115, 25, 322, 200);
+
+ mUseButton = new Button(_("Use"), "use", this);
+
+ mEmotes = new EmoteContainer();
+ mEmotes->addSelectionListener(this);
+
+ mEmoteScroll = new ScrollArea(mEmotes);
+ mEmoteScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ place(0, 0, mEmoteScroll, 5, 4);
+ place(4, 4, mUseButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+
+ mUseButton->setSize(60, mUseButton->getHeight());
+
+ loadWindowState();
+}
+
+void EmoteWindow::action(const gcn::ActionEvent &event)
+{
+ int emote = mEmotes->getSelectedEmote();
+
+ if (!emote)
+ return;
+
+ player_node->emote(emote);
+}
+
+int EmoteWindow::getSelectedEmote() const
+{
+ return mEmotes->getSelectedEmote();
+}
diff --git a/src/gui/emotewindow.h b/src/gui/emotewindow.h
new file mode 100644
index 00000000..8e36e5ce
--- /dev/null
+++ b/src/gui/emotewindow.h
@@ -0,0 +1,68 @@
+/*
+ * Aethyra
+ * Copyright 2009 Aethyra Development Team
+ *
+ * This file is part of Aethyra.
+ *
+ * Aethyra 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.
+ *
+ * Aethyra 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 Aethyra; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef EMOTEWINDOW_H
+#define EMOTEWINDOW_H
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/selectionlistener.hpp>
+
+#include "window.h"
+
+#include "../guichanfwd.h"
+
+class EmoteContainer;
+class TextBox;
+
+/**
+ * Emote dialog.
+ *
+ * \ingroup Interface
+ */
+class EmoteWindow : public Window, gcn::ActionListener,
+ gcn::SelectionListener
+{
+ public:
+ /**
+ * Constructor.
+ */
+ EmoteWindow();
+
+ /**
+ * Called when receiving actions from the widgets.
+ */
+ void action(const gcn::ActionEvent &event);
+
+ /**
+ * Returns the selected item.
+ */
+ int getSelectedEmote() const;
+
+ private:
+ EmoteContainer *mEmotes;
+
+ gcn::Button *mUseButton;
+ gcn::ScrollArea *mEmoteScroll;
+};
+
+extern EmoteWindow *emoteWindow;
+
+#endif
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index aa6825f2..1fb2b601 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -19,14 +19,20 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define BOX_WIDTH 36
+#define BOX_HEIGHT 36
+
+#include <guichan/font.hpp>
+
+#include "button.h"
#include "equipmentwindow.h"
+#include "playerbox.h"
#include "../equipment.h"
-#include "../inventory.h"
-#include "../localplayer.h"
#include "../graphics.h"
+#include "../inventory.h"
#include "../item.h"
-#include "../log.h"
+#include "../localplayer.h"
#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
@@ -34,19 +40,57 @@
#include "../utils/gettext.h"
#include "../utils/tostring.h"
+// Positions of the boxes, 2nd dimension is X and Y respectively.
+static const int boxPosition[][2] = {
+ {50, 208}, // EQUIP_LEGS_SLOT
+ {8, 123}, // EQUIP_FIGHT1_SLOT
+ {8, 78}, // EQUIP_GLOVES_SLOT
+ {129, 168}, // EQUIP_RING2_SLOT
+ {8, 168}, // EQUIP_RING1_SLOT
+ {129, 123}, // EQUIP_FIGHT2_SLOT
+ {90, 208}, // EQUIP_FEET_SLOT
+ {50, 40}, // EQUIP_CAPE_SLOT
+ {70, 0}, // EQUIP_HEAD_SLOT
+ {90, 40}, // EQUIP_TORSO_SLOT
+ {129, 78} // EQUIP_AMMO_SLOT
+};
+
EquipmentWindow::EquipmentWindow(Equipment *equipment):
Window(_("Equipment")),
- mEquipment(equipment)
+ mEquipment(equipment),
+ mSelected(-1)
+
{
+ // Control that shows the Player
+ mPlayerBox = new PlayerBox;
+ mPlayerBox->setDimension(gcn::Rectangle(50, 80, 74, 123));
+ mPlayerBox->setPlayer(player_node);
+
setWindowName("Equipment");
setCloseButton(true);
- setDefaultSize(5, 230, 200, 140);
+ setDefaultSize(5, 195, 180, 300);
loadWindowState();
+
+ mUnequip = new Button(_("Unequip"), "unequip", this);
+ gcn::Rectangle const &area = getChildrenArea();
+ mUnequip->setPosition(area.width - mUnequip->getWidth() - 5,
+ area.height - mUnequip->getHeight() - 5);
+
+ add(mPlayerBox);
+ add(mUnequip);
+
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+ {
+ mEquipBox[i].posX = boxPosition[i][0] + getPadding();
+ mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight();
+ }
+
mInventory = player_node->getInventory();
}
EquipmentWindow::~EquipmentWindow()
{
+ delete mUnequip;
}
void EquipmentWindow::draw(gcn::Graphics *graphics)
@@ -54,37 +98,85 @@ void EquipmentWindow::draw(gcn::Graphics *graphics)
// Draw window graphics
Window::draw(graphics);
- Item *item;
- Image *image;
+ Item* item;
- // Rectangles around items are black
- graphics->setColor(gcn::Color(0, 0, 0));
+ Graphics *g = static_cast<Graphics*>(graphics);
- for (int i = 0; i < EQUIPMENT_SIZE; i++) {
- graphics->drawRectangle(gcn::Rectangle(10 + 36 * (i % 4),
- 36 * (i / 4) + 25, 32, 32));
+ Window::drawChildren(graphics);
- if (!(item = mInventory->getItem(mEquipment->getEquipment(i))))
- continue;
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
+ {
+ item = (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+ if (item)
+ {
+ // Draw Item.
+ Image* image = item->getImage();
+ g->drawImage(image, mEquipBox[i].posX, mEquipBox[i].posY);
+ if (i == EQUIP_AMMO_SLOT)
+ {
+ g->setColor(gcn::Color(0, 0, 0));
+ graphics->drawText(toString(item->getQuantity()),
+ mEquipBox[i].posX + (BOX_WIDTH / 2),
+ mEquipBox[i].posY - getFont()->getHeight(),
+ gcn::Graphics::CENTER);
+ }
+ }
- image = item->getImage();
- if (image)
+ if (i == mSelected)
+ {
+ // Set color red.
+ g->setColor(gcn::Color(255, 0, 0));
+ }
+ else
{
- static_cast<Graphics*>(graphics)->drawImage(
- image, 36 * (i % 4) + 10, 36 * (i / 4) + 25);
+ // Set color black.
+ g->setColor(gcn::Color(0, 0, 0));
}
+
+ // Draw box border.
+ g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT));
+ }
+}
+
+void EquipmentWindow::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "unequip" && mSelected > -1)
+ {
+ Item* item = (mSelected != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(mSelected)) :
+ mInventory->getItem(mEquipment->getArrows());
+ player_node->unequipItem(item);
+ mSelected = -1;
}
+}
+
+void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent)
+{
+ Window::mousePressed(mouseEvent);
- graphics->drawRectangle(gcn::Rectangle(160, 25, 32, 32));
+ const int x = mouseEvent.getX();
+ const int y = mouseEvent.getY();
- if (!(item = mInventory->getItem(mEquipment->getArrows())))
- return;
+ Item* item;
- image = item->getImage();
- if (image)
+ // Checks if any of the presses were in the equip boxes.
+ for (int i = EQUIP_LEGS_SLOT; i < EQUIP_VECTOREND; i++)
{
- static_cast<Graphics*>(graphics)->drawImage(image, 160, 25);
+ item = (i != EQUIP_AMMO_SLOT) ?
+ mInventory->getItem(mEquipment->getEquipment(i)) :
+ mInventory->getItem(mEquipment->getArrows());
+ gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY,
+ BOX_WIDTH, BOX_HEIGHT);
+ if (tRect.isPointInRect(x, y))
+ {
+ if (item)
+ {
+ mSelected = i;
+ }
+ }
}
- graphics->drawText(toString(item->getQuantity()), 170, 62,
- gcn::Graphics::CENTER);
}
+
diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h
index e2420134..0b3aede0 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -22,17 +22,29 @@
#ifndef EQUIPMENTWINDOW_H
#define EQUIPMENTWINDOW_H
+#include <guichan/actionlistener.hpp>
+
#include "window.h"
-#include "../inventory.h"
class Equipment;
+class Inventory;
+class PlayerBox;
+
+/**
+ * Equipment box.
+ */
+struct EquipBox
+{
+ int posX;
+ int posY;
+};
/**
* Equipment dialog.
*
* \ingroup Interface
*/
-class EquipmentWindow : public Window
+class EquipmentWindow : public Window, public gcn::ActionListener
{
public:
/**
@@ -50,9 +62,36 @@ class EquipmentWindow : public Window
*/
void draw(gcn::Graphics *graphics);
+ void action(const gcn::ActionEvent &event);
+
+ void mousePressed(gcn::MouseEvent& mouseEvent);
+
+ enum {
+ // Equipment rules:
+ EQUIP_LEGS_SLOT = 0,
+ EQUIP_FIGHT1_SLOT,
+ EQUIP_GLOVES_SLOT,
+ EQUIP_RING2_SLOT,
+ EQUIP_RING1_SLOT,
+ EQUIP_FIGHT2_SLOT,
+ EQUIP_FEET_SLOT,
+ EQUIP_CAPE_SLOT,
+ EQUIP_HEAD_SLOT,
+ EQUIP_TORSO_SLOT,
+ EQUIP_AMMO_SLOT,
+ EQUIP_VECTOREND
+ };
+
+
private:
Equipment *mEquipment;
Inventory *mInventory;
+ gcn::Button *mUnequip; /**< Button for unequipping. */
+ EquipBox mEquipBox[EQUIP_VECTOREND]; /**< Equipment Boxes. */
+
+ PlayerBox *mPlayerBox;
+
+ int mSelected; /**< Index of selected item. */
};
extern EquipmentWindow *equipmentWindow;
diff --git a/src/gui/focushandler.cpp b/src/gui/focushandler.cpp
index 3ceed595..dd605be6 100644
--- a/src/gui/focushandler.cpp
+++ b/src/gui/focushandler.cpp
@@ -21,7 +21,6 @@
#include "focushandler.h"
-
void FocusHandler::requestModalFocus(gcn::Widget *widget)
{
/* If there is another widget with modal focus, remove its modal focus
diff --git a/src/gui/gccontainer.h b/src/gui/gccontainer.h
index da584a42..0a573645 100644
--- a/src/gui/gccontainer.h
+++ b/src/gui/gccontainer.h
@@ -26,6 +26,8 @@
#include <guichan/widgets/container.hpp>
+#include "../guichanfwd.h"
+
/**
* A garbage collecting container. Childs added to this container are
* automatically deleted when the container is deleted.
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index 2da451a3..642e916b 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "gui.h"
-
#include <guichan/exception.hpp>
#include <guichan/image.hpp>
#include <guichan/imagefont.hpp>
#include "focushandler.h"
+#include "gui.h"
#include "sdlinput.h"
#include "truetypefont.h"
#include "viewport.h"
@@ -39,12 +38,12 @@
#include "../resources/image.h"
#include "../resources/imageset.h"
-#include "../resources/resourcemanager.h"
#include "../resources/imageloader.h"
+#include "../resources/resourcemanager.h"
// Guichan stuff
Gui *gui = 0;
-Viewport *viewport = 0; /**< Viewport on the map. */
+Viewport *viewport = 0; /**< Viewport on the map. */
SDLInput *guiInput = 0;
// Fonts used in showing hits
@@ -52,6 +51,9 @@ gcn::Font *hitRedFont = 0;
gcn::Font *hitBlueFont = 0;
gcn::Font *hitYellowFont = 0;
+// Bolded font
+gcn::Font *boldFont = 0;
+
class GuiConfigListener : public ConfigListener
{
public:
@@ -115,14 +117,26 @@ Gui::Gui(Graphics *graphics):
+ e.getMessage());
}
+ // Set bold font
+ path = resman->getPath("fonts/dejavusans-bold.ttf");
+ try {
+ const int fontSize = config.getValue("fontSize", 11);
+ boldFont = new TrueTypeFont(path, fontSize);
+ }
+ catch (gcn::Exception e)
+ {
+ logger->error(std::string("Unable to load dejavusans-bold.ttf: ")
+ + e.getMessage());
+ }
+
gcn::Widget::setGlobalFont(mGuiFont);
// Load hits' colourful fonts
try {
hitRedFont = new gcn::ImageFont("graphics/gui/hits_red.png",
- "0123456789");
+ "0123456789crit! ");
hitBlueFont = new gcn::ImageFont("graphics/gui/hits_blue.png",
- "0123456789");
+ "0123456789crit! ");
hitYellowFont = new gcn::ImageFont("graphics/gui/hits_yellow.png",
"0123456789misxp ");
}
@@ -158,6 +172,7 @@ Gui::~Gui()
mMouseCursors->decRef();
delete mGuiFont;
+ delete boldFont;
delete viewport;
delete getTop();
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 95cd5815..9681d44a 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -26,8 +26,8 @@
#include "../guichanfwd.h"
-class GuiConfigListener;
class Graphics;
+class GuiConfigListener;
class ImageSet;
class SDLInput;
class Viewport;
@@ -125,4 +125,9 @@ extern gcn::Font *hitRedFont;
extern gcn::Font *hitBlueFont;
extern gcn::Font *hitYellowFont;
+/**
+ * Bolded text font
+ */
+extern gcn::Font *boldFont;
+
#endif
diff --git a/src/gui/help.cpp b/src/gui/help.cpp
index 390cb44e..6b14f6d8 100644
--- a/src/gui/help.cpp
+++ b/src/gui/help.cpp
@@ -19,12 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "help.h"
-
#include "button.h"
#include "browserbox.h"
+#include "help.h"
#include "scrollarea.h"
+#include "widgets/layout.h"
+
#include "../resources/resourcemanager.h"
#include "../utils/gettext.h"
@@ -33,7 +34,8 @@ HelpWindow::HelpWindow():
Window(_("Help"))
{
setContentSize(455, 350);
- setWindowName("Help");
+ setWindowName(_("Help"));
+ setResizable(true);
mBrowserBox = new BrowserBox();
mBrowserBox->setOpaque(false);
@@ -48,8 +50,11 @@ HelpWindow::HelpWindow():
mBrowserBox->setLinkHandler(this);
- add(mScrollArea);
- add(okButton);
+ place(0, 0, mScrollArea, 5, 3).setPadding(3);
+ place(4, 3, okButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
setLocationRelativeTo(getParent());
}
diff --git a/src/gui/help.h b/src/gui/help.h
index e3d9246d..2ba74c0a 100644
--- a/src/gui/help.h
+++ b/src/gui/help.h
@@ -24,8 +24,8 @@
#include <guichan/actionlistener.hpp>
-#include "window.h"
#include "linkhandler.h"
+#include "window.h"
#include "../guichanfwd.h"
diff --git a/src/gui/inttextfield.cpp b/src/gui/inttextfield.cpp
index eb61c4d7..fcbe938d 100644
--- a/src/gui/inttextfield.cpp
+++ b/src/gui/inttextfield.cpp
@@ -20,7 +20,6 @@
*/
#include "inttextfield.h"
-
#include "sdlinput.h"
#include "../utils/tostring.h"
diff --git a/src/gui/inttextfield.h b/src/gui/inttextfield.h
index 4dfef8e1..2a913ef6 100644
--- a/src/gui/inttextfield.h
+++ b/src/gui/inttextfield.h
@@ -24,6 +24,8 @@
#include "textfield.h"
+#include "../guichanfwd.h"
+
/**
* TextBox which only accepts numbers as input.
*/
@@ -58,8 +60,7 @@ class IntTextField : public TextField
/**
* Responds to key presses.
*/
- void
- keyPressed(gcn::KeyEvent &event);
+ void keyPressed(gcn::KeyEvent &event);
private:
int mMin; /**< Minimum value */
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 31ebb86e..58c13910 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -19,72 +19,91 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "inventorywindow.h"
-
#include <string>
+#include <guichan/font.hpp>
#include <guichan/mouseinput.hpp>
+
#include <guichan/widgets/label.hpp>
#include "button.h"
#include "gui.h"
+#include "inventorywindow.h"
#include "item_amount.h"
#include "itemcontainer.h"
+#include "progressbar.h"
#include "scrollarea.h"
+#include "textbox.h"
#include "viewport.h"
+#include "widgets/layout.h"
+
#include "../inventory.h"
#include "../item.h"
-#include "../localplayer.h"
#include "../resources/iteminfo.h"
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
-InventoryWindow::InventoryWindow():
- Window(_("Inventory"))
+InventoryWindow::InventoryWindow(int invSize):
+ Window(_("Inventory")),
+ mMaxSlots(invSize),
+ mItemDesc(false)
{
- setWindowName("Inventory");
+ setWindowName(_("Inventory"));
setResizable(true);
setCloseButton(true);
- setMinWidth(240);
- setMinHeight(172);
+
// If you adjust these defaults, don't forget to adjust the trade window's.
- setDefaultSize(115, 25, 322, 200);
+ setDefaultSize(115, 25, 375, 300);
- mUseButton = new Button(_("Use"), "use", this);
+ std::string longestUseString = getFont()->getWidth(_("Equip")) >
+ getFont()->getWidth(_("Use")) ?
+ _("Equip") : _("Use");
+
+ if (getFont()->getWidth(longestUseString) <
+ getFont()->getWidth(_("Unequip")))
+ {
+ longestUseString = _("Unequip");
+ }
+
+ mUseButton = new Button(longestUseString, "use", this);
mDropButton = new Button(_("Drop"), "drop", this);
- mItems = new ItemContainer(player_node->getInventory());
+ mItems = new ItemContainer(player_node->getInventory(), 2);
mItems->addSelectionListener(this);
mInvenScroll = new ScrollArea(mItems);
mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mItemNameLabel = new gcn::Label("Name:");
- mItemDescriptionLabel = new gcn::Label("Description:");
- mItemEffectLabel = new gcn::Label("Effect:");
- mWeightLabel = new gcn::Label("Weight:");
- mWeightLabel->setPosition(8, 8);
- mInvenScroll->setPosition(8,
- mWeightLabel->getY() + mWeightLabel->getHeight() + 5);
- mInvenSlotLabel = new gcn::Label("Slots used:");
- mInvenSlotLabel->setPosition(mWeightLabel->getX()
- + mWeightLabel->getWidth() + 100, 8);
-
- add(mUseButton);
- add(mDropButton);
- add(mInvenScroll);
- add(mItemNameLabel);
- add(mItemDescriptionLabel);
- add(mItemEffectLabel);
- add(mWeightLabel);
- add(mInvenSlotLabel);
-
- mUseButton->setSize(60, mUseButton->getHeight());
+ mTotalWeight = toString(player_node->mTotalWeight);
+ mMaxWeight = toString(player_node->mMaxWeight);
+ mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
+
+ mSlotsLabel = new gcn::Label(_("Slots: "));
+ mWeightLabel = new gcn::Label(_("Weight: "));
+
+ mSlotsBar = new ProgressBar(1.0f, 100, 20, 225, 200, 25);
+ mWeightBar = new ProgressBar(1.0f, 100, 20, 0, 0, 255);
+
+ setMinHeight(130);
+ setMinWidth(mWeightLabel->getWidth() + mSlotsLabel->getWidth() + 310);
+
+ place(0, 0, mInvenScroll, 7, 4);
+ place(0, 4, mWeightLabel).setPadding(3);
+ place(1, 4, mWeightBar, 2);
+ place(3, 4, mSlotsLabel).setPadding(3);
+ place(4, 4, mSlotsBar, 2);
+ place(5, 5, mDropButton);
+ place(6, 5, mUseButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
loadWindowState();
+ setLocationRelativeTo(getParent());
}
void InventoryWindow::logic()
@@ -95,15 +114,39 @@ void InventoryWindow::logic()
// redesign of InventoryWindow and ItemContainer probably.
updateButtons();
- // Update weight information
- mWeightLabel->setCaption(strprintf(_("Weight: %d / %d"),
- player_node->mTotalWeight,
- player_node->mMaxWeight));
+ if ((mMaxWeight != toString(player_node->mMaxWeight)) ||
+ mTotalWeight != toString(player_node->mTotalWeight) ||
+ mUsedSlots != toString(player_node->getInventory()->getNumberOfSlotsUsed()))
+ {
+ mTotalWeight = toString(player_node->mTotalWeight);
+ mMaxWeight = toString(player_node->mMaxWeight);
+ mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
+
+ // Weight Bar coloration
+ if (int(player_node->mTotalWeight) < int(player_node->mMaxWeight / 3))
+ {
+ mWeightBar->setColor(0, 0, 255); // Blue
+ }
+ else if (int(player_node->mTotalWeight) <
+ int((player_node->mMaxWeight / 3) * 2))
+ {
+ mWeightBar->setColor(255, 255, 0); // Yellow
+ }
+ else
+ {
+ mWeightBar->setColor(255, 0, 0); // Red
+ }
+
+ // Adjust progress bars
+ mSlotsBar->setProgress((float)
+ player_node->getInventory()->getNumberOfSlotsUsed() / mMaxSlots);
+ mWeightBar->setProgress((float) player_node->mTotalWeight /
+ player_node->mMaxWeight);
- // Update number of items in inventory
- mInvenSlotLabel->setCaption(strprintf(_("Slots used: %d / %d"),
- player_node->getInventory()->getNumberOfSlotsUsed(),
- player_node->getInventory()->getInventorySize()));
+ mSlotsBar->setText(strprintf("%s/%d", mUsedSlots.c_str(), mMaxSlots));
+ mWeightBar->setText(strprintf("%sg/%sg", mTotalWeight.c_str(),
+ mMaxWeight.c_str()));
+ }
}
void InventoryWindow::action(const gcn::ActionEvent &event)
@@ -113,55 +156,30 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
if (!item)
return;
- if (event.getId() == "use") {
- if (item->isEquipment()) {
- if (item->isEquipped()) {
+ if (event.getId() == "use")
+ {
+ if (item->isEquipment())
+ {
+ if (item->isEquipped())
player_node->unequipItem(item);
- }
- else {
+ else
player_node->equipItem(item);
- }
}
- else {
+ else
player_node->useItem(item);
- }
}
else if (event.getId() == "drop")
{
- if (item->getQuantity() == 1) {
+ if (item->getQuantity() == 1)
player_node->dropItem(item, 1);
- }
- else {
+ else
+ {
// Choose amount of items to drop
new ItemAmountWindow(AMOUNT_ITEM_DROP, this, item);
}
}
}
-void InventoryWindow::valueChanged(const gcn::SelectionEvent &event)
-{
- const Item *item = mItems->getSelectedItem();
-
- // Update name, effect and description
- if (!item)
- {
- mItemNameLabel->setCaption(strprintf(_("Name: %s"), ""));
- mItemEffectLabel->setCaption(strprintf(_("Effect: %s"), ""));
- mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"), ""));
- }
- else
- {
- const ItemInfo& itemInfo = item->getInfo();
- mItemNameLabel->setCaption(
- strprintf(_("Name: %s"), itemInfo.getName().c_str()));
- mItemEffectLabel->setCaption(
- strprintf(_("Effect: %s"), itemInfo.getEffect().c_str()));
- mItemDescriptionLabel->setCaption(
- strprintf(_("Description: %s"),
- itemInfo.getDescription().c_str()));
- }
-}
-
void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
{
Window::mouseClicked(event);
@@ -182,55 +200,19 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
}
}
-void InventoryWindow::widgetResized(const gcn::Event &event)
-{
- Window::widgetResized(event);
-
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- // Adjust widgets
- mUseButton->setPosition(8, height - 8 - mUseButton->getHeight());
- mDropButton->setPosition(8 + mUseButton->getWidth() + 5,
- mUseButton->getY());
-
- mItemNameLabel->setDimension(gcn::Rectangle(8,
- mUseButton->getY() - 5 - mItemNameLabel->getHeight(),
- width - 16,
- mItemNameLabel->getHeight()));
- mItemEffectLabel->setDimension(gcn::Rectangle(8,
- mItemNameLabel->getY() - 5 - mItemEffectLabel->getHeight(),
- width - 16,
- mItemEffectLabel->getHeight()));
- mItemDescriptionLabel->setDimension(gcn::Rectangle(8,
- mItemEffectLabel->getY() - 5 - mItemDescriptionLabel->getHeight(),
- width - 16,
- mItemDescriptionLabel->getHeight()));
-
- mInvenScroll->setSize(width - 16,
- mItemDescriptionLabel->getY() - mWeightLabel->getHeight() - 18);
-
- mWeightLabel->setWidth(width - 16);
- mInvenSlotLabel->setWidth(width - 16);
-}
-
void InventoryWindow::updateButtons()
{
const Item *selectedItem = mItems->getSelectedItem();
if (selectedItem && selectedItem->isEquipment())
{
- if (selectedItem->isEquipped()) {
+ if (selectedItem->isEquipped())
mUseButton->setCaption(_("Unequip"));
- }
- else {
+ else
mUseButton->setCaption(_("Equip"));
- }
}
- else {
+ else
mUseButton->setCaption(_("Use"));
- }
mUseButton->setEnabled(selectedItem != 0);
mDropButton->setEnabled(selectedItem != 0);
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 402ab0d2..2c19ce26 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -28,9 +28,12 @@
#include "window.h"
#include "../guichanfwd.h"
+#include "../localplayer.h"
class Item;
class ItemContainer;
+class ProgressBar;
+class TextBox;
/**
* Inventory dialog.
@@ -38,13 +41,13 @@ class ItemContainer;
* \ingroup Interface
*/
class InventoryWindow : public Window, gcn::ActionListener,
- gcn::SelectionListener
+ gcn::SelectionListener
{
public:
/**
* Constructor.
*/
- InventoryWindow();
+ InventoryWindow(int invSize = (INVENTORY_SIZE - 2));
/**
* Logic (updates buttons and weight information).
@@ -61,30 +64,30 @@ class InventoryWindow : public Window, gcn::ActionListener,
*/
Item* getSelectedItem() const;
- /**
- * Updates labels to currently selected item.
- */
- void valueChanged(const gcn::SelectionEvent &event);
-
void mouseClicked(gcn::MouseEvent &event);
- /**
- * Called whenever the widget changes size.
- */
- void widgetResized(const gcn::Event &event);
-
private:
void updateButtons(); /**< Updates button states. */
ItemContainer *mItems;
+ std::string mWeight;
+ std::string mSlots;
+ std::string mUsedSlots;
+ std::string mTotalWeight;
+ std::string mMaxWeight;
gcn::Button *mUseButton, *mDropButton;
gcn::ScrollArea *mInvenScroll;
- gcn::Label *mItemNameLabel;
- gcn::Label *mItemDescriptionLabel;
- gcn::Label *mItemEffectLabel;
+
gcn::Label *mWeightLabel;
- gcn::Label *mInvenSlotLabel;
+ gcn::Label *mSlotsLabel;
+
+ ProgressBar *mWeightBar;
+ ProgressBar *mSlotsBar;
+
+ int mMaxSlots;
+
+ bool mItemDesc;
};
extern InventoryWindow *inventoryWindow;
diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp
index 7ef3d71b..d8682c95 100644
--- a/src/gui/item_amount.cpp
+++ b/src/gui/item_amount.cpp
@@ -19,10 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "item_amount.h"
-
#include "button.h"
#include "inttextfield.h"
+#include "item_amount.h"
#include "slider.h"
#include "trade.h"
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index a0885279..e3ecdd4e 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -21,13 +21,18 @@
#include "itemcontainer.h"
+#include "itempopup.h"
+
#include <guichan/mouseinput.hpp>
#include <guichan/selectionlistener.hpp>
+#include <SDL_mouse.h>
+
#include "../graphics.h"
#include "../inventory.h"
#include "../item.h"
#include "../itemshortcut.h"
+#include "../localplayer.h"
#include "../log.h"
#include "../resources/image.h"
@@ -41,11 +46,14 @@ const int ItemContainer::gridHeight = 42; // item icon height + 10
static const int NO_ITEM = -1;
-ItemContainer::ItemContainer(Inventory *inventory):
+ItemContainer::ItemContainer(Inventory *inventory, int offset):
mInventory(inventory),
mSelectedItemIndex(NO_ITEM),
- mLastSelectedItemId(NO_ITEM)
+ mLastSelectedItemId(NO_ITEM),
+ mOffset(offset)
{
+ mItemPopup = new ItemPopup();
+
ResourceManager *resman = ResourceManager::getInstance();
mSelImg = resman->getImage("graphics/gui/selection.png");
@@ -86,10 +94,11 @@ void ItemContainer::draw(gcn::Graphics *graphics)
}
/*
- * eAthena seems to start inventory from the 3rd slot. Still a mystery to
- * us why, make sure not to copy this oddity to our own server.
+ * mOffset is used to compensate for some weirdness that eAthena inherited from
+ * Ragnarok Online. Inventory slots and cart slots are +2 from their actual index,
+ * while storage slots are +1.
*/
- for (int i = 2; i < INVENTORY_SIZE; i++)
+ for (int i = mOffset; i < mInventory->getSize(); i++)
{
Item *item = mInventory->getItem(i);
@@ -138,6 +147,7 @@ void ItemContainer::recalculateHeight()
const int rows = (mMaxItems / cols) + (mMaxItems % cols > 0 ? 1 : 0);
const int height = rows * gridHeight + 8;
+
if (height != getHeight())
setHeight(height);
}
@@ -159,8 +169,8 @@ void ItemContainer::selectNone()
void ItemContainer::refindSelectedItem()
{
- if (mSelectedItemIndex != NO_ITEM) {
-
+ if (mSelectedItemIndex != NO_ITEM)
+ {
if (mInventory->getItem(mSelectedItemIndex) &&
mInventory->getItem(mSelectedItemIndex)->getId() == mLastSelectedItemId)
return; // we're already fine
@@ -170,7 +180,8 @@ void ItemContainer::refindSelectedItem()
for (int i = 0; i <= mMaxItems + 1; i++)
if (mInventory->getItem(i) &&
- mInventory->getItem(i)->getId() == mLastSelectedItemId) {
+ mInventory->getItem(i)->getId() == mLastSelectedItemId)
+ {
mSelectedItemIndex = i;
return;
}
@@ -179,14 +190,16 @@ void ItemContainer::refindSelectedItem()
mLastSelectedItemId = mSelectedItemIndex = NO_ITEM;
}
-
void ItemContainer::setSelectedItemIndex(int index)
{
int newSelectedItemIndex;
- // mMaxItems is broken because of eAthena's odd inventory layout and the client's refusal
- // to handle it properly, so we work around the issue right here.
- if (index < 0 || index > mMaxItems + 1 || mInventory->getItem(index) == NULL)
+ /*
+ * mOffset is used to compensate for some weirdness that eAthena inherited from
+ * Ragnarok Online. Inventory slots and cart slots are +2 from their actual index,
+ * while storage slots are +1.
+ */
+ if (index < 0 || index > mMaxItems + mOffset || mInventory->getItem(index) == NULL)
newSelectedItemIndex = NO_ITEM;
else
newSelectedItemIndex = index;
@@ -218,14 +231,14 @@ void ItemContainer::distributeValueChangedEvent()
void ItemContainer::mousePressed(gcn::MouseEvent &event)
{
- int button = event.getButton();
+ const int button = event.getButton();
if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT)
{
int columns = getWidth() / gridWidth;
int mx = event.getX();
int my = event.getY();
- int index = mx / gridWidth + ((my / gridHeight) * columns) + 2;
+ int index = mx / gridWidth + ((my / gridHeight) * columns) + mOffset;
itemShortcut->setItemSelected(-1);
setSelectedItemIndex(index);
@@ -236,3 +249,38 @@ void ItemContainer::mousePressed(gcn::MouseEvent &event)
itemShortcut->setItemSelected(item->getId());
}
}
+
+// Show ItemTooltip
+void ItemContainer::mouseMoved(gcn::MouseEvent &event)
+{
+ Item *item = mInventory->getItem(getSlotIndex(event.getX(), event.getY()));
+
+ if (item)
+ {
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->setOpaque(false);
+ mItemPopup->view(mouseX, mouseY);
+ }
+ else
+ {
+ mItemPopup->setVisible(false);
+ }
+}
+
+// Hide ItemTooltip
+void ItemContainer::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
+}
+
+int ItemContainer::getSlotIndex(const int posX, const int posY) const
+{
+ int columns = getWidth() / gridWidth;
+ int index = posX / gridWidth + ((posY / gridHeight) * columns) + mOffset;
+
+ return (index);
+}
+
diff --git a/src/gui/itemcontainer.h b/src/gui/itemcontainer.h
index a40237af..1fa76343 100644
--- a/src/gui/itemcontainer.h
+++ b/src/gui/itemcontainer.h
@@ -22,15 +22,18 @@
#ifndef ITEMCONTAINER_H
#define ITEMCONTAINER_H
+#include <list>
+
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
-#include <list>
+#include "../guichanfwd.h"
class Image;
class Inventory;
class Item;
+class ItemPopup;
namespace gcn {
class SelectionListener;
@@ -41,14 +44,15 @@ namespace gcn {
*
* \ingroup GUI
*/
-class ItemContainer : public gcn::Widget, public gcn::MouseListener,
- public gcn::WidgetListener
+class ItemContainer : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::WidgetListener
{
public:
/**
* Constructor. Initializes the graphic.
*/
- ItemContainer(Inventory *inventory);
+ ItemContainer(Inventory *inventory, int offset);
/**
* Destructor.
@@ -104,7 +108,11 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener,
}
private:
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
+
/**
+
* Sets the currently selected item. Invalid (e.g., negative) indices set `no item'.
*/
void setSelectedItemIndex(int index);
@@ -124,12 +132,24 @@ class ItemContainer : public gcn::Widget, public gcn::MouseListener,
*/
void distributeValueChangedEvent();
+ /**
+ * Gets the slot index based on the cursor position.
+ *
+ * @param posX The X Coordinate position.
+ * @param posY The Y Coordinate position.
+ * @return The slot index on success, -1 on failure.
+ */
+ int getSlotIndex(const int posX, const int posY) const;
+
Inventory *mInventory;
Image *mSelImg;
- int mSelectedItemIndex;
- int mLastSelectedItemId; // last selected item ID. If we lose the item, find again by ID.
+ int mSelectedItemIndex;
+ int mLastSelectedItemId; // last selected item ID. If we lose the item, find again by ID.
int mMaxItems;
+ int mOffset;
+
+ ItemPopup *mItemPopup;
std::list<gcn::SelectionListener*> mListeners;
diff --git a/src/gui/itemlinkhandler.cpp b/src/gui/itemlinkhandler.cpp
new file mode 100644
index 00000000..34c12a0c
--- /dev/null
+++ b/src/gui/itemlinkhandler.cpp
@@ -0,0 +1,63 @@
+/*
+ * The Mana World
+ * Copyright 2009 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 <SDL_mouse.h>
+
+#include "itemlinkhandler.h"
+#include "itempopup.h"
+
+#include "../resources/iteminfo.h"
+#include "../resources/itemdb.h"
+
+#include <sstream>
+#include <string>
+
+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);
+ int mouseX, mouseY;
+
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(iteminfo);
+
+ if (mItemPopup->isVisible())
+ mItemPopup->setVisible(false);
+ else
+ mItemPopup->view(mouseX, mouseY);
+ }
+}
diff --git a/src/gui/itemlinkhandler.h b/src/gui/itemlinkhandler.h
new file mode 100644
index 00000000..cd6fd900
--- /dev/null
+++ b/src/gui/itemlinkhandler.h
@@ -0,0 +1,40 @@
+/*
+ * The Mana World
+ * Copyright 2009 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 ITEM_LINK_HANDLER_H_
+#define ITEM_LINK_HANDLER_H_
+
+#include "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/itempopup.cpp b/src/gui/itempopup.cpp
new file mode 100644
index 00000000..8235d640
--- /dev/null
+++ b/src/gui/itempopup.cpp
@@ -0,0 +1,176 @@
+/*
+ * The Mana World
+ * Copyright (C) 2008 The Legend of Mazzeroth Development Team
+ * Copyright (C) 2008 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 <guichan/font.hpp>
+
+#include <guichan/widgets/label.hpp>
+
+#include "gui.h"
+#include "itempopup.h"
+#include "windowcontainer.h"
+
+#include "widgets/layout.h"
+
+#include "../resources/image.h"
+#include "../resources/iteminfo.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/gettext.h"
+#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
+
+ItemPopup::ItemPopup():
+ Window()
+{
+ setResizable(false);
+ setShowTitle(false);
+ setTitleBarHeight(0);
+
+ // Item Name
+ mItemName = new gcn::Label("Label");
+ mItemName->setFont(gui->getFont());
+ mItemName->setPosition(2, 2);
+ mItemName->setWidth(getWidth() - 4);
+ mItemName->setFont(boldFont);
+
+ // Item Description
+ mItemDesc = new TextBox();
+ mItemDesc->setEditable(false);
+ mItemDesc->setMinWidth(186);
+ mItemDesc->setTextWrapped("");
+ mItemDescScroll = new ScrollArea(mItemDesc);
+
+ mItemDescScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemDescScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemDescScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
+ mItemDescScroll->setOpaque(false);
+ mItemDescScroll->setPosition(2, getFont()->getHeight());
+
+ // Item Effect
+ mItemEffect = new TextBox();
+ mItemEffect->setEditable(false);
+ mItemEffect->setMinWidth(186);
+ mItemEffect->setTextWrapped("");
+ mItemEffectScroll = new ScrollArea(mItemEffect);
+
+ mItemEffectScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemEffectScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemEffectScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
+ mItemEffectScroll->setOpaque(false);
+ mItemEffectScroll->setPosition(2, (2 * getFont()->getHeight()) + 5);
+
+ // Item Weight
+ mItemWeight = new TextBox();
+ mItemWeight->setEditable(false);
+ mItemWeight->setMinWidth(186);
+ mItemWeight->setTextWrapped("");
+ mItemWeightScroll = new ScrollArea(mItemWeight);
+
+ mItemWeightScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemWeightScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mItemWeightScroll->setDimension(gcn::Rectangle(0, 0, 196, getFont()->getHeight()));
+ mItemWeightScroll->setOpaque(false);
+ mItemWeightScroll->setPosition(2, (3 * getFont()->getHeight()) + 10);
+
+ add(mItemName);
+ add(mItemDescScroll);
+ add(mItemEffectScroll);
+ add(mItemWeightScroll);
+
+ setLocationRelativeTo(getParent());
+
+ // LEEOR / TODO: This causes an exception error.
+ //moveToBottom(getParent());
+}
+
+void ItemPopup::setItem(const ItemInfo &item)
+{
+ const gcn::Rectangle &area = getChildrenArea();
+ const int width = area.width;
+
+ mItemDesc->setMinWidth(width - 10);
+ mItemEffect->setMinWidth(width - 10);
+ mItemWeight->setMinWidth(width - 10);
+
+ mItemName->setCaption(item.getName());
+ mItemDesc->setTextWrapped(item.getDescription());
+ mItemEffect->setTextWrapped(item.getEffect());
+ mItemWeight->setTextWrapped(_("Weight: ") + toString(item.getWeight()) +
+ _(" grams"));
+
+ int numRowsDesc = mItemDesc->getNumberOfRows();
+ int numRowsEffect = mItemEffect->getNumberOfRows();
+ int numRowsWeight = mItemWeight->getNumberOfRows();
+
+ mItemDescScroll->setDimension(gcn::Rectangle(2, 0, 196,
+ numRowsDesc * getFont()->getHeight()));
+
+ mItemEffectScroll->setDimension(gcn::Rectangle(2, 0, 196,
+ numRowsEffect * getFont()->getHeight()));
+
+ mItemWeightScroll->setDimension(gcn::Rectangle(2, 0, 196,
+ numRowsWeight * getFont()->getHeight()));
+
+ if(item.getEffect() == "")
+ {
+ setContentSize(200, (numRowsDesc * getFont()->getHeight() +
+ (3 * getFont()->getHeight())));
+
+ mItemWeightScroll->setPosition(2,
+ (numRowsDesc * getFont()->getHeight()) +
+ (2 * getFont()->getHeight()));
+ }
+ else
+ {
+ setContentSize(200, (numRowsDesc * getFont()->getHeight()) +
+ (numRowsEffect * getFont()->getHeight()) +
+ (3 * getFont()->getHeight()));
+
+ mItemWeightScroll->setPosition(2,
+ (numRowsDesc * getFont()->getHeight()) +
+ (numRowsEffect * getFont()->getHeight()) +
+ (2 * getFont()->getHeight()));
+ }
+
+ mItemDescScroll->setPosition(2, 20);
+ mItemEffectScroll->setPosition(2, (numRowsDesc * getFont()->getHeight()) +
+ (2 * getFont()->getHeight()));
+}
+
+unsigned int ItemPopup::getNumRows()
+{
+ return mItemDesc->getNumberOfRows() + mItemEffect->getNumberOfRows() +
+ mItemWeight->getNumberOfRows();
+}
+
+void ItemPopup::view(int x, int y)
+{
+ if (windowContainer->getWidth() < (x + getWidth() + 5))
+ x = windowContainer->getWidth() - getWidth();
+ if ((y - getHeight() - 5) < 0)
+ y = 0;
+ else
+ y = y - getHeight() - 5;
+ setPosition(x, y);
+ setVisible(true);
+ requestMoveToTop();
+}
diff --git a/src/gui/buddywindow.h b/src/gui/itempopup.h
index 4eed3a2c..b6120af8 100644
--- a/src/gui/buddywindow.h
+++ b/src/gui/itempopup.h
@@ -1,6 +1,7 @@
/*
* The Mana World
- * Copyright (C) 2004 The Mana World Development Team
+ * Copyright (C) 2008 The Legend of Mazzeroth Development Team
+ * Copyright (C) 2008 The Mana World Development Team
*
* This file is part of The Mana World.
*
@@ -19,38 +20,32 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef BUDDYWINDOW_H
-#define BUDDYWINDOW_H
-
-#include <guichan/actionlistener.hpp>
+#ifndef ITEMPOPUP_H__
+#define ITEMPOPUP_H__
+#include "scrollarea.h"
+#include "textbox.h"
#include "window.h"
-#include "../guichanfwd.h"
-
-class BuddyList;
+#include "../item.h"
-/**
- * Window showing buddy list.
- *
- * \ingroup Interface
- */
-class BuddyWindow : public Window, public gcn::ActionListener
+class ItemPopup : public Window
{
public:
- /**
- * Constructor.
- */
- BuddyWindow();
+ ItemPopup();
- /**
- * Performs action.
- */
- void action(const gcn::ActionEvent &event);
+ void setItem(const ItemInfo &item);
+ unsigned int getNumRows();
+ void view(int x, int y);
private:
- BuddyList *mBuddyList;
- gcn::ListBox *mListbox;
+ gcn::Label *mItemName;
+ TextBox *mItemDesc;
+ TextBox *mItemEffect;
+ TextBox *mItemWeight;
+ ScrollArea *mItemDescScroll;
+ ScrollArea *mItemEffectScroll;
+ ScrollArea *mItemWeightScroll;
};
-#endif /* BUDDYWINDOW_H */
+#endif // ITEMPOPUP_H__
diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp
index b2f70348..3735afe2 100644
--- a/src/gui/itemshortcutcontainer.cpp
+++ b/src/gui/itemshortcutcontainer.cpp
@@ -18,15 +18,20 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <SDL_mouse.h>
+#include "gui.h"
#include "itemshortcutcontainer.h"
+#include "itempopup.h"
+#include "viewport.h"
-#include "../localplayer.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../inventory.h"
#include "../item.h"
#include "../itemshortcut.h"
#include "../keyboardconfig.h"
+#include "../localplayer.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
@@ -34,21 +39,25 @@
#include "../utils/tostring.h"
ItemShortcutContainer::ItemShortcutContainer():
- mGridWidth(1),
- mGridHeight(1),
mItemClicked(false),
mItemMoved(NULL)
{
+ mGridWidth=1;
+ mGridHeight=1;
addMouseListener(this);
addWidgetListener(this);
+ mItemPopup = new ItemPopup();
+
ResourceManager *resman = ResourceManager::getInstance();
mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png");
mMaxItems = itemShortcut->getItemCount();
- mBoxHeight = 42;
- mBoxWidth = 36;
+ mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8));
+
+ mBoxHeight = mBackgroundImg->getHeight();
+ mBoxWidth = mBackgroundImg->getWidth();
}
ItemShortcutContainer::~ItemShortcutContainer()
@@ -56,8 +65,7 @@ ItemShortcutContainer::~ItemShortcutContainer()
mBackgroundImg->decRef();
}
-void
-ItemShortcutContainer::logic()
+void ItemShortcutContainer::logic()
{
gcn::Widget::logic();
@@ -70,8 +78,7 @@ ItemShortcutContainer::logic()
}
}
-void
-ItemShortcutContainer::draw(gcn::Graphics *graphics)
+void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
Graphics *g = static_cast<Graphics*>(graphics);
@@ -87,7 +94,8 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics)
// Draw item keyboard shortcut.
const char *key = SDL_GetKeyName(
- (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_0 + i));
+ (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i));
+ graphics->setColor(0x000000);
g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT);
if (itemShortcut->getItem(i) < 0)
@@ -97,6 +105,8 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics)
player_node->getInventory()->findItem(itemShortcut->getItem(i));
if (item) {
// Draw item icon.
+ const std::string label =
+ item->isEquipped() ? "Eq." : toString(item->getQuantity());
Image* image = item->getImage();
if (image) {
const std::string label =
@@ -129,35 +139,23 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics)
}
}
-void ItemShortcutContainer::widgetResized(const gcn::Event &event)
+void ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
{
- 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) {
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ if (!mItemMoved && mItemClicked)
+ {
const int index = getIndexFromGrid(event.getX(), event.getY());
- if (index == -1) {
- return;
- }
const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1)
+ return;
+
if (itemId < 0)
return;
+
Item *item = player_node->getInventory()->findItem(itemId);
+
if (item)
{
mItemMoved = item;
@@ -171,39 +169,56 @@ ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
}
}
-void
-ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
+void ItemShortcutContainer::mousePressed(gcn::MouseEvent &event)
{
const int index = getIndexFromGrid(event.getX(), event.getY());
- if (index == -1) {
+ if (index == -1)
return;
- }
- // Stores the selected item if theirs one.
- if (itemShortcut->isItemSelected()) {
- itemShortcut->setItem(index);
- itemShortcut->setItemSelected(-1);
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+
+ // Stores the selected item if theirs one.
+ if (itemShortcut->isItemSelected())
+ {
+ itemShortcut->setItem(index);
+ itemShortcut->setItemSelected(-1);
+ }
+ else if (itemShortcut->getItem(index))
+ mItemClicked = true;
}
- 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.
+ */
+ int mx, my;
+ SDL_GetMouseState(&mx, &my);
+ viewport->showPopup(mx, my, item);
}
}
-void
-ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
+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) {
+ if (index == -1)
+ {
mItemMoved = NULL;
return;
}
- if (mItemMoved) {
+ if (mItemMoved)
+ {
itemShortcut->setItems(index, mItemMoved->getId());
mItemMoved = NULL;
}
@@ -211,25 +226,43 @@ ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
{
itemShortcut->useItem(index);
}
- if (mItemClicked) {
+ if (mItemClicked)
mItemClicked = false;
- }
}
}
-int
-ItemShortcutContainer::getIndexFromGrid(int pointX, int pointY) const
+// Show ItemTooltip
+void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event)
{
- const gcn::Rectangle tRect = gcn::Rectangle(
- 0, 0, mGridWidth * mBoxWidth, mGridHeight * mBoxHeight);
- if (!tRect.isPointInRect(pointX, pointY)) {
- return -1;
+ const int index = getIndexFromGrid(event.getX(), event.getY());
+ const int itemId = itemShortcut->getItem(index);
+
+ if (index == -1)
+ return;
+
+ if (itemId < 0)
+ return;
+
+ Item *item = player_node->getInventory()->findItem(itemId);
+
+ if (item)
+ {
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+
+ mItemPopup->setItem(item->getInfo());
+ mItemPopup->setOpaque(false);
+ mItemPopup->view(mouseX, mouseY);
}
- const int index = ((pointY / mBoxHeight) * mGridWidth) +
- pointX / mBoxWidth;
- if (index >= mMaxItems)
+ else
{
- return -1;
+ mItemPopup->setVisible(false);
}
- return index;
}
+
+// Hide ItemTooltip
+void ItemShortcutContainer::mouseExited(gcn::MouseEvent &event)
+{
+ mItemPopup->setVisible(false);
+}
+
diff --git a/src/gui/itemshortcutcontainer.h b/src/gui/itemshortcutcontainer.h
index cdaf6713..d6a04d7b 100644
--- a/src/gui/itemshortcutcontainer.h
+++ b/src/gui/itemshortcutcontainer.h
@@ -23,20 +23,21 @@
#define ITEMSHORTCUTCONTAINER_H
#include <guichan/mouselistener.hpp>
-#include <guichan/widget.hpp>
-#include <guichan/widgetlistener.hpp>
+
+#include "shortcutcontainer.h"
+
+#include "../guichanfwd.h"
class Image;
class Item;
+class ItemPopup;
/**
* An item shortcut container. Used to quickly use items.
*
* \ingroup GUI
*/
-class ItemShortcutContainer : public gcn::Widget,
- public gcn::WidgetListener,
- public gcn::MouseListener
+class ItemShortcutContainer : public ShortcutContainer
{
public:
/**
@@ -60,12 +61,6 @@ class ItemShortcutContainer : public gcn::Widget,
void draw(gcn::Graphics *graphics);
/**
- * Invoked when a widget changes its size. This is used to determine
- * the new height of the container.
- */
- void widgetResized(const gcn::Event &event);
-
- /**
* Handles mouse when dragged.
*/
void mouseDragged(gcn::MouseEvent &event);
@@ -80,34 +75,14 @@ class ItemShortcutContainer : public gcn::Widget,
*/
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;
+ void mouseExited(gcn::MouseEvent &event);
+ void mouseMoved(gcn::MouseEvent &event);
- int mMaxItems;
- int mBoxWidth;
- int mBoxHeight;
- int mCursorPosX, mCursorPosY;
- int mGridWidth, mGridHeight;
bool mItemClicked;
Item *mItemMoved;
+
+ ItemPopup *mItemPopup;
};
#endif
diff --git a/src/gui/listbox.cpp b/src/gui/listbox.cpp
index b72c64cf..990a0ade 100644
--- a/src/gui/listbox.cpp
+++ b/src/gui/listbox.cpp
@@ -19,13 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "listbox.h"
-
#include <guichan/font.hpp>
#include <guichan/graphics.hpp>
#include <guichan/listmodel.hpp>
#include <guichan/mouseinput.hpp>
+#include "listbox.h"
+
ListBox::ListBox(gcn::ListModel *listModel):
gcn::ListBox(listModel)
{
@@ -36,7 +36,7 @@ void ListBox::draw(gcn::Graphics *graphics)
if (!mListModel)
return;
- graphics->setColor(gcn::Color(110, 160, 255));
+ graphics->setColor(gcn::Color(235, 200, 115));
graphics->setFont(getFont());
int fontHeight = getFont()->getHeight();
@@ -57,8 +57,7 @@ void ListBox::draw(gcn::Graphics *graphics)
}
}
-void
-ListBox::mouseDragged(gcn::MouseEvent &event)
+void ListBox::mouseDragged(gcn::MouseEvent &event)
{
// Pretend mouse is pressed continuously while dragged. Causes list
// selection to be updated as is default in many GUIs.
diff --git a/src/gui/listbox.h b/src/gui/listbox.h
index 934ea82e..3d0062bc 100644
--- a/src/gui/listbox.h
+++ b/src/gui/listbox.h
@@ -24,6 +24,8 @@
#include <guichan/widgets/listbox.hpp>
+#include "../guichanfwd.h"
+
class SelectionListener;
/**
diff --git a/src/gui/login.cpp b/src/gui/login.cpp
index 2b87f6df..8de2867c 100644
--- a/src/gui/login.cpp
+++ b/src/gui/login.cpp
@@ -19,24 +19,31 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "login.h"
-
#include <string>
+#include <vector>
#include <guichan/widgets/label.hpp>
-#include "../main.h"
-#include "../logindata.h"
-
#include "button.h"
#include "checkbox.h"
+#include "login.h"
#include "ok_dialog.h"
#include "passwordfield.h"
#include "textfield.h"
#include "widgets/layout.h"
+#include "../main.h"
+#include "../logindata.h"
+#include "../configuration.h"
+
#include "../utils/gettext.h"
+#include "../utils/tostring.h"
+
+static const int MAX_SERVER_LIST_SIZE = 5;
+static const int LOGIN_DIALOG_WIDTH = 220;
+static const int LOGIN_DIALOG_HEIGHT = 140;
+static const int FIELD_WIDTH = LOGIN_DIALOG_WIDTH - 70;
LoginDialog::LoginDialog(LoginData *loginData):
Window(_("Login")), mLoginData(loginData)
@@ -44,36 +51,64 @@ LoginDialog::LoginDialog(LoginData *loginData):
gcn::Label *userLabel = new gcn::Label(_("Name:"));
gcn::Label *passLabel = new gcn::Label(_("Password:"));
gcn::Label *serverLabel = new gcn::Label(_("Server:"));
+ gcn::Label *portLabel = new gcn::Label(_("Port:"));
+ gcn::Label *dropdownLabel = new gcn::Label(_("Recent:"));
+ std::vector<std::string> dfltServer;
+ dfltServer.push_back("server.themanaworld.org");
+ dfltServer.push_back("server.themanaworld.org");
+ std::vector<std::string> dfltPort;
+ dfltPort.push_back("21001");
+ dfltPort.push_back("22001");
+ dfltPort.push_back("21001");
+ mServerList = new DropDownList("MostRecent00", dfltServer, dfltPort,
+ MAX_SERVER_LIST_SIZE);
+ mServerListBox = new gcn::ListBox(mServerList);
+ mServerScrollArea = new ScrollArea();
+
mUserField = new TextField(mLoginData->username);
mPassField = new PasswordField(mLoginData->password);
- mServerField = new TextField(mLoginData->hostname);
+ mServerField = new TextField(mServerList->getServerAt(0));
+ mPortField = new TextField(mServerList->getPortAt(0));
+ mServerDropDown = new DropDown(mServerList,
+ mServerScrollArea,
+ mServerListBox);
+
mKeepCheck = new CheckBox(_("Remember Username"), mLoginData->remember);
- mOkButton = new Button(_("Ok"), "ok", this);
+ mOkButton = new Button(_("OK"), "ok", this);
mCancelButton = new Button(_("Cancel"), "cancel", this);
mRegisterButton = new Button(_("Register"), "register", this);
mUserField->setActionEventId("ok");
mPassField->setActionEventId("ok");
mServerField->setActionEventId("ok");
+ mServerDropDown->setActionEventId("changeSelection");
mUserField->addKeyListener(this);
mPassField->addKeyListener(this);
mServerField->addKeyListener(this);
+ mPortField->addKeyListener(this);
+ mServerDropDown->addKeyListener(this);
mUserField->addActionListener(this);
mPassField->addActionListener(this);
mServerField->addActionListener(this);
+ mPortField->addActionListener(this);
+ mServerDropDown->addActionListener(this);
mKeepCheck->addActionListener(this);
place(0, 0, userLabel);
place(0, 1, passLabel);
place(0, 2, serverLabel);
- place(1, 0, mUserField, 3).setPadding(2);
- place(1, 1, mPassField, 3).setPadding(2);
- place(1, 2, mServerField, 3).setPadding(2);
- place(0, 3, mKeepCheck, 4);
- place(0, 4, mRegisterButton).setHAlign(LayoutCell::LEFT);
- place(2, 4, mOkButton);
- place(3, 4, mCancelButton);
+ place(0, 3, portLabel);
+ place(0, 4, dropdownLabel);
+ place(1, 0, mUserField, 3).setPadding(1);
+ place(1, 1, mPassField, 3).setPadding(1);
+ place(1, 2, mServerField, 3).setPadding(1);
+ place(1, 3, mPortField, 3).setPadding(1);
+ place(1, 4, mServerDropDown, 3).setPadding(1);
+ place(0, 5, mKeepCheck, 4);
+ place(0, 6, mRegisterButton).setHAlign(LayoutCell::LEFT);
+ place(2, 6, mCancelButton);
+ place(3, 6, mOkButton);
reflowLayout(250, 0);
setLocationRelativeTo(getParent());
@@ -90,6 +125,9 @@ LoginDialog::LoginDialog(LoginData *loginData):
LoginDialog::~LoginDialog()
{
+ delete mServerList;
+ delete mServerListBox;
+ delete mServerScrollArea;
}
void LoginDialog::action(const gcn::ActionEvent &event)
@@ -97,6 +135,7 @@ void LoginDialog::action(const gcn::ActionEvent &event)
if (event.getId() == "ok" && canSubmit())
{
mLoginData->hostname = mServerField->getText();
+ mLoginData->port = getUShort(mPortField->getText());
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
mLoginData->remember = mKeepCheck->isSelected();
@@ -104,9 +143,15 @@ void LoginDialog::action(const gcn::ActionEvent &event)
mOkButton->setEnabled(false);
mRegisterButton->setEnabled(false);
-
+ mServerList->save(mServerField->getText(), mPortField->getText());
state = ACCOUNT_STATE;
}
+ else if (event.getId() == "changeSelection")
+ {
+ int selected = mServerListBox->getSelected();
+ mServerField->setText(mServerList->getServerAt(selected));
+ mPortField->setText(mServerList->getPortAt(selected));
+ }
else if (event.getId() == "cancel")
{
state = EXIT_STATE;
@@ -115,6 +160,14 @@ void LoginDialog::action(const gcn::ActionEvent &event)
{
// Transfer these fields on to the register dialog
mLoginData->hostname = mServerField->getText();
+ if (isUShort(mPortField->getText()))
+ {
+ mLoginData->port = getUShort(mPortField->getText());
+ }
+ else
+ {
+ mLoginData->port = 6901;
+ }
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
@@ -132,5 +185,138 @@ bool LoginDialog::canSubmit()
return !mUserField->getText().empty() &&
!mPassField->getText().empty() &&
!mServerField->getText().empty() &&
+ isUShort(mPortField->getText()) &&
state == LOGIN_STATE;
}
+
+bool LoginDialog::isUShort(const std::string &str)
+{
+ if (str == "")
+ {
+ return false;
+ }
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ if (*strPtr < '0' || *strPtr > '9')
+ {
+ return false;
+ }
+ l = l * 10 + (*strPtr - '0'); // *strPtr - '0' will never be negative
+ if (l > 65535)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+unsigned short LoginDialog::getUShort(const std::string &str)
+{
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ l = l * 10 + (*strPtr - '0');
+ }
+ return static_cast<unsigned short>(l);
+}
+
+/**
+ * LoginDialog::DropDownList
+ */
+
+void LoginDialog::DropDownList::saveEntry(const std::string &server,
+ const std::string &port, int &saved)
+{
+ if (saved < MAX_SERVER_LIST_SIZE && server != "")
+ {
+ config.setValue(mConfigPrefix + "Server" + toString(saved), server);
+ config.setValue(mConfigPrefix + "Port" + toString(saved), port);
+ ++saved;
+ }
+}
+
+LoginDialog::DropDownList::DropDownList(std::string prefix,
+ std::vector<std::string> dflt,
+ std::vector<std::string> dfltPort,
+ int maxEntries) :
+ mConfigPrefix(prefix),
+ mMaxEntries(maxEntries)
+{
+ for (int i = 0; i < maxEntries; ++i)
+ {
+ std::string server = config.getValue(mConfigPrefix + "Server" +
+ toString(i), "");
+ if (server == "") // Just in case had original config entries
+ {
+ server = config.getValue(mConfigPrefix + "ServerList" +
+ toString(i), "");
+ }
+ std::string port = config.getValue(mConfigPrefix + "Port" +
+ toString(i), dfltPort.front());
+
+ if (server != "")
+ {
+ mServers.push_back(server);
+ mPorts.push_back(port);
+ }
+ }
+ if (mServers.size() == 0)
+ {
+ mServers.assign(dflt.begin(), dflt.end());
+ mPorts.assign(dfltPort.begin(), dfltPort.end());
+ }
+}
+
+void LoginDialog::DropDownList::save(const std::string &server,
+ const std::string &port)
+{
+ int position = 0;
+ saveEntry(server, port, position);
+ for (std::vector<std::string>::const_iterator sPtr = mServers.begin(),
+ sEnd = mServers.end(),
+ pPtr = mPorts.begin(),
+ pEnd = mPorts.end();
+ sPtr != sEnd && pPtr != pEnd;
+ ++sPtr, ++pPtr)
+ {
+ if (*sPtr != server || *pPtr != port)
+ {
+ saveEntry(*sPtr, *pPtr, position);
+ }
+ }
+}
+
+int LoginDialog::DropDownList::getNumberOfElements()
+{
+ return mServers.size();
+}
+
+std::string LoginDialog::DropDownList::getElementAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return getServerAt(i) + ":" + getPortAt(i);
+}
+
+std::string LoginDialog::DropDownList::getServerAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return mServers.at(i);
+}
+
+std::string LoginDialog::DropDownList::getPortAt(int i)
+{
+ if (i < 0 || i >= getNumberOfElements())
+ {
+ return "";
+ }
+ return mPorts.at(i);
+}
diff --git a/src/gui/login.h b/src/gui/login.h
index 7dd59a96..b85e5ae1 100644
--- a/src/gui/login.h
+++ b/src/gui/login.h
@@ -23,10 +23,17 @@
#define LOGIN_H
#include <iosfwd>
+#include <string>
+#include <vector>
+
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+#include "scrollarea.h"
#include "window.h"
+
+#include "widgets/dropdown.h"
+
#include "../guichanfwd.h"
class LoginData;
@@ -67,18 +74,66 @@ class LoginDialog : public Window, public gcn::ActionListener,
* Returns whether submit can be enabled. This is true in the login
* state, when all necessary fields have some text.
*/
- bool
- canSubmit();
+ bool canSubmit();
+
+ /**
+ * Function to decide whether string is an unsigned short or not
+ *
+ * @param str the string to parse
+ *
+ * @return true is str is an unsigned short, false otherwise
+ */
+ static bool isUShort(const std::string &str);
+
+ /**
+ * Converts string to an unsigned short (undefined if invalid)
+ *
+ * @param str the string to parse
+ *
+ * @return the value str represents
+ */
+ static unsigned short getUShort(const std::string &str);
+ DropDown *mServerDropDown;
gcn::TextField *mUserField;
gcn::TextField *mPassField;
gcn::TextField *mServerField;
+ gcn::TextField *mPortField;
gcn::CheckBox *mKeepCheck;
gcn::Button *mOkButton;
gcn::Button *mCancelButton;
gcn::Button *mRegisterButton;
LoginData *mLoginData;
+
+ /**
+ * Helper class to keep a list of all the recent entries for the
+ * dropdown
+ */
+ class DropDownList : public gcn::ListModel
+ {
+ private:
+ std::vector<std::string> mServers;
+ std::vector<std::string> mPorts;
+ std::string mConfigPrefix;
+ int mMaxEntries;
+ void saveEntry(const std::string &server,
+ const std::string &port, int &saved);
+ public:
+ DropDownList(std::string prefix,
+ std::vector<std::string> dfltServer,
+ std::vector<std::string> dfltPort,
+ int maxEntries);
+ void save(const std::string &server, const std::string &port);
+ int getNumberOfElements();
+ std::string getElementAt(int i);
+ std::string getServerAt(int i);
+ std::string getPortAt(int i);
+ };
+ DropDownList *mServerList;
+ gcn::ListBox *mServerListBox;
+ ScrollArea *mServerScrollArea;
+
};
#endif
diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp
index e19cc3e8..0dcc999f 100644
--- a/src/gui/menuwindow.cpp
+++ b/src/gui/menuwindow.cpp
@@ -19,23 +19,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "menuwindow.h"
-
#include <string>
#include <guichan/actionlistener.hpp>
#include "button.h"
+#include "menuwindow.h"
#include "windowcontainer.h"
#include "../utils/gettext.h"
-extern Window *setupWindow;
-extern Window *inventoryWindow;
+extern Window *chatWindow;
extern Window *equipmentWindow;
+extern Window *inventoryWindow;
+extern Window *itemShortcutWindow;
+extern Window *emoteWindow;
+extern Window *setupWindow;
extern Window *skillDialog;
extern Window *statusWindow;
-extern Window *itemShortcutWindow;
namespace {
struct MenuWindowListener : public gcn::ActionListener
@@ -58,12 +59,14 @@ MenuWindow::MenuWindow():
// Buttons
static const char *buttonNames[] =
{
- N_("Status"),
- N_("Equipment"),
- N_("Inventory"),
- N_("Skills"),
- N_("Shortcut"),
- N_("Setup"),
+ _("Chat"),
+ _("Status"),
+ _("Equipment"),
+ _("Inventory"),
+ _("Skills"),
+ _("Shortcut"),
+ _("Emote"),
+ _("Setup"),
0
};
int x = 0, h = 0;
@@ -91,27 +94,35 @@ void MenuWindowListener::action(const gcn::ActionEvent &event)
{
Window *window = NULL;
- if (event.getId() == "Status")
+ if (event.getId() == _("Chat"))
+ {
+ window = chatWindow;
+ }
+ else if (event.getId() == _("Status"))
{
window = statusWindow;
}
- else if (event.getId() == "Equipment")
+ else if (event.getId() == _("Equipment"))
{
window = equipmentWindow;
}
- else if (event.getId() == "Inventory")
+ else if (event.getId() == _("Inventory"))
{
window = inventoryWindow;
}
- else if (event.getId() == "Skills")
+ else if (event.getId() == _("Skills"))
{
window = skillDialog;
}
- else if (event.getId() == "Shortcut")
+ else if (event.getId() == _("Shortcut"))
{
window = itemShortcutWindow;
}
- else if (event.getId() == "Setup")
+ else if (event.getId() == _("Emote"))
+ {
+ window = emoteWindow;
+ }
+ else if (event.getId() == _("Setup"))
{
window = setupWindow;
}
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index f5c0c1e6..7802b583 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -19,10 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <guichan/font.hpp>
+
#include "minimap.h"
#include "../being.h"
#include "../beingmanager.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../localplayer.h"
@@ -30,13 +33,17 @@
#include "../utils/gettext.h"
+bool Minimap::mShow = true;
+
Minimap::Minimap():
Window(_("MiniMap")),
- mMapImage(NULL)
+ mMapImage(NULL),
+ mProportion(0.5)
{
- setWindowName("MiniMap");
+ setWindowName(_("MiniMap"));
+ mShow = config.getValue(getWindowName() + "Visible", true);
setDefaultSize(5, 25, 100, 100);
- loadWindowState();
+ setResizable(true);
}
Minimap::~Minimap()
@@ -53,13 +60,57 @@ void Minimap::setMapImage(Image *img)
mMapImage = img;
if (mMapImage)
- mMapImage->setAlpha(0.7);
+ {
+ const int offsetX = 2 * getPadding();
+ const int offsetY = getTitleBarHeight() + getPadding();
+ const int titleWidth = getFont()->getWidth(getCaption()) + 15;
+ const int mapWidth = mMapImage->getWidth() < 100 ?
+ mMapImage->getWidth() + offsetX : 100;
+ const int mapHeight = mMapImage->getHeight() < 100 ?
+ mMapImage->getHeight() + offsetY : 100;
+
+ setMinWidth(mapWidth > titleWidth ? mapWidth : titleWidth);
+ setMinHeight(mapHeight);
+ setMaxWidth(mMapImage->getWidth() + offsetX);
+ setMaxHeight(mMapImage->getHeight() + offsetY);
+
+ mMapImage->setAlpha(config.getValue("guialpha", 0.8));
+
+ // Set content size to be within the minimum and maximum boundaries
+ setWidth(getMinWidth() < getWidth() ? getWidth() : getMinWidth());
+ if (getMaxWidth() > getWidth())
+ setWidth(getMaxWidth());
+ setHeight(getMinHeight() < getHeight() ? getHeight() : getMinHeight());
+ if (getMaxHeight() > getHeight())
+ setHeight(getMaxHeight());
+
+ setDefaultSize(getX(), getY(), getWidth(), getHeight());
+ resetToDefaultSize();
+
+ loadWindowState();
+ setVisible(mShow);
+ }
+ else
+ {
+ setVisible(false);
+ }
+}
+
+void Minimap::toggle()
+{
+ mShow = !mShow;
+ config.setValue(getWindowName() + "Visible", mShow);
}
void Minimap::draw(gcn::Graphics *graphics)
{
+ setVisible(mShow);
+
Window::draw(graphics);
+ if (!mShow)
+ return;
+
const gcn::Rectangle a = getChildrenArea();
graphics->pushClipArea(a);
@@ -72,8 +123,8 @@ void Minimap::draw(gcn::Graphics *graphics)
if (mMapImage->getWidth() > a.width ||
mMapImage->getHeight() > a.height)
{
- mapOriginX = (a.width - player_node->mX) / 2;
- mapOriginY = (a.height - player_node->mY) / 2;
+ mapOriginX = (int) (((a.width) / 2) - (player_node->mX * mProportion));
+ mapOriginY = (int) (((a.height) / 2) - (player_node->mY * mProportion));
const int minOriginX = a.width - mMapImage->getWidth();
const int minOriginY = a.height - mMapImage->getHeight();
@@ -87,6 +138,7 @@ void Minimap::draw(gcn::Graphics *graphics)
if (mapOriginY > 0)
mapOriginY = 0;
}
+
static_cast<Graphics*>(graphics)->
drawImage(mMapImage, mapOriginX, mapOriginY);
}
@@ -122,10 +174,11 @@ void Minimap::draw(gcn::Graphics *graphics)
continue;
}
- const int offset = (dotSize - 1) / 2;
+ const int offset = (int) ((dotSize - 1) * mProportion);
+
graphics->fillRectangle(gcn::Rectangle(
- being->mX / 2 + mapOriginX - offset,
- being->mY / 2 + mapOriginY - offset,
+ (int) (being->mX * mProportion) + mapOriginX - offset,
+ (int) (being->mY * mProportion) + mapOriginY - offset,
dotSize, dotSize));
}
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index 67f5eb18..b4574ad5 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -24,6 +24,8 @@
#include "window.h"
+#include "../guichanfwd.h"
+
class Image;
/**
@@ -50,12 +52,24 @@ class Minimap : public Window
void setMapImage(Image *img);
/**
+ * Sets the map proportion (1 means 1 tile to one pixel, .5 means 2 tiles to 1 pixel, etc.)
+ */
+ void setProportion(float proportion) { mProportion = proportion; }
+
+ /**
+ * Toggles the displaying of the minimap.
+ */
+ void toggle();
+
+ /**
* Draws the minimap.
*/
void draw(gcn::Graphics *graphics);
private:
Image *mMapImage;
+ float mProportion;
+ static bool mShow;
};
extern Minimap *minimap;
diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp
index e613a745..915db961 100644
--- a/src/gui/ministatus.cpp
+++ b/src/gui/ministatus.cpp
@@ -19,14 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "ministatus.h"
-
#include "gui.h"
+#include "ministatus.h"
#include "progressbar.h"
-#include "../localplayer.h"
#include "../configuration.h"
#include "../graphics.h"
+#include "../localplayer.h"
#include "../utils/tostring.h"
@@ -90,24 +89,22 @@ void MiniStatusWindow::update()
mHpBar->setColor(0, 171, 34); // Green
}
+ float xp = (float) player_node->getXp() / player_node->mXpForNextLevel;
+
+ if (xp != xp) xp = 0.0f; // check for NaN
+ if (xp < 0.0f) xp = 0.0f; // make sure the experience isn't negative (uninitialized pointer most likely)
+ if (xp > 1.0f) xp = 1.0f;
+
mHpBar->setProgress((float) player_node->mHp / player_node->mMaxHp);
mMpBar->setProgress((float) player_node->mMp / player_node->mMaxMp);
- if (player_node->MATK <= 0)
- mMpBar->setColor(100, 100, 100); // grey, to indicate that we lack magic
- else
- mMpBar->setColor(26, 102, 230); // blue, to indicate that we have magic
-
- mXpBar->setProgress(
- (float) player_node->getXp() / player_node->mXpForNextLevel);
+ mXpBar->setProgress(xp);
// Update labels
mHpBar->setText(toString(player_node->mHp));
mMpBar->setText(toString(player_node->mMp));
std::stringstream updatedText;
- updatedText << (int) (
- (float) player_node->getXp() /
- player_node->mXpForNextLevel * 100) << "%";
+ updatedText << (float) ((int) (xp * 10000.0f)) / 100.0f << "%";
// Displays the number of monsters to next lvl
// (disabled for now but interesting idea)
diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp
index 6ad698bc..a2e043d1 100644
--- a/src/gui/npc_text.cpp
+++ b/src/gui/npc_text.cpp
@@ -19,14 +19,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npc_text.h"
-
#include <string>
+#include "npc_text.h"
#include "browserbox.h"
#include "button.h"
#include "scrollarea.h"
+#include "widgets/layout.h"
+
#include "../npc.h"
#include "../utils/gettext.h"
@@ -39,24 +40,24 @@ NpcTextDialog::NpcTextDialog():
setMinWidth(200);
setMinHeight(150);
+ setDefaultSize(0, 0, 260, 200);
+
mBrowserBox = new BrowserBox(BrowserBox::AUTO_WRAP);
- mBrowserBox->setOpaque(true);
+ mBrowserBox->setOpaque(false);
scrollArea = new ScrollArea(mBrowserBox);
okButton = new Button(_("OK"), "ok", this);
- setContentSize(260, 175);
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
scrollArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, 250, 160 - okButton->getHeight()));
- okButton->setPosition(
- 260 - 5 - okButton->getWidth(),
- 175 - 5 - okButton->getHeight());
- add(scrollArea);
- add(okButton);
+ place(0, 0, scrollArea, 5).setPadding(3);
+ place(4, 1, okButton);
+
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+ loadWindowState();
setLocationRelativeTo(getParent());
}
@@ -76,21 +77,6 @@ void NpcTextDialog::addText(const std::string &text)
mBrowserBox->addRow(text);
}
-void NpcTextDialog::widgetResized(const gcn::Event &event)
-{
- Window::widgetResized(event);
-
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, width - 10, height - 15 - okButton->getHeight()));
- okButton->setPosition(
- width - 5 - okButton->getWidth(),
- height - 5 - okButton->getHeight());
-}
-
void NpcTextDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "ok")
diff --git a/src/gui/npc_text.h b/src/gui/npc_text.h
index c881467a..b4b6f1af 100644
--- a/src/gui/npc_text.h
+++ b/src/gui/npc_text.h
@@ -23,8 +23,10 @@
#define NPC_TEXT_H
#include <iosfwd>
+
#include <guichan/actionlistener.hpp>
+#include "scrollarea.h"
#include "window.h"
class BrowserBox;
@@ -45,13 +47,6 @@ class NpcTextDialog : public Window, public gcn::ActionListener
NpcTextDialog();
/**
- * Called when resizing the window.
- *
- * @param event The calling event
- */
- void widgetResized(const gcn::Event &event);
-
- /**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
diff --git a/src/gui/npcintegerdialog.cpp b/src/gui/npcintegerdialog.cpp
index ec91d736..65a1a7f1 100644
--- a/src/gui/npcintegerdialog.cpp
+++ b/src/gui/npcintegerdialog.cpp
@@ -107,5 +107,6 @@ void NpcIntegerDialog::action(const gcn::ActionEvent &event)
setVisible(false);
current_npc->integerInput(mValueField->getValue());
current_npc = 0;
+ mValueField->reset();
}
}
diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp
index 4b05df5a..bb815680 100644
--- a/src/gui/npclistdialog.cpp
+++ b/src/gui/npclistdialog.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "npclistdialog.h"
-
#include <sstream>
-#include "button.h"
-#include "scrollarea.h"
#include "listbox.h"
+#include "npclistdialog.h"
+
+#include "widgets/layout.h"
#include "../npc.h"
@@ -39,6 +38,8 @@ NpcListDialog::NpcListDialog():
setMinWidth(200);
setMinHeight(150);
+ setDefaultSize(0, 0, 260, 200);
+
mItemList = new ListBox(this);
scrollArea = new ScrollArea(mItemList);
okButton = new Button(_("OK"), "ok", this);
@@ -46,23 +47,15 @@ NpcListDialog::NpcListDialog():
setContentSize(260, 175);
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, 250, 160 - okButton->getHeight()));
- cancelButton->setPosition(
- 260 - 5 - cancelButton->getWidth(),
- 175 - 5 - cancelButton->getHeight());
- okButton->setPosition(
- cancelButton->getX() - 5 - okButton->getWidth(),
- cancelButton->getY());
- mItemList->setActionEventId("item");
+ place(0, 0, scrollArea, 5).setPadding(3);
+ place(3, 1, okButton);
+ place(4, 1, cancelButton);
- mItemList->addActionListener(this);
-
- add(scrollArea);
- add(okButton);
- add(cancelButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
+ loadWindowState();
setLocationRelativeTo(getParent());
}
@@ -90,24 +83,6 @@ void NpcListDialog::reset()
mItems.clear();
}
-void NpcListDialog::widgetResized(const gcn::Event &event)
-{
- Window::widgetResized(event);
-
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, width - 10, height - 15 - okButton->getHeight()));
- cancelButton->setPosition(
- width - 5 - cancelButton->getWidth(),
- height - 5 - cancelButton->getHeight());
- okButton->setPosition(
- cancelButton->getX() - 5 - okButton->getWidth(),
- cancelButton->getY());
-}
-
void NpcListDialog::action(const gcn::ActionEvent &event)
{
int choice = 0;
diff --git a/src/gui/npclistdialog.h b/src/gui/npclistdialog.h
index 2ae4aae3..ffeced3d 100644
--- a/src/gui/npclistdialog.h
+++ b/src/gui/npclistdialog.h
@@ -28,6 +28,8 @@
#include <guichan/actionlistener.hpp>
#include <guichan/listmodel.hpp>
+#include "button.h"
+#include "scrollarea.h"
#include "window.h"
#include "../guichanfwd.h"
@@ -49,13 +51,6 @@ class NpcListDialog : public Window, public gcn::ActionListener,
NpcListDialog();
/**
- * Called when resizing the window
- *
- * @param event The calling event
- */
- void widgetResized(const gcn::Event &event);
-
- /**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
diff --git a/src/gui/npcstringdialog.cpp b/src/gui/npcstringdialog.cpp
index 1c92d620..ccb3c411 100644
--- a/src/gui/npcstringdialog.cpp
+++ b/src/gui/npcstringdialog.cpp
@@ -42,8 +42,8 @@ NpcStringDialog::NpcStringDialog():
cancelButton = new Button(_("Cancel"), "cancel", this);
place(0, 0, mValueField, 3);
- place(1, 1, okButton);
- place(2, 1, cancelButton);
+ place(1, 1, cancelButton);
+ place(2, 1, okButton);
reflowLayout(175, 0);
setLocationRelativeTo(getParent());
@@ -69,6 +69,7 @@ void NpcStringDialog::action(const gcn::ActionEvent &event)
setVisible(false);
current_npc->stringInput(mValueField->getText());
current_npc = 0;
+ mValueField->setText("");
}
bool NpcStringDialog::isInputFocused()
diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp
index a2134d5d..dc66a900 100644
--- a/src/gui/ok_dialog.cpp
+++ b/src/gui/ok_dialog.cpp
@@ -20,9 +20,8 @@
*/
#include "ok_dialog.h"
-#include "textbox.h"
-#include "button.h"
-#include "scrollarea.h"
+
+#include <guichan/font.hpp>
#include "../utils/gettext.h"
@@ -30,25 +29,45 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg,
Window *parent):
Window(title, true, parent)
{
- TextBox *textBox = new TextBox();
- textBox->setEditable(false);
+ mTextBox = new TextBox();
+ mTextBox->setEditable(false);
+ mTextBox->setOpaque(false);
+
+ mTextArea = new ScrollArea(mTextBox);
+ okButton = new Button(_("Ok"), "ok", this);
+
+ mTextArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mTextArea->setOpaque(false);
- gcn::ScrollArea *scrollArea = new ScrollArea(textBox);
- gcn::Button *okButton = new Button(_("Ok"), "ok", this);
+ mTextBox->setMinWidth(260);
+ mTextBox->setTextWrapped(msg);
- setContentSize(260, 175);
- scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
- scrollArea->setDimension(gcn::Rectangle(
- 5, 5, 250, 160 - okButton->getHeight()));
+ int numRows = mTextBox->getNumberOfRows();
- textBox->setTextWrapped(msg);
+ if (numRows > 1)
+ {
+ // 15 == height of each line of text (based on font heights)
+ // 14 == row top + bottom graphic pixel heights
+ setContentSize(mTextBox->getMinWidth() + 15, 15 + (numRows * 15) + okButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, mTextBox->getMinWidth() + 5,
+ 3 + (numRows * 14)));
+ }
+ else
+ {
+ int width = getFont()->getWidth(title);
+ if (width < getFont()->getWidth(msg))
+ width = getFont()->getWidth(msg);
+ if (width < okButton->getWidth())
+ width = okButton->getWidth();
+ setContentSize(width + 15, 30 + okButton->getHeight());
+ mTextArea->setDimension(gcn::Rectangle(4, 5, width + 5, 17));
+ }
- okButton->setPosition(
- 260 - 5 - okButton->getWidth(),
- 175 - 5 - okButton->getHeight());
+ okButton->setPosition((mTextBox->getMinWidth() - okButton->getWidth()) / 2,
+ (numRows * 14) + okButton->getHeight() - 8);
- add(scrollArea);
+ add(mTextArea);
add(okButton);
setLocationRelativeTo(getParent());
@@ -56,6 +75,11 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg,
okButton->requestFocus();
}
+unsigned int OkDialog::getNumRows()
+{
+ return mTextBox->getNumberOfRows();
+}
+
void OkDialog::action(const gcn::ActionEvent &event)
{
// Proxy button events to our listeners
diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h
index 44dc6bb9..78b3d44f 100644
--- a/src/gui/ok_dialog.h
+++ b/src/gui/ok_dialog.h
@@ -24,8 +24,13 @@
#include <guichan/actionlistener.hpp>
+#include "button.h"
+#include "scrollarea.h"
+#include "textbox.h"
#include "window.h"
+#include "../guichanfwd.h"
+
/**
* An 'Ok' button dialog.
*
@@ -41,10 +46,17 @@ class OkDialog : public Window, public gcn::ActionListener {
OkDialog(const std::string &title, const std::string &msg,
Window *parent = NULL);
+ unsigned int getNumRows();
+
/**
* Called when receiving actions from the widgets.
*/
void action(const gcn::ActionEvent &event);
+
+ private:
+ TextBox *mTextBox;
+ ScrollArea *mTextArea;
+ gcn::Button *okButton;
};
#endif
diff --git a/src/gui/passwordfield.h b/src/gui/passwordfield.h
index d6082e3f..e01bedbd 100644
--- a/src/gui/passwordfield.h
+++ b/src/gui/passwordfield.h
@@ -24,12 +24,15 @@
#include "textfield.h"
+#include "../guichanfwd.h"
+
/**
* A password field.
*
* \ingroup GUI
*/
-class PasswordField : public TextField {
+class PasswordField : public TextField
+{
public:
/**
* Constructor, initializes the password field with the given string.
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
index 8f698df5..c22d407c 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -23,8 +23,10 @@
#include "playerbox.h"
-#include "../player.h"
+#include "../animatedsprite.h"
+#include "../configuration.h"
#include "../graphics.h"
+#include "../player.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
@@ -54,6 +56,7 @@ PlayerBox::PlayerBox(const Player *player):
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++;
}
}
@@ -83,7 +86,13 @@ void PlayerBox::draw(gcn::Graphics *graphics)
bs = getFrameSize();
x = getWidth() / 2 - 16 + bs;
y = getHeight() / 2 + bs;
- mPlayer->draw(static_cast<Graphics*>(graphics), x, y);
+ for (int i = 0; i < Being::VECTOREND_SPRITE; i++)
+ {
+ if (mPlayer->getSprite(i) != NULL)
+ {
+ mPlayer->getSprite(i)->draw(static_cast<Graphics*>(graphics), x, y);
+ }
+ }
}
}
diff --git a/src/gui/playerbox.h b/src/gui/playerbox.h
index d66db4d4..5aacd26f 100644
--- a/src/gui/playerbox.h
+++ b/src/gui/playerbox.h
@@ -24,6 +24,8 @@
#include <guichan/widgets/scrollarea.hpp>
+#include "../guichanfwd.h"
+
class ImageRect;
class Player;
@@ -51,8 +53,7 @@ class PlayerBox : public gcn::ScrollArea
* player to <code>NULL</code> causes the box not to draw any
* character.
*/
- void
- setPlayer(const Player *player) { mPlayer = player; }
+ void setPlayer(const Player *player) { mPlayer = player; }
/**
* Draws the scroll area.
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index 06a2ad87..9b0c2370 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -19,16 +19,16 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "popupmenu.h"
-
#include <cassert>
#include <iostream>
#include <guichan/focushandler.hpp>
#include "browserbox.h"
+#include "chat.h"
#include "inventorywindow.h"
#include "item_amount.h"
+#include "popupmenu.h"
#include "windowcontainer.h"
#include "../being.h"
@@ -39,8 +39,11 @@
#include "../npc.h"
#include "../player_relations.h"
-#include "../resources/iteminfo.h"
+#include "../net/messageout.h"
+#include "../net/protocol.h"
+
#include "../resources/itemdb.h"
+#include "../resources/iteminfo.h"
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
@@ -72,51 +75,53 @@ void PopupMenu::showPopup(int x, int y, Being *being)
switch (being->getType())
{
- case Being::PLAYER:
- {
- // Players can be traded with. Later also attack, follow and
- // add as buddy will be options in this menu.
- const std::string &name = being->getName();
- mBrowserBox->addRow(
- strprintf(_("@@trade|Trade With %s@@"), name.c_str()));
- mBrowserBox->addRow(
- strprintf(_("@@attack|Attack %s@@"), name.c_str()));
-
- mBrowserBox->addRow("##3---");
-
- switch (player_relations.getRelation(name)) {
- case PlayerRelation::NEUTRAL:
- mBrowserBox->addRow("@@friend|Befriend " + name + "@@");
-
- case PlayerRelation::FRIEND:
- mBrowserBox->addRow("@@disregard|Disregard " + name + "@@");
- mBrowserBox->addRow("@@ignore|Ignore " + name + "@@");
- break;
-
- case PlayerRelation::DISREGARDED:
- mBrowserBox->addRow("@@unignore|Un-Ignore " + name + "@@");
- mBrowserBox->addRow("@@ignore|Completely ignore " + name + "@@");
- break;
-
- case PlayerRelation::IGNORED:
- mBrowserBox->addRow("@@unignore|Un-Ignore " + name + "@@");
- break;
- }
-
- //mBrowserBox->addRow("@@follow|Follow " + name + "@@");
- //mBrowserBox->addRow("@@buddy|Add " + name + " to Buddy List@@");
- }
- break;
-
- case Being::NPC:
- // NPCs can be talked to (single option, candidate for removal
- // unless more options would be added)
- mBrowserBox->addRow(_("@@talk|Talk To NPC@@"));
- break;
-
- default:
- /* Other beings aren't interesting... */
- break;
+ case Being::PLAYER:
+ {
+ // Players can be traded with. Later also attack, follow and
+ // add as buddy will be options in this menu.
+ const std::string &name = being->getName();
+ mBrowserBox->addRow(_("@@trade|Trade With ") + name + "@@");
+ mBrowserBox->addRow(_("@@attack|Attack ") + name + "@@");
+
+ mBrowserBox->addRow("##3---");
+
+ switch (player_relations.getRelation(name)) {
+ case PlayerRelation::NEUTRAL:
+ mBrowserBox->addRow(_("@@friend|Befriend ") + name + "@@");
+
+ case PlayerRelation::FRIEND:
+ mBrowserBox->addRow(_("@@disregard|Disregard ") + name + "@@");
+ mBrowserBox->addRow(_("@@ignore|Ignore ") + name + "@@");
+ break;
+
+ case PlayerRelation::DISREGARDED:
+ mBrowserBox->addRow(_("@@unignore|Un-Ignore ") + name + "@@");
+ mBrowserBox->addRow(_("@@ignore|Completely ignore ") + name + "@@");
+ break;
+
+ case PlayerRelation::IGNORED:
+ mBrowserBox->addRow(_("@@unignore|Un-Ignore ") + name + "@@");
+ break;
+ }
+
+ //mBrowserBox->addRow(_("@@follow|Follow ") + name + "@@");
+ //mBrowserBox->addRow(_("@@buddy|Add ") + name + " to Buddy List@@");
+
+ mBrowserBox->addRow("##3---");
+ mBrowserBox->addRow(_("@@party-invite|Invite ") + name +
+ " to party@@");
+ }
+ break;
+
+ case Being::NPC:
+ // NPCs can be talked to (single option, candidate for removal
+ // unless more options would be added)
+ mBrowserBox->addRow(_("@@talk|Talk To NPC@@"));
+ break;
+
+ default:
+ /* Other beings aren't interesting... */
+ break;
}
//browserBox->addRow("@@look|Look To@@");
@@ -148,28 +153,28 @@ void PopupMenu::handleLink(const std::string& link)
// Talk To action
if (link == "talk" &&
- being != NULL &&
- being->getType() == Being::NPC &&
- current_npc == 0)
+ being != NULL &&
+ being->getType() == Being::NPC &&
+ current_npc == 0)
{
- dynamic_cast<NPC*>(being)->talk();
+ dynamic_cast<NPC*>(being)->talk();
}
// Trade action
else if (link == "trade" &&
- being != NULL &&
- being->getType() == Being::PLAYER)
+ being != NULL &&
+ being->getType() == Being::PLAYER)
{
- player_node->trade(being);
- tradePartnerName = being->getName();
+ player_node->trade(being);
+ tradePartnerName = being->getName();
}
// Attack action
else if (link == "attack" &&
- being != NULL &&
- being->getType() == Being::PLAYER)
+ being != NULL &&
+ being->getType() == Being::PLAYER)
{
- player_node->attack(being, true);
+ player_node->attack(being, true);
}
else if (link == "unignore" &&
@@ -194,10 +199,10 @@ void PopupMenu::handleLink(const std::string& link)
}
else if (link == "friend" &&
- being != NULL &&
- being->getType() == Being::PLAYER)
+ being != NULL &&
+ being->getType() == Being::PLAYER)
{
- player_relations.setRelation(being->getName(), PlayerRelation::FRIEND);
+ player_relations.setRelation(being->getName(), PlayerRelation::FRIEND);
}
/*
@@ -210,16 +215,16 @@ void PopupMenu::handleLink(const std::string& link)
// Add Buddy action
else if ((link == "buddy") && being != NULL && being->isPlayer())
{
- if (!buddyWindow->isVisible())
- buddyWindow->setVisible(true);
+ if (!buddyWindow->isVisible())
+ buddyWindow->setVisible(true);
- buddyWindow->addBuddy(being->getName());
+ buddyWindow->addBuddy(being->getName());
}*/
// Pick Up Floor Item action
else if ((link == "pickup") && mFloorItem != NULL)
{
- player_node->pickUp(mFloorItem);
+ player_node->pickUp(mFloorItem);
}
// Look To action
@@ -229,39 +234,46 @@ void PopupMenu::handleLink(const std::string& link)
else if (link == "use")
{
- assert(mItem);
- if (mItem->isEquipment())
- {
- if (mItem->isEquipped())
- {
- player_node->unequipItem(mItem);
- }
- else
- {
- player_node->equipItem(mItem);
- }
- }
- else
- {
- player_node->useItem(mItem);
- }
+ assert(mItem);
+ if (mItem->isEquipment())
+ {
+ if (mItem->isEquipped())
+ {
+ player_node->unequipItem(mItem);
+ }
+ else
+ {
+ player_node->equipItem(mItem);
+ }
+ }
+ else
+ {
+ player_node->useItem(mItem);
+ }
}
- else if (link == "drop")
+ else if (link == "chat")
{
- new ItemAmountWindow(AMOUNT_ITEM_DROP, inventoryWindow, mItem);
+ chatWindow->addItemText(mItem->getId(), mItem->getInfo().getName());
}
- else if (link == "description")
+ else if (link == "drop")
+ {
+ new ItemAmountWindow(AMOUNT_ITEM_DROP, inventoryWindow, mItem);
+ }
+ else if (link == "party-invite" &&
+ being != NULL &&
+ being->getType() == Being::PLAYER)
{
- // do nothing for now, I need to write
- // a window for the description first
+ MessageOut outMsg(player_node->getNetwork());
+ outMsg.writeInt16(CMSG_PARTY_INVITE);
+ outMsg.writeInt32(being->getId());
}
// Unknown actions
else
{
- std::cout << link << std::endl;
+ std::cout << link << std::endl;
}
setVisible(false);
@@ -288,7 +300,7 @@ void PopupMenu::showPopup(int x, int y, Item *item)
mBrowserBox->addRow(_("@@use|Use@@"));
mBrowserBox->addRow(_("@@drop|Drop@@"));
- mBrowserBox->addRow(_("@@description|Description@@"));
+ mBrowserBox->addRow(_("@@chat|Add to Chat@@"));
mBrowserBox->addRow("##3---");
mBrowserBox->addRow(_("@@cancel|Cancel@@"));
@@ -299,9 +311,9 @@ void PopupMenu::showPopup(int x, int y)
{
setContentSize(mBrowserBox->getWidth() + 8, mBrowserBox->getHeight() + 8);
if (windowContainer->getWidth() < (x + getWidth() + 5))
- x = windowContainer->getWidth() - getWidth();
+ x = windowContainer->getWidth() - getWidth();
if (windowContainer->getHeight() < (y + getHeight() + 5))
- y = windowContainer->getHeight() - getHeight();
+ y = windowContainer->getHeight() - getHeight();
setPosition(x, y);
setVisible(true);
requestMoveToTop();
diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h
index 1165bcb2..2694abd8 100644
--- a/src/gui/popupmenu.h
+++ b/src/gui/popupmenu.h
@@ -24,15 +24,14 @@
#include <SDL.h> // for Uint32
-#include "window.h"
#include "linkhandler.h"
+#include "window.h"
class Being;
class BrowserBox;
class FloorItem;
class Item;
-
/**
* Window showing popup menu.
*/
diff --git a/src/gui/progressbar.cpp b/src/gui/progressbar.cpp
index d877bfbc..ecc0017d 100644
--- a/src/gui/progressbar.cpp
+++ b/src/gui/progressbar.cpp
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "gui.h"
#include "progressbar.h"
#include "../graphics.h"
@@ -105,7 +106,7 @@ void ProgressBar::draw(gcn::Graphics *graphics)
// The label
if (!mText.empty()) {
- gcn::Font *f = getFont();
+ gcn::Font *f = boldFont;
const int textX = getWidth() / 2;
const int textY = (getHeight() - f->getHeight()) / 2;
diff --git a/src/gui/progressbar.h b/src/gui/progressbar.h
index a4b30b04..ee0a5f81 100644
--- a/src/gui/progressbar.h
+++ b/src/gui/progressbar.h
@@ -25,9 +25,10 @@
#include <guichan/widget.hpp>
#include <SDL_types.h>
-
#include <string>
+#include "../guichanfwd.h"
+
class ImageRect;
/**
@@ -81,12 +82,12 @@ class ProgressBar : public gcn::Widget
Uint8 getRed() const { return mRed; }
/**
- * Returns the red value of color.
+ * Returns the green value of color.
*/
Uint8 getGreen() const { return mGreen; }
/**
- * Returns the red value of color.
+ * Returns the blue value of color.
*/
Uint8 getBlue() const { return mBlue; }
diff --git a/src/gui/radiobutton.h b/src/gui/radiobutton.h
index 2d2bdbb7..dcd62802 100644
--- a/src/gui/radiobutton.h
+++ b/src/gui/radiobutton.h
@@ -24,8 +24,9 @@
#include <guichan/widgets/radiobutton.hpp>
-class Image;
+#include "../guichanfwd.h"
+class Image;
/*
* Guichan based RadioButton with custom look
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index 5605ef96..9c337d9e 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "register.h"
-
#include <string>
#include <sstream>
@@ -34,10 +32,13 @@
#include "button.h"
#include "checkbox.h"
#include "login.h"
+#include "ok_dialog.h"
#include "passwordfield.h"
#include "radiobutton.h"
+#include "register.h"
#include "textfield.h"
-#include "ok_dialog.h"
+
+#include "../utils/tostring.h"
#include "widgets/layout.h"
@@ -80,10 +81,12 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
gcn::Label *passwordLabel = new gcn::Label(_("Password:"));
gcn::Label *confirmLabel = new gcn::Label(_("Confirm:"));
gcn::Label *serverLabel = new gcn::Label(_("Server:"));
+ gcn::Label *portLabel = new gcn::Label(_("Port:"));
mUserField = new TextField(loginData->username);
mPasswordField = new PasswordField(loginData->password);
mConfirmField = new PasswordField;
mServerField = new TextField(loginData->hostname);
+ mPortField = new TextField(toString(loginData->port));
mMaleButton = new RadioButton(_("Male"), "sex", true);
mFemaleButton = new RadioButton(_("Female"), "sex", false);
mRegisterButton = new Button(_("Register"), "register", this);
@@ -97,10 +100,12 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
place(1, 3, mMaleButton);
place(2, 3, mFemaleButton);
place(0, 4, serverLabel);
+ place(0, 5, portLabel);
place(1, 0, mUserField, 3).setPadding(2);
place(1, 1, mPasswordField, 3).setPadding(2);
place(1, 2, mConfirmField, 3).setPadding(2);
place(1, 4, mServerField, 3).setPadding(2);
+ place(1, 5, mPortField, 3).setPadding(2);
place = getPlacer(0, 2);
place(1, 0, mRegisterButton);
place(2, 0, mCancelButton);
@@ -110,6 +115,7 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
mPasswordField->addKeyListener(this);
mConfirmField->addKeyListener(this);
mServerField->addKeyListener(this);
+ mPortField->addKeyListener(this);
/* TODO:
* This is a quick and dirty way to respond to the ENTER key, regardless of
@@ -120,10 +126,13 @@ RegisterDialog::RegisterDialog(LoginData *loginData):
mPasswordField->setActionEventId("register");
mConfirmField->setActionEventId("register");
mServerField->setActionEventId("register");
+ mPortField->setActionEventId("register");
+
mUserField->addActionListener(this);
mPasswordField->addActionListener(this);
mConfirmField->addActionListener(this);
mServerField->addActionListener(this);
+ mPortField->addActionListener(this);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -147,7 +156,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
else if (event.getId() == "register" && canSubmit())
{
const std::string user = mUserField->getText();
- logger->log("RegisterDialog::register Username is %s", user.c_str());
+ logger->log(_("RegisterDialog::register Username is %s"), user.c_str());
std::string errorMsg;
int error = 0;
@@ -216,7 +225,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
mRegisterButton->setEnabled(false);
mLoginData->hostname = mServerField->getText();
- mLoginData->port = (short) config.getValue("port", 0);
+ mLoginData->port = getUShort(mPortField->getText());
mLoginData->username = mUserField->getText();
mLoginData->password = mPasswordField->getText();
mLoginData->username += mFemaleButton->isSelected() ? "_F" : "_M";
@@ -238,5 +247,40 @@ bool RegisterDialog::canSubmit() const
!mPasswordField->getText().empty() &&
!mConfirmField->getText().empty() &&
!mServerField->getText().empty() &&
+ isUShort(mPortField->getText()) &&
state == REGISTER_STATE;
}
+
+bool RegisterDialog::isUShort(const std::string &str)
+{
+ if (str == "")
+ {
+ return false;
+ }
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ if (*strPtr < '0' || *strPtr > '9')
+ {
+ return false;
+ }
+ l = l * 10 + (*strPtr - '0'); // *strPtr - '0' will never be negative
+ if (l > 65535)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+unsigned short RegisterDialog::getUShort(const std::string &str)
+{
+ unsigned long l = 0;
+ for (std::string::const_iterator strPtr = str.begin(), strEnd = str.end();
+ strPtr != strEnd; ++strPtr)
+ {
+ l = l * 10 + (*strPtr - '0');
+ }
+ return static_cast<unsigned short>(l);
+}
diff --git a/src/gui/register.h b/src/gui/register.h
index 3dddae0f..4b95a07b 100644
--- a/src/gui/register.h
+++ b/src/gui/register.h
@@ -23,10 +23,12 @@
#define REGISTER_H
#include <iosfwd>
+
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
#include "window.h"
+
#include "../guichanfwd.h"
class LoginData;
@@ -72,10 +74,29 @@ class RegisterDialog : public Window, public gcn::ActionListener,
*/
bool canSubmit() const;
+ /**
+ * Function to decide whether string is an unsigned short or not
+ *
+ * @param str the string to parse
+ *
+ * @return true if str is an unsigned short, false otherwise
+ */
+ static bool isUShort(const std::string &str);
+
+ /**
+ * Converts string to an unsigned short (undefined if invalid)
+ *
+ * @param str the string to parse
+ *
+ * @return the value str represents
+ */
+ static unsigned short getUShort(const std::string &str);
+
gcn::TextField *mUserField;
gcn::TextField *mPasswordField;
gcn::TextField *mConfirmField;
gcn::TextField *mServerField;
+ gcn::TextField *mPortField;
gcn::Button *mRegisterButton;
gcn::Button *mCancelButton;
diff --git a/src/gui/scrollarea.cpp b/src/gui/scrollarea.cpp
index 8a74cd72..1d7f8472 100644
--- a/src/gui/scrollarea.cpp
+++ b/src/gui/scrollarea.cpp
@@ -23,6 +23,7 @@
#include "scrollarea.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -94,6 +95,7 @@ void ScrollArea::init()
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++;
}
}
@@ -106,12 +108,15 @@ void ScrollArea::init()
int vsgridy[4] = {0, 4, 15, 19};
a = 0;
- for (y = 0; y < 3; y++) {
- for (x = 0; x < 3; x++) {
+ for (y = 0; y < 3; y++)
+ {
+ for (x = 0; x < 3; x++)
+ {
vMarker.grid[a] = vscroll->getSubImage(
vsgridx[x], vsgridy[y],
vsgridx[x + 1] - vsgridx[x],
vsgridy[y + 1] - vsgridy[y]);
+ vMarker.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
a++;
}
}
@@ -197,7 +202,8 @@ void ScrollArea::drawFrame(gcn::Graphics *graphics)
int w = getWidth() + bs * 2;
int h = getHeight() + bs * 2;
- if (mOpaque) {
+ if (mOpaque)
+ {
static_cast<Graphics*>(graphics)->
drawImageRect(0, 0, w, h, background);
}
@@ -207,10 +213,12 @@ void ScrollArea::setOpaque(bool opaque)
{
mOpaque = opaque;
- if (mOpaque) {
+ if (mOpaque)
+ {
setFrameSize(2);
}
- else {
+ else
+ {
setFrameSize(0);
}
}
@@ -220,7 +228,8 @@ void ScrollArea::drawButton(gcn::Graphics *graphics, BUTTON_DIR dir)
int state = 0;
gcn::Rectangle dim;
- switch(dir) {
+ switch(dir)
+ {
case UP:
state = mUpButtonPressed ? 1 : 0;
dim = getUpButtonDimension();
diff --git a/src/gui/scrollarea.h b/src/gui/scrollarea.h
index 1641f318..4fababfa 100644
--- a/src/gui/scrollarea.h
+++ b/src/gui/scrollarea.h
@@ -24,6 +24,8 @@
#include <guichan/widgets/scrollarea.hpp>
+#include "../guichanfwd.h"
+
class Image;
class ImageRect;
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index cc6f02d5..7976e32e 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "sell.h"
-
#include <cassert>
#include <guichan/widgets/label.hpp>
@@ -28,6 +26,7 @@
#include "button.h"
#include "shoplistbox.h"
#include "scrollarea.h"
+#include "sell.h"
#include "shop.h"
#include "slider.h"
@@ -36,13 +35,14 @@
#include "../item.h"
#include "../npc.h"
-#include "../resources/iteminfo.h"
-
#include "../net/messageout.h"
#include "../net/protocol.h"
+#include "../resources/iteminfo.h"
+
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
+#include "../utils/tostring.h"
SellDialog::SellDialog(Network *network):
Window(_("Sell")),
diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp
index d38fb2e3..d18f365c 100644
--- a/src/gui/setup.cpp
+++ b/src/gui/setup.cpp
@@ -19,31 +19,33 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup.h"
+#include <algorithm>
+#include <iostream>
#include "button.h"
+#include "setup.h"
#include "setup_audio.h"
+#include "setup_colours.h"
#include "setup_joystick.h"
-#include "setup_video.h"
#include "setup_keyboard.h"
#include "setup_players.h"
+#include "setup_video.h"
#include "widgets/tabbedarea.h"
#include "../utils/dtor.h"
#include "../utils/gettext.h"
-#include <algorithm>
-#include <iostream>
-
-extern Window *statusWindow;
-extern Window *minimap;
extern Window *chatWindow;
-extern Window *inventoryWindow;
extern Window *equipmentWindow;
extern Window *helpWindow;
+extern Window *inventoryWindow;
+extern Window *minimap;
extern Window *skillDialog;
+extern Window *statusWindow;
extern Window *itemShortcutWindow;
+extern Window *emoteShortcutWindow;
+extern Window *emoteWindow;
extern Window *tradeWindow;
Setup::Setup():
@@ -58,7 +60,8 @@ Setup::Setup():
N_("Apply"), N_("Cancel"), N_("Reset Windows"), 0
};
int x = width;
- for (const char **curBtn = buttonNames; *curBtn; ++curBtn) {
+ for (const char **curBtn = buttonNames; *curBtn; ++curBtn)
+ {
Button *btn = new Button(gettext(*curBtn), *curBtn, this);
x -= btn->getWidth() + 5;
btn->setPosition(x, height - btn->getHeight() - 5);
@@ -90,6 +93,10 @@ Setup::Setup():
panel->addTab(_("Keyboard"), tab);
mTabs.push_back(tab);
+ tab = new Setup_Colours();
+ panel->addTab(_("Colors"), tab);
+ mTabs.push_back(tab);
+
tab = new Setup_Players();
panel->addTab(_("Players"), tab);
mTabs.push_back(tab);
@@ -131,6 +138,8 @@ void Setup::action(const gcn::ActionEvent &event)
helpWindow->resetToDefaultSize();
skillDialog->resetToDefaultSize();
itemShortcutWindow->resetToDefaultSize();
+ emoteShortcutWindow->resetToDefaultSize();
+ emoteWindow->resetToDefaultSize();
tradeWindow->resetToDefaultSize();
}
}
diff --git a/src/gui/setup.h b/src/gui/setup.h
index 881961f6..e4eb0902 100644
--- a/src/gui/setup.h
+++ b/src/gui/setup.h
@@ -28,6 +28,8 @@
#include "window.h"
+#include "../guichanfwd.h"
+
class SetupTab;
/**
@@ -51,8 +53,7 @@ class Setup : public Window, public gcn::ActionListener
/**
* Event handling method.
*/
- void
- action(const gcn::ActionEvent &event);
+ void action(const gcn::ActionEvent &event);
private:
std::list<SetupTab*> mTabs;
diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp
index b9fc1d2d..7090136e 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -19,12 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_audio.h"
-
#include <guichan/widgets/label.hpp>
#include "checkbox.h"
#include "ok_dialog.h"
+#include "setup_audio.h"
#include "slider.h"
#include "widgets/layouthelper.h"
diff --git a/src/gui/setup_audio.h b/src/gui/setup_audio.h
index 5345d3cf..2f5cd736 100644
--- a/src/gui/setup_audio.h
+++ b/src/gui/setup_audio.h
@@ -22,10 +22,10 @@
#ifndef GUI_SETUP_AUDIO_H
#define GUI_SETUP_AUDIO_H
-#include "setuptab.h"
-
#include <guichan/actionlistener.hpp>
+#include "setuptab.h"
+
#include "../guichanfwd.h"
class Setup_Audio : public SetupTab, public gcn::ActionListener
diff --git a/src/gui/setup_colours.cpp b/src/gui/setup_colours.cpp
new file mode 100644
index 00000000..c08c94ef
--- /dev/null
+++ b/src/gui/setup_colours.cpp
@@ -0,0 +1,226 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Douglas Boffey *
+ * *
+ * DougABoffey@netscape.net *
+ * 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 *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed with The Mana Experiment *
+ * 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 <vector>
+
+#include <guichan/listmodel.hpp>
+#include <guichan/widgets/label.hpp>
+#include <guichan/widgets/slider.hpp>
+
+#include "colour.h"
+#include "scrollarea.h"
+#include "setup_colours.h"
+#include "slider.h"
+#include "textfield.h"
+
+#include "widgets/layouthelper.h"
+
+#include "../configuration.h"
+
+#include "../utils/gettext.h"
+
+Setup_Colours::Setup_Colours() :
+ mSelected(-1)
+{
+ setOpaque(false);
+
+ mColourBox = new gcn::ListBox(textColour);
+ mColourBox->setActionEventId("colour_box");
+ mColourBox->addActionListener(this);
+
+ mScroll = new ScrollArea(mColourBox);
+ mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mScroll->setWidth(90);
+
+ mRedLabel = new gcn::Label(_("Red: "));
+
+ mRedText = new TextField();
+ mRedText->setWidth(40);
+ mRedText->setRange(0, 255);
+ mRedText->setNumeric(true);
+ mRedText->addListener(this);
+
+ mRedSlider = new Slider(0, 255);
+ mRedSlider->setWidth(90);
+ mRedSlider->setValue(mRedText->getValue());
+ mRedSlider->setActionEventId("slider_red");
+ mRedSlider->addActionListener(this);
+
+ mGreenLabel = new gcn::Label(_("Green: "));
+
+ mGreenText = new TextField();
+ mGreenText->setWidth(40);
+ mGreenText->setRange(0, 255);
+ mGreenText->setNumeric(true);
+ mGreenText->addListener(this);
+
+ mGreenSlider = new Slider(0, 255);
+ mGreenSlider->setWidth(90);
+ mGreenSlider->setValue(mGreenText->getValue());
+ mGreenSlider->setActionEventId("slider_green");
+ mGreenSlider->addActionListener(this);
+
+ mBlueLabel = new gcn::Label(_("Blue: "));
+
+ mBlueText = new TextField();
+ mBlueText->setWidth(40);
+ mBlueText->setRange(0, 255);
+ mBlueText->setNumeric(true);
+ mBlueText->addListener(this);
+
+ mBlueSlider = new Slider(0, 255);
+ mBlueSlider->setWidth(90);
+ mBlueSlider->setValue(mBlueText->getValue());
+ mBlueSlider->setActionEventId("slider_blue");
+ mBlueSlider->addActionListener(this);
+
+ setOpaque(false);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mScroll, 1, 3).setPadding(2);
+ place(1, 0, mRedLabel, 2);
+ place(3, 0, mRedSlider);
+ place(4, 0, mRedText).setPadding(1);
+ place(1, 1, mGreenLabel, 2);
+ place(3, 1, mGreenSlider);
+ place(4, 1, mGreenText).setPadding(1);
+ place(1, 2, mBlueLabel, 2);
+ place(3, 2, mBlueSlider);
+ place(4, 2, mBlueText).setPadding(1);
+
+ setDimension(gcn::Rectangle(0, 0, 290, 150));
+}
+
+Setup_Colours::~Setup_Colours()
+{
+ delete mRedLabel;
+ delete mRedSlider;
+ delete mRedText;
+
+ delete mGreenLabel;
+ delete mGreenSlider;
+ delete mGreenText;
+
+ delete mBlueLabel;
+ delete mBlueSlider;
+ delete mBlueText;
+
+ delete mScroll;
+}
+
+void Setup_Colours::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == "colour_box")
+ {
+ mSelected = mColourBox->getSelected();
+ int col = textColour->getColourAt(mSelected);
+ setEntry(mRedSlider, mRedText, col >> 16);
+ setEntry(mGreenSlider, mGreenText, (col >> 8) & 0xff);
+ setEntry(mBlueSlider, mBlueText, col & 0xff);
+ return;
+ }
+
+ if (event.getId() == "slider_red")
+ {
+ char buffer[30];
+ std::sprintf(buffer, "%d", static_cast<int>(mRedSlider->getValue()));
+ mRedText->setText(buffer);
+ updateColour();
+ return;
+ }
+
+ if (event.getId() == "slider_green")
+ {
+ char buffer[30];
+ std::sprintf(buffer, "%d", static_cast<int>(mGreenSlider->getValue()));
+ mGreenText->setText(buffer);
+ updateColour();
+ return;
+ }
+
+ if (event.getId() == "slider_blue")
+ {
+ char buffer[30];
+ std::sprintf(buffer, "%d", static_cast<int>(mBlueSlider->getValue()));
+ mBlueText->setText(buffer);
+ updateColour();
+ return;
+ }
+}
+
+void Setup_Colours::setEntry(Slider *s, TextField *t, int value)
+{
+ s->setValue(value);
+ char buffer[100];
+ sprintf(buffer, "%d", value);
+ t->setText(buffer);
+}
+
+void Setup_Colours::apply()
+{
+ textColour->commit();
+}
+
+void Setup_Colours::cancel()
+{
+ textColour->rollback();
+ int col = textColour->getColourAt(mSelected);
+ setEntry(mRedSlider, mRedText, col >> 16);
+ setEntry(mGreenSlider, mGreenText, (col >> 8) & 0xff);
+ setEntry(mBlueSlider, mBlueText, col & 0xff);
+}
+
+void Setup_Colours::listen(const TextField *tf)
+{
+ if (tf == mRedText)
+ {
+ mRedSlider->setValue(tf->getValue());
+ updateColour();
+ return;
+ }
+ if (tf == mGreenText)
+ {
+ mGreenSlider->setValue(tf->getValue());
+ updateColour();
+ return;
+ }
+ if (tf == mBlueText)
+ {
+ mBlueSlider->setValue(tf->getValue());
+ updateColour();
+ return;
+ }
+}
+
+void Setup_Colours::updateColour()
+{
+ if (mSelected == -1)
+ {
+ return;
+ }
+ int rgb = static_cast<int>(mRedSlider->getValue()) << 16 |
+ static_cast<int>(mGreenSlider->getValue()) << 8 |
+ static_cast<int>(mBlueSlider->getValue());
+ textColour->setColourAt(mSelected, rgb);
+}
diff --git a/src/gui/setup_colours.h b/src/gui/setup_colours.h
new file mode 100644
index 00000000..628efb43
--- /dev/null
+++ b/src/gui/setup_colours.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Douglas Boffey *
+ * *
+ * DougABoffey@netscape.net *
+ * 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 *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed with The Mana Experiment *
+ * 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 _SETUP_COLOURS_H
+#define _SETUP_COLOURS_H
+
+#include <string>
+#include <vector>
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/widgets/label.hpp>
+#include <guichan/widgets/listbox.hpp>
+
+#include "scrollarea.h"
+#include "setuptab.h"
+#include "slider.h"
+#include "textfield.h"
+
+#include "../guichanfwd.h"
+
+class Setup_Colours : public SetupTab, public gcn::ActionListener,
+ public TextFieldListener
+{
+ public:
+ Setup_Colours();
+ ~Setup_Colours();
+ void apply();
+ void cancel();
+ void action(const gcn::ActionEvent &event);
+
+ void listen(const TextField *tf);
+ private:
+ gcn::ListBox *mColourBox;
+ ScrollArea *mScroll;
+ int mSelected;
+
+ gcn::Label *mRedLabel;
+ Slider *mRedSlider;
+ TextField *mRedText;
+ int mRedValue;
+
+ gcn::Label *mGreenLabel;
+ Slider *mGreenSlider;
+ TextField *mGreenText;
+ int mGreenValue;
+
+ gcn::Label *mBlueLabel;
+ Slider *mBlueSlider;
+ TextField *mBlueText;
+ int mBlueValue;
+
+ void setEntry(Slider *s, TextField *t, int value);
+ void updateColour();
+};
+#endif
diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp
index f8fc194f..2c726b87 100644
--- a/src/gui/setup_joystick.cpp
+++ b/src/gui/setup_joystick.cpp
@@ -19,12 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_joystick.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
#include "checkbox.h"
+#include "setup_joystick.h"
#include "widgets/layouthelper.h"
@@ -62,7 +61,8 @@ Setup_Joystick::Setup_Joystick():
void Setup_Joystick::action(const gcn::ActionEvent &event)
{
- if (!joystick) {
+ if (!joystick)
+ {
return;
}
@@ -72,12 +72,15 @@ void Setup_Joystick::action(const gcn::ActionEvent &event)
}
else
{
- if (joystick->isCalibrating()) {
+ if (joystick->isCalibrating())
+ {
mCalibrateButton->setCaption(_("Calibrate"));
mCalibrateLabel->setCaption
(_("Press the button to start calibration"));
joystick->finishCalibration();
- } else {
+ }
+ else
+ {
mCalibrateButton->setCaption(_("Stop"));
mCalibrateLabel->setCaption(_("Rotate the stick"));
joystick->startCalibration();
diff --git a/src/gui/setup_joystick.h b/src/gui/setup_joystick.h
index dd8c331f..2dc56439 100644
--- a/src/gui/setup_joystick.h
+++ b/src/gui/setup_joystick.h
@@ -22,10 +22,10 @@
#ifndef GUI_SETUP_JOYSTICK_H
#define GUI_SETUP_JOYSTICK_H
-#include "setuptab.h"
-
#include <guichan/actionlistener.hpp>
+#include "setuptab.h"
+
#include "../guichanfwd.h"
class Setup_Joystick : public SetupTab, public gcn::ActionListener
diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp
index cf44731c..c6b6869a 100644
--- a/src/gui/setup_keyboard.cpp
+++ b/src/gui/setup_keyboard.cpp
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_keyboard.h"
+#include <SDL_keyboard.h>
#include <guichan/widgets/label.hpp>
#include <guichan/listmodel.hpp>
@@ -28,6 +28,9 @@
#include "listbox.h"
#include "ok_dialog.h"
#include "scrollarea.h"
+#include "setup_keyboard.h"
+
+#include "widgets/layouthelper.h"
#include "widgets/layouthelper.h"
@@ -37,8 +40,6 @@
#include "../utils/gettext.h"
#include "../utils/tostring.h"
-#include <SDL_keyboard.h>
-
/**
* The list model for key function list.
*
diff --git a/src/gui/setup_keyboard.h b/src/gui/setup_keyboard.h
index f04be792..d4966053 100644
--- a/src/gui/setup_keyboard.h
+++ b/src/gui/setup_keyboard.h
@@ -22,14 +22,14 @@
#ifndef GUI_SETUP_KEYBOARD_H
#define GUI_SETUP_KEYBOARD_H
-#include "setuptab.h"
-#include "button.h"
-#include "../guichanfwd.h"
+#include <string>
#include <guichan/actionlistener.hpp>
+#include "button.h"
+#include "setuptab.h"
-#include <string>
+#include "../guichanfwd.h"
class Setup_Keyboard : public SetupTab, public gcn::ActionListener
{
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
index 1d8649eb..9a7fb441 100644
--- a/src/gui/setup_players.cpp
+++ b/src/gui/setup_players.cpp
@@ -19,11 +19,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_players.h"
+#include <vector>
+
+#include <guichan/widgets/dropdown.hpp>
+#include <guichan/widgets/label.hpp>
#include "button.h"
#include "checkbox.h"
#include "ok_dialog.h"
+#include "setup_players.h"
#include "widgets/layouthelper.h"
@@ -34,11 +38,6 @@
#include "../utils/gettext.h"
-#include <guichan/widgets/dropdown.hpp>
-#include <guichan/widgets/label.hpp>
-
-#include <vector>
-
#define COLUMNS_NR 2 // name plus listbox
#define NAME_COLUMN 0
#define RELATION_CHOICE_COLUMN 1
@@ -198,7 +197,7 @@ public:
virtual std::string getElementAt(int i)
{
if (i >= getNumberOfElements()) {
- return "???";
+ return _("???");
}
return (*player_relations.getPlayerIgnoreStrategies())[i]->mDescription;
}
diff --git a/src/gui/setup_players.h b/src/gui/setup_players.h
index d380d9f6..22c8a9b6 100644
--- a/src/gui/setup_players.h
+++ b/src/gui/setup_players.h
@@ -22,15 +22,14 @@
#ifndef GUI_SETUP_PLAYERS_H
#define GUI_SETUP_PLAYERS_H
-#include "setuptab.h"
+#include <guichan/actionlistener.hpp>
-#include "scrollarea.h"
#include "button.h"
+#include "scrollarea.h"
+#include "setuptab.h"
#include "table.h"
-#include <guichan/actionlistener.hpp>
#include "../guichanfwd.h"
-
#include "../player_relations.h"
class PlayerTableModel;
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 53041a9c..2381ab41 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -19,11 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "setup_video.h"
-
+#include <SDL.h>
#include <string>
#include <vector>
-#include <SDL.h>
#include <guichan/key.hpp>
#include <guichan/listmodel.hpp>
@@ -34,6 +32,7 @@
#include "listbox.h"
#include "ok_dialog.h"
#include "scrollarea.h"
+#include "setup_video.h"
#include "slider.h"
#include "textfield.h"
@@ -41,6 +40,7 @@
#include "../configuration.h"
#include "../graphics.h"
+#include "../localplayer.h"
#include "../log.h"
#include "../main.h"
#include "../particle.h"
@@ -89,9 +89,9 @@ ModeListModel::ModeListModel()
/* Check which modes are available */
if (modes == (SDL_Rect **)0) {
- logger->log("No modes available");
+ logger->log(_("No modes available"));
} else if (modes == (SDL_Rect **)-1) {
- logger->log("All resolutions available");
+ logger->log(_("All resolutions available"));
} else {
//logger->log("Available Modes");
for (int i = 0; modes[i]; ++i) {
@@ -107,6 +107,9 @@ Setup_Video::Setup_Video():
mFullScreenEnabled(config.getValue("screen", 0)),
mOpenGLEnabled(config.getValue("opengl", 0)),
mCustomCursorEnabled(config.getValue("customcursor", 1)),
+ mParticleEffectsEnabled(config.getValue("particleeffects", 1)),
+ mSpeechBubbleEnabled(config.getValue("speechbubble", 1)),
+ mNameEnabled(config.getValue("showownname", 0)),
mOpacity(config.getValue("guialpha", 0.8)),
mFps((int) config.getValue("fpslimit", 0)),
mModeListModel(new ModeListModel),
@@ -114,6 +117,9 @@ Setup_Video::Setup_Video():
mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)),
mOpenGLCheckBox(new CheckBox(_("OpenGL"), mOpenGLEnabled)),
mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)),
+ mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)),
+ mSpeechBubbleCheckBox(new CheckBox(_("Speech bubbles"), mSpeechBubbleEnabled)),
+ mNameCheckBox(new CheckBox(_("Show name"), mNameEnabled)),
mAlphaSlider(new Slider(0.2, 1.0)),
mFpsCheckBox(new CheckBox(_("FPS Limit:"))),
mFpsSlider(new Slider(10, 200)),
@@ -137,13 +143,12 @@ Setup_Video::Setup_Video():
scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
gcn::Label *alphaLabel = new gcn::Label(_("Gui opacity"));
-
gcn::Label *scrollRadiusLabel = new gcn::Label(_("Scroll radius"));
gcn::Label *scrollLazinessLabel = new gcn::Label(_("Scroll laziness"));
gcn::Label *overlayDetailLabel = new gcn::Label(_("Ambient FX"));
gcn::Label *particleDetailLabel = new gcn::Label(_("Particle Detail"));
- mModeList->setEnabled(false);
+ mModeList->setEnabled(true);
#ifndef USE_OPENGL
mOpenGLCheckBox->setEnabled(false);
#endif
@@ -159,7 +164,11 @@ Setup_Video::Setup_Video():
mFpsSlider->setEnabled(mFps > 0);
mFpsCheckBox->setSelected(mFps > 0);
+ mModeList->setActionEventId("videomode");
mCustomCursorCheckBox->setActionEventId("customcursor");
+ mParticleEffectsCheckBox->setActionEventId("particleeffects");
+ mSpeechBubbleCheckBox->setActionEventId("speechbubble");
+ mNameCheckBox->setActionEventId("showownname");
mAlphaSlider->setActionEventId("guialpha");
mFpsCheckBox->setActionEventId("fpslimitcheckbox");
mFpsSlider->setActionEventId("fpslimitslider");
@@ -172,7 +181,11 @@ Setup_Video::Setup_Video():
mParticleDetailSlider->setActionEventId("particledetailslider");
mParticleDetailField->setActionEventId("particledetailfield");
+ mModeList->addActionListener(this);
mCustomCursorCheckBox->addActionListener(this);
+ mParticleEffectsCheckBox->addActionListener(this);
+ mSpeechBubbleCheckBox->addActionListener(this);
+ mNameCheckBox->addActionListener(this);
mAlphaSlider->addActionListener(this);
mFpsCheckBox->addActionListener(this);
mFpsSlider->addActionListener(this);
@@ -227,30 +240,33 @@ Setup_Video::Setup_Video():
LayoutHelper h(this);
ContainerPlacer place = h.getPlacer(0, 0);
- place(0, 0, scrollArea, 1, 4).setPadding(2);
+ place(0, 0, scrollArea, 1, 6).setPadding(2);
place(1, 0, mFsCheckBox, 3);
place(1, 1, mOpenGLCheckBox, 3);
place(1, 2, mCustomCursorCheckBox, 3);
-
- place(0, 4, mAlphaSlider);
- place(0, 5, mFpsSlider);
- place(0, 6, mScrollRadiusSlider);
- place(0, 7, mScrollLazinessSlider);
- place(0, 8, mOverlayDetailSlider);
- place(0, 9, mParticleDetailSlider);
-
- place(1, 4, alphaLabel, 2);
- place(1, 5, mFpsCheckBox).setPadding(3);
- place(1, 6, scrollRadiusLabel);
- place(1, 7, scrollLazinessLabel);
- place(1, 8, overlayDetailLabel);
- place(1, 9, particleDetailLabel);
-
- place(2, 5, mFpsField).setPadding(1);
- place(2, 6, mScrollRadiusField).setPadding(1);
- place(2, 7, mScrollLazinessField).setPadding(1);
- place(2, 8, mOverlayDetailField, 2).setPadding(2);
- place(2, 9, mParticleDetailField, 2).setPadding(2);
+ place(1, 3, mSpeechBubbleCheckBox, 3);
+ place(1, 4, mNameCheckBox, 3);
+ place(1, 5, mParticleEffectsCheckBox, 3);
+
+ place(0, 7, mAlphaSlider);
+ place(0, 8, mFpsSlider);
+ place(0, 9, mScrollRadiusSlider);
+ place(0, 10, mScrollLazinessSlider);
+ place(0, 11, mOverlayDetailSlider);
+ place(0, 12, mParticleDetailSlider);
+
+ place(1, 7, alphaLabel, 2);
+ place(1, 8, mFpsCheckBox).setPadding(3);
+ place(1, 9, scrollRadiusLabel);
+ place(1, 10, scrollLazinessLabel);
+ place(1, 11, overlayDetailLabel);
+ place(1, 12, particleDetailLabel);
+
+ place(2, 8, mFpsField).setPadding(1);
+ place(2, 9, mScrollRadiusField).setPadding(1);
+ place(2, 10, mScrollLazinessField).setPadding(1);
+ place(2, 11, mOverlayDetailField, 2).setPadding(2);
+ place(2, 12, mParticleDetailField, 2).setPadding(2);
setDimension(gcn::Rectangle(0, 0, 295, 250));
}
@@ -284,9 +300,9 @@ void Setup_Video::apply()
if (!graphics->setFullscreen(fullscreen))
{
std::stringstream error;
- error << "Failed to switch to " <<
- (fullscreen ? "windowed" : "fullscreen") <<
- "mode and restoration of old mode also failed!" <<
+ error << _("Failed to switch to ") <<
+ (fullscreen ? _("windowed") : _("fullscreen")) <<
+ _("mode and restoration of old mode also failed!") <<
std::endl;
logger->error(error.str());
}
@@ -316,8 +332,11 @@ void Setup_Video::apply()
// We sync old and new values at apply time
mFullScreenEnabled = config.getValue("screen", 0);
mCustomCursorEnabled = config.getValue("customcursor", 1);
+ mParticleEffectsEnabled = config.getValue("particleeffects", 1);
+ mSpeechBubbleEnabled = config.getValue("speechbubble", 1);
+ mNameEnabled = config.getValue("showownname", 0);
mOpacity = config.getValue("guialpha", 0.8);
- mOverlayDetail = (int)config.getValue("OverlayDetail", 2);
+ mOverlayDetail = (int) config.getValue("OverlayDetail", 2);
mOpenGLEnabled = config.getValue("opengl", 0);
}
@@ -346,6 +365,9 @@ void Setup_Video::cancel()
mFsCheckBox->setSelected(mFullScreenEnabled);
mOpenGLCheckBox->setSelected(mOpenGLEnabled);
mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
+ mParticleEffectsCheckBox->setSelected(mParticleEffectsEnabled);
+ mSpeechBubbleCheckBox->setSelected(mSpeechBubbleEnabled);
+ mNameCheckBox->setSelected(mNameEnabled);
mAlphaSlider->setValue(mOpacity);
mOverlayDetailSlider->setValue(mOverlayDetail);
mParticleDetailSlider->setValue(mParticleDetail);
@@ -357,13 +379,46 @@ void Setup_Video::cancel()
config.setValue("screen", mFullScreenEnabled ? 1 : 0);
config.setValue("customcursor", mCustomCursorEnabled ? 1 : 0);
+ config.setValue("particleeffects", mParticleEffectsEnabled ? 1 : 0);
+ config.setValue("speechbubble", mSpeechBubbleEnabled ? 1 : 0);
+ config.setValue("showownname", mNameEnabled ? 1 : 0);
config.setValue("guialpha", mOpacity);
config.setValue("opengl", mOpenGLEnabled ? 1 : 0);
}
void Setup_Video::action(const gcn::ActionEvent &event)
{
- if (event.getId() == "guialpha")
+ if (event.getId() == "videomode")
+ {
+ const std::string mode = mModeListModel->getElementAt(mModeList->getSelected());
+ const int width = atoi(mode.substr(0, mode.find("x")).c_str());
+ const int height = atoi(mode.substr(mode.find("x") + 1).c_str());
+ const int bpp = 0;
+ const bool fullscreen = ((int) config.getValue("screen", 0) == 1);
+ const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
+
+ // Try to set the desired video mode
+ if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
+ {
+ std::cerr << _("Couldn't set ")
+ << width << "x" << height << "x" << bpp << _(" video mode: ")
+ << SDL_GetError() << std::endl;
+ exit(1);
+ }
+
+ // Initialize for drawing
+ graphics->_endDraw();
+ graphics->_beginDraw();
+ graphics->updateScreen();
+
+ // TODO: Find out why the drawing area doesn't resize without a restart.
+ new OkDialog(_("Screen resolution changed"),
+ _("Restart your client for the change to take effect."));
+
+ config.setValue("screenwidth", width);
+ config.setValue("screenheight", height);
+ }
+ else if (event.getId() == "guialpha")
{
config.setValue("guialpha", mAlphaSlider->getValue());
}
@@ -372,6 +427,27 @@ void Setup_Video::action(const gcn::ActionEvent &event)
config.setValue("customcursor",
mCustomCursorCheckBox->isSelected() ? 1 : 0);
}
+ else if (event.getId() == "particleeffects")
+ {
+ config.setValue("particleeffects",
+ mParticleEffectsCheckBox->isSelected() ? 1 : 0);
+ new OkDialog(_("Particle effect settings changed"),
+ _("Restart your client or change maps for the change to take effect."));
+ }
+ else if (event.getId() == "speechbubble")
+ {
+ config.setValue("speechbubble",
+ mSpeechBubbleCheckBox->isSelected() ? 1 : 0);
+ }
+ else if (event.getId() == "showownname")
+ {
+ // Notify the local player that settings have changed for the name
+ // and requires an update
+ if (player_node)
+ player_node->mUpdateName = true;
+ config.setValue("showownname",
+ mNameCheckBox->isSelected() ? 1 : 0);
+ }
else if (event.getId() == "fpslimitslider")
{
mFps = (int) mFpsSlider->getValue();
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index b7011186..d863fb64 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -22,11 +22,11 @@
#ifndef GUI_SETUP_VIDEO_H
#define GUI_SETUP_VIDEO_H
-#include "setuptab.h"
-
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+#include "setuptab.h"
+
#include "../guichanfwd.h"
class Setup_Video : public SetupTab, public gcn::ActionListener,
@@ -53,6 +53,9 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
bool mFullScreenEnabled;
bool mOpenGLEnabled;
bool mCustomCursorEnabled;
+ bool mParticleEffectsEnabled;
+ bool mSpeechBubbleEnabled;
+ bool mNameEnabled;
double mOpacity;
int mFps;
@@ -62,6 +65,9 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
gcn::CheckBox *mFsCheckBox;
gcn::CheckBox *mOpenGLCheckBox;
gcn::CheckBox *mCustomCursorCheckBox;
+ gcn::CheckBox *mParticleEffectsCheckBox;
+ gcn::CheckBox *mSpeechBubbleCheckBox;
+ gcn::CheckBox *mNameCheckBox;
gcn::Slider *mAlphaSlider;
gcn::CheckBox *mFpsCheckBox;
diff --git a/src/gui/shop.h b/src/gui/shop.h
index 4a03b2bc..22b649d0 100644
--- a/src/gui/shop.h
+++ b/src/gui/shop.h
@@ -27,10 +27,11 @@
#include <guichan/listmodel.hpp>
-#include "../resources/image.h"
-
+#include "../guichanfwd.h"
#include "../shopitem.h"
+#include "../resources/image.h"
+
class ShopItems : public gcn::ListModel
{
public:
diff --git a/src/gui/shoplistbox.cpp b/src/gui/shoplistbox.cpp
index 2517d749..765b9f08 100644
--- a/src/gui/shoplistbox.cpp
+++ b/src/gui/shoplistbox.cpp
@@ -19,14 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "shoplistbox.h"
-
+#include <guichan/basiccontainer.hpp>
#include <guichan/font.hpp>
#include <guichan/graphics.hpp>
+#include <guichan/imagefont.hpp>
#include <guichan/listmodel.hpp>
#include <guichan/mouseinput.hpp>
-#include <guichan/imagefont.hpp>
-#include <guichan/basiccontainer.hpp>
+
+#include "shoplistbox.h"
#include "../graphics.h"
@@ -72,7 +72,7 @@ void ShopListBox::draw(gcn::Graphics *gcnGraphics)
if (i == mSelected)
{
- backgroundColor = gcn::Color(110, 160, 255);
+ backgroundColor = gcn::Color(235, 200, 115);
}
else if (mShopItems &&
mPlayerMoney < mShopItems->at(i)->getPrice() && mPriceCheck)
diff --git a/src/gui/shoplistbox.h b/src/gui/shoplistbox.h
index bad848d6..733af4eb 100644
--- a/src/gui/shoplistbox.h
+++ b/src/gui/shoplistbox.h
@@ -25,6 +25,8 @@
#include "listbox.h"
#include "shop.h"
+#include "../guichanfwd.h"
+
/**
* 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
diff --git a/src/gui/shortcutcontainer.cpp b/src/gui/shortcutcontainer.cpp
new file mode 100644
index 00000000..d03bc809
--- /dev/null
+++ b/src/gui/shortcutcontainer.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "shortcutcontainer.h"
+
+#include "../graphics.h"
+#include "../inventory.h"
+#include "../item.h"
+#include "../itemshortcut.h"
+#include "../keyboardconfig.h"
+#include "../localplayer.h"
+
+#include "../resources/image.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/tostring.h"
+
+ShortcutContainer::ShortcutContainer():
+ mGridWidth(1),
+ mGridHeight(1)
+{
+}
+
+
+void ShortcutContainer::widgetResized(const gcn::Event &event)
+{
+ 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;
+ }
+}
+
+int ShortcutContainer::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/shortcutcontainer.h b/src/gui/shortcutcontainer.h
new file mode 100644
index 00000000..66aca6c3
--- /dev/null
+++ b/src/gui/shortcutcontainer.h
@@ -0,0 +1,107 @@
+/*
+ * 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 SHORTCUTCONTAINER_H__
+#define SHORTCUTCONTAINER_H__
+
+#include <guichan/mouselistener.hpp>
+#include <guichan/widget.hpp>
+#include <guichan/widgetlistener.hpp>
+
+#include "../guichanfwd.h"
+
+class Image;
+
+/**
+ * An item shortcut container. Used to quickly use items.
+ *
+ * \ingroup GUI
+ */
+class ShortcutContainer : public gcn::Widget,
+ public gcn::WidgetListener,
+ public gcn::MouseListener
+{
+ public:
+ /**
+ * Constructor. Initializes the graphic.
+ */
+ ShortcutContainer();
+
+ /**
+ * Destructor.
+ */
+ ~ShortcutContainer(){}
+
+ /**
+ * Draws the items.
+ */
+ 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;
+
+ virtual int getMaxItems()
+ { return mMaxItems; }
+
+ virtual int getBoxWidth()
+ { return mBoxWidth; }
+
+ virtual int getBoxHeight()
+ { 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;
+
+ int mMaxItems;
+ int mBoxWidth;
+ int mBoxHeight;
+ int mCursorPosX, mCursorPosY;
+ int mGridWidth, mGridHeight;
+};
+
+#endif
diff --git a/src/gui/itemshortcutwindow.cpp b/src/gui/shortcutwindow.cpp
index 6fe1a10b..3a7cf0e0 100644
--- a/src/gui/itemshortcutwindow.cpp
+++ b/src/gui/shortcutwindow.cpp
@@ -19,23 +19,23 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "itemshortcutwindow.h"
-
-#include "itemshortcutcontainer.h"
+#include "shortcutcontainer.h"
+#include "shortcutwindow.h"
#include "scrollarea.h"
+#include "../configuration.h"
+
static const int SCROLL_PADDING = 0;
-ItemShortcutWindow::ItemShortcutWindow()
+ShortcutWindow::ShortcutWindow(const char *title, ShortcutContainer *content)
{
- setWindowName("ItemShortcut");
+ setWindowName(title);
// 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;
+ mItems = content;
const int border = SCROLL_PADDING * 2 + getPadding() * 2;
setMinWidth(mItems->getBoxWidth() + border);
@@ -43,6 +43,14 @@ ItemShortcutWindow::ItemShortcutWindow()
setMaxWidth(mItems->getBoxWidth() * mItems->getMaxItems() + border);
setMaxHeight(mItems->getBoxHeight() * mItems->getMaxItems() + border);
+ const int width = (int) config.getValue("screenwidth", 800);
+ const int height = (int) config.getValue("screenheight", 600);
+
+ setDefaultSize(width - mItems->getBoxWidth() - border,
+ height - (mItems->getBoxHeight() * mItems->getMaxItems()) -
+ border, mItems->getBoxWidth() + border,
+ (mItems->getBoxHeight() * mItems->getMaxItems()) + border);
+
mScrollArea = new ScrollArea(mItems);
mScrollArea->setPosition(SCROLL_PADDING, SCROLL_PADDING);
mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
@@ -53,13 +61,13 @@ ItemShortcutWindow::ItemShortcutWindow()
loadWindowState();
}
-ItemShortcutWindow::~ItemShortcutWindow()
+ShortcutWindow::~ShortcutWindow()
{
delete mItems;
delete mScrollArea;
}
-void ItemShortcutWindow::widgetResized(const gcn::Event &event)
+void ShortcutWindow::widgetResized(const gcn::Event &event)
{
Window::widgetResized(event);
diff --git a/src/gui/itemshortcutwindow.h b/src/gui/shortcutwindow.h
index baa34b13..0168669e 100644
--- a/src/gui/itemshortcutwindow.h
+++ b/src/gui/shortcutwindow.h
@@ -19,12 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef ITEMSHORTCUTWINDOW_H
-#define ITEMSHORTCUTWINDOW_H
+#ifndef SHORTCUTWINDOW_H
+#define SHORTCUTWINDOW_H
#include "window.h"
-class ItemShortcutContainer;
+#include "../guichanfwd.h"
+
+class ShortcutContainer;
class ScrollArea;
/**
@@ -32,18 +34,18 @@ class ScrollArea;
*
* \ingroup Interface
*/
-class ItemShortcutWindow : public Window
+class ShortcutWindow : public Window
{
public:
/**
* Constructor.
*/
- ItemShortcutWindow();
+ ShortcutWindow(const char *title, ShortcutContainer *content);
/**
* Destructor.
*/
- ~ItemShortcutWindow();
+ ~ShortcutWindow();
/**
* Called whenever the widget changes size.
@@ -51,11 +53,13 @@ class ItemShortcutWindow : public Window
void widgetResized(const gcn::Event &event);
private:
- ItemShortcutContainer *mItems;
+ ShortcutWindow();
+ ShortcutContainer *mItems;
ScrollArea *mScrollArea;
};
-extern ItemShortcutWindow *itemShortcutWindow;
+extern ShortcutWindow *itemShortcutWindow;
+extern ShortcutWindow *emoteShortcutWindow;
#endif
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index 4afd913d..304719b6 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -21,13 +21,13 @@
#include <guichan/widgets/label.hpp>
-#include "skill.h"
-
#include "button.h"
#include "listbox.h"
-#include "scrollarea.h"
+#include "skill.h"
#include "windowcontainer.h"
+#include "widgets/layout.h"
+
#include "../localplayer.h"
#include "../log.h"
@@ -36,7 +36,7 @@
#include "../utils/strprintf.h"
#include "../utils/xml.h"
-static const char *SKILLS_FILE = "skills.xml";
+static const char *SKILLS_FILE = _("skills.xml");
struct SkillInfo {
std::string name;
@@ -51,21 +51,24 @@ class SkillGuiTableModel : public StaticTableModel
{
public:
SkillGuiTableModel(SkillDialog *dialog) :
- StaticTableModel(0, 3)
+ StaticTableModel(0, 3, 0xbdb5aa)
{
mEntriesNr = 0;
mDialog = dialog;
update();
}
- virtual int getRows() { return mEntriesNr; }
+ virtual int getRows(void)
+ {
+ return mEntriesNr;
+ }
virtual int getColumnWidth(int index)
{
- switch (index) {
- case 0: return 160;
- default: return 35;
- }
+ if (index == 0)
+ return 160;
+
+ return 35;
}
virtual int getRowHeight()
@@ -83,7 +86,8 @@ public:
mEntriesNr = mDialog->getSkills().size();
resize();
- for (int i = 0; i < mEntriesNr; i++) {
+ for (int i = 0; i < mEntriesNr; i++)
+ {
SKILL *skill = mDialog->getSkills()[i];
SkillInfo const *info;
char tmp[128];
@@ -123,31 +127,33 @@ SkillDialog::SkillDialog():
mTable.setModel(mTableModel);
mTable.setLinewiseSelection(true);
- setWindowName("Skills");
+ setWindowName(_("Skills"));
setCloseButton(true);
setDefaultSize(windowContainer->getWidth() - 260, 25, 255, 260);
+ setMinHeight(50 + mTableModel->getHeight());
+ setMinWidth(200);
+
// mSkillListBox = new ListBox(this);
ScrollArea *skillScrollArea = new ScrollArea(&mTable);
mPointsLabel = new gcn::Label(strprintf(_("Skill points: %d"), 0));
- mIncButton = new Button(_("Up"), "inc", this);
- mUseButton = new Button(_("Use"), "use", this);
+ mIncButton = new Button(_("Up"), _("inc"), this);
+ mUseButton = new Button(_("Use"), _("use"), this);
mUseButton->setEnabled(false);
// mSkillListBox->setActionEventId("skill");
mTable.setActionEventId("skill");
skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180));
- mPointsLabel->setDimension(gcn::Rectangle(8, 190, 200, 16));
- mIncButton->setPosition(skillScrollArea->getX(), 210);
- mUseButton->setPosition(mIncButton->getX() + mIncButton->getWidth() + 5,
- 210);
+ skillScrollArea->setOpaque(false);
+
+ place(0, 0, skillScrollArea, 5).setPadding(3);
+ place(0, 1, mPointsLabel, 2);
+ place(3, 2, mIncButton);
+ place(4, 2, mUseButton);
- add(skillScrollArea);
- add(mPointsLabel);
- add(mIncButton);
- add(mUseButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
// mSkillListBox->addActionListener(this);
mTable.addActionListener(this);
@@ -167,9 +173,7 @@ void SkillDialog::action(const gcn::ActionEvent &event)
// Increment skill
int selectedSkill = mTable.getSelectedRow();//mSkillListBox->getSelected();
if (selectedSkill >= 0)
- {
player_node->raiseSkill(mSkillList[selectedSkill]->id);
- }
}
else if (event.getId() == "skill")
{
@@ -178,9 +182,7 @@ void SkillDialog::action(const gcn::ActionEvent &event)
player_node->mSkillPoint > 0);
}
else if (event.getId() == "close")
- {
setVisible(false);
- }
}
void SkillDialog::update()
@@ -190,7 +192,8 @@ void SkillDialog::update()
int selectedSkill = mTable.getSelectedRow();
- if (selectedSkill >= 0) {
+ if (selectedSkill >= 0)
+ {
int skillId = mSkillList[selectedSkill]->id;
bool modifiable;
@@ -201,10 +204,12 @@ void SkillDialog::update()
mIncButton->setEnabled(modifiable
&& player_node->mSkillPoint > 0);
- } else
+ }
+ else
mIncButton->setEnabled(false);
mTableModel->update();
+ setMinHeight(50 + mTableModel->getHeight());
}
int SkillDialog::getNumberOfElements()
@@ -214,10 +219,10 @@ int SkillDialog::getNumberOfElements()
bool SkillDialog::hasSkill(int id)
{
- for (unsigned int i = 0; i < mSkillList.size(); i++) {
- if (mSkillList[i]->id == id) {
+ for (unsigned int i = 0; i < mSkillList.size(); i++)
+ {
+ if (mSkillList[i]->id == id)
return true;
- }
}
return false;
}
@@ -233,8 +238,10 @@ void SkillDialog::addSkill(int id, int lvl, int mp)
void SkillDialog::setSkill(int id, int lvl, int mp)
{
- for (unsigned int i = 0; i < mSkillList.size(); i++) {
- if (mSkillList[i]->id == id) {
+ for (unsigned int i = 0; i < mSkillList.size(); i++)
+ {
+ if (mSkillList[i]->id == id)
+ {
mSkillList[i]->lv = lvl;
mSkillList[i]->sp = mp;
}
@@ -256,7 +263,7 @@ static void initSkillinfo()
if (!root || !xmlStrEqual(root->name, BAD_CAST "skills"))
{
- logger->log("Error loading skills file: %s", SKILLS_FILE);
+ logger->log(_("Error loading skills file: %s"), SKILLS_FILE);
skill_db.resize(2, emptySkillInfo);
skill_db[1].name = "Basic";
skill_db[1].modifiable = true;
diff --git a/src/gui/skill.h b/src/gui/skill.h
index 893a61e7..582892f0 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -24,9 +24,11 @@
#include <vector>
-#include <guichan/listmodel.hpp>
#include <guichan/actionlistener.hpp>
+#include <guichan/listmodel.hpp>
+#include "scrollarea.h"
+#include "table.h"
#include "window.h"
#include "table.h"
@@ -72,6 +74,7 @@ class SkillDialog : public Window, public gcn::ActionListener
private:
GuiTable mTable;//gcn::ListBox *mSkillListBox;
+ ScrollArea *skillScrollArea;
SkillGuiTableModel *mTableModel;
gcn::Label *mPointsLabel;
gcn::Button *mIncButton;
diff --git a/src/gui/slider.h b/src/gui/slider.h
index 1fe668c5..c14c5be9 100644
--- a/src/gui/slider.h
+++ b/src/gui/slider.h
@@ -24,8 +24,9 @@
#include <guichan/widgets/slider.hpp>
-class Image;
+#include "../guichanfwd.h"
+class Image;
/**
* Slider widget. Same as the Guichan slider but with custom look.
diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp
new file mode 100644
index 00000000..a6bb5563
--- /dev/null
+++ b/src/gui/speechbubble.cpp
@@ -0,0 +1,111 @@
+/*
+ * The Legend of Mazzeroth
+ * Copyright (C) 2008, The Legend of Mazzeroth Development Team
+ *
+ * This file is part of The Legend of Mazzeroth based on original code
+ * from The Mana World.
+ *
+ * The Legend of Mazzeroth 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 Legend of Mazzeroth 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 Legend of Mazzeroth; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <guichan/font.hpp>
+
+#include <guichan/widgets/label.hpp>
+
+#include "gui.h"
+#include "speechbubble.h"
+
+#include "../resources/image.h"
+#include "../resources/resourcemanager.h"
+
+#include "../utils/gettext.h"
+
+// TODO: Fix windows so that they can each load their own skins without the
+// other windows overriding another window's skin.
+SpeechBubble::SpeechBubble():
+ Window(_("Speech"), false, NULL, "graphics/gui/speechbubble.xml")
+{
+ // Height == Top Graphic (14px) + 1 Row of Text (15px) + Bottom Graphic (17px)
+ setContentSize(140, 46);
+ setShowTitle(false);
+ setTitleBarHeight(0);
+
+ mCaption = new gcn::Label("");
+ mCaption->setFont(boldFont);
+ mCaption->setPosition(5, 3);
+
+ mSpeechBox = new TextBox();
+ mSpeechBox->setEditable(false);
+ mSpeechBox->setOpaque(false);
+
+ mSpeechArea = new ScrollArea(mSpeechBox);
+
+ mSpeechArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mSpeechArea->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mSpeechArea->setDimension(gcn::Rectangle(4, boldFont->getHeight() + 3,
+ 130, 28));
+ mSpeechArea->setOpaque(false);
+
+ add(mCaption);
+ add(mSpeechArea);
+
+ setLocationRelativeTo(getParent());
+
+ // LEEOR / TODO: This causes an exception error.
+ //moveToBottom(getParent());
+
+ mSpeechBox->setTextWrapped( "" );
+}
+
+void SpeechBubble::setCaption(const std::string &name, const gcn::Color &color)
+{
+ mCaption->setCaption(name);
+ mCaption->adjustSize();
+ mCaption->setForegroundColor(color);
+}
+
+void SpeechBubble::setText(std::string mText)
+{
+ mSpeechBox->setMinWidth(140);
+ mSpeechBox->setTextWrapped(mText);
+
+ const int fontHeight = getFont()->getHeight();
+ const int numRows = mSpeechBox->getNumberOfRows() + 1;
+
+ if (numRows > 2)
+ {
+ // 15 == height of each line of text (based on font heights)
+ // 14 == speechbubble Top + Bottom graphic pixel heights
+ setContentSize(mSpeechBox->getMinWidth() + fontHeight,
+ (numRows * fontHeight) + 6);
+ mSpeechArea->setDimension(gcn::Rectangle(4, fontHeight + 3,
+ mSpeechBox->getMinWidth() + 5,
+ (numRows * fontHeight)));
+ }
+ else
+ {
+ int width = mCaption->getWidth() + 3;
+ if (width < getFont()->getWidth(mText))
+ width = getFont()->getWidth(mText);
+ setContentSize(width + fontHeight, (fontHeight * 2) + 6);
+ mSpeechArea->setDimension(gcn::Rectangle(4, fontHeight + 3,
+ width, fontHeight));
+ }
+}
+
+unsigned int SpeechBubble::getNumRows()
+{
+ return mSpeechBox->getNumberOfRows();
+}
diff --git a/src/gui/speechbubble.h b/src/gui/speechbubble.h
new file mode 100644
index 00000000..23733813
--- /dev/null
+++ b/src/gui/speechbubble.h
@@ -0,0 +1,48 @@
+/*
+ * The Legend of Mazzeroth
+ * Copyright (C) 2008, The Legend of Mazzeroth Development Team
+ *
+ * This file is part of The Legend of Mazzeroth based on original code
+ * from The Mana World.
+ *
+ * The Legend of Mazzeroth 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 Legend of Mazzeroth 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 Legend of Mazzeroth; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LOM_SPEECHBUBBLE_H__
+#define _LOM_SPEECHBUBBLE_H__
+
+#include "scrollarea.h"
+#include "textbox.h"
+#include "window.h"
+
+class SpeechBubble : public Window
+{
+ public:
+
+ SpeechBubble();
+
+ void setCaption(const std::string &name,
+ const gcn::Color &color = 0x000000);
+ void setText(std::string mText);
+ void setLocation(int x, int y);
+ unsigned int getNumRows();
+
+ private:
+ gcn::Label *mCaption;
+ TextBox *mSpeechBox;
+ ScrollArea *mSpeechArea;
+};
+
+#endif
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index b95a1eb8..bd6048f3 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -19,12 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "status.h"
-
#include <guichan/widgets/label.hpp>
#include "button.h"
#include "progressbar.h"
+#include "status.h"
#include "windowcontainer.h"
#include "../localplayer.h"
@@ -37,11 +36,10 @@ StatusWindow::StatusWindow(LocalPlayer *player):
Window(player->getName()),
mPlayer(player)
{
- setWindowName("Status");
- setResizable(true);
+ setWindowName(_("Status"));
setCloseButton(true);
setDefaultSize((windowContainer->getWidth() - 365) / 2,
- (windowContainer->getHeight() - 255) / 2, 365, 275);
+ (windowContainer->getHeight() - 255) / 2, 400, 275);
loadWindowState();
// ----------------------
@@ -52,19 +50,19 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mGpLabel = new gcn::Label(strprintf(_("Job: %d"), 0));
mJobLvlLabel = new gcn::Label(strprintf(_("Money: %d GP"), 0));
- mHpLabel = new gcn::Label("HP:");
+ mHpLabel = new gcn::Label(_("HP:"));
mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34);
mHpValueLabel = new gcn::Label;
- mXpLabel = new gcn::Label("Exp:");
+ mXpLabel = new gcn::Label(_("Exp:"));
mXpBar = new ProgressBar(1.0f, 80, 15, 143, 192, 211);
mXpValueLabel = new gcn::Label;
- mMpLabel = new gcn::Label("MP:");
+ mMpLabel = new gcn::Label(_("MP:"));
mMpBar = new ProgressBar(1.0f, 80, 15, 26, 102, 230);
mMpValueLabel = new gcn::Label;
- mJobXpLabel = new gcn::Label("Job:");
+ mJobXpLabel = new gcn::Label(_("Job:"));
mJobXpBar = new ProgressBar(1.0f, 80, 15, 220, 135, 203);
mJobValueLabel = new gcn::Label;
diff --git a/src/gui/status.h b/src/gui/status.h
index 6d360caf..14a7617e 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -33,7 +33,6 @@
class LocalPlayer;
class ProgressBar;
-
/**
* The player status dialog.
*
diff --git a/src/gui/table.cpp b/src/gui/table.cpp
index f6678737..7e855523 100644
--- a/src/gui/table.cpp
+++ b/src/gui/table.cpp
@@ -19,13 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "table.h"
+#include <cassert>
#include <guichan/graphics.hpp>
#include <guichan/actionlistener.hpp>
-#include <cassert>
-
+#include "table.h"
class GuiTableActionListener : public gcn::ActionListener
{
@@ -100,6 +99,7 @@ void GuiTable::setModel(TableModel *new_model)
mModel->removeListener(this);
}
+
mModel = new_model;
installActionListeners();
@@ -109,7 +109,6 @@ void GuiTable::setModel(TableModel *new_model)
}
}
-
void GuiTable::recomputeDimensions()
{
int rows_nr = mModel->getRows();
@@ -296,7 +295,6 @@ void GuiTable::keyPressed(gcn::KeyEvent& keyEvent)
{
}
-
// -- MouseListener notifications
void GuiTable::mousePressed(gcn::MouseEvent& mouseEvent)
{
@@ -386,7 +384,6 @@ int GuiTable::getColumnForX(int x)
return column;
}
-
void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler)
{
gcn::Widget::_setFocusHandler(focusHandler);
diff --git a/src/gui/table.h b/src/gui/table.h
index c7ede36c..9dde8900 100644
--- a/src/gui/table.h
+++ b/src/gui/table.h
@@ -31,6 +31,7 @@
#include <guichan/widget.hpp>
#include "table_model.h"
+
#include "../guichanfwd.h"
class GuiTableActionListener;
diff --git a/src/gui/table_model.cpp b/src/gui/table_model.cpp
index 7bc29b47..e69ee808 100644
--- a/src/gui/table_model.cpp
+++ b/src/gui/table_model.cpp
@@ -19,10 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "table_model.h"
+#include <cstdlib>
+#include <guichan/graphics.hpp>
#include <guichan/widget.hpp>
-#include <cstdlib>
+
+#include "table_model.h"
#include "../utils/dtor.h"
@@ -49,14 +51,16 @@ void TableModel::signalAfterUpdate()
}
-
#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) :
+StaticTableModel::StaticTableModel(int row, int column,
+ gcn::Color backgroundColor, bool opacity) :
mRows(row),
mColumns(column),
- mHeight(1)
+ mHeight(1),
+ mOpaque(opacity),
+ mBackgroundColor(backgroundColor)
{
mTableModel.resize(row * column, NULL);
mWidths.resize(column, 1);
@@ -143,3 +147,42 @@ int StaticTableModel::getColumns()
{
return mColumns;
}
+
+int StaticTableModel::getWidth(void)
+{
+ int width = 0;
+
+ for (unsigned int i = 0; i < mWidths.size(); i++)
+ {
+ width += mWidths[i];
+ }
+
+ return width;
+}
+
+int StaticTableModel::getHeight(void)
+{
+ return (mColumns * mHeight);
+}
+
+void StaticTableModel::drawBackground(gcn::Graphics *graphics)
+{
+ if (isOpaque())
+ {
+ for (unsigned int i = 0; i < mTableModel.size(); i++)
+ {
+ mTableModel[i]->setBackgroundColor(mBackgroundColor);
+ }
+ }
+}
+
+void StaticTableModel::setOpaque(bool opaque)
+{
+ mOpaque = opaque;
+}
+
+bool StaticTableModel::isOpaque() const
+{
+ return mOpaque;
+}
+
diff --git a/src/gui/table_model.h b/src/gui/table_model.h
index d245d7bd..03b69dba 100644
--- a/src/gui/table_model.h
+++ b/src/gui/table_model.h
@@ -22,12 +22,13 @@
#ifndef TABLE_MODEL_H
#define TABLE_MODEL_H
-#include "../guichanfwd.h"
+#include <set>
+#include <vector>
+#include <guichan/color.hpp>
#include <guichan/gui.hpp>
-#include <set>
-#include <vector>
+#include "../guichanfwd.h"
class TableModelListener
{
@@ -100,7 +101,8 @@ private:
class StaticTableModel : public TableModel
{
public:
- StaticTableModel(int width, int height);
+ StaticTableModel(int width, int height, gcn::Color background = 0xffffff,
+ bool opacity = true);
virtual ~StaticTableModel();
/**
@@ -130,17 +132,49 @@ public:
*/
virtual void resize();
+ /**
+ * 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);
+
+ /**
+ * Checks if the scroll area is opaque, that is if the scroll area
+ * displays its background.
+ *
+ * @return True if the scroll area is opaque, false otherwise.
+ */
+ virtual bool isOpaque() const;
+
virtual int getRows();
virtual int getColumns();
virtual int getRowHeight();
+ virtual int getWidth();
+ virtual int getHeight();
virtual int getColumnWidth(int index);
virtual gcn::Widget *getElementAt(int row, int column);
protected:
int mRows, mColumns;
int mHeight;
+ bool mOpaque;
std::vector<gcn::Widget *> mTableModel;
std::vector<int> mWidths;
+
+ /**
+ * Holds the background color of the table.
+ */
+ gcn::Color mBackgroundColor;
+
+ /**
+ * Draws the background of the table, that is
+ * the area behind the content.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ virtual void drawBackground(gcn::Graphics *graphics);
};
#endif /* !defined(TABLE_MODEL_H) */
diff --git a/src/gui/textbox.cpp b/src/gui/textbox.cpp
index 75f0b5a1..ee03c79d 100644
--- a/src/gui/textbox.cpp
+++ b/src/gui/textbox.cpp
@@ -19,13 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "textbox.h"
-
#include <sstream>
#include <guichan/basiccontainer.hpp>
#include <guichan/font.hpp>
+#include "textbox.h"
+
TextBox::TextBox():
gcn::TextBox()
{
@@ -43,6 +43,8 @@ void TextBox::setTextWrapped(const std::string &text)
std::stringstream wrappedStream;
std::string::size_type newlinePos, lastNewlinePos = 0;
+ int minWidth = 0;
+ int xpos;
do
{
@@ -57,7 +59,7 @@ void TextBox::setTextWrapped(const std::string &text)
std::string line =
text.substr(lastNewlinePos, newlinePos - lastNewlinePos);
std::string::size_type spacePos, lastSpacePos = 0;
- int xpos = 0;
+ xpos = 0;
do
{
@@ -73,7 +75,7 @@ void TextBox::setTextWrapped(const std::string &text)
int width = getFont()->getWidth(word);
- if (xpos != 0 && xpos + width < getWidth())
+ if (xpos != 0 && xpos + width + getFont()->getWidth(" ") <= mMinWidth)
{
xpos += width + getFont()->getWidth(" ");
wrappedStream << " " << word;
@@ -85,10 +87,30 @@ void TextBox::setTextWrapped(const std::string &text)
}
else
{
+ if (xpos > minWidth)
+ {
+ minWidth = xpos;
+ }
+ // The window wasn't big enough. Resize it and try again.
+ if (minWidth > mMinWidth)
+ {
+ mMinWidth = minWidth;
+ wrappedStream.clear();
+ wrappedStream.str("");
+ spacePos = 0;
+ lastNewlinePos = 0;
+ newlinePos = text.find("\n", lastNewlinePos);
+ line = text.substr(lastNewlinePos, newlinePos -
+ lastNewlinePos);
+ width = 0;
+ break;
+ }
+ else
+ {
+ wrappedStream << "\n" << word;
+ }
xpos = width;
- wrappedStream << "\n" << word;
}
-
lastSpacePos = spacePos + 1;
}
while (spacePos != line.size());
@@ -97,10 +119,15 @@ void TextBox::setTextWrapped(const std::string &text)
{
wrappedStream << "\n";
}
-
lastNewlinePos = newlinePos + 1;
}
while (newlinePos != text.size());
+ if (xpos > minWidth)
+ {
+ minWidth = xpos;
+ }
+ mMinWidth = minWidth;
+
gcn::TextBox::setText(wrappedStream.str());
}
diff --git a/src/gui/textbox.h b/src/gui/textbox.h
index a42562ea..98b60402 100644
--- a/src/gui/textbox.h
+++ b/src/gui/textbox.h
@@ -24,6 +24,8 @@
#include <guichan/widgets/textbox.hpp>
+#include "../guichanfwd.h"
+
/**
* A text box, meant to be used inside a scroll area. Same as the Guichan text
* box except this one doesn't have a background or border, instead completely
@@ -42,6 +44,19 @@ class TextBox : public gcn::TextBox {
* Sets the text after wrapping it to the current width of the widget.
*/
void setTextWrapped(const std::string &text);
+
+ /**
+ * Get the minimum text width for the text box.
+ */
+ int getMinWidth() { return mMinWidth; }
+
+ /**
+ * Set the minimum text width for the text box.
+ */
+ void setMinWidth(int width) { mMinWidth = width; }
+
+ private:
+ int mMinWidth;
};
#endif
diff --git a/src/gui/textfield.cpp b/src/gui/textfield.cpp
index f7b02cbf..3369195d 100644
--- a/src/gui/textfield.cpp
+++ b/src/gui/textfield.cpp
@@ -19,14 +19,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "textfield.h"
-
#include <algorithm>
#include <guichan/font.hpp>
#include "sdlinput.h"
+#include "textfield.h"
+#include "../configuration.h"
#include "../graphics.h"
#include "../resources/image.h"
@@ -40,7 +40,9 @@ int TextField::instances = 0;
ImageRect TextField::skin;
TextField::TextField(const std::string& text):
- gcn::TextField(text)
+ gcn::TextField(text),
+ mNumeric(false),
+ mListener(0)
{
setFrameSize(2);
@@ -62,6 +64,7 @@ TextField::TextField(const std::string& text):
gridx[x], gridy[y],
gridx[x + 1] - gridx[x] + 1,
gridy[y + 1] - gridy[y] + 1);
+ skin.grid[a]->setAlpha(config.getValue("guialpha", 0.8));
a++;
}
}
@@ -105,6 +108,42 @@ void TextField::drawFrame(gcn::Graphics *graphics)
static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
}
+void TextField::setNumeric(bool numeric)
+{
+ mNumeric = numeric;
+ if (!numeric)
+ {
+ return;
+ }
+ const char *text = mText.c_str();
+ for (const char *textPtr = text; *textPtr; ++textPtr)
+ {
+ if (*textPtr < '0' || *textPtr > '9')
+ {
+ setText(mText.substr(0, textPtr - text));
+ return;
+ }
+ }
+}
+
+int TextField::getValue() const
+{
+ if (!mNumeric)
+ {
+ return 0;
+ }
+ int value = atoi(mText.c_str());
+ if (value < mMinimum)
+ {
+ return mMinimum;
+ }
+ if (value > mMaximum)
+ {
+ return mMaximum;
+ }
+ return value;
+}
+
void TextField::keyPressed(gcn::KeyEvent &keyEvent)
{
int val = keyEvent.getKey().getValue();
diff --git a/src/gui/textfield.h b/src/gui/textfield.h
index 3570f89d..a2432175 100644
--- a/src/gui/textfield.h
+++ b/src/gui/textfield.h
@@ -24,7 +24,16 @@
#include <guichan/widgets/textfield.hpp>
+#include "../guichanfwd.h"
+
class ImageRect;
+class TextField;
+
+class TextFieldListener
+{
+ public:
+ virtual void listen(const TextField *value) = 0;
+};
/**
* A text field.
@@ -54,13 +63,47 @@ class TextField : public gcn::TextField {
void drawFrame(gcn::Graphics *graphics);
/**
+ * Determine whether the field should be numeric or not
+ */
+ void setNumeric(bool numeric);
+
+ /**
+ * Set the range on the field if it is numeric
+ */
+ void setRange(int min, int max) {mMinimum = min; mMaximum = max; }
+
+ /**
* Processes one keypress.
*/
void keyPressed(gcn::KeyEvent &keyEvent);
+ /**
+ * Set the minimum value for a range
+ */
+ void setMinimum(int min) {mMinimum = min; }
+
+ /**
+ * Set the maximum value for a range
+ */
+ void setMaximum(int max) {mMaximum = max; }
+
+ /**
+ * Return the value for a numeric field
+ */
+ int getValue() const;
+
+ /**
+ * Add a listener
+ */
+ void addListener(TextFieldListener *listener) {mListener = listener; }
+
private:
static int instances;
static ImageRect skin;
+ bool mNumeric;
+ int mMinimum;
+ int mMaximum;
+ TextFieldListener *mListener;
};
#endif
diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp
index 66df55b8..c89e55a2 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "trade.h"
-
#include <sstream>
#include <guichan/widgets/label.hpp>
@@ -32,9 +30,13 @@
#include "itemcontainer.h"
#include "scrollarea.h"
#include "textfield.h"
+#include "trade.h"
+
+#include "widgets/layout.h"
#include "../inventory.h"
#include "../item.h"
+#include "../localplayer.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
@@ -46,12 +48,12 @@
#include "../utils/tostring.h"
TradeWindow::TradeWindow(Network *network):
- Window("Trade: You"),
+ Window(_("Trade: You")),
mNetwork(network),
- mMyInventory(new Inventory),
- mPartnerInventory(new Inventory)
+ mMyInventory(new Inventory(INVENTORY_SIZE)),
+ mPartnerInventory(new Inventory(INVENTORY_SIZE))
{
- setWindowName("Trade");
+ setWindowName(_("Trade"));
setDefaultSize(115, 227, 342, 209);
setResizable(true);
@@ -63,47 +65,43 @@ TradeWindow::TradeWindow(Network *network):
mCancelButton = new Button(_("Cancel"), "cancel", this);
mTradeButton = new Button(_("Trade"), "trade", this);
- mMyItemContainer = new ItemContainer(mMyInventory.get());
+ mTradeButton->setEnabled(false);
+
+ mMyItemContainer = new ItemContainer(mMyInventory.get(), 2);
+ mMyItemContainer->setWidth(160);
mMyItemContainer->addSelectionListener(this);
- mMyItemContainer->setPosition(2, 2);
mMyScroll = new ScrollArea(mMyItemContainer);
- mMyScroll->setPosition(8, 8);
- mPartnerItemContainer = new ItemContainer(mPartnerInventory.get());
+ mPartnerItemContainer = new ItemContainer(mPartnerInventory.get(), 2);
+ mPartnerItemContainer->setWidth(160);
mPartnerItemContainer->addSelectionListener(this);
- mPartnerItemContainer->setPosition(2, 58);
mPartnerScroll = new ScrollArea(mPartnerItemContainer);
- mPartnerScroll->setPosition(8, 64);
mMoneyLabel = new gcn::Label(strprintf(_("You get %d GP."), 0));
mMoneyLabel2 = new gcn::Label(_("You give:"));
mMoneyField = new TextField;
mMoneyField->setWidth(50);
- mAddButton->adjustSize();
- mOkButton->adjustSize();
- mCancelButton->adjustSize();
- mTradeButton->adjustSize();
-
- mTradeButton->setEnabled(false);
-
- mItemNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
- mItemDescriptionLabel = new gcn::Label(
- strprintf(_("Description: %s"), ""));
-
- add(mMyScroll);
- add(mPartnerScroll);
- add(mAddButton);
- add(mOkButton);
- add(mCancelButton);
- add(mTradeButton);
- add(mItemNameLabel);
- add(mItemDescriptionLabel);
- add(mMoneyLabel2);
- add(mMoneyField);
- add(mMoneyLabel);
+ place(1, 0, mMoneyLabel);
+ place(0, 1, mMyScroll).setPadding(3);
+ place(1, 1, mPartnerScroll).setPadding(3);
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+ place(0, 0, mMoneyLabel2);
+ place(1, 0, mMoneyField);
+ place = getPlacer(0, 2);
+ place(0, 0, mAddButton);
+ place(1, 0, mOkButton);
+ place(2, 0, mTradeButton);
+ place(3, 0, mCancelButton);
+ Layout &layout = getLayout();
+ layout.extend(0, 2, 2, 1);
+ layout.setRowHeight(1, Layout::AUTO_SET);
+ layout.setRowHeight(2, 0);
+ layout.setColWidth(0, Layout::AUTO_SET);
+ layout.setColWidth(1, Layout::AUTO_SET);
loadWindowState();
}
@@ -114,48 +112,13 @@ TradeWindow::~TradeWindow()
void TradeWindow::widgetResized(const gcn::Event &event)
{
- Window::widgetResized(event);
+ mMyItemContainer->setWidth(mMyScroll->getWidth());
+ mPartnerItemContainer->setWidth(mPartnerScroll->getWidth());
- const gcn::Rectangle &area = getChildrenArea();
- const int width = area.width;
- const int height = area.height;
-
- mMoneyLabel2->setPosition(8, height - 8 - mMoneyLabel2->getHeight());
- mMoneyField->setPosition(
- 8 + mMoneyLabel2->getWidth(),
- height - 8 - mMoneyField->getHeight());
- mMoneyLabel->setPosition(
- mMoneyField->getX() + mMoneyField->getWidth() + 6,
- mMoneyLabel2->getY());
-
- mCancelButton->setPosition(width - 8 - mCancelButton->getWidth(),
- height - 8 - mCancelButton->getHeight());
- mTradeButton->setPosition(
- mCancelButton->getX() - 4 - mTradeButton->getWidth(),
- mCancelButton->getY());
- mOkButton->setPosition(mTradeButton->getX() - 4 - mOkButton->getWidth(),
- mCancelButton->getY());
- mAddButton->setPosition(mOkButton->getX() - 4 - mAddButton->getWidth(),
- mCancelButton->getY());
-
- mItemDescriptionLabel->setPosition(8,
- mOkButton->getY() - mItemDescriptionLabel->getHeight() - 4);
- mItemNameLabel->setPosition(8,
- mItemDescriptionLabel->getY() - mItemNameLabel->getHeight() - 4);
-
- const int remaining = mItemNameLabel->getY() - 4 - 8 - 8;
- const int itemContainerHeight = remaining / 2;
-
- mMyItemContainer->setSize(width - 24 - 12 - 1,
- (INVENTORY_SIZE * 24) / (width / 24) - 1);
- mMyScroll->setSize(width - 16, itemContainerHeight);
-
- mPartnerItemContainer->setSize(width - 24 - 12 - 1,
- (INVENTORY_SIZE * 24) / (width / 24) - 1);
- mPartnerScroll->setSize(width - 16, itemContainerHeight);
- mPartnerScroll->setPosition(8, 8 + itemContainerHeight + 8);
+ Window::widgetResized(event);
}
+
void TradeWindow::addMoney(int amount)
{
mMoneyLabel->setCaption(strprintf(_("You get %d GP."), amount));
@@ -164,38 +127,40 @@ void TradeWindow::addMoney(int amount)
void TradeWindow::addItem(int id, bool own, int quantity, bool equipment)
{
- if (own) {
+ if (own)
+ {
+ mMyItemContainer->setWidth(mMyScroll->getWidth());
mMyInventory->addItem(id, quantity, equipment);
- } else {
+ }
+ else
+ {
+ mPartnerItemContainer->setWidth(mPartnerScroll->getWidth());
mPartnerInventory->addItem(id, quantity, equipment);
}
}
void TradeWindow::removeItem(int id, bool own)
{
- if (own) {
+ if (own)
mMyInventory->removeItem(id);
- } else {
+ else
mPartnerInventory->removeItem(id);
- }
}
void TradeWindow::changeQuantity(int index, bool own, int quantity)
{
- if (own) {
+ if (own)
mMyInventory->getItem(index)->setQuantity(quantity);
- } else {
+ else
mPartnerInventory->getItem(index)->setQuantity(quantity);
- }
}
void TradeWindow::increaseQuantity(int index, bool own, int quantity)
{
- if (own) {
+ if (own)
mMyInventory->getItem(index)->increaseQuantity(quantity);
- } else {
+ else
mPartnerInventory->getItem(index)->increaseQuantity(quantity);
- }
}
void TradeWindow::reset()
@@ -218,21 +183,30 @@ void TradeWindow::setTradeButton(bool enabled)
void TradeWindow::receivedOk(bool own)
{
- if (own) {
+ if (own)
+ {
mOkMe = true;
- if (mOkOther) {
+ if (mOkOther)
+ {
mTradeButton->setEnabled(true);
mOkButton->setEnabled(false);
- } else {
+ }
+ else
+ {
mTradeButton->setEnabled(false);
mOkButton->setEnabled(false);
}
- } else {
+ }
+ else
+ {
mOkOther = true;
- if (mOkMe) {
+ if (mOkMe)
+ {
mTradeButton->setEnabled(true);
mOkButton->setEnabled(false);
- } else {
+ }
+ else
+ {
mTradeButton->setEnabled(false);
mOkButton->setEnabled(true);
}
@@ -256,22 +230,9 @@ void TradeWindow::valueChanged(const gcn::SelectionEvent &event)
*/
if (event.getSource() == mMyItemContainer &&
(item = mMyItemContainer->getSelectedItem()))
- {
mPartnerItemContainer->selectNone();
- }
else if ((item = mPartnerItemContainer->getSelectedItem()))
- {
mMyItemContainer->selectNone();
- }
-
- // Update name and description
- ItemInfo const *info = item ? &item->getInfo() : NULL;
- mItemNameLabel->setCaption(strprintf(_("Name: %s"),
- info ? info->getName().c_str() : ""));
- mItemNameLabel->adjustSize();
- mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"),
- info ? info->getDescription().c_str() : ""));
- mItemDescriptionLabel->adjustSize();
}
void TradeWindow::action(const gcn::ActionEvent &event)
@@ -286,16 +247,19 @@ void TradeWindow::action(const gcn::ActionEvent &event)
if (mMyInventory->getFreeSlot() < 1)
return;
- if (mMyInventory->contains(item)) {
+ if (mMyInventory->contains(item))
+ {
chatWindow->chatLog(_("Failed adding item. You can not "
"overlap one kind of item on the window."), BY_SERVER);
return;
}
- if (item->getQuantity() == 1) {
+ if (item->getQuantity() == 1)
+ {
tradeItem(item, 1);
}
- else {
+ else
+ {
// Choose amount of items to trade
new ItemAmountWindow(AMOUNT_TRADE_ADD, this, item);
}
@@ -317,7 +281,9 @@ void TradeWindow::action(const gcn::ActionEvent &event)
outMsg.writeInt16(CMSG_TRADE_ITEM_ADD_REQUEST);
outMsg.writeInt16(0);
outMsg.writeInt32(tempInt);
- } else {
+ }
+ else
+ {
mMoneyField->setText("");
}
mMoneyField->setEnabled(false);
diff --git a/src/gui/trade.h b/src/gui/trade.h
index 3129c4b9..df724038 100644
--- a/src/gui/trade.h
+++ b/src/gui/trade.h
@@ -128,8 +128,6 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
ItemContainer *mMyItemContainer;
ItemContainer *mPartnerItemContainer;
- gcn::Label *mItemNameLabel;
- gcn::Label *mItemDescriptionLabel;
gcn::Label *mMoneyLabel;
gcn::Label *mMoneyLabel2;
gcn::Button *mAddButton, *mOkButton, *mCancelButton, *mTradeButton;
diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp
index f65b3446..66855b77 100644
--- a/src/gui/truetypefont.cpp
+++ b/src/gui/truetypefont.cpp
@@ -19,12 +19,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "truetypefont.h"
-
#include <list>
#include <guichan/exception.hpp>
+#include "truetypefont.h"
+
#include "../graphics.h"
#include "../resources/image.h"
@@ -74,7 +74,6 @@ class TextChunk
gcn::Color color;
};
-
// Word surfaces cache
static std::list<TextChunk> cache;
typedef std::list<TextChunk>::iterator CacheIterator;
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index 96c2e95c..67e05bbd 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "updatewindow.h"
-
#include <iostream>
#include <SDL.h>
#include <SDL_thread.h>
@@ -32,6 +30,9 @@
#include "button.h"
#include "progressbar.h"
#include "scrollarea.h"
+#include "updatewindow.h"
+
+#include "widgets/layout.h"
// Curl should be included after Guichan to avoid Windows redefinitions
#include <curl/curl.h>
@@ -40,11 +41,11 @@
#include "../log.h"
#include "../main.h"
+#include "../resources/resourcemanager.h"
+
#include "../utils/gettext.h"
#include "../utils/tostring.h"
-#include "../resources/resourcemanager.h"
-
/**
* Calculates the Alder-32 checksum for the given file.
*/
@@ -68,14 +69,13 @@ static unsigned long fadler32(FILE *file)
/**
* Load the given file into a vector of strings.
*/
-std::vector<std::string>
-loadTextFile(const std::string &fileName)
+std::vector<std::string> loadTextFile(const std::string &fileName)
{
std::vector<std::string> lines;
std::ifstream fin(fileName.c_str());
if (!fin) {
- logger->log("Couldn't load text file: %s", fileName.c_str());
+ logger->log(_("Couldn't load text file: %s"), fileName.c_str());
return lines;
}
@@ -107,34 +107,29 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
{
mCurlError[0] = 0;
- const int h = 240;
- const int w = 320;
- setContentSize(w, h);
-
mBrowserBox = new BrowserBox();
mScrollArea = new ScrollArea(mBrowserBox);
mLabel = new gcn::Label(_("Connecting..."));
- mProgressBar = new ProgressBar(0.0, w - 10, 20, 37, 70, 200);
+ mProgressBar = new ProgressBar(0.0, 310, 20, 168, 116, 31);
mCancelButton = new Button(_("Cancel"), "cancel", this);
mPlayButton = new Button(_("Play"), "play", this);
mBrowserBox->setOpaque(false);
mPlayButton->setEnabled(false);
- mCancelButton->setPosition(5, h - 5 - mCancelButton->getHeight());
- mPlayButton->setPosition(
- mCancelButton->getX() + mCancelButton->getWidth() + 5,
- h - 5 - mPlayButton->getHeight());
- mProgressBar->setPosition(5, mCancelButton->getY() - 20 - 5);
- mLabel->setPosition(5, mProgressBar->getY() - mLabel->getHeight() - 5);
+ ContainerPlacer place;
+ place = getPlacer(0, 0);
+
+ place(0, 0, mScrollArea, 5, 3).setPadding(3);
+ place(0, 3, mLabel, 5);
+ place(0, 4, mProgressBar, 5);
+ place(3, 5, mCancelButton);
+ place(4, 5, mPlayButton);
- mScrollArea->setDimension(gcn::Rectangle(5, 5, 310, mLabel->getY() - 12));
+ reflowLayout(320, 240);
- add(mScrollArea);
- add(mLabel);
- add(mProgressBar);
- add(mCancelButton);
- add(mPlayButton);
+ Layout &layout = getLayout();
+ layout.setRowHeight(0, Layout::AUTO_SET);
setLocationRelativeTo(getParent());
setVisible(true);
@@ -198,7 +193,7 @@ void UpdaterWindow::loadNews()
{
if (!mMemoryBuffer)
{
- logger->log("Couldn't load news");
+ logger->log(_("Couldn't load news"));
return;
}
@@ -246,8 +241,7 @@ int UpdaterWindow::updateProgress(void *ptr,
return 0;
}
-size_t
-UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
+size_t UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(stream);
size_t totalMem = size * nmemb;
@@ -330,8 +324,8 @@ int UpdaterWindow::downloadThread(void *ptr)
{
case CURLE_COULDNT_CONNECT:
default:
- std::cerr << "curl error " << res << ": "
- << uw->mCurlError << " host: " << url.c_str()
+ std::cerr << _("curl error ") << res << ": "
+ << uw->mCurlError << _(" host: ") << url.c_str()
<< std::endl;
break;
}
@@ -366,7 +360,7 @@ int UpdaterWindow::downloadThread(void *ptr)
// Remove the corrupted file
::remove(outFilename.c_str());
logger->log(
- "Checksum for file %s failed: (%lx/%lx)",
+ _("Checksum for file %s failed: (%lx/%lx)"),
uw->mCurrentFile.c_str(),
adler, uw->mCurrentChecksum);
attempts++;
@@ -416,7 +410,7 @@ void UpdaterWindow::download()
if (mThread == NULL)
{
- logger->log("Unable to create mThread");
+ logger->log(_("Unable to create mThread"));
mDownloadStatus = UPDATE_ERROR;
}
}
@@ -454,9 +448,9 @@ void UpdaterWindow::logic()
mThread = NULL;
}
mBrowserBox->addRow("");
- mBrowserBox->addRow("##1 The update process is incomplete.");
- mBrowserBox->addRow("##1 It is strongly recommended that");
- mBrowserBox->addRow("##1 you try again later");
+ mBrowserBox->addRow(_("##1 The update process is incomplete."));
+ mBrowserBox->addRow(_("##1 It is strongly recommended that"));
+ mBrowserBox->addRow(_("##1 you try again later"));
mBrowserBox->addRow(mCurlError);
mScrollArea->setVerticalScrollAmount(
mScrollArea->getVerticalMaxScroll());
@@ -510,7 +504,7 @@ void UpdaterWindow::logic()
}
else
{
- logger->log("%s already here", mCurrentFile.c_str());
+ logger->log(_("%s already here"), mCurrentFile.c_str());
}
mLineIndex++;
}
diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h
index 3acbfb7e..6450ece2 100644
--- a/src/gui/updatewindow.h
+++ b/src/gui/updatewindow.h
@@ -23,6 +23,7 @@
#define _UPDATERWINDOW_H
#include <guichan/actionlistener.hpp>
+
#include <string>
#include <vector>
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index ff0883f7..326a7189 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -19,17 +19,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "viewport.h"
+#include <cassert>
#include "gui.h"
-#include "popupmenu.h"
#include "ministatus.h"
+#include "popupmenu.h"
+#include "viewport.h"
-#include "../simpleanimation.h"
#include "../beingmanager.h"
#include "../configuration.h"
#include "../flooritemmanager.h"
#include "../graphics.h"
+#include "../keyboardconfig.h"
#include "../localplayer.h"
#include "../map.h"
#include "../monster.h"
@@ -37,15 +38,13 @@
#include "../textmanager.h"
#include "../resources/animation.h"
-#include "../resources/monsterinfo.h"
-#include "../resources/resourcemanager.h"
#include "../resources/image.h"
#include "../resources/imageset.h"
+#include "../resources/monsterinfo.h"
+#include "../resources/resourcemanager.h"
#include "../utils/tostring.h"
-#include <cassert>
-
extern volatile int tick_time;
Viewport::Viewport():
@@ -70,76 +69,21 @@ Viewport::Viewport():
config.addListener("ScrollRadius", this);
mPopupMenu = new PopupMenu();
-
- // Load target cursors
- loadTargetCursor("graphics/gui/target-cursor-blue-s.png", 44, 35,
- false, Being::TC_SMALL);
- loadTargetCursor("graphics/gui/target-cursor-red-s.png", 44, 35,
- true, Being::TC_SMALL);
- loadTargetCursor("graphics/gui/target-cursor-blue-m.png", 62, 44,
- false, Being::TC_MEDIUM);
- loadTargetCursor("graphics/gui/target-cursor-red-m.png", 62, 44,
- true, Being::TC_MEDIUM);
- loadTargetCursor("graphics/gui/target-cursor-blue-l.png", 82, 60,
- false, Being::TC_LARGE);
- loadTargetCursor("graphics/gui/target-cursor-red-l.png", 82, 60,
- true, Being::TC_LARGE);
-}
-
-void
-Viewport::loadTargetCursor(std::string filename, int width, int height,
- bool outRange, Being::TargetCursorSize size)
-{
- assert(size > -1);
- assert(size < 3);
-
- ImageSet* currentImageSet;
- SimpleAnimation* currentCursor;
-
- ResourceManager *resman = ResourceManager::getInstance();
-
- currentImageSet = resman->getImageSet(filename, width, height);
- Animation *anim = new Animation();
- for (unsigned int i = 0; i < currentImageSet->size(); ++i)
- {
- anim->addFrame(currentImageSet->get(i), 75, 0, 0);
- }
- currentCursor = new SimpleAnimation(anim);
-
- if (outRange)
- {
- mOutRangeImages[size] = currentImageSet;
- mTargetCursorOutRange[size] = currentCursor;
- }
- else {
- mInRangeImages[size] = currentImageSet;
- mTargetCursorInRange[size] = currentCursor;
- }
}
Viewport::~Viewport()
{
delete mPopupMenu;
-
- for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
- {
- delete mTargetCursorInRange[i];
- delete mTargetCursorOutRange[i];
- mInRangeImages[i]->decRef();
- mOutRangeImages[i]->decRef();
- }
}
-void
-Viewport::setMap(Map *map)
+void Viewport::setMap(Map *map)
{
mMap = map;
}
extern MiniStatusWindow *miniStatusWindow;
-void
-Viewport::draw(gcn::Graphics *gcnGraphics)
+void Viewport::draw(gcn::Graphics *gcnGraphics)
{
static int lastTick = tick_time;
@@ -148,6 +92,10 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
Graphics *graphics = static_cast<Graphics*>(gcnGraphics);
+ // Ensure the client doesn't freak out if a feature localplayer uses
+ // is dependent on a map.
+ player_node->mMapInitialized = true;
+
// Avoid freaking out when tick_time overflows
if (tick_time < lastTick)
{
@@ -225,37 +173,39 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
if (mMap)
{
mMap->draw(graphics, (int) mPixelViewX, (int) mPixelViewY);
- drawTargetCursor(graphics); // TODO: Draw the cursor with the sprite
- }
- // Find a path from the player to the mouse, and draw it. This is for debug
- // purposes.
- if (mShowDebugPath && mMap)
- {
- // Get the current mouse position
- int mouseX, mouseY;
- SDL_GetMouseState(&mouseX, &mouseY);
+ // Find a path from the player to the mouse, and draw it. This is for debug
+ // purposes.
+ if (mShowDebugPath)
+ {
+ // Get the current mouse position
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
- int mouseTileX = mouseX / 32 + mTileViewX;
- int mouseTileY = mouseY / 32 + mTileViewY;
+ int mouseTileX = mouseX / 32 + mTileViewX;
+ int mouseTileY = mouseY / 32 + mTileViewY;
- Path debugPath = mMap->findPath(
- player_node->mX, player_node->mY,
- mouseTileX, mouseTileY);
+ Path debugPath = mMap->findPath(player_node->mX, player_node->mY, mouseTileX, mouseTileY);
- graphics->setColor(gcn::Color(255, 0, 0));
- for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++)
- {
- int squareX = i->x * 32 - (int) mPixelViewX + 12;
- int squareY = i->y * 32 - (int) mPixelViewY + 12;
+ graphics->setColor(gcn::Color(255, 0, 0));
+ for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++)
+ {
+ int squareX = i->x * 32 - (int) mPixelViewX + 12;
+ int squareY = i->y * 32 - (int) mPixelViewY + 12;
- graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8));
- graphics->drawText(
- toString(mMap->getMetaTile(i->x, i->y)->Gcost),
- squareX + 4, squareY + 12, gcn::Graphics::CENTER);
+ graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8));
+ graphics->drawText(toString(mMap->getMetaTile(i->x, i->y)->Gcost), squareX + 4, squareY + 12, gcn::Graphics::CENTER);
+ }
}
}
+ if (player_node->mUpdateName)
+ {
+ player_node->mUpdateName = false;
+ player_node->setName(player_node->getName());
+ }
+
+
// Draw text
if (textManager)
{
@@ -266,6 +216,7 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
Beings &beings = beingManager->getAll();
for (BeingIterator i = beings.begin(); i != beings.end(); i++)
{
+ (*i)->drawSpeech(graphics, -(int) mPixelViewX, -(int) mPixelViewY);
(*i)->drawEmotion(graphics, -(int) mPixelViewX, -(int) mPixelViewY);
}
@@ -276,8 +227,7 @@ Viewport::draw(gcn::Graphics *gcnGraphics)
WindowContainer::draw(gcnGraphics);
}
-void
-Viewport::logic()
+void Viewport::logic()
{
WindowContainer::logic();
@@ -294,49 +244,9 @@ Viewport::logic()
mouseY / 32 + mTileViewY);
mWalkTime = player_node->mWalkTime;
}
-
- for (int i = 0; i < 3; i++)
- {
- mTargetCursorInRange[i]->update(10);
- mTargetCursorOutRange[i]->update(10);
- }
}
-void
-Viewport::drawTargetCursor(Graphics *graphics)
-{
- // Draw target marker if needed
- Being *target = player_node->getTarget();
- if (target)
- {
- // Calculate target circle position
-
- // Find whether target is in range
- int rangeX = abs(target->mX - player_node->mX);
- int rangeY = abs(target->mY - player_node->mY);
- int attackRange = player_node->getAttackRange();
-
- // Get the correct target cursors graphic
- Being::TargetCursorSize cursorSize = target->getTargetCursorSize();
- Image* targetCursor;
- if (rangeX > attackRange || rangeY > attackRange)
- {
- targetCursor = mTargetCursorOutRange[cursorSize]->getCurrentImage();
- }
- else {
- targetCursor = mTargetCursorInRange[cursorSize]->getCurrentImage();
- }
-
- // Draw the target cursor at the correct position
- int posX = target->getPixelX() + 16 - targetCursor->getWidth() / 2 - (int) mPixelViewX;
- int posY = target->getPixelY() + 16 - targetCursor->getHeight() / 2 - (int) mPixelViewY;
-
- graphics->drawImage(targetCursor, posX, posY);
- }
-}
-
-void
-Viewport::mousePressed(gcn::MouseEvent &event)
+void Viewport::mousePressed(gcn::MouseEvent &event)
{
// Check if we are alive and kickin'
if (!mMap || !player_node || player_node->mAction == Being::DEAD)
@@ -348,8 +258,10 @@ Viewport::mousePressed(gcn::MouseEvent &event)
mPlayerFollowMouse = false;
- int tilex = event.getX() / 32 + mTileViewX;
- int tiley = event.getY() / 32 + mTileViewY;
+ const int tilex = event.getX() / 32 + mTileViewX;
+ const int tiley = event.getY() / 32 + mTileViewY;
+ const int x = (int)((float) event.getX() + mPixelViewX);
+ const int y = (int)((float) event.getY() + mPixelViewY);
// Right click might open a popup
if (event.getButton() == gcn::MouseEvent::RIGHT)
@@ -357,11 +269,11 @@ Viewport::mousePressed(gcn::MouseEvent &event)
Being *being;
FloorItem *floorItem;
- if ((being = beingManager->findBeing(tilex, tiley)) &&
- being != player_node)
+ if ((being = beingManager->findBeingByPixel(x, y)) &&
+ being != player_node)
{
- mPopupMenu->showPopup(event.getX(), event.getY(), being);
- return;
+ mPopupMenu->showPopup(event.getX(), event.getY(), being);
+ return;
}
else if((floorItem = floorItemManager->findByCoordinates(tilex, tiley)))
{
@@ -382,11 +294,9 @@ Viewport::mousePressed(gcn::MouseEvent &event)
{
Being *being;
FloorItem *item;
-
+
// Interact with some being
-// if ((being = beingManager->findBeing(tilex, tiley))
- int x = (int)((float) event.getX() + mPixelViewX);
- int y = (int)((float) event.getY() + mPixelViewY);
+// if ((being = beingManager->findBeing(tilex, tiley)))
if ((being = beingManager->findBeingByPixel(x, y)))
{
switch (being->getType())
@@ -400,59 +310,47 @@ Viewport::mousePressed(gcn::MouseEvent &event)
if (being->mAction == Being::DEAD)
break;
- if (player_node->withinAttackRange(being))
+ if (player_node->withinAttackRange(being) || keyboard.isKeyActive(keyboard.KEY_ATTACK))
{
- player_node->attack(being, true);
+ player_node->setGotoTarget(being);
+ player_node->attack(being, !keyboard.isKeyActive(keyboard.KEY_TARGET));
}
else
{
- Uint8 *keys = SDL_GetKeyState(NULL);
- if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
- {
- player_node->stopAttack();
- player_node->setGotoTarget(being);
- }
+ player_node->setDestination(tilex, tiley);
}
break;
default:
break;
- }
+ }
}
// Pick up some item
else if ((item = floorItemManager->findByCoordinates(tilex, tiley)))
{
- player_node->pickUp(item);
+ player_node->pickUp(item);
}
// Just walk around
else
{
- // XXX XXX XXX REALLY UGLY!
- Uint8 *keys = SDL_GetKeyState(NULL);
- if (!(keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]))
- {
- player_node->setDestination(tilex, tiley);
- player_node->stopAttack();
- }
+ player_node->stopAttack();
+ player_node->setDestination(tilex, tiley);
mPlayerFollowMouse = true;
}
}
else if (event.getButton() == gcn::MouseEvent::MIDDLE)
{
// Find the being nearest to the clicked position
- Being *target = beingManager->findNearestLivingBeing(
- tilex, tiley,
- 20, Being::MONSTER);
-
+ Being *target = beingManager->findBeingByPixel(x, y);
+
if (target)
{
- player_node->setTarget(target);
+ player_node->setTarget(target);
}
}
}
-void
-Viewport::mouseDragged(gcn::MouseEvent &event)
+void Viewport::mouseDragged(gcn::MouseEvent &event)
{
if (!mMap || !player_node)
return;
@@ -465,20 +363,17 @@ Viewport::mouseDragged(gcn::MouseEvent &event)
}
}
-void
-Viewport::mouseReleased(gcn::MouseEvent &event)
+void Viewport::mouseReleased(gcn::MouseEvent &event)
{
mPlayerFollowMouse = false;
}
-void
-Viewport::showPopup(int x, int y, Item *item)
+void Viewport::showPopup(int x, int y, Item *item)
{
mPopupMenu->showPopup(x, y, item);
}
-void
-Viewport::optionChanged(const std::string &name)
+void Viewport::optionChanged(const std::string &name)
{
mScrollLaziness = (int) config.getValue("ScrollLaziness", 32);
mScrollRadius = (int) config.getValue("ScrollRadius", 32);
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index 8965ad95..5ed40166 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -26,8 +26,9 @@
#include "windowcontainer.h"
-#include "../configlistener.h"
#include "../being.h"
+#include "../configlistener.h"
+#include "../guichanfwd.h"
class Map;
class FloorItem;
@@ -35,7 +36,6 @@ class ImageSet;
class Item;
class PopupMenu;
class Graphics;
-class SimpleAnimation;
/**
* The viewport on the map. Displays the current map and handles mouse input
@@ -62,97 +62,65 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
/**
* Sets the map displayed by the viewport.
*/
- void
- setMap(Map *map);
+ void setMap(Map *map);
/**
* Draws the viewport.
*/
- void
- draw(gcn::Graphics *graphics);
+ void draw(gcn::Graphics *graphics);
/**
* Implements player to keep following mouse.
*/
- void
- logic();
+ void logic();
/**
* Toggles whether the path debug graphics are shown
*/
- void
- toggleDebugPath() { mShowDebugPath = !mShowDebugPath; }
+ void toggleDebugPath() { mShowDebugPath = !mShowDebugPath; }
/**
* Handles mouse press on map.
*/
- void
- mousePressed(gcn::MouseEvent &event);
+ void mousePressed(gcn::MouseEvent &event);
/**
* Handles mouse move on map
*/
- void
- mouseDragged(gcn::MouseEvent &event);
+ void mouseDragged(gcn::MouseEvent &event);
/**
* Handles mouse button release on map.
*/
- void
- mouseReleased(gcn::MouseEvent &event);
+ void mouseReleased(gcn::MouseEvent &event);
/**
* Shows a popup for an item.
* TODO Find some way to get rid of Item here
*/
- void
- showPopup(int x, int y, Item *item);
+ void showPopup(int x, int y, Item *item);
/**
* A relevant config option changed.
*/
- void
- optionChanged(const std::string &name);
+ void optionChanged(const std::string &name);
/**
- * Returns camera x offset in tiles.
+ * Returns camera x offset in pixels.
*/
- int
- getCameraX() { return mTileViewX; }
+ int getCameraX() const { return (int) mPixelViewX; }
/**
- * Returns camera y offset in tiles.
+ * Returns camera y offset in pixels.
*/
- int
- getCameraY() { return mTileViewY; }
+ int getCameraY() const { return (int) mPixelViewY; }
/**
* Changes viewpoint by relative pixel coordinates.
*/
- void
- scrollBy(float x, float y) { mPixelViewX += x; mPixelViewY += y; }
+ void scrollBy(float x, float y) { mPixelViewX += x; mPixelViewY += y; }
private:
- /**
- * Helper function for loading target cursors
- */
- void
- loadTargetCursor(std::string filename, int width, int height,
- bool outRange, Being::TargetCursorSize size);
-
- /**
- * Draws range based target cursor
- */
- void
- drawTargetCursor(Graphics *graphics);
-
- /**
- * Draws target name
- */
- void
- drawTargetName(Graphics *graphics);
-
-
Map *mMap; /**< The current map. */
int mScrollRadius;
@@ -165,18 +133,6 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
int mTileViewY; /**< Current viewpoint in tiles. */
bool mShowDebugPath; /**< Show a path from player to pointer. */
- /** Images of in range target cursor. */
- ImageSet *mInRangeImages[Being::NUM_TC];
-
- /** Images of out of range target cursor. */
- ImageSet *mOutRangeImages[Being::NUM_TC];
-
- /** Animated in range target cursor. */
- SimpleAnimation *mTargetCursorInRange[Being::NUM_TC];
-
- /** Animated out of range target cursor. */
- SimpleAnimation *mTargetCursorOutRange[Being::NUM_TC];
-
bool mPlayerFollowMouse;
int mWalkTime;
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
new file mode 100644
index 00000000..88a12d68
--- /dev/null
+++ b/src/gui/widgets/dropdown.cpp
@@ -0,0 +1,167 @@
+/*
+ * 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
+ */
+
+#include <algorithm>
+
+#include "dropdown.h"
+
+#include "../../graphics.h"
+
+#include "../../resources/image.h"
+#include "../../resources/resourcemanager.h"
+
+#include "../../utils/dtor.h"
+
+int DropDown::instances = 0;
+Image *DropDown::buttons[2][2];
+ImageRect DropDown::skin;
+
+DropDown::DropDown(gcn::ListModel *listModel,
+ gcn::ScrollArea *scrollArea,
+ gcn::ListBox *listBox):
+ gcn::DropDown::DropDown(listModel,
+ scrollArea, listBox)
+{
+ setFrameSize(2);
+
+ // Initialize graphics
+ if (instances == 0)
+ {
+ // Load the background skin
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Get the button skin
+ buttons[1][0] =
+ resman->getImage("graphics/gui/vscroll_up_default.png");
+ buttons[0][0] =
+ resman->getImage("graphics/gui/vscroll_down_default.png");
+ buttons[1][1] =
+ resman->getImage("graphics/gui/vscroll_up_pressed.png");
+ buttons[0][1] =
+ resman->getImage("graphics/gui/vscroll_down_pressed.png");
+
+ // get the border skin
+ Image *boxBorder = resman->getImage("graphics/gui/deepbox.png");
+ int gridx[4] = {0, 3, 28, 31};
+ int gridy[4] = {0, 3, 28, 31};
+ int a = 0, x, y;
+
+ for (y = 0; y < 3; y++) {
+ for (x = 0; x < 3; x++) {
+ skin.grid[a] = boxBorder->getSubImage(
+ gridx[x], gridy[y],
+ gridx[x + 1] - gridx[x] + 1,
+ gridy[y + 1] - gridy[y] + 1);
+ a++;
+ }
+ }
+
+ boxBorder->decRef();
+ }
+
+ instances++;
+}
+
+DropDown::~DropDown()
+{
+ instances--;
+ // Free images memory
+ if (instances == 0)
+ {
+ buttons[0][0]->decRef();
+ buttons[0][1]->decRef();
+ buttons[1][0]->decRef();
+ buttons[1][1]->decRef();
+
+ for_each(skin.grid, skin.grid + 9, dtor<Image*>());
+ }
+}
+
+void DropDown::draw(gcn::Graphics* graphics)
+{
+ int h;
+
+ if (mDroppedDown)
+ {
+ h = mFoldedUpHeight;
+ }
+ else
+ {
+ h = getHeight();
+ }
+
+ int alpha = getBaseColor().a;
+ gcn::Color faceColor = getBaseColor();
+ faceColor.a = alpha;
+ gcn::Color highlightColor = faceColor + 0x303030;
+ highlightColor.a = alpha;
+ gcn::Color shadowColor = faceColor - 0x303030;
+ shadowColor.a = alpha;
+
+
+ graphics->setColor(getBackgroundColor());
+ graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), h));
+
+ graphics->setColor(getForegroundColor());
+ graphics->setFont(getFont());
+
+ if (mListBox->getListModel() && mListBox->getSelected() >= 0)
+ {
+ graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
+ }
+
+ if (isFocused())
+ {
+ graphics->setColor(highlightColor);
+ graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth() - h, h));
+ }
+
+ drawButton(graphics);
+
+ if (mDroppedDown)
+ {
+ drawChildren(graphics);
+
+ // Draw two lines separating the ListBox with se selected
+ // element view.
+ graphics->setColor(highlightColor);
+ graphics->drawLine(0, h, getWidth(), h);
+ graphics->setColor(shadowColor);
+ graphics->drawLine(0, h + 1, getWidth(), h + 1);
+ }
+}
+
+void DropDown::drawFrame(gcn::Graphics *graphics)
+{
+ const int bs = getFrameSize();
+ const int w = getWidth() + bs * 2;
+ const int h = getHeight() + bs * 2;
+
+ static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
+}
+
+void DropDown::drawButton(gcn::Graphics *graphics)
+{
+ int height = mDroppedDown ? mFoldedUpHeight : getHeight();
+
+ static_cast<Graphics*>(graphics)->
+ drawImage(buttons[mDroppedDown][mPushed], getWidth() - height + 2, 1);
+}
diff --git a/src/gui/widgets/dropdown.h b/src/gui/widgets/dropdown.h
new file mode 100644
index 00000000..25ae05f8
--- /dev/null
+++ b/src/gui/widgets/dropdown.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
+ */
+
+#ifndef DROPDOWN_H
+#define DROPDOWN_H
+
+#include <iosfwd>
+
+#include <guichan/widgets/dropdown.hpp>
+
+#include "../listbox.h"
+#include "../scrollarea.h"
+
+#include "../../guichanfwd.h"
+
+class Image;
+class ImageRect;
+
+ /**
+ * A drop down box from which you can select different values. It is one of
+ * the most complicated Widgets you will find in Guichan. For drawing the
+ * DroppedDown box it uses one ScrollArea and one ListBox. It also uses an
+ * internal FocusHandler to handle the focus of the internal ScollArea and
+ * ListBox. DropDown uses a ListModel to handle the list. To be able to use
+ * DropDown you must give DropDown an implemented ListModel which represents
+ * your list.
+ */
+class DropDown : public gcn::DropDown
+{
+ public:
+ /**
+ * Contructor.
+ *
+ * @param listModel the ListModel to use.
+ * @param scrollArea the ScrollArea to use.
+ * @param listBox the listBox to use.
+ * @see ListModel, ScrollArea, ListBox.
+ */
+ DropDown(gcn::ListModel *listModel = NULL,
+ gcn::ScrollArea *scrollArea = NULL,
+ gcn::ListBox *listBox = NULL);
+
+ /**
+ * Destructor.
+ */
+ ~DropDown();
+
+ void draw(gcn::Graphics* graphics);
+
+ void drawFrame(gcn::Graphics* graphics);
+
+
+ protected:
+ /**
+ * Draws the button with the little down arrow.
+ *
+ * @param graphics a Graphics object to draw with.
+ */
+ void drawButton(gcn::Graphics *graphics);
+
+ // Add own Images.
+ static int instances;
+ static Image *buttons[2][2];
+ static ImageRect skin;
+};
+
+#endif // end DROPDOWN_H
+
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index 00689575..4b8bb4da 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -19,10 +19,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "resizegrip.h"
-
#include <guichan/graphics.hpp>
+#include "resizegrip.h"
+
#include "../../graphics.h"
#include "../../resources/image.h"
@@ -31,13 +31,13 @@
Image *ResizeGrip::gripImage = 0;
int ResizeGrip::mInstances = 0;
-ResizeGrip::ResizeGrip()
+ResizeGrip::ResizeGrip(std::string image)
{
if (mInstances == 0)
{
// Load the grip image
ResourceManager *resman = ResourceManager::getInstance();
- gripImage = resman->getImage("graphics/gui/resize.png");
+ gripImage = resman->getImage(image);
}
mInstances++;
@@ -56,8 +56,7 @@ ResizeGrip::~ResizeGrip()
}
}
-void
-ResizeGrip::draw(gcn::Graphics *graphics)
+void ResizeGrip::draw(gcn::Graphics *graphics)
{
static_cast<Graphics*>(graphics)->drawImage(gripImage, 0, 0);
}
diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h
index 5c6ea4bd..7f1329a2 100644
--- a/src/gui/widgets/resizegrip.h
+++ b/src/gui/widgets/resizegrip.h
@@ -24,6 +24,8 @@
#include <guichan/widget.hpp>
+#include "../../guichanfwd.h"
+
class Image;
/**
@@ -39,7 +41,7 @@ class ResizeGrip : public gcn::Widget
/**
* Constructor.
*/
- ResizeGrip();
+ ResizeGrip(std::string image = "graphics/gui/resize.png");
/**
* Destructor.
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index ed5bb8fc..e0e88b31 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -24,11 +24,12 @@
#include <climits>
#include <guichan/exception.hpp>
-#include <guichan/widgets/icon.hpp>
-#include "window.h"
+#include <guichan/widgets/icon.hpp>
#include "gui.h"
+#include "gccontainer.h"
+#include "window.h"
#include "windowcontainer.h"
#include "widgets/layout.h"
@@ -42,24 +43,28 @@
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
+#include "../utils/xml.h"
+
ConfigListener *Window::windowConfigListener = 0;
WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
int Window::mouseResize = 0;
-ImageRect Window::border;
+//ImageRect Window::border;
Image *Window::closeImage = NULL;
+bool Window::mAlphaChanged = false;
class WindowConfigListener : public ConfigListener
{
void optionChanged(const std::string &)
{
- for_each(Window::border.grid, Window::border.grid + 9,
- std::bind2nd(std::mem_fun(&Image::setAlpha),
- config.getValue("guialpha", 0.8)));
+ Window::mAlphaChanged = true;
+// for_each(Window::border.grid, Window::border.grid + 9,
+// std::bind2nd(std::mem_fun(&Image::setAlpha),
+// config.getValue("guialpha", 0.8)));
}
};
-Window::Window(const std::string& caption, bool modal, Window *parent):
+Window::Window(const std::string& caption, bool modal, Window *parent, const std::string& skin):
gcn::Window(caption),
mGrip(0),
mParent(parent),
@@ -72,31 +77,23 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
mMinWinWidth(100),
mMinWinHeight(40),
mMaxWinWidth(INT_MAX),
- mMaxWinHeight(INT_MAX)
+ mMaxWinHeight(INT_MAX),
+ mSkin(skin)
{
logger->log("Window::Window(\"%s\")", caption.c_str());
- if (!windowContainer) {
+ if (!windowContainer)
+ {
throw GCN_EXCEPTION("Window::Window(): no windowContainer set");
}
+ // Loads the skin
+ loadSkin(mSkin);
+
+ setGuiAlpha();
+
if (instances == 0)
{
- // Load static resources
- ResourceManager *resman = ResourceManager::getInstance();
- Image *dBorders = resman->getImage("graphics/gui/vscroll_grey.png");
- border.grid[0] = dBorders->getSubImage(0, 0, 4, 4);
- border.grid[1] = dBorders->getSubImage(4, 0, 3, 4);
- border.grid[2] = dBorders->getSubImage(7, 0, 4, 4);
- border.grid[3] = dBorders->getSubImage(0, 4, 4, 10);
- border.grid[4] = resman->getImage("graphics/gui/bg_quad_dis.png");
- border.grid[5] = dBorders->getSubImage(7, 4, 4, 10);
- border.grid[6] = dBorders->getSubImage(0, 15, 4, 4);
- 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");
@@ -130,12 +127,14 @@ Window::~Window()
const std::string &name = mWindowName;
// Saving X, Y and Width and Height for resizables in the config
- if (!name.empty()) {
+ if (!name.empty())
+ {
config.setValue(name + "WinX", getX());
config.setValue(name + "WinY", getY());
config.setValue(name + "Visible", isVisible());
- if (mGrip) {
+ if (mGrip)
+ {
config.setValue(name + "WinWidth", getWidth());
config.setValue(name + "WinHeight", getHeight());
}
@@ -152,22 +151,19 @@ Window::~Window()
instances--;
+ // Clean up static resources
+ for( int i = 0; i < 9; i++ )
+ {
+ delete border.grid[i];
+ border.grid[i] = NULL;
+ }
+
if (instances == 0)
{
config.removeListener("guialpha", windowConfigListener);
delete windowConfigListener;
windowConfigListener = NULL;
- // Clean up static resources
- delete border.grid[0];
- delete border.grid[1];
- delete border.grid[2];
- delete border.grid[3];
- border.grid[4]->decRef();
- delete border.grid[5];
- delete border.grid[6];
- delete border.grid[7];
- delete border.grid[8];
closeImage->decRef();
}
}
@@ -524,6 +520,187 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
return resizeHandles;
}
+void Window::setGuiAlpha()
+{
+ //logger->log("Window::setGuiAlpha: Alpha Value %f", config.getValue("guialpha", 0.8));
+ for(int i = 0; i < 9; i++)
+ {
+ //logger->log("Window::setGuiAlpha: Border Image (%i)", i);
+ border.grid[i]->setAlpha(config.getValue("guialpha", 0.8));
+ }
+
+ mAlphaChanged = false;
+}
+
+void Window::loadSkin(const std::string filename)
+{
+ const std::string windowId = Window::getId();
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ logger->log("Loading Window Skin '%s'.", filename.c_str());
+ logger->log("Loading Window ID '%s'.", windowId.c_str());
+
+
+ if(filename == "")
+ logger->error("Window::loadSkin(): Invalid File Name.");
+
+ // TODO:
+ // If there is an error loading the specified file, we should try to revert
+ // to a 'default' skin file. Only if the 'default' skin file can't be loaded
+ // should we have a terminating error.
+ XML::Document doc(filename);
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skinset"))
+ {
+ logger->error("Widget Skinning error");
+ }
+
+ std::string skinSetImage;
+ skinSetImage = XML::getProperty(rootNode, "image", "");
+ Image *dBorders = NULL;
+ if(skinSetImage != "")
+ {
+ logger->log("Window::loadSkin(): <skinset> defines '%s' as a skin image.", skinSetImage.c_str());
+ dBorders = resman->getImage("graphics/gui/" + skinSetImage);//"graphics/gui/speech_bubble.png");
+ }
+ else
+ {
+ logger->error("Window::loadSkin(): Skinset does not define an image!");
+ }
+
+ //iterate <widget>'s
+ for_each_xml_child_node(widgetNode, rootNode)
+ {
+ if (!xmlStrEqual(widgetNode->name, BAD_CAST "widget"))
+ continue;
+
+ std::string widgetType;
+ widgetType = XML::getProperty(widgetNode, "type", "unknown");
+ if (widgetType == "Window")
+ {
+ // Iterate through <part>'s
+ // LEEOR / TODO:
+ // We need to make provisions to load in a CloseButton image. For now it
+ // can just be hard-coded.
+ for_each_xml_child_node(partNode, widgetNode)
+ {
+ if (!xmlStrEqual(partNode->name, BAD_CAST "part"))
+ {
+ continue;
+ }
+
+ std::string partType;
+ partType = XML::getProperty(partNode, "type", "unknown");
+ // TOP ROW
+ if(partType == "top-left-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[0] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if(partType == "top-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[1] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if(partType == "top-right-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[2] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+
+ // MIDDLE ROW
+ else if(partType == "left-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[3] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if(partType == "bg-quad")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[4] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if(partType == "right-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[5] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+
+ // BOTTOM ROW
+ else if(partType == "bottom-left-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[6] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if(partType == "bottom-edge")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[7] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+ else if(partType == "bottom-right-corner")
+ {
+ const int xPos = XML::getProperty(partNode, "xpos", 0);
+ const int yPos = XML::getProperty(partNode, "ypos", 0);
+ const int width = XML::getProperty(partNode, "width", 1);
+ const int height = XML::getProperty(partNode, "height", 1);
+
+ border.grid[8] = dBorders->getSubImage(xPos, yPos, width, height);
+ }
+
+ // Part is of an uknown type.
+ else
+ {
+ logger->log("Window::loadSkin(): Unknown Part Type '%s'", partType.c_str());
+ }
+ }
+ }
+ // Widget is of an uknown type.
+ else
+ {
+ logger->log("Window::loadSkin(): Unknown Widget Type '%s'", widgetType.c_str());
+ }
+ }
+ dBorders->decRef();
+
+ logger->log("Finished loading Window Skin.");
+
+ // Hard-coded for now until we update the above code to look for window buttons.
+ closeImage = resman->getImage("graphics/gui/close_button.png");
+}
+
Layout &Window::getLayout()
{
if (!mLayout) mLayout = new Layout;
diff --git a/src/gui/window.h b/src/gui/window.h
index 19d59c26..deaf984c 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -22,9 +22,11 @@
#ifndef WINDOW_H
#define WINDOW_H
-#include <guichan/widgets/window.hpp>
#include <guichan/widgetlistener.hpp>
+#include <guichan/widgets/window.hpp>
+
+#include "../graphics.h"
#include "../guichanfwd.h"
class ConfigListener;
@@ -56,9 +58,10 @@ class Window : public gcn::Window, gcn::WidgetListener
* @param parent The parent window. This is the window standing above
* this one in the window hiearchy. When reordering,
* a window will never go below its parent window.
+ * @param skin The location where the window's skin XML can be found.
*/
Window(const std::string &caption = "Window", bool modal = false,
- Window *parent = NULL);
+ Window *parent = NULL, const std::string &skin = "graphics/gui/gui.xml");
/**
* Destructor. Deletes all the added widgets.
@@ -126,6 +129,26 @@ class Window : public gcn::Window, gcn::WidgetListener
void setMaxHeight(unsigned int height);
/**
+ * Gets the minimum width of the window.
+ */
+ int getMinWidth() { return mMinWinWidth; }
+
+ /**
+ * Gets the minimum height of the window.
+ */
+ int getMinHeight() { return mMinWinHeight; }
+
+ /**
+ * Gets the maximum width of the window.
+ */
+ int getMaxWidth() { return mMaxWinWidth; }
+
+ /**
+ * Gets the minimum height of the window.
+ */
+ int getMaxHeight() { return mMaxWinHeight; }
+
+ /**
* Sets flag to show a title or not.
*/
void setShowTitle(bool flag)
@@ -238,6 +261,11 @@ class Window : public gcn::Window, gcn::WidgetListener
void reflowLayout(int w = 0, int h = 0);
/**
+ * Loads a window skin
+ */
+ void loadSkin(const std::string filename);
+
+ /**
* Adds a widget to the window and sets it at given cell.
*/
LayoutCell &place(int x, int y, gcn::Widget *, int w = 1, int h = 1);
@@ -269,6 +297,8 @@ class Window : public gcn::Window, gcn::WidgetListener
*/
int getResizeHandles(gcn::MouseEvent &event);
+ void setGuiAlpha();
+
ResizeGrip *mGrip; /**< Resize grip */
Window *mParent; /**< The parent window */
Layout *mLayout; /**< Layout handler */
@@ -277,6 +307,7 @@ class Window : public gcn::Window, gcn::WidgetListener
bool mModal; /**< Window is modal */
bool mCloseButton; /**< Window has a close button */
bool mSticky; /**< Window resists minimization */
+ static bool mAlphaChanged; /**< Whether the alpha percent was changed */
int mMinWinWidth; /**< Minimum window width */
int mMinWinHeight; /**< Minimum window height */
int mMaxWinWidth; /**< Maximum window width */
@@ -285,6 +316,7 @@ class Window : public gcn::Window, gcn::WidgetListener
int mDefaultY; /**< Default window Y position */
int mDefaultWidth; /**< Default window width */
int mDefaultHeight; /**< Default window height */
+ std::string mSkin; /**< Name of the skin to use */
/**
* The config listener that listens to changes relevant to all windows.
@@ -293,7 +325,7 @@ class Window : public gcn::Window, gcn::WidgetListener
static int mouseResize; /**< Active resize handles */
static int instances; /**< Number of Window instances */
- static ImageRect border; /**< The window border and background */
+ ImageRect border; /**< The window border and background */
static Image *closeImage; /**< Close Button Image */
/**
diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h
index a25f2037..a3e80223 100644
--- a/src/gui/windowcontainer.h
+++ b/src/gui/windowcontainer.h
@@ -24,6 +24,8 @@
#include <guichan/widgets/container.hpp>
+#include "../guichanfwd.h"
+
/**
* A window container. This container adds functionality for more convenient
* widget (windows in particular) destruction.