diff options
author | Andrei Karas <akaras@inbox.ru> | 2013-09-30 18:43:40 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2013-09-30 18:43:40 +0300 |
commit | 112058d7208f9a48a14d943e560b3b703647653a (patch) | |
tree | 8123b89ceee53577733f32fe15880fe7538ec473 /src/gui/widgets | |
parent | 64781090e80fa93a43ce37f0705bbb1cf22ed8bf (diff) | |
download | manaverse-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')
48 files changed, 4894 insertions, 20 deletions
diff --git a/src/gui/widgets/setupitem.h b/src/gui/widgets/setupitem.h index dae7d83d9..f566d6db0 100644 --- a/src/gui/widgets/setupitem.h +++ b/src/gui/widgets/setupitem.h @@ -22,7 +22,7 @@ #define GUI_WIDGETS_SETUPITEM_H #include "gui/widgets/button.h" -#include "gui/widgets/setuptabscroll.h" +#include "gui/widgets/tabs/setuptabscroll.h" #include <guichan/actionlistener.hpp> diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp index a08b8430e..44b2ea8d8 100644 --- a/src/gui/widgets/tabbedarea.cpp +++ b/src/gui/widgets/tabbedarea.cpp @@ -27,7 +27,7 @@ #include "gui/widgets/button.h" #include "gui/widgets/scrollarea.h" -#include "gui/widgets/tab.h" +#include "gui/widgets/tabs/tab.h" #include <guichan/widgets/container.hpp> diff --git a/src/gui/widgets/battletab.cpp b/src/gui/widgets/tabs/battletab.cpp index 3f97af5b9..fa7e252f0 100644 --- a/src/gui/widgets/battletab.cpp +++ b/src/gui/widgets/tabs/battletab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/battletab.h" +#include "gui/widgets/tabs/battletab.h" #include "chatlogger.h" #include "configuration.h" diff --git a/src/gui/widgets/battletab.h b/src/gui/widgets/tabs/battletab.h index 35a0f1b66..b4aa1d1df 100644 --- a/src/gui/widgets/battletab.h +++ b/src/gui/widgets/tabs/battletab.h @@ -23,7 +23,7 @@ #ifndef GUI_WIDGETS_BATTLETAB_H #define GUI_WIDGETS_BATTLETAB_H -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" /** * A tab for a party chat channel. diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/tabs/chattab.cpp index e863643d3..2c0628581 100644 --- a/src/gui/widgets/chattab.cpp +++ b/src/gui/widgets/tabs/chattab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" #include "chatlogger.h" #include "client.h" diff --git a/src/gui/widgets/chattab.h b/src/gui/widgets/tabs/chattab.h index 07192ab6b..e7744a8c1 100644 --- a/src/gui/widgets/chattab.h +++ b/src/gui/widgets/tabs/chattab.h @@ -26,7 +26,7 @@ #include "gui/windows/chatwindow.h" #include "gui/widgets/browserbox.h" -#include "gui/widgets/tab.h" +#include "gui/widgets/tabs/tab.h" #include "localconsts.h" diff --git a/src/gui/widgets/gmtab.cpp b/src/gui/widgets/tabs/gmtab.cpp index c8bf8ac98..25ec67f19 100644 --- a/src/gui/widgets/gmtab.cpp +++ b/src/gui/widgets/tabs/gmtab.cpp @@ -18,7 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/gmtab.h" +#include "gui/widgets/tabs/gmtab.h" #include "chatlogger.h" diff --git a/src/gui/widgets/gmtab.h b/src/gui/widgets/tabs/gmtab.h index 53e4e9644..28ccabe8a 100644 --- a/src/gui/widgets/gmtab.h +++ b/src/gui/widgets/tabs/gmtab.h @@ -21,7 +21,7 @@ #ifndef GUI_WIDGETS_GMTAB_H #define GUI_WIDGETS_GMTAB_H -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" /** * A tab for whispers from a single player. diff --git a/src/gui/widgets/guildchattab.cpp b/src/gui/widgets/tabs/guildchattab.cpp index 99723e7e4..4188a8843 100644 --- a/src/gui/widgets/guildchattab.cpp +++ b/src/gui/widgets/tabs/guildchattab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/guildchattab.h" +#include "gui/widgets/tabs/guildchattab.h" #include "chatlogger.h" #include "configuration.h" diff --git a/src/gui/widgets/guildchattab.h b/src/gui/widgets/tabs/guildchattab.h index e60970b50..f7aebcf55 100644 --- a/src/gui/widgets/guildchattab.h +++ b/src/gui/widgets/tabs/guildchattab.h @@ -23,7 +23,7 @@ #ifndef GUI_WIDGETS_GUILDCHATTAB_H #define GUI_WIDGETS_GUILDCHATTAB_H -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" /** * A tab for a guild chat channel. diff --git a/src/gui/widgets/langtab.cpp b/src/gui/widgets/tabs/langtab.cpp index 1ee4eef75..7bea453c7 100644 --- a/src/gui/widgets/langtab.cpp +++ b/src/gui/widgets/tabs/langtab.cpp @@ -18,7 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/langtab.h" +#include "gui/widgets/tabs/langtab.h" #include "chatlogger.h" diff --git a/src/gui/widgets/langtab.h b/src/gui/widgets/tabs/langtab.h index 0a0ff48c3..fa4e7c08c 100644 --- a/src/gui/widgets/langtab.h +++ b/src/gui/widgets/tabs/langtab.h @@ -21,7 +21,7 @@ #ifndef GUI_WIDGETS_LANGTAB_H #define GUI_WIDGETS_LANGTAB_H -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" class LangTab final : public ChatTab { 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/setuptab.cpp b/src/gui/widgets/tabs/setuptab.cpp index 68246cd0a..79df5e4bb 100644 --- a/src/gui/widgets/setuptab.cpp +++ b/src/gui/widgets/tabs/setuptab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/setuptab.h" +#include "gui/widgets/tabs/setuptab.h" #include "debug.h" diff --git a/src/gui/widgets/setuptab.h b/src/gui/widgets/tabs/setuptab.h index ab866ba28..ab866ba28 100644 --- a/src/gui/widgets/setuptab.h +++ b/src/gui/widgets/tabs/setuptab.h diff --git a/src/gui/widgets/setuptabscroll.cpp b/src/gui/widgets/tabs/setuptabscroll.cpp index f36d6d54e..48a27a550 100644 --- a/src/gui/widgets/setuptabscroll.cpp +++ b/src/gui/widgets/tabs/setuptabscroll.cpp @@ -18,7 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/setuptabscroll.h" +#include "gui/widgets/tabs/setuptabscroll.h" #include "gui/widgets/scrollarea.h" #include "gui/widgets/setupitem.h" diff --git a/src/gui/widgets/setuptabscroll.h b/src/gui/widgets/tabs/setuptabscroll.h index 8854e173e..e7be18709 100644 --- a/src/gui/widgets/setuptabscroll.h +++ b/src/gui/widgets/tabs/setuptabscroll.h @@ -21,7 +21,7 @@ #ifndef GUI_WIDGETS_SETUPTABSCROLL_H #define GUI_WIDGETS_SETUPTABSCROLL_H -#include "gui/widgets/setuptab.h" +#include "gui/widgets/tabs/setuptab.h" #include <map> #include <set> diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tabs/tab.cpp index 8c974cf97..8c25e7b1d 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tabs/tab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/tab.h" +#include "gui/widgets/tabs/tab.h" #include "client.h" #include "graphicsvertexes.h" diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tabs/tab.h index ecd0ae494..ecd0ae494 100644 --- a/src/gui/widgets/tab.h +++ b/src/gui/widgets/tabs/tab.h diff --git a/src/gui/widgets/tradetab.cpp b/src/gui/widgets/tabs/tradetab.cpp index c0a4d4d33..f9e1dc9e0 100644 --- a/src/gui/widgets/tradetab.cpp +++ b/src/gui/widgets/tabs/tradetab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/tradetab.h" +#include "gui/widgets/tabs/tradetab.h" #include "chatlogger.h" diff --git a/src/gui/widgets/tradetab.h b/src/gui/widgets/tabs/tradetab.h index 6948a81ff..8c28704a4 100644 --- a/src/gui/widgets/tradetab.h +++ b/src/gui/widgets/tabs/tradetab.h @@ -23,7 +23,7 @@ #ifndef GUI_WIDGETS_TRADETAB_H #define GUI_WIDGETS_TRADETAB_H -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" /** * A tab for a party chat channel. diff --git a/src/gui/widgets/whispertab.cpp b/src/gui/widgets/tabs/whispertab.cpp index 01298880e..7ad14ac65 100644 --- a/src/gui/widgets/whispertab.cpp +++ b/src/gui/widgets/tabs/whispertab.cpp @@ -20,7 +20,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "gui/widgets/whispertab.h" +#include "gui/widgets/tabs/whispertab.h" #include "chatlogger.h" #include "commands.h" diff --git a/src/gui/widgets/whispertab.h b/src/gui/widgets/tabs/whispertab.h index 599350c90..97e6427c2 100644 --- a/src/gui/widgets/whispertab.h +++ b/src/gui/widgets/tabs/whispertab.h @@ -23,7 +23,7 @@ #ifndef GUI_WIDGETS_WHISPERTAB_H #define GUI_WIDGETS_WHISPERTAB_H -#include "gui/widgets/chattab.h" +#include "gui/widgets/tabs/chattab.h" /** * A tab for whispers from a single player. |