diff options
author | David Athay <ko2fan@gmail.com> | 2009-01-13 00:28:58 +0000 |
---|---|---|
committer | David Athay <ko2fan@gmail.com> | 2009-01-13 00:28:58 +0000 |
commit | 224da21ea258450fcc78dd7635de84aba1d1df5e (patch) | |
tree | dc4df492779986aff60ed785f4821daae968d023 /src/gui | |
parent | d7a5438d3c7b140c0966243bae98ff447385d246 (diff) | |
parent | ed60c53eb2fe5ef377fc726df796d0aaf2005c6c (diff) | |
download | mana-client-224da21ea258450fcc78dd7635de84aba1d1df5e.tar.gz mana-client-224da21ea258450fcc78dd7635de84aba1d1df5e.tar.bz2 mana-client-224da21ea258450fcc78dd7635de84aba1d1df5e.tar.xz mana-client-224da21ea258450fcc78dd7635de84aba1d1df5e.zip |
Merge branch 'master' of git://gitorious.org/tmw/eathena
Diffstat (limited to 'src/gui')
61 files changed, 2231 insertions, 1191 deletions
diff --git a/src/gui/box.cpp b/src/gui/box.cpp deleted file mode 100644 index 59d8c135..00000000 --- a/src/gui/box.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 "box.h" - -Box::Box(): - padding(0) -{ - setOpaque(false); -} - -Box::~Box() -{ -} - -unsigned int Box::getPadding() -{ - return padding; -} - -void Box::setPadding(unsigned int p) -{ - padding = p; -} diff --git a/src/gui/box.h b/src/gui/box.h deleted file mode 100644 index 46654b48..00000000 --- a/src/gui/box.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 BOX_H -#define BOX_H - -#include <guichan/widgets/container.hpp> - -#include "../guichanfwd.h" - -class Box : public gcn::Container -{ - public: - /** - * Returns padding. - */ - unsigned int getPadding(); - - /** - * Sets padding between widgets. - */ - void setPadding(unsigned int); - - protected: - Box(); - virtual ~Box(); - - /** - * Spacing between client widgets. - */ - unsigned int padding; - - virtual void draw(gcn::Graphics *) = 0; - - typedef std::list<gcn::Widget*> Widgets; - typedef Widgets::iterator WidgetIterator; -}; - -#endif diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp index 3e446928..03540d31 100644 --- a/src/gui/browserbox.cpp +++ b/src/gui/browserbox.cpp @@ -21,11 +21,8 @@ #include <algorithm> -#include <guichan/graphics.hpp> -#include <guichan/imagefont.hpp> -#include <guichan/mouseinput.hpp> - #include "browserbox.h" + #include "linkhandler.h" #include "truetypefont.h" @@ -143,7 +140,7 @@ void BrowserBox::addRow(const std::string &row) if (mMode == AUTO_WRAP) { - unsigned int j, y = 0; + unsigned int y = 0; unsigned int nextChar; const char *hyphen = "~"; int hyphenWidth = font->getWidth(hyphen); @@ -152,7 +149,7 @@ void BrowserBox::addRow(const std::string &row) for (TextRowIterator i = mTextRows.begin(); i != mTextRows.end(); i++) { std::string row = *i; - for (j = 0; j < row.size(); j++) + for (unsigned int j = 0; j < row.size(); j++) { std::string character = row.substr(j, 1); x += font->getWidth(character); @@ -266,7 +263,6 @@ BrowserBox::draw(gcn::Graphics *graphics) } } - unsigned int j; int x = 0, y = 0; int wrappedLines = 0; TrueTypeFont *font = static_cast<TrueTypeFont*>(getFont()); @@ -277,17 +273,45 @@ BrowserBox::draw(gcn::Graphics *graphics) int selColor = BLACK; int prevColor = selColor; std::string row = *(i); + bool wrapped = false; x = 0; - for (j = 0; j < row.size(); j++) + // Check for separator lines + if (row.find("---", 0) == 0) + { + for (x = 0; x < getWidth(); x++) + { + font->drawString(graphics, "-", x, y); + x += font->getWidth("-") - 2; + } + y += font->getHeight(); + continue; + } + + // TODO: Check if we must take texture size limits into account here + // TODO: Check if some of the O(n) calls can be removed + for (std::string::size_type start = 0, end = std::string::npos; + start != std::string::npos; + start = end, end = std::string::npos) { - if ( (mUseLinksAndUserColors && (j + 3) <= row.size()) || - (!mUseLinksAndUserColors && (j == 0)) ) + // Wrapped line continuation shall be indented + if (wrapped) + { + y += font->getHeight(); + x = 15; + } + + // "Tokenize" the string at control sequences + if (mUseLinksAndUserColors) + end = row.find("##", start + 1); + + if (mUseLinksAndUserColors || + (!mUseLinksAndUserColors && (start == 0))) { // Check for color change in format "##x", x = [L,P,0..9] - if ((row.at(j) == '#') && (row.at(j + 1) == '#')) + if (row.find("##", start) == start && row.size() > start + 2) { - switch (row.at(j + 2)) + switch (row.at(start + 2)) { case 'L': // Link color prevColor = selColor; @@ -337,72 +361,64 @@ BrowserBox::draw(gcn::Graphics *graphics) prevColor = selColor; selColor = BLACK; } - j += 3; - - if (j == row.size()) - { - break; - } + start += 3; } graphics->setColor(gcn::Color(selColor)); } - // Check for line separators in format "---" - if (row == "---") - { - for (x = 0; x < getWidth(); x++) - { - font->drawString(graphics, "-", x, y); - x += font->getWidth("-") - 2; - } - break; - } - // Draw each char - else - { - std::string character = row.substr(j, 1); - font->drawString(graphics, character, x, y); - x += font->getWidth(character.c_str()); + std::string::size_type len = + end == std::string::npos ? end : end - start; + std::string part = row.substr(start, len); - // Auto wrap mode - if (mMode == AUTO_WRAP) + // Auto wrap mode + if (mMode == AUTO_WRAP && + (x + font->getWidth(part.c_str()) + 10) > getWidth()) + { + bool forced = false; + char const *hyphen = "~"; + int hyphenWidth = font->getWidth(hyphen); + + /* FIXME: This code layout makes it easy to crash remote + clients by talking garbage. Forged long utf-8 characters + will cause either a buffer underflow in substr or an + infinite loop in the main loop. */ + do { - unsigned int nextChar = j + 1; - const char *hyphen = "~"; - int hyphenWidth = font->getWidth(hyphen); + if (!forced) + end = row.rfind(" ", end); - // Wraping between words (at blank spaces) - if ((nextChar < row.size()) && (row.at(nextChar) == ' ')) + // Check if we have to (stupidly) force-wrap + if (end == std::string::npos || end <= start) { - int nextSpacePos = row.find(" ", (nextChar + 1)); - if (nextSpacePos <= 0) - { - nextSpacePos = row.size() - 1; - } - int nextWordWidth = font->getWidth( - row.substr(nextChar, - (nextSpacePos - nextChar))); - - if ((x + nextWordWidth + 10) > getWidth()) - { - x = 15; // Ident in new line - y += font->getHeight(); - wrappedLines++; - j++; - } + forced = true; + end = row.size(); + x += hyphenWidth * 2; // Account for the wrap-notifier + continue; } - // Wrapping looong lines (brutal force) - else if ((x + 2 * hyphenWidth) > getWidth()) - { - font->drawString(graphics, hyphen, - getWidth() - hyphenWidth, y); - x = 15; // Ident in new line - y += font->getHeight(); - wrappedLines++; - } + // Skip to the start of the current character + while ((row[end] & 192) == 128) + end--; + end--; // And then to the last byte of the previous one + + part = row.substr(start, end - start + 1); + } while ((x + font->getWidth(part.c_str()) + 10) > getWidth()); + + if (forced) + { + x -= hyphenWidth; // Remove the wrap-notifier accounting + font->drawString(graphics, hyphen, + getWidth() - hyphenWidth, y); + end++; // Skip to the next character } + else + end += 2; // Skip to after the space + + wrapped = true; + wrappedLines++; } + font->drawString(graphics, part, x, y); + x += font->getWidth(part.c_str()); } y += font->getHeight(); setHeight((mTextRows.size() + wrappedLines) * font->getHeight()); diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h index 465ff497..cb4c23ed 100644 --- a/src/gui/browserbox.h +++ b/src/gui/browserbox.h @@ -25,8 +25,8 @@ #include <iosfwd> #include <vector> -#include <guichan/widget.hpp> #include <guichan/mouselistener.hpp> +#include <guichan/widget.hpp> #include "../guichanfwd.h" #include "../main.h" diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp index 714f52db..4d028ab3 100644 --- a/src/gui/buy.cpp +++ b/src/gui/buy.cpp @@ -29,15 +29,18 @@ #include "shoplistbox.h" #include "slider.h" +#include "widgets/layout.h" + #include "../npc.h" #include "../net/messageout.h" #include "../net/protocol.h" -#include "../utils/tostring.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" BuyDialog::BuyDialog(Network *network): - Window("Buy"), mNetwork(network), + Window(_("Buy")), mNetwork(network), mMoney(0), mAmountItems(0), mMaxItems(0) { setWindowName("Buy"); @@ -52,17 +55,16 @@ BuyDialog::BuyDialog(Network *network): mScrollArea = new ScrollArea(mShopItemList); mSlider = new Slider(1.0); mQuantityLabel = new gcn::Label("0"); - mMoneyLabel = new gcn::Label("Price : 0 GP / 0 GP"); + mMoneyLabel = new gcn::Label(strprintf(_("Price: %d GP / Total: %d GP"), 0, 0)); mIncreaseButton = new Button("+", "+", this); mDecreaseButton = new Button("-", "-", this); - mBuyButton = new Button("Buy", "buy", this); - mQuitButton = new Button("Quit", "quit", this); - mItemDescLabel = new gcn::Label("Description:"); - mItemEffectLabel = new gcn::Label("Effect:"); + mBuyButton = new Button(_("Buy"), "buy", this); + mQuitButton = new Button(_("Quit"), "quit", this); + mItemDescLabel = new gcn::Label(strprintf(_("Description: %s"), "")); + mItemEffectLabel = new gcn::Label(strprintf(_("Effect: %s"), "")); mIncreaseButton->setSize(20, 20); mDecreaseButton->setSize(20, 20); - mQuantityLabel->setWidth(60); mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mIncreaseButton->setEnabled(false); @@ -70,22 +72,22 @@ BuyDialog::BuyDialog(Network *network): mBuyButton->setEnabled(false); mSlider->setEnabled(false); - mShopItemList->setActionEventId("item"); mSlider->setActionEventId("slider"); - - mShopItemList->addSelectionListener(this); mSlider->addActionListener(this); + mShopItemList->addSelectionListener(this); - add(mScrollArea); - add(mSlider); - add(mQuantityLabel); - add(mBuyButton); - add(mQuitButton); - add(mIncreaseButton); - add(mDecreaseButton); - add(mMoneyLabel); - add(mItemDescLabel); - add(mItemEffectLabel); + place(0, 0, mScrollArea, 5).setPadding(3); + place(0, 1, mQuantityLabel, 2); + place(2, 1, mSlider, 3); + place(0, 2, mMoneyLabel, 5); + place(0, 3, mItemEffectLabel, 5); + place(0, 4, mItemDescLabel, 5); + place(0, 5, mDecreaseButton); + place(1, 5, mIncreaseButton); + place(3, 5, mBuyButton); + place(4, 5, mQuitButton); + Layout &layout = getLayout(); + layout.setRowHeight(0, Layout::AUTO_SET); loadWindowState(); setLocationRelativeTo(getParent()); @@ -159,7 +161,7 @@ void BuyDialog::action(const gcn::ActionEvent &event) } // TODO: Actually we'd have a bug elsewhere if this check for the number // of items to be bought ever fails, Bertram removed the assertions, is - // there a better way to ensure this fails in an _obivous_ way in C++? + // there a better way to ensure this fails in an _obvious_ way in C++? else if (event.getId() == "buy" && mAmountItems > 0 && mAmountItems <= mMaxItems) { @@ -191,53 +193,7 @@ void BuyDialog::valueChanged(const gcn::SelectionEvent &event) mSlider->gcn::Slider::setScale(1, mMaxItems); } -void BuyDialog::widgetResized(const gcn::Event &event) -{ - Window::widgetResized(event); - - const gcn::Rectangle &area = getChildrenArea(); - const int width = area.width; - const int height = area.height; - - mDecreaseButton->setPosition(8, height - 8 - mDecreaseButton->getHeight()); - mIncreaseButton->setPosition( - mDecreaseButton->getX() + mDecreaseButton->getWidth() + 5, - mDecreaseButton->getY()); - - mQuitButton->setPosition( - width - 8 - mQuitButton->getWidth(), - height - 8 - mQuitButton->getHeight()); - mBuyButton->setPosition( - mQuitButton->getX() - 5 - mBuyButton->getWidth(), - mQuitButton->getY()); - - mItemDescLabel->setDimension(gcn::Rectangle(8, - mBuyButton->getY() - 5 - mItemDescLabel->getHeight(), - width - 16, - mItemDescLabel->getHeight())); - mItemEffectLabel->setDimension(gcn::Rectangle(8, - mItemDescLabel->getY() - 5 - mItemEffectLabel->getHeight(), - width - 16, - mItemEffectLabel->getHeight())); - mMoneyLabel->setDimension(gcn::Rectangle(8, - mItemEffectLabel->getY() - 5 - mMoneyLabel->getHeight(), - width - 16, - mMoneyLabel->getHeight())); - - mQuantityLabel->setPosition( - width - mQuantityLabel->getWidth() - 8, - mMoneyLabel->getY() - 5 - mQuantityLabel->getHeight()); - mSlider->setDimension(gcn::Rectangle(8, - mQuantityLabel->getY(), - mQuantityLabel->getX() - 8 - 8, - 10)); - - mScrollArea->setDimension(gcn::Rectangle(8, 8, width - 16, - mSlider->getY() - 5 - 8)); -} - -void -BuyDialog::updateButtonsAndLabels() +void BuyDialog::updateButtonsAndLabels() { const int selectedItem = mShopItemList->getSelected(); int price = 0; @@ -246,8 +202,10 @@ BuyDialog::updateButtonsAndLabels() { const ItemInfo &info = mShopItems->at(selectedItem)->getInfo(); - mItemDescLabel->setCaption("Description: " + info.getDescription()); - mItemEffectLabel->setCaption("Effect: " + info.getEffect()); + mItemDescLabel->setCaption + (strprintf(_("Description: %s"), info.getDescription().c_str())); + mItemEffectLabel->setCaption + (strprintf(_("Effect: %s"), info.getEffect().c_str())); int itemPrice = mShopItems->at(selectedItem)->getPrice(); @@ -263,8 +221,8 @@ BuyDialog::updateButtonsAndLabels() } else { - mItemDescLabel->setCaption("Description:"); - mItemEffectLabel->setCaption("Effect:"); + mItemDescLabel->setCaption(strprintf(_("Description: %s"), "")); + mItemEffectLabel->setCaption(strprintf(_("Effect: %s"), "")); mMaxItems = 0; mAmountItems = 0; } @@ -276,8 +234,7 @@ BuyDialog::updateButtonsAndLabels() mSlider->setEnabled(mMaxItems > 1); // Update quantity and money labels - mQuantityLabel->setCaption( - toString(mAmountItems) + " / " + toString(mMaxItems)); - mMoneyLabel->setCaption("Price: " + toString(price) + " GP / " - + toString(mMoney - price) + " GP" ); + mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems)); + mMoneyLabel->setCaption + (strprintf(_("Price: %d GP / Total: %d GP"), price, mMoney - price)); } diff --git a/src/gui/buy.h b/src/gui/buy.h index 0915385a..329d35ec 100644 --- a/src/gui/buy.h +++ b/src/gui/buy.h @@ -93,13 +93,7 @@ class BuyDialog : public Window, public gcn::ActionListener, /** * Updates the state of buttons and labels. */ - void - updateButtonsAndLabels(); - - /** - * Called whenever the widget changes size. - */ - void widgetResized(const gcn::Event &event); + void updateButtonsAndLabels(); private: Network *mNetwork; diff --git a/src/gui/buysell.cpp b/src/gui/buysell.cpp index 42380882..a8223ca4 100644 --- a/src/gui/buysell.cpp +++ b/src/gui/buysell.cpp @@ -25,18 +25,20 @@ #include "../npc.h" +#include "../utils/gettext.h" + BuySellDialog::BuySellDialog(): - Window("Shop") + Window(_("Shop")) { Button *buyButton = 0; - const char *buttonNames[] = { - "Buy", "Sell", "Cancel", 0 + static const char *buttonNames[] = { + N_("Buy"), N_("Sell"), N_("Cancel"), 0 }; int x = 10, y = 10; for (const char **curBtn = buttonNames; *curBtn; curBtn++) { - Button *btn = new Button(*curBtn, *curBtn, this); + Button *btn = new Button(gettext(*curBtn), *curBtn, this); if (!buyButton) buyButton = btn; // For focus request btn->setPosition(x, y); add(btn); diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp index d951f12e..643a598f 100644 --- a/src/gui/char_select.cpp +++ b/src/gui/char_select.cpp @@ -31,6 +31,8 @@ #include "playerbox.h" #include "textfield.h" +#include "widgets/layout.h" + #include "../game.h" #include "../localplayer.h" #include "../main.h" @@ -38,7 +40,8 @@ #include "../net/charserverhandler.h" #include "../net/messageout.h" -#include "../utils/tostring.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" #include "../utils/trim.h" // Defined in main.cpp, used here for setting the char create dialog @@ -57,8 +60,8 @@ class CharDeleteConfirm : public ConfirmDialog }; CharDeleteConfirm::CharDeleteConfirm(CharSelectDialog *m): - ConfirmDialog("Confirm", "Are you sure you want to delete this character?", - m), + ConfirmDialog(_("Confirm Character Delete"), + _("Are you sure you want to delete this character?"), m), master(m) { } @@ -74,55 +77,42 @@ void CharDeleteConfirm::action(const gcn::ActionEvent &event) CharSelectDialog::CharSelectDialog(Network *network, LockedArray<LocalPlayer*> *charInfo, - unsigned char gender): - Window("Select Character"), mNetwork(network), + Gender gender): + 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); - - mNameLabel = new gcn::Label("Name"); - mLevelLabel = new gcn::Label("Level"); - mJobLevelLabel = new gcn::Label("Job Level"); - mMoneyLabel = new gcn::Label("Money"); - mPlayerBox = new PlayerBox(); - - int w = 195; - int h = 220; - setContentSize(w, h); - mPlayerBox->setDimension(gcn::Rectangle(5, 5, w - 10, 90)); - mNameLabel->setDimension(gcn::Rectangle(10, 100, 128, 16)); - mLevelLabel->setDimension(gcn::Rectangle(10, 116, 128, 16)); - mJobLevelLabel->setDimension(gcn::Rectangle(10, 132, 128, 16)); - mMoneyLabel->setDimension(gcn::Rectangle(10, 148, 128, 16)); - mPreviousButton->setPosition(5, 170); - mNextButton->setPosition(mPreviousButton->getWidth() + 10, 170); - mNewCharButton->setPosition(5, h - 5 - mNewCharButton->getHeight()); - mDelCharButton->setPosition( - 5 + mNewCharButton->getWidth() + 5, - mNewCharButton->getY()); - mCancelButton->setPosition( - w - 5 - mCancelButton->getWidth(), - mNewCharButton->getY()); - mSelectButton->setPosition( - mCancelButton->getX() - 5 - mSelectButton->getWidth(), - mNewCharButton->getY()); - - add(mPlayerBox); - add(mSelectButton); - add(mCancelButton); - add(mNewCharButton); - add(mDelCharButton); - add(mPreviousButton); - add(mNextButton); - add(mNameLabel); - add(mLevelLabel); - add(mJobLevelLabel); - add(mMoneyLabel); + 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); + + 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); + + 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 = getPlacer(0, 2); + place(0, 0, mSelectButton); + place(1, 0, mCancelButton); + reflowLayout(265, 0); setLocationRelativeTo(getParent()); setVisible(true); @@ -178,10 +168,10 @@ void CharSelectDialog::updatePlayerInfo() if (pi) { - mNameLabel->setCaption(pi->getName()); - mLevelLabel->setCaption("Lvl: " + toString(pi->mLevel)); - mJobLevelLabel->setCaption("Job Lvl: " + toString(pi->mJobLevel)); - mMoneyLabel->setCaption("Gold: " + toString(pi->mGp)); + mNameLabel->setCaption(strprintf(_("Name: %s"), pi->getName().c_str())); + mLevelLabel->setCaption(strprintf(_("Level: %d"), pi->mLevel)); + mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), pi->mJobLevel)); + mMoneyLabel->setCaption(strprintf(_("Gold: %d"), pi->mGp)); if (!mCharSelected) { mNewCharButton->setEnabled(false); @@ -190,10 +180,10 @@ void CharSelectDialog::updatePlayerInfo() } } else { - mNameLabel->setCaption("Name"); - mLevelLabel->setCaption("Level"); - mJobLevelLabel->setCaption("Job Level"); - mMoneyLabel->setCaption("Money"); + 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); mSelectButton->setEnabled(false); @@ -249,23 +239,23 @@ bool CharSelectDialog::selectByName(const std::string &name) } CharCreateDialog::CharCreateDialog(Window *parent, int slot, Network *network, - unsigned char gender): - Window("Create Character", true, parent), mNetwork(network), mSlot(slot) + Gender gender): + Window(_("Create Character"), true, parent), mNetwork(network), mSlot(slot) { mPlayer = new Player(0, 0, NULL); mPlayer->setGender(gender); mPlayer->setHairStyle(rand() % Being::getHairStylesNr(), rand() % Being::getHairColorsNr()); mNameField = new TextField(""); - mNameLabel = new gcn::Label("Name:"); + mNameLabel = new gcn::Label(_("Name:")); mNextHairColorButton = new Button(">", "nextcolor", this); mPrevHairColorButton = new Button("<", "prevcolor", this); - mHairColorLabel = new gcn::Label("Hair Color:"); + mHairColorLabel = new gcn::Label(_("Hair Color:")); mNextHairStyleButton = new Button(">", "nextstyle", this); mPrevHairStyleButton = new Button("<", "prevstyle", this); - mHairStyleLabel = new gcn::Label("Hair Style:"); - mCreateButton = new Button("Create", "create", this); - mCancelButton = new Button("Cancel", "cancel", this); + mHairStyleLabel = new gcn::Label(_("Hair Style:")); + mCreateButton = new Button(_("Create"), "create", this); + mCancelButton = new Button(_("Cancel"), "cancel", this); mPlayerBox = new PlayerBox(mPlayer); mNameField->setActionEventId("create"); diff --git a/src/gui/char_select.h b/src/gui/char_select.h index 0890bea9..22c247b6 100644 --- a/src/gui/char_select.h +++ b/src/gui/char_select.h @@ -26,6 +26,7 @@ #include "../guichanfwd.h" #include "../lockedarray.h" +#include "../being.h" #include <guichan/actionlistener.hpp> @@ -48,7 +49,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener */ CharSelectDialog(Network *network, LockedArray<LocalPlayer*> *charInfo, - unsigned char gender); + Gender gender); void action(const gcn::ActionEvent &event); @@ -76,7 +77,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener PlayerBox *mPlayerBox; - unsigned char mGender; + Gender mGender; bool mCharSelected; /** @@ -102,7 +103,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener * Constructor. */ CharCreateDialog(Window *parent, int slot, Network *network, - unsigned char gender); + Gender gender); /** * Destructor. diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp index ce068ad1..3d3309fb 100644 --- a/src/gui/char_server.cpp +++ b/src/gui/char_server.cpp @@ -31,6 +31,8 @@ #include "../net/network.h" // TODO this is just for iptostring, move that? +#include "../utils/gettext.h" +#include "../utils/strprintf.h" #include "../utils/tostring.h" extern SERVER_INFO **server_info; @@ -47,15 +49,15 @@ class ServerListModel : public gcn::ListModel { }; ServerSelectDialog::ServerSelectDialog(LoginData *loginData, int nextState): - Window("Select Server"), + Window(_("Select Server")), mLoginData(loginData), mNextState(nextState) { mServerListModel = new ServerListModel(); mServerList = new ListBox(mServerListModel); ScrollArea *mScrollArea = new ScrollArea(mServerList); - mOkButton = new Button("OK", "ok", this); - Button *mCancelButton = new Button("Cancel", "cancel", this); + mOkButton = new Button(_("OK"), "ok", this); + Button *mCancelButton = new Button(_("Cancel"), "cancel", this); setContentSize(200, 100); diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index edde42d0..d61ec021 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -23,13 +23,13 @@ #include <sstream> #include <guichan/focushandler.hpp> -#include <guichan/key.hpp> #include "chat.h" #include "browserbox.h" #include "chatinput.h" #include "scrollarea.h" +#include "sdlinput.h" #include "windowcontainer.h" #include "../configuration.h" @@ -39,6 +39,8 @@ #include "../net/messageout.h" #include "../net/protocol.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" #include "../utils/trim.h" ChatWindow::ChatWindow(Network *network): @@ -91,8 +93,7 @@ void ChatWindow::widgetResized(const gcn::Event &event) mChatInput->getHeight() - 5); } -void -ChatWindow::chatLog(std::string line, int own) +void ChatWindow::chatLog(std::string line, int own) { // Trim whitespace trim(line); @@ -117,11 +118,14 @@ ChatWindow::chatLog(std::string line, int own) std::string lineColor = "##0"; // Equiv. to BrowserBox::BLACK switch (own) { case BY_GM: - if (tmp.nick.empty()) - tmp.nick = std::string("Global announcement: "); - else - tmp.nick = std::string("Global announcement from " + tmp.nick - + std::string(": ")); + if (tmp.nick.empty()) { + tmp.nick = _("Global announcement:"); + tmp.nick += " "; + } else { + tmp.nick = strprintf(_("Global announcement from %s:"), + tmp.nick.c_str()); + tmp.nick += " "; + } lineColor = "##1"; // Equiv. to BrowserBox::RED break; case BY_PLAYER: @@ -133,12 +137,14 @@ ChatWindow::chatLog(std::string line, int own) lineColor = "##0"; // Equiv. to BrowserBox::BLACK break; case BY_SERVER: - tmp.nick = "Server: "; + tmp.nick = _("Server:"); + tmp.nick += " "; tmp.text = line; lineColor = "##7"; // Equiv. to BrowserBox::PINK break; case ACT_WHISPER: - tmp.nick += CAT_WHISPER; + tmp.nick = strprintf(_("%s whispers:"), tmp.nick.c_str()); + tmp.nick += " "; lineColor = "##3"; // Equiv. to BrowserBox::BLUE break; case ACT_IS: @@ -182,14 +188,12 @@ ChatWindow::chatLog(std::string line, int own) } } -void -ChatWindow::chatLog(CHATSKILL act) +void ChatWindow::chatLog(CHATSKILL act) { chatLog(const_msg(act), BY_SERVER); } -void -ChatWindow::action(const gcn::ActionEvent &event) +void ChatWindow::action(const gcn::ActionEvent &event) { if (event.getId() == "chatinput") { @@ -222,8 +226,7 @@ ChatWindow::action(const gcn::ActionEvent &event) } } -void -ChatWindow::requestChatFocus() +void ChatWindow::requestChatFocus() { // Make sure chatWindow is visible if (!isVisible()) @@ -243,19 +246,18 @@ ChatWindow::requestChatFocus() mChatInput->requestFocus(); } -bool -ChatWindow::isInputFocused() +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, + int prefixlen) { std::string recvnick = ""; msg.erase(0, prefixlen + 1); - if (msg.substr(0,1) == "\"") + if (msg.substr(0, 1) == "\"") { const std::string::size_type pos = msg.find('"', 1); if (pos != std::string::npos) { @@ -278,11 +280,12 @@ ChatWindow::whisper(const std::string &nick, std::string msg, int prefixlen) outMsg.writeString(recvnick, 24); outMsg.writeString(msg, msg.length()); - chatLog("Whispering to " + recvnick + " : " + msg, BY_PLAYER); + chatLog(strprintf(_("Whispering to %s: %s"), + recvnick.c_str(), msg.c_str()), + BY_PLAYER); } -void -ChatWindow::chatSend(const std::string &nick, std::string msg) +void ChatWindow::chatSend(const std::string &nick, std::string msg) { /* Some messages are managed client side, while others * require server handling by proper packet. Probably @@ -350,81 +353,82 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) whisper(nick, msg, IS_SHORT_WHISPER_LENGTH); else { - chatLog("Unknown command", BY_SERVER); + chatLog(_("Unknown command"), BY_SERVER); } } -std::string -ChatWindow::const_msg(CHATSKILL act) +std::string ChatWindow::const_msg(CHATSKILL act) { std::string msg; if (act.success == SKILL_FAILED && act.skill == SKILL_BASIC) { switch (act.bskill) { - case BSKILL_TRADE : - msg = "Trade failed!"; + case BSKILL_TRADE: + msg = _("Trade failed!"); break; - case BSKILL_EMOTE : - msg = "Emote failed!"; + case BSKILL_EMOTE: + msg = _("Emote failed!"); break; - case BSKILL_SIT : - msg = "Sit failed!"; + case BSKILL_SIT: + msg = _("Sit failed!"); break; - case BSKILL_CREATECHAT : - msg = "Chat creating failed!"; + case BSKILL_CREATECHAT: + msg = _("Chat creating failed!"); break; - case BSKILL_JOINPARTY : - msg = "Could not join party!"; + case BSKILL_JOINPARTY: + msg = _("Could not join party!"); break; - case BSKILL_SHOUT : - msg = "Cannot shout!"; + case BSKILL_SHOUT: + msg = _("Cannot shout!"); break; } + msg += " "; + switch (act.reason) { - case RFAIL_SKILLDEP : - msg += " You have not yet reached a high enough lvl!"; + case RFAIL_SKILLDEP: + msg += _("You have not yet reached a high enough lvl!"); break; - case RFAIL_INSUFHP : - msg += " Insufficient HP!"; + case RFAIL_INSUFHP: + msg += _("Insufficient HP!"); break; - case RFAIL_INSUFSP : - msg += " Insufficient SP!"; + case RFAIL_INSUFSP: + msg += _("Insufficient SP!"); break; - case RFAIL_NOMEMO : - msg += " You have no memos!"; + case RFAIL_NOMEMO: + msg += _("You have no memos!"); break; - case RFAIL_SKILLDELAY : - msg += " You cannot do that right now!"; + case RFAIL_SKILLDELAY: + msg += _("You cannot do that right now!"); break; - case RFAIL_ZENY : - msg += " Seems you need more Zeny... ;-)"; + case RFAIL_ZENY: + msg += _("Seems you need more Zeny... ;-)"); break; - case RFAIL_WEAPON : - msg += " You cannot use this skill with that kind of weapon!"; + case RFAIL_WEAPON: + msg += _("You cannot use this skill with that kind of weapon!"); break; - case RFAIL_REDGEM : - msg += " You need another red gem!"; + case RFAIL_REDGEM: + msg += _("You need another red gem!"); break; - case RFAIL_BLUEGEM : - msg += " You need another blue gem!"; + case RFAIL_BLUEGEM: + msg += _("You need another blue gem!"); break; - case RFAIL_OVERWEIGHT : - msg += " You're carrying to much to do this!"; + case RFAIL_OVERWEIGHT: + msg += _("You're carrying to much to do this!"); break; - default : - msg += " Huh? What's that?"; + default: + msg += _("Huh? What's that?"); break; } } else { - switch(act.skill) { + switch (act.skill) { case SKILL_WARP : - msg = "Warp failed..."; + msg = _("Warp failed..."); break; case SKILL_STEAL : - msg = "Could not steal anything..."; + msg = _("Could not steal anything..."); break; case SKILL_ENVENOM : - msg = "Poison had no effect..."; + msg = _("Poison had no effect..."); break; } } @@ -432,8 +436,7 @@ ChatWindow::const_msg(CHATSKILL act) return msg; } -void -ChatWindow::scroll(int amount) +void ChatWindow::scroll(int amount) { if (!isVisible()) return; @@ -445,10 +448,9 @@ ChatWindow::scroll(int amount) mTextOutput->showPart(scr); } -void -ChatWindow::keyPressed(gcn::KeyEvent &event) +void ChatWindow::keyPressed(gcn::KeyEvent &event) { - if (event.getKey().getValue() == gcn::Key::DOWN && + if (event.getKey().getValue() == Key::DOWN && mCurHist != mHistory.end()) { // Move forward through the history @@ -461,7 +463,7 @@ ChatWindow::keyPressed(gcn::KeyEvent &event) mCurHist = prevHist; } } - else if (event.getKey().getValue() == gcn::Key::UP && + else if (event.getKey().getValue() == Key::UP && mCurHist != mHistory.begin() && mHistory.size() > 0) { // Move backward through the history @@ -471,15 +473,13 @@ ChatWindow::keyPressed(gcn::KeyEvent &event) } } -void -ChatWindow::setInputText(std::string input_str) +void ChatWindow::setInputText(std::string input_str) { mChatInput->setText(input_str + " "); requestChatFocus(); } -void -ChatWindow::setVisible(bool isVisible) +void ChatWindow::setVisible(bool isVisible) { Window::setVisible(isVisible); @@ -493,67 +493,68 @@ ChatWindow::setVisible(bool isVisible) void ChatWindow::help(const std::string &msg1, const std::string &msg2) { - chatLog("-- Help --", BY_SERVER); + chatLog(_("-- Help --"), BY_SERVER); if (msg1 == "") { - chatLog("/announce: Global announcement (GM only)", BY_SERVER); - chatLog("/clear: Clears this window", BY_SERVER); - chatLog("/help: Display this help.", BY_SERVER); - chatLog("/where: Display map name", 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); + chatLog(_("/announce: Global announcement (GM only)"), BY_SERVER); + chatLog(_("/clear: Clears this window"), BY_SERVER); + chatLog(_("/help: Display this help"), BY_SERVER); + chatLog(_("/where: Display map name"), 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") { - 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); + 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") { - chatLog("Command: /clear", BY_SERVER); - chatLog("This command clears the chat log of previous chat.", + chatLog(_("Command: /clear"), BY_SERVER); + chatLog(_("This command clears the chat log of previous chat."), BY_SERVER); return; } if (msg1 == "help") { - chatLog("Command: /help", BY_SERVER); - chatLog("This command displays a list of all commands available.", + 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); + chatLog(_("Command: /help <command>"), BY_SERVER); + chatLog(_("This command displays help on <command>."), BY_SERVER); return; } if (msg1 == "where") { - chatLog("Command: /where", BY_SERVER); - chatLog("This command displays the name of the current map.", + chatLog(_("Command: /where"), BY_SERVER); + chatLog(_("This command displays the name of the current map."), BY_SERVER); return; } if (msg1 == "whisper" || msg1 == "w") { - 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); + 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; } if (msg1 == "who") { - chatLog("Command: /who", BY_SERVER); - chatLog("This command displays the number of players currently " - "online.", BY_SERVER); + chatLog(_("Command: /who"), BY_SERVER); + chatLog(_("This command displays the number of players currently " + "online."), BY_SERVER); return; } - 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 09c3712b..dc0d002d 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -183,20 +183,16 @@ class ChatWindow : public Window, public gcn::ActionListener, * // for simple message by a user /- message * chatlog.chat_send("Zaeiru", "Hello to all users on the screen!"); */ - void - chatSend(const std::string &nick, std::string msg); + void chatSend(const std::string &nick, std::string msg); /** Called when key is pressed */ - void - keyPressed(gcn::KeyEvent &event); + void keyPressed(gcn::KeyEvent &event); /** Called to set current text */ - void - setInputText(std::string input_str); + void setInputText(std::string input_str); /** Override to reset mTmpVisible */ - void - setVisible(bool visible); + void setVisible(bool visible); /** * Scrolls the chat window @@ -205,8 +201,7 @@ class ChatWindow : public Window, public gcn::ActionListener, * up, positive numbers scroll down. The absolute amount indicates the * amount of 1/8ths of chat window real estate that should be scrolled. */ - void - scroll(int amount); + void scroll(int amount); /** * help implements the /help command @@ -214,15 +209,13 @@ class ChatWindow : public Window, public gcn::ActionListener, * @param msg1 is the command that the player needs help on * @param msg2 is the sub-command relating to the command */ - void - help(const std::string &msg1, const std::string &msg2); + 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, int prefixlen); /** One item in the chat log */ struct CHATLOG diff --git a/src/gui/confirm_dialog.cpp b/src/gui/confirm_dialog.cpp index 9ef94f62..5f2b9cb2 100644 --- a/src/gui/confirm_dialog.cpp +++ b/src/gui/confirm_dialog.cpp @@ -25,14 +25,15 @@ #include "button.h" +#include "../utils/gettext.h" ConfirmDialog::ConfirmDialog(const std::string &title, const std::string &msg, Window *parent): Window(title, true, parent) { gcn::Label *textLabel = new gcn::Label(msg); - gcn::Button *yesButton = new Button("Yes", "yes", this); - gcn::Button *noButton = new Button("No", "no", this); + gcn::Button *yesButton = new Button(_("Yes"), "yes", this); + gcn::Button *noButton = new Button(_("No"), "no", this); int w = textLabel->getWidth() + 20; int inWidth = yesButton->getWidth() + noButton->getWidth() + 5; diff --git a/src/gui/connection.cpp b/src/gui/connection.cpp index 8ad3b436..0f43ff14 100644 --- a/src/gui/connection.cpp +++ b/src/gui/connection.cpp @@ -30,6 +30,8 @@ #include "../main.h" +#include "../utils/gettext.h" + namespace { struct ConnectionActionListener : public gcn::ActionListener { @@ -42,9 +44,9 @@ ConnectionDialog::ConnectionDialog(): { setContentSize(200, 100); - Button *cancelButton = new Button("Cancel", "cancelButton", &listener); + Button *cancelButton = new Button(_("Cancel"), "cancelButton", &listener); mProgressBar = new ProgressBar(0.0, 200 - 10, 20, 128, 128, 128); - gcn::Label *label = new gcn::Label("Connecting..."); + gcn::Label *label = new gcn::Label(_("Connecting...")); cancelButton->setPosition(5, 100 - 5 - cancelButton->getHeight()); mProgressBar->setPosition(5, cancelButton->getY() - 25); diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index 762ca8e8..f3a143be 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -31,10 +31,12 @@ #include "../resources/iteminfo.h" #include "../resources/resourcemanager.h" +#include "../utils/gettext.h" #include "../utils/tostring.h" EquipmentWindow::EquipmentWindow(Equipment *equipment): - Window("Equipment"), mEquipment(equipment) + Window(_("Equipment")), + mEquipment(equipment) { setWindowName("Equipment"); setCloseButton(true); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a65cb0fb..87bab0ea 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -24,12 +24,9 @@ #include <guichan/exception.hpp> #include <guichan/image.hpp> #include <guichan/imagefont.hpp> -#include <SDL/SDL_ttf.h> - -// Should stay here because of Guichan being sensitive to headers order -#include <guichan/sdl/sdlinput.hpp> #include "focushandler.h" +#include "sdlinput.h" #include "truetypefont.h" #include "viewport.h" #include "window.h" @@ -48,7 +45,7 @@ // Guichan stuff Gui *gui; Viewport *viewport; /**< Viewport on the map. */ -gcn::SDLInput *guiInput; /**< GUI input. */ +SDLInput *guiInput; // Fonts used in showing hits gcn::Font *hitRedFont; @@ -91,7 +88,7 @@ Gui::Gui(Graphics *graphics): gcn::Image::setImageLoader(&imageLoader); // Set input - guiInput = new gcn::SDLInput(); + guiInput = new SDLInput; setInput(guiInput); // Set focus handler @@ -106,9 +103,12 @@ Gui::Gui(Graphics *graphics): Window::setWindowContainer(guiTop); setTop(guiTop); - // Set global font (based on ISO-8859-15) + ResourceManager *resman = ResourceManager::getInstance(); + + // Set global font + std::string path = resman->getPath("fonts/dejavusans.ttf"); try { - mGuiFont = new TrueTypeFont("data/fonts/dejavusans.ttf", 12); + mGuiFont = new TrueTypeFont(path, 11); } catch (gcn::Exception e) { diff --git a/src/gui/gui.h b/src/gui/gui.h index 15d5d99c..7d390df9 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -29,6 +29,7 @@ class GuiConfigListener; class Graphics; class ImageSet; +class SDLInput; class Viewport; /** @@ -115,7 +116,7 @@ class Gui : public gcn::Gui extern Gui *gui; /**< The GUI system */ extern Viewport *viewport; /**< The viewport */ -extern gcn::SDLInput *guiInput; /**< GUI input */ +extern SDLInput *guiInput; /**< GUI input */ /** * Fonts used in showing hits diff --git a/src/gui/hbox.cpp b/src/gui/hbox.cpp deleted file mode 100644 index 020e85c6..00000000 --- a/src/gui/hbox.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 "hbox.h" - -void HBox::draw(gcn::Graphics *graphics) -{ - int widgetCount = mWidgets.size(); - int childHeight = getHeight(); - if (widgetCount == 0) - return; - int childWidth = getWidth() / widgetCount; - - int i = 0; - for (WidgetIterator w = mWidgets.begin(); w != mWidgets.end(); w++) { - (*w)->setPosition(childWidth * i - padding, 0); - (*w)->setSize(childWidth, childHeight); - i++; - } - gcn::Container::draw(graphics); -} diff --git a/src/gui/hbox.h b/src/gui/hbox.h deleted file mode 100644 index 4b241383..00000000 --- a/src/gui/hbox.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 HBOX_H -#define HBOX_H - -#include "box.h" - -class HBox : public Box -{ - public: - void draw(gcn::Graphics *); -}; - -#endif diff --git a/src/gui/help.cpp b/src/gui/help.cpp index 290679b9..a52119b8 100644 --- a/src/gui/help.cpp +++ b/src/gui/help.cpp @@ -27,8 +27,10 @@ #include "../resources/resourcemanager.h" +#include "../utils/gettext.h" + HelpWindow::HelpWindow(): - Window("Help") + Window(_("Help")) { setContentSize(455, 350); setWindowName("Help"); @@ -36,7 +38,7 @@ HelpWindow::HelpWindow(): mBrowserBox = new BrowserBox(); mBrowserBox->setOpaque(false); mScrollArea = new ScrollArea(mBrowserBox); - Button *okButton = new Button("Close", "close", this); + Button *okButton = new Button(_("Close"), "close", this); mScrollArea->setDimension(gcn::Rectangle( 5, 5, 445, 335 - okButton->getHeight())); diff --git a/src/gui/inttextbox.cpp b/src/gui/inttextbox.cpp index 4825fbf5..a995f084 100644 --- a/src/gui/inttextbox.cpp +++ b/src/gui/inttextbox.cpp @@ -21,7 +21,7 @@ #include "inttextbox.h" -#include <guichan/key.hpp> +#include "sdlinput.h" #include "../utils/tostring.h" @@ -35,17 +35,20 @@ IntTextBox::keyPressed(gcn::KeyEvent &event) { const gcn::Key &key = event.getKey(); - if (key.isNumber() || key.getValue() == gcn::Key::BACKSPACE - || key.getValue() == gcn::Key::DELETE) + if (key.getValue() == Key::BACKSPACE || + key.getValue() == Key::DELETE) { - gcn::TextBox::keyPressed(event); + setText(std::string()); + event.consume(); } - std::stringstream s(gcn::TextBox::getText()); + if (!key.isNumber()) return; + TextField::keyPressed(event); + + std::istringstream s(getText()); int i; s >> i; - if (gcn::TextBox::getText() != "") - setInt(i); + setInt(i); } void IntTextBox::setRange(int min, int max) @@ -56,9 +59,7 @@ void IntTextBox::setRange(int min, int max) int IntTextBox::getInt() { - if (gcn::TextBox::getText() == "") - return 0; - return mValue; + return getText().empty() ? mMin : mValue; } void IntTextBox::setInt(int i) diff --git a/src/gui/inttextbox.h b/src/gui/inttextbox.h index 8fc8e404..8dad0c39 100644 --- a/src/gui/inttextbox.h +++ b/src/gui/inttextbox.h @@ -22,12 +22,12 @@ #ifndef INTTEXTBOX_H #define INTTEXTBOX_H -#include "textbox.h" +#include "textfield.h" /** * TextBox which only accepts numbers as input. */ -class IntTextBox : public TextBox +class IntTextBox : public TextField { public: /** diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 0e1c5291..ac368aa7 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -39,10 +39,11 @@ #include "../resources/iteminfo.h" -#include "../utils/tostring.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" InventoryWindow::InventoryWindow(): - Window("Inventory") + Window(_("Inventory")) { setWindowName("Inventory"); setResizable(true); @@ -52,8 +53,8 @@ InventoryWindow::InventoryWindow(): // If you adjust these defaults, don't forget to adjust the trade window's. setDefaultSize(115, 25, 322, 200); - mUseButton = new Button("Use", "use", this); - mDropButton = new Button("Drop", "drop", this); + mUseButton = new Button(_("Use"), "use", this); + mDropButton = new Button(_("Drop"), "drop", this); mItems = new ItemContainer(player_node->getInventory()); mItems->addSelectionListener(this); @@ -95,15 +96,14 @@ void InventoryWindow::logic() updateButtons(); // Update weight information - mWeightLabel->setCaption( - "Weight: " + toString(player_node->mTotalWeight) + - "/" + toString(player_node->mMaxWeight)); + mWeightLabel->setCaption(strprintf(_("Weight: %d / %d"), + player_node->mTotalWeight, + player_node->mMaxWeight)); // Update number of items in inventory - mInvenSlotLabel->setCaption( - "Slots used: " - + toString(player_node->getInventory()->getNumberOfSlotsUsed()) - + "/" + toString(player_node->getInventory()->getInventorySize())); + mInvenSlotLabel->setCaption(strprintf(_("Slots used: %d / %d"), + player_node->getInventory()->getNumberOfSlotsUsed(), + player_node->getInventory()->getInventorySize())); } void InventoryWindow::action(const gcn::ActionEvent &event) @@ -145,20 +145,20 @@ void InventoryWindow::valueChanged(const gcn::SelectionEvent &event) // Update name, effect and description if (!item) { - mItemNameLabel->setCaption("Name:"); - mItemEffectLabel->setCaption("Effect:"); - mItemDescriptionLabel->setCaption("Description:"); + mItemNameLabel->setCaption(strprintf(_("Name: %s"), "")); + mItemEffectLabel->setCaption(strprintf(_("Effect: %s"), "")); + mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"), "")); } else { const ItemInfo& itemInfo = item->getInfo(); - std::string SomeText; - SomeText = "Name: " + itemInfo.getName(); - mItemNameLabel->setCaption(SomeText); - SomeText = "Effect: " + itemInfo.getEffect(); - mItemEffectLabel->setCaption(SomeText); - SomeText = "Description: " + itemInfo.getDescription(); - mItemDescriptionLabel->setCaption(SomeText); + mItemNameLabel->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())); } } @@ -170,7 +170,8 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event) { Item *item = mItems->getSelectedItem(); - if (!item) return; + if (!item) + return; /* Convert relative to the window coordinates to absolute screen * coordinates. @@ -221,14 +222,14 @@ void InventoryWindow::updateButtons() if (selectedItem && selectedItem->isEquipment()) { if (selectedItem->isEquipped()) { - mUseButton->setCaption("Unequip"); + mUseButton->setCaption(_("Unequip")); } else { - mUseButton->setCaption("Equip"); + mUseButton->setCaption(_("Equip")); } } else { - mUseButton->setCaption("Use"); + mUseButton->setCaption(_("Use")); } mUseButton->setEnabled(selectedItem != 0); diff --git a/src/gui/item_amount.cpp b/src/gui/item_amount.cpp index 2e8941e8..17c3243a 100644 --- a/src/gui/item_amount.cpp +++ b/src/gui/item_amount.cpp @@ -26,64 +26,64 @@ #include "slider.h" #include "trade.h" +#include "widgets/layout.h" + #include "../item.h" #include "../localplayer.h" +#include "../utils/gettext.h" + ItemAmountWindow::ItemAmountWindow(int usage, Window *parent, Item *item): - Window("Select amount of items to drop.", true, parent), + Window("", true, parent), mItem(item) { - // New labels + const int maxRange = mItem->getQuantity(); + + // Integer field mItemAmountTextBox = new IntTextBox(1); + mItemAmountTextBox->setRange(1, maxRange); + mItemAmountTextBox->setWidth(30); + mItemAmountTextBox->setActionEventId("Dummy"); + mItemAmountTextBox->addActionListener(this); + + // Slider + mItemAmountSlide = new Slider(1.0, maxRange); + mItemAmountSlide->setHeight(10); + mItemAmountSlide->setActionEventId("Slide"); + mItemAmountSlide->addActionListener(this); - // New buttons + // Buttons Button *minusButton = new Button("-", "Minus", this); + minusButton->setSize(20, 20); Button *plusButton = new Button("+", "Plus", this); - Button *okButton = new Button("Okay", "Drop", this); - Button *cancelButton = new Button("Cancel", "Cancel", this); - mItemAmountSlide = new Slider(1.0, mItem->getQuantity()); - - mItemAmountTextBox->setRange(1, mItem->getQuantity()); - mItemAmountSlide->setDimension(gcn::Rectangle(5, 120, 180, 10)); - - // Set button events Id - mItemAmountSlide->setActionEventId("Slide"); - - // Set position - mItemAmountTextBox->setPosition(35, 10); - mItemAmountTextBox->setSize(24, 16); - plusButton->setPosition(60, 5); - minusButton->setPosition(10, 5); - mItemAmountSlide->setPosition(10, 35); - okButton->setPosition(10, 50); - cancelButton->setPosition(60, 50); - - // Assemble - add(mItemAmountTextBox); - add(plusButton); - add(minusButton); - add(mItemAmountSlide); - add(okButton); - add(cancelButton); - - mItemAmountSlide->addActionListener(this); + plusButton->setSize(20, 20); + Button *okButton = new Button(_("Ok"), "Drop", this); + Button *cancelButton = new Button(_("Cancel"), "Cancel", this); + + // Set positions + place(0, 0, minusButton); + place(1, 0, mItemAmountTextBox).setPadding(2); + place(2, 0, plusButton); + place(0, 1, mItemAmountSlide, 6); + place(4, 2, okButton); + place(5, 2, cancelButton); + reflowLayout(250, 0); resetAmount(); switch (usage) { case AMOUNT_TRADE_ADD: - setCaption("Select amount of items to trade."); + setCaption(_("Select amount of items to trade.")); okButton->setActionEventId("AddTrade"); break; case AMOUNT_ITEM_DROP: - setCaption("Select amount of items to drop."); + setCaption(_("Select amount of items to drop.")); okButton->setActionEventId("Drop"); break; default: break; } - setContentSize(200, 80); setLocationRelativeTo(getParentWindow()); setVisible(true); } @@ -101,16 +101,6 @@ void ItemAmountWindow::action(const gcn::ActionEvent &event) { scheduleDelete(); } - else if (event.getId() == "Drop") - { - player_node->dropItem(mItem, mItemAmountTextBox->getInt()); - scheduleDelete(); - } - else if (event.getId() == "AddTrade") - { - tradeWindow->tradeItem(mItem, mItemAmountTextBox->getInt()); - scheduleDelete(); - } else if (event.getId() == "Plus") { amount++; @@ -123,7 +113,16 @@ void ItemAmountWindow::action(const gcn::ActionEvent &event) { amount = static_cast<int>(mItemAmountSlide->getValue()); } + else if (event.getId() == "Drop") + { + player_node->dropItem(mItem, mItemAmountTextBox->getInt()); + scheduleDelete(); + } + else if (event.getId() == "AddTrade") + { + tradeWindow->tradeItem(mItem, mItemAmountTextBox->getInt()); + scheduleDelete(); + } mItemAmountTextBox->setInt(amount); mItemAmountSlide->setValue(amount); } - diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp index 9115b1fb..65f8132a 100644 --- a/src/gui/itemcontainer.cpp +++ b/src/gui/itemcontainer.cpp @@ -115,6 +115,7 @@ void ItemContainer::draw(gcn::Graphics *graphics) } // Draw item caption + graphics->setColor(gcn::Color(0, 0, 0)); graphics->drawText( (item->isEquipped() ? "Eq." : toString(item->getQuantity())), itemX + gridWidth / 2, diff --git a/src/gui/itemshortcutcontainer.cpp b/src/gui/itemshortcutcontainer.cpp index 2ea5d584..ac62dbd6 100644 --- a/src/gui/itemshortcutcontainer.cpp +++ b/src/gui/itemshortcutcontainer.cpp @@ -75,6 +75,7 @@ ItemShortcutContainer::draw(gcn::Graphics *graphics) { Graphics *g = static_cast<Graphics*>(graphics); + graphics->setColor(gcn::Color(0, 0, 0)); graphics->setFont(getFont()); for (int i = 0; i < mMaxItems; i++) diff --git a/src/gui/login.cpp b/src/gui/login.cpp index 06a5f9f0..db81c683 100644 --- a/src/gui/login.cpp +++ b/src/gui/login.cpp @@ -34,46 +34,23 @@ #include "passwordfield.h" #include "textfield.h" +#include "widgets/layout.h" + +#include "../utils/gettext.h" + LoginDialog::LoginDialog(LoginData *loginData): - Window("Login"), mLoginData(loginData) + Window(_("Login")), mLoginData(loginData) { - gcn::Label *userLabel = new gcn::Label("Name:"); - gcn::Label *passLabel = new gcn::Label("Password:"); - gcn::Label *serverLabel = new gcn::Label("Server:"); + gcn::Label *userLabel = new gcn::Label(_("Name:")); + gcn::Label *passLabel = new gcn::Label(_("Password:")); + gcn::Label *serverLabel = new gcn::Label(_("Server:")); mUserField = new TextField(mLoginData->username); mPassField = new PasswordField(mLoginData->password); mServerField = new TextField(mLoginData->hostname); - mKeepCheck = new CheckBox("Keep", mLoginData->remember); - mOkButton = new Button("OK", "ok", this); - mCancelButton = new Button("Cancel", "cancel", this); - mRegisterButton = new Button("Register", "register", this); - - const int width = 220; - const int height = 100; - - setContentSize(width, height); - - userLabel->setPosition(5, 5); - passLabel->setPosition(5, 14 + userLabel->getHeight()); - serverLabel->setPosition( - 5, 23 + userLabel->getHeight() + passLabel->getHeight()); - mUserField->setPosition(65, 5); - mPassField->setPosition(65, 14 + userLabel->getHeight()); - mServerField->setPosition( - 65, 23 + userLabel->getHeight() + passLabel->getHeight()); - mUserField->setWidth(width - 70); - mPassField->setWidth(width - 70); - mServerField->setWidth(width - 70); - mKeepCheck->setPosition(4, 77); - mCancelButton->setPosition( - width - mCancelButton->getWidth() - 5, - height - mCancelButton->getHeight() - 5); - mOkButton->setPosition( - mCancelButton->getX() - mOkButton->getWidth() - 5, - height - mOkButton->getHeight() - 5); - mRegisterButton->setPosition( - mKeepCheck->getX() + mKeepCheck->getWidth() + 10, - height - mRegisterButton->getHeight() - 5); + mKeepCheck = new CheckBox(_("Remember Username"), mLoginData->remember); + mOkButton = new Button(_("Ok"), "ok", this); + mCancelButton = new Button(_("Cancel"), "cancel", this); + mRegisterButton = new Button(_("Register"), "register", this); mUserField->setActionEventId("ok"); mPassField->setActionEventId("ok"); @@ -87,16 +64,17 @@ LoginDialog::LoginDialog(LoginData *loginData): mServerField->addActionListener(this); mKeepCheck->addActionListener(this); - add(userLabel); - add(passLabel); - add(serverLabel); - add(mUserField); - add(mPassField); - add(mServerField); - add(mKeepCheck); - add(mOkButton); - add(mCancelButton); - add(mRegisterButton); + 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); + reflowLayout(250, 0); setLocationRelativeTo(getParent()); setVisible(true); @@ -114,8 +92,7 @@ LoginDialog::~LoginDialog() { } -void -LoginDialog::action(const gcn::ActionEvent &event) +void LoginDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "ok" && canSubmit()) { @@ -145,14 +122,12 @@ LoginDialog::action(const gcn::ActionEvent &event) } } -void -LoginDialog::keyPressed(gcn::KeyEvent &keyEvent) +void LoginDialog::keyPressed(gcn::KeyEvent &keyEvent) { mOkButton->setEnabled(canSubmit()); } -bool -LoginDialog::canSubmit() +bool LoginDialog::canSubmit() { return !mUserField->getText().empty() && !mPassField->getText().empty() && diff --git a/src/gui/menuwindow.cpp b/src/gui/menuwindow.cpp index 3c3e4ab8..0893cb1c 100644 --- a/src/gui/menuwindow.cpp +++ b/src/gui/menuwindow.cpp @@ -28,6 +28,8 @@ #include "button.h" #include "windowcontainer.h" +#include "../utils/gettext.h" + extern Window *setupWindow; extern Window *inventoryWindow; extern Window *equipmentWindow; @@ -54,21 +56,21 @@ MenuWindow::MenuWindow(): setTitleBarHeight(0); // Buttons - const char *buttonNames[] = + static const char *buttonNames[] = { - "Status", - "Equipment", - "Inventory", - "Skills", - "Shortcut", - "Setup", + N_("Status"), + N_("Equipment"), + N_("Inventory"), + N_("Skills"), + N_("Shortcut"), + N_("Setup"), 0 }; int x = 0, h = 0; for (const char **curBtn = buttonNames; *curBtn; curBtn++) { - gcn::Button *btn = new Button(*curBtn, *curBtn, &listener); + gcn::Button *btn = new Button(gettext(*curBtn), *curBtn, &listener); btn->setPosition(x, 0); add(btn); x += btn->getWidth() + 3; diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index 231c749f..55132d6d 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -28,8 +28,10 @@ #include "../resources/image.h" +#include "../utils/gettext.h" + Minimap::Minimap(): - Window("Map"), + Window(_("MiniMap")), mMapImage(NULL) { setWindowName("MiniMap"); diff --git a/src/gui/npc_text.cpp b/src/gui/npc_text.cpp index 34c9cce1..c9ace303 100644 --- a/src/gui/npc_text.cpp +++ b/src/gui/npc_text.cpp @@ -29,8 +29,10 @@ #include "../npc.h" +#include "../utils/gettext.h" + NpcTextDialog::NpcTextDialog(): - Window("NPC") + Window(_("NPC")) { setResizable(true); @@ -41,7 +43,7 @@ NpcTextDialog::NpcTextDialog(): mTextBox->setEditable(false); scrollArea = new ScrollArea(mTextBox); - okButton = new Button("OK", "ok", this); + okButton = new Button(_("OK"), "ok", this); setContentSize(260, 175); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); diff --git a/src/gui/npclistdialog.cpp b/src/gui/npclistdialog.cpp index cdd38312..bff6994d 100644 --- a/src/gui/npclistdialog.cpp +++ b/src/gui/npclistdialog.cpp @@ -29,8 +29,10 @@ #include "../npc.h" +#include "../utils/gettext.h" + NpcListDialog::NpcListDialog(): - Window("NPC") + Window(_("NPC")) { setResizable(true); @@ -39,8 +41,8 @@ NpcListDialog::NpcListDialog(): mItemList = new ListBox(this); scrollArea = new ScrollArea(mItemList); - okButton = new Button("OK", "ok", this); - cancelButton = new Button("Cancel", "cancel", this); + okButton = new Button(_("OK"), "ok", this); + cancelButton = new Button(_("Cancel"), "cancel", this); setContentSize(260, 175); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp index d43c8e69..9db3cd7b 100644 --- a/src/gui/ok_dialog.cpp +++ b/src/gui/ok_dialog.cpp @@ -24,6 +24,8 @@ #include "button.h" #include "scrollarea.h" +#include "../utils/gettext.h" + OkDialog::OkDialog(const std::string &title, const std::string &msg, Window *parent): Window(title, true, parent) @@ -32,7 +34,7 @@ OkDialog::OkDialog(const std::string &title, const std::string &msg, textBox->setEditable(false); gcn::ScrollArea *scrollArea = new ScrollArea(textBox); - gcn::Button *okButton = new Button("Ok", "ok", this); + gcn::Button *okButton = new Button(_("Ok"), "ok", this); setContentSize(260, 175); scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 07719d2c..1f5b3556 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -42,6 +42,9 @@ #include "../resources/iteminfo.h" #include "../resources/itemdb.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" + extern std::string tradePartnerName; PopupMenu::PopupMenu(): @@ -52,7 +55,7 @@ PopupMenu::PopupMenu(): { setResizable(false); setTitleBarHeight(0); - mShowTitle = false; + setShowTitle(false); mBrowserBox = new BrowserBox(); mBrowserBox->setPosition(4, 4); @@ -74,8 +77,10 @@ void PopupMenu::showPopup(int x, int y, Being *being) // 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( + strprintf(_("@@trade|Trade With %s@@"), name.c_str())); + mBrowserBox->addRow( + strprintf(_("@@attack|Attack %s@@"), name.c_str())); mBrowserBox->addRow("##3---"); @@ -106,7 +111,7 @@ void PopupMenu::showPopup(int x, int y, Being *being) 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@@"); + mBrowserBox->addRow(_("@@talk|Talk To NPC@@")); break; default: @@ -116,7 +121,7 @@ void PopupMenu::showPopup(int x, int y, Being *being) //browserBox->addRow("@@look|Look To@@"); mBrowserBox->addRow("##3---"); - mBrowserBox->addRow("@@cancel|Cancel@@"); + mBrowserBox->addRow(_("@@cancel|Cancel@@")); showPopup(x, y); } @@ -128,11 +133,11 @@ void PopupMenu::showPopup(int x, int y, FloorItem *floorItem) // Floor item can be picked up (single option, candidate for removal) std::string name = ItemDB::get(mFloorItem->getItemId()).getName(); - mBrowserBox->addRow("@@pickup|Pick Up " + name + "@@"); + mBrowserBox->addRow(strprintf(_("@@pickup|Pick Up %s@@"), name.c_str())); //browserBox->addRow("@@look|Look To@@"); mBrowserBox->addRow("##3---"); - mBrowserBox->addRow("@@cancel|Cancel@@"); + mBrowserBox->addRow(_("@@cancel|Cancel@@")); showPopup(x, y); } @@ -275,17 +280,17 @@ void PopupMenu::showPopup(int x, int y, Item *item) if (item->isEquipment()) { if (item->isEquipped()) - mBrowserBox->addRow("@@use|Unequip@@"); + mBrowserBox->addRow(_("@@use|Unequip@@")); else - mBrowserBox->addRow("@@use|Equip@@"); + mBrowserBox->addRow(_("@@use|Equip@@")); } else - mBrowserBox->addRow("@@use|Use@@"); + mBrowserBox->addRow(_("@@use|Use@@")); - mBrowserBox->addRow("@@drop|Drop@@"); - mBrowserBox->addRow("@@description|Description@@"); + mBrowserBox->addRow(_("@@drop|Drop@@")); + mBrowserBox->addRow(_("@@description|Description@@")); mBrowserBox->addRow("##3---"); - mBrowserBox->addRow("@@cancel|Cancel@@"); + mBrowserBox->addRow(_("@@cancel|Cancel@@")); showPopup(x, y); } diff --git a/src/gui/radiobutton.cpp b/src/gui/radiobutton.cpp index 5f929e62..619ec84f 100644 --- a/src/gui/radiobutton.cpp +++ b/src/gui/radiobutton.cpp @@ -81,3 +81,22 @@ void RadioButton::drawBox(gcn::Graphics* graphics) static_cast<Graphics*>(graphics)->drawImage(box, 2, 2); } } + +void RadioButton::draw(gcn::Graphics* graphics) +{ + + graphics->pushClipArea(gcn::Rectangle(1, + 1, + getWidth() - 1, + getHeight() - 1)); + + drawBox(graphics); + + graphics->popClipArea(); + + graphics->setFont(getFont()); + graphics->setColor(getForegroundColor()); + + int h = getHeight() + getHeight() / 2; + graphics->drawText(getCaption(), h - 2, 0); +} diff --git a/src/gui/radiobutton.h b/src/gui/radiobutton.h index 6506444f..09f703dc 100644 --- a/src/gui/radiobutton.h +++ b/src/gui/radiobutton.h @@ -48,6 +48,12 @@ class RadioButton : public gcn::RadioButton { */ void drawBox(gcn::Graphics* graphics); + /** + * Implementation of the draw methods. + * Thus, avoiding the rhomb around the radio button. + */ + void draw(gcn::Graphics* graphics); + private: static int instances; static Image *radioNormal; diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 2a97a3e5..ce36efa2 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -39,6 +39,9 @@ #include "textfield.h" #include "ok_dialog.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" + void WrongDataNoticeListener::setTarget(gcn::TextField *textField) { @@ -59,18 +62,18 @@ RegisterDialog::RegisterDialog(LoginData *loginData): mWrongDataNoticeListener(new WrongDataNoticeListener()), mLoginData(loginData) { - gcn::Label *userLabel = new gcn::Label("Name:"); - gcn::Label *passwordLabel = new gcn::Label("Password:"); - gcn::Label *confirmLabel = new gcn::Label("Confirm:"); - gcn::Label *serverLabel = new gcn::Label("Server:"); + gcn::Label *userLabel = new gcn::Label(_("Name:")); + gcn::Label *passwordLabel = new gcn::Label(_("Password:")); + gcn::Label *confirmLabel = new gcn::Label(_("Confirm:")); + gcn::Label *serverLabel = new gcn::Label(_("Server:")); mUserField = new TextField(loginData->username); mPasswordField = new PasswordField(loginData->password); mConfirmField = new PasswordField(); mServerField = new TextField(loginData->hostname); - mMaleButton = new RadioButton("Male", "sex", true); - mFemaleButton = new RadioButton("Female", "sex", false); - mRegisterButton = new Button("Register", "register", this); - mCancelButton = new Button("Cancel", "cancel", this); + mMaleButton = new RadioButton(_("Male"), "sex", true); + mFemaleButton = new RadioButton(_("Female"), "sex", false); + mRegisterButton = new Button(_("Register"), "register", this); + mCancelButton = new Button(_("Cancel"), "cancel", this); const int width = 220; const int height = 150; @@ -163,45 +166,45 @@ RegisterDialog::action(const gcn::ActionEvent &event) const std::string user = mUserField->getText(); logger->log("RegisterDialog::register Username is %s", user.c_str()); - std::stringstream errorMsg; + std::string errorMsg; int error = 0; if (user.length() < LEN_MIN_USERNAME) { // Name too short - errorMsg << "The username needs to be at least " - << LEN_MIN_USERNAME - << " characters long."; + errorMsg = strprintf + (_("The username needs to be at least %d characters long."), + LEN_MIN_USERNAME); error = 1; } else if (user.length() > LEN_MAX_USERNAME - 1 ) { // Name too long - errorMsg << "The username needs to be less than " - << LEN_MAX_USERNAME - << " characters long."; + errorMsg = strprintf + (_("The username needs to be less than %d characters long."), + LEN_MAX_USERNAME); error = 1; } else if (mPasswordField->getText().length() < LEN_MIN_PASSWORD) { // Pass too short - errorMsg << "The password needs to be at least " - << LEN_MIN_PASSWORD - << " characters long."; + errorMsg = strprintf + (_("The password needs to be at least %d characters long."), + LEN_MIN_PASSWORD); error = 2; } else if (mPasswordField->getText().length() > LEN_MAX_PASSWORD - 1 ) { // Pass too long - errorMsg << "The password needs to be less than " - << LEN_MAX_PASSWORD - << " characters long."; + errorMsg = strprintf + (_("The password needs to be less than %d characters long."), + LEN_MAX_PASSWORD); error = 2; } else if (mPasswordField->getText() != mConfirmField->getText()) { // Password does not match with the confirmation one - errorMsg << "Passwords do not match."; + errorMsg = _("Passwords do not match."); error = 2; } @@ -220,8 +223,8 @@ RegisterDialog::action(const gcn::ActionEvent &event) mWrongDataNoticeListener->setTarget(this->mPasswordField); } - OkDialog *mWrongRegisterNotice = new OkDialog("Error", - errorMsg.str()); + OkDialog *mWrongRegisterNotice = + new OkDialog(_("Error"), errorMsg); mWrongRegisterNotice->addActionListener(mWrongDataNoticeListener); } else diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp new file mode 100644 index 00000000..ee94b2c6 --- /dev/null +++ b/src/gui/sdlinput.cpp @@ -0,0 +1,429 @@ +/* _______ __ __ __ ______ __ __ _______ __ __ + * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ + * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / + * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / + * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / + * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / + * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ + * + * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson + * Copyright 2007 The Mana World Development Team + * + * Js_./ + * Per Larsson a.k.a finalman _RqZ{a<^_aa + * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a// + * _Qhm`] _f "'c 1!5m + * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[ + * .)j(] .d_/ '-( P . S + * License: (BSD) <Td/Z <fP"5(\"??"\a. .L + * Redistribution and use in source and _dV>ws?a-?' ._/L #' + * binary forms, with or without )4d[#7r, . ' )d`)[ + * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam' + * that the following conditions are met: j<<WP+k/);. _W=j f + * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$ + * retain the above copyright notice, ]E.pYY(Q]>. a J@\ + * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a + * following disclaimer. 4'_uomm\. )L);-4 (3= + * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[ + * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m + * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/ + * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m + * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]' + * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W" + * 3. Neither the name of Guichan nor the :$we` _! + _/ . j? + * names of its contributors may be used =3)= _f (_yQmWW$#( " + * to endorse or promote products derived - W, sQQQQmZQ#Wwa].. + * from this software without specific (js, \[QQW$QWW#?!V"". + * prior written permission. ]y:.<\.. . + * -]n w/ ' [. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ ! + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , ' + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- % + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'., + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?" + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. . + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^ + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sdlinput.h" + +#include <guichan/exception.hpp> + +SDLInput::SDLInput() +{ + mMouseInWindow = true; + mMouseDown = false; +} + +bool SDLInput::isKeyQueueEmpty() +{ + return mKeyInputQueue.empty(); +} + +gcn::KeyInput SDLInput::dequeueKeyInput() +{ + gcn::KeyInput keyInput; + + if (mKeyInputQueue.empty()) + { + throw GCN_EXCEPTION("The queue is empty."); + } + + keyInput = mKeyInputQueue.front(); + mKeyInputQueue.pop(); + + return keyInput; +} + +bool SDLInput::isMouseQueueEmpty() +{ + return mMouseInputQueue.empty(); +} + +gcn::MouseInput SDLInput::dequeueMouseInput() +{ + gcn::MouseInput mouseInput; + + if (mMouseInputQueue.empty()) + { + throw GCN_EXCEPTION("The queue is empty."); + } + + mouseInput = mMouseInputQueue.front(); + mMouseInputQueue.pop(); + + return mouseInput; +} + +void SDLInput::pushInput(SDL_Event event) +{ + gcn::KeyInput keyInput; + gcn::MouseInput mouseInput; + + switch (event.type) + { + case SDL_KEYDOWN: + keyInput.setKey(gcn::Key(convertKeyCharacter(event))); + keyInput.setType(gcn::KeyInput::PRESSED); + keyInput.setShiftPressed(event.key.keysym.mod & KMOD_SHIFT); + keyInput.setControlPressed(event.key.keysym.mod & KMOD_CTRL); + keyInput.setAltPressed(event.key.keysym.mod & KMOD_ALT); + keyInput.setMetaPressed(event.key.keysym.mod & KMOD_META); + keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP0 + && event.key.keysym.sym <= SDLK_KP_EQUALS); + + mKeyInputQueue.push(keyInput); + break; + + case SDL_KEYUP: + keyInput.setKey(gcn::Key(convertKeyCharacter(event))); + keyInput.setType(gcn::KeyInput::RELEASED); + keyInput.setShiftPressed(event.key.keysym.mod & KMOD_SHIFT); + keyInput.setControlPressed(event.key.keysym.mod & KMOD_CTRL); + keyInput.setAltPressed(event.key.keysym.mod & KMOD_ALT); + keyInput.setMetaPressed(event.key.keysym.mod & KMOD_META); + keyInput.setNumericPad(event.key.keysym.sym >= SDLK_KP0 + && event.key.keysym.sym <= SDLK_KP_EQUALS); + + mKeyInputQueue.push(keyInput); + break; + + case SDL_MOUSEBUTTONDOWN: + mMouseDown = true; + mouseInput.setX(event.button.x); + mouseInput.setY(event.button.y); + mouseInput.setButton(convertMouseButton(event.button.button)); + + if (event.button.button == SDL_BUTTON_WHEELDOWN) + { + mouseInput.setType(gcn::MouseInput::WHEEL_MOVED_DOWN); + } + else if (event.button.button == SDL_BUTTON_WHEELUP) + { + mouseInput.setType(gcn::MouseInput::WHEEL_MOVED_UP); + } + else + { + mouseInput.setType(gcn::MouseInput::PRESSED); + } + mouseInput.setTimeStamp(SDL_GetTicks()); + mMouseInputQueue.push(mouseInput); + break; + + case SDL_MOUSEBUTTONUP: + mMouseDown = false; + mouseInput.setX(event.button.x); + mouseInput.setY(event.button.y); + mouseInput.setButton(convertMouseButton(event.button.button)); + mouseInput.setType(gcn::MouseInput::RELEASED); + mouseInput.setTimeStamp(SDL_GetTicks()); + mMouseInputQueue.push(mouseInput); + break; + + case SDL_MOUSEMOTION: + mouseInput.setX(event.button.x); + mouseInput.setY(event.button.y); + mouseInput.setButton(gcn::MouseInput::EMPTY); + mouseInput.setType(gcn::MouseInput::MOVED); + mouseInput.setTimeStamp(SDL_GetTicks()); + mMouseInputQueue.push(mouseInput); + break; + + case SDL_ACTIVEEVENT: + /* + * This occurs when the mouse leaves the window and the Gui-chan + * application loses its mousefocus. + */ + if ((event.active.state & SDL_APPMOUSEFOCUS) + && !event.active.gain) + { + mMouseInWindow = false; + + if (!mMouseDown) + { + mouseInput.setX(-1); + mouseInput.setY(-1); + mouseInput.setButton(gcn::MouseInput::EMPTY); + mouseInput.setType(gcn::MouseInput::MOVED); + mMouseInputQueue.push(mouseInput); + } + } + + if ((event.active.state & SDL_APPMOUSEFOCUS) + && event.active.gain) + { + mMouseInWindow = true; + } + break; + + } // end switch +} + +int SDLInput::convertMouseButton(int button) +{ + switch (button) + { + case SDL_BUTTON_LEFT: + return gcn::MouseInput::LEFT; + case SDL_BUTTON_RIGHT: + return gcn::MouseInput::RIGHT; + case SDL_BUTTON_MIDDLE: + return gcn::MouseInput::MIDDLE; + default: + // We have an unknown mouse type which is ignored. + return button; + } +} + +int SDLInput::convertKeyCharacter(SDL_Event event) +{ + SDL_keysym keysym = event.key.keysym; + + int value = keysym.unicode; + + switch (keysym.sym) + { + case SDLK_TAB: + value = Key::TAB; + break; + case SDLK_LALT: + value = Key::LEFT_ALT; + break; + case SDLK_RALT: + value = Key::RIGHT_ALT; + break; + case SDLK_LSHIFT: + value = Key::LEFT_SHIFT; + break; + case SDLK_RSHIFT: + value = Key::RIGHT_SHIFT; + break; + case SDLK_LCTRL: + value = Key::LEFT_CONTROL; + break; + case SDLK_RCTRL: + value = Key::RIGHT_CONTROL; + break; + case SDLK_BACKSPACE: + value = Key::BACKSPACE; + break; + case SDLK_PAUSE: + value = Key::PAUSE; + break; + case SDLK_SPACE: + // Special characters like ~ (tilde) ends up + // with the keysym.sym SDLK_SPACE which + // without this check would be lost. The check + // is only valid on key down events in SDL. + if (event.type == SDL_KEYUP || keysym.unicode == ' ') + { + value = Key::SPACE; + } + break; + case SDLK_ESCAPE: + value = Key::ESCAPE; + break; + case SDLK_DELETE: + value = Key::DELETE; + break; + case SDLK_INSERT: + value = Key::INSERT; + break; + case SDLK_HOME: + value = Key::HOME; + break; + case SDLK_END: + value = Key::END; + break; + case SDLK_PAGEUP: + value = Key::PAGE_UP; + break; + case SDLK_PRINT: + value = Key::PRINT_SCREEN; + break; + case SDLK_PAGEDOWN: + value = Key::PAGE_DOWN; + break; + case SDLK_F1: + value = Key::F1; + break; + case SDLK_F2: + value = Key::F2; + break; + case SDLK_F3: + value = Key::F3; + break; + case SDLK_F4: + value = Key::F4; + break; + case SDLK_F5: + value = Key::F5; + break; + case SDLK_F6: + value = Key::F6; + break; + case SDLK_F7: + value = Key::F7; + break; + case SDLK_F8: + value = Key::F8; + break; + case SDLK_F9: + value = Key::F9; + break; + case SDLK_F10: + value = Key::F10; + break; + case SDLK_F11: + value = Key::F11; + break; + case SDLK_F12: + value = Key::F12; + break; + case SDLK_F13: + value = Key::F13; + break; + case SDLK_F14: + value = Key::F14; + break; + case SDLK_F15: + value = Key::F15; + break; + case SDLK_NUMLOCK: + value = Key::NUM_LOCK; + break; + case SDLK_CAPSLOCK: + value = Key::CAPS_LOCK; + break; + case SDLK_SCROLLOCK: + value = Key::SCROLL_LOCK; + break; + case SDLK_RMETA: + value = Key::RIGHT_META; + break; + case SDLK_LMETA: + value = Key::LEFT_META; + break; + case SDLK_LSUPER: + value = Key::LEFT_SUPER; + break; + case SDLK_RSUPER: + value = Key::RIGHT_SUPER; + break; + case SDLK_MODE: + value = Key::ALT_GR; + break; + case SDLK_UP: + value = Key::UP; + break; + case SDLK_DOWN: + value = Key::DOWN; + break; + case SDLK_LEFT: + value = Key::LEFT; + break; + case SDLK_RIGHT: + value = Key::RIGHT; + break; + case SDLK_RETURN: + value = Key::ENTER; + break; + case SDLK_KP_ENTER: + value = Key::ENTER; + break; + + default: + break; + } + + if (!(keysym.mod & KMOD_NUM)) + { + switch (keysym.sym) + { + case SDLK_KP0: + value = Key::INSERT; + break; + case SDLK_KP1: + value = Key::END; + break; + case SDLK_KP2: + value = Key::DOWN; + break; + case SDLK_KP3: + value = Key::PAGE_DOWN; + break; + case SDLK_KP4: + value = Key::LEFT; + break; + case SDLK_KP5: + value = 0; + break; + case SDLK_KP6: + value = Key::RIGHT; + break; + case SDLK_KP7: + value = Key::HOME; + break; + case SDLK_KP8: + value = Key::UP; + break; + case SDLK_KP9: + value = Key::PAGE_UP; + break; + default: + break; + } + } + + return value; +} diff --git a/src/gui/sdlinput.h b/src/gui/sdlinput.h new file mode 100644 index 00000000..72d949e1 --- /dev/null +++ b/src/gui/sdlinput.h @@ -0,0 +1,188 @@ +/* _______ __ __ __ ______ __ __ _______ __ __ + * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ + * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / + * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / + * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / + * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / + * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ + * + * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson + * Copyright 2007 The Mana World Development Team + * + * Js_./ + * Per Larsson a.k.a finalman _RqZ{a<^_aa + * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a// + * _Qhm`] _f "'c 1!5m + * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[ + * .)j(] .d_/ '-( P . S + * License: (BSD) <Td/Z <fP"5(\"??"\a. .L + * Redistribution and use in source and _dV>ws?a-?' ._/L #' + * binary forms, with or without )4d[#7r, . ' )d`)[ + * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam' + * that the following conditions are met: j<<WP+k/);. _W=j f + * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$ + * retain the above copyright notice, ]E.pYY(Q]>. a J@\ + * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a + * following disclaimer. 4'_uomm\. )L);-4 (3= + * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[ + * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m + * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/ + * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m + * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]' + * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W" + * 3. Neither the name of Guichan nor the :$we` _! + _/ . j? + * names of its contributors may be used =3)= _f (_yQmWW$#( " + * to endorse or promote products derived - W, sQQQQmZQ#Wwa].. + * from this software without specific (js, \[QQW$QWW#?!V"". + * prior written permission. ]y:.<\.. . + * -]n w/ ' [. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ ! + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , ' + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- % + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'., + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?" + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. . + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^ + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TMW_SDLINPUT_ +#define _TMW_SDLINPUT_ + +#include <queue> + +#include <SDL/SDL.h> + +#include <guichan/input.hpp> +#include <guichan/keyinput.hpp> +#include <guichan/mouseinput.hpp> +#include <guichan/platform.hpp> + +namespace Key +{ + enum + { + SPACE = ' ', + TAB = '\t', + ENTER = '\n', + // Negative values, to avoid conflicts with higher character codes. + LEFT_ALT = -1000, + RIGHT_ALT, + LEFT_SHIFT, + RIGHT_SHIFT, + LEFT_CONTROL, + RIGHT_CONTROL, + LEFT_META, + RIGHT_META, + LEFT_SUPER, + RIGHT_SUPER, + INSERT, + HOME, + PAGE_UP, + DELETE, + END, + PAGE_DOWN, + ESCAPE, + CAPS_LOCK, + BACKSPACE, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + PRINT_SCREEN, + SCROLL_LOCK, + PAUSE, + NUM_LOCK, + ALT_GR, + LEFT, + RIGHT, + UP, + DOWN + }; +} + +/** + * SDL implementation of Input. + */ +class SDLInput : public gcn::Input +{ +public: + + /** + * Constructor. + */ + SDLInput(); + + /** + * Pushes an SDL event. It should be called at least once per frame to + * update input with user input. + * + * @param event an event from SDL. + */ + virtual void pushInput(SDL_Event event); + + /** + * Polls all input. It exists for input driver compatibility. If you + * only use SDL and plan sticking with SDL you can safely ignore this + * function as it in the SDL case does nothing. + */ + virtual void _pollInput() { } + + + // Inherited from Input + + virtual bool isKeyQueueEmpty(); + + virtual gcn::KeyInput dequeueKeyInput(); + + virtual bool isMouseQueueEmpty(); + + virtual gcn::MouseInput dequeueMouseInput(); + +protected: + /** + * Converts a mouse button from SDL to a Guichan mouse button + * representation. + * + * @param button an SDL mouse button. + * @return a Guichan mouse button. + */ + int convertMouseButton(int button); + + /** + * Converts an SDL event key to a key value. + * + * @param event an SDL event with a key to convert. + * @return a key value. + * @see Key + */ + int convertKeyCharacter(SDL_Event event); + + std::queue<gcn::KeyInput> mKeyInputQueue; + std::queue<gcn::MouseInput> mMouseInputQueue; + + bool mMouseDown; + bool mMouseInWindow; +}; + +#endif diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp index 6df1cbf6..f7f66345 100644 --- a/src/gui/sell.cpp +++ b/src/gui/sell.cpp @@ -31,6 +31,8 @@ #include "shop.h" #include "slider.h" +#include "widgets/layout.h" + #include "../item.h" #include "../npc.h" @@ -39,10 +41,11 @@ #include "../net/messageout.h" #include "../net/protocol.h" -#include "../utils/tostring.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" SellDialog::SellDialog(Network *network): - Window("Sell"), + Window(_("Sell")), mNetwork(network), mMaxItems(0), mAmountItems(0) { @@ -58,17 +61,17 @@ SellDialog::SellDialog(Network *network): mScrollArea = new ScrollArea(mShopItemList); mSlider = new Slider(1.0); mQuantityLabel = new gcn::Label("0"); - mMoneyLabel = new gcn::Label("Money: 0 GP / Total: 0 GP"); + mMoneyLabel = new gcn::Label( + strprintf(_("Price: %d GP / Total: %d GP"), 0, 0)); mIncreaseButton = new Button("+", "+", this); mDecreaseButton = new Button("-", "-", this); - mSellButton = new Button("Sell", "sell", this); - mQuitButton = new Button("Quit", "quit", this); - mItemDescLabel = new gcn::Label("Description:"); - mItemEffectLabel = new gcn::Label("Effect:"); + mSellButton = new Button(_("Sell"), "sell", this); + mQuitButton = new Button(_("Quit"), "quit", this); + mItemDescLabel = new gcn::Label(strprintf(_("Description: %s"), "")); + mItemEffectLabel = new gcn::Label(strprintf(_("Effect: %s"), "")); mIncreaseButton->setSize(20, 20); mDecreaseButton->setSize(20, 20); - mQuantityLabel->setWidth(60); mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); mIncreaseButton->setEnabled(false); @@ -77,23 +80,22 @@ SellDialog::SellDialog(Network *network): mSlider->setEnabled(false); mShopItemList->setPriceCheck(false); - mShopItemList->setActionEventId("item"); - mSlider->setActionEventId("slider"); - - mShopItemList->addActionListener(this); mShopItemList->addSelectionListener(this); + mSlider->setActionEventId("slider"); mSlider->addActionListener(this); - add(mScrollArea); - add(mSlider); - add(mQuantityLabel); - add(mMoneyLabel); - add(mItemEffectLabel); - add(mItemDescLabel); - add(mIncreaseButton); - add(mDecreaseButton); - add(mSellButton); - add(mQuitButton); + place(0, 0, mScrollArea, 5).setPadding(3); + place(0, 1, mQuantityLabel, 2); + place(2, 1, mSlider, 3); + place(0, 2, mMoneyLabel, 5); + place(0, 3, mItemEffectLabel, 5); + place(0, 4, mItemDescLabel, 5); + place(0, 5, mDecreaseButton); + place(1, 5, mIncreaseButton); + place(3, 5, mSellButton); + place(4, 5, mQuitButton); + Layout &layout = getLayout(); + layout.setRowHeight(0, Layout::AUTO_SET); loadWindowState(); setLocationRelativeTo(getParent()); @@ -210,65 +212,25 @@ void SellDialog::valueChanged(const gcn::SelectionEvent &event) mSlider->gcn::Slider::setScale(1, mMaxItems); } -void SellDialog::widgetResized(const gcn::Event &event) -{ - Window::widgetResized(event); - - gcn::Rectangle area = getChildrenArea(); - int width = area.width; - int height = area.height; - - mDecreaseButton->setPosition(8, height - 8 - mDecreaseButton->getHeight()); - mIncreaseButton->setPosition( - mDecreaseButton->getX() + mDecreaseButton->getWidth() + 5, - mDecreaseButton->getY()); - - mQuitButton->setPosition( - width - 8 - mQuitButton->getWidth(), - height - 8 - mQuitButton->getHeight()); - mSellButton->setPosition( - mQuitButton->getX() - 5 - mSellButton->getWidth(), - mQuitButton->getY()); - - mItemDescLabel->setDimension(gcn::Rectangle(8, - mSellButton->getY() - 5 - mItemDescLabel->getHeight(), - width - 16, - mItemDescLabel->getHeight())); - mItemEffectLabel->setDimension(gcn::Rectangle(8, - mItemDescLabel->getY() - 5 - mItemEffectLabel->getHeight(), - width - 16, - mItemEffectLabel->getHeight())); - mMoneyLabel->setDimension(gcn::Rectangle(8, - mItemEffectLabel->getY() - 5 - mMoneyLabel->getHeight(), - width - 16, - mMoneyLabel->getHeight())); - - mQuantityLabel->setPosition( - width - mQuantityLabel->getWidth() - 8, - mMoneyLabel->getY() - 5 - mQuantityLabel->getHeight()); - mSlider->setDimension(gcn::Rectangle(8, - mQuantityLabel->getY(), - mQuantityLabel->getX() - 8 - 8, - 10)); - - mScrollArea->setDimension(gcn::Rectangle(8, 8, width - 16, - mSlider->getY() - 5 - 8)); -} - void SellDialog::setMoney(int amount) { mPlayerMoney = amount; mShopItemList->setPlayersMoney(amount); } -void -SellDialog::updateButtonsAndLabels() +void SellDialog::updateButtonsAndLabels() { int selectedItem = mShopItemList->getSelected(); int income = 0; if (selectedItem > -1) { + const ItemInfo &info = mShopItems->at(selectedItem)->getInfo(); + mItemDescLabel->setCaption + (strprintf(_("Description: %s"), info.getDescription().c_str())); + mItemEffectLabel->setCaption + (strprintf(_("Effect: %s"), info.getEffect().c_str())); + mMaxItems = mShopItems->at(selectedItem)->getQuantity(); if (mAmountItems > mMaxItems) { @@ -276,17 +238,13 @@ SellDialog::updateButtonsAndLabels() } income = mAmountItems * mShopItems->at(selectedItem)->getPrice(); - - const ItemInfo &info = mShopItems->at(selectedItem)->getInfo(); - mItemDescLabel->setCaption("Description: " + info.getDescription()); - mItemEffectLabel->setCaption("Effect: " + info.getEffect()); } else { + mItemDescLabel->setCaption(strprintf(_("Description: %s"), "")); + mItemEffectLabel->setCaption(strprintf(_("Effect: %s"), "")); mMaxItems = 0; mAmountItems = 0; - mItemDescLabel->setCaption("Description:"); - mItemEffectLabel->setCaption("Effect:"); } // Update Buttons and slider @@ -296,8 +254,8 @@ SellDialog::updateButtonsAndLabels() mSlider->setEnabled(mMaxItems > 1); // Update the quantity and money labels - mQuantityLabel->setCaption( - toString(mAmountItems) + " / " + toString(mMaxItems)); - mMoneyLabel->setCaption("Money: " + toString(income) + " GP / Total: " - + toString(mPlayerMoney + income) + " GP"); + mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems)); + mMoneyLabel->setCaption + (strprintf(_("Price: %d GP / Total: %d GP"), + income, mPlayerMoney + income)); } diff --git a/src/gui/sell.h b/src/gui/sell.h index 48961efc..0bf8b5a6 100644 --- a/src/gui/sell.h +++ b/src/gui/sell.h @@ -77,11 +77,6 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener void valueChanged(const gcn::SelectionEvent &event); /** - * Called whenever the widget changes size. - */ - void widgetResized(const gcn::Event &event); - - /** * Gives Player's Money amount */ void setMoney(int amount); diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 2da9d1b5..067d8d64 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -32,6 +32,8 @@ #include "tabbedcontainer.h" #include "../utils/dtor.h" +#include "../utils/gettext.h" + #include <iostream> extern Window *statusWindow; @@ -52,12 +54,12 @@ Setup::Setup(): int height = 265; setContentSize(width, height); - const char *buttonNames[] = { - "Apply", "Cancel", "Reset Windows", 0 + static const char *buttonNames[] = { + N_("Apply"), N_("Cancel"), N_("Reset Windows"), 0 }; int x = width; for (const char **curBtn = buttonNames; *curBtn; ++curBtn) { - Button *btn = new Button(*curBtn, *curBtn, this); + Button *btn = new Button(gettext(*curBtn), *curBtn, this); x -= btn->getWidth() + 5; btn->setPosition(x, height - btn->getHeight() - 5); add(btn); @@ -74,23 +76,23 @@ Setup::Setup(): SetupTab *tab; tab = new Setup_Video(); - panel->addTab(tab, "Video"); + panel->addTab(tab, _("Video")); mTabs.push_back(tab); tab = new Setup_Audio(); - panel->addTab(tab, "Audio"); + panel->addTab(tab, _("Audio")); mTabs.push_back(tab); tab = new Setup_Joystick(); - panel->addTab(tab, "Joystick"); + panel->addTab(tab, _("Joystick")); mTabs.push_back(tab); tab = new Setup_Keyboard(); - panel->addTab(tab, "Keyboard"); + panel->addTab(tab, _("Keyboard")); mTabs.push_back(tab); tab = new Setup_Players(); - panel->addTab(tab, "Players"); + panel->addTab(tab, _("Players")); mTabs.push_back(tab); add(panel); diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp index a027e133..c595edc9 100644 --- a/src/gui/setup_audio.cpp +++ b/src/gui/setup_audio.cpp @@ -31,18 +31,20 @@ #include "../log.h" #include "../sound.h" +#include "../utils/gettext.h" + Setup_Audio::Setup_Audio(): mMusicVolume((int)config.getValue("musicVolume", 60)), mSfxVolume((int)config.getValue("sfxVolume", 100)), mSoundEnabled(config.getValue("sound", 0)), - mSoundCheckBox(new CheckBox("Sound", mSoundEnabled)), + mSoundCheckBox(new CheckBox(_("Sound"), mSoundEnabled)), mSfxSlider(new Slider(0, 128)), mMusicSlider(new Slider(0, 128)) { setOpaque(false); - gcn::Label *sfxLabel = new gcn::Label("Sfx volume"); - gcn::Label *musicLabel = new gcn::Label("Music volume"); + gcn::Label *sfxLabel = new gcn::Label(_("Sfx volume")); + gcn::Label *musicLabel = new gcn::Label(_("Music volume")); mSfxSlider->setActionEventId("sfx"); mMusicSlider->setActionEventId("music"); diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp index c59068f7..a718f87e 100644 --- a/src/gui/setup_joystick.cpp +++ b/src/gui/setup_joystick.cpp @@ -28,12 +28,14 @@ #include "../configuration.h" #include "../joystick.h" +#include "../utils/gettext.h" + extern Joystick *joystick; Setup_Joystick::Setup_Joystick(): - mCalibrateLabel(new gcn::Label("Press the button to start calibration")), - mCalibrateButton(new Button("Calibrate", "calibrate", this)), - mJoystickEnabled(new CheckBox("Enable joystick")) + mCalibrateLabel(new gcn::Label(_("Press the button to start calibration"))), + mCalibrateButton(new Button(_("Calibrate"), "calibrate", this)), + mJoystickEnabled(new CheckBox(_("Enable joystick"))) { setOpaque(false); mJoystickEnabled->setPosition(10, 10); @@ -63,13 +65,13 @@ void Setup_Joystick::action(const gcn::ActionEvent &event) else { if (joystick->isCalibrating()) { - mCalibrateButton->setCaption("Calibrate"); - mCalibrateLabel->setCaption( - "Press the button to start calibration"); + mCalibrateButton->setCaption(_("Calibrate")); + mCalibrateLabel->setCaption + (_("Press the button to start calibration")); joystick->finishCalibration(); } else { - mCalibrateButton->setCaption("Stop"); - mCalibrateLabel->setCaption("Rotate the stick"); + mCalibrateButton->setCaption(_("Stop")); + mCalibrateLabel->setCaption(_("Rotate the stick")); joystick->startCalibration(); } } diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp index c6247487..de3c0ce1 100644 --- a/src/gui/setup_keyboard.cpp +++ b/src/gui/setup_keyboard.cpp @@ -32,6 +32,7 @@ #include "../configuration.h" #include "../keyboardconfig.h" +#include "../utils/gettext.h" #include "../utils/tostring.h" #include <SDL_keyboard.h> @@ -84,13 +85,13 @@ Setup_Keyboard::Setup_Keyboard(): scrollArea->setDimension(gcn::Rectangle(10, 10, 200, 140)); add(scrollArea); - mAssignKeyButton = new Button("Assign", "assign", this); + mAssignKeyButton = new Button(_("Assign"), "assign", this); mAssignKeyButton->setPosition(165, 155); mAssignKeyButton->addActionListener(this); mAssignKeyButton->setEnabled(false); add(mAssignKeyButton); - mMakeDefaultButton = new Button("Default", "makeDefault", this); + mMakeDefaultButton = new Button(_("Default"), "makeDefault", this); mMakeDefaultButton->setPosition(10, 155); mMakeDefaultButton->addActionListener(this); add(mMakeDefaultButton); @@ -111,8 +112,9 @@ void Setup_Keyboard::apply() if (keyboard.hasConflicts()) { - new OkDialog("Key Conflict(s) Detected.", - "Resolve them, or gameplay may result in strange behaviour."); + new OkDialog(_("Key Conflict(s) Detected."), + _("Resolve them, or gameplay may result in strange " + "behaviour.")); } keyboard.setEnabled(true); keyboard.store(); @@ -170,7 +172,7 @@ void Setup_Keyboard::newKeyCallback(int index) void Setup_Keyboard::refreshKeys() { - for(int i = 0; i < keyboard.KEY_TOTAL; i++) + for (int i = 0; i < keyboard.KEY_TOTAL; i++) { refreshAssignedKey(i); } diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp index c556a82d..122f54e1 100644 --- a/src/gui/setup_players.cpp +++ b/src/gui/setup_players.cpp @@ -30,6 +30,8 @@ #include "../log.h" #include "../sound.h" +#include "../utils/gettext.h" + #include <guichan/widgets/dropdown.hpp> #include <guichan/widgets/label.hpp> @@ -47,10 +49,16 @@ #define WIDGET_AT(row, column) (((row) * COLUMNS_NR) + column) -static std::string table_titles[COLUMNS_NR] = {"name", "relation"}; +static const char *table_titles[COLUMNS_NR] = { + N_("Name"), + N_("Relation") +}; -static const std::string RELATION_NAMES[PlayerRelation::RELATIONS_NR] = { - "neutral", "friend", "disregarded", "ignored" +static const char *RELATION_NAMES[PlayerRelation::RELATIONS_NR] = { + N_("Neutral"), + N_("Friend"), + N_("Disregarded"), + N_("Ignored") }; class PlayerRelationListModel : public gcn::ListModel @@ -67,7 +75,7 @@ public: { if (i >= getNumberOfElements() || i < 0) return ""; - return RELATION_NAMES[i]; + return gettext(RELATION_NAMES[i]); } }; @@ -136,7 +144,8 @@ public: virtual void updateModelInRow(int row) { - gcn::DropDown *choicebox = dynamic_cast<gcn::DropDown *>(getElementAt(row, RELATION_CHOICE_COLUMN)); + gcn::DropDown *choicebox = dynamic_cast<gcn::DropDown *>( + getElementAt(row, RELATION_CHOICE_COLUMN)); player_relations.setRelation(getPlayerAt(row), static_cast<PlayerRelation::relation>(choicebox->getSelected())); } @@ -202,21 +211,27 @@ Setup_Players::Setup_Players(): mPlayerTable(new GuiTable(mPlayerTableModel)), mPlayerTitleTable(new GuiTable(mPlayerTableTitleModel)), mPlayerScrollArea(new ScrollArea(mPlayerTable)), - mPersistIgnores(new CheckBox("save player list", player_relations.getPersistIgnores())), - mDefaultTrading(new CheckBox("allow trading", player_relations.getDefault() & PlayerRelation::TRADE)), - mDefaultWhisper(new CheckBox("allow whispers", player_relations.getDefault() & PlayerRelation::WHISPER)), - mDeleteButton(new Button("Delete", ACTION_DELETE, this)), + mPersistIgnores(new CheckBox(_("Save player list"), + player_relations.getPersistIgnores())), + mDefaultTrading(new CheckBox(_("Allow trading"), + player_relations.getDefault() & PlayerRelation::TRADE)), + mDefaultWhisper(new CheckBox(_("Allow whispers"), + player_relations.getDefault() & PlayerRelation::WHISPER)), + mDeleteButton(new Button(_("Delete"), ACTION_DELETE, this)), mIgnoreActionChoicesBox(new gcn::DropDown(new IgnoreChoicesListModel())) { setOpaque(false); int table_width = NAME_COLUMN_WIDTH + RELATION_CHOICE_COLUMN_WIDTH; mPlayerTableTitleModel->fixColumnWidth(NAME_COLUMN, NAME_COLUMN_WIDTH); - mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN, RELATION_CHOICE_COLUMN_WIDTH); + mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN, + RELATION_CHOICE_COLUMN_WIDTH); mPlayerTitleTable->setDimension(gcn::Rectangle(10, 10, table_width, 10)); mPlayerTitleTable->setBackgroundColor(gcn::Color(0xbf, 0xbf, 0xbf)); - for (int i = 0; i < COLUMNS_NR; i++) - mPlayerTableTitleModel->set(0, i, new gcn::Label(table_titles[i])); + for (int i = 0; i < COLUMNS_NR; i++) { + mPlayerTableTitleModel->set(0, i, + new gcn::Label(gettext(table_titles[i]))); + } mPlayerTitleTable->setLinewiseSelection(true); mPlayerScrollArea->setDimension(gcn::Rectangle(10, 25, table_width + COLUMNS_NR, 90)); @@ -227,7 +242,7 @@ Setup_Players::Setup_Players(): mDeleteButton->setPosition(10, 118); - gcn::Label *ignore_action_label = new gcn::Label("When ignoring:"); + gcn::Label *ignore_action_label = new gcn::Label(_("When ignoring:")); ignore_action_label->setPosition(80, 118); mIgnoreActionChoicesBox->setDimension(gcn::Rectangle(80, 132, 120, 12)); @@ -269,9 +284,9 @@ Setup_Players::~Setup_Players() void Setup_Players::reset() { - // We now have to search through the list of ignore choices to find the current - // selection. We could use an index into the table of config options in - // player_relations instead of strategies to sidestep this. + // We now have to search through the list of ignore choices to find the + // current selection. We could use an index into the table of config + // options in player_relations instead of strategies to sidestep this. int selection = 0; for (unsigned int i = 0; i < player_relations.getPlayerIgnoreStrategies()->size(); ++i) if ((*player_relations.getPlayerIgnoreStrategies())[i] == @@ -303,9 +318,10 @@ void Setup_Players::cancel() void Setup_Players::action(const gcn::ActionEvent &event) { if (event.getId() == ACTION_TABLE) { - // temporarily eliminate ourselves: we are fully aware of this change, so there is no - // need for asynchronous updates. (In fact, thouse might destroy the widet that - // triggered them, which would be rather embarrassing.) + // temporarily eliminate ourselves: we are fully aware of this change, + // so there is no need for asynchronous updates. (In fact, thouse + // might destroy the widet that triggered them, which would be rather + // embarrassing.) player_relations.removeListener(this); int row = mPlayerTable->getSelectedRow(); @@ -336,6 +352,8 @@ void Setup_Players::action(const gcn::ActionEvent &event) void Setup_Players::updatedPlayer(const std::string &name) { mPlayerTableModel->playerRelationsUpdated(); - mDefaultTrading->setSelected(player_relations.getDefault() & PlayerRelation::TRADE); - mDefaultWhisper->setSelected(player_relations.getDefault() & PlayerRelation::WHISPER); + mDefaultTrading->setSelected( + player_relations.getDefault() & PlayerRelation::TRADE); + mDefaultWhisper->setSelected( + player_relations.getDefault() & PlayerRelation::WHISPER); } diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 23d2d9c2..cc39caed 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -43,6 +43,7 @@ #include "../main.h" #include "../particle.h" +#include "../utils/gettext.h" #include "../utils/tostring.h" extern Graphics *graphics; @@ -108,11 +109,11 @@ Setup_Video::Setup_Video(): mFps((int) config.getValue("fpslimit", 0)), mModeListModel(new ModeListModel), mModeList(new ListBox(mModeListModel)), - mFsCheckBox(new CheckBox("Full screen", mFullScreenEnabled)), - mOpenGLCheckBox(new CheckBox("OpenGL", mOpenGLEnabled)), - mCustomCursorCheckBox(new CheckBox("Custom cursor", mCustomCursorEnabled)), + mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)), + mOpenGLCheckBox(new CheckBox(_("OpenGL"), mOpenGLEnabled)), + mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)), mAlphaSlider(new Slider(0.2, 1.0)), - mFpsCheckBox(new CheckBox("FPS Limit: ")), + mFpsCheckBox(new CheckBox(_("FPS Limit:"))), mFpsSlider(new Slider(10, 200)), mFpsField(new TextField), mOriginalScrollLaziness((int) config.getValue("ScrollLaziness", 16)), @@ -131,7 +132,7 @@ Setup_Video::Setup_Video(): setOpaque(false); ScrollArea *scrollArea = new ScrollArea(mModeList); - gcn::Label *alphaLabel = new gcn::Label("Gui opacity"); + gcn::Label *alphaLabel = new gcn::Label(_("Gui opacity")); mModeList->setEnabled(false); #ifndef USE_OPENGL @@ -188,7 +189,7 @@ Setup_Video::Setup_Video(): mParticleDetailField->addKeyListener(this); mScrollRadiusSlider->setDimension(gcn::Rectangle(10, 120, 75, 10)); - gcn::Label *scrollRadiusLabel = new gcn::Label("Scroll radius"); + gcn::Label *scrollRadiusLabel = new gcn::Label(_("Scroll radius")); scrollRadiusLabel->setPosition(90, 120); mScrollRadiusField->setPosition(mFpsField->getX(), 120); mScrollRadiusField->setWidth(30); @@ -196,7 +197,7 @@ Setup_Video::Setup_Video(): mScrollRadiusSlider->setValue(mOriginalScrollRadius); mScrollLazinessSlider->setDimension(gcn::Rectangle(10, 140, 75, 10)); - gcn::Label *scrollLazinessLabel = new gcn::Label("Scroll laziness"); + gcn::Label *scrollLazinessLabel = new gcn::Label(_("Scroll laziness")); scrollLazinessLabel->setPosition(90, 140); mScrollLazinessField->setPosition(mFpsField->getX(), 140); mScrollLazinessField->setWidth(30); @@ -204,42 +205,42 @@ Setup_Video::Setup_Video(): mScrollLazinessSlider->setValue(mOriginalScrollLaziness); mOverlayDetailSlider->setDimension(gcn::Rectangle(10, 160, 75, 10)); - gcn::Label *overlayDetailLabel = new gcn::Label("Ambient FX"); + gcn::Label *overlayDetailLabel = new gcn::Label(_("Ambient FX")); overlayDetailLabel->setPosition(90, 160); mOverlayDetailField->setPosition(180, 160); mOverlayDetailField->setWidth(30); switch (mOverlayDetail) { case 0: - mOverlayDetailField->setCaption("off"); + mOverlayDetailField->setCaption(_("off")); break; case 1: - mOverlayDetailField->setCaption("low"); + mOverlayDetailField->setCaption(_("low")); break; case 2: - mOverlayDetailField->setCaption("high"); + mOverlayDetailField->setCaption(_("high")); break; } mOverlayDetailSlider->setValue(mOverlayDetail); mParticleDetailSlider->setDimension(gcn::Rectangle(10, 180, 75, 10)); - gcn::Label *particleDetailLabel = new gcn::Label("Particle Detail"); + gcn::Label *particleDetailLabel = new gcn::Label(_("Particle Detail")); particleDetailLabel->setPosition(90, 180); mParticleDetailField->setPosition(180, 180); mParticleDetailField->setWidth(60); switch (mParticleDetail) { case 0: - mParticleDetailField->setCaption("low"); + mParticleDetailField->setCaption(_("low")); break; case 1: - mParticleDetailField->setCaption("medium"); + mParticleDetailField->setCaption(_("medium")); break; case 2: - mParticleDetailField->setCaption("high"); + mParticleDetailField->setCaption(_("high")); break; case 3: - mParticleDetailField->setCaption("max"); + mParticleDetailField->setCaption(_("max")); break; } mParticleDetailSlider->setValue(mParticleDetail); @@ -305,8 +306,8 @@ void Setup_Video::apply() } #if defined(WIN32) || defined(__APPLE__) } else { - new OkDialog("Switching to full screen", - "Restart needed for changes to take effect."); + new OkDialog(_("Switching to full screen"), + _("Restart needed for changes to take effect.")); } #endif config.setValue("screen", fullscreen ? 1 : 0); @@ -318,8 +319,8 @@ void Setup_Video::apply() config.setValue("opengl", mOpenGLCheckBox->isSelected() ? 1 : 0); // OpenGL can currently only be changed by restarting, notify user. - new OkDialog("Changing OpenGL", - "Applying change to OpenGL requires restart."); + new OkDialog(_("Changing OpenGL"), + _("Applying change to OpenGL requires restart.")); } // FPS change @@ -408,13 +409,13 @@ void Setup_Video::action(const gcn::ActionEvent &event) switch (val) { case 0: - mOverlayDetailField->setCaption("off"); + mOverlayDetailField->setCaption(_("off")); break; case 1: - mOverlayDetailField->setCaption("low"); + mOverlayDetailField->setCaption(_("low")); break; case 2: - mOverlayDetailField->setCaption("high"); + mOverlayDetailField->setCaption(_("high")); break; } config.setValue("OverlayDetail", val); @@ -425,16 +426,16 @@ void Setup_Video::action(const gcn::ActionEvent &event) switch (val) { case 0: - mParticleDetailField->setCaption("low"); + mParticleDetailField->setCaption(_("low")); break; case 1: - mParticleDetailField->setCaption("medium"); + mParticleDetailField->setCaption(_("medium")); break; case 2: - mParticleDetailField->setCaption("high"); + mParticleDetailField->setCaption(_("high")); break; case 3: - mParticleDetailField->setCaption("max"); + mParticleDetailField->setCaption(_("max")); break; } config.setValue("particleEmitterSkip", 3 - val); diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 82108f84..8b8c58cd 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -29,12 +29,14 @@ #include "windowcontainer.h" #include "../localplayer.h" +#include "../log.h" #include "../utils/dtor.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" #include "../utils/xml.h" -#include "../log.h" -#define SKILLS_FILE "skills.xml" +static const char *SKILLS_FILE = "skills.xml"; struct SkillInfo { std::string name; @@ -73,7 +75,10 @@ public: virtual void update() { - static const SkillInfo fakeSkillInfo = { "Mystery Skill", false }; + static const SkillInfo fakeSkillInfo = { + _("Mystery Skill"), + false + }; mEntriesNr = mDialog->getSkills().size(); resize(); @@ -90,13 +95,13 @@ public: info = &fakeSkillInfo; sprintf(tmp, "%c%s", info->modifiable? ' ' : '*', info->name.c_str()); - gcn::Label *name_label = new gcn::Label(std::string(tmp)); + gcn::Label *name_label = new gcn::Label(tmp); sprintf(tmp, "Lv:%i", skill->lv); - gcn::Label *lv_label = new gcn::Label(std::string(tmp)); + gcn::Label *lv_label = new gcn::Label(tmp); sprintf(tmp, "Sp:%i", skill->sp); - gcn::Label *sp_label = new gcn::Label(std::string(tmp)); + gcn::Label *sp_label = new gcn::Label(tmp); set(i, 0, name_label); set(i, 1, lv_label); @@ -111,7 +116,7 @@ private: SkillDialog::SkillDialog(): - Window("Skills") + Window(_("Skills")) { initSkillinfo(); mTableModel = new SkillGuiTableModel(this); @@ -124,9 +129,9 @@ SkillDialog::SkillDialog(): // mSkillListBox = new ListBox(this); ScrollArea *skillScrollArea = new ScrollArea(&mTable); - mPointsLabel = new gcn::Label("Skill Points:"); - mIncButton = new Button("Up", "inc", this); - mUseButton = new Button("Use", "use", this); + mPointsLabel = new gcn::Label(strprintf(_("Skill points: %d"), 0)); + mIncButton = new Button(_("Up"), "inc", this); + mUseButton = new Button(_("Use"), "use", this); mUseButton->setEnabled(false); // mSkillListBox->setActionEventId("skill"); @@ -180,11 +185,8 @@ void SkillDialog::action(const gcn::ActionEvent &event) void SkillDialog::update() { - if (mPointsLabel != NULL) { - char tmp[128]; - sprintf(tmp, "Skill points: %i", player_node->mSkillPoint); - mPointsLabel->setCaption(tmp); - } + mPointsLabel->setCaption(strprintf(_("Skill points: %d"), + player_node->mSkillPoint)); int selectedSkill = mTable.getSelectedRow(); @@ -254,8 +256,7 @@ static void initSkillinfo() if (!root || !xmlStrEqual(root->name, BAD_CAST "skills")) { - logger->log("Error loading skills file: " - 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/status.cpp b/src/gui/status.cpp index 1a257ae8..a5bb77c3 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -29,6 +29,8 @@ #include "../localplayer.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" #include "../utils/tostring.h" StatusWindow::StatusWindow(LocalPlayer *player): @@ -46,25 +48,25 @@ StatusWindow::StatusWindow(LocalPlayer *player): // Status Part // ---------------------- - mLvlLabel = new gcn::Label("Level:"); - mGpLabel = new gcn::Label("Money:"); - mJobLvlLabel = new gcn::Label("Job:"); + mLvlLabel = new gcn::Label(strprintf(_("Level: %d"), 0)); + mGpLabel = new gcn::Label(strprintf(_("Job: %d"), 0)); + mJobLvlLabel = new gcn::Label(strprintf(_("Money: %d GP"), 0)); mHpLabel = new gcn::Label("HP:"); mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34); - mHpValueLabel = new gcn::Label(""); + mHpValueLabel = new gcn::Label; mXpLabel = new gcn::Label("Exp:"); mXpBar = new ProgressBar(1.0f, 80, 15, 143, 192, 211); - mXpValueLabel = new gcn::Label(""); + mXpValueLabel = new gcn::Label; mMpLabel = new gcn::Label("MP:"); mMpBar = new ProgressBar(1.0f, 80, 15, 26, 102, 230); - mMpValueLabel = new gcn::Label(""); + mMpValueLabel = new gcn::Label; mJobXpLabel = new gcn::Label("Job:"); mJobXpBar = new ProgressBar(1.0f, 80, 15, 220, 135, 203); - mJobValueLabel = new gcn::Label(""); + mJobValueLabel = new gcn::Label; int y = 3; int x = 5; @@ -122,34 +124,34 @@ StatusWindow::StatusWindow(LocalPlayer *player): // ---------------------- // Static Labels - gcn::Label *mStatsTitleLabel = new gcn::Label("Stats"); - gcn::Label *mStatsTotalLabel = new gcn::Label("Total"); - gcn::Label *mStatsCostLabel = new gcn::Label("Cost"); + gcn::Label *mStatsTitleLabel = new gcn::Label(_("Stats")); + gcn::Label *mStatsTotalLabel = new gcn::Label(_("Total")); + gcn::Label *mStatsCostLabel = new gcn::Label(_("Cost")); // Derived Stats - mStatsAttackLabel = new gcn::Label("Attack:"); - mStatsDefenseLabel= new gcn::Label("Defense:"); - mStatsMagicAttackLabel = new gcn::Label("M.Attack:"); - mStatsMagicDefenseLabel = new gcn::Label("M.Defense:"); - mStatsAccuracyLabel = new gcn::Label("% Accuracy:"); - mStatsEvadeLabel = new gcn::Label("% Evade:"); - mStatsReflexLabel = new gcn::Label("% Reflex:"); - - mStatsAttackPoints = new gcn::Label(""); - mStatsDefensePoints = new gcn::Label(""); - mStatsMagicAttackPoints = new gcn::Label(""); - mStatsMagicDefensePoints = new gcn::Label(""); - mStatsAccuracyPoints = new gcn::Label("% Accuracy:"); - mStatsEvadePoints = new gcn::Label("% Evade:"); - mStatsReflexPoints = new gcn::Label("% Reflex:"); + mStatsAttackLabel = new gcn::Label(_("Attack:")); + mStatsDefenseLabel= new gcn::Label(_("Defense:")); + mStatsMagicAttackLabel = new gcn::Label(_("M.Attack:")); + mStatsMagicDefenseLabel = new gcn::Label(_("M.Defense:")); + mStatsAccuracyLabel = new gcn::Label(_("% Accuracy:")); + mStatsEvadeLabel = new gcn::Label(_("% Evade:")); + mStatsReflexLabel = new gcn::Label(_("% Reflex:")); + + mStatsAttackPoints = new gcn::Label; + mStatsDefensePoints = new gcn::Label; + mStatsMagicAttackPoints = new gcn::Label; + mStatsMagicDefensePoints = new gcn::Label; + mStatsAccuracyPoints = new gcn::Label; + mStatsEvadePoints = new gcn::Label; + mStatsReflexPoints = new gcn::Label; // New labels for (int i = 0; i < 6; i++) { - mStatsLabel[i] = new gcn::Label(); - mStatsDisplayLabel[i] = new gcn::Label(); + mStatsLabel[i] = new gcn::Label; + mStatsDisplayLabel[i] = new gcn::Label; mPointsLabel[i] = new gcn::Label("0"); } - mRemainingStatsPointsLabel = new gcn::Label(); + mRemainingStatsPointsLabel = new gcn::Label; // Set button events Id mStatsButton[0] = new Button("+", "STR", this); @@ -227,13 +229,13 @@ void StatusWindow::update() { // Status Part // ----------- - mLvlLabel->setCaption("Level: " + toString(mPlayer->mLevel)); + mLvlLabel->setCaption(strprintf(_("Level: %d"), mPlayer->mLevel)); mLvlLabel->adjustSize(); - mJobLvlLabel->setCaption("Job: " + toString(mPlayer->mJobLevel)); + mJobLvlLabel->setCaption(strprintf(_("Job: %d"), mPlayer->mJobLevel)); mJobLvlLabel->adjustSize(); - mGpLabel->setCaption("Money: " + toString(mPlayer->mGp) + " GP"); + mGpLabel->setCaption(strprintf(_("Money: %d GP"), mPlayer->mGp)); mGpLabel->adjustSize(); mHpValueLabel->setCaption(toString(mPlayer->mHp) + @@ -276,20 +278,20 @@ void StatusWindow::update() // Stats Part // ---------- - static const std::string attrNames[6] = { - "Strength", - "Agility", - "Vitality", - "Intelligence", - "Dexterity", - "Luck" + static const char *attrNames[6] = { + N_("Strength"), + N_("Agility"), + N_("Vitality"), + N_("Intelligence"), + N_("Dexterity"), + N_("Luck") }; int statusPoints = mPlayer->mStatsPointsToAttribute; // Update labels for (int i = 0; i < 6; i++) { - mStatsLabel[i]->setCaption(attrNames[i]); + mStatsLabel[i]->setCaption(gettext(attrNames[i])); mStatsDisplayLabel[i]->setCaption(toString((int) mPlayer->mAttr[i])); mPointsLabel[i]->setCaption(toString((int) mPlayer->mAttrUp[i])); @@ -299,8 +301,8 @@ void StatusWindow::update() mStatsButton[i]->setEnabled(mPlayer->mAttrUp[i] <= statusPoints); } - mRemainingStatsPointsLabel->setCaption("Remaining Status Points: " + - toString(statusPoints)); + mRemainingStatsPointsLabel->setCaption( + strprintf(_("Remaining Status Points: %d"), statusPoints)); mRemainingStatsPointsLabel->adjustSize(); // Derived Stats Points @@ -353,12 +355,12 @@ void StatusWindow::update() mXpBar->getX() + mXpBar->getWidth() + 5, mXpLabel->getY()); - mJobXpLabel->setPosition(mXpBar->getX() - mJobXpLabel->getWidth() - 5, + mJobXpLabel->setPosition(mXpBar->getX() - mJobXpLabel->getWidth() - 5, mMpLabel->getY()); mJobXpBar->setPosition( mJobXpLabel->getX() + mJobXpLabel->getWidth() + 5, mJobXpLabel->getY()); - mJobValueLabel->setPosition(mJobXpBar->getX() + mJobXpBar->getWidth() + 5, + mJobValueLabel->setPosition(mJobXpBar->getX() + mJobXpBar->getWidth() + 5, mJobXpLabel->getY()); } diff --git a/src/gui/textfield.cpp b/src/gui/textfield.cpp index ea82ba77..bbedb29d 100644 --- a/src/gui/textfield.cpp +++ b/src/gui/textfield.cpp @@ -19,11 +19,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "textfield.h" + #include <algorithm> #include <guichan/font.hpp> -#include "textfield.h" +#include "sdlinput.h" #include "../graphics.h" @@ -32,6 +34,8 @@ #include "../utils/dtor.h" +#undef DELETE //Win32 compatibility hack + int TextField::instances = 0; ImageRect TextField::skin; @@ -100,3 +104,99 @@ void TextField::drawFrame(gcn::Graphics *graphics) static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin); } + +void TextField::keyPressed(gcn::KeyEvent &keyEvent) +{ + int val = keyEvent.getKey().getValue(); + + if (val >= 32) + { + int l; + if (val < 128) l = 1; // 0xxxxxxx + else if (val < 0x800) l = 2; // 110xxxxx 10xxxxxx + else if (val < 0x10000) l = 3; // 1110xxxx 10xxxxxx 10xxxxxx + else l = 4; // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + char buf[4]; + for (int i = 0; i < l; ++i) + { + buf[i] = val >> (6 * (l - i - 1)); + if (i > 0) buf[i] = (buf[i] & 63) | 128; + } + + if (l > 1) buf[0] |= 255 << (8 - l); + + mText.insert(mCaretPosition, std::string(buf, buf + l)); + mCaretPosition += l; + } + + /* In UTF-8, 10xxxxxx is only used for inner parts of characters. So skip + them when processing key presses. */ + + switch (val) + { + case Key::LEFT: + { + while (mCaretPosition > 0) + { + --mCaretPosition; + if ((mText[mCaretPosition] & 192) != 128) + break; + } + } break; + + case Key::RIGHT: + { + unsigned sz = mText.size(); + while (mCaretPosition < sz) + { + ++mCaretPosition; + if (mCaretPosition == sz || + (mText[mCaretPosition] & 192) != 128) + break; + } + } break; + + case Key::DELETE: + { + unsigned sz = mText.size(); + while (mCaretPosition < sz) + { + --sz; + mText.erase(mCaretPosition, 1); + if (mCaretPosition == sz || + (mText[mCaretPosition] & 192) != 128) + break; + } + } break; + + case Key::BACKSPACE: + { + while (mCaretPosition > 0) + { + --mCaretPosition; + int v = mText[mCaretPosition]; + mText.erase(mCaretPosition, 1); + if ((v & 192) != 128) break; + } + } break; + + case Key::ENTER: + distributeActionEvent(); + break; + + case Key::HOME: + mCaretPosition = 0; + break; + + case Key::END: + mCaretPosition = mText.size(); + break; + + case Key::TAB: + return; + } + + keyEvent.consume(); + fixScroll(); +} diff --git a/src/gui/textfield.h b/src/gui/textfield.h index 60a50c69..b808fad2 100644 --- a/src/gui/textfield.h +++ b/src/gui/textfield.h @@ -53,6 +53,11 @@ class TextField : public gcn::TextField { */ void drawFrame(gcn::Graphics *graphics); + /** + * Processes one keypress. + */ + void keyPressed(gcn::KeyEvent &keyEvent); + private: static int instances; static ImageRect skin; diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp index 9347cc02..405d871f 100644 --- a/src/gui/trade.cpp +++ b/src/gui/trade.cpp @@ -41,6 +41,8 @@ #include "../resources/iteminfo.h" +#include "../utils/gettext.h" +#include "../utils/strprintf.h" #include "../utils/tostring.h" TradeWindow::TradeWindow(Network *network): @@ -56,10 +58,10 @@ TradeWindow::TradeWindow(Network *network): setMinWidth(342); setMinHeight(209); - mAddButton = new Button("Add", "add", this); - mOkButton = new Button("Ok", "ok", this); - mCancelButton = new Button("Cancel", "cancel", this); - mTradeButton = new Button("Trade", "trade", this); + mAddButton = new Button(_("Add"), "add", this); + mOkButton = new Button(_("Ok"), "ok", this); + mCancelButton = new Button(_("Cancel"), "cancel", this); + mTradeButton = new Button(_("Trade"), "trade", this); mMyItemContainer = new ItemContainer(mMyInventory.get()); mMyItemContainer->addSelectionListener(this); @@ -75,8 +77,8 @@ TradeWindow::TradeWindow(Network *network): mPartnerScroll = new ScrollArea(mPartnerItemContainer); mPartnerScroll->setPosition(8, 64); - mMoneyLabel = new gcn::Label("You get: 0 GP"); - mMoneyLabel2 = new gcn::Label("You give:"); + mMoneyLabel = new gcn::Label(strprintf(_("You get %d GP."), 0)); + mMoneyLabel2 = new gcn::Label(_("You give:")); mMoneyField = new TextField; mMoneyField->setWidth(50); @@ -87,8 +89,9 @@ TradeWindow::TradeWindow(Network *network): mTradeButton->setEnabled(false); - mItemNameLabel = new gcn::Label("Name:"); - mItemDescriptionLabel = new gcn::Label("Description:"); + mItemNameLabel = new gcn::Label(strprintf(_("Name: %s"), "")); + mItemDescriptionLabel = new gcn::Label( + strprintf(_("Description: %s"), "")); add(mMyScroll); add(mPartnerScroll); @@ -150,7 +153,7 @@ void TradeWindow::widgetResized(const gcn::Event &event) void TradeWindow::addMoney(int amount) { - mMoneyLabel->setCaption("You get: " + toString(amount) + " GP"); + mMoneyLabel->setCaption(strprintf(_("You get %d GP."), amount)); mMoneyLabel->adjustSize(); } @@ -198,7 +201,7 @@ void TradeWindow::reset() mOkButton->setEnabled(true); mOkOther = false; mOkMe = false; - mMoneyLabel->setCaption("You get: 0 GP"); + mMoneyLabel->setCaption(strprintf(_("You get %d GP."), 0)); mMoneyField->setEnabled(true); mMoneyField->setText(""); } @@ -257,21 +260,11 @@ void TradeWindow::valueChanged(const gcn::SelectionEvent &event) } // Update name and description - if (!item) - { - mItemNameLabel->setCaption("Name:"); - mItemDescriptionLabel->setCaption("Description:"); - } - else - { - std::string SomeText; - SomeText = "Name: " + item->getInfo().getName(); - mItemNameLabel->setCaption(SomeText); - mItemNameLabel->adjustSize(); - SomeText = "Description: " + item->getInfo().getDescription(); - mItemDescriptionLabel->setCaption(SomeText); - mItemDescriptionLabel->adjustSize(); - } + ItemInfo const *info = item ? &item->getInfo() : NULL; + mItemNameLabel->setCaption(strprintf(_("Name: %s"), + info ? info->getName().c_str() : "")); + mItemDescriptionLabel->setCaption(strprintf(_("Description: %s"), + info ? info->getDescription().c_str() : "")); } void TradeWindow::action(const gcn::ActionEvent &event) @@ -287,8 +280,8 @@ void TradeWindow::action(const gcn::ActionEvent &event) return; if (mMyInventory->contains(item)) { - chatWindow->chatLog("Failed adding item. You can not " - "overlap one kind of item on the window.", BY_SERVER); + chatWindow->chatLog(_("Failed adding item. You can not " + "overlap one kind of item on the window."), BY_SERVER); return; } diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp index 7f9abd3a..0eed6f08 100644 --- a/src/gui/truetypefont.cpp +++ b/src/gui/truetypefont.cpp @@ -17,8 +17,6 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ */ #include "truetypefont.h" @@ -47,8 +45,7 @@ class TextChunk bool operator==(const TextChunk &chunk) const { - return ( - chunk.text == text && chunk.color == color); + return (chunk.text == text && chunk.color == color); } void generate(TTF_Font *font) @@ -84,7 +81,7 @@ typedef std::list<TextChunk>::iterator CacheIterator; static int fontCounter; -TrueTypeFont::TrueTypeFont(const std::string& filename, int size) +TrueTypeFont::TrueTypeFont(const std::string &filename, int size) { if (fontCounter == 0 && TTF_Init() == -1) { @@ -167,7 +164,7 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics, g->drawImage(cache.front().img, x, y); } -int TrueTypeFont::getWidth(const std::string& text) const +int TrueTypeFont::getWidth(const std::string &text) const { int w, h; TTF_SizeUTF8(mFont, text.c_str(), &w, &h); diff --git a/src/gui/truetypefont.h b/src/gui/truetypefont.h index 48502f1f..e8617c7d 100644 --- a/src/gui/truetypefont.h +++ b/src/gui/truetypefont.h @@ -17,8 +17,6 @@ * You should have received a copy of the GNU General Public License * along with The Mana World; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ */ #ifndef _TMW_TRUETYPEFONT_H @@ -44,74 +42,7 @@ class TrueTypeFont : public gcn::Font * @param filename Font filename. * @param size Font size. */ - TrueTypeFont(const std::string& filename, int size); - - /** - * Destructor. - */ - ~TrueTypeFont(); - - virtual int getWidth(const std::string& text) const; - - virtual int getHeight() const; - - /** - * @see Font::drawString - */ - void drawString(gcn::Graphics* graphics, const std::string& text, int x, int y); - - private: - TTF_Font *mFont; -}; - -#endif -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * The Mana World is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_TRUETYPEFONT_H -#define _TMW_TRUETYPEFONT_H - -#include <string> - -#include <guichan/font.hpp> -#include <guichan/graphics.hpp> -#include <SDL/SDL_ttf.h> - -/** - * A wrapper around SDL_ttf for allowing the use of TrueType fonts. - * - * <b>NOTE:</b> This class needs SDL_ttf to be initialized. - */ -class TrueTypeFont : public gcn::Font -{ - public: - /** - * Constructor. - * - * @param filename Font filename. - * @param size Font size. - */ - TrueTypeFont(const std::string& filename, int size); + TrueTypeFont(const std::string &filename, int size); /** * Destructor. @@ -125,7 +56,9 @@ class TrueTypeFont : public gcn::Font /** * @see Font::drawString */ - void drawString(gcn::Graphics* graphics, const std::string& text, int x, int y); + void drawString(gcn::Graphics *graphics, + const std::string &text, + int x, int y); private: TTF_Font *mFont; diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 7f7d45fc..a6857d21 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -40,6 +40,7 @@ #include "../log.h" #include "../main.h" +#include "../utils/gettext.h" #include "../utils/tostring.h" #include "../resources/resourcemanager.h" @@ -89,7 +90,7 @@ loadTextFile(const std::string &fileName) UpdaterWindow::UpdaterWindow(const std::string &updateHost, const std::string &updatesDir): - Window("Updating..."), + Window(_("Updating...")), mThread(NULL), mDownloadStatus(UPDATE_NEWS), mUpdateHost(updateHost), @@ -112,10 +113,10 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost, mBrowserBox = new BrowserBox(); mScrollArea = new ScrollArea(mBrowserBox); - mLabel = new gcn::Label("Connecting..."); + mLabel = new gcn::Label(_("Connecting...")); mProgressBar = new ProgressBar(0.0, w - 10, 20, 37, 70, 200); - mCancelButton = new Button("Cancel", "cancel", this); - mPlayButton = new Button("Play", "play", this); + mCancelButton = new Button(_("Cancel"), "cancel", this); + mPlayButton = new Button(_("Play"), "play", this); mBrowserBox->setOpaque(false); mPlayButton->setEnabled(false); @@ -228,8 +229,9 @@ int UpdaterWindow::updateProgress(void *ptr, float progress = dn / dt; UpdaterWindow *uw = reinterpret_cast<UpdaterWindow *>(ptr); - if (progress < 0) progress = 0.0f; - if (progress > 1) progress = 1.0f; + if (progress != progress) progress = 0.0f; // check for NaN + if (progress < 0.0f) progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway. + if (progress > 1.0f) progress = 1.0f; uw->setLabel( uw->mCurrentFile + " (" + toString((int) (progress * 100)) + "%)"); @@ -521,7 +523,7 @@ void UpdaterWindow::logic() break; case UPDATE_COMPLETE: enable(); - setLabel("Completed"); + setLabel(_("Completed")); break; case UPDATE_IDLE: break; diff --git a/src/gui/vbox.cpp b/src/gui/vbox.cpp deleted file mode 100644 index 2ec1112d..00000000 --- a/src/gui/vbox.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 "vbox.h" - -void VBox::draw(gcn::Graphics *graphics) -{ - if (mWidgets.empty()) - { - return; - } - - int childWidth = getWidth(); - int childHeight = getHeight() / mWidgets.size(); - int i = 0; - - for (WidgetIterator w = mWidgets.begin(); w != mWidgets.end(); w++) - { - (*w)->setPosition(0, childHeight * i - padding); - (*w)->setSize(childWidth, childHeight); - i++; - } - - gcn::Container::draw(graphics); -} diff --git a/src/gui/vbox.h b/src/gui/vbox.h deleted file mode 100644 index 2072ab24..00000000 --- a/src/gui/vbox.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 VBOX_H -#define VBOX_H - -#include "box.h" - -class VBox : public Box -{ - public: - void draw(gcn::Graphics *); -}; - -#endif diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 37aa40ce..9eab7c95 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -21,8 +21,6 @@ #include "viewport.h" -#include <guichan/sdl/sdlinput.hpp> - #include "gui.h" #include "popupmenu.h" #include "ministatus.h" diff --git a/src/gui/widgets/layout.cpp b/src/gui/widgets/layout.cpp new file mode 100644 index 00000000..bcc54cf7 --- /dev/null +++ b/src/gui/widgets/layout.cpp @@ -0,0 +1,327 @@ +/* + * 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 <cassert> + +#include "layout.h" + +ContainerPlacer ContainerPlacer::at(int x, int y) +{ + return ContainerPlacer(mContainer, &mCell->at(x, y)); +} + +LayoutCell &ContainerPlacer::operator() + (int x, int y, gcn::Widget *wg, int w, int h) +{ + mContainer->add(wg); + return mCell->place(wg, x, y, w, h); +} + +LayoutCell::~LayoutCell() +{ + if (mType == ARRAY) delete mArray; +} + +LayoutArray &LayoutCell::getArray() +{ + assert(mType != WIDGET); + if (mType == ARRAY) return *mArray; + mArray = new LayoutArray; + mType = ARRAY; + mExtent[0] = 1; + mExtent[1] = 1; + mPadding = 0; + mAlign[0] = FILL; + mAlign[1] = FILL; + return *mArray; +} + +void LayoutCell::reflow(int nx, int ny, int nw, int nh) +{ + assert(mType != NONE); + nx += mPadding; + ny += mPadding; + nw -= 2 * mPadding; + nh -= 2 * mPadding; + if (mType == ARRAY) + mArray->reflow(nx, ny, nw, nh); + else + mWidget->setDimension(gcn::Rectangle(nx, ny, nw, nh)); +} + +void LayoutCell::computeSizes() +{ + assert(mType == ARRAY); + + for (std::vector< std::vector< LayoutCell * > >::iterator + i = mArray->mCells.begin(), i_end = mArray->mCells.end(); + i != i_end; ++i) + { + for (std::vector< LayoutCell * >::iterator + j = i->begin(), j_end = i->end(); j != j_end; ++j) + { + LayoutCell *cell = *j; + if (cell && cell->mType == ARRAY) cell->computeSizes(); + } + } + + mSize[0] = mArray->getSize(0); + mSize[1] = mArray->getSize(1); +} + +LayoutArray::LayoutArray(): mSpacing(4) +{ +} + +LayoutArray::~LayoutArray() +{ + for (std::vector< std::vector< LayoutCell * > >::iterator + i = mCells.begin(), i_end = mCells.end(); i != i_end; ++i) + { + for (std::vector< LayoutCell * >::iterator + j = i->begin(), j_end = i->end(); j != j_end; ++j) + { + delete *j; + } + } +} + +LayoutCell &LayoutArray::at(int x, int y, int w, int h) +{ + resizeGrid(x + w, y + h); + LayoutCell *&cell = mCells[y][x]; + if (!cell) + { + cell = new LayoutCell; + } + return *cell; +} + +void LayoutArray::resizeGrid(int w, int h) +{ + bool extW = w && w > (int)mSizes[0].size(), + extH = h && h > (int)mSizes[1].size(); + if (!extW && !extH) return; + + if (extH) + { + mSizes[1].resize(h, Layout::AUTO_DEF); + mCells.resize(h); + if (!extW) w = mSizes[0].size(); + } + + if (extW) + { + mSizes[0].resize(w, Layout::AUTO_DEF); + } + + for (std::vector< std::vector< LayoutCell * > >::iterator + i = mCells.begin(), i_end = mCells.end(); i != i_end; ++i) + { + i->resize(w, NULL); + } +} + +void LayoutArray::setColWidth(int n, int w) +{ + resizeGrid(n + 1, 0); + mSizes[0][n] = w; +} + +void LayoutArray::setRowHeight(int n, int h) +{ + resizeGrid(0, n + 1); + mSizes[1][n] = h; +} + +void LayoutArray::matchColWidth(int n1, int n2) +{ + resizeGrid(std::max(n1, n2) + 1, 0); + std::vector< short > widths = getSizes(0, Layout::AUTO_DEF); + int s = std::max(widths[n1], widths[n2]); + mSizes[0][n1] = s; + mSizes[0][n2] = s; +} + +void LayoutArray::extend(int x, int y, int w, int h) +{ + LayoutCell &cell = at(x, y, w, h); + cell.mExtent[0] = w; + cell.mExtent[1] = h; +} + +LayoutCell &LayoutArray::place(gcn::Widget *widget, int x, int y, int w, int h) +{ + LayoutCell &cell = at(x, y, w, h); + assert(cell.mType == LayoutCell::NONE); + cell.mType = LayoutCell::WIDGET; + cell.mWidget = widget; + cell.mSize[0] = w == 1 ? widget->getWidth() : 0; + cell.mSize[1] = h == 1 ? widget->getHeight() : 0; + cell.mExtent[0] = w; + cell.mExtent[1] = h; + cell.mPadding = 0; + cell.mAlign[0] = LayoutCell::FILL; + cell.mAlign[1] = LayoutCell::FILL; + short &cs = mSizes[0][x], &rs = mSizes[1][y]; + if (cs == Layout::AUTO_DEF && w == 1) cs = 0; + if (rs == Layout::AUTO_DEF && h == 1) rs = 0; + return cell; +} + +void LayoutArray::align(int &pos, int &size, int dim, + LayoutCell const &cell, short *sizes) const +{ + int size_max = sizes[0]; + for (int i = 1; i < cell.mExtent[dim]; ++i) + size_max += sizes[i] + mSpacing; + size = std::min<int>(cell.mSize[dim], size_max); + + switch (cell.mAlign[dim]) + { + case LayoutCell::LEFT: + return; + case LayoutCell::RIGHT: + pos += size_max - size; + return; + case LayoutCell::CENTER: + pos += (size_max - size) / 2; + return; + case LayoutCell::FILL: + size = size_max; + return; + } +} + +std::vector< short > LayoutArray::getSizes(int dim, int upp) const +{ + int gridW = mSizes[0].size(), gridH = mSizes[1].size(); + std::vector< short > sizes = mSizes[dim]; + + // Compute minimum sizes. + for (int gridY = 0; gridY < gridH; ++gridY) + { + for (int gridX = 0; gridX < gridW; ++gridX) + { + LayoutCell const *cell = mCells[gridY][gridX]; + if (!cell || cell->mType == LayoutCell::NONE) continue; + + if (cell->mExtent[dim] == 1) + { + int n = dim == 0 ? gridX : gridY; + int s = cell->mSize[dim] + cell->mPadding * 2; + if (s > sizes[n]) sizes[n] = s; + } + } + } + + if (upp == Layout::AUTO_DEF) return sizes; + + // Compute the FILL sizes. + int nb = sizes.size(); + int nbFill = 0; + for (int i = 0; i < nb; ++i) + { + if (mSizes[dim][i] <= Layout::AUTO_DEF) + { + ++nbFill; + if (mSizes[dim][i] == Layout::AUTO_SET || + sizes[i] <= Layout::AUTO_DEF) + { + sizes[i] = 0; + } + } + upp -= sizes[i] + mSpacing; + } + upp = upp + mSpacing; + + if (nbFill == 0) return sizes; + + for (int i = 0; i < nb; ++i) + { + if (mSizes[dim][i] > Layout::AUTO_DEF) continue; + int s = upp / nbFill; + sizes[i] += s; + upp -= s; + --nbFill; + } + + return sizes; +} + +int LayoutArray::getSize(int dim) const +{ + std::vector< short > sizes = getSizes(dim, Layout::AUTO_DEF); + int size = 0; + int nb = sizes.size(); + for (int i = 0; i < nb; ++i) + { + if (sizes[i] > Layout::AUTO_DEF) size += sizes[i]; + size += mSpacing; + } + return size - mSpacing; +} + +void LayoutArray::reflow(int nx, int ny, int nw, int nh) +{ + int gridW = mSizes[0].size(), gridH = mSizes[1].size(); + + std::vector< short > widths = getSizes(0, nw); + std::vector< short > heights = getSizes(1, nh); + + int y = ny; + for (int gridY = 0; gridY < gridH; ++gridY) + { + int x = nx; + for (int gridX = 0; gridX < gridW; ++gridX) + { + LayoutCell *cell = mCells[gridY][gridX]; + if (cell && cell->mType != LayoutCell::NONE) + { + int dx = x, dy = y, dw, dh; + align(dx, dw, 0, *cell, &widths[gridX]); + align(dy, dh, 1, *cell, &heights[gridY]); + cell->reflow(dx, dy, dw, dh); + } + x += widths[gridX] + mSpacing; + } + y += heights[gridY] + mSpacing; + } +} + +Layout::Layout(): mComputed(false) +{ + getArray(); + setPadding(6); +} + +void Layout::reflow(int &nw, int &nh) +{ + if (!mComputed) + { + computeSizes(); + mComputed = true; + } + + nw = nw == 0 ? mSize[0] + 2 * mPadding : nw; + nh = nh == 0 ? mSize[1] + 2 * mPadding : nh; + LayoutCell::reflow(0, 0, nw, nh); +} diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h new file mode 100644 index 00000000..d631c154 --- /dev/null +++ b/src/gui/widgets/layout.h @@ -0,0 +1,320 @@ +/* + * The Mana World + * Copyright 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _TMW_WIDGET_LAYOUT_H__ +#define _TMW_WIDGET_LAYOUT_H__ + +#include <vector> + +#include <guichan/widgets/container.hpp> + +class LayoutCell; + +/** + * This class is a helper for adding widgets to nested tables in a window. + */ +class ContainerPlacer +{ + public: + + ContainerPlacer(gcn::Container *c = NULL, LayoutCell *l = NULL): + mContainer(c), mCell(l) + {} + + /** + * Gets the pointed cell. + */ + LayoutCell &getCell() + { return *mCell; } + + /** + * Returns a placer for the same container but to an inner cell. + */ + ContainerPlacer at(int x, int y); + + /** + * Adds the given widget to the container and places it in the layout. + * @see LayoutArray::place + */ + LayoutCell &operator() + (int x, int y, gcn::Widget *, int w = 1, int h = 1); + + private: + + gcn::Container *mContainer; + LayoutCell *mCell; +}; + +/** + * This class contains a rectangular array of cells. + */ +class LayoutArray +{ + friend class LayoutCell; + + public: + + LayoutArray(); + + ~LayoutArray(); + + /** + * Returns a reference on the cell at given position. + */ + LayoutCell &at(int x, int y, int w = 1, int h = 1); + + /** + * Places a widget in a given cell. + * @param w number of columns the widget spawns. + * @param h number of rows the widget spawns. + * @note When @a w is 1, the width of column @a x is reset to zero if + * it was AUTO_DEF. Similarly for @a h. + */ + LayoutCell &place(gcn::Widget *, int x, int y, int w = 1, int h = 1); + + /** + * Sets the minimum width of a column. + */ + void setColWidth(int n, int w); + + /** + * Sets the minimum height of a row. + */ + void setRowHeight(int n, int h); + + /** + * Sets the widths of two columns to the maximum of their widths. + */ + void matchColWidth(int n1, int n2); + + /** + * Spawns a cell over several columns/rows. + */ + void extend(int x, int y, int w, int h); + + /** + * Computes and sets the positions of all the widgets. + * @param nW width of the array, used to resize the AUTO_ columns. + * @param nH height of the array, used to resize the AUTO_ rows. + */ + void reflow(int nX, int nY, int nW, int nH); + + private: + + // Copy not allowed, as the array owns all its cells. + LayoutArray(LayoutArray const &); + LayoutArray &operator=(LayoutArray const &); + + /** + * Gets the position and size of a widget along a given axis + */ + void align(int &pos, int &size, int dim, + LayoutCell const &cell, short *sizes) const; + + /** + * Ensures the private vectors are large enough. + */ + void resizeGrid(int w, int h); + + /** + * Gets the column/row sizes along a given axis. + * @param upp target size for the array. Ignored if AUTO_DEF. + */ + std::vector< short > getSizes(int dim, int upp) const; + + /** + * Gets the total size along a given axis. + */ + int getSize(int dim) const; + + std::vector< short > mSizes[2]; + std::vector< std::vector < LayoutCell * > > mCells; + + char mSpacing; +}; + +/** + * This class describes the formatting of a widget in the cell of a layout + * table. Horizontally, a widget can either fill the width of the cell (minus + * the cell padding), or it can retain its size and be flushed left, or flush + * right, or centered in the cell. The process is similar for the vertical + * alignment, except that top is represented by LEFT and bottom by RIGHT. + */ +class LayoutCell +{ + friend class Layout; + friend class LayoutArray; + + public: + + enum Alignment + { + LEFT, RIGHT, CENTER, FILL + }; + + LayoutCell(): mType(NONE) {} + + ~LayoutCell(); + + /** + * Sets the padding around the cell content. + */ + LayoutCell &setPadding(int p) + { mPadding = p; return *this; } + + /** + * Sets the horizontal alignment of the cell content. + */ + LayoutCell &setHAlign(Alignment a) + { mAlign[0] = a; return *this; } + + /** + * Sets the vertical alignment of the cell content. + */ + LayoutCell &setVAlign(Alignment a) + { mAlign[1] = a; return *this; } + + /** + * @see LayoutArray::at + */ + LayoutCell &at(int x, int y) + { return getArray().at(x, y); } + + /** + * @see LayoutArray::place + */ + LayoutCell &place(gcn::Widget *wg, int x, int y, int w = 1, int h = 1) + { return getArray().place(wg, x, y, w, h); } + + /** + * @see LayoutArray::matchColWidth + */ + void matchColWidth(int n1, int n2) + { getArray().matchColWidth(n1, n2); } + + /** + * @see LayoutArray::setColWidth + */ + void setColWidth(int n, int w) + { getArray().setColWidth(n, w); } + + /** + * @see LayoutArray::setRowHeight + */ + void setRowHeight(int n, int h) + { getArray().setRowHeight(n, h); } + + /** + * @see LayoutArray::extend. + */ + void extend(int x, int y, int w, int h) + { getArray().extend(x, y, w, h); } + + /** + * Sets the minimum widths and heights of this cell and of all the + * inner cells. + */ + void computeSizes(); + + private: + + // Copy not allowed, as the cell may own an array. + LayoutCell(LayoutCell const &); + LayoutCell &operator=(LayoutCell const &); + + union + { + gcn::Widget *mWidget; + LayoutArray *mArray; + }; + + enum + { + NONE, WIDGET, ARRAY + }; + + /** + * Returns the embedded array. Creates it if the cell does not contain + * anything yet. Aborts if it contains a widget. + */ + LayoutArray &getArray(); + + /** + * @see LayoutArray::reflow + */ + void reflow(int nx, int ny, int nw, int nh); + + short mSize[2]; + char mPadding; + char mExtent[2]; + char mAlign[2]; + char mNbFill[2]; + char mType; +}; + +/** + * This class is an helper for setting the position of widgets. They are + * positioned along the cells of some rectangular tables. The layout may either + * be a single table or a tree of nested tables. + * + * The size of a given table column can either be set manually or be chosen + * from the widest widget of the column. An empty column has a AUTO_DEF width, + * which means it will be extended so that the layout fits its minimum width. + * + * The process is similar for table rows. By default, there is a spacing of 4 + * pixels between rows and between columns, and a margin of 6 pixels around the + * whole layout. + */ +class Layout: public LayoutCell +{ + public: + + Layout(); + + /** + * Sets the margin around the layout. + */ + void setMargin(int m) + { setPadding(m); } + + /** + * Sets the positions of all the widgets. + * @see LayoutArray::reflow + */ + void reflow(int &nW, int &nH); + + /** + * When the minimum size of the layout is less than the available size, + * the remaining pixels are equally split amongst the FILL items. + */ + enum + { + AUTO_DEF = -42, /**< Default value, behaves like AUTO_ADD. */ + AUTO_SET = -43, /**< Uses the share as the new size. */ + AUTO_ADD = -44 /**< Adds the share to the current size. */ + }; + + private: + + bool mComputed; +}; + +#endif diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 630b4ddd..dfe7ac64 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -20,8 +20,8 @@ */ #include <algorithm> -#include <climits> #include <cassert> +#include <climits> #include <guichan/exception.hpp> #include <guichan/widgets/icon.hpp> @@ -29,9 +29,9 @@ #include "window.h" #include "gui.h" -#include "gccontainer.h" #include "windowcontainer.h" +#include "widgets/layout.h" #include "widgets/resizegrip.h" #include "../configlistener.h" @@ -63,6 +63,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent): gcn::Window(caption), mGrip(0), mParent(parent), + mLayout(NULL), mWindowName("window"), mShowTitle(true), mModal(modal), @@ -76,7 +77,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent): logger->log("Window::Window(\"%s\")", caption.c_str()); if (!windowContainer) { - throw GCN_EXCEPTION("Window::Window. no windowContainer set"); + throw GCN_EXCEPTION("Window::Window(): no windowContainer set"); } if (instances == 0) @@ -108,11 +109,6 @@ Window::Window(const std::string& caption, bool modal, Window *parent): setPadding(3); setTitleBarHeight(20); - // Add chrome - mChrome = new GCContainer(); - mChrome->setOpaque(false); - gcn::Window::add(mChrome); - // Add this window to the window container windowContainer->add(this); @@ -145,6 +141,15 @@ Window::~Window() } } + delete mLayout; + + while (!mWidgets.empty()) + { + gcn::Widget *w = mWidgets.front(); + remove(w); + delete(w); + } + instances--; if (instances == 0) @@ -165,9 +170,6 @@ Window::~Window() delete border.grid[8]; closeImage->decRef(); } - - delete mChrome; - delete mGrip; } void Window::setWindowContainer(WindowContainer *wc) @@ -202,7 +204,6 @@ void Window::draw(gcn::Graphics *graphics) void Window::setContentSize(int width, int height) { - mChrome->setSize(width, height); setSize(width + 2 * getPadding(), height + getPadding() + getTitleBarHeight()); } @@ -248,10 +249,11 @@ void Window::setResizable(bool r) mGrip = new ResizeGrip(); mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x); mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y); - gcn::Window::add(mGrip); + add(mGrip); } else { + remove(mGrip); delete mGrip; mGrip = 0; } @@ -259,15 +261,19 @@ void Window::setResizable(bool r) void Window::widgetResized(const gcn::Event &event) { - const gcn::Rectangle area = getChildrenArea(); - - mChrome->setSize(area.width, area.height); - if (mGrip) { + const gcn::Rectangle area = getChildrenArea(); mGrip->setPosition(getWidth() - mGrip->getWidth() - area.x, getHeight() - mGrip->getHeight() - area.y); } + + if (mLayout) + { + int w = getWidth() - 2 * getPadding(); + int h = getHeight() - getPadding() - getTitleBarHeight(); + mLayout->reflow(w, h); + } } void Window::setCloseButton(bool flag) @@ -292,14 +298,7 @@ bool Window::isSticky() void Window::setVisible(bool visible) { - if (isSticky()) - { - gcn::Window::setVisible(true); - } - else - { - gcn::Window::setVisible(visible); - } + gcn::Window::setVisible(isSticky() || visible); } void Window::scheduleDelete() @@ -307,16 +306,6 @@ void Window::scheduleDelete() windowContainer->scheduleDelete(this); } -void Window::add(gcn::Widget *w) -{ - mChrome->add(w); -} - -void Window::add(gcn::Widget *w, int x, int y) -{ - mChrome->add(w, x, y); -} - void Window::mousePressed(gcn::MouseEvent &event) { // Let Guichan move window to top and figure out title bar drag @@ -535,3 +524,29 @@ int Window::getResizeHandles(gcn::MouseEvent &event) return resizeHandles; } + +Layout &Window::getLayout() +{ + if (!mLayout) mLayout = new Layout; + return *mLayout; +} + +LayoutCell &Window::place(int x, int y, gcn::Widget *wg, int w, int h) +{ + add(wg); + return getLayout().place(wg, x, y, w, h); +} + +ContainerPlacer Window::getPlacer(int x, int y) +{ + return ContainerPlacer(this, &getLayout().at(x, y)); +} + +void Window::reflowLayout(int w, int h) +{ + assert(mLayout); + mLayout->reflow(w, h); + delete mLayout; + mLayout = NULL; + setContentSize(w, h); +} diff --git a/src/gui/window.h b/src/gui/window.h index 984c6f06..a49788a5 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -28,11 +28,13 @@ #include "../guichanfwd.h" class ConfigListener; -class GCContainer; +class ContainerPlacer; +class Image; class ImageRect; +class Layout; +class LayoutCell; class ResizeGrip; class WindowContainer; -class Image; /** * A window. This window can be dragged around and has a title bar. Windows are @@ -59,7 +61,7 @@ class Window : public gcn::Window, gcn::WidgetListener Window *parent = NULL); /** - * Destructor. + * Destructor. Deletes all the added widgets. */ ~Window(); @@ -74,18 +76,6 @@ class Window : public gcn::Window, gcn::WidgetListener void draw(gcn::Graphics *graphics); /** - * Adds a widget to the window. The widget will be deleted by the - * window. - */ - void add(gcn::Widget *w); - - /** - * Adds a widget to the window and also specifices its position. The - * widget will be deleted by the window. - */ - void add(gcn::Widget *w, int x, int y); - - /** * Sets the size of this window. */ void setContentSize(int width, int height); @@ -163,8 +153,7 @@ class Window : public gcn::Window, gcn::WidgetListener * * @return The parent window or <code>NULL</code> if there is none. */ - Window* - getParentWindow() { return mParent; } + Window *getParentWindow() { return mParent; } /** * Schedule this window for deletion. It will be deleted at the start @@ -204,14 +193,12 @@ class Window : public gcn::Window, gcn::WidgetListener /** * Sets the name of the window. This is not the window title. */ - void - setWindowName(const std::string &name) { mWindowName = name; } + void setWindowName(const std::string &name) { mWindowName = name; } /** * Returns the name of the window. This is not the window title. */ - const std::string& - getWindowName() { return mWindowName; } + const std::string &getWindowName() { return mWindowName; } /** * Reads the position (and the size for resizable windows) in the @@ -220,21 +207,51 @@ class Window : public gcn::Window, gcn::WidgetListener * Don't forget to set these default values and resizable before * calling this function. */ - virtual void loadWindowState(); + void loadWindowState(); /** * Set the default win pos and size. * (which can be different of the actual ones.) */ - virtual void setDefaultSize(int defaultX, int defaultY, - int defaultWidth, int defaultHeight); + void setDefaultSize(int defaultX, int defaultY, + int defaultWidth, int defaultHeight); /** * Reset the win pos and size to default. Don't forget to set defaults * first. */ - virtual void resetToDefaultSize(); + void resetToDefaultSize(); + + /** + * Gets the layout handler for this window. + */ + Layout &getLayout(); + + /** + * Computes the position of the widgets according to the current + * layout. Resizes the window so that the layout fits. Deletes the + * layout. + * @param w if non-zero, force the window to this width. + * @param h if non-zero, force the window to this height. + * @note This function is meant to be called with fixed-size windows. + */ + void reflowLayout(int w = 0, int h = 0); + /** + * 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); + + /** + * Returns a proxy for adding widgets in an inner table of the layout. + */ + ContainerPlacer getPlacer(int x, int y); + + protected: + /** The window container windows add themselves to. */ + static WindowContainer *windowContainer; + + private: enum ResizeHandles { TOP = 0x01, @@ -243,7 +260,6 @@ class Window : public gcn::Window, gcn::WidgetListener LEFT = 0x08 }; - protected: /** * Determines if the mouse is in a resize area and returns appropriate * resize handles. Also initializes drag offset in case the resize @@ -253,9 +269,9 @@ class Window : public gcn::Window, gcn::WidgetListener */ int getResizeHandles(gcn::MouseEvent &event); - GCContainer *mChrome; /**< Contained container */ ResizeGrip *mGrip; /**< Resize grip */ Window *mParent; /**< The parent window */ + Layout *mLayout; /**< Layout handler */ std::string mWindowName; /**< Name of the window */ bool mShowTitle; /**< Window has a title bar */ bool mModal; /**< Window is modal */ @@ -270,9 +286,6 @@ class Window : public gcn::Window, gcn::WidgetListener int mDefaultWidth; /**< Default window width */ int mDefaultHeight; /**< Default window height */ - /** The window container windows add themselves to. */ - static WindowContainer *windowContainer; - /** * The config listener that listens to changes relevant to all windows. */ |