summaryrefslogtreecommitdiff
path: root/src/gui/widgets/tabs
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2013-09-30 18:43:40 +0300
committerAndrei Karas <akaras@inbox.ru>2013-09-30 18:43:40 +0300
commit112058d7208f9a48a14d943e560b3b703647653a (patch)
tree8123b89ceee53577733f32fe15880fe7538ec473 /src/gui/widgets/tabs
parent64781090e80fa93a43ce37f0705bbb1cf22ed8bf (diff)
downloadmanaverse-112058d7208f9a48a14d943e560b3b703647653a.tar.gz
manaverse-112058d7208f9a48a14d943e560b3b703647653a.tar.bz2
manaverse-112058d7208f9a48a14d943e560b3b703647653a.tar.xz
manaverse-112058d7208f9a48a14d943e560b3b703647653a.zip
move tabs into tabs directory.
Diffstat (limited to 'src/gui/widgets/tabs')
-rw-r--r--src/gui/widgets/tabs/battletab.cpp48
-rw-r--r--src/gui/widgets/tabs/battletab.h48
-rw-r--r--src/gui/widgets/tabs/chattab.cpp547
-rw-r--r--src/gui/widgets/tabs/chattab.h212
-rw-r--r--src/gui/widgets/tabs/gmtab.cpp62
-rw-r--r--src/gui/widgets/tabs/gmtab.h53
-rw-r--r--src/gui/widgets/tabs/guildchattab.cpp152
-rw-r--r--src/gui/widgets/tabs/guildchattab.h60
-rw-r--r--src/gui/widgets/tabs/langtab.cpp43
-rw-r--r--src/gui/widgets/tabs/langtab.h43
-rw-r--r--src/gui/widgets/tabs/setup_audio.cpp204
-rw-r--r--src/gui/widgets/tabs/setup_audio.h45
-rw-r--r--src/gui/widgets/tabs/setup_chat.cpp208
-rw-r--r--src/gui/widgets/tabs/setup_chat.h40
-rw-r--r--src/gui/widgets/tabs/setup_colors.cpp445
-rw-r--r--src/gui/widgets/tabs/setup_colors.h93
-rw-r--r--src/gui/widgets/tabs/setup_input.cpp414
-rw-r--r--src/gui/widgets/tabs/setup_input.h104
-rw-r--r--src/gui/widgets/tabs/setup_joystick.cpp187
-rw-r--r--src/gui/widgets/tabs/setup_joystick.h62
-rw-r--r--src/gui/widgets/tabs/setup_other.cpp404
-rw-r--r--src/gui/widgets/tabs/setup_other.h49
-rw-r--r--src/gui/widgets/tabs/setup_perfomance.cpp163
-rw-r--r--src/gui/widgets/tabs/setup_perfomance.h43
-rw-r--r--src/gui/widgets/tabs/setup_players.cpp104
-rw-r--r--src/gui/widgets/tabs/setup_players.h36
-rw-r--r--src/gui/widgets/tabs/setup_relations.cpp445
-rw-r--r--src/gui/widgets/tabs/setup_relations.h83
-rw-r--r--src/gui/widgets/tabs/setup_theme.cpp541
-rw-r--r--src/gui/widgets/tabs/setup_theme.h105
-rw-r--r--src/gui/widgets/tabs/setup_touch.cpp139
-rw-r--r--src/gui/widgets/tabs/setup_touch.h41
-rw-r--r--src/gui/widgets/tabs/setup_video.cpp576
-rw-r--r--src/gui/widgets/tabs/setup_video.h82
-rw-r--r--src/gui/widgets/tabs/setup_visual.cpp213
-rw-r--r--src/gui/widgets/tabs/setup_visual.h48
-rw-r--r--src/gui/widgets/tabs/setuptab.cpp39
-rw-r--r--src/gui/widgets/tabs/setuptab.h74
-rw-r--r--src/gui/widgets/tabs/setuptabscroll.cpp134
-rw-r--r--src/gui/widgets/tabs/setuptabscroll.h75
-rw-r--r--src/gui/widgets/tabs/tab.cpp346
-rw-r--r--src/gui/widgets/tabs/tab.h187
-rw-r--r--src/gui/widgets/tabs/tradetab.cpp51
-rw-r--r--src/gui/widgets/tabs/tradetab.h51
-rw-r--r--src/gui/widgets/tabs/whispertab.cpp196
-rw-r--r--src/gui/widgets/tabs/whispertab.h74
46 files changed, 7369 insertions, 0 deletions
diff --git a/src/gui/widgets/tabs/battletab.cpp b/src/gui/widgets/tabs/battletab.cpp
new file mode 100644
index 000000000..fa7e252f0
--- /dev/null
+++ b/src/gui/widgets/tabs/battletab.cpp
@@ -0,0 +1,48 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/battletab.h"
+
+#include "chatlogger.h"
+#include "configuration.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+BattleTab::BattleTab(const Widget2 *const widget) :
+ // TRANSLATORS: battle chat tab name
+ ChatTab(widget, _("Battle"), "")
+{
+ if (config.getBoolValue("showChatHistory"))
+ loadFromLogFile("#Battle");
+}
+
+BattleTab::~BattleTab()
+{
+}
+
+void BattleTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ chatLogger->log(std::string("#Battle"), std::string(msg));
+}
diff --git a/src/gui/widgets/tabs/battletab.h b/src/gui/widgets/tabs/battletab.h
new file mode 100644
index 000000000..b4aa1d1df
--- /dev/null
+++ b/src/gui/widgets/tabs/battletab.h
@@ -0,0 +1,48 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_BATTLETAB_H
+#define GUI_WIDGETS_BATTLETAB_H
+
+#include "gui/widgets/tabs/chattab.h"
+
+/**
+ * A tab for a party chat channel.
+ */
+class BattleTab final : public ChatTab
+{
+ public:
+ explicit BattleTab(const Widget2 *const widget);
+
+ A_DELETE_COPY(BattleTab)
+
+ ~BattleTab();
+
+ int getType() const override A_WARN_UNUSED
+ { return ChatTab::TAB_BATTLE; }
+
+ void saveToLogFile(const std::string &msg) const override;
+};
+
+extern BattleTab *battleChatTab;
+
+#endif // GUI_WIDGETS_BATTLETAB_H
diff --git a/src/gui/widgets/tabs/chattab.cpp b/src/gui/widgets/tabs/chattab.cpp
new file mode 100644
index 000000000..2c0628581
--- /dev/null
+++ b/src/gui/widgets/tabs/chattab.cpp
@@ -0,0 +1,547 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/chattab.h"
+
+#include "chatlogger.h"
+#include "client.h"
+#include "commandhandler.h"
+#include "configuration.h"
+#include "soundconsts.h"
+#include "soundmanager.h"
+
+#include "being/localplayer.h"
+
+#include "gui/windows/helpwindow.h"
+
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/itemlinkhandler.h"
+#include "gui/widgets/tabbedarea.h"
+
+#include "net/chathandler.h"
+#include "net/net.h"
+
+#include "resources/iteminfo.h"
+#include "resources/itemdb.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+static const unsigned int MAX_WORD_SIZE = 50;
+
+ChatTab::ChatTab(const Widget2 *const widget, const std::string &name,
+ const std::string &channel) :
+ Tab(widget),
+ mTextOutput(new BrowserBox(this, BrowserBox::AUTO_WRAP)),
+ mScrollArea(new ScrollArea(mTextOutput, false)),
+ mChannelName(channel),
+ mAllowHightlight(true),
+ mRemoveNames(false),
+ mNoAway(false),
+ mShowOnline(false)
+{
+ setCaption(name);
+
+ mTextOutput->setOpaque(false);
+ mTextOutput->setMaxRow(config.getIntValue("ChatLogLength"));
+ if (chatWindow)
+ mTextOutput->setLinkHandler(chatWindow->mItemLinkHandler);
+ mTextOutput->setAlwaysUpdate(false);
+
+ mScrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER,
+ gcn::ScrollArea::SHOW_ALWAYS);
+ mScrollArea->setScrollAmount(0, 1);
+
+ if (chatWindow)
+ chatWindow->addTab(this);
+}
+
+ChatTab::~ChatTab()
+{
+ if (chatWindow)
+ chatWindow->removeTab(this);
+
+ delete mTextOutput;
+ mTextOutput = nullptr;
+ delete mScrollArea;
+ mScrollArea = nullptr;
+}
+
+void ChatTab::chatLog(std::string line, Own own,
+ const bool ignoreRecord, const bool tryRemoveColors)
+{
+ // Trim whitespace
+ trim(line);
+
+ if (line.empty())
+ return;
+
+ if (tryRemoveColors && own == BY_OTHER &&
+ config.getBoolValue("removeColors"))
+ {
+ line = removeColors(line);
+ if (line.empty())
+ return;
+ }
+
+ const unsigned lineLim = config.getIntValue("chatMaxCharLimit");
+ if (lineLim > 0 && line.length() > lineLim)
+ line = line.substr(0, lineLim);
+
+ if (line.empty())
+ return;
+
+ CHATLOG tmp;
+ tmp.own = own;
+ tmp.nick.clear();
+ tmp.text = line;
+
+ const size_t pos = line.find(" : ");
+ if (pos != std::string::npos)
+ {
+ if (line.length() <= pos + 3)
+ return;
+
+ tmp.nick = line.substr(0, pos);
+ tmp.text = line.substr(pos + 3);
+ }
+ else
+ {
+ // Fix the owner of welcome message.
+ if (line.length() > 7 && line.substr(0, 7) == "Welcome")
+ own = BY_SERVER;
+ }
+
+ // *implements actions in a backwards compatible way*
+ if ((own == BY_PLAYER || own == BY_OTHER) &&
+ tmp.text.at(0) == '*' &&
+ tmp.text.at(tmp.text.length()-1) == '*')
+ {
+ tmp.text[0] = ' ';
+ tmp.text.erase(tmp.text.length() - 1);
+ own = ACT_IS;
+ }
+
+ std::string lineColor("##C");
+ switch (own)
+ {
+ case BY_GM:
+ if (tmp.nick.empty())
+ {
+ // TRANSLATORS: chat message
+ tmp.nick = std::string(_("Global announcement:")).append(" ");
+ lineColor = "##G";
+ }
+ else
+ {
+ // TRANSLATORS: chat message
+ tmp.nick = strprintf(_("Global announcement from %s:"),
+ tmp.nick.c_str()).append(" ");
+ lineColor = "##g"; // Equiv. to BrowserBox::RED
+ }
+ break;
+ case BY_PLAYER:
+ tmp.nick.append(": ");
+ lineColor = "##Y";
+ break;
+ case BY_OTHER:
+ case BY_UNKNOWN:
+ tmp.nick.append(": ");
+ lineColor = "##C";
+ break;
+ case BY_SERVER:
+ // TRANSLATORS: chat message
+ tmp.nick.clear();
+ tmp.text = line;
+ lineColor = "##S";
+ break;
+ case BY_CHANNEL:
+ tmp.nick.clear();
+ lineColor = "##2"; // Equiv. to BrowserBox::GREEN
+ break;
+ case ACT_WHISPER:
+ // TRANSLATORS: chat message
+ tmp.nick = strprintf(_("%s whispers: %s"), tmp.nick.c_str(), "");
+ lineColor = "##W";
+ break;
+ case ACT_IS:
+ lineColor = "##I";
+ break;
+ case BY_LOGGER:
+ tmp.nick.clear();
+ tmp.text = line;
+ lineColor = "##L";
+ break;
+ default:
+ break;
+ }
+
+ if (tmp.nick == ": ")
+ {
+ tmp.nick.clear();
+ lineColor = "##S";
+ }
+
+ // if configured, move magic messages log to debug chat tab
+ if (localChatTab && this == localChatTab
+ && ((config.getBoolValue("showMagicInDebug") && own == BY_PLAYER
+ && tmp.text.length() > 1 && tmp.text.at(0) == '#'
+ && tmp.text.at(1) != '#')
+ || (config.getBoolValue("serverMsgInDebug") && (own == BY_SERVER
+ || tmp.nick.empty()))))
+ {
+ if (debugChatTab)
+ debugChatTab->chatLog(line, own, ignoreRecord, tryRemoveColors);
+ return;
+ }
+
+ // Get the current system time
+ time_t t;
+ time(&t);
+
+ if (config.getBoolValue("useLocalTime"))
+ {
+ const struct tm *timeInfo;
+ timeInfo = localtime(&t);
+ if (timeInfo)
+ {
+ line = strprintf("%s[%02d:%02d] %s%s", lineColor.c_str(),
+ timeInfo->tm_hour, timeInfo->tm_min, tmp.nick.c_str(),
+ tmp.text.c_str());
+ }
+ else
+ {
+ line = strprintf("%s %s%s", lineColor.c_str(),
+ tmp.nick.c_str(), tmp.text.c_str());
+ }
+ }
+ else
+ {
+ // Format the time string properly
+ std::stringstream timeStr;
+ timeStr << "[" << ((((t / 60) / 60) % 24 < 10) ? "0" : "")
+ << static_cast<int>(((t / 60) / 60) % 24)
+ << ":" << (((t / 60) % 60 < 10) ? "0" : "")
+ << static_cast<int>((t / 60) % 60)
+ << "] ";
+ line = std::string(lineColor).append(timeStr.str()).append(
+ tmp.nick).append(tmp.text);
+ }
+
+ if (config.getBoolValue("enableChatLog"))
+ saveToLogFile(line);
+
+ mTextOutput->setMaxRow(config.getIntValue("chatMaxLinesLimit"));
+
+ // We look if the Vertical Scroll Bar is set at the max before
+ // adding a row, otherwise the max will always be a row higher
+ // at comparison.
+ if (mScrollArea->getVerticalScrollAmount() + 2 >=
+ mScrollArea->getVerticalMaxScroll())
+ {
+ addRow(line);
+ mScrollArea->setVerticalScrollAmount(
+ mScrollArea->getVerticalMaxScroll());
+ }
+ else
+ {
+ addRow(line);
+ }
+
+ if (chatWindow && this == localChatTab)
+ chatWindow->addToAwayLog(line);
+
+ mScrollArea->logic();
+ if (own != BY_PLAYER)
+ {
+ if (own == BY_SERVER && (getType() == TAB_PARTY
+ || getType() == TAB_GUILD))
+ {
+ return;
+ }
+
+ const TabbedArea *const tabArea = getTabbedArea();
+ if (!tabArea)
+ return;
+
+ if (this != tabArea->getSelectedTab())
+ {
+ if (getFlash() == 0)
+ {
+ if (chatWindow && chatWindow->findHighlight(tmp.text))
+ {
+ setFlash(2);
+ soundManager.playGuiSound(SOUND_HIGHLIGHT);
+ }
+ else
+ {
+ setFlash(1);
+ }
+ }
+ else if (getFlash() == 2)
+ {
+ if (chatWindow && chatWindow->findHighlight(tmp.text))
+ soundManager.playGuiSound(SOUND_HIGHLIGHT);
+ }
+ }
+
+ if ((getAllowHighlight() || own == BY_GM)
+ && (this != tabArea->getSelectedTab()
+ || (client->getIsMinimized() || (!client->getMouseFocused()
+ && !client->getInputFocused()))))
+ {
+ if (own == BY_GM)
+ {
+ if (chatWindow)
+ chatWindow->unHideWindow();
+ soundManager.playGuiSound(SOUND_GLOBAL);
+ }
+ else if (own != BY_SERVER)
+ {
+ if (chatWindow)
+ chatWindow->unHideWindow();
+ playNewMessageSound();
+ }
+ client->newChatMessage();
+ }
+ }
+}
+
+void ChatTab::chatLog(const std::string &nick, std::string msg)
+{
+ const Own byWho = (nick == player_node->getName() ? BY_PLAYER : BY_OTHER);
+ if (byWho == BY_OTHER && config.getBoolValue("removeColors"))
+ msg = removeColors(msg);
+ chatLog(std::string(nick).append(" : ").append(msg), byWho, false, false);
+}
+
+void ChatTab::chatInput(const std::string &message)
+{
+ std::string msg = message;
+ trim(msg);
+
+ if (msg.empty())
+ return;
+
+ // Check for item link
+ size_t start = msg.find('[');
+ size_t sz = msg.size();
+ while (start + 1 < sz && start != std::string::npos
+ && msg[start + 1] != '@')
+ {
+ const size_t end = msg.find(']', start);
+ if (start + 1 != end && end != std::string::npos)
+ {
+ // Catch multiple embeds and ignore them
+ // so it doesn't crash the client.
+ while ((msg.find('[', start + 1) != std::string::npos) &&
+ (msg.find('[', start + 1) < end))
+ {
+ start = msg.find('[', start + 1);
+ }
+
+ std::string temp;
+ if (start + 1 < sz && end < sz && end > start + 1)
+ {
+ temp = msg.substr(start + 1, end - start - 1);
+
+ const ItemInfo &itemInfo = ItemDB::get(temp);
+ if (itemInfo.getId() != 0)
+ {
+ msg.insert(end, "@@");
+ msg.insert(start + 1, "|");
+ msg.insert(start + 1, toString(itemInfo.getId()));
+ msg.insert(start + 1, "@@");
+ sz = msg.size();
+ }
+ }
+ }
+ start = msg.find('[', start + 1);
+ }
+
+ Commands::replaceVars(msg);
+
+ switch (msg[0])
+ {
+ case '/':
+ handleCommand(std::string(msg, 1));
+ break;
+ case '?':
+ if (msg.size() > 1)
+ handleHelp(std::string(msg, 1));
+ else
+ handleInput(msg);
+ break;
+ default:
+ handleInput(msg);
+ break;
+ }
+}
+
+void ChatTab::scroll(const int amount)
+{
+ const int range = mScrollArea->getHeight() / 8 * amount;
+ gcn::Rectangle scr;
+ scr.y = mScrollArea->getVerticalScrollAmount() + range;
+ scr.height = abs(range);
+ mTextOutput->showPart(scr);
+}
+
+void ChatTab::clearText()
+{
+ mTextOutput->clearRows();
+}
+
+void ChatTab::handleInput(const std::string &msg)
+{
+ if (chatWindow)
+ {
+ Net::getChatHandler()->talk(chatWindow->doReplace(msg),
+ mChannelName);
+ }
+ else
+ {
+ Net::getChatHandler()->talk(msg, mChannelName);
+ }
+}
+
+void ChatTab::handleCommand(const std::string &msg)
+{
+ if (commandHandler)
+ commandHandler->handleCommands(msg, this);
+}
+
+void ChatTab::handleHelp(const std::string &msg)
+{
+ if (commandHandler)
+ helpWindow->search(msg);
+}
+
+bool ChatTab::handleCommands(const std::string &type, const std::string &args)
+{
+ // need split to commands and call each
+
+ return handleCommand(type, args);
+}
+
+void ChatTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ {
+ if (getType() == TAB_INPUT)
+ {
+ chatLogger->log(msg);
+ }
+ else if (getType() == TAB_DEBUG
+ && config.getBoolValue("enableDebugLog"))
+ {
+ chatLogger->log("#Debug", msg);
+ }
+ }
+}
+
+int ChatTab::getType() const
+{
+ if (getCaption() == "General" || getCaption() == _("General"))
+ return TAB_INPUT;
+ else if (getCaption() == "Debug" || getCaption() == _("Debug"))
+ return TAB_DEBUG;
+ else
+ return TAB_UNKNOWN;
+}
+
+void ChatTab::addRow(std::string &line)
+{
+ if (line.find("[@@http") == std::string::npos)
+ {
+ size_t idx = 0;
+ for (size_t f = 0; f < line.length(); f++)
+ {
+ if (line.at(f) == ' ')
+ {
+ idx = f;
+ }
+ else if (f - idx > MAX_WORD_SIZE)
+ {
+ line.insert(f, " ");
+ idx = f;
+ }
+ }
+ }
+ mTextOutput->addRow(line);
+}
+
+void ChatTab::loadFromLogFile(const std::string &name)
+{
+ if (chatLogger)
+ {
+ std::list<std::string> list;
+ chatLogger->loadLast(name, list, 5);
+ std::list<std::string>::const_iterator i = list.begin();
+ while (i != list.end())
+ {
+ std::string line("##9" + *i);
+ addRow(line);
+ ++i;
+ }
+ }
+}
+
+void ChatTab::addNewRow(std::string &line)
+{
+ if (mScrollArea->getVerticalScrollAmount() >=
+ mScrollArea->getVerticalMaxScroll())
+ {
+ addRow(line);
+ mScrollArea->setVerticalScrollAmount(
+ mScrollArea->getVerticalMaxScroll());
+ }
+ else
+ {
+ addRow(line);
+ }
+ mScrollArea->logic();
+}
+
+void ChatTab::playNewMessageSound() const
+{
+ soundManager.playGuiSound(SOUND_WHISPER);
+}
+
+void ChatTab::showOnline(const std::string &nick,
+ const bool isOnline)
+{
+ if (!mShowOnline)
+ return;
+
+ if (isOnline)
+ {
+ // TRANSLATORS: chat message
+ chatLog(strprintf(_("%s is now Online."), nick.c_str()));
+ }
+ else
+ {
+ // TRANSLATORS: chat message
+ chatLog(strprintf(_("%s is now Offline."), nick.c_str()));
+ }
+}
diff --git a/src/gui/widgets/tabs/chattab.h b/src/gui/widgets/tabs/chattab.h
new file mode 100644
index 000000000..e7744a8c1
--- /dev/null
+++ b/src/gui/widgets/tabs/chattab.h
@@ -0,0 +1,212 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_CHATTAB_H
+#define GUI_WIDGETS_CHATTAB_H
+
+#include "gui/windows/chatwindow.h"
+
+#include "gui/widgets/browserbox.h"
+#include "gui/widgets/tabs/tab.h"
+
+#include "localconsts.h"
+
+class ScrollArea;
+
+const std::string GENERAL_CHANNEL = "";
+const std::string TRADE_CHANNEL = "";
+
+/**
+ * A tab for the chat window. This is special to ease chat handling.
+ */
+class ChatTab : public Tab
+{
+ public:
+ enum Type
+ {
+ TAB_UNKNOWN = 0,
+ TAB_INPUT,
+ TAB_WHISPER,
+ TAB_PARTY,
+ TAB_GUILD,
+ TAB_DEBUG,
+ TAB_TRADE,
+ TAB_BATTLE,
+ TAB_LANG,
+ TAB_GM
+ };
+
+ /**
+ * Constructor.
+ */
+ ChatTab(const Widget2 *const widget, const std::string &name,
+ const std::string &channel);
+
+ A_DELETE_COPY(ChatTab)
+
+ virtual ~ChatTab();
+
+ /**
+ * Adds a line of text to our message list. Parameters:
+ *
+ * @param line Text message.
+ * @param own Type of message (usually the owner-type).
+ * @param channelName which channel to send the message to.
+ * @param ignoreRecord should this not be recorded?
+ * @param removeColors try remove color if configured
+ */
+ void chatLog(std::string line, Own own = BY_SERVER,
+ const bool ignoreRecord = false,
+ const bool tryRemoveColors = true);
+
+ /**
+ * Adds the text to the message list
+ *
+ * @param msg The message text which is to be sent.
+ */
+ void chatLog(const std::string &nick, std::string msg);
+
+ /**
+ * Determines whether the message is a command or message, then
+ * sends the given message to the game server to be said, or to the
+ * command handler
+ *
+ * @param msg The message text which is to be sent.
+ */
+ void chatInput(const std::string &msg);
+
+ /**
+ * Scrolls the chat window
+ *
+ * @param amount direction and amount to scroll. Negative numbers scroll
+ * 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(const int amount);
+
+ /**
+ * Clears the text from the tab
+ */
+ void clearText();
+
+ /**
+ * Add any extra help text to the output. Allows tabs to define help
+ * for commands defined by the tab itself.
+ */
+ virtual void showHelp()
+ { }
+
+ /**
+ * Handle special commands. Allows a tab to handle commands it
+ * defines itself.
+ *
+ * @returns true if the command was handled
+ * false if the command was not handled
+ */
+ virtual bool handleCommand(const std::string &type A_UNUSED,
+ const std::string &args A_UNUSED)
+ { return false; }
+
+ /**
+ * Handle special commands. Allows a tab to handle commands it
+ * defines itself.
+ *
+ * @returns true if the command was handled
+ * false if the command was not handled
+ */
+ virtual bool handleCommands(const std::string &type,
+ const std::string &args);
+
+ /**
+ * Returns type of the being.
+ */
+ virtual int getType() const A_WARN_UNUSED;
+
+ virtual void saveToLogFile(const std::string &msg) const;
+
+ const std::list<std::string> &getRows() const A_WARN_UNUSED
+ { return mTextOutput->getRows(); }
+
+ bool hasRows() const A_WARN_UNUSED
+ { return mTextOutput->hasRows(); }
+
+ void loadFromLogFile(const std::string &name);
+
+ bool getAllowHighlight() const A_WARN_UNUSED
+ { return mAllowHightlight; }
+
+ void setAllowHighlight(const bool n)
+ { mAllowHightlight = n; }
+
+ bool getRemoveNames() const A_WARN_UNUSED
+ { return mRemoveNames; }
+
+ void setRemoveNames(const bool n)
+ { mRemoveNames = n; }
+
+ bool getNoAway() const A_WARN_UNUSED
+ { return mNoAway; }
+
+ void setNoAway(const bool n)
+ { mNoAway = n; }
+
+ void addNewRow(std::string &line);
+
+ void showOnline(const std::string &nick,
+ const bool isOnline);
+
+ virtual void playNewMessageSound() const;
+
+ const std::string &getChannelName() const
+ { return mChannelName; }
+
+ protected:
+ friend class ChatWindow;
+ friend class WhisperWindow;
+
+ virtual void setCurrent() override
+ { setFlash(0); }
+
+ virtual void handleInput(const std::string &msg);
+
+ virtual void handleCommand(const std::string &msg);
+
+ virtual void handleHelp(const std::string &msg);
+
+ virtual void getAutoCompleteList(StringVect&) const
+ {}
+
+ void addRow(std::string &line);
+
+ BrowserBox *mTextOutput;
+ ScrollArea *mScrollArea;
+ std::string mChannelName;
+ bool mAllowHightlight;
+ bool mRemoveNames;
+ bool mNoAway;
+ bool mShowOnline;
+};
+
+extern ChatTab *localChatTab;
+extern ChatTab *debugChatTab;
+
+#endif // GUI_WIDGETS_CHATTAB_H
diff --git a/src/gui/widgets/tabs/gmtab.cpp b/src/gui/widgets/tabs/gmtab.cpp
new file mode 100644
index 000000000..25ec67f19
--- /dev/null
+++ b/src/gui/widgets/tabs/gmtab.cpp
@@ -0,0 +1,62 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/gmtab.h"
+
+#include "chatlogger.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+GmTab::GmTab(const Widget2 *const widget) :
+ // TRANSLATORS: gb tab name
+ ChatTab(widget, _("GM"), "")
+{
+ setTabColor(&getThemeColor(Theme::GM_CHAT_TAB),
+ &getThemeColor(Theme::GM_CHAT_TAB_OUTLINE));
+ setHighlightedTabColor(&getThemeColor(Theme::GM_CHAT_TAB_HIGHLIGHTED),
+ &getThemeColor(Theme::GM_CHAT_TAB_HIGHLIGHTED_OUTLINE));
+ setSelectedTabColor(&getThemeColor(Theme::GM_CHAT_TAB_SELECTED),
+ &getThemeColor(Theme::GM_CHAT_TAB_SELECTED_OUTLINE));
+}
+
+GmTab::~GmTab()
+{
+}
+
+void GmTab::handleInput(const std::string &msg)
+{
+ ChatTab::handleInput("@wgm " + msg);
+}
+
+void GmTab::handleCommand(const std::string &msg A_UNUSED)
+{
+}
+
+void GmTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ chatLogger->log("#GM", msg);
+}
+
+void GmTab::getAutoCompleteList(StringVect &names A_UNUSED) const
+{
+}
diff --git a/src/gui/widgets/tabs/gmtab.h b/src/gui/widgets/tabs/gmtab.h
new file mode 100644
index 000000000..28ccabe8a
--- /dev/null
+++ b/src/gui/widgets/tabs/gmtab.h
@@ -0,0 +1,53 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_GMTAB_H
+#define GUI_WIDGETS_GMTAB_H
+
+#include "gui/widgets/tabs/chattab.h"
+
+/**
+ * A tab for whispers from a single player.
+ */
+class GmTab final : public ChatTab
+{
+ public:
+ explicit GmTab(const Widget2 *const widget);
+
+ A_DELETE_COPY(GmTab)
+
+ ~GmTab();
+
+ int getType() const override A_WARN_UNUSED
+ { return ChatTab::TAB_GM; }
+
+ void saveToLogFile(const std::string &msg) const override;
+
+ protected:
+ void getAutoCompleteList(StringVect &names) const override;
+
+ void handleInput(const std::string &msg) override;
+
+ void handleCommand(const std::string &msg) override;
+};
+
+extern GmTab *gmChatTab;
+
+#endif // GUI_WIDGETS_GMTAB_H
diff --git a/src/gui/widgets/tabs/guildchattab.cpp b/src/gui/widgets/tabs/guildchattab.cpp
new file mode 100644
index 000000000..4188a8843
--- /dev/null
+++ b/src/gui/widgets/tabs/guildchattab.cpp
@@ -0,0 +1,152 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/guildchattab.h"
+
+#include "chatlogger.h"
+#include "configuration.h"
+#include "guildmanager.h"
+#include "soundconsts.h"
+#include "soundmanager.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+GuildChatTab::GuildChatTab(const Widget2 *const widget) :
+ // TRANSLATORS: guild chat tab name
+ ChatTab(widget, _("Guild"), "")
+{
+ setTabColor(&getThemeColor(Theme::GUILD_CHAT_TAB),
+ &getThemeColor(Theme::GUILD_CHAT_TAB_OUTLINE));
+ setHighlightedTabColor(&getThemeColor(Theme::GUILD_CHAT_TAB_HIGHLIGHTED),
+ &getThemeColor(Theme::GUILD_CHAT_TAB_HIGHLIGHTED_OUTLINE));
+ setSelectedTabColor(&getThemeColor(Theme::GUILD_CHAT_TAB_SELECTED),
+ &getThemeColor(Theme::GUILD_CHAT_TAB_SELECTED_OUTLINE));
+ mShowOnline = config.getBoolValue("showGuildOnline");
+ config.addListener("showGuildOnline", this);
+}
+
+GuildChatTab::~GuildChatTab()
+{
+ config.removeListeners(this);
+}
+
+bool GuildChatTab::handleCommand(const std::string &type,
+ const std::string &args)
+{
+ if (type == "help")
+ {
+ if (args == "invite")
+ {
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("Command: /invite <nick>"));
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("This command invites <nick> to the guild you're in."));
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("If the <nick> has spaces in it, enclose it in "
+ "double quotes (\")."));
+ }
+ else if (args == "leave")
+ {
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("Command: /leave"));
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("This command causes the player to leave the guild."));
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (type == "invite" && guildManager)
+ {
+ guildManager->invite(args);
+ }
+ else if (type == "leave" && guildManager)
+ {
+ guildManager->leave();
+ }
+ else if (type == "kick" && guildManager)
+ {
+ guildManager->kick(args);
+ }
+ else if (type == "notice" && guildManager)
+ {
+ guildManager->notice(args);
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void GuildChatTab::handleInput(const std::string &msg)
+{
+ if (!guildManager)
+ return;
+
+ if (chatWindow)
+ guildManager->chat(chatWindow->doReplace(msg));
+ else
+ guildManager->chat(msg);
+}
+
+void GuildChatTab::showHelp()
+{
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("/help > Display this help."));
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("/invite > Invite a player to your guild"));
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("/leave > Leave the guild you are in"));
+ // TRANSLATORS: guild chat tab help
+ chatLog(_("/kick > Kick someone from the guild you are in"));
+}
+
+void GuildChatTab::getAutoCompleteList(StringVect &names) const
+{
+ if (!guildManager)
+ return;
+
+ guildManager->getNames(names);
+ names.push_back("/notice ");
+}
+
+void GuildChatTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ chatLogger->log("#Guild", msg);
+}
+
+void GuildChatTab::playNewMessageSound() const
+{
+ soundManager.playGuiSound(SOUND_GUILD);
+}
+
+void GuildChatTab::optionChanged(const std::string &value)
+{
+ if (value == "showGuildOnline")
+ mShowOnline = config.getBoolValue("showGuildOnline");
+}
diff --git a/src/gui/widgets/tabs/guildchattab.h b/src/gui/widgets/tabs/guildchattab.h
new file mode 100644
index 000000000..f7aebcf55
--- /dev/null
+++ b/src/gui/widgets/tabs/guildchattab.h
@@ -0,0 +1,60 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_GUILDCHATTAB_H
+#define GUI_WIDGETS_GUILDCHATTAB_H
+
+#include "gui/widgets/tabs/chattab.h"
+
+/**
+ * A tab for a guild chat channel.
+ */
+class GuildChatTab final : public ChatTab, public ConfigListener
+{
+ public:
+ explicit GuildChatTab(const Widget2 *const widget);
+
+ A_DELETE_COPY(GuildChatTab)
+
+ ~GuildChatTab();
+
+ bool handleCommand(const std::string &type,
+ const std::string &args) override;
+
+ void showHelp() override;
+
+ void saveToLogFile(const std::string &msg) const override;
+
+ int getType() const override A_WARN_UNUSED
+ { return ChatTab::TAB_GUILD; }
+
+ void playNewMessageSound() const override;
+
+ void optionChanged(const std::string &value) override;
+
+ protected:
+ void handleInput(const std::string &msg) override;
+
+ void getAutoCompleteList(StringVect &names) const override;
+};
+
+#endif // GUI_WIDGETS_GUILDCHATTAB_H
diff --git a/src/gui/widgets/tabs/langtab.cpp b/src/gui/widgets/tabs/langtab.cpp
new file mode 100644
index 000000000..7bea453c7
--- /dev/null
+++ b/src/gui/widgets/tabs/langtab.cpp
@@ -0,0 +1,43 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/langtab.h"
+
+#include "chatlogger.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+LangTab::LangTab(const Widget2 *const widget, const std::string &lang) :
+ // TRANSLATORS: lang chat tab name
+ ChatTab(widget, _("Lang"), lang + " ")
+{
+}
+
+LangTab::~LangTab()
+{
+}
+
+void LangTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ chatLogger->log(std::string("#Lang"), std::string(msg));
+}
diff --git a/src/gui/widgets/tabs/langtab.h b/src/gui/widgets/tabs/langtab.h
new file mode 100644
index 000000000..fa4e7c08c
--- /dev/null
+++ b/src/gui/widgets/tabs/langtab.h
@@ -0,0 +1,43 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_LANGTAB_H
+#define GUI_WIDGETS_LANGTAB_H
+
+#include "gui/widgets/tabs/chattab.h"
+
+class LangTab final : public ChatTab
+{
+ public:
+ LangTab(const Widget2 *const widget, const std::string &lang);
+
+ A_DELETE_COPY(LangTab)
+
+ ~LangTab();
+
+ int getType() const override A_WARN_UNUSED
+ { return ChatTab::TAB_LANG; }
+
+ void saveToLogFile(const std::string &msg) const override;
+};
+
+extern LangTab *langChatTab;
+
+#endif // GUI_WIDGETS_LANGTAB_H
diff --git a/src/gui/widgets/tabs/setup_audio.cpp b/src/gui/widgets/tabs/setup_audio.cpp
new file mode 100644
index 000000000..219cf30f2
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_audio.cpp
@@ -0,0 +1,204 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_audio.h"
+
+#include "main.h"
+#include "map.h"
+
+#include "configuration.h"
+#include "soundmanager.h"
+
+#include "gui/viewport.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
+#include "gui/widgets/scrollarea.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+class SoundsModel final : public NamesModel
+{
+public:
+ SoundsModel() :
+ NamesModel()
+ {
+ mNames.push_back(gettext("(no sound)"));
+ Theme::fillSoundsList(mNames);
+ }
+
+ ~SoundsModel()
+ { }
+};
+
+Setup_Audio::Setup_Audio(const Widget2 *const widget) :
+ SetupTabScroll(widget),
+ mSoundModel(new SoundsModel),
+ mChannelsList(new SetupItemNames)
+{
+ // TRANSLATORS: audio tab in settings
+ setName(_("Audio"));
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Basic settings"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable Audio"), "", "sound", this, "soundEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable music"), "",
+ "playMusic", this, "playMusicEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable game sfx"), "",
+ "playBattleSound", this, "playBattleSoundEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable gui sfx"), "",
+ "playGuiSound", this, "playGuiSoundEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemSlider(_("Sfx volume"), "", "sfxVolume",
+ this, "sfxVolumeEvent", 0, soundManager.getMaxVolume(), 150, true);
+
+ // TRANSLATORS: settings option
+ new SetupItemSlider(_("Music volume"), "", "musicVolume",
+ this, "musicVolumeEvent", 0, soundManager.getMaxVolume(), 150, true);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable music fade out"), "",
+ "fadeoutmusic", this, "fadeoutmusicEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Audio frequency"), "",
+ "audioFrequency", this, "audioFrequencyEvent", 14000, 192000);
+
+ // TRANSLATORS: audio type
+ mChannelsList->push_back(_("mono"));
+ // TRANSLATORS: audio type
+ mChannelsList->push_back(_("stereo"));
+ // TRANSLATORS: audio type
+ mChannelsList->push_back(_("surround"));
+ // TRANSLATORS: audio type
+ mChannelsList->push_back(_("surround+center+lfe"));
+ // TRANSLATORS: settings option
+ new SetupItemSlider2(_("Audio channels"), "", "audioChannels", this,
+ "audioChannels", 1, 4, mChannelsList);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Sound effects"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Information dialog sound"), "",
+ "soundinfo", this, "soundinfoEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Request dialog sound"), "",
+ "soundrequest", this, "soundrequestEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Whisper message sound"), "",
+ "soundwhisper", this, "soundwhisperEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Guild / Party message sound"), "",
+ "soundguild", this, "soundguildEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Highlight message sound"), "",
+ "soundhighlight", this, "soundhighlightEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Global message sound"), "",
+ "soundglobal", this, "soundglobalEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Error message sound"), "",
+ "sounderror", this, "sounderrorEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Trade request sound"), "",
+ "soundtrade", this, "soundtradeEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Show window sound"), "",
+ "soundshowwindow", this, "soundshowwindowEvent", mSoundModel);
+
+ // TRANSLATORS: settings option
+ new SetupItemSound(_("Hide window sound"), "",
+ "soundhidewindow", this, "soundhidewindowEvent", mSoundModel);
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Other"), "", this);
+
+#ifdef USE_MUMBLE
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable mumble voice chat"), "",
+ "enableMumble", this, "enableMumbleEvent");
+#endif
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Download music"), "",
+ "download-music", this, "download-musicEvent");
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+Setup_Audio::~Setup_Audio()
+{
+ delete mSoundModel;
+ mSoundModel = nullptr;
+
+ delete mChannelsList;
+ mChannelsList = nullptr;
+}
+
+void Setup_Audio::apply()
+{
+ SetupTabScroll::apply();
+ if (config.getBoolValue("sound"))
+ {
+ soundManager.init();
+ if (viewport && config.getBoolValue("playMusic"))
+ {
+ const Map *const map = viewport->getMap();
+ if (map)
+ soundManager.playMusic(map->getMusicFile());
+ }
+ else
+ {
+ soundManager.stopMusic();
+ }
+ }
+ else
+ {
+ soundManager.close();
+ }
+}
diff --git a/src/gui/widgets/tabs/setup_audio.h b/src/gui/widgets/tabs/setup_audio.h
new file mode 100644
index 000000000..98cdc5470
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_audio.h
@@ -0,0 +1,45 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_AUDIO_H
+#define GUI_SETUP_AUDIO_H
+
+#include "gui/widgets/setupitem.h"
+
+class Setup_Audio final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Audio(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Audio)
+
+ ~Setup_Audio();
+
+ void apply() override;
+
+ private:
+ gcn::ListModel *mSoundModel;
+
+ SetupItemNames *mChannelsList;
+};
+
+#endif // GUI_SETUP_AUDIO_H
diff --git a/src/gui/widgets/tabs/setup_chat.cpp b/src/gui/widgets/tabs/setup_chat.cpp
new file mode 100644
index 000000000..e5acd10e5
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_chat.cpp
@@ -0,0 +1,208 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_chat.h"
+
+#include "gui/windows/chatwindow.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/setupitem.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+extern int serverVersion;
+
+Setup_Chat::Setup_Chat(const Widget2 *const widget) :
+ SetupTabScroll(widget)
+{
+ // TRANSLATORS: settings tab name
+ setName(_("Chat"));
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Window"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Auto hide chat window"), "",
+ "autohideChat", this, "autohideChatEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Protect chat focus"), "",
+ "protectChatFocus", this, "protectChatFocusEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Colors"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Remove colors from received chat messages"), "",
+ "removeColors", this, "removeColorsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show chat colors list"), "",
+ "showChatColorsList", this, "showChatColorsListEvent");
+
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Commands"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Allow magic and GM commands in all chat tabs"),
+ "", "allowCommandsInChatTabs", this, "allowCommandsInChatTabsEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Limits"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Limit max chars in chat line"), "",
+ "chatMaxCharLimit", this, "chatMaxCharLimitEvent", 0, 500);
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Limit max lines in chat"), "",
+ "chatMaxLinesLimit", this, "chatMaxLinesLimitEvent", 0, 500);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Logs"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable chat Log"), "",
+ "enableChatLog", this, "enableChatLogEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable debug chat Log"), "",
+ "enableDebugLog", this, "enableDebugLogEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show chat history"), "",
+ "showChatHistory", this, "showChatHistoryEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show party online messages"), "",
+ "showPartyOnline", this, "showPartyOnlineEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show guild online messages"), "",
+ "showGuildOnline", this, "showGuildOnlineEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Messages"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Hide shop messages"), "",
+ "hideShopMessages", this, "hideShopMessagesEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Tabs"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Put all whispers in tabs"), "",
+ "whispertab", this, "whispertabEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Log magic messages in debug tab"), "",
+ "showMagicInDebug", this, "showMagicInDebugEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show server messages in debug tab"), "",
+ "serverMsgInDebug", this, "serverMsgInDebugEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable trade tab"), "",
+ "enableTradeTab", this, "enableTradeTabEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable gm tab"), "",
+ "enableGmTab", this, "enableGmTabEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable language tab"), "",
+ "enableLangTab", this, "enableLangTabEvent", false);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show all languages messages"), "",
+ "showAllLang", this, "showAllLangEvent", false);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable battle tab"), "",
+ "enableBattleTab", this, "enableBattleTabEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show battle events"), "",
+ "showBattleEvents", this, "showBattleEventsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Resize chat tabs if need"), "",
+ "hideChatInput", this, "hideChatInputEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Time"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Use local time"), "",
+ "useLocalTime", this, "useLocalTimeEvent");
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Other"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemTextField(_("Highlight words (separated by comma)"), "",
+ "highlightWords", this, "highlightWordsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemTextField(_("Globals ignore names (separated by comma)"), "",
+ "globalsFilter", this, "globalsFilterEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show MVP messages"), "",
+ "showMVP", this, "showMVPEvent");
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+void Setup_Chat::apply()
+{
+ SetupTabScroll::apply();
+
+ if (chatWindow)
+ {
+ chatWindow->adjustTabSize();
+ chatWindow->parseHighlights();
+ }
+}
+
+void Setup_Chat::externalUpdated()
+{
+ reread("enableLangTab");
+ reread("showAllLang");
+}
diff --git a/src/gui/widgets/tabs/setup_chat.h b/src/gui/widgets/tabs/setup_chat.h
new file mode 100644
index 000000000..108f67a7f
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_chat.h
@@ -0,0 +1,40 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_CHAT_H
+#define GUI_SETUP_CHAT_H
+
+#include "gui/widgets/tabs/setuptabscroll.h"
+
+class Setup_Chat final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Chat(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Chat)
+
+ void apply() override;
+
+ void externalUpdated() override;
+};
+
+#endif // GUI_SETUP_CHAT_H
diff --git a/src/gui/widgets/tabs/setup_colors.cpp b/src/gui/widgets/tabs/setup_colors.cpp
new file mode 100644
index 000000000..f5b834b6a
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_colors.cpp
@@ -0,0 +1,445 @@
+/*
+ * Configurable text colors
+ * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net>
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_colors.h"
+
+#include "gui/gui.h"
+#include "gui/sdlfont.h"
+#include "gui/userpalette.h"
+
+#include "gui/widgets/browserbox.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/listbox.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/slider.h"
+#include "gui/widgets/textfield.h"
+#include "gui/widgets/textpreview.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include <string>
+#include <cmath>
+
+#include "debug.h"
+
+// TRANSLATORS: color selection preview message
+const char *const Setup_Colors::rawmsg =
+ N_("This is what the color looks like");
+
+Setup_Colors::Setup_Colors(const Widget2 *const widget) :
+ SetupTab(widget),
+ gcn::SelectionListener(),
+ mColorBox(new ListBox(this, userPalette, "")),
+ mScroll(new ScrollArea(mColorBox, true, "setup_colors_background.xml")),
+ mPreview(new BrowserBox(this, BrowserBox::AUTO_WRAP)),
+ mTextPreview(new TextPreview(this, gettext(rawmsg))),
+ mPreviewBox(new ScrollArea(mPreview, true,
+ "setup_colors_preview_background.xml")),
+ mSelected(-1),
+ // TRANSLATORS: colors tab. label.
+ mGradTypeLabel(new Label(this, _("Type:"))),
+ mGradTypeSlider(new Slider(0, 3)),
+ mGradTypeText(new Label(this)),
+ // TRANSLATORS: colors tab. label.
+ mGradDelayLabel(new Label(this, _("Delay:"))),
+ mGradDelaySlider(new Slider(20, 100)),
+ mGradDelayText(new TextField(this)),
+ // TRANSLATORS: colors tab. label.
+ mRedLabel(new Label(this, _("Red:"))),
+ mRedSlider(new Slider(0, 255)),
+ mRedText(new TextField(this)),
+ // TRANSLATORS: colors tab. label.
+ mGreenLabel(new Label(this, _("Green:"))),
+ mGreenSlider(new Slider(0, 255)),
+ mGreenText(new TextField(this)),
+ // TRANSLATORS: colors tab. label.
+ mBlueLabel(new Label(this, _("Blue:"))),
+ mBlueSlider(new Slider(0, 255)),
+ mBlueText(new TextField(this))
+{
+ // TRANSLATORS: settings colors tab name
+ setName(_("Colors"));
+ mColorBox->addSelectionListener(this);
+ mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mPreview->setOpaque(false);
+
+ // don't do anything with links
+ mPreview->setLinkHandler(nullptr);
+
+ mPreviewBox->setHeight(20);
+ mPreviewBox->setScrollPolicy(gcn::ScrollArea::SHOW_NEVER,
+ gcn::ScrollArea::SHOW_NEVER);
+
+ mGradTypeSlider->setWidth(180);
+ mGradTypeSlider->setActionEventId("slider_grad");
+ mGradTypeSlider->setValue(0);
+ mGradTypeSlider->addActionListener(this);
+ mGradTypeSlider->setEnabled(false);
+
+ // TRANSLATORS: color type
+ std::string longText = _("Static");
+
+ const gcn::Font *const font = getFont();
+ if (getFont()->getWidth(_("Pulse")) > font->getWidth(longText))
+ {
+ // TRANSLATORS: color type
+ longText = _("Pulse");
+ }
+ if (getFont()->getWidth(_("Rainbow")) > font->getWidth(longText))
+ {
+ // TRANSLATORS: color type
+ longText = _("Rainbow");
+ }
+ if (getFont()->getWidth(_("Spectrum")) > font->getWidth(longText))
+ {
+ // TRANSLATORS: color type
+ longText = _("Spectrum");
+ }
+
+ mGradTypeText->setCaption(longText);
+
+ mGradDelayText->setWidth(40);
+ mGradDelayText->setRange(20, 100);
+ mGradDelayText->setNumeric(true);
+ mGradDelayText->setEnabled(false);
+
+ mGradDelaySlider->setWidth(180);
+ mGradDelaySlider->setValue(mGradDelayText->getValue());
+ mGradDelaySlider->setActionEventId("slider_graddelay");
+ mGradDelaySlider->addActionListener(this);
+ mGradDelaySlider->setEnabled(false);
+
+ mRedText->setWidth(40);
+ mRedText->setRange(0, 255);
+ mRedText->setNumeric(true);
+ mRedText->setEnabled(false);
+
+ mRedSlider->setWidth(180);
+ mRedSlider->setValue(mRedText->getValue());
+ mRedSlider->setActionEventId("slider_red");
+ mRedSlider->addActionListener(this);
+ mRedSlider->setEnabled(false);
+
+ mGreenText->setWidth(40);
+ mGreenText->setRange(0, 255);
+ mGreenText->setNumeric(true);
+ mGreenText->setEnabled(false);
+
+ mGreenSlider->setWidth(180);
+ mGreenSlider->setValue(mGreenText->getValue());
+ mGreenSlider->setActionEventId("slider_green");
+ mGreenSlider->addActionListener(this);
+ mGreenSlider->setEnabled(false);
+
+ mBlueText->setWidth(40);
+ mBlueText->setRange(0, 255);
+ mBlueText->setNumeric(true);
+ mBlueText->setEnabled(false);
+
+ mBlueSlider->setWidth(180);
+ mBlueSlider->setValue(mBlueText->getValue());
+ mBlueSlider->setActionEventId("slider_blue");
+ mBlueSlider->addActionListener(this);
+ mBlueSlider->setEnabled(false);
+
+ setOpaque(false);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mScroll, 6, 6).setPadding(2);
+ place(0, 6, mPreviewBox, 6).setPadding(2);
+ place(0, 7, mGradTypeLabel, 3);
+ place(3, 7, mGradTypeSlider);
+ place(4, 7, mGradTypeText, 2).setPadding(1);
+ place(0, 8, mRedLabel, 3);
+ place(3, 8, mRedSlider);
+ place(5, 8, mRedText).setPadding(1);
+ place(0, 9, mGreenLabel, 3);
+ place(3, 9, mGreenSlider);
+ place(5, 9, mGreenText).setPadding(1);
+ place(0, 10, mBlueLabel, 3);
+ place(3, 10, mBlueSlider);
+ place(5, 10, mBlueText).setPadding(1);
+ place(0, 11, mGradDelayLabel, 3);
+ place(3, 11, mGradDelaySlider);
+ place(5, 11, mGradDelayText).setPadding(1);
+
+ mGradTypeText->setCaption("");
+
+ setDimension(gcn::Rectangle(0, 0, 365, 350));
+}
+
+Setup_Colors::~Setup_Colors()
+{
+ if (mPreviewBox && mPreviewBox->getContent() == mPreview)
+ {
+ delete mTextPreview;
+ mTextPreview = nullptr;
+ }
+ else
+ {
+ delete mPreview;
+ mPreview = nullptr;
+ }
+}
+
+void Setup_Colors::action(const gcn::ActionEvent &event)
+{
+ const std::string &eventId = event.getId();
+ if (eventId == "slider_grad")
+ {
+ updateGradType();
+ updateColor();
+ return;
+ }
+
+ if (eventId == "slider_graddelay")
+ {
+ mGradDelayText->setText(toString(
+ std::floor(mGradDelaySlider->getValue())));
+ updateColor();
+ return;
+ }
+ if (eventId == "slider_red")
+ {
+ mRedText->setText(toString(std::floor(mRedSlider->getValue())));
+ updateColor();
+ return;
+ }
+ if (eventId == "slider_green")
+ {
+ mGreenText->setText(toString(std::floor(mGreenSlider->getValue())));
+ updateColor();
+ return;
+ }
+ if (eventId == "slider_blue")
+ {
+ mBlueText->setText(toString(std::floor(mBlueSlider->getValue())));
+ updateColor();
+ return;
+ }
+}
+
+void Setup_Colors::valueChanged(const gcn::SelectionEvent &event A_UNUSED)
+{
+ if (!userPalette)
+ return;
+
+ mSelected = mColorBox->getSelected();
+ const int type = userPalette->getColorTypeAt(mSelected);
+ const gcn::Color *col = &userPalette->getColor(type);
+ const Palette::GradientType grad = userPalette->getGradientType(type);
+ const int delay = userPalette->getGradientDelay(type);
+
+ mPreview->clearRows();
+ mPreviewBox->setContent(mTextPreview);
+ mTextPreview->setFont(boldFont);
+ mTextPreview->setTextColor(col);
+ mTextPreview->setTextBGColor(nullptr);
+ mTextPreview->setOpaque(false);
+ mTextPreview->setShadow(true);
+ mTextPreview->setOutline(true);
+ mTextPreview->useTextAlpha(false);
+
+ switch (type)
+ {
+ case UserPalette::AIR_COLLISION_HIGHLIGHT:
+ case UserPalette::WATER_COLLISION_HIGHLIGHT:
+ case UserPalette::GROUNDTOP_COLLISION_HIGHLIGHT:
+ case UserPalette::COLLISION_HIGHLIGHT:
+ case UserPalette::PORTAL_HIGHLIGHT:
+ case UserPalette::HOME_PLACE:
+ case UserPalette::ROAD_POINT:
+ mTextPreview->setBGColor(col);
+ mTextPreview->setOpaque(true);
+ mTextPreview->setOutline(false);
+ mTextPreview->setShadow(false);
+ break;
+ case UserPalette::ATTACK_RANGE_BORDER:
+ case UserPalette::HOME_PLACE_BORDER:
+ mTextPreview->setFont(gui->getFont());
+ mTextPreview->setTextColor(col);
+ mTextPreview->setOutline(false);
+ mTextPreview->setShadow(false);
+ break;
+ case UserPalette::PARTICLE:
+ case UserPalette::EXP_INFO:
+ case UserPalette::PICKUP_INFO:
+ case UserPalette::HIT_PLAYER_MONSTER:
+ case UserPalette::HIT_MONSTER_PLAYER:
+ case UserPalette::HIT_CRITICAL:
+ case UserPalette::MISS:
+ case UserPalette::HIT_LOCAL_PLAYER_MONSTER:
+ case UserPalette::HIT_LOCAL_PLAYER_CRITICAL:
+ case UserPalette::HIT_LOCAL_PLAYER_MISS:
+ case UserPalette::ATTACK_RANGE:
+ case UserPalette::MONSTER_ATTACK_RANGE:
+ case UserPalette::FLOOR_ITEM_TEXT:
+ mTextPreview->setShadow(false);
+ break;
+ default:
+ break;
+ }
+
+ switch (type)
+ {
+ case UserPalette::PORTAL_HIGHLIGHT:
+ case UserPalette::ATTACK_RANGE:
+ case UserPalette::ATTACK_RANGE_BORDER:
+ case UserPalette::MONSTER_ATTACK_RANGE:
+ case UserPalette::HOME_PLACE:
+ case UserPalette::HOME_PLACE_BORDER:
+ case UserPalette::AIR_COLLISION_HIGHLIGHT:
+ case UserPalette::WATER_COLLISION_HIGHLIGHT:
+ case UserPalette::GROUNDTOP_COLLISION_HIGHLIGHT:
+ case UserPalette::COLLISION_HIGHLIGHT:
+ case UserPalette::WALKABLE_HIGHLIGHT:
+ case UserPalette::ROAD_POINT:
+ case UserPalette::MONSTER_HP:
+ case UserPalette::MONSTER_HP2:
+ case UserPalette::PLAYER_HP:
+ case UserPalette::PLAYER_HP2:
+ case UserPalette::FLOOR_ITEM_TEXT:
+ // TRANSLATORS: colors tab. label.
+ mGradDelayLabel->setCaption(_("Alpha:"));
+ mGradDelayText->setRange(0, 255);
+ mGradDelaySlider->setScale(0, 255);
+ break;
+ default:
+ // TRANSLATORS: colors tab. label.
+ mGradDelayLabel->setCaption(_("Delay:"));
+ mGradDelayText->setRange(20, 100);
+ mGradDelaySlider->setScale(20, 100);
+ break;
+ }
+ if (grad != Palette::STATIC && grad != Palette::PULSE)
+ { // If nonstatic color, don't display the current, but the committed
+ // color at the sliders
+ col = &userPalette->getCommittedColor(type);
+ }
+ else if (grad == Palette::PULSE)
+ {
+ col = &userPalette->getTestColor(type);
+ }
+
+ setEntry(mGradDelaySlider, mGradDelayText, delay);
+ setEntry(mRedSlider, mRedText, col->r);
+ setEntry(mGreenSlider, mGreenText, col->g);
+ setEntry(mBlueSlider, mBlueText, col->b);
+
+ mGradTypeSlider->setValue(grad);
+ updateGradType();
+ mGradTypeSlider->setEnabled(true);
+}
+
+void Setup_Colors::setEntry(Slider *const s, TextField *const t,
+ const int value)
+{
+ if (s)
+ s->setValue(value);
+ if (t)
+ t->setText(toString(value));
+}
+
+void Setup_Colors::apply()
+{
+ if (userPalette)
+ userPalette->commit();
+}
+
+void Setup_Colors::cancel()
+{
+ if (!userPalette)
+ return;
+
+ userPalette->rollback();
+ const int type = userPalette->getColorTypeAt(mSelected);
+ const gcn::Color *const col = &userPalette->getColor(type);
+ mGradTypeSlider->setValue(userPalette->getGradientType(type));
+ const int delay = userPalette->getGradientDelay(type);
+ setEntry(mGradDelaySlider, mGradDelayText, delay);
+ setEntry(mRedSlider, mRedText, col->r);
+ setEntry(mGreenSlider, mGreenText, col->g);
+ setEntry(mBlueSlider, mBlueText, col->b);
+}
+
+void Setup_Colors::updateGradType()
+{
+ if (mSelected == -1 || !userPalette)
+ return;
+
+ mSelected = mColorBox->getSelected();
+ const int type = userPalette->getColorTypeAt(mSelected);
+ const Palette::GradientType grad = userPalette->getGradientType(type);
+
+ mGradTypeText->setCaption(
+ // TRANSLATORS: color type
+ (grad == Palette::STATIC) ? _("Static") :
+ // TRANSLATORS: color type
+ (grad == Palette::PULSE) ? _("Pulse") :
+ // TRANSLATORS: color type
+ (grad == Palette::RAINBOW) ? _("Rainbow") : _("Spectrum"));
+
+ const bool enable = (grad == Palette::STATIC || grad == Palette::PULSE);
+ const bool delayEnable = true;
+
+ mGradDelayText->setEnabled(delayEnable);
+ mGradDelaySlider->setEnabled(delayEnable);
+
+ mRedText->setEnabled(enable);
+ mRedSlider->setEnabled(enable);
+ mGreenText->setEnabled(enable);
+ mGreenSlider->setEnabled(enable);
+ mBlueText->setEnabled(enable);
+ mBlueSlider->setEnabled(enable);
+}
+
+void Setup_Colors::updateColor()
+{
+ if (mSelected == -1 || !userPalette)
+ return;
+
+ const int type = userPalette->getColorTypeAt(mSelected);
+ const Palette::GradientType grad = static_cast<Palette::GradientType>(
+ static_cast<int>(mGradTypeSlider->getValue()));
+ const int delay = static_cast<int>(mGradDelaySlider->getValue());
+ userPalette->setGradient(type, grad);
+ userPalette->setGradientDelay(type, delay);
+
+ if (grad == Palette::STATIC)
+ {
+ userPalette->setColor(type,
+ static_cast<int>(mRedSlider->getValue()),
+ static_cast<int>(mGreenSlider->getValue()),
+ static_cast<int>(mBlueSlider->getValue()));
+ }
+ else if (grad == Palette::PULSE)
+ {
+ userPalette->setTestColor(type, gcn::Color(
+ static_cast<int>(mRedSlider->getValue()),
+ static_cast<int>(mGreenSlider->getValue()),
+ static_cast<int>(mBlueSlider->getValue())));
+ }
+}
diff --git a/src/gui/widgets/tabs/setup_colors.h b/src/gui/widgets/tabs/setup_colors.h
new file mode 100644
index 000000000..fcc6a378f
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_colors.h
@@ -0,0 +1,93 @@
+/*
+ * Configurable text colors
+ * Copyright (C) 2008 Douglas Boffey <dougaboffey@netscape.net>
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_COLORS_H
+#define GUI_SETUP_COLORS_H
+
+#include "gui/widgets/tabs/setuptab.h"
+
+#include <guichan/selectionlistener.hpp>
+
+#include <string>
+
+class BrowserBox;
+class Label;
+class ListBox;
+class ScrollArea;
+class Slider;
+class TextField;
+class TextPreview;
+
+class Setup_Colors final : public SetupTab,
+ public gcn::SelectionListener
+{
+ public:
+ explicit Setup_Colors(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Colors)
+
+ ~Setup_Colors();
+
+ void apply() override;
+
+ void cancel() override;
+
+ void action(const gcn::ActionEvent &event) override;
+
+ void valueChanged(const gcn::SelectionEvent &event) override;
+
+ private:
+ static const char *const rawmsg;
+
+ ListBox *mColorBox;
+ ScrollArea *mScroll;
+ BrowserBox *mPreview;
+ TextPreview *mTextPreview;
+ ScrollArea *mPreviewBox;
+ int mSelected;
+
+ Label *mGradTypeLabel;
+ Slider *mGradTypeSlider;
+ Label *mGradTypeText;
+
+ Label *mGradDelayLabel;
+ Slider *mGradDelaySlider;
+ TextField *mGradDelayText;
+
+ Label *mRedLabel;
+ Slider *mRedSlider;
+ TextField *mRedText;
+
+ Label *mGreenLabel;
+ Slider *mGreenSlider;
+ TextField *mGreenText;
+
+ Label *mBlueLabel;
+ Slider *mBlueSlider;
+ TextField *mBlueText;
+
+ static void setEntry(Slider *const s, TextField *const t,
+ const int value);
+ void updateColor();
+ void updateGradType();
+};
+
+#endif // GUI_SETUP_COLORS_H
diff --git a/src/gui/widgets/tabs/setup_input.cpp b/src/gui/widgets/tabs/setup_input.cpp
new file mode 100644
index 000000000..35fa4204a
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_input.cpp
@@ -0,0 +1,414 @@
+/*
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_input.h"
+
+#include "configuration.h"
+
+#include "input/inputmanager.h"
+#include "input/keyboardconfig.h"
+
+#include "gui/setupactiondata.h"
+
+#include "gui/windows/okdialog.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/listbox.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/tabstrip.h"
+
+#include <guichan/listmodel.hpp>
+
+#include "debug.h"
+
+static int selectedData = 0;
+static const int setupGroups = 9;
+
+/**
+ * The list model for key function list.
+ *
+ * \ingroup Interface
+ */
+class KeyListModel final : public gcn::ListModel
+{
+ public:
+ KeyListModel() :
+ mDataNum(0),
+ mSize(0)
+ {
+ }
+
+ A_DELETE_COPY(KeyListModel)
+
+ /**
+ * Returns the number of elements in container.
+ */
+ int getNumberOfElements() override
+ { return mSize; }
+
+ /**
+ * Returns element from container.
+ */
+ std::string getElementAt(int i) override
+ { return setupActionData[selectedData][i].text; }
+
+ /**
+ * Sets element from container.
+ */
+ void setElementAt(const int i, const std::string &caption)
+ { setupActionData[selectedData][i].text = caption; }
+
+ void setSize(const int size)
+ { mSize = size; }
+
+ void setDataNum(const int num)
+ { mDataNum = num; }
+
+ private:
+ int mDataNum;
+ int mSize;
+};
+
+Setup_Input::Setup_Input(const Widget2 *const widget) :
+ SetupTab(widget),
+ mKeyListModel(new KeyListModel),
+ mKeyList(new ListBox(this, mKeyListModel, "")),
+ // TRANSLATORS: button in input settings tab
+ mAssignKeyButton(new Button(this, _("Assign"), "assign", this)),
+ // TRANSLATORS: button in input settings tab
+ mUnassignKeyButton(new Button(this, _("Unassign"), "unassign", this)),
+ // TRANSLATORS: button in input settings tab
+ mDefaultButton(new Button(this, _("Default"), "default", this)),
+ // TRANSLATORS: button in input settings tab
+ mResetKeysButton(new Button(this, _("Reset all keys"), "resetkeys", this)),
+ mTabs(new TabStrip(this, config.getIntValue("fontSize") + 10)),
+ mScrollArea(new ScrollArea(mKeyList, true, "setup_input_background.xml")),
+ mKeySetting(false),
+ mActionDataSize(new int [9])
+{
+ inputManager.setSetupInput(this);
+ // TRANSLATORS: setting tab name
+ setName(_("Input"));
+
+ selectedData = 0;
+
+ for (int f = 0; f < setupGroups; f ++)
+ {
+ int cnt = 0;
+ while (!setupActionData[f][cnt].name.empty())
+ cnt ++;
+ mActionDataSize[f] = cnt;
+ }
+
+ mKeyListModel->setSize(mActionDataSize[0]);
+ refreshKeys();
+ if (gui)
+ mKeyList->setFont(reinterpret_cast<gcn::Font*>(gui->getHelpFont()));
+ mKeyList->addActionListener(this);
+
+ mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
+ mAssignKeyButton->addActionListener(this);
+ mAssignKeyButton->setEnabled(false);
+ mUnassignKeyButton->addActionListener(this);
+ mUnassignKeyButton->setEnabled(false);
+ mResetKeysButton->addActionListener(this);
+ mDefaultButton->addActionListener(this);
+
+ mTabs->addActionListener(this);
+ mTabs->setActionEventId("tabs_");
+ int k = 0;
+ while (pages[k])
+ {
+ mTabs->addButton(gettext(pages[k]), pages[k]);
+ k ++;
+ }
+
+ fixTranslations();
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mTabs, 5);
+ place(0, 1, mScrollArea, 5, 5).setPadding(2);
+ place(0, 6, mResetKeysButton);
+ place(2, 6, mAssignKeyButton);
+ place(3, 6, mUnassignKeyButton);
+ place(4, 6, mDefaultButton);
+
+ int width = 600;
+ if (config.getIntValue("screenwidth") >= 730)
+ width += 100;
+
+ setDimension(gcn::Rectangle(0, 0, width, 350));
+}
+
+Setup_Input::~Setup_Input()
+{
+ delete mKeyList;
+ mKeyList = nullptr;
+ delete mKeyListModel;
+ mKeyListModel = nullptr;
+
+ delete mAssignKeyButton;
+ mAssignKeyButton = nullptr;
+ delete mUnassignKeyButton;
+ mUnassignKeyButton = nullptr;
+ delete mResetKeysButton;
+ mResetKeysButton = nullptr;
+ delete [] mActionDataSize;
+ mActionDataSize = nullptr;
+ delete mScrollArea;
+ mScrollArea = nullptr;
+}
+
+void Setup_Input::apply()
+{
+ keyUnresolved();
+ int key1, key2;
+
+ if (inputManager.hasConflicts(key1, key2))
+ {
+ const std::string str1 = keyToString(key1);
+ const std::string str2 = keyToString(key2);
+
+ // TRANSLATORS: input settings error header
+ new OkDialog(_("Key Conflict(s) Detected."),
+ // TRANSLATORS: input settings error
+ strprintf(_("Conflict \"%s\" and \"%s\" keys. "
+ "Resolve them, or gameplay may result in strange behaviour."),
+ gettext(str1.c_str()), gettext(str2.c_str())), DIALOG_ERROR);
+ }
+ keyboard.setEnabled(true);
+ inputManager.store();
+}
+
+void Setup_Input::cancel()
+{
+ keyUnresolved();
+ inputManager.retrieve();
+ keyboard.setEnabled(true);
+ refreshKeys();
+}
+
+void Setup_Input::action(const gcn::ActionEvent &event)
+{
+ const std::string id = event.getId();
+
+ if (event.getSource() == mKeyList)
+ {
+ if (!mKeySetting)
+ {
+ const int i(mKeyList->getSelected());
+ if (i >= 0 && i < mActionDataSize[selectedData])
+ {
+ if (setupActionData[selectedData][i].actionId
+ == static_cast<int>(Input::KEY_NO_VALUE))
+ {
+ mAssignKeyButton->setEnabled(false);
+ mUnassignKeyButton->setEnabled(false);
+ }
+ else
+ {
+ mAssignKeyButton->setEnabled(true);
+ mUnassignKeyButton->setEnabled(true);
+ }
+ }
+ }
+ }
+ else if (id == "assign")
+ {
+ mKeySetting = true;
+ mAssignKeyButton->setEnabled(false);
+ keyboard.setEnabled(false);
+ const int i(mKeyList->getSelected());
+ if (i >= 0 && i < mActionDataSize[selectedData])
+ {
+ const SetupActionData &key = setupActionData[selectedData][i];
+ const int ik = key.actionId;
+ inputManager.setNewKeyIndex(ik);
+ mKeyListModel->setElementAt(i, std::string(
+ gettext(key.name.c_str())).append(": ?"));
+ }
+ }
+ else if (id == "unassign")
+ {
+ const int i(mKeyList->getSelected());
+ if (i >= 0 && i < mActionDataSize[selectedData])
+ {
+ const SetupActionData &key = setupActionData[selectedData][i];
+ const int ik = key.actionId;
+ inputManager.setNewKeyIndex(ik);
+ refreshAssignedKey(mKeyList->getSelected());
+ inputManager.unassignKey();
+ inputManager.setNewKeyIndex(static_cast<int>(Input::KEY_NO_VALUE));
+ }
+ mAssignKeyButton->setEnabled(true);
+ }
+ else if (id == "resetkeys")
+ {
+ inputManager.resetKeys();
+ inputManager.update();
+ refreshKeys();
+ }
+ else if (id == "default")
+ {
+ const int i(mKeyList->getSelected());
+ if (i >= 0 && i < mActionDataSize[selectedData])
+ {
+ const SetupActionData &key = setupActionData[selectedData][i];
+ const int ik = key.actionId;
+ inputManager.makeDefault(ik);
+ refreshKeys();
+ }
+ }
+ else if (strStartWith(id, "tabs_"))
+ {
+ int k = 0;
+ std::string str("tabs_");
+ while (pages[k])
+ {
+ if (str + pages[k] == id)
+ break;
+ k ++;
+ }
+ if (pages[k] && str + pages[k] == id)
+ {
+ selectedData = k;
+ mKeyListModel->setSize(mActionDataSize[k]);
+ refreshKeys();
+ mKeyList->setSelected(0);
+ }
+ }
+}
+
+void Setup_Input::refreshAssignedKey(const int index)
+{
+ const SetupActionData &key = setupActionData[selectedData][index];
+ if (key.actionId == static_cast<int>(Input::KEY_NO_VALUE))
+ {
+ const std::string str(" \342\200\225\342\200\225\342\200\225"
+ "\342\200\225\342\200\225 ");
+ mKeyListModel->setElementAt(index,
+ str + gettext(key.name.c_str()) + str);
+ }
+ else
+ {
+ std::string str = gettext(key.name.c_str());
+ unsigned int sz = 20;
+ if (mainGraphics->mWidth > 800)
+ sz = 30;
+ while (str.size() < sz)
+ str.append(" ");
+ mKeyListModel->setElementAt(index, strprintf("%s: %s", str.c_str(),
+ inputManager.getKeyStringLong(key.actionId).c_str()));
+ }
+}
+
+void Setup_Input::newKeyCallback(const int index)
+{
+ mKeySetting = false;
+ const int i = keyToSetupData(index);
+ if (i >= 0)
+ refreshAssignedKey(i);
+ mAssignKeyButton->setEnabled(true);
+}
+
+int Setup_Input::keyToSetupData(const int index) const
+{
+ for (int i = 0; i < mActionDataSize[selectedData]; i++)
+ {
+ const SetupActionData &key = setupActionData[selectedData][i];
+ if (key.actionId == index)
+ return i;
+ }
+ return -1;
+}
+
+std::string Setup_Input::keyToString(const int index) const
+{
+ for (int f = 0; f < setupGroups; f ++)
+ {
+ for (int i = 0; i < mActionDataSize[f]; i++)
+ {
+ const SetupActionData &key = setupActionData[f][i];
+ if (key.actionId == index)
+ return key.name;
+ }
+ }
+ // TRANSLATORS: unknown key name
+ return _("unknown");
+}
+
+void Setup_Input::refreshKeys()
+{
+ for (int i = 0; i < mActionDataSize[selectedData]; i++)
+ refreshAssignedKey(i);
+}
+
+void Setup_Input::keyUnresolved()
+{
+ if (mKeySetting)
+ {
+ newKeyCallback(inputManager.getNewKeyIndex());
+ inputManager.setNewKeyIndex(static_cast<int>(Input::KEY_NO_VALUE));
+ }
+}
+
+void Setup_Input::fixTranslation(SetupActionData *const actionDatas,
+ const int actionStart, const int actionEnd,
+ const std::string &text) const
+{
+ int k = 0;
+
+ while (!actionDatas[k].name.empty())
+ {
+ SetupActionData &data = actionDatas[k];
+
+ const int actionId = data.actionId;
+ if (actionId >= actionStart && actionId <= actionEnd)
+ {
+ data.name = strprintf(gettext(text.c_str()),
+ actionId - actionStart + 1);
+ }
+ k ++;
+ }
+}
+
+void Setup_Input::fixTranslations() const
+{
+ fixTranslation(setupActionData1, static_cast<int>(Input::KEY_SHORTCUT_1),
+ static_cast<int>(Input::KEY_SHORTCUT_20), "Item Shortcut %d");
+
+ fixTranslation(setupActionData3, static_cast<int>(Input::KEY_EMOTE_1),
+ static_cast<int>(Input::KEY_EMOTE_48), "Emote Shortcut %d");
+
+ fixTranslation(setupActionData4, static_cast<int>(Input::KEY_OUTFIT_1),
+ static_cast<int>(Input::KEY_OUTFIT_48), "Outfit Shortcut %d");
+
+ fixTranslation(setupActionData7, static_cast<int>(
+ Input::KEY_MOVE_TO_POINT_1),
+ static_cast<int>(Input::KEY_MOVE_TO_POINT_48),
+ "Move to point Shortcut %d");
+}
diff --git a/src/gui/widgets/tabs/setup_input.h b/src/gui/widgets/tabs/setup_input.h
new file mode 100644
index 000000000..03113913e
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_input.h
@@ -0,0 +1,104 @@
+/*
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_INPUT_H
+#define GUI_SETUP_INPUT_H
+
+#include "gui/widgets/tabs/setuptab.h"
+
+#include <string>
+
+class Button;
+class ListBox;
+class KeyListModel;
+class ScrollArea;
+class TabStrip;
+
+struct SetupActionData;
+
+class Setup_Input final : public SetupTab
+{
+ public:
+ /**
+ * Constructor
+ */
+ explicit Setup_Input(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Input)
+
+ /**
+ * Destructor
+ */
+ ~Setup_Input();
+
+ void apply() override;
+
+ void cancel() override;
+
+ void action(const gcn::ActionEvent &event) override;
+
+ /**
+ * Get an update on the assigned key.
+ */
+ void refreshAssignedKey(const int index);
+
+ /**
+ * The callback function when a new key has been pressed.
+ */
+ void newKeyCallback(const int index);
+
+ /**
+ * Shorthand method to update all the keys.
+ */
+ void refreshKeys();
+
+ /**
+ * If a key function is unresolved, then this reverts it.
+ */
+ void keyUnresolved();
+
+ int keyToSetupData(const int index) const A_WARN_UNUSED;
+
+ std::string keyToString(const int index) const A_WARN_UNUSED;
+
+ private:
+ void fixTranslations() const;
+
+ void fixTranslation(SetupActionData *const actionDatas,
+ const int actionStart, const int actionEnd,
+ const std::string &text) const;
+
+ KeyListModel *mKeyListModel;
+ ListBox *mKeyList;
+
+ Button *mAssignKeyButton;
+ Button *mUnassignKeyButton;
+ Button *mDefaultButton;
+ Button *mResetKeysButton;
+ TabStrip *mTabs;
+ ScrollArea *mScrollArea;
+ bool mKeySetting; /**< flag to check if key being set. */
+ int *mActionDataSize;
+};
+
+#endif // GUI_SETUP_INPUT_H
diff --git a/src/gui/widgets/tabs/setup_joystick.cpp b/src/gui/widgets/tabs/setup_joystick.cpp
new file mode 100644
index 000000000..15b6959a9
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_joystick.cpp
@@ -0,0 +1,187 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_joystick.h"
+
+#include "configuration.h"
+
+#include "input/joystick.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/checkbox.h"
+#include "gui/widgets/dropdown.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+extern Joystick *joystick;
+
+Setup_Joystick::Setup_Joystick(const Widget2 *const widget) :
+ SetupTab(widget),
+ mCalibrateLabel(new Label(this,
+ // TRANSLATORS: joystick settings tab label
+ _("Press the button to start calibration"))),
+ // TRANSLATORS: joystick settings tab button
+ mCalibrateButton(new Button(this, _("Calibrate"), "calibrate", this)),
+ // TRANSLATORS: joystick settings tab button
+ mDetectButton(new Button(this, _("Detect joysticks"), "detect", this)),
+ mOriginalJoystickEnabled(config.getBoolValue("joystickEnabled")),
+ // TRANSLATORS: joystick settings tab checkbox
+ mJoystickEnabled(new CheckBox(this, _("Enable joystick"))),
+ mNamesModel(new NamesModel),
+ mNamesDropDown(new DropDown(this, mNamesModel)),
+ // TRANSLATORS: joystick settings tab checkbox
+ mUseInactiveCheckBox(new CheckBox(this, _("Use joystick if client "
+ "window inactive"), config.getBoolValue("useInactiveJoystick")))
+{
+ // TRANSLATORS: joystick settings tab name
+ setName(_("Joystick"));
+
+ Joystick::getNames(mNamesModel->getNames());
+
+ mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
+ mJoystickEnabled->setActionEventId("joystick");
+ mJoystickEnabled->addActionListener(this);
+ mCalibrateButton->setEnabled(mOriginalJoystickEnabled);
+
+ mNamesDropDown->setActionEventId("name");
+ mNamesDropDown->addActionListener(this);
+
+ if (joystick)
+ {
+ mNamesDropDown->setSelected(joystick->getNumber());
+ }
+ else
+ {
+ unsigned sel = config.getIntValue("selectedJoystick");
+ if (sel >= mNamesModel->size())
+ sel = 0;
+ mNamesDropDown->setSelected(sel);
+ }
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mJoystickEnabled);
+ place(0, 1, mNamesDropDown);
+ place(0, 2, mUseInactiveCheckBox);
+ place(0, 3, mDetectButton);
+ place(0, 4, mCalibrateLabel);
+ place(0, 5, mCalibrateButton);
+
+ setDimension(gcn::Rectangle(0, 0, 365, 75));
+}
+
+Setup_Joystick::~Setup_Joystick()
+{
+ delete mNamesModel;
+ mNamesModel = nullptr;
+}
+
+void Setup_Joystick::action(const gcn::ActionEvent &event)
+{
+ const gcn::Widget *const source = event.getSource();
+ if (source == mJoystickEnabled)
+ {
+ setTempEnabled(mJoystickEnabled->isSelected());
+ }
+ else if (source == mNamesDropDown)
+ {
+ if (joystick)
+ joystick->setNumber(mNamesDropDown->getSelected());
+ }
+ else if (source == mDetectButton)
+ {
+ if (joystick)
+ {
+ joystick->reload();
+ Joystick::getNames(mNamesModel->getNames());
+ mNamesDropDown->setSelected(joystick->getNumber());
+ }
+ }
+ else
+ {
+ if (!joystick)
+ return;
+
+ if (joystick->isCalibrating())
+ {
+ // TRANSLATORS: joystick settings tab button
+ mCalibrateButton->setCaption(_("Calibrate"));
+ mCalibrateLabel->setCaption
+ // TRANSLATORS: joystick settings tab label
+ (_("Press the button to start calibration"));
+ joystick->finishCalibration();
+ }
+ else
+ {
+ // TRANSLATORS: joystick settings tab button
+ mCalibrateButton->setCaption(_("Stop"));
+ mCalibrateLabel->setCaption(
+ // TRANSLATORS: joystick settings tab label
+ _("Rotate the stick and don't press buttons"));
+ joystick->startCalibration();
+ }
+ }
+}
+
+void Setup_Joystick::setTempEnabled(const bool sel)
+{
+ Joystick::setEnabled(sel);
+ mCalibrateButton->setEnabled(sel);
+ if (joystick)
+ {
+ if (sel)
+ joystick->open();
+ else
+ joystick->close();
+ }
+}
+
+void Setup_Joystick::cancel()
+{
+ if (joystick)
+ joystick->setEnabled(mOriginalJoystickEnabled);
+
+ if (mOriginalJoystickEnabled != mJoystickEnabled->isSelected())
+ setTempEnabled(mOriginalJoystickEnabled);
+
+ mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
+}
+
+void Setup_Joystick::apply()
+{
+ if (!joystick)
+ return;
+
+ config.setValue("joystickEnabled",
+ joystick ? joystick->isEnabled() : false);
+
+ config.setValue("useInactiveJoystick", mUseInactiveCheckBox->isSelected());
+ if (joystick)
+ joystick->setUseInactive(mUseInactiveCheckBox->isSelected());
+}
diff --git a/src/gui/widgets/tabs/setup_joystick.h b/src/gui/widgets/tabs/setup_joystick.h
new file mode 100644
index 000000000..3110da9b6
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_joystick.h
@@ -0,0 +1,62 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_JOYSTICK_H
+#define GUI_SETUP_JOYSTICK_H
+
+#include "gui/widgets/tabs/setuptab.h"
+
+class Button;
+class CheckBox;
+class DropDown;
+class Label;
+class NamesModel;
+
+class Setup_Joystick final : public SetupTab
+{
+ public:
+ explicit Setup_Joystick(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Joystick)
+
+ ~Setup_Joystick();
+
+ void apply() override;
+
+ void cancel() override;
+
+ void action(const gcn::ActionEvent &event) override;
+
+ void setTempEnabled(const bool sel);
+
+ private:
+ Label *mCalibrateLabel;
+ Button *mCalibrateButton;
+ Button *mDetectButton;
+ bool mOriginalJoystickEnabled;
+ CheckBox *mJoystickEnabled;
+ NamesModel *mNamesModel;
+ DropDown *mNamesDropDown;
+ CheckBox *mUseInactiveCheckBox;
+};
+
+#endif // GUI_SETUP_JOYSTICK_H
diff --git a/src/gui/widgets/tabs/setup_other.cpp b/src/gui/widgets/tabs/setup_other.cpp
new file mode 100644
index 000000000..ec4e2fe06
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_other.cpp
@@ -0,0 +1,404 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_other.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
+#include "gui/widgets/setupitem.h"
+#include "gui/widgets/scrollarea.h"
+
+#include "configuration.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+static const int shortcutsListSize = 3;
+
+static const char *const shortcutsList[] =
+{
+ // TRANSLATORS: show buttons at top right corner type
+ N_("Always show"),
+ // TRANSLATORS: show buttons at top right corner type
+ N_("Auto hide in small resolution"),
+ // TRANSLATORS: show buttons at top right corner type
+ N_("Always auto hide")
+};
+
+static const int proxyTypeListSize = 8;
+
+static const char *const proxyTypeList[] =
+{
+ // TRANSLATORS: Proxy type selection
+ N_("System proxy"),
+ // TRANSLATORS: Proxy type selection
+ N_("Direct connection"),
+ "HTTP",
+ "HTTP 1.0",
+ "SOCKS4",
+ "SOCKS4A",
+ "SOCKS5",
+ // TRANSLATORS: Proxy type selection
+ N_("SOCKS5 hostname")
+};
+
+static const int densityListSize = 7;
+
+static const char *const densityList[] =
+{
+ // TRANSLATORS: screen density type
+ N_("default"),
+ // TRANSLATORS: screen density type
+ N_("low"),
+ // TRANSLATORS: screen density type
+ N_("medium"),
+ // TRANSLATORS: screen density type
+ N_("tv"),
+ // TRANSLATORS: screen density type
+ N_("high"),
+ // TRANSLATORS: screen density type
+ N_("xhigh"),
+ // TRANSLATORS: screen density type
+ N_("xxhigh")
+};
+
+Setup_Other::Setup_Other(const Widget2 *const widget) :
+ SetupTabScroll(widget),
+ mProxyTypeList(new NamesModel),
+ mShortcutsList(new NamesModel),
+ mDensityList(new NamesModel)
+{
+ // TRANSLATORS: misc tab in settings
+ setName(_("Misc"));
+
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Monsters"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show damage inflicted to monsters"), "",
+ "showMonstersTakedDamage", this, "showMonstersTakedDamageEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Auto target only reachable monsters"), "",
+ "targetOnlyReachable", this, "targetOnlyReachableEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Highlight monster attack range"), "",
+ "highlightMonsterAttackRange", this,
+ "highlightMonsterAttackRangeEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show monster hp bar"), "",
+ "showMobHP", this, "showMobHPEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Cycle monster targets"), "",
+ "cycleMonsters", this, "cycleMonstersEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Map"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show warps particles"), "",
+ "warpParticle", this, "warpParticleEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Highlight map portals"), "",
+ "highlightMapPortals", this, "highlightMapPortalsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Highlight floor items"), "",
+ "floorItemsHighlight", this, "floorItemsHighlightEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Highlight player attack range"), "",
+ "highlightAttackRange", this, "highlightAttackRangeEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show extended minimaps"), "",
+ "showExtMinimaps", this, "showExtMinimapsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Draw path"), "", "drawPath",
+ this, "drawPathEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Draw hotkeys on map"), "", "drawHotKeys",
+ this, "drawHotKeysEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable lazy scrolling"), "",
+ "enableLazyScrolling", this, "enableLazyScrollingEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Scroll laziness"), "", "ScrollLaziness",
+ this, "ScrollLazinessEvent", 1, 160);
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Scroll radius"), "", "ScrollRadius",
+ this, "ScrollRadiusEvent", 0, 32);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Auto resize minimaps"), "", "autoresizeminimaps",
+ this, "autoresizeminimapsEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Moving"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Auto fix position"), "",
+ "autofixPos", this, "autofixPosEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Attack while moving"), "",
+ "attackMoving", this, "attackMovingEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Attack next target"), "",
+ "attackNext", this, "attackNextEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Sync player move"), "", "syncPlayerMove",
+ this, "syncPlayerMoveEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemTextField(_("Crazy move A program"), "",
+ "crazyMoveProgram", this, "crazyMoveProgramEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Mouse relative moves "
+ "(good for touch interfaces)"), "", "mouseDirectionMove",
+ this, "mouseDirectionMoveEvent");
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Player"), "", this);
+
+ new SetupItemCheckBox(_("Show own hp bar"), "",
+ "showOwnHP", this, "showOwnHPEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable quick stats"), "",
+ "quickStats", this, "quickStatsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Cycle player targets"), "",
+ "cyclePlayers", this, "cyclePlayersEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show job exp messages"), "",
+ "showJobExp", this, "showJobExpEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show players popups"), "",
+ "showBeingPopup", this, "showBeingPopupEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemTextField(_("Afk message"), "",
+ "afkMessage", this, "afkMessageEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show job"), "", "showJob",
+ this, "showJobEvent", false);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable attack filter"), "",
+ "enableAttackFilter", this, "enableAttackFilterEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable pickup filter"), "",
+ "enablePickupFilter", this, "enablePickupFilterEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable advert protocol"), "",
+ "enableAdvert", this, "enableAdvertEvent");
+
+ new SetupItemCheckBox(_("Enable weight notifications"), "",
+ "weightMsg", this, "weightMsgEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Shop"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Accept sell/buy requests"), "",
+ "autoShop", this, "autoShopEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable shop mode"), "",
+ "tradebot", this, "tradebotEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("NPC"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Cycle npc targets"), "",
+ "cycleNPC", this, "cycleNPCEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Log NPC dialogue"), "", "logNpcInGui",
+ this, "logNpcInGuiEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Bots support"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable auction bot support"), "",
+ "enableAuctionBot", this, "enableAuctionBotEvent", false);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable guild bot support and disable native "
+ "guild support"), "", "enableGuildBot", this,
+ "enableGuildBotEvent", false);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Keyboard"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Repeat delay"), "",
+ "repeateDelay", this, "repeateDelayEvent", 0, 10000);
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Repeat interval"), "",
+ "repeateInterval", this, "repeateIntervalEvent", 0, 10000);
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Custom repeat interval"), "",
+ "repeateInterval2", this, "repeateInterval2Event", 0, 10000);
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Windows"), "", this);
+
+ mShortcutsList->fillFromArray(&shortcutsList[0], shortcutsListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Shortcut buttons"), "", "autohideButtons", this,
+ "autohideButtonsEvent", mShortcutsList, 200);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Proxy server"), "", this);
+
+ mProxyTypeList->fillFromArray(&proxyTypeList[0], proxyTypeListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Proxy type"), "", "downloadProxyType", this,
+ "downloadProxyTypeEvent", mProxyTypeList, 200);
+
+ // TRANSLATORS: settings option
+ new SetupItemTextField(_("Proxy address:port"), "",
+ "downloadProxy", this, "downloadProxyEvent");
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Other"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable server side attack"), "",
+ "serverAttack", this, "serverAttackEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable double clicks"), "",
+ "doubleClick", this, "doubleClickEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable bot checker"), "",
+ "enableBotCheker", this, "enableBotChekerEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable buggy servers protection "
+ "(do not disable)"), "", "enableBuggyServers", this,
+ "enableBuggyServersEvent", false);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable debug log"), "",
+ "debugLog", this, "debugLogEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable OpenGL log"), "",
+ "debugOpenGL", this, "debugOpenGLEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable input log"), "",
+ "logInput", this, "logInputEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Low traffic mode"), "", "lowTraffic",
+ this, "lowTrafficEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Hide shield sprite"), "", "hideShield",
+ this, "hideShieldEvent");
+
+#ifndef ANDROID
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Use FBO for screenshots (only for opengl)"),
+ "", "usefbo", this, "usefboEvent");
+#endif
+
+ // TRANSLATORS: settings option
+ new SetupItemIntTextField(_("Network delay between sub servers"),
+ "", "networksleep", this, "networksleepEvent", 0, 10000);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show background"), "", "showBackground",
+ this, "showBackgroundEvent");
+
+ mDensityList->fillFromArray(&densityList[0], densityListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Screen density override"), "",
+ "screenDensity", this, "screenDensityEvent", mDensityList, 100);
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+Setup_Other::~Setup_Other()
+{
+ delete mProxyTypeList;
+ mProxyTypeList = nullptr;
+ delete mShortcutsList;
+ mShortcutsList = nullptr;
+ delete mDensityList;
+ mDensityList = nullptr;
+}
+
+void Setup_Other::apply()
+{
+ SetupTabScroll::apply();
+
+ logger->setDebugLog(config.getBoolValue("debugLog"));
+}
+
+void Setup_Other::externalUpdated()
+{
+ reread("showJob");
+ reread("enableGuildBot");
+ reread("enableAuctionBot");
+ reread("enableBuggyServers");
+}
diff --git a/src/gui/widgets/tabs/setup_other.h b/src/gui/widgets/tabs/setup_other.h
new file mode 100644
index 000000000..10e83517b
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_other.h
@@ -0,0 +1,49 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_OTHER_H
+#define GUI_SETUP_OTHER_H
+
+#include "gui/widgets/tabs/setuptabscroll.h"
+
+class NamesModel;
+
+class Setup_Other final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Other(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Other)
+
+ ~Setup_Other();
+
+ void apply() override;
+
+ void externalUpdated() override;
+
+ protected:
+ NamesModel *mProxyTypeList;
+ NamesModel *mShortcutsList;
+ NamesModel *mDensityList;
+};
+
+#endif // GUI_SETUP_OTHER_H
diff --git a/src/gui/widgets/tabs/setup_perfomance.cpp b/src/gui/widgets/tabs/setup_perfomance.cpp
new file mode 100644
index 000000000..25d91841e
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_perfomance.cpp
@@ -0,0 +1,163 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_perfomance.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/setupitem.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+static const int texturesListSize = 4;
+
+static const char *const texturesList[] =
+{
+ // TRANSLATORS: texture compression type
+ N_("No"),
+ "s3tc",
+ "fxt1",
+ "ARB"
+};
+
+Setup_Perfomance::Setup_Perfomance(const Widget2 *const widget) :
+ SetupTabScroll(widget),
+ mTexturesList(new NamesModel)
+{
+ // TRANSLATORS: settings tab name
+ setName(_("Performance"));
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Better performance (enable for better performance)"),
+ "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Auto adjust performance"), "",
+ "adjustPerfomance", this, "adjustPerfomanceEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Hw acceleration"), "",
+ "hwaccel", this, "hwaccelEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable opacity cache (Software, can "
+ "use much memory)"), "", "alphaCache", this, "alphaCacheEvent");
+
+#ifndef USE_SDL2
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable map reduce (Software)"), "",
+ "enableMapReduce", this, "enableMapReduceEvent");
+#endif
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable compound sprite delay (Software)"), "",
+ "enableCompoundSpriteDelay", this, "enableCompoundSpriteDelayEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable delayed images load (OpenGL)"), "",
+ "enableDelayedAnimations", this, "enableDelayedAnimationsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable texture sampler (OpenGL)"), "",
+ "useTextureSampler", this, "useTextureSamplerEvent");
+
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Better quality (disable for better performance)"),
+ "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable alpha channel fix (Software, can "
+ "be very slow)"), "Can slow down drawing", "enableAlphaFix",
+ this, "enableAlphaFixEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show beings transparency"), "",
+ "beingopacity", this, "beingopacityEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable reorder sprites."), "",
+ "enableReorderSprites", this, "enableReorderSpritesEvent");
+
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Small memory (enable for lower memory usage)"),
+ "", this);
+
+#ifndef USE_SDL2
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Disable advanced beings caching (Software)"), "",
+ "disableAdvBeingCaching", this, "disableAdvBeingCachingEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Disable beings caching (Software)"), "",
+ "disableBeingCaching", this, "disableBeingCachingEvent");
+#endif
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Different options (enable or disable can "
+ "improve performance)"), "", this);
+
+
+ mTexturesList->fillFromArray(&texturesList[0], texturesListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Enable texture compression (OpenGL)"), "",
+ "compresstextures", this, "compresstexturesEvent", mTexturesList, 100);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable rectangular texture extension (OpenGL)"),
+ "", "rectangulartextures", this, "rectangulartexturesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Use new texture internal format (OpenGL)"),
+ "", "newtextures", this, "newtexturesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable texture atlases (OpenGL)"), "",
+ "useAtlases", this, "useAtlasesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Cache all sprites per map (can use "
+ "additinal memory)"), "", "uselonglivesprites", this,
+ "uselonglivespritesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Cache all sounds (can use additinal memory)"),
+ "", "uselonglivesounds", this,
+ "uselonglivesoundsEvent");
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+Setup_Perfomance::~Setup_Perfomance()
+{
+ delete mTexturesList;
+ mTexturesList = nullptr;
+}
diff --git a/src/gui/widgets/tabs/setup_perfomance.h b/src/gui/widgets/tabs/setup_perfomance.h
new file mode 100644
index 000000000..1695dec1f
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_perfomance.h
@@ -0,0 +1,43 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_PERFOMANCE_H
+#define GUI_SETUP_PERFOMANCE_H
+
+#include "gui/widgets/tabs/setuptabscroll.h"
+
+class NamesModel;
+
+class Setup_Perfomance final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Perfomance(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Perfomance)
+
+ ~Setup_Perfomance();
+
+ private:
+ NamesModel *mTexturesList;
+};
+
+#endif // GUI_SETUP_PERFOMANCE_H
diff --git a/src/gui/widgets/tabs/setup_players.cpp b/src/gui/widgets/tabs/setup_players.cpp
new file mode 100644
index 000000000..68d1b2eb8
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_players.cpp
@@ -0,0 +1,104 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_players.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/setupitem.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+Setup_Players::Setup_Players(const Widget2 *const widget) :
+ SetupTabScroll(widget)
+{
+ // TRANSLATORS: settings tab name
+ setName(_("Players"));
+
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show gender"), "",
+ "showgender", this, "showgenderEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show level"), "",
+ "showlevel", this, "showlevelEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show own name"), "",
+ "showownname", this, "showownnameEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable extended mouse targeting"), "",
+ "extMouseTargeting", this, "extMouseTargetingEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Target dead players"), "",
+ "targetDeadPlayers", this, "targetDeadPlayersEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Visible names"), "",
+ "visiblenames", this, "visiblenamesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Auto move names"), "",
+ "moveNames", this, "moveNamesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Secure trades"), "",
+ "securetrades", this, "securetradesEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemTextField(_("Unsecure chars in names"), "",
+ "unsecureChars", this, "unsecureCharsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show statuses"), "",
+ "showPlayersStatus", this, "showPlayersStatusEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show ip addresses on screenshots"), "",
+ "showip", this, "showipEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Allow self heal with mouse click"), "",
+ "selfMouseHeal", this, "selfMouseHealEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Group friends in who is online window"), "",
+ "groupFriends", this, "groupFriendsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Hide erased players nicks"), "",
+ "hideErased", this, "hideErasedEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Use special diagonal speed in players moving"),
+ "", "useDiagonalSpeed", this, "useDiagonalSpeedEvent");
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
diff --git a/src/gui/widgets/tabs/setup_players.h b/src/gui/widgets/tabs/setup_players.h
new file mode 100644
index 000000000..af0709c08
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_players.h
@@ -0,0 +1,36 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_PLAYERS_H
+#define GUI_SETUP_PLAYERS_H
+
+#include "gui/widgets/tabs/setuptabscroll.h"
+
+class Setup_Players final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Players(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Players)
+};
+
+#endif // GUI_SETUP_PLAYERS_H
diff --git a/src/gui/widgets/tabs/setup_relations.cpp b/src/gui/widgets/tabs/setup_relations.cpp
new file mode 100644
index 000000000..4e1bdb376
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_relations.cpp
@@ -0,0 +1,445 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_relations.h"
+
+#include "actorspritemanager.h"
+
+#include "being/localplayer.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/checkbox.h"
+#include "gui/widgets/dropdown.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/guitable.h"
+
+#include "utils/dtor.h"
+#include "utils/gettext.h"
+
+static const int COLUMNS_NR = 2; // name plus listbox
+static const int NAME_COLUMN = 0;
+static const unsigned int RELATION_CHOICE_COLUMN = 1;
+
+static const unsigned int ROW_HEIGHT = 12;
+// The following column widths really shouldn't be hardcoded
+// but should scale with the size of the widget... except
+// that, right now, the widget doesn't exactly scale either.
+static const unsigned int NAME_COLUMN_WIDTH = 230;
+static const unsigned int RELATION_CHOICE_COLUMN_WIDTH = 80;
+
+#define WIDGET_AT(row, column) (((row) * COLUMNS_NR) + column)
+
+#include "debug.h"
+
+static const char *const table_titles[COLUMNS_NR] =
+{
+ // TRANSLATORS: relations table header
+ N_("Name"),
+ // TRANSLATORS: relations table header
+ N_("Relation")
+};
+
+static const char *const RELATION_NAMES[PlayerRelation::RELATIONS_NR] =
+{
+ // TRANSLATORS: relation type
+ N_("Neutral"),
+ // TRANSLATORS: relation type
+ N_("Friend"),
+ // TRANSLATORS: relation type
+ N_("Disregarded"),
+ // TRANSLATORS: relation type
+ N_("Ignored"),
+ // TRANSLATORS: relation type
+ N_("Erased"),
+ // TRANSLATORS: relation type
+ N_("Blacklisted"),
+ // TRANSLATORS: relation type
+ N_("Enemy")
+};
+
+class PlayerRelationListModel final : public gcn::ListModel
+{
+public:
+ ~PlayerRelationListModel()
+ { }
+
+ int getNumberOfElements() override
+ {
+ return PlayerRelation::RELATIONS_NR;
+ }
+
+ std::string getElementAt(int i) override
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "";
+ return gettext(RELATION_NAMES[i]);
+ }
+};
+
+class PlayerTableModel final : public Widget2, public TableModel
+{
+public:
+ explicit PlayerTableModel(const Widget2 *const widget) :
+ Widget2(widget),
+ TableModel(),
+ mPlayers(nullptr),
+ mWidgets(),
+ mListModel(new PlayerRelationListModel)
+ {
+ playerRelationsUpdated();
+ }
+
+ A_DELETE_COPY(PlayerTableModel)
+
+ ~PlayerTableModel()
+ {
+ freeWidgets();
+ delete mListModel;
+ mListModel = nullptr;
+ delete mPlayers;
+ mPlayers = nullptr;
+ }
+
+ int getRows() const override
+ {
+ if (mPlayers)
+ return static_cast<int>(mPlayers->size());
+ else
+ return 0;
+ }
+
+ int getColumns() const override
+ {
+ return COLUMNS_NR;
+ }
+
+ int getRowHeight() const override
+ {
+ return ROW_HEIGHT;
+ }
+
+ int getColumnWidth(const int index) const override
+ {
+ if (index == NAME_COLUMN)
+ return NAME_COLUMN_WIDTH;
+ else
+ return RELATION_CHOICE_COLUMN_WIDTH;
+ }
+
+ void playerRelationsUpdated()
+ {
+ signalBeforeUpdate();
+
+ freeWidgets();
+ StringVect *const player_names = player_relations.getPlayers();
+
+ if (!player_names)
+ return;
+
+ delete mPlayers;
+ mPlayers = player_names;
+
+ // set up widgets
+ for (unsigned int r = 0, sz = static_cast<unsigned int>(
+ player_names->size()); r < sz; ++r)
+ {
+ const std::string name = (*player_names)[r];
+ gcn::Widget *const widget = new Label(this, name);
+ mWidgets.push_back(widget);
+
+ DropDown *const choicebox = new DropDown(this, mListModel);
+ choicebox->setSelected(player_relations.getRelation(name));
+ mWidgets.push_back(choicebox);
+ }
+
+ signalAfterUpdate();
+ }
+
+ void updateModelInRow(const int row) const
+ {
+ const DropDown *const choicebox = static_cast<DropDown *>(
+ getElementAt(row, RELATION_CHOICE_COLUMN));
+ player_relations.setRelation(getPlayerAt(row),
+ static_cast<PlayerRelation::Relation>(
+ choicebox->getSelected()));
+ }
+
+
+ gcn::Widget *getElementAt(int row, int column) const override
+ {
+ return mWidgets[WIDGET_AT(row, column)];
+ }
+
+ void freeWidgets()
+ {
+ delete mPlayers;
+ mPlayers = nullptr;
+
+ delete_all(mWidgets);
+ mWidgets.clear();
+ }
+
+ std::string getPlayerAt(const int index) const
+ {
+ if (index < 0 || index >= static_cast<signed>(mPlayers->size()))
+ return "";
+ return (*mPlayers)[index];
+ }
+
+protected:
+ StringVect *mPlayers;
+ std::vector<gcn::Widget *> mWidgets;
+ PlayerRelationListModel *mListModel;
+};
+
+/**
+ * Class for choosing one of the various `what to do when ignoring a player' options
+ */
+class IgnoreChoicesListModel final : public gcn::ListModel
+{
+public:
+ ~IgnoreChoicesListModel()
+ { }
+
+ int getNumberOfElements() override
+ {
+ return static_cast<int>(player_relations.getPlayerIgnoreStrategies()
+ ->size());
+ }
+
+ std::string getElementAt(int i) override
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "???";
+
+ return (*player_relations.getPlayerIgnoreStrategies())
+ [i]->mDescription;
+ }
+};
+
+static const std::string ACTION_DELETE("delete");
+static const std::string ACTION_TABLE("table");
+static const std::string ACTION_STRATEGY("strategy");
+
+Setup_Relations::Setup_Relations(const Widget2 *const widget) :
+ SetupTab(widget),
+ PlayerRelationsListener(),
+ mPlayerTableTitleModel(new StaticTableModel(1, COLUMNS_NR)),
+ mPlayerTableModel(new PlayerTableModel(this)),
+ mPlayerTable(new GuiTable(mPlayerTableModel)),
+ mPlayerTitleTable(new GuiTable(this, mPlayerTableTitleModel)),
+ mPlayerScrollArea(new ScrollArea(mPlayerTable)),
+ // TRANSLATORS: relation dialog button
+ mDefaultTrading(new CheckBox(this, _("Allow trading"),
+ player_relations.getDefault() & PlayerRelation::TRADE)),
+ // TRANSLATORS: relation dialog button
+ mDefaultWhisper(new CheckBox(this, _("Allow whispers"),
+ player_relations.getDefault() & PlayerRelation::WHISPER)),
+ mDeleteButton(new Button(this, _("Delete"), ACTION_DELETE, this)),
+ mIgnoreActionChoicesModel(new IgnoreChoicesListModel),
+ mIgnoreActionChoicesBox(new DropDown(widget, mIgnoreActionChoicesModel))
+{
+ // TRANSLATORS: relation dialog name
+ setName(_("Relations"));
+
+ mPlayerTable->setOpaque(false);
+
+ mPlayerTableTitleModel->fixColumnWidth(NAME_COLUMN, NAME_COLUMN_WIDTH);
+ mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN,
+ RELATION_CHOICE_COLUMN_WIDTH);
+ mPlayerTitleTable->setBackgroundColor(gcn::Color(0xbf, 0xbf, 0xbf));
+
+
+ for (int i = 0; i < COLUMNS_NR; i++)
+ {
+ mPlayerTableTitleModel->set(0, i, new Label(
+ this, gettext(table_titles[i])));
+ }
+
+ mPlayerTitleTable->setLinewiseSelection(true);
+
+ mPlayerScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mPlayerTable->setActionEventId(ACTION_TABLE);
+ mPlayerTable->setLinewiseSelection(true);
+ mPlayerTable->addActionListener(this);
+
+ // TRANSLATORS: relation dialog label
+ Label *const ignore_action_label = new Label(this, _("When ignoring:"));
+
+ mIgnoreActionChoicesBox->setActionEventId(ACTION_STRATEGY);
+ mIgnoreActionChoicesBox->addActionListener(this);
+
+ int ignore_strategy_index = 0; // safe default
+
+ if (player_relations.getPlayerIgnoreStrategy())
+ {
+ ignore_strategy_index = player_relations.getPlayerIgnoreStrategyIndex(
+ player_relations.getPlayerIgnoreStrategy()->mShortName);
+ if (ignore_strategy_index < 0)
+ ignore_strategy_index = 0;
+ }
+ mIgnoreActionChoicesBox->setSelected(ignore_strategy_index);
+ mIgnoreActionChoicesBox->adjustHeight();
+
+ reset();
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mPlayerTitleTable, 6);
+ place(0, 1, mPlayerScrollArea, 6, 4).setPadding(2);
+ place(0, 5, mDeleteButton);
+ place(3, 5, ignore_action_label, 1);
+ place(4, 5, mIgnoreActionChoicesBox, 2).setPadding(2);
+ place(3, 6, mDefaultTrading, 3);
+ place(3, 7, mDefaultWhisper, 3);
+
+ player_relations.addListener(this);
+
+ setDimension(gcn::Rectangle(0, 0, 500, 350));
+}
+
+Setup_Relations::~Setup_Relations()
+{
+ player_relations.removeListener(this);
+ delete mIgnoreActionChoicesModel;
+ mIgnoreActionChoicesModel = nullptr;
+}
+
+
+void Setup_Relations::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.
+ int selection = 0;
+ for (size_t i = 0, sz = player_relations.getPlayerIgnoreStrategies()
+ ->size(); i < sz; ++ i)
+ {
+ if ((*player_relations.getPlayerIgnoreStrategies())[i] ==
+ player_relations.getPlayerIgnoreStrategy())
+ {
+ selection = static_cast<int>(i);
+ break;
+ }
+ }
+ mIgnoreActionChoicesBox->setSelected(selection);
+}
+
+void Setup_Relations::apply()
+{
+ player_relations.store();
+
+ const unsigned int old_default_relations = player_relations.getDefault() &
+ ~(PlayerRelation::TRADE | PlayerRelation::WHISPER);
+ player_relations.setDefault(old_default_relations
+ | (mDefaultTrading->isSelected() ? PlayerRelation::TRADE : 0)
+ | (mDefaultWhisper->isSelected() ? PlayerRelation::WHISPER : 0));
+
+ if (actorSpriteManager)
+ actorSpriteManager->updatePlayerNames();
+
+ if (player_node)
+ player_node->setCheckNameSetting(true);
+}
+
+void Setup_Relations::cancel()
+{
+}
+
+void Setup_Relations::action(const gcn::ActionEvent &event)
+{
+ const std::string &eventId = event.getId();
+ if (eventId == 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.)
+ player_relations.removeListener(this);
+
+ const int row = mPlayerTable->getSelectedRow();
+ if (row >= 0)
+ mPlayerTableModel->updateModelInRow(row);
+
+ player_relations.addListener(this);
+ }
+ else if (eventId == ACTION_DELETE)
+ {
+ const int player_index = mPlayerTable->getSelectedRow();
+
+ if (player_index < 0)
+ return;
+
+ player_relations.removePlayer(mPlayerTableModel->getPlayerAt(
+ player_index));
+ }
+ else if (eventId == ACTION_STRATEGY)
+ {
+ PlayerIgnoreStrategy *const s =
+ (*player_relations.getPlayerIgnoreStrategies())[
+ mIgnoreActionChoicesBox->getSelected()];
+
+ player_relations.setPlayerIgnoreStrategy(s);
+ }
+}
+
+void Setup_Relations::updatedPlayer(const std::string &name A_UNUSED)
+{
+ mPlayerTableModel->playerRelationsUpdated();
+ mDefaultTrading->setSelected(
+ player_relations.getDefault() & PlayerRelation::TRADE);
+ mDefaultWhisper->setSelected(
+ player_relations.getDefault() & PlayerRelation::WHISPER);
+ if (player_node)
+ player_node->updateName();
+}
+
+void Setup_Relations::updateAll()
+{
+ PlayerTableModel *const model = new PlayerTableModel(this);
+ mPlayerTable->setModel(model);
+ delete mPlayerTableModel;
+ mPlayerTableModel = model;
+ int ignore_strategy_index = 0; // safe default
+
+ if (player_relations.getPlayerIgnoreStrategy())
+ {
+ ignore_strategy_index = player_relations.getPlayerIgnoreStrategyIndex(
+ player_relations.getPlayerIgnoreStrategy()->mShortName);
+ if (ignore_strategy_index < 0)
+ ignore_strategy_index = 0;
+ }
+ mIgnoreActionChoicesBox->setSelected(ignore_strategy_index);
+ mIgnoreActionChoicesBox->adjustHeight();
+ reset();
+}
+void Setup_Relations::externalUpdated()
+{
+ mDefaultTrading->setSelected(
+ player_relations.getDefault() & PlayerRelation::TRADE);
+ mDefaultWhisper->setSelected(
+ player_relations.getDefault() & PlayerRelation::WHISPER);
+}
diff --git a/src/gui/widgets/tabs/setup_relations.h b/src/gui/widgets/tabs/setup_relations.h
new file mode 100644
index 000000000..789dd5f3e
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_relations.h
@@ -0,0 +1,83 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_RELATIONS_H
+#define GUI_SETUP_RELATIONS_H
+
+#include "being/playerrelations.h"
+
+#include "gui/widgets/tabs/setuptab.h"
+
+class Button;
+class CheckBox;
+class DropDown;
+class GuiTable;
+class PlayerTableModel;
+class ScrollArea;
+class StaticTableModel;
+
+namespace gcn
+{
+ class ListModel;
+}
+
+class Setup_Relations final : public SetupTab,
+ public PlayerRelationsListener
+{
+public:
+ explicit Setup_Relations(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Relations)
+
+ ~Setup_Relations();
+
+ void apply() override;
+
+ void cancel() override;
+
+ void reset();
+
+ void action(const gcn::ActionEvent &event) override;
+
+ void updatedPlayer(const std::string &name);
+
+ void updateAll();
+
+ void externalUpdated() override;
+
+private:
+ StaticTableModel *mPlayerTableTitleModel;
+ PlayerTableModel *mPlayerTableModel;
+ GuiTable *mPlayerTable;
+ GuiTable *mPlayerTitleTable;
+ ScrollArea *mPlayerScrollArea;
+
+ CheckBox *mDefaultTrading;
+ CheckBox *mDefaultWhisper;
+
+ Button *mDeleteButton;
+
+ gcn::ListModel *mIgnoreActionChoicesModel;
+ DropDown *mIgnoreActionChoicesBox;
+};
+
+#endif // GUI_SETUP_RELATIONS_H
diff --git a/src/gui/widgets/tabs/setup_theme.cpp b/src/gui/widgets/tabs/setup_theme.cpp
new file mode 100644
index 000000000..dde3ad04e
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_theme.cpp
@@ -0,0 +1,541 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_theme.h"
+
+#include "gui/gui.h"
+
+#include "gui/windows/okdialog.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/dropdown.h"
+#include "gui/widgets/extendedlistmodel.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
+
+#include "configuration.h"
+
+#include "utils/gettext.h"
+
+#include "resources/resourcemanager.h"
+
+#include "debug.h"
+
+const char* ACTION_THEME = "theme";
+const char* ACTION_FONT = "font";
+const char* ACTION_LANG = "lang";
+const char* ACTION_BOLD_FONT = "bold font";
+const char* ACTION_PARTICLE_FONT = "particle font";
+const char* ACTION_HELP_FONT = "help font";
+const char* ACTION_SECURE_FONT = "secure font";
+const char* ACTION_JAPAN_FONT = "japan font";
+const char* ACTION_INFO = "info";
+
+class ThemesModel final : public NamesModel
+{
+public:
+ ThemesModel() :
+ NamesModel()
+ {
+ mNames.push_back(gettext("(default)"));
+ Theme::fillSkinsList(mNames);
+ }
+
+ ~ThemesModel()
+ { }
+};
+
+class FontsModel final : public NamesModel
+{
+public:
+ FontsModel() :
+ NamesModel()
+ { Theme::fillFontsList(mNames); }
+
+ ~FontsModel()
+ { }
+};
+
+const int maxFontSizes = 16;
+
+const char *SIZE_NAME[maxFontSizes] =
+{
+ // TRANSLATORS: font size
+ N_("Very small (8)"),
+ // TRANSLATORS: font size
+ N_("Very small (9)"),
+ // TRANSLATORS: font size
+ N_("Tiny (10)"),
+ // TRANSLATORS: font size
+ N_("Small (11)"),
+ // TRANSLATORS: font size
+ N_("Medium (12)"),
+ // TRANSLATORS: font size
+ N_("Normal (13)"),
+ // TRANSLATORS: font size
+ N_("Large (14)"),
+ // TRANSLATORS: font size
+ N_("Large (15)"),
+ // TRANSLATORS: font size
+ N_("Large (16)"),
+ // TRANSLATORS: font size
+ N_("Big (17)"),
+ // TRANSLATORS: font size
+ N_("Big (18)"),
+ // TRANSLATORS: font size
+ N_("Big (19)"),
+ // TRANSLATORS: font size
+ N_("Very big (20)"),
+ // TRANSLATORS: font size
+ N_("Very big (21)"),
+ // TRANSLATORS: font size
+ N_("Very big (22)"),
+ // TRANSLATORS: font size
+ N_("Huge (23)"),
+};
+
+class FontSizeChoiceListModel final : public gcn::ListModel
+{
+public:
+ ~FontSizeChoiceListModel()
+ { }
+
+ int getNumberOfElements() override A_WARN_UNUSED
+ { return maxFontSizes; }
+
+ std::string getElementAt(int i) override A_WARN_UNUSED
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "???";
+
+ return gettext(SIZE_NAME[i]);
+ }
+};
+
+struct Language final
+{
+ std::string name;
+ std::string value;
+ std::string icon;
+};
+
+const int langs_count = 17;
+
+const Language LANG_NAME[langs_count] =
+{
+ // TRANSLATORS: language
+ {N_("(default)"), "", ""},
+ // TRANSLATORS: language
+ {N_("Chinese (China)"), "zh_CN", "cn.png"},
+ // TRANSLATORS: language
+ {N_("Czech"), "cs_CZ", "cz.png"},
+ // TRANSLATORS: language
+ {N_("English"), "C", "en.png"},
+ // TRANSLATORS: language
+ {N_("Finnish"), "fi_FI", "fi.png"},
+ // TRANSLATORS: language
+ {N_("French"), "fr_FR", "fr.png"},
+ // TRANSLATORS: language
+ {N_("German"), "de_DE", "de.png"},
+ // TRANSLATORS: language
+ {N_("Indonesian"), "id_ID", "id.png"},
+ // TRANSLATORS: language
+ {N_("Italian"), "it_IT", "it.png"},
+ // TRANSLATORS: language
+ {N_("Polish"), "pl_PL", "pl.png"},
+ // TRANSLATORS: language
+ {N_("Japanese"), "ja_JP", "jp.png"},
+ // TRANSLATORS: language
+ {N_("Dutch (Belgium/Flemish)"), "nl_BE", "nl_BE.png"},
+ // TRANSLATORS: language
+ {N_("Portuguese"), "pt_PT", "pt.png"},
+ // TRANSLATORS: language
+ {N_("Portuguese (Brazilian)"), "pt_BR", "pt_BR.png"},
+ // TRANSLATORS: language
+ {N_("Russian"), "ru_RU", "ru.png"},
+ // TRANSLATORS: language
+ {N_("Spanish (Castilian)"), "es_ES", "es.png"},
+ // TRANSLATORS: language
+ {N_("Turkish"), "tr_TR", "tr.png"}
+};
+
+class LangListModel final : public ExtendedListModel
+{
+public:
+ LangListModel()
+ {
+ ResourceManager *const resman = ResourceManager::getInstance();
+ for (int f = 0; f < langs_count; f ++)
+ {
+ mIcons[f] = resman->getImage("graphics/flags/"
+ + LANG_NAME[f].icon);
+ }
+ }
+
+ A_DELETE_COPY(LangListModel)
+
+ ~LangListModel()
+ {
+ for (int f = 0; f < langs_count; f ++)
+ {
+ Image *const img = mIcons[f];
+ if (img)
+ img->decRef();
+ }
+ }
+
+ int getNumberOfElements() override A_WARN_UNUSED
+ { return langs_count; }
+
+ std::string getElementAt(int i) override A_WARN_UNUSED
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "???";
+
+ return gettext(LANG_NAME[i].name.c_str());
+ }
+
+ const Image *getImageAt(int i) override A_WARN_UNUSED
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return nullptr;
+ return mIcons[i];
+ }
+
+ Image *mIcons[langs_count];
+};
+
+Setup_Theme::Setup_Theme(const Widget2 *const widget) :
+ SetupTab(widget),
+ // TRANSLATORS: theme settings label
+ mThemeLabel(new Label(this, _("Gui theme"))),
+ mThemesModel(new ThemesModel),
+ mThemeDropDown(new DropDown(this, mThemesModel)),
+ mTheme(config.getStringValue("theme")),
+ mInfo(Theme::loadInfo(mTheme)),
+ mFontsModel(new FontsModel),
+ // TRANSLATORS: theme settings label
+ mFontLabel(new Label(this, _("Main Font"))),
+ mFontDropDown(new DropDown(this, mFontsModel)),
+ mFont(config.getStringValue("font")),
+ mLangListModel(new LangListModel),
+ // TRANSLATORS: theme settings label
+ mLangLabel(new Label(this, _("Language"))),
+ mLangDropDown(new DropDown(this, mLangListModel, true)),
+ mLang(config.getStringValue("lang")),
+ // TRANSLATORS: theme settings label
+ mBoldFontLabel(new Label(this, _("Bold font"))),
+ mBoldFontDropDown(new DropDown(this, mFontsModel)),
+ mBoldFont(config.getStringValue("boldFont")),
+ // TRANSLATORS: theme settings label
+ mParticleFontLabel(new Label(this, _("Particle font"))),
+ mParticleFontDropDown(new DropDown(this, mFontsModel)),
+ mParticleFont(config.getStringValue("particleFont")),
+ // TRANSLATORS: theme settings label
+ mHelpFontLabel(new Label(this, _("Help font"))),
+ mHelpFontDropDown(new DropDown(this, mFontsModel)),
+ mHelpFont(config.getStringValue("helpFont")),
+ // TRANSLATORS: theme settings label
+ mSecureFontLabel(new Label(this, _("Secure font"))),
+ mSecureFontDropDown(new DropDown(this, mFontsModel)),
+ mSecureFont(config.getStringValue("secureFont")),
+ // TRANSLATORS: theme settings label
+ mJapanFontLabel(new Label(this, _("Japanese font"))),
+ mJapanFontDropDown(new DropDown(this, mFontsModel)),
+ mJapanFont(config.getStringValue("japanFont")),
+ mFontSizeListModel(new FontSizeChoiceListModel),
+ // TRANSLATORS: theme settings label
+ mFontSizeLabel(new Label(this, _("Font size"))),
+ mFontSize(config.getIntValue("fontSize")),
+ mFontSizeDropDown(new DropDown(this, mFontSizeListModel)),
+ mNpcFontSizeListModel(new FontSizeChoiceListModel),
+ // TRANSLATORS: theme settings label
+ mNpcFontSizeLabel(new Label(this, _("Npc font size"))),
+ mNpcFontSize(config.getIntValue("npcfontSize")),
+ mNpcFontSizeDropDown(new DropDown(this, mNpcFontSizeListModel)),
+ // TRANSLATORS: button name with information about selected theme
+ mInfoButton(new Button(this, _("i"), ACTION_INFO, this)),
+ mThemeInfo()
+{
+ // TRANSLATORS: theme settings tab name
+ setName(_("Theme"));
+
+ mThemeDropDown->setActionEventId(ACTION_THEME);
+ mThemeDropDown->addActionListener(this);
+ mFontDropDown->setActionEventId(ACTION_FONT);
+ mFontDropDown->addActionListener(this);
+ mLangDropDown->setActionEventId(ACTION_LANG);
+ mLangDropDown->addActionListener(this);
+ mBoldFontDropDown->setActionEventId(ACTION_BOLD_FONT);
+ mBoldFontDropDown->addActionListener(this);
+ mParticleFontDropDown->setActionEventId(ACTION_PARTICLE_FONT);
+ mParticleFontDropDown->addActionListener(this);
+ mHelpFontDropDown->setActionEventId(ACTION_HELP_FONT);
+ mHelpFontDropDown->addActionListener(this);
+ mSecureFontDropDown->setActionEventId(ACTION_SECURE_FONT);
+ mSecureFontDropDown->addActionListener(this);
+ mJapanFontDropDown->setActionEventId(ACTION_JAPAN_FONT);
+ mJapanFontDropDown->addActionListener(this);
+ mFontSizeDropDown->setSelected(mFontSize - 9);
+ mFontSizeDropDown->adjustHeight();
+ mNpcFontSizeDropDown->setSelected(mNpcFontSize - 9);
+ mNpcFontSizeDropDown->adjustHeight();
+
+ const std::string skin = Theme::getThemeName();
+ if (!skin.empty())
+ mThemeDropDown->setSelectedString(skin);
+ else
+ mThemeDropDown->setSelected(0);
+
+ const std::string str = config.getStringValue("lang");
+ for (int f = 0; f < langs_count; f ++)
+ {
+ if (LANG_NAME[f].value == str)
+ {
+ mLangDropDown->setSelected(f);
+ break;
+ }
+ }
+
+ mFontDropDown->setSelectedString(getFileName(
+ config.getStringValue("font")));
+ mBoldFontDropDown->setSelectedString(getFileName(
+ config.getStringValue("boldFont")));
+ mParticleFontDropDown->setSelectedString(getFileName(
+ config.getStringValue("particleFont")));
+ mHelpFontDropDown->setSelectedString(getFileName(
+ config.getStringValue("helpFont")));
+ mSecureFontDropDown->setSelectedString(getFileName(
+ config.getStringValue("secureFont")));
+ mJapanFontDropDown->setSelectedString(getFileName(
+ config.getStringValue("japanFont")));
+
+ updateInfo();
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, mThemeLabel, 5);
+ place(0, 1, mLangLabel, 5);
+ place(0, 2, mFontSizeLabel, 5);
+ place(0, 3, mNpcFontSizeLabel, 5);
+ place(0, 4, mFontLabel, 5);
+ place(0, 5, mBoldFontLabel, 5);
+ place(0, 6, mParticleFontLabel, 5);
+ place(0, 7, mHelpFontLabel, 5);
+ place(0, 8, mSecureFontLabel, 5);
+ place(0, 9, mJapanFontLabel, 5);
+
+ place(6, 0, mThemeDropDown, 10);
+ place(6, 1, mLangDropDown, 10);
+ place(6, 2, mFontSizeDropDown, 10);
+ place(6, 3, mNpcFontSizeDropDown, 10);
+ place(6, 4, mFontDropDown, 10);
+ place(6, 5, mBoldFontDropDown, 10);
+ place(6, 6, mParticleFontDropDown, 10);
+ place(6, 7, mHelpFontDropDown, 10);
+ place(6, 8, mSecureFontDropDown, 10);
+ place(6, 9, mJapanFontDropDown, 10);
+
+ place(17, 0, mInfoButton, 1);
+
+ int size = mainGraphics->mWidth - 10;
+ const int maxWidth = mFontSize * 30 + 290;
+ if (size < 465)
+ size = 465;
+ else if (size > maxWidth)
+ size = maxWidth;
+
+ setDimension(gcn::Rectangle(0, 0, size, 500));
+}
+
+Setup_Theme::~Setup_Theme()
+{
+ delete mInfo;
+ mInfo = nullptr;
+
+ delete mThemesModel;
+ mThemesModel = nullptr;
+
+ delete mFontsModel;
+ mFontsModel = nullptr;
+
+ delete mFontSizeListModel;
+ mFontSizeListModel = nullptr;
+
+ delete mNpcFontSizeListModel;
+ mNpcFontSizeListModel = nullptr;
+
+ delete mLangListModel;
+ mLangListModel = nullptr;
+
+ delete mInfo;
+ mInfo = nullptr;
+}
+
+void Setup_Theme::updateInfo()
+{
+ delete mInfo;
+ mInfo = Theme::loadInfo(mTheme);
+ if (mInfo)
+ {
+ // TRANSLATORS: theme info dialog
+ mThemeInfo = std::string(_("Name: ")).append(mInfo->name)
+ .append("\n").append(_("Copyright:")).append("\n")
+ .append(mInfo->copyright);
+ }
+ else
+ {
+ mThemeInfo.clear();
+ }
+ replaceAll(mThemeInfo, "\\n", "\n");
+ mInfoButton->setEnabled(!mThemeInfo.empty());
+}
+
+void Setup_Theme::action(const gcn::ActionEvent &event)
+{
+ const std::string &eventId = event.getId();
+ if (eventId == ACTION_THEME)
+ {
+ if (mThemeDropDown->getSelected() == 0)
+ mTheme.clear();
+ else
+ mTheme = mThemeDropDown->getSelectedString();
+ updateInfo();
+ }
+ else if (eventId == ACTION_FONT)
+ {
+ mFont = mFontDropDown->getSelectedString();
+ }
+ else if (eventId == ACTION_LANG)
+ {
+ const int id = mLangDropDown->getSelected();
+ if (id < 0 || id >= langs_count)
+ mLang.clear();
+ else
+ mLang = LANG_NAME[id].value;
+ }
+ else if (eventId == ACTION_BOLD_FONT)
+ {
+ mBoldFont = mBoldFontDropDown->getSelectedString();
+ }
+ else if (eventId == ACTION_PARTICLE_FONT)
+ {
+ mParticleFont = mParticleFontDropDown->getSelectedString();
+ }
+ else if (eventId == ACTION_HELP_FONT)
+ {
+ mHelpFont = mHelpFontDropDown->getSelectedString();
+ }
+ else if (eventId == ACTION_SECURE_FONT)
+ {
+ mSecureFont = mSecureFontDropDown->getSelectedString();
+ }
+ else if (eventId == ACTION_JAPAN_FONT)
+ {
+ mJapanFont = mJapanFontDropDown->getSelectedString();
+ }
+ else if (eventId == ACTION_INFO)
+ {
+ // TRANSLATORS: theme info dialog header
+ new OkDialog(_("Theme info"), mThemeInfo, DIALOG_OK,
+ false, true, nullptr, 600);
+ }
+}
+
+void Setup_Theme::cancel()
+{
+ mTheme = config.getStringValue("theme");
+ mLang = config.getStringValue("lang");
+ mFont = getFileName(config.getStringValue("font"));
+ mBoldFont = getFileName(config.getStringValue("boldFont"));
+ mParticleFont = getFileName(config.getStringValue("particleFont"));
+ mHelpFont = getFileName(config.getStringValue("helpFont"));
+ mSecureFont = getFileName(config.getStringValue("secureFont"));
+ mJapanFont = getFileName(config.getStringValue("japanFont"));
+}
+
+#define updateField(name1, name2) if (!mInfo->name1.empty()) \
+ name2 = mInfo->name1;
+
+void Setup_Theme::apply()
+{
+ if (config.getStringValue("theme") != mTheme)
+ {
+ // TRANSLATORS: theme message dialog
+ new OkDialog(_("Theme Changed"), _("Restart your client for "
+ "the change to take effect."));
+ }
+
+ config.setValue("selectedSkin", "");
+ if (config.getStringValue("theme") != mTheme && mInfo)
+ {
+ updateField(font, mFont);
+ updateField(boldFont, mBoldFont);
+ updateField(particleFont, mParticleFont);
+ updateField(helpFont, mHelpFont);
+ updateField(secureFont, mSecureFont);
+ updateField(japanFont, mJapanFont);
+ if (mInfo->fontSize)
+ {
+ const int size = mInfo->fontSize - 9;
+ if (size >= 0)
+ mFontSizeDropDown->setSelected(size);
+ }
+ if (mInfo->npcfontSize)
+ {
+ const int size = mInfo->npcfontSize - 9;
+ if (size >= 0)
+ mNpcFontSizeDropDown->setSelected(size);
+ }
+ if (mInfo->guiAlpha > 0.01F)
+ config.setValue("guialpha", mInfo->guiAlpha);
+ }
+ config.setValue("theme", mTheme);
+ config.setValue("lang", mLang);
+ if (config.getValue("font", "dejavusans.ttf") != mFont
+ || config.getValue("boldFont", "dejavusans-bold.ttf") != mBoldFont
+ || config.getValue("particleFont", "dejavusans.ttf") != mParticleFont
+ || config.getValue("helpFont", "dejavusansmono.ttf") != mHelpFont
+ || config.getValue("secureFont", "dejavusansmono.ttf") != mSecureFont
+ || config.getValue("japanFont", "mplus-1p-regular.ttf") != mJapanFont
+ || config.getIntValue("fontSize")
+ != static_cast<int>(mFontSizeDropDown->getSelected()) + 9
+ || config.getIntValue("npcfontSize")
+ != static_cast<int>(mNpcFontSizeDropDown->getSelected()) + 9)
+ {
+ config.setValue("font", "fonts/" + getFileName(mFont));
+ config.setValue("boldFont", "fonts/" + getFileName(mBoldFont));
+ config.setValue("particleFont", "fonts/" + getFileName(mParticleFont));
+ config.setValue("helpFont", "fonts/" + getFileName(mHelpFont));
+ config.setValue("secureFont", "fonts/" + getFileName(mSecureFont));
+ config.setValue("japanFont", "fonts/" + getFileName(mJapanFont));
+ config.setValue("fontSize", mFontSizeDropDown->getSelected() + 9);
+ config.setValue("npcfontSize",
+ mNpcFontSizeDropDown->getSelected() + 9);
+ gui->updateFonts();
+ }
+}
+
+#undef updateField
diff --git a/src/gui/widgets/tabs/setup_theme.h b/src/gui/widgets/tabs/setup_theme.h
new file mode 100644
index 000000000..96d07aa15
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_theme.h
@@ -0,0 +1,105 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_THEME_H
+#define GUI_SETUP_THEME_H
+
+#include "gui/widgets/tabs/setuptab.h"
+
+class Button;
+class DropDown;
+class FontsModel;
+class FontSizeChoiceListModel;
+class Label;
+class LangListModel;
+class ThemesModel;
+
+class Setup_Theme final : public SetupTab
+{
+ public:
+ explicit Setup_Theme(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Theme)
+
+ ~Setup_Theme();
+
+ void apply() override;
+
+ void cancel() override;
+
+ void action(const gcn::ActionEvent &event) override;
+
+ void updateInfo();
+
+ private:
+ Label *mThemeLabel;
+ ThemesModel *mThemesModel;
+ DropDown *mThemeDropDown;
+ std::string mTheme;
+ ThemeInfo *mInfo;
+
+ FontsModel *mFontsModel;
+ Label *mFontLabel;
+ DropDown *mFontDropDown;
+ std::string mFont;
+
+ LangListModel *mLangListModel;
+
+ Label *mLangLabel;
+ DropDown *mLangDropDown;
+ std::string mLang;
+
+ Label *mBoldFontLabel;
+ DropDown *mBoldFontDropDown;
+ std::string mBoldFont;
+
+ Label *mParticleFontLabel;
+ DropDown *mParticleFontDropDown;
+ std::string mParticleFont;
+
+ Label *mHelpFontLabel;
+ DropDown *mHelpFontDropDown;
+ std::string mHelpFont;
+
+ Label *mSecureFontLabel;
+ DropDown *mSecureFontDropDown;
+ std::string mSecureFont;
+
+ Label *mJapanFontLabel;
+ DropDown *mJapanFontDropDown;
+ std::string mJapanFont;
+
+ FontSizeChoiceListModel *mFontSizeListModel;
+ Label *mFontSizeLabel;
+ int mFontSize;
+ DropDown *mFontSizeDropDown;
+
+ FontSizeChoiceListModel *mNpcFontSizeListModel;
+ Label *mNpcFontSizeLabel;
+ int mNpcFontSize;
+ DropDown *mNpcFontSizeDropDown;
+
+ Button *mInfoButton;
+ std::string mThemeInfo;
+};
+
+#endif // GUI_SETUP_THEME_H
diff --git a/src/gui/widgets/tabs/setup_touch.cpp b/src/gui/widgets/tabs/setup_touch.cpp
new file mode 100644
index 000000000..e3081427d
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_touch.cpp
@@ -0,0 +1,139 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_touch.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/scrollarea.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#include "debug.h"
+
+static const int sizeListSize = 4;
+
+static const char *const sizeList[] =
+{
+ // TRANSLATORS: onscreen button size
+ N_("Small"),
+ // TRANSLATORS: onscreen button size
+ N_("Normal"),
+ // TRANSLATORS: onscreen button size
+ N_("Medium"),
+ // TRANSLATORS: onscreen button size
+ N_("Large")
+};
+
+static const int formatListSize = 2;
+
+static const char *const formatList[] =
+{
+ "2x1",
+ "2x2",
+};
+
+Setup_Touch::Setup_Touch(const Widget2 *const widget) :
+ SetupTabScroll(widget),
+ mSizeList(new NamesModel),
+ mFormatList(new NamesModel),
+ mActionsList(new TouchActionsModel)
+{
+ // TRANSLATORS: touch settings tab
+ setName(_("Touch"));
+
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+ mSizeList->fillFromArray(&sizeList[0], sizeListSize);
+ mFormatList->fillFromArray(&formatList[0], formatListSize);
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Onscreen keyboard"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show onscreen keyboard icon"), "",
+ "showScreenKeyboard", this, "showScreenKeyboardEvent");
+
+ // TRANSLATORS: settings option
+ new SetupActionDropDown(_("Keyboard icon action"), "",
+ "screenActionKeyboard", this, "screenActionKeyboardEvent",
+ mActionsList, 250);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Onscreen joystick"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show onscreen joystick"), "",
+ "showScreenJoystick", this, "showScreenJoystickEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Joystick size"), "", "screenJoystickSize", this,
+ "screenJoystickEvent", mSizeList, 100);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Onscreen buttons"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show onscreen buttons"), "",
+ "showScreenButtons", this, "showScreenButtonsEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Buttons format"), "", "screenButtonsFormat", this,
+ "screenButtonsFormatEvent", mFormatList, 100);
+
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Buttons size"), "", "screenButtonsSize", this,
+ "screenButtonsSizeEvent", mSizeList, 100);
+
+ // TRANSLATORS: settings option
+ new SetupActionDropDown(strprintf(_("Button %u action"), 1U), "",
+ "screenActionButton0", this, "screenActionButton0Event",
+ mActionsList, 250);
+
+ // TRANSLATORS: settings option
+ new SetupActionDropDown(strprintf(_("Button %u action"), 2U), "",
+ "screenActionButton1", this, "screenActionButton1Event",
+ mActionsList, 250);
+
+ // TRANSLATORS: settings option
+ new SetupActionDropDown(strprintf(_("Button %u action"), 3U), "",
+ "screenActionButton2", this, "screenActionButton2Event",
+ mActionsList, 250);
+
+ // TRANSLATORS: settings option
+ new SetupActionDropDown(strprintf(_("Button %u action"), 4U), "",
+ "screenActionButton3", this, "screenActionButton3Event",
+ mActionsList, 250);
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+Setup_Touch::~Setup_Touch()
+{
+ delete mSizeList;
+ mSizeList = nullptr;
+ delete mFormatList;
+ mFormatList = nullptr;
+ delete mActionsList;
+ mActionsList = nullptr;
+}
diff --git a/src/gui/widgets/tabs/setup_touch.h b/src/gui/widgets/tabs/setup_touch.h
new file mode 100644
index 000000000..b908ce19d
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_touch.h
@@ -0,0 +1,41 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2012-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_TOUCH_H
+#define GUI_SETUP_TOUCH_H
+
+#include "gui/widgets/setuptouchitem.h"
+
+class Setup_Touch final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Touch(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Touch)
+
+ ~Setup_Touch();
+
+ protected:
+ NamesModel *mSizeList;
+ NamesModel *mFormatList;
+ TouchActionsModel *mActionsList;
+};
+
+#endif // GUI_SETUP_TOUCH_H
diff --git a/src/gui/widgets/tabs/setup_video.cpp b/src/gui/widgets/tabs/setup_video.cpp
new file mode 100644
index 000000000..bd53763cc
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_video.cpp
@@ -0,0 +1,576 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_video.h"
+
+#include "client.h"
+#include "configuration.h"
+
+#include "graphicsmanager.h"
+
+#include "gui/windows/okdialog.h"
+#include "gui/windows/textdialog.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/checkbox.h"
+#include "gui/widgets/label.h"
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/listbox.h"
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/slider.h"
+#include "gui/widgets/dropdown.h"
+
+#include "render/rendererslistsdl.h"
+
+#include "utils/gettext.h"
+#include "utils/sdlhelper.h"
+
+#include "test/testmain.h"
+
+#include <guichan/listmodel.hpp>
+
+#include <algorithm>
+
+#include "debug.h"
+
+extern Graphics *mainGraphics;
+
+class ModeListModel final : public gcn::ListModel
+{
+ public:
+ ModeListModel();
+
+ A_DELETE_COPY(ModeListModel)
+
+ ~ModeListModel()
+ { }
+
+ /**
+ * Returns the number of elements in container.
+ */
+ int getNumberOfElements() override
+ { return static_cast<int>(mVideoModes.size()); }
+
+ /**
+ * Returns element from container.
+ */
+ std::string getElementAt(int i)
+ { return mVideoModes[i]; }
+
+ /**
+ * Returns the index corresponding to the given video mode.
+ * E.g.: "800x600".
+ * or -1 if not found.
+ */
+ int getIndexOf(const std::string &widthXHeightMode);
+
+ private:
+ void addCustomMode(const std::string &mode);
+
+ StringVect mVideoModes;
+};
+
+#ifndef ANDROID
+static bool modeSorter(const std::string &mode1, const std::string &mode2)
+{
+ const int width1 = atoi(mode1.substr(0, mode1.find("x")).c_str());
+ const int height1 = atoi(mode1.substr(mode1.find("x") + 1).c_str());
+ if (!width1 || !height1)
+ return false;
+
+ const int width2 = atoi(mode2.substr(0, mode2.find("x")).c_str());
+ const int height2 = atoi(mode2.substr(mode2.find("x") + 1).c_str());
+ if (!width2 || !height2)
+ return false;
+ if (width1 != width2)
+ return width1 < width2;
+
+ if (height1 != height2)
+ return height1 < height2;
+
+ return false;
+}
+#endif
+
+ModeListModel::ModeListModel() :
+ mVideoModes()
+{
+ SDL::getAllVideoModes(mVideoModes);
+#ifndef ANDROID
+ addCustomMode("640x480");
+ addCustomMode("800x600");
+ addCustomMode("1024x768");
+ addCustomMode("1280x1024");
+ addCustomMode("1400x900");
+ addCustomMode("1500x990");
+ addCustomMode(toString(mainGraphics->mWidth).append("x")
+ .append(toString(mainGraphics->mHeight)));
+
+ std::sort(mVideoModes.begin(), mVideoModes.end(), modeSorter);
+ mVideoModes.push_back("custom");
+#endif
+}
+
+void ModeListModel::addCustomMode(const std::string &mode)
+{
+ StringVectCIter it = mVideoModes.begin();
+ const StringVectCIter it_end = mVideoModes.end();
+ while (it != it_end)
+ {
+ if (*it == mode)
+ return;
+ ++ it;
+ }
+ mVideoModes.push_back(mode);
+}
+
+int ModeListModel::getIndexOf(const std::string &widthXHeightMode)
+{
+ std::string currentMode("");
+ for (int i = 0; i < getNumberOfElements(); i++)
+ {
+ currentMode = getElementAt(i);
+ if (currentMode == widthXHeightMode)
+ return i;
+ }
+ return -1;
+}
+
+class OpenGLListModel final : public gcn::ListModel
+{
+public:
+ ~OpenGLListModel()
+ { }
+
+ int getNumberOfElements() override
+ { return renderModesListSize; }
+
+ std::string getElementAt(int i) override
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "???";
+ return gettext(OPENGL_NAME[i]);
+ }
+};
+
+Setup_Video::Setup_Video(const Widget2 *const widget) :
+ SetupTab(widget),
+ gcn::KeyListener(),
+ mFullScreenEnabled(config.getBoolValue("screen")),
+ mOpenGLEnabled(intToRenderType(config.getIntValue("opengl"))),
+ mFps(config.getIntValue("fpslimit")),
+ mAltFps(config.getIntValue("altfpslimit")),
+ mModeListModel(new ModeListModel),
+ mOpenGLListModel(new OpenGLListModel),
+ mModeList(new ListBox(widget, mModeListModel, "")),
+ // TRANSLATORS: video settings checkbox
+ mFsCheckBox(new CheckBox(this, _("Full screen"), mFullScreenEnabled)),
+ mOpenGLDropDown(new DropDown(widget, mOpenGLListModel)),
+ // TRANSLATORS: video settings checkbox
+ mFpsCheckBox(new CheckBox(this, _("FPS limit:"))),
+ mFpsSlider(new Slider(2, 160)),
+ mFpsLabel(new Label(this)),
+ mAltFpsSlider(new Slider(2, 160)),
+ // TRANSLATORS: video settings label
+ mAltFpsLabel(new Label(this, _("Alt FPS limit: "))),
+#if !defined(ANDROID) && !defined(__APPLE__)
+ // TRANSLATORS: video settings button
+ mDetectButton(new Button(this, _("Detect best mode"), "detect", this)),
+#endif
+ mDialog(nullptr),
+ mCustomCursorEnabled(config.getBoolValue("customcursor")),
+ mEnableResize(config.getBoolValue("enableresize")),
+ mNoFrame(config.getBoolValue("noframe")),
+ mCustomCursorCheckBox(new CheckBox(this,
+#ifdef ANDROID
+ // TRANSLATORS: video settings checkbox
+ _("Show cursor"),
+#else
+ // TRANSLATORS: video settings checkbox
+ _("Custom cursor"),
+#endif
+ mCustomCursorEnabled)),
+ // TRANSLATORS: video settings checkbox
+ mEnableResizeCheckBox(new CheckBox(this, _("Enable resize"),
+ mEnableResize)),
+ // TRANSLATORS: video settings checkbox
+ mNoFrameCheckBox(new CheckBox(this, _("No frame"), mNoFrame))
+{
+ // TRANSLATORS: video settings tab name
+ setName(_("Video"));
+
+ ScrollArea *const scrollArea = new ScrollArea(mModeList,
+ true, "setup_video_background.xml");
+ scrollArea->setWidth(150);
+ scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+
+ mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]);
+
+ mModeList->setEnabled(true);
+
+ // TRANSLATORS: video settings label
+ mFpsLabel->setCaption(mFps > 0 ? toString(mFps) : _("None"));
+ mFpsLabel->setWidth(60);
+ // TRANSLATORS: video settings label
+ mAltFpsLabel->setCaption(_("Alt FPS limit: ") + (mAltFps > 0
+ ? toString(mAltFps) : _("None")));
+ mAltFpsLabel->setWidth(150);
+ mFpsSlider->setValue(mFps);
+ mFpsSlider->setEnabled(mFps > 0);
+ mAltFpsSlider->setValue(mAltFps);
+ mAltFpsSlider->setEnabled(mAltFps > 0);
+ mFpsCheckBox->setSelected(mFps > 0);
+
+ // Pre-select the current video mode.
+ const std::string videoMode = toString(mainGraphics->mWidth).append("x")
+ .append(toString(mainGraphics->mHeight));
+ mModeList->setSelected(mModeListModel->getIndexOf(videoMode));
+
+ mModeList->setActionEventId("videomode");
+ mCustomCursorCheckBox->setActionEventId("customcursor");
+ mFpsCheckBox->setActionEventId("fpslimitcheckbox");
+ mFpsSlider->setActionEventId("fpslimitslider");
+ mAltFpsSlider->setActionEventId("altfpslimitslider");
+ mOpenGLDropDown->setActionEventId("opengl");
+ mEnableResizeCheckBox->setActionEventId("enableresize");
+ mNoFrameCheckBox->setActionEventId("noframe");
+
+ mModeList->addActionListener(this);
+ mCustomCursorCheckBox->addActionListener(this);
+ mFpsCheckBox->addActionListener(this);
+ mFpsSlider->addActionListener(this);
+ mAltFpsSlider->addActionListener(this);
+ mOpenGLDropDown->addActionListener(this);
+ mEnableResizeCheckBox->addActionListener(this);
+ mNoFrameCheckBox->addActionListener(this);
+
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+
+ place(0, 0, scrollArea, 1, 5).setPadding(2);
+ place(0, 5, mOpenGLDropDown, 1);
+
+ place(1, 0, mFsCheckBox, 2);
+
+ place(1, 1, mCustomCursorCheckBox, 3);
+
+ place(1, 2, mEnableResizeCheckBox, 2);
+ place(1, 3, mNoFrameCheckBox, 2);
+
+ place(0, 6, mFpsSlider);
+ place(1, 6, mFpsCheckBox).setPadding(3);
+ place(2, 6, mFpsLabel).setPadding(1);
+
+ place(0, 7, mAltFpsSlider);
+ place(1, 7, mAltFpsLabel).setPadding(3);
+
+#if !defined(ANDROID) && !defined(__APPLE__)
+ place(0, 8, mDetectButton);
+#else
+ mNoFrameCheckBox->setEnabled(false);
+ mEnableResizeCheckBox->setEnabled(false);
+ mFsCheckBox->setEnabled(false);
+#endif
+
+ int width = 600;
+
+ if (config.getIntValue("screenwidth") >= 730)
+ width += 100;
+
+ setDimension(gcn::Rectangle(0, 0, width, 300));
+}
+
+Setup_Video::~Setup_Video()
+{
+ delete mModeListModel;
+ mModeListModel = nullptr;
+ delete mModeList;
+ mModeList = nullptr;
+ delete mOpenGLListModel;
+ mOpenGLListModel = nullptr;
+ delete mDialog;
+ mDialog = nullptr;
+}
+
+void Setup_Video::apply()
+{
+ // Full screen changes
+ bool fullscreen = mFsCheckBox->isSelected();
+ if (fullscreen != config.getBoolValue("screen"))
+ {
+ /* The OpenGL test is only necessary on Windows, since switching
+ * to/from full screen works fine on Linux. On Windows we'd have to
+ * reinitialize the OpenGL state and reload all textures.
+ *
+ * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode
+ */
+
+#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
+ // checks for opengl usage
+ if (intToRenderType(config.getIntValue("opengl")) == RENDER_SOFTWARE)
+ {
+#endif
+ if (!mainGraphics->setFullscreen(fullscreen))
+ {
+ fullscreen = !fullscreen;
+ if (!mainGraphics->setFullscreen(fullscreen))
+ {
+ std::stringstream errorMsg;
+ if (fullscreen)
+ {
+ // TRANSLATORS: video error message
+ errorMsg << _("Failed to switch to windowed mode "
+ "and restoration of old mode also "
+ "failed!") << std::endl;
+ }
+ else
+ {
+ // TRANSLATORS: video error message
+ errorMsg << _("Failed to switch to fullscreen mode"
+ " and restoration of old mode also "
+ "failed!") << std::endl;
+ }
+ logger->safeError(errorMsg.str());
+ }
+ }
+#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
+ }
+ else
+ {
+ // TRANSLATORS: video settings warning
+ new OkDialog(_("Switching to Full Screen"),
+ // TRANSLATORS: video settings warning
+ _("Restart needed for changes to take effect."));
+ }
+#endif
+ config.setValue("screen", fullscreen);
+ }
+
+ const int sel = mOpenGLDropDown->getSelected();
+ RenderType mode = RENDER_SOFTWARE;
+ if (sel >= 0 && static_cast<unsigned int>(sel) < sizeof(indexToRender))
+ mode = indexToRender[mOpenGLDropDown->getSelected()];
+
+ // OpenGL change
+ if (mode != mOpenGLEnabled)
+ {
+ config.setValue("opengl", static_cast<int>(mode));
+
+ // OpenGL can currently only be changed by restarting, notify user.
+ // TRANSLATORS: video settings warning
+ new OkDialog(_("Changing to OpenGL"),
+ // TRANSLATORS: video settings warning
+ _("Applying change to OpenGL requires restart."));
+ }
+
+ mFps = mFpsCheckBox->isSelected() ?
+ static_cast<int>(mFpsSlider->getValue()) : 0;
+
+ mAltFps = static_cast<int>(mAltFpsSlider->getValue());
+
+ mFpsSlider->setEnabled(mFps > 0);
+
+ mAltFpsSlider->setEnabled(mAltFps > 0);
+
+ // FPS change
+ config.setValue("fpslimit", mFps);
+ config.setValue("altfpslimit", mAltFps);
+
+ // We sync old and new values at apply time
+ mFullScreenEnabled = config.getBoolValue("screen");
+ mCustomCursorEnabled = config.getBoolValue("customcursor");
+
+ mOpenGLEnabled = intToRenderType(config.getIntValue("opengl"));
+ mEnableResize = config.getBoolValue("enableresize");
+ mNoFrame = config.getBoolValue("noframe");
+}
+
+void Setup_Video::cancel()
+{
+ mFpsCheckBox->setSelected(mFps > 0);
+ mFsCheckBox->setSelected(mFullScreenEnabled);
+ mOpenGLDropDown->setSelected(renderToIndex[mOpenGLEnabled]);
+ mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
+ mFpsSlider->setValue(mFps);
+ mFpsSlider->setEnabled(mFps > 0);
+ mAltFpsSlider->setValue(mAltFps);
+ mAltFpsSlider->setEnabled(mAltFps > 0);
+ mFpsLabel->setCaption(mFpsCheckBox->isSelected()
+ // TRANSLATORS: video settings label
+ ? toString(mFps) : _("None"));
+ // TRANSLATORS: video settings label
+ mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps));
+ mEnableResizeCheckBox->setSelected(mEnableResize);
+ mNoFrameCheckBox->setSelected(mNoFrame);
+
+ config.setValue("screen", mFullScreenEnabled);
+
+ // Set back to the current video mode.
+ std::string videoMode = toString(mainGraphics->mWidth).append("x")
+ .append(toString(mainGraphics->mHeight));
+ mModeList->setSelected(mModeListModel->getIndexOf(videoMode));
+ config.setValue("screenwidth", mainGraphics->mWidth);
+ config.setValue("screenheight", mainGraphics->mHeight);
+
+ config.setValue("customcursor", mCustomCursorEnabled);
+ config.setValue("opengl", static_cast<int>(mOpenGLEnabled));
+ config.setValue("enableresize", mEnableResize);
+ config.setValue("noframe", mNoFrame);
+}
+
+void Setup_Video::action(const gcn::ActionEvent &event)
+{
+ const std::string &id = event.getId();
+
+ if (id == "videomode")
+ {
+ std::string mode = mModeListModel->getElementAt(
+ mModeList->getSelected());
+
+ if (mode == "custom")
+ {
+ if (mDialog)
+ {
+ mode = mDialog->getText();
+ mDialog = nullptr;
+ }
+ else
+ {
+ mDialog = new TextDialog(
+ // TRANSLATORS: resolution question dialog
+ _("Custom resolution (example: 1024x768)"),
+ // TRANSLATORS: resolution question dialog
+ _("Enter new resolution: "));
+ mDialog->setActionEventId("videomode");
+ mDialog->addActionListener(this);
+ return;
+ }
+ }
+ const int width = atoi(mode.substr(0, mode.find("x")).c_str());
+ const int height = atoi(mode.substr(mode.find("x") + 1).c_str());
+ if (!width || !height)
+ return;
+
+ if (width != mainGraphics->mWidth || height != mainGraphics->mHeight)
+ {
+#if defined(WIN32) || defined(__APPLE__) || defined(ANDROID)
+ if (intToRenderType(config.getIntValue("opengl"))
+ == RENDER_SOFTWARE)
+ {
+ client->resizeVideo(width, height);
+ }
+ else
+ {
+ if (width < mainGraphics->mWidth
+ || height < mainGraphics->mHeight)
+ {
+ // TRANSLATORS: video settings warning
+ new OkDialog(_("Screen Resolution Changed"),
+ // TRANSLATORS: video settings warning
+ _("Restart your client for the change to take effect.")
+ + std::string("\n") + _("Some windows may be moved to "
+ "fit the lowered resolution."));
+ }
+ else
+ {
+ // TRANSLATORS: video settings warning
+ new OkDialog(_("Screen Resolution Changed"),
+ // TRANSLATORS: video settings warning
+ _("Restart your client for the change"
+ " to take effect."));
+ }
+ }
+#else
+ mainGraphics->setWindowSize(width, height);
+ client->resizeVideo(width, height);
+#endif
+ }
+
+ config.setValue("oldscreen", config.getBoolValue("screen"));
+ config.setValue("oldscreenwidth", mainGraphics->mWidth);
+ config.setValue("oldscreenheight", mainGraphics->mHeight);
+ config.setValue("screenwidth", width);
+ config.setValue("screenheight", height);
+ }
+ if (id == "~videomode")
+ {
+ mDialog = nullptr;
+ }
+ else if (id == "customcursor")
+ {
+ config.setValue("customcursor", mCustomCursorCheckBox->isSelected());
+ }
+ else if (id == "fpslimitcheckbox" || id == "fpslimitslider")
+ {
+ int tempFps = static_cast<int>(mFpsSlider->getValue());
+ if (id == "fpslimitcheckbox" && !mFpsSlider->isEnabled())
+ tempFps = 60;
+ else
+ tempFps = tempFps > 0 ? tempFps : 60;
+ mFps = mFpsCheckBox->isSelected() ? tempFps : 0;
+ // TRANSLATORS: video settings label
+ const std::string text = mFps > 0 ? toString(mFps) : _("None");
+
+ mFpsLabel->setCaption(text);
+ mFpsSlider->setValue(mFps);
+ mFpsSlider->setEnabled(mFps > 0);
+ }
+ else if (id == "altfpslimitslider")
+ {
+ int tempFps = static_cast<int>(mAltFpsSlider->getValue());
+ tempFps = tempFps > 0 ? tempFps : static_cast<int>(
+ mAltFpsSlider->getScaleStart());
+ mAltFps = tempFps;
+ // TRANSLATORS: video settings label
+ const std::string text = mAltFps > 0 ? toString(mAltFps) : _("None");
+
+ // TRANSLATORS: video settings label
+ mAltFpsLabel->setCaption(_("Alt FPS limit: ") + text);
+ mAltFpsSlider->setValue(mAltFps);
+ mAltFpsSlider->setEnabled(mAltFps > 0);
+ }
+ else if (id == "enableresize")
+ {
+ config.setValue("enableresize", mEnableResizeCheckBox->isSelected());
+ }
+ else if (id == "noframe")
+ {
+ config.setValue("noframe", mNoFrameCheckBox->isSelected());
+ }
+#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__)
+ else if (id == "detect")
+ {
+ TestMain *test = graphicsManager.startDetection();
+ if (test)
+ {
+ const int val = test->getConfig().getValueInt("opengl", -1);
+ if (val >= 0 && static_cast<unsigned int>(val)
+ < sizeof(renderToIndex) / sizeof(int))
+ {
+ mOpenGLDropDown->setSelected(renderToIndex[val]);
+ }
+ delete test;
+ }
+ }
+#endif
+}
diff --git a/src/gui/widgets/tabs/setup_video.h b/src/gui/widgets/tabs/setup_video.h
new file mode 100644
index 000000000..e8fb415c9
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_video.h
@@ -0,0 +1,82 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_VIDEO_H
+#define GUI_SETUP_VIDEO_H
+
+#include "gui/widgets/tabs/setuptab.h"
+
+#include <guichan/keylistener.hpp>
+
+class Button;
+class CheckBox;
+class DropDown;
+class Label;
+class ListBox;
+class ModeListModel;
+class OpenGLListModel;
+class Slider;
+class TextDialog;
+
+class Setup_Video final : public SetupTab, public gcn::KeyListener
+{
+ public:
+ explicit Setup_Video(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Video)
+
+ ~Setup_Video();
+
+ void apply() override;
+
+ void cancel() override;
+
+ void action(const gcn::ActionEvent &event) override;
+
+ private:
+ bool mFullScreenEnabled;
+ RenderType mOpenGLEnabled;
+ int mFps;
+ int mAltFps;
+ ModeListModel *mModeListModel;
+ OpenGLListModel *mOpenGLListModel;
+ ListBox *mModeList;
+ CheckBox *mFsCheckBox;
+ DropDown *mOpenGLDropDown;
+ CheckBox *mFpsCheckBox;
+ Slider *mFpsSlider;
+ Label *mFpsLabel;
+ Slider *mAltFpsSlider;
+ Label *mAltFpsLabel;
+#if !defined(ANDROID) && !defined(__APPLE__)
+ Button *mDetectButton;
+#endif
+ TextDialog *mDialog;
+ bool mCustomCursorEnabled;
+ bool mEnableResize;
+ bool mNoFrame;
+ CheckBox *mCustomCursorCheckBox;
+ CheckBox *mEnableResizeCheckBox;
+ CheckBox *mNoFrameCheckBox;
+};
+
+#endif // GUI_SETUP_VIDEO_H
diff --git a/src/gui/widgets/tabs/setup_visual.cpp b/src/gui/widgets/tabs/setup_visual.cpp
new file mode 100644
index 000000000..f19b3508f
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_visual.cpp
@@ -0,0 +1,213 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setup_visual.h"
+
+#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/namesmodel.h"
+#include "gui/widgets/scrollarea.h"
+
+#include "client.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+static const int speachListSize = 4;
+
+static const char *const speachList[] =
+{
+ // TRANSLATORS: speach type
+ N_("No text"),
+ // TRANSLATORS: speach type
+ N_("Text"),
+ // TRANSLATORS: speach type
+ N_("Bubbles, no names"),
+ // TRANSLATORS: speach type
+ N_("Bubbles with names")
+};
+
+static const int ambientFxListSize = 3;
+
+static const char *const ambientFxList[] =
+{
+ // TRANSLATORS: ambient effect type
+ N_("off"),
+ // TRANSLATORS: ambient effect type
+ N_("low"),
+ // TRANSLATORS: ambient effect type
+ N_("high")
+};
+
+static const int particleTypeListSize = 3;
+
+static const char *const particleTypeList[] =
+{
+ // TRANSLATORS: patricle effects type
+ N_("best quality"),
+ // TRANSLATORS: patricle effects type
+ N_("normal"),
+ // TRANSLATORS: patricle effects type
+ N_("best performance")
+};
+
+static const int vSyncListSize = 3;
+
+static const char *const vSyncList[] =
+{
+ // TRANSLATORS: vsync type
+ N_("default"),
+ // TRANSLATORS: vsync type
+ N_("off"),
+ // TRANSLATORS: vsync type
+ N_("on")
+};
+
+Setup_Visual::Setup_Visual(const Widget2 *const widget) :
+ SetupTabScroll(widget),
+ mSpeachList(new NamesModel),
+ mAmbientFxList(new NamesModel),
+ mParticleList(new SetupItemNames),
+ mParticleTypeList(new NamesModel),
+ mVSyncList(new NamesModel)
+{
+ // TRANSLATORS: settings tab name
+ setName(_("Visual"));
+ // Do the layout
+ LayoutHelper h(this);
+ ContainerPlacer place = h.getPlacer(0, 0);
+ place(0, 0, mScroll, 10, 10);
+
+ mPreferredFirstItemSize = 150;
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Notifications"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show pickup notifications in chat"), "",
+ "showpickupchat", this, "showpickupchatEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Show pickup notifications as particle effects"),
+ "", "showpickupparticle", this, "showpickupparticleEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemLabel(_("Effects"), "", this);
+
+#ifndef ANDROID
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Grab mouse and keyboard input"),
+ "", "grabinput", this, "grabinputEvent");
+#endif
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Blurring textures (OpenGL)"),
+ "", "blur", this, "blurEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemSlider(_("Gui opacity"), "", "guialpha",
+ this, "guialphaEvent", 0.1, 1.0, 150, true);
+
+ mSpeachList->fillFromArray(&speachList[0], speachListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Overhead text"), "", "speech", this,
+ "speechEvent", mSpeachList, 200);
+
+ mAmbientFxList->fillFromArray(&ambientFxList[0], ambientFxListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Ambient FX"), "", "OverlayDetail", this,
+ "OverlayDetailEvent", mAmbientFxList, 100);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Particle effects"), "",
+ "particleeffects", this, "particleeffectsEvent");
+
+ // TRANSLATORS: particle details
+ mParticleList->push_back(_("low"));
+ // TRANSLATORS: particle details
+ mParticleList->push_back(_("medium"));
+ // TRANSLATORS: particle details
+ mParticleList->push_back(_("high"));
+ // TRANSLATORS: particle details
+ mParticleList->push_back(_("max"));
+ (new SetupItemSlider2(_("Particle detail"), "", "particleEmitterSkip",
+ this, "particleEmitterSkipEvent", 0, 3,
+ mParticleList, true))->setInvertValue(3);
+
+ mParticleTypeList->fillFromArray(&particleTypeList[0],
+ particleTypeListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Particle physics"), "", "particleFastPhysics",
+ this, "particleFastPhysicsEvent", mParticleTypeList, 200);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Gamma"), "", this);
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Enable gamma control"),
+ "", "enableGamma", this, "enableGammaEvent");
+
+ // TRANSLATORS: settings option
+ new SetupItemSlider(_("Gamma"), "", "gamma",
+ this, "gammeEvent", 1, 20, 350, true);
+
+
+ // TRANSLATORS: settings group
+ new SetupItemLabel(_("Other"), "", this);
+
+ mVSyncList->fillFromArray(&vSyncList[0], vSyncListSize);
+ // TRANSLATORS: settings option
+ new SetupItemDropDown(_("Vsync"), "", "vsync", this,
+ "vsyncEvent", mVSyncList, 100);
+
+#if defined(WIN32) || defined(__APPLE__)
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Center game window"),
+ "", "centerwindow", this, "centerwindowEvent");
+#endif
+
+ // TRANSLATORS: settings option
+ new SetupItemCheckBox(_("Allow screensaver to run"),
+ "", "allowscreensaver", this, "allowscreensaverEvent");
+
+ setDimension(gcn::Rectangle(0, 0, 550, 350));
+}
+
+Setup_Visual::~Setup_Visual()
+{
+ delete mSpeachList;
+ mSpeachList = nullptr;
+ delete mAmbientFxList;
+ mAmbientFxList = nullptr;
+ delete mParticleList;
+ mParticleList = nullptr;
+ delete mParticleTypeList;
+ mParticleTypeList = nullptr;
+ delete mVSyncList;
+ mVSyncList = nullptr;
+}
+
+void Setup_Visual::apply()
+{
+ SetupTabScroll::apply();
+ Client::applyGrabMode();
+}
diff --git a/src/gui/widgets/tabs/setup_visual.h b/src/gui/widgets/tabs/setup_visual.h
new file mode 100644
index 000000000..e1492d028
--- /dev/null
+++ b/src/gui/widgets/tabs/setup_visual.h
@@ -0,0 +1,48 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009-2010 Andrei Karas
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_SETUP_VISUAL_H
+#define GUI_SETUP_VISUAL_H
+
+#include "gui/widgets/setupitem.h"
+
+class NamesModel;
+
+class Setup_Visual final : public SetupTabScroll
+{
+ public:
+ explicit Setup_Visual(const Widget2 *const widget);
+
+ A_DELETE_COPY(Setup_Visual)
+
+ ~Setup_Visual();
+
+ void apply() override;
+
+ private:
+ NamesModel *mSpeachList;
+ NamesModel *mAmbientFxList;
+ SetupItemNames *mParticleList;
+ NamesModel *mParticleTypeList;
+ NamesModel *mVSyncList;
+};
+
+#endif // GUI_SETUP_VISUAL_H
diff --git a/src/gui/widgets/tabs/setuptab.cpp b/src/gui/widgets/tabs/setuptab.cpp
new file mode 100644
index 000000000..79df5e4bb
--- /dev/null
+++ b/src/gui/widgets/tabs/setuptab.cpp
@@ -0,0 +1,39 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setuptab.h"
+
+#include "debug.h"
+
+SetupTab::SetupTab(const Widget2 *const widget) :
+ Container(widget),
+ gcn::ActionListener(),
+ gcn::WidgetListener(),
+ mName()
+{
+ setOpaque(false);
+ addWidgetListener(this);
+}
+
+void SetupTab::externalUpdated()
+{
+}
diff --git a/src/gui/widgets/tabs/setuptab.h b/src/gui/widgets/tabs/setuptab.h
new file mode 100644
index 000000000..ab866ba28
--- /dev/null
+++ b/src/gui/widgets/tabs/setuptab.h
@@ -0,0 +1,74 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_SETUPTAB_H
+#define GUI_WIDGETS_SETUPTAB_H
+
+#include "gui/widgets/container.h"
+
+#include <guichan/actionlistener.hpp>
+#include <guichan/widgetlistener.hpp>
+
+#include <string>
+
+#include "localconsts.h"
+
+/**
+ * A container for the contents of a tab in the setup window.
+ */
+class SetupTab : public Container,
+ public gcn::ActionListener,
+ public gcn::WidgetListener
+{
+ public:
+ A_DELETE_COPY(SetupTab)
+
+ const std::string &getName() const A_WARN_UNUSED
+ { return mName; }
+
+ /**
+ * Called when the Apply button is pressed in the setup window.
+ */
+ virtual void apply() = 0;
+
+ /**
+ * Called when the Cancel button is pressed in the setup window.
+ */
+ virtual void cancel() = 0;
+
+ virtual void externalUpdated();
+
+ protected:
+ explicit SetupTab(const Widget2 *const widget);
+
+ /**
+ * Sets the name displayed on the tab. Should be set in the
+ * constructor of a subclass.
+ */
+ void setName(const std::string &name)
+ { mName = name; }
+
+ private:
+ std::string mName;
+};
+
+#endif // GUI_WIDGETS_SETUPTAB_H
diff --git a/src/gui/widgets/tabs/setuptabscroll.cpp b/src/gui/widgets/tabs/setuptabscroll.cpp
new file mode 100644
index 000000000..48a27a550
--- /dev/null
+++ b/src/gui/widgets/tabs/setuptabscroll.cpp
@@ -0,0 +1,134 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/setuptabscroll.h"
+
+#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/setupitem.h"
+#include "gui/widgets/vertcontainer.h"
+
+#include "debug.h"
+
+SetupTabScroll::SetupTabScroll(const Widget2 *const widget) :
+ SetupTab(widget),
+ mContainer(new VertContainer(this, 25, false, 8)),
+ mScroll(new ScrollArea(mContainer, false)),
+ mItems(),
+ mAllItems(),
+ mPreferredFirstItemSize(200)
+{
+ mScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
+ mScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
+}
+
+SetupTabScroll::~SetupTabScroll()
+{
+ mScroll = nullptr;
+
+ delete mContainer;
+ mContainer = nullptr;
+
+ std::set<SetupItem*>::iterator it = mAllItems.begin();
+ const std::set<SetupItem*>::iterator it_end = mAllItems.end();
+ while (it != it_end)
+ {
+ delete *it;
+ ++ it;
+ }
+ mAllItems.clear();
+}
+
+void SetupTabScroll::addControl(SetupItem *const widget)
+{
+ const std::string actionId = widget->getActionEventId();
+ if (!actionId.empty())
+ {
+ const std::map<std::string, SetupItem*>::iterator iter
+ = mItems.find(actionId);
+ if (iter != mItems.end())
+ {
+ delete (*iter).second;
+ mItems.erase(iter);
+ }
+ mItems[actionId] = widget;
+ }
+ mAllItems.insert(widget);
+}
+
+void SetupTabScroll::addControl(SetupItem *const widget,
+ const std::string &event)
+{
+ const std::map<std::string, SetupItem*>::iterator iter
+ = mItems.find(event);
+ if (iter != mItems.end())
+ {
+ delete (*iter).second;
+ mItems.erase(iter);
+ }
+ mItems[event] = widget;
+ mAllItems.insert(widget);
+}
+
+void SetupTabScroll::apply()
+{
+ for (std::map<std::string, SetupItem*>::const_iterator
+ iter = mItems.begin(), iter_end = mItems.end();
+ iter != iter_end; ++ iter)
+ {
+ if ((*iter).second)
+ (*iter).second->apply((*iter).first);
+ }
+}
+
+void SetupTabScroll::cancel()
+{
+ for (std::map<std::string, SetupItem*>::const_iterator
+ iter = mItems.begin(), iter_end = mItems.end();
+ iter != iter_end; ++ iter)
+ {
+ if ((*iter).second)
+ (*iter).second->cancel((*iter).first);
+ }
+}
+
+void SetupTabScroll::externalUpdated()
+{
+ for (std::map<std::string, SetupItem*>::const_iterator
+ iter = mItems.begin(), iter_end = mItems.end();
+ iter != iter_end; ++ iter)
+ {
+ SetupItem *const widget = (*iter).second;
+ if (widget && !widget->isMainConfig())
+ widget->externalUpdated((*iter).first);
+ }
+}
+
+void SetupTabScroll::widgetResized(const gcn::Event &event A_UNUSED)
+{
+ mScroll->setWidth(getWidth() - 12);
+ mScroll->setHeight(getHeight() - 12 - 12);
+}
+
+void SetupTabScroll::reread(const std::string &name)
+{
+ SetupItem *const item = mItems[name + "Event"];
+ if (item)
+ item->rereadValue();
+}
diff --git a/src/gui/widgets/tabs/setuptabscroll.h b/src/gui/widgets/tabs/setuptabscroll.h
new file mode 100644
index 000000000..e7be18709
--- /dev/null
+++ b/src/gui/widgets/tabs/setuptabscroll.h
@@ -0,0 +1,75 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_SETUPTABSCROLL_H
+#define GUI_WIDGETS_SETUPTABSCROLL_H
+
+#include "gui/widgets/tabs/setuptab.h"
+
+#include <map>
+#include <set>
+
+#include "localconsts.h"
+
+class SetupItem;
+class ScrollArea;
+class VertContainer;
+
+class SetupTabScroll : public SetupTab
+{
+ public:
+ explicit SetupTabScroll(const Widget2 *const widget);
+
+ A_DELETE_COPY(SetupTabScroll)
+
+ virtual ~SetupTabScroll();
+
+ void addControl(SetupItem *const widget);
+
+ void addControl(SetupItem *const widget, const std::string &event);
+
+ VertContainer *getContainer() const A_WARN_UNUSED
+ { return mContainer; }
+
+ virtual void apply() override;
+
+ virtual void cancel() override;
+
+ virtual void externalUpdated() override;
+
+ virtual void action(const gcn::ActionEvent &event A_UNUSED) override
+ { }
+
+ int getPreferredFirstItemSize() A_WARN_UNUSED
+ { return mPreferredFirstItemSize; }
+
+ void widgetResized(const gcn::Event &event) override;
+
+ void reread(const std::string &name);
+
+ protected:
+ VertContainer *mContainer;
+ ScrollArea *mScroll;
+ std::map<std::string, SetupItem*> mItems;
+ std::set<SetupItem*> mAllItems;
+ int mPreferredFirstItemSize;
+};
+
+#endif // GUI_WIDGETS_SETUPTABSCROLL_H
diff --git a/src/gui/widgets/tabs/tab.cpp b/src/gui/widgets/tabs/tab.cpp
new file mode 100644
index 000000000..8c25e7b1d
--- /dev/null
+++ b/src/gui/widgets/tabs/tab.cpp
@@ -0,0 +1,346 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/tab.h"
+
+#include "client.h"
+#include "graphicsvertexes.h"
+
+#include "gui/widgets/label.h"
+#include "gui/widgets/tabbedarea.h"
+
+#include "debug.h"
+
+int Tab::mInstances = 0;
+float Tab::mAlpha = 1.0;
+
+enum
+{
+ TAB_STANDARD = 0, // 0
+ TAB_HIGHLIGHTED, // 1
+ TAB_SELECTED, // 2
+ TAB_UNUSED, // 3
+ TAB_COUNT // 4 - Must be last.
+};
+
+static std::string const data[TAB_COUNT] =
+{
+ "tab.xml",
+ "tab_highlighted.xml",
+ "tab_selected.xml",
+ "tab_unused.xml"
+};
+
+Skin *Tab::tabImg[TAB_COUNT];
+
+Tab::Tab(const Widget2 *const widget) :
+ gcn::BasicContainer(),
+ Widget2(widget),
+ gcn::MouseListener(),
+ gcn::WidgetListener(),
+ mLabel(new Label(this)),
+ mTabbedArea(nullptr),
+ mTabColor(&getThemeColor(Theme::TAB)),
+ mTabOutlineColor(&getThemeColor(Theme::TAB_OUTLINE)),
+ mTabHighlightedColor(&getThemeColor(Theme::TAB_HIGHLIGHTED)),
+ mTabHighlightedOutlineColor(&getThemeColor(
+ Theme::TAB_HIGHLIGHTED_OUTLINE)),
+ mTabSelectedColor(&getThemeColor(Theme::TAB_SELECTED)),
+ mTabSelectedOutlineColor(&getThemeColor(Theme::TAB_SELECTED_OUTLINE)),
+ mFlashColor(&getThemeColor(Theme::TAB_FLASH)),
+ mFlashOutlineColor(&getThemeColor(Theme::TAB_FLASH_OUTLINE)),
+ mPlayerFlashColor(&getThemeColor(Theme::TAB_PLAYER_FLASH)),
+ mPlayerFlashOutlineColor(&getThemeColor(Theme::TAB_PLAYER_FLASH_OUTLINE)),
+ mFlash(0),
+ mVertexes(new ImageCollection),
+ mImage(nullptr),
+ mMode(0),
+ mRedraw(true),
+ mHasMouse(false)
+{
+ init();
+}
+
+Tab::~Tab()
+{
+ if (gui)
+ gui->removeDragged(this);
+
+ mInstances--;
+ if (mInstances == 0 && Theme::instance())
+ {
+ Theme *const theme = Theme::instance();
+ for (int mode = 0; mode < TAB_COUNT; mode ++)
+ theme->unload(tabImg[mode]);
+ }
+
+ delete mLabel;
+ mLabel = nullptr;
+
+ if (mImage)
+ {
+ mImage->decRef();
+ mImage = nullptr;
+ }
+ delete mVertexes;
+ mVertexes = nullptr;
+}
+
+void Tab::init()
+{
+ addMouseListener(this);
+ setFocusable(false);
+ setFrameSize(0);
+ mFlash = 0;
+
+ addWidgetListener(this);
+
+ if (mInstances == 0)
+ {
+ // Load the skin
+ Theme *const theme = Theme::instance();
+ if (theme)
+ {
+ for (int mode = 0; mode < TAB_COUNT; mode ++)
+ tabImg[mode] = theme->load(data[mode], "tab.xml");
+ }
+ updateAlpha();
+ }
+ mInstances++;
+
+ add(mLabel);
+
+ const Skin *const skin = tabImg[TAB_STANDARD];
+ if (!skin)
+ return;
+ const int padding = skin->getPadding();
+
+ mLabel->setPosition(padding, padding);
+}
+
+void Tab::updateAlpha()
+{
+ const float alpha = std::max(client->getGuiAlpha(),
+ Theme::instance()->getMinimumOpacity());
+
+ if (alpha != mAlpha)
+ {
+ mAlpha = alpha;
+ for (int a = 0; a < 9; a++)
+ {
+ for (int t = 0; t < TAB_COUNT; t++)
+ {
+ Skin *const skin = tabImg[t];
+ if (skin)
+ {
+ const ImageRect &rect = skin->getBorder();
+ Image *const image = rect.grid[a];
+ if (image)
+ image->setAlpha(mAlpha);
+ }
+ }
+ }
+ }
+}
+
+void Tab::draw(gcn::Graphics *graphics)
+{
+ BLOCK_START("Tab::draw")
+ int mode = TAB_STANDARD;
+
+ // check which type of tab to draw
+ if (mTabbedArea)
+ {
+ if (mTabbedArea->isTabSelected(this))
+ {
+ mLabel->setForegroundColorAll(*mTabSelectedColor,
+ *mTabSelectedOutlineColor);
+ mode = TAB_SELECTED;
+ // if tab is selected, it doesnt need to highlight activity
+ mFlash = 0;
+ }
+ else if (mHasMouse)
+ {
+ mLabel->setForegroundColorAll(*mTabHighlightedColor,
+ *mTabHighlightedOutlineColor);
+ mode = TAB_HIGHLIGHTED;
+ }
+ else
+ {
+ mLabel->setForegroundColorAll(*mTabColor, *mTabOutlineColor);
+ }
+
+ switch (mFlash)
+ {
+ case 1:
+ mLabel->setForegroundColorAll(*mFlashColor,
+ *mFlashOutlineColor);
+ break;
+ case 2:
+ mLabel->setForegroundColorAll(*mPlayerFlashColor,
+ *mPlayerFlashOutlineColor);
+ break;
+ default:
+ break;
+ }
+ }
+
+ const Skin *const skin = tabImg[mode];
+ if (!skin)
+ {
+ BLOCK_END("Tab::draw")
+ return;
+ }
+
+ updateAlpha();
+
+ Graphics *const g = static_cast<Graphics*>(graphics);
+
+ if (skin)
+ {
+ // draw tab
+ if (openGLMode != RENDER_SAFE_OPENGL)
+ {
+ const ImageRect &rect = skin->getBorder();
+ if (mRedraw || mode != mMode || g->getRedraw())
+ {
+ mMode = mode;
+ mRedraw = false;
+ mVertexes->clear();
+ g->calcWindow(mVertexes, 0, 0,
+ mDimension.width, mDimension.height, rect);
+
+ if (mImage)
+ {
+ const Skin *const skin1 = tabImg[TAB_STANDARD];
+ if (skin1)
+ {
+ const int padding = skin1->getPadding();
+ g->calcTile(mVertexes, mImage, padding, padding);
+ }
+ }
+ }
+
+ g->drawTile(mVertexes);
+ }
+ else
+ {
+ g->drawImageRect(0, 0,
+ mDimension.width, mDimension.height, skin->getBorder());
+ if (mImage)
+ {
+ const Skin *const skin1 = tabImg[TAB_STANDARD];
+ if (skin1)
+ {
+ const int padding = skin1->getPadding();
+ g->drawImage(mImage, padding, padding);
+ }
+ }
+ }
+ }
+
+ drawChildren(graphics);
+ BLOCK_END("Tab::draw")
+}
+
+void Tab::widgetResized(const gcn::Event &event A_UNUSED)
+{
+ mRedraw = true;
+}
+
+void Tab::widgetMoved(const gcn::Event &event A_UNUSED)
+{
+ mRedraw = true;
+}
+
+void Tab::setLabelFont(gcn::Font *const font)
+{
+ if (!mLabel)
+ return;
+
+ mLabel->setFont(font);
+ mLabel->adjustSize();
+ adjustSize();
+}
+
+
+void Tab::adjustSize()
+{
+ const Skin *const skin = tabImg[TAB_STANDARD];
+ if (!skin)
+ return;
+ const int pad2 = skin->getPadding() * 2;
+
+ if (mImage)
+ {
+ const SDL_Rect &rect = mImage->mBounds;
+ setSize(rect.w + pad2, rect.h + pad2);
+ }
+ else
+ {
+ setSize(mLabel->getWidth() + pad2,
+ mLabel->getHeight() + pad2);
+ }
+
+ if (mTabbedArea)
+ mTabbedArea->adjustTabPositions();
+}
+
+void Tab::setTabbedArea(TabbedArea* tabbedArea)
+{
+ mTabbedArea = tabbedArea;
+}
+
+TabbedArea* Tab::getTabbedArea() const
+{
+ return mTabbedArea;
+}
+
+void Tab::setCaption(const std::string &caption)
+{
+ mLabel->setCaption(caption);
+ mLabel->adjustSize();
+ adjustSize();
+}
+
+void Tab::setImage(Image *const image)
+{
+ if (mImage)
+ mImage->decRef();
+ mImage = image;
+ adjustSize();
+}
+
+const std::string &Tab::getCaption() const
+{
+ return mLabel->getCaption();
+}
+
+void Tab::mouseEntered(gcn::MouseEvent& mouseEvent A_UNUSED)
+{
+ mHasMouse = true;
+}
+
+void Tab::mouseExited(gcn::MouseEvent& mouseEvent A_UNUSED)
+{
+ mHasMouse = false;
+}
diff --git a/src/gui/widgets/tabs/tab.h b/src/gui/widgets/tabs/tab.h
new file mode 100644
index 000000000..ecd0ae494
--- /dev/null
+++ b/src/gui/widgets/tabs/tab.h
@@ -0,0 +1,187 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_TAB_H
+#define GUI_WIDGETS_TAB_H
+
+#include "gui/widgets/widget2.h"
+
+#include <guichan/basiccontainer.hpp>
+#include <guichan/mouselistener.hpp>
+#include <guichan/widgetlistener.hpp>
+
+#include "localconsts.h"
+
+class ImageCollection;
+class Label;
+class Skin;
+class TabbedArea;
+
+/**
+ * A tab, the same as the Guichan tab in 0.8, but extended
+ */
+class Tab : public gcn::BasicContainer,
+ public Widget2,
+ public gcn::MouseListener,
+ public gcn::WidgetListener
+{
+ public:
+ explicit Tab(const Widget2 *const widget);
+
+ A_DELETE_COPY(Tab)
+
+ virtual ~Tab();
+
+ /**
+ * Update the alpha value to the graphic components.
+ */
+ void updateAlpha();
+
+ /**
+ * Draw the tabbed area.
+ */
+ void draw(gcn::Graphics *graphics) override;
+
+ /**
+ * Set the normal color for the tab's text.
+ */
+ void setTabColor(const gcn::Color *const color1,
+ const gcn::Color *const color2)
+ {
+ mTabColor = color1;
+ mTabOutlineColor = color2;
+ }
+
+ /**
+ * Set the highlighted color for the tab's text.
+ */
+ void setHighlightedTabColor(const gcn::Color *const color1,
+ const gcn::Color *const color2)
+ {
+ mTabHighlightedColor = color1;
+ mTabHighlightedOutlineColor = color2;
+ }
+
+ /**
+ * Set the selected color for the tab's text.
+ */
+ void setSelectedTabColor(const gcn::Color *const color1,
+ const gcn::Color *const color2)
+ {
+ mTabSelectedColor = color1;
+ mTabSelectedOutlineColor = color2;
+ }
+
+ /**
+ * Set the flash color for the tab's text.
+ */
+ void setFlashTabColor(const gcn::Color *const color1,
+ const gcn::Color *const color2)
+ {
+ mFlashColor = color1;
+ mFlashOutlineColor = color2;
+ }
+
+ /**
+ * Set the player flash color for the tab's text.
+ */
+ void setPlayerFlashTabColor(const gcn::Color *const color1,
+ const gcn::Color *const color2)
+ {
+ mPlayerFlashColor = color1;
+ mPlayerFlashOutlineColor = color2;
+ }
+
+ /**
+ * Set tab flashing state
+ */
+ void setFlash(const int flash)
+ { mFlash = flash; }
+
+ int getFlash() const A_WARN_UNUSED
+ { return mFlash; }
+
+ void widgetResized(const gcn::Event &event) override;
+
+ void widgetMoved(const gcn::Event &event) override;
+
+ void setLabelFont(gcn::Font *const font);
+
+ Label *getLabel() const A_WARN_UNUSED
+ { return mLabel; }
+
+ void adjustSize();
+
+ void setTabbedArea(TabbedArea* tabbedArea);
+
+ TabbedArea* getTabbedArea() const A_WARN_UNUSED;
+
+ void setCaption(const std::string& caption);
+
+ const std::string &getCaption() const A_WARN_UNUSED;
+
+ void mouseEntered(gcn::MouseEvent &mouseEvent) override;
+
+ void mouseExited(gcn::MouseEvent &mouseEvent) override;
+
+ void setImage(Image *const image);
+
+ protected:
+ friend class TabbedArea;
+
+ virtual void setCurrent()
+ { }
+
+ Label* mLabel;
+
+
+ TabbedArea* mTabbedArea;
+
+ private:
+ /** Load images if no other instances exist yet */
+ void init();
+
+ static Skin *tabImg[4]; /**< Tab state graphics */
+ static int mInstances; /**< Number of tab instances */
+ static float mAlpha;
+
+ const gcn::Color *mTabColor;
+ const gcn::Color *mTabOutlineColor;
+ const gcn::Color *mTabHighlightedColor;
+ const gcn::Color *mTabHighlightedOutlineColor;
+ const gcn::Color *mTabSelectedColor;
+ const gcn::Color *mTabSelectedOutlineColor;
+ const gcn::Color *mFlashColor;
+ const gcn::Color *mFlashOutlineColor;
+ const gcn::Color *mPlayerFlashColor;
+ const gcn::Color *mPlayerFlashOutlineColor;
+ int mFlash;
+ ImageCollection *mVertexes;
+ Image *mImage;
+ int mMode;
+ bool mRedraw;
+
+ protected:
+ bool mHasMouse;
+};
+
+#endif // GUI_WIDGETS_TAB_H
diff --git a/src/gui/widgets/tabs/tradetab.cpp b/src/gui/widgets/tabs/tradetab.cpp
new file mode 100644
index 000000000..f9e1dc9e0
--- /dev/null
+++ b/src/gui/widgets/tabs/tradetab.cpp
@@ -0,0 +1,51 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2008-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/tradetab.h"
+
+#include "chatlogger.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+TradeTab::TradeTab(const Widget2 *const widget) :
+ // TRANSLATORS: trade chat tab name
+ ChatTab(widget, _("Trade"), TRADE_CHANNEL)
+{
+}
+
+TradeTab::~TradeTab()
+{
+}
+
+void TradeTab::handleInput(const std::string &msg)
+{
+ std::string str("\302\202" + msg);
+ ChatTab::handleInput(str);
+}
+
+void TradeTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ chatLogger->log(std::string("#Trade"), std::string(msg));
+}
diff --git a/src/gui/widgets/tabs/tradetab.h b/src/gui/widgets/tabs/tradetab.h
new file mode 100644
index 000000000..8c28704a4
--- /dev/null
+++ b/src/gui/widgets/tabs/tradetab.h
@@ -0,0 +1,51 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_TRADETAB_H
+#define GUI_WIDGETS_TRADETAB_H
+
+#include "gui/widgets/tabs/chattab.h"
+
+/**
+ * A tab for a party chat channel.
+ */
+class TradeTab final : public ChatTab
+{
+ public:
+ explicit TradeTab(const Widget2 *const widget);
+
+ A_DELETE_COPY(TradeTab)
+
+ ~TradeTab();
+
+ int getType() const override A_WARN_UNUSED
+ { return ChatTab::TAB_TRADE; }
+
+ void saveToLogFile(const std::string &msg) const override;
+
+ protected:
+ void handleInput(const std::string &msg) override;
+};
+
+extern TradeTab *tradeChatTab;
+
+#endif // GUI_WIDGETS_TRADETAB_H
diff --git a/src/gui/widgets/tabs/whispertab.cpp b/src/gui/widgets/tabs/whispertab.cpp
new file mode 100644
index 000000000..7ad14ac65
--- /dev/null
+++ b/src/gui/widgets/tabs/whispertab.cpp
@@ -0,0 +1,196 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/widgets/tabs/whispertab.h"
+
+#include "chatlogger.h"
+#include "commands.h"
+
+#include "being/localplayer.h"
+
+#include "net/chathandler.h"
+#include "net/net.h"
+
+#include "gui/widgets/windowcontainer.h"
+
+#include "utils/gettext.h"
+
+#include "debug.h"
+
+WhisperTab::WhisperTab(const Widget2 *const widget, const std::string &nick) :
+ ChatTab(widget, nick, ""),
+ mNick(nick)
+{
+ setWhisperTabColors();
+}
+
+WhisperTab::~WhisperTab()
+{
+ if (chatWindow)
+ chatWindow->removeWhisper(mNick);
+}
+
+void WhisperTab::handleInput(const std::string &msg)
+{
+ if (chatWindow)
+ {
+ Net::getChatHandler()->privateMessage(mNick,
+ chatWindow->doReplace(msg));
+ }
+ else
+ {
+ Net::getChatHandler()->privateMessage(mNick, msg);
+ }
+
+ if (player_node)
+ chatLog(player_node->getName(), msg);
+ else
+ chatLog("?", msg);
+}
+
+void WhisperTab::handleCommand(const std::string &msg)
+{
+ if (msg == "close")
+ {
+ delete this;
+ return;
+ }
+
+ const size_t pos = msg.find(' ');
+ const std::string type(msg, 0, pos);
+ const std::string args(msg, pos == std::string::npos
+ ? msg.size() : pos + 1);
+
+ if (type == "me")
+ {
+ std::string str = strprintf("*%s*", args.c_str());
+ Net::getChatHandler()->privateMessage(mNick, str);
+ if (player_node)
+ chatLog(player_node->getName(), str);
+ else
+ chatLog("?", str);
+ }
+ else
+ {
+ ChatTab::handleCommand(msg);
+ }
+}
+
+void WhisperTab::showHelp()
+{
+ // TRANSLATORS: whisper tab help
+ chatLog(_("/ignore > Ignore the other player"));
+ // TRANSLATORS: whisper tab help
+ chatLog(_("/unignore > Stop ignoring the other player"));
+ // TRANSLATORS: whisper tab help
+ chatLog(_("/close > Close the whisper tab"));
+}
+
+bool WhisperTab::handleCommand(const std::string &type,
+ const std::string &args)
+{
+ if (type == "help")
+ {
+ if (args == "close")
+ {
+ // TRANSLATORS: whisper tab help
+ chatLog(_("Command: /close"));
+ // TRANSLATORS: whisper tab help
+ chatLog(_("This command closes the current whisper tab."));
+ }
+ else if (args == "ignore")
+ {
+ // TRANSLATORS: whisper tab help
+ chatLog(_("Command: /ignore"));
+ // TRANSLATORS: whisper tab help
+ chatLog(_("This command ignores the other player regardless of "
+ "current relations."));
+ }
+ else if (args == "unignore")
+ {
+ // TRANSLATORS: whisper tab help
+ chatLog(_("Command: /unignore <player>"));
+ // TRANSLATORS: whisper tab help
+ chatLog(_("This command stops ignoring the other player if they "
+ "are being ignored."));
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (type == "close")
+ {
+ if (windowContainer)
+ windowContainer->scheduleDelete(this);
+ else
+ delete this;
+ if (chatWindow)
+ chatWindow->defaultTab();
+ }
+ else if (type == "ignore")
+ {
+ Commands::ignore(mNick, this);
+ }
+ else if (type == "unignore")
+ {
+ Commands::unignore(mNick, this);
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void WhisperTab::saveToLogFile(const std::string &msg) const
+{
+ if (chatLogger)
+ chatLogger->log(getNick(), msg);
+}
+
+void WhisperTab::getAutoCompleteList(StringVect &names) const
+{
+ names.push_back(mNick);
+}
+
+void WhisperTab::setWhisperTabColors()
+{
+ setTabColor(&getThemeColor(Theme::WHISPER_TAB),
+ &getThemeColor(Theme::WHISPER_TAB_OUTLINE));
+ setHighlightedTabColor(&getThemeColor(Theme::WHISPER_TAB_HIGHLIGHTED),
+ &getThemeColor(Theme::WHISPER_TAB_HIGHLIGHTED_OUTLINE));
+ setSelectedTabColor(&getThemeColor(Theme::WHISPER_TAB_SELECTED),
+ &getThemeColor(Theme::WHISPER_TAB_SELECTED_OUTLINE));
+}
+
+void WhisperTab::setWhisperTabOfflineColors()
+{
+ setTabColor(&getThemeColor(Theme::WHISPER_TAB_OFFLINE),
+ &getThemeColor(Theme::WHISPER_TAB_OFFLINE_OUTLINE));
+ setHighlightedTabColor(&getThemeColor(
+ Theme::WHISPER_TAB_OFFLINE_HIGHLIGHTED), &getThemeColor(
+ Theme::WHISPER_TAB_OFFLINE_HIGHLIGHTED_OUTLINE));
+ setSelectedTabColor(&getThemeColor(Theme::WHISPER_TAB_OFFLINE_SELECTED),
+ &getThemeColor(Theme::WHISPER_TAB_OFFLINE_SELECTED_OUTLINE));
+}
diff --git a/src/gui/widgets/tabs/whispertab.h b/src/gui/widgets/tabs/whispertab.h
new file mode 100644
index 000000000..97e6427c2
--- /dev/null
+++ b/src/gui/widgets/tabs/whispertab.h
@@ -0,0 +1,74 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2013 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUI_WIDGETS_WHISPERTAB_H
+#define GUI_WIDGETS_WHISPERTAB_H
+
+#include "gui/widgets/tabs/chattab.h"
+
+/**
+ * A tab for whispers from a single player.
+ */
+class WhisperTab final : public ChatTab
+{
+ public:
+ A_DELETE_COPY(WhisperTab)
+
+ const std::string &getNick() const A_WARN_UNUSED
+ { return mNick; }
+
+ void showHelp() override;
+
+ bool handleCommand(const std::string &type,
+ const std::string &args) override;
+
+ int getType() const override A_WARN_UNUSED
+ { return ChatTab::TAB_WHISPER; }
+
+ void saveToLogFile(const std::string &msg) const override;
+
+ void setWhisperTabColors();
+
+ void setWhisperTabOfflineColors();
+
+ protected:
+ friend class ChatWindow;
+
+ void getAutoCompleteList(StringVect &names) const override;
+ /**
+ * Constructor.
+ *
+ * @param nick the name of the player this tab is whispering to
+ */
+ WhisperTab(const Widget2 *const widget, const std::string &nick);
+
+ ~WhisperTab();
+
+ void handleInput(const std::string &msg) override;
+
+ void handleCommand(const std::string &msg) override;
+
+ private:
+ std::string mNick;
+};
+
+#endif // GUI_WIDGETS_WHISPERTAB_H